<commit_before>/*
Copyright 2018 The Knative Authors

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

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

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

package test

// crd contains functions that construct boilerplate CRD definitions.

import (
	"math/rand"
	"sync"
	"time"

	corev1 "k8s.io/api/core/v1"
	"k8s.io/apimachinery/pkg/api/resource"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

	"github.com/knative/pkg/test/logging"
	"github.com/knative/serving/pkg/apis/serving/v1alpha1"
)

// ResourceNames holds names of various resources.
type ResourceNames struct {
	Config        string
	Route         string
	Revision      string
	Service       string
	TrafficTarget string
	Domain        string
	Image         string
}

// ResourceObjects holds types of the resource objects.
type ResourceObjects struct {
	Route    *v1alpha1.Route
	Config   *v1alpha1.Configuration
	Service  *v1alpha1.Service
	Revision *v1alpha1.Revision
}

// Route returns a Route object in namespace using the route and configuration
// names in names.
func Route(namespace string, names ResourceNames) *v1alpha1.Route {
	return &v1alpha1.Route{
		ObjectMeta: metav1.ObjectMeta{
			Namespace: namespace,
			Name:      names.Route,
		},
		Spec: v1alpha1.RouteSpec{
			Traffic: []v1alpha1.TrafficTarget{{
				Name:              names.TrafficTarget,
				ConfigurationName: names.Config,
				Percent:           100,
			}},
		},
	}
}

// BlueGreenRoute returns a Route object in namespace using the route and configuration
// names in names. Traffic is split evenly between blue and green.
func BlueGreenRoute(namespace string, names, blue, green ResourceNames) *v1alpha1.Route {
	return &v1alpha1.Route{
		ObjectMeta: metav1.ObjectMeta{
			Namespace: namespace,
			Name:      names.Route,
		},
		Spec: v1alpha1.RouteSpec{
			Traffic: []v1alpha1.TrafficTarget{{
				Name:         blue.TrafficTarget,
				RevisionName: blue.Revision,
				Percent:      50,
			}, {
				Name:         green.TrafficTarget,
				RevisionName: green.Revision,
				Percent:      50,
			}},
		},
	}
}

// ConfigurationSpec returns the spec of a configuration to be used throughout different
// CRD helpers.
func ConfigurationSpec(imagePath string, options *Options) *v1alpha1.ConfigurationSpec {
	spec := &v1alpha1.ConfigurationSpec{
		RevisionTemplate: v1alpha1.RevisionTemplateSpec{
			Spec: v1alpha1.RevisionSpec{
				Container: corev1.Container{
					Image:          imagePath,
					Resources:      options.ContainerResources,
					ReadinessProbe: options.ReadinessProbe,
				},
				ContainerConcurrency: v1alpha1.RevisionContainerConcurrencyType(options.ContainerConcurrency),
			},
		},
	}

	if options.RevisionTimeoutSeconds > 0 {
		spec.RevisionTemplate.Spec.TimeoutSeconds = options.RevisionTimeoutSeconds
	}

	if options.EnvVars != nil {
		spec.RevisionTemplate.Spec.Container.Env = options.EnvVars
	}

	return spec
}

// Configuration returns a Configuration object in namespace with the name names.Config
// that uses the image specified by names.Image
func Configuration(namespace string, names ResourceNames, options *Options) *v1alpha1.Configuration {
	config := &v1alpha1.Configuration{
		ObjectMeta: metav1.ObjectMeta{
			Namespace: namespace,
			Name:      names.Config,
		},
		Spec: *ConfigurationSpec(ImagePath(names.Image), options),
	}
	if options.ContainerPorts != nil && len(options.ContainerPorts) > 0 {
		config.Spec.RevisionTemplate.Spec.Container.Ports = options.ContainerPorts
	}
	return config
}

// ConfigurationWithBuild returns a Configurtion object in the `namespace`
// with the name `names.Config` that uses the provided Build spec `build`
// and image specified by `names.Image`.
func ConfigurationWithBuild(namespace string, names ResourceNames, build *v1alpha1.RawExtension) *v1alpha1.Configuration {
	return &v1alpha1.Configuration{
		ObjectMeta: metav1.ObjectMeta{
			Namespace: namespace,
			Name:      names.Config,
		},
		Spec: v1alpha1.ConfigurationSpec{
			Build: build,
			RevisionTemplate: v1alpha1.RevisionTemplateSpec{
				Spec: v1alpha1.RevisionSpec{
					Container: corev1.Container{
						Image: ImagePath(names.Image),
					},
				},
			},
		},
	}
}

// LatestService returns a RunLatest Service object in namespace with the name names.Service
// that uses the image specified by names.Image.
func LatestService(namespace string, names ResourceNames, options *Options) *v1alpha1.Service {
	return &v1alpha1.Service{
		ObjectMeta: metav1.ObjectMeta{
			Namespace: namespace,
			Name:      names.Service,
		},
		Spec: v1alpha1.ServiceSpec{
			RunLatest: &v1alpha1.RunLatestType{
				Configuration: *ConfigurationSpec(ImagePath(names.Image), options),
			},
		},
	}
}

// LatestServiceWithResources returns a RunLatest Service object in namespace with the name names.Service
// that uses the image specified by names.Image, and small constant resources.
func LatestServiceWithResources(namespace string, names ResourceNames, options *Options) *v1alpha1.Service {
	svc := LatestService(namespace, names, options)
	svc.Spec.RunLatest.Configuration.RevisionTemplate.Spec.Container.Resources = corev1.ResourceRequirements{
		Limits: corev1.ResourceList{
			corev1.ResourceCPU:    resource.MustParse("10m"),
			corev1.ResourceMemory: resource.MustParse("50Mi"),
		},
		Requests: corev1.ResourceList{
			corev1.ResourceCPU:    resource.MustParse("10m"),
			corev1.ResourceMemory: resource.MustParse("20Mi"),
		},
	}
	return svc
}

// ReleaseService returns a Release Service object in namespace with the name names.Service that uses
// the image specified by names.Image. It also takes a list of 1-2 revisons and a rolloutPercent to be
// used to configure routing
func ReleaseService(svc *v1alpha1.Service, revisions []string, rolloutPercent int) *v1alpha1.Service {
	var config v1alpha1.ConfigurationSpec
	if svc.Spec.RunLatest != nil {
		config = svc.Spec.RunLatest.Configuration
	} else if svc.Spec.Release != nil {
		config = svc.Spec.Release.Configuration
	} else if svc.Spec.Pinned != nil {
		config = svc.Spec.Pinned.Configuration
	}
	return &v1alpha1.Service{
		ObjectMeta: svc.ObjectMeta,
		Spec: v1alpha1.ServiceSpec{
			Release: &v1alpha1.ReleaseType{
				Revisions:      revisions,
				RolloutPercent: rolloutPercent,
				Configuration:  config,
			},
		},
	}
}

// ManualService returns a Manual Service object in namespace with the name names.Service
func ManualService(svc *v1alpha1.Service) *v1alpha1.Service {
	return &v1alpha1.Service{
		ObjectMeta: svc.ObjectMeta,
		Spec: v1alpha1.ServiceSpec{
			Manual: &v1alpha1.ManualType{},
		},
	}
}

const (
	letterBytes   = "abcdefghijklmnopqrstuvwxyz"
	randSuffixLen = 8
)

// r is used by AppendRandomString to generate a random string. It is seeded with the time
// at import so the strings will be different between test runs.
var (
	r        *rand.Rand
	rndMutex *sync.Mutex
)

// once is used to initialize r
var once sync.Once

func initSeed(logger *logging.BaseLogger) func() {
	return func() {
		seed := time.Now().UTC().UnixNano()
		logger.Infof("Seeding rand.Rand with %d", seed)
		r = rand.New(rand.NewSource(seed))
		rndMutex = &sync.Mutex{}
	}
}

// AppendRandomString will generate a random string that begins with prefix. This is useful
// if you want to make sure that your tests can run at the same time against the same
// environment without conflicting. This method will seed rand with the current time when
// called for the first time.
func AppendRandomString(prefix string, logger *logging.BaseLogger) string {
	once.Do(initSeed(logger))
	suffix := make([]byte, randSuffixLen)
	rndMutex.Lock()
	for i := range suffix {
		suffix[i] = letterBytes[r.Intn(len(letterBytes))]
	}
	rndMutex.Unlock()
	return prefix + string(suffix)
}
<commit_msg>Fix a very important typo in the comment! (#2944)<commit_after>/*
Copyright 2018 The Knative Authors

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

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

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

package test

// crd contains functions that construct boilerplate CRD definitions.

import (
	"math/rand"
	"sync"
	"time"

	corev1 "k8s.io/api/core/v1"
	"k8s.io/apimachinery/pkg/api/resource"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

	"github.com/knative/pkg/test/logging"
	"github.com/knative/serving/pkg/apis/serving/v1alpha1"
)

// ResourceNames holds names of various resources.
type ResourceNames struct {
	Config        string
	Route         string
	Revision      string
	Service       string
	TrafficTarget string
	Domain        string
	Image         string
}

// ResourceObjects holds types of the resource objects.
type ResourceObjects struct {
	Route    *v1alpha1.Route
	Config   *v1alpha1.Configuration
	Service  *v1alpha1.Service
	Revision *v1alpha1.Revision
}

// Route returns a Route object in namespace using the route and configuration
// names in names.
func Route(namespace string, names ResourceNames) *v1alpha1.Route {
	return &v1alpha1.Route{
		ObjectMeta: metav1.ObjectMeta{
			Namespace: namespace,
			Name:      names.Route,
		},
		Spec: v1alpha1.RouteSpec{
			Traffic: []v1alpha1.TrafficTarget{{
				Name:              names.TrafficTarget,
				ConfigurationName: names.Config,
				Percent:           100,
			}},
		},
	}
}

// BlueGreenRoute returns a Route object in namespace using the route and configuration
// names in names. Traffic is split evenly between blue and green.
func BlueGreenRoute(namespace string, names, blue, green ResourceNames) *v1alpha1.Route {
	return &v1alpha1.Route{
		ObjectMeta: metav1.ObjectMeta{
			Namespace: namespace,
			Name:      names.Route,
		},
		Spec: v1alpha1.RouteSpec{
			Traffic: []v1alpha1.TrafficTarget{{
				Name:         blue.TrafficTarget,
				RevisionName: blue.Revision,
				Percent:      50,
			}, {
				Name:         green.TrafficTarget,
				RevisionName: green.Revision,
				Percent:      50,
			}},
		},
	}
}

// ConfigurationSpec returns the spec of a configuration to be used throughout different
// CRD helpers.
func ConfigurationSpec(imagePath string, options *Options) *v1alpha1.ConfigurationSpec {
	spec := &v1alpha1.ConfigurationSpec{
		RevisionTemplate: v1alpha1.RevisionTemplateSpec{
			Spec: v1alpha1.RevisionSpec{
				Container: corev1.Container{
					Image:          imagePath,
					Resources:      options.ContainerResources,
					ReadinessProbe: options.ReadinessProbe,
				},
				ContainerConcurrency: v1alpha1.RevisionContainerConcurrencyType(options.ContainerConcurrency),
			},
		},
	}

	if options.RevisionTimeoutSeconds > 0 {
		spec.RevisionTemplate.Spec.TimeoutSeconds = options.RevisionTimeoutSeconds
	}

	if options.EnvVars != nil {
		spec.RevisionTemplate.Spec.Container.Env = options.EnvVars
	}

	return spec
}

// Configuration returns a Configuration object in namespace with the name names.Config
// that uses the image specified by names.Image
func Configuration(namespace string, names ResourceNames, options *Options) *v1alpha1.Configuration {
	config := &v1alpha1.Configuration{
		ObjectMeta: metav1.ObjectMeta{
			Namespace: namespace,
			Name:      names.Config,
		},
		Spec: *ConfigurationSpec(ImagePath(names.Image), options),
	}
	if options.ContainerPorts != nil && len(options.ContainerPorts) > 0 {
		config.Spec.RevisionTemplate.Spec.Container.Ports = options.ContainerPorts
	}
	return config
}

// ConfigurationWithBuild returns a Configuration object in the `namespace`
// with the name `names.Config` that uses the provided Build spec `build`
// and image specified by `names.Image`.
func ConfigurationWithBuild(namespace string, names ResourceNames, build *v1alpha1.RawExtension) *v1alpha1.Configuration {
	return &v1alpha1.Configuration{
		ObjectMeta: metav1.ObjectMeta{
			Namespace: namespace,
			Name:      names.Config,
		},
		Spec: v1alpha1.ConfigurationSpec{
			Build: build,
			RevisionTemplate: v1alpha1.RevisionTemplateSpec{
				Spec: v1alpha1.RevisionSpec{
					Container: corev1.Container{
						Image: ImagePath(names.Image),
					},
				},
			},
		},
	}
}

// LatestService returns a RunLatest Service object in namespace with the name names.Service
// that uses the image specified by names.Image.
func LatestService(namespace string, names ResourceNames, options *Options) *v1alpha1.Service {
	return &v1alpha1.Service{
		ObjectMeta: metav1.ObjectMeta{
			Namespace: namespace,
			Name:      names.Service,
		},
		Spec: v1alpha1.ServiceSpec{
			RunLatest: &v1alpha1.RunLatestType{
				Configuration: *ConfigurationSpec(ImagePath(names.Image), options),
			},
		},
	}
}

// LatestServiceWithResources returns a RunLatest Service object in namespace with the name names.Service
// that uses the image specified by names.Image, and small constant resources.
func LatestServiceWithResources(namespace string, names ResourceNames, options *Options) *v1alpha1.Service {
	svc := LatestService(namespace, names, options)
	svc.Spec.RunLatest.Configuration.RevisionTemplate.Spec.Container.Resources = corev1.ResourceRequirements{
		Limits: corev1.ResourceList{
			corev1.ResourceCPU:    resource.MustParse("10m"),
			corev1.ResourceMemory: resource.MustParse("50Mi"),
		},
		Requests: corev1.ResourceList{
			corev1.ResourceCPU:    resource.MustParse("10m"),
			corev1.ResourceMemory: resource.MustParse("20Mi"),
		},
	}
	return svc
}

// ReleaseService returns a Release Service object in namespace with the name names.Service that uses
// the image specified by names.Image. It also takes a list of 1-2 revisons and a rolloutPercent to be
// used to configure routing
func ReleaseService(svc *v1alpha1.Service, revisions []string, rolloutPercent int) *v1alpha1.Service {
	var config v1alpha1.ConfigurationSpec
	if svc.Spec.RunLatest != nil {
		config = svc.Spec.RunLatest.Configuration
	} else if svc.Spec.Release != nil {
		config = svc.Spec.Release.Configuration
	} else if svc.Spec.Pinned != nil {
		config = svc.Spec.Pinned.Configuration
	}
	return &v1alpha1.Service{
		ObjectMeta: svc.ObjectMeta,
		Spec: v1alpha1.ServiceSpec{
			Release: &v1alpha1.ReleaseType{
				Revisions:      revisions,
				RolloutPercent: rolloutPercent,
				Configuration:  config,
			},
		},
	}
}

// ManualService returns a Manual Service object in namespace with the name names.Service
func ManualService(svc *v1alpha1.Service) *v1alpha1.Service {
	return &v1alpha1.Service{
		ObjectMeta: svc.ObjectMeta,
		Spec: v1alpha1.ServiceSpec{
			Manual: &v1alpha1.ManualType{},
		},
	}
}

const (
	letterBytes   = "abcdefghijklmnopqrstuvwxyz"
	randSuffixLen = 8
)

// r is used by AppendRandomString to generate a random string. It is seeded with the time
// at import so the strings will be different between test runs.
var (
	r        *rand.Rand
	rndMutex *sync.Mutex
)

// once is used to initialize r
var once sync.Once

func initSeed(logger *logging.BaseLogger) func() {
	return func() {
		seed := time.Now().UTC().UnixNano()
		logger.Infof("Seeding rand.Rand with %d", seed)
		r = rand.New(rand.NewSource(seed))
		rndMutex = &sync.Mutex{}
	}
}

// AppendRandomString will generate a random string that begins with prefix. This is useful
// if you want to make sure that your tests can run at the same time against the same
// environment without conflicting. This method will seed rand with the current time when
// called for the first time.
func AppendRandomString(prefix string, logger *logging.BaseLogger) string {
	once.Do(initSeed(logger))
	suffix := make([]byte, randSuffixLen)
	rndMutex.Lock()
	for i := range suffix {
		suffix[i] = letterBytes[r.Intn(len(letterBytes))]
	}
	rndMutex.Unlock()
	return prefix + string(suffix)
}
<|endoftext|>


<commit_before>// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public
// License along with this program. If not, see <http://www.gnu.org/licenses/>.

package veto

import (
	"github.com/nmeum/marvin/irc"
	"github.com/nmeum/marvin/modules"
	"time"
)

type Module struct {
	timer       *time.Timer
	duration    time.Duration
	DurationStr string `json:"duration"`
}

func Init(moduleSet *modules.ModuleSet) {
	moduleSet.Register(new(Module))
}

func (m *Module) Name() string {
	return "veto"
}

func (m *Module) Help() string {
	return "USAGE: !veto"
}

func (m *Module) Defaults() {
	m.DurationStr = "0h90s"
}

func (m *Module) Load(client *irc.Client) (err error) {
	m.duration, err = time.ParseDuration(m.DurationStr)
	if err != nil {
		return
	}

	client.CmdHook("privmsg", m.vetoCmd)
	return
}

func (m *Module) Start() bool {
	ret := false
	m.timer = time.AfterFunc(m.duration, func() {
		ret = true
		m.timer = nil
	})

	return ret
}

func (m *Module) vetoCmd(client *irc.Client, msg irc.Message) error {
	if msg.Data != "!veto" && m.timer != nil {
		return nil
	}

	m.timer.Stop()
	m.timer = nil

	return client.Write("NOTICE %s :%s has invoked his right to veto.",
		msg.Receiver, msg.Sender.Name)
}
<commit_msg>veto: Be more reliable<commit_after>// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public
// License along with this program. If not, see <http://www.gnu.org/licenses/>.

package veto

import (
	"github.com/nmeum/marvin/irc"
	"github.com/nmeum/marvin/modules"
	"time"
)

type Module struct {
	timer       *time.Timer
	duration    time.Duration
	DurationStr string `json:"duration"`
}

func Init(moduleSet *modules.ModuleSet) {
	moduleSet.Register(new(Module))
}

func (m *Module) Name() string {
	return "veto"
}

func (m *Module) Help() string {
	return "USAGE: !veto"
}

func (m *Module) Defaults() {
	m.DurationStr = "0h90s"
}

func (m *Module) Load(client *irc.Client) (err error) {
	m.duration, err = time.ParseDuration(m.DurationStr)
	if err != nil {
		return
	}

	client.CmdHook("privmsg", m.vetoCmd)
	return
}

func (m *Module) Start() bool {
	ret := false
	m.timer = time.AfterFunc(m.duration, func() {
		ret = true
	})

	return ret
}

func (m *Module) vetoCmd(client *irc.Client, msg irc.Message) error {
	if msg.Data != "!veto" {
		return nil
	}

	if m.timer != nil && m.timer.Stop() {
		return client.Write("NOTICE %s :%s has invoked his right to veto",
			msg.Receiver, msg.Sender.Name)
	}

	return client.Write("NOTICE %s :%s", msg.Receiver, "no vote takes place currently")
}
<|endoftext|>


<commit_before>package engines

import (
	"encoding/json"
	"errors"
	"fmt"
	"net/url"
	"os"
	"strconv"
	"time"

	log "github.com/Sirupsen/logrus"

	"github.com/camptocamp/bivac/metrics"
	"github.com/camptocamp/bivac/orchestrators"
	"github.com/camptocamp/bivac/util"
	"github.com/camptocamp/bivac/volume"
)

// ResticEngine implements a backup engine with Restic
type ResticEngine struct {
	Orchestrator orchestrators.Orchestrator
	Volume       *volume.Volume
}

// Snapshot is a struct returned by the function snapshots()
type Snapshot struct {
	Time     time.Time `json:"time"`
	Parent   string    `json:"parent"`
	Tree     string    `json:"tree"`
	Path     []string  `json:"path"`
	Hostname string    `json:"hostname"`
	ID       string    `json:"id"`
	ShortID  string    `json:"short_id"`
}

// GetName returns the engine name
func (*ResticEngine) GetName() string {
	return "Restic"
}

// Backup performs the backup of the passed volume
func (r *ResticEngine) Backup() (err error) {

	v := r.Volume

	targetURL, err := url.Parse(v.Config.TargetURL)
	if err != nil {
		err = fmt.Errorf("failed to parse target URL: %v", err)
		return
	}

	c := r.Orchestrator.GetHandler()
	v.Target = targetURL.String() + "/" + r.Orchestrator.GetPath(v)
	v.BackupDir = v.Mountpoint + "/" + v.BackupDir
	v.Mount = v.Name + ":" + v.Mountpoint + ":ro"

	err = util.Retry(3, r.init)
	if err != nil {
		err = fmt.Errorf("failed to create a secure repository: %v", err)
		r.sendBackupStatus(1, v.Name)
		return
	}

	err = util.Retry(3, r.resticBackup)
	if err != nil {
		err = fmt.Errorf("failed to backup the volume: %v", err)
		r.sendBackupStatus(1, v.Name)
		return
	}

	err = util.Retry(3, r.forget)
	if err != nil {
		err = fmt.Errorf("failed to forget the oldest snapshots: %v", err)
		r.sendBackupStatus(1, v.Name)
		return
	}

	if c.IsCheckScheduled(v) {
		err = util.Retry(3, r.verify)
		if err != nil {
			err = fmt.Errorf("failed to verify backup: %v", err)
			r.sendBackupStatus(1, v.Name)
			return err
		}
	}

	r.sendBackupStatus(0, v.Name)

	return
}

// init initialize a secure repository
func (r *ResticEngine) init() (err error) {
	v := r.Volume

	// Check if the repository already exists
	state, _, err := r.launchRestic(
		[]string{
			"-r",
			v.Target,
			"snapshots",
		},
		[]*volume.Volume{},
	)
	if err != nil {
		err = fmt.Errorf("failed to launch Restic to verify the existence of the repository: %v", err)
		return
	}
	if state == 0 {
		log.WithFields(log.Fields{
			"volume": v.Name,
		}).Info("The repository already exists, skipping initialization.")
		return nil
	}

	// Initialize the repository
	state, _, err = r.launchRestic(
		[]string{
			"-r",
			v.Target,
			"init",
		},
		[]*volume.Volume{
			v,
		},
	)
	if err != nil {
		err = fmt.Errorf("failed to launch Restic to initialize the repository: %v", err)
		return
	}
	if state != 0 {
		err = fmt.Errorf("Restic exited with state %v while initializing the repository", state)
		return
	}
	return
}

// resticBackup performs the backup of a volume with Restic
func (r *ResticEngine) resticBackup() (err error) {
	c := r.Orchestrator.GetHandler()
	v := r.Volume
	state, _, err := r.launchRestic(
		[]string{
			"--hostname",
			c.Hostname,
			"-r",
			v.Target,
			"backup",
			v.BackupDir,
		},
		[]*volume.Volume{
			v,
		},
	)
	if err != nil {
		err = fmt.Errorf("failed to launch Restic to backup the volume: %v", err)
	}
	if state != 0 {
		err = fmt.Errorf("Restic exited with state %v while backuping the volume", state)
	}

	metric := r.Volume.MetricsHandler.NewMetric("bivac_backupExitCode", "gauge")
	metric.UpdateEvent(
		&metrics.Event{
			Labels: map[string]string{
				"volume": v.Name,
			},
			Value: strconv.Itoa(state),
		},
	)
	return
}

// verify checks that the backup is usable
func (r *ResticEngine) verify() (err error) {
	v := r.Volume
	state, _, err := r.launchRestic(
		[]string{
			"-r",
			v.Target,
			"check",
		},
		[]*volume.Volume{},
	)
	if err != nil {
		err = fmt.Errorf("failed to launch Restic to check the backup: %v", err)
		return
	}
	if state == 0 {
		now := time.Now().Local()
		os.Chtimes(v.Mountpoint+"/.bivac_last_check", now, now)
	} else {
		err = fmt.Errorf("Restic exited with state %v while checking the backup", state)
	}

	metric := r.Volume.MetricsHandler.NewMetric("bivac_verifyExitCode", "gauge")
	err = metric.UpdateEvent(
		&metrics.Event{
			Labels: map[string]string{
				"volume": v.Name,
			},
			Value: strconv.Itoa(state),
		},
	)
	return
}

// forget removes a snapshot
func (r *ResticEngine) forget() (err error) {

	v := r.Volume

	snapshots, err := r.snapshots()
	if err != nil {
		return
	}
	if len(snapshots) == 0 {
		err = errors.New("No snapshots found but bucket should contains at least current backup")
		return
	}

	duration, err := util.GetDurationFromInterval(v.Config.RemoveOlderThan)
	if err != nil {
		return err
	}

	validSnapshots := 0
	now := time.Now()
	for _, snapshot := range snapshots {
		expiration := snapshot.Time.Add(duration)
		if now.Before(expiration) {
			validSnapshots++
		}
	}

	state, output, err := r.launchRestic(
		[]string{
			"-r",
			v.Target,
			"forget",
			"--prune",
			"--keep-last",
			fmt.Sprintf("%d", validSnapshots),
		},
		[]*volume.Volume{},
	)
	if err != nil {
		err = fmt.Errorf("failed to launch Restic to forget the snapshot: %v", err)
		return err
	}

	if state != 0 {
		err = fmt.Errorf("restic failed to forget old snapshots: %v", output)
		return err
	}
	return
}

// snapshots lists snapshots
func (r *ResticEngine) snapshots() (snapshots []Snapshot, err error) {
	v := r.Volume

	_, output, err := r.launchRestic(
		[]string{
			"-r",
			v.Target,
			"snapshots",
			"--json",
		},
		[]*volume.Volume{},
	)
	if err != nil {
		err = fmt.Errorf("failed to launch Restic to check the backup: %v", err)
		return
	}

	if err := json.Unmarshal([]byte(output), &snapshots); err != nil {
		err = fmt.Errorf("failed to parse JSON output: %v", err)
		return snapshots, err
	}
	return
}

// sendBackupStatus creates a metric which represents the backup status. 0 == OK / 1 == KO
func (r *ResticEngine) sendBackupStatus(status int, volume string) {
	metric := r.Volume.MetricsHandler.NewMetric("bivac_backupExitCode", "gauge")
	err := metric.UpdateEvent(
		&metrics.Event{
			Labels: map[string]string{
				"volume": volume,
			},
			Value: strconv.Itoa(status),
		},
	)
	if err != nil {
		log.Errorf("failed to send metric: %v", err)
	}
}

// launchRestic starts a restic container with the given command
func (r *ResticEngine) launchRestic(cmd []string, volumes []*volume.Volume) (state int, stdout string, err error) {
	config := r.Orchestrator.GetHandler().Config
	image := config.Restic.Image

	// Disable cache to avoid volume issues with Kubernetes
	cmd = append(cmd, "--no-cache")

	env := map[string]string{
		"AWS_ACCESS_KEY_ID":      config.AWS.AccessKeyID,
		"AWS_SECRET_ACCESS_KEY":  config.AWS.SecretAccessKey,
		"OS_USERNAME":            config.Swift.Username,
		"OS_PASSWORD":            config.Swift.Password,
		"OS_AUTH_URL":            config.Swift.AuthURL,
		"OS_TENANT_NAME":         config.Swift.TenantName,
		"OS_REGION_NAME":         config.Swift.RegionName,
		"OS_USER_DOMAIN_NAME":    config.Swift.UserDomainName,
		"OS_PROJECT_NAME":        config.Swift.ProjectName,
		"OS_PROJECT_DOMAIN_NAME": config.Swift.ProjectDomainName,
		"RESTIC_PASSWORD":        config.Restic.Password,
	}

	for k, v := range config.ExtraEnv {
		env[k] = v
	}

	return r.Orchestrator.LaunchContainer(image, env, cmd, volumes)
}
<commit_msg>Check last backup date from bucket (#225)<commit_after>package engines

import (
	"encoding/json"
	"errors"
	"fmt"
	"net/url"
	"os"
	"strconv"
	"time"

	log "github.com/Sirupsen/logrus"

	"github.com/camptocamp/bivac/metrics"
	"github.com/camptocamp/bivac/orchestrators"
	"github.com/camptocamp/bivac/util"
	"github.com/camptocamp/bivac/volume"
)

// ResticEngine implements a backup engine with Restic
type ResticEngine struct {
	Orchestrator orchestrators.Orchestrator
	Volume       *volume.Volume
}

// Snapshot is a struct returned by the function snapshots()
type Snapshot struct {
	Time     time.Time `json:"time"`
	Parent   string    `json:"parent"`
	Tree     string    `json:"tree"`
	Path     []string  `json:"path"`
	Hostname string    `json:"hostname"`
	ID       string    `json:"id"`
	ShortID  string    `json:"short_id"`
}

// GetName returns the engine name
func (*ResticEngine) GetName() string {
	return "Restic"
}

// Backup performs the backup of the passed volume
func (r *ResticEngine) Backup() (err error) {

	v := r.Volume

	targetURL, err := url.Parse(v.Config.TargetURL)
	if err != nil {
		err = fmt.Errorf("failed to parse target URL: %v", err)
		return
	}

	c := r.Orchestrator.GetHandler()
	v.Target = targetURL.String() + "/" + r.Orchestrator.GetPath(v)
	v.BackupDir = v.Mountpoint + "/" + v.BackupDir
	v.Mount = v.Name + ":" + v.Mountpoint + ":ro"

	err = util.Retry(3, r.init)
	if err != nil {
		err = fmt.Errorf("failed to create a secure repository: %v", err)
		r.sendBackupStatus(1, v.Name)
		return
	}

	err = util.Retry(3, r.resticBackup)
	if err != nil {
		err = fmt.Errorf("failed to backup the volume: %v", err)
		r.sendBackupStatus(1, v.Name)
		return
	}

	err = util.Retry(3, r.forget)
	if err != nil {
		err = fmt.Errorf("failed to forget the oldest snapshots: %v", err)
		r.sendBackupStatus(1, v.Name)
		return
	}

	if c.IsCheckScheduled(v) {
		err = util.Retry(3, r.verify)
		if err != nil {
			err = fmt.Errorf("failed to verify backup: %v", err)
			r.sendBackupStatus(1, v.Name)
			return
		}
	}

	r.sendBackupStatus(0, v.Name)

	return
}

// init initialize a secure repository
func (r *ResticEngine) init() (err error) {
	v := r.Volume

	// Check if the repository already exists
	state, _, err := r.launchRestic(
		[]string{
			"-r",
			v.Target,
			"snapshots",
		},
		[]*volume.Volume{},
	)
	if err != nil {
		err = fmt.Errorf("failed to launch Restic to verify the existence of the repository: %v", err)
		return
	}
	if state == 0 {
		log.WithFields(log.Fields{
			"volume": v.Name,
		}).Info("The repository already exists, skipping initialization.")
		return nil
	}

	// Initialize the repository
	state, _, err = r.launchRestic(
		[]string{
			"-r",
			v.Target,
			"init",
		},
		[]*volume.Volume{
			v,
		},
	)
	if err != nil {
		err = fmt.Errorf("failed to launch Restic to initialize the repository: %v", err)
		return
	}
	if state != 0 {
		err = fmt.Errorf("Restic exited with state %v while initializing the repository", state)
		return
	}
	return
}

// resticBackup performs the backup of a volume with Restic
func (r *ResticEngine) resticBackup() (err error) {
	c := r.Orchestrator.GetHandler()
	v := r.Volume
	state, _, err := r.launchRestic(
		[]string{
			"--hostname",
			c.Hostname,
			"-r",
			v.Target,
			"backup",
			v.BackupDir,
		},
		[]*volume.Volume{
			v,
		},
	)
	if err != nil {
		err = fmt.Errorf("failed to launch Restic to backup the volume: %v", err)
	}
	if state != 0 {
		err = fmt.Errorf("Restic exited with state %v while backuping the volume", state)
	}

	metric := r.Volume.MetricsHandler.NewMetric("bivac_backupExitCode", "gauge")
	metric.UpdateEvent(
		&metrics.Event{
			Labels: map[string]string{
				"volume": v.Name,
			},
			Value: strconv.Itoa(state),
		},
	)
	return
}

// verify checks that the backup is usable
func (r *ResticEngine) verify() (err error) {
	v := r.Volume
	state, _, err := r.launchRestic(
		[]string{
			"-r",
			v.Target,
			"check",
		},
		[]*volume.Volume{},
	)
	if err != nil {
		err = fmt.Errorf("failed to launch Restic to check the backup: %v", err)
		return
	}
	if state == 0 {
		now := time.Now().Local()
		os.Chtimes(v.Mountpoint+"/.bivac_last_check", now, now)
	} else {
		err = fmt.Errorf("Restic exited with state %v while checking the backup", state)
	}

	metric := r.Volume.MetricsHandler.NewMetric("bivac_verifyExitCode", "gauge")
	err = metric.UpdateEvent(
		&metrics.Event{
			Labels: map[string]string{
				"volume": v.Name,
			},
			Value: strconv.Itoa(state),
		},
	)
	return
}

// forget removes a snapshot
func (r *ResticEngine) forget() (err error) {

	v := r.Volume

	snapshots, err := r.snapshots()
	if err != nil {
		return
	}
	if len(snapshots) == 0 {
		err = errors.New("No snapshots found but bucket should contains at least current backup")
		return
	}

	// Send last backup date to pushgateway
	metric := r.Volume.MetricsHandler.NewMetric("bivac_lastBackup", "counter")
	metric.UpdateEvent(
		&metrics.Event{
			Labels: map[string]string{
				"volume": v.Name,
			},
			Value: strconv.FormatInt(snapshots[len(snapshots)-1].Time.Unix(), 10),
		},
	)

	// Send oldest backup date to pushgateway
	metric = r.Volume.MetricsHandler.NewMetric("bivac_oldestBackup", "counter")
	metric.UpdateEvent(
		&metrics.Event{
			Labels: map[string]string{
				"volume": v.Name,
			},
			Value: strconv.FormatInt(snapshots[0].Time.Unix(), 10),
		},
	)

	// Send snapshots count to pushgateway
	metric = r.Volume.MetricsHandler.NewMetric("bivac_backupCount", "gauge")
	metric.UpdateEvent(
		&metrics.Event{
			Labels: map[string]string{
				"volume": v.Name,
			},
			Value: strconv.FormatInt(int64(len(snapshots)), 10),
		},
	)

	duration, err := util.GetDurationFromInterval(v.Config.RemoveOlderThan)
	if err != nil {
		return err
	}

	validSnapshots := 0
	now := time.Now()
	for _, snapshot := range snapshots {
		expiration := snapshot.Time.Add(duration)
		if now.Before(expiration) {
			validSnapshots++
		}
	}

	state, output, err := r.launchRestic(
		[]string{
			"-r",
			v.Target,
			"forget",
			"--prune",
			"--keep-last",
			fmt.Sprintf("%d", validSnapshots),
		},
		[]*volume.Volume{},
	)
	if err != nil {
		err = fmt.Errorf("failed to launch Restic to forget the snapshot: %v", err)
		return err
	}

	if state != 0 {
		err = fmt.Errorf("restic failed to forget old snapshots: %v", output)
		return err
	}
	return
}

// snapshots lists snapshots
func (r *ResticEngine) snapshots() (snapshots []Snapshot, err error) {
	v := r.Volume

	_, output, err := r.launchRestic(
		[]string{
			"-r",
			v.Target,
			"snapshots",
			"--json",
		},
		[]*volume.Volume{},
	)
	if err != nil {
		err = fmt.Errorf("failed to launch Restic to check the backup: %v", err)
		return
	}

	if err := json.Unmarshal([]byte(output), &snapshots); err != nil {
		err = fmt.Errorf("failed to parse JSON output: %v", err)
		return snapshots, err
	}
	return
}

// sendBackupStatus creates a metric which represents the backup status. 0 == OK / 1 == KO
func (r *ResticEngine) sendBackupStatus(status int, volume string) {
	metric := r.Volume.MetricsHandler.NewMetric("bivac_backupExitCode", "gauge")
	err := metric.UpdateEvent(
		&metrics.Event{
			Labels: map[string]string{
				"volume": volume,
			},
			Value: strconv.Itoa(status),
		},
	)
	if err != nil {
		log.Errorf("failed to send metric: %v", err)
	}
}

// launchRestic starts a restic container with the given command
func (r *ResticEngine) launchRestic(cmd []string, volumes []*volume.Volume) (state int, stdout string, err error) {
	config := r.Orchestrator.GetHandler().Config
	image := config.Restic.Image

	// Disable cache to avoid volume issues with Kubernetes
	cmd = append(cmd, "--no-cache")

	env := map[string]string{
		"AWS_ACCESS_KEY_ID":      config.AWS.AccessKeyID,
		"AWS_SECRET_ACCESS_KEY":  config.AWS.SecretAccessKey,
		"OS_USERNAME":            config.Swift.Username,
		"OS_PASSWORD":            config.Swift.Password,
		"OS_AUTH_URL":            config.Swift.AuthURL,
		"OS_TENANT_NAME":         config.Swift.TenantName,
		"OS_REGION_NAME":         config.Swift.RegionName,
		"OS_USER_DOMAIN_NAME":    config.Swift.UserDomainName,
		"OS_PROJECT_NAME":        config.Swift.ProjectName,
		"OS_PROJECT_DOMAIN_NAME": config.Swift.ProjectDomainName,
		"RESTIC_PASSWORD":        config.Restic.Password,
	}

	for k, v := range config.ExtraEnv {
		env[k] = v
	}

	return r.Orchestrator.LaunchContainer(image, env, cmd, volumes)
}
<|endoftext|>


<commit_before>package eval

import (
	"time"

	"github.com/gansoi/gansoi/checks"
	"github.com/gansoi/gansoi/database"
	"github.com/gansoi/gansoi/logger"
)

type (
	// Evaluator will evaluate check results from all nodes on the leader node.
	Evaluator struct {
		db            database.ReadWriter
		historyLength int
	}
)

// NewEvaluator will instantiate a new Evaluator listening to cluster changes,
// and evaluating results as they arrive.
func NewEvaluator(db database.ReadWriter) *Evaluator {
	e := &Evaluator{
		db:            db,
		historyLength: 5,
	}

	return e
}

func statesFromHistory(history []checks.CheckResult) States {
	var states States
	for _, result := range history {
		state := StateDown

		if result.Error == "" {
			state = StateUp
		}

		states = append(states, state)
	}

	return states
}

// evaluate will FIXME
func (e *Evaluator) evaluate(checkResult *checks.CheckResult) (*Evaluation, error) {
	clock := time.Now()

	// Get latest evaluation.
	eval, _ := LatestEvaluation(e.db, checkResult)
	if eval == nil {
		eval = NewEvaluation(clock, checkResult)
	}
	eval.End = clock

	// Get historyLength checkResults.
	var history []checks.CheckResult
	e.db.Find("CheckHostID", checkResult.CheckHostID, &history, e.historyLength, 0, true)

	if len(history) < e.historyLength {
		logger.Debug("evaluator", "Not enough history for %s yet", checkResult.CheckHostID)
	}

	eval.History = statesFromHistory(history)

	state := StateUnknown
	if len(history) == e.historyLength {
		state = eval.History.Reduce()
	}

	// If the state has changed, we allocate a new evaluation and end the old.
	if eval.State != state {
		e.db.Save(eval)

		nextEval := NewEvaluation(clock, checkResult)
		nextEval.State = state
		nextEval.History = eval.History

		eval = nextEval
	}

	logger.Debug("eval", "%s: %s (%s) %v", eval.CheckHostID, eval.History.Reduce().ColorString(), eval.End.Sub(eval.Start).String(), eval.History)

	return eval, e.db.Save(eval)
}

// PostApply implements databse.Listener.
func (e *Evaluator) PostApply(leader bool, command database.Command, data interface{}) {
	// If we're not the leader, we abort. Only the leader should evaluate
	// check results.
	if !leader {
		return
	}

	// We're only interested in saves for now.
	if command != database.CommandSave {
		return
	}

	switch data.(type) {
	case *checks.CheckResult:
		e.evaluate(data.(*checks.CheckResult))
	}
}
<commit_msg>Debug colors :)<commit_after>package eval

import (
	"time"

	"github.com/gansoi/gansoi/checks"
	"github.com/gansoi/gansoi/database"
	"github.com/gansoi/gansoi/logger"
)

type (
	// Evaluator will evaluate check results from all nodes on the leader node.
	Evaluator struct {
		db            database.ReadWriter
		historyLength int
	}
)

// NewEvaluator will instantiate a new Evaluator listening to cluster changes,
// and evaluating results as they arrive.
func NewEvaluator(db database.ReadWriter) *Evaluator {
	e := &Evaluator{
		db:            db,
		historyLength: 5,
	}

	return e
}

func statesFromHistory(history []checks.CheckResult) States {
	var states States
	for _, result := range history {
		state := StateDown

		if result.Error == "" {
			state = StateUp
		}

		states = append(states, state)
	}

	return states
}

// evaluate will FIXME
func (e *Evaluator) evaluate(checkResult *checks.CheckResult) (*Evaluation, error) {
	clock := time.Now()

	// Get latest evaluation.
	eval, _ := LatestEvaluation(e.db, checkResult)
	if eval == nil {
		eval = NewEvaluation(clock, checkResult)
	}
	eval.End = clock

	// Get historyLength checkResults.
	var history []checks.CheckResult
	e.db.Find("CheckHostID", checkResult.CheckHostID, &history, e.historyLength, 0, true)

	if len(history) < e.historyLength {
		logger.Debug("evaluator", "Not enough history for %s yet", checkResult.CheckHostID)
	}

	eval.History = statesFromHistory(history)

	state := StateUnknown
	if len(history) == e.historyLength {
		state = eval.History.Reduce()
	}

	// If the state has changed, we allocate a new evaluation and end the old.
	if eval.State != state {
		e.db.Save(eval)

		nextEval := NewEvaluation(clock, checkResult)
		nextEval.State = state
		nextEval.History = eval.History

		eval = nextEval
	}

	logger.Debug("eval", "%s: %s (%s) %s", eval.CheckHostID, eval.History.Reduce().ColorString(), eval.End.Sub(eval.Start).String(), eval.History.ColorString())

	return eval, e.db.Save(eval)
}

// PostApply implements databse.Listener.
func (e *Evaluator) PostApply(leader bool, command database.Command, data interface{}) {
	// If we're not the leader, we abort. Only the leader should evaluate
	// check results.
	if !leader {
		return
	}

	// We're only interested in saves for now.
	if command != database.CommandSave {
		return
	}

	switch data.(type) {
	case *checks.CheckResult:
		e.evaluate(data.(*checks.CheckResult))
	}
}
<|endoftext|>


<commit_before>package testSuit

import (
	"bytes"
	"image"
	"image/color"
	"image/gif"
	"image/jpeg"
	"image/png"
	"io"
	"math/rand"
	"mime/multipart"
	"net/http"
	"net/http/httptest"
	"net/url"
	"strings"
	"time"

	"github.com/gin-gonic/gin"
	"github.com/google/uuid"
)

// TestSuit http api 테스트 형식
type TestSuit struct {
	Method      string
	URL         string
	Data        url.Values
	Buffer      io.Reader
	ContentType string
	r           *gin.Engine
}

// Do 테스트 실행
func (ts *TestSuit) Do(handler gin.HandlerFunc) (*httptest.ResponseRecorder, *httptest.ResponseRecorder) {
	var req *http.Request

	if ts.ContentType == "" {
		ts.ContentType = "application/x-www-form-urlencoded"
	}

	if ts.Method == "ALL" {
		if ts.Data != nil {
			encodedData := ts.Data.Encode()

			reqGet, _ := http.NewRequest("GET", ts.URL, nil)
			reqGet.Header.Add("Content-Type", ts.ContentType)
			reqGet.URL.RawQuery = encodedData

			reqPost, _ := http.NewRequest("POST", ts.URL,
				strings.NewReader(encodedData))
			reqPost.Header.Add("Content-Type", ts.ContentType)

			respGet := httptest.NewRecorder()
			respPost := httptest.NewRecorder()
			ts.r.ServeHTTP(respGet, reqGet)
			ts.r.ServeHTTP(respPost, reqPost)

			return respGet, respPost
		}

		req, _ = http.NewRequest(ts.Method, ts.URL, nil)
		req.Header.Add("Content-Type", ts.ContentType)

	} else {
		if ts.Data != nil {

			switch ts.Method {
			case "GET":
				req, _ = http.NewRequest(ts.Method, ts.URL, nil)
				req.URL.RawQuery = ts.Data.Encode()
				req.Header.Add("Content-Type", ts.ContentType)
			case "POST":
				req, _ = http.NewRequest(ts.Method, ts.URL,
					strings.NewReader(ts.Data.Encode()))
				req.Header.Add("Content-Type", ts.ContentType)
			}

		} else if ts.Buffer != nil {
			req, _ = http.NewRequest(ts.Method, ts.URL, ts.Buffer)
			req.Header.Add("Content-Type", ts.ContentType)
		} else {
			req, _ = http.NewRequest(ts.Method, ts.URL, nil)
			req.Header.Add("Content-Type", ts.ContentType)
		}
	}

	resp := httptest.NewRecorder()
	ts.r.ServeHTTP(resp, req)
	return resp, nil
}

func getGinEngine() *gin.Engine {
	gin.SetMode(gin.TestMode)
	r := gin.New()

	return r
}

func genImage(ext string, width, height int) (*bytes.Buffer, string, error) {
	rand.Seed(time.Now().UTC().UnixNano())

	img := image.NewRGBA(image.Rect(0, 0, width, height))
	for x := 0; x < width; x++ {
		for y := 0; y < height; y++ {
			img.Set(x, y, color.RGBA{
				uint8(rand.Intn(255)),
				uint8(rand.Intn(255)),
				uint8(rand.Intn(255)),
				uint8(rand.Intn(255)),
			})
		}
	}

	nameFix := uuid.New().URN()
	buffer := &bytes.Buffer{}
	bufferWriter := multipart.NewWriter(buffer)
	formWriter, err := bufferWriter.CreateFormFile("file", nameFix+".png")
	contentType := bufferWriter.FormDataContentType()

	switch ext {
	case "png":
		png.Encode(formWriter, img)
		bufferWriter.Close()
	case "jpg":
		jpeg.Encode(formWriter, img, nil)
		bufferWriter.Close()
	case "gif":
		gif.Encode(formWriter, img, nil)
		bufferWriter.Close()
	}
	return buffer, contentType, err
}
<commit_msg>export func<commit_after>package testSuit

import (
	"bytes"
	"image"
	"image/color"
	"image/gif"
	"image/jpeg"
	"image/png"
	"io"
	"math/rand"
	"mime/multipart"
	"net/http"
	"net/http/httptest"
	"net/url"
	"strings"
	"time"

	"github.com/gin-gonic/gin"
	"github.com/google/uuid"
)

// TestSuit http request test form
type TestSuit struct {
	Method      string
	URL         string
	Data        url.Values
	Buffer      io.Reader
	ContentType string
	r           *gin.Engine
}

// Do start test
func (ts *TestSuit) Do(handler gin.HandlerFunc) (*httptest.ResponseRecorder, *httptest.ResponseRecorder) {
	var req *http.Request

	if ts.ContentType == "" {
		ts.ContentType = "application/x-www-form-urlencoded"
	}

	if ts.Method == "ALL" {
		if ts.Data != nil {
			encodedData := ts.Data.Encode()

			reqGet, _ := http.NewRequest("GET", ts.URL, nil)
			reqGet.Header.Add("Content-Type", ts.ContentType)
			reqGet.URL.RawQuery = encodedData

			reqPost, _ := http.NewRequest("POST", ts.URL,
				strings.NewReader(encodedData))
			reqPost.Header.Add("Content-Type", ts.ContentType)

			respGet := httptest.NewRecorder()
			respPost := httptest.NewRecorder()
			ts.r.ServeHTTP(respGet, reqGet)
			ts.r.ServeHTTP(respPost, reqPost)

			return respGet, respPost
		}

		req, _ = http.NewRequest(ts.Method, ts.URL, nil)
		req.Header.Add("Content-Type", ts.ContentType)

	} else {
		if ts.Data != nil {

			switch ts.Method {
			case "GET":
				req, _ = http.NewRequest(ts.Method, ts.URL, nil)
				req.URL.RawQuery = ts.Data.Encode()
				req.Header.Add("Content-Type", ts.ContentType)
			case "POST":
				req, _ = http.NewRequest(ts.Method, ts.URL,
					strings.NewReader(ts.Data.Encode()))
				req.Header.Add("Content-Type", ts.ContentType)
			}

		} else if ts.Buffer != nil {
			req, _ = http.NewRequest(ts.Method, ts.URL, ts.Buffer)
			req.Header.Add("Content-Type", ts.ContentType)
		} else {
			req, _ = http.NewRequest(ts.Method, ts.URL, nil)
			req.Header.Add("Content-Type", ts.ContentType)
		}
	}

	resp := httptest.NewRecorder()
	ts.r.ServeHTTP(resp, req)
	return resp, nil
}

// GetGinEngine create gin.Engine with test mode
func GetGinEngine() *gin.Engine {
	gin.SetMode(gin.TestMode)
	r := gin.New()

	return r
}

// GenImage generate randomize image
func GenImage(ext string, width, height int) (*bytes.Buffer, string, error) {
	rand.Seed(time.Now().UTC().UnixNano())

	img := image.NewRGBA(image.Rect(0, 0, width, height))
	for x := 0; x < width; x++ {
		for y := 0; y < height; y++ {
			img.Set(x, y, color.RGBA{
				uint8(rand.Intn(255)),
				uint8(rand.Intn(255)),
				uint8(rand.Intn(255)),
				uint8(rand.Intn(255)),
			})
		}
	}

	nameFix := uuid.New().URN()
	buffer := &bytes.Buffer{}
	bufferWriter := multipart.NewWriter(buffer)
	formWriter, err := bufferWriter.CreateFormFile("file", nameFix+".png")
	contentType := bufferWriter.FormDataContentType()

	switch ext {
	case "png":
		png.Encode(formWriter, img)
		bufferWriter.Close()
	case "jpg":
		jpeg.Encode(formWriter, img, nil)
		bufferWriter.Close()
	case "gif":
		gif.Encode(formWriter, img, nil)
		bufferWriter.Close()
	}
	return buffer, contentType, err
}
<|endoftext|>


<commit_before>// Copyright 2015 Martin Gallagher. All rights reserved.
// Use of this source code is governed by the Apache License,
// Version 2.0 that can be found in the LICENSE file.

package main

import (
	"log"
	"net/http"
	"os"
	"os/signal"
	"syscall"

	// Local
	"./website"

	// External
	"github.com/martingallagher/routify/router"
)

func main() {
	http.HandleFunc("/", globalHandler)

	addr := "0.0.0.0:1337"

	// Fire up goroutine so we can capture signals
	go func() {
		log.Fatal(http.ListenAndServe(addr, nil))
	}()

	log.Printf("server started: http://%s", addr)

	// Capture signals e.g. CTRL+C
	sig := make(chan os.Signal, 1)

	signal.Notify(sig, os.Interrupt, syscall.SIGTERM)

	// Wait for signal
	<-sig
}

func globalHandler(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-type", "text/plain; charset=utf-8")

	h, p, err := website.Routes.Get(r)

	if err != nil {
		if e, ok := err.(*router.Error); ok {
			w.WriteHeader(e.StatusCode())
			w.Write([]byte(e.Error()))
		} else {
			w.WriteHeader(http.StatusInternalServerError)
			w.Write([]byte("Wups, internal error!"))
		}

		return
	}

	h(w, r, p)
}
<commit_msg>Leverage ServeHTTP() - greatly simplifies the example code.<commit_after>// Copyright 2015 Martin Gallagher. All rights reserved.
// Use of this source code is governed by the Apache License,
// Version 2.0 that can be found in the LICENSE file.

package main

import (
	"log"
	"net/http"
	"os"
	"os/signal"
	"syscall"
	"time"

	"./website"
)

func main() {
	addr := "0.0.0.0:1337"
	server := &http.Server{
		Addr:         addr,
		Handler:      website.Routes,
		ReadTimeout:  5 * time.Second,
		WriteTimeout: 5 * time.Second,
	}

	// Fire up goroutine so we can capture signals
	go func() {
		log.Fatal(server.ListenAndServe())
	}()

	log.Printf("server started: http://%s", addr)

	// Capture signals e.g. CTRL+C
	sig := make(chan os.Signal, 1)

	signal.Notify(sig, os.Interrupt, syscall.SIGTERM)

	// Wait for signal
	<-sig
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"regexp"
	"strconv"
	"strings"

	"github.com/fatih/color"
	"github.com/jinzhu/now"
	"github.com/peterh/liner"
	"github.com/pkg/errors"
	"github.com/urfave/cli"

	"github.com/lukasdietrich/todo/model"
)

var (
	duePattern      = regexp.MustCompile(`(?i)\s*\bdue\s+(\S+)$`)
	keywordsPattern = regexp.MustCompile(`(\+\S+)\b`)
)

func CmdList(db *database) cli.Command {
	return cli.Command{
		Name:  "list",
		Usage: "List pending tasks",
		Action: func(c *cli.Context) error {
			var list []model.Task
			if err := db.pending().Find(&list).Error; err != nil {
				return err
			}

			for i, task := range list {
				check := ' '
				if task.Completed != nil {
					check = 'x'
				}

				desc := keywordsPattern.ReplaceAllStringFunc(task.Description,
					func(s string) string {
						return color.MagentaString("%s", s)
					})

				due := formatDueDate(task.Due.Time(), true)

				fmt.Printf("%s %s %s %s\n",
					color.CyanString("%2d", i+1),
					color.YellowString("(%c)", check),
					color.CyanString("%11s", due),
					desc,
				)
			}

			return nil
		},
	}
}

func CmdAdd(db *database) cli.Command {
	return cli.Command{
		Name:      "add",
		Usage:     "Add a new task",
		ArgsUsage: "[description] [due ...]",
		Action: func(c *cli.Context) error {
			content, err := parseInput(strings.Join(c.Args(), " "))
			if err != nil {
				return err
			}

			now := model.Now()
			task := model.Task{
				ID: model.NewGUID(),
				Metadata: model.Metadata{
					Created:  now,
					Modified: now,
				},
				Content: *content,
			}

			if err := db.Create(task).Error; err != nil {
				return errors.Wrap(err, "could not save task")
			}

			fmt.Printf("added task <%s>\n",
				color.CyanString("%s", task.ID))
			return nil
		},
	}
}

func CmdEdit(db *database) cli.Command {
	return cli.Command{
		Name:      "edit",
		Usage:     "Edit an existing task",
		ArgsUsage: "[task number]",
		Action: func(c *cli.Context) error {
			task, err := findTask(db, c.Args())
			if err != nil {
				return err
			}

			line := liner.NewLiner()
			line.SetCtrlCAborts(true)

			defer line.Close()

			taskString := fmt.Sprintf("%s due %s",
				task.Description,
				formatDueDate(task.Due.Time(), false))

			input, err := line.PromptWithSuggestion("", taskString, -1)
			if err != nil {
				return errors.Wrap(err, "edit canceled")
			}

			edited, err := parseInput(input)
			if err != nil {
				return err
			}

			update := model.Task{
				Metadata: model.Metadata{
					Modified: model.Now(),
				},
				Content: *edited,
			}

			err = db.Model(task).Updates(&update).Error
			if err != nil {
				return errors.Wrap(err, "could not update task")
			}

			fmt.Printf("edited task <%s>\n",
				color.CyanString("%s", task.ID))
			return nil
		},
	}
}

func CmdDo(db *database) cli.Command {
	return cli.Command{
		Name:      "do",
		Usage:     "Mark a task as completed",
		ArgsUsage: "[task number]",
		Action: func(c *cli.Context) error {
			task, err := findTask(db, c.Args())
			if err != nil {
				return err
			}

			if task.Completed != nil {
				return errors.New("task already completed")
			}

			now := model.Now()
			err = db.Model(&task).Updates(&model.Metadata{Completed: &now}).Error
			if err != nil {
				return errors.Wrap(err, "could not update task")
			}

			fmt.Printf("marked as completed <%s>\n",
				color.CyanString("%s", task.ID))
			return nil
		},
	}
}

func CmdArchive(db *database) cli.Command {
	return cli.Command{
		Name:  "archive",
		Usage: "Archive completed tasks",
		Action: func(c *cli.Context) error {
			res := db.Model(&model.Task{}).
				Where("archived is null").
				Where("completed is not null").
				UpdateColumn("archived", model.Now())
			if err := res.Error; err != nil {
				return errors.Wrap(err, "could not archive tasks")
			}

			fmt.Printf("%s tasks archived\n",
				color.CyanString("%d", res.RowsAffected))
			return nil
		},
	}
}

func parseInput(input string) (*model.Content, error) {
	var (
		index   = duePattern.FindStringSubmatchIndex(input)
		content = model.Content{
			Description: input,
			Due:         model.FromTime(now.EndOfDay()),
		}
	)

	if len(index) == 4 {
		due, err := parseDueDate(input[index[2]:])
		if err != nil {
			return nil, errors.Wrap(err, "invalid due date")
		}

		content.Due = model.FromTime(due)
		content.Description = input[:index[0]]
	}

	return &content, nil
}

func findTask(db *database, args []string) (*model.Task, error) {
	if len(args) < 1 {
		return nil, errors.New("too few arguments")
	}

	num, err := strconv.Atoi(args[0])
	if err != nil {
		return nil, errors.Wrap(err, "could not parse task number")
	}

	var task model.Task
	err = db.pending().
		Offset(num - 1).
		Limit(1).
		First(&task).
		Error

	return &task, err
}
<commit_msg>Add alias `ls` for `list`<commit_after>package main

import (
	"fmt"
	"regexp"
	"strconv"
	"strings"

	"github.com/fatih/color"
	"github.com/jinzhu/now"
	"github.com/peterh/liner"
	"github.com/pkg/errors"
	"github.com/urfave/cli"

	"github.com/lukasdietrich/todo/model"
)

var (
	duePattern      = regexp.MustCompile(`(?i)\s*\bdue\s+(\S+)$`)
	keywordsPattern = regexp.MustCompile(`(\+\S+)\b`)
)

func CmdList(db *database) cli.Command {
	return cli.Command{
		Name:    "list",
		Aliases: []string{"ls"},
		Usage:   "List pending tasks",
		Action: func(c *cli.Context) error {
			var list []model.Task
			if err := db.pending().Find(&list).Error; err != nil {
				return err
			}

			for i, task := range list {
				check := ' '
				if task.Completed != nil {
					check = 'x'
				}

				desc := keywordsPattern.ReplaceAllStringFunc(task.Description,
					func(s string) string {
						return color.MagentaString("%s", s)
					})

				due := formatDueDate(task.Due.Time(), true)

				fmt.Printf("%s %s %s %s\n",
					color.CyanString("%2d", i+1),
					color.YellowString("(%c)", check),
					color.CyanString("%11s", due),
					desc,
				)
			}

			return nil
		},
	}
}

func CmdAdd(db *database) cli.Command {
	return cli.Command{
		Name:      "add",
		Usage:     "Add a new task",
		ArgsUsage: "[description] [due ...]",
		Action: func(c *cli.Context) error {
			content, err := parseInput(strings.Join(c.Args(), " "))
			if err != nil {
				return err
			}

			now := model.Now()
			task := model.Task{
				ID: model.NewGUID(),
				Metadata: model.Metadata{
					Created:  now,
					Modified: now,
				},
				Content: *content,
			}

			if err := db.Create(task).Error; err != nil {
				return errors.Wrap(err, "could not save task")
			}

			fmt.Printf("added task <%s>\n",
				color.CyanString("%s", task.ID))
			return nil
		},
	}
}

func CmdEdit(db *database) cli.Command {
	return cli.Command{
		Name:      "edit",
		Usage:     "Edit an existing task",
		ArgsUsage: "[task number]",
		Action: func(c *cli.Context) error {
			task, err := findTask(db, c.Args())
			if err != nil {
				return err
			}

			line := liner.NewLiner()
			line.SetCtrlCAborts(true)

			defer line.Close()

			taskString := fmt.Sprintf("%s due %s",
				task.Description,
				formatDueDate(task.Due.Time(), false))

			input, err := line.PromptWithSuggestion("", taskString, -1)
			if err != nil {
				return errors.Wrap(err, "edit canceled")
			}

			edited, err := parseInput(input)
			if err != nil {
				return err
			}

			update := model.Task{
				Metadata: model.Metadata{
					Modified: model.Now(),
				},
				Content: *edited,
			}

			err = db.Model(task).Updates(&update).Error
			if err != nil {
				return errors.Wrap(err, "could not update task")
			}

			fmt.Printf("edited task <%s>\n",
				color.CyanString("%s", task.ID))
			return nil
		},
	}
}

func CmdDo(db *database) cli.Command {
	return cli.Command{
		Name:      "do",
		Usage:     "Mark a task as completed",
		ArgsUsage: "[task number]",
		Action: func(c *cli.Context) error {
			task, err := findTask(db, c.Args())
			if err != nil {
				return err
			}

			if task.Completed != nil {
				return errors.New("task already completed")
			}

			now := model.Now()
			err = db.Model(&task).Updates(&model.Metadata{Completed: &now}).Error
			if err != nil {
				return errors.Wrap(err, "could not update task")
			}

			fmt.Printf("marked as completed <%s>\n",
				color.CyanString("%s", task.ID))
			return nil
		},
	}
}

func CmdArchive(db *database) cli.Command {
	return cli.Command{
		Name:  "archive",
		Usage: "Archive completed tasks",
		Action: func(c *cli.Context) error {
			res := db.Model(&model.Task{}).
				Where("archived is null").
				Where("completed is not null").
				UpdateColumn("archived", model.Now())
			if err := res.Error; err != nil {
				return errors.Wrap(err, "could not archive tasks")
			}

			fmt.Printf("%s tasks archived\n",
				color.CyanString("%d", res.RowsAffected))
			return nil
		},
	}
}

func parseInput(input string) (*model.Content, error) {
	var (
		index   = duePattern.FindStringSubmatchIndex(input)
		content = model.Content{
			Description: input,
			Due:         model.FromTime(now.EndOfDay()),
		}
	)

	if len(index) == 4 {
		due, err := parseDueDate(input[index[2]:])
		if err != nil {
			return nil, errors.Wrap(err, "invalid due date")
		}

		content.Due = model.FromTime(due)
		content.Description = input[:index[0]]
	}

	return &content, nil
}

func findTask(db *database, args []string) (*model.Task, error) {
	if len(args) < 1 {
		return nil, errors.New("too few arguments")
	}

	num, err := strconv.Atoi(args[0])
	if err != nil {
		return nil, errors.Wrap(err, "could not parse task number")
	}

	var task model.Task
	err = db.pending().
		Offset(num - 1).
		Limit(1).
		First(&task).
		Error

	return &task, err
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"math"
	"math/rand"
	"strconv"
	"sync"
)

type Ville struct {
	index int
	x, y  float64
}

func chooseCitie(tau [][]float64, etha [][]float64, alpha int, beta int, copyVilles []Ville, current Ville) (Ville, []Ville) {
	var prob []float64 = make([]float64, len(copyVilles))
	var i int = current.index
	var sum float64 = 0.0

	// on calcule les valeurs de tau[i][j]^alpha * etha[i][j]^beta
	for index, ville := range copyVilles {
		prob[index] = math.Pow(tau[i][ville.index], float64(alpha)) * math.Pow(etha[i][ville.index], float64(beta))
		sum += prob[index]
	}

	// on normalise pour avoir des probas
	for index, _ := range copyVilles {
		prob[index] /= sum
	}

	// probability denstiy function
	pcf := prob[0]
	// pour tout le éléments
	for index, _ := range prob {
		// si rand < élément, on le choisit,
		// si non, on calcule la distribution cumulée
		if rand.Float64() < pcf {
			res := copyVilles[index]
			copyVilles = deleteItem(index, copyVilles)

			return res, copyVilles
		}
		if index+1 <= len(prob)+1 {
			pcf += prob[index+1]
		}
	}
	res := copyVilles[len(prob)-1]
	copyVilles = deleteItem(len(prob)-1, copyVilles)

	return res, copyVilles
}

func updateDelta(Q float64, solution []Ville, delta [][]float64) {

	n := len(solution)
	L := norm(solution)

	for index := 1; index < n; index++ {
		i := solution[index-1].index
		j := solution[index].index
		delta[i][j] += Q / L
	}
	i := solution[n-1].index
	j := solution[0].index

	delta[i][j] += Q / L

}

func updatePath(tau [][]float64, delta [][]float64, rho float64) {

	for i, _ := range tau {
		for j, _ := range tau[i] {
			tau[i][j] = (1-rho)*tau[i][j] + delta[i][j]
		}
	}
}

func antSequentiel(t_max int, m int, villes []Ville, Q float64) []Ville {
	// first we declare the alpha, beta, tau, rho
	// delta, etha
	alpha := 1
	beta := 5
	rho := 0.1
	var newM int = m

	tau := make([][]float64, len(villes))
	for i, _ := range tau {
		tau[i] = make([]float64, len(villes))
		for j, _ := range tau[i] {
			tau[i][j] = 1 / Q
		}
	}

	etha := make([][]float64, len(villes))
	for i, _ := range etha {
		etha[i] = make([]float64, len(villes))
		for j, _ := range etha[i] {
			etha[i][j] = 1 / math.Sqrt(math.Pow(villes[i].x-villes[j].x, 2)+math.Pow(villes[i].y-villes[j].y, 2))
		}
		etha[i][i] = 0
	}

	delta := make([][]float64, len(villes))
	for i, _ := range delta {
		delta[i] = make([]float64, len(villes))
		for j, _ := range delta[i] {
			delta[i][j] = 0
		}
	}

	var best []Ville = villes

	for t_max > 0 {
		for newM > 0 {
			// on crée une copie des villes
			var copyVilles []Ville = make([]Ville, len(villes))
			copy(copyVilles[:], villes)
			// on crée la solution
			var solution []Ville = make([]Ville, len(villes))
			var i int = 0

			// on choisit le première ville
			// et on supprime l'élément de la copie
			var index int = int(math.Mod(float64(m), float64(len(villes))))
			solution[i] = copyVilles[index]
			copyVilles = deleteItem(index, copyVilles)
			i++

			for len(copyVilles) > 0 {
				// on choisit la ville
				solution[i], copyVilles = chooseCitie(tau, etha, alpha, beta, copyVilles, solution[i-1])
				i++
			}
			// on met à jour les phéromones
			updateDelta(Q, solution, delta)
			// on met à jour le best si il est meilleur que le courrant
			if norm(best) > norm(solution) {
				best = solution
			}
			newM--
		}
		// on met à jour tau
		updatePath(tau, delta, rho)
		newM = m
		t_max--
		// on met delta a 0 pour la nouvelle itération
		for ii, _ := range delta {
			for jj, _ := range delta[ii] {
				delta[ii][jj] = 0.0
			}
		}
	}
	return best
}

func antParallel(t_max int, m int, villes []Ville, Q float64) []Ville {
	// first we declare the alpha, beta, tau, rho
	// delta, etha
	alpha := 1
	beta := 5
	rho := 0.9
	var newM int = m

	tau := make([][]float64, len(villes))
	for i, _ := range tau {
		tau[i] = make([]float64, len(villes))
		for j, _ := range tau[i] {
			tau[i][j] = 1 / Q
		}
	}

	etha := make([][]float64, len(villes))
	for i, _ := range etha {
		etha[i] = make([]float64, len(villes))
		for j, _ := range etha[i] {
			etha[i][j] = 1 / math.Sqrt(math.Pow(villes[i].x-villes[j].x, 2)+math.Pow(villes[i].y-villes[j].y, 2))
		}
		etha[i][i] = 0
	}

	delta := make([][]float64, len(villes))
	for i, _ := range delta {
		delta[i] = make([]float64, len(villes))
		for j, _ := range delta[i] {
			delta[i][j] = 0
		}
	}

	var best []Ville = villes
	l := sync.Mutex{}

	for t_max > 0 {
		var vg sync.WaitGroup

		vg.Add(newM)
		for newM > 0 {
			go iteration(&tau, villes, newM, etha, alpha, beta, Q, &delta, &best, &l, &vg)
			newM--
		}
		vg.Wait()
		// on met à jour tau
		updatePath(tau, delta, rho)
		newM = m
		t_max--
		// on met delta a 0 pour la nouvelle itération
		for ii, _ := range delta {
			for jj, _ := range delta[ii] {
				delta[ii][jj] = 0.0
			}
		}
	}
	return best
}

func wrapper(file string, t_max int, m int, titre string, out string, version string) {
	villes := readFile(file)
	solution := greedy(file)
	if version == "sequentiel" {
		res := antSequentiel(t_max, m, villes, norm(solution))
		plotting(res, titre, "X", "Y", out)

	} else if version == "parallel" {
		res := antParallel(t_max, m, villes, norm(solution))
		plotting(res, titre, "X", "Y", out)

	} else {
		fmt.Println("Error")
	}
}

func wrapper_ten(file string, t_max int, m int, version string) {
	villes := readFile(file)
	solution := greedy(file)
	res := make([]float64, 20)
	if version == "sequentiel" {
		for index, _ := range res {
			res[index] = norm(antSequentiel(t_max, m, villes, norm(solution)))
		}
	} else if version == "parallel" {
		for index, _ := range res {
			res[index] = norm(antParallel(t_max, m, villes, norm(solution)))
			barring(res, file+" with AS parallel\nt_max = "+change(t_max)+"\nm = "+change(m), file)
		}
	}
	barring(res, file+" with AS", file)

	fmt.Print(file + "\t-> mean = ")
	fmt.Print(mean(res))
	fmt.Print("  std = ")
	fmt.Println(stdDev(res, mean(res)))
}

func change(number int) string {
	return strconv.FormatInt(int64(number), 10)
}

func main() {
	fmt.Println("Start:")
	t_max := 100

	// wrapper("./data/cities.dat", t_max, 17, "Cities.dat with AS\n"+"t_max = "+change(t_max)+"\nm = "+change(17), "citieAnt", "parallel")
	// wrapper("./data/cities2.dat", t_max, 49, "Cities2.dat with AS\n"+"t_max = "+change(t_max)+"\nm = "+change(49), "citieAnt2", "parallel")
	// wrapper("./data/cities50.dat", t_max, 50, "Cities50.dat with AS\n"+"t_max = "+change(t_max)+"\nm = "+change(50), "citieAnt50", "parallel")
	// wrapper("./data/cities60.dat", t_max, 60, "Cities60.dat with AS\n"+"t_max = "+change(t_max)+"\nm = "+change(60), "citieAnt60", "parallel")
	// wrapper("./data/cities80.dat", t_max, 80, "Cities80.dat with AS\n"+"t_max = "+change(t_max)+"\nm = "+change(80), "citieAnt80", "parallel")
	// wrapper("./data/cities100.dat", t_max, 100, "Cities100.dat with AS\n"+"t_max = "+change(t_max)+"\nm = "+change(100), "citieAnt100", "parallel")

	// wrapper_ten("./data/cities.dat", t_max, 17, "parallel")
	// wrapper_ten("./data/cities2.dat", t_max, 49, "parallel")
	// wrapper_ten("./data/cities50.dat", t_max, 50, "parallel")
	wrapper_ten("./data/cities60.dat", t_max, 60, "parallel")
	// wrapper_ten("./data/cities80.dat", t_max, 80, "parallel")
	// wrapper_ten("./data/cities100.dat", t_max, 100, "parallel")
}
<commit_msg>ajout benchmark<commit_after>package main

import (
	"fmt"
	"math"
	"math/rand"
	"strconv"
	"sync"
	"time"
)

type Ville struct {
	index int
	x, y  float64
}

func chooseCitie(tau [][]float64, etha [][]float64, alpha int, beta int, copyVilles []Ville, current Ville) (Ville, []Ville) {
	var prob []float64 = make([]float64, len(copyVilles))
	var i int = current.index
	var sum float64 = 0.0

	// on calcule les valeurs de tau[i][j]^alpha * etha[i][j]^beta
	for index, ville := range copyVilles {
		prob[index] = math.Pow(tau[i][ville.index], float64(alpha)) * math.Pow(etha[i][ville.index], float64(beta))
		sum += prob[index]
	}

	// on normalise pour avoir des probas
	for index, _ := range copyVilles {
		prob[index] /= sum
	}

	// probability denstiy function
	pcf := prob[0]
	// pour tout le éléments
	for index, _ := range prob {
		// si rand < élément, on le choisit,
		// si non, on calcule la distribution cumulée
		if rand.Float64() < pcf {
			res := copyVilles[index]
			copyVilles = deleteItem(index, copyVilles)

			return res, copyVilles
		}
		if index+1 <= len(prob)+1 {
			pcf += prob[index+1]
		}
	}
	res := copyVilles[len(prob)-1]
	copyVilles = deleteItem(len(prob)-1, copyVilles)

	return res, copyVilles
}

func updateDelta(Q float64, solution []Ville, delta [][]float64) {

	n := len(solution)
	L := norm(solution)

	for index := 1; index < n; index++ {
		i := solution[index-1].index
		j := solution[index].index
		delta[i][j] += Q / L
	}
	i := solution[n-1].index
	j := solution[0].index

	delta[i][j] += Q / L

}

func updatePath(tau [][]float64, delta [][]float64, rho float64) {

	for i, _ := range tau {
		for j, _ := range tau[i] {
			tau[i][j] = (1-rho)*tau[i][j] + delta[i][j]
		}
	}
}

func antSequentiel(t_max int, m int, villes []Ville, Q float64) []Ville {
	// first we declare the alpha, beta, tau, rho
	// delta, etha
	alpha := 1
	beta := 5
	rho := 0.1
	var newM int = m

	tau := make([][]float64, len(villes))
	for i, _ := range tau {
		tau[i] = make([]float64, len(villes))
		for j, _ := range tau[i] {
			tau[i][j] = 1 / Q
		}
	}

	etha := make([][]float64, len(villes))
	for i, _ := range etha {
		etha[i] = make([]float64, len(villes))
		for j, _ := range etha[i] {
			etha[i][j] = 1 / math.Sqrt(math.Pow(villes[i].x-villes[j].x, 2)+math.Pow(villes[i].y-villes[j].y, 2))
		}
		etha[i][i] = 0
	}

	delta := make([][]float64, len(villes))
	for i, _ := range delta {
		delta[i] = make([]float64, len(villes))
		for j, _ := range delta[i] {
			delta[i][j] = 0
		}
	}

	var best []Ville = villes

	for t_max > 0 {
		for newM > 0 {
			// on crée une copie des villes
			var copyVilles []Ville = make([]Ville, len(villes))
			copy(copyVilles[:], villes)
			// on crée la solution
			var solution []Ville = make([]Ville, len(villes))
			var i int = 0

			// on choisit le première ville
			// et on supprime l'élément de la copie
			var index int = int(math.Mod(float64(m), float64(len(villes))))
			solution[i] = copyVilles[index]
			copyVilles = deleteItem(index, copyVilles)
			i++

			for len(copyVilles) > 0 {
				// on choisit la ville
				solution[i], copyVilles = chooseCitie(tau, etha, alpha, beta, copyVilles, solution[i-1])
				i++
			}
			// on met à jour les phéromones
			updateDelta(Q, solution, delta)
			// on met à jour le best si il est meilleur que le courrant
			if norm(best) > norm(solution) {
				best = solution
			}
			newM--
		}
		// on met à jour tau
		updatePath(tau, delta, rho)
		newM = m
		t_max--
		// on met delta a 0 pour la nouvelle itération
		for ii, _ := range delta {
			for jj, _ := range delta[ii] {
				delta[ii][jj] = 0.0
			}
		}
	}
	return best
}

func antParallel(t_max int, m int, villes []Ville, Q float64) []Ville {
	// first we declare the alpha, beta, tau, rho
	// delta, etha
	alpha := 1
	beta := 5
	rho := 0.9
	var newM int = m

	tau := make([][]float64, len(villes))
	for i, _ := range tau {
		tau[i] = make([]float64, len(villes))
		for j, _ := range tau[i] {
			tau[i][j] = 1 / Q
		}
	}

	etha := make([][]float64, len(villes))
	for i, _ := range etha {
		etha[i] = make([]float64, len(villes))
		for j, _ := range etha[i] {
			etha[i][j] = 1 / math.Sqrt(math.Pow(villes[i].x-villes[j].x, 2)+math.Pow(villes[i].y-villes[j].y, 2))
		}
		etha[i][i] = 0
	}

	delta := make([][]float64, len(villes))
	for i, _ := range delta {
		delta[i] = make([]float64, len(villes))
		for j, _ := range delta[i] {
			delta[i][j] = 0
		}
	}

	var best []Ville = villes
	l := sync.Mutex{}

	for t_max > 0 {
		var vg sync.WaitGroup

		vg.Add(newM)
		for newM > 0 {
			go iteration(&tau, villes, newM, etha, alpha, beta, Q, &delta, &best, &l, &vg)
			newM--
		}
		vg.Wait()
		// on met à jour tau
		updatePath(tau, delta, rho)
		newM = m
		t_max--
		// on met delta a 0 pour la nouvelle itération
		for ii, _ := range delta {
			for jj, _ := range delta[ii] {
				delta[ii][jj] = 0.0
			}
		}
	}
	return best
}

func wrapper(file string, t_max int, m int, titre string, out string, version string) {
	villes := readFile(file)
	solution := greedy(file)
	if version == "sequentiel" {
		start := time.Now()
		res := antSequentiel(t_max, m, villes, norm(solution))
		stop := time.Since(start)
		fmt.Printf("Take : %s", stop)
		plotting(res, titre, "X", "Y", out)

	} else if version == "parallel" {
		start := time.Now()
		res := antParallel(t_max, m, villes, norm(solution))
		stop := time.Since(start)
		fmt.Printf("Take : %s", stop)
		plotting(res, titre, "X", "Y", out)

	} else {
		fmt.Println("Error")
	}
}

func wrapper_ten(file string, t_max int, m int, version string) {
	villes := readFile(file)
	solution := greedy(file)
	res := make([]float64, 20)
	if version == "sequentiel" {
		for index, _ := range res {
			res[index] = norm(antSequentiel(t_max, m, villes, norm(solution)))
		}
	} else if version == "parallel" {
		for index, _ := range res {
			res[index] = norm(antParallel(t_max, m, villes, norm(solution)))
			barring(res, file+" with AS parallel\nt_max = "+change(t_max)+"\nm = "+change(m), file)
		}
	}
	barring(res, file+" with AS", file)

	fmt.Print(file + "\t-> mean = ")
	fmt.Print(mean(res))
	fmt.Print("  std = ")
	fmt.Println(stdDev(res, mean(res)))
}

func change(number int) string {
	return strconv.FormatInt(int64(number), 10)
}

func main() {
	fmt.Println("Start:")
	t_max := 30

	// wrapper("./data/cities.dat", t_max, 17, "Cities.dat with AS\n"+"t_max = "+change(t_max)+"\nm = "+change(17), "citieAnt", "parallel")
	wrapper("./data/cities2.dat", t_max, 49, "Cities2.dat with AS\n"+"t_max = "+change(t_max)+"\nm = "+change(49), "citieAnt2", "parallel")
	// wrapper("./data/cities50.dat", t_max, 50, "Cities50.dat with AS\n"+"t_max = "+change(t_max)+"\nm = "+change(50), "citieAnt50", "parallel")
	// wrapper("./data/cities60.dat", t_max, 60, "Cities60.dat with AS\n"+"t_max = "+change(t_max)+"\nm = "+change(60), "citieAnt60", "parallel")
	// wrapper("./data/cities80.dat", t_max, 80, "Cities80.dat with AS\n"+"t_max = "+change(t_max)+"\nm = "+change(80), "citieAnt80", "parallel")
	// wrapper("./data/cities100.dat", t_max, 100, "Cities100.dat with AS\n"+"t_max = "+change(t_max)+"\nm = "+change(100), "citieAnt100", "parallel")

	// wrapper_ten("./data/cities.dat", t_max, 17, "parallel")
	// wrapper_ten("./data/cities2.dat", t_max, 49, "parallel")
	// wrapper_ten("./data/cities50.dat", t_max, 50, "parallel")
	// wrapper_ten("./data/cities60.dat", t_max, 60, "parallel")
	// wrapper_ten("./data/cities80.dat", t_max, 80, "parallel")
	// wrapper_ten("./data/cities100.dat", t_max, 100, "parallel")
}
<|endoftext|>


<commit_before>package storage

import (
	"crypto/rand"
	. "github.com/smartystreets/goconvey/convey"
	"io/ioutil"
	"log"
	"net/http"
	"path/filepath"
	"reflect"
	"testing"
)

func randData(n int) []byte {
	const alphanum = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
	var bytes = make([]byte, n)
	rand.Read(bytes)
	for i, b := range bytes {
		bytes[i] = alphanum[b%byte(len(alphanum))]
	}
	return bytes
}

func randString(n int) string {
	return string(randData(n))
}

func TestIntegration(t *testing.T) {
	Convey("Integration", t, func() {
		c, err := NewEnv()
		So(err, ShouldBeNil)
		So(c, ShouldNotBeNil)
		Convey("Info", func() {
			info := c.Info()
			So(info.BytesUsed, ShouldNotEqual, 0)
			So(info.ObjectCount, ShouldNotEqual, 0)
			So(info.ContainerCount, ShouldNotEqual, 0)
		})
		Convey("Upload", func() {
			uploadData := randData(512)
			f, err := ioutil.TempFile("", randString(12))
			defer f.Close()
			f.Write(uploadData)
			So(err, ShouldBeNil)
			filename := f.Name()
			basename := filepath.Base(filename)
			container := "test"
			So(c.UploadFile(filename, container), ShouldBeNil)
			Convey("Download", func() {
				link := c.URL(container, basename)
				log.Println("GET", link)
				req, err := http.NewRequest("GET", link, nil)
				So(err, ShouldBeNil)
				res, err := c.Do(req)
				So(err, ShouldBeNil)
				So(res.StatusCode, ShouldEqual, http.StatusOK)
				defer res.Body.Close()
				data, err := ioutil.ReadAll(res.Body)
				So(err, ShouldBeNil)
				So(string(data), ShouldEqual, string(uploadData))
				So(reflect.DeepEqual(data, uploadData), ShouldBeTrue)
			})
		})
	})
}
<commit_msg>implemented skipping for integration tests<commit_after>package storage

import (
	"crypto/rand"
	. "github.com/smartystreets/goconvey/convey"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"path/filepath"
	"reflect"
	"testing"
)

func randData(n int) []byte {
	const alphanum = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
	var bytes = make([]byte, n)
	rand.Read(bytes)
	for i, b := range bytes {
		bytes[i] = alphanum[b%byte(len(alphanum))]
	}
	return bytes
}

func randString(n int) string {
	return string(randData(n))
}

func TestIntegration(t *testing.T) {
	test := func() {
		c, err := NewEnv()
		So(err, ShouldBeNil)
		So(c, ShouldNotBeNil)
		Convey("Info", func() {
			info := c.Info()
			So(info.BytesUsed, ShouldNotEqual, 0)
			So(info.ObjectCount, ShouldNotEqual, 0)
			So(info.ContainerCount, ShouldNotEqual, 0)
		})
		Convey("Upload", func() {
			uploadData := randData(512)
			f, err := ioutil.TempFile("", randString(12))
			defer f.Close()
			f.Write(uploadData)
			So(err, ShouldBeNil)
			filename := f.Name()
			basename := filepath.Base(filename)
			container := "test"
			So(c.UploadFile(filename, container), ShouldBeNil)
			Convey("Download", func() {
				link := c.URL(container, basename)
				log.Println("GET", link)
				req, err := http.NewRequest("GET", link, nil)
				So(err, ShouldBeNil)
				res, err := c.Do(req)
				So(err, ShouldBeNil)
				So(res.StatusCode, ShouldEqual, http.StatusOK)
				defer res.Body.Close()
				data, err := ioutil.ReadAll(res.Body)
				So(err, ShouldBeNil)
				So(string(data), ShouldEqual, string(uploadData))
				So(reflect.DeepEqual(data, uploadData), ShouldBeTrue)
			})
		})
	}
	if len(os.Getenv(EnvKey)) == 0 || len(os.Getenv(EnvUser)) == 0 {
		test = nil
	}
	name := "Integration"
	if test != nil {
		Convey(name, t, test)
	} else {
		log.Println("Credentials not provided. Skipping integration tests")
		Convey(name, t, nil)
	}
}
<|endoftext|>


<commit_before>// +build !windows

/*
Copyright 2019 The Kubernetes Authors.

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

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

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

package mount

import (
	"fmt"
	"os"
	"strconv"
	"strings"
	"syscall"

	utilio "k8s.io/utils/io"
)

const (
	// At least number of fields per line in /proc/<pid>/mountinfo.
	expectedAtLeastNumFieldsPerMountInfo = 10
	// How many times to retry for a consistent read of /proc/mounts.
	maxListTries = 3
)

// IsCorruptedMnt return true if err is about corrupted mount point
func IsCorruptedMnt(err error) bool {
	if err == nil {
		return false
	}
	var underlyingError error
	switch pe := err.(type) {
	case nil:
		return false
	case *os.PathError:
		underlyingError = pe.Err
	case *os.LinkError:
		underlyingError = pe.Err
	case *os.SyscallError:
		underlyingError = pe.Err
	}

	return underlyingError == syscall.ENOTCONN || underlyingError == syscall.ESTALE || underlyingError == syscall.EIO || underlyingError == syscall.EACCES || underlyingError == syscall.EHOSTDOWN
}

// MountInfo represents a single line in /proc/<pid>/mountinfo.
type MountInfo struct { // nolint: golint
	// Unique ID for the mount (maybe reused after umount).
	ID int
	// The ID of the parent mount (or of self for the root of this mount namespace's mount tree).
	ParentID int
	// Major indicates one half of the device ID which identifies the device class
	// (parsed from `st_dev` for files on this filesystem).
	Major int
	// Minor indicates one half of the device ID which identifies a specific
	// instance of device (parsed from `st_dev` for files on this filesystem).
	Minor int
	// The pathname of the directory in the filesystem which forms the root of this mount.
	Root string
	// Mount source, filesystem-specific information. e.g. device, tmpfs name.
	Source string
	// Mount point, the pathname of the mount point.
	MountPoint string
	// Optional fieds, zero or more fields of the form "tag[:value]".
	OptionalFields []string
	// The filesystem type in the form "type[.subtype]".
	FsType string
	// Per-mount options.
	MountOptions []string
	// Per-superblock options.
	SuperOptions []string
}

// ParseMountInfo parses /proc/xxx/mountinfo.
func ParseMountInfo(filename string) ([]MountInfo, error) {
	content, err := utilio.ConsistentRead(filename, maxListTries)
	if err != nil {
		return []MountInfo{}, err
	}
	contentStr := string(content)
	infos := []MountInfo{}

	for _, line := range strings.Split(contentStr, "\n") {
		if line == "" {
			// the last split() item is empty string following the last \n
			continue
		}
		// See `man proc` for authoritative description of format of the file.
		fields := strings.Fields(line)
		if len(fields) < expectedAtLeastNumFieldsPerMountInfo {
			return nil, fmt.Errorf("wrong number of fields in (expected at least %d, got %d): %s", expectedAtLeastNumFieldsPerMountInfo, len(fields), line)
		}
		id, err := strconv.Atoi(fields[0])
		if err != nil {
			return nil, err
		}
		parentID, err := strconv.Atoi(fields[1])
		if err != nil {
			return nil, err
		}
		mm := strings.Split(fields[2], ":")
		if len(mm) != 2 {
			return nil, fmt.Errorf("parsing '%s' failed: unexpected minor:major pair %s", line, mm)
		}
		major, err := strconv.Atoi(mm[0])
		if err != nil {
			return nil, fmt.Errorf("parsing '%s' failed: unable to parse major device id, err:%v", mm[0], err)
		}
		minor, err := strconv.Atoi(mm[1])
		if err != nil {
			return nil, fmt.Errorf("parsing '%s' failed: unable to parse minor device id, err:%v", mm[1], err)
		}

		info := MountInfo{
			ID:           id,
			ParentID:     parentID,
			Major:        major,
			Minor:        minor,
			Root:         fields[3],
			MountPoint:   fields[4],
			MountOptions: strings.Split(fields[5], ","),
		}
		// All fields until "-" are "optional fields".
		i := 6
		for ; i < len(fields) && fields[i] != "-"; i++ {
			info.OptionalFields = append(info.OptionalFields, fields[i])
		}
		// Parse the rest 3 fields.
		i++
		if len(fields)-i < 3 {
			return nil, fmt.Errorf("expect 3 fields in %s, got %d", line, len(fields)-i)
		}
		info.FsType = fields[i]
		info.Source = fields[i+1]
		info.SuperOptions = strings.Split(fields[i+2], ",")
		infos = append(infos, info)
	}
	return infos, nil
}

// isMountPointMatch returns true if the path in mp is the same as dir.
// Handles case where mountpoint dir has been renamed due to stale NFS mount.
func isMountPointMatch(mp MountPoint, dir string) bool {
	deletedDir := fmt.Sprintf("%s\\040(deleted)", dir)
	return ((mp.Path == dir) || (mp.Path == deletedDir))
}
<commit_msg>ConsistentRead tries 10 times<commit_after>// +build !windows

/*
Copyright 2019 The Kubernetes Authors.

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

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

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

package mount

import (
	"fmt"
	"os"
	"strconv"
	"strings"
	"syscall"

	utilio "k8s.io/utils/io"
)

const (
	// At least number of fields per line in /proc/<pid>/mountinfo.
	expectedAtLeastNumFieldsPerMountInfo = 10
	// How many times to retry for a consistent read of /proc/mounts.
	maxListTries = 10
)

// IsCorruptedMnt return true if err is about corrupted mount point
func IsCorruptedMnt(err error) bool {
	if err == nil {
		return false
	}
	var underlyingError error
	switch pe := err.(type) {
	case nil:
		return false
	case *os.PathError:
		underlyingError = pe.Err
	case *os.LinkError:
		underlyingError = pe.Err
	case *os.SyscallError:
		underlyingError = pe.Err
	}

	return underlyingError == syscall.ENOTCONN || underlyingError == syscall.ESTALE || underlyingError == syscall.EIO || underlyingError == syscall.EACCES || underlyingError == syscall.EHOSTDOWN
}

// MountInfo represents a single line in /proc/<pid>/mountinfo.
type MountInfo struct { // nolint: golint
	// Unique ID for the mount (maybe reused after umount).
	ID int
	// The ID of the parent mount (or of self for the root of this mount namespace's mount tree).
	ParentID int
	// Major indicates one half of the device ID which identifies the device class
	// (parsed from `st_dev` for files on this filesystem).
	Major int
	// Minor indicates one half of the device ID which identifies a specific
	// instance of device (parsed from `st_dev` for files on this filesystem).
	Minor int
	// The pathname of the directory in the filesystem which forms the root of this mount.
	Root string
	// Mount source, filesystem-specific information. e.g. device, tmpfs name.
	Source string
	// Mount point, the pathname of the mount point.
	MountPoint string
	// Optional fieds, zero or more fields of the form "tag[:value]".
	OptionalFields []string
	// The filesystem type in the form "type[.subtype]".
	FsType string
	// Per-mount options.
	MountOptions []string
	// Per-superblock options.
	SuperOptions []string
}

// ParseMountInfo parses /proc/xxx/mountinfo.
func ParseMountInfo(filename string) ([]MountInfo, error) {
	content, err := utilio.ConsistentRead(filename, maxListTries)
	if err != nil {
		return []MountInfo{}, err
	}
	contentStr := string(content)
	infos := []MountInfo{}

	for _, line := range strings.Split(contentStr, "\n") {
		if line == "" {
			// the last split() item is empty string following the last \n
			continue
		}
		// See `man proc` for authoritative description of format of the file.
		fields := strings.Fields(line)
		if len(fields) < expectedAtLeastNumFieldsPerMountInfo {
			return nil, fmt.Errorf("wrong number of fields in (expected at least %d, got %d): %s", expectedAtLeastNumFieldsPerMountInfo, len(fields), line)
		}
		id, err := strconv.Atoi(fields[0])
		if err != nil {
			return nil, err
		}
		parentID, err := strconv.Atoi(fields[1])
		if err != nil {
			return nil, err
		}
		mm := strings.Split(fields[2], ":")
		if len(mm) != 2 {
			return nil, fmt.Errorf("parsing '%s' failed: unexpected minor:major pair %s", line, mm)
		}
		major, err := strconv.Atoi(mm[0])
		if err != nil {
			return nil, fmt.Errorf("parsing '%s' failed: unable to parse major device id, err:%v", mm[0], err)
		}
		minor, err := strconv.Atoi(mm[1])
		if err != nil {
			return nil, fmt.Errorf("parsing '%s' failed: unable to parse minor device id, err:%v", mm[1], err)
		}

		info := MountInfo{
			ID:           id,
			ParentID:     parentID,
			Major:        major,
			Minor:        minor,
			Root:         fields[3],
			MountPoint:   fields[4],
			MountOptions: strings.Split(fields[5], ","),
		}
		// All fields until "-" are "optional fields".
		i := 6
		for ; i < len(fields) && fields[i] != "-"; i++ {
			info.OptionalFields = append(info.OptionalFields, fields[i])
		}
		// Parse the rest 3 fields.
		i++
		if len(fields)-i < 3 {
			return nil, fmt.Errorf("expect 3 fields in %s, got %d", line, len(fields)-i)
		}
		info.FsType = fields[i]
		info.Source = fields[i+1]
		info.SuperOptions = strings.Split(fields[i+2], ",")
		infos = append(infos, info)
	}
	return infos, nil
}

// isMountPointMatch returns true if the path in mp is the same as dir.
// Handles case where mountpoint dir has been renamed due to stale NFS mount.
func isMountPointMatch(mp MountPoint, dir string) bool {
	deletedDir := fmt.Sprintf("%s\\040(deleted)", dir)
	return ((mp.Path == dir) || (mp.Path == deletedDir))
}
<|endoftext|>


<commit_before>package balls

func maxDistance(position []int, m int) int {
	return 0
}
<commit_msg>sovle 1552 use binary search<commit_after>package balls

import "sort"

func maxDistance(position []int, m int) int {
	return useBinarySearch(position, m)
}

// useBinarySearch time complexity O(N*logM) where M = max(position) - min(position), space complexity O(1)
func useBinarySearch(position []int, m int) int {
	sort.Ints(position)
	n := len(position)
	if m == 2 {
		return position[n-1] - position[0]
	}
	// l, r means the min and max distance between two balls
	// ans its monotonically increasing, so we could use binary search
	l, r := 0, position[n-1]-position[0]
	for l < r {
		mid := r - (r-l)/2
		if count(mid, position) >= m {
			l = mid
		} else {
			r = mid - 1
		}
	}
	return l

}

func count(d int, position []int) int {
	ans, cur := 1, position[0]
	for i := 1; i < len(position); i++ {
		if position[i]-cur >= d {
			ans++
			cur = position[i]
		}
	}
	return ans
}
<|endoftext|>


<commit_before>package logrus_gcloud_formatter

import (
	"encoding/json"
	"fmt"
	"github.com/Sirupsen/logrus"
)

type LogrusGoogleCloudFormatter struct {
	Type string // if not empty use for logstash type field.

	// TimestampFormat sets the format used for timestamps.
	TimestampFormat string
}

func levelToString(level logrus.Level) string {
	switch level {
	case logrus.DebugLevel:
		return "debug"
	case logrus.InfoLevel:
		return "info"
	case logrus.WarnLevel:
		return "warning"
	case logrus.ErrorLevel:
		return "error"
	case logrus.FatalLevel:
		return "critical"
	case logrus.PanicLevel:
		return "critical"
	}

	return "info"
}

func (f *LogrusGoogleCloudFormatter) Format(entry *logrus.Entry) ([]byte, error) {
	fields := make(logrus.Fields)

	for k, v := range entry.Data {
		fields[k] = v
	}

	fields["timestamp"] = entry.Time.Unix()
	fields["message"] = entry.Message
	fields["severity"] = levelToString(entry.Level)

	serialized, err := json.Marshal(fields)
	if err != nil {
		return nil, fmt.Errorf("Failed to marshal fields to JSON, %v", err)
	}
	return append(serialized, '\n'), nil
}
<commit_msg>fix: convert Sirupse to lower case<commit_after>package logrus_gcloud_formatter

import (
	"encoding/json"
	"fmt"
	"github.com/sirupsen/logrus"
)

type LogrusGoogleCloudFormatter struct {
	Type string // if not empty use for logstash type field.

	// TimestampFormat sets the format used for timestamps.
	TimestampFormat string
}

func levelToString(level logrus.Level) string {
	switch level {
	case logrus.DebugLevel:
		return "debug"
	case logrus.InfoLevel:
		return "info"
	case logrus.WarnLevel:
		return "warning"
	case logrus.ErrorLevel:
		return "error"
	case logrus.FatalLevel:
		return "critical"
	case logrus.PanicLevel:
		return "critical"
	}

	return "info"
}

func (f *LogrusGoogleCloudFormatter) Format(entry *logrus.Entry) ([]byte, error) {
	fields := make(logrus.Fields)

	for k, v := range entry.Data {
		fields[k] = v
	}

	fields["timestamp"] = entry.Time.Unix()
	fields["message"] = entry.Message
	fields["severity"] = levelToString(entry.Level)

	serialized, err := json.Marshal(fields)
	if err != nil {
		return nil, fmt.Errorf("Failed to marshal fields to JSON, %v", err)
	}
	return append(serialized, '\n'), nil
}
<|endoftext|>