<commit_before>// (c) Copyright IBM Corp. 2021
// (c) Copyright Instana Inc. 2021

package instana

// Version is the version of Instana sensor
const Version = "1.25.0"
<commit_msg>Bump go-sensor version to 1.26.0<commit_after>// (c) Copyright IBM Corp. 2021
// (c) Copyright Instana Inc. 2021

package instana

// Version is the version of Instana sensor
const Version = "1.26.0"
<|endoftext|>


<commit_before>package main

import (
	"fmt"
)

var Version = &NxVersion{
	Major: 1,
	Minor: 0,
	Patch: 1,
}

type NxVersion struct {
	Major int
	Minor int
	Patch int
}

func (v *NxVersion) String() string {
	return fmt.Sprintf("%d.%d.%d", v.Major, v.Minor, v.Patch)
}
<commit_msg>Bump version<commit_after>package main

import (
	"fmt"
)

var Version = &NxVersion{
	Major: 1,
	Minor: 1,
	Patch: 1,
}

type NxVersion struct {
	Major int
	Minor int
	Patch int
}

func (v *NxVersion) String() string {
	return fmt.Sprintf("%d.%d.%d", v.Major, v.Minor, v.Patch)
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"reflect"
	"sync"
	"time"

	api "github.com/armon/consul-api"
)

const (
	// The amount of time to do a blocking query for
	defaultWaitTime = 60 * time.Second

	// pollErrorSleep the amount of time to sleep when an error occurs
	// TODO: make this an exponential backoff.
	pollErrorSleep = 5 * time.Second
)

type Watcher struct {
	// DataCh is the chan where new WatchData will be published
	DataCh chan *WatchData

	// ErrCh is the chan where any errors will be published
	ErrCh chan error

	// stopCh is a chan that is only published when polling should stop
	stopCh chan struct{}

	// client is the mechanism for communicating with the Consul API
	client *api.Client

	// dependencies is the slice of Dependencies this Watcher will poll
	dependencies []Dependency

	// waitGroup is the WaitGroup to ensure all Go routines return when we stop
	waitGroup sync.WaitGroup
}

//
func NewWatcher(client *api.Client, dependencies []Dependency) (*Watcher, error) {
	watcher := &Watcher{
		client:       client,
		dependencies: dependencies,
	}
	if err := watcher.init(); err != nil {
		return nil, err
	}

	return watcher, nil
}

//
func (w *Watcher) Watch() error {
	views := make([]*WatchData, 0, len(w.dependencies))
	for _, dependency := range w.dependencies {
		view, err := NewWatchData(dependency)
		if err != nil {
			return err
		}

		views = append(views, view)
	}

	for _, view := range views {
		go view.poll(w)
		w.waitGroup.Add(1)
	}

	return nil
}

//
func (w *Watcher) Stop() {
	close(w.stopCh)
	w.waitGroup.Wait()
}

//
func (w *Watcher) init() error {
	if w.client == nil {
		return fmt.Errorf("watcher: missing Consul API client")
	}

	if len(w.dependencies) == 0 {
		return fmt.Errorf("watcher: must supply at least one Dependency")
	}

	// Setup the chans
	w.DataCh = make(chan *WatchData)
	w.ErrCh = make(chan error)
	w.stopCh = make(chan struct{})

	return nil
}

/// ------------------------- ///

type WatchData struct {
	dependency Dependency
	data       interface{}
	lastIndex  uint64
}

//
func NewWatchData(dependency Dependency) (*WatchData, error) {
	if dependency == nil {
		return nil, fmt.Errorf("watchdata: missing Dependency")
	}

	return &WatchData{dependency: dependency}, nil
}

//
func (wd *WatchData) poll(w *Watcher) {
	for {
		// Break from the function if we are done
		select {
		case <-w.stopCh:
			w.waitGroup.Done()
			return
		default:
			break
		}

		options := &api.QueryOptions{
			WaitTime:  defaultWaitTime,
			WaitIndex: wd.lastIndex,
		}
		data, qm, err := wd.dependency.Fetch(w.client, options)
		if err != nil {
			w.ErrCh <- err
			time.Sleep(pollErrorSleep)
			continue
		}

		// Consul is allowed to return even if there's no new data. Ignore data if
		// the index is the same.
		if qm.LastIndex == wd.lastIndex {
			continue
		}

		// Update the index in case we got a new version, but the data is the same
		wd.lastIndex = qm.LastIndex

		// Do not trigger a render if the data is the same
		if reflect.DeepEqual(data, wd.data) {
			continue
		}

		// If we got this far, there is new data!
		wd.data = data
		w.DataCh <- wd
	}
}
<commit_msg>Explicitly check if we have received data in the WatchData<commit_after>package main

import (
	"fmt"
	"reflect"
	"sync"
	"time"

	api "github.com/armon/consul-api"
)

const (
	// The amount of time to do a blocking query for
	defaultWaitTime = 60 * time.Second

	// pollErrorSleep the amount of time to sleep when an error occurs
	// TODO: make this an exponential backoff.
	pollErrorSleep = 5 * time.Second
)

type Watcher struct {
	// DataCh is the chan where new WatchData will be published
	DataCh chan *WatchData

	// ErrCh is the chan where any errors will be published
	ErrCh chan error

	// stopCh is a chan that is only published when polling should stop
	stopCh chan struct{}

	// client is the mechanism for communicating with the Consul API
	client *api.Client

	// dependencies is the slice of Dependencies this Watcher will poll
	dependencies []Dependency

	// waitGroup is the WaitGroup to ensure all Go routines return when we stop
	waitGroup sync.WaitGroup
}

//
func NewWatcher(client *api.Client, dependencies []Dependency) (*Watcher, error) {
	watcher := &Watcher{
		client:       client,
		dependencies: dependencies,
	}
	if err := watcher.init(); err != nil {
		return nil, err
	}

	return watcher, nil
}

//
func (w *Watcher) Watch() error {
	views := make([]*WatchData, 0, len(w.dependencies))
	for _, dependency := range w.dependencies {
		view, err := NewWatchData(dependency)
		if err != nil {
			return err
		}

		views = append(views, view)
	}

	for _, view := range views {
		go view.poll(w)
		w.waitGroup.Add(1)
	}

	return nil
}

//
func (w *Watcher) Stop() {
	close(w.stopCh)
	w.waitGroup.Wait()
}

//
func (w *Watcher) init() error {
	if w.client == nil {
		return fmt.Errorf("watcher: missing Consul API client")
	}

	if len(w.dependencies) == 0 {
		return fmt.Errorf("watcher: must supply at least one Dependency")
	}

	// Setup the chans
	w.DataCh = make(chan *WatchData)
	w.ErrCh = make(chan error)
	w.stopCh = make(chan struct{})

	return nil
}

/// ------------------------- ///

type WatchData struct {
	dependency   Dependency
	data         interface{}
	receivedData bool
	lastIndex    uint64
}

//
func NewWatchData(dependency Dependency) (*WatchData, error) {
	if dependency == nil {
		return nil, fmt.Errorf("watchdata: missing Dependency")
	}

	return &WatchData{dependency: dependency}, nil
}

//
func (wd *WatchData) poll(w *Watcher) {
	for {
		// Break from the function if we are done
		select {
		case <-w.stopCh:
			w.waitGroup.Done()
			return
		default:
			break
		}

		options := &api.QueryOptions{
			WaitTime:  defaultWaitTime,
			WaitIndex: wd.lastIndex,
		}
		data, qm, err := wd.dependency.Fetch(w.client, options)
		if err != nil {
			w.ErrCh <- err
			time.Sleep(pollErrorSleep)
			continue
		}

		// Consul is allowed to return even if there's no new data. Ignore data if
		// the index is the same.
		if qm.LastIndex == wd.lastIndex {
			continue
		}

		// Update the index in case we got a new version, but the data is the same
		wd.lastIndex = qm.LastIndex

		// Do not trigger a render if we have gotten data and the data is the same
		if wd.receivedData && reflect.DeepEqual(data, wd.data) {
			continue
		}

		// If we got this far, there is new data!
		wd.data = data
		wd.receivedData = true
		w.DataCh <- wd
	}
}
<|endoftext|>


<commit_before>/*
Copyright 2016 The Kubernetes Authors.

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

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

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

package kube

import (
	"time"
)

type ObjectMeta struct {
	Name        string            `json:"name,omitempty"`
	Namespace   string            `json:"namespace,omitempty"`
	Labels      map[string]string `json:"labels,omitempty"`
	Annotations map[string]string `json:"annotations,omitempty"`

	ResourceVersion string `json:"resourceVersion,omitempty"`
	UID             string `json:"uid,omitempty"`
}

type Secret struct {
	Metadata ObjectMeta        `json:"metadata,omitempty"`
	Data     map[string]string `json:"data,omitempty"`
}

type PodTemplateSpec struct {
	Metadata ObjectMeta `json:"metadata,omitempty"`
	Spec     PodSpec    `json:"spec,omitempty"`
}

type Pod struct {
	Metadata ObjectMeta `json:"metadata,omitempty"`
	Spec     PodSpec    `json:"spec,omitempty"`
	Status   PodStatus  `json:"status,omitempty"`
}

type PodSpec struct {
	Volumes       []Volume          `json:"volumes,omitempty"`
	Containers    []Container       `json:"containers,omitempty"`
	RestartPolicy string            `json:"restartPolicy,omitempty"`
	NodeSelector  map[string]string `json:"nodeSelector,omitempty"`
}

type PodPhase string

const (
	PodPending   PodPhase = "Pending"
	PodRunning   PodPhase = "Running"
	PodSucceeded PodPhase = "Succeeded"
	PodFailed    PodPhase = "Failed"
	PodUnknown   PodPhase = "Unknown"
)

const (
	Evicted = "Evicted"
)

type PodStatus struct {
	Phase     PodPhase  `json:"phase,omitempty"`
	Message   string    `json:"message,omitempty"`
	Reason    string    `json:"reason,omitempty"`
	StartTime time.Time `json:"startTime,omitempty"`
}

type Volume struct {
	Name        string             `json:"name,omitempty"`
	Secret      *SecretSource      `json:"secret,omitempty"`
	DownwardAPI *DownwardAPISource `json:"downwardAPI,omitempty"`
	HostPath    *HostPathSource    `json:"hostPath,omitempty"`
	ConfigMap   *ConfigMapSource   `json:"configMap,omitempty"`
}

type ConfigMapSource struct {
	Name string `json:"name,omitempty"`
}

type HostPathSource struct {
	Path string `json:"path,omitempty"`
}

type SecretSource struct {
	Name        string `json:"secretName,omitempty"`
	DefaultMode int32  `json:"defaultMode,omitempty"`
}

type DownwardAPISource struct {
	Items []DownwardAPIFile `json:"items,omitempty"`
}

type DownwardAPIFile struct {
	Path  string              `json:"path"`
	Field ObjectFieldSelector `json:"fieldRef,omitempty"`
}

type ObjectFieldSelector struct {
	FieldPath string `json:"fieldPath"`
}

type Container struct {
	Name            string   `json:"name,omitempty"`
	Image           string   `json:"image,omitempty"`
	ImagePullPolicy string   `json:"imagePullPolicy,omitempty"`
	Command         []string `json:"command,omitempty"`
	Args            []string `json:"args,omitempty"`
	WorkDir         string   `json:"workingDir,omitempty"`
	Env             []EnvVar `json:"env,omitempty"`
	Ports           []Port   `json:"ports,omitempty"`

	Resources       Resources        `json:"resources,omitempty"`
	SecurityContext *SecurityContext `json:"securityContext,omitempty"`
	VolumeMounts    []VolumeMount    `json:"volumeMounts,omitempty"`
}

type Port struct {
	ContainerPort int `json:"containerPort,omitempty"`
	HostPort      int `json:"hostPort,omitempty"`
}

type EnvVar struct {
	Name      string        `json:"name,omitempty"`
	Value     string        `json:"value,omitempty"`
	ValueFrom *EnvVarSource `json:"valueFrom,omitempty"`
}

type EnvVarSource struct {
	ConfigMap ConfigMapKeySelector `json:"configMapKeyRef,omitempty"`
}

type ConfigMapKeySelector struct {
	Name string `json:"name,omitempty"`
	Key  string `json:"key,omitempty"`
}

type Resources struct {
	Requests *ResourceRequest `json:"requests,omitempty"`
	Limits   *ResourceRequest `json:"limits,omitempty"`
}

type ResourceRequest struct {
	CPU    string `json:"cpu,omitempty"`
	Memory string `json:"memory,omitempty"`
}

type SecurityContext struct {
	Privileged bool `json:"privileged,omitempty"`
}

type VolumeMount struct {
	Name      string `json:"name,omitempty"`
	ReadOnly  bool   `json:"readOnly,omitempty"`
	MountPath string `json:"mountPath,omitempty"`
}

type ConfigMap struct {
	Metadata ObjectMeta        `json:"metadata,omitempty"`
	Data     map[string]string `json:"data,omitempty"`
}
<commit_msg>add EmtpyDir Volumes to prow kube types<commit_after>/*
Copyright 2016 The Kubernetes Authors.

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

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

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

package kube

import (
	"time"
)

type ObjectMeta struct {
	Name        string            `json:"name,omitempty"`
	Namespace   string            `json:"namespace,omitempty"`
	Labels      map[string]string `json:"labels,omitempty"`
	Annotations map[string]string `json:"annotations,omitempty"`

	ResourceVersion string `json:"resourceVersion,omitempty"`
	UID             string `json:"uid,omitempty"`
}

type Secret struct {
	Metadata ObjectMeta        `json:"metadata,omitempty"`
	Data     map[string]string `json:"data,omitempty"`
}

type PodTemplateSpec struct {
	Metadata ObjectMeta `json:"metadata,omitempty"`
	Spec     PodSpec    `json:"spec,omitempty"`
}

type Pod struct {
	Metadata ObjectMeta `json:"metadata,omitempty"`
	Spec     PodSpec    `json:"spec,omitempty"`
	Status   PodStatus  `json:"status,omitempty"`
}

type PodSpec struct {
	Volumes       []Volume          `json:"volumes,omitempty"`
	Containers    []Container       `json:"containers,omitempty"`
	RestartPolicy string            `json:"restartPolicy,omitempty"`
	NodeSelector  map[string]string `json:"nodeSelector,omitempty"`
}

type PodPhase string

const (
	PodPending   PodPhase = "Pending"
	PodRunning   PodPhase = "Running"
	PodSucceeded PodPhase = "Succeeded"
	PodFailed    PodPhase = "Failed"
	PodUnknown   PodPhase = "Unknown"
)

const (
	Evicted = "Evicted"
)

type PodStatus struct {
	Phase     PodPhase  `json:"phase,omitempty"`
	Message   string    `json:"message,omitempty"`
	Reason    string    `json:"reason,omitempty"`
	StartTime time.Time `json:"startTime,omitempty"`
}

type Volume struct {
	Name         string `json:"name,omitempty"`
	VolumeSource `json:",inline"`
}

// VolumeSource represents the source location of a volume to mount.
// Only one of its members may be specified.
type VolumeSource struct {
	HostPath    *HostPathSource       `json:"hostPath,omitempty"`
	EmptyDir    *EmptyDirVolumeSource `json:"emptyDir,omitemtpy"`
	Secret      *SecretSource         `json:"secret,omitempty"`
	DownwardAPI *DownwardAPISource    `json:"downwardAPI,omitempty"`
	ConfigMap   *ConfigMapSource      `json:"configMap,omitempty"`
}

type HostPathSource struct {
	Path string `json:"path,omitempty"`
}

type SecretSource struct {
	Name        string `json:"secretName,omitempty"`
	DefaultMode int32  `json:"defaultMode,omitempty"`
}

type EmptyDirVolumeSource struct {
	// NOTE: fields ommitted here as Prow does not currently use them
}

type ConfigMapSource struct {
	Name string `json:"name,omitempty"`
}

type DownwardAPISource struct {
	Items []DownwardAPIFile `json:"items,omitempty"`
}

type DownwardAPIFile struct {
	Path  string              `json:"path"`
	Field ObjectFieldSelector `json:"fieldRef,omitempty"`
}

type ObjectFieldSelector struct {
	FieldPath string `json:"fieldPath"`
}

type Container struct {
	Name            string   `json:"name,omitempty"`
	Image           string   `json:"image,omitempty"`
	ImagePullPolicy string   `json:"imagePullPolicy,omitempty"`
	Command         []string `json:"command,omitempty"`
	Args            []string `json:"args,omitempty"`
	WorkDir         string   `json:"workingDir,omitempty"`
	Env             []EnvVar `json:"env,omitempty"`
	Ports           []Port   `json:"ports,omitempty"`

	Resources       Resources        `json:"resources,omitempty"`
	SecurityContext *SecurityContext `json:"securityContext,omitempty"`
	VolumeMounts    []VolumeMount    `json:"volumeMounts,omitempty"`
}

type Port struct {
	ContainerPort int `json:"containerPort,omitempty"`
	HostPort      int `json:"hostPort,omitempty"`
}

type EnvVar struct {
	Name      string        `json:"name,omitempty"`
	Value     string        `json:"value,omitempty"`
	ValueFrom *EnvVarSource `json:"valueFrom,omitempty"`
}

type EnvVarSource struct {
	ConfigMap ConfigMapKeySelector `json:"configMapKeyRef,omitempty"`
}

type ConfigMapKeySelector struct {
	Name string `json:"name,omitempty"`
	Key  string `json:"key,omitempty"`
}

type Resources struct {
	Requests *ResourceRequest `json:"requests,omitempty"`
	Limits   *ResourceRequest `json:"limits,omitempty"`
}

type ResourceRequest struct {
	CPU    string `json:"cpu,omitempty"`
	Memory string `json:"memory,omitempty"`
}

type SecurityContext struct {
	Privileged bool `json:"privileged,omitempty"`
}

type VolumeMount struct {
	Name      string `json:"name,omitempty"`
	ReadOnly  bool   `json:"readOnly,omitempty"`
	MountPath string `json:"mountPath,omitempty"`
}

type ConfigMap struct {
	Metadata ObjectMeta        `json:"metadata,omitempty"`
	Data     map[string]string `json:"data,omitempty"`
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"bytes"
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"strings"

	"code.google.com/p/goplan9/plan9"
	"code.google.com/p/goplan9/plan9/client"
)

type window struct {
	Id    string
	Props string
	Tags  []string
}

func (win window) String() string {
	return win.Id + " " + win.Props + " " + strings.Join(win.Tags, "+")
}

type wmii struct {
	conn *client.Conn
	fsys *client.Fsys
}

func newWmii() (*wmii, error) {
	conn, err := client.DialService("wmii")
	if err != nil {
		return nil, err
	}

	fsys, err := conn.Attach(nil, "", "")
	if err != nil {
		conn.Close()
		return nil, err
	}

	return &wmii{conn: conn, fsys: fsys}, nil
}

func (wm *wmii) Close() error {
	return wm.conn.Close()
}

func (wm *wmii) Windows() ([]window, error) {
	dirname := "/client"
	dirs, err := wm.readDir(dirname)
	if err != nil {
		return nil, err
	}

	wins := make([]window, 0, len(dirs))
	for _, dir := range dirs {
		if dir.Name == "sel" {
			continue
		}
		fname := fmt.Sprintf("/client/%s/props", dir.Name)
		props, err := wm.readFile(fname)
		if err != nil {
			fmt.Fprintf(os.Stderr, "wmiinav: read %s: %s", fname, err)
		}
		fname = fmt.Sprintf("/client/%s/tags", dir.Name)
		tagstr, err := wm.readFile(fname)
		if err != nil {
			fmt.Fprintf(os.Stderr, "wmiinav: read %s: %s", fname, err)
		}
		tags := []string{}
		for _, tag := range strings.Split(string(tagstr), "+") {
			if tag != "" {
				tags = append(tags, tag)
			}
		}

		wins = append(wins, window{Id: dir.Name, Props: string(props), Tags: tags})
	}

	return wins, nil
}

func (wm *wmii) SelectWindow(id string) error {
	return wm.writeFile("/tag/sel/ctl", []byte(fmt.Sprintf("select client %s\n", id)))
}

func (wm *wmii) View(tag string) error {
	return wm.writeFile("/ctl", []byte(fmt.Sprintf("view %s\n", tag)))
}

func (wm *wmii) CurrentTag() (string, error) {
	buf, err := wm.readFile("/ctl")
	if err != nil {
		return "", err
	}

	sc := bufio.NewScanner(bytes.NewReader(buf))
	for sc.Scan() {
		line := sc.Text()
		if strings.HasPrefix(line, "view ") {
			return strings.TrimSpace(line[5:]), nil
		}
	}

	return "", sc.Err()
}

func (wm *wmii) AddTag(win *window, tag string) error {
	win.Tags = append(win.Tags, tag)
	return wm.writeFile(fmt.Sprintf("/client/%s/tags", win.Id), []byte("+" + tag))
}

func (wm *wmii) readDir(name string) ([]*plan9.Dir, error) {
	fid, err := wm.fsys.Open(name, plan9.OREAD)
	if err != nil {
		return nil, err
	}
	defer fid.Close()
	return fid.Dirreadall()
}

func (wm *wmii) readFile(name string) ([]byte, error) {
	fid, err := wm.fsys.Open(name, plan9.OREAD)
	if err != nil {
		return nil, err
	}
	defer fid.Close()
	return ioutil.ReadAll(fid)
}

func (wm *wmii) writeFile(name string, data []byte) error {
	fid, err := wm.fsys.Open(name, plan9.OWRITE)
	if err != nil {
		return err
	}
	_, err = fid.Write(data)
	fid.Close()
	return err
}

func selectWindow(windows []window) (int, error) {

	items := make([]string, len(windows))
	for i := range items {
		items[i] = fmt.Sprintf("<%d> [%s] %s", i, strings.Join(windows[i].Tags, "+"), windows[i].Props)
	}

	dmenu := exec.Command("dmenu", "-l", "7", "-i", "-b")

	in, err := dmenu.StdinPipe()
	if err != nil {
		return -1, err
	}

	go func() {
		for _, item := range items {
			fmt.Fprintln(in, item)
		}
		in.Close()
	}()

	out, err := dmenu.Output()
	if err != nil {
		return -1, err
	}

	if len(out) > 0 {
		sel := string(out[:len(out)-1])
		for i, item := range items {
			if item == sel {
				return i, nil
			}
		}
	}

	return -1, nil
}

func main() {
	wm, err := newWmii()
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}
	defer wm.Close()

	windows, err := wm.Windows()
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}

	sel, err := selectWindow(windows)
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}

	if sel < 0 {
		return
	}

	win := windows[sel]

	if len(win.Tags) == 0 {
		fmt.Fprintf(os.Stderr, "selected window has no tags\n")
		return
	}

	ctag, _ := wm.CurrentTag()
	ntag := win.Tags[0]

	for _, tag := range win.Tags {
		if tag == ctag {
			ntag = tag
		}
	}

	if ntag != ctag {
		if err := wm.View(ntag); err != nil {
			fmt.Fprintln(os.Stderr, err)
			os.Exit(1)
		}
	}

	if err := wm.SelectWindow(win.Id); err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}
}
<commit_msg>add current tag to selected window if untagged<commit_after>package main

import (
	"bufio"
	"bytes"
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"strings"

	"code.google.com/p/goplan9/plan9"
	"code.google.com/p/goplan9/plan9/client"
)

type window struct {
	Id    string
	Props string
	Tags  []string
}

func (win window) String() string {
	return win.Id + " " + win.Props + " " + strings.Join(win.Tags, "+")
}

type wmii struct {
	conn *client.Conn
	fsys *client.Fsys
}

func newWmii() (*wmii, error) {
	conn, err := client.DialService("wmii")
	if err != nil {
		return nil, err
	}

	fsys, err := conn.Attach(nil, "", "")
	if err != nil {
		conn.Close()
		return nil, err
	}

	return &wmii{conn: conn, fsys: fsys}, nil
}

func (wm *wmii) Close() error {
	return wm.conn.Close()
}

func (wm *wmii) Windows() ([]window, error) {
	dirname := "/client"
	dirs, err := wm.readDir(dirname)
	if err != nil {
		return nil, err
	}

	wins := make([]window, 0, len(dirs))
	for _, dir := range dirs {
		if dir.Name == "sel" {
			continue
		}
		fname := fmt.Sprintf("/client/%s/props", dir.Name)
		props, err := wm.readFile(fname)
		if err != nil {
			fmt.Fprintf(os.Stderr, "wmiinav: read %s: %s", fname, err)
		}
		fname = fmt.Sprintf("/client/%s/tags", dir.Name)
		tagstr, err := wm.readFile(fname)
		if err != nil {
			fmt.Fprintf(os.Stderr, "wmiinav: read %s: %s", fname, err)
		}
		tags := []string{}
		for _, tag := range strings.Split(string(tagstr), "+") {
			if tag != "" {
				tags = append(tags, tag)
			}
		}

		wins = append(wins, window{Id: dir.Name, Props: string(props), Tags: tags})
	}

	return wins, nil
}

func (wm *wmii) SelectWindow(id string) error {
	return wm.writeFile("/tag/sel/ctl", []byte(fmt.Sprintf("select client %s\n", id)))
}

func (wm *wmii) View(tag string) error {
	return wm.writeFile("/ctl", []byte(fmt.Sprintf("view %s\n", tag)))
}

func (wm *wmii) CurrentTag() (string, error) {
	buf, err := wm.readFile("/ctl")
	if err != nil {
		return "", err
	}

	sc := bufio.NewScanner(bytes.NewReader(buf))
	for sc.Scan() {
		line := sc.Text()
		if strings.HasPrefix(line, "view ") {
			return strings.TrimSpace(line[5:]), nil
		}
	}

	return "", sc.Err()
}

func (wm *wmii) AddTag(win *window, tag string) error {
	win.Tags = append(win.Tags, tag)
	return wm.writeFile(fmt.Sprintf("/client/%s/tags", win.Id), []byte("+" + tag))
}

func (wm *wmii) readDir(name string) ([]*plan9.Dir, error) {
	fid, err := wm.fsys.Open(name, plan9.OREAD)
	if err != nil {
		return nil, err
	}
	defer fid.Close()
	return fid.Dirreadall()
}

func (wm *wmii) readFile(name string) ([]byte, error) {
	fid, err := wm.fsys.Open(name, plan9.OREAD)
	if err != nil {
		return nil, err
	}
	defer fid.Close()
	return ioutil.ReadAll(fid)
}

func (wm *wmii) writeFile(name string, data []byte) error {
	fid, err := wm.fsys.Open(name, plan9.OWRITE)
	if err != nil {
		return err
	}
	_, err = fid.Write(data)
	fid.Close()
	return err
}

func selectWindow(windows []window) (int, error) {

	items := make([]string, len(windows))
	for i := range items {
		items[i] = fmt.Sprintf("<%d> [%s] %s", i, strings.Join(windows[i].Tags, "+"), windows[i].Props)
	}

	dmenu := exec.Command("dmenu", "-l", "7", "-i", "-b")

	in, err := dmenu.StdinPipe()
	if err != nil {
		return -1, err
	}

	go func() {
		for _, item := range items {
			fmt.Fprintln(in, item)
		}
		in.Close()
	}()

	out, err := dmenu.Output()
	if err != nil {
		return -1, err
	}

	if len(out) > 0 {
		sel := string(out[:len(out)-1])
		for i, item := range items {
			if item == sel {
				return i, nil
			}
		}
	}

	return -1, nil
}

func main() {
	wm, err := newWmii()
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}
	defer wm.Close()

	windows, err := wm.Windows()
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}

	sel, err := selectWindow(windows)
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}

	if sel < 0 {
		return
	}

	win := windows[sel]
	ctag, _ := wm.CurrentTag()

	if len(win.Tags) == 0 {
		err := wm.AddTag(&win, ctag)
		if err != nil {
			fmt.Println(os.Stderr, err)
			os.Exit(1)
		}
	}

	ntag := win.Tags[0]
	for _, tag := range win.Tags {
		if tag == ctag {
			ntag = tag
		}
	}

	if ntag != ctag {
		if err := wm.View(ntag); err != nil {
			fmt.Fprintln(os.Stderr, err)
			os.Exit(1)
		}
	}

	if err := wm.SelectWindow(win.Id); err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}
}
<|endoftext|>


<commit_before>package provisioner

import (
	"fmt"
	"os"

	"github.com/mitchellh/packer/common"
	"github.com/mitchellh/packer/helper/config"
	"github.com/mitchellh/packer/packer"
	"github.com/mitchellh/packer/template/interpolate"
)

type Config struct {
	common.PackerConfig `mapstructure:",squash"`

	Stemcell        string `mapstructure:"stemcell"`
	StemcellVersion string `mapstructure:"stemcell_version"`

	Release        string `mapstructure:"release"`
	ReleaseVersion string `mapstructure:"release_version"`

	Manifest string `mapstructure:"deployment_manifest"`

	ctx interpolate.Context
}

type Provisioner struct {
	config Config
}

func (p *Provisioner) Prepare(raws ...interface{}) error {

	err := config.Decode(&p.config, &config.DecodeOpts{
		Interpolate:        true,
		InterpolateContext: &p.config.ctx,
		InterpolateFilter: &interpolate.RenderFilter{
			Exclude: []string{},
		},
	}, raws...)
	if err != nil {
		return err
	}

	return nil
}

func (p *Provisioner) Provision(ui packer.Ui, comm packer.Communicator) error {

	p.uploadStemcell(ui, comm)
	p.uploadBoshRelease(ui, comm)
	p.uploadDeploymentManifest(ui, comm)
	p.deploy(ui, comm)
	return nil
}

func (p *Provisioner) Cancel() {
	os.Exit(0)
}

func (p *Provisioner) uploadStemcell(ui packer.Ui, comm packer.Communicator) error {
	ui.Say(fmt.Sprintf("Uploading stemcell %s", p.config.Stemcell))

	cmd := fmt.Sprintf("bosh upload stemcell --skip-if-exists https://bosh.io/d/stemcells/%s", p.config.Stemcell)
	if p.config.StemcellVersion != "" {
		cmd += fmt.Sprintf("?v=%s", p.config.StemcellVersion)
	}

	remoteCmd := &packer.RemoteCmd{Command: cmd}
	err := remoteCmd.StartWithUi(comm, ui)
	if err != nil {
		return fmt.Errorf("Starting command: %s", err)
	}

	if remoteCmd.ExitStatus != 0 {
		return fmt.Errorf("Non-zero exit status: %d", remoteCmd.ExitStatus)
	}

	return nil
}

func (p *Provisioner) uploadBoshRelease(ui packer.Ui, comm packer.Communicator) error {
	ui.Say(fmt.Sprintf("Uploading release %s", p.config.Release))

	cmd := fmt.Sprintf("bosh upload release --skip-if-exists https://bosh.io/d/github.com/%s", p.config.Release)
	if p.config.ReleaseVersion != "" {
		cmd += fmt.Sprintf("?v=%s", p.config.ReleaseVersion)
	}

	remoteCmd := &packer.RemoteCmd{Command: cmd}
	err := remoteCmd.StartWithUi(comm, ui)
	if err != nil {
		return fmt.Errorf("Starting command: %s", err)
	}

	if remoteCmd.ExitStatus != 0 {
		return fmt.Errorf("Non-zero exit status: %d", remoteCmd.ExitStatus)
	}

	return nil
}

func (p *Provisioner) uploadDeploymentManifest(ui packer.Ui, comm packer.Communicator) error {
	ui.Say(fmt.Sprintf("Uploading manifest: %s", p.config.Manifest))

	cmd := "mkdir ~/deployments"
	remoteCmd := &packer.RemoteCmd{Command: cmd}
	err := remoteCmd.StartWithUi(comm, ui)
	if err != nil {
		return fmt.Errorf("Starting command: %s", err)
	}

	if remoteCmd.ExitStatus != 0 {
		return fmt.Errorf("Non-zero exit status: %d", remoteCmd.ExitStatus)
	}

	f, err := os.Open(p.config.Manifest)
	if err != nil {
		return err
	}
	defer f.Close()

	fi, err := f.Stat()
	if err != nil {
		return err
	}

	err = comm.Upload(fmt.Sprintf("~/deployments/%s", p.config.Manifest), f, &fi)
	if err != nil {
		ui.Error(fmt.Sprintf("Upload of Manifest failed: %s", err))
		return err
	}

	return nil
}

func (p *Provisioner) deploy(ui packer.Ui, comm packer.Communicator) error {
	ui.Say("Deploying")
	return nil
}
<commit_msg>Remove redundant tags<commit_after>package provisioner

import (
	"fmt"
	"os"

	"github.com/mitchellh/packer/common"
	"github.com/mitchellh/packer/helper/config"
	"github.com/mitchellh/packer/packer"
	"github.com/mitchellh/packer/template/interpolate"
)

type Config struct {
	common.PackerConfig `mapstructure:",squash"`

	Stemcell        string
	StemcellVersion string `mapstructure:"stemcell_version"`

	Release        string
	ReleaseVersion string `mapstructure:"release_version"`

	Manifest string

	ctx interpolate.Context
}

type Provisioner struct {
	config Config
}

func (p *Provisioner) Prepare(raws ...interface{}) error {

	err := config.Decode(&p.config, &config.DecodeOpts{
		Interpolate:        true,
		InterpolateContext: &p.config.ctx,
		InterpolateFilter: &interpolate.RenderFilter{
			Exclude: []string{},
		},
	}, raws...)
	if err != nil {
		return err
	}

	return nil
}

func (p *Provisioner) Provision(ui packer.Ui, comm packer.Communicator) error {

	p.uploadStemcell(ui, comm)
	p.uploadBoshRelease(ui, comm)
	p.uploadDeploymentManifest(ui, comm)
	p.deploy(ui, comm)
	return nil
}

func (p *Provisioner) Cancel() {
	os.Exit(0)
}

func (p *Provisioner) uploadStemcell(ui packer.Ui, comm packer.Communicator) error {
	ui.Say(fmt.Sprintf("Uploading stemcell %s", p.config.Stemcell))

	cmd := fmt.Sprintf("bosh upload stemcell --skip-if-exists https://bosh.io/d/stemcells/%s", p.config.Stemcell)
	if p.config.StemcellVersion != "" {
		cmd += fmt.Sprintf("?v=%s", p.config.StemcellVersion)
	}

	remoteCmd := &packer.RemoteCmd{Command: cmd}
	err := remoteCmd.StartWithUi(comm, ui)
	if err != nil {
		return fmt.Errorf("Starting command: %s", err)
	}

	if remoteCmd.ExitStatus != 0 {
		return fmt.Errorf("Non-zero exit status: %d", remoteCmd.ExitStatus)
	}

	return nil
}

func (p *Provisioner) uploadBoshRelease(ui packer.Ui, comm packer.Communicator) error {
	ui.Say(fmt.Sprintf("Uploading release %s", p.config.Release))

	cmd := fmt.Sprintf("bosh upload release --skip-if-exists https://bosh.io/d/github.com/%s", p.config.Release)
	if p.config.ReleaseVersion != "" {
		cmd += fmt.Sprintf("?v=%s", p.config.ReleaseVersion)
	}

	remoteCmd := &packer.RemoteCmd{Command: cmd}
	err := remoteCmd.StartWithUi(comm, ui)
	if err != nil {
		return fmt.Errorf("Starting command: %s", err)
	}

	if remoteCmd.ExitStatus != 0 {
		return fmt.Errorf("Non-zero exit status: %d", remoteCmd.ExitStatus)
	}

	return nil
}

func (p *Provisioner) uploadDeploymentManifest(ui packer.Ui, comm packer.Communicator) error {
	ui.Say(fmt.Sprintf("Uploading manifest: %s", p.config.Manifest))

	cmd := "mkdir ~/deployments"
	remoteCmd := &packer.RemoteCmd{Command: cmd}
	err := remoteCmd.StartWithUi(comm, ui)
	if err != nil {
		return fmt.Errorf("Starting command: %s", err)
	}

	if remoteCmd.ExitStatus != 0 {
		return fmt.Errorf("Non-zero exit status: %d", remoteCmd.ExitStatus)
	}

	f, err := os.Open(p.config.Manifest)
	if err != nil {
		return err
	}
	defer f.Close()

	fi, err := f.Stat()
	if err != nil {
		return err
	}

	err = comm.Upload(fmt.Sprintf("~/deployments/%s", p.config.Manifest), f, &fi)
	if err != nil {
		ui.Error(fmt.Sprintf("Upload of Manifest failed: %s", err))
		return err
	}

	return nil
}

func (p *Provisioner) deploy(ui packer.Ui, comm packer.Communicator) error {
	ui.Say("Deploying")
	return nil
}
<|endoftext|>


<commit_before><commit_msg>Now generating a default server-config.json when not created yet<commit_after><|endoftext|>


<commit_before>package aws

import (
	"fmt"
	"log"
	"regexp"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/backup"
	"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
	"github.com/hashicorp/terraform-plugin-sdk/helper/validation"
)

func resourceAwsBackupVaultNotifications() *schema.Resource {
	return &schema.Resource{
		Create: resourceAwsBackupVaultNotificationsCreate,
		Read:   resourceAwsBackupVaultNotificationsRead,
		Delete: resourceAwsBackupVaultNotificationsDelete,
		Importer: &schema.ResourceImporter{
			State: schema.ImportStatePassthrough,
		},

		Schema: map[string]*schema.Schema{
			"backup_vault_name": {
				Type:         schema.TypeString,
				Required:     true,
				ForceNew:     true,
				ValidateFunc: validation.StringMatch(regexp.MustCompile(`^[a-zA-Z0-9\-\_\.]{1,50}$`), "must consist of lowercase letters, numbers, and hyphens."),
			},
			"sns_topic_arn": {
				Type:         schema.TypeString,
				Required:     true,
				ForceNew:     true,
				ValidateFunc: validateArn,
			},
			"backup_vault_events": {
				Type:     schema.TypeSet,
				Required: true,
				ForceNew: true,
				Elem: &schema.Schema{
					Type: schema.TypeString,
					ValidateFunc: validation.StringInSlice([]string{
						backup.VaultEventBackupJobStarted,
						backup.VaultEventBackupJobCompleted,
						backup.VaultEventBackupJobSuccessful,
						backup.VaultEventBackupJobFailed,
						backup.VaultEventBackupJobExpired,
						backup.VaultEventRestoreJobStarted,
						backup.VaultEventRestoreJobSuccessful,
						backup.VaultEventRestoreJobCompleted,
						backup.VaultEventRestoreJobFailed,
						backup.VaultEventCopyJobFailed,
						backup.VaultEventCopyJobStarted,
						backup.VaultEventCopyJobSuccessful,
						backup.VaultEventRecoveryPointModified,
						backup.VaultEventBackupPlanCreated,
						backup.VaultEventBackupPlanModified,
					}, false),
				},
			},
			"backup_vault_arn": {
				Type:     schema.TypeString,
				Computed: true,
			},
		},
	}
}

func resourceAwsBackupVaultNotificationsCreate(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).backupconn

	input := &backup.PutBackupVaultNotificationsInput{
		BackupVaultName:   aws.String(d.Get("backup_vault_name").(string)),
		SNSTopicArn:       aws.String(d.Get("sns_topic_arn").(string)),
		BackupVaultEvents: expandStringSet(d.Get("backup_vault_events").(*schema.Set)),
	}

	_, err := conn.PutBackupVaultNotifications(input)
	if err != nil {
		return fmt.Errorf("error creating Backup Vault Notifications (%s): %w", d.Id(), err)
	}

	d.SetId(d.Get("backup_vault_name").(string))

	return resourceAwsBackupVaultNotificationsRead(d, meta)
}

func resourceAwsBackupVaultNotificationsRead(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).backupconn

	input := &backup.GetBackupVaultNotificationsInput{
		BackupVaultName: aws.String(d.Id()),
	}

	resp, err := conn.GetBackupVaultNotifications(input)
	if isAWSErr(err, backup.ErrCodeResourceNotFoundException, "") {
		log.Printf("[WARN] Backup Vault Notifcations %s not found, removing from state", d.Id())
		d.SetId("")
		return nil
	}

	if err != nil {
		return fmt.Errorf("error reading Backup Vault Notifications (%s): %w", d.Id(), err)
	}
	d.Set("backup_vault_name", resp.BackupVaultName)
	d.Set("sns_topic_arn", resp.SNSTopicArn)
	d.Set("backup_vault_arn", resp.BackupVaultArn)
	if err := d.Set("backup_vault_events", flattenStringSet(resp.BackupVaultEvents)); err != nil {
	  return fmt.Errorf("error setting backup_vault_events: %w", err)
	}

	return nil
}

func resourceAwsBackupVaultNotificationsDelete(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).backupconn

	input := &backup.DeleteBackupVaultNotificationsInput{
		BackupVaultName: aws.String(d.Id()),
	}

	_, err := conn.DeleteBackupVaultNotifications(input)
	if err != nil {
		if isAWSErr(err, backup.ErrCodeResourceNotFoundException, "") {
			return nil
		}
		return fmt.Errorf("error deleting Backup Vault Notification (%s): %w", d.Id(), err)
	}

	return nil
}
<commit_msg>Update aws/resource_aws_backup_vault_notifications.go<commit_after>package aws

import (
	"fmt"
	"log"
	"regexp"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/backup"
	"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
	"github.com/hashicorp/terraform-plugin-sdk/helper/validation"
)

func resourceAwsBackupVaultNotifications() *schema.Resource {
	return &schema.Resource{
		Create: resourceAwsBackupVaultNotificationsCreate,
		Read:   resourceAwsBackupVaultNotificationsRead,
		Delete: resourceAwsBackupVaultNotificationsDelete,
		Importer: &schema.ResourceImporter{
			State: schema.ImportStatePassthrough,
		},

		Schema: map[string]*schema.Schema{
			"backup_vault_name": {
				Type:         schema.TypeString,
				Required:     true,
				ForceNew:     true,
				ValidateFunc: validation.StringMatch(regexp.MustCompile(`^[a-zA-Z0-9\-\_\.]{1,50}$`), "must consist of lowercase letters, numbers, and hyphens."),
			},
			"sns_topic_arn": {
				Type:         schema.TypeString,
				Required:     true,
				ForceNew:     true,
				ValidateFunc: validateArn,
			},
			"backup_vault_events": {
				Type:     schema.TypeSet,
				Required: true,
				ForceNew: true,
				Elem: &schema.Schema{
					Type: schema.TypeString,
					ValidateFunc: validation.StringInSlice([]string{
						backup.VaultEventBackupJobStarted,
						backup.VaultEventBackupJobCompleted,
						backup.VaultEventBackupJobSuccessful,
						backup.VaultEventBackupJobFailed,
						backup.VaultEventBackupJobExpired,
						backup.VaultEventRestoreJobStarted,
						backup.VaultEventRestoreJobSuccessful,
						backup.VaultEventRestoreJobCompleted,
						backup.VaultEventRestoreJobFailed,
						backup.VaultEventCopyJobFailed,
						backup.VaultEventCopyJobStarted,
						backup.VaultEventCopyJobSuccessful,
						backup.VaultEventRecoveryPointModified,
						backup.VaultEventBackupPlanCreated,
						backup.VaultEventBackupPlanModified,
					}, false),
				},
			},
			"backup_vault_arn": {
				Type:     schema.TypeString,
				Computed: true,
			},
		},
	}
}

func resourceAwsBackupVaultNotificationsCreate(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).backupconn

	input := &backup.PutBackupVaultNotificationsInput{
		BackupVaultName:   aws.String(d.Get("backup_vault_name").(string)),
		SNSTopicArn:       aws.String(d.Get("sns_topic_arn").(string)),
		BackupVaultEvents: expandStringSet(d.Get("backup_vault_events").(*schema.Set)),
	}

	_, err := conn.PutBackupVaultNotifications(input)
	if err != nil {
		return fmt.Errorf("error creating Backup Vault Notifications (%s): %w", d.Id(), err)
	}

	d.SetId(d.Get("backup_vault_name").(string))

	return resourceAwsBackupVaultNotificationsRead(d, meta)
}

func resourceAwsBackupVaultNotificationsRead(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).backupconn

	input := &backup.GetBackupVaultNotificationsInput{
		BackupVaultName: aws.String(d.Id()),
	}

	resp, err := conn.GetBackupVaultNotifications(input)
	if isAWSErr(err, backup.ErrCodeResourceNotFoundException, "") {
		log.Printf("[WARN] Backup Vault Notifcations %s not found, removing from state", d.Id())
		d.SetId("")
		return nil
	}

	if err != nil {
		return fmt.Errorf("error reading Backup Vault Notifications (%s): %w", d.Id(), err)
	}
	d.Set("backup_vault_name", resp.BackupVaultName)
	d.Set("sns_topic_arn", resp.SNSTopicArn)
	d.Set("backup_vault_arn", resp.BackupVaultArn)
	if err := d.Set("backup_vault_events", flattenStringSet(resp.BackupVaultEvents)); err != nil {
	  return fmt.Errorf("error setting backup_vault_events: %w", err)
	}

	return nil
}

func resourceAwsBackupVaultNotificationsDelete(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).backupconn

	input := &backup.DeleteBackupVaultNotificationsInput{
		BackupVaultName: aws.String(d.Id()),
	}

	_, err := conn.DeleteBackupVaultNotifications(input)
	if err != nil {
		if isAWSErr(err, backup.ErrCodeResourceNotFoundException, "") {
			return nil
		}
		return fmt.Errorf("error deleting Backup Vault Notifications (%s): %w", d.Id(), err)
	}

	return nil
}
<|endoftext|>


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

package docker

import (
	"bytes"
	"net"
	"net/http"
	"net/http/httptest"
	"net/url"
	"sync"
	"time"

	"github.com/tsuru/config"
	"github.com/tsuru/tsuru/app"
	"gopkg.in/mgo.v2/bson"
	"launchpad.net/gocheck"
)

func (s *S) TestHealthcheck(c *gocheck.C) {
	var requests []*http.Request
	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		requests = append(requests, r)
		w.WriteHeader(http.StatusCreated)
	}))
	defer server.Close()
	a := app.App{Name: "myapp1", CustomData: map[string]interface{}{
		"healthcheck": map[string]interface{}{
			"path":   "/x/y",
			"method": "Post",
			"status": http.StatusCreated,
		},
	}}
	err := s.storage.Apps().Insert(a)
	c.Assert(err, gocheck.IsNil)
	defer s.storage.Apps().RemoveAll(bson.M{"name": a.Name})
	url, _ := url.Parse(server.URL)
	host, port, _ := net.SplitHostPort(url.Host)
	cont := container{AppName: a.Name, HostAddr: host, HostPort: port}
	buf := bytes.Buffer{}
	err = runHealthcheck(&cont, &buf)
	c.Assert(err, gocheck.IsNil)
	c.Assert(requests, gocheck.HasLen, 1)
	c.Assert(requests[0].URL.Path, gocheck.Equals, "/x/y")
	c.Assert(requests[0].Method, gocheck.Equals, "POST")
	c.Assert(buf.String(), gocheck.Equals, " ---> healthcheck successful()\n")
}

func (s *S) TestHealthcheckWithMatch(c *gocheck.C) {
	var requests []*http.Request
	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		requests = append(requests, r)
		if len(requests) == 1 {
			w.Write([]byte("invalid"))
		} else {
			w.Write([]byte("something"))
		}
	}))
	defer server.Close()
	a := app.App{Name: "myapp1", CustomData: map[string]interface{}{
		"healthcheck": map[string]interface{}{
			"path":   "/x/y",
			"method": "Get",
			"status": 200,
			"match":  ".*some.*",
		},
	}}
	err := s.storage.Apps().Insert(a)
	c.Assert(err, gocheck.IsNil)
	defer s.storage.Apps().RemoveAll(bson.M{"name": a.Name})
	url, _ := url.Parse(server.URL)
	host, port, _ := net.SplitHostPort(url.Host)
	cont := container{AppName: a.Name, HostAddr: host, HostPort: port}
	buf := bytes.Buffer{}
	err = runHealthcheck(&cont, &buf)
	c.Assert(err, gocheck.ErrorMatches, ".*unexpected result, expected \"(?s).*some.*\", got: invalid")
	c.Assert(requests, gocheck.HasLen, 1)
	c.Assert(requests[0].Method, gocheck.Equals, "GET")
	err = runHealthcheck(&cont, &buf)
	c.Assert(err, gocheck.IsNil)
	c.Assert(requests, gocheck.HasLen, 2)
	c.Assert(requests[1].URL.Path, gocheck.Equals, "/x/y")
	c.Assert(requests[1].Method, gocheck.Equals, "GET")
}

func (s *S) TestHealthcheckDefaultCheck(c *gocheck.C) {
	var requests []*http.Request
	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		requests = append(requests, r)
		w.WriteHeader(http.StatusOK)
	}))
	defer server.Close()
	a := app.App{Name: "myapp1", CustomData: map[string]interface{}{
		"healthcheck": map[string]interface{}{
			"path": "/x/y",
		},
	}}
	err := s.storage.Apps().Insert(a)
	c.Assert(err, gocheck.IsNil)
	defer s.storage.Apps().RemoveAll(bson.M{"name": a.Name})
	url, _ := url.Parse(server.URL)
	host, port, _ := net.SplitHostPort(url.Host)
	cont := container{AppName: a.Name, HostAddr: host, HostPort: port}
	buf := bytes.Buffer{}
	err = runHealthcheck(&cont, &buf)
	c.Assert(err, gocheck.IsNil)
	c.Assert(requests, gocheck.HasLen, 1)
	c.Assert(requests[0].Method, gocheck.Equals, "GET")
	c.Assert(requests[0].URL.Path, gocheck.Equals, "/x/y")
}

func (s *S) TestHealthcheckNoHealthcheck(c *gocheck.C) {
	var requests []*http.Request
	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		requests = append(requests, r)
		w.WriteHeader(http.StatusOK)
	}))
	defer server.Close()
	a := app.App{Name: "myapp1"}
	err := s.storage.Apps().Insert(a)
	c.Assert(err, gocheck.IsNil)
	defer s.storage.Apps().RemoveAll(bson.M{"name": a.Name})
	url, _ := url.Parse(server.URL)
	host, port, _ := net.SplitHostPort(url.Host)
	cont := container{AppName: a.Name, HostAddr: host, HostPort: port}
	buf := bytes.Buffer{}
	err = runHealthcheck(&cont, &buf)
	c.Assert(err, gocheck.IsNil)
	c.Assert(requests, gocheck.HasLen, 0)
}

func (s *S) TestHealthcheckNoPath(c *gocheck.C) {
	var requests []*http.Request
	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		requests = append(requests, r)
		w.WriteHeader(http.StatusOK)
	}))
	defer server.Close()
	a := app.App{Name: "myapp1", CustomData: map[string]interface{}{
		"healthcheck": map[string]interface{}{
			"method": "GET",
			"status": 200,
		},
	}}
	err := s.storage.Apps().Insert(a)
	c.Assert(err, gocheck.IsNil)
	defer s.storage.Apps().RemoveAll(bson.M{"name": a.Name})
	url, _ := url.Parse(server.URL)
	host, port, _ := net.SplitHostPort(url.Host)
	cont := container{AppName: a.Name, HostAddr: host, HostPort: port}
	buf := bytes.Buffer{}
	err = runHealthcheck(&cont, &buf)
	c.Assert(err, gocheck.IsNil)
	c.Assert(requests, gocheck.HasLen, 0)
}

func (s *S) TestHealthcheckKeepsTryingWithServerDown(c *gocheck.C) {
	var requests []*http.Request
	lock := sync.Mutex{}
	shouldRun := false
	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		lock.Lock()
		defer lock.Unlock()
		requests = append(requests, r)
		if shouldRun {
			w.WriteHeader(http.StatusOK)
		} else {
			hj := w.(http.Hijacker)
			conn, _, _ := hj.Hijack()
			conn.Close()
		}
	}))
	a := app.App{Name: "myapp1", CustomData: map[string]interface{}{
		"healthcheck": map[string]interface{}{
			"path": "/x/y",
		},
	}}
	err := s.storage.Apps().Insert(a)
	c.Assert(err, gocheck.IsNil)
	defer s.storage.Apps().RemoveAll(bson.M{"name": a.Name})
	url, _ := url.Parse(server.URL)
	host, port, _ := net.SplitHostPort(url.Host)
	cont := container{AppName: a.Name, HostAddr: host, HostPort: port}
	buf := bytes.Buffer{}
	go func() {
		time.Sleep(1 * time.Second)
		lock.Lock()
		defer lock.Unlock()
		shouldRun = true
	}()
	err = runHealthcheck(&cont, &buf)
	c.Assert(err, gocheck.IsNil)
	c.Assert(buf.String(), gocheck.Matches, `(?s).*---> healthcheck fail.*?Trying again in 3s.*---> healthcheck successful.*`)
	c.Assert(requests, gocheck.HasLen, 2)
	c.Assert(requests[0].Method, gocheck.Equals, "GET")
	c.Assert(requests[0].URL.Path, gocheck.Equals, "/x/y")
	c.Assert(requests[1].Method, gocheck.Equals, "GET")
	c.Assert(requests[1].URL.Path, gocheck.Equals, "/x/y")
}

func (s *S) TestHealthcheckErrorsAfterMaxTime(c *gocheck.C) {
	a := app.App{Name: "myapp1", CustomData: map[string]interface{}{
		"healthcheck": map[string]interface{}{
			"path": "/x/y",
		},
	}}
	err := s.storage.Apps().Insert(a)
	c.Assert(err, gocheck.IsNil)
	defer s.storage.Apps().RemoveAll(bson.M{"name": a.Name})
	url, _ := url.Parse("http://some-invalid-server-name.some-invalid-server-name.com:9123")
	host, port, _ := net.SplitHostPort(url.Host)
	cont := container{AppName: a.Name, HostAddr: host, HostPort: port}
	buf := bytes.Buffer{}
	config.Set("docker:healthcheck:max-time", 1)
	defer config.Unset("docker:healthcheck:max-time")
	done := make(chan struct{})
	go func() {
		err = runHealthcheck(&cont, &buf)
		close(done)
	}()
	select {
	case <-time.After(5 * time.Second):
		c.Fatal("Timed out waiting for healthcheck to fail")
	case <-done:
	}
	c.Assert(err, gocheck.ErrorMatches, "healthcheck fail.*lookup some-invalid-server-name.some-invalid-server-name.com: no such host")
}

func (s *S) TestSuccessfulHealthcheckWithAllowedFailures(c *gocheck.C) {
	var requests []*http.Request
	lock := sync.Mutex{}
	step := 0
	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		lock.Lock()
		defer lock.Unlock()
		requests = append(requests, r)
		if step == 2 {
			w.WriteHeader(http.StatusOK)
		} else if step == 1 {
			w.WriteHeader(http.StatusBadGateway)
		} else {
			hj := w.(http.Hijacker)
			conn, _, _ := hj.Hijack()
			conn.Close()
		}
	}))
	a := app.App{Name: "myapp1", CustomData: map[string]interface{}{
		"healthcheck": map[string]interface{}{
			"path": "/x/y",
			"allowed_failures": 1,
		},
	}}
	err := s.storage.Apps().Insert(a)
	c.Assert(err, gocheck.IsNil)
	defer s.storage.Apps().RemoveAll(bson.M{"name": a.Name})
	url, _ := url.Parse(server.URL)
	host, port, _ := net.SplitHostPort(url.Host)
	cont := container{AppName: a.Name, HostAddr: host, HostPort: port}
	buf := bytes.Buffer{}
	go func() {
		time.Sleep(1 * time.Second)
		lock.Lock()
		step = 1
		lock.Unlock()
		time.Sleep(3 * time.Second)
		lock.Lock()
		defer lock.Unlock()
		step = 2
	}()
	err = runHealthcheck(&cont, &buf)
	c.Assert(err, gocheck.IsNil)
	c.Assert(buf.String(), gocheck.Matches, `(?s).*---> healthcheck fail.*?Trying again in 3s.*---> healthcheck fail.*?Trying again in 3s.*---> healthcheck successful.*`)
	c.Assert(requests, gocheck.HasLen, 3)
	c.Assert(requests[0].Method, gocheck.Equals, "GET")
	c.Assert(requests[0].URL.Path, gocheck.Equals, "/x/y")
	c.Assert(requests[1].Method, gocheck.Equals, "GET")
	c.Assert(requests[1].URL.Path, gocheck.Equals, "/x/y")
	c.Assert(requests[2].Method, gocheck.Equals, "GET")
	c.Assert(requests[2].URL.Path, gocheck.Equals, "/x/y")
}
<commit_msg>fix gofmt and goimport errors<commit_after>// Copyright 2015 tsuru authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package docker

import (
	"bytes"
	"net"
	"net/http"
	"net/http/httptest"
	"net/url"
	"sync"
	"time"

	"github.com/tsuru/config"
	"github.com/tsuru/tsuru/app"
	"gopkg.in/mgo.v2/bson"
	"launchpad.net/gocheck"
)

func (s *S) TestHealthcheck(c *gocheck.C) {
	var requests []*http.Request
	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		requests = append(requests, r)
		w.WriteHeader(http.StatusCreated)
	}))
	defer server.Close()
	a := app.App{Name: "myapp1", CustomData: map[string]interface{}{
		"healthcheck": map[string]interface{}{
			"path":   "/x/y",
			"method": "Post",
			"status": http.StatusCreated,
		},
	}}
	err := s.storage.Apps().Insert(a)
	c.Assert(err, gocheck.IsNil)
	defer s.storage.Apps().RemoveAll(bson.M{"name": a.Name})
	url, _ := url.Parse(server.URL)
	host, port, _ := net.SplitHostPort(url.Host)
	cont := container{AppName: a.Name, HostAddr: host, HostPort: port}
	buf := bytes.Buffer{}
	err = runHealthcheck(&cont, &buf)
	c.Assert(err, gocheck.IsNil)
	c.Assert(requests, gocheck.HasLen, 1)
	c.Assert(requests[0].URL.Path, gocheck.Equals, "/x/y")
	c.Assert(requests[0].Method, gocheck.Equals, "POST")
	c.Assert(buf.String(), gocheck.Equals, " ---> healthcheck successful()\n")
}

func (s *S) TestHealthcheckWithMatch(c *gocheck.C) {
	var requests []*http.Request
	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		requests = append(requests, r)
		if len(requests) == 1 {
			w.Write([]byte("invalid"))
		} else {
			w.Write([]byte("something"))
		}
	}))
	defer server.Close()
	a := app.App{Name: "myapp1", CustomData: map[string]interface{}{
		"healthcheck": map[string]interface{}{
			"path":   "/x/y",
			"method": "Get",
			"status": 200,
			"match":  ".*some.*",
		},
	}}
	err := s.storage.Apps().Insert(a)
	c.Assert(err, gocheck.IsNil)
	defer s.storage.Apps().RemoveAll(bson.M{"name": a.Name})
	url, _ := url.Parse(server.URL)
	host, port, _ := net.SplitHostPort(url.Host)
	cont := container{AppName: a.Name, HostAddr: host, HostPort: port}
	buf := bytes.Buffer{}
	err = runHealthcheck(&cont, &buf)
	c.Assert(err, gocheck.ErrorMatches, ".*unexpected result, expected \"(?s).*some.*\", got: invalid")
	c.Assert(requests, gocheck.HasLen, 1)
	c.Assert(requests[0].Method, gocheck.Equals, "GET")
	err = runHealthcheck(&cont, &buf)
	c.Assert(err, gocheck.IsNil)
	c.Assert(requests, gocheck.HasLen, 2)
	c.Assert(requests[1].URL.Path, gocheck.Equals, "/x/y")
	c.Assert(requests[1].Method, gocheck.Equals, "GET")
}

func (s *S) TestHealthcheckDefaultCheck(c *gocheck.C) {
	var requests []*http.Request
	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		requests = append(requests, r)
		w.WriteHeader(http.StatusOK)
	}))
	defer server.Close()
	a := app.App{Name: "myapp1", CustomData: map[string]interface{}{
		"healthcheck": map[string]interface{}{
			"path": "/x/y",
		},
	}}
	err := s.storage.Apps().Insert(a)
	c.Assert(err, gocheck.IsNil)
	defer s.storage.Apps().RemoveAll(bson.M{"name": a.Name})
	url, _ := url.Parse(server.URL)
	host, port, _ := net.SplitHostPort(url.Host)
	cont := container{AppName: a.Name, HostAddr: host, HostPort: port}
	buf := bytes.Buffer{}
	err = runHealthcheck(&cont, &buf)
	c.Assert(err, gocheck.IsNil)
	c.Assert(requests, gocheck.HasLen, 1)
	c.Assert(requests[0].Method, gocheck.Equals, "GET")
	c.Assert(requests[0].URL.Path, gocheck.Equals, "/x/y")
}

func (s *S) TestHealthcheckNoHealthcheck(c *gocheck.C) {
	var requests []*http.Request
	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		requests = append(requests, r)
		w.WriteHeader(http.StatusOK)
	}))
	defer server.Close()
	a := app.App{Name: "myapp1"}
	err := s.storage.Apps().Insert(a)
	c.Assert(err, gocheck.IsNil)
	defer s.storage.Apps().RemoveAll(bson.M{"name": a.Name})
	url, _ := url.Parse(server.URL)
	host, port, _ := net.SplitHostPort(url.Host)
	cont := container{AppName: a.Name, HostAddr: host, HostPort: port}
	buf := bytes.Buffer{}
	err = runHealthcheck(&cont, &buf)
	c.Assert(err, gocheck.IsNil)
	c.Assert(requests, gocheck.HasLen, 0)
}

func (s *S) TestHealthcheckNoPath(c *gocheck.C) {
	var requests []*http.Request
	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		requests = append(requests, r)
		w.WriteHeader(http.StatusOK)
	}))
	defer server.Close()
	a := app.App{Name: "myapp1", CustomData: map[string]interface{}{
		"healthcheck": map[string]interface{}{
			"method": "GET",
			"status": 200,
		},
	}}
	err := s.storage.Apps().Insert(a)
	c.Assert(err, gocheck.IsNil)
	defer s.storage.Apps().RemoveAll(bson.M{"name": a.Name})
	url, _ := url.Parse(server.URL)
	host, port, _ := net.SplitHostPort(url.Host)
	cont := container{AppName: a.Name, HostAddr: host, HostPort: port}
	buf := bytes.Buffer{}
	err = runHealthcheck(&cont, &buf)
	c.Assert(err, gocheck.IsNil)
	c.Assert(requests, gocheck.HasLen, 0)
}

func (s *S) TestHealthcheckKeepsTryingWithServerDown(c *gocheck.C) {
	var requests []*http.Request
	lock := sync.Mutex{}
	shouldRun := false
	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		lock.Lock()
		defer lock.Unlock()
		requests = append(requests, r)
		if shouldRun {
			w.WriteHeader(http.StatusOK)
		} else {
			hj := w.(http.Hijacker)
			conn, _, _ := hj.Hijack()
			conn.Close()
		}
	}))
	a := app.App{Name: "myapp1", CustomData: map[string]interface{}{
		"healthcheck": map[string]interface{}{
			"path": "/x/y",
		},
	}}
	err := s.storage.Apps().Insert(a)
	c.Assert(err, gocheck.IsNil)
	defer s.storage.Apps().RemoveAll(bson.M{"name": a.Name})
	url, _ := url.Parse(server.URL)
	host, port, _ := net.SplitHostPort(url.Host)
	cont := container{AppName: a.Name, HostAddr: host, HostPort: port}
	buf := bytes.Buffer{}
	go func() {
		time.Sleep(1 * time.Second)
		lock.Lock()
		defer lock.Unlock()
		shouldRun = true
	}()
	err = runHealthcheck(&cont, &buf)
	c.Assert(err, gocheck.IsNil)
	c.Assert(buf.String(), gocheck.Matches, `(?s).*---> healthcheck fail.*?Trying again in 3s.*---> healthcheck successful.*`)
	c.Assert(requests, gocheck.HasLen, 2)
	c.Assert(requests[0].Method, gocheck.Equals, "GET")
	c.Assert(requests[0].URL.Path, gocheck.Equals, "/x/y")
	c.Assert(requests[1].Method, gocheck.Equals, "GET")
	c.Assert(requests[1].URL.Path, gocheck.Equals, "/x/y")
}

func (s *S) TestHealthcheckErrorsAfterMaxTime(c *gocheck.C) {
	a := app.App{Name: "myapp1", CustomData: map[string]interface{}{
		"healthcheck": map[string]interface{}{
			"path": "/x/y",
		},
	}}
	err := s.storage.Apps().Insert(a)
	c.Assert(err, gocheck.IsNil)
	defer s.storage.Apps().RemoveAll(bson.M{"name": a.Name})
	url, _ := url.Parse("http://some-invalid-server-name.some-invalid-server-name.com:9123")
	host, port, _ := net.SplitHostPort(url.Host)
	cont := container{AppName: a.Name, HostAddr: host, HostPort: port}
	buf := bytes.Buffer{}
	config.Set("docker:healthcheck:max-time", 1)
	defer config.Unset("docker:healthcheck:max-time")
	done := make(chan struct{})
	go func() {
		err = runHealthcheck(&cont, &buf)
		close(done)
	}()
	select {
	case <-time.After(5 * time.Second):
		c.Fatal("Timed out waiting for healthcheck to fail")
	case <-done:
	}
	c.Assert(err, gocheck.ErrorMatches, "healthcheck fail.*lookup some-invalid-server-name.some-invalid-server-name.com: no such host")
}

func (s *S) TestSuccessfulHealthcheckWithAllowedFailures(c *gocheck.C) {
	var requests []*http.Request
	lock := sync.Mutex{}
	step := 0
	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		lock.Lock()
		defer lock.Unlock()
		requests = append(requests, r)
		if step == 2 {
			w.WriteHeader(http.StatusOK)
		} else if step == 1 {
			w.WriteHeader(http.StatusBadGateway)
		} else {
			hj := w.(http.Hijacker)
			conn, _, _ := hj.Hijack()
			conn.Close()
		}
	}))
	a := app.App{Name: "myapp1", CustomData: map[string]interface{}{
		"healthcheck": map[string]interface{}{
			"path":             "/x/y",
			"allowed_failures": 1,
		},
	}}
	err := s.storage.Apps().Insert(a)
	c.Assert(err, gocheck.IsNil)
	defer s.storage.Apps().RemoveAll(bson.M{"name": a.Name})
	url, _ := url.Parse(server.URL)
	host, port, _ := net.SplitHostPort(url.Host)
	cont := container{AppName: a.Name, HostAddr: host, HostPort: port}
	buf := bytes.Buffer{}
	go func() {
		time.Sleep(1 * time.Second)
		lock.Lock()
		step = 1
		lock.Unlock()
		time.Sleep(3 * time.Second)
		lock.Lock()
		defer lock.Unlock()
		step = 2
	}()
	err = runHealthcheck(&cont, &buf)
	c.Assert(err, gocheck.IsNil)
	c.Assert(buf.String(), gocheck.Matches, `(?s).*---> healthcheck fail.*?Trying again in 3s.*---> healthcheck fail.*?Trying again in 3s.*---> healthcheck successful.*`)
	c.Assert(requests, gocheck.HasLen, 3)
	c.Assert(requests[0].Method, gocheck.Equals, "GET")
	c.Assert(requests[0].URL.Path, gocheck.Equals, "/x/y")
	c.Assert(requests[1].Method, gocheck.Equals, "GET")
	c.Assert(requests[1].URL.Path, gocheck.Equals, "/x/y")
	c.Assert(requests[2].Method, gocheck.Equals, "GET")
	c.Assert(requests[2].URL.Path, gocheck.Equals, "/x/y")
}
<|endoftext|>


<commit_before>// This package implements a provisioner for Packer that uses
// Chef to provision the remote machine, specifically with chef-solo (that is,
// without a Chef server).
package chefsolo

import (
	"bytes"
	"encoding/json"
	"fmt"
	"github.com/mitchellh/packer/common"
	"github.com/mitchellh/packer/packer"
	"os"
	"path/filepath"
	"strings"
)

const (
	RemoteStagingPath    = "/tmp/provision/chef-solo"
	RemoteFileCachePath  = "/tmp/provision/chef-solo"
	RemoteCookbookPath   = "/tmp/provision/chef-solo/cookbooks"
	DefaultCookbooksPath = "cookbooks"
)

var Ui packer.Ui

type Config struct {
	common.PackerConfig `mapstructure:",squash"`

	CookbookPaths       []string `mapstructure:"cookbook_paths"`
	ExecuteCommand      string   `mapstructure:"execute_command"`
	InstallCommand      string   `mapstructure:"install_command"`
	RemoteCookbookPaths []string `mapstructure:"remote_cookbook_paths"`
	Json                map[string]interface{}
	PreventSudo         bool     `mapstructure:"prevent_sudo"`
	RunList             []string `mapstructure:"run_list"`
	SkipInstall         bool     `mapstructure:"skip_install"`
	StagingDir          string   `mapstructure:"staging_directory"`

	tpl *packer.ConfigTemplate
}

type Provisioner struct {
	config Config
}

type ConfigTemplate struct {
	CookbookPaths string
}

type ExecuteTemplate struct {
	ConfigPath string
	JsonPath   string
	Sudo       bool
}

type InstallChefTemplate struct {
	Sudo bool
}

func (p *Provisioner) Prepare(raws ...interface{}) error {
	md, err := common.DecodeConfig(&p.config, raws...)
	if err != nil {
		return err
	}

	p.config.tpl, err = packer.NewConfigTemplate()
	if err != nil {
		return err
	}
	p.config.tpl.UserVars = p.config.PackerUserVars

	if p.config.ExecuteCommand == "" {
		p.config.ExecuteCommand = "{{if .Sudo}}sudo {{end}}chef-solo --no-color -c {{.ConfigPath}} -j {{.JsonPath}}"
	}

	if p.config.InstallCommand == "" {
		p.config.InstallCommand = "curl -L https://www.opscode.com/chef/install.sh | {{if .Sudo}}sudo {{end}}bash"
	}

	if p.config.RunList == nil {
		p.config.RunList = make([]string, 0)
	}

	if p.config.StagingDir == "" {
		p.config.StagingDir = "/tmp/packer-chef-solo"
	}

	// Accumulate any errors
	errs := common.CheckUnusedConfig(md)

	for _, path := range p.config.CookbookPaths {
		pFileInfo, err := os.Stat(path)

		if err != nil || !pFileInfo.IsDir() {
			errs = packer.MultiErrorAppend(
				errs, fmt.Errorf("Bad cookbook path '%s': %s", path, err))
		}
	}

	if errs != nil && len(errs.Errors) > 0 {
		return errs
	}

	return nil
}

func (p *Provisioner) Provision(ui packer.Ui, comm packer.Communicator) error {
	if !p.config.SkipInstall {
		if err := p.installChef(ui, comm); err != nil {
			return fmt.Errorf("Error installing Chef: %s", err)
		}
	}

	if err := p.createDir(ui, comm, p.config.StagingDir); err != nil {
		return fmt.Errorf("Error creating staging directory: %s", err)
	}

	cookbookPaths := make([]string, 0, len(p.config.CookbookPaths))
	for i, path := range p.config.CookbookPaths {
		targetPath := fmt.Sprintf("%s/cookbooks-%d", p.config.StagingDir, i)
		if err := p.uploadDirectory(ui, comm, targetPath, path); err != nil {
			return fmt.Errorf("Error uploading cookbooks: %s", err)
		}

		cookbookPaths = append(cookbookPaths, targetPath)
	}

	configPath, err := p.createConfig(ui, comm, cookbookPaths)
	if err != nil {
		return fmt.Errorf("Error creating Chef config file: %s", err)
	}

	jsonPath, err := p.createJson(ui, comm)
	if err != nil {
		return fmt.Errorf("Error creating JSON attributes: %s", err)
	}

	if err := p.executeChef(ui, comm, configPath, jsonPath); err != nil {
		return fmt.Errorf("Error executing Chef: %s", err)
	}

	return nil
}

func (p *Provisioner) uploadDirectory(ui packer.Ui, comm packer.Communicator, dst string, src string) error {
	if err := p.createDir(ui, comm, dst); err != nil {
		return err
	}

	// Make sure there is a trailing "/" so that the directory isn't
	// created on the other side.
	if src[len(src)-1] != '/' {
		src = src + "/"
	}

	return comm.UploadDir(dst, src, nil)
}

func (p *Provisioner) createConfig(ui packer.Ui, comm packer.Communicator, localCookbooks []string) (string, error) {
	ui.Message("Creating configuration file 'solo.rb'")

	cookbook_paths := make([]string, len(p.config.RemoteCookbookPaths)+len(localCookbooks))
	for i, path := range p.config.RemoteCookbookPaths {
		cookbook_paths[i] = fmt.Sprintf(`"%s"`, path)
	}

	for i, path := range localCookbooks {
		i = len(p.config.RemoteCookbookPaths) + i
		cookbook_paths[i] = fmt.Sprintf(`"%s"`, path)
	}

	configString, err := p.config.tpl.Process(DefaultConfigTemplate, &ConfigTemplate{
		CookbookPaths: strings.Join(cookbook_paths, ","),
	})
	if err != nil {
		return "", err
	}

	remotePath := filepath.Join(p.config.StagingDir, "solo.rb")
	if err := comm.Upload(remotePath, bytes.NewReader([]byte(configString))); err != nil {
		return "", err
	}

	return remotePath, nil
}

func (p *Provisioner) createJson(ui packer.Ui, comm packer.Communicator) (string, error) {
	ui.Message("Creating JSON attribute file")

	jsonData := make(map[string]interface{})

	// Copy the configured JSON
	for k, v := range p.config.Json {
		jsonData[k] = v
	}

	// Set the run list if it was specified
	if len(p.config.RunList) > 0 {
		jsonData["run_list"] = p.config.RunList
	}

	jsonBytes, err := json.MarshalIndent(jsonData, "", "  ")
	if err != nil {
		return "", err
	}

	// Upload the bytes
	remotePath := filepath.Join(p.config.StagingDir, "node.json")
	if err := comm.Upload(remotePath, bytes.NewReader(jsonBytes)); err != nil {
		return "", err
	}

	return remotePath, nil
}

func (p *Provisioner) createDir(ui packer.Ui, comm packer.Communicator, dir string) error {
	ui.Message(fmt.Sprintf("Creating directory: %s", dir))
	cmd := &packer.RemoteCmd{
		Command: fmt.Sprintf("mkdir -p '%s'", dir),
	}

	if err := cmd.StartWithUi(comm, ui); err != nil {
		return err
	}

	if cmd.ExitStatus != 0 {
		return fmt.Errorf("Non-zero exit status.")
	}

	return nil
}

func (p *Provisioner) executeChef(ui packer.Ui, comm packer.Communicator, config string, json string) error {
	command, err := p.config.tpl.Process(p.config.InstallCommand, &ExecuteTemplate{
		ConfigPath: config,
		JsonPath:   json,
		Sudo:       !p.config.PreventSudo,
	})
	if err != nil {
		return err
	}

	ui.Message(fmt.Sprintf("Executing Chef: %s", command))

	cmd := &packer.RemoteCmd{
		Command: command,
	}

	if err := cmd.StartWithUi(comm, ui); err != nil {
		return err
	}

	if cmd.ExitStatus != 0 {
		return fmt.Errorf("Non-zero exit status: %d", cmd.ExitStatus)
	}

	return nil
}

func (p *Provisioner) installChef(ui packer.Ui, comm packer.Communicator) error {
	ui.Message("Installing Chef...")

	command, err := p.config.tpl.Process(p.config.InstallCommand, &InstallChefTemplate{
		Sudo: !p.config.PreventSudo,
	})
	if err != nil {
		return err
	}

	cmd := &packer.RemoteCmd{Command: command}
	if err := cmd.StartWithUi(comm, ui); err != nil {
		return err
	}

	if cmd.ExitStatus != 0 {
		return fmt.Errorf(
			"Install script exited with non-zero exit status %d", cmd.ExitStatus)
	}

	return nil
}

var DefaultConfigTemplate = `
cookbook_path [{{.CookbookPaths}}]
`
<commit_msg>provisioner/chef-solo: remove unused constants and variables<commit_after>// This package implements a provisioner for Packer that uses
// Chef to provision the remote machine, specifically with chef-solo (that is,
// without a Chef server).
package chefsolo

import (
	"bytes"
	"encoding/json"
	"fmt"
	"github.com/mitchellh/packer/common"
	"github.com/mitchellh/packer/packer"
	"os"
	"path/filepath"
	"strings"
)

type Config struct {
	common.PackerConfig `mapstructure:",squash"`

	CookbookPaths       []string `mapstructure:"cookbook_paths"`
	ExecuteCommand      string   `mapstructure:"execute_command"`
	InstallCommand      string   `mapstructure:"install_command"`
	RemoteCookbookPaths []string `mapstructure:"remote_cookbook_paths"`
	Json                map[string]interface{}
	PreventSudo         bool     `mapstructure:"prevent_sudo"`
	RunList             []string `mapstructure:"run_list"`
	SkipInstall         bool     `mapstructure:"skip_install"`
	StagingDir          string   `mapstructure:"staging_directory"`

	tpl *packer.ConfigTemplate
}

type Provisioner struct {
	config Config
}

type ConfigTemplate struct {
	CookbookPaths string
}

type ExecuteTemplate struct {
	ConfigPath string
	JsonPath   string
	Sudo       bool
}

type InstallChefTemplate struct {
	Sudo bool
}

func (p *Provisioner) Prepare(raws ...interface{}) error {
	md, err := common.DecodeConfig(&p.config, raws...)
	if err != nil {
		return err
	}

	p.config.tpl, err = packer.NewConfigTemplate()
	if err != nil {
		return err
	}
	p.config.tpl.UserVars = p.config.PackerUserVars

	if p.config.ExecuteCommand == "" {
		p.config.ExecuteCommand = "{{if .Sudo}}sudo {{end}}chef-solo --no-color -c {{.ConfigPath}} -j {{.JsonPath}}"
	}

	if p.config.InstallCommand == "" {
		p.config.InstallCommand = "curl -L https://www.opscode.com/chef/install.sh | {{if .Sudo}}sudo {{end}}bash"
	}

	if p.config.RunList == nil {
		p.config.RunList = make([]string, 0)
	}

	if p.config.StagingDir == "" {
		p.config.StagingDir = "/tmp/packer-chef-solo"
	}

	// Accumulate any errors
	errs := common.CheckUnusedConfig(md)

	for _, path := range p.config.CookbookPaths {
		pFileInfo, err := os.Stat(path)

		if err != nil || !pFileInfo.IsDir() {
			errs = packer.MultiErrorAppend(
				errs, fmt.Errorf("Bad cookbook path '%s': %s", path, err))
		}
	}

	if errs != nil && len(errs.Errors) > 0 {
		return errs
	}

	return nil
}

func (p *Provisioner) Provision(ui packer.Ui, comm packer.Communicator) error {
	if !p.config.SkipInstall {
		if err := p.installChef(ui, comm); err != nil {
			return fmt.Errorf("Error installing Chef: %s", err)
		}
	}

	if err := p.createDir(ui, comm, p.config.StagingDir); err != nil {
		return fmt.Errorf("Error creating staging directory: %s", err)
	}

	cookbookPaths := make([]string, 0, len(p.config.CookbookPaths))
	for i, path := range p.config.CookbookPaths {
		targetPath := fmt.Sprintf("%s/cookbooks-%d", p.config.StagingDir, i)
		if err := p.uploadDirectory(ui, comm, targetPath, path); err != nil {
			return fmt.Errorf("Error uploading cookbooks: %s", err)
		}

		cookbookPaths = append(cookbookPaths, targetPath)
	}

	configPath, err := p.createConfig(ui, comm, cookbookPaths)
	if err != nil {
		return fmt.Errorf("Error creating Chef config file: %s", err)
	}

	jsonPath, err := p.createJson(ui, comm)
	if err != nil {
		return fmt.Errorf("Error creating JSON attributes: %s", err)
	}

	if err := p.executeChef(ui, comm, configPath, jsonPath); err != nil {
		return fmt.Errorf("Error executing Chef: %s", err)
	}

	return nil
}

func (p *Provisioner) uploadDirectory(ui packer.Ui, comm packer.Communicator, dst string, src string) error {
	if err := p.createDir(ui, comm, dst); err != nil {
		return err
	}

	// Make sure there is a trailing "/" so that the directory isn't
	// created on the other side.
	if src[len(src)-1] != '/' {
		src = src + "/"
	}

	return comm.UploadDir(dst, src, nil)
}

func (p *Provisioner) createConfig(ui packer.Ui, comm packer.Communicator, localCookbooks []string) (string, error) {
	ui.Message("Creating configuration file 'solo.rb'")

	cookbook_paths := make([]string, len(p.config.RemoteCookbookPaths)+len(localCookbooks))
	for i, path := range p.config.RemoteCookbookPaths {
		cookbook_paths[i] = fmt.Sprintf(`"%s"`, path)
	}

	for i, path := range localCookbooks {
		i = len(p.config.RemoteCookbookPaths) + i
		cookbook_paths[i] = fmt.Sprintf(`"%s"`, path)
	}

	configString, err := p.config.tpl.Process(DefaultConfigTemplate, &ConfigTemplate{
		CookbookPaths: strings.Join(cookbook_paths, ","),
	})
	if err != nil {
		return "", err
	}

	remotePath := filepath.Join(p.config.StagingDir, "solo.rb")
	if err := comm.Upload(remotePath, bytes.NewReader([]byte(configString))); err != nil {
		return "", err
	}

	return remotePath, nil
}

func (p *Provisioner) createJson(ui packer.Ui, comm packer.Communicator) (string, error) {
	ui.Message("Creating JSON attribute file")

	jsonData := make(map[string]interface{})

	// Copy the configured JSON
	for k, v := range p.config.Json {
		jsonData[k] = v
	}

	// Set the run list if it was specified
	if len(p.config.RunList) > 0 {
		jsonData["run_list"] = p.config.RunList
	}

	jsonBytes, err := json.MarshalIndent(jsonData, "", "  ")
	if err != nil {
		return "", err
	}

	// Upload the bytes
	remotePath := filepath.Join(p.config.StagingDir, "node.json")
	if err := comm.Upload(remotePath, bytes.NewReader(jsonBytes)); err != nil {
		return "", err
	}

	return remotePath, nil
}

func (p *Provisioner) createDir(ui packer.Ui, comm packer.Communicator, dir string) error {
	ui.Message(fmt.Sprintf("Creating directory: %s", dir))
	cmd := &packer.RemoteCmd{
		Command: fmt.Sprintf("mkdir -p '%s'", dir),
	}

	if err := cmd.StartWithUi(comm, ui); err != nil {
		return err
	}

	if cmd.ExitStatus != 0 {
		return fmt.Errorf("Non-zero exit status.")
	}

	return nil
}

func (p *Provisioner) executeChef(ui packer.Ui, comm packer.Communicator, config string, json string) error {
	command, err := p.config.tpl.Process(p.config.InstallCommand, &ExecuteTemplate{
		ConfigPath: config,
		JsonPath:   json,
		Sudo:       !p.config.PreventSudo,
	})
	if err != nil {
		return err
	}

	ui.Message(fmt.Sprintf("Executing Chef: %s", command))

	cmd := &packer.RemoteCmd{
		Command: command,
	}

	if err := cmd.StartWithUi(comm, ui); err != nil {
		return err
	}

	if cmd.ExitStatus != 0 {
		return fmt.Errorf("Non-zero exit status: %d", cmd.ExitStatus)
	}

	return nil
}

func (p *Provisioner) installChef(ui packer.Ui, comm packer.Communicator) error {
	ui.Message("Installing Chef...")

	command, err := p.config.tpl.Process(p.config.InstallCommand, &InstallChefTemplate{
		Sudo: !p.config.PreventSudo,
	})
	if err != nil {
		return err
	}

	cmd := &packer.RemoteCmd{Command: command}
	if err := cmd.StartWithUi(comm, ui); err != nil {
		return err
	}

	if cmd.ExitStatus != 0 {
		return fmt.Errorf(
			"Install script exited with non-zero exit status %d", cmd.ExitStatus)
	}

	return nil
}

var DefaultConfigTemplate = `
cookbook_path [{{.CookbookPaths}}]
`
<|endoftext|>


<commit_before>package proxy

import (
	"net/http"
	"regexp"
	"strings"

	"github.com/fsouza/go-dockerclient"
	. "github.com/weaveworks/weave/common"
)

var containerIDRegexp = regexp.MustCompile("^/v[0-9\\.]*/containers/([^/]*)/.*")

type startContainerInterceptor struct {
	client  *docker.Client
	withDNS bool
}

func (i *startContainerInterceptor) InterceptRequest(r *http.Request) error {
	return nil
}

func (i *startContainerInterceptor) InterceptResponse(r *http.Response) error {
	containerID := ""
	if subs := containerIDRegexp.FindStringSubmatch(r.Request.URL.Path); subs == nil {
		Warning.Printf("No container id found in request with path %s", r.Request.URL.Path)
		return nil
	} else {
		containerID = subs[1]
	}

	container, err := i.client.InspectContainer(containerID)
	if err != nil {
		Warning.Printf("Error inspecting container %s: %v", containerID, err)
		return nil
	}

	cidrs, ok := weaveCIDRsFromConfig(container.Config)
	if !ok {
		Debug.Print("No Weave CIDR, ignoring")
		return nil
	}
	Info.Printf("Container %s was started with CIDR \"%s\"", containerID, strings.Join(cidrs, " "))
	args := []string{"attach"}
	args = append(args, cidrs...)
	args = append(args, containerID)
	if _, err := callWeave(args...); err != nil {
		Warning.Printf("Attaching container %s to weave failed: %v", containerID, err)
		return nil
	}
	return nil
}
<commit_msg>golint cleanup of else block<commit_after>package proxy

import (
	"net/http"
	"regexp"
	"strings"

	"github.com/fsouza/go-dockerclient"
	. "github.com/weaveworks/weave/common"
)

var containerIDRegexp = regexp.MustCompile("^/v[0-9\\.]*/containers/([^/]*)/.*")

type startContainerInterceptor struct {
	client  *docker.Client
	withDNS bool
}

func (i *startContainerInterceptor) InterceptRequest(r *http.Request) error {
	return nil
}

func (i *startContainerInterceptor) InterceptResponse(r *http.Response) error {
	if subs := containerIDRegexp.FindStringSubmatch(r.Request.URL.Path); subs == nil {
		Warning.Printf("No container id found in request with path %s", r.Request.URL.Path)
		return nil
	}
	containerID := subs[1]

	container, err := i.client.InspectContainer(containerID)
	if err != nil {
		Warning.Printf("Error inspecting container %s: %v", containerID, err)
		return nil
	}

	cidrs, ok := weaveCIDRsFromConfig(container.Config)
	if !ok {
		Debug.Print("No Weave CIDR, ignoring")
		return nil
	}
	Info.Printf("Container %s was started with CIDR \"%s\"", containerID, strings.Join(cidrs, " "))
	args := []string{"attach"}
	args = append(args, cidrs...)
	args = append(args, containerID)
	if _, err := callWeave(args...); err != nil {
		Warning.Printf("Attaching container %s to weave failed: %v", containerID, err)
		return nil
	}
	return nil
}
<|endoftext|>


<commit_before>// Package jsonapi provides structures and methods to implement JSON API
// compatible APIs. Most methods are tailored to be used together with the
// echo framework, yet all of them also have a native counterpart in the compat
// sub package that allows implementing APIs using the standard HTTP library.
package jsonapi

import (
	"io"

	"github.com/fatih/structs"
)

// MediaType is the official JSON API media type that should be used by
// all requests and responses.
const MediaType = "application/vnd.api+json"

// The Requester interface must be implemented by adapters to make framework
// specific request objects compatible with jsonapi.
type Requester interface {
	Method() string
	Get(key string) string
	Path() string
	QueryParams() map[string][]string
}

// The Responder interface must be implemented by adapters to make framework
// specific response objects compatible with jsonapi.
type Responder interface {
	io.Writer

	Set(key, value string)
	WriteHeader(status int)
}

// Map is a general purpose map of string keys and arbitrary values.
type Map map[string]interface{}

// StructToMap will assign the fields of the source struct to a new map and
// additionally filter the map on only include the fields specified if there
// are any.
//
// Note: The "json" tag will be respected to write proper field names.
func StructToMap(source interface{}, fields []string) Map {
	// prepare structs helper
	s := structs.New(source)
	s.TagName = "json"

	// create map
	m := Map(s.Map())

	// return map directly of no fields are specified
	if len(fields) == 0 {
		return m
	}

	// filter map
	for key := range m {
		ok := false

		// check if field is present
		for _, field := range fields {
			if field == key {
				ok = true
			}
		}

		// otherwise remove field
		if !ok {
			delete(m, key)
		}
	}

	return m
}
<commit_msg>updated<commit_after>// Package jsonapi provides structures and methods to implement JSON API
// compatible APIs. Most methods are tailored to be used together with the
// echo framework, yet all of them also have a native counterpart in the compat
// sub package that allows implementing APIs using the standard HTTP library.
package jsonapi

import (
	"io"

	"github.com/fatih/structs"
)

// MediaType is the official JSON API media type that should be used by
// all requests and responses.
const MediaType = "application/vnd.api+json"

// The Requester interface must be implemented by adapters to make framework
// specific request objects compatible with jsonapi.
type Requester interface {
	Method() string
	Get(key string) string
	Path() string
	QueryParams() map[string][]string
}

// The Responder interface must be implemented by adapters to make framework
// specific response objects compatible with jsonapi.
type Responder interface {
	io.Writer

	Set(key, value string)
	WriteHeader(status int)
}

// Map is a general purpose map of string keys and arbitrary values.
type Map map[string]interface{}

// StructToMap will assign the fields of the source struct to a new map and
// additionally filter the map to only include the fields specified.
//
// Note: The "json" tag will be respected to write proper field names.
//
// Note: If no fields to filter are specified, not filtering will be applied.
func StructToMap(source interface{}, fields []string) Map {
	// prepare structs helper
	s := structs.New(source)
	s.TagName = "json"

	// create map
	m := Map(s.Map())

	// return map directly of no fields are specified
	if len(fields) == 0 {
		return m
	}

	// filter map
	for key := range m {
		ok := false

		// check if field is present
		for _, field := range fields {
			if field == key {
				ok = true
			}
		}

		// otherwise remove field
		if !ok {
			delete(m, key)
		}
	}

	return m
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"flag"
	"fmt"
	"github.com/howeyc/fsnotify"
	"log"
	"os"
	"os/signal"
	"path/filepath"
	"strings"
	"sync"
	"syscall"
	"time"
)

var (
	help           = flag.Bool("help", false, "print this help text")
	h              = flag.Bool("h", false, "print this help text")
	command        = flag.String("c", "", "command to run when files change in given directories")
	ignore         = flag.String("i", "", "comma-separated list of files to ignore")
	stdin          = flag.Bool("stdin", false, "read list of files to track from stdin, not the command-line")
	waitForCommand = flag.Bool("w", false, "wait for the command to finish and do not attempt to kill it")
	delayDur       = flag.Duration("delay", 750*time.Millisecond, "the time to wait between runs of the command if many fs events occur")
	verbose        = flag.Bool("v", false, "verbose output")
)

func usage() {
	fmt.Fprintf(os.Stderr, "usage: justrun -c 'SOME BASH COMMAND' [FILEPATH]*\n")
	flag.PrintDefaults()
	os.Exit(1)
}

func argError(format string, obj ...interface{}) {
	fmt.Fprintf(os.Stderr, "justrun: "+format+"\n", obj...)
	usage()
}

func main() {
	flag.Usage = usage
	flag.Parse()
	if *help || *h {
		argError("help requested")
	}
	if len(*command) == 0 {
		argError("no command given with -c")
	}
	if *stdin && len(flag.Args()) != 0 {
		argError("expected files to come in over stdin, but got paths '%s' in the commandline", strings.Join(flag.Args(), ", "))
	}
	var inputPaths []string
	if *stdin {
		sc := bufio.NewScanner(os.Stdin)
		for sc.Scan() {
			inputPaths = append(inputPaths, sc.Text())
		}
		if sc.Err() != nil {
			argError("error reading from stdin: %s", sc.Err())
		}
	} else {
		inputPaths = flag.Args()
	}

	if len(inputPaths) == 0 {
		argError("no file paths provided to watch")
	}
	ignoreNames := strings.Split(*ignore, ",")
	ignored := make(map[string]bool)
	ignoredDirs := make([]string, 0)
	for _, in := range ignoreNames {
		in = strings.TrimSpace(in)
		if len(in) == 0 {
			continue
		}
		path, err := filepath.Abs(in)
		if err != nil {
			log.Fatalf("unable to get current working dir")
		}
		ignored[path] = true
		dirPath := path
		if path[len(path)-1] != '/' {
			dirPath += "/"
		}
		ignoredDirs = append(ignoredDirs, dirPath)
	}
	ig := &ignorer{ignored, ignoredDirs}
	cmd := &cmdWrapper{Mutex: new(sync.Mutex), command: *command, cmd: nil}

	sigCh := make(chan os.Signal)
	signal.Notify(sigCh, os.Interrupt, syscall.SIGTERM)
	go waitForInterrupt(sigCh, cmd)

	cmdCh := make(chan time.Time, 100)
	w, err := fsnotify.NewWatcher()
	if err != nil {
		log.Fatal(err)
	}
	go listenForEvents(w, cmdCh, ig)

	for _, path := range inputPaths {
		if ig.IsIgnored(path) {
			continue
		}
		err = w.Watch(path)
		if err != nil {
			log.Fatalf("unable to watch '%s': %s", path, err)
		}
	}
	lastStartTime := time.Unix(0, 0)
	done := make(chan error)
	wasDelayed := false
	reload(cmd, done, &lastStartTime)
	tick := time.NewTicker(*delayDur)
	for {
		select {
		case t := <-cmdCh:
			if lastStartTime.After(t) {
				continue
			}
			// Using delayDur here and in NewTicker is slightly semantically
			// incorrect, but it simplifies our config and prevents the
			// egregious reloading.
			if time.Now().Sub(t) < *delayDur {
				wasDelayed = true
				continue
			}
			wasDelayed = false
			reload(cmd, done, &lastStartTime)
			tick = time.NewTicker(*delayDur)
		case <-tick.C:
			if wasDelayed {
				wasDelayed = false
				reload(cmd, done, &lastStartTime)
			}
		}
	}
}

func reload(cmd *cmdWrapper, done chan error, lastStartTime *time.Time) {
	shutdownCommand(cmd, done)
	*lastStartTime = time.Now()
	runCommand(cmd, done)
}

func runCommand(cmd *cmdWrapper, done chan error) {
	log.Printf("running '%s'\n",  *command)
	err := cmd.Start()
	if err != nil {
		log.Printf("command failed: %s", err)
		return
	}
	if *waitForCommand {
		err := cmd.Wait()
		go func() { done <- err }()
		return
	}
	go func() {
		err := cmd.Wait()
		done <- err
	}()
}

func shutdownCommand(cmd *cmdWrapper, done chan error) {
	err := cmd.Terminate()
	if err != nil {
		return
	}

waitOrRetry:
	select {
	case <-done:
		break
	case <-time.After(300 * time.Millisecond):
		err := cmd.Terminate()
		if err == nil {
			// If terminate claims to succeed, we want to make sure the done
			// message came across. If the done message doesn't come, the
			// process didn't die anad we need to try terminating again.
			goto waitOrRetry
		}
		break
	}
	msg := "terminating current command"
	if *verbose {
		msg += fmt.Sprintf(" %d", cmd.cmd.Process.Pid)
	}
	log.Println(msg)
}

func waitForInterrupt(sigCh chan os.Signal, cmd *cmdWrapper) {
	defer os.Exit(0)
	<-sigCh
	err := cmd.Terminate()
	if err != nil {
		log.Printf("on interrupt, unable to kill command: %s", err)
	}
}

type ignorer struct {
	ignored     map[string]bool
	ignoredDirs []string
}

func (ig *ignorer) IsIgnored(path string) bool {
	en, err := filepath.Abs(path)
	if err != nil {
		log.Fatalf("unable to get current working dir")
	}
	if ig.ignored[en] {
		return true
	}
	for _, dir := range ig.ignoredDirs {
		if strings.HasPrefix(en, dir) {
			return true
		}
	}
	return false
}

func listenForEvents(w *fsnotify.Watcher, cmdCh chan time.Time, ignorer *ignorer) {
	for {
		select {
		case ev := <-w.Event:
			if ignorer.IsIgnored(ev.Name) {
				continue
			}
			if *verbose {
				log.Printf("file changed: %s", ev)
			}
			cmdCh <- time.Now()
		case err := <-w.Error:
			log.Println("error:", err)
		}
	}
}
<commit_msg>correct rename watching<commit_after>package main

import (
	"bufio"
	"flag"
	"fmt"
	"log"
	"os"
	"os/signal"
	"path/filepath"
	"strings"
	"sync"
	"syscall"
	"time"

	"github.com/howeyc/fsnotify"
)

var (
	help           = flag.Bool("help", false, "print this help text")
	h              = flag.Bool("h", false, "print this help text")
	command        = flag.String("c", "", "command to run when files change in given directories")
	ignore         = flag.String("i", "", "comma-separated list of files to ignore")
	stdin          = flag.Bool("stdin", false, "read list of files to track from stdin, not the command-line")
	waitForCommand = flag.Bool("w", false, "wait for the command to finish and do not attempt to kill it")
	delayDur       = flag.Duration("delay", 750*time.Millisecond, "the time to wait between runs of the command if many fs events occur")
	verbose        = flag.Bool("v", false, "verbose output")
)

func usage() {
	fmt.Fprintf(os.Stderr, "usage: justrun -c 'SOME BASH COMMAND' [FILEPATH]*\n")
	flag.PrintDefaults()
	os.Exit(1)
}

func argError(format string, obj ...interface{}) {
	fmt.Fprintf(os.Stderr, "justrun: "+format+"\n", obj...)
	usage()
}

func main() {
	flag.Usage = usage
	flag.Parse()
	if *help || *h {
		argError("help requested")
	}
	if len(*command) == 0 {
		argError("no command given with -c")
	}
	if *stdin && len(flag.Args()) != 0 {
		argError("expected files to come in over stdin, but got paths '%s' in the commandline", strings.Join(flag.Args(), ", "))
	}
	var inputPaths []string
	if *stdin {
		sc := bufio.NewScanner(os.Stdin)
		for sc.Scan() {
			inputPaths = append(inputPaths, sc.Text())
		}
		if sc.Err() != nil {
			argError("error reading from stdin: %s", sc.Err())
		}
	} else {
		inputPaths = flag.Args()
	}

	if len(inputPaths) == 0 {
		argError("no file paths provided to watch")
	}
	ignoreNames := strings.Split(*ignore, ",")
	ignored := make(map[string]bool)
	ignoredDirs := make([]string, 0)
	for _, in := range ignoreNames {
		in = strings.TrimSpace(in)
		if len(in) == 0 {
			continue
		}
		path, err := filepath.Abs(in)
		if err != nil {
			log.Fatalf("unable to get current working dir")
		}
		ignored[path] = true
		dirPath := path
		if path[len(path)-1] != '/' {
			dirPath += "/"
		}
		ignoredDirs = append(ignoredDirs, dirPath)
	}
	ig := &ignorer{ignored, ignoredDirs}
	cmd := &cmdWrapper{Mutex: new(sync.Mutex), command: *command, cmd: nil}

	sigCh := make(chan os.Signal)
	signal.Notify(sigCh, os.Interrupt, syscall.SIGTERM)
	go waitForInterrupt(sigCh, cmd)

	cmdCh := make(chan time.Time, 100)
	w, err := fsnotify.NewWatcher()
	if err != nil {
		log.Fatal(err)
	}
	go listenForEvents(w, cmdCh, ig)

	for _, path := range inputPaths {
		if ig.IsIgnored(path) {
			continue
		}
		err = w.Watch(path)
		if err != nil {
			log.Fatalf("unable to watch '%s': %s", path, err)
		}
	}

	lastStartTime := time.Unix(0, 0)
	done := make(chan error)
	wasDelayed := false
	reload(cmd, done, &lastStartTime)
	tick := time.NewTicker(*delayDur)
	for {
		select {
		case t := <-cmdCh:
			if lastStartTime.After(t) {
				continue
			}
			// Using delayDur here and in NewTicker is slightly semantically
			// incorrect, but it simplifies our config and prevents the
			// egregious reloading.
			if time.Now().Sub(t) < *delayDur {
				wasDelayed = true
				continue
			}
			wasDelayed = false
			reload(cmd, done, &lastStartTime)
			tick = time.NewTicker(*delayDur)
		case <-tick.C:
			if wasDelayed {
				wasDelayed = false
				reload(cmd, done, &lastStartTime)
			}
		}
	}
}

func reload(cmd *cmdWrapper, done chan error, lastStartTime *time.Time) {
	shutdownCommand(cmd, done)
	*lastStartTime = time.Now()
	runCommand(cmd, done)
}

func runCommand(cmd *cmdWrapper, done chan error) {
	log.Printf("running '%s'\n", *command)
	err := cmd.Start()
	if err != nil {
		log.Printf("command failed: %s", err)
		return
	}
	if *waitForCommand {
		err := cmd.Wait()
		go func() { done <- err }()
		return
	}
	go func() {
		err := cmd.Wait()
		done <- err
	}()
}

func shutdownCommand(cmd *cmdWrapper, done chan error) {
	err := cmd.Terminate()
	if err != nil {
		return
	}

waitOrRetry:
	select {
	case <-done:
		break
	case <-time.After(300 * time.Millisecond):
		err := cmd.Terminate()
		if err == nil {
			// If terminate claims to succeed, we want to make sure the done
			// message came across. If the done message doesn't come, the
			// process didn't die anad we need to try terminating again.
			goto waitOrRetry
		}
		break
	}
	msg := "terminating current command"
	if *verbose {
		msg += fmt.Sprintf(" %d", cmd.cmd.Process.Pid)
	}
	log.Println(msg)
}

func waitForInterrupt(sigCh chan os.Signal, cmd *cmdWrapper) {
	defer os.Exit(0)
	<-sigCh
	err := cmd.Terminate()
	if err != nil {
		log.Printf("on interrupt, unable to kill command: %s", err)
	}
}

type ignorer struct {
	ignored     map[string]bool
	ignoredDirs []string
}

func (ig *ignorer) IsIgnored(path string) bool {
	en, err := filepath.Abs(path)
	if err != nil {
		log.Fatalf("unable to get current working dir")
	}
	if ig.ignored[en] {
		return true
	}
	for _, dir := range ig.ignoredDirs {
		if strings.HasPrefix(en, dir) {
			return true
		}
	}
	return false
}

func listenForEvents(w *fsnotify.Watcher, cmdCh chan time.Time, ignorer *ignorer) {
	for {
		select {
		case ev := <-w.Event:
			if ignorer.IsIgnored(ev.Name) {
				continue
			}
			if *verbose {
				log.Printf("file changed: %s", ev)
			}
			if ev.IsRename() {
				w.Watch(ev.Name)
			}
			cmdCh <- time.Now()
		case err := <-w.Error:
			log.Println("error:", err)
		}
	}
}
<|endoftext|>


<commit_before>package k8s

import (
  _ "fmt"
  "errors"
  "encoding/base64"
)

func GetSecret (namespace, key, data string) (string, error){
  s := &Secret{}

  s, err := getSecret(namespace, key)
  if err != nil {
    return "", errors.New("missing key" + key)
  }
  v := s.Data[data]
  d, err := base64.StdEncoding.DecodeString(v)
  if err != nil {
    return "", err
  }
  return string(d), nil
}
<commit_msg>remove struct<commit_after>package k8s

import (
  _ "fmt"
  "errors"
  "encoding/base64"
)

func GetSecret (namespace, key, data string) (string, error){
  s, err := getSecret(namespace, key)
  if err != nil {
    return "", errors.New("missing key" + key)
  }
  v := s.Data[data]
  d, err := base64.StdEncoding.DecodeString(v)
  if err != nil {
    return "", err
  }
  return string(d), nil
}
<|endoftext|>