<commit_before>// Copyright 2011, 2012, 2013 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package environs_test

import (
	"os"
	"path/filepath"

	gc "launchpad.net/gocheck"

	"launchpad.net/juju-core/environs"
	"launchpad.net/juju-core/environs/config"
	"launchpad.net/juju-core/provider/dummy"
	"launchpad.net/juju-core/testing"
	jc "launchpad.net/juju-core/testing/checkers"
)

type suite struct{}

var _ = gc.Suite(suite{})

func (suite) TearDownTest(c *gc.C) {
	dummy.Reset()
}

var invalidConfigTests = []struct {
	env string
	err string
}{
	{"'", "YAML error:.*"},
	{`
default: unknown
environments:
    only:
        type: unknown
`, `default environment .* does not exist`,
	},
}

func (suite) TestInvalidConfig(c *gc.C) {
	for i, t := range invalidConfigTests {
		c.Logf("running test %v", i)
		_, err := environs.ReadEnvironsBytes([]byte(t.env))
		c.Check(err, gc.ErrorMatches, t.err)
	}
}

var invalidEnvTests = []struct {
	env  string
	name string
	err  string
}{
	{`
environments:
    only:
        foo: bar
`, "", `environment "only" has no type`,
	}, {`
environments:
    only:
        foo: bar
`, "only", `environment "only" has no type`,
	}, {`
environments:
    only:
        foo: bar
        type: crazy
`, "only", `environment "only" has an unknown provider type "crazy"`,
	},
}

func (suite) TestInvalidEnv(c *gc.C) {
	defer testing.MakeFakeHomeNoEnvironments(c, "only").Restore()
	for i, t := range invalidEnvTests {
		c.Logf("running test %v", i)
		es, err := environs.ReadEnvironsBytes([]byte(t.env))
		c.Check(err, gc.IsNil)
		cfg, err := es.Config(t.name)
		c.Check(err, gc.ErrorMatches, t.err)
		c.Check(cfg, gc.IsNil)
	}
}

func (suite) TestNoEnv(c *gc.C) {
	defer testing.MakeFakeHomeNoEnvironments(c).Restore()
	es, err := environs.ReadEnvirons("")
	c.Assert(es, gc.IsNil)
	c.Assert(err, jc.Satisfies, environs.IsNoEnv)
}

var configTests = []struct {
	env   string
	check func(c *gc.C, envs *environs.Environs)
}{
	{`
environments:
    only:
        type: dummy
        state-server: false
`, func(c *gc.C, envs *environs.Environs) {
		cfg, err := envs.Config("")
		c.Assert(err, gc.IsNil)
		c.Assert(cfg.Name(), gc.Equals, "only")
	}}, {`
default:
    invalid
environments:
    valid:
        type: dummy
        state-server: false
    invalid:
        type: crazy
`, func(c *gc.C, envs *environs.Environs) {
		cfg, err := envs.Config("")
		c.Assert(err, gc.ErrorMatches, `environment "invalid" has an unknown provider type "crazy"`)
		c.Assert(cfg, gc.IsNil)
		cfg, err = envs.Config("valid")
		c.Assert(err, gc.IsNil)
		c.Assert(cfg.Name(), gc.Equals, "valid")
	}}, {`
environments:
    one:
        type: dummy
        state-server: false
    two:
        type: dummy
        state-server: false
`, func(c *gc.C, envs *environs.Environs) {
		cfg, err := envs.Config("")
		c.Assert(err, gc.ErrorMatches, `no default environment found`)
		c.Assert(cfg, gc.IsNil)
	}},
}

func (suite) TestConfig(c *gc.C) {
	defer testing.MakeFakeHomeNoEnvironments(c, "only", "valid", "one", "two").Restore()
	for i, t := range configTests {
		c.Logf("running test %v", i)
		envs, err := environs.ReadEnvironsBytes([]byte(t.env))
		c.Assert(err, gc.IsNil)
		t.check(c, envs)
	}
}

func (suite) TestDefaultConfigFile(c *gc.C) {
	defer testing.MakeEmptyFakeHome(c).Restore()

	env := `
environments:
    only:
        type: dummy
        state-server: false
        authorized-keys: i-am-a-key
`
	outfile, err := environs.WriteEnvirons("", env)
	c.Assert(err, gc.IsNil)
	path := testing.HomePath(".juju", "environments.yaml")
	c.Assert(path, gc.Equals, outfile)

	envs, err := environs.ReadEnvirons("")
	c.Assert(err, gc.IsNil)
	cfg, err := envs.Config("")
	c.Assert(err, gc.IsNil)
	c.Assert(cfg.Name(), gc.Equals, "only")
}

func (suite) TestConfigPerm(c *gc.C) {
	defer testing.MakeSampleHome(c).Restore()

	path := testing.HomePath(".juju")
	info, err := os.Lstat(path)
	c.Assert(err, gc.IsNil)
	oldPerm := info.Mode().Perm()
	env := `
environments:
    only:
        type: dummy
        state-server: false
        authorized-keys: i-am-a-key
`
	outfile, err := environs.WriteEnvirons("", env)
	c.Assert(err, gc.IsNil)

	info, err = os.Lstat(outfile)
	c.Assert(err, gc.IsNil)
	c.Assert(info.Mode().Perm(), gc.Equals, os.FileMode(0600))

	info, err = os.Lstat(filepath.Dir(outfile))
	c.Assert(err, gc.IsNil)
	c.Assert(info.Mode().Perm(), gc.Equals, oldPerm)

}

func (suite) TestNamedConfigFile(c *gc.C) {
	defer testing.MakeFakeHomeNoEnvironments(c, "only").Restore()

	env := `
environments:
    only:
        type: dummy
        state-server: false
        authorized-keys: i-am-a-key
`
	path := filepath.Join(c.MkDir(), "a-file")
	outfile, err := environs.WriteEnvirons(path, env)
	c.Assert(err, gc.IsNil)
	c.Assert(path, gc.Equals, outfile)

	envs, err := environs.ReadEnvirons(path)
	c.Assert(err, gc.IsNil)
	cfg, err := envs.Config("")
	c.Assert(err, gc.IsNil)
	c.Assert(cfg.Name(), gc.Equals, "only")
}

func (suite) TestConfigRoundTrip(c *gc.C) {
	c.Skip("what is this really meant to be testing")
	cfg, err := config.New(config.NoDefaults, dummySampleConfig())
	c.Assert(err, gc.IsNil)
	provider, err := environs.Provider(cfg.Type())
	c.Assert(err, gc.IsNil)
	cfg, err = provider.Validate(cfg, nil)
	c.Assert(err, gc.IsNil)
	// This fails because the configuration isn't prepared.
	env, err := environs.New(cfg)
	c.Assert(err, gc.IsNil)
	c.Assert(cfg.AllAttrs(), gc.DeepEquals, env.Config().AllAttrs())
}

func inMap(attrs testing.Attrs, attr string) bool {
	_, ok := attrs[attr]
	return ok
}

func (suite) TestBootstrapConfig(c *gc.C) {
	defer testing.MakeFakeHomeNoEnvironments(c, "bladaam").Restore()
	attrs := dummySampleConfig().Merge(testing.Attrs{
		"agent-version": "1.2.3",
	})
	c.Assert(inMap(attrs, "secret"), jc.IsTrue)
	c.Assert(inMap(attrs, "ca-private-key"), jc.IsTrue)
	c.Assert(inMap(attrs, "admin-secret"), jc.IsTrue)

	cfg, err := config.New(config.NoDefaults, attrs)
	c.Assert(err, gc.IsNil)
	c.Assert(err, gc.IsNil)

	cfg1, err := environs.BootstrapConfig(cfg)
	c.Assert(err, gc.IsNil)

	expect := cfg.AllAttrs()
	delete(expect, "secret")
	expect["admin-secret"] = ""
	expect["ca-private-key"] = ""
	c.Assert(cfg1.AllAttrs(), gc.DeepEquals, expect)
}
<commit_msg>environs: remove redundant test<commit_after>// Copyright 2011, 2012, 2013 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package environs_test

import (
	"os"
	"path/filepath"

	gc "launchpad.net/gocheck"

	"launchpad.net/juju-core/environs"
	"launchpad.net/juju-core/environs/config"
	"launchpad.net/juju-core/provider/dummy"
	"launchpad.net/juju-core/testing"
	jc "launchpad.net/juju-core/testing/checkers"
)

type suite struct{}

var _ = gc.Suite(suite{})

func (suite) TearDownTest(c *gc.C) {
	dummy.Reset()
}

var invalidConfigTests = []struct {
	env string
	err string
}{
	{"'", "YAML error:.*"},
	{`
default: unknown
environments:
    only:
        type: unknown
`, `default environment .* does not exist`,
	},
}

func (suite) TestInvalidConfig(c *gc.C) {
	for i, t := range invalidConfigTests {
		c.Logf("running test %v", i)
		_, err := environs.ReadEnvironsBytes([]byte(t.env))
		c.Check(err, gc.ErrorMatches, t.err)
	}
}

var invalidEnvTests = []struct {
	env  string
	name string
	err  string
}{
	{`
environments:
    only:
        foo: bar
`, "", `environment "only" has no type`,
	}, {`
environments:
    only:
        foo: bar
`, "only", `environment "only" has no type`,
	}, {`
environments:
    only:
        foo: bar
        type: crazy
`, "only", `environment "only" has an unknown provider type "crazy"`,
	},
}

func (suite) TestInvalidEnv(c *gc.C) {
	defer testing.MakeFakeHomeNoEnvironments(c, "only").Restore()
	for i, t := range invalidEnvTests {
		c.Logf("running test %v", i)
		es, err := environs.ReadEnvironsBytes([]byte(t.env))
		c.Check(err, gc.IsNil)
		cfg, err := es.Config(t.name)
		c.Check(err, gc.ErrorMatches, t.err)
		c.Check(cfg, gc.IsNil)
	}
}

func (suite) TestNoEnv(c *gc.C) {
	defer testing.MakeFakeHomeNoEnvironments(c).Restore()
	es, err := environs.ReadEnvirons("")
	c.Assert(es, gc.IsNil)
	c.Assert(err, jc.Satisfies, environs.IsNoEnv)
}

var configTests = []struct {
	env   string
	check func(c *gc.C, envs *environs.Environs)
}{
	{`
environments:
    only:
        type: dummy
        state-server: false
`, func(c *gc.C, envs *environs.Environs) {
		cfg, err := envs.Config("")
		c.Assert(err, gc.IsNil)
		c.Assert(cfg.Name(), gc.Equals, "only")
	}}, {`
default:
    invalid
environments:
    valid:
        type: dummy
        state-server: false
    invalid:
        type: crazy
`, func(c *gc.C, envs *environs.Environs) {
		cfg, err := envs.Config("")
		c.Assert(err, gc.ErrorMatches, `environment "invalid" has an unknown provider type "crazy"`)
		c.Assert(cfg, gc.IsNil)
		cfg, err = envs.Config("valid")
		c.Assert(err, gc.IsNil)
		c.Assert(cfg.Name(), gc.Equals, "valid")
	}}, {`
environments:
    one:
        type: dummy
        state-server: false
    two:
        type: dummy
        state-server: false
`, func(c *gc.C, envs *environs.Environs) {
		cfg, err := envs.Config("")
		c.Assert(err, gc.ErrorMatches, `no default environment found`)
		c.Assert(cfg, gc.IsNil)
	}},
}

func (suite) TestConfig(c *gc.C) {
	defer testing.MakeFakeHomeNoEnvironments(c, "only", "valid", "one", "two").Restore()
	for i, t := range configTests {
		c.Logf("running test %v", i)
		envs, err := environs.ReadEnvironsBytes([]byte(t.env))
		c.Assert(err, gc.IsNil)
		t.check(c, envs)
	}
}

func (suite) TestDefaultConfigFile(c *gc.C) {
	defer testing.MakeEmptyFakeHome(c).Restore()

	env := `
environments:
    only:
        type: dummy
        state-server: false
        authorized-keys: i-am-a-key
`
	outfile, err := environs.WriteEnvirons("", env)
	c.Assert(err, gc.IsNil)
	path := testing.HomePath(".juju", "environments.yaml")
	c.Assert(path, gc.Equals, outfile)

	envs, err := environs.ReadEnvirons("")
	c.Assert(err, gc.IsNil)
	cfg, err := envs.Config("")
	c.Assert(err, gc.IsNil)
	c.Assert(cfg.Name(), gc.Equals, "only")
}

func (suite) TestConfigPerm(c *gc.C) {
	defer testing.MakeSampleHome(c).Restore()

	path := testing.HomePath(".juju")
	info, err := os.Lstat(path)
	c.Assert(err, gc.IsNil)
	oldPerm := info.Mode().Perm()
	env := `
environments:
    only:
        type: dummy
        state-server: false
        authorized-keys: i-am-a-key
`
	outfile, err := environs.WriteEnvirons("", env)
	c.Assert(err, gc.IsNil)

	info, err = os.Lstat(outfile)
	c.Assert(err, gc.IsNil)
	c.Assert(info.Mode().Perm(), gc.Equals, os.FileMode(0600))

	info, err = os.Lstat(filepath.Dir(outfile))
	c.Assert(err, gc.IsNil)
	c.Assert(info.Mode().Perm(), gc.Equals, oldPerm)

}

func (suite) TestNamedConfigFile(c *gc.C) {
	defer testing.MakeFakeHomeNoEnvironments(c, "only").Restore()

	env := `
environments:
    only:
        type: dummy
        state-server: false
        authorized-keys: i-am-a-key
`
	path := filepath.Join(c.MkDir(), "a-file")
	outfile, err := environs.WriteEnvirons(path, env)
	c.Assert(err, gc.IsNil)
	c.Assert(path, gc.Equals, outfile)

	envs, err := environs.ReadEnvirons(path)
	c.Assert(err, gc.IsNil)
	cfg, err := envs.Config("")
	c.Assert(err, gc.IsNil)
	c.Assert(cfg.Name(), gc.Equals, "only")
}

func inMap(attrs testing.Attrs, attr string) bool {
	_, ok := attrs[attr]
	return ok
}

func (suite) TestBootstrapConfig(c *gc.C) {
	defer testing.MakeFakeHomeNoEnvironments(c, "bladaam").Restore()
	attrs := dummySampleConfig().Merge(testing.Attrs{
		"agent-version": "1.2.3",
	})
	c.Assert(inMap(attrs, "secret"), jc.IsTrue)
	c.Assert(inMap(attrs, "ca-private-key"), jc.IsTrue)
	c.Assert(inMap(attrs, "admin-secret"), jc.IsTrue)

	cfg, err := config.New(config.NoDefaults, attrs)
	c.Assert(err, gc.IsNil)
	c.Assert(err, gc.IsNil)

	cfg1, err := environs.BootstrapConfig(cfg)
	c.Assert(err, gc.IsNil)

	expect := cfg.AllAttrs()
	delete(expect, "secret")
	expect["admin-secret"] = ""
	expect["ca-private-key"] = ""
	c.Assert(cfg1.AllAttrs(), gc.DeepEquals, expect)
}
<|endoftext|>


<commit_before>// Copyright 2015-2017 trivago GmbH
//
// 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 consumer

import (
	"io"
	"os"
	"strings"
	"sync"
	"time"

	"github.com/trivago/gollum/core"
	"github.com/trivago/tgo"
	"github.com/trivago/tgo/tio"
)

const (
	consoleBufferGrowSize = 256
)

// Console consumer:
//
// This consumer reads from stdin or a named pipe. A message is generated after
// each newline character.
//
// Metadata:
//
// - pipe: name of the pipe the message was received on
//
// Parameters:
//
// - Pipe: Defines the pipe to read from. This can be "stdin" or the path
// to a named pipe. If the named pipe is not existing it will be creared.
// By default this paramater is set to "stdin".
//
// - Permissions: Accepts an octal number string containing the unix file
// permissions used when creating a named pipe.
// By default this paramater is set to "0664".
//
// - ExitOnEOF: Can be set to true to trigger an exit signal if the pipe is closed
// i.e. when EOF is detected.
// By default this paramater is set to "true".
//
// Configuration example:
//
//  ConsoleIn:
//    Type: consumer.Console
//    Streams: console
//    Pipe: /tmp/namedpipe
//    Permissions: "0664"
//    ExitOnEOF: false
type Console struct {
	core.SimpleConsumer `gollumdoc:"embed_type"`
	autoExit            bool   `config:"ExitOnEOF" default:"true"`
	pipeName            string `config:"Pipe" default:"stdin"`
	pipePerm            uint32 `config:"Permissions" default:"0644"`
	pipe                *os.File
}

func init() {
	core.TypeRegistry.Register(Console{})
}

// Configure initializes this consumer with values from a plugin config.
func (cons *Console) Configure(conf core.PluginConfigReader) {
	switch strings.ToLower(cons.pipeName) {
	case "stdin":
		cons.pipe = os.Stdin
		cons.pipeName = "stdin"
	default:
		cons.pipe = nil
	}
}

// Enqueue creates a new message
func (cons *Console) Enqueue(data []byte) {
	metaData := core.Metadata{}
	metaData.SetValue("pipe", []byte(cons.pipeName))

	cons.EnqueueWithMetadata(data, metaData)
}

// Consume listens to stdin.
func (cons *Console) Consume(workers *sync.WaitGroup) {
	go cons.readPipe()
	cons.ControlLoop()
}

func (cons *Console) readPipe() {
	if cons.pipe == nil {
		var err error
		if cons.pipe, err = tio.OpenNamedPipe(cons.pipeName, cons.pipePerm); err != nil {
			cons.Logger.Error(err)
			time.AfterFunc(3*time.Second, cons.readPipe)
			return // ### return, try again ###
		}

		defer cons.pipe.Close()
	}

	buffer := tio.NewBufferedReader(consoleBufferGrowSize, 0, 0, "\n")
	for cons.IsActive() {
		err := buffer.ReadAll(cons.pipe, cons.Enqueue)
		switch err {
		case io.EOF:
			if cons.autoExit {
				cons.Logger.Info("Exit triggered by EOF.")
				tgo.ShutdownCallback()
			}

		case nil:
			// ignore
		default:
			cons.Logger.Error(err)
		}
	}
}
<commit_msg>remove colons from doc sections<commit_after>// Copyright 2015-2017 trivago GmbH
//
// 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 consumer

import (
	"io"
	"os"
	"strings"
	"sync"
	"time"

	"github.com/trivago/gollum/core"
	"github.com/trivago/tgo"
	"github.com/trivago/tgo/tio"
)

const (
	consoleBufferGrowSize = 256
)

// Console consumer
//
// This consumer reads from stdin or a named pipe. A message is generated after
// each newline character.
//
// Metadata
//
// - pipe: name of the pipe the message was received on
//
// Parameters
//
// - Pipe: Defines the pipe to read from. This can be "stdin" or the path
// to a named pipe. If the named pipe is not existing it will be creared.
// By default this paramater is set to "stdin".
//
// - Permissions: Accepts an octal number string containing the unix file
// permissions used when creating a named pipe.
// By default this paramater is set to "0664".
//
// - ExitOnEOF: Can be set to true to trigger an exit signal if the pipe is closed
// i.e. when EOF is detected.
// By default this paramater is set to "true".
//
// Configuration example
//
//  ConsoleIn:
//    Type: consumer.Console
//    Streams: console
//    Pipe: /tmp/namedpipe
//    Permissions: "0664"
//    ExitOnEOF: false
type Console struct {
	core.SimpleConsumer `gollumdoc:"embed_type"`
	autoExit            bool   `config:"ExitOnEOF" default:"true"`
	pipeName            string `config:"Pipe" default:"stdin"`
	pipePerm            uint32 `config:"Permissions" default:"0644"`
	pipe                *os.File
}

func init() {
	core.TypeRegistry.Register(Console{})
}

// Configure initializes this consumer with values from a plugin config.
func (cons *Console) Configure(conf core.PluginConfigReader) {
	switch strings.ToLower(cons.pipeName) {
	case "stdin":
		cons.pipe = os.Stdin
		cons.pipeName = "stdin"
	default:
		cons.pipe = nil
	}
}

// Enqueue creates a new message
func (cons *Console) Enqueue(data []byte) {
	metaData := core.Metadata{}
	metaData.SetValue("pipe", []byte(cons.pipeName))

	cons.EnqueueWithMetadata(data, metaData)
}

// Consume listens to stdin.
func (cons *Console) Consume(workers *sync.WaitGroup) {
	go cons.readPipe()
	cons.ControlLoop()
}

func (cons *Console) readPipe() {
	if cons.pipe == nil {
		var err error
		if cons.pipe, err = tio.OpenNamedPipe(cons.pipeName, cons.pipePerm); err != nil {
			cons.Logger.Error(err)
			time.AfterFunc(3*time.Second, cons.readPipe)
			return // ### return, try again ###
		}

		defer cons.pipe.Close()
	}

	buffer := tio.NewBufferedReader(consoleBufferGrowSize, 0, 0, "\n")
	for cons.IsActive() {
		err := buffer.ReadAll(cons.pipe, cons.Enqueue)
		switch err {
		case io.EOF:
			if cons.autoExit {
				cons.Logger.Info("Exit triggered by EOF.")
				tgo.ShutdownCallback()
			}

		case nil:
			// ignore
		default:
			cons.Logger.Error(err)
		}
	}
}
<|endoftext|>


<commit_before>package models

import (
	"errors"
	"github.com/jinzhu/gorm"
	"github.com/koding/bongo"
	"time"
)

type NotificationContent struct {
	// unique identifier of NotificationContent
	Id int64 `json:"id"`

	// target of the activity (replied messageId, followed accountId etc.)
	TargetId int64 `json:"targetId"          sql:"NOT NULL"`

	// Type of the NotificationContent
	TypeConstant string `json:"typeConstant" sql:"NOT NULL;TYPE:VARCHAR(100);"`

	// Creation date of the NotificationContent
	CreatedAt time.Time `json:"createdAt"`
}

const (
	// NotificationContent Types
	NotificationContent_TYPE_LIKE     = "like"
	NotificationContent_TYPE_UPVOTE   = "upvote"
	NotificationContent_TYPE_DOWNVOTE = "downvote"
	NotificationContent_TYPE_COMMENT  = "comment"
	NotificationContent_TYPE_FOLLOW   = "follow"
	NotificationContent_TYPE_JOIN     = "join"
	NotificationContent_TYPE_LEAVE    = "leave"
)

func NewNotificationContent() *NotificationContent {
	return &NotificationContent{}
}

func (n *NotificationContent) GetId() int64 {
	return n.Id
}

func (n NotificationContent) TableName() string {
	return "api.notification_content"
}

// Create checks for NotificationContent using type_constant and target_id
// and creates new one if it does not exist.
func (n *NotificationContent) Create() error {
	s := map[string]interface{}{
		"type_constant": n.TypeConstant,
		"target_id":     n.TargetId,
	}
	q := bongo.NewQS(s)
	if err := n.One(q); err != nil {
		if err != gorm.RecordNotFound {
			return err
		}
		return bongo.B.Create(n)
	}

	return nil
}

func (n *NotificationContent) One(q *bongo.Query) error {
	return bongo.B.One(n, n, q)
}

func (n *NotificationContent) ById(id int64) error {
	return bongo.B.ById(n, id)
}

// CreateNotification validates notifiable instance and creates a new notification
// with actor activity.
func CreateNotificationContent(i Notifiable) (*NotificationContent, error) {
	// first check for type constant and target id
	if i.GetType() == "" {
		return nil, errors.New("Type must be set")
	}

	if i.GetTargetId() == 0 {
		return nil, errors.New("TargetId must be set")
	}

	if i.GetActorId() == 0 {
		return nil, errors.New("ActorId must be set")
	}

	// check for previous NotificationContent create if it does not exist (type:comment targetId:messageId)
	nc := NewNotificationContent()
	nc.TypeConstant = i.GetType()
	nc.TargetId = i.GetTargetId()

	if err := nc.Create(); err != nil {
		return nil, err
	}

	a := NewNotificationActivity()
	a.NotificationContentId = nc.Id
	a.ActorId = i.GetActorId()
	if err := a.Create(); err != nil {
		return nil, err
	}

	return nc, nil
}

// FetchByIds fetches notification contents with given ids
func (n *NotificationContent) FetchByIds(ids []int64) ([]NotificationContent, error) {
	notificationContents := make([]NotificationContent, 0)
	if err := bongo.B.FetchByIds(n, &notificationContents, ids); err != nil {
		return nil, err
	}
	return notificationContents, nil
}

// FetchMapByIds returns NotificationContent map with given ids
func (n *NotificationContent) FetchMapByIds(ids []int64) (map[int64]NotificationContent, error) {
	ncList, err := n.FetchByIds(ids)
	if err != nil {
		return nil, err
	}

	ncMap := make(map[int64]NotificationContent, 0)
	for _, nc := range ncList {
		ncMap[nc.Id] = nc
	}

	return ncMap, nil
}

// GetEventType retrieves related event name for the NotificationContent instance
func (n *NotificationContent) GetEventType() string {
	// TODO it could be stored in a map
	switch n.TypeConstant {
	case NotificationContent_TYPE_LIKE:
		return "LikeIsAdded"
	case NotificationContent_TYPE_COMMENT:
		return "ReplyIsAdded"
	case NotificationContent_TYPE_FOLLOW:
		return "FollowHappened"
	case NotificationContent_TYPE_JOIN:
		return "GroupJoined"
	case NotificationContent_TYPE_LEAVE:
		return "GroupLeft"
	default:
		return "undefined"
	}
}

// CreateNotificationType creates an instance of notifiable subclasses
func CreateNotificationContentType(notificationType string) (Notifiable, error) {
	switch notificationType {
	case NotificationContent_TYPE_LIKE:
		return NewInteractionNotification(notificationType), nil
	case NotificationContent_TYPE_COMMENT:
		return NewReplyNotification(), nil
	case NotificationContent_TYPE_FOLLOW:
		return NewFollowNotification(), nil
	case NotificationContent_TYPE_JOIN:
		return NewGroupNotification(notificationType), nil
	case NotificationContent_TYPE_LEAVE:
		return NewGroupNotification(notificationType), nil
	default:
		return nil, errors.New("undefined notification type")
	}

}

func (nc *NotificationContent) AfterCreate() {
	bongo.B.AfterCreate(nc)
}

func (nc *NotificationContent) AfterUpdate() {
	bongo.B.AfterUpdate(nc)
}

func (nc *NotificationContent) AfterDelete() {
	bongo.B.AfterDelete(nc)
}
<commit_msg>Social: NotificationContent Create method notificationcontent fetcher lines are taken into FindByTarget method<commit_after>package models

import (
	"errors"
	"github.com/jinzhu/gorm"
	"github.com/koding/bongo"
	"time"
)

type NotificationContent struct {
	// unique identifier of NotificationContent
	Id int64 `json:"id"`

	// target of the activity (replied messageId, followed accountId etc.)
	TargetId int64 `json:"targetId"          sql:"NOT NULL"`

	// Type of the NotificationContent
	TypeConstant string `json:"typeConstant" sql:"NOT NULL;TYPE:VARCHAR(100);"`

	// Creation date of the NotificationContent
	CreatedAt time.Time `json:"createdAt"`
}

const (
	// NotificationContent Types
	NotificationContent_TYPE_LIKE     = "like"
	NotificationContent_TYPE_UPVOTE   = "upvote"
	NotificationContent_TYPE_DOWNVOTE = "downvote"
	NotificationContent_TYPE_COMMENT  = "comment"
	NotificationContent_TYPE_FOLLOW   = "follow"
	NotificationContent_TYPE_JOIN     = "join"
	NotificationContent_TYPE_LEAVE    = "leave"
)

func NewNotificationContent() *NotificationContent {
	return &NotificationContent{}
}

func (n *NotificationContent) GetId() int64 {
	return n.Id
}

func (n NotificationContent) TableName() string {
	return "api.notification_content"
}

// Create checks for NotificationContent using type_constant and target_id
// and creates new one if it does not exist.
func (n *NotificationContent) Create() error {
	if err := n.FindByTarget(); err != nil {
		if err != gorm.RecordNotFound {
			return err
		}
		return bongo.B.Create(n)
	}

	return nil
}

func (n *NotificationContent) One(q *bongo.Query) error {
	return bongo.B.One(n, n, q)
}

func (n *NotificationContent) ById(id int64) error {
	return bongo.B.ById(n, id)
}

func (n *NotificationContent) FindByTarget() error {
	s := map[string]interface{}{
		"type_constant": n.TypeConstant,
		"target_id":     n.TargetId,
	}
	q := bongo.NewQS(s)

	return n.One(q)
}

// CreateNotification validates notifiable instance and creates a new notification
// with actor activity.
func CreateNotificationContent(i Notifiable) (*NotificationContent, error) {
	// first check for type constant and target id
	if i.GetType() == "" {
		return nil, errors.New("Type must be set")
	}

	if i.GetTargetId() == 0 {
		return nil, errors.New("TargetId must be set")
	}

	if i.GetActorId() == 0 {
		return nil, errors.New("ActorId must be set")
	}

	// check for previous NotificationContent create if it does not exist (type:comment targetId:messageId)
	nc := NewNotificationContent()
	nc.TypeConstant = i.GetType()
	nc.TargetId = i.GetTargetId()

	if err := nc.Create(); err != nil {
		return nil, err
	}

	a := NewNotificationActivity()
	a.NotificationContentId = nc.Id
	a.ActorId = i.GetActorId()
	if err := a.Create(); err != nil {
		return nil, err
	}

	return nc, nil
}

// FetchByIds fetches notification contents with given ids
func (n *NotificationContent) FetchByIds(ids []int64) ([]NotificationContent, error) {
	notificationContents := make([]NotificationContent, 0)
	if err := bongo.B.FetchByIds(n, &notificationContents, ids); err != nil {
		return nil, err
	}
	return notificationContents, nil
}

// FetchMapByIds returns NotificationContent map with given ids
func (n *NotificationContent) FetchMapByIds(ids []int64) (map[int64]NotificationContent, error) {
	ncList, err := n.FetchByIds(ids)
	if err != nil {
		return nil, err
	}

	ncMap := make(map[int64]NotificationContent, 0)
	for _, nc := range ncList {
		ncMap[nc.Id] = nc
	}

	return ncMap, nil
}

// GetEventType retrieves related event name for the NotificationContent instance
func (n *NotificationContent) GetEventType() string {
	// TODO it could be stored in a map
	switch n.TypeConstant {
	case NotificationContent_TYPE_LIKE:
		return "LikeIsAdded"
	case NotificationContent_TYPE_COMMENT:
		return "ReplyIsAdded"
	case NotificationContent_TYPE_FOLLOW:
		return "FollowHappened"
	case NotificationContent_TYPE_JOIN:
		return "GroupJoined"
	case NotificationContent_TYPE_LEAVE:
		return "GroupLeft"
	default:
		return "undefined"
	}
}

// CreateNotificationType creates an instance of notifiable subclasses
func CreateNotificationContentType(notificationType string) (Notifiable, error) {
	switch notificationType {
	case NotificationContent_TYPE_LIKE:
		return NewInteractionNotification(notificationType), nil
	case NotificationContent_TYPE_COMMENT:
		return NewReplyNotification(), nil
	case NotificationContent_TYPE_FOLLOW:
		return NewFollowNotification(), nil
	case NotificationContent_TYPE_JOIN:
		return NewGroupNotification(notificationType), nil
	case NotificationContent_TYPE_LEAVE:
		return NewGroupNotification(notificationType), nil
	default:
		return nil, errors.New("undefined notification type")
	}

}

func (nc *NotificationContent) AfterCreate() {
	bongo.B.AfterCreate(nc)
}

func (nc *NotificationContent) AfterUpdate() {
	bongo.B.AfterUpdate(nc)
}

func (nc *NotificationContent) AfterDelete() {
	bongo.B.AfterDelete(nc)
}
<|endoftext|>


<commit_before>package dataframe

import (
	"bytes"
	"errors"
	"strconv"
	"sync"
)

// Errors
var (
	ErrInvalidTypesLen       = errors.New("the length of types does not match with the one of item names")
	ErrInvalidType           = errors.New("invalid type")
	ErrDuplicatedItemName    = errors.New("duplicated itemName")
	ErrNoData                = errors.New("no data")
	ErrInvalidDataColsNum    = errors.New("invalid number of data columns")
	ErrItemNameAlreadyExists = errors.New("itemName already exists")
	ErrItemNameNotExist      = errors.New("itemName does not exist")
)

// DataFrame represents a data frame.
type DataFrame struct {
	bd         *baseData
	fromRowIdx int // inclusive
	toRowIdx   int // exclusive
}

// RowNum returns the number of rows.
func (df *DataFrame) RowNum() int {
	return df.toRowIdx - df.fromRowIdx
}

// ColNum returns the number of columns.
func (df *DataFrame) ColNum() int {
	return len(df.bd.itemNames)
}

// Head creates a new data frame which has top n rows of
// the original data frame.
func (df *DataFrame) Head(n int) *DataFrame {
	return &DataFrame{df.bd, df.fromRowIdx, min(df.fromRowIdx+n, df.toRowIdx)}
}

// Tail creates a new data frame which has last n rows of
// the original data frame.
func (df *DataFrame) Tail(n int) *DataFrame {
	return &DataFrame{df.bd, max(df.toRowIdx-n, df.fromRowIdx), df.toRowIdx}
}

// String returns the string expression of the data frame.
func (df *DataFrame) String() string {
	bf := bytes.NewBufferString("")

	for i, itemName := range df.bd.itemNames {
		if i > 0 {
			bf.WriteRune(' ')
		}

		bf.WriteString(itemName)
	}

	bf.WriteRune('\n')

	for i, n := 0, min(maxPrintRows, (df.toRowIdx-df.fromRowIdx)); i < n; i++ {
		if i > 0 {
			bf.WriteRune('\n')
		}

		for j, itemName := range df.bd.itemNames {
			if j > 0 {
				bf.WriteRune(' ')
			}

			t := df.bd.types[itemName]

			if t == String {
				bf.WriteString(df.bd.stringCols[itemName][i+df.fromRowIdx])
			} else {
				bf.WriteString(strconv.FormatFloat(df.bd.float64Cols[itemName][i+df.fromRowIdx], 'f', 8, 64))
			}
		}
	}

	return bf.String()
}

// AppendFloat64ColFromStringCol creates a float64 column from a string column and
// appends it to the data frame.
func (df *DataFrame) AppendFloat64ColFromStringCol(itemName, srcItemName string, convert func(string) (float64, error)) error {
	if _, exist := df.bd.stringCols[itemName]; exist {
		return ErrItemNameAlreadyExists
	}

	if _, exist := df.bd.float64Cols[itemName]; exist {
		return ErrItemNameAlreadyExists
	}

	stringCol, exist := df.bd.stringCols[srcItemName]
	if !exist {
		return ErrItemNameNotExist
	}

	n := len(stringCol)

	float64Col := make([]float64, n)

	ch := make(chan error, numConcurrency)

	d := divUp(n, numConcurrency)

	for i := 0; i < numConcurrency; i++ {
		from := d * i
		to := min(d*(i+1), n)

		go setFloat64FromString(float64Col, stringCol, from, to, convert, ch)
	}

	errs := make([]error, 0, numConcurrency)

	for i := 0; i < numConcurrency; i++ {
		err := <-ch
		if err != nil {
			errs = append(errs, err)
		}
	}

	if len(errs) > 0 {
		return &MultiError{",", errs}
	}

	df.bd.itemNames = append(df.bd.itemNames, itemName)
	df.bd.types[itemName] = Float64
	df.bd.float64Cols[itemName] = float64Col

	return nil
}

// Float64Values creates and returns float64 2d slice.
func (df *DataFrame) Float64Values(itemNames []string) ([][]float64, error) {
	n := df.RowNum()

	v := make([][]float64, n)

	cn := len(itemNames)

	float64Cols := make([][]float64, cn)

	for i, itemName := range itemNames {
		float64Col, exist := df.bd.float64Cols[itemName]
		if !exist {
			return nil, ErrItemNameNotExist
		}

		float64Cols[i] = float64Col
	}

	wg := new(sync.WaitGroup)
	wg.Add(numConcurrency)

	d := divUp(n, numConcurrency)

	for i := 0; i < numConcurrency; i++ {
		from := df.fromRowIdx + d*i
		to := df.fromRowIdx + min(d*(i+1), n)

		go setFloat64Values(v, float64Cols, cn, from, to, wg)
	}

	wg.Wait()

	return v, nil
}

// setFloat64Values sets float64 values to v.
func setFloat64Values(v, float64Cols [][]float64, cn int, from, to int, wg *sync.WaitGroup) {
	defer wg.Done()

	for i := from; i < to; i++ {
		v[i] = make([]float64, cn)

		for j := 0; j < cn; j++ {
			v[i][j] = float64Cols[j][i]
		}
	}
}

// setFloat64FromString creates a float64 data from a string data and
// appends it to the slice.
func setFloat64FromString(float64Col []float64, stringCol []string, from, to int, convert func(string) (float64, error), ch chan<- error) {
	for i := from; i < to; i++ {
		f, err := convert(stringCol[i])
		if err != nil {
			ch <- err
			return
		}

		float64Col[i] = f
	}

	ch <- nil
}

// New creates and returns a data frame.
func New(data [][]string, config Config) (*DataFrame, error) {
	bd, err := newBaseData(data, config)
	if err != nil {
		return nil, err
	}

	return &DataFrame{bd, 0, bd.rowNum()}, nil
}
<commit_msg>Update dataframe/dataframe.go<commit_after>package dataframe

import (
	"bytes"
	"errors"
	"strconv"
	"sync"
)

// Errors
var (
	ErrInvalidTypesLen       = errors.New("the length of types does not match with the one of item names")
	ErrInvalidType           = errors.New("invalid type")
	ErrDuplicatedItemName    = errors.New("duplicated itemName")
	ErrNoData                = errors.New("no data")
	ErrInvalidDataColsNum    = errors.New("invalid number of data columns")
	ErrItemNameAlreadyExists = errors.New("itemName already exists")
	ErrItemNameNotExist      = errors.New("itemName does not exist")
)

// DataFrame represents a data frame.
type DataFrame struct {
	bd         *baseData
	fromRowIdx int // inclusive
	toRowIdx   int // exclusive
}

// RowNum returns the number of rows.
func (df *DataFrame) RowNum() int {
	return df.toRowIdx - df.fromRowIdx
}

// ColNum returns the number of columns.
func (df *DataFrame) ColNum() int {
	return len(df.bd.itemNames)
}

// Head creates a new data frame which has top n rows of
// the original data frame.
func (df *DataFrame) Head(n int) *DataFrame {
	return &DataFrame{df.bd, df.fromRowIdx, min(df.fromRowIdx+n, df.toRowIdx)}
}

// Tail creates a new data frame which has last n rows of
// the original data frame.
func (df *DataFrame) Tail(n int) *DataFrame {
	return &DataFrame{df.bd, max(df.toRowIdx-n, df.fromRowIdx), df.toRowIdx}
}

// String returns the string expression of the data frame.
func (df *DataFrame) String() string {
	bf := bytes.NewBufferString("")

	for i, itemName := range df.bd.itemNames {
		if i > 0 {
			bf.WriteRune(' ')
		}

		bf.WriteString(itemName)
	}

	bf.WriteRune('\n')

	for i, n := 0, min(maxPrintRows, (df.toRowIdx-df.fromRowIdx)); i < n; i++ {
		if i > 0 {
			bf.WriteRune('\n')
		}

		for j, itemName := range df.bd.itemNames {
			if j > 0 {
				bf.WriteRune(' ')
			}

			t := df.bd.types[itemName]

			if t == String {
				bf.WriteString(df.bd.stringCols[itemName][i+df.fromRowIdx])
			} else {
				bf.WriteString(strconv.FormatFloat(df.bd.float64Cols[itemName][i+df.fromRowIdx], 'f', 8, 64))
			}
		}
	}

	return bf.String()
}

// AppendFloat64ColFromStringCol creates a float64 column from a string column and
// appends it to the data frame.
func (df *DataFrame) AppendFloat64ColFromStringCol(itemName, srcItemName string, convert func(string) (float64, error)) error {
	if _, exist := df.bd.stringCols[itemName]; exist {
		return ErrItemNameAlreadyExists
	}

	if _, exist := df.bd.float64Cols[itemName]; exist {
		return ErrItemNameAlreadyExists
	}

	stringCol, exist := df.bd.stringCols[srcItemName]
	if !exist {
		return ErrItemNameNotExist
	}

	n := len(stringCol)

	float64Col := make([]float64, n)

	ch := make(chan error, numConcurrency)

	d := divUp(n, numConcurrency)

	for i := 0; i < numConcurrency; i++ {
		from := d * i
		to := min(d*(i+1), n)

		go setFloat64FromString(float64Col, stringCol, from, to, convert, ch)
	}

	errs := make([]error, 0, numConcurrency)

	for i := 0; i < numConcurrency; i++ {
		err := <-ch
		if err != nil {
			errs = append(errs, err)
		}
	}

	if len(errs) > 0 {
		return &MultiError{",", errs}
	}

	df.bd.itemNames = append(df.bd.itemNames, itemName)
	df.bd.types[itemName] = Float64
	df.bd.float64Cols[itemName] = float64Col

	return nil
}

// Float64Col returns a float64 column.
func (df *DataFrame) Float64Col(itemName string) ([]float64, error) {
	float64Col, exist := df.bd.float64Cols[itemName]
	if !exist {
		return nil, ErrItemNameNotExist
	}

	return float64Col, nil
}

// Float64Values creates and returns float64 2d slice.
func (df *DataFrame) Float64Values(itemNames []string) ([][]float64, error) {
	n := df.RowNum()

	v := make([][]float64, n)

	cn := len(itemNames)

	float64Cols := make([][]float64, cn)

	for i, itemName := range itemNames {
		float64Col, exist := df.bd.float64Cols[itemName]
		if !exist {
			return nil, ErrItemNameNotExist
		}

		float64Cols[i] = float64Col
	}

	wg := new(sync.WaitGroup)
	wg.Add(numConcurrency)

	d := divUp(n, numConcurrency)

	for i := 0; i < numConcurrency; i++ {
		from := df.fromRowIdx + d*i
		to := df.fromRowIdx + min(d*(i+1), n)

		go setFloat64Values(v, float64Cols, cn, from, to, wg)
	}

	wg.Wait()

	return v, nil
}

// setFloat64Values sets float64 values to v.
func setFloat64Values(v, float64Cols [][]float64, cn int, from, to int, wg *sync.WaitGroup) {
	defer wg.Done()

	for i := from; i < to; i++ {
		v[i] = make([]float64, cn)

		for j := 0; j < cn; j++ {
			v[i][j] = float64Cols[j][i]
		}
	}
}

// setFloat64FromString creates a float64 data from a string data and
// appends it to the slice.
func setFloat64FromString(float64Col []float64, stringCol []string, from, to int, convert func(string) (float64, error), ch chan<- error) {
	for i := from; i < to; i++ {
		f, err := convert(stringCol[i])
		if err != nil {
			ch <- err
			return
		}

		float64Col[i] = f
	}

	ch <- nil
}

// New creates and returns a data frame.
func New(data [][]string, config Config) (*DataFrame, error) {
	bd, err := newBaseData(data, config)
	if err != nil {
		return nil, err
	}

	return &DataFrame{bd, 0, bd.rowNum()}, nil
}
<|endoftext|>


<commit_before>package middleware

import (
	"bufio"
	"compress/flate"
	"compress/gzip"
	"errors"
	"io"
	"net"
	"net/http"
	"regexp"
	"sort"
	"strings"
)

var encoders = map[string]EncoderFunc{}

var acceptEncodingAlgorithmsRe = regexp.MustCompile(`([a-z]{2,}|\*)`)

func init() {
	// TODO:
	// lzma: Opera.
	// sdch: Chrome, Android. Gzip output + dictionary header.
	// br:   Brotli.

	// TODO: Exception for old MSIE browsers that can't handle non-HTML?
	// https://zoompf.com/blog/2012/02/lose-the-wait-http-compression
	SetEncoder("gzip", encoderGzip)

	// HTTP 1.1 "deflate" (RFC 2616) stands for DEFLATE data (RFC 1951)
	// wrapped with zlib (RFC 1950). The zlib wrapper uses Adler-32
	// checksum compared to CRC-32 used in "gzip" and thus is faster.
	//
	// But.. some old browsers (MSIE, Safari 5.1) incorrectly expect
	// raw DEFLATE data only, without the mentioned zlib wrapper.
	// Because of this major confusion, most modern browsers try it
	// both ways, first looking for zlib headers.
	// Quote by Mark Adler: http://stackoverflow.com/a/9186091/385548
	//
	// The list of browsers having problems is quite big, see:
	// http://zoompf.com/blog/2012/02/lose-the-wait-http-compression
	// https://web.archive.org/web/20120321182910/http://www.vervestudios.co/projects/compression-tests/results
	//
	// That's why we prefer gzip over deflate. It's just more reliable
	// and not significantly slower than gzip.
	SetEncoder("deflate", encoderDeflate)

	// NOTE: Not implemented, intentionally:
	// case "compress": // LZW. Deprecated.
	// case "bzip2":    // Too slow on-the-fly.
	// case "zopfli":   // Too slow on-the-fly.
	// case "xz":       // Too slow on-the-fly.
}

// An EncoderFunc is a function that wraps the provided ResponseWriter with a
// streaming compression algorithm and returns it.
//
// In case of failure, the function should return nil.
type EncoderFunc func(w http.ResponseWriter, level int) io.Writer

// SetEncoder can be used to set the implementation of a compression algorithm.
//
// The encoding should be a standardised identifier. See:
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept-Encoding
//
// For example, add the Brotli algortithm:
//
//  import brotli_enc "gopkg.in/kothar/brotli-go.v0/enc"
//
//  middleware.SetEncoder("br", func(w http.ResponseWriter, level int) io.Writer {
//    params := brotli_enc.NewBrotliParams()
//    params.SetQuality(level)
//    return brotli_enc.NewBrotliWriter(params, w)
//  })
func SetEncoder(encoding string, fn EncoderFunc) {
	if encoding == "" {
		panic("the encoding can not be empty")
	}
	if fn == nil {
		panic("attempted to set a nil encoder function")
	}
	encoders[encoding] = fn
}

var defaultContentTypes = map[string]struct{}{
	"text/html":                {},
	"text/css":                 {},
	"text/plain":               {},
	"text/javascript":          {},
	"application/javascript":   {},
	"application/x-javascript": {},
	"application/json":         {},
	"application/atom+xml":     {},
	"application/rss+xml":      {},
	"image/svg+xml":            {},
}

// DefaultCompress is a middleware that compresses response
// body of predefined content types to a data format based
// on Accept-Encoding request header. It uses a default
// compression level.
func DefaultCompress(next http.Handler) http.Handler {
	return Compress(flate.DefaultCompression)(next)
}

// Compress is a middleware that compresses response
// body of a given content types to a data format based
// on Accept-Encoding request header. It uses a given
// compression level.
func Compress(level int, types ...string) func(next http.Handler) http.Handler {
	contentTypes := defaultContentTypes
	if len(types) > 0 {
		contentTypes = make(map[string]struct{}, len(types))
		for _, t := range types {
			contentTypes[t] = struct{}{}
		}
	}

	return func(next http.Handler) http.Handler {
		fn := func(w http.ResponseWriter, r *http.Request) {
			encoder, encoding := selectEncoder(r.Header)
			mcw := &maybeCompressResponseWriter{
				ResponseWriter: w,
				w:              w,
				contentTypes:   contentTypes,
				encoder:        encoder,
				encoding:       encoding,
				level:          level,
			}
			defer mcw.Close()

			next.ServeHTTP(mcw, r)
		}

		return http.HandlerFunc(fn)
	}
}

func selectEncoder(h http.Header) (EncoderFunc, string) {
	header := h.Get("Accept-Encoding")

	// Parse the names of all accepted algorithms from the header.
	var accepted []string
	for _, m := range acceptEncodingAlgorithmsRe.FindAllStringSubmatch(header, -1) {
		accepted = append(accepted, m[1])
	}

	sort.Sort(byPerformance(accepted))

	// Select the first mutually supported algorithm.
	for _, name := range accepted {
		if fn, ok := encoders[name]; ok {
			return fn, name
		}
	}
	return nil, ""
}

type byPerformance []string

func (l byPerformance) Len() int      { return len(l) }
func (l byPerformance) Swap(i, j int) { l[i], l[j] = l[j], l[i] }
func (l byPerformance) Less(i, j int) bool {
	// Higher number = higher preference. This causes unknown names, which map
	// to 0, to always be less prefered.
	scores := map[string]int{
		"br":      3,
		"gzip":    2,
		"deflate": 1,
	}
	return scores[l[i]] > scores[l[j]]
}

type maybeCompressResponseWriter struct {
	http.ResponseWriter
	w            io.Writer
	encoder      EncoderFunc
	encoding     string
	contentTypes map[string]struct{}
	level        int
	wroteHeader  bool
}

func (w *maybeCompressResponseWriter) WriteHeader(code int) {
	if w.wroteHeader {
		return
	}
	w.wroteHeader = true
	defer w.ResponseWriter.WriteHeader(code)

	// Already compressed data?
	if w.ResponseWriter.Header().Get("Content-Encoding") != "" {
		return
	}

	// Parse the first part of the Content-Type response header.
	contentType := ""
	parts := strings.Split(w.ResponseWriter.Header().Get("Content-Type"), ";")
	if len(parts) > 0 {
		contentType = parts[0]
	}

	// Is the content type compressable?
	if _, ok := w.contentTypes[contentType]; !ok {
		return
	}

	if w.encoder != nil && w.encoding != "" {
		if wr := w.encoder(w.ResponseWriter, w.level); wr != nil {
			w.w = wr
			w.Header().Set("Content-Encoding", w.encoding)
			// The content-length after compression is unknown
			w.Header().Del("Content-Length")
		}
	}
}

func (w *maybeCompressResponseWriter) Write(p []byte) (int, error) {
	if !w.wroteHeader {
		w.WriteHeader(http.StatusOK)
	}

	return w.w.Write(p)
}

func (w *maybeCompressResponseWriter) Flush() {
	if f, ok := w.w.(http.Flusher); ok {
		f.Flush()
	}
}

func (w *maybeCompressResponseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) {
	if hj, ok := w.w.(http.Hijacker); ok {
		return hj.Hijack()
	}
	return nil, nil, errors.New("chi/middleware: http.Hijacker is unavailable on the writer")
}

func (w *maybeCompressResponseWriter) Push(target string, opts *http.PushOptions) error {
	if ps, ok := w.w.(http.Pusher); ok {
		return ps.Push(target, opts)
	}
	return errors.New("chi/middleware: http.Pusher is unavailable on the writer")
}

func (w *maybeCompressResponseWriter) Close() error {
	if c, ok := w.w.(io.WriteCloser); ok {
		return c.Close()
	}
	return errors.New("chi/middleware: io.WriteCloser is unavailable on the writer")
}

func encoderGzip(w http.ResponseWriter, level int) io.Writer {
	gw, err := gzip.NewWriterLevel(w, level)
	if err != nil {
		return nil
	}
	return gw
}

func encoderDeflate(w http.ResponseWriter, level int) io.Writer {
	dw, err := flate.NewWriter(w, level)
	if err != nil {
		return nil
	}
	return dw
}
<commit_msg>middleware: minor improvements to Compress mw handler<commit_after>package middleware

import (
	"bufio"
	"compress/flate"
	"compress/gzip"
	"errors"
	"io"
	"net"
	"net/http"
	"strings"
)

var encoders = map[string]EncoderFunc{}

var encodingPrecedence = []string{"br", "gzip", "deflate"}

func init() {
	// TODO:
	// lzma: Opera.
	// sdch: Chrome, Android. Gzip output + dictionary header.
	// br:   Brotli, see https://github.com/go-chi/chi/pull/326

	// TODO: Exception for old MSIE browsers that can't handle non-HTML?
	// https://zoompf.com/blog/2012/02/lose-the-wait-http-compression
	SetEncoder("gzip", encoderGzip)

	// HTTP 1.1 "deflate" (RFC 2616) stands for DEFLATE data (RFC 1951)
	// wrapped with zlib (RFC 1950). The zlib wrapper uses Adler-32
	// checksum compared to CRC-32 used in "gzip" and thus is faster.
	//
	// But.. some old browsers (MSIE, Safari 5.1) incorrectly expect
	// raw DEFLATE data only, without the mentioned zlib wrapper.
	// Because of this major confusion, most modern browsers try it
	// both ways, first looking for zlib headers.
	// Quote by Mark Adler: http://stackoverflow.com/a/9186091/385548
	//
	// The list of browsers having problems is quite big, see:
	// http://zoompf.com/blog/2012/02/lose-the-wait-http-compression
	// https://web.archive.org/web/20120321182910/http://www.vervestudios.co/projects/compression-tests/results
	//
	// That's why we prefer gzip over deflate. It's just more reliable
	// and not significantly slower than gzip.
	SetEncoder("deflate", encoderDeflate)

	// NOTE: Not implemented, intentionally:
	// case "compress": // LZW. Deprecated.
	// case "bzip2":    // Too slow on-the-fly.
	// case "zopfli":   // Too slow on-the-fly.
	// case "xz":       // Too slow on-the-fly.
}

// An EncoderFunc is a function that wraps the provided ResponseWriter with a
// streaming compression algorithm and returns it.
//
// In case of failure, the function should return nil.
type EncoderFunc func(w http.ResponseWriter, level int) io.Writer

// SetEncoder can be used to set the implementation of a compression algorithm.
//
// The encoding should be a standardised identifier. See:
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept-Encoding
//
// For example, add the Brotli algortithm:
//
//  import brotli_enc "gopkg.in/kothar/brotli-go.v0/enc"
//
//  middleware.SetEncoder("br", func(w http.ResponseWriter, level int) io.Writer {
//    params := brotli_enc.NewBrotliParams()
//    params.SetQuality(level)
//    return brotli_enc.NewBrotliWriter(params, w)
//  })
func SetEncoder(encoding string, fn EncoderFunc) {
	encoding = strings.ToLower(encoding)
	if encoding == "" {
		panic("the encoding can not be empty")
	}
	if fn == nil {
		panic("attempted to set a nil encoder function")
	}
	encoders[encoding] = fn

	var e string
	for _, v := range encodingPrecedence {
		if v == encoding {
			e = v
		}
	}

	if e == "" {
		encodingPrecedence = append([]string{e}, encodingPrecedence...)
	}
}

var defaultContentTypes = map[string]struct{}{
	"text/html":                {},
	"text/css":                 {},
	"text/plain":               {},
	"text/javascript":          {},
	"application/javascript":   {},
	"application/x-javascript": {},
	"application/json":         {},
	"application/atom+xml":     {},
	"application/rss+xml":      {},
	"image/svg+xml":            {},
}

// DefaultCompress is a middleware that compresses response
// body of predefined content types to a data format based
// on Accept-Encoding request header. It uses a default
// compression level.
func DefaultCompress(next http.Handler) http.Handler {
	return Compress(flate.DefaultCompression)(next)
}

// Compress is a middleware that compresses response
// body of a given content types to a data format based
// on Accept-Encoding request header. It uses a given
// compression level.
//
// NOTE: make sure to set the Content-Type header on your response
// otherwise this middleware will not compress the response body. For ex, in
// your handler you should set w.Header().Set("Content-Type", http.DetectContentType(yourBody))
// or set it manually.
func Compress(level int, types ...string) func(next http.Handler) http.Handler {
	contentTypes := defaultContentTypes
	if len(types) > 0 {
		contentTypes = make(map[string]struct{}, len(types))
		for _, t := range types {
			contentTypes[t] = struct{}{}
		}
	}

	return func(next http.Handler) http.Handler {
		fn := func(w http.ResponseWriter, r *http.Request) {
			encoder, encoding := selectEncoder(r.Header)

			cw := &compressResponseWriter{
				ResponseWriter: w,
				w:              w,
				contentTypes:   contentTypes,
				encoder:        encoder,
				encoding:       encoding,
				level:          level,
			}
			defer cw.Close()

			next.ServeHTTP(cw, r)
		}

		return http.HandlerFunc(fn)
	}
}

func selectEncoder(h http.Header) (EncoderFunc, string) {
	header := h.Get("Accept-Encoding")

	// Parse the names of all accepted algorithms from the header.
	accepted := strings.Split(strings.ToLower(header), ",")

	// Find supported encoder by accepted list by precedence
	for _, name := range encodingPrecedence {
		if fn, ok := encoders[name]; ok && matchAcceptEncoding(accepted, name) {
			return fn, name
		}
	}

	// No encoder found to match the accepted encoding
	return nil, ""
}

func matchAcceptEncoding(accepted []string, encoding string) bool {
	for _, v := range accepted {
		if strings.Index(v, encoding) >= 0 {
			return true
		}
	}
	return false
}

type compressResponseWriter struct {
	http.ResponseWriter
	w            io.Writer
	encoder      EncoderFunc
	encoding     string
	contentTypes map[string]struct{}
	level        int
	wroteHeader  bool
}

func (w *compressResponseWriter) WriteHeader(code int) {
	if w.wroteHeader {
		return
	}
	w.wroteHeader = true
	defer w.WriteHeader(code)

	// Already compressed data?
	if w.Header().Get("Content-Encoding") != "" {
		return
	}

	// Parse the first part of the Content-Type response header.
	contentType := ""
	parts := strings.Split(w.Header().Get("Content-Type"), ";")
	if len(parts) > 0 {
		contentType = parts[0]
	}

	// Is the content type compressable?
	if _, ok := w.contentTypes[contentType]; !ok {
		return
	}

	if w.encoder != nil && w.encoding != "" {
		if wr := w.encoder(w.ResponseWriter, w.level); wr != nil {
			w.w = wr
			w.Header().Set("Content-Encoding", w.encoding)

			// The content-length after compression is unknown
			w.Header().Del("Content-Length")
		}
	}
}

func (w *compressResponseWriter) Write(p []byte) (int, error) {
	if !w.wroteHeader {
		w.WriteHeader(http.StatusOK)
	}

	return w.w.Write(p)
}

func (w *compressResponseWriter) Flush() {
	if f, ok := w.w.(http.Flusher); ok {
		f.Flush()
	}
}

func (w *compressResponseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) {
	if hj, ok := w.w.(http.Hijacker); ok {
		return hj.Hijack()
	}
	return nil, nil, errors.New("chi/middleware: http.Hijacker is unavailable on the writer")
}

func (w *compressResponseWriter) Push(target string, opts *http.PushOptions) error {
	if ps, ok := w.w.(http.Pusher); ok {
		return ps.Push(target, opts)
	}
	return errors.New("chi/middleware: http.Pusher is unavailable on the writer")
}

func (w *compressResponseWriter) Close() error {
	if c, ok := w.w.(io.WriteCloser); ok {
		return c.Close()
	}
	return errors.New("chi/middleware: io.WriteCloser is unavailable on the writer")
}

func encoderGzip(w http.ResponseWriter, level int) io.Writer {
	gw, err := gzip.NewWriterLevel(w, level)
	if err != nil {
		return nil
	}
	return gw
}

func encoderDeflate(w http.ResponseWriter, level int) io.Writer {
	dw, err := flate.NewWriter(w, level)
	if err != nil {
		return nil
	}
	return dw
}
<|endoftext|>


<commit_before><commit_msg>update dashboard<commit_after><|endoftext|>


<commit_before>package vendio

import (
	"time"

	"github.com/lexicality/vending/shared/vending"
	"github.com/op/go-logging"
	rpio "github.com/stianeikeland/go-rpio"
)

// Bottom 16 pins starting at physical pin 21
var outPins = [vending.MaxLocations]rpio.Pin{
	9, 25, 11, 8,
	7, 0, 1, 5,
	6, 12, 13, 19,
	16, 26, 20, 21,
}

// Two bit input status
const (
	inLow  rpio.Pin = 23 // 16
	inHigh rpio.Pin = 24 // 18
)

type MotorMode uint8

const (
	MotorOff MotorMode = iota
	MotorOn
	MotorJammed
	MotorEmpty
)

const (
	VendTime = time.Second * 30
	// VendCheckInterval = time.Millisecond * 500
	VendCheckInterval = time.Second
)

func sprintPinMode(mode rpio.State) string {
	if mode == rpio.High {
		return "High"
	}
	return "Low"
}

type hardware struct {
	log *logging.Logger
}

func (hw *hardware) Setup() error {
	if hw.log != nil {
		hw.log.Info("Hello I'm ARM!")
	}

	err := rpio.Open()
	if err != nil {
		return err
	}

	for _, pin := range outPins {
		pin.Output()
		pin.Low()
	}

	inHigh.Input()
	inLow.Input()

	return nil
}

func (hw *hardware) Teardown() error {
	return rpio.Close()
}

func (hw *hardware) getMotorMode() MotorMode {
	highPin := inHigh.Read()
	lowPin := inLow.Read()
	if hw.log != nil {
		hw.log.Debugf("MOTOR STATE PINS: %s %s", sprintPinMode(highPin), sprintPinMode(lowPin))
	}
	// TODO: Know something john snow
	return MotorOff

	h := highPin == rpio.High
	l := lowPin == rpio.Low
	// This is made up and is probably wrong
	if h && l {
		return MotorJammed
	} else if h && !l {
		return MotorOn
	} else if !h && l {
		return MotorEmpty
	} else {
		return MotorOff
	}
}

func (hw *hardware) Vend(location uint8) error {
	if hw.log != nil {
		hw.log.Infof("~~~I AM VENDING ITEM #%d!", location)
	}

	if location > vending.MaxLocations {
		return ErrInvalidLocation
	}

	hw.log.Debugf("INPUT HIGH BIT: %")

	for _, pin := range outPins {
		pin.Low()
	}
	outPins[location].High()
	// Always stop
	defer outPins[location].Low()

	// It takes ${VendTime} seconds to push out an item under normal circumstances
	endTimer := time.NewTimer(VendTime)
	defer endTimer.Stop()
	// Check every ${VendCheckInterval} that we've not become jammed
	checkTicker := time.NewTicker(VendCheckInterval)
	defer checkTicker.Stop()

	// Trigger the ticker check immediately
	t := make(chan bool)
	defer close(t)
	t <- true
	for {
		select {
		case <-endTimer.C:
			return nil
		case <-t:
		case <-checkTicker.C:
			motorState := hw.getMotorMode()
			if motorState == MotorJammed {
				return ErrMachineJammed
			} else if motorState == MotorEmpty {
				// TODO: If it shows up as empty after 29 seconds of not being empty it's probably a successful vend
				return ErrLocationEmpty
			}
		}
	}
}
<commit_msg>Fix input debugging on rpi<commit_after>package vendio

import (
	"time"

	"github.com/lexicality/vending/shared/vending"
	"github.com/op/go-logging"
	rpio "github.com/stianeikeland/go-rpio"
)

// Bottom 16 pins starting at physical pin 21
var outPins = [vending.MaxLocations]rpio.Pin{
	9, 25, 11, 8,
	7, 0, 1, 5,
	6, 12, 13, 19,
	16, 26, 20, 21,
}

// Two bit input status
const (
	inLow  rpio.Pin = 23 // 16
	inHigh rpio.Pin = 24 // 18
)

type MotorMode uint8

const (
	MotorOff MotorMode = iota
	MotorOn
	MotorJammed
	MotorEmpty
)

const (
	VendTime = time.Second * 30
	// VendCheckInterval = time.Millisecond * 500
	VendCheckInterval = time.Second
)

func sprintPinMode(mode rpio.State) string {
	if mode == rpio.High {
		return "High"
	}
	return "Low"
}

type hardware struct {
	log *logging.Logger
}

func (hw *hardware) Setup() error {
	if hw.log != nil {
		hw.log.Info("Hello I'm ARM!")
	}

	err := rpio.Open()
	if err != nil {
		return err
	}

	for _, pin := range outPins {
		pin.Output()
		pin.Low()
	}

	inHigh.Input()
	inLow.Input()

	return nil
}

func (hw *hardware) Teardown() error {
	return rpio.Close()
}

func (hw *hardware) getMotorMode() MotorMode {
	highPin := inHigh.Read()
	lowPin := inLow.Read()
	if hw.log != nil {
		hw.log.Debugf("MOTOR STATE PINS: %s %s", sprintPinMode(highPin), sprintPinMode(lowPin))
	}
	// TODO: Know something john snow
	return MotorOff

	h := highPin == rpio.High
	l := lowPin == rpio.Low
	// This is made up and is probably wrong
	if h && l {
		return MotorJammed
	} else if h && !l {
		return MotorOn
	} else if !h && l {
		return MotorEmpty
	} else {
		return MotorOff
	}
}

func (hw *hardware) Vend(location uint8) error {
	if hw.log != nil {
		hw.log.Infof("~~~I AM VENDING ITEM #%d!", location)
	}

	if location > vending.MaxLocations {
		return ErrInvalidLocation
	}

	// Dump debugging info before starting
	hw.getMotorMode()

	for _, pin := range outPins {
		pin.Low()
	}
	outPins[location].High()
	// Always stop
	defer outPins[location].Low()

	// It takes ${VendTime} seconds to push out an item under normal circumstances
	endTimer := time.NewTimer(VendTime)
	defer endTimer.Stop()
	// Check every ${VendCheckInterval} that we've not become jammed
	checkTicker := time.NewTicker(VendCheckInterval)
	defer checkTicker.Stop()

	// Trigger the ticker check immediately
	t := make(chan bool)
	defer close(t)
	t <- true
	for {
		select {
		case <-endTimer.C:
			return nil
		case <-t:
		case <-checkTicker.C:
			motorState := hw.getMotorMode()
			if motorState == MotorJammed {
				return ErrMachineJammed
			} else if motorState == MotorEmpty {
				// TODO: If it shows up as empty after 29 seconds of not being empty it's probably a successful vend
				return ErrLocationEmpty
			}
		}
	}
}
<|endoftext|>


<commit_before>package errorcollector

import (
	"errors"
	"testing"
)

func TestErrorCollector(t *testing.T) {
	tests := []struct {
		funcs         []func() error
		notNil        bool
		expectedError string
	}{
		{
			[]func() error{},
			false,
			"",
		},
		{
			[]func() error{
				func() error { return nil },
				func() error { return nil },
				func() error { return nil },
			},
			false,
			"",
		},
		{
			[]func() error{
				func() error { return errors.New("beep") },
				func() error { return nil },
				func() error { return nil },
			},
			true,
			"collected errors: beep",
		},
		{
			[]func() error{
				func() error { return errors.New("beep") },
				func() error { return nil },
				func() error { return errors.New("boop") },
			},
			true,
			"collected errors: beep, boop",
		},
		{
			[]func() error{
				func() error {
					collector := New()
					subCollector := New()
					collector.Collect(errors.New("beep"))
					collector.Collect(errors.New("boop"))
					subCollector.Collect(errors.New("biip"))
					subCollector.Collect(nil)
					collector.Collect(subCollector)
					return collector
				},
				func() error { return nil },
				func() error { return errors.New("baap") },
			},
			true,
			"collected errors: beep, boop, biip, baap",
		},
	}

	for _, test := range tests {
		errors := New()
		for _, fn := range test.funcs {
			errors.Collect(fn())
		}
		if (errors != nil) != test.notNil {
			t.Errorf(
				"Expected error to be %v, error was %v",
				test.notNil,
				errors)
		}
		if errors != nil && errors.Error() != test.expectedError {
			t.Errorf(
				"Expected error to return %v, got %v",
				test.expectedError,
				errors.Error())
		}

	}
}

func BenchmarkErrorCollector(b *testing.B) {
	for i := 0; i < b.N; i++ {
		collector := New()
		childCollector := New()
		collector.Collect(errors.New("beep"))
		childCollector.Collect(errors.New("boop"))
		collector.Collect(childCollector)
	}
}
<commit_msg>add test case for collecting empty collector<commit_after>package errorcollector

import (
	"errors"
	"testing"
)

func TestErrorCollector(t *testing.T) {
	tests := []struct {
		funcs         []func() error
		notNil        bool
		expectedError string
	}{
		{
			[]func() error{},
			false,
			"",
		},
		{
			[]func() error{
				func() error { return nil },
				func() error { return nil },
				func() error { return nil },
			},
			false,
			"",
		},
		{
			[]func() error{
				func() error { return errors.New("beep") },
				func() error { return nil },
				func() error { return nil },
			},
			true,
			"collected errors: beep",
		},
		{
			[]func() error{
				func() error { return errors.New("beep") },
				func() error { return nil },
				func() error { return errors.New("boop") },
			},
			true,
			"collected errors: beep, boop",
		},
		{
			[]func() error{
				func() error {
					collector := New()
					subCollector := New()
					collector.Collect(errors.New("beep"))
					collector.Collect(errors.New("boop"))
					subCollector.Collect(errors.New("biip"))
					subCollector.Collect(nil)
					collector.Collect(subCollector)
					return collector
				},
				func() error { return nil },
				func() error { return errors.New("baap") },
			},
			true,
			"collected errors: beep, boop, biip, baap",
		},
		{
			[]func() error{
				func() error {
					collector := New()
					subCollector := New()
					collector.Collect(subCollector)
					return collector
				},
				func() error { return nil },
				func() error { return nil },
			},
			false,
			"",
		},
	}

	for _, test := range tests {
		errors := New()
		for _, fn := range test.funcs {
			errors.Collect(fn())
		}
		if (errors != nil) != test.notNil {
			t.Errorf(
				"Expected error to be %v, error was %v",
				test.notNil,
				errors)
		}
		if errors != nil && errors.Error() != test.expectedError {
			t.Errorf(
				"Expected error to return %v, got %v",
				test.expectedError,
				errors.Error())
		}

	}
}

func BenchmarkErrorCollector(b *testing.B) {
	for i := 0; i < b.N; i++ {
		collector := New()
		childCollector := New()
		collector.Collect(errors.New("beep"))
		childCollector.Collect(errors.New("boop"))
		collector.Collect(childCollector)
	}
}
<|endoftext|>


<commit_before>package main

import (
    "fmt"
    "os"
    "path"
    "regexp"
    "strings"
    "strconv"

    "golang.org/x/net/context"

    "github.com/adrahon/2deploy/deployer"

    "github.com/docker/libcompose/config"
    "github.com/docker/libcompose/project"

    "github.com/docker/docker/client"
    "github.com/docker/docker/api/types"
    "github.com/docker/docker/api/types/swarm"
     mounttypes "github.com/docker/docker/api/types/mount"
)

func main() {

    project_name := ProjectName()

    project := project.NewProject(&project.Context{
            ComposeFiles: []string{"docker-compose.yml"},
            ProjectName:  project_name,
    }, nil, &config.ParseOptions{})

    if err := project.Parse(); err != nil {
		fmt.Println(err)
		os.Exit(1)
    }

    cli, err := client.NewEnvClient()
    if err != nil {
		fmt.Println(err)
		os.Exit(1)
    }

    deployer := deployer.NewDeployer(cli, context.Background())

    // # Check if stack exists

    // Networks

    default_network := ""
    if project.NetworkConfigs == nil || len(project.NetworkConfigs) == 0 {
        // if no network create default
        name := fmt.Sprintf("%s_default", project_name)
        config := config.NetworkConfig { Driver: "overlay", }
		err := deployer.NetworkCreate(name, &config)
		if err != nil {
			fmt.Println(err)
		}
        default_network = name
    } else {
        for name, config := range project.NetworkConfigs {
            // # if network external check if exists
            if config.External.External {
                real_name := name
                if config.External.Name != "" {
                    real_name = config.External.Name
                }
                fmt.Printf("Checking if external network %q exists\n", real_name)
                err := deployer.CheckNetworkExists(real_name)
				if err != nil {
					fmt.Println(err)
					os.Exit(1)
				}

            } else {
                // else create network
                real_name := fmt.Sprintf("%s_%s", project_name, name)
				err := deployer.NetworkCreate(real_name, config)
				if err != nil {
					fmt.Println(err)
				}
            }
        }
    }

    // # Volumes

    if project.VolumeConfigs == nil || len(project.VolumeConfigs) == 0 {
        // no volumes
        fmt.Println("No volumes")
    } else {
        for name, config := range project.VolumeConfigs {
            // # if volume external check if exists
            if config.External.External {
                fmt.Printf("Volume: %q (external)\n", name)
                // handle external name
                if config.External.Name != "" {
                    fmt.Printf("Volume: %q (external: %q)\n", name, config.External.Name)
                }
            } else if config.Driver != "" {
                // # else create volume ?
                fmt.Printf("Volume: %q\n", name)
            }
        }
    }

	// # Services

    if project.ServiceConfigs == nil {
        // no services, abort
		fmt.Println("No services defined, aborting")
		os.Exit(1)
    } else {
        for name, config := range project.ServiceConfigs.All() {
			service_name := fmt.Sprintf("%s_%s", project_name, name)

            ports := []swarm.PortConfig{}
            for _, p := range config.Ports {
                port := strings.Split(p, ":")
                if len(port) > 1 {
                    t, _ := strconv.Atoi(port[1])
                    p, _ := strconv.Atoi(port[0])
					ports = append(ports, swarm.PortConfig{
						TargetPort:    uint32(t),
						PublishedPort: uint32(p),
					})
                } else {
                    t, _ := strconv.Atoi(port[0])
					ports = append(ports, swarm.PortConfig{
						TargetPort:    uint32(t),
					})
                }
            }

			nets := []swarm.NetworkAttachmentConfig{}
            // use default network if exists
            if default_network != "" {
                nets = append(nets, swarm.NetworkAttachmentConfig{Target: default_network})
            } else {
                if config.Networks != nil && len(config.Networks.Networks) != 0 {
                    for _, network := range config.Networks.Networks {
                        nets = append(nets, swarm.NetworkAttachmentConfig{Target: network.RealName})
                    }
                }
            }

			mounts := []mounttypes.Mount{}
			if config.Volumes != nil && len(config.Volumes.Volumes) != 0 {
				for _, volume := range config.Volumes.Volumes {
                    mounts = append(mounts, mounttypes.Mount{ Type: mounttypes.TypeVolume, Target: volume.Destination, })
				}
			}

			service_spec := swarm.ServiceSpec{
				Annotations: swarm.Annotations{
					Name:   service_name,
				},
				TaskTemplate: swarm.TaskSpec{
					ContainerSpec: swarm.ContainerSpec{
						Image:   config.Image,
						Command: config.Command,
						// Args:    service.Args,
						Env:     config.Environment,
						// Labels:  runconfigopts.ConvertKVStringsToMap(opts.containerLabels.GetAll()),
						// Dir:             opts.workdir,
						// User:            opts.user,
						// Groups:          opts.groups,
						Mounts:  mounts,
						// StopGracePeriod: opts.stopGrace.Value(),
					},
					// Networks:      convertNetworks(opts.networks),
					// Resources:     opts.resources.ToResourceRequirements(),
					// RestartPolicy: opts.restartPolicy.ToRestartPolicy(),
					// Placement: &swarm.Placement{
					//     Constraints: opts.constraints,
					//},
					// LogDriver: opts.logDriver.toLogDriver(),
				},
				EndpointSpec: &swarm.EndpointSpec{
			    		Ports: ports,
				},
				Networks: nets,
			}

            fmt.Printf("Creating service %q\n", service_name)

            s, err := cli.ServiceCreate(context.Background(), service_spec, types.ServiceCreateOptions{})
			if err != nil {
				fmt.Println(err)
				os.Exit(1)
			}

            fmt.Printf("ID: %s\n\n", s.ID)

            if config.Volumes != nil && len(config.Volumes.Volumes) != 0 {
                for _, volume := range config.Volumes.Volumes {
                    fmt.Printf("  Volume: %q\n", volume)
                }
            }
        }

	}

}

func ProjectName() string {
    // # Get stack name from --name
	// # Get stack name from directory if not passed
    pwd, err := os.Getwd()
    if err != nil {
        fmt.Println(err)
        os.Exit(1)
    }
    _, dir := path.Split(pwd)

    r := regexp.MustCompile("[^a-z0-9]+")
    return r.ReplaceAllString(strings.ToLower(dir), "")
}

<commit_msg>Remove debug messages<commit_after>package main

import (
    "fmt"
    "os"
    "path"
    "regexp"
    "strings"
    "strconv"

    "golang.org/x/net/context"

    "github.com/adrahon/2deploy/deployer"

    "github.com/docker/libcompose/config"
    "github.com/docker/libcompose/project"

    "github.com/docker/docker/client"
    "github.com/docker/docker/api/types"
    "github.com/docker/docker/api/types/swarm"
     mounttypes "github.com/docker/docker/api/types/mount"
)

func main() {

    project_name := ProjectName()

    project := project.NewProject(&project.Context{
            ComposeFiles: []string{"docker-compose.yml"},
            ProjectName:  project_name,
    }, nil, &config.ParseOptions{})

    if err := project.Parse(); err != nil {
		fmt.Println(err)
		os.Exit(1)
    }

    cli, err := client.NewEnvClient()
    if err != nil {
		fmt.Println(err)
		os.Exit(1)
    }

    deployer := deployer.NewDeployer(cli, context.Background())

    // # Check if stack exists

    // Networks

    default_network := ""
    if project.NetworkConfigs == nil || len(project.NetworkConfigs) == 0 {
        // if no network create default
        name := fmt.Sprintf("%s_default", project_name)
        config := config.NetworkConfig { Driver: "overlay", }
		err := deployer.NetworkCreate(name, &config)
		if err != nil {
			fmt.Println(err)
		}
        default_network = name
    } else {
        for name, config := range project.NetworkConfigs {
            // # if network external check if exists
            if config.External.External {
                real_name := name
                if config.External.Name != "" {
                    real_name = config.External.Name
                }
                fmt.Printf("Checking if external network %q exists\n", real_name)
                err := deployer.CheckNetworkExists(real_name)
				if err != nil {
					fmt.Println(err)
					os.Exit(1)
				}

            } else {
                // else create network
                real_name := fmt.Sprintf("%s_%s", project_name, name)
				err := deployer.NetworkCreate(real_name, config)
				if err != nil {
					fmt.Println(err)
				}
            }
        }
    }

    // # Volumes

    if project.VolumeConfigs != nil && len(project.VolumeConfigs) != 0 {
        for name, config := range project.VolumeConfigs {
            // # if volume external check if exists
            if config.External.External {
                fmt.Printf("Volume: %q (external)\n", name)
                // handle external name
                if config.External.Name != "" {
                    fmt.Printf("Volume: %q (external: %q)\n", name, config.External.Name)
                }
            } else if config.Driver != "" {
                // # else create volume ?
                fmt.Printf("Volume: %q\n", name)
            }
        }
    }

	// # Services

    if project.ServiceConfigs == nil {
        // no services, abort
		fmt.Println("No services defined, aborting")
		os.Exit(1)
    } else {
        for name, config := range project.ServiceConfigs.All() {
			service_name := fmt.Sprintf("%s_%s", project_name, name)

            ports := []swarm.PortConfig{}
            for _, p := range config.Ports {
                port := strings.Split(p, ":")
                if len(port) > 1 {
                    t, _ := strconv.Atoi(port[1])
                    p, _ := strconv.Atoi(port[0])
					ports = append(ports, swarm.PortConfig{
						TargetPort:    uint32(t),
						PublishedPort: uint32(p),
					})
                } else {
                    t, _ := strconv.Atoi(port[0])
					ports = append(ports, swarm.PortConfig{
						TargetPort:    uint32(t),
					})
                }
            }

			nets := []swarm.NetworkAttachmentConfig{}
            // use default network if exists
            if default_network != "" {
                nets = append(nets, swarm.NetworkAttachmentConfig{Target: default_network})
            } else {
                if config.Networks != nil && len(config.Networks.Networks) != 0 {
                    for _, network := range config.Networks.Networks {
                        nets = append(nets, swarm.NetworkAttachmentConfig{Target: network.RealName})
                    }
                }
            }

			mounts := []mounttypes.Mount{}
			if config.Volumes != nil && len(config.Volumes.Volumes) != 0 {
				for _, volume := range config.Volumes.Volumes {
                    mounts = append(mounts, mounttypes.Mount{ Type: mounttypes.TypeVolume, Target: volume.Destination, })
				}
			}

			service_spec := swarm.ServiceSpec{
				Annotations: swarm.Annotations{
					Name:   service_name,
				},
				TaskTemplate: swarm.TaskSpec{
					ContainerSpec: swarm.ContainerSpec{
						Image:   config.Image,
						Command: config.Command,
						// Args:    service.Args,
						Env:     config.Environment,
						// Labels:  runconfigopts.ConvertKVStringsToMap(opts.containerLabels.GetAll()),
						// Dir:             opts.workdir,
						// User:            opts.user,
						// Groups:          opts.groups,
						Mounts:  mounts,
						// StopGracePeriod: opts.stopGrace.Value(),
					},
					// Networks:      convertNetworks(opts.networks),
					// Resources:     opts.resources.ToResourceRequirements(),
					// RestartPolicy: opts.restartPolicy.ToRestartPolicy(),
					// Placement: &swarm.Placement{
					//     Constraints: opts.constraints,
					//},
					// LogDriver: opts.logDriver.toLogDriver(),
				},
				EndpointSpec: &swarm.EndpointSpec{
			    		Ports: ports,
				},
				Networks: nets,
			}

            fmt.Printf("Creating service %q\n", service_name)

            _, err := cli.ServiceCreate(context.Background(), service_spec, types.ServiceCreateOptions{})
			if err != nil {
				fmt.Println(err)
				os.Exit(1)
			}

        }

	}

}

func ProjectName() string {
    // # Get stack name from --name
	// # Get stack name from directory if not passed
    pwd, err := os.Getwd()
    if err != nil {
        fmt.Println(err)
        os.Exit(1)
    }
    _, dir := path.Split(pwd)

    r := regexp.MustCompile("[^a-z0-9]+")
    return r.ReplaceAllString(strings.ToLower(dir), "")
}

<|endoftext|>


<commit_before>package test

import (
	"errors"
	"fmt"
	"io/ioutil"
	"os"
	"testing"

	"github.com/franela/goreq"
	ogcli "github.com/opsgenie/opsgenie-go-sdk/client"
	itg "github.com/opsgenie/opsgenie-go-sdk/integration"
	"github.com/opsgenie/opsgenie-go-sdk/policy"
	"github.com/stretchr/testify/require"
	"github.com/stretchr/testify/suite"
	yaml "gopkg.in/yaml.v2"
)

type ClientTestConfig struct {
	Alert struct {
		ApiKey  string   `yaml:"apiKey"`
		User    string   `yaml:"user"`
		Team    string   `yaml:"team"`
		Actions []string `yaml:"actions"`
	} `yaml:"alert"`

	OpsGenieApiUrl string `yaml:"opsgenie.api.url"`
}

type EntityNames struct {
	Integration string `json:"integration"`
	Team        string `json:"team"`
	Policy      string `json:"policy"`
}

// common globals
var cli *ogcli.OpsGenieAlertClient
var CONFIG_FILE_NAME string = "client_at_test_cfg.yaml"
var testCfg ClientTestConfig
var hbCli *ogcli.OpsGenieHeartbeatClient
var itgCli *ogcli.OpsGenieIntegrationClient
var policyCli *ogcli.OpsGeniePolicyClient
var entityNames EntityNames

func TestEnableDisableIntegration(t *testing.T) {
	disableReq := itg.DisableIntegrationRequest{Name: entityNames.Integration}
	disableResp, disableErr := itgCli.Disable(disableReq)

	require.Nil(t, disableErr)
	require.NotNil(t, disableResp)
	require.Equal(t, 200, disableResp.Code, "Response Code should be 200")
	require.Equal(t, "success", disableResp.Status, "Response Code should be 200")
	t.Log("[OK] integration disabled")

	enableReq := itg.EnableIntegrationRequest{Name: entityNames.Integration}
	enableResp, enableErr := itgCli.Enable(enableReq)

	require.Nil(t, enableErr)
	require.NotNil(t, enableResp)
	require.Equal(t, 200, enableResp.Code, "Response Code should be 200")
	require.Equal(t, "success", enableResp.Status, "Response Code should be 200")
	t.Log("[OK] integration enabled")
}

func TestEnableDisablePolicy(t *testing.T) {
	disableReq := policy.DisablePolicyRequest{Name: entityNames.Policy}
	disableResp, disableErr := policyCli.Disable(disableReq)
	require.Nil(t, disableErr)
	require.NotNil(t, disableResp)
	require.Equal(t, 200, disableResp.Code, "Response Code should be 200")
	t.Log("[OK] policy disabled")

	enableReq := policy.EnablePolicyRequest{Name: entityNames.Policy}
	enableResp, enableErr := policyCli.Enable(enableReq)

	require.Nil(t, enableErr)
	require.NotNil(t, enableResp)
	require.Equal(t, 200, enableResp.Code, "Response Code should be 200")
	t.Log("[OK] policy enabled")
}

func TestAlertClientSuite(t *testing.T) {
	suite.Run(t, new(AlertTestSuite))
}

func TestHeartbeatClientSuite(t *testing.T) {
	suite.Run(t, new(HeartbeatTestSuite))
}

// utility function
func readSettingsFromConfigFile() error {
	cfgData, err := ioutil.ReadFile(CONFIG_FILE_NAME)
	if err != nil {
		return errors.New("Can not read from the configuration file: " + err.Error())
	}
	err = yaml.Unmarshal(cfgData, &testCfg)
	if err != nil {
		return errors.New("Can not parse the configuration file: " + err.Error())
	}
	return nil
}

// setup the test suite
func TestMain(m *testing.M) {
	// read the settings
	err := readSettingsFromConfigFile()
	if err != nil {
		panic(err)
	}

	// create an opsgenie client
	opsGenieClient := new(ogcli.OpsGenieClient)
	opsGenieClient.SetApiKey(testCfg.Alert.ApiKey)
	opsGenieClient.SetOpsGenieApiUrl(testCfg.OpsGenieApiUrl)
	//	set := ogcli.HttpTransportSettings{RequestTimeout: 20 * time.Second, ConnectionTimeout: 10 * time.Second }
	//	opsGenieClient.SetHttpTransportSettings(&set)
	opsGenieClient.SetClientProxyConfiguration(&ogcli.ClientProxyConfiguration{Host: "192.168.127.1", Port: 808, Protocol: "http"})

	req := goreq.Request{Method: "POST", Uri: opsGenieClient.GetOpsGenieApiUrl() + "/v1/json/sdkSetup", Body: map[string]string{"apiKey": opsGenieClient.GetApiKey()}}
	resp, err := req.Do()
	if err != nil {
		fmt.Println("Could not send request to create test team, integration, policy; " + err.Error())
	}
	if resp != nil {
		defer resp.Body.Close()
		if err = resp.Body.FromJsonTo(&entityNames); err != nil {
			fmt.Println("Server response for sdkSetup can not be parsed, " + err.Error())
		}
	}

	var cliErr error
	cli, cliErr = opsGenieClient.Alert()

	if cliErr != nil {
		panic(cliErr.Error())
	}

	hbCli, cliErr = opsGenieClient.Heartbeat()

	if cliErr != nil {
		panic(cliErr)
	}

	itgCli, cliErr = opsGenieClient.Integration()

	if cliErr != nil {
		panic(cliErr)
	}

	policyCli, cliErr = opsGenieClient.Policy()

	if cliErr != nil {
		panic(cliErr)
	}

	os.Exit(m.Run())
}
<commit_msg>testmain method proxy setting removal<commit_after>package test

import (
	"errors"
	"fmt"
	"io/ioutil"
	"os"
	"testing"

	"github.com/franela/goreq"
	ogcli "github.com/opsgenie/opsgenie-go-sdk/client"
	itg "github.com/opsgenie/opsgenie-go-sdk/integration"
	"github.com/opsgenie/opsgenie-go-sdk/policy"
	"github.com/stretchr/testify/require"
	"github.com/stretchr/testify/suite"
	yaml "gopkg.in/yaml.v2"
)

type ClientTestConfig struct {
	Alert struct {
		ApiKey  string   `yaml:"apiKey"`
		User    string   `yaml:"user"`
		Team    string   `yaml:"team"`
		Actions []string `yaml:"actions"`
	} `yaml:"alert"`

	OpsGenieApiUrl string `yaml:"opsgenie.api.url"`
}

type EntityNames struct {
	Integration string `json:"integration"`
	Team        string `json:"team"`
	Policy      string `json:"policy"`
}

// common globals
var cli *ogcli.OpsGenieAlertClient
var CONFIG_FILE_NAME string = "client_at_test_cfg.yaml"
var testCfg ClientTestConfig
var hbCli *ogcli.OpsGenieHeartbeatClient
var itgCli *ogcli.OpsGenieIntegrationClient
var policyCli *ogcli.OpsGeniePolicyClient
var entityNames EntityNames

func TestEnableDisableIntegration(t *testing.T) {
	disableReq := itg.DisableIntegrationRequest{Name: entityNames.Integration}
	disableResp, disableErr := itgCli.Disable(disableReq)

	require.Nil(t, disableErr)
	require.NotNil(t, disableResp)
	require.Equal(t, 200, disableResp.Code, "Response Code should be 200")
	require.Equal(t, "success", disableResp.Status, "Response Code should be 200")
	t.Log("[OK] integration disabled")

	enableReq := itg.EnableIntegrationRequest{Name: entityNames.Integration}
	enableResp, enableErr := itgCli.Enable(enableReq)

	require.Nil(t, enableErr)
	require.NotNil(t, enableResp)
	require.Equal(t, 200, enableResp.Code, "Response Code should be 200")
	require.Equal(t, "success", enableResp.Status, "Response Code should be 200")
	t.Log("[OK] integration enabled")
}

func TestEnableDisablePolicy(t *testing.T) {
	disableReq := policy.DisablePolicyRequest{Name: entityNames.Policy}
	disableResp, disableErr := policyCli.Disable(disableReq)
	require.Nil(t, disableErr)
	require.NotNil(t, disableResp)
	require.Equal(t, 200, disableResp.Code, "Response Code should be 200")
	t.Log("[OK] policy disabled")

	enableReq := policy.EnablePolicyRequest{Name: entityNames.Policy}
	enableResp, enableErr := policyCli.Enable(enableReq)

	require.Nil(t, enableErr)
	require.NotNil(t, enableResp)
	require.Equal(t, 200, enableResp.Code, "Response Code should be 200")
	t.Log("[OK] policy enabled")
}

func TestAlertClientSuite(t *testing.T) {
	suite.Run(t, new(AlertTestSuite))
}

func TestHeartbeatClientSuite(t *testing.T) {
	suite.Run(t, new(HeartbeatTestSuite))
}

// utility function
func readSettingsFromConfigFile() error {
	cfgData, err := ioutil.ReadFile(CONFIG_FILE_NAME)
	if err != nil {
		return errors.New("Can not read from the configuration file: " + err.Error())
	}
	err = yaml.Unmarshal(cfgData, &testCfg)
	if err != nil {
		return errors.New("Can not parse the configuration file: " + err.Error())
	}
	return nil
}

// setup the test suite
func TestMain(m *testing.M) {
	// read the settings
	err := readSettingsFromConfigFile()
	if err != nil {
		panic(err)
	}

	// create an opsgenie client
	opsGenieClient := new(ogcli.OpsGenieClient)
	opsGenieClient.SetApiKey(testCfg.Alert.ApiKey)
	opsGenieClient.SetOpsGenieApiUrl(testCfg.OpsGenieApiUrl)

	req := goreq.Request{Method: "POST", Uri: opsGenieClient.GetOpsGenieApiUrl() + "/v1/json/sdkSetup", Body: map[string]string{"apiKey": opsGenieClient.GetApiKey()}}
	resp, err := req.Do()
	if err != nil {
		fmt.Println("Could not send request to create test team, integration, policy; " + err.Error())
	}
	if resp != nil {
		defer resp.Body.Close()
		if err = resp.Body.FromJsonTo(&entityNames); err != nil {
			fmt.Println("Server response for sdkSetup can not be parsed, " + err.Error())
		}
	}

	var cliErr error
	cli, cliErr = opsGenieClient.Alert()

	if cliErr != nil {
		panic(cliErr.Error())
	}

	hbCli, cliErr = opsGenieClient.Heartbeat()

	if cliErr != nil {
		panic(cliErr)
	}

	itgCli, cliErr = opsGenieClient.Integration()

	if cliErr != nil {
		panic(cliErr)
	}

	policyCli, cliErr = opsGenieClient.Policy()

	if cliErr != nil {
		panic(cliErr)
	}

	os.Exit(m.Run())
}
<|endoftext|>