<commit_before>// Package execution contains all logic for execution of external commands
// based on Environment struct.
//
// This file contains supervising routines.
package execution

import (
	"fmt"
	"os"
	"sync"
	"time"

	log "github.com/Sirupsen/logrus"
)

// supervisor defines structure which has all required data for supervising
// of running process.
type supervisor struct {
	allowedExitCodes  map[int]bool
	cmd               *command
	command           []string
	exitCodeChannel   chan int
	gracefulSignal    os.Signal
	gracefulTimeout   time.Duration
	hasTTY            bool
	keepAlivers       *sync.WaitGroup
	restartOnFailures bool
	supervisorChannel chan supervisorAction
}

func (s *supervisor) String() string {
	return fmt.Sprintf("%+v", *s)
}

// Just starts execution of the command and therefore its supervising.
func (s *supervisor) Start() {
	s.stop()

	if cmd, err := newCommand(s.command, s.hasTTY); err != nil {
		log.WithField("error", err).Panicf("Cannot start command!")
	} else {
		s.cmd = cmd
	}

	log.WithField("cmd", s.cmd).Info("Start process.")

	if s.restartOnFailures {
		go s.keepAlive()
	} else {
		go s.getExitCode()
	}
}

// Signal defines a callback for the incoming supervisorAction signal and
// reacts in expected way in a sync fashion.
func (s *supervisor) Signal(event supervisorAction) {
	switch event {
	case supervisorRestart:
		log.WithField("event", event).Info("Incoming restart event.")
		s.stop()
		s.Start()
	case supervisorStop:
		log.WithField("event", event).Info("Incoming stop event.")
		s.stop()
		s.exitCodeChannel <- s.cmd.ExitCode()
	}
}

// stopped just a thin wrapper which tells if command is stopped or not.
func (s *supervisor) stopped() bool {
	if s.cmd == nil {
		return true
	}
	return s.cmd.Stopped()
}

// stop just do what it names.
func (s *supervisor) stop() {
	log.Info("Stop external process.")

	log.Debug("Disable keepalivers.")
	s.keepAlivers.Wait()
	log.Debug("Keepalivers disabled.")

	if !s.stopped() {
		log.Debug("Start stopping process.")
		s.cmd.Stop(s.gracefulSignal, s.gracefulTimeout)
	} else {
		log.Debug("Process already stopped.")
	}
}

// keepAlive is just a function to be executed in goroutine. It tracks
// command execution and restarts if necessary.
func (s *supervisor) keepAlive() {
	s.keepAlivers.Add(1)
	defer s.keepAlivers.Done()

	log.Debug("Start keepaliver.")
	for {
		if s.stopped() {
			exitCode := s.cmd.ExitCode()
			if _, ok := s.allowedExitCodes[exitCode]; ok {
				log.WithFields(log.Fields{
					"exitCode":     exitCode,
					"allowedCodes": s.allowedExitCodes,
				}).Info("Exit code means we have to stop the execution.")
				s.exitCodeChannel <- exitCode
				return
			} else {
				log.Debug("Process is stopped, restarting.")
				s.supervisorChannel <- supervisorRestart
				log.Debug("Stop keepaliver.")
			}

			return
		}
		time.Sleep(timeoutSupervising)
	}
}

// getExitCode has to be executed if no real supervising is performed. It just
// returns the command exit code.
func (s *supervisor) getExitCode() {
	for {
		if s.stopped() {
			s.exitCodeChannel <- s.cmd.ExitCode()
		}
		time.Sleep(timeoutSupervising)
	}
}

// newSupervisor returns new supervisor structure based on the given arguments.
// No command execution is performed at that moment.
func newSupervisor(command []string,
	exitCodeChannel chan int,
	gracefulSignal os.Signal,
	gracefulTimeout time.Duration,
	hasTTY bool,
	restartOnFailures bool,
	supervisorChannel chan supervisorAction,
	allowedExitCodes map[int]bool) *supervisor {
	return &supervisor{
		allowedExitCodes:  allowedExitCodes,
		command:           command,
		exitCodeChannel:   exitCodeChannel,
		gracefulSignal:    gracefulSignal,
		gracefulTimeout:   gracefulTimeout,
		hasTTY:            hasTTY,
		keepAlivers:       new(sync.WaitGroup),
		restartOnFailures: restartOnFailures,
		supervisorChannel: supervisorChannel,
	}
}
<commit_msg>Small correction<commit_after>// Package execution contains all logic for execution of external commands
// based on Environment struct.
//
// This file contains supervising routines.
package execution

import (
	"fmt"
	"os"
	"sync"
	"time"

	log "github.com/Sirupsen/logrus"
)

// supervisor defines structure which has all required data for supervising
// of running process.
type supervisor struct {
	allowedExitCodes  map[int]bool
	cmd               *command
	command           []string
	exitCodeChannel   chan int
	gracefulSignal    os.Signal
	gracefulTimeout   time.Duration
	hasTTY            bool
	keepAlivers       *sync.WaitGroup
	restartOnFailures bool
	supervisorChannel chan supervisorAction
}

func (s *supervisor) String() string {
	return fmt.Sprintf("%+v", *s)
}

// Just starts execution of the command and therefore its supervising.
func (s *supervisor) Start() {
	s.stop()

	if cmd, err := newCommand(s.command, s.hasTTY); err != nil {
		log.WithField("error", err).Panicf("Cannot start command!")
	} else {
		s.cmd = cmd
	}

	log.WithField("cmd", s.cmd).Info("Start process.")

	if s.restartOnFailures {
		go s.keepAlive()
	} else {
		go s.getExitCode()
	}
}

// Signal defines a callback for the incoming supervisorAction signal and
// reacts in expected way in a sync fashion.
func (s *supervisor) Signal(event supervisorAction) {
	switch event {
	case supervisorRestart:
		log.WithField("event", event).Info("Incoming restart event.")
		s.stop()
		s.Start()
	case supervisorStop:
		log.WithField("event", event).Info("Incoming stop event.")
		s.stop()
		s.exitCodeChannel <- s.cmd.ExitCode()
	}
}

// stopped just a thin wrapper which tells if command is stopped or not.
func (s *supervisor) stopped() bool {
	if s.cmd == nil {
		return true
	}
	return s.cmd.Stopped()
}

// stop just do what it names.
func (s *supervisor) stop() {
	log.Info("Stop external process.")

	log.Debug("Disable keepalivers.")
	s.keepAlivers.Wait()
	log.Debug("Keepalivers disabled.")

	if !s.stopped() {
		log.Debug("Start stopping process.")
		s.cmd.Stop(s.gracefulSignal, s.gracefulTimeout)
	} else {
		log.Debug("Process already stopped.")
	}
}

// keepAlive is just a function to be executed in goroutine. It tracks
// command execution and restarts if necessary.
func (s *supervisor) keepAlive() {
	s.keepAlivers.Add(1)
	defer s.keepAlivers.Done()

	log.Debug("Start keepaliver.")
	for {
		if s.stopped() {
			exitCode := s.cmd.ExitCode()
			if _, ok := s.allowedExitCodes[exitCode]; ok {
				log.WithFields(log.Fields{
					"exitCode":     exitCode,
					"allowedCodes": s.allowedExitCodes,
				}).Debug("Exit code means we have to stop the execution.")
				s.supervisorChannel <- supervisorStop
			} else {
				log.Debug("Process is stopped, restarting.")
				s.supervisorChannel <- supervisorRestart
			}

			log.Debug("Stop keepaliver.")
			return
		}
		time.Sleep(timeoutSupervising)
	}
}

// getExitCode has to be executed if no real supervising is performed. It just
// returns the command exit code.
func (s *supervisor) getExitCode() {
	for {
		if s.stopped() {
			s.exitCodeChannel <- s.cmd.ExitCode()
		}
		time.Sleep(timeoutSupervising)
	}
}

// newSupervisor returns new supervisor structure based on the given arguments.
// No command execution is performed at that moment.
func newSupervisor(command []string,
	exitCodeChannel chan int,
	gracefulSignal os.Signal,
	gracefulTimeout time.Duration,
	hasTTY bool,
	restartOnFailures bool,
	supervisorChannel chan supervisorAction,
	allowedExitCodes map[int]bool) *supervisor {
	return &supervisor{
		allowedExitCodes:  allowedExitCodes,
		command:           command,
		exitCodeChannel:   exitCodeChannel,
		gracefulSignal:    gracefulSignal,
		gracefulTimeout:   gracefulTimeout,
		hasTTY:            hasTTY,
		keepAlivers:       new(sync.WaitGroup),
		restartOnFailures: restartOnFailures,
		supervisorChannel: supervisorChannel,
	}
}
<|endoftext|>


<commit_before>// +build darwin

package notify

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

	"github.com/gopasspw/gopass/pkg/ctxutil"
)

const (
	terminalNotifier string = "terminal-notifier"
	osascript        string = "osascript"
)

var execCommand = exec.Command
var execLookPath = exec.LookPath

// Notify displays a desktop notification using osascript
func Notify(ctx context.Context, subj, msg string) error {
	if os.Getenv("GOPASS_NO_NOTIFY") != "" || !ctxutil.IsNotifications(ctx) {
		return nil
	}

	// check if terminal-notifier was installed else use the applescript fallback
	tn, _ := executableExists(terminalNotifier)
	if tn {
		return tnNotification(msg, subj)
	}
	return osaNotification(msg, subj)
}

// display notification with osascript
func osaNotification(msg string, subj string) error {
	_, err := executableExists(osascript)
	if err != nil {
		return err
	}
	args := []string{"-e", `display notification "` + msg + `" with title "` + subj + `"`}
	return execNotification(osascript, args)
}

// exec notification program with passed arguments
func execNotification(executable string, args []string) error {
	return execCommand(executable, strings.Join(args[:], " ")).Start()
}

// display notification with terminal-notifier
func tnNotification(msg string, subj string) error {
	arguments := []string{"-title", "Gopass", "-message", msg, "-subtitle", subj, "-appIcon", iconURI()}
	return execNotification(terminalNotifier, arguments)
}

// check if executable exists
func executableExists(executable string) (bool, error) {
	_, err := execLookPath(executable)
	if err != nil {
		return false, err
	}
	return true, nil
}
<commit_msg>Fix notifications on darwin (#1578)<commit_after>// +build darwin

package notify

import (
	"context"
	"os"
	"os/exec"

	"github.com/gopasspw/gopass/pkg/ctxutil"
)

const (
	terminalNotifier string = "terminal-notifier"
	osascript        string = "osascript"
)

var execCommand = exec.Command
var execLookPath = exec.LookPath

// Notify displays a desktop notification using osascript
func Notify(ctx context.Context, subj, msg string) error {
	if os.Getenv("GOPASS_NO_NOTIFY") != "" || !ctxutil.IsNotifications(ctx) {
		return nil
	}

	// check if terminal-notifier was installed else use the applescript fallback
	tn, _ := executableExists(terminalNotifier)
	if tn {
		return tnNotification(msg, subj)
	}
	return osaNotification(msg, subj)
}

// display notification with osascript
func osaNotification(msg string, subj string) error {
	_, err := executableExists(osascript)
	if err != nil {
		return err
	}
	args := []string{"-e", `display notification "` + msg + `" with title "` + subj + `"`}
	return execNotification(osascript, args)
}

// exec notification program with passed arguments
func execNotification(executable string, args []string) error {
	return execCommand(executable, args...).Start()
}

// display notification with terminal-notifier
func tnNotification(msg string, subj string) error {
	arguments := []string{"-title", "Gopass", "-message", msg, "-subtitle", subj, "-appIcon", iconURI()}
	return execNotification(terminalNotifier, arguments)
}

// check if executable exists
func executableExists(executable string) (bool, error) {
	_, err := execLookPath(executable)
	if err != nil {
		return false, err
	}
	return true, nil
}
<|endoftext|>


<commit_before>// Copyright 2018 The Ebiten 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 packing_test

import (
	"testing"

	. "github.com/hajimehoshi/ebiten/internal/packing"
)

func TestBSP(t *testing.T) {
	type Rect struct {
		X      int
		Y      int
		Width  int
		Height int
	}

	type Op struct {
		Width      int
		Height     int
		FreeNodeID int
	}

	cases := []struct {
		In  []Op
		Out []*Rect
	}{
		{
			In: []Op{
				{100, 100, -1},
				{100, 100, -1},
				{100, 100, -1},
				{100, 100, -1},
				{100, 100, -1},
				{100, 100, -1},
				{0, 0, 1},
				{0, 0, 3},
				{0, 0, 5},
				{0, 0, 0},
				{0, 0, 2},
				{0, 0, 4},
				{MaxSize, MaxSize, -1},
			},
			Out: []*Rect{
				{0, 0, 100, 100},
				{0, 100, 100, 100},
				{0, 200, 100, 100},
				{0, 300, 100, 100},
				{0, 400, 100, 100},
				{0, 500, 100, 100},
				nil,
				nil,
				nil,
				nil,
				nil,
				nil,
				{0, 0, MaxSize, MaxSize},
			},
		},
		{
			In: []Op{
				{200, 400, -1},
				{MaxSize, MaxSize, -1},
				{200, 400, -1},
				{100, 100, -1},
				{400, 400, -1},
				{MaxSize, MaxSize, -1},
				{1000, 1000, -1},
				{1200, 1200, -1},
				{200, 200, -1},
				{0, 0, 2},
				{200, 400, -1},
			},
			Out: []*Rect{
				{0, 0, 200, 400},
				nil,
				{0, 400, 200, 400},
				{0, 800, 100, 100},
				{200, 0, 400, 400},
				nil,
				{200, 400, 1000, 1000},
				nil,
				{0, 900, 200, 200},
				nil,
				{0, 400, 200, 400},
			},
		},
		{
			In: []Op{
				{512, 512, -1},
				{512, 512, -1},
				{512, 512, -1},
				{512, 512, -1},

				{512, 512, -1},
				{512, 512, -1},
				{512, 512, -1},
				{512, 512, -1},

				{512, 512, -1},
				{512, 512, -1},
				{512, 512, -1},
				{512, 512, -1},

				{512, 512, -1},
				{512, 512, -1},
				{512, 512, -1},
				{512, 512, -1},

				{512, 512, -1},
			},
			Out: []*Rect{
				{0, 0, 512, 512},
				{0, 512, 512, 512},
				{0, 1024, 512, 512},
				{0, 1536, 512, 512},

				{512, 0, 512, 512},
				{1024, 0, 512, 512},
				{1536, 0, 512, 512},
				{512, 512, 512, 512},

				{512, 1024, 512, 512},
				{512, 1536, 512, 512},
				{1024, 512, 512, 512},
				{1536, 512, 512, 512},

				{1024, 1024, 512, 512},
				{1024, 1536, 512, 512},
				{1536, 1024, 512, 512},
				{1536, 1536, 512, 512},

				nil,
			},
		},
		{
			In: []Op{
				{600, 600, -1},
				{600, 600, -1},
				{600, 600, -1},
				{600, 600, -1},
				{600, 600, -1},
				{600, 600, -1},
				{600, 600, -1},
				{600, 600, -1},
				{600, 600, -1},
				{600, 600, -1},
			},
			Out: []*Rect{
				{0, 0, 600, 600},
				{0, 600, 600, 600},
				{0, 1200, 600, 600},
				{600, 0, 600, 600},
				{1200, 0, 600, 600},
				{600, 600, 600, 600},
				{600, 1200, 600, 600},
				{1200, 600, 600, 600},
				{1200, 1200, 600, 600},
				nil,
			},
		},
	}

	for caseIndex, c := range cases {
		p := &Page{}
		nodes := []*Node{}
		for _, in := range c.In {
			if in.FreeNodeID == -1 {
				n := p.Alloc(in.Width, in.Height)
				nodes = append(nodes, n)
			} else {
				p.Free(nodes[in.FreeNodeID])
				nodes = append(nodes, nil)
			}
		}
		for i, out := range c.Out {
			if nodes[i] == nil {
				if out != nil {
					t.Errorf("(%d) nodes[%d]: should be nil but %v", caseIndex, i, out)
				}
				continue
			}
			x, y, width, height := nodes[i].Region()
			got := Rect{x, y, width, height}
			if out == nil {
				t.Errorf("(%d) nodes[%d]: got: %v, want: %v", caseIndex, i, got, nil)
				continue
			}
			want := *out
			if got != want {
				t.Errorf("(%d) nodes[%d]: got: %v, want: %v", caseIndex, i, got, want)
			}
		}
	}
}
<commit_msg>packing: Rename tests<commit_after>// Copyright 2018 The Ebiten 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 packing_test

import (
	"testing"

	. "github.com/hajimehoshi/ebiten/internal/packing"
)

func TestPage(t *testing.T) {
	type Rect struct {
		X      int
		Y      int
		Width  int
		Height int
	}

	type Op struct {
		Width      int
		Height     int
		FreeNodeID int
	}

	cases := []struct {
		In  []Op
		Out []*Rect
	}{
		{
			In: []Op{
				{100, 100, -1},
				{100, 100, -1},
				{100, 100, -1},
				{100, 100, -1},
				{100, 100, -1},
				{100, 100, -1},
				{0, 0, 1},
				{0, 0, 3},
				{0, 0, 5},
				{0, 0, 0},
				{0, 0, 2},
				{0, 0, 4},
				{MaxSize, MaxSize, -1},
			},
			Out: []*Rect{
				{0, 0, 100, 100},
				{0, 100, 100, 100},
				{0, 200, 100, 100},
				{0, 300, 100, 100},
				{0, 400, 100, 100},
				{0, 500, 100, 100},
				nil,
				nil,
				nil,
				nil,
				nil,
				nil,
				{0, 0, MaxSize, MaxSize},
			},
		},
		{
			In: []Op{
				{200, 400, -1},
				{MaxSize, MaxSize, -1},
				{200, 400, -1},
				{100, 100, -1},
				{400, 400, -1},
				{MaxSize, MaxSize, -1},
				{1000, 1000, -1},
				{1200, 1200, -1},
				{200, 200, -1},
				{0, 0, 2},
				{200, 400, -1},
			},
			Out: []*Rect{
				{0, 0, 200, 400},
				nil,
				{0, 400, 200, 400},
				{0, 800, 100, 100},
				{200, 0, 400, 400},
				nil,
				{200, 400, 1000, 1000},
				nil,
				{0, 900, 200, 200},
				nil,
				{0, 400, 200, 400},
			},
		},
		{
			In: []Op{
				{512, 512, -1},
				{512, 512, -1},
				{512, 512, -1},
				{512, 512, -1},

				{512, 512, -1},
				{512, 512, -1},
				{512, 512, -1},
				{512, 512, -1},

				{512, 512, -1},
				{512, 512, -1},
				{512, 512, -1},
				{512, 512, -1},

				{512, 512, -1},
				{512, 512, -1},
				{512, 512, -1},
				{512, 512, -1},

				{512, 512, -1},
			},
			Out: []*Rect{
				{0, 0, 512, 512},
				{0, 512, 512, 512},
				{0, 1024, 512, 512},
				{0, 1536, 512, 512},

				{512, 0, 512, 512},
				{1024, 0, 512, 512},
				{1536, 0, 512, 512},
				{512, 512, 512, 512},

				{512, 1024, 512, 512},
				{512, 1536, 512, 512},
				{1024, 512, 512, 512},
				{1536, 512, 512, 512},

				{1024, 1024, 512, 512},
				{1024, 1536, 512, 512},
				{1536, 1024, 512, 512},
				{1536, 1536, 512, 512},

				nil,
			},
		},
		{
			In: []Op{
				{600, 600, -1},
				{600, 600, -1},
				{600, 600, -1},
				{600, 600, -1},
				{600, 600, -1},
				{600, 600, -1},
				{600, 600, -1},
				{600, 600, -1},
				{600, 600, -1},
				{600, 600, -1},
			},
			Out: []*Rect{
				{0, 0, 600, 600},
				{0, 600, 600, 600},
				{0, 1200, 600, 600},
				{600, 0, 600, 600},
				{1200, 0, 600, 600},
				{600, 600, 600, 600},
				{600, 1200, 600, 600},
				{1200, 600, 600, 600},
				{1200, 1200, 600, 600},
				nil,
			},
		},
	}

	for caseIndex, c := range cases {
		p := &Page{}
		nodes := []*Node{}
		for _, in := range c.In {
			if in.FreeNodeID == -1 {
				n := p.Alloc(in.Width, in.Height)
				nodes = append(nodes, n)
			} else {
				p.Free(nodes[in.FreeNodeID])
				nodes = append(nodes, nil)
			}
		}
		for i, out := range c.Out {
			if nodes[i] == nil {
				if out != nil {
					t.Errorf("(%d) nodes[%d]: should be nil but %v", caseIndex, i, out)
				}
				continue
			}
			x, y, width, height := nodes[i].Region()
			got := Rect{x, y, width, height}
			if out == nil {
				t.Errorf("(%d) nodes[%d]: got: %v, want: %v", caseIndex, i, got, nil)
				continue
			}
			want := *out
			if got != want {
				t.Errorf("(%d) nodes[%d]: got: %v, want: %v", caseIndex, i, got, want)
			}
		}
	}
}
<|endoftext|>


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

package setters

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

	"sigs.k8s.io/kustomize/kyaml/kio"
	"sigs.k8s.io/kustomize/kyaml/setters"
)

func PerformSetters(path string) error {
	rw := &kio.LocalPackageReadWriter{
		PackagePath:           path,
		KeepReaderAnnotations: false,
		IncludeSubpackages:    true,
	}

	// auto-fill setters from the environment
	var fltrs []kio.Filter
	for i := range os.Environ() {
		e := os.Environ()[i]
		if !strings.HasPrefix(e, "KPT_SET_") {
			continue
		}
		parts := strings.SplitN(e, "=", 2)
		if len(parts) < 2 {
			continue
		}
		k, v := strings.TrimPrefix(parts[0], "KPT_SET_"), parts[1]
		k = strings.ToLower(k)
		fltrs = append(fltrs, &setters.PerformSetters{Name: k, Value: v, SetBy: "kpt"})
	}

	// auto-fill setters from gcloud
	gcloudConfig := []string{"compute.region", "compute.zone", "core.project"}
	for _, c := range gcloudConfig {
		gcloudCmd := exec.Command("gcloud",
			"config", "list", "--format", fmt.Sprintf("value(%s)", c))
		b, err := gcloudCmd.Output()
		if err != nil {
			// don't fail if gcloud fails -- it may not be installed or have this config property
			continue
		}
		v := strings.TrimSpace(string(b))
		fltrs = append(fltrs, &setters.PerformSetters{Name: fmt.Sprintf("gcloud.%s", c), Value: v, SetBy: "kpt"})
	}

	if len(fltrs) == 0 {
		return nil
	}

	return kio.Pipeline{Inputs: []kio.Reader{rw}, Filters: fltrs, Outputs: []kio.Writer{rw}}.
		Execute()
}
<commit_msg>Don't auto-set gcloud values that are empty<commit_after>// Copyright 2019 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package setters

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

	"sigs.k8s.io/kustomize/kyaml/kio"
	"sigs.k8s.io/kustomize/kyaml/setters"
)

func PerformSetters(path string) error {
	rw := &kio.LocalPackageReadWriter{
		PackagePath:           path,
		KeepReaderAnnotations: false,
		IncludeSubpackages:    true,
	}

	// auto-fill setters from the environment
	var fltrs []kio.Filter
	for i := range os.Environ() {
		e := os.Environ()[i]
		if !strings.HasPrefix(e, "KPT_SET_") {
			continue
		}
		parts := strings.SplitN(e, "=", 2)
		if len(parts) < 2 {
			continue
		}
		k, v := strings.TrimPrefix(parts[0], "KPT_SET_"), parts[1]
		k = strings.ToLower(k)
		fltrs = append(fltrs, &setters.PerformSetters{Name: k, Value: v, SetBy: "kpt"})
	}

	// auto-fill setters from gcloud
	gcloudConfig := []string{"compute.region", "compute.zone", "core.project"}
	for _, c := range gcloudConfig {
		gcloudCmd := exec.Command("gcloud",
			"config", "list", "--format", fmt.Sprintf("value(%s)", c))
		b, err := gcloudCmd.Output()
		if err != nil {
			// don't fail if gcloud fails -- it may not be installed or have this config property
			continue
		}
		v := strings.TrimSpace(string(b))
		if v == "" {
			// don't replace values that aren't set - stick with the defaults as defined in the manifest
			continue
		}
		fltrs = append(fltrs, &setters.PerformSetters{Name: fmt.Sprintf("gcloud.%s", c), Value: v, SetBy: "kpt"})
	}

	if len(fltrs) == 0 {
		return nil
	}

	return kio.Pipeline{Inputs: []kio.Reader{rw}, Filters: fltrs, Outputs: []kio.Writer{rw}}.
		Execute()
}
<|endoftext|>


<commit_before>package main

import (
	"context"
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"os/signal"
	"runtime"
	"syscall"
	"time"

	stdhttp "net/http"

	"github.com/multimfi/bot/pkg/http"
	"github.com/multimfi/bot/pkg/irc"
)

var buildversion = "devel"

type errFunc func() error

func fatal(fs ...errFunc) {
	for _, f := range fs {
		go func(f errFunc) {
			err := f()
			if err != nil {
				log.Fatal(err)
			}
		}(f)
	}
}

func config(file, tfile string) *http.Config {
	r := new(http.Config)

	f, err := ioutil.ReadFile(file)
	if os.IsNotExist(err) {
		log.Printf("config error: %v", err)
		return nil
	}

	if err != nil {
		log.Fatalf("config error: %v", err)
	}

	if err := json.Unmarshal(f, r); err != nil {
		log.Fatalf("config error: %v", err)
	}

	f, err = ioutil.ReadFile(tfile)
	if os.IsNotExist(err) {
		log.Printf("config error: %v", err)
		return r
	}
	if err != nil {
		log.Fatalf("config error: %v", err)
	}

	r.Template = string(f)
	return r
}

func version() string {
	return fmt.Sprintf("build: %s, runtime: %s", buildversion, runtime.Version())
}

var (
	flagConfig      = flag.String("cfg", "bot.json", "bot configuration file")
	flagTemplate    = flag.String("cfg.template", "template.tmpl", "template file")
	flagIRCServer   = flag.String("irc.server", "127.0.0.1:6667", "irc server address")
	flagIRCChannel  = flag.String("irc.channel", "#test", "irc channel to join")
	flagIRCUsername = flag.String("irc.user", "Bot", "irc username")
	flagIRCNickname = flag.String("irc.nick", "bot", "irc nickname")
	flagAMListen    = flag.String("alertmanager.addr", "127.0.0.1:9500", "alertmanager webhook listen address")
	flagVersion     = flag.Bool("version", false, "version")
)

func main() {
	log.SetFlags(log.Lshortfile)
	flag.Parse()

	if *flagVersion {
		fmt.Fprintln(os.Stderr, version())
		os.Exit(0)
	}

	mux := stdhttp.NewServeMux()

	hs := &stdhttp.Server{
		Addr:    *flagAMListen,
		Handler: mux,
	}
	ic := irc.NewClient(
		*flagIRCNickname,
		*flagIRCUsername,
		*flagIRCChannel,
		*flagIRCServer,
	)

	ic.Handle("!version", func(string) string {
		return version()
	})

	ic.Handle("!ping", func(string) string {
		return "pong"
	})

	srv := http.NewServer(ic, mux, config(*flagConfig, *flagTemplate))

	fatal(
		srv.Dial,
		hs.ListenAndServe,
	)

	ctx := context.Background()
	sig := make(chan os.Signal)
	signal.Notify(sig, os.Interrupt, syscall.SIGTERM)

	select {
	case s := <-sig:
		log.Printf("received signal %s, shutting down", s)

		ic.Quit()

		ctx, cfunc := context.WithTimeout(ctx, time.Second*5)
		defer cfunc()
		if err := hs.Shutdown(ctx); err != nil {
			log.Fatal(err)
		}
	}
}
<commit_msg>daemon: do not return early<commit_after>package main

import (
	"context"
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"os/signal"
	"runtime"
	"syscall"
	"time"

	stdhttp "net/http"

	"github.com/multimfi/bot/pkg/http"
	"github.com/multimfi/bot/pkg/irc"
)

var buildversion = "devel"

type errFunc func() error

func fatal(fs ...errFunc) {
	for _, f := range fs {
		go func(f errFunc) {
			err := f()
			if err != nil {
				log.Fatal(err)
			}
		}(f)
	}
}

func config(file, tfile string) *http.Config {
	r := new(http.Config)

	f, err := ioutil.ReadFile(file)
	if os.IsNotExist(err) {
		log.Printf("config error: %v", err)
	} else if err != nil {
		log.Fatalf("config error: %v", err)
	} else {
		if err := json.Unmarshal(f, r); err != nil {
			log.Fatalf("config json error: %v", err)
		}
	}

	f, err = ioutil.ReadFile(tfile)
	if os.IsNotExist(err) {
		log.Printf("config template error: %v", err)
		return r
	}
	if err != nil {
		log.Fatalf("config template error: %v", err)
	}
	r.Template = string(f)
	return r
}

func version() string {
	return fmt.Sprintf("build: %s, runtime: %s", buildversion, runtime.Version())
}

var (
	flagConfig      = flag.String("cfg", "bot.json", "bot configuration file")
	flagTemplate    = flag.String("cfg.template", "template.tmpl", "template file")
	flagIRCServer   = flag.String("irc.server", "127.0.0.1:6667", "irc server address")
	flagIRCChannel  = flag.String("irc.channel", "#test", "irc channel to join")
	flagIRCUsername = flag.String("irc.user", "Bot", "irc username")
	flagIRCNickname = flag.String("irc.nick", "bot", "irc nickname")
	flagAMListen    = flag.String("alertmanager.addr", "127.0.0.1:9500", "alertmanager webhook listen address")
	flagVersion     = flag.Bool("version", false, "version")
)

func main() {
	log.SetFlags(log.Lshortfile)
	flag.Parse()

	if *flagVersion {
		fmt.Fprintln(os.Stderr, version())
		os.Exit(0)
	}

	mux := stdhttp.NewServeMux()

	hs := &stdhttp.Server{
		Addr:    *flagAMListen,
		Handler: mux,
	}
	ic := irc.NewClient(
		*flagIRCNickname,
		*flagIRCUsername,
		*flagIRCChannel,
		*flagIRCServer,
	)

	ic.Handle("!version", func(string) string {
		return version()
	})

	ic.Handle("!ping", func(string) string {
		return "pong"
	})

	srv := http.NewServer(ic, mux, config(*flagConfig, *flagTemplate))

	fatal(
		srv.Dial,
		hs.ListenAndServe,
	)

	ctx := context.Background()
	sig := make(chan os.Signal)
	signal.Notify(sig, os.Interrupt, syscall.SIGTERM)

	select {
	case s := <-sig:
		log.Printf("received signal %s, shutting down", s)

		ic.Quit()

		ctx, cfunc := context.WithTimeout(ctx, time.Second*5)
		defer cfunc()
		if err := hs.Shutdown(ctx); err != nil {
			log.Fatal(err)
		}
	}
}
<|endoftext|>


<commit_before>package command

import (
	"bytes"
	"encoding/json"
	"flag"
	"fmt"
	"log"
	"os"
	"strings"
	"sync"
	"syscall"
	"time"

	"github.com/Shopify/sarama"
	"github.com/funkygao/gafka/ctx"
	"github.com/funkygao/gafka/zk"
	"github.com/funkygao/go-metrics"
	"github.com/funkygao/gocli"
	"github.com/funkygao/golib/color"
	"github.com/funkygao/golib/gofmt"
	"github.com/funkygao/golib/signal"
)

var (
	stats *peekStats
)

type peekStats struct {
	MsgCountPerSecond metrics.Meter
	MsgBytesPerSecond metrics.Meter
}

func newPeekStats() *peekStats {
	this := &peekStats{
		MsgCountPerSecond: metrics.NewMeter(),
		MsgBytesPerSecond: metrics.NewMeter(),
	}

	metrics.Register("msg.count.per.second", this.MsgCountPerSecond)
	metrics.Register("msg.bytes.per.second", this.MsgBytesPerSecond)
	return this
}

func (this *peekStats) start() {
	metrics.Log(metrics.DefaultRegistry, time.Second*10,
		log.New(os.Stdout, "metrics: ", log.Lmicroseconds))
}

type Peek struct {
	Ui  cli.Ui
	Cmd string

	offset   int64
	lastN    int64 // peek the most recent N messages
	colorize bool
	limit    int
	quit     chan struct{}
	once     sync.Once
	column   string
	pretty   bool
	bodyOnly bool
}

func (this *Peek) Run(args []string) (exitCode int) {
	var (
		cluster      string
		zone         string
		topicPattern string
		partitionId  int
		wait         time.Duration
		silence      bool
	)
	cmdFlags := flag.NewFlagSet("peek", flag.ContinueOnError)
	cmdFlags.Usage = func() { this.Ui.Output(this.Help()) }
	cmdFlags.StringVar(&zone, "z", ctx.ZkDefaultZone(), "")
	cmdFlags.StringVar(&cluster, "c", "", "")
	cmdFlags.StringVar(&topicPattern, "t", "", "")
	cmdFlags.IntVar(&partitionId, "p", 0, "")
	cmdFlags.BoolVar(&this.colorize, "color", true, "")
	cmdFlags.Int64Var(&this.lastN, "last", -1, "")
	cmdFlags.BoolVar(&this.pretty, "pretty", false, "")
	cmdFlags.IntVar(&this.limit, "n", -1, "")
	cmdFlags.StringVar(&this.column, "col", "", "")
	cmdFlags.Int64Var(&this.offset, "offset", sarama.OffsetNewest, "")
	cmdFlags.BoolVar(&silence, "s", false, "")
	cmdFlags.DurationVar(&wait, "d", time.Hour, "")
	cmdFlags.BoolVar(&this.bodyOnly, "body", false, "")
	if err := cmdFlags.Parse(args); err != nil {
		return 1
	}

	if this.pretty {
		this.bodyOnly = true
	}

	this.quit = make(chan struct{})

	if silence {
		stats := newPeekStats()
		go stats.start()
	}

	zkzone := zk.NewZkZone(zk.DefaultConfig(zone, ctx.ZoneZkAddrs(zone)))
	msgChan := make(chan *sarama.ConsumerMessage, 20000) // msg aggerator channel
	if cluster == "" {
		zkzone.ForSortedClusters(func(zkcluster *zk.ZkCluster) {
			this.consumeCluster(zkcluster, topicPattern, partitionId, msgChan)
		})
	} else {
		zkcluster := zkzone.NewCluster(cluster)
		this.consumeCluster(zkcluster, topicPattern, partitionId, msgChan)
	}

	signal.RegisterSignalsHandler(func(sig os.Signal) {
		log.Printf("received signal: %s", strings.ToUpper(sig.String()))
		log.Println("quiting...")

		this.once.Do(func() {
			close(this.quit)
		})
	}, syscall.SIGINT, syscall.SIGTERM)

	var (
		startAt = time.Now()
		msg     *sarama.ConsumerMessage
		total   int
		bytesN  int64
	)

	var (
		j          map[string]string
		prettyJSON bytes.Buffer
	)

LOOP:
	for {
		if time.Since(startAt) >= wait {
			this.Ui.Output(fmt.Sprintf("Total: %s msgs, %s, elapsed: %s",
				gofmt.Comma(int64(total)), gofmt.ByteSize(bytesN), time.Since(startAt)))
			elapsed := time.Since(startAt).Seconds()
			if elapsed > 1. {
				this.Ui.Output(fmt.Sprintf("Speed: %d/s", total/int(elapsed)))
				this.Ui.Output(fmt.Sprintf("Size : %s/msg", gofmt.ByteSize(bytesN/int64(total))))
			}

			return
		}

		select {
		case <-this.quit:
			this.Ui.Output(fmt.Sprintf("Total: %s msgs, %s, elapsed: %s",
				gofmt.Comma(int64(total)), gofmt.ByteSize(bytesN), time.Since(startAt)))
			elapsed := time.Since(startAt).Seconds()
			if elapsed > 1. {
				this.Ui.Output(fmt.Sprintf("Speed: %d/s", total/int(elapsed)))
				this.Ui.Output(fmt.Sprintf("Size : %s/msg", gofmt.ByteSize(bytesN/int64(total))))
			}

			return

		case <-time.After(time.Second):
			continue

		case msg = <-msgChan:
			if silence {
				stats.MsgCountPerSecond.Mark(1)
				stats.MsgBytesPerSecond.Mark(int64(len(msg.Value)))
			} else {
				if this.column != "" {
					if err := json.Unmarshal(msg.Value, &j); err != nil {
						this.Ui.Error(err.Error())
					} else {
						if this.bodyOnly {
							if this.pretty {
								if err = json.Indent(&prettyJSON, []byte(j[this.column]), "", "    "); err != nil {
									fmt.Println(err.Error())
								} else {
									fmt.Println(string(prettyJSON.Bytes()))
								}
							} else {
								fmt.Println(j[this.column])
							}
						} else if this.colorize {
							this.Ui.Output(fmt.Sprintf("%s/%d %s k:%s v:%s",
								color.Green(msg.Topic), msg.Partition,
								gofmt.Comma(msg.Offset), string(msg.Key), j[this.column]))
						} else {
							// colored UI will have invisible chars output
							fmt.Println(fmt.Sprintf("%s/%d %s k:%s v:%s",
								msg.Topic, msg.Partition,
								gofmt.Comma(msg.Offset), string(msg.Key), j[this.column]))
						}
					}

				} else {
					if this.bodyOnly {
						if this.pretty {
							json.Indent(&prettyJSON, msg.Value, "", "    ")
							fmt.Println(string(prettyJSON.Bytes()))
						} else {
							fmt.Println(string(msg.Value))
						}
					} else if this.colorize {
						this.Ui.Output(fmt.Sprintf("%s/%d %s k:%s, v:%s",
							color.Green(msg.Topic), msg.Partition,
							gofmt.Comma(msg.Offset), string(msg.Key), string(msg.Value)))
					} else {
						// colored UI will have invisible chars output
						fmt.Println(fmt.Sprintf("%s/%d %s k:%s, v:%s",
							msg.Topic, msg.Partition,
							gofmt.Comma(msg.Offset), string(msg.Key), string(msg.Value)))
					}
				}
			}

			total++
			bytesN += int64(len(msg.Value))

			if this.limit > 0 && total >= this.limit {
				break LOOP

			}
			if this.lastN > 0 && total >= int(this.lastN) {
				break LOOP
			}

		}
	}

	return
}

func (this *Peek) consumeCluster(zkcluster *zk.ZkCluster, topicPattern string,
	partitionId int, msgChan chan *sarama.ConsumerMessage) {
	brokerList := zkcluster.BrokerList()
	if len(brokerList) == 0 {
		return
	}
	kfk, err := sarama.NewClient(brokerList, sarama.NewConfig())
	if err != nil {
		this.Ui.Output(err.Error())
		return
	}
	//defer kfk.Close() // FIXME how to close it

	topics, err := kfk.Topics()
	if err != nil {
		this.Ui.Output(err.Error())
		return
	}

	for _, t := range topics {
		if patternMatched(t, topicPattern) {
			go this.simpleConsumeTopic(kfk, t, int32(partitionId), msgChan)
		}
	}

}

func (this *Peek) simpleConsumeTopic(kfk sarama.Client, topic string, partitionId int32,
	msgCh chan *sarama.ConsumerMessage) {
	consumer, err := sarama.NewConsumerFromClient(kfk)
	if err != nil {
		panic(err)
	}
	defer consumer.Close()

	if partitionId == -1 {
		// all partitions
		partitions, err := kfk.Partitions(topic)
		if err != nil {
			panic(err)
		}

		for _, p := range partitions {
			offset := this.offset
			if this.lastN > 0 {
				latestOffset, err := kfk.GetOffset(topic, p, sarama.OffsetNewest)
				swallow(err)

				oldestOffset, err := kfk.GetOffset(topic, p, sarama.OffsetOldest)
				swallow(err)

				offset = latestOffset - this.lastN
				if offset < oldestOffset {
					offset = oldestOffset
				}

				if offset == 0 {
					// no message in store
					return
				}
			}

			go this.consumePartition(kfk, consumer, topic, p, msgCh, offset)
		}

	} else {
		offset := this.offset
		if this.lastN > 0 {
			latestOffset, err := kfk.GetOffset(topic, partitionId, sarama.OffsetNewest)
			swallow(err)
			offset = latestOffset - this.lastN
			if offset < 0 {
				offset = sarama.OffsetOldest
			}
		}
		this.consumePartition(kfk, consumer, topic, partitionId, msgCh, offset)
	}

}

func (this *Peek) consumePartition(kfk sarama.Client, consumer sarama.Consumer,
	topic string, partitionId int32, msgCh chan *sarama.ConsumerMessage, offset int64) {
	p, err := consumer.ConsumePartition(topic, partitionId, offset)
	if err != nil {
		this.Ui.Error(fmt.Sprintf("%s/%d: offset=%d %v", topic, partitionId, offset, err))
		return
	}
	defer p.Close()

	n := int64(0)
	for {
		select {
		case <-this.quit:
			return

		case msg := <-p.Messages():
			msgCh <- msg

			n++
			if this.lastN > 0 && n >= this.lastN {
				return
			}
		}
	}
}

func (*Peek) Synopsis() string {
	return "Peek kafka cluster messages ongoing from any offset"
}

func (this *Peek) Help() string {
	help := fmt.Sprintf(`
Usage: %s peek [options]

    Peek kafka cluster messages ongoing from any offset

Options:

    -z zone
      Default %s

    -c cluster

    -t topic pattern

    -p partition id
      -1 will peek all partitions of a topic

    -pretty
      Pretty print the json message body

    -col json column name
      Will json decode message and extract specified column value only

    -last n
      Peek the most recent N messages

    -offset message offset value
      -1 OffsetNewest, -2 OffsetOldest.
      You can specify your own offset.
      Default -1(OffsetNewest)

    -n count
      Limit how many messages to consume

    -d duration
      Limit how long to keep peeking
      e,g. -d 5m

    -body
      Only display message body

    -s
      Silence mode, only display statastics instead of message content

    -color
      Enable colorized output
`, this.Cmd, ctx.ZkDefaultZone())
	return strings.TrimSpace(help)
}
<commit_msg>fix issue: divide by zero<commit_after>package command

import (
	"bytes"
	"encoding/json"
	"flag"
	"fmt"
	"log"
	"os"
	"strings"
	"sync"
	"syscall"
	"time"

	"github.com/Shopify/sarama"
	"github.com/funkygao/gafka/ctx"
	"github.com/funkygao/gafka/zk"
	"github.com/funkygao/go-metrics"
	"github.com/funkygao/gocli"
	"github.com/funkygao/golib/color"
	"github.com/funkygao/golib/gofmt"
	"github.com/funkygao/golib/signal"
)

var (
	stats *peekStats
)

type peekStats struct {
	MsgCountPerSecond metrics.Meter
	MsgBytesPerSecond metrics.Meter
}

func newPeekStats() *peekStats {
	this := &peekStats{
		MsgCountPerSecond: metrics.NewMeter(),
		MsgBytesPerSecond: metrics.NewMeter(),
	}

	metrics.Register("msg.count.per.second", this.MsgCountPerSecond)
	metrics.Register("msg.bytes.per.second", this.MsgBytesPerSecond)
	return this
}

func (this *peekStats) start() {
	metrics.Log(metrics.DefaultRegistry, time.Second*10,
		log.New(os.Stdout, "metrics: ", log.Lmicroseconds))
}

type Peek struct {
	Ui  cli.Ui
	Cmd string

	offset   int64
	lastN    int64 // peek the most recent N messages
	colorize bool
	limit    int
	quit     chan struct{}
	once     sync.Once
	column   string
	pretty   bool
	bodyOnly bool
}

func (this *Peek) Run(args []string) (exitCode int) {
	var (
		cluster      string
		zone         string
		topicPattern string
		partitionId  int
		wait         time.Duration
		silence      bool
	)
	cmdFlags := flag.NewFlagSet("peek", flag.ContinueOnError)
	cmdFlags.Usage = func() { this.Ui.Output(this.Help()) }
	cmdFlags.StringVar(&zone, "z", ctx.ZkDefaultZone(), "")
	cmdFlags.StringVar(&cluster, "c", "", "")
	cmdFlags.StringVar(&topicPattern, "t", "", "")
	cmdFlags.IntVar(&partitionId, "p", 0, "")
	cmdFlags.BoolVar(&this.colorize, "color", true, "")
	cmdFlags.Int64Var(&this.lastN, "last", -1, "")
	cmdFlags.BoolVar(&this.pretty, "pretty", false, "")
	cmdFlags.IntVar(&this.limit, "n", -1, "")
	cmdFlags.StringVar(&this.column, "col", "", "")
	cmdFlags.Int64Var(&this.offset, "offset", sarama.OffsetNewest, "")
	cmdFlags.BoolVar(&silence, "s", false, "")
	cmdFlags.DurationVar(&wait, "d", time.Hour, "")
	cmdFlags.BoolVar(&this.bodyOnly, "body", false, "")
	if err := cmdFlags.Parse(args); err != nil {
		return 1
	}

	if this.pretty {
		this.bodyOnly = true
	}

	this.quit = make(chan struct{})

	if silence {
		stats := newPeekStats()
		go stats.start()
	}

	zkzone := zk.NewZkZone(zk.DefaultConfig(zone, ctx.ZoneZkAddrs(zone)))
	msgChan := make(chan *sarama.ConsumerMessage, 20000) // msg aggerator channel
	if cluster == "" {
		zkzone.ForSortedClusters(func(zkcluster *zk.ZkCluster) {
			this.consumeCluster(zkcluster, topicPattern, partitionId, msgChan)
		})
	} else {
		zkcluster := zkzone.NewCluster(cluster)
		this.consumeCluster(zkcluster, topicPattern, partitionId, msgChan)
	}

	signal.RegisterSignalsHandler(func(sig os.Signal) {
		log.Printf("received signal: %s", strings.ToUpper(sig.String()))
		log.Println("quiting...")

		this.once.Do(func() {
			close(this.quit)
		})
	}, syscall.SIGINT, syscall.SIGTERM)

	var (
		startAt = time.Now()
		msg     *sarama.ConsumerMessage
		total   int
		bytesN  int64
	)

	var (
		j          map[string]string
		prettyJSON bytes.Buffer
	)

LOOP:
	for {
		if time.Since(startAt) >= wait {
			this.Ui.Output(fmt.Sprintf("Total: %s msgs, %s, elapsed: %s",
				gofmt.Comma(int64(total)), gofmt.ByteSize(bytesN), time.Since(startAt)))
			elapsed := time.Since(startAt).Seconds()
			if elapsed > 1. {
				this.Ui.Output(fmt.Sprintf("Speed: %d/s", total/int(elapsed)))
				if total > 0 {
					this.Ui.Output(fmt.Sprintf("Size : %s/msg", gofmt.ByteSize(bytesN/int64(total))))
				}
			}

			return
		}

		select {
		case <-this.quit:
			this.Ui.Output(fmt.Sprintf("Total: %s msgs, %s, elapsed: %s",
				gofmt.Comma(int64(total)), gofmt.ByteSize(bytesN), time.Since(startAt)))
			elapsed := time.Since(startAt).Seconds()
			if elapsed > 1. {
				this.Ui.Output(fmt.Sprintf("Speed: %d/s", total/int(elapsed)))
				this.Ui.Output(fmt.Sprintf("Size : %s/msg", gofmt.ByteSize(bytesN/int64(total))))
			}

			return

		case <-time.After(time.Second):
			continue

		case msg = <-msgChan:
			if silence {
				stats.MsgCountPerSecond.Mark(1)
				stats.MsgBytesPerSecond.Mark(int64(len(msg.Value)))
			} else {
				if this.column != "" {
					if err := json.Unmarshal(msg.Value, &j); err != nil {
						this.Ui.Error(err.Error())
					} else {
						if this.bodyOnly {
							if this.pretty {
								if err = json.Indent(&prettyJSON, []byte(j[this.column]), "", "    "); err != nil {
									fmt.Println(err.Error())
								} else {
									fmt.Println(string(prettyJSON.Bytes()))
								}
							} else {
								fmt.Println(j[this.column])
							}
						} else if this.colorize {
							this.Ui.Output(fmt.Sprintf("%s/%d %s k:%s v:%s",
								color.Green(msg.Topic), msg.Partition,
								gofmt.Comma(msg.Offset), string(msg.Key), j[this.column]))
						} else {
							// colored UI will have invisible chars output
							fmt.Println(fmt.Sprintf("%s/%d %s k:%s v:%s",
								msg.Topic, msg.Partition,
								gofmt.Comma(msg.Offset), string(msg.Key), j[this.column]))
						}
					}

				} else {
					if this.bodyOnly {
						if this.pretty {
							json.Indent(&prettyJSON, msg.Value, "", "    ")
							fmt.Println(string(prettyJSON.Bytes()))
						} else {
							fmt.Println(string(msg.Value))
						}
					} else if this.colorize {
						this.Ui.Output(fmt.Sprintf("%s/%d %s k:%s, v:%s",
							color.Green(msg.Topic), msg.Partition,
							gofmt.Comma(msg.Offset), string(msg.Key), string(msg.Value)))
					} else {
						// colored UI will have invisible chars output
						fmt.Println(fmt.Sprintf("%s/%d %s k:%s, v:%s",
							msg.Topic, msg.Partition,
							gofmt.Comma(msg.Offset), string(msg.Key), string(msg.Value)))
					}
				}
			}

			total++
			bytesN += int64(len(msg.Value))

			if this.limit > 0 && total >= this.limit {
				break LOOP

			}
			if this.lastN > 0 && total >= int(this.lastN) {
				break LOOP
			}

		}
	}

	return
}

func (this *Peek) consumeCluster(zkcluster *zk.ZkCluster, topicPattern string,
	partitionId int, msgChan chan *sarama.ConsumerMessage) {
	brokerList := zkcluster.BrokerList()
	if len(brokerList) == 0 {
		return
	}
	kfk, err := sarama.NewClient(brokerList, sarama.NewConfig())
	if err != nil {
		this.Ui.Output(err.Error())
		return
	}
	//defer kfk.Close() // FIXME how to close it

	topics, err := kfk.Topics()
	if err != nil {
		this.Ui.Output(err.Error())
		return
	}

	for _, t := range topics {
		if patternMatched(t, topicPattern) {
			go this.simpleConsumeTopic(kfk, t, int32(partitionId), msgChan)
		}
	}

}

func (this *Peek) simpleConsumeTopic(kfk sarama.Client, topic string, partitionId int32,
	msgCh chan *sarama.ConsumerMessage) {
	consumer, err := sarama.NewConsumerFromClient(kfk)
	if err != nil {
		panic(err)
	}
	defer consumer.Close()

	if partitionId == -1 {
		// all partitions
		partitions, err := kfk.Partitions(topic)
		if err != nil {
			panic(err)
		}

		for _, p := range partitions {
			offset := this.offset
			if this.lastN > 0 {
				latestOffset, err := kfk.GetOffset(topic, p, sarama.OffsetNewest)
				swallow(err)

				oldestOffset, err := kfk.GetOffset(topic, p, sarama.OffsetOldest)
				swallow(err)

				offset = latestOffset - this.lastN
				if offset < oldestOffset {
					offset = oldestOffset
				}

				if offset == 0 {
					// no message in store
					return
				}
			}

			go this.consumePartition(kfk, consumer, topic, p, msgCh, offset)
		}

	} else {
		offset := this.offset
		if this.lastN > 0 {
			latestOffset, err := kfk.GetOffset(topic, partitionId, sarama.OffsetNewest)
			swallow(err)
			offset = latestOffset - this.lastN
			if offset < 0 {
				offset = sarama.OffsetOldest
			}
		}
		this.consumePartition(kfk, consumer, topic, partitionId, msgCh, offset)
	}

}

func (this *Peek) consumePartition(kfk sarama.Client, consumer sarama.Consumer,
	topic string, partitionId int32, msgCh chan *sarama.ConsumerMessage, offset int64) {
	p, err := consumer.ConsumePartition(topic, partitionId, offset)
	if err != nil {
		this.Ui.Error(fmt.Sprintf("%s/%d: offset=%d %v", topic, partitionId, offset, err))
		return
	}
	defer p.Close()

	n := int64(0)
	for {
		select {
		case <-this.quit:
			return

		case msg := <-p.Messages():
			msgCh <- msg

			n++
			if this.lastN > 0 && n >= this.lastN {
				return
			}
		}
	}
}

func (*Peek) Synopsis() string {
	return "Peek kafka cluster messages ongoing from any offset"
}

func (this *Peek) Help() string {
	help := fmt.Sprintf(`
Usage: %s peek [options]

    Peek kafka cluster messages ongoing from any offset

Options:

    -z zone
      Default %s

    -c cluster

    -t topic pattern

    -p partition id
      -1 will peek all partitions of a topic

    -pretty
      Pretty print the json message body

    -col json column name
      Will json decode message and extract specified column value only

    -last n
      Peek the most recent N messages

    -offset message offset value
      -1 OffsetNewest, -2 OffsetOldest.
      You can specify your own offset.
      Default -1(OffsetNewest)

    -n count
      Limit how many messages to consume

    -d duration
      Limit how long to keep peeking
      e,g. -d 5m

    -body
      Only display message body

    -s
      Silence mode, only display statastics instead of message content

    -color
      Enable colorized output
`, this.Cmd, ctx.ZkDefaultZone())
	return strings.TrimSpace(help)
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/wojtechnology/glacier/core"
	"github.com/wojtechnology/glacier/crypto"
	"github.com/wojtechnology/glacier/logging"
	"github.com/wojtechnology/glacier/loop"
	"github.com/wojtechnology/glacier/meddb"
	"os"
)

func initBlockchain() (*core.Blockchain, error) {
	addresses := []string{"localhost"}
	database := "prod"

	// Init db that contains meddb
	db, err := meddb.NewRethinkBlockchainDB(addresses, database)
	if err != nil {
		return nil, err
	}

	// Init bigtable that contains cells
	bt, err := meddb.NewRethinkBigtable(addresses, database)
	if err != nil {
		return nil, err
	}

	privKey, err := crypto.NewPrivateKey()
	if err != nil {
		return nil, err
	}

	bc := core.NewBlockchain(
		db,
		bt,
		&core.Node{PubKey: []byte{69}, PrivKey: privKey},
		[]*core.Node{&core.Node{PubKey: []byte{69}}},
	)
	return bc, nil
}

func main() {
	bc, err := initBlockchain()
	if err != nil {
		panic(err)
	}
	logging.InitLoggers(os.Stdout, os.Stderr)
	logging.Info("Glacier is now running!")

	errChannel := make(chan error)
	go loop.IOLoop(bc, errChannel)
	go loop.ReassignTransactionsLoop(bc, errChannel)
	go loop.AddBlockLoop(bc, errChannel)
	go loop.VoteOnBlocksLoop(bc, errChannel)

	err = <-errChannel
	panic(err)
}
<commit_msg>Move around import<commit_after>package main

import (
	"os"

	"github.com/wojtechnology/glacier/core"
	"github.com/wojtechnology/glacier/crypto"
	"github.com/wojtechnology/glacier/logging"
	"github.com/wojtechnology/glacier/loop"
	"github.com/wojtechnology/glacier/meddb"
)

func initBlockchain() (*core.Blockchain, error) {
	addresses := []string{"localhost"}
	database := "prod"

	// Init db that contains meddb
	db, err := meddb.NewRethinkBlockchainDB(addresses, database)
	if err != nil {
		return nil, err
	}

	// Init bigtable that contains cells
	bt, err := meddb.NewRethinkBigtable(addresses, database)
	if err != nil {
		return nil, err
	}

	privKey, err := crypto.NewPrivateKey()
	if err != nil {
		return nil, err
	}

	bc := core.NewBlockchain(
		db,
		bt,
		&core.Node{PubKey: []byte{69}, PrivKey: privKey},
		[]*core.Node{&core.Node{PubKey: []byte{69}}},
	)
	return bc, nil
}

func main() {
	bc, err := initBlockchain()
	if err != nil {
		panic(err)
	}
	logging.InitLoggers(os.Stdout, os.Stderr)
	logging.Info("Glacier is now running!")

	errChannel := make(chan error)
	go loop.IOLoop(bc, errChannel)
	go loop.ReassignTransactionsLoop(bc, errChannel)
	go loop.AddBlockLoop(bc, errChannel)
	go loop.VoteOnBlocksLoop(bc, errChannel)

	err = <-errChannel
	panic(err)
}
<|endoftext|>


<commit_before>/*
Copyright The Helm 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 main

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

	"github.com/spf13/cobra"

	"helm.sh/helm/v3/cmd/helm/require"
)

const completionDesc = `
Generate autocompletion scripts for Helm for the specified shell.
`
const bashCompDesc = `
Generate the autocompletion script for Helm for the bash shell.

To load completions in your current shell session:
$ source <(helm completion bash)

To load completions for every new session, execute once:
Linux:
  $ helm completion bash > /etc/bash_completion.d/helm
MacOS:
  $ helm completion bash > /usr/local/etc/bash_completion.d/helm
`

const zshCompDesc = `
Generate the autocompletion script for Helm for the zsh shell.

To load completions in your current shell session:
$ source <(helm completion zsh)

To load completions for every new session, execute once:
$ helm completion zsh > "${fpath[1]}/_helm"
`

const fishCompDesc = `
Generate the autocompletion script for Helm for the fish shell.

To load completions in your current shell session:
$ helm completion fish | source

To load completions for every new session, execute once:
$ helm completion fish > ~/.config/fish/completions/helm.fish

You will need to start a new shell for this setup to take effect.
`

const (
	noDescFlagName = "no-descriptions"
	noDescFlagText = "disable completion descriptions"
)

var disableCompDescriptions bool

func newCompletionCmd(out io.Writer) *cobra.Command {
	cmd := &cobra.Command{
		Use:   "completion",
		Short: "generate autocompletion scripts for the specified shell",
		Long:  completionDesc,
		Args:  require.NoArgs,
	}

	bash := &cobra.Command{
		Use:                   "bash",
		Short:                 "generate autocompletion script for bash",
		Long:                  bashCompDesc,
		Args:                  require.NoArgs,
		DisableFlagsInUseLine: true,
		ValidArgsFunction:     noCompletions,
		RunE: func(cmd *cobra.Command, args []string) error {
			return runCompletionBash(out, cmd)
		},
	}

	zsh := &cobra.Command{
		Use:               "zsh",
		Short:             "generate autocompletion script for zsh",
		Long:              zshCompDesc,
		Args:              require.NoArgs,
		ValidArgsFunction: noCompletions,
		RunE: func(cmd *cobra.Command, args []string) error {
			return runCompletionZsh(out, cmd)
		},
	}
	zsh.Flags().BoolVar(&disableCompDescriptions, noDescFlagName, false, noDescFlagText)

	fish := &cobra.Command{
		Use:               "fish",
		Short:             "generate autocompletion script for fish",
		Long:              fishCompDesc,
		Args:              require.NoArgs,
		ValidArgsFunction: noCompletions,
		RunE: func(cmd *cobra.Command, args []string) error {
			return runCompletionFish(out, cmd)
		},
	}
	fish.Flags().BoolVar(&disableCompDescriptions, noDescFlagName, false, noDescFlagText)

	cmd.AddCommand(bash, zsh, fish)

	return cmd
}

func runCompletionBash(out io.Writer, cmd *cobra.Command) error {
	err := cmd.Root().GenBashCompletion(out)

	// In case the user renamed the helm binary (e.g., to be able to run
	// both helm2 and helm3), we hook the new binary name to the completion function
	if binary := filepath.Base(os.Args[0]); binary != "helm" {
		renamedBinaryHook := `
# Hook the command used to generate the completion script
# to the helm completion function to handle the case where
# the user renamed the helm binary
if [[ $(type -t compopt) = "builtin" ]]; then
    complete -o default -F __start_helm %[1]s
else
    complete -o default -o nospace -F __start_helm %[1]s
fi
`
		fmt.Fprintf(out, renamedBinaryHook, binary)
	}

	return err
}

func runCompletionZsh(out io.Writer, cmd *cobra.Command) error {
	var err error
	if disableCompDescriptions {
		err = cmd.Root().GenZshCompletionNoDesc(out)
	} else {
		err = cmd.Root().GenZshCompletion(out)
	}

	// In case the user renamed the helm binary (e.g., to be able to run
	// both helm2 and helm3), we hook the new binary name to the completion function
	if binary := filepath.Base(os.Args[0]); binary != "helm" {
		renamedBinaryHook := `
# Hook the command used to generate the completion script
# to the helm completion function to handle the case where
# the user renamed the helm binary
compdef _helm %[1]s
`
		fmt.Fprintf(out, renamedBinaryHook, binary)
	}

	// Cobra doesn't source zsh completion file, explicitly doing it here
	fmt.Fprintf(out, "compdef _helm helm")

	return err
}

func runCompletionFish(out io.Writer, cmd *cobra.Command) error {
	return cmd.Root().GenFishCompletion(out, !disableCompDescriptions)
}

// Function to disable file completion
func noCompletions(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
	return nil, cobra.ShellCompDirectiveNoFileComp
}
<commit_msg>Improve markdown rendering of commands help for shell completion<commit_after>/*
Copyright The Helm 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 main

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

	"github.com/spf13/cobra"

	"helm.sh/helm/v3/cmd/helm/require"
)

const completionDesc = `
Generate autocompletion scripts for Helm for the specified shell.
`
const bashCompDesc = `
Generate the autocompletion script for Helm for the bash shell.

To load completions in your current shell session:

    source <(helm completion bash)

To load completions for every new session, execute once:
- Linux:

      helm completion bash > /etc/bash_completion.d/helm

- MacOS:

      helm completion bash > /usr/local/etc/bash_completion.d/helm
`

const zshCompDesc = `
Generate the autocompletion script for Helm for the zsh shell.

To load completions in your current shell session:

    source <(helm completion zsh)

To load completions for every new session, execute once:

    helm completion zsh > "${fpath[1]}/_helm"
`

const fishCompDesc = `
Generate the autocompletion script for Helm for the fish shell.

To load completions in your current shell session:

    helm completion fish | source

To load completions for every new session, execute once:

    helm completion fish > ~/.config/fish/completions/helm.fish

You will need to start a new shell for this setup to take effect.
`

const (
	noDescFlagName = "no-descriptions"
	noDescFlagText = "disable completion descriptions"
)

var disableCompDescriptions bool

func newCompletionCmd(out io.Writer) *cobra.Command {
	cmd := &cobra.Command{
		Use:   "completion",
		Short: "generate autocompletion scripts for the specified shell",
		Long:  completionDesc,
		Args:  require.NoArgs,
	}

	bash := &cobra.Command{
		Use:                   "bash",
		Short:                 "generate autocompletion script for bash",
		Long:                  bashCompDesc,
		Args:                  require.NoArgs,
		DisableFlagsInUseLine: true,
		ValidArgsFunction:     noCompletions,
		RunE: func(cmd *cobra.Command, args []string) error {
			return runCompletionBash(out, cmd)
		},
	}

	zsh := &cobra.Command{
		Use:               "zsh",
		Short:             "generate autocompletion script for zsh",
		Long:              zshCompDesc,
		Args:              require.NoArgs,
		ValidArgsFunction: noCompletions,
		RunE: func(cmd *cobra.Command, args []string) error {
			return runCompletionZsh(out, cmd)
		},
	}
	zsh.Flags().BoolVar(&disableCompDescriptions, noDescFlagName, false, noDescFlagText)

	fish := &cobra.Command{
		Use:               "fish",
		Short:             "generate autocompletion script for fish",
		Long:              fishCompDesc,
		Args:              require.NoArgs,
		ValidArgsFunction: noCompletions,
		RunE: func(cmd *cobra.Command, args []string) error {
			return runCompletionFish(out, cmd)
		},
	}
	fish.Flags().BoolVar(&disableCompDescriptions, noDescFlagName, false, noDescFlagText)

	cmd.AddCommand(bash, zsh, fish)

	return cmd
}

func runCompletionBash(out io.Writer, cmd *cobra.Command) error {
	err := cmd.Root().GenBashCompletion(out)

	// In case the user renamed the helm binary (e.g., to be able to run
	// both helm2 and helm3), we hook the new binary name to the completion function
	if binary := filepath.Base(os.Args[0]); binary != "helm" {
		renamedBinaryHook := `
# Hook the command used to generate the completion script
# to the helm completion function to handle the case where
# the user renamed the helm binary
if [[ $(type -t compopt) = "builtin" ]]; then
    complete -o default -F __start_helm %[1]s
else
    complete -o default -o nospace -F __start_helm %[1]s
fi
`
		fmt.Fprintf(out, renamedBinaryHook, binary)
	}

	return err
}

func runCompletionZsh(out io.Writer, cmd *cobra.Command) error {
	var err error
	if disableCompDescriptions {
		err = cmd.Root().GenZshCompletionNoDesc(out)
	} else {
		err = cmd.Root().GenZshCompletion(out)
	}

	// In case the user renamed the helm binary (e.g., to be able to run
	// both helm2 and helm3), we hook the new binary name to the completion function
	if binary := filepath.Base(os.Args[0]); binary != "helm" {
		renamedBinaryHook := `
# Hook the command used to generate the completion script
# to the helm completion function to handle the case where
# the user renamed the helm binary
compdef _helm %[1]s
`
		fmt.Fprintf(out, renamedBinaryHook, binary)
	}

	// Cobra doesn't source zsh completion file, explicitly doing it here
	fmt.Fprintf(out, "compdef _helm helm")

	return err
}

func runCompletionFish(out io.Writer, cmd *cobra.Command) error {
	return cmd.Root().GenFishCompletion(out, !disableCompDescriptions)
}

// Function to disable file completion
func noCompletions(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
	return nil, cobra.ShellCompDirectiveNoFileComp
}
<|endoftext|>


<commit_before>package main

import (
	"crypto/rand"
	"crypto/rsa"
	"crypto/tls"
	"crypto/x509"
	"encoding/pem"
	"flag"
	"fmt"
	"math/big"
	"net"

	log "github.com/golang/glog"
	"github.com/openconfig/lemming"
	"github.com/openconfig/lemming/sysrib"
	"github.com/spf13/pflag"
	"github.com/spf13/viper"
	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials"
	"google.golang.org/grpc/credentials/insecure"
)

var (
	port   = pflag.Int("port", 6030, "localhost port to listen to.")
	target = pflag.String("target", "fakedut", "name of the fake target")
	// nolint:unused,varcheck
	enableDataplane = pflag.Bool("enable_dataplane", false, "Controls whether to enable dataplane")
	enableTLS       = pflag.Bool("enable_tls", false, "Controls whether to enable TLS for gNXI services. If enabled and TLS key/cert path unspecified, a generated cert is used.")
)

func main() {
	pflag.CommandLine.AddGoFlagSet(flag.CommandLine)
	pflag.Parse()
	viper.BindPFlags(pflag.CommandLine)

	lis, err := net.Listen("tcp", fmt.Sprintf(":%d", *port))
	if err != nil {
		log.Fatalf("Failed to start listener: %v", err)
	}
	creds, err := newCreds()
	if err != nil {
		log.Fatalf("failed to create credentials: %v", err)
	}

	f, err := lemming.New(lis, *target, sysrib.ZAPI_ADDR, grpc.Creds(creds))
	if err != nil {
		log.Fatalf("Failed to start lemming: %v", err)
	}
	defer f.Stop()

	log.Info("lemming initialization complete")
	select {}
}

// newCreds returns either insecure or tls credentials, depending the enable_tls flag.
// TODO: figure out long term plan for certs, this implementation is here to unblock using Ondatra KNEBind.
func newCreds() (credentials.TransportCredentials, error) {
	if !*enableTLS {
		return insecure.NewCredentials(), nil
	}
	key, err := rsa.GenerateKey(rand.Reader, 2048)
	if err != nil {
		return nil, err
	}
	tmpl := &x509.Certificate{
		SerialNumber: big.NewInt(1234),
	}

	certDer, err := x509.CreateCertificate(rand.Reader, tmpl, tmpl, &key.PublicKey, key)
	if err != nil {
		return nil, err
	}
	certPem := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: certDer})

	keyDer, err := x509.MarshalPKCS8PrivateKey(key)
	if err != nil {
		return nil, err
	}
	keyPem := pem.EncodeToMemory(&pem.Block{Type: "PRIVATE KEY", Bytes: keyDer})

	serverCert, err := tls.X509KeyPair(certPem, keyPem)
	if err != nil {
		return nil, err
	}
	return credentials.NewTLS(&tls.Config{
		MinVersion:   tls.VersionTLS13,
		Certificates: []tls.Certificate{serverCert},
	}), nil
}
<commit_msg>Fix typo<commit_after>package main

import (
	"crypto/rand"
	"crypto/rsa"
	"crypto/tls"
	"crypto/x509"
	"encoding/pem"
	"flag"
	"fmt"
	"math/big"
	"net"

	log "github.com/golang/glog"
	"github.com/openconfig/lemming"
	"github.com/openconfig/lemming/sysrib"
	"github.com/spf13/pflag"
	"github.com/spf13/viper"
	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials"
	"google.golang.org/grpc/credentials/insecure"
)

var (
	port   = pflag.Int("port", 6030, "localhost port to listen to.")
	target = pflag.String("target", "fakedut", "name of the fake target")
	// nolint:unused,varcheck
	enableDataplane = pflag.Bool("enable_dataplane", false, "Controls whether to enable dataplane")
	enableTLS       = pflag.Bool("enable_tls", false, "Controls whether to enable TLS for gNXI services. If enabled and TLS key/cert path unspecified, a generated cert is used.")
)

func main() {
	pflag.CommandLine.AddGoFlagSet(flag.CommandLine)
	pflag.Parse()
	viper.BindPFlags(pflag.CommandLine)

	lis, err := net.Listen("tcp", fmt.Sprintf(":%d", *port))
	if err != nil {
		log.Fatalf("Failed to start listener: %v", err)
	}
	creds, err := newCreds()
	if err != nil {
		log.Fatalf("failed to create credentials: %v", err)
	}

	f, err := lemming.New(lis, *target, sysrib.ZAPIAddr, grpc.Creds(creds))
	if err != nil {
		log.Fatalf("Failed to start lemming: %v", err)
	}
	defer f.Stop()

	log.Info("lemming initialization complete")
	select {}
}

// newCreds returns either insecure or tls credentials, depending the enable_tls flag.
// TODO: figure out long term plan for certs, this implementation is here to unblock using Ondatra KNEBind.
func newCreds() (credentials.TransportCredentials, error) {
	if !*enableTLS {
		return insecure.NewCredentials(), nil
	}
	key, err := rsa.GenerateKey(rand.Reader, 2048)
	if err != nil {
		return nil, err
	}
	tmpl := &x509.Certificate{
		SerialNumber: big.NewInt(1234),
	}

	certDer, err := x509.CreateCertificate(rand.Reader, tmpl, tmpl, &key.PublicKey, key)
	if err != nil {
		return nil, err
	}
	certPem := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: certDer})

	keyDer, err := x509.MarshalPKCS8PrivateKey(key)
	if err != nil {
		return nil, err
	}
	keyPem := pem.EncodeToMemory(&pem.Block{Type: "PRIVATE KEY", Bytes: keyDer})

	serverCert, err := tls.X509KeyPair(certPem, keyPem)
	if err != nil {
		return nil, err
	}
	return credentials.NewTLS(&tls.Config{
		MinVersion:   tls.VersionTLS13,
		Certificates: []tls.Certificate{serverCert},
	}), nil
}
<|endoftext|>


<commit_before>package main

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

	"github.com/zyedidia/tcell"
)

// TermMessage sends a message to the user in the terminal. This usually occurs before
// micro has been fully initialized -- ie if there is an error in the syntax highlighting
// regular expressions
// The function must be called when the screen is not initialized
// This will write the message, and wait for the user
// to press and key to continue
func TermMessage(msg ...interface{}) {
	screenWasNil := screen == nil
	if !screenWasNil {
		screen.Fini()
	}

	fmt.Println(msg...)
	fmt.Print("\nPress enter to continue")

	reader := bufio.NewReader(os.Stdin)
	reader.ReadString('\n')

	if !screenWasNil {
		InitScreen()
	}
}

// TermError sends an error to the user in the terminal. Like TermMessage except formatted
// as an error
func TermError(filename string, lineNum int, err string) {
	TermMessage(filename + ", " + strconv.Itoa(lineNum) + ": " + err)
}

// Messenger is an object that makes it easy to send messages to the user
// and get input from the user
type Messenger struct {
	// Are we currently prompting the user?
	hasPrompt bool
	// Is there a message to print
	hasMessage bool

	// Message to print
	message string
	// The user's response to a prompt
	response string
	// style to use when drawing the message
	style tcell.Style

	// We have to keep track of the cursor for prompting
	cursorx int

	// This map stores the history for all the different kinds of uses Prompt has
	// It's a map of history type -> history array
	history    map[string][]string
	historyNum int

	// Is the current message a message from the gutter
	gutterMessage bool
}

// Message sends a message to the user
func (m *Messenger) Message(msg ...interface{}) {
	buf := new(bytes.Buffer)
	fmt.Fprint(buf, msg...)
	m.message = buf.String()
	m.style = defStyle

	if _, ok := colorscheme["message"]; ok {
		m.style = colorscheme["message"]
	}
	m.hasMessage = true
}

// Error sends an error message to the user
func (m *Messenger) Error(msg ...interface{}) {
	buf := new(bytes.Buffer)
	fmt.Fprint(buf, msg...)
	m.message = buf.String()
	m.style = defStyle.
		Foreground(tcell.ColorBlack).
		Background(tcell.ColorMaroon)

	if _, ok := colorscheme["error-message"]; ok {
		m.style = colorscheme["error-message"]
	}
	m.hasMessage = true
}

// YesNoPrompt asks the user a yes or no question (waits for y or n) and returns the result
func (m *Messenger) YesNoPrompt(prompt string) (bool, bool) {
	m.Message(prompt)

	_, h := screen.Size()
	for {
		m.Clear()
		m.Display()
		screen.ShowCursor(Count(m.message), h-1)
		screen.Show()
		event := <-events

		switch e := event.(type) {
		case *tcell.EventKey:
			switch e.Key() {
			case tcell.KeyRune:
				if e.Rune() == 'y' {
					return true, false
				} else if e.Rune() == 'n' {
					return false, false
				}
			case tcell.KeyCtrlC, tcell.KeyCtrlQ, tcell.KeyEscape:
				return false, true
			}
		}
	}
}

type Completion int

const (
	NoCompletion Completion = iota
	FileCompletion
	CommandCompletion
	HelpCompletion
	OptionCompletion
)

// Prompt sends the user a message and waits for a response to be typed in
// This function blocks the main loop while waiting for input
func (m *Messenger) Prompt(prompt, historyType string, completionTypes ...Completion) (string, bool) {
	m.hasPrompt = true
	m.Message(prompt)
	if _, ok := m.history[historyType]; !ok {
		m.history[historyType] = []string{""}
	} else {
		m.history[historyType] = append(m.history[historyType], "")
	}
	m.historyNum = len(m.history[historyType]) - 1

	response, canceled := "", true

	RedrawAll()
	for m.hasPrompt {
		var suggestions []string
		m.Clear()

		event := <-events

		switch e := event.(type) {
		case *tcell.EventKey:
			switch e.Key() {
			case tcell.KeyCtrlQ, tcell.KeyCtrlC, tcell.KeyEscape:
				// Cancel
				m.hasPrompt = false
			case tcell.KeyEnter:
				// User is done entering their response
				m.hasPrompt = false
				response, canceled = m.response, false
				m.history[historyType][len(m.history[historyType])-1] = response
			case tcell.KeyTab:
				args := strings.Split(m.response, " ")
				currentArgNum := len(args) - 1
				currentArg := args[currentArgNum]
				var completionType Completion

				if completionTypes[0] == CommandCompletion && currentArgNum > 0 {
					if command, ok := commands[args[0]]; ok {
						completionTypes = append([]Completion{CommandCompletion}, command.completions...)
					}
				}

				if currentArgNum >= len(completionTypes) {
					completionType = completionTypes[len(completionTypes)-1]
				} else {
					completionType = completionTypes[currentArgNum]
				}

				var chosen string
				if completionType == FileCompletion {
					chosen, suggestions = FileComplete(currentArg)
				} else if completionType == CommandCompletion {
					chosen, suggestions = CommandComplete(currentArg)
				} else if completionType == HelpCompletion {
					chosen, suggestions = HelpComplete(currentArg)
				} else if completionType == OptionCompletion {
					chosen, suggestions = OptionComplete(currentArg)
				}

				if chosen != "" {
					if len(args) > 1 {
						chosen = " " + chosen
					}
					m.response = strings.Join(args[:len(args)-1], " ") + chosen
					m.cursorx = Count(m.response)
				}
			}
		}

		m.HandleEvent(event, m.history[historyType])

		messenger.Clear()
		for _, v := range tabs[curTab].views {
			v.Display()
		}
		DisplayTabs()
		messenger.Display()
		if len(suggestions) > 1 {
			m.DisplaySuggestions(suggestions)
		}
		screen.Show()
	}

	m.Reset()
	return response, canceled
}

// HandleEvent handles an event for the prompter
func (m *Messenger) HandleEvent(event tcell.Event, history []string) {
	switch e := event.(type) {
	case *tcell.EventKey:
		switch e.Key() {
		case tcell.KeyUp:
			if m.historyNum > 0 {
				m.historyNum--
				m.response = history[m.historyNum]
				m.cursorx = Count(m.response)
			}
		case tcell.KeyDown:
			if m.historyNum < len(history)-1 {
				m.historyNum++
				m.response = history[m.historyNum]
				m.cursorx = Count(m.response)
			}
		case tcell.KeyLeft:
			if m.cursorx > 0 {
				m.cursorx--
			}
		case tcell.KeyRight:
			if m.cursorx < Count(m.response) {
				m.cursorx++
			}
		case tcell.KeyBackspace2, tcell.KeyBackspace:
			if m.cursorx > 0 {
				m.response = string([]rune(m.response)[:m.cursorx-1]) + string(m.response[m.cursorx:])
				m.cursorx--
			}
		case tcell.KeyRune:
			m.response = Insert(m.response, m.cursorx, string(e.Rune()))
			m.cursorx++
		}
		history[m.historyNum] = m.response
	}
}

// Reset resets the messenger's cursor, message and response
func (m *Messenger) Reset() {
	m.cursorx = 0
	m.message = ""
	m.response = ""
}

// Clear clears the line at the bottom of the editor
func (m *Messenger) Clear() {
	w, h := screen.Size()
	for x := 0; x < w; x++ {
		screen.SetContent(x, h-1, ' ', nil, defStyle)
	}
}

func (m *Messenger) DisplaySuggestions(suggestions []string) {
	w, screenH := screen.Size()

	y := screenH - 2
	for x := 0; x < w; x++ {
		screen.SetContent(x, y, ' ', nil, defStyle.Reverse(true))
	}

	x := 1
	for _, suggestion := range suggestions {
		for _, c := range suggestion {
			screen.SetContent(x, y, c, nil, defStyle.Reverse(true))
			x++
		}
		screen.SetContent(x, y, ' ', nil, defStyle.Reverse(true))
		x++
	}
}

// Display displays messages or prompts
func (m *Messenger) Display() {
	_, h := screen.Size()
	if m.hasMessage {
		runes := []rune(m.message + m.response)
		for x := 0; x < len(runes); x++ {
			screen.SetContent(x, h-1, runes[x], nil, m.style)
		}
	}
	if m.hasPrompt {
		screen.ShowCursor(Count(m.message)+m.cursorx, h-1)
		screen.Show()
	}
}

// A GutterMessage is a message displayed on the side of the editor
type GutterMessage struct {
	lineNum int
	msg     string
	kind    int
}

// These are the different types of messages
const (
	// GutterInfo represents a simple info message
	GutterInfo = iota
	// GutterWarning represents a compiler warning
	GutterWarning
	// GutterError represents a compiler error
	GutterError
)
<commit_msg>Fix statusline suggestion style<commit_after>package main

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

	"github.com/zyedidia/tcell"
)

// TermMessage sends a message to the user in the terminal. This usually occurs before
// micro has been fully initialized -- ie if there is an error in the syntax highlighting
// regular expressions
// The function must be called when the screen is not initialized
// This will write the message, and wait for the user
// to press and key to continue
func TermMessage(msg ...interface{}) {
	screenWasNil := screen == nil
	if !screenWasNil {
		screen.Fini()
	}

	fmt.Println(msg...)
	fmt.Print("\nPress enter to continue")

	reader := bufio.NewReader(os.Stdin)
	reader.ReadString('\n')

	if !screenWasNil {
		InitScreen()
	}
}

// TermError sends an error to the user in the terminal. Like TermMessage except formatted
// as an error
func TermError(filename string, lineNum int, err string) {
	TermMessage(filename + ", " + strconv.Itoa(lineNum) + ": " + err)
}

// Messenger is an object that makes it easy to send messages to the user
// and get input from the user
type Messenger struct {
	// Are we currently prompting the user?
	hasPrompt bool
	// Is there a message to print
	hasMessage bool

	// Message to print
	message string
	// The user's response to a prompt
	response string
	// style to use when drawing the message
	style tcell.Style

	// We have to keep track of the cursor for prompting
	cursorx int

	// This map stores the history for all the different kinds of uses Prompt has
	// It's a map of history type -> history array
	history    map[string][]string
	historyNum int

	// Is the current message a message from the gutter
	gutterMessage bool
}

// Message sends a message to the user
func (m *Messenger) Message(msg ...interface{}) {
	buf := new(bytes.Buffer)
	fmt.Fprint(buf, msg...)
	m.message = buf.String()
	m.style = defStyle

	if _, ok := colorscheme["message"]; ok {
		m.style = colorscheme["message"]
	}
	m.hasMessage = true
}

// Error sends an error message to the user
func (m *Messenger) Error(msg ...interface{}) {
	buf := new(bytes.Buffer)
	fmt.Fprint(buf, msg...)
	m.message = buf.String()
	m.style = defStyle.
		Foreground(tcell.ColorBlack).
		Background(tcell.ColorMaroon)

	if _, ok := colorscheme["error-message"]; ok {
		m.style = colorscheme["error-message"]
	}
	m.hasMessage = true
}

// YesNoPrompt asks the user a yes or no question (waits for y or n) and returns the result
func (m *Messenger) YesNoPrompt(prompt string) (bool, bool) {
	m.Message(prompt)

	_, h := screen.Size()
	for {
		m.Clear()
		m.Display()
		screen.ShowCursor(Count(m.message), h-1)
		screen.Show()
		event := <-events

		switch e := event.(type) {
		case *tcell.EventKey:
			switch e.Key() {
			case tcell.KeyRune:
				if e.Rune() == 'y' {
					return true, false
				} else if e.Rune() == 'n' {
					return false, false
				}
			case tcell.KeyCtrlC, tcell.KeyCtrlQ, tcell.KeyEscape:
				return false, true
			}
		}
	}
}

type Completion int

const (
	NoCompletion Completion = iota
	FileCompletion
	CommandCompletion
	HelpCompletion
	OptionCompletion
)

// Prompt sends the user a message and waits for a response to be typed in
// This function blocks the main loop while waiting for input
func (m *Messenger) Prompt(prompt, historyType string, completionTypes ...Completion) (string, bool) {
	m.hasPrompt = true
	m.Message(prompt)
	if _, ok := m.history[historyType]; !ok {
		m.history[historyType] = []string{""}
	} else {
		m.history[historyType] = append(m.history[historyType], "")
	}
	m.historyNum = len(m.history[historyType]) - 1

	response, canceled := "", true

	RedrawAll()
	for m.hasPrompt {
		var suggestions []string
		m.Clear()

		event := <-events

		switch e := event.(type) {
		case *tcell.EventKey:
			switch e.Key() {
			case tcell.KeyCtrlQ, tcell.KeyCtrlC, tcell.KeyEscape:
				// Cancel
				m.hasPrompt = false
			case tcell.KeyEnter:
				// User is done entering their response
				m.hasPrompt = false
				response, canceled = m.response, false
				m.history[historyType][len(m.history[historyType])-1] = response
			case tcell.KeyTab:
				args := strings.Split(m.response, " ")
				currentArgNum := len(args) - 1
				currentArg := args[currentArgNum]
				var completionType Completion

				if completionTypes[0] == CommandCompletion && currentArgNum > 0 {
					if command, ok := commands[args[0]]; ok {
						completionTypes = append([]Completion{CommandCompletion}, command.completions...)
					}
				}

				if currentArgNum >= len(completionTypes) {
					completionType = completionTypes[len(completionTypes)-1]
				} else {
					completionType = completionTypes[currentArgNum]
				}

				var chosen string
				if completionType == FileCompletion {
					chosen, suggestions = FileComplete(currentArg)
				} else if completionType == CommandCompletion {
					chosen, suggestions = CommandComplete(currentArg)
				} else if completionType == HelpCompletion {
					chosen, suggestions = HelpComplete(currentArg)
				} else if completionType == OptionCompletion {
					chosen, suggestions = OptionComplete(currentArg)
				}

				if chosen != "" {
					if len(args) > 1 {
						chosen = " " + chosen
					}
					m.response = strings.Join(args[:len(args)-1], " ") + chosen
					m.cursorx = Count(m.response)
				}
			}
		}

		m.HandleEvent(event, m.history[historyType])

		messenger.Clear()
		for _, v := range tabs[curTab].views {
			v.Display()
		}
		DisplayTabs()
		messenger.Display()
		if len(suggestions) > 1 {
			m.DisplaySuggestions(suggestions)
		}
		screen.Show()
	}

	m.Reset()
	return response, canceled
}

// HandleEvent handles an event for the prompter
func (m *Messenger) HandleEvent(event tcell.Event, history []string) {
	switch e := event.(type) {
	case *tcell.EventKey:
		switch e.Key() {
		case tcell.KeyUp:
			if m.historyNum > 0 {
				m.historyNum--
				m.response = history[m.historyNum]
				m.cursorx = Count(m.response)
			}
		case tcell.KeyDown:
			if m.historyNum < len(history)-1 {
				m.historyNum++
				m.response = history[m.historyNum]
				m.cursorx = Count(m.response)
			}
		case tcell.KeyLeft:
			if m.cursorx > 0 {
				m.cursorx--
			}
		case tcell.KeyRight:
			if m.cursorx < Count(m.response) {
				m.cursorx++
			}
		case tcell.KeyBackspace2, tcell.KeyBackspace:
			if m.cursorx > 0 {
				m.response = string([]rune(m.response)[:m.cursorx-1]) + string(m.response[m.cursorx:])
				m.cursorx--
			}
		case tcell.KeyRune:
			m.response = Insert(m.response, m.cursorx, string(e.Rune()))
			m.cursorx++
		}
		history[m.historyNum] = m.response
	}
}

// Reset resets the messenger's cursor, message and response
func (m *Messenger) Reset() {
	m.cursorx = 0
	m.message = ""
	m.response = ""
}

// Clear clears the line at the bottom of the editor
func (m *Messenger) Clear() {
	w, h := screen.Size()
	for x := 0; x < w; x++ {
		screen.SetContent(x, h-1, ' ', nil, defStyle)
	}
}

func (m *Messenger) DisplaySuggestions(suggestions []string) {
	w, screenH := screen.Size()

	y := screenH - 2

	statusLineStyle := defStyle.Reverse(true)
	if style, ok := colorscheme["statusline"]; ok {
		statusLineStyle = style
	}

	for x := 0; x < w; x++ {
		screen.SetContent(x, y, ' ', nil, statusLineStyle)
	}

	x := 1
	for _, suggestion := range suggestions {
		for _, c := range suggestion {
			screen.SetContent(x, y, c, nil, statusLineStyle)
			x++
		}
		screen.SetContent(x, y, ' ', nil, statusLineStyle)
		x++
	}
}

// Display displays messages or prompts
func (m *Messenger) Display() {
	_, h := screen.Size()
	if m.hasMessage {
		runes := []rune(m.message + m.response)
		for x := 0; x < len(runes); x++ {
			screen.SetContent(x, h-1, runes[x], nil, m.style)
		}
	}
	if m.hasPrompt {
		screen.ShowCursor(Count(m.message)+m.cursorx, h-1)
		screen.Show()
	}
}

// A GutterMessage is a message displayed on the side of the editor
type GutterMessage struct {
	lineNum int
	msg     string
	kind    int
}

// These are the different types of messages
const (
	// GutterInfo represents a simple info message
	GutterInfo = iota
	// GutterWarning represents a compiler warning
	GutterWarning
	// GutterError represents a compiler error
	GutterError
)
<|endoftext|>


<commit_before>package cmd

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"sort"
	"strconv"

	"github.com/ghchinoy/ce-go/ce"
	"github.com/olekukonko/tablewriter"
	"github.com/spf13/cobra"
)

// elementsCmd represents the elements command
var transformationsCmd = &cobra.Command{
	Use:   "transformations",
	Short: "Manage Transformations on the Platform",
	Long:  `Manage Transformations on the Platform`,
}

// associateTransformationCmd adds a Transformation to an Element, given a Transformation JSON file
// This isn't ready - a Transformation requires a vendorName otherwise an added Transformation
// may not map to an Element's
var associateTransformationCmd = &cobra.Command{
	Use:    "associate <element_key | element_id> <transformation.json> [name]",
	Short:  "Associate a Transformation with an Element",
	Long:   "Associate a Transformation with an Element given a Transformation JSON file path",
	Hidden: true,
	Run: func(cmd *cobra.Command, args []string) {
		// check for profile
		profilemap, err := getAuth(profile)
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}
		if len(args) < 2 {
			fmt.Println("Please provide both an Element key|id and a path to a Transformation JSON file")
			os.Exit(1)
		}
		// validate Element ID
		elementid, err := ce.ElementKeyToID(args[0], profilemap)
		if err != nil {
			fmt.Println(err.Error())
			return
		}
		// validate Transformation json file
		var transformation ce.Transformation
		txbytes, err := ioutil.ReadFile(args[1])
		if err != nil {
			fmt.Println("Supplied file cannot be read", err.Error())
			os.Exit(1)
		}
		err = json.Unmarshal(txbytes, &transformation)
		if err != nil {
			fmt.Println("Supplied file does not contain a Transformation", err.Error())
			os.Exit(1)
		}
		// Provide a name for the object if supplied
		if len(args) == 3 {
			transformation.ObjectName = args[2]
		}

		bodybytes, status, curlcmd, err := ce.AssociateTransformationWithElement(
			profilemap["base"], profilemap["auth"],
			strconv.Itoa(elementid),
			transformation)
		if err != nil {
			fmt.Println("Unable to import Transformation", err.Error())
			os.Exit(1)
		}
		// handle global options, curl
		if showCurl {
			log.Println(curlcmd)
		}
		if status != 200 {
			fmt.Println("Non-200 status: ", status)
			var message interface{}
			json.Unmarshal(bodybytes, &message)
			fmt.Printf("%s\n", message)
			os.Exit(1)
		}
		fmt.Printf("%s\n", bodybytes)

	},
}

var withElementAssociations bool

// listTransformationsCmd is the command to list Transformations
// the flag --with-elements will also list the Elements the Transformation has associations with
var listTransformationsCmd = &cobra.Command{
	Use:   "list",
	Short: "List Transformations",
	Long:  "List Transformations on the Platform",
	Run: func(cmd *cobra.Command, args []string) {
		// check for profile
		profilemap, err := getAuth(profile)
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}
		bodybytes, statuscode, curlcmd, err := ce.GetTransformations(profilemap["base"], profilemap["auth"])
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}
		// handle global options, curl
		if showCurl {
			log.Println(curlcmd)
		}
		// handle non 200
		if statuscode != 200 {
			log.Printf("HTTP Error: %v\n", statuscode)
			// handle this nicely, show error description
		}
		if outputJSON {
			// todo uplift to output package, output/FormattedJSON
			var transformations interface{}
			err = json.Unmarshal(bodybytes, &transformations)
			if err != nil {
				fmt.Println("Can't unmarshal")
				os.Exit(1)
			}
			formattedbytes, err := json.MarshalIndent(transformations, "", "    ")
			if err != nil {
				fmt.Println("Can't format json")
				os.Exit(1)
			}
			fmt.Printf("%s", formattedbytes)
			os.Exit(0)
		}

		txs := make(map[string]ce.Transformation)
		err = json.Unmarshal(bodybytes, &txs)
		if err != nil {
			fmt.Println("Unable to parse Transformations", err.Error())
			os.Exit(1)
		}
		// sort by key
		var keys []string
		for k := range txs {
			keys = append(keys, k)
		}
		sort.Strings(keys)

		elementAssociations := make(map[string][]string)
		if withElementAssociations {
			for _, k := range keys {
				bodybytes, status, _, err := ce.GetTransformationAssocation(profilemap["base"], profilemap["auth"], k)
				if err != nil {
					break
				}
				if status != 200 {
					break
				}
				var associations []ce.AccountElement
				err = json.Unmarshal(bodybytes, &associations)
				if err != nil {
					break
				}
				var elements []string
				for _, e := range associations {
					elements = append(elements, e.Element.Key)
				}
				elementAssociations[k] = elements
			}
		}

		data := [][]string{}
		for _, k := range keys {
			v := txs[k]
			if withElementAssociations {
				data = append(data, []string{
					k,
					v.Level,
					fmt.Sprintf("%v", len(v.Fields)),
					fmt.Sprintf("%v %s", len(elementAssociations[k]), elementAssociations[k]),
				})
			} else {
				data = append(data, []string{
					k,
					v.Level,
					fmt.Sprintf("%v", len(v.Fields)),
				})
			}
		}
		table := tablewriter.NewWriter(os.Stdout)
		//table.SetHeader([]string{"Resource", "Vendor", "Level", "# Fields", "# Configs", "Legacy", "Start Date"})
		if withElementAssociations {
			table.SetHeader([]string{"Resource", "Level", "# Fields", "Elements"})
		} else {
			table.SetHeader([]string{"Resource", "Level", "# Fields"})
		}
		table.SetBorder(false)
		table.AppendBulk(data)
		table.Render()
	},
}

func init() {
	RootCmd.AddCommand(transformationsCmd)

	transformationsCmd.PersistentFlags().StringVar(&profile, "profile", "default", "profile name")
	transformationsCmd.PersistentFlags().BoolVarP(&outputJSON, "json", "j", false, "output as json")
	transformationsCmd.PersistentFlags().BoolVarP(&showCurl, "curl", "c", false, "show curl command")
	//transformationsCmd.PersistentFlags().BoolVarP(&outputCSV, "csv", "", false, "output as CSV")
	transformationsCmd.AddCommand(listTransformationsCmd)
	listTransformationsCmd.PersistentFlags().BoolVarP(&withElementAssociations, "with-elements", "", false, "show Element associations")
	transformationsCmd.AddCommand(associateTransformationCmd)
}
<commit_msg>copyright comments<commit_after>// Copyright © 2017 G. Hussain Chinoy <ghchinoy@gmail.com>
//
// 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 cmd

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"sort"
	"strconv"

	"github.com/ghchinoy/ce-go/ce"
	"github.com/olekukonko/tablewriter"
	"github.com/spf13/cobra"
)

// elementsCmd represents the elements command
var transformationsCmd = &cobra.Command{
	Use:   "transformations",
	Short: "Manage Transformations on the Platform",
	Long:  `Manage Transformations on the Platform`,
}

// associateTransformationCmd adds a Transformation to an Element, given a Transformation JSON file
// This isn't ready - a Transformation requires a vendorName otherwise an added Transformation
// may not map to an Element's
var associateTransformationCmd = &cobra.Command{
	Use:    "associate <element_key | element_id> <transformation.json> [name]",
	Short:  "Associate a Transformation with an Element",
	Long:   "Associate a Transformation with an Element given a Transformation JSON file path",
	Hidden: true,
	Run: func(cmd *cobra.Command, args []string) {
		// check for profile
		profilemap, err := getAuth(profile)
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}
		if len(args) < 2 {
			fmt.Println("Please provide both an Element key|id and a path to a Transformation JSON file")
			os.Exit(1)
		}
		// validate Element ID
		elementid, err := ce.ElementKeyToID(args[0], profilemap)
		if err != nil {
			fmt.Println(err.Error())
			return
		}
		// validate Transformation json file
		var transformation ce.Transformation
		txbytes, err := ioutil.ReadFile(args[1])
		if err != nil {
			fmt.Println("Supplied file cannot be read", err.Error())
			os.Exit(1)
		}
		err = json.Unmarshal(txbytes, &transformation)
		if err != nil {
			fmt.Println("Supplied file does not contain a Transformation", err.Error())
			os.Exit(1)
		}
		// Provide a name for the object if supplied
		if len(args) == 3 {
			transformation.ObjectName = args[2]
		}

		bodybytes, status, curlcmd, err := ce.AssociateTransformationWithElement(
			profilemap["base"], profilemap["auth"],
			strconv.Itoa(elementid),
			transformation)
		if err != nil {
			fmt.Println("Unable to import Transformation", err.Error())
			os.Exit(1)
		}
		// handle global options, curl
		if showCurl {
			log.Println(curlcmd)
		}
		if status != 200 {
			fmt.Println("Non-200 status: ", status)
			var message interface{}
			json.Unmarshal(bodybytes, &message)
			fmt.Printf("%s\n", message)
			os.Exit(1)
		}
		fmt.Printf("%s\n", bodybytes)

	},
}

var withElementAssociations bool

// listTransformationsCmd is the command to list Transformations
// the flag --with-elements will also list the Elements the Transformation has associations with
var listTransformationsCmd = &cobra.Command{
	Use:   "list",
	Short: "List Transformations",
	Long:  "List Transformations on the Platform",
	Run: func(cmd *cobra.Command, args []string) {
		// check for profile
		profilemap, err := getAuth(profile)
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}
		bodybytes, statuscode, curlcmd, err := ce.GetTransformations(profilemap["base"], profilemap["auth"])
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}
		// handle global options, curl
		if showCurl {
			log.Println(curlcmd)
		}
		// handle non 200
		if statuscode != 200 {
			log.Printf("HTTP Error: %v\n", statuscode)
			// handle this nicely, show error description
		}
		if outputJSON {
			// todo uplift to output package, output/FormattedJSON
			var transformations interface{}
			err = json.Unmarshal(bodybytes, &transformations)
			if err != nil {
				fmt.Println("Can't unmarshal")
				os.Exit(1)
			}
			formattedbytes, err := json.MarshalIndent(transformations, "", "    ")
			if err != nil {
				fmt.Println("Can't format json")
				os.Exit(1)
			}
			fmt.Printf("%s", formattedbytes)
			os.Exit(0)
		}

		txs := make(map[string]ce.Transformation)
		err = json.Unmarshal(bodybytes, &txs)
		if err != nil {
			fmt.Println("Unable to parse Transformations", err.Error())
			os.Exit(1)
		}
		// sort by key
		var keys []string
		for k := range txs {
			keys = append(keys, k)
		}
		sort.Strings(keys)

		elementAssociations := make(map[string][]string)
		if withElementAssociations {
			for _, k := range keys {
				bodybytes, status, _, err := ce.GetTransformationAssocation(profilemap["base"], profilemap["auth"], k)
				if err != nil {
					break
				}
				if status != 200 {
					break
				}
				var associations []ce.AccountElement
				err = json.Unmarshal(bodybytes, &associations)
				if err != nil {
					break
				}
				var elements []string
				for _, e := range associations {
					elements = append(elements, e.Element.Key)
				}
				elementAssociations[k] = elements
			}
		}

		data := [][]string{}
		for _, k := range keys {
			v := txs[k]
			if withElementAssociations {
				data = append(data, []string{
					k,
					v.Level,
					fmt.Sprintf("%v", len(v.Fields)),
					fmt.Sprintf("%v %s", len(elementAssociations[k]), elementAssociations[k]),
				})
			} else {
				data = append(data, []string{
					k,
					v.Level,
					fmt.Sprintf("%v", len(v.Fields)),
				})
			}
		}
		table := tablewriter.NewWriter(os.Stdout)
		//table.SetHeader([]string{"Resource", "Vendor", "Level", "# Fields", "# Configs", "Legacy", "Start Date"})
		if withElementAssociations {
			table.SetHeader([]string{"Resource", "Level", "# Fields", "Elements"})
		} else {
			table.SetHeader([]string{"Resource", "Level", "# Fields"})
		}
		table.SetBorder(false)
		table.AppendBulk(data)
		table.Render()
	},
}

func init() {
	RootCmd.AddCommand(transformationsCmd)

	transformationsCmd.PersistentFlags().StringVar(&profile, "profile", "default", "profile name")
	transformationsCmd.PersistentFlags().BoolVarP(&outputJSON, "json", "j", false, "output as json")
	transformationsCmd.PersistentFlags().BoolVarP(&showCurl, "curl", "c", false, "show curl command")
	//transformationsCmd.PersistentFlags().BoolVarP(&outputCSV, "csv", "", false, "output as CSV")
	transformationsCmd.AddCommand(listTransformationsCmd)
	listTransformationsCmd.PersistentFlags().BoolVarP(&withElementAssociations, "with-elements", "", false, "show Element associations")
	transformationsCmd.AddCommand(associateTransformationCmd)
}
<|endoftext|>


<commit_before>/*
Copyright 2018 Google LLC

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

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

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

package cmd

import (
	"fmt"
	"os"

	"github.com/GoogleContainerTools/kaniko/pkg/cache"
	"github.com/GoogleContainerTools/kaniko/pkg/config"
	"github.com/GoogleContainerTools/kaniko/pkg/constants"
	"github.com/GoogleContainerTools/kaniko/pkg/util"
	"github.com/pkg/errors"
	"github.com/spf13/cobra"
)

var (
	opts     = &config.WarmerOptions{}
	logLevel string
)

func init() {
	RootCmd.PersistentFlags().StringVarP(&logLevel, "verbosity", "v", constants.DefaultLogLevel, "Log level (debug, info, warn, error, fatal, panic")
	addKanikoOptionsFlags(RootCmd)
	addHiddenFlags(RootCmd)
}

var RootCmd = &cobra.Command{
	Use: "cache warmer",
	PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
		if err := util.ConfigureLogging(logLevel); err != nil {
			return err
		}
		if len(opts.Images) == 0 {
			return errors.New("You must select at least one image to cache")
		}
		return nil
	},
	Run: func(cmd *cobra.Command, args []string) {
		if err := cache.WarmCache(opts); err != nil {
			exit(errors.Wrap(err, "Failed warming cache"))
		}
	},
}

// addKanikoOptionsFlags configures opts
func addKanikoOptionsFlags(cmd *cobra.Command) {
	RootCmd.PersistentFlags().VarP(&opts.Images, "image", "i", "Image to cache. Set it repeatedly for multiple images.")
	RootCmd.PersistentFlags().StringVarP(&opts.CacheDir, "cache-dir", "c", "/cache", "Directory of the cache.")
}

// addHiddenFlags marks certain flags as hidden from the executor help text
func addHiddenFlags(cmd *cobra.Command) {
	RootCmd.PersistentFlags().MarkHidden("azure-container-registry-config")
}

func exit(err error) {
	fmt.Println(err)
	os.Exit(1)
}
<commit_msg>create cache directory if it doesn't already exist<commit_after>/*
Copyright 2018 Google LLC

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

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

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

package cmd

import (
	"fmt"
	"os"

	"github.com/GoogleContainerTools/kaniko/pkg/cache"
	"github.com/GoogleContainerTools/kaniko/pkg/config"
	"github.com/GoogleContainerTools/kaniko/pkg/constants"
	"github.com/GoogleContainerTools/kaniko/pkg/util"
	"github.com/pkg/errors"
	"github.com/spf13/cobra"
)

var (
	opts     = &config.WarmerOptions{}
	logLevel string
)

func init() {
	RootCmd.PersistentFlags().StringVarP(&logLevel, "verbosity", "v", constants.DefaultLogLevel, "Log level (debug, info, warn, error, fatal, panic")
	addKanikoOptionsFlags(RootCmd)
	addHiddenFlags(RootCmd)
}

var RootCmd = &cobra.Command{
	Use: "cache warmer",
	PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
		if err := util.ConfigureLogging(logLevel); err != nil {
			return err
		}
		if len(opts.Images) == 0 {
			return errors.New("You must select at least one image to cache")
		}
		return nil
	},
	Run: func(cmd *cobra.Command, args []string) {
		if _, err := os.Stat(opts.CacheDir); os.IsNotExist(err) {
			err = os.MkdirAll(opts.CacheDir, 0755)
			if err != nil {
				exit(errors.Wrap(err, "Failed to create cache directory"))
			}
		}
		if err := cache.WarmCache(opts); err != nil {
			exit(errors.Wrap(err, "Failed warming cache"))
		}
	},
}

// addKanikoOptionsFlags configures opts
func addKanikoOptionsFlags(cmd *cobra.Command) {
	RootCmd.PersistentFlags().VarP(&opts.Images, "image", "i", "Image to cache. Set it repeatedly for multiple images.")
	RootCmd.PersistentFlags().StringVarP(&opts.CacheDir, "cache-dir", "c", "/cache", "Directory of the cache.")
}

// addHiddenFlags marks certain flags as hidden from the executor help text
func addHiddenFlags(cmd *cobra.Command) {
	RootCmd.PersistentFlags().MarkHidden("azure-container-registry-config")
}

func exit(err error) {
	fmt.Println(err)
	os.Exit(1)
}
<|endoftext|>