<commit_before>/*
Copyright 2016 The Kubernetes Authors 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.
*/

package main

import (
	"encoding/json"
 	"fmt"

	"github.com/golang/glog"
	"github.com/prometheus/client_golang/prometheus"
	"golang.org/x/net/context"
	"k8s.io/client-go/kubernetes"
	"k8s.io/client-go/pkg/api"
	"k8s.io/client-go/pkg/api/v1"
	"k8s.io/client-go/tools/cache"
)

var (
	descPodInfo = prometheus.NewDesc(
		"kube_pod_info",
		"Information about pod.",
		[]string{"namespace", "pod", "host_ip", "pod_ip", "node", "controllers"}, nil,
	)
	descPodStatusPhase = prometheus.NewDesc(
		"kube_pod_status_phase",
		"The pods current phase.",
		[]string{"namespace", "pod", "phase"}, nil,
	)
	descPodStatusReady = prometheus.NewDesc(
		"kube_pod_status_ready",
		"Describes whether the pod is ready to serve requests.",
		[]string{"namespace", "pod", "condition"}, nil,
	)
	descPodStatusScheduled = prometheus.NewDesc(
		"kube_pod_status_scheduled",
		"Describes the status of the scheduling process for the pod.",
		[]string{"namespace", "pod", "condition"}, nil,
	)
	descPodContainerInfo = prometheus.NewDesc(
		"kube_pod_container_info",
		"Information about a container in a pod.",
		[]string{"namespace", "pod", "container", "image", "image_id", "container_id"}, nil,
	)
	descPodContainerStatusWaiting = prometheus.NewDesc(
		"kube_pod_container_status_waiting",
		"Describes whether the container is currently in waiting state.",
		[]string{"namespace", "pod", "container"}, nil,
	)
	descPodContainerStatusRunning = prometheus.NewDesc(
		"kube_pod_container_status_running",
		"Describes whether the container is currently in running state.",
		[]string{"namespace", "pod", "container"}, nil,
	)
	descPodContainerStatusTerminated = prometheus.NewDesc(
		"kube_pod_container_status_terminated",
		"Describes whether the container is currently in terminated state.",
		[]string{"namespace", "pod", "container"}, nil,
	)
	descPodContainerStatusReady = prometheus.NewDesc(
		"kube_pod_container_status_ready",
		"Describes whether the containers readiness check succeeded.",
		[]string{"namespace", "pod", "container"}, nil,
	)
	descPodContainerStatusRestarts = prometheus.NewDesc(
		"kube_pod_container_status_restarts",
		"The number of container restarts per container.",
		[]string{"namespace", "pod", "container"}, nil,
	)

	descPodContainerResourceRequestsCpuCores = prometheus.NewDesc(
		"kube_pod_container_resource_requests_cpu_cores",
		"The number of requested cpu cores by a container.",
		[]string{"namespace", "pod", "container", "node"}, nil,
	)

	descPodContainerResourceRequestsMemoryBytes = prometheus.NewDesc(
		"kube_pod_container_resource_requests_memory_bytes",
		"The number of requested memory bytes  by a container.",
		[]string{"namespace", "pod", "container", "node"}, nil,
	)

	descPodContainerResourceLimitsCpuCores = prometheus.NewDesc(
		"kube_pod_container_resource_limits_cpu_cores",
		"The limit on cpu cores to be used by a container.",
		[]string{"namespace", "pod", "container", "node"}, nil,
	)

	descPodContainerResourceLimitsMemoryBytes = prometheus.NewDesc(
		"kube_pod_container_resource_limits_memory_bytes",
		"The limit on memory to be used by a container in bytes.",
		[]string{"namespace", "pod", "container", "node"}, nil,
	)
)

type PodLister func() ([]v1.Pod, error)

func (l PodLister) List() ([]v1.Pod, error) {
	return l()
}

func RegisterPodCollector(registry prometheus.Registerer, kubeClient kubernetes.Interface) {
	client := kubeClient.CoreV1().RESTClient()
	plw := cache.NewListWatchFromClient(client, "pods", api.NamespaceAll, nil)
	pinf := cache.NewSharedInformer(plw, &v1.Pod{}, resyncPeriod)

	podLister := PodLister(func() (pods []v1.Pod, err error) {
		for _, m := range pinf.GetStore().List() {
			pods = append(pods, *m.(*v1.Pod))
		}
		return pods, nil
	})

	registry.MustRegister(&podCollector{store: podLister})
	go pinf.Run(context.Background().Done())
}

type podStore interface {
	List() (pods []v1.Pod, err error)
}

// podCollector collects metrics about all pods in the cluster.
type podCollector struct {
	store podStore
}

// Describe implements the prometheus.Collector interface.
func (pc *podCollector) Describe(ch chan<- *prometheus.Desc) {
	ch <- descPodInfo
	ch <- descPodStatusPhase
	ch <- descPodStatusReady
	ch <- descPodStatusScheduled
	ch <- descPodContainerInfo
	ch <- descPodContainerStatusWaiting
	ch <- descPodContainerStatusRunning
	ch <- descPodContainerStatusTerminated
	ch <- descPodContainerStatusReady
	ch <- descPodContainerStatusRestarts
	ch <- descPodContainerResourceRequestsCpuCores
	ch <- descPodContainerResourceRequestsMemoryBytes
	ch <- descPodContainerResourceLimitsCpuCores
	ch <- descPodContainerResourceLimitsMemoryBytes
}

func printControllers(annotation map[string]string) string {
	value, ok := annotation[api.CreatedByAnnotation]
	if ok {
		var r api.SerializedReference
		err := json.Unmarshal([]byte(value), &r)
		if err == nil {
			return fmt.Sprintf("%s/%s", r.Reference.Kind, r.Reference.Name)
		}
	}
	return "<none>"
}

// Collect implements the prometheus.Collector interface.
func (pc *podCollector) Collect(ch chan<- prometheus.Metric) {
	pods, err := pc.store.List()
	if err != nil {
		glog.Errorf("listing pods failed: %s", err)
		return
	}
	for _, p := range pods {
		pc.collectPod(ch, p)
	}
}

func (pc *podCollector) collectPod(ch chan<- prometheus.Metric, p v1.Pod) {
	nodeName := p.Spec.NodeName
	addConstMetric := func(desc *prometheus.Desc, t prometheus.ValueType, v float64, lv ...string) {
		lv = append([]string{p.Namespace, p.Name}, lv...)
		ch <- prometheus.MustNewConstMetric(desc, t, v, lv...)
	}
	addGauge := func(desc *prometheus.Desc, v float64, lv ...string) {
		addConstMetric(desc, prometheus.GaugeValue, v, lv...)
	}
	addCounter := func(desc *prometheus.Desc, v float64, lv ...string) {
		addConstMetric(desc, prometheus.CounterValue, v, lv...)
	}

	addGauge(descPodInfo, 1, p.Status.HostIP, p.Status.PodIP, nodeName, printControllers(p.Annotations))
	addGauge(descPodStatusPhase, 1, string(p.Status.Phase))

	for _, c := range p.Status.Conditions {
		switch c.Type {
		case v1.PodReady:
			addConditionMetrics(ch, descPodStatusReady, c.Status, p.Namespace, p.Name)
		case v1.PodScheduled:
			addConditionMetrics(ch, descPodStatusScheduled, c.Status, p.Namespace, p.Name)
		}
	}

	for _, cs := range p.Status.ContainerStatuses {
		addGauge(descPodContainerInfo, 1,
			cs.Name, cs.Image, cs.ImageID, cs.ContainerID,
		)
		addGauge(descPodContainerStatusWaiting, boolFloat64(cs.State.Waiting != nil), cs.Name)
		addGauge(descPodContainerStatusRunning, boolFloat64(cs.State.Running != nil), cs.Name)
		addGauge(descPodContainerStatusTerminated, boolFloat64(cs.State.Terminated != nil), cs.Name)
		addGauge(descPodContainerStatusReady, boolFloat64(cs.Ready), cs.Name)
		addCounter(descPodContainerStatusRestarts, float64(cs.RestartCount), cs.Name)
	}

	for _, c := range p.Spec.Containers {
		req := c.Resources.Requests
		lim := c.Resources.Limits

		if cpu, ok := req[v1.ResourceCPU]; ok {
			addGauge(descPodContainerResourceRequestsCpuCores, float64(cpu.MilliValue())/1000,
				c.Name, nodeName)
		}
		if mem, ok := req[v1.ResourceMemory]; ok {
			addGauge(descPodContainerResourceRequestsMemoryBytes, float64(mem.Value()),
				c.Name, nodeName)
		}

		if cpu, ok := lim[v1.ResourceCPU]; ok {
			addGauge(descPodContainerResourceLimitsCpuCores, float64(cpu.MilliValue())/1000,
				c.Name, nodeName)
		}
		if mem, ok := lim[v1.ResourceMemory]; ok {
			addGauge(descPodContainerResourceLimitsMemoryBytes, float64(mem.Value()),
				c.Name, nodeName)
		}
	}
}
<commit_msg>make kube_pod_info be clearer<commit_after>/*
Copyright 2016 The Kubernetes Authors 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.
*/

package main

import (
	"encoding/json"
 	"fmt"

	"github.com/golang/glog"
	"github.com/prometheus/client_golang/prometheus"
	"golang.org/x/net/context"
	"k8s.io/client-go/kubernetes"
	"k8s.io/client-go/pkg/api"
	"k8s.io/client-go/pkg/api/v1"
	"k8s.io/client-go/tools/cache"
)

var (
	descPodInfo = prometheus.NewDesc(
		"kube_pod_info",
		"Information about pod.",
		[]string{"namespace", "pod", "host_ip", "pod_ip", "node", "created_by"}, nil,
	)
	descPodStatusPhase = prometheus.NewDesc(
		"kube_pod_status_phase",
		"The pods current phase.",
		[]string{"namespace", "pod", "phase"}, nil,
	)
	descPodStatusReady = prometheus.NewDesc(
		"kube_pod_status_ready",
		"Describes whether the pod is ready to serve requests.",
		[]string{"namespace", "pod", "condition"}, nil,
	)
	descPodStatusScheduled = prometheus.NewDesc(
		"kube_pod_status_scheduled",
		"Describes the status of the scheduling process for the pod.",
		[]string{"namespace", "pod", "condition"}, nil,
	)
	descPodContainerInfo = prometheus.NewDesc(
		"kube_pod_container_info",
		"Information about a container in a pod.",
		[]string{"namespace", "pod", "container", "image", "image_id", "container_id"}, nil,
	)
	descPodContainerStatusWaiting = prometheus.NewDesc(
		"kube_pod_container_status_waiting",
		"Describes whether the container is currently in waiting state.",
		[]string{"namespace", "pod", "container"}, nil,
	)
	descPodContainerStatusRunning = prometheus.NewDesc(
		"kube_pod_container_status_running",
		"Describes whether the container is currently in running state.",
		[]string{"namespace", "pod", "container"}, nil,
	)
	descPodContainerStatusTerminated = prometheus.NewDesc(
		"kube_pod_container_status_terminated",
		"Describes whether the container is currently in terminated state.",
		[]string{"namespace", "pod", "container"}, nil,
	)
	descPodContainerStatusReady = prometheus.NewDesc(
		"kube_pod_container_status_ready",
		"Describes whether the containers readiness check succeeded.",
		[]string{"namespace", "pod", "container"}, nil,
	)
	descPodContainerStatusRestarts = prometheus.NewDesc(
		"kube_pod_container_status_restarts",
		"The number of container restarts per container.",
		[]string{"namespace", "pod", "container"}, nil,
	)

	descPodContainerResourceRequestsCpuCores = prometheus.NewDesc(
		"kube_pod_container_resource_requests_cpu_cores",
		"The number of requested cpu cores by a container.",
		[]string{"namespace", "pod", "container", "node"}, nil,
	)

	descPodContainerResourceRequestsMemoryBytes = prometheus.NewDesc(
		"kube_pod_container_resource_requests_memory_bytes",
		"The number of requested memory bytes  by a container.",
		[]string{"namespace", "pod", "container", "node"}, nil,
	)

	descPodContainerResourceLimitsCpuCores = prometheus.NewDesc(
		"kube_pod_container_resource_limits_cpu_cores",
		"The limit on cpu cores to be used by a container.",
		[]string{"namespace", "pod", "container", "node"}, nil,
	)

	descPodContainerResourceLimitsMemoryBytes = prometheus.NewDesc(
		"kube_pod_container_resource_limits_memory_bytes",
		"The limit on memory to be used by a container in bytes.",
		[]string{"namespace", "pod", "container", "node"}, nil,
	)
)

type PodLister func() ([]v1.Pod, error)

func (l PodLister) List() ([]v1.Pod, error) {
	return l()
}

func RegisterPodCollector(registry prometheus.Registerer, kubeClient kubernetes.Interface) {
	client := kubeClient.CoreV1().RESTClient()
	plw := cache.NewListWatchFromClient(client, "pods", api.NamespaceAll, nil)
	pinf := cache.NewSharedInformer(plw, &v1.Pod{}, resyncPeriod)

	podLister := PodLister(func() (pods []v1.Pod, err error) {
		for _, m := range pinf.GetStore().List() {
			pods = append(pods, *m.(*v1.Pod))
		}
		return pods, nil
	})

	registry.MustRegister(&podCollector{store: podLister})
	go pinf.Run(context.Background().Done())
}

type podStore interface {
	List() (pods []v1.Pod, err error)
}

// podCollector collects metrics about all pods in the cluster.
type podCollector struct {
	store podStore
}

// Describe implements the prometheus.Collector interface.
func (pc *podCollector) Describe(ch chan<- *prometheus.Desc) {
	ch <- descPodInfo
	ch <- descPodStatusPhase
	ch <- descPodStatusReady
	ch <- descPodStatusScheduled
	ch <- descPodContainerInfo
	ch <- descPodContainerStatusWaiting
	ch <- descPodContainerStatusRunning
	ch <- descPodContainerStatusTerminated
	ch <- descPodContainerStatusReady
	ch <- descPodContainerStatusRestarts
	ch <- descPodContainerResourceRequestsCpuCores
	ch <- descPodContainerResourceRequestsMemoryBytes
	ch <- descPodContainerResourceLimitsCpuCores
	ch <- descPodContainerResourceLimitsMemoryBytes
}

func extractCreatedBy(annotation map[string]string) string {
	value, ok := annotation[api.CreatedByAnnotation]
	if ok {
		var r api.SerializedReference
		err := json.Unmarshal([]byte(value), &r)
		if err == nil {
			return fmt.Sprintf("%s/%s", r.Reference.Kind, r.Reference.Name)
		}
	}
	return "<none>"
}

// Collect implements the prometheus.Collector interface.
func (pc *podCollector) Collect(ch chan<- prometheus.Metric) {
	pods, err := pc.store.List()
	if err != nil {
		glog.Errorf("listing pods failed: %s", err)
		return
	}
	for _, p := range pods {
		pc.collectPod(ch, p)
	}
}

func (pc *podCollector) collectPod(ch chan<- prometheus.Metric, p v1.Pod) {
	nodeName := p.Spec.NodeName
	addConstMetric := func(desc *prometheus.Desc, t prometheus.ValueType, v float64, lv ...string) {
		lv = append([]string{p.Namespace, p.Name}, lv...)
		ch <- prometheus.MustNewConstMetric(desc, t, v, lv...)
	}
	addGauge := func(desc *prometheus.Desc, v float64, lv ...string) {
		addConstMetric(desc, prometheus.GaugeValue, v, lv...)
	}
	addCounter := func(desc *prometheus.Desc, v float64, lv ...string) {
		addConstMetric(desc, prometheus.CounterValue, v, lv...)
	}

	addGauge(descPodInfo, 1, p.Status.HostIP, p.Status.PodIP, nodeName, extractCreatedBy(p.Annotations))
	addGauge(descPodStatusPhase, 1, string(p.Status.Phase))

	for _, c := range p.Status.Conditions {
		switch c.Type {
		case v1.PodReady:
			addConditionMetrics(ch, descPodStatusReady, c.Status, p.Namespace, p.Name)
		case v1.PodScheduled:
			addConditionMetrics(ch, descPodStatusScheduled, c.Status, p.Namespace, p.Name)
		}
	}

	for _, cs := range p.Status.ContainerStatuses {
		addGauge(descPodContainerInfo, 1,
			cs.Name, cs.Image, cs.ImageID, cs.ContainerID,
		)
		addGauge(descPodContainerStatusWaiting, boolFloat64(cs.State.Waiting != nil), cs.Name)
		addGauge(descPodContainerStatusRunning, boolFloat64(cs.State.Running != nil), cs.Name)
		addGauge(descPodContainerStatusTerminated, boolFloat64(cs.State.Terminated != nil), cs.Name)
		addGauge(descPodContainerStatusReady, boolFloat64(cs.Ready), cs.Name)
		addCounter(descPodContainerStatusRestarts, float64(cs.RestartCount), cs.Name)
	}

	for _, c := range p.Spec.Containers {
		req := c.Resources.Requests
		lim := c.Resources.Limits

		if cpu, ok := req[v1.ResourceCPU]; ok {
			addGauge(descPodContainerResourceRequestsCpuCores, float64(cpu.MilliValue())/1000,
				c.Name, nodeName)
		}
		if mem, ok := req[v1.ResourceMemory]; ok {
			addGauge(descPodContainerResourceRequestsMemoryBytes, float64(mem.Value()),
				c.Name, nodeName)
		}

		if cpu, ok := lim[v1.ResourceCPU]; ok {
			addGauge(descPodContainerResourceLimitsCpuCores, float64(cpu.MilliValue())/1000,
				c.Name, nodeName)
		}
		if mem, ok := lim[v1.ResourceMemory]; ok {
			addGauge(descPodContainerResourceLimitsMemoryBytes, float64(mem.Value()),
				c.Name, nodeName)
		}
	}
}
<|endoftext|>


<commit_before>package user

import (
	"sync"
	"time"

	"github.com/v2ray/v2ray-core/common/collect"
	"github.com/v2ray/v2ray-core/proxy/vmess/config"
)

const (
	updateIntervalSec = 10
	cacheDurationSec  = 120
)

type UserSet interface {
	AddUser(user config.User) error
	GetUser(timeHash []byte) (config.User, int64, bool)
}

type TimedUserSet struct {
	validUsers          []config.User
	userHash            map[string]indexTimePair
	userHashDeleteQueue *collect.TimedQueue
	access              sync.RWMutex
}

type indexTimePair struct {
	index   int
	timeSec int64
}

func NewTimedUserSet() UserSet {
	tus := &TimedUserSet{
		validUsers:          make([]config.User, 0, 16),
		userHash:            make(map[string]indexTimePair, 512),
		userHashDeleteQueue: collect.NewTimedQueue(updateIntervalSec),
		access:              sync.RWMutex{},
	}
	go tus.updateUserHash(time.Tick(updateIntervalSec * time.Second))
	go tus.removeEntries(tus.userHashDeleteQueue.RemovedEntries())
	return tus
}

func (us *TimedUserSet) removeEntries(entries <-chan interface{}) {
	for entry := range entries {
		us.access.Lock()
		delete(us.userHash, entry.(string))
		us.access.Unlock()
	}
}

func (us *TimedUserSet) generateNewHashes(lastSec, nowSec int64, idx int, id *config.ID) {
	idHash := NewTimeHash(HMACHash{})
	for lastSec < nowSec {
		idHash := idHash.Hash(id.Bytes[:], lastSec)
		us.access.Lock()
		us.userHash[string(idHash)] = indexTimePair{idx, lastSec}
		us.access.Unlock()
		us.userHashDeleteQueue.Add(string(idHash), lastSec+2*cacheDurationSec)
		lastSec++
	}
}

func (us *TimedUserSet) updateUserHash(tick <-chan time.Time) {
	lastSec := time.Now().Unix() - cacheDurationSec

	for now := range tick {
		nowSec := now.Unix() + cacheDurationSec
		for idx, user := range us.validUsers {
			us.generateNewHashes(lastSec, nowSec, idx, user.ID())
		}
		lastSec = nowSec
	}
}

func (us *TimedUserSet) AddUser(user config.User) error {
	id := user.ID()
	idx := len(us.validUsers)
	us.validUsers = append(us.validUsers, user)

	nowSec := time.Now().Unix()
	lastSec := nowSec - cacheDurationSec
	us.generateNewHashes(lastSec, nowSec+cacheDurationSec, idx, id)

	return nil
}

func (us TimedUserSet) GetUser(userHash []byte) (config.User, int64, bool) {
	defer us.access.RUnlock()
	us.access.RLock()
	pair, found := us.userHash[string(userHash)]
	if found {
		return us.validUsers[pair.index], pair.timeSec, true
	}
	return nil, 0, false
}
<commit_msg>FIx a bug that mutex is passed by value.<commit_after>package user

import (
	"sync"
	"time"

	"github.com/v2ray/v2ray-core/common/collect"
	"github.com/v2ray/v2ray-core/proxy/vmess/config"
)

const (
	updateIntervalSec = 10
	cacheDurationSec  = 120
)

type UserSet interface {
	AddUser(user config.User) error
	GetUser(timeHash []byte) (config.User, int64, bool)
}

type TimedUserSet struct {
	validUsers          []config.User
	userHash            map[string]indexTimePair
	userHashDeleteQueue *collect.TimedQueue
	access              sync.RWMutex
}

type indexTimePair struct {
	index   int
	timeSec int64
}

func NewTimedUserSet() UserSet {
	tus := &TimedUserSet{
		validUsers:          make([]config.User, 0, 16),
		userHash:            make(map[string]indexTimePair, 512),
		userHashDeleteQueue: collect.NewTimedQueue(updateIntervalSec),
		access:              sync.RWMutex{},
	}
	go tus.updateUserHash(time.Tick(updateIntervalSec * time.Second))
	go tus.removeEntries(tus.userHashDeleteQueue.RemovedEntries())
	return tus
}

func (us *TimedUserSet) removeEntries(entries <-chan interface{}) {
	for entry := range entries {
		us.access.Lock()
		delete(us.userHash, entry.(string))
		us.access.Unlock()
	}
}

func (us *TimedUserSet) generateNewHashes(lastSec, nowSec int64, idx int, id *config.ID) {
	idHash := NewTimeHash(HMACHash{})
	for lastSec < nowSec {
		idHash := idHash.Hash(id.Bytes[:], lastSec)
		us.access.Lock()
		us.userHash[string(idHash)] = indexTimePair{idx, lastSec}
		us.access.Unlock()
		us.userHashDeleteQueue.Add(string(idHash), lastSec+2*cacheDurationSec)
		lastSec++
	}
}

func (us *TimedUserSet) updateUserHash(tick <-chan time.Time) {
	lastSec := time.Now().Unix() - cacheDurationSec

	for now := range tick {
		nowSec := now.Unix() + cacheDurationSec
		for idx, user := range us.validUsers {
			us.generateNewHashes(lastSec, nowSec, idx, user.ID())
		}
		lastSec = nowSec
	}
}

func (us *TimedUserSet) AddUser(user config.User) error {
	id := user.ID()
	idx := len(us.validUsers)
	us.validUsers = append(us.validUsers, user)

	nowSec := time.Now().Unix()
	lastSec := nowSec - cacheDurationSec
	us.generateNewHashes(lastSec, nowSec+cacheDurationSec, idx, id)

	return nil
}

func (us *TimedUserSet) GetUser(userHash []byte) (config.User, int64, bool) {
	defer us.access.RUnlock()
	us.access.RLock()
	pair, found := us.userHash[string(userHash)]
	if found {
		return us.validUsers[pair.index], pair.timeSec, true
	}
	return nil, 0, false
}
<|endoftext|>


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

package main

import (
	"bytes"
	"container/list"
	"fmt"
	"io"
	"os"
	"os/exec"
	"strconv"
	"strings"

	"github.com/codegangsta/cli"
	"github.com/qiniu/log"

	"github.com/gogits/git"
	"github.com/gogits/gogs/models"
	"github.com/gogits/gogs/modules/base"
)

var (
	COMMANDS_READONLY = map[string]int{
		"git-upload-pack":    models.AU_WRITABLE,
		"git upload-pack":    models.AU_WRITABLE,
		"git-upload-archive": models.AU_WRITABLE,
	}

	COMMANDS_WRITE = map[string]int{
		"git-receive-pack": models.AU_READABLE,
		"git receive-pack": models.AU_READABLE,
	}
)

var CmdServ = cli.Command{
	Name:  "serv",
	Usage: "This command just should be called by ssh shell",
	Description: `
gogs serv provide access auth for repositories`,
	Action: runServ,
	Flags:  []cli.Flag{},
}

func parseCmd(cmd string) (string, string) {
	ss := strings.SplitN(cmd, " ", 2)
	if len(ss) != 2 {
		return "", ""
	}

	verb, args := ss[0], ss[1]
	if verb == "git" {
		ss = strings.SplitN(args, " ", 2)
		args = ss[1]
		verb = fmt.Sprintf("%s %s", verb, ss[0])
	}
	return verb, args
}

func In(b string, sl map[string]int) bool {
	_, e := sl[b]
	return e
}

func runServ(k *cli.Context) {
	base.NewConfigContext()
	models.LoadModelsConfig()
	models.NewEngine()

	keys := strings.Split(os.Args[2], "-")
	if len(keys) != 2 {
		fmt.Println("auth file format error")
		return
	}

	keyId, err := strconv.ParseInt(keys[1], 10, 64)
	if err != nil {
		fmt.Println("auth file format error")
		return
	}
	user, err := models.GetUserByKeyId(keyId)
	if err != nil {
		fmt.Println("You have no right to access")
		return
	}

	cmd := os.Getenv("SSH_ORIGINAL_COMMAND")
	if cmd == "" {
		println("Hi", user.Name, "! You've successfully authenticated, but Gogs does not provide shell access.")
		return
	}

	verb, args := parseCmd(cmd)
	rRepo := strings.Trim(args, "'")
	rr := strings.SplitN(rRepo, "/", 2)
	if len(rr) != 2 {
		println("Unavilable repository", args)
		return
	}
	repoName := rr[1]
	if strings.HasSuffix(repoName, ".git") {
		repoName = repoName[:len(repoName)-4]
	}

	//os.Setenv("userName", user.Name)
	//os.Setenv("userId", strconv.Itoa(int(user.Id)))
	repo, err := models.GetRepositoryByName(user.Id, repoName)
	var isExist bool = true
	if err != nil {
		if err == models.ErrRepoNotExist {
			isExist = false
		} else {
			println("Unavilable repository", err)
			return
		}
	}
	//os.Setenv("repoId", strconv.Itoa(int(repo.Id)))
	//os.Setenv("repoName", repoName)

	isWrite := In(verb, COMMANDS_WRITE)
	isRead := In(verb, COMMANDS_READONLY)

	switch {
	case isWrite:
		has, err := models.HasAccess(user.Name, repoName, models.AU_WRITABLE)
		if err != nil {
			println("Inernel error:", err)
			return
		}
		if !has {
			println("You have no right to write this repository")
			return
		}
	case isRead:
		has, err := models.HasAccess(user.Name, repoName, models.AU_READABLE)
		if err != nil {
			println("Inernel error")
			return
		}
		if !has {
			has, err = models.HasAccess(user.Name, repoName, models.AU_WRITABLE)
			if err != nil {
				println("Inernel error")
				return
			}
		}
		if !has {
			println("You have no right to access this repository")
			return
		}
	default:
		println("Unknown command")
		return
	}

	if !isExist {
		if isRead {
			println("Repository", user.Name+"/"+repoName, "is not exist")
			return
		} else if isWrite {
			_, err := models.CreateRepository(user, repoName, "", "", "", false, true)
			if err != nil {
				println("Create repository failed")
				return
			}
		}
	}

	rep, err := git.OpenRepository(models.RepoPath(user.Name, repoName))
	if err != nil {
		println(err.Error())
		return
	}

	refs, err := rep.AllReferencesMap()
	if err != nil {
		println(err.Error())
		return
	}

	gitcmd := exec.Command(verb, rRepo)
	gitcmd.Dir = base.RepoRootPath

	var s string
	b := bytes.NewBufferString(s)

	gitcmd.Stdout = io.MultiWriter(os.Stdout, b)
	gitcmd.Stdin = io.MultiReader(os.Stdin, b)
	gitcmd.Stderr = os.Stderr

	if err = gitcmd.Run(); err != nil {
		println("execute command error:", err.Error())
	}

	// update
	w, _ := os.Create("serve.log")
	defer w.Close()
	log.SetOutput(w)

	var t = "ok refs/heads/"
	var i int
	var refname string
	for {
		l, err := b.ReadString('\n')
		if err != nil {
			break
		}
		i = i + 1
		l = l[:len(l)-1]
		idx := strings.Index(l, t)
		if idx > 0 {
			refname = l[idx+len(t):]
		}
	}
	var ref *git.Reference
	var ok bool

	var l *list.List
	//log.Info("----", refname, "-----")
	if ref, ok = refs[refname]; !ok {
		refs, err = rep.AllReferencesMap()
		if err != nil {
			println(err.Error())
			return
		}
		if ref, ok = refs[refname]; !ok {
			println("unknow reference name", refname)
			return
		}
		l, err = ref.AllCommits()
		if err != nil {
			println(err.Error())
			return
		}
	} else {
		//log.Info("----", ref, "-----")
		var last *git.Commit
		//log.Info("00000", ref.Oid.String())
		last, err = ref.LastCommit()
		if err != nil {
			println(err.Error())
			return
		}

		ref2, err := rep.LookupReference(ref.Name)
		if err != nil {
			println(err.Error())
			return
		}

		//log.Info("11111", ref2.Oid.String())
		before, err := ref2.LastCommit()
		if err != nil {
			println(err.Error())
			return
		}
		//log.Info("----", before.Id(), "-----", last.Id())
		l = ref.CommitsBetween(before, last)
	}

	commits := make([][]string, 0)
	for e := l.Back(); e != nil; e = e.Prev() {
		commit := e.Value.(*git.Commit)
		commits = append(commits, []string{commit.Id().String(), commit.Message()})
	}

	if err = models.CommitRepoAction(user.Id, user.Name,
		repo.Id, ref.BranchName(), commits); err != nil {
		log.Error("runUpdate.models.CommitRepoAction: %v", err, commits)
	} else {
		//log.Info("refname", refname)
		//log.Info("Listen: %v", cmd)
		//fmt.Println("...", cmd)

		//runUpdate(k)
		c := exec.Command("exec", "git", "update-server-info")
		c.Run()
	}
}
<commit_msg>log import fixed<commit_after>// Copyright 2014 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package main

import (
	"bytes"
	"container/list"
	"fmt"
	"io"
	"os"
	"os/exec"
	"strconv"
	"strings"

	"github.com/codegangsta/cli"
	"github.com/gogits/gogs/modules/log"

	"github.com/gogits/git"
	"github.com/gogits/gogs/models"
	"github.com/gogits/gogs/modules/base"
)

var (
	COMMANDS_READONLY = map[string]int{
		"git-upload-pack":    models.AU_WRITABLE,
		"git upload-pack":    models.AU_WRITABLE,
		"git-upload-archive": models.AU_WRITABLE,
	}

	COMMANDS_WRITE = map[string]int{
		"git-receive-pack": models.AU_READABLE,
		"git receive-pack": models.AU_READABLE,
	}
)

var CmdServ = cli.Command{
	Name:  "serv",
	Usage: "This command just should be called by ssh shell",
	Description: `
gogs serv provide access auth for repositories`,
	Action: runServ,
	Flags:  []cli.Flag{},
}

func parseCmd(cmd string) (string, string) {
	ss := strings.SplitN(cmd, " ", 2)
	if len(ss) != 2 {
		return "", ""
	}

	verb, args := ss[0], ss[1]
	if verb == "git" {
		ss = strings.SplitN(args, " ", 2)
		args = ss[1]
		verb = fmt.Sprintf("%s %s", verb, ss[0])
	}
	return verb, args
}

func In(b string, sl map[string]int) bool {
	_, e := sl[b]
	return e
}

func runServ(k *cli.Context) {
	base.NewConfigContext()
	models.LoadModelsConfig()
	models.NewEngine()

	keys := strings.Split(os.Args[2], "-")
	if len(keys) != 2 {
		fmt.Println("auth file format error")
		return
	}

	keyId, err := strconv.ParseInt(keys[1], 10, 64)
	if err != nil {
		fmt.Println("auth file format error")
		return
	}
	user, err := models.GetUserByKeyId(keyId)
	if err != nil {
		fmt.Println("You have no right to access")
		return
	}

	cmd := os.Getenv("SSH_ORIGINAL_COMMAND")
	if cmd == "" {
		println("Hi", user.Name, "! You've successfully authenticated, but Gogs does not provide shell access.")
		return
	}

	verb, args := parseCmd(cmd)
	rRepo := strings.Trim(args, "'")
	rr := strings.SplitN(rRepo, "/", 2)
	if len(rr) != 2 {
		println("Unavilable repository", args)
		return
	}
	repoName := rr[1]
	if strings.HasSuffix(repoName, ".git") {
		repoName = repoName[:len(repoName)-4]
	}

	//os.Setenv("userName", user.Name)
	//os.Setenv("userId", strconv.Itoa(int(user.Id)))
	repo, err := models.GetRepositoryByName(user.Id, repoName)
	var isExist bool = true
	if err != nil {
		if err == models.ErrRepoNotExist {
			isExist = false
		} else {
			println("Unavilable repository", err)
			return
		}
	}
	//os.Setenv("repoId", strconv.Itoa(int(repo.Id)))
	//os.Setenv("repoName", repoName)

	isWrite := In(verb, COMMANDS_WRITE)
	isRead := In(verb, COMMANDS_READONLY)

	switch {
	case isWrite:
		has, err := models.HasAccess(user.Name, repoName, models.AU_WRITABLE)
		if err != nil {
			println("Inernel error:", err)
			return
		}
		if !has {
			println("You have no right to write this repository")
			return
		}
	case isRead:
		has, err := models.HasAccess(user.Name, repoName, models.AU_READABLE)
		if err != nil {
			println("Inernel error")
			return
		}
		if !has {
			has, err = models.HasAccess(user.Name, repoName, models.AU_WRITABLE)
			if err != nil {
				println("Inernel error")
				return
			}
		}
		if !has {
			println("You have no right to access this repository")
			return
		}
	default:
		println("Unknown command")
		return
	}

	if !isExist {
		if isRead {
			println("Repository", user.Name+"/"+repoName, "is not exist")
			return
		} else if isWrite {
			_, err := models.CreateRepository(user, repoName, "", "", "", false, true)
			if err != nil {
				println("Create repository failed")
				return
			}
		}
	}

	rep, err := git.OpenRepository(models.RepoPath(user.Name, repoName))
	if err != nil {
		println(err.Error())
		return
	}

	refs, err := rep.AllReferencesMap()
	if err != nil {
		println(err.Error())
		return
	}

	gitcmd := exec.Command(verb, rRepo)
	gitcmd.Dir = base.RepoRootPath

	var s string
	b := bytes.NewBufferString(s)

	gitcmd.Stdout = io.MultiWriter(os.Stdout, b)
	gitcmd.Stdin = io.MultiReader(os.Stdin, b)
	gitcmd.Stderr = os.Stderr

	if err = gitcmd.Run(); err != nil {
		println("execute command error:", err.Error())
	}

	// update
	//w, _ := os.Create("serve.log")
	//defer w.Close()
	//log.SetOutput(w)

	var t = "ok refs/heads/"
	var i int
	var refname string
	for {
		l, err := b.ReadString('\n')
		if err != nil {
			break
		}
		i = i + 1
		l = l[:len(l)-1]
		idx := strings.Index(l, t)
		if idx > 0 {
			refname = l[idx+len(t):]
		}
	}
	var ref *git.Reference
	var ok bool

	var l *list.List
	//log.Info("----", refname, "-----")
	if ref, ok = refs[refname]; !ok {
		refs, err = rep.AllReferencesMap()
		if err != nil {
			println(err.Error())
			return
		}
		if ref, ok = refs[refname]; !ok {
			println("unknow reference name", refname)
			return
		}
		l, err = ref.AllCommits()
		if err != nil {
			println(err.Error())
			return
		}
	} else {
		//log.Info("----", ref, "-----")
		var last *git.Commit
		//log.Info("00000", ref.Oid.String())
		last, err = ref.LastCommit()
		if err != nil {
			println(err.Error())
			return
		}

		ref2, err := rep.LookupReference(ref.Name)
		if err != nil {
			println(err.Error())
			return
		}

		//log.Info("11111", ref2.Oid.String())
		before, err := ref2.LastCommit()
		if err != nil {
			println(err.Error())
			return
		}
		//log.Info("----", before.Id(), "-----", last.Id())
		l = ref.CommitsBetween(before, last)
	}

	commits := make([][]string, 0)
	for e := l.Back(); e != nil; e = e.Prev() {
		commit := e.Value.(*git.Commit)
		commits = append(commits, []string{commit.Id().String(), commit.Message()})
	}

	if err = models.CommitRepoAction(user.Id, user.Name,
		repo.Id, ref.BranchName(), commits); err != nil {
		log.Error("runUpdate.models.CommitRepoAction: %v", err, commits)
	} else {
		//log.Info("refname", refname)
		//log.Info("Listen: %v", cmd)
		//fmt.Println("...", cmd)

		//runUpdate(k)
		c := exec.Command("exec", "git", "update-server-info")
		c.Run()
	}
}
<|endoftext|>


<commit_before>package gode

import (
	"archive/tar"
	"compress/gzip"
	"io"
	"net/http"
	"os"
	"path/filepath"
)

// IsSetup returns true if node is setup in the client's RootPath directory
func (c *Client) IsSetup() bool {
	// TODO: better check if it is setup
	exists, _ := fileExists(c.NodePath)
	return exists
}

// Setup downloads and sets up node in the client's RootPath directory
func (c *Client) Setup() error {
	err := os.MkdirAll(c.RootPath, 0777)
	if err != nil {
		return err
	}
	resp, err := http.Get(c.NodeURL)
	if err != nil {
		return err
	}
	defer resp.Body.Close()
	uncompressed, err := gzip.NewReader(resp.Body)
	if err != nil {
		return err
	}
	archive := tar.NewReader(uncompressed)
	for {
		hdr, err := archive.Next()
		if err == io.EOF {
			break
		}
		if err != nil {
			return err
		}
		path := filepath.Join(c.RootPath, hdr.Name)
		switch {
		case hdr.FileInfo().IsDir():
			err = os.Mkdir(path, 0777)
			if err != nil {
				return err
			}
		case hdr.Linkname != "":
			err = os.Symlink(hdr.Linkname, path)
			if err != nil {
				return err
			}
		default:
			file, err := os.Create(path)
			if err != nil {
				return err
			}
			defer file.Close()
			_, err = io.Copy(file, archive)
			if err != nil {
				return err
			}
		}
		err = os.Chmod(path, hdr.FileInfo().Mode())
		if err != nil {
			return err
		}
	}
	return nil
}
<commit_msg>refactored setup<commit_after>package gode

import (
	"archive/tar"
	"compress/gzip"
	"io"
	"net/http"
	"os"
	"path/filepath"
)

// IsSetup returns true if node is setup in the client's RootPath directory
func (c *Client) IsSetup() bool {
	// TODO: better check if it is setup
	exists, _ := fileExists(c.NodePath)
	return exists
}

// Setup downloads and sets up node in the client's RootPath directory
func (c *Client) Setup() error {
	err := os.MkdirAll(c.RootPath, 0777)
	if err != nil {
		return err
	}
	resp, err := http.Get(c.NodeURL)
	if err != nil {
		return err
	}
	defer resp.Body.Close()
	uncompressed, err := gzip.NewReader(resp.Body)
	if err != nil {
		return err
	}
	return extractArchive(tar.NewReader(uncompressed), c.RootPath)
}

func extractArchive(archive *tar.Reader, rootPath string) error {
	for {
		hdr, err := archive.Next()
		if err == io.EOF {
			return nil
		}
		if err != nil {
			return err
		}
		path := filepath.Join(rootPath, hdr.Name)
		switch {
		case hdr.FileInfo().IsDir():
			if err := os.Mkdir(path, hdr.FileInfo().Mode()); err != nil {
				return err
			}
		case hdr.Linkname != "":
			if err := os.Symlink(hdr.Linkname, path); err != nil {
				return err
			}
		default:
			if err := extractFile(archive, hdr, path); err != nil {
				return err
			}
		}
	}
}

func extractFile(archive *tar.Reader, hdr *tar.Header, path string) error {
	file, err := os.Create(path)
	if err != nil {
		return err
	}
	defer file.Close()
	_, err = io.Copy(file, archive)
	if err != nil {
		return err
	}
	return os.Chmod(path, hdr.FileInfo().Mode())
}
<|endoftext|>


<commit_before>package lbtransport

import (
	"context"
	"net"
	"net/http"
	"sync"
	"time"

	"github.com/jpillora/backoff"
	"github.com/mwitkow/go-httpwares/tags"
	"github.com/mwitkow/kedge/lib/http/ctxtags"
	"github.com/mwitkow/kedge/lib/reporter"
	"github.com/mwitkow/kedge/lib/reporter/errtypes"
	"github.com/pkg/errors"
	"github.com/prometheus/client_golang/prometheus"
	"google.golang.org/grpc/naming"
	"github.com/sirupsen/logrus"
)

type tripper struct {
	targetName string

	parent           http.RoundTripper
	policy           LBPolicy
	lastResolveError error

	currentTargets []*Target
	mu             sync.RWMutex
	cancel         context.CancelFunc
}

var (
	failedDialsCounter = prometheus.NewCounterVec(
		prometheus.CounterOpts{
			Namespace: "kedge",
			Subsystem: "http_lbtransport",
			Name:      "failed_dials",
			Help:      "Total number of failed dials that are in resolver and should blacklist the target.",
		},
		[]string{"resolve_addr", "target"},
	)
)

func init() {
	prometheus.MustRegister(failedDialsCounter)
}

// New creates a new load-balanced Round Tripper for a single backend.
//
// This RoundTripper is meant to only dial a single backend, and will throw errors if the req.URL.Host
// doesn't match the targetAddr.
//
// For resolving backend addresses it uses a grpc.naming.Resolver, allowing for generic use.
func New(ctx context.Context, targetAddr string, parent http.RoundTripper, resolver naming.Resolver, policy LBPolicy) (*tripper, error) {
	innerCtx, cancel := context.WithCancel(ctx)
	s := &tripper{
		targetName:     targetAddr,
		parent:         parent,
		policy:         policy,
		currentTargets: []*Target{},
		cancel:         cancel,
	}

	go s.run(innerCtx, resolver, targetAddr)
	return s, nil
}

func (s *tripper) run(ctx context.Context, resolver naming.Resolver, targetAddr string) {
	resolveRetryBackoff := &backoff.Backoff{
		Min:    50 * time.Millisecond,
		Jitter: true,
		Factor: 2,
		Max:    2 * time.Second,
	}
	var lastNextError error

	for ctx.Err() == nil {
		watcher, err := resolver.Resolve(targetAddr)
		if err != nil {
			s.mu.Lock()
			s.currentTargets = []*Target{}
			// Don't loose lastNextError if there.
			if lastNextError != nil {
				err = errors.Wrap(lastNextError, err.Error())
			}
			s.lastResolveError = errors.Wrapf(err, "Failed to Resolver target %s. Retrying with backoff.", targetAddr)
			s.mu.Unlock()
			time.Sleep(resolveRetryBackoff.Duration())
			continue
		}
		resolveRetryBackoff.Reset()

		innerCtx, innerCancel := context.WithCancel(ctx)
		go func() {
			select {
			case <-innerCtx.Done():
				watcher.Close()
			}
		}()

		localCurrentTargets := []*Target{}
		// Starting getting Next updates. On Error we will retry.
		for ctx.Err() == nil {
			updates, err := watcher.Next() // blocking call until new updates are there
			if err != nil {
				lastNextError = err
				break // watcher.Errors are unrecoverable, so try to Resolve again from the beginning.
			}

			for _, u := range updates {
				if u.Op == naming.Add {
					localCurrentTargets = append(localCurrentTargets, &Target{DialAddr: u.Addr})
				} else if u.Op == naming.Delete {
					kept := []*Target{}
					for _, t := range localCurrentTargets {
						if u.Addr != t.DialAddr {
							kept = append(kept, t)
						}
					}
					localCurrentTargets = kept
				}
			}
			s.mu.Lock()
			s.currentTargets = localCurrentTargets
			s.mu.Unlock()
		}
		innerCancel()
	}
}

func (s *tripper) RoundTrip(r *http.Request) (*http.Response, error) {
	tags := http_ctxtags.ExtractInbound(r)
	tags.Set(ctxtags.TagForBackendTarget, s.targetName)

	s.mu.RLock()
	targetsRef := s.currentTargets
	lastResolvErr := s.lastResolveError
	s.mu.RUnlock()
	if len(targetsRef) == 0 {
		if lastResolvErr == nil {
			lastResolvErr = errors.New("0 resolved addresses")
		}
		err := errors.Wrapf(lastResolvErr, "lb: no resolution available for %s", s.targetName)
		reporter.Extract(r).ReportError(errtypes.NoResolutionAvailable, err)
		return nil, err
	}

	picker := s.policy.Picker()
	for {
		target, err := picker.Pick(r, targetsRef)
		if err != nil {
			err = errors.Wrapf(err, "lb: failed choosing valid target for %s", s.targetName)
			reporter.Extract(r).ReportError(errtypes.NoConnToAllResolvedAddresses, err)
			return nil, err
		}

		// Override the host for downstream Tripper, usually http.DefaultTransport.
		// http.Default transport uses `URL.Host` for Dial(<host>) and relevant connection pooling.
		// We override it to make sure it enters the appropriate dial method and the appropriate connection pool.
		// See http.connectMethodKey.
		r.URL.Host = target.DialAddr
		resp, err := s.parent.RoundTrip(r)
		if err == nil {
			return resp, nil
		}

		if !isDialError(err) {
			// Debug
			logrus.WithError(err).Error("DialError on lbtransport")
			return resp, err
		}

		failedDialsCounter.WithLabelValues(s.targetName, target.DialAddr).Inc()

		// Retry without this target.
		// NOTE: We need to trust picker that it blacklist the targets well.
		picker.ExcludeTarget(target)
	}
}

func isDialError(err error) bool {
	if opErr, ok := err.(*net.OpError); ok {
		if opErr.Op == "dial" {
			return true
		}
	}
	return false
}
<commit_msg>Debug more.<commit_after>package lbtransport

import (
	"context"
	"net"
	"net/http"
	"sync"
	"time"

	"github.com/jpillora/backoff"
	"github.com/mwitkow/go-httpwares/tags"
	"github.com/mwitkow/kedge/lib/http/ctxtags"
	"github.com/mwitkow/kedge/lib/reporter"
	"github.com/mwitkow/kedge/lib/reporter/errtypes"
	"github.com/pkg/errors"
	"github.com/prometheus/client_golang/prometheus"
	"google.golang.org/grpc/naming"
	"github.com/sirupsen/logrus"
)

type tripper struct {
	targetName string

	parent           http.RoundTripper
	policy           LBPolicy
	lastResolveError error

	currentTargets []*Target
	mu             sync.RWMutex
	cancel         context.CancelFunc
}

var (
	failedDialsCounter = prometheus.NewCounterVec(
		prometheus.CounterOpts{
			Namespace: "kedge",
			Subsystem: "http_lbtransport",
			Name:      "failed_dials",
			Help:      "Total number of failed dials that are in resolver and should blacklist the target.",
		},
		[]string{"resolve_addr", "target"},
	)
)

func init() {
	prometheus.MustRegister(failedDialsCounter)
}

// New creates a new load-balanced Round Tripper for a single backend.
//
// This RoundTripper is meant to only dial a single backend, and will throw errors if the req.URL.Host
// doesn't match the targetAddr.
//
// For resolving backend addresses it uses a grpc.naming.Resolver, allowing for generic use.
func New(ctx context.Context, targetAddr string, parent http.RoundTripper, resolver naming.Resolver, policy LBPolicy) (*tripper, error) {
	innerCtx, cancel := context.WithCancel(ctx)
	s := &tripper{
		targetName:     targetAddr,
		parent:         parent,
		policy:         policy,
		currentTargets: []*Target{},
		cancel:         cancel,
	}

	go s.run(innerCtx, resolver, targetAddr)
	return s, nil
}

func (s *tripper) run(ctx context.Context, resolver naming.Resolver, targetAddr string) {
	resolveRetryBackoff := &backoff.Backoff{
		Min:    50 * time.Millisecond,
		Jitter: true,
		Factor: 2,
		Max:    2 * time.Second,
	}
	var lastNextError error

	for ctx.Err() == nil {
		watcher, err := resolver.Resolve(targetAddr)
		if err != nil {
			s.mu.Lock()
			s.currentTargets = []*Target{}
			// Don't loose lastNextError if there.
			if lastNextError != nil {
				err = errors.Wrap(lastNextError, err.Error())
			}
			s.lastResolveError = errors.Wrapf(err, "Failed to Resolver target %s. Retrying with backoff.", targetAddr)
			s.mu.Unlock()
			time.Sleep(resolveRetryBackoff.Duration())
			continue
		}
		resolveRetryBackoff.Reset()

		innerCtx, innerCancel := context.WithCancel(ctx)
		go func() {
			select {
			case <-innerCtx.Done():
				watcher.Close()
			}
		}()

		localCurrentTargets := []*Target{}
		// Starting getting Next updates. On Error we will retry.
		for ctx.Err() == nil {
			updates, err := watcher.Next() // blocking call until new updates are there
			if err != nil {
				lastNextError = err
				break // watcher.Errors are unrecoverable, so try to Resolve again from the beginning.
			}

			for _, u := range updates {
				if u.Op == naming.Add {
					localCurrentTargets = append(localCurrentTargets, &Target{DialAddr: u.Addr})
				} else if u.Op == naming.Delete {
					kept := []*Target{}
					for _, t := range localCurrentTargets {
						if u.Addr != t.DialAddr {
							kept = append(kept, t)
						}
					}
					localCurrentTargets = kept
				}
			}
			s.mu.Lock()
			s.currentTargets = localCurrentTargets
			s.mu.Unlock()
		}
		innerCancel()
	}
}

func (s *tripper) RoundTrip(r *http.Request) (*http.Response, error) {
	tags := http_ctxtags.ExtractInbound(r)
	tags.Set(ctxtags.TagForBackendTarget, s.targetName)

	s.mu.RLock()
	targetsRef := s.currentTargets
	lastResolvErr := s.lastResolveError
	s.mu.RUnlock()
	if len(targetsRef) == 0 {
		if lastResolvErr == nil {
			lastResolvErr = errors.New("0 resolved addresses")
		}
		err := errors.Wrapf(lastResolvErr, "lb: no resolution available for %s", s.targetName)
		reporter.Extract(r).ReportError(errtypes.NoResolutionAvailable, err)
		return nil, err
	}

	picker := s.policy.Picker()
	for {
		target, err := picker.Pick(r, targetsRef)
		if err != nil {
			err = errors.Wrapf(err, "lb: failed choosing valid target for %s", s.targetName)
			reporter.Extract(r).ReportError(errtypes.NoConnToAllResolvedAddresses, err)
			return nil, err
		}

		// Override the host for downstream Tripper, usually http.DefaultTransport.
		// http.Default transport uses `URL.Host` for Dial(<host>) and relevant connection pooling.
		// We override it to make sure it enters the appropriate dial method and the appropriate connection pool.
		// See http.connectMethodKey.
		r.URL.Host = target.DialAddr
		resp, err := s.parent.RoundTrip(r)
		if err == nil {
			return resp, nil
		}

		if !isDialError(err) {
			// Debug
			logrus.WithError(err).Error("NON DialError on lbtransport")
			return resp, err
		}

		logrus.WithError(err).Error("DialError on lbtransport")
		failedDialsCounter.WithLabelValues(s.targetName, target.DialAddr).Inc()

		// Retry without this target.
		// NOTE: We need to trust picker that it blacklist the targets well.
		picker.ExcludeTarget(target)
	}
}

func isDialError(err error) bool {
	if opErr, ok := err.(*net.OpError); ok {
		if opErr.Op == "dial" {
			return true
		}
	}
	return false
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"net/url"
	"strings"
	"time"

	"github.com/aryann/difflib"

	githubApp "github.com/google/go-github/github"
)

const noneString = "<none>"

type branches struct {
	repo    *Repo
	auth    *Authentication
	client  *githubApp.Client
	option  string
	oldList []string
	newList []string
}

func (e *branches) String() string {
	return Stringify(e)
}

type BranchCommit struct {
	OldCommit string
	NewCommit string
}

func (e *BranchCommit) String() string {
	return Stringify(e)
}

type LocalDiffs struct {
	RepoName   string
	Provider   string
	References map[string]*BranchCommit
	Others     []*LocalRef
}

func (e *LocalDiffs) String() string {
	return Stringify(e)
}

var mailContent = &MailContent{}

type MailContent struct {
	WebsiteURL string
	User       string // provider/username
	Name       string
	Data       []*LocalDiffs
}

// LocalRef is used tracking Repo and Branch from the email
type LocalRef struct {
	Title      string
	References []string
}

func (e *LocalRef) String() string {
	return Stringify(e)
}

func forceRunHandler(w http.ResponseWriter, r *http.Request) {

	// Redirect user if not logged in
	hc := &httpContext{w, r}
	redirected := hc.redirectUnlessLoggedIn()
	if redirected {
		return
	}
	userInfo := hc.userLoggedinInfo()
	configFile := userInfo.getConfigFile()

	// hidden feature: useful for testing. pass ?save=false in the POST url
	isSaveFalse := isSaveSetToFalse(r.URL.Query())

	cronJob{configFile, !isSaveFalse}.Run()

	hc.addFlash("Check email to see latest information")

	http.Redirect(w, r, homePageForLoggedIn, 302)
}

func isSaveSetToFalse(q url.Values) bool {
	if len(q["save"]) == 0 {
		return false
	}
	if q["save"][0] == "false" {
		return true
	}
	return false
}

// Move to helper. statndard directory walk
func fetchFiles(provider string) []string {
	dir := fmt.Sprintf("%s/%s", config.DataDir, provider)
	fis, err := ioutil.ReadDir(dir)
	if err != nil {
		log.Println(err)
		return []string{}
	}
	files := make([]string, len(fis))
	for i, fi := range fis {
		if fi.IsDir() {
			// TODO - merge by os.sep
			files[i] = dir + "/" + fi.Name() + "/" + config.SettingsFile
		}
	}
	return files
}

// load all files and adds the cron entries
func getData(provider string) {
	files := fetchFiles("github")
	for i, filename := range files {
		if filename == "" {
			continue
		}
		conf := new(Setting)
		log.Printf("Processing file %d - %s\n", i, filename)
		conf.load(filename)
		upsertCronEntry(conf)
	}
}

type userNotFound struct{}

func (userNotFound) Error() string {
	return fmt.Sprintf("No email address found for account. Visit Settings Page")
}

// process is called from the cron job
func process(conf *Setting) ([]*LocalDiffs, error) {
	if conf.usersEmail() == "" {
		log.Printf("No email address for %s\n", conf.Auth.UserName)
		return nil, &userNotFound{}
	}
	client := newGithubClient(conf.Auth.Token)
	branch := &branches{
		client: client,
		auth:   conf.Auth,
	}

	var allLocalDiffs = make([]*LocalDiffs, 0, len(conf.Repos))

	// loop through repos and their branches
	for _, repo := range conf.Repos {
		var localDiffs = &LocalDiffs{
			RepoName: repo.Repo,
			Provider: conf.Auth.Provider,
		}
		allLocalDiffs = append(allLocalDiffs, localDiffs)

		// branch is reused here without creating new ones
		branch.repo = repo

		if repo.Branches || len(repo.NamedReferences) > 0 {
			newBranches := getNewInfo(branch, "branches")
			if len(repo.NamedReferences) > 0 {

				data := make(map[string]*BranchCommit)
				b := conf.Info[repo.Repo]
				// TODO set newInformation as part of the config loader
				// TODO bug - if we are no longer tracking a branch, we need to remove it from the new list
				if b == nil {
					conf.Info[branch.repo.Repo] = newInformation()
					b = conf.Info[branch.repo.Repo]
				}
				for branch, commitID := range b.Commits {
					data[branch] = &BranchCommit{
						OldCommit: commitID,
					}
				}

				// check if data still keeps the data
				diffWithOldCommits(newBranches, branch, data)

				for i, t := range data {
					// save new data from commitDiff.data
					if t.NewCommit != noneString {
						b.Commits[i] = t.NewCommit
					}
				}
				localDiffs.References = data
			}

			if repo.Branches {
				branchesDiff := diffWithOldBranches(newBranches, branch, "branches", conf.Info)
				l := &LocalRef{
					Title:      "Branches",
					References: branchesDiff,
				}
				localDiffs.Others = append(localDiffs.Others, l)
			}
		}

		if repo.Tags {
			newTags := getNewInfo(branch, "tags")
			tagsDiff := diffWithOldBranches(newTags, branch, "tags", conf.Info)
			l := &LocalRef{
				Title:      "Tags",
				References: tagsDiff,
			}
			localDiffs.Others = append(localDiffs.Others, l)
		}
	}
	return allLocalDiffs, nil
}
func processForMail(conf *Setting) error {

	diff, _ := process(conf)

	mailContent = &MailContent{
		WebsiteURL: config.ServerProto + config.ServerHost,
		User:       fmt.Sprintf("%s/%s", conf.Auth.Provider, conf.Auth.UserName),
		Name:       conf.usersName(),
	}
	mailContent.Data = diff

	htmlBuffer := &bytes.Buffer{}
	displayPage(htmlBuffer, "changes_mail", mailContent)
	html, _ := ioutil.ReadAll(htmlBuffer)

	textBuffer := &bytes.Buffer{}
	displayPage(textBuffer, "changes_mail_text", mailContent)
	text, _ := ioutil.ReadAll(textBuffer)
	textContent := strings.Replace(string(text), "\n\n", "\n", -1)
	textContent = strings.Replace(textContent, "\n\n", "\n", -1)

	loc, _ := time.LoadLocation(conf.User.TimeZoneName)
	t := time.Now().In(loc)
	subject := "[GitNotify] New Updates from your Repositories - " + t.Format("02 Jan 2006 | 15 Hrs")

	to := &recepient{
		Name:     conf.usersName(),
		Address:  conf.usersEmail(),
		UserName: conf.Auth.UserName,
		Provider: conf.Auth.Provider,
	}

	ctx := &emailCtx{
		Subject:  subject,
		TextBody: textContent,
		HTMLBody: string(html),
	}

	sendEmail(to, ctx)
	return nil
}

func getNewInfo(branch *branches, option string) []*TagInfo {
	branch.option = option
	return getBranchTagInfo(branch.client, branch.repo.Repo, option)
}

func diffWithOldBranches(v []*TagInfo, branch *branches, option string, info map[string]*Information) []string {
	newBranches := make([]string, len(v))
	for i, a := range v {
		newBranches[i] = a.Name
	}

	branch.newList = newBranches
	t := info[branch.repo.Repo]
	if option == "tags" && t != nil {
		branch.oldList = t.Tags
	} else if option == "branches" && t != nil {
		branch.oldList = t.Branches
	}
	diff := getNewStrings(branch.oldList, branch.newList)
	if t == nil {
		info[branch.repo.Repo] = newInformation()
		t = info[branch.repo.Repo]
	}
	if option == "tags" {
		t.Tags = branch.newList
	} else if option == "branches" {
		t.Branches = branch.newList
	}

	return diff
}

func getNewStrings(old, new []string) []string {
	strs := make([]string, 0, 1)
	for _, s := range difflib.Diff(old, new) {
		if s.Delta == difflib.RightOnly {
			strs = append(strs, s.Payload)
		}
	}
	return strs
}

// in the branches we are tracking,
// newcommit is "" // means that we are no longer tracking the branch/ref
// newcommit is <none> if branch is not found/deleted in remote
func diffWithOldCommits(v []*TagInfo, branch *branches, data map[string]*BranchCommit) {
	for _, a := range branch.repo.NamedReferences {
		s := string(a)
		c := data[s]
		if c == nil {
			c = &BranchCommit{}
			data[s] = c
		}
		c.NewCommit = findBranchCommit(v, s)
	}
}

func findBranchCommit(v []*TagInfo, branch string) string {
	for _, a := range v {
		if a.Name == branch {
			return a.Commit.Sha
		}
	}
	return noneString
}
<commit_msg>add flash message in case email is not configured<commit_after>package main

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"net/url"
	"strings"
	"time"

	"github.com/aryann/difflib"

	githubApp "github.com/google/go-github/github"
)

const noneString = "<none>"

type branches struct {
	repo    *Repo
	auth    *Authentication
	client  *githubApp.Client
	option  string
	oldList []string
	newList []string
}

func (e *branches) String() string {
	return Stringify(e)
}

type BranchCommit struct {
	OldCommit string
	NewCommit string
}

func (e *BranchCommit) String() string {
	return Stringify(e)
}

type LocalDiffs struct {
	RepoName   string
	Provider   string
	References map[string]*BranchCommit
	Others     []*LocalRef
}

func (e *LocalDiffs) String() string {
	return Stringify(e)
}

var mailContent = &MailContent{}

type MailContent struct {
	WebsiteURL string
	User       string // provider/username
	Name       string
	Data       []*LocalDiffs
}

// LocalRef is used tracking Repo and Branch from the email
type LocalRef struct {
	Title      string
	References []string
}

func (e *LocalRef) String() string {
	return Stringify(e)
}

func forceRunHandler(w http.ResponseWriter, r *http.Request) {

	// Redirect user if not logged in
	hc := &httpContext{w, r}
	redirected := hc.redirectUnlessLoggedIn()
	if redirected {
		return
	}
	userInfo := hc.userLoggedinInfo()
	configFile := userInfo.getConfigFile()

	conf := new(Setting)
	conf.load(configFile)
	if conf.usersEmail() == "" {
		hc.addFlash("Email is not set. Go to /user to set")
	} else {
		// hidden feature: useful for testing. pass ?save=false in the POST url
		isSaveFalse := isSaveSetToFalse(r.URL.Query())
		cronJob{configFile, !isSaveFalse}.Run()
		hc.addFlash("Check email to see latest changes")
	}

	http.Redirect(w, r, homePageForLoggedIn, 302)
}

func isSaveSetToFalse(q url.Values) bool {
	if len(q["save"]) == 0 {
		return false
	}
	if q["save"][0] == "false" {
		return true
	}
	return false
}

// Move to helper. statndard directory walk
func fetchFiles(provider string) []string {
	dir := fmt.Sprintf("%s/%s", config.DataDir, provider)
	fis, err := ioutil.ReadDir(dir)
	if err != nil {
		log.Println(err)
		return []string{}
	}
	files := make([]string, len(fis))
	for i, fi := range fis {
		if fi.IsDir() {
			// TODO - merge by os.sep
			files[i] = dir + "/" + fi.Name() + "/" + config.SettingsFile
		}
	}
	return files
}

// load all files and adds the cron entries
func getData(provider string) {
	files := fetchFiles("github")
	for i, filename := range files {
		if filename == "" {
			continue
		}
		conf := new(Setting)
		log.Printf("Processing file %d - %s\n", i, filename)
		conf.load(filename)
		upsertCronEntry(conf)
	}
}

type userNotFound struct{}

func (userNotFound) Error() string {
	return fmt.Sprintf("No email address found for account. Visit Settings Page")
}

// process is called from the cron job
func process(conf *Setting) ([]*LocalDiffs, error) {
	if conf.usersEmail() == "" {
		log.Printf("No email address for %s\n", conf.Auth.UserName)
		return nil, &userNotFound{}
	}
	client := newGithubClient(conf.Auth.Token)
	branch := &branches{
		client: client,
		auth:   conf.Auth,
	}

	var allLocalDiffs = make([]*LocalDiffs, 0, len(conf.Repos))

	// loop through repos and their branches
	for _, repo := range conf.Repos {
		var localDiffs = &LocalDiffs{
			RepoName: repo.Repo,
			Provider: conf.Auth.Provider,
		}
		allLocalDiffs = append(allLocalDiffs, localDiffs)

		// branch is reused here without creating new ones
		branch.repo = repo

		if repo.Branches || len(repo.NamedReferences) > 0 {
			newBranches := getNewInfo(branch, "branches")
			if len(repo.NamedReferences) > 0 {

				data := make(map[string]*BranchCommit)
				b := conf.Info[repo.Repo]
				// TODO set newInformation as part of the config loader
				// TODO bug - if we are no longer tracking a branch, we need to remove it from the new list
				if b == nil {
					conf.Info[branch.repo.Repo] = newInformation()
					b = conf.Info[branch.repo.Repo]
				}
				for branch, commitID := range b.Commits {
					data[branch] = &BranchCommit{
						OldCommit: commitID,
					}
				}

				// check if data still keeps the data
				diffWithOldCommits(newBranches, branch, data)

				for i, t := range data {
					// save new data from commitDiff.data
					if t.NewCommit != noneString {
						b.Commits[i] = t.NewCommit
					}
				}
				localDiffs.References = data
			}

			if repo.Branches {
				branchesDiff := diffWithOldBranches(newBranches, branch, "branches", conf.Info)
				l := &LocalRef{
					Title:      "Branches",
					References: branchesDiff,
				}
				localDiffs.Others = append(localDiffs.Others, l)
			}
		}

		if repo.Tags {
			newTags := getNewInfo(branch, "tags")
			tagsDiff := diffWithOldBranches(newTags, branch, "tags", conf.Info)
			l := &LocalRef{
				Title:      "Tags",
				References: tagsDiff,
			}
			localDiffs.Others = append(localDiffs.Others, l)
		}
	}
	return allLocalDiffs, nil
}
func processForMail(conf *Setting) error {

	diff, _ := process(conf)

	mailContent = &MailContent{
		WebsiteURL: config.ServerProto + config.ServerHost,
		User:       fmt.Sprintf("%s/%s", conf.Auth.Provider, conf.Auth.UserName),
		Name:       conf.usersName(),
	}
	mailContent.Data = diff

	htmlBuffer := &bytes.Buffer{}
	displayPage(htmlBuffer, "changes_mail", mailContent)
	html, _ := ioutil.ReadAll(htmlBuffer)

	textBuffer := &bytes.Buffer{}
	displayPage(textBuffer, "changes_mail_text", mailContent)
	text, _ := ioutil.ReadAll(textBuffer)
	textContent := strings.Replace(string(text), "\n\n", "\n", -1)
	textContent = strings.Replace(textContent, "\n\n", "\n", -1)

	loc, _ := time.LoadLocation(conf.User.TimeZoneName)
	t := time.Now().In(loc)
	subject := "[GitNotify] New Updates from your Repositories - " + t.Format("02 Jan 2006 | 15 Hrs")

	to := &recepient{
		Name:     conf.usersName(),
		Address:  conf.usersEmail(),
		UserName: conf.Auth.UserName,
		Provider: conf.Auth.Provider,
	}

	ctx := &emailCtx{
		Subject:  subject,
		TextBody: textContent,
		HTMLBody: string(html),
	}

	sendEmail(to, ctx)
	return nil
}

func getNewInfo(branch *branches, option string) []*TagInfo {
	branch.option = option
	return getBranchTagInfo(branch.client, branch.repo.Repo, option)
}

func diffWithOldBranches(v []*TagInfo, branch *branches, option string, info map[string]*Information) []string {
	newBranches := make([]string, len(v))
	for i, a := range v {
		newBranches[i] = a.Name
	}

	branch.newList = newBranches
	t := info[branch.repo.Repo]
	if option == "tags" && t != nil {
		branch.oldList = t.Tags
	} else if option == "branches" && t != nil {
		branch.oldList = t.Branches
	}
	diff := getNewStrings(branch.oldList, branch.newList)
	if t == nil {
		info[branch.repo.Repo] = newInformation()
		t = info[branch.repo.Repo]
	}
	if option == "tags" {
		t.Tags = branch.newList
	} else if option == "branches" {
		t.Branches = branch.newList
	}

	return diff
}

func getNewStrings(old, new []string) []string {
	strs := make([]string, 0, 1)
	for _, s := range difflib.Diff(old, new) {
		if s.Delta == difflib.RightOnly {
			strs = append(strs, s.Payload)
		}
	}
	return strs
}

// in the branches we are tracking,
// newcommit is "" // means that we are no longer tracking the branch/ref
// newcommit is <none> if branch is not found/deleted in remote
func diffWithOldCommits(v []*TagInfo, branch *branches, data map[string]*BranchCommit) {
	for _, a := range branch.repo.NamedReferences {
		s := string(a)
		c := data[s]
		if c == nil {
			c = &BranchCommit{}
			data[s] = c
		}
		c.NewCommit = findBranchCommit(v, s)
	}
}

func findBranchCommit(v []*TagInfo, branch string) string {
	for _, a := range v {
		if a.Name == branch {
			return a.Commit.Sha
		}
	}
	return noneString
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"os"
	"time"

	docker "github.com/fsouza/go-dockerclient"
)

type Run struct {
	Id         string
	VolumePath string
	Container  *docker.Container
	Client     *docker.Client
	Request    *Request
}

type RunResult struct {
	ExitCode int    `json:"exit_code"`
	Output   string `json:"output"`
	Duration string `json:"-"`
}

func NewRun(config *Config, client *docker.Client, req *Request) *Run {
	id, _ := randomHex(20)

	return &Run{
		Id:         id,
		Client:     client,
		VolumePath: fmt.Sprintf("%s/%s", config.SharedPath, id),
		Request:    req,
	}
}

func (run *Run) Setup() error {
	fullPath := fmt.Sprintf("%s/%s", run.VolumePath, run.Request.Filename)

	if err := os.Mkdir(run.VolumePath, 0777); err != nil {
		return err
	}

	if err := ioutil.WriteFile(fullPath, []byte(run.Request.Content), 0666); err != nil {
		return err
	}

	opts := docker.CreateContainerOptions{
		HostConfig: &docker.HostConfig{
			Binds: []string{
				run.VolumePath + ":/code",
				run.VolumePath + ":/tmp",
			},
			ReadonlyRootfs: true,
			Memory:         33554432, // 32 mb
			MemorySwap:     0,
		},
		Config: &docker.Config{
			Hostname:        "bitrun",
			Image:           run.Request.Image,
			AttachStdout:    true,
			AttachStderr:    true,
			AttachStdin:     false,
			OpenStdin:       false,
			Tty:             true,
			NetworkDisabled: true,
			WorkingDir:      "/code",
			Cmd:             []string{"bash", "-c", run.Request.Command},
		},
	}

	container, err := run.Client.CreateContainer(opts)
	if err != nil {
		return nil
	}

	run.Container = container
	return nil
}

func (run *Run) Start() (*RunResult, error) {
	ts := time.Now()

	err := run.Client.StartContainer(run.Container.ID, run.Container.HostConfig)
	if err != nil {
		return nil, err
	}

	result := RunResult{}

	exitCode, err := run.Client.WaitContainer(run.Container.ID)
	if err != nil {
		return nil, err
	}

	result.Duration = time.Now().Sub(ts).String()
	result.ExitCode = exitCode

	buff := bytes.NewBuffer([]byte{})

	err = run.Client.Logs(docker.LogsOptions{
		Container:    run.Container.ID,
		Stdout:       true,
		Stderr:       true,
		OutputStream: buff,
		ErrorStream:  buff,
		RawTerminal:  true,
	})

	if err != nil {
		return nil, err
	}

	result.Output = buff.String()
	return &result, nil
}

func (run *Run) Destroy() error {
	if run.Container != nil {
		run.Client.RemoveContainer(docker.RemoveContainerOptions{
			ID:            run.Container.ID,
			RemoveVolumes: true,
			Force:         true,
		})
	}

	return os.RemoveAll(run.VolumePath)
}
<commit_msg>Fix return val<commit_after>package main

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"os"
	"time"

	docker "github.com/fsouza/go-dockerclient"
)

type Run struct {
	Id         string
	VolumePath string
	Container  *docker.Container
	Client     *docker.Client
	Request    *Request
}

type RunResult struct {
	ExitCode int    `json:"exit_code"`
	Output   string `json:"output"`
	Duration string `json:"-"`
}

func NewRun(config *Config, client *docker.Client, req *Request) *Run {
	id, _ := randomHex(20)

	return &Run{
		Id:         id,
		Client:     client,
		VolumePath: fmt.Sprintf("%s/%s", config.SharedPath, id),
		Request:    req,
	}
}

func (run *Run) Setup() error {
	fullPath := fmt.Sprintf("%s/%s", run.VolumePath, run.Request.Filename)

	if err := os.Mkdir(run.VolumePath, 0777); err != nil {
		return err
	}

	if err := ioutil.WriteFile(fullPath, []byte(run.Request.Content), 0666); err != nil {
		return err
	}

	opts := docker.CreateContainerOptions{
		HostConfig: &docker.HostConfig{
			Binds: []string{
				run.VolumePath + ":/code",
				run.VolumePath + ":/tmp",
			},
			ReadonlyRootfs: true,
			Memory:         33554432, // 32 mb
			MemorySwap:     0,
		},
		Config: &docker.Config{
			Hostname:        "bitrun",
			Image:           run.Request.Image,
			AttachStdout:    true,
			AttachStderr:    true,
			AttachStdin:     false,
			OpenStdin:       false,
			Tty:             true,
			NetworkDisabled: true,
			WorkingDir:      "/code",
			Cmd:             []string{"bash", "-c", run.Request.Command},
		},
	}

	container, err := run.Client.CreateContainer(opts)
	if err != nil {
		return err
	}

	run.Container = container
	return nil
}

func (run *Run) Start() (*RunResult, error) {
	ts := time.Now()

	err := run.Client.StartContainer(run.Container.ID, run.Container.HostConfig)
	if err != nil {
		return nil, err
	}

	result := RunResult{}

	exitCode, err := run.Client.WaitContainer(run.Container.ID)
	if err != nil {
		return nil, err
	}

	result.Duration = time.Now().Sub(ts).String()
	result.ExitCode = exitCode

	buff := bytes.NewBuffer([]byte{})

	err = run.Client.Logs(docker.LogsOptions{
		Container:    run.Container.ID,
		Stdout:       true,
		Stderr:       true,
		OutputStream: buff,
		ErrorStream:  buff,
		RawTerminal:  true,
	})

	if err != nil {
		return nil, err
	}

	result.Output = buff.String()
	return &result, nil
}

func (run *Run) Destroy() error {
	if run.Container != nil {
		run.Client.RemoveContainer(docker.RemoveContainerOptions{
			ID:            run.Container.ID,
			RemoveVolumes: true,
			Force:         true,
		})
	}

	return os.RemoveAll(run.VolumePath)
}
<|endoftext|>


<commit_before>package main

/*
loadTinzenite loads an existing Tinzenite directory and runs it.
*/import (
	"fmt"
	"github.com/tinzenite/bootstrap"
	"github.com/tinzenite/core"
	"github.com/tinzenite/shared"
	"log"
	"os"
	"os/signal"
	"time"
)

func bootstrapTinzenite(path string) {
	var boot *bootstrap.Bootstrap
	var err error
	done := make(chan bool)
	if shared.IsTinzenite(path) {
		boot, err = bootstrap.Load(path, func() {
			done <- true
		})
		if err != nil {
			logMain("Bootstrap load error:", err.Error())
			return
		}
	} else {
		peerName := getString("Enter the peer name for this Tinzenite directory:")
		boot, err = bootstrap.Create(path, peerName, func() {
			done <- true
		})
		if err != nil {
			logMain("Bootstrap create error:", err.Error())
			return
		}
		// connect to:
		address := getString("Please enter the address of the peer to connect to:")
		err = boot.Start(address)
		if err != nil {
			logMain("Bootstrap start error:", err.Error())
			// return because we don't want to store a faulty bootstrap
			return
		}
		err = boot.Store()
		if err != nil {
			logMain("Bootstrap store error:", err.Error())
		}
	}
	// print information
	address, _ := boot.Address()
	fmt.Printf("Bootstrapping.\nID: %s\n", address)
	// wait for successful bootstrap
	<-done
	log.Println("Closing Bootstrap.")
	// this is required before closing boot because ToxCore may still need to
	// notify the other client that the file transfers are complete - this can
	// take a few iterations, so we delay for a second to give it time to do that.
	<-time.Tick(1 * time.Second)
	// manually close boot if we're done! It won't close itself!
	boot.Close()
	// continue to executing the directory
	fmt.Println("Bootstrapping was successful. Loading Tinzenite.")
	loadTinzenite(path)
}

func createTinzenite(path string) {
	if shared.IsTinzenite(path) {
		logMain("Directory is already a valid Tinzenite directory!")
		return
	}
	// get options
	peerName := getString("Enter the peer name for this Tinzenite directory:")
	userName := getString("Enter your username:")
	password := getString("Enter a password for this Tinzenite network:")
	relPath := shared.CreatePathRoot(path)
	tinzenite, err := core.CreateTinzenite(relPath.LastElement(), relPath.FullPath(), peerName, userName, password)
	if err != nil {
		logMain("Creation error:", err.Error())
		return
	}
	err = tinzenite.SyncLocal()
	if err != nil {
		logMain("Initial model sync error:", err.Error())
	}
	// run tinzenite until killed
	runTinzenite(tinzenite)
}

func loadTinzenite(path string) {
	if !shared.IsTinzenite(path) {
		logMain("Directory is not a valid Tinzenite directory!")
		return
	}
	password := getString("Please enter the directory password:")
	tinzenite, err := core.LoadTinzenite(path, password)
	if err != nil {
		// TODO catch wrong password and allow retry
		logMain("Loading error:", err.Error())
		return
	}
	err = tinzenite.SyncLocal()
	if err != nil {
		logMain("Initial model sync error:", err.Error())
	}
	// run tinzenite until killed
	runTinzenite(tinzenite)
}

/*
runTinzenite runs the given Tinzenite instance.
*/
func runTinzenite(t *core.Tinzenite) {
	// do this here so that it is guaranteed to be set
	t.RegisterPeerValidation(allowPeer)
	// print important info
	address, _ := t.Address()
	fmt.Printf("Running peer <%s>.\nID: %s\n", t.Name(), address)
	// run update and sync in intervalls
	var counter int
	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt)
	for {
		select {
		case <-time.Tick(time.Duration(10) * time.Second):
			if counter >= 5 {
				// log.Println("DEBUG: Model sync")
				counter = 0
				err := t.SyncRemote()
				if err != nil {
					logMain("SyncRemote error:", err.Error())
				}
				continue
			}
			// log.Println("DEBUG: Update")
			counter++
			err := t.SyncLocal()
			if err != nil {
				logMain("SyncLocal error:", err.Error())
			}
		case <-c:
			// on interrupt close tinzenite
			t.Close()
			return
		} // select
	} // for
}

/*
allowPeer asks the user whether to accept the given peer.
*/
func allowPeer(address string, wantsTrust bool) bool {
	// TODO actually ask!
	log.Println("TODO: Actually ask, for now accepting everything!", address)
	return true
}
<commit_msg>commented something in for debuging<commit_after>package main

/*
loadTinzenite loads an existing Tinzenite directory and runs it.
*/import (
	"fmt"
	"github.com/tinzenite/bootstrap"
	"github.com/tinzenite/core"
	"github.com/tinzenite/shared"
	"log"
	"os"
	"os/signal"
	"time"
)

func bootstrapTinzenite(path string) {
	var boot *bootstrap.Bootstrap
	var err error
	done := make(chan bool)
	if shared.IsTinzenite(path) {
		boot, err = bootstrap.Load(path, func() {
			done <- true
		})
		if err != nil {
			logMain("Bootstrap load error:", err.Error())
			return
		}
	} else {
		peerName := getString("Enter the peer name for this Tinzenite directory:")
		boot, err = bootstrap.Create(path, peerName, func() {
			done <- true
		})
		if err != nil {
			logMain("Bootstrap create error:", err.Error())
			return
		}
		// connect to:
		address := getString("Please enter the address of the peer to connect to:")
		err = boot.Start(address)
		if err != nil {
			logMain("Bootstrap start error:", err.Error())
			// return because we don't want to store a faulty bootstrap
			return
		}
		err = boot.Store()
		if err != nil {
			logMain("Bootstrap store error:", err.Error())
		}
	}
	// print information
	address, _ := boot.Address()
	fmt.Printf("Bootstrapping.\nID: %s\n", address)
	// wait for successful bootstrap
	<-done
	log.Println("Closing Bootstrap.")
	// this is required before closing boot because ToxCore may still need to
	// notify the other client that the file transfers are complete - this can
	// take a few iterations, so we delay for a second to give it time to do that.
	<-time.Tick(1 * time.Second)
	// manually close boot if we're done! It won't close itself!
	boot.Close()
	// continue to executing the directory
	fmt.Println("Bootstrapping was successful. Loading Tinzenite.")
	loadTinzenite(path)
}

func createTinzenite(path string) {
	if shared.IsTinzenite(path) {
		logMain("Directory is already a valid Tinzenite directory!")
		return
	}
	// get options
	peerName := getString("Enter the peer name for this Tinzenite directory:")
	userName := getString("Enter your username:")
	password := getString("Enter a password for this Tinzenite network:")
	relPath := shared.CreatePathRoot(path)
	tinzenite, err := core.CreateTinzenite(relPath.LastElement(), relPath.FullPath(), peerName, userName, password)
	if err != nil {
		logMain("Creation error:", err.Error())
		return
	}
	err = tinzenite.SyncLocal()
	if err != nil {
		logMain("Initial model sync error:", err.Error())
	}
	// run tinzenite until killed
	runTinzenite(tinzenite)
}

func loadTinzenite(path string) {
	if !shared.IsTinzenite(path) {
		logMain("Directory is not a valid Tinzenite directory!")
		return
	}
	password := getString("Please enter the directory password:")
	tinzenite, err := core.LoadTinzenite(path, password)
	if err != nil {
		// TODO catch wrong password and allow retry
		logMain("Loading error:", err.Error())
		return
	}
	err = tinzenite.SyncLocal()
	if err != nil {
		logMain("Initial model sync error:", err.Error())
	}
	// run tinzenite until killed
	runTinzenite(tinzenite)
}

/*
runTinzenite runs the given Tinzenite instance.
*/
func runTinzenite(t *core.Tinzenite) {
	// do this here so that it is guaranteed to be set
	t.RegisterPeerValidation(allowPeer)
	// print important info
	address, _ := t.Address()
	fmt.Printf("Running peer <%s>.\nID: %s\n", t.Name(), address)
	// run update and sync in intervalls
	var counter int
	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt)
	for {
		select {
		case <-time.Tick(time.Duration(10) * time.Second):
			if counter >= 5 {
				// TODO remove once Merge bug is fixed
				log.Println("DEBUG: Model sync ---------------------------")
				counter = 0
				err := t.SyncRemote()
				if err != nil {
					logMain("SyncRemote error:", err.Error())
				}
				continue
			}
			// log.Println("DEBUG: Update")
			counter++
			err := t.SyncLocal()
			if err != nil {
				logMain("SyncLocal error:", err.Error())
			}
		case <-c:
			// on interrupt close tinzenite
			t.Close()
			return
		} // select
	} // for
}

/*
allowPeer asks the user whether to accept the given peer.
*/
func allowPeer(address string, wantsTrust bool) bool {
	// TODO actually ask!
	log.Println("TODO: Actually ask, for now accepting everything!", address)
	return true
}
<|endoftext|>


<commit_before>package main

/*
loadTinzenite loads an existing Tinzenite directory and runs it.
*/import (
	"fmt"
	"github.com/tinzenite/bootstrap"
	"github.com/tinzenite/core"
	"github.com/tinzenite/shared"
	"log"
	"os"
	"os/signal"
	"time"
)

func bootstrapTinzenite(path string) {
	var boot *bootstrap.Bootstrap
	var err error
	var done chan bool
	if shared.IsTinzenite(path) {
		boot, err = bootstrap.Load(path, func() {
			done <- true
		})
		if err != nil {
			logMain("Bootstrap load error:", err.Error())
			return
		}
	} else {
		peerName := getString("Enter the peer name for this Tinzenite directory:")
		boot, err = bootstrap.Create(path, peerName, func() {
			done <- true
		})
		if err != nil {
			logMain("Bootstrap create error:", err.Error())
			return
		}
		// connect to:
		address := getString("Please enter the address of the peer to connect to:")
		err = boot.Start(address)
		if err != nil {
			logMain("Bootstrap start error:", err.Error())
			// return because we don't want to store a faulty bootstrap
			return
		}
		err = boot.Store()
		if err != nil {
			logMain("Bootstrap store error:", err.Error())
		}
	}
	// print information
	address, _ := boot.Address()
	fmt.Printf("Bootstrapping.\nID: %s\n", address)
	// wait for successful bootstrap
	<-done
	log.Println("DEBUG: Success!")
	// continue to executing the directory
	loadTinzenite(path)
}

func createTinzenite(path string) {
	if shared.IsTinzenite(path) {
		logMain("Directory is already a valid Tinzenite directory!")
		return
	}
	// get options
	peerName := getString("Enter the peer name for this Tinzenite directory:")
	userName := getString("Your username:")
	password := getString("Enter a directory password:")
	relPath := shared.CreatePathRoot(path)
	tinzenite, err := core.CreateTinzenite(relPath.LastElement(), relPath.FullPath(), peerName, userName, password)
	if err != nil {
		logMain("Creation error:", err.Error())
		return
	}
	err = tinzenite.SyncLocal()
	if err != nil {
		logMain("Initial model sync error:", err.Error())
	}
	// run tinzenite until killed
	runTinzenite(tinzenite)
}

func loadTinzenite(path string) {
	if !shared.IsTinzenite(path) {
		logMain("Directory is not a valid Tinzenite directory!")
		return
	}
	password := getString("Please enter the directory password:")
	tinzenite, err := core.LoadTinzenite(path, password)
	if err != nil {
		// TODO catch wrong password and allow retry
		logMain("Loading error:", err.Error())
		return
	}
	err = tinzenite.SyncLocal()
	if err != nil {
		logMain("Initial model sync error:", err.Error())
	}
	// run tinzenite until killed
	runTinzenite(tinzenite)
}

/*
runTinzenite runs the given Tinzenite instance.
*/
func runTinzenite(t *core.Tinzenite) {
	// do this here so that it is guaranteed to be set
	t.RegisterPeerValidation(allowPeer)
	// print important info
	address, _ := t.Address()
	fmt.Printf("Running peer <%s>.\nID: %s\n", t.Name(), address)
	// run update and sync in intervalls
	var counter int
	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt)
	for {
		select {
		case <-time.Tick(time.Duration(10) * time.Second):
			if counter >= 5 {
				log.Println("DEBUG: Model sync")
				counter = 0
				err := t.SyncRemote()
				if err != nil {
					logMain("SyncRemote error:", err.Error())
				}
				continue
			}
			log.Println("DEBUG: Update")
			counter++
			err := t.SyncLocal()
			if err != nil {
				logMain("SyncLocal error:", err.Error())
			}
		case <-c:
			// on interrupt close tinzenite
			t.Close()
			return
		} // select
	} // for
}

/*
allowPeer asks the user whether to accept the given peer.
*/
func allowPeer(address string, wantsTrust bool) bool {
	// TODO actually ask!
	log.Println("TODO: Actually ask, for now accepting everything!", address)
	return true
}
<commit_msg>corrections<commit_after>package main

/*
loadTinzenite loads an existing Tinzenite directory and runs it.
*/import (
	"fmt"
	"github.com/tinzenite/bootstrap"
	"github.com/tinzenite/core"
	"github.com/tinzenite/shared"
	"log"
	"os"
	"os/signal"
	"time"
)

func bootstrapTinzenite(path string) {
	var boot *bootstrap.Bootstrap
	var err error
	done := make(chan bool)
	if shared.IsTinzenite(path) {
		boot, err = bootstrap.Load(path, func() {
			done <- true
		})
		if err != nil {
			logMain("Bootstrap load error:", err.Error())
			return
		}
	} else {
		peerName := getString("Enter the peer name for this Tinzenite directory:")
		boot, err = bootstrap.Create(path, peerName, func() {
			done <- true
		})
		if err != nil {
			logMain("Bootstrap create error:", err.Error())
			return
		}
		// connect to:
		address := getString("Please enter the address of the peer to connect to:")
		err = boot.Start(address)
		if err != nil {
			logMain("Bootstrap start error:", err.Error())
			// return because we don't want to store a faulty bootstrap
			return
		}
		err = boot.Store()
		if err != nil {
			logMain("Bootstrap store error:", err.Error())
		}
	}
	// print information
	address, _ := boot.Address()
	fmt.Printf("Bootstrapping.\nID: %s\n", address)
	// wait for successful bootstrap
	<-done
	fmt.Println("Bootstrapping was successful. Loading Tinzenite.")
	// continue to executing the directory
	loadTinzenite(path)
}

func createTinzenite(path string) {
	if shared.IsTinzenite(path) {
		logMain("Directory is already a valid Tinzenite directory!")
		return
	}
	// get options
	peerName := getString("Enter the peer name for this Tinzenite directory:")
	userName := getString("Your username:")
	password := getString("Enter a directory password:")
	relPath := shared.CreatePathRoot(path)
	tinzenite, err := core.CreateTinzenite(relPath.LastElement(), relPath.FullPath(), peerName, userName, password)
	if err != nil {
		logMain("Creation error:", err.Error())
		return
	}
	err = tinzenite.SyncLocal()
	if err != nil {
		logMain("Initial model sync error:", err.Error())
	}
	// run tinzenite until killed
	runTinzenite(tinzenite)
}

func loadTinzenite(path string) {
	if !shared.IsTinzenite(path) {
		logMain("Directory is not a valid Tinzenite directory!")
		return
	}
	password := getString("Please enter the directory password:")
	tinzenite, err := core.LoadTinzenite(path, password)
	if err != nil {
		// TODO catch wrong password and allow retry
		logMain("Loading error:", err.Error())
		return
	}
	err = tinzenite.SyncLocal()
	if err != nil {
		logMain("Initial model sync error:", err.Error())
	}
	// run tinzenite until killed
	runTinzenite(tinzenite)
}

/*
runTinzenite runs the given Tinzenite instance.
*/
func runTinzenite(t *core.Tinzenite) {
	// do this here so that it is guaranteed to be set
	t.RegisterPeerValidation(allowPeer)
	// print important info
	address, _ := t.Address()
	fmt.Printf("Running peer <%s>.\nID: %s\n", t.Name(), address)
	// run update and sync in intervalls
	var counter int
	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt)
	for {
		select {
		case <-time.Tick(time.Duration(10) * time.Second):
			if counter >= 5 {
				// log.Println("DEBUG: Model sync")
				counter = 0
				err := t.SyncRemote()
				if err != nil {
					logMain("SyncRemote error:", err.Error())
				}
				continue
			}
			// log.Println("DEBUG: Update")
			counter++
			err := t.SyncLocal()
			if err != nil {
				logMain("SyncLocal error:", err.Error())
			}
		case <-c:
			// on interrupt close tinzenite
			t.Close()
			return
		} // select
	} // for
}

/*
allowPeer asks the user whether to accept the given peer.
*/
func allowPeer(address string, wantsTrust bool) bool {
	// TODO actually ask!
	log.Println("TODO: Actually ask, for now accepting everything!", address)
	return true
}
<|endoftext|>


<commit_before>package buildah

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"strings"

	"github.com/Sirupsen/logrus"
	"github.com/containers/storage/pkg/ioutils"
	"github.com/opencontainers/image-spec/specs-go/v1"
	"github.com/opencontainers/runtime-spec/specs-go"
	"github.com/opencontainers/runtime-tools/generate"
)

const (
	// DefaultWorkingDir is used if none was specified.
	DefaultWorkingDir = "/"
	// DefaultRuntime is the default command to use to run the container.
	DefaultRuntime = "runc"
)

// RunOptions can be used to alter how a command is run in the container.
type RunOptions struct {
	// Hostname is the hostname we set for the running container.
	Hostname string
	// Runtime is the name of the command to run.  It should accept the same arguments that runc does.
	Runtime string
	// Args adds global arguments for the runtime.
	Args []string
	// Mounts are additional mount points which we want to provide.
	Mounts []specs.Mount
}

func getExportOptions() generate.ExportOptions {
	return generate.ExportOptions{}
}

// Run runs the specified command in the container's root filesystem.
func (b *Builder) Run(command []string, options RunOptions) error {
	path, err := ioutil.TempDir(os.TempDir(), Package)
	if err != nil {
		return err
	}
	logrus.Debugf("using %q to hold bundle data", path)
	defer func() {
		if err2 := os.RemoveAll(path); err2 != nil {
			logrus.Errorf("error removing %q: %v", path, err2)
		}
	}()
	config := b.updatedConfig()
	image := v1.Image{}
	err = json.Unmarshal(config, &image)
	if err != nil {
		return err
	}
	user, err := getUser(image.Config.User)
	if err != nil {
		return err
	}
	g := generate.New()

	if image.OS != "" {
		g.SetPlatformOS(image.OS)
	}
	if image.Architecture != "" {
		g.SetPlatformArch(image.Architecture)
	}
	g.SetProcessUID(user.UID)
	g.SetProcessGID(user.GID)
	for _, envSpec := range image.Config.Env {
		env := strings.SplitN(envSpec, "=", 2)
		if len(env) > 1 {
			g.AddProcessEnv(env[0], env[1])
		}
	}
	if len(command) > 0 {
		g.SetProcessArgs(command)
	} else if len(image.Config.Cmd) != 0 {
		g.SetProcessArgs(image.Config.Cmd)
	} else if len(image.Config.Entrypoint) != 0 {
		g.SetProcessArgs(image.Config.Entrypoint)
	}
	if image.Config.WorkingDir != "" {
		g.SetProcessCwd(image.Config.WorkingDir)
	}
	if options.Hostname != "" {
		g.SetHostname(options.Hostname)
	}
	for volume := range image.Config.Volumes {
		g.AddTmpfsMount(volume, nil)
	}
	mountPoint, err := b.Mount("")
	if err != nil {
		return err
	}
	defer func() {
		if err2 := b.Unmount(); err2 != nil {
			logrus.Errorf("error unmounting container: %v", err2)
		}
	}()
	g.SetRootPath(mountPoint)
	g.SetProcessTerminal(true)
	spec := g.Spec()
	if spec.Process.Cwd == "" {
		spec.Process.Cwd = DefaultWorkingDir
	}
	if err := os.MkdirAll(filepath.Join(mountPoint, b.Workdir), 0755); err != nil {
		return fmt.Errorf("error ensuring working directory %q exists: %v)", b.Workdir, err)
	}
	mounts := options.Mounts
	for _, specMount := range spec.Mounts {
		override := false
		for _, mount := range mounts {
			if specMount.Destination == mount.Destination {
				// Already have an override for it, so skip this one.
				override = true
			}
		}
		if !override {
			mounts = append(mounts, specMount)
		}
	}
	spec.Mounts = mounts
	specbytes, err := json.Marshal(spec)
	if err != nil {
		return err
	}
	err = ioutils.AtomicWriteFile(filepath.Join(path, "config.json"), specbytes, 0600)
	if err != nil {
		return fmt.Errorf("error storing runtime configuration: %v", err)
	}
	logrus.Debugf("config = %v", string(specbytes))
	runtime := options.Runtime
	if runtime == "" {
		runtime = DefaultRuntime
	}
	args := append(options.Args, "run", "-b", path, Package+"-"+b.ContainerID)
	cmd := exec.Command(runtime, args...)
	cmd.Dir = mountPoint
	cmd.Stdin = os.Stdin
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	err = cmd.Run()
	if err != nil {
		logrus.Debugf("error running runc %v: %v", spec.Process.Args, err)
	}
	return err
}
<commit_msg>Make Run() commands share the host's network<commit_after>package buildah

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"strings"

	"github.com/Sirupsen/logrus"
	"github.com/containers/storage/pkg/ioutils"
	"github.com/opencontainers/image-spec/specs-go/v1"
	"github.com/opencontainers/runtime-spec/specs-go"
	"github.com/opencontainers/runtime-tools/generate"
)

const (
	// DefaultWorkingDir is used if none was specified.
	DefaultWorkingDir = "/"
	// DefaultRuntime is the default command to use to run the container.
	DefaultRuntime = "runc"
)

// RunOptions can be used to alter how a command is run in the container.
type RunOptions struct {
	// Hostname is the hostname we set for the running container.
	Hostname string
	// Runtime is the name of the command to run.  It should accept the same arguments that runc does.
	Runtime string
	// Args adds global arguments for the runtime.
	Args []string
	// Mounts are additional mount points which we want to provide.
	Mounts []specs.Mount
}

func getExportOptions() generate.ExportOptions {
	return generate.ExportOptions{}
}

// Run runs the specified command in the container's root filesystem.
func (b *Builder) Run(command []string, options RunOptions) error {
	path, err := ioutil.TempDir(os.TempDir(), Package)
	if err != nil {
		return err
	}
	logrus.Debugf("using %q to hold bundle data", path)
	defer func() {
		if err2 := os.RemoveAll(path); err2 != nil {
			logrus.Errorf("error removing %q: %v", path, err2)
		}
	}()
	config := b.updatedConfig()
	image := v1.Image{}
	err = json.Unmarshal(config, &image)
	if err != nil {
		return err
	}
	user, err := getUser(image.Config.User)
	if err != nil {
		return err
	}
	g := generate.New()

	if image.OS != "" {
		g.SetPlatformOS(image.OS)
	}
	if image.Architecture != "" {
		g.SetPlatformArch(image.Architecture)
	}
	g.SetProcessUID(user.UID)
	g.SetProcessGID(user.GID)
	for _, envSpec := range image.Config.Env {
		env := strings.SplitN(envSpec, "=", 2)
		if len(env) > 1 {
			g.AddProcessEnv(env[0], env[1])
		}
	}
	if len(command) > 0 {
		g.SetProcessArgs(command)
	} else if len(image.Config.Cmd) != 0 {
		g.SetProcessArgs(image.Config.Cmd)
	} else if len(image.Config.Entrypoint) != 0 {
		g.SetProcessArgs(image.Config.Entrypoint)
	}
	if image.Config.WorkingDir != "" {
		g.SetProcessCwd(image.Config.WorkingDir)
	}
	if options.Hostname != "" {
		g.SetHostname(options.Hostname)
	}
	for volume := range image.Config.Volumes {
		g.AddTmpfsMount(volume, nil)
	}
	mountPoint, err := b.Mount("")
	if err != nil {
		return err
	}
	defer func() {
		if err2 := b.Unmount(); err2 != nil {
			logrus.Errorf("error unmounting container: %v", err2)
		}
	}()
	g.SetRootPath(mountPoint)
	g.SetProcessTerminal(true)
	g.RemoveLinuxNamespace("network")
	spec := g.Spec()
	if spec.Process.Cwd == "" {
		spec.Process.Cwd = DefaultWorkingDir
	}
	if err := os.MkdirAll(filepath.Join(mountPoint, b.Workdir), 0755); err != nil {
		return fmt.Errorf("error ensuring working directory %q exists: %v)", b.Workdir, err)
	}
	mounts := options.Mounts
	for _, specMount := range spec.Mounts {
		override := false
		for _, mount := range mounts {
			if specMount.Destination == mount.Destination {
				// Already have an override for it, so skip this one.
				override = true
			}
		}
		if !override {
			mounts = append(mounts, specMount)
		}
	}
	spec.Mounts = mounts
	specbytes, err := json.Marshal(spec)
	if err != nil {
		return err
	}
	err = ioutils.AtomicWriteFile(filepath.Join(path, "config.json"), specbytes, 0600)
	if err != nil {
		return fmt.Errorf("error storing runtime configuration: %v", err)
	}
	logrus.Debugf("config = %v", string(specbytes))
	runtime := options.Runtime
	if runtime == "" {
		runtime = DefaultRuntime
	}
	args := append(options.Args, "run", "-b", path, Package+"-"+b.ContainerID)
	cmd := exec.Command(runtime, args...)
	cmd.Dir = mountPoint
	cmd.Stdin = os.Stdin
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	err = cmd.Run()
	if err != nil {
		logrus.Debugf("error running runc %v: %v", spec.Process.Args, err)
	}
	return err
}
<|endoftext|>


<commit_before>package drawer

import (
	"sync"
	"time"

	"github.com/flamingyawn/discryptord/lib/types"
)

// ParsePriceData :: Parse Price Data
func ParsePriceData(data []types.HistoTicker) types.AxesMap {
	var wg, wg2 sync.WaitGroup

	axes := types.AxesMap{
		X:        make([]time.Time, len(data)),
		Y:        make([]float64, len(data)),
		Vol:      make([]float64, len(data)),
		VolFixed: make([]float64, len(data)),
		Ymin:     10000000000.0,
		Ymax:     0.0,
		Volmin:   10000000000.0,
		Volmax:   0.0,
	}

	wg.Add(len(data))
	for i, minute := range data {
		go func(i int, minute types.HistoTicker) {
			defer wg.Done()

			axes.X[i] = time.Unix(minute.Time, 0)
			axes.Y[i] = minute.Close
			axes.Vol[i] = minute.Volumeto
			axes.VolFixed[i] = minute.Volumeto

			if axes.Y[i] < axes.Ymin {
				axes.Ymin = axes.Y[i]
			} else if axes.Y[i] > axes.Ymax {
				axes.Ymax = axes.Y[i]
			}

			if axes.Vol[i] < axes.Volmin {
				axes.Volmin = axes.Vol[i]
			} else if axes.Vol[i] > axes.Volmax {
				axes.Volmax = axes.Vol[i]
			}

		}(i, minute)
	}
	wg.Wait()

	wg2.Add(len(axes.Vol))
	for i, v := range axes.Vol {
		go func(i int, v float64) {
			defer wg2.Done()
			volRange := (axes.Volmax - axes.Volmin)
			yRange := (axes.Ymax - axes.Ymin)
			axes.Vol[i] = (((v - axes.Volmin) / volRange) * yRange) + axes.Ymin
		}(i, v)
	}
	wg2.Wait()

	return axes
}
<commit_msg>add logEnabled bool to price parser to convert prices to log<commit_after>package drawer

import (
	"math"
	"sync"
	"time"

	"github.com/flamingyawn/discryptord/lib/types"
)

// ParsePriceData :: Parse Price Data
func ParsePriceData(data []types.HistoTicker, logEnabled bool) types.AxesMap {
	var wg, wg2 sync.WaitGroup

	axes := types.AxesMap{
		X:        make([]time.Time, len(data)),
		Y:        make([]float64, len(data)),
		Vol:      make([]float64, len(data)),
		VolFixed: make([]float64, len(data)),
		Ymin:     10000000000.0,
		Ymax:     0.0,
		Volmin:   10000000000.0,
		Volmax:   0.0,
	}

	wg.Add(len(data))
	for i, minute := range data {
		go func(i int, minute types.HistoTicker) {
			defer wg.Done()

			axes.X[i] = time.Unix(minute.Time, 0)

			if logEnabled {
				if minute.Close != 0 {
					axes.Y[i] = math.Log10(minute.Close)
				} else {
					axes.Y[i] = 0
				}
				if minute.Volumeto != 0 {
					axes.Vol[i] = math.Log10(minute.Volumeto)
				} else {
					axes.Vol[i] = 0
				}
			} else {
				axes.Y[i] = minute.Close
				axes.Vol[i] = minute.Volumeto
			}

			axes.VolFixed[i] = axes.Vol[i]

			if axes.Y[i] < axes.Ymin {
				axes.Ymin = axes.Y[i]
			} else if axes.Y[i] > axes.Ymax {
				axes.Ymax = axes.Y[i]
			}

			if axes.Vol[i] < axes.Volmin {
				axes.Volmin = axes.Vol[i]
			} else if axes.Vol[i] > axes.Volmax {
				axes.Volmax = axes.Vol[i]
			}

		}(i, minute)
	}

	wg.Wait()

	wg2.Add(len(axes.Vol))
	for i, v := range axes.Vol {
		go func(i int, v float64) {
			defer wg2.Done()
			volRange := (axes.Volmax - axes.Volmin)
			yRange := (axes.Ymax - axes.Ymin)
			axes.Vol[i] = (((v - axes.Volmin) / volRange) * yRange) + axes.Ymin
		}(i, v)
	}
	wg2.Wait()

	return axes
}
<|endoftext|>