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

// Handler for Docker containers.
package docker

import (
	"fmt"
	"math"
	"path"
	"strings"
	"time"

	"github.com/google/cadvisor/container"
	containerlibcontainer "github.com/google/cadvisor/container/libcontainer"
	"github.com/google/cadvisor/fs"
	info "github.com/google/cadvisor/info/v1"
	"github.com/google/cadvisor/utils"

	docker "github.com/fsouza/go-dockerclient"
	"github.com/opencontainers/runc/libcontainer/cgroups"
	cgroupfs "github.com/opencontainers/runc/libcontainer/cgroups/fs"
	libcontainerconfigs "github.com/opencontainers/runc/libcontainer/configs"
)

const (
	// Path to aufs dir where all the files exist.
	// aufs/layers is ignored here since it does not hold a lot of data.
	// aufs/mnt contains the mount points used to compose the rootfs. Hence it is also ignored.
	pathToAufsDir = "aufs/diff"
	// Path to the directory where docker stores log files if the json logging driver is enabled.
	pathToContainersDir = "containers"
	// Path to the overlayfs storage driver directory.
	pathToOverlayDir = "overlay"
)

type dockerContainerHandler struct {
	client             *docker.Client
	name               string
	id                 string
	aliases            []string
	machineInfoFactory info.MachineInfoFactory

	// Absolute path to the cgroup hierarchies of this container.
	// (e.g.: "cpu" -> "/sys/fs/cgroup/cpu/test")
	cgroupPaths map[string]string

	// Manager of this container's cgroups.
	cgroupManager cgroups.Manager

	storageDriver storageDriver
	fsInfo        fs.FsInfo
	storageDirs   []string

	// Time at which this container was created.
	creationTime time.Time

	// Metadata labels associated with the container.
	labels map[string]string

	// The container PID used to switch namespaces as required
	pid int

	// Image name used for this container.
	image string

	// The host root FS to read
	rootFs string

	// The network mode of the container
	networkMode string

	// Filesystem handler.
	fsHandler fsHandler
}

func newDockerContainerHandler(
	client *docker.Client,
	name string,
	machineInfoFactory info.MachineInfoFactory,
	fsInfo fs.FsInfo,
	storageDriver storageDriver,
	cgroupSubsystems *containerlibcontainer.CgroupSubsystems,
	inHostNamespace bool,
) (container.ContainerHandler, error) {
	// Create the cgroup paths.
	cgroupPaths := make(map[string]string, len(cgroupSubsystems.MountPoints))
	for key, val := range cgroupSubsystems.MountPoints {
		cgroupPaths[key] = path.Join(val, name)
	}

	// Generate the equivalent cgroup manager for this container.
	cgroupManager := &cgroupfs.Manager{
		Cgroups: &libcontainerconfigs.Cgroup{
			Name: name,
		},
		Paths: cgroupPaths,
	}

	rootFs := "/"
	if !inHostNamespace {
		rootFs = "/rootfs"
	}

	id := ContainerNameToDockerId(name)

	// Add the Containers dir where the log files are stored.
	storageDirs := []string{path.Join(*dockerRootDir, pathToContainersDir, id)}

	switch storageDriver {
	case aufsStorageDriver:
		// Add writable layer for aufs.
		storageDirs = append(storageDirs, path.Join(*dockerRootDir, pathToAufsDir, id))
	case overlayStorageDriver:
		storageDirs = append(storageDirs, path.Join(*dockerRootDir, pathToOverlayDir, id))
	}

	handler := &dockerContainerHandler{
		id:                 id,
		client:             client,
		name:               name,
		machineInfoFactory: machineInfoFactory,
		cgroupPaths:        cgroupPaths,
		cgroupManager:      cgroupManager,
		storageDriver:      storageDriver,
		fsInfo:             fsInfo,
		rootFs:             rootFs,
		storageDirs:        storageDirs,
		fsHandler:          newFsHandler(time.Minute, storageDirs, fsInfo),
	}

	// Start the filesystem handler.
	handler.fsHandler.start()

	// We assume that if Inspect fails then the container is not known to docker.
	ctnr, err := client.InspectContainer(id)
	if err != nil {
		return nil, fmt.Errorf("failed to inspect container %q: %v", id, err)
	}
	handler.creationTime = ctnr.Created
	handler.pid = ctnr.State.Pid

	// Add the name and bare ID as aliases of the container.
	handler.aliases = append(handler.aliases, strings.TrimPrefix(ctnr.Name, "/"), id)
	handler.labels = ctnr.Config.Labels
	handler.image = ctnr.Config.Image
	handler.networkMode = ctnr.HostConfig.NetworkMode

	return handler, nil
}

func (self *dockerContainerHandler) ContainerReference() (info.ContainerReference, error) {
	return info.ContainerReference{
		Name:      self.name,
		Aliases:   self.aliases,
		Namespace: DockerNamespace,
	}, nil
}

func (self *dockerContainerHandler) readLibcontainerConfig() (*libcontainerconfigs.Config, error) {
	config, err := containerlibcontainer.ReadConfig(*dockerRootDir, *dockerRunDir, self.id)
	if err != nil {
		return nil, fmt.Errorf("failed to read libcontainer config: %v", err)
	}

	// Replace cgroup parent and name with our own since we may be running in a different context.
	if config.Cgroups == nil {
		config.Cgroups = new(libcontainerconfigs.Cgroup)
	}
	config.Cgroups.Name = self.name
	config.Cgroups.Parent = "/"

	return config, nil
}

func libcontainerConfigToContainerSpec(config *libcontainerconfigs.Config, mi *info.MachineInfo) info.ContainerSpec {
	var spec info.ContainerSpec
	spec.HasMemory = true
	spec.Memory.Limit = math.MaxUint64
	spec.Memory.SwapLimit = math.MaxUint64
	if config.Cgroups.Memory > 0 {
		spec.Memory.Limit = uint64(config.Cgroups.Memory)
	}
	if config.Cgroups.MemorySwap > 0 {
		spec.Memory.SwapLimit = uint64(config.Cgroups.MemorySwap)
	}

	// Get CPU info
	spec.HasCpu = true
	spec.Cpu.Limit = 1024
	if config.Cgroups.CpuShares != 0 {
		spec.Cpu.Limit = uint64(config.Cgroups.CpuShares)
	}
	spec.Cpu.Mask = utils.FixCpuMask(config.Cgroups.CpusetCpus, mi.NumCores)

	spec.HasDiskIo = true

	return spec
}

var (
	hasNetworkModes = map[string]bool{
		"host":    true,
		"bridge":  true,
		"default": true,
	}
)

func hasNet(networkMode string) bool {
	return hasNetworkModes[networkMode]
}

func (self *dockerContainerHandler) GetSpec() (info.ContainerSpec, error) {
	mi, err := self.machineInfoFactory.GetMachineInfo()
	if err != nil {
		return info.ContainerSpec{}, err
	}
	libcontainerConfig, err := self.readLibcontainerConfig()
	if err != nil {
		return info.ContainerSpec{}, err
	}

	spec := libcontainerConfigToContainerSpec(libcontainerConfig, mi)
	spec.CreationTime = self.creationTime

	spec.HasFilesystem = false
	switch self.storageDriver {
	case aufsStorageDriver:
	case overlayStorageDriver:
		spec.HasFilesystem = true
	}

	spec.Labels = self.labels
	spec.Image = self.image
	spec.HasNetwork = hasNet(self.networkMode)

	return spec, err
}

func (self *dockerContainerHandler) getFsStats(stats *info.ContainerStats) error {
	switch self.storageDriver {
	case aufsStorageDriver:
	case overlayStorageDriver:
		break
	default:
		return nil
	}

	// As of now we assume that all the storage dirs are on the same device.
	// The first storage dir will be that of the image layers.
	deviceInfo, err := self.fsInfo.GetDirFsDevice(self.storageDirs[0])
	if err != nil {
		return err
	}

	mi, err := self.machineInfoFactory.GetMachineInfo()
	if err != nil {
		return err
	}
	var limit uint64 = 0
	// Docker does not impose any filesystem limits for containers. So use capacity as limit.
	for _, fs := range mi.Filesystems {
		if fs.Device == deviceInfo.Device {
			limit = fs.Capacity
			break
		}
	}

	fsStat := info.FsStats{Device: deviceInfo.Device, Limit: limit}

	fsStat.Usage = self.fsHandler.usage()
	stats.Filesystem = append(stats.Filesystem, fsStat)

	return nil
}

// TODO(vmarmol): Get from libcontainer API instead of cgroup manager when we don't have to support older Dockers.
func (self *dockerContainerHandler) GetStats() (*info.ContainerStats, error) {
	stats, err := containerlibcontainer.GetStats(self.cgroupManager, self.rootFs, self.pid)
	if err != nil {
		return stats, err
	}
	// Clean up stats for containers that don't have their own network - this
	// includes containers running in Kubernetes pods that use the network of the
	// infrastructure container. This stops metrics being reported multiple times
	// for each container in a pod.
	if !hasNet(self.networkMode) {
		stats.Network = info.NetworkStats{}
	}

	// Get filesystem stats.
	err = self.getFsStats(stats)
	if err != nil {
		return stats, err
	}

	return stats, nil
}

func (self *dockerContainerHandler) ListContainers(listType container.ListType) ([]info.ContainerReference, error) {
	// No-op for Docker driver.
	return []info.ContainerReference{}, nil
}

func (self *dockerContainerHandler) GetCgroupPath(resource string) (string, error) {
	path, ok := self.cgroupPaths[resource]
	if !ok {
		return "", fmt.Errorf("could not find path for resource %q for container %q\n", resource, self.name)
	}
	return path, nil
}

func (self *dockerContainerHandler) ListThreads(listType container.ListType) ([]int, error) {
	// TODO(vmarmol): Implement.
	return nil, nil
}

func (self *dockerContainerHandler) GetContainerLabels() map[string]string {
	return self.labels
}

func (self *dockerContainerHandler) ListProcesses(listType container.ListType) ([]int, error) {
	return containerlibcontainer.GetProcesses(self.cgroupManager)
}

func (self *dockerContainerHandler) WatchSubcontainers(events chan container.SubcontainerEvent) error {
	return fmt.Errorf("watch is unimplemented in the Docker container driver")
}

func (self *dockerContainerHandler) StopWatchingSubcontainers() error {
	// No-op for Docker driver.
	return nil
}

func (self *dockerContainerHandler) Exists() bool {
	return containerlibcontainer.Exists(*dockerRootDir, *dockerRunDir, self.id)
}

func DockerInfo() (map[string]string, error) {
	client, err := Client()
	if err != nil {
		return nil, fmt.Errorf("unable to communicate with docker daemon: %v", err)
	}
	info, err := client.Info()
	if err != nil {
		return nil, err
	}
	return info.Map(), nil
}

func DockerImages() ([]docker.APIImages, error) {
	client, err := Client()
	if err != nil {
		return nil, fmt.Errorf("unable to communicate with docker daemon: %v", err)
	}
	images, err := client.ListImages(docker.ListImagesOptions{All: false})
	if err != nil {
		return nil, err
	}
	return images, nil
}
<commit_msg>Fix case statements dealing with storageDriver<commit_after>// Copyright 2014 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Handler for Docker containers.
package docker

import (
	"fmt"
	"math"
	"path"
	"strings"
	"time"

	"github.com/google/cadvisor/container"
	containerlibcontainer "github.com/google/cadvisor/container/libcontainer"
	"github.com/google/cadvisor/fs"
	info "github.com/google/cadvisor/info/v1"
	"github.com/google/cadvisor/utils"

	docker "github.com/fsouza/go-dockerclient"
	"github.com/opencontainers/runc/libcontainer/cgroups"
	cgroupfs "github.com/opencontainers/runc/libcontainer/cgroups/fs"
	libcontainerconfigs "github.com/opencontainers/runc/libcontainer/configs"
)

const (
	// Path to aufs dir where all the files exist.
	// aufs/layers is ignored here since it does not hold a lot of data.
	// aufs/mnt contains the mount points used to compose the rootfs. Hence it is also ignored.
	pathToAufsDir = "aufs/diff"
	// Path to the directory where docker stores log files if the json logging driver is enabled.
	pathToContainersDir = "containers"
	// Path to the overlayfs storage driver directory.
	pathToOverlayDir = "overlay"
)

type dockerContainerHandler struct {
	client             *docker.Client
	name               string
	id                 string
	aliases            []string
	machineInfoFactory info.MachineInfoFactory

	// Absolute path to the cgroup hierarchies of this container.
	// (e.g.: "cpu" -> "/sys/fs/cgroup/cpu/test")
	cgroupPaths map[string]string

	// Manager of this container's cgroups.
	cgroupManager cgroups.Manager

	storageDriver storageDriver
	fsInfo        fs.FsInfo
	storageDirs   []string

	// Time at which this container was created.
	creationTime time.Time

	// Metadata labels associated with the container.
	labels map[string]string

	// The container PID used to switch namespaces as required
	pid int

	// Image name used for this container.
	image string

	// The host root FS to read
	rootFs string

	// The network mode of the container
	networkMode string

	// Filesystem handler.
	fsHandler fsHandler
}

func newDockerContainerHandler(
	client *docker.Client,
	name string,
	machineInfoFactory info.MachineInfoFactory,
	fsInfo fs.FsInfo,
	storageDriver storageDriver,
	cgroupSubsystems *containerlibcontainer.CgroupSubsystems,
	inHostNamespace bool,
) (container.ContainerHandler, error) {
	// Create the cgroup paths.
	cgroupPaths := make(map[string]string, len(cgroupSubsystems.MountPoints))
	for key, val := range cgroupSubsystems.MountPoints {
		cgroupPaths[key] = path.Join(val, name)
	}

	// Generate the equivalent cgroup manager for this container.
	cgroupManager := &cgroupfs.Manager{
		Cgroups: &libcontainerconfigs.Cgroup{
			Name: name,
		},
		Paths: cgroupPaths,
	}

	rootFs := "/"
	if !inHostNamespace {
		rootFs = "/rootfs"
	}

	id := ContainerNameToDockerId(name)

	// Add the Containers dir where the log files are stored.
	storageDirs := []string{path.Join(*dockerRootDir, pathToContainersDir, id)}

	switch storageDriver {
	case aufsStorageDriver:
		// Add writable layer for aufs.
		storageDirs = append(storageDirs, path.Join(*dockerRootDir, pathToAufsDir, id))
	case overlayStorageDriver:
		storageDirs = append(storageDirs, path.Join(*dockerRootDir, pathToOverlayDir, id))
	}

	handler := &dockerContainerHandler{
		id:                 id,
		client:             client,
		name:               name,
		machineInfoFactory: machineInfoFactory,
		cgroupPaths:        cgroupPaths,
		cgroupManager:      cgroupManager,
		storageDriver:      storageDriver,
		fsInfo:             fsInfo,
		rootFs:             rootFs,
		storageDirs:        storageDirs,
		fsHandler:          newFsHandler(time.Minute, storageDirs, fsInfo),
	}

	// Start the filesystem handler.
	handler.fsHandler.start()

	// We assume that if Inspect fails then the container is not known to docker.
	ctnr, err := client.InspectContainer(id)
	if err != nil {
		return nil, fmt.Errorf("failed to inspect container %q: %v", id, err)
	}
	handler.creationTime = ctnr.Created
	handler.pid = ctnr.State.Pid

	// Add the name and bare ID as aliases of the container.
	handler.aliases = append(handler.aliases, strings.TrimPrefix(ctnr.Name, "/"), id)
	handler.labels = ctnr.Config.Labels
	handler.image = ctnr.Config.Image
	handler.networkMode = ctnr.HostConfig.NetworkMode

	return handler, nil
}

func (self *dockerContainerHandler) ContainerReference() (info.ContainerReference, error) {
	return info.ContainerReference{
		Name:      self.name,
		Aliases:   self.aliases,
		Namespace: DockerNamespace,
	}, nil
}

func (self *dockerContainerHandler) readLibcontainerConfig() (*libcontainerconfigs.Config, error) {
	config, err := containerlibcontainer.ReadConfig(*dockerRootDir, *dockerRunDir, self.id)
	if err != nil {
		return nil, fmt.Errorf("failed to read libcontainer config: %v", err)
	}

	// Replace cgroup parent and name with our own since we may be running in a different context.
	if config.Cgroups == nil {
		config.Cgroups = new(libcontainerconfigs.Cgroup)
	}
	config.Cgroups.Name = self.name
	config.Cgroups.Parent = "/"

	return config, nil
}

func libcontainerConfigToContainerSpec(config *libcontainerconfigs.Config, mi *info.MachineInfo) info.ContainerSpec {
	var spec info.ContainerSpec
	spec.HasMemory = true
	spec.Memory.Limit = math.MaxUint64
	spec.Memory.SwapLimit = math.MaxUint64
	if config.Cgroups.Memory > 0 {
		spec.Memory.Limit = uint64(config.Cgroups.Memory)
	}
	if config.Cgroups.MemorySwap > 0 {
		spec.Memory.SwapLimit = uint64(config.Cgroups.MemorySwap)
	}

	// Get CPU info
	spec.HasCpu = true
	spec.Cpu.Limit = 1024
	if config.Cgroups.CpuShares != 0 {
		spec.Cpu.Limit = uint64(config.Cgroups.CpuShares)
	}
	spec.Cpu.Mask = utils.FixCpuMask(config.Cgroups.CpusetCpus, mi.NumCores)

	spec.HasDiskIo = true

	return spec
}

var (
	hasNetworkModes = map[string]bool{
		"host":    true,
		"bridge":  true,
		"default": true,
	}
)

func hasNet(networkMode string) bool {
	return hasNetworkModes[networkMode]
}

func (self *dockerContainerHandler) GetSpec() (info.ContainerSpec, error) {
	mi, err := self.machineInfoFactory.GetMachineInfo()
	if err != nil {
		return info.ContainerSpec{}, err
	}
	libcontainerConfig, err := self.readLibcontainerConfig()
	if err != nil {
		return info.ContainerSpec{}, err
	}

	spec := libcontainerConfigToContainerSpec(libcontainerConfig, mi)
	spec.CreationTime = self.creationTime

	switch self.storageDriver {
	case aufsStorageDriver, overlayStorageDriver:
		spec.HasFilesystem = true
	default:
		spec.HasFilesystem = false
	}

	spec.Labels = self.labels
	spec.Image = self.image
	spec.HasNetwork = hasNet(self.networkMode)

	return spec, err
}

func (self *dockerContainerHandler) getFsStats(stats *info.ContainerStats) error {
	switch self.storageDriver {
	case aufsStorageDriver, overlayStorageDriver:
	default:
		return nil
	}

	// As of now we assume that all the storage dirs are on the same device.
	// The first storage dir will be that of the image layers.
	deviceInfo, err := self.fsInfo.GetDirFsDevice(self.storageDirs[0])
	if err != nil {
		return err
	}

	mi, err := self.machineInfoFactory.GetMachineInfo()
	if err != nil {
		return err
	}
	var limit uint64 = 0
	// Docker does not impose any filesystem limits for containers. So use capacity as limit.
	for _, fs := range mi.Filesystems {
		if fs.Device == deviceInfo.Device {
			limit = fs.Capacity
			break
		}
	}

	fsStat := info.FsStats{Device: deviceInfo.Device, Limit: limit}

	fsStat.Usage = self.fsHandler.usage()
	stats.Filesystem = append(stats.Filesystem, fsStat)

	return nil
}

// TODO(vmarmol): Get from libcontainer API instead of cgroup manager when we don't have to support older Dockers.
func (self *dockerContainerHandler) GetStats() (*info.ContainerStats, error) {
	stats, err := containerlibcontainer.GetStats(self.cgroupManager, self.rootFs, self.pid)
	if err != nil {
		return stats, err
	}
	// Clean up stats for containers that don't have their own network - this
	// includes containers running in Kubernetes pods that use the network of the
	// infrastructure container. This stops metrics being reported multiple times
	// for each container in a pod.
	if !hasNet(self.networkMode) {
		stats.Network = info.NetworkStats{}
	}

	// Get filesystem stats.
	err = self.getFsStats(stats)
	if err != nil {
		return stats, err
	}

	return stats, nil
}

func (self *dockerContainerHandler) ListContainers(listType container.ListType) ([]info.ContainerReference, error) {
	// No-op for Docker driver.
	return []info.ContainerReference{}, nil
}

func (self *dockerContainerHandler) GetCgroupPath(resource string) (string, error) {
	path, ok := self.cgroupPaths[resource]
	if !ok {
		return "", fmt.Errorf("could not find path for resource %q for container %q\n", resource, self.name)
	}
	return path, nil
}

func (self *dockerContainerHandler) ListThreads(listType container.ListType) ([]int, error) {
	// TODO(vmarmol): Implement.
	return nil, nil
}

func (self *dockerContainerHandler) GetContainerLabels() map[string]string {
	return self.labels
}

func (self *dockerContainerHandler) ListProcesses(listType container.ListType) ([]int, error) {
	return containerlibcontainer.GetProcesses(self.cgroupManager)
}

func (self *dockerContainerHandler) WatchSubcontainers(events chan container.SubcontainerEvent) error {
	return fmt.Errorf("watch is unimplemented in the Docker container driver")
}

func (self *dockerContainerHandler) StopWatchingSubcontainers() error {
	// No-op for Docker driver.
	return nil
}

func (self *dockerContainerHandler) Exists() bool {
	return containerlibcontainer.Exists(*dockerRootDir, *dockerRunDir, self.id)
}

func DockerInfo() (map[string]string, error) {
	client, err := Client()
	if err != nil {
		return nil, fmt.Errorf("unable to communicate with docker daemon: %v", err)
	}
	info, err := client.Info()
	if err != nil {
		return nil, err
	}
	return info.Map(), nil
}

func DockerImages() ([]docker.APIImages, error) {
	client, err := Client()
	if err != nil {
		return nil, fmt.Errorf("unable to communicate with docker daemon: %v", err)
	}
	images, err := client.ListImages(docker.ListImagesOptions{All: false})
	if err != nil {
		return nil, err
	}
	return images, nil
}
<|endoftext|>


<commit_before>/*
   Copyright 2013 Juliano Martinez <juliano@martinez.io>

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

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

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

   @author: Juliano Martinez
*/

package utils

import (
	"fmt"
	"log"
	"log/syslog"
)

var (
	_log, s_err = syslog.New(syslog.LOG_ERR, "cloudboss")
)

func Check(err error, message string) {
	check(err, message, false)
}

func CheckPanic(err error, message string) {
	check(err, message, true)
}

func Log(message string) {
	CheckPanic(s_err, "Unable to write syslog message")
	_log.Info(message)
	defer _log.Close()
}

func check(err error, message string, _panic bool) {
	if err != nil {
		msg := fmt.Sprintf("%s: %s", message, err)
		if s_err != nil {
			log.Fatalln("Unable to write syslog message")
		}
		_log.Warning(msg)
		defer _log.Close()
		log.Fatalln(msg)
		if _panic {
			panic(msg)
		}
	}
}
<commit_msg>changed log name<commit_after>/*
   Copyright 2013 Juliano Martinez <juliano@martinez.io>

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

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

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

   @author: Juliano Martinez
*/

package utils

import (
	"fmt"
	"log"
	"log/syslog"
)

var (
	_log, s_err = syslog.New(syslog.LOG_ERR, "hpr")
)

func Check(err error, message string) {
	check(err, message, false)
}

func CheckPanic(err error, message string) {
	check(err, message, true)
}

func Log(message string) {
	CheckPanic(s_err, "Unable to write syslog message")
	_log.Info(message)
	defer _log.Close()
}

func check(err error, message string, _panic bool) {
	if err != nil {
		msg := fmt.Sprintf("%s: %s", message, err)
		if s_err != nil {
			log.Fatalln("Unable to write syslog message")
		}
		_log.Warning(msg)
		defer _log.Close()
		log.Fatalln(msg)
		if _panic {
			panic(msg)
		}
	}
}
<|endoftext|>


<commit_before>package utils

import (
	"sync"

	"github.com/pborman/uuid"
)

// GenerateUUID generates a new uuid for a minion
func GenerateUUID(name string) uuid.UUID {
	u := uuid.NewSHA1(uuid.NameSpace_DNS, []byte(name))

	return u
}

// Concurrentmap is a map type that can be safely shared between
// goroutines that require read/write access to a map
type ConcurrentMap struct {
	sync.RWMutex
	items map[string]interface{}
}

// ConcurrentMapItem contains a key/value pair item of a concurrent map
type ConcurrentMapItem struct {
	Key   string
	Value interface{}
}

// NewConcurrentMap creates a new concurrent map
func NewConcurrentMap() *ConcurrentMap {
	cm := &ConcurrentMap{
		items: make(map[string]interface{}),
	}

	return cm
}

// Set adds an item to a concurrent map
func (cm *ConcurrentMap) Set(key string, value interface{}) {
	cm.Lock()
	defer cm.Unlock()

	cm.items[key] = value
}

// Get retrieves the value for a concurrent map item
func (cm *ConcurrentMap) Get(key string) (interface{}, bool) {
	cm.Lock()
	defer cm.Unlock()

	value, ok := cm.items[key]

	return value, ok
}

// Iter iterates over the items in a concurrent map
// Each item is sent over a channel, so that
// we can iterate over the map using the builtin range keyword
func (cm *ConcurrentMap) Iter() <-chan ConcurrentMapItem {
	c := make(chan ConcurrentMapItem)

	f := func() {
		cm.Lock()
		defer cm.Unlock()

		for k, v := range cm.items {
			c <- ConcurrentMapItem{k, v}
		}
		close(c)
	}
	go f()

	return c
}

// ConcurrentSlice type that can be safely shared between goroutines
type ConcurrentSlice struct {
	sync.RWMutex
	items []interface{}
}

// ConcurrentSliceItem contains the index/value pair of an item in a
// concurrent slice
type ConcurrentSliceItem struct {
	Index int
	Value interface{}
}

// NewConcurrentSlice creates a new concurrent slice
func NewConcurrentSlice() *ConcurrentSlice {
	cs := &ConcurrentSlice{
		items: make([]interface{}, 0),
	}

	return cs
}

// Append adds an item to the concurrent slice
func (cs *ConcurrentSlice) Append(item interface{}) {
	cs.Lock()
	defer cs.Unlock()

	cs.items = append(cs.items, item)
}

// Iter iterates over the items in the concurrent slice
// Each item is sent over a channel, so that
// we can iterate over the slice using the builin range keyword
func (cs *ConcurrentSlice) Iter() <-chan ConcurrentSliceItem {
	c := make(chan ConcurrentSliceItem)

	f := func() {
		cs.Lock()
		defer cs.Lock()
		for index, value := range cs.items {
			c <- ConcurrentSliceItem{index, value}
		}
		close(c)
	}
	go f()

	return c
}
<commit_msg>doc comment update<commit_after>package utils

import (
	"sync"

	"github.com/pborman/uuid"
)

// GenerateUUID generates a new uuid for a minion
func GenerateUUID(name string) uuid.UUID {
	u := uuid.NewSHA1(uuid.NameSpace_DNS, []byte(name))

	return u
}

// ConcurrentMap is a map type that can be safely shared between
// goroutines that require read/write access to a map
type ConcurrentMap struct {
	sync.RWMutex
	items map[string]interface{}
}

// ConcurrentMapItem contains a key/value pair item of a concurrent map
type ConcurrentMapItem struct {
	Key   string
	Value interface{}
}

// NewConcurrentMap creates a new concurrent map
func NewConcurrentMap() *ConcurrentMap {
	cm := &ConcurrentMap{
		items: make(map[string]interface{}),
	}

	return cm
}

// Set adds an item to a concurrent map
func (cm *ConcurrentMap) Set(key string, value interface{}) {
	cm.Lock()
	defer cm.Unlock()

	cm.items[key] = value
}

// Get retrieves the value for a concurrent map item
func (cm *ConcurrentMap) Get(key string) (interface{}, bool) {
	cm.Lock()
	defer cm.Unlock()

	value, ok := cm.items[key]

	return value, ok
}

// Iter iterates over the items in a concurrent map
// Each item is sent over a channel, so that
// we can iterate over the map using the builtin range keyword
func (cm *ConcurrentMap) Iter() <-chan ConcurrentMapItem {
	c := make(chan ConcurrentMapItem)

	f := func() {
		cm.Lock()
		defer cm.Unlock()

		for k, v := range cm.items {
			c <- ConcurrentMapItem{k, v}
		}
		close(c)
	}
	go f()

	return c
}

// ConcurrentSlice type that can be safely shared between goroutines
type ConcurrentSlice struct {
	sync.RWMutex
	items []interface{}
}

// ConcurrentSliceItem contains the index/value pair of an item in a
// concurrent slice
type ConcurrentSliceItem struct {
	Index int
	Value interface{}
}

// NewConcurrentSlice creates a new concurrent slice
func NewConcurrentSlice() *ConcurrentSlice {
	cs := &ConcurrentSlice{
		items: make([]interface{}, 0),
	}

	return cs
}

// Append adds an item to the concurrent slice
func (cs *ConcurrentSlice) Append(item interface{}) {
	cs.Lock()
	defer cs.Unlock()

	cs.items = append(cs.items, item)
}

// Iter iterates over the items in the concurrent slice
// Each item is sent over a channel, so that
// we can iterate over the slice using the builin range keyword
func (cs *ConcurrentSlice) Iter() <-chan ConcurrentSliceItem {
	c := make(chan ConcurrentSliceItem)

	f := func() {
		cs.Lock()
		defer cs.Lock()
		for index, value := range cs.items {
			c <- ConcurrentSliceItem{index, value}
		}
		close(c)
	}
	go f()

	return c
}
<|endoftext|>


<commit_before>package utils

import (
	//"fmt"
	"fmt"
	"math"
	"math/big"
	"math/rand"
	"time"
)

type TupleInt struct {
	A int
	B int
}

//Euclidean modulous
func Mod(a, b int) int {
	ab := big.NewInt(int64(a))
	bb := big.NewInt(int64(b))
	return int(ab.Mod(ab, bb).Int64())
}

//Dot product
func DotInt(a, b []int) int {
	if len(a) != len(b) {
		panic("Params have differing lengths")
	}
	result := 0
	for i := range a {
		result += a[i] * b[i]
	}
	return result
}

//Populates integer slice with index values
func FillSliceWithIdxInt(values []int) {
	for i := range values {
		values[i] = i
	}
}

//Populates float64 slice with specified value
func FillSliceInt(values []int, value int) {
	for i := range values {
		values[i] = value
	}
}

//Populates float64 slice with specified value
func FillSliceFloat64(values []float64, value float64) {
	for i := range values {
		values[i] = value
	}
}

//Populates bool slice with specified value
func FillSliceBool(values []bool, value bool) {
	for i := range values {
		values[i] = value
	}
}

//Populates bool slice with specified value
func FillSliceRangeBool(values []bool, value bool, start, length int) {
	for i := 0; i < length; i++ {
		values[start+i] = value
	}
}

//Returns the subset of values specified by indices
func SubsetSliceInt(values, indices []int) []int {
	result := make([]int, len(indices))
	for i, val := range indices {
		result[i] = values[val]
	}
	return result
}

//Returns the subset of values specified by indices
func SubsetSliceFloat64(values []float64, indices []int) []float64 {
	result := make([]float64, len(indices))
	for i, val := range indices {
		result[i] = values[val]
	}
	return result
}

//Creates an integer slice with indices containing
// the specified initial value
func MakeSliceInt(size, initialValue int) []int {
	result := make([]int, size)
	if initialValue != 0 {
		for i, _ := range result {
			result[i] = initialValue
		}
	}
	return result
}

func MakeSliceFloat64(size int, initialValue float64) []float64 {
	result := make([]float64, size)
	if initialValue != 0 {
		for i, _ := range result {
			result[i] = initialValue
		}
	}
	return result
}

//Returns cartesian product of specified
//2d arrayb
func CartProductInt(values [][]int) [][]int {
	pos := make([]int, len(values))
	var result [][]int

	for pos[0] < len(values[0]) {
		temp := make([]int, len(values))
		for j := 0; j < len(values); j++ {
			temp[j] = values[j][pos[j]]
		}
		result = append(result, temp)
		pos[len(values)-1]++
		for k := len(values) - 1; k >= 1; k-- {
			if pos[k] >= len(values[k]) {
				pos[k] = 0
				pos[k-1]++
			} else {
				break
			}
		}
	}
	return result
}

//Searches int slice for specified integer
func ContainsInt(q int, vals []int) bool {
	for _, val := range vals {
		if val == q {
			return true
		}
	}
	return false
}

func ContainsFloat64(q float64, vals []float64) bool {
	for _, val := range vals {
		if val == q {
			return true
		}
	}
	return false
}

// type CompareInt func(int) bool

// func CountInt(q CompareInt, vals []int) int {
// 	count := 0
// 	for i := range vals {
// 		if q(i) {
// 			count++
// 		}
// 	}
// 	return count
// }

func RandFloatRange(min, max float64) float64 {
	return rand.Float64()*(max-min) + min
}

//returns max index wise comparison
func MaxInt(a, b []int) []int {
	result := make([]int, len(a))
	for i := 0; i < len(a); i++ {
		if a[i] > b[i] {
			result[i] = a[i]
		} else {
			result[i] = b[i]
		}
	}

	return result
}

//Returns max value from specified int slice
func MaxSliceInt(values []int) int {
	max := 0
	for i := 0; i < len(values); i++ {
		if values[i] > max {
			max = values[i]
		}
	}
	return max
}

//Returns max value from specified float slice
func MaxSliceFloat64(values []float64) float64 {
	max := 0.0
	for i := 0; i < len(values); i++ {
		if values[i] > max {
			max = values[i]
		}
	}
	return max
}

//Returns product of set of integers
func ProdInt(vals []int) int {
	sum := 1
	for x := 0; x < len(vals); x++ {
		sum *= vals[x]
	}

	if sum == 1 {
		return 0
	} else {
		return sum
	}
}

//Returns cumulative product
func CumProdInt(vals []int) []int {
	if len(vals) < 2 {
		return vals
	}
	result := make([]int, len(vals))
	result[0] = vals[0]
	for x := 1; x < len(vals); x++ {
		result[x] = vals[x] * result[x-1]
	}

	return result
}

//Returns cumulative product starting from end
func RevCumProdInt(vals []int) []int {
	if len(vals) < 2 {
		return vals
	}
	result := make([]int, len(vals))
	result[len(vals)-1] = vals[len(vals)-1]
	for x := len(vals) - 2; x >= 0; x-- {
		result[x] = vals[x] * result[x+1]
	}

	return result
}

func RoundPrec(x float64, prec int) float64 {
	if math.IsNaN(x) || math.IsInf(x, 0) {
		return x
	}

	sign := 1.0
	if x < 0 {
		sign = -1
		x *= -1
	}

	var rounder float64
	pow := math.Pow(10, float64(prec))
	intermed := x * pow
	_, frac := math.Modf(intermed)

	if frac >= 0.5 {
		rounder = math.Ceil(intermed)
	} else {
		rounder = math.Floor(intermed)
	}

	return rounder / pow * sign
}

//Helper for unit tests where int literals are easier
// to read
func Make2DBool(values [][]int) [][]bool {
	result := make([][]bool, len(values))

	for i, val := range values {
		result[i] = make([]bool, len(val))
		for j, col := range val {
			result[i][j] = col == 1
		}
	}

	return result
}

func Make1DBool(values []int) []bool {
	result := make([]bool, len(values))
	for i, val := range values {
		result[i] = val == 1
	}
	return result
}

//Returns number of on bits
func CountInt(values []int, value int) int {
	count := 0
	for _, val := range values {
		if val == value {
			count++
		}
	}
	return count
}

//Returns number of on bits
func CountFloat64(values []float64, value float64) int {
	count := 0
	for _, val := range values {
		if val == value {
			count++
		}
	}
	return count
}

//Returns number of on bits
func CountTrue(values []bool) int {
	count := 0
	for _, val := range values {
		if val {
			count++
		}
	}
	return count
}

//Or's 2 bool slices
func OrBool(a, b []bool) []bool {
	result := make([]bool, len(a))
	for i, val := range a {
		result[i] = val || b[i]
	}
	return result
}

//Returns random slice of floats of specified length
func RandomSample(length int) []float64 {
	result := make([]float64, length)

	for i, _ := range result {
		result[i] = rand.Float64()
	}

	return result
}

func Bool2Int(s []bool) []int {
	result := make([]int, len(s))
	for idx, val := range s {
		if val {
			result[idx] = 1
		} else {
			result[idx] = 0
		}

	}
	return result
}

func timeTrack(start time.Time, name string) {
	elapsed := time.Since(start)
	fmt.Printf("%s took %s \n", name, elapsed)
}

func SumSliceFloat64(values []float64) float64 {
	result := 0.0
	for _, val := range values {
		result += val
	}
	return result
}

//Returns "on" indices
func OnIndices(s []bool) []int {
	var result []int
	for idx, val := range s {
		if val {
			result = append(result, idx)
		}
	}
	return result
}

// Returns complement of s and t
func Complement(s []int, t []int) []int {
	result := make([]int, 0, len(s))
	for _, val := range s {
		found := false
		for _, v2 := range t {
			if v2 == val {
				found = true
				break
			}
		}
		if !found {
			result = append(result, val)
		}
	}
	return result
}

func Add(s []int, t []int) []int {
	result := make([]int, 0, len(s)+len(t))
	result = append(result, s...)

	for _, val := range t {
		if ContainsInt(val, s) {
			result = append(result, val)
		}
	}
	return result
}
<commit_msg>fix add<commit_after>package utils

import (
	//"fmt"
	"fmt"
	"math"
	"math/big"
	"math/rand"
	"time"
)

type TupleInt struct {
	A int
	B int
}

//Euclidean modulous
func Mod(a, b int) int {
	ab := big.NewInt(int64(a))
	bb := big.NewInt(int64(b))
	return int(ab.Mod(ab, bb).Int64())
}

//Dot product
func DotInt(a, b []int) int {
	if len(a) != len(b) {
		panic("Params have differing lengths")
	}
	result := 0
	for i := range a {
		result += a[i] * b[i]
	}
	return result
}

//Populates integer slice with index values
func FillSliceWithIdxInt(values []int) {
	for i := range values {
		values[i] = i
	}
}

//Populates float64 slice with specified value
func FillSliceInt(values []int, value int) {
	for i := range values {
		values[i] = value
	}
}

//Populates float64 slice with specified value
func FillSliceFloat64(values []float64, value float64) {
	for i := range values {
		values[i] = value
	}
}

//Populates bool slice with specified value
func FillSliceBool(values []bool, value bool) {
	for i := range values {
		values[i] = value
	}
}

//Populates bool slice with specified value
func FillSliceRangeBool(values []bool, value bool, start, length int) {
	for i := 0; i < length; i++ {
		values[start+i] = value
	}
}

//Returns the subset of values specified by indices
func SubsetSliceInt(values, indices []int) []int {
	result := make([]int, len(indices))
	for i, val := range indices {
		result[i] = values[val]
	}
	return result
}

//Returns the subset of values specified by indices
func SubsetSliceFloat64(values []float64, indices []int) []float64 {
	result := make([]float64, len(indices))
	for i, val := range indices {
		result[i] = values[val]
	}
	return result
}

//Creates an integer slice with indices containing
// the specified initial value
func MakeSliceInt(size, initialValue int) []int {
	result := make([]int, size)
	if initialValue != 0 {
		for i, _ := range result {
			result[i] = initialValue
		}
	}
	return result
}

func MakeSliceFloat64(size int, initialValue float64) []float64 {
	result := make([]float64, size)
	if initialValue != 0 {
		for i, _ := range result {
			result[i] = initialValue
		}
	}
	return result
}

//Returns cartesian product of specified
//2d arrayb
func CartProductInt(values [][]int) [][]int {
	pos := make([]int, len(values))
	var result [][]int

	for pos[0] < len(values[0]) {
		temp := make([]int, len(values))
		for j := 0; j < len(values); j++ {
			temp[j] = values[j][pos[j]]
		}
		result = append(result, temp)
		pos[len(values)-1]++
		for k := len(values) - 1; k >= 1; k-- {
			if pos[k] >= len(values[k]) {
				pos[k] = 0
				pos[k-1]++
			} else {
				break
			}
		}
	}
	return result
}

//Searches int slice for specified integer
func ContainsInt(q int, vals []int) bool {
	for _, val := range vals {
		if val == q {
			return true
		}
	}
	return false
}

func ContainsFloat64(q float64, vals []float64) bool {
	for _, val := range vals {
		if val == q {
			return true
		}
	}
	return false
}

// type CompareInt func(int) bool

// func CountInt(q CompareInt, vals []int) int {
// 	count := 0
// 	for i := range vals {
// 		if q(i) {
// 			count++
// 		}
// 	}
// 	return count
// }

func RandFloatRange(min, max float64) float64 {
	return rand.Float64()*(max-min) + min
}

//returns max index wise comparison
func MaxInt(a, b []int) []int {
	result := make([]int, len(a))
	for i := 0; i < len(a); i++ {
		if a[i] > b[i] {
			result[i] = a[i]
		} else {
			result[i] = b[i]
		}
	}

	return result
}

//Returns max value from specified int slice
func MaxSliceInt(values []int) int {
	max := 0
	for i := 0; i < len(values); i++ {
		if values[i] > max {
			max = values[i]
		}
	}
	return max
}

//Returns max value from specified float slice
func MaxSliceFloat64(values []float64) float64 {
	max := 0.0
	for i := 0; i < len(values); i++ {
		if values[i] > max {
			max = values[i]
		}
	}
	return max
}

//Returns product of set of integers
func ProdInt(vals []int) int {
	sum := 1
	for x := 0; x < len(vals); x++ {
		sum *= vals[x]
	}

	if sum == 1 {
		return 0
	} else {
		return sum
	}
}

//Returns cumulative product
func CumProdInt(vals []int) []int {
	if len(vals) < 2 {
		return vals
	}
	result := make([]int, len(vals))
	result[0] = vals[0]
	for x := 1; x < len(vals); x++ {
		result[x] = vals[x] * result[x-1]
	}

	return result
}

//Returns cumulative product starting from end
func RevCumProdInt(vals []int) []int {
	if len(vals) < 2 {
		return vals
	}
	result := make([]int, len(vals))
	result[len(vals)-1] = vals[len(vals)-1]
	for x := len(vals) - 2; x >= 0; x-- {
		result[x] = vals[x] * result[x+1]
	}

	return result
}

func RoundPrec(x float64, prec int) float64 {
	if math.IsNaN(x) || math.IsInf(x, 0) {
		return x
	}

	sign := 1.0
	if x < 0 {
		sign = -1
		x *= -1
	}

	var rounder float64
	pow := math.Pow(10, float64(prec))
	intermed := x * pow
	_, frac := math.Modf(intermed)

	if frac >= 0.5 {
		rounder = math.Ceil(intermed)
	} else {
		rounder = math.Floor(intermed)
	}

	return rounder / pow * sign
}

//Helper for unit tests where int literals are easier
// to read
func Make2DBool(values [][]int) [][]bool {
	result := make([][]bool, len(values))

	for i, val := range values {
		result[i] = make([]bool, len(val))
		for j, col := range val {
			result[i][j] = col == 1
		}
	}

	return result
}

func Make1DBool(values []int) []bool {
	result := make([]bool, len(values))
	for i, val := range values {
		result[i] = val == 1
	}
	return result
}

//Returns number of on bits
func CountInt(values []int, value int) int {
	count := 0
	for _, val := range values {
		if val == value {
			count++
		}
	}
	return count
}

//Returns number of on bits
func CountFloat64(values []float64, value float64) int {
	count := 0
	for _, val := range values {
		if val == value {
			count++
		}
	}
	return count
}

//Returns number of on bits
func CountTrue(values []bool) int {
	count := 0
	for _, val := range values {
		if val {
			count++
		}
	}
	return count
}

//Or's 2 bool slices
func OrBool(a, b []bool) []bool {
	result := make([]bool, len(a))
	for i, val := range a {
		result[i] = val || b[i]
	}
	return result
}

//Returns random slice of floats of specified length
func RandomSample(length int) []float64 {
	result := make([]float64, length)

	for i, _ := range result {
		result[i] = rand.Float64()
	}

	return result
}

func Bool2Int(s []bool) []int {
	result := make([]int, len(s))
	for idx, val := range s {
		if val {
			result[idx] = 1
		} else {
			result[idx] = 0
		}

	}
	return result
}

func timeTrack(start time.Time, name string) {
	elapsed := time.Since(start)
	fmt.Printf("%s took %s \n", name, elapsed)
}

func SumSliceFloat64(values []float64) float64 {
	result := 0.0
	for _, val := range values {
		result += val
	}
	return result
}

//Returns "on" indices
func OnIndices(s []bool) []int {
	var result []int
	for idx, val := range s {
		if val {
			result = append(result, idx)
		}
	}
	return result
}

// Returns complement of s and t
func Complement(s []int, t []int) []int {
	result := make([]int, 0, len(s))
	for _, val := range s {
		found := false
		for _, v2 := range t {
			if v2 == val {
				found = true
				break
			}
		}
		if !found {
			result = append(result, val)
		}
	}
	return result
}

func Add(s []int, t []int) []int {
	result := make([]int, 0, len(s)+len(t))
	result = append(result, s...)

	for _, val := range t {
		if !ContainsInt(val, s) {
			result = append(result, val)
		}
	}
	return result
}
<|endoftext|>


<commit_before>package utils

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"os"
	"time"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/awserr"
	"github.com/aws/aws-sdk-go/aws/credentials"
	"github.com/aws/aws-sdk-go/aws/request"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/cloudformation"
)

type AwsRequest interface {
	Send() error
}

type RequestHandler interface {
	HandleRequest(req AwsRequest) error
}

type AwsRequestHandler struct {
}

func (r *AwsRequestHandler) HandleRequest(req AwsRequest) error {
	s := 1
	var err error
	for err = req.Send(); err != nil; err = req.Send() {
		if reqerr, ok := err.(awserr.RequestFailure); ok {
			if reqerr.Code() == "RequestLimitExceeded" {
				time.Sleep(time.Duration(s) * time.Second)
				s = s * 2
				continue
			}
		}
		return err
	}
	return nil
}

type Input struct {
	Source struct {
		Name               string `json:"name"`
		AwsAccessKeyId     string `json:"aws_access_key_id"`
		AwsSecretAccessKey string `json:"aws_secret_access_key"`
		Region             string `json:"region"`
	} `json:"source"`
	Version struct {
		LastUpdatedTime string `json:"LastUpdatedTime"`
	} `json:"version"`
	Params struct {
		Template     string   `json:"template"`
		Parameters   string   `json:"parameters"`
		Tags         string   `json:"tags"`
		Capabilities []string `json:"capabilities"`
		Delete       bool     `json:"delete"`
		Wait         bool     `json:"wait"`
	} `json:"params"`
}

func GetInput() Input {
	bytes, err := ioutil.ReadAll(os.Stdin)
	if err != nil {
		panic(err)
	}
	input := Input{}
	err = json.Unmarshal(bytes, &input)
	if err != nil {
		panic(err)
	}
	return input
}

type AwsCloudformationSvc interface {
	DescribeStacksRequest(input *cloudformation.DescribeStacksInput) (req *request.Request, output *cloudformation.DescribeStacksOutput)
	CreateStackRequest(input *cloudformation.CreateStackInput) (req *request.Request, output *cloudformation.CreateStackOutput)
	UpdateStackRequest(input *cloudformation.UpdateStackInput) (req *request.Request, output *cloudformation.UpdateStackOutput)
	DescribeStackEventsRequest(input *cloudformation.DescribeStackEventsInput) (req *request.Request, output *cloudformation.DescribeStackEventsOutput)
	DeleteStackRequest(input *cloudformation.DeleteStackInput) (req *request.Request, output *cloudformation.DeleteStackOutput)
}

func GetCloudformationService(input Input) AwsCloudformationSvc {
	creds := credentials.NewStaticCredentials(input.Source.AwsAccessKeyId, input.Source.AwsSecretAccessKey, "")
	awsConfig := aws.NewConfig().WithCredentials(creds).WithRegion(input.Source.Region)
	sess := session.Must(session.NewSession(awsConfig))
	svc := cloudformation.New(sess)
	return svc
}

func GoToBuildDirectory() {
	files, err := ioutil.ReadDir("/tmp/build")
	if err != nil {
		panic(err)
	}

	if len(files) != 1 {
		fmt.Printf("Expected only 1 file in /tmp/build but found %d: %v\n", len(files), files)
		os.Exit(1)
	}

	os.Chdir("/tmp/build/" + files[0].Name())
}

func Logln(a ...interface{}) {
	fmt.Fprintln(os.Stderr, a...)
}

func Logf(format string, a ...interface{}) {
	fmt.Fprintf(os.Stderr, format, a)
}
<commit_msg>Added some logging<commit_after>package utils

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"os"
	"time"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/awserr"
	"github.com/aws/aws-sdk-go/aws/credentials"
	"github.com/aws/aws-sdk-go/aws/request"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/cloudformation"
)

type AwsRequest interface {
	Send() error
}

type RequestHandler interface {
	HandleRequest(req AwsRequest) error
}

type AwsRequestHandler struct {
}

func (r *AwsRequestHandler) HandleRequest(req AwsRequest) error {
	s := 1
	var err error
	for err = req.Send(); err != nil; err = req.Send() {
		if reqerr, ok := err.(awserr.RequestFailure); ok {
			if reqerr.Code() == "RequestLimitExceeded" {
				time.Sleep(time.Duration(s) * time.Second)
				s = s * 2
				continue
			}
			Logln("HandleRequest error code:", reqerr.Code())
		}
		return err
	}
	return nil
}

type Input struct {
	Source struct {
		Name               string `json:"name"`
		AwsAccessKeyId     string `json:"aws_access_key_id"`
		AwsSecretAccessKey string `json:"aws_secret_access_key"`
		Region             string `json:"region"`
	} `json:"source"`
	Version struct {
		LastUpdatedTime string `json:"LastUpdatedTime"`
	} `json:"version"`
	Params struct {
		Template     string   `json:"template"`
		Parameters   string   `json:"parameters"`
		Tags         string   `json:"tags"`
		Capabilities []string `json:"capabilities"`
		Delete       bool     `json:"delete"`
		Wait         bool     `json:"wait"`
	} `json:"params"`
}

func GetInput() Input {
	bytes, err := ioutil.ReadAll(os.Stdin)
	if err != nil {
		panic(err)
	}
	input := Input{}
	err = json.Unmarshal(bytes, &input)
	if err != nil {
		panic(err)
	}
	return input
}

type AwsCloudformationSvc interface {
	DescribeStacksRequest(input *cloudformation.DescribeStacksInput) (req *request.Request, output *cloudformation.DescribeStacksOutput)
	CreateStackRequest(input *cloudformation.CreateStackInput) (req *request.Request, output *cloudformation.CreateStackOutput)
	UpdateStackRequest(input *cloudformation.UpdateStackInput) (req *request.Request, output *cloudformation.UpdateStackOutput)
	DescribeStackEventsRequest(input *cloudformation.DescribeStackEventsInput) (req *request.Request, output *cloudformation.DescribeStackEventsOutput)
	DeleteStackRequest(input *cloudformation.DeleteStackInput) (req *request.Request, output *cloudformation.DeleteStackOutput)
}

func GetCloudformationService(input Input) AwsCloudformationSvc {
	creds := credentials.NewStaticCredentials(input.Source.AwsAccessKeyId, input.Source.AwsSecretAccessKey, "")
	awsConfig := aws.NewConfig().WithCredentials(creds).WithRegion(input.Source.Region)
	sess := session.Must(session.NewSession(awsConfig))
	svc := cloudformation.New(sess)
	return svc
}

func GoToBuildDirectory() {
	files, err := ioutil.ReadDir("/tmp/build")
	if err != nil {
		panic(err)
	}

	if len(files) != 1 {
		Logf("Expected only 1 file in /tmp/build but found %d: %v\n", len(files), files)
		os.Exit(1)
	}

	os.Chdir("/tmp/build/" + files[0].Name())
}

func Logln(a ...interface{}) {
	fmt.Fprintln(os.Stderr, a...)
}

func Logf(format string, a ...interface{}) {
	fmt.Fprintf(os.Stderr, format, a)
}
<|endoftext|>


<commit_before>package utils

import (
	"errors"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"runtime"
	"strings"
)

func Check(err error) {
	if err != nil {
		log.Fatalf("fatal: %v\n", err)
	}
}

func ConcatPaths(paths ...string) string {
	return strings.Join(paths, "/")
}

func BrowserLauncher() ([]string, error) {
	browser := os.Getenv("BROWSER")
	if browser == "" {
		browser = searchBrowserLauncher(runtime.GOOS)
	}

	if browser == "" {
		return nil, errors.New("Please set $BROWSER to a web launcher")
	}

	return strings.Split(browser, " "), nil
}

func searchBrowserLauncher(goos string) (browser string) {
	switch goos {
	case "darwin":
		browser = "open"
	case "windows":
		browser = "cmd /c start"
	default:
		candidates := []string{"xdg-open", "cygstart", "x-www-browser", "firefox",
			"opera", "mozilla", "netscape"}
		for _, b := range candidates {
			path, err := exec.LookPath(b)
			if err == nil {
				browser = path
				break
			}
		}
	}

	return browser
}

func DirName() (string, error) {
	dir, err := os.Getwd()
	if err != nil {
		return "", err
	}

	name := filepath.Base(dir)
	name = strings.Replace(name, " ", "-", -1)
	return name, nil
}

func IsOption(confirm, short, long string) bool {
	return strings.EqualFold(confirm, short) || strings.EqualFold(confirm, long)
}
<commit_msg>Print error to stderr instead of using log<commit_after>package utils

import (
	"errors"
	"fmt"
	"os"
	"os/exec"
	"path/filepath"
	"runtime"
	"strings"
)

func Check(err error) {
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}
}

func ConcatPaths(paths ...string) string {
	return strings.Join(paths, "/")
}

func BrowserLauncher() ([]string, error) {
	browser := os.Getenv("BROWSER")
	if browser == "" {
		browser = searchBrowserLauncher(runtime.GOOS)
	}

	if browser == "" {
		return nil, errors.New("Please set $BROWSER to a web launcher")
	}

	return strings.Split(browser, " "), nil
}

func searchBrowserLauncher(goos string) (browser string) {
	switch goos {
	case "darwin":
		browser = "open"
	case "windows":
		browser = "cmd /c start"
	default:
		candidates := []string{"xdg-open", "cygstart", "x-www-browser", "firefox",
			"opera", "mozilla", "netscape"}
		for _, b := range candidates {
			path, err := exec.LookPath(b)
			if err == nil {
				browser = path
				break
			}
		}
	}

	return browser
}

func DirName() (string, error) {
	dir, err := os.Getwd()
	if err != nil {
		return "", err
	}

	name := filepath.Base(dir)
	name = strings.Replace(name, " ", "-", -1)
	return name, nil
}

func IsOption(confirm, short, long string) bool {
	return strings.EqualFold(confirm, short) || strings.EqualFold(confirm, long)
}
<|endoftext|>


<commit_before>package utils

import (
	"fmt"
	"net/http"
	"net/url"
	"os"
	"reflect"
	"regexp"
	"runtime"
	"runtime/debug"
	"time"

	"github.com/jinzhu/gorm"
	"github.com/qor/qor"

	"strings"
)

// HumanizeString Humanize separates string based on capitalizd letters
// e.g. "OrderItem" -> "Order Item"
func HumanizeString(str string) string {
	var human []rune
	for i, l := range str {
		if i > 0 && isUppercase(byte(l)) {
			if i > 0 && !isUppercase(str[i-1]) || i+1 < len(str) && !isUppercase(str[i+1]) {
				human = append(human, rune(' '))
			}
		}
		human = append(human, l)
	}
	return strings.Title(string(human))
}

func isUppercase(char byte) bool {
	return 'A' <= char && char <= 'Z'
}

var upcaseRegexp = regexp.MustCompile("[A-Z]{3,}[a-z]")

// ToParamString replaces spaces and separates words (by uppercase letters) with
// underscores in a string, also downcase it
// e.g. ToParamString -> to_param_string, To ParamString -> to_param_string
func ToParamString(str string) string {
	return gorm.ToDBName(strings.Replace(str, " ", "_", -1))
}

// PatchURL updates the query part of the current request url. You can
// access it in template by `patch_url`.
//     patch_url "google.com" "key" "value"
func PatchURL(originalURL string, params ...interface{}) (patchedURL string, err error) {
	url, err := url.Parse(originalURL)
	if err != nil {
		return
	}

	query := url.Query()
	for i := 0; i < len(params)/2; i++ {
		// Check if params is key&value pair
		key := fmt.Sprintf("%v", params[i*2])
		value := fmt.Sprintf("%v", params[i*2+1])

		if value == "" {
			query.Del(key)
		} else {
			query.Set(key, value)
		}
	}

	url.RawQuery = query.Encode()
	patchedURL = url.String()
	return
}

// GetLocale get locale from request, cookie, after get the locale, will write the locale to the cookie if possible
func GetLocale(context *qor.Context) string {
	if locale := context.Request.Header.Get("Locale"); locale != "" {
		return locale
	}

	if locale := context.Request.URL.Query().Get("locale"); locale != "" {
		if context.Writer != nil {
			context.Request.Header.Set("Locale", locale)
			c := http.Cookie{Name: "locale", Value: locale, Expires: time.Now().AddDate(1, 0, 0), Path: "/", HttpOnly: true}
			http.SetCookie(context.Writer, &c)
		}
		return locale
	}

	if locale, err := context.Request.Cookie("locale"); err == nil {
		return locale.Value
	}

	return ""
}

// Stringify stringify any data, if it is a struct, will try to use its Name, Title, Code field, else will use its primary key
func Stringify(object interface{}) string {
	if obj, ok := object.(interface {
		Stringify() string
	}); ok {
		return obj.Stringify()
	}

	scope := gorm.Scope{Value: object}
	for _, column := range []string{"Name", "Title", "Code"} {
		if field, ok := scope.FieldByName(column); ok {
			return fmt.Sprintf("%v", field.Field.Interface())
		}
	}

	if scope.PrimaryField() != nil {
		if scope.PrimaryKeyZero() {
			return ""
		}
		return fmt.Sprintf("%v#%v", scope.GetModelStruct().ModelType.Name(), scope.PrimaryKeyValue())
	}

	return fmt.Sprint(reflect.Indirect(reflect.ValueOf(object)).Interface())
}

// ModelType get value's model type
func ModelType(value interface{}) reflect.Type {
	reflectType := reflect.Indirect(reflect.ValueOf(value)).Type()

	for reflectType.Kind() == reflect.Ptr || reflectType.Kind() == reflect.Slice {
		reflectType = reflectType.Elem()
	}

	return reflectType
}

// ParseTagOption parse tag options to hash
func ParseTagOption(str string) map[string]string {
	tags := strings.Split(str, ";")
	setting := map[string]string{}
	for _, value := range tags {
		v := strings.Split(value, ":")
		k := strings.TrimSpace(strings.ToUpper(v[0]))
		if len(v) == 2 {
			setting[k] = v[1]
		} else {
			setting[k] = k
		}
	}
	return setting
}

// ExitWithMsg debug error messages and print stack
func ExitWithMsg(msg interface{}, value ...interface{}) {
	fmt.Printf("\n"+filenameWithLineNum()+"\n%v\n", append([]interface{}{msg}, value...)...)
	debug.PrintStack()
}

func filenameWithLineNum() string {
	var total = 10
	var results []string
	for i := 2; i < 15; i++ {
		if _, file, line, ok := runtime.Caller(i); ok {
			total--
			results = append(results[:0],
				append(
					[]string{fmt.Sprintf("%v:%v", strings.TrimPrefix(file, os.Getenv("GOPATH")+"src/"), line)},
					results[0:]...)...)

			if total == 0 {
				return strings.Join(results, "\n")
			}
		}
	}
	return ""
}
<commit_msg>Add set cookie method<commit_after>package utils

import (
	"fmt"
	"net/http"
	"net/url"
	"os"
	"reflect"
	"regexp"
	"runtime"
	"runtime/debug"
	"time"

	"github.com/jinzhu/gorm"
	"github.com/qor/qor"

	"strings"
)

// HumanizeString Humanize separates string based on capitalizd letters
// e.g. "OrderItem" -> "Order Item"
func HumanizeString(str string) string {
	var human []rune
	for i, l := range str {
		if i > 0 && isUppercase(byte(l)) {
			if i > 0 && !isUppercase(str[i-1]) || i+1 < len(str) && !isUppercase(str[i+1]) {
				human = append(human, rune(' '))
			}
		}
		human = append(human, l)
	}
	return strings.Title(string(human))
}

func isUppercase(char byte) bool {
	return 'A' <= char && char <= 'Z'
}

var upcaseRegexp = regexp.MustCompile("[A-Z]{3,}[a-z]")

// ToParamString replaces spaces and separates words (by uppercase letters) with
// underscores in a string, also downcase it
// e.g. ToParamString -> to_param_string, To ParamString -> to_param_string
func ToParamString(str string) string {
	return gorm.ToDBName(strings.Replace(str, " ", "_", -1))
}

// PatchURL updates the query part of the current request url. You can
// access it in template by `patch_url`.
//     patch_url "google.com" "key" "value"
func PatchURL(originalURL string, params ...interface{}) (patchedURL string, err error) {
	url, err := url.Parse(originalURL)
	if err != nil {
		return
	}

	query := url.Query()
	for i := 0; i < len(params)/2; i++ {
		// Check if params is key&value pair
		key := fmt.Sprintf("%v", params[i*2])
		value := fmt.Sprintf("%v", params[i*2+1])

		if value == "" {
			query.Del(key)
		} else {
			query.Set(key, value)
		}
	}

	url.RawQuery = query.Encode()
	patchedURL = url.String()
	return
}

// GetLocale get locale from request, cookie, after get the locale, will write the locale to the cookie if possible
func GetLocale(context *qor.Context) string {
	if locale := context.Request.Header.Get("Locale"); locale != "" {
		return locale
	}

	if locale := context.Request.URL.Query().Get("locale"); locale != "" {
		if context.Writer != nil {
			context.Request.Header.Set("Locale", locale)
			c := http.Cookie{Name: "locale", Value: locale, Expires: time.Now().AddDate(1, 0, 0), Path: "/", HttpOnly: true}
			http.SetCookie(context.Writer, &c)
		}
		return locale
	}

	if locale, err := context.Request.Cookie("locale"); err == nil {
		return locale.Value
	}

	return ""
}

// SetCookie set cookie for context
func SetCookie(cookie http.Cookie, context *qor.Context) string {
	cookie.HttpOnly = true

	// set https cookie
	if context.Request != nil && context.Request.URL.Scheme == "https" {
		cookie.Secure = true
	}

	// set default path
	if cookie.Path == "" {
		cookie.Path = "/"
	}

	http.SetCookie(context.Writer, &cookie)
}

// Stringify stringify any data, if it is a struct, will try to use its Name, Title, Code field, else will use its primary key
func Stringify(object interface{}) string {
	if obj, ok := object.(interface {
		Stringify() string
	}); ok {
		return obj.Stringify()
	}

	scope := gorm.Scope{Value: object}
	for _, column := range []string{"Name", "Title", "Code"} {
		if field, ok := scope.FieldByName(column); ok {
			return fmt.Sprintf("%v", field.Field.Interface())
		}
	}

	if scope.PrimaryField() != nil {
		if scope.PrimaryKeyZero() {
			return ""
		}
		return fmt.Sprintf("%v#%v", scope.GetModelStruct().ModelType.Name(), scope.PrimaryKeyValue())
	}

	return fmt.Sprint(reflect.Indirect(reflect.ValueOf(object)).Interface())
}

// ModelType get value's model type
func ModelType(value interface{}) reflect.Type {
	reflectType := reflect.Indirect(reflect.ValueOf(value)).Type()

	for reflectType.Kind() == reflect.Ptr || reflectType.Kind() == reflect.Slice {
		reflectType = reflectType.Elem()
	}

	return reflectType
}

// ParseTagOption parse tag options to hash
func ParseTagOption(str string) map[string]string {
	tags := strings.Split(str, ";")
	setting := map[string]string{}
	for _, value := range tags {
		v := strings.Split(value, ":")
		k := strings.TrimSpace(strings.ToUpper(v[0]))
		if len(v) == 2 {
			setting[k] = v[1]
		} else {
			setting[k] = k
		}
	}
	return setting
}

// ExitWithMsg debug error messages and print stack
func ExitWithMsg(msg interface{}, value ...interface{}) {
	fmt.Printf("\n"+filenameWithLineNum()+"\n%v\n", append([]interface{}{msg}, value...)...)
	debug.PrintStack()
}

func filenameWithLineNum() string {
	var total = 10
	var results []string
	for i := 2; i < 15; i++ {
		if _, file, line, ok := runtime.Caller(i); ok {
			total--
			results = append(results[:0],
				append(
					[]string{fmt.Sprintf("%v:%v", strings.TrimPrefix(file, os.Getenv("GOPATH")+"src/"), line)},
					results[0:]...)...)

			if total == 0 {
				return strings.Join(results, "\n")
			}
		}
	}
	return ""
}
<|endoftext|>


<commit_before>package buffer

import (
	"sync"

	"github.com/pachyderm/pachyderm/src/client/pkg/grpcutil"
)

var bufPool = sync.Pool{
	New: func() interface{} {
		return make([]byte, grpcutil.MaxMsgSize/10)
	},
}

func Get() []byte {
	return bufPool.Get().([]byte)
}

func Put(buf []byte) {
	bufPool.Put(buf)
}
<commit_msg>Specify buffer size directly in the buffer package to get rid of import cycle<commit_after>package buffer

import (
	"sync"
)

var bufPool = sync.Pool{
	New: func() interface{} {
		// We use 2MB as the default buffer size because this buffer pool
		// is typically used for gRPC and 2MB is:
		// 1. Reasonably smaller than the max gRPC size (which is 20MB)
		// 2. Small enough that having hundreds of these buffers won't
		// overwhelm the node
		// 3. Large enough for message-sending to be efficient
		return make([]byte, 2*1024*1024)
	},
}

func Get() []byte {
	return bufPool.Get().([]byte)
}

func Put(buf []byte) {
	bufPool.Put(buf)
}
<|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 cache

import (
	"testing"
	"time"

	"k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/runtime"
	"k8s.io/apimachinery/pkg/util/wait"
	"k8s.io/apimachinery/pkg/watch"
)

func TestMutationDetector(t *testing.T) {
	fakeWatch := watch.NewFake()
	lw := &testLW{
		WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) {
			return fakeWatch, nil
		},
		ListFunc: func(options metav1.ListOptions) (runtime.Object, error) {
			return &v1.PodList{}, nil
		},
	}
	pod := &v1.Pod{
		ObjectMeta: metav1.ObjectMeta{
			Name:   "anything",
			Labels: map[string]string{"check": "foo"},
		},
	}
	stopCh := make(chan struct{})
	defer close(stopCh)
	mutationFound := make(chan bool)

	informer := NewSharedInformer(lw, &v1.Pod{}, 1*time.Second).(*sharedIndexInformer)
	detector := &defaultCacheMutationDetector{
		name:   "name",
		period: 1 * time.Second,
		failureFunc: func(message string) {
			mutationFound <- true
		},
	}
	informer.cacheMutationDetector = detector
	go informer.Run(stopCh)

	fakeWatch.Add(pod)

	wait.PollImmediate(100*time.Millisecond, wait.ForeverTestTimeout, func() (bool, error) {
		detector.addedObjsLock.Lock()
		defer detector.addedObjsLock.Unlock()
		return len(detector.addedObjs) > 0, nil
	})

	detector.compareObjectsLock.Lock()
	pod.Labels["change"] = "true"
	detector.compareObjectsLock.Unlock()

	select {
	case <-mutationFound:
	}

}
<commit_msg>Add test timeout to mutation detector test<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 cache

import (
	"testing"
	"time"

	"k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/runtime"
	"k8s.io/apimachinery/pkg/util/wait"
	"k8s.io/apimachinery/pkg/watch"
)

func TestMutationDetector(t *testing.T) {
	fakeWatch := watch.NewFake()
	lw := &testLW{
		WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) {
			return fakeWatch, nil
		},
		ListFunc: func(options metav1.ListOptions) (runtime.Object, error) {
			return &v1.PodList{}, nil
		},
	}
	pod := &v1.Pod{
		ObjectMeta: metav1.ObjectMeta{
			Name:   "anything",
			Labels: map[string]string{"check": "foo"},
		},
	}
	stopCh := make(chan struct{})
	defer close(stopCh)
	mutationFound := make(chan bool)

	informer := NewSharedInformer(lw, &v1.Pod{}, 1*time.Second).(*sharedIndexInformer)
	detector := &defaultCacheMutationDetector{
		name:           "name",
		period:         1 * time.Second,
		retainDuration: 2 * time.Minute,
		failureFunc: func(message string) {
			mutationFound <- true
		},
	}
	informer.cacheMutationDetector = detector
	go informer.Run(stopCh)

	fakeWatch.Add(pod)

	wait.PollImmediate(100*time.Millisecond, wait.ForeverTestTimeout, func() (bool, error) {
		detector.addedObjsLock.Lock()
		defer detector.addedObjsLock.Unlock()
		return len(detector.addedObjs) > 0, nil
	})

	detector.compareObjectsLock.Lock()
	pod.Labels["change"] = "true"
	detector.compareObjectsLock.Unlock()

	select {
	case <-mutationFound:
	case <-time.After(wait.ForeverTestTimeout):
		t.Fatalf("failed waiting for mutating detector")
	}

}
<|endoftext|>


<commit_before>package main

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

	"github.com/linuxkit/linuxkit/src/cmd/linuxkit/pkglib"
)

func pkgShowTag(args []string) {
	flags := flag.NewFlagSet("pkg show-tag", flag.ExitOnError)
	flags.Usage = func() {
		invoked := filepath.Base(os.Args[0])
		fmt.Fprintf(os.Stderr, "USAGE: %s pkg show-tag [options] path\n\n", invoked)
		fmt.Fprintf(os.Stderr, "'path' specifies the path to the package source directory.\n")
		fmt.Fprintf(os.Stderr, "\n")
		flags.PrintDefaults()
	}

	pkgs, err := pkglib.NewFromCLI(flags, args...)
	if err != nil {
		fmt.Fprintf(os.Stderr, "%v\n", err)
		os.Exit(1)
	}
	for _, p := range pkgs {
		fmt.Println(p.Tag())
	}
}
<commit_msg>option to show canonical tag<commit_after>package main

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

	"github.com/linuxkit/linuxkit/src/cmd/linuxkit/pkglib"
)

func pkgShowTag(args []string) {
	flags := flag.NewFlagSet("pkg show-tag", flag.ExitOnError)
	flags.Usage = func() {
		invoked := filepath.Base(os.Args[0])
		fmt.Fprintf(os.Stderr, "USAGE: %s pkg show-tag [options] path\n\n", invoked)
		fmt.Fprintf(os.Stderr, "'path' specifies the path to the package source directory.\n")
		fmt.Fprintf(os.Stderr, "\n")
		flags.PrintDefaults()
	}
	canonical := flags.Bool("canonical", false, "Show canonical name, e.g. docker.io/linuxkit/foo:1234, instead of the default, e.g. linuxkit/foo:1234")

	pkgs, err := pkglib.NewFromCLI(flags, args...)
	if err != nil {
		fmt.Fprintf(os.Stderr, "%v\n", err)
		os.Exit(1)
	}
	for _, p := range pkgs {
		tag := p.Tag()
		if *canonical {
			tag = p.FullTag()
		}
		fmt.Println(tag)
	}
}
<|endoftext|>


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

package main

import (
	"bufio"
	"bytes"
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"runtime"
	"strconv"
	"strings"
	"testing"
)

func loadSyms(t *testing.T) map[string]string {
	switch runtime.GOOS {
	case "android", "nacl":
		t.Skipf("skipping on %s", runtime.GOOS)
	}

	cmd := exec.Command("go", "tool", "nm", os.Args[0])
	out, err := cmd.CombinedOutput()
	if err != nil {
		t.Fatalf("go tool nm %v: %v\n%s", os.Args[0], err, string(out))
	}
	syms := make(map[string]string)
	scanner := bufio.NewScanner(bytes.NewReader(out))
	for scanner.Scan() {
		f := strings.Fields(scanner.Text())
		if len(f) < 3 {
			continue
		}
		syms[f[2]] = f[0]
	}
	if err := scanner.Err(); err != nil {
		t.Fatalf("error reading symbols: %v", err)
	}
	return syms
}

func runObjDump(t *testing.T, exe, startaddr, endaddr string) (path, lineno string) {
	switch runtime.GOOS {
	case "android", "nacl":
		t.Skipf("skipping on %s", runtime.GOOS)
	}

	cmd := exec.Command(exe, os.Args[0], startaddr, endaddr)
	out, err := cmd.CombinedOutput()
	if err != nil {
		t.Fatalf("go tool objdump %v: %v\n%s", os.Args[0], err, string(out))
	}
	f := strings.Split(string(out), "\n")
	if len(f) < 1 {
		t.Fatal("objdump output must have at least one line")
	}
	pathAndLineNo := f[0]
	f = strings.Split(pathAndLineNo, ":")
	if runtime.GOOS == "windows" {
		switch len(f) {
		case 2:
			return f[0], f[1]
		case 3:
			return f[0] + ":" + f[1], f[2]
		default:
			t.Fatalf("no line number found in %q", pathAndLineNo)
		}
	}
	if len(f) != 2 {
		t.Fatalf("no line number found in %q", pathAndLineNo)
	}
	return f[0], f[1]
}

func testObjDump(t *testing.T, exe, startaddr, endaddr string, line int) {
	srcPath, srcLineNo := runObjDump(t, exe, startaddr, endaddr)
	fi1, err := os.Stat("objdump_test.go")
	if err != nil {
		t.Fatalf("Stat failed: %v", err)
	}
	fi2, err := os.Stat(srcPath)
	if err != nil {
		t.Fatalf("Stat failed: %v", err)
	}
	if !os.SameFile(fi1, fi2) {
		t.Fatalf("objdump_test.go and %s are not same file", srcPath)
	}
	if srcLineNo != fmt.Sprint(line) {
		t.Fatalf("line number = %v; want %d", srcLineNo, line)
	}
}

func TestObjDump(t *testing.T) {
	_, _, line, _ := runtime.Caller(0)
	syms := loadSyms(t)

	tmp, exe := buildObjdump(t)
	defer os.RemoveAll(tmp)

	startaddr := syms["cmd/objdump.TestObjDump"]
	addr, err := strconv.ParseUint(startaddr, 16, 64)
	if err != nil {
		t.Fatalf("invalid start address %v: %v", startaddr, err)
	}
	endaddr := fmt.Sprintf("%x", addr+10)
	testObjDump(t, exe, startaddr, endaddr, line-1)
	testObjDump(t, exe, "0x"+startaddr, "0x"+endaddr, line-1)
}

func buildObjdump(t *testing.T) (tmp, exe string) {
	switch runtime.GOOS {
	case "android", "nacl":
		t.Skipf("skipping on %s", runtime.GOOS)
	}

	tmp, err := ioutil.TempDir("", "TestObjDump")
	if err != nil {
		t.Fatal("TempDir failed: ", err)
	}

	exe = filepath.Join(tmp, "testobjdump.exe")
	out, err := exec.Command("go", "build", "-o", exe, "cmd/objdump").CombinedOutput()
	if err != nil {
		os.RemoveAll(tmp)
		t.Fatalf("go build -o %v cmd/objdump: %v\n%s", exe, err, string(out))
	}
	return
}

var x86Need = []string{
	"fmthello.go:6",
	"TEXT main.main(SB)",
	"JMP main.main(SB)",
	"CALL fmt.Println(SB)",
	"RET",
}

var armNeed = []string{
	"fmthello.go:6",
	"TEXT main.main(SB)",
	"B.LS main.main(SB)",
	"BL fmt.Println(SB)",
	"RET",
}

// objdump is fully cross platform: it can handle binaries
// from any known operating system and architecture.
// We could in principle add binaries to testdata and check
// all the supported systems during this test. However, the
// binaries would be about 1 MB each, and we don't want to
// add that much junk to the hg repository. Instead, build a
// binary for the current system (only) and test that objdump
// can handle that one.

func testDisasm(t *testing.T, flags ...string) {
	tmp, exe := buildObjdump(t)
	defer os.RemoveAll(tmp)

	hello := filepath.Join(tmp, "hello.exe")
	args := []string{"build", "-o", hello}
	args = append(args, flags...)
	args = append(args, "testdata/fmthello.go")
	out, err := exec.Command("go", args...).CombinedOutput()
	if err != nil {
		t.Fatalf("go build fmthello.go: %v\n%s", err, out)
	}
	need := []string{
		"fmthello.go:6",
		"TEXT main.main(SB)",
	}
	switch runtime.GOARCH {
	case "amd64", "386":
		need = append(need, x86Need...)
	case "arm":
		need = append(need, armNeed...)
	}

	out, err = exec.Command(exe, "-s", "main.main", hello).CombinedOutput()
	if err != nil {
		t.Fatalf("objdump fmthello.exe: %v\n%s", err, out)
	}

	text := string(out)
	ok := true
	for _, s := range need {
		if !strings.Contains(text, s) {
			t.Errorf("disassembly missing '%s'", s)
			ok = false
		}
	}
	if !ok {
		t.Logf("full disassembly:\n%s", text)
	}
}

func TestDisasm(t *testing.T) {
	testDisasm(t)
}

func TestDisasmExtld(t *testing.T) {
	switch runtime.GOOS {
	case "plan9", "windows":
		t.Skipf("skipping on %s", runtime.GOOS)
	}
	testDisasm(t, "-ldflags=-linkmode=external")
}
<commit_msg>cmd/objdump: disable test failing on arm5<commit_after>// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import (
	"bufio"
	"bytes"
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"runtime"
	"strconv"
	"strings"
	"testing"
)

func loadSyms(t *testing.T) map[string]string {
	switch runtime.GOOS {
	case "android", "nacl":
		t.Skipf("skipping on %s", runtime.GOOS)
	}

	cmd := exec.Command("go", "tool", "nm", os.Args[0])
	out, err := cmd.CombinedOutput()
	if err != nil {
		t.Fatalf("go tool nm %v: %v\n%s", os.Args[0], err, string(out))
	}
	syms := make(map[string]string)
	scanner := bufio.NewScanner(bytes.NewReader(out))
	for scanner.Scan() {
		f := strings.Fields(scanner.Text())
		if len(f) < 3 {
			continue
		}
		syms[f[2]] = f[0]
	}
	if err := scanner.Err(); err != nil {
		t.Fatalf("error reading symbols: %v", err)
	}
	return syms
}

func runObjDump(t *testing.T, exe, startaddr, endaddr string) (path, lineno string) {
	switch runtime.GOOS {
	case "android", "nacl":
		t.Skipf("skipping on %s", runtime.GOOS)
	}

	cmd := exec.Command(exe, os.Args[0], startaddr, endaddr)
	out, err := cmd.CombinedOutput()
	if err != nil {
		t.Fatalf("go tool objdump %v: %v\n%s", os.Args[0], err, string(out))
	}
	f := strings.Split(string(out), "\n")
	if len(f) < 1 {
		t.Fatal("objdump output must have at least one line")
	}
	pathAndLineNo := f[0]
	f = strings.Split(pathAndLineNo, ":")
	if runtime.GOOS == "windows" {
		switch len(f) {
		case 2:
			return f[0], f[1]
		case 3:
			return f[0] + ":" + f[1], f[2]
		default:
			t.Fatalf("no line number found in %q", pathAndLineNo)
		}
	}
	if len(f) != 2 {
		t.Fatalf("no line number found in %q", pathAndLineNo)
	}
	return f[0], f[1]
}

func testObjDump(t *testing.T, exe, startaddr, endaddr string, line int) {
	srcPath, srcLineNo := runObjDump(t, exe, startaddr, endaddr)
	fi1, err := os.Stat("objdump_test.go")
	if err != nil {
		t.Fatalf("Stat failed: %v", err)
	}
	fi2, err := os.Stat(srcPath)
	if err != nil {
		t.Fatalf("Stat failed: %v", err)
	}
	if !os.SameFile(fi1, fi2) {
		t.Fatalf("objdump_test.go and %s are not same file", srcPath)
	}
	if srcLineNo != fmt.Sprint(line) {
		t.Fatalf("line number = %v; want %d", srcLineNo, line)
	}
}

func TestObjDump(t *testing.T) {
	_, _, line, _ := runtime.Caller(0)
	syms := loadSyms(t)

	tmp, exe := buildObjdump(t)
	defer os.RemoveAll(tmp)

	startaddr := syms["cmd/objdump.TestObjDump"]
	addr, err := strconv.ParseUint(startaddr, 16, 64)
	if err != nil {
		t.Fatalf("invalid start address %v: %v", startaddr, err)
	}
	endaddr := fmt.Sprintf("%x", addr+10)
	testObjDump(t, exe, startaddr, endaddr, line-1)
	testObjDump(t, exe, "0x"+startaddr, "0x"+endaddr, line-1)
}

func buildObjdump(t *testing.T) (tmp, exe string) {
	switch runtime.GOOS {
	case "android", "nacl":
		t.Skipf("skipping on %s", runtime.GOOS)
	}

	tmp, err := ioutil.TempDir("", "TestObjDump")
	if err != nil {
		t.Fatal("TempDir failed: ", err)
	}

	exe = filepath.Join(tmp, "testobjdump.exe")
	out, err := exec.Command("go", "build", "-o", exe, "cmd/objdump").CombinedOutput()
	if err != nil {
		os.RemoveAll(tmp)
		t.Fatalf("go build -o %v cmd/objdump: %v\n%s", exe, err, string(out))
	}
	return
}

var x86Need = []string{
	"fmthello.go:6",
	"TEXT main.main(SB)",
	"JMP main.main(SB)",
	"CALL fmt.Println(SB)",
	"RET",
}

var armNeed = []string{
	"fmthello.go:6",
	"TEXT main.main(SB)",
	//"B.LS main.main(SB)", // TODO(rsc): restore; golang.org/issue/9021
	"BL fmt.Println(SB)",
	"RET",
}

// objdump is fully cross platform: it can handle binaries
// from any known operating system and architecture.
// We could in principle add binaries to testdata and check
// all the supported systems during this test. However, the
// binaries would be about 1 MB each, and we don't want to
// add that much junk to the hg repository. Instead, build a
// binary for the current system (only) and test that objdump
// can handle that one.

func testDisasm(t *testing.T, flags ...string) {
	tmp, exe := buildObjdump(t)
	defer os.RemoveAll(tmp)

	hello := filepath.Join(tmp, "hello.exe")
	args := []string{"build", "-o", hello}
	args = append(args, flags...)
	args = append(args, "testdata/fmthello.go")
	out, err := exec.Command("go", args...).CombinedOutput()
	if err != nil {
		t.Fatalf("go build fmthello.go: %v\n%s", err, out)
	}
	need := []string{
		"fmthello.go:6",
		"TEXT main.main(SB)",
	}
	switch runtime.GOARCH {
	case "amd64", "386":
		need = append(need, x86Need...)
	case "arm":
		need = append(need, armNeed...)
	}

	out, err = exec.Command(exe, "-s", "main.main", hello).CombinedOutput()
	if err != nil {
		t.Fatalf("objdump fmthello.exe: %v\n%s", err, out)
	}

	text := string(out)
	ok := true
	for _, s := range need {
		if !strings.Contains(text, s) {
			t.Errorf("disassembly missing '%s'", s)
			ok = false
		}
	}
	if !ok {
		t.Logf("full disassembly:\n%s", text)
	}
}

func TestDisasm(t *testing.T) {
	testDisasm(t)
}

func TestDisasmExtld(t *testing.T) {
	switch runtime.GOOS {
	case "plan9", "windows":
		t.Skipf("skipping on %s", runtime.GOOS)
	}
	testDisasm(t, "-ldflags=-linkmode=external")
}
<|endoftext|>


<commit_before>package search

import (
	"testing"

	"sort"

	"github.com/Goita/go-goita/goita"
)

func TestSolve(t *testing.T) {
	board := goita.ParseBoard("11244556,12234569,11123378,11113457,s3,371,411,115,2p,3p,4p,145,252,3p,4p,124,2p")
	ret := Solve(board)
	sort.Slice(ret, func(i, j int) bool {
		return ret[i].Move.OrderKey() < ret[j].Move.OrderKey()
	})
	if len(ret) != 4 || ret[0].Score != -40 || ret[1].Score != -40 || ret[2].Score != -50 || ret[3].Score != -40 {
		t.Errorf("search.Solve() = %v, want [p:-40] [81:-40] [82:-50] [83:-40]", ret)
	}
	//[[p:-40 -> 3p,443,1p,2p,3p,415,1p,2p,3p,417] [81:-40 -> 381,413,1p,2p,3p,454,1p,2p,3p,417] [82:-50 -> 382,4p,1p,2p,311,413,1p,232,3p,4p,1p,264,3p,4p,1p,218] [83:-40 -> 383,4p,1p,2p,311,413,1p,234,3p,4p,1p,261,3p,415,1p,2p,3p,447]]
}

func BenchmarkSolve(b *testing.B) {
	board := goita.ParseBoard("11244556,12234569,11123378,11113457,s3,371,411,115,2p,3p,4p,145,252,3p,4p,124,2p")
	for i := 0; i < b.N; i++ {
		Solve(board)
	}
	// fmt.Println(ret)
}
<commit_msg>fix: import cycle<commit_after>package search

import (
	"fmt"
	"testing"

	"github.com/Goita/go-goita/goita"
)

func TestSolve(t *testing.T) {
	board := goita.ParseBoard("11244556,12234569,11123378,11113457,s3,371,411,115,2p,3p,4p,145,252,3p,4p,124,2p")
	ret := Solve(board)
	moves := board.GetPossibleMoves()
	results := make([]*EvaluatedMove, 0, len(moves))
	for r := range ret {
		results = append(results, r)
		fmt.Printf("move:[%v] score:[%v] %v\n\n", r.Move, r.Score, r.History.History(board.Turn))
	}
	if len(results) != 4 || results[0].Score != -40 || results[1].Score != -40 || results[2].Score != -50 || results[3].Score != -40 {
		t.Errorf("search.Solve() = %v, want [p:-40] [81:-40] [82:-50] [83:-40]", ret)
	}
	//[[p:-40 -> 3p,443,1p,2p,3p,415,1p,2p,3p,417] [81:-40 -> 381,413,1p,2p,3p,454,1p,2p,3p,417] [82:-50 -> 382,4p,1p,2p,311,413,1p,232,3p,4p,1p,264,3p,4p,1p,218] [83:-40 -> 383,4p,1p,2p,311,413,1p,234,3p,4p,1p,261,3p,415,1p,2p,3p,447]]
}

func BenchmarkSolve(b *testing.B) {
	board := goita.ParseBoard("11244556,12234569,11123378,11113457,s3,371,411,115,2p,3p,4p,145,252,3p,4p,124,2p")
	for i := 0; i < b.N; i++ {
		Solve(board)
	}
	// fmt.Println(ret)
}
<|endoftext|>


<commit_before>package server

import (
	"testing"

	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/suite"
	"github.com/garyburd/redigo/redis"

	"warcluster/entities/db"
)

const (
	user        = "{\"Command\": \"login\", \"Username\": \"JohnDoe\", \"TwitterId\": \"some twitter ID\"}"
	setupParams = "{\"Command\": \"setup_parameters\", \"Fraction\": 0, \"SunTextureId\": 0}"
)

type ClientTestSuite struct {
    suite.Suite
    conn redis.Conn
    session *testSession
}

func (suite *ClientTestSuite) SetupTest() {
    suite.conn = db.Pool.Get()
	suite.conn.Do("FLUSHDB")
	suite.session = new(testSession)
}

func (suite *ClientTestSuite) TearDownTest() {
	suite.conn.Close()
}

func (suite *ClientTestSuite) TestRegisterNewUser() {
	suite.session.Send([]byte(user))
	suite.session.Send([]byte(setupParams))

	players_before, err := redis.Strings(suite.conn.Do("KEYS", "player.*"))
	before := len(players_before)

	_, err = authenticate(suite.session)

	assert.Nil(suite.T(), err)

	players_after, err := redis.Strings(suite.conn.Do("KEYS", "player.*"))
	after := len(players_after)

	assert.Nil(suite.T(), err)

	assert.Equal(suite.T(), before + 1, after)
}

func (suite *ClientTestSuite) TestAuthenticateExcistingUser() {
	suite.session.Send([]byte(user))
	suite.session.Send([]byte(setupParams))
	suite.session.Send([]byte(user))

	players_before, err := redis.Strings(suite.conn.Do("KEYS", "player.*"))
	before := len(players_before)

	authenticate(suite.session)
	authenticate(suite.session)

	players_after, err := redis.Strings(suite.conn.Do("KEYS", "player.*"))
	after := len(players_after)

	assert.Nil(suite.T(), err)

	assert.Equal(suite.T(), before + 1, after)
}

func (suite *ClientTestSuite) TestAuthenticateUserWithIncompleteData() {
	suite.session.Send([]byte("{\"Command\": \"login\", \"TwitterId\": \"some twitter ID\"}"))

	players_before, err := redis.Strings(suite.conn.Do("KEYS", "player.*"))
	before := len(players_before)

	authenticate(suite.session)

	players_after, err := redis.Strings(suite.conn.Do("KEYS", "player.*"))
	after := len(players_after)

	assert.Nil(suite.T(), err)

	assert.Equal(suite.T(), before, after)
}

func (suite *ClientTestSuite) TestAuthenticateUserWithNilData() {
	suite.session.Send(nil)
	_, err := authenticate(suite.session)

	assert.NotNil(suite.T(), err)
}

func (suite *ClientTestSuite) TestAuthenticateUserWithInvalidJSONData() {
	suite.session.Send([]byte("panda"))
	_, err := authenticate(suite.session)

	assert.NotNil(suite.T(), err)
}

func (suite *ClientTestSuite) TestAuthenticateUserWithNilSetupData() {
	suite.session.Send([]byte(user))
	suite.session.Send(nil)
	_, err := authenticate(suite.session)

	assert.NotNil(suite.T(), err)
}

func TestClientTestSuite (t *testing.T) {
    suite.Run(t, new(ClientTestSuite))
}
<commit_msg>Gofmt<commit_after>package server

import (
	"testing"

	"github.com/garyburd/redigo/redis"
	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/suite"

	"warcluster/entities/db"
)

const (
	user        = "{\"Command\": \"login\", \"Username\": \"JohnDoe\", \"TwitterId\": \"some twitter ID\"}"
	setupParams = "{\"Command\": \"setup_parameters\", \"Fraction\": 0, \"SunTextureId\": 0}"
)

type ClientTestSuite struct {
	suite.Suite
	conn    redis.Conn
	session *testSession
}

func (suite *ClientTestSuite) SetupTest() {
	suite.conn = db.Pool.Get()
	suite.conn.Do("FLUSHDB")
	suite.session = new(testSession)
}

func (suite *ClientTestSuite) TearDownTest() {
	suite.conn.Close()
}

func (suite *ClientTestSuite) TestRegisterNewUser() {
	suite.session.Send([]byte(user))
	suite.session.Send([]byte(setupParams))

	players_before, err := redis.Strings(suite.conn.Do("KEYS", "player.*"))
	before := len(players_before)

	_, err = authenticate(suite.session)

	assert.Nil(suite.T(), err)

	players_after, err := redis.Strings(suite.conn.Do("KEYS", "player.*"))
	after := len(players_after)

	assert.Nil(suite.T(), err)

	assert.Equal(suite.T(), before+1, after)
}

func (suite *ClientTestSuite) TestAuthenticateExcistingUser() {
	suite.session.Send([]byte(user))
	suite.session.Send([]byte(setupParams))
	suite.session.Send([]byte(user))

	players_before, err := redis.Strings(suite.conn.Do("KEYS", "player.*"))
	before := len(players_before)

	authenticate(suite.session)
	authenticate(suite.session)

	players_after, err := redis.Strings(suite.conn.Do("KEYS", "player.*"))
	after := len(players_after)

	assert.Nil(suite.T(), err)

	assert.Equal(suite.T(), before+1, after)
}

func (suite *ClientTestSuite) TestAuthenticateUserWithIncompleteData() {
	suite.session.Send([]byte("{\"Command\": \"login\", \"TwitterId\": \"some twitter ID\"}"))

	players_before, err := redis.Strings(suite.conn.Do("KEYS", "player.*"))
	before := len(players_before)

	authenticate(suite.session)

	players_after, err := redis.Strings(suite.conn.Do("KEYS", "player.*"))
	after := len(players_after)

	assert.Nil(suite.T(), err)

	assert.Equal(suite.T(), before, after)
}

func (suite *ClientTestSuite) TestAuthenticateUserWithNilData() {
	suite.session.Send(nil)
	_, err := authenticate(suite.session)

	assert.NotNil(suite.T(), err)
}

func (suite *ClientTestSuite) TestAuthenticateUserWithInvalidJSONData() {
	suite.session.Send([]byte("panda"))
	_, err := authenticate(suite.session)

	assert.NotNil(suite.T(), err)
}

func (suite *ClientTestSuite) TestAuthenticateUserWithNilSetupData() {
	suite.session.Send([]byte(user))
	suite.session.Send(nil)
	_, err := authenticate(suite.session)

	assert.NotNil(suite.T(), err)
}

func TestClientTestSuite(t *testing.T) {
	suite.Run(t, new(ClientTestSuite))
}
<|endoftext|>


<commit_before>package installer

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"strings"

	"github.com/tsuru/tsuru-client/tsuru/installer/dm"
)

var defaultCompose = `
version: "3"

services:
  redis:
    image: redis:latest
    networks:
      - tsuru
    volumes:
      - redis-data:/data/db

  mongo:
    image: mongo:latest
    networks:
      - tsuru
    volumes:
      - mongo-data:/data

  planb:
    image: tsuru/planb:latest
    command: --listen :8080 --read-redis-host redis --write-redis-host redis
    ports:
      - 80:8080
    networks:
      - tsuru
    depends_on:
      - redis

  registry:
    image: registry:2
    environment:
      - "REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY=/var/lib/registry"
      - "REGISTRY_HTTP_TLS_CERTIFICATE=/certs/{{CLUSTER_ADDR}}:5000/registry-cert.pem"
      - "REGISTRY_HTTP_TLS_KEY=/certs/{{CLUSTER_ADDR}}:5000/registry-key.pem"
    volumes:
      - "/etc/docker/certs.d:/certs:ro"
      - registry-data:/var/lib/registry
    ports:
      - 5000:5000
    networks:
      - tsuru

  tsuru:
    image: tsuru/api:v1
    volumes:
      - "/etc/docker/certs.d:/certs:ro"
    ports:
      - 8080:8080
    networks:
      - tsuru
    depends_on:
      - redis
      - mongo
      - registry
      - planb
    environment:
      - MONGODB_ADDR=mongo
      - MONGODB_PORT=27017
      - REDIS_ADDR=redis
      - REDIS_PORT=6379
      - HIPACHE_DOMAIN={{CLUSTER_ADDR}}.nip.io
      - REGISTRY_ADDR={{CLUSTER_PRIVATE_ADDR}}
      - REGISTRY_PORT=5000
      - TSURU_ADDR=http://{{CLUSTER_ADDR}}
      - TSURU_PORT=8080
      - IAAS_CONF={{IAAS_CONF}}

networks:
  tsuru:
    driver: overlay
    ipam:
      driver: default
      config:
        - subnet: 10.0.9.0/24

volumes:
  mongo-data:
  redis-data:
  registry-data:
`

func resolveConfig(baseConfig string, customConfigs map[string]string) (string, error) {
	if baseConfig == "" {
		baseConfig = defaultCompose
	} else {
		b, err := ioutil.ReadFile(baseConfig)
		if err != nil {
			return "", err
		}
		baseConfig = string(b)
	}
	for k, v := range customConfigs {
		if v != "" {
			baseConfig = strings.Replace(baseConfig, fmt.Sprintf("{{%s}}", k), v, -1)
		}
	}
	return baseConfig, nil
}

func composeDeploy(c ServiceCluster, installConfig *InstallOpts) error {
	componentsConfig := installConfig.ComponentsConfig
	manager := c.GetManager()
	componentsConfig.IaaSConfig.Dockermachine.InsecureRegistry = fmt.Sprintf("%s:5000", dm.GetPrivateIP(manager))
	iaasConfig, err := json.Marshal(componentsConfig.IaaSConfig)
	if err != nil {
		return fmt.Errorf("failed to marshal iaas config: %s", err)
	}
	configs := map[string]string{
		"CLUSTER_ADDR":         manager.Base.Address,
		"CLUSTER_PRIVATE_ADDR": dm.GetPrivateIP(manager),
		"IAAS_CONF":            string(iaasConfig),
	}
	config, err := resolveConfig(installConfig.ComposeFile, configs)
	if err != nil {
		return err
	}
	remoteWriteCmdFmt := "printf '%%s' '%s' | sudo tee %s"
	_, err = manager.Host.RunSSHCommand(fmt.Sprintf(remoteWriteCmdFmt, config, "/tmp/compose.yml"))
	if err != nil {
		return fmt.Errorf("failed to write remote file: %s", err)
	}
	fmt.Printf("Deploying compose file in cluster manager....\n")
	output, err := manager.Host.RunSSHCommand("sudo docker deploy -c /tmp/compose.yml tsuru")
	if err != nil {
		return err
	}
	fmt.Printf(output)
	return nil
}
<commit_msg>installer: use private IP for registry certificate<commit_after>package installer

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"strings"

	"github.com/tsuru/tsuru-client/tsuru/installer/dm"
)

var defaultCompose = `
version: "3"

services:
  redis:
    image: redis:latest
    networks:
      - tsuru
    volumes:
      - redis-data:/data/db

  mongo:
    image: mongo:latest
    networks:
      - tsuru
    volumes:
      - mongo-data:/data

  planb:
    image: tsuru/planb:latest
    command: --listen :8080 --read-redis-host redis --write-redis-host redis
    ports:
      - 80:8080
    networks:
      - tsuru
    depends_on:
      - redis

  registry:
    image: registry:2
    environment:
      - "REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY=/var/lib/registry"
      - "REGISTRY_HTTP_TLS_CERTIFICATE=/certs/{{CLUSTER_PRIVATE_ADDR}}:5000/registry-cert.pem"
      - "REGISTRY_HTTP_TLS_KEY=/certs/{{CLUSTER_PRIVATE_ADDR}}:5000/registry-key.pem"
    volumes:
      - "/etc/docker/certs.d:/certs:ro"
      - registry-data:/var/lib/registry
    ports:
      - 5000:5000
    networks:
      - tsuru

  tsuru:
    image: tsuru/api:v1
    volumes:
      - "/etc/docker/certs.d:/certs:ro"
    ports:
      - 8080:8080
    networks:
      - tsuru
    depends_on:
      - redis
      - mongo
      - registry
      - planb
    environment:
      - MONGODB_ADDR=mongo
      - MONGODB_PORT=27017
      - REDIS_ADDR=redis
      - REDIS_PORT=6379
      - HIPACHE_DOMAIN={{CLUSTER_ADDR}}.nip.io
      - REGISTRY_ADDR={{CLUSTER_PRIVATE_ADDR}}
      - REGISTRY_PORT=5000
      - TSURU_ADDR=http://{{CLUSTER_ADDR}}
      - TSURU_PORT=8080
      - IAAS_CONF={{IAAS_CONF}}

networks:
  tsuru:
    driver: overlay
    ipam:
      driver: default
      config:
        - subnet: 10.0.9.0/24

volumes:
  mongo-data:
  redis-data:
  registry-data:
`

func resolveConfig(baseConfig string, customConfigs map[string]string) (string, error) {
	if baseConfig == "" {
		baseConfig = defaultCompose
	} else {
		b, err := ioutil.ReadFile(baseConfig)
		if err != nil {
			return "", err
		}
		baseConfig = string(b)
	}
	for k, v := range customConfigs {
		if v != "" {
			baseConfig = strings.Replace(baseConfig, fmt.Sprintf("{{%s}}", k), v, -1)
		}
	}
	return baseConfig, nil
}

func composeDeploy(c ServiceCluster, installConfig *InstallOpts) error {
	componentsConfig := installConfig.ComponentsConfig
	manager := c.GetManager()
	componentsConfig.IaaSConfig.Dockermachine.InsecureRegistry = fmt.Sprintf("%s:5000", dm.GetPrivateIP(manager))
	iaasConfig, err := json.Marshal(componentsConfig.IaaSConfig)
	if err != nil {
		return fmt.Errorf("failed to marshal iaas config: %s", err)
	}
	configs := map[string]string{
		"CLUSTER_ADDR":         manager.Base.Address,
		"CLUSTER_PRIVATE_ADDR": dm.GetPrivateIP(manager),
		"IAAS_CONF":            string(iaasConfig),
	}
	config, err := resolveConfig(installConfig.ComposeFile, configs)
	if err != nil {
		return err
	}
	remoteWriteCmdFmt := "printf '%%s' '%s' | sudo tee %s"
	_, err = manager.Host.RunSSHCommand(fmt.Sprintf(remoteWriteCmdFmt, config, "/tmp/compose.yml"))
	if err != nil {
		return fmt.Errorf("failed to write remote file: %s", err)
	}
	fmt.Printf("Deploying compose file in cluster manager....\n")
	output, err := manager.Host.RunSSHCommand("sudo docker deploy -c /tmp/compose.yml tsuru")
	if err != nil {
		return err
	}
	fmt.Printf(output)
	return nil
}
<|endoftext|>