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

package commands

import (
	"fmt"
	"io/ioutil"
	"sort"
	"testing"

	"github.com/digitalocean/doctl"
	"github.com/digitalocean/doctl/do"
	domocks "github.com/digitalocean/doctl/do/mocks"
	"github.com/digitalocean/doctl/pkg/runner"
	"github.com/digitalocean/doctl/pkg/ssh"
	"github.com/digitalocean/godo"
	"github.com/spf13/viper"
	"github.com/stretchr/testify/assert"
)

var (
	testDroplet = do.Droplet{
		Droplet: &godo.Droplet{
			ID: 1,
			Image: &godo.Image{
				ID:           1,
				Name:         "an-image",
				Distribution: "DOOS",
			},
			Name: "a-droplet",
			Networks: &godo.Networks{
				V4: []godo.NetworkV4{
					{IPAddress: "8.8.8.8", Type: "public"},
					{IPAddress: "172.16.1.2", Type: "private"},
				},
			},
			Region: &godo.Region{
				Slug: "test0",
				Name: "test 0",
			},
		},
	}

	anotherTestDroplet = do.Droplet{
		Droplet: &godo.Droplet{
			ID: 3,
			Image: &godo.Image{
				ID:           1,
				Name:         "an-image",
				Distribution: "DOOS",
			},
			Name: "another-droplet",
			Networks: &godo.Networks{
				V4: []godo.NetworkV4{
					{IPAddress: "8.8.8.9", Type: "public"},
					{IPAddress: "172.16.1.4", Type: "private"},
				},
			},
			Region: &godo.Region{
				Slug: "test0",
				Name: "test 0",
			},
		},
	}

	testPrivateDroplet = do.Droplet{
		Droplet: &godo.Droplet{
			ID: 1,
			Image: &godo.Image{
				ID:           1,
				Name:         "an-image",
				Distribution: "DOOS",
			},
			Name: "a-droplet",
			Networks: &godo.Networks{
				V4: []godo.NetworkV4{
					{IPAddress: "172.16.1.2", Type: "private"},
				},
			},
			Region: &godo.Region{
				Slug: "test0",
				Name: "test 0",
			},
		},
	}

	testDropletList        = do.Droplets{testDroplet, anotherTestDroplet}
	testPrivateDropletList = do.Droplets{testPrivateDroplet}
	testKernel             = do.Kernel{Kernel: &godo.Kernel{ID: 1}}
	testKernelList         = do.Kernels{testKernel}
	testFloatingIP         = do.FloatingIP{
		FloatingIP: &godo.FloatingIP{
			Droplet: testDroplet.Droplet,
			Region:  testDroplet.Region,
			IP:      "127.0.0.1",
		},
	}
	testFloatingIPList = do.FloatingIPs{testFloatingIP}
)

func assertCommandNames(t *testing.T, cmd *Command, expected ...string) {
	var names []string

	for _, c := range cmd.Commands() {
		names = append(names, c.Name())
		if c.Name() == "list" {
			assert.Contains(t, c.Aliases, "ls", "Missing 'ls' alias for 'list' command.")
		}
	}

	sort.Strings(expected)
	sort.Strings(names)
	assert.Equal(t, expected, names)
}

type testFn func(c *CmdConfig, tm *tcMocks)

type tcMocks struct {
	keys              domocks.KeysService
	sizes             domocks.SizesService
	regions           domocks.RegionsService
	images            domocks.ImagesService
	imageActions      domocks.ImageActionsService
	floatingIPs       domocks.FloatingIPsService
	floatingIPActions domocks.FloatingIPActionsService
	droplets          domocks.DropletsService
	dropletActions    domocks.DropletActionsService
	domains           domocks.DomainsService
	volumes           domocks.VolumesService
	volumeActions     domocks.VolumeActionsService
	actions           domocks.ActionsService
	account           domocks.AccountService
	tags              domocks.TagsService
}

func withTestClient(t *testing.T, tFn testFn) {
	ogConfig := doctl.DoitConfig
	defer func() {
		doctl.DoitConfig = ogConfig
	}()

	cfg := NewTestConfig()
	doctl.DoitConfig = cfg

	tm := &tcMocks{}

	config := &CmdConfig{
		NS:   "test",
		Doit: cfg,
		Out:  ioutil.Discard,

		// can stub this out, since the return is dictated by the mocks.
		initServices: func(c *CmdConfig) error { return nil },

		Keys:              func() do.KeysService { return &tm.keys },
		Sizes:             func() do.SizesService { return &tm.sizes },
		Regions:           func() do.RegionsService { return &tm.regions },
		Images:            func() do.ImagesService { return &tm.images },
		ImageActions:      func() do.ImageActionsService { return &tm.imageActions },
		FloatingIPs:       func() do.FloatingIPsService { return &tm.floatingIPs },
		FloatingIPActions: func() do.FloatingIPActionsService { return &tm.floatingIPActions },
		Droplets:          func() do.DropletsService { return &tm.droplets },
		DropletActions:    func() do.DropletActionsService { return &tm.dropletActions },
		Domains:           func() do.DomainsService { return &tm.domains },
		Actions:           func() do.ActionsService { return &tm.actions },
		Account:           func() do.AccountService { return &tm.account },
		Tags:              func() do.TagsService { return &tm.tags },
		Volumes:           func() do.VolumesService { return &tm.volumes },
		VolumeActions:     func() do.VolumeActionsService { return &tm.volumeActions },
	}

	tFn(config, tm)

	assert.True(t, tm.account.AssertExpectations(t))
	assert.True(t, tm.actions.AssertExpectations(t))
	assert.True(t, tm.domains.AssertExpectations(t))
	assert.True(t, tm.dropletActions.AssertExpectations(t))
	assert.True(t, tm.droplets.AssertExpectations(t))
	assert.True(t, tm.floatingIPActions.AssertExpectations(t))
	assert.True(t, tm.floatingIPs.AssertExpectations(t))
	assert.True(t, tm.imageActions.AssertExpectations(t))
	assert.True(t, tm.images.AssertExpectations(t))
	assert.True(t, tm.regions.AssertExpectations(t))
	assert.True(t, tm.sizes.AssertExpectations(t))
	assert.True(t, tm.keys.AssertExpectations(t))
	assert.True(t, tm.tags.AssertExpectations(t))
	assert.True(t, tm.volumes.AssertExpectations(t))
	assert.True(t, tm.volumeActions.AssertExpectations(t))
}

type TestConfig struct {
	SSHFn func(user, host, keyPath string, port int, opts ssh.Options) runner.Runner
	v     *viper.Viper
}

var _ doctl.Config = &TestConfig{}

func NewTestConfig() *TestConfig {
	return &TestConfig{
		SSHFn: func(u, h, kp string, p int, opts ssh.Options) runner.Runner {
			return &doctl.MockRunner{}
		},
		v: viper.New(),
	}
}

var _ doctl.Config = &TestConfig{}

func (c *TestConfig) GetGodoClient(trace bool) (*godo.Client, error) {
	return &godo.Client{}, nil
}

func (c *TestConfig) SSH(user, host, keyPath string, port int, opts ssh.Options) runner.Runner {
	return c.SSHFn(user, host, keyPath, port, opts)
}

func (c *TestConfig) Set(ns, key string, val interface{}) {
	nskey := fmt.Sprintf("%s-%s", ns, key)
	c.v.Set(nskey, val)
}

func (c *TestConfig) GetString(ns, key string) (string, error) {
	nskey := fmt.Sprintf("%s-%s", ns, key)
	return c.v.GetString(nskey), nil
}

func (c *TestConfig) GetInt(ns, key string) (int, error) {
	nskey := fmt.Sprintf("%s-%s", ns, key)
	return c.v.GetInt(nskey), nil
}

func (c *TestConfig) GetStringSlice(ns, key string) ([]string, error) {
	nskey := fmt.Sprintf("%s-%s", ns, key)
	return c.v.GetStringSlice(nskey), nil
}

func (c *TestConfig) GetBool(ns, key string) (bool, error) {
	nskey := fmt.Sprintf("%s-%s", ns, key)
	return c.v.GetBool(nskey), nil
}
<commit_msg>defined tm.snapshots<commit_after>/*
Copyright 2016 The Doctl Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
    http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package commands

import (
	"fmt"
	"io/ioutil"
	"sort"
	"testing"

	"github.com/digitalocean/doctl"
	"github.com/digitalocean/doctl/do"
	domocks "github.com/digitalocean/doctl/do/mocks"
	"github.com/digitalocean/doctl/pkg/runner"
	"github.com/digitalocean/doctl/pkg/ssh"
	"github.com/digitalocean/godo"
	"github.com/spf13/viper"
	"github.com/stretchr/testify/assert"
)

var (
	testDroplet = do.Droplet{
		Droplet: &godo.Droplet{
			ID: 1,
			Image: &godo.Image{
				ID:           1,
				Name:         "an-image",
				Distribution: "DOOS",
			},
			Name: "a-droplet",
			Networks: &godo.Networks{
				V4: []godo.NetworkV4{
					{IPAddress: "8.8.8.8", Type: "public"},
					{IPAddress: "172.16.1.2", Type: "private"},
				},
			},
			Region: &godo.Region{
				Slug: "test0",
				Name: "test 0",
			},
		},
	}

	anotherTestDroplet = do.Droplet{
		Droplet: &godo.Droplet{
			ID: 3,
			Image: &godo.Image{
				ID:           1,
				Name:         "an-image",
				Distribution: "DOOS",
			},
			Name: "another-droplet",
			Networks: &godo.Networks{
				V4: []godo.NetworkV4{
					{IPAddress: "8.8.8.9", Type: "public"},
					{IPAddress: "172.16.1.4", Type: "private"},
				},
			},
			Region: &godo.Region{
				Slug: "test0",
				Name: "test 0",
			},
		},
	}

	testPrivateDroplet = do.Droplet{
		Droplet: &godo.Droplet{
			ID: 1,
			Image: &godo.Image{
				ID:           1,
				Name:         "an-image",
				Distribution: "DOOS",
			},
			Name: "a-droplet",
			Networks: &godo.Networks{
				V4: []godo.NetworkV4{
					{IPAddress: "172.16.1.2", Type: "private"},
				},
			},
			Region: &godo.Region{
				Slug: "test0",
				Name: "test 0",
			},
		},
	}

	testDropletList        = do.Droplets{testDroplet, anotherTestDroplet}
	testPrivateDropletList = do.Droplets{testPrivateDroplet}
	testKernel             = do.Kernel{Kernel: &godo.Kernel{ID: 1}}
	testKernelList         = do.Kernels{testKernel}
	testFloatingIP         = do.FloatingIP{
		FloatingIP: &godo.FloatingIP{
			Droplet: testDroplet.Droplet,
			Region:  testDroplet.Region,
			IP:      "127.0.0.1",
		},
	}
	testFloatingIPList = do.FloatingIPs{testFloatingIP}
)

func assertCommandNames(t *testing.T, cmd *Command, expected ...string) {
	var names []string

	for _, c := range cmd.Commands() {
		names = append(names, c.Name())
		if c.Name() == "list" {
			assert.Contains(t, c.Aliases, "ls", "Missing 'ls' alias for 'list' command.")
		}
	}

	sort.Strings(expected)
	sort.Strings(names)
	assert.Equal(t, expected, names)
}

type testFn func(c *CmdConfig, tm *tcMocks)

type tcMocks struct {
	keys              domocks.KeysService
	sizes             domocks.SizesService
	regions           domocks.RegionsService
	images            domocks.ImagesService
	imageActions      domocks.ImageActionsService
	floatingIPs       domocks.FloatingIPsService
	floatingIPActions domocks.FloatingIPActionsService
	droplets          domocks.DropletsService
	dropletActions    domocks.DropletActionsService
	domains           domocks.DomainsService
	volumes           domocks.VolumesService
	volumeActions     domocks.VolumeActionsService
	actions           domocks.ActionsService
	account           domocks.AccountService
	tags              domocks.TagsService
	snapshots         domocks.SnapshotsService
}

func withTestClient(t *testing.T, tFn testFn) {
	ogConfig := doctl.DoitConfig
	defer func() {
		doctl.DoitConfig = ogConfig
	}()

	cfg := NewTestConfig()
	doctl.DoitConfig = cfg

	tm := &tcMocks{}

	config := &CmdConfig{
		NS:   "test",
		Doit: cfg,
		Out:  ioutil.Discard,

		// can stub this out, since the return is dictated by the mocks.
		initServices: func(c *CmdConfig) error { return nil },

		Keys:              func() do.KeysService { return &tm.keys },
		Sizes:             func() do.SizesService { return &tm.sizes },
		Regions:           func() do.RegionsService { return &tm.regions },
		Images:            func() do.ImagesService { return &tm.images },
		ImageActions:      func() do.ImageActionsService { return &tm.imageActions },
		FloatingIPs:       func() do.FloatingIPsService { return &tm.floatingIPs },
		FloatingIPActions: func() do.FloatingIPActionsService { return &tm.floatingIPActions },
		Droplets:          func() do.DropletsService { return &tm.droplets },
		DropletActions:    func() do.DropletActionsService { return &tm.dropletActions },
		Domains:           func() do.DomainsService { return &tm.domains },
		Actions:           func() do.ActionsService { return &tm.actions },
		Account:           func() do.AccountService { return &tm.account },
		Tags:              func() do.TagsService { return &tm.tags },
		Volumes:           func() do.VolumesService { return &tm.volumes },
		VolumeActions:     func() do.VolumeActionsService { return &tm.volumeActions },
	}

	tFn(config, tm)

	assert.True(t, tm.account.AssertExpectations(t))
	assert.True(t, tm.actions.AssertExpectations(t))
	assert.True(t, tm.domains.AssertExpectations(t))
	assert.True(t, tm.dropletActions.AssertExpectations(t))
	assert.True(t, tm.droplets.AssertExpectations(t))
	assert.True(t, tm.floatingIPActions.AssertExpectations(t))
	assert.True(t, tm.floatingIPs.AssertExpectations(t))
	assert.True(t, tm.imageActions.AssertExpectations(t))
	assert.True(t, tm.images.AssertExpectations(t))
	assert.True(t, tm.regions.AssertExpectations(t))
	assert.True(t, tm.sizes.AssertExpectations(t))
	assert.True(t, tm.keys.AssertExpectations(t))
	assert.True(t, tm.tags.AssertExpectations(t))
	assert.True(t, tm.volumes.AssertExpectations(t))
	assert.True(t, tm.volumeActions.AssertExpectations(t))
}

type TestConfig struct {
	SSHFn func(user, host, keyPath string, port int, opts ssh.Options) runner.Runner
	v     *viper.Viper
}

var _ doctl.Config = &TestConfig{}

func NewTestConfig() *TestConfig {
	return &TestConfig{
		SSHFn: func(u, h, kp string, p int, opts ssh.Options) runner.Runner {
			return &doctl.MockRunner{}
		},
		v: viper.New(),
	}
}

var _ doctl.Config = &TestConfig{}

func (c *TestConfig) GetGodoClient(trace bool) (*godo.Client, error) {
	return &godo.Client{}, nil
}

func (c *TestConfig) SSH(user, host, keyPath string, port int, opts ssh.Options) runner.Runner {
	return c.SSHFn(user, host, keyPath, port, opts)
}

func (c *TestConfig) Set(ns, key string, val interface{}) {
	nskey := fmt.Sprintf("%s-%s", ns, key)
	c.v.Set(nskey, val)
}

func (c *TestConfig) GetString(ns, key string) (string, error) {
	nskey := fmt.Sprintf("%s-%s", ns, key)
	return c.v.GetString(nskey), nil
}

func (c *TestConfig) GetInt(ns, key string) (int, error) {
	nskey := fmt.Sprintf("%s-%s", ns, key)
	return c.v.GetInt(nskey), nil
}

func (c *TestConfig) GetStringSlice(ns, key string) ([]string, error) {
	nskey := fmt.Sprintf("%s-%s", ns, key)
	return c.v.GetStringSlice(nskey), nil
}

func (c *TestConfig) GetBool(ns, key string) (bool, error) {
	nskey := fmt.Sprintf("%s-%s", ns, key)
	return c.v.GetBool(nskey), nil
}
<|endoftext|>


<commit_before>package buf_test

import (
	"bytes"
	"io"
	"testing"

	. "v2ray.com/core/common/buf"
	"v2ray.com/core/transport/pipe"
	. "v2ray.com/ext/assert"
)

func TestAdaptiveReader(t *testing.T) {
	assert := With(t)

	reader := NewReader(bytes.NewReader(make([]byte, 1024*1024)))
	b, err := reader.ReadMultiBuffer()
	assert(err, IsNil)
	assert(b.Len(), Equals, int32(Size))

	b, err = reader.ReadMultiBuffer()
	assert(err, IsNil)
	assert(b.Len(), Equals, int32(8*1024))

	b, err = reader.ReadMultiBuffer()
	assert(err, IsNil)
	assert(b.Len(), Equals, int32(32*1024))

	b, err = reader.ReadMultiBuffer()
	assert(err, IsNil)
	assert(b.Len(), Equals, int32(128*1024))
}

func TestBytesReaderWriteTo(t *testing.T) {
	assert := With(t)

	pReader, pWriter := pipe.New(pipe.WithSizeLimit(1024))
	reader := &BufferedReader{Reader: pReader}
	b1 := New()
	b1.WriteBytes('a', 'b', 'c')
	b2 := New()
	b2.WriteBytes('e', 'f', 'g')
	assert(pWriter.WriteMultiBuffer(NewMultiBufferValue(b1, b2)), IsNil)
	pWriter.Close()

	pReader2, pWriter2 := pipe.New(pipe.WithSizeLimit(1024))
	writer := NewBufferedWriter(pWriter2)
	writer.SetBuffered(false)

	nBytes, err := io.Copy(writer, reader)
	assert(err, IsNil)
	assert(nBytes, Equals, int64(6))

	mb, err := pReader2.ReadMultiBuffer()
	assert(err, IsNil)
	assert(len(mb), Equals, 2)
	assert(mb[0].String(), Equals, "abc")
	assert(mb[1].String(), Equals, "efg")
}

func TestBytesReaderMultiBuffer(t *testing.T) {
	assert := With(t)

	pReader, pWriter := pipe.New(pipe.WithSizeLimit(1024))
	reader := &BufferedReader{Reader: pReader}
	b1 := New()
	b1.WriteBytes('a', 'b', 'c')
	b2 := New()
	b2.WriteBytes('e', 'f', 'g')
	assert(pWriter.WriteMultiBuffer(NewMultiBufferValue(b1, b2)), IsNil)
	pWriter.Close()

	mbReader := NewReader(reader)
	mb, err := mbReader.ReadMultiBuffer()
	assert(err, IsNil)
	assert(len(mb), Equals, 2)
	assert(mb[0].String(), Equals, "abc")
	assert(mb[1].String(), Equals, "efg")
}

func TestReaderInterface(t *testing.T) {
	assert := With(t)

	assert((*BytesToBufferReader)(nil), Implements, (*io.Reader)(nil))
	assert((*BytesToBufferReader)(nil), Implements, (*Reader)(nil))

	assert((*BufferedReader)(nil), Implements, (*Reader)(nil))
	assert((*BufferedReader)(nil), Implements, (*io.Reader)(nil))
	assert((*BufferedReader)(nil), Implements, (*io.ByteReader)(nil))
	assert((*BufferedReader)(nil), Implements, (*io.WriterTo)(nil))
}
<commit_msg>fix test case on arm<commit_after>package buf_test

import (
	"bytes"
	"io"
	"runtime"
	"testing"

	. "v2ray.com/core/common/buf"
	"v2ray.com/core/transport/pipe"
	. "v2ray.com/ext/assert"
)

func TestAdaptiveReader(t *testing.T) {
	if runtime.GOARCH != "amd64" {
		t.Skip("Smart reader only works on highend devices.")
		return
	}

	assert := With(t)

	reader := NewReader(bytes.NewReader(make([]byte, 1024*1024)))
	b, err := reader.ReadMultiBuffer()
	assert(err, IsNil)
	assert(b.Len(), Equals, int32(Size))

	b, err = reader.ReadMultiBuffer()
	assert(err, IsNil)
	assert(b.Len(), Equals, int32(8*1024))

	b, err = reader.ReadMultiBuffer()
	assert(err, IsNil)
	assert(b.Len(), Equals, int32(32*1024))

	b, err = reader.ReadMultiBuffer()
	assert(err, IsNil)
	assert(b.Len(), Equals, int32(128*1024))
}

func TestBytesReaderWriteTo(t *testing.T) {
	assert := With(t)

	pReader, pWriter := pipe.New(pipe.WithSizeLimit(1024))
	reader := &BufferedReader{Reader: pReader}
	b1 := New()
	b1.WriteBytes('a', 'b', 'c')
	b2 := New()
	b2.WriteBytes('e', 'f', 'g')
	assert(pWriter.WriteMultiBuffer(NewMultiBufferValue(b1, b2)), IsNil)
	pWriter.Close()

	pReader2, pWriter2 := pipe.New(pipe.WithSizeLimit(1024))
	writer := NewBufferedWriter(pWriter2)
	writer.SetBuffered(false)

	nBytes, err := io.Copy(writer, reader)
	assert(err, IsNil)
	assert(nBytes, Equals, int64(6))

	mb, err := pReader2.ReadMultiBuffer()
	assert(err, IsNil)
	assert(len(mb), Equals, 2)
	assert(mb[0].String(), Equals, "abc")
	assert(mb[1].String(), Equals, "efg")
}

func TestBytesReaderMultiBuffer(t *testing.T) {
	assert := With(t)

	pReader, pWriter := pipe.New(pipe.WithSizeLimit(1024))
	reader := &BufferedReader{Reader: pReader}
	b1 := New()
	b1.WriteBytes('a', 'b', 'c')
	b2 := New()
	b2.WriteBytes('e', 'f', 'g')
	assert(pWriter.WriteMultiBuffer(NewMultiBufferValue(b1, b2)), IsNil)
	pWriter.Close()

	mbReader := NewReader(reader)
	mb, err := mbReader.ReadMultiBuffer()
	assert(err, IsNil)
	assert(len(mb), Equals, 2)
	assert(mb[0].String(), Equals, "abc")
	assert(mb[1].String(), Equals, "efg")
}

func TestReaderInterface(t *testing.T) {
	assert := With(t)

	assert((*BytesToBufferReader)(nil), Implements, (*io.Reader)(nil))
	assert((*BytesToBufferReader)(nil), Implements, (*Reader)(nil))

	assert((*BufferedReader)(nil), Implements, (*Reader)(nil))
	assert((*BufferedReader)(nil), Implements, (*io.Reader)(nil))
	assert((*BufferedReader)(nil), Implements, (*io.ByteReader)(nil))
	assert((*BufferedReader)(nil), Implements, (*io.WriterTo)(nil))
}
<|endoftext|>


<commit_before>package assigners_test

import (
	"github.com/stretchr/testify/assert"
	"github.com/vlad-doru/experimento/assigners"
	"github.com/vlad-doru/experimento/utils/test"

	"testing"
)

func TestBasicABDeterminism(t *testing.T) {
	a := assigners.NewBasicAB()
	desc, err := test.GetDefaultExperimentDescription()
	assert.NotNil(t, a)
	assert.Nil(t, err)
	sampleSize := 1000
	checkSize := 1000
	for i := 0; i < sampleSize; i++ {
		randID := test.RandString(6, 10)
		expected, err := a.AssignGroup(randID, desc)
		assert.Nil(t, err)
		for j := 0; j < checkSize; j++ {
			actual, err := a.AssignGroup(randID, desc)
			assert.Nil(t, err)
			assert.Equal(t, expected, actual)
			if (actual != expected) || (err != nil) {
				assert.FailNow(t, "BasicAB assigner behaviour is non deterministic.")
			}
		}
	}
}

func TestBasicABDistribution(t *testing.T) {
	a := assigners.NewBasicAB()
	desc, err := test.GetDefaultExperimentDescription()
	assert.NotNil(t, a)
	assert.Nil(t, err)
	sampleSize := 100000
	count := map[string]int{}
	for i := 0; i < sampleSize; i++ {
		randID := test.RandString(6, 10)
		group, err := a.AssignGroup(randID, desc)
		count[group]++
		assert.Nil(t, err)
	}
	// Check if the distribution is correct.
	assert.InEpsilon(t, test.ExpControlGroupSize, float64(count["control"])/float64(sampleSize), 0.01)
	assert.InEpsilon(t, test.ExpTestGroupSize, float64(count["test"])/float64(sampleSize), 0.01)
}
<commit_msg>Added a new assertion in the test.<commit_after>package assigners_test

import (
	"github.com/stretchr/testify/assert"
	"github.com/vlad-doru/experimento/assigners"
	"github.com/vlad-doru/experimento/utils/test"

	"testing"
)

func TestBasicABDeterminism(t *testing.T) {
	test.SetSeed(1)
	a := assigners.NewBasicAB()
	desc, err := test.GetDefaultExperimentDescription()
	assert.NotNil(t, a)
	assert.Nil(t, err)
	sampleSize := 1000
	checkSize := 1000
	for i := 0; i < sampleSize; i++ {
		randID := test.RandString(6, 10)
		expected, err := a.AssignGroup(randID, desc)
		assert.Nil(t, err)
		for j := 0; j < checkSize; j++ {
			actual, err := a.AssignGroup(randID, desc)
			assert.Nil(t, err)
			assert.Equal(t, expected, actual)
			if (actual != expected) || (err != nil) {
				assert.FailNow(t, "BasicAB assigner behaviour is non deterministic.")
			}
		}
	}
}

func TestBasicABDistribution(t *testing.T) {
	test.SetSeed(1)
	a := assigners.NewBasicAB()
	desc, err := test.GetDefaultExperimentDescription()
	assert.NotNil(t, a)
	assert.Nil(t, err)
	sampleSize := 100000
	count := map[string]int{}
	for i := 0; i < sampleSize; i++ {
		randID := test.RandString(6, 10)
		group, err := a.AssignGroup(randID, desc)
		count[group]++
		assert.Nil(t, err)
	}
	// Check if the distribution is correct.
	assert.InEpsilon(t, test.ExpControlGroupSize, float64(count["control"])/float64(sampleSize), 0.01)
	assert.InEpsilon(t, test.ExpTestGroupSize, float64(count["test"])/float64(sampleSize), 0.01)
	assert.Equal(t, count["control"]+count["test"], sampleSize, "There were other groups returned, other than test and control")
}
<|endoftext|>


<commit_before>package comparer

import (
	"bufio"
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"reflect"
	"runtime"
	"strings"
	"testing"
)

var wd, _ = os.Getwd()

func TestCompareFolder(t *testing.T) {
	fileMissing := "no such file or directory"
	if runtime.GOOS == "windows" {
		fileMissing = "The system cannot find the file specified."
	}
	tests := []struct {
		name     string
		PathA    string
		PathB    string
		Expected error
	}{
		{
			name:     "no dir",
			PathA:    "fakeDir1",
			PathB:    "fakeDir2",
			Expected: fmt.Errorf("chdir fakeDir1: %s", fileMissing),
		},
	}
	for _, test := range tests {
		err := Compare(test.PathA, test.PathB)
		if !reflect.DeepEqual(err.Error(), test.Expected.Error()) {
			t.Errorf("Wanted error %v, got %v", test.Expected, err)
		}
	}
	err := Compare(filepath.Join(wd, "testPaths", "Original"), filepath.Join(wd, "testPaths", "Translation"))
	if err != nil {
		t.Errorf("Wanted error %v, got %v", nil, err)
	}
}

func TestReadFile(t *testing.T) {
	DocType = "xml"
	type args struct {
		file string
		path string
	}
	tests := []struct {
		name    string
		args    args
		want    map[string]string
		wantErr bool
	}{
		{
			name: "read file",
			args: args{
				file: "File01.xml",
				path: filepath.Join(wd, "testPaths", "Original"),
			},
			want:    map[string]string{"<linha1>": "TEste", "<linha2>": "teste", "<linha3>": "teste"},
			wantErr: false,
		},
		{
			name: "cant read invalid file",
			args: args{
				file: "inexistant.xml",
				path: filepath.Join(wd, "testPaths", "Original"),
			},
			wantErr: true,
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			got, err := readFile(tt.args.file, tt.args.path)
			if (err != nil) != tt.wantErr {
				t.Errorf("readFile() error = %v, wantErr %v", err, tt.wantErr)
				return
			}
			if !reflect.DeepEqual(got, tt.want) {
				t.Errorf("readFile() = %v, want %v", got, tt.want)
			}
		})
	}
}

func TestFindMissing(t *testing.T) {
	type args struct {
		original    map[string]string
		translation map[string]string
	}
	tests := []struct {
		name string
		args args
		want map[string]string
	}{
		{
			name: "find missing Tags",
			args: args{
				original:    map[string]string{"<linha 1>": "", "<linha 2>": "", "<linha 3>": "teste"},
				translation: map[string]string{"<linha 1>": "", "<linha 2>": ""},
			},
			want: map[string]string{"<linha 3>": "teste"},
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			if got := findMissing(tt.args.original, tt.args.translation); !reflect.DeepEqual(got, tt.want) {
				t.Errorf("findMissing() = %v, want %v", got, tt.want)
			}
		})
	}
}

func TestReadFiles(t *testing.T) {
	tests := []struct {
		name    string
		orgF    string
		trltF   string
		wantErr bool
	}{
		{
			name:    "testing equal files",
			orgF:    filepath.Join("testPaths", "Original", "File01.xml"),
			trltF:   filepath.Join("testPaths", "Translation", "File01.xml"),
			wantErr: false,
		},
		{
			name:    "testing no such original file",
			orgF:    filepath.Join("testPaths", "Original", "invalid.xml"),
			wantErr: true,
		},
		{
			name:    "invalid translation path",
			orgF:    filepath.Join("xayah", "fake"),
			wantErr: true,
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			if err := readFiles(filepath.Join(wd, tt.orgF), filepath.Join(wd, tt.trltF)); (err != nil) != tt.wantErr {
				t.Errorf("name: %s\nreadFiles() error = %v, wantErr %v", tt.name, err, tt.wantErr)
			}
		})
	}
}

func TestReadFilesWithOutdatedTags(t *testing.T) {
	tests := []struct {
		name    string
		orgF    string
		trltF   string
		wantErr bool
	}{
		{
			name:    "testing equal files",
			orgF:    filepath.Join("testPaths", "Original", "File03.xml"),
			trltF:   filepath.Join("testPaths", "Translation", "File03.xml"),
			wantErr: false,
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			if err := readFiles(filepath.Join(wd, tt.orgF), filepath.Join(wd, tt.trltF)); (err != nil) != tt.wantErr {
				t.Errorf("readFiles() error = %v, wantErr %v", err, tt.wantErr)
			}
		})
	}
	f, err := os.Open(filepath.Join(wd, tests[0].trltF))
	if err != nil {
		t.Error(err)
	}
	defer f.Close()
	scanner := bufio.NewScanner(f)
	var outdated bool
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), "OUTDATED") {
			outdated = true
		}
	}
	if !outdated {
		t.Error("File File03.xml should have a outdated tag")
	}
	err = ioutil.WriteFile(filepath.Join(wd, "testPaths", "Translation", "File03.xml"), []byte("<linha4></linha4>"), 0644)
	if err != nil {
		t.Error(err)
	}
}

func TestCheckTransDir(t *testing.T) {
	os.Chdir("..")
	wd, _ := os.Getwd()
	tests := []struct {
		name           string
		originalDir    string
		translationDir string
		wantErr        bool
	}{
		{
			name:           "test translation has no dir1",
			originalDir:    filepath.Join(wd, "English", "Dir1"),
			translationDir: filepath.Join(wd, "Translation"),
			wantErr:        false,
		},
		{
			name:           "test same name dirs should pass",
			originalDir:    filepath.Join(wd, "English", "Dir1"),
			translationDir: filepath.Join(wd, "English"),
			wantErr:        false,
		},
		{
			name:           "test fake dirs should err",
			originalDir:    filepath.Join(wd, "English", "Dir1"),
			translationDir: filepath.Join(wd, "kai'sa"),
			wantErr:        true,
		},
	}
	for _, tt := range tests {
		if err := checkTransDirExists(tt.originalDir, tt.translationDir); (err != nil) != tt.wantErr {
			t.Errorf("\nname: %s\ndir: %s\ncheckTransDir() error = %v, wantErr %v", tt.name, tt.translationDir, err, tt.wantErr)
		}
	}
	err := os.Remove(filepath.Join(wd, "Translation", "Dir1"))
	if err != nil {
		t.Errorf("Error = %v", err)
	}
}

func Test_writeToFileMissingTags(t *testing.T) {
	type args struct {
		trltF       string
		missingTags map[string]string
		outdated    bool
	}
	tests := []struct {
		name    string
		args    args
		wantErr bool
	}{
		{
			name: "cant open invalid translation file",
			args: args{
				trltF: filepath.Join("testPaths", "Translation", "garen.txt"),
			},
			wantErr: true,
		},
		{
			name: "cant open invalid translation file",
			args: args{
				trltF: filepath.Join("testPaths", "Translation", "garen.txt"),
			},
			wantErr: true,
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			if err := writeToFileMissingTags(tt.args.trltF, tt.args.missingTags, tt.args.outdated); (err != nil) != tt.wantErr {
				t.Errorf("name: %s\n writeToFileMissingTags() error = %v, wantErr %v", tt.name, err, tt.wantErr)
			}
		})
	}
}
<commit_msg>comparer_test: comment unconsistent test case<commit_after>package comparer

import (
	"bufio"
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"reflect"
	"runtime"
	"strings"
	"testing"
)

var wd, _ = os.Getwd()

func TestCompareFolder(t *testing.T) {
	fileMissing := "no such file or directory"
	if runtime.GOOS == "windows" {
		fileMissing = "The system cannot find the file specified."
	}
	tests := []struct {
		name     string
		PathA    string
		PathB    string
		Expected error
	}{
		{
			name:     "no dir",
			PathA:    "fakeDir1",
			PathB:    "fakeDir2",
			Expected: fmt.Errorf("chdir fakeDir1: %s", fileMissing),
		},
	}
	for _, test := range tests {
		err := Compare(test.PathA, test.PathB)
		if !reflect.DeepEqual(err.Error(), test.Expected.Error()) {
			t.Errorf("Wanted error %v, got %v", test.Expected, err)
		}
	}
	err := Compare(filepath.Join(wd, "testPaths", "Original"), filepath.Join(wd, "testPaths", "Translation"))
	if err != nil {
		t.Errorf("Wanted error %v, got %v", nil, err)
	}
}

func TestReadFile(t *testing.T) {
	DocType = "xml"
	type args struct {
		file string
		path string
	}
	tests := []struct {
		name    string
		args    args
		want    map[string]string
		wantErr bool
	}{
		{
			name: "read file",
			args: args{
				file: "File01.xml",
				path: filepath.Join(wd, "testPaths", "Original"),
			},
			want:    map[string]string{"<linha1>": "TEste", "<linha2>": "teste", "<linha3>": "teste"},
			wantErr: false,
		},
		{
			name: "cant read invalid file",
			args: args{
				file: "inexistant.xml",
				path: filepath.Join(wd, "testPaths", "Original"),
			},
			wantErr: true,
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			got, err := readFile(tt.args.file, tt.args.path)
			if (err != nil) != tt.wantErr {
				t.Errorf("readFile() error = %v, wantErr %v", err, tt.wantErr)
				return
			}
			if !reflect.DeepEqual(got, tt.want) {
				t.Errorf("readFile() = %v, want %v", got, tt.want)
			}
		})
	}
}

func TestFindMissing(t *testing.T) {
	type args struct {
		original    map[string]string
		translation map[string]string
	}
	tests := []struct {
		name string
		args args
		want map[string]string
	}{
		{
			name: "find missing Tags",
			args: args{
				original:    map[string]string{"<linha 1>": "", "<linha 2>": "", "<linha 3>": "teste"},
				translation: map[string]string{"<linha 1>": "", "<linha 2>": ""},
			},
			want: map[string]string{"<linha 3>": "teste"},
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			if got := findMissing(tt.args.original, tt.args.translation); !reflect.DeepEqual(got, tt.want) {
				t.Errorf("findMissing() = %v, want %v", got, tt.want)
			}
		})
	}
}

func TestReadFiles(t *testing.T) {
	tests := []struct {
		name    string
		orgF    string
		trltF   string
		wantErr bool
	}{
		{
			name:    "testing equal files",
			orgF:    filepath.Join("testPaths", "Original", "File01.xml"),
			trltF:   filepath.Join("testPaths", "Translation", "File01.xml"),
			wantErr: false,
		},
		{
			name:    "testing no such original file",
			orgF:    filepath.Join("testPaths", "Original", "invalid.xml"),
			wantErr: true,
		},
		{
			name:    "invalid translation path",
			orgF:    filepath.Join("xayah", "fake"),
			wantErr: true,
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			if err := readFiles(filepath.Join(wd, tt.orgF), filepath.Join(wd, tt.trltF)); (err != nil) != tt.wantErr {
				t.Errorf("name: %s\nreadFiles() error = %v, wantErr %v", tt.name, err, tt.wantErr)
			}
		})
	}
}

func TestReadFilesWithOutdatedTags(t *testing.T) {
	tests := []struct {
		name    string
		orgF    string
		trltF   string
		wantErr bool
	}{
		{
			name:    "testing equal files",
			orgF:    filepath.Join("testPaths", "Original", "File03.xml"),
			trltF:   filepath.Join("testPaths", "Translation", "File03.xml"),
			wantErr: false,
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			if err := readFiles(filepath.Join(wd, tt.orgF), filepath.Join(wd, tt.trltF)); (err != nil) != tt.wantErr {
				t.Errorf("readFiles() error = %v, wantErr %v", err, tt.wantErr)
			}
		})
	}
	f, err := os.Open(filepath.Join(wd, tests[0].trltF))
	if err != nil {
		t.Error(err)
	}
	defer f.Close()
	scanner := bufio.NewScanner(f)
	var outdated bool
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), "OUTDATED") {
			outdated = true
		}
	}
	if !outdated {
		t.Error("File File03.xml should have a outdated tag")
	}
	err = ioutil.WriteFile(filepath.Join(wd, "testPaths", "Translation", "File03.xml"), []byte("<linha4></linha4>"), 0644)
	if err != nil {
		t.Error(err)
	}
}

func TestCheckTransDir(t *testing.T) {
	os.Chdir("..")
	wd, _ := os.Getwd()
	tests := []struct {
		name           string
		originalDir    string
		translationDir string
		wantErr        bool
	}{
		{
			name:           "test translation has no dir1",
			originalDir:    filepath.Join(wd, "English", "Dir1"),
			translationDir: filepath.Join(wd, "Translation"),
			wantErr:        false,
		},
		// local: shows no err
		// had to remove this, bc it should return nil
		// but on CI when it calls os.Open(...), somehow it
		// shows an error of "no such file or directory"
		// and tests return another after that: (on mkdir call)
		// "checkTransDir() error = mkdir Dir1: file exists, wantErr false"
		// {
		// 	name:           "test same name dirs should pass",
		// 	originalDir:    filepath.Join(wd, "English", "Dir1"),
		// 	translationDir: filepath.Join(wd, "English"),
		// 	wantErr:        true,
		// },
		{
			name:           "test fake dirs should err",
			originalDir:    filepath.Join(wd, "English", "Dir1"),
			translationDir: filepath.Join(wd, "kai'sa"),
			wantErr:        true,
		},
	}
	for _, tt := range tests {
		if err := checkTransDirExists(tt.originalDir, tt.translationDir); (err != nil) != tt.wantErr {
			t.Errorf("\nname: %s\ndir: %s\ncheckTransDir() error = %v, wantErr %v", tt.name, tt.translationDir, err, tt.wantErr)
		}
	}
	err := os.Remove(filepath.Join(wd, "Translation", "Dir1"))
	if err != nil {
		t.Errorf("Error = %v", err)
	}
}

func Test_writeToFileMissingTags(t *testing.T) {
	type args struct {
		trltF       string
		missingTags map[string]string
		outdated    bool
	}
	tests := []struct {
		name    string
		args    args
		wantErr bool
	}{
		{
			name: "cant open invalid translation file",
			args: args{
				trltF: filepath.Join("testPaths", "Translation", "garen.txt"),
			},
			wantErr: true,
		},
		{
			name: "cant open invalid translation file",
			args: args{
				trltF: filepath.Join("testPaths", "Translation", "garen.txt"),
			},
			wantErr: true,
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			if err := writeToFileMissingTags(tt.args.trltF, tt.args.missingTags, tt.args.outdated); (err != nil) != tt.wantErr {
				t.Errorf("name: %s\n writeToFileMissingTags() error = %v, wantErr %v", tt.name, err, tt.wantErr)
			}
		})
	}
}
<|endoftext|>


<commit_before>package api

import (
	"fmt"
	"github.com/nais/naisd/api/app"
	v1 "k8s.io/api/core/v1"
	k8sextensions "k8s.io/api/extensions/v1beta1"
	k8smeta "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/util/intstr"
	"k8s.io/client-go/kubernetes"
)

const (
	defaultRedisPort          = 6379
	defaultRedisExporterPort  = 9121
	defaultRedisExporterImage = "oliver006/redis_exporter:1.0.3"
	defaultRedisImage         = "redis:5-alpine"
)

type Redis struct {
	Enabled  bool
	Image    string
	Limits   ResourceList
	Requests ResourceList
}

func updateDefaultRedisValues(redis Redis) Redis {
	if redis.Image == "" {
		redis.Image = defaultRedisImage
	}
	if len(redis.Limits.Cpu) == 0 {
		redis.Limits.Cpu = "100m"
	}
	if len(redis.Limits.Memory) == 0 {
		redis.Limits.Memory = "128Mi"
	}
	if len(redis.Requests.Cpu) == 0 {
		redis.Requests.Cpu= "100m"
	}
	if len(redis.Requests.Memory) == 0 {
		redis.Requests.Memory = "128Mi"
	}
	return redis
}

func createRedisPodSpec(redis Redis) v1.PodSpec {
	return v1.PodSpec{
		Containers: []v1.Container{
			{
				Name:  "redis",
				Image: redis.Image,
				Resources: createResourceLimits(redis.Requests.Cpu, redis.Requests.Memory,
					redis.Limits.Cpu, redis.Limits.Memory),
				ImagePullPolicy: v1.PullIfNotPresent,
				Ports: []v1.ContainerPort{
					{
						ContainerPort: int32(defaultRedisPort),
						Name:          DefaultPortName,
						Protocol:      v1.ProtocolTCP,
					},
				},
			},
			{
				Name:  "exporter",
				Image: defaultRedisExporterImage,
				Resources: createResourceLimits("100m", "100Mi",
					"100m", "100Mi"),
				ImagePullPolicy: v1.PullIfNotPresent,
				Ports: []v1.ContainerPort{
					{
						ContainerPort: int32(defaultRedisExporterPort),
						Name:          DefaultPortName,
						Protocol:      v1.ProtocolTCP,
					},
				},
			},
		},
	}
}

func createRedisDeploymentSpec(resourceName string, spec app.Spec, redis Redis) (k8sextensions.DeploymentSpec, error) {
	objectMeta := generateObjectMeta(spec)
	objectMeta.Name = resourceName
	objectMeta.Annotations = map[string]string{
		"prometheus.io/scrape": "true",
		"prometheus.io/port":   string(defaultRedisExporterPort),
		"prometheus.io/path":   "/metrics",
	}

	return k8sextensions.DeploymentSpec{
		Replicas: int32p(1),
		Selector: &k8smeta.LabelSelector{
			MatchLabels: createPodSelector(spec),
		},
		Strategy: k8sextensions.DeploymentStrategy{
			Type: k8sextensions.RecreateDeploymentStrategyType,
		},
		ProgressDeadlineSeconds: int32p(300),
		RevisionHistoryLimit:    int32p(10),
		Template: v1.PodTemplateSpec{
			ObjectMeta: objectMeta,
			Spec:       createRedisPodSpec(redis),
		},
	}, nil
}

func createRedisDeploymentDef(resourceName string, spec app.Spec, redis Redis, existingDeployment *k8sextensions.Deployment) (*k8sextensions.Deployment, error) {
	existingDeployment.Spec, _ = createRedisDeploymentSpec(resourceName, spec, redis)
	return existingDeployment, nil
}

func createOrUpdateRedisInstance(spec app.Spec, redis Redis, k8sClient kubernetes.Interface) (*k8sextensions.Deployment, error) {
	redisName := fmt.Sprintf("%s-redis", spec.ResourceName())
	existingDeployment, err := getExistingDeployment(redisName, spec.Namespace, k8sClient)

	if err != nil {
		return nil, fmt.Errorf("unable to get existing deployment: %s", err)
	}

	deploymentDef, err := createRedisDeploymentDef(redisName, spec, redis, existingDeployment)

	if err != nil {
		return nil, fmt.Errorf("unable to create deployment: %s", err)
	}

	return createOrUpdateDeploymentResource(deploymentDef, spec.Namespace, k8sClient)
}

func createRedisServiceDef(spec app.Spec) *v1.Service {
	return &v1.Service{
		TypeMeta: k8smeta.TypeMeta{
			Kind:       "Service",
			APIVersion: "v1",
		},
		ObjectMeta: generateObjectMeta(spec),
		Spec: v1.ServiceSpec{
			Type:     v1.ServiceTypeClusterIP,
			Selector: createPodSelector(spec),
			Ports: []v1.ServicePort{
				{
					Name:     DefaultPortName,
					Protocol: v1.ProtocolTCP,
					Port:     6379,
					TargetPort: intstr.IntOrString{
						Type:   intstr.String,
						StrVal: DefaultPortName,
					},
				},
			},
		},
	}
}

func createOrUpdateRedisService(spec app.Spec, k8sClient kubernetes.Interface) (*v1.Service, error) {
	service, err := getExistingService(spec.ResourceName(), spec.Namespace, k8sClient)

	if err != nil {
		return nil, fmt.Errorf("unable to get existing service: %s", err)
	} else if service == nil {
		service = createRedisServiceDef(spec)
		service.Name = fmt.Sprintf("%s-redis", spec.ResourceName())
	}

	service.ObjectMeta = addLabelsToObjectMeta(service.ObjectMeta, spec)
	return createOrUpdateServiceResource(service, spec.Namespace, k8sClient)
}
<commit_msg>Fixed formatering gofmt<commit_after>package api

import (
	"fmt"
	"github.com/nais/naisd/api/app"
	v1 "k8s.io/api/core/v1"
	k8sextensions "k8s.io/api/extensions/v1beta1"
	k8smeta "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/util/intstr"
	"k8s.io/client-go/kubernetes"
)

const (
	defaultRedisPort          = 6379
	defaultRedisExporterPort  = 9121
	defaultRedisExporterImage = "oliver006/redis_exporter:1.0.3"
	defaultRedisImage         = "redis:5-alpine"
)

type Redis struct {
	Enabled  bool
	Image    string
	Limits   ResourceList
	Requests ResourceList
}

func updateDefaultRedisValues(redis Redis) Redis {
	if redis.Image == "" {
		redis.Image = defaultRedisImage
	}
	if len(redis.Limits.Cpu) == 0 {
		redis.Limits.Cpu = "100m"
	}
	if len(redis.Limits.Memory) == 0 {
		redis.Limits.Memory = "128Mi"
	}
	if len(redis.Requests.Cpu) == 0 {
		redis.Requests.Cpu = "100m"
	}
	if len(redis.Requests.Memory) == 0 {
		redis.Requests.Memory = "128Mi"
	}
	return redis
}

func createRedisPodSpec(redis Redis) v1.PodSpec {
	return v1.PodSpec{
		Containers: []v1.Container{
			{
				Name:  "redis",
				Image: redis.Image,
				Resources: createResourceLimits(redis.Requests.Cpu, redis.Requests.Memory,
					redis.Limits.Cpu, redis.Limits.Memory),
				ImagePullPolicy: v1.PullIfNotPresent,
				Ports: []v1.ContainerPort{
					{
						ContainerPort: int32(defaultRedisPort),
						Name:          DefaultPortName,
						Protocol:      v1.ProtocolTCP,
					},
				},
			},
			{
				Name:  "exporter",
				Image: defaultRedisExporterImage,
				Resources: createResourceLimits("100m", "100Mi",
					"100m", "100Mi"),
				ImagePullPolicy: v1.PullIfNotPresent,
				Ports: []v1.ContainerPort{
					{
						ContainerPort: int32(defaultRedisExporterPort),
						Name:          DefaultPortName,
						Protocol:      v1.ProtocolTCP,
					},
				},
			},
		},
	}
}

func createRedisDeploymentSpec(resourceName string, spec app.Spec, redis Redis) (k8sextensions.DeploymentSpec, error) {
	objectMeta := generateObjectMeta(spec)
	objectMeta.Name = resourceName
	objectMeta.Annotations = map[string]string{
		"prometheus.io/scrape": "true",
		"prometheus.io/port":   string(defaultRedisExporterPort),
		"prometheus.io/path":   "/metrics",
	}

	return k8sextensions.DeploymentSpec{
		Replicas: int32p(1),
		Selector: &k8smeta.LabelSelector{
			MatchLabels: createPodSelector(spec),
		},
		Strategy: k8sextensions.DeploymentStrategy{
			Type: k8sextensions.RecreateDeploymentStrategyType,
		},
		ProgressDeadlineSeconds: int32p(300),
		RevisionHistoryLimit:    int32p(10),
		Template: v1.PodTemplateSpec{
			ObjectMeta: objectMeta,
			Spec:       createRedisPodSpec(redis),
		},
	}, nil
}

func createRedisDeploymentDef(resourceName string, spec app.Spec, redis Redis, existingDeployment *k8sextensions.Deployment) (*k8sextensions.Deployment, error) {
	existingDeployment.Spec, _ = createRedisDeploymentSpec(resourceName, spec, redis)
	return existingDeployment, nil
}

func createOrUpdateRedisInstance(spec app.Spec, redis Redis, k8sClient kubernetes.Interface) (*k8sextensions.Deployment, error) {
	redisName := fmt.Sprintf("%s-redis", spec.ResourceName())
	existingDeployment, err := getExistingDeployment(redisName, spec.Namespace, k8sClient)

	if err != nil {
		return nil, fmt.Errorf("unable to get existing deployment: %s", err)
	}

	deploymentDef, err := createRedisDeploymentDef(redisName, spec, redis, existingDeployment)

	if err != nil {
		return nil, fmt.Errorf("unable to create deployment: %s", err)
	}

	return createOrUpdateDeploymentResource(deploymentDef, spec.Namespace, k8sClient)
}

func createRedisServiceDef(spec app.Spec) *v1.Service {
	return &v1.Service{
		TypeMeta: k8smeta.TypeMeta{
			Kind:       "Service",
			APIVersion: "v1",
		},
		ObjectMeta: generateObjectMeta(spec),
		Spec: v1.ServiceSpec{
			Type:     v1.ServiceTypeClusterIP,
			Selector: createPodSelector(spec),
			Ports: []v1.ServicePort{
				{
					Name:     DefaultPortName,
					Protocol: v1.ProtocolTCP,
					Port:     6379,
					TargetPort: intstr.IntOrString{
						Type:   intstr.String,
						StrVal: DefaultPortName,
					},
				},
			},
		},
	}
}

func createOrUpdateRedisService(spec app.Spec, k8sClient kubernetes.Interface) (*v1.Service, error) {
	service, err := getExistingService(spec.ResourceName(), spec.Namespace, k8sClient)

	if err != nil {
		return nil, fmt.Errorf("unable to get existing service: %s", err)
	} else if service == nil {
		service = createRedisServiceDef(spec)
		service.Name = fmt.Sprintf("%s-redis", spec.ResourceName())
	}

	service.ObjectMeta = addLabelsToObjectMeta(service.ObjectMeta, spec)
	return createOrUpdateServiceResource(service, spec.Namespace, k8sClient)
}
<|endoftext|>


<commit_before>package main

import (
	"compress/zlib"
	"encoding/binary"
	"fmt"
	"io"
	"os"
	"path/filepath"
	"strings"
	"strconv"
)

var (
	ChunkNotFoundError = os.NewError("Chunk Missing")
)

type BetaWorld struct {
	worldDir string
	mask     ChunkMask
}

type McrFile struct {
	*os.File
}

func (w *BetaWorld) OpenChunk(x, z int) (io.ReadCloser, os.Error) {
	var mcrName = fmt.Sprintf("r.%v.%v.mcr", x>>5, z>>5)
	var mcrPath = filepath.Join(w.worldDir, "region", mcrName)

	var file, mcrOpenErr = os.Open(mcrPath)
	if mcrOpenErr != nil {
		return nil, mcrOpenErr
	}
	defer func() {
		if file != nil {
			file.Close()
		}
	}()

	var mcr = &McrFile{file}
	var loc, readLocErr = mcr.ReadLocation(x, z)
	if readLocErr != nil {
		return nil, readLocErr
	}

	if loc == 0 {
		return nil, os.NewError(fmt.Sprintf("Chunk missing: %v,%v in %v. %v", x, z, mcrName, (x&31)+(z&31)*32))
	}

	var (
		length          uint32
		compressionType byte
	)

	var _, seekErr = mcr.Seek(int64(loc.Offset()), 0)
	if seekErr != nil {
		return nil, seekErr
	}

	var lengthReadErr = binary.Read(mcr, binary.BigEndian, &length)
	if lengthReadErr != nil {
		return nil, lengthReadErr
	}

	var compressionTypeErr = binary.Read(mcr, binary.BigEndian, &compressionType)
	if compressionTypeErr != nil {
		return nil, compressionTypeErr
	}

	var r, zlibNewErr = zlib.NewReader(mcr)
	if zlibNewErr != nil {
		return nil, zlibNewErr
	}

	var pair = &ReadCloserPair{r, file}
	file = nil
	return pair, nil
}

func (r McrFile) ReadLocation(x, z int) (ChunkLocation, os.Error) {
	var _, seekErr = r.Seek(int64(4*((x&31)+(z&31)*32)), 0)
	if seekErr != nil {
		return ChunkLocation(0), seekErr
	}
	var location uint32
	var readErr = binary.Read(r, binary.BigEndian, &location)
	if readErr != nil {
		return ChunkLocation(0), readErr
	}
	return ChunkLocation(location), nil
}

type ChunkLocation uint32

func (cl ChunkLocation) Offset() int {
	return 4096 * (int(cl) >> 8)
}

func (cl ChunkLocation) Sectors() int {
	return (int(cl) & 0xff)
}

func (w *BetaWorld) ChunkPool() (ChunkPool, os.Error) {
	var regionDirname = filepath.Join(w.worldDir, "region")
	var dir, dirOpenErr = os.Open(regionDirname)
	if dirOpenErr != nil {
		return nil, dirOpenErr
	}
	defer dir.Close()

	var pool = &BetaChunkPool{make(map[uint64]bool)}

	for {
		var filenames, readErr = dir.Readdirnames(1)
		if readErr != nil {
			return nil, readErr
		}

		if len(filenames) == 0 {
			break
		}

		var fields = strings.FieldsFunc(filenames[0], func(c int) bool { return c == '.' })

		if len(fields) == 4 {
			var (
				rx, rxErr = strconv.Atoi(fields[1])
				rz, ryErr = strconv.Atoi(fields[2])
			)

			if rxErr == nil && ryErr == nil {
				var regionFilename = filepath.Join(regionDirname, filenames[0])
				var region, regionOpenErr = os.Open(regionFilename)
				if regionOpenErr != nil {
					return nil, regionOpenErr
				}
				defer region.Close()

				for cz := 0; cz < 32; cz++ {
					for cx := 0; cx < 32; cx++ {
						var location uint32
						var readErr = binary.Read(region, binary.BigEndian, &location)
						if readErr == os.EOF {
							continue
						}
						if readErr != nil {
							return nil, readErr
						}
						if location != 0 {
							var (
								x = rx*32 + cx
								z = rz*32 + cz
							)

							if !w.mask.IsMasked(x, z) {
								pool.chunkMap[betaChunkPoolKey(x, z)] = true
							}
						}
					}
				}
			}
		}
	}

	return pool, nil
}

type BetaChunkPool struct {
	chunkMap map[uint64]bool
}

func (p *BetaChunkPool) Pop(x, z int) bool {
	var key = betaChunkPoolKey(x, z)
	var _, exists = p.chunkMap[key]
	p.chunkMap[key] = false, false
	return exists
}

func (p *BetaChunkPool) Remaining() int {
	return len(p.chunkMap)
}

func betaChunkPoolKey(x, z int) uint64 {
	return uint64(x)<<32 + uint64(z)
}
<commit_msg>Reduce the peak file handle count for large worlds<commit_after>package main

import (
	"compress/zlib"
	"encoding/binary"
	"fmt"
	"io"
	"os"
	"path/filepath"
	"strings"
	"strconv"
)

var (
	ChunkNotFoundError = os.NewError("Chunk Missing")
)

type BetaWorld struct {
	worldDir string
	mask     ChunkMask
}

type McrFile struct {
	*os.File
}

func (w *BetaWorld) OpenChunk(x, z int) (io.ReadCloser, os.Error) {
	var mcrName = fmt.Sprintf("r.%v.%v.mcr", x>>5, z>>5)
	var mcrPath = filepath.Join(w.worldDir, "region", mcrName)

	var file, mcrOpenErr = os.Open(mcrPath)
	if mcrOpenErr != nil {
		return nil, mcrOpenErr
	}
	defer func() {
		if file != nil {
			file.Close()
		}
	}()

	var mcr = &McrFile{file}
	var loc, readLocErr = mcr.ReadLocation(x, z)
	if readLocErr != nil {
		return nil, readLocErr
	}

	if loc == 0 {
		return nil, os.NewError(fmt.Sprintf("Chunk missing: %v,%v in %v. %v", x, z, mcrName, (x&31)+(z&31)*32))
	}

	var (
		length          uint32
		compressionType byte
	)

	var _, seekErr = mcr.Seek(int64(loc.Offset()), 0)
	if seekErr != nil {
		return nil, seekErr
	}

	var lengthReadErr = binary.Read(mcr, binary.BigEndian, &length)
	if lengthReadErr != nil {
		return nil, lengthReadErr
	}

	var compressionTypeErr = binary.Read(mcr, binary.BigEndian, &compressionType)
	if compressionTypeErr != nil {
		return nil, compressionTypeErr
	}

	var r, zlibNewErr = zlib.NewReader(mcr)
	if zlibNewErr != nil {
		return nil, zlibNewErr
	}

	var pair = &ReadCloserPair{r, file}
	file = nil
	return pair, nil
}

func (r McrFile) ReadLocation(x, z int) (ChunkLocation, os.Error) {
	var _, seekErr = r.Seek(int64(4*((x&31)+(z&31)*32)), 0)
	if seekErr != nil {
		return ChunkLocation(0), seekErr
	}
	var location uint32
	var readErr = binary.Read(r, binary.BigEndian, &location)
	if readErr != nil {
		return ChunkLocation(0), readErr
	}
	return ChunkLocation(location), nil
}

type ChunkLocation uint32

func (cl ChunkLocation) Offset() int {
	return 4096 * (int(cl) >> 8)
}

func (cl ChunkLocation) Sectors() int {
	return (int(cl) & 0xff)
}

func (w *BetaWorld) ChunkPool() (ChunkPool, os.Error) {
	var regionDirname = filepath.Join(w.worldDir, "region")
	var dir, dirOpenErr = os.Open(regionDirname)
	if dirOpenErr != nil {
		return nil, dirOpenErr
	}
	defer dir.Close()

	var pool = &BetaChunkPool{make(map[uint64]bool)}

	for {
		var filenames, readErr = dir.Readdirnames(1)
		if readErr != nil {
			return nil, readErr
		}

		if len(filenames) == 0 {
			break
		}

		var fields = strings.FieldsFunc(filenames[0], func(c int) bool { return c == '.' })

		if len(fields) == 4 {
			var (
				rx, rxErr = strconv.Atoi(fields[1])
				rz, ryErr = strconv.Atoi(fields[2])
			)

			if rxErr == nil && ryErr == nil {
				var regionFilename = filepath.Join(regionDirname, filenames[0])
				var mcrErr = w.poolMcrChunks(regionFilename, pool, rx, rz)
				if mcrErr != nil {
					return nil, mcrErr
				}
			}
		}
	}

	return pool, nil
}

func (w *BetaWorld) poolMcrChunks(regionFilename string, pool *BetaChunkPool, rx, rz int) os.Error {
	var region, regionOpenErr = os.Open(regionFilename)
	if regionOpenErr != nil {
		return regionOpenErr
	}
	defer region.Close()

	for cz := 0; cz < 32; cz++ {
		for cx := 0; cx < 32; cx++ {
			var location uint32
			var readErr = binary.Read(region, binary.BigEndian, &location)
			if readErr == os.EOF {
				continue
			}
			if readErr != nil {
				return readErr
			}
			if location != 0 {
				var (
					x = rx*32 + cx
					z = rz*32 + cz
				)

				if !w.mask.IsMasked(x, z) {
					pool.chunkMap[betaChunkPoolKey(x, z)] = true
				}
			}
		}
	}

	return nil
}

type BetaChunkPool struct {
	chunkMap map[uint64]bool
}

func (p *BetaChunkPool) Pop(x, z int) bool {
	var key = betaChunkPoolKey(x, z)
	var _, exists = p.chunkMap[key]
	p.chunkMap[key] = false, false
	return exists
}

func (p *BetaChunkPool) Remaining() int {
	return len(p.chunkMap)
}

func betaChunkPoolKey(x, z int) uint64 {
	return uint64(x)<<32 + uint64(z)
}
<|endoftext|>


<commit_before>package api

import (
	"time"
)

// MemoryStats holds memory usage related stats
type MemoryStats struct {
	RSS            uint64
	Cache          uint64
	Swap           uint64
	MaxUsage       uint64
	KernelUsage    uint64
	KernelMaxUsage uint64
	Measured       []string
}

// CpuStats holds cpu usage related stats
type CpuStats struct {
	SystemMode       float64
	UserMode         float64
	TotalTicks       float64
	ThrottledPeriods uint64
	ThrottledTime    uint64
	Percent          float64
	Measured         []string
}

// ResourceUsage holds information related to cpu and memory stats
type ResourceUsage struct {
	MemoryStats *MemoryStats
	CpuStats    *CpuStats
}

// TaskResourceUsage holds aggregated resource usage of all processes in a Task
// and the resource usage of the individual pids
type TaskResourceUsage struct {
	ResourceUsage *ResourceUsage
	Timestamp     int64
	Pids          map[string]*ResourceUsage
}

// AllocResourceUsage holds the aggregated task resource usage of the
// allocation.
type AllocResourceUsage struct {
	ResourceUsage *ResourceUsage
	Tasks         map[string]*TaskResourceUsage
	Timestamp     int64
}

// RestartPolicy defines how the Nomad client restarts
// tasks in a taskgroup when they fail
type RestartPolicy struct {
	Interval time.Duration
	Attempts int
	Delay    time.Duration
	Mode     string
}

// The ServiceCheck data model represents the consul health check that
// Nomad registers for a Task
type ServiceCheck struct {
	Id            string
	Name          string
	Type          string
	Command       string
	Args          []string
	Path          string
	Protocol      string `mapstructure:"port"`
	PortLabel     string `mapstructure:"port"`
	Interval      time.Duration
	Timeout       time.Duration
	InitialStatus string `mapstructure:"initial_status"`
}

// The Service model represents a Consul service definition
type Service struct {
	Id        string
	Name      string
	Tags      []string
	PortLabel string `mapstructure:"port"`
	Checks    []ServiceCheck
}

// EphemeralDisk is an ephemeral disk object
type EphemeralDisk struct {
	Sticky bool
	SizeMB int `mapstructure:"size"`
}

// TaskGroup is the unit of scheduling.
type TaskGroup struct {
	Name          string
	Count         int
	Constraints   []*Constraint
	Tasks         []*Task
	RestartPolicy *RestartPolicy
	EphemeralDisk *EphemeralDisk
	Meta          map[string]string
}

// NewTaskGroup creates a new TaskGroup.
func NewTaskGroup(name string, count int) *TaskGroup {
	return &TaskGroup{
		Name:  name,
		Count: count,
	}
}

// Constrain is used to add a constraint to a task group.
func (g *TaskGroup) Constrain(c *Constraint) *TaskGroup {
	g.Constraints = append(g.Constraints, c)
	return g
}

// AddMeta is used to add a meta k/v pair to a task group
func (g *TaskGroup) SetMeta(key, val string) *TaskGroup {
	if g.Meta == nil {
		g.Meta = make(map[string]string)
	}
	g.Meta[key] = val
	return g
}

// AddTask is used to add a new task to a task group.
func (g *TaskGroup) AddTask(t *Task) *TaskGroup {
	g.Tasks = append(g.Tasks, t)
	return g
}

// RequireDisk adds a ephemeral disk to the task group
func (g *TaskGroup) RequireDisk(disk *EphemeralDisk) *TaskGroup {
	g.EphemeralDisk = disk
	return g
}

// LogConfig provides configuration for log rotation
type LogConfig struct {
	MaxFiles      int
	MaxFileSizeMB int
}

// Task is a single process in a task group.
type Task struct {
	Name        string
	Driver      string
	User        string
	Config      map[string]interface{}
	Constraints []*Constraint
	Env         map[string]string
	Services    []Service
	Resources   *Resources
	Meta        map[string]string
	KillTimeout time.Duration
	LogConfig   *LogConfig
	Artifacts   []*TaskArtifact
	Vault       *Vault
}

// TaskArtifact is used to download artifacts before running a task.
type TaskArtifact struct {
	GetterSource  string
	GetterOptions map[string]string
	RelativeDest  string
}

type Vault struct {
	Policies []string
}

// NewTask creates and initializes a new Task.
func NewTask(name, driver string) *Task {
	return &Task{
		Name:   name,
		Driver: driver,
	}
}

// Configure is used to configure a single k/v pair on
// the task.
func (t *Task) SetConfig(key string, val interface{}) *Task {
	if t.Config == nil {
		t.Config = make(map[string]interface{})
	}
	t.Config[key] = val
	return t
}

// SetMeta is used to add metadata k/v pairs to the task.
func (t *Task) SetMeta(key, val string) *Task {
	if t.Meta == nil {
		t.Meta = make(map[string]string)
	}
	t.Meta[key] = val
	return t
}

// Require is used to add resource requirements to a task.
func (t *Task) Require(r *Resources) *Task {
	t.Resources = r
	return t
}

// Constraint adds a new constraints to a single task.
func (t *Task) Constrain(c *Constraint) *Task {
	t.Constraints = append(t.Constraints, c)
	return t
}

// SetLogConfig sets a log config to a task
func (t *Task) SetLogConfig(l *LogConfig) *Task {
	t.LogConfig = l
	return t
}

// TaskState tracks the current state of a task and events that caused state
// transitions.
type TaskState struct {
	State  string
	Events []*TaskEvent
}

const (
	TaskDriverFailure          = "Driver Failure"
	TaskReceived               = "Received"
	TaskFailedValidation       = "Failed Validation"
	TaskStarted                = "Started"
	TaskTerminated             = "Terminated"
	TaskKilling                = "Killing"
	TaskKilled                 = "Killed"
	TaskRestarting             = "Restarting"
	TaskNotRestarting          = "Not Restarting"
	TaskDownloadingArtifacts   = "Downloading Artifacts"
	TaskArtifactDownloadFailed = "Failed Artifact Download"
	TaskDiskExceeded           = "Disk Exceeded"
	TaskVaultRenewalFailed     = "Vault token renewal failed"
	TaskSiblingFailed          = "Sibling task failed"
)

// TaskEvent is an event that effects the state of a task and contains meta-data
// appropriate to the events type.
type TaskEvent struct {
	Type            string
	Time            int64
	RestartReason   string
	DriverError     string
	ExitCode        int
	Signal          int
	Message         string
	KillTimeout     time.Duration
	KillError       string
	StartDelay      int64
	DownloadError   string
	ValidationError string
	DiskLimit       int64
	DiskSize        int64
	FailedSibling   string
	VaultError      string
}
<commit_msg>Add env<commit_after>package api

import (
	"time"
)

// MemoryStats holds memory usage related stats
type MemoryStats struct {
	RSS            uint64
	Cache          uint64
	Swap           uint64
	MaxUsage       uint64
	KernelUsage    uint64
	KernelMaxUsage uint64
	Measured       []string
}

// CpuStats holds cpu usage related stats
type CpuStats struct {
	SystemMode       float64
	UserMode         float64
	TotalTicks       float64
	ThrottledPeriods uint64
	ThrottledTime    uint64
	Percent          float64
	Measured         []string
}

// ResourceUsage holds information related to cpu and memory stats
type ResourceUsage struct {
	MemoryStats *MemoryStats
	CpuStats    *CpuStats
}

// TaskResourceUsage holds aggregated resource usage of all processes in a Task
// and the resource usage of the individual pids
type TaskResourceUsage struct {
	ResourceUsage *ResourceUsage
	Timestamp     int64
	Pids          map[string]*ResourceUsage
}

// AllocResourceUsage holds the aggregated task resource usage of the
// allocation.
type AllocResourceUsage struct {
	ResourceUsage *ResourceUsage
	Tasks         map[string]*TaskResourceUsage
	Timestamp     int64
}

// RestartPolicy defines how the Nomad client restarts
// tasks in a taskgroup when they fail
type RestartPolicy struct {
	Interval time.Duration
	Attempts int
	Delay    time.Duration
	Mode     string
}

// The ServiceCheck data model represents the consul health check that
// Nomad registers for a Task
type ServiceCheck struct {
	Id            string
	Name          string
	Type          string
	Command       string
	Args          []string
	Path          string
	Protocol      string `mapstructure:"port"`
	PortLabel     string `mapstructure:"port"`
	Interval      time.Duration
	Timeout       time.Duration
	InitialStatus string `mapstructure:"initial_status"`
}

// The Service model represents a Consul service definition
type Service struct {
	Id        string
	Name      string
	Tags      []string
	PortLabel string `mapstructure:"port"`
	Checks    []ServiceCheck
}

// EphemeralDisk is an ephemeral disk object
type EphemeralDisk struct {
	Sticky bool
	SizeMB int `mapstructure:"size"`
}

// TaskGroup is the unit of scheduling.
type TaskGroup struct {
	Name          string
	Count         int
	Constraints   []*Constraint
	Tasks         []*Task
	RestartPolicy *RestartPolicy
	EphemeralDisk *EphemeralDisk
	Meta          map[string]string
}

// NewTaskGroup creates a new TaskGroup.
func NewTaskGroup(name string, count int) *TaskGroup {
	return &TaskGroup{
		Name:  name,
		Count: count,
	}
}

// Constrain is used to add a constraint to a task group.
func (g *TaskGroup) Constrain(c *Constraint) *TaskGroup {
	g.Constraints = append(g.Constraints, c)
	return g
}

// AddMeta is used to add a meta k/v pair to a task group
func (g *TaskGroup) SetMeta(key, val string) *TaskGroup {
	if g.Meta == nil {
		g.Meta = make(map[string]string)
	}
	g.Meta[key] = val
	return g
}

// AddTask is used to add a new task to a task group.
func (g *TaskGroup) AddTask(t *Task) *TaskGroup {
	g.Tasks = append(g.Tasks, t)
	return g
}

// RequireDisk adds a ephemeral disk to the task group
func (g *TaskGroup) RequireDisk(disk *EphemeralDisk) *TaskGroup {
	g.EphemeralDisk = disk
	return g
}

// LogConfig provides configuration for log rotation
type LogConfig struct {
	MaxFiles      int
	MaxFileSizeMB int
}

// Task is a single process in a task group.
type Task struct {
	Name        string
	Driver      string
	User        string
	Config      map[string]interface{}
	Constraints []*Constraint
	Env         map[string]string
	Services    []Service
	Resources   *Resources
	Meta        map[string]string
	KillTimeout time.Duration
	LogConfig   *LogConfig
	Artifacts   []*TaskArtifact
	Vault       *Vault
}

// TaskArtifact is used to download artifacts before running a task.
type TaskArtifact struct {
	GetterSource  string
	GetterOptions map[string]string
	RelativeDest  string
}

type Vault struct {
	Policies []string
	Env      bool
}

// NewTask creates and initializes a new Task.
func NewTask(name, driver string) *Task {
	return &Task{
		Name:   name,
		Driver: driver,
	}
}

// Configure is used to configure a single k/v pair on
// the task.
func (t *Task) SetConfig(key string, val interface{}) *Task {
	if t.Config == nil {
		t.Config = make(map[string]interface{})
	}
	t.Config[key] = val
	return t
}

// SetMeta is used to add metadata k/v pairs to the task.
func (t *Task) SetMeta(key, val string) *Task {
	if t.Meta == nil {
		t.Meta = make(map[string]string)
	}
	t.Meta[key] = val
	return t
}

// Require is used to add resource requirements to a task.
func (t *Task) Require(r *Resources) *Task {
	t.Resources = r
	return t
}

// Constraint adds a new constraints to a single task.
func (t *Task) Constrain(c *Constraint) *Task {
	t.Constraints = append(t.Constraints, c)
	return t
}

// SetLogConfig sets a log config to a task
func (t *Task) SetLogConfig(l *LogConfig) *Task {
	t.LogConfig = l
	return t
}

// TaskState tracks the current state of a task and events that caused state
// transitions.
type TaskState struct {
	State  string
	Events []*TaskEvent
}

const (
	TaskDriverFailure          = "Driver Failure"
	TaskReceived               = "Received"
	TaskFailedValidation       = "Failed Validation"
	TaskStarted                = "Started"
	TaskTerminated             = "Terminated"
	TaskKilling                = "Killing"
	TaskKilled                 = "Killed"
	TaskRestarting             = "Restarting"
	TaskNotRestarting          = "Not Restarting"
	TaskDownloadingArtifacts   = "Downloading Artifacts"
	TaskArtifactDownloadFailed = "Failed Artifact Download"
	TaskDiskExceeded           = "Disk Exceeded"
	TaskVaultRenewalFailed     = "Vault token renewal failed"
	TaskSiblingFailed          = "Sibling task failed"
)

// TaskEvent is an event that effects the state of a task and contains meta-data
// appropriate to the events type.
type TaskEvent struct {
	Type            string
	Time            int64
	RestartReason   string
	DriverError     string
	ExitCode        int
	Signal          int
	Message         string
	KillTimeout     time.Duration
	KillError       string
	StartDelay      int64
	DownloadError   string
	ValidationError string
	DiskLimit       int64
	DiskSize        int64
	FailedSibling   string
	VaultError      string
}
<|endoftext|>


<commit_before>package api

import (
	"encoding/json"
	"errors"
	"fmt"
	"net/http"
	"path"

	log "github.com/coreos/fleet/Godeps/_workspace/src/github.com/golang/glog"

	"github.com/coreos/fleet/job"
	"github.com/coreos/fleet/registry"
	"github.com/coreos/fleet/schema"
	"github.com/coreos/fleet/unit"
)

func wireUpUnitsResource(mux *http.ServeMux, prefix string, reg registry.Registry) {
	base := path.Join(prefix, "units")
	ur := unitsResource{reg, base}
	mux.Handle(base, &ur)
	mux.Handle(base+"/", &ur)
}

type unitsResource struct {
	reg      registry.Registry
	basePath string
}

func (ur *unitsResource) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
	if isCollectionPath(ur.basePath, req.URL.Path) {
		switch req.Method {
		case "GET":
			ur.list(rw, req)
		default:
			sendError(rw, http.StatusMethodNotAllowed, errors.New("only GET supported against this resource"))
		}
	} else if item, ok := isItemPath(ur.basePath, req.URL.Path); ok {
		switch req.Method {
		case "GET":
			ur.get(rw, req, item)
		case "DELETE":
			ur.destroy(rw, req, item)
		case "PUT":
			ur.set(rw, req, item)
		default:
			sendError(rw, http.StatusMethodNotAllowed, errors.New("only GET, PUT and DELETE supported against this resource"))
		}
	} else {
		sendError(rw, http.StatusNotFound, nil)
	}
}

func (ur *unitsResource) set(rw http.ResponseWriter, req *http.Request, item string) {
	if validateContentType(req) != nil {
		sendError(rw, http.StatusNotAcceptable, errors.New("application/json is only supported Content-Type"))
		return
	}

	var su schema.Unit
	dec := json.NewDecoder(req.Body)
	err := dec.Decode(&su)
	if err != nil {
		sendError(rw, http.StatusBadRequest, fmt.Errorf("unable to decode body: %v", err))
		return
	}

	u, err := ur.reg.Unit(item)
	if err != nil {
		log.Errorf("Failed fetching Unit(%s) from Registry: %v", item, err)
		sendError(rw, http.StatusInternalServerError, nil)
		return
	}

	var uf *unit.UnitFile
	if len(su.Options) > 0 {
		uf = schema.MapSchemaUnitOptionsToUnitFile(su.Options)
	}

	// TODO(bcwaldon): Assert value of DesiredState is launched, loaded or inactive
	ds := job.JobState(su.DesiredState)

	if u != nil {
		ur.update(rw, u, ds)
	} else if uf != nil {
		ur.create(rw, item, ds, uf)
	} else {
		sendError(rw, http.StatusConflict, errors.New("unit does not exist and no fileContents provided"))
	}
}

func (ur *unitsResource) create(rw http.ResponseWriter, item string, ds job.JobState, uf *unit.UnitFile) {
	u := job.Unit{Name: item, Unit: *uf}
	if err := ur.reg.CreateUnit(&u); err != nil {
		log.Errorf("Failed creating Unit(%s) in Registry: %v", u.Name, err)
		sendError(rw, http.StatusInternalServerError, nil)
		return
	}

	if err := ur.reg.SetUnitTargetState(u.Name, ds); err != nil {
		log.Errorf("Failed setting target state of Unit(%s): %v", u.Name, err)
		sendError(rw, http.StatusInternalServerError, nil)
		return
	}

	rw.WriteHeader(http.StatusNoContent)
}

func (ur *unitsResource) update(rw http.ResponseWriter, u *job.Unit, ds job.JobState) {
	if err := ur.reg.SetUnitTargetState(u.Name, ds); err != nil {
		log.Errorf("Failed setting target state of Unit(%s): %v", u.Name, err)
		sendError(rw, http.StatusInternalServerError, nil)
		return
	}

	rw.WriteHeader(http.StatusNoContent)
}

func (ur *unitsResource) destroy(rw http.ResponseWriter, req *http.Request, item string) {
	u, err := ur.reg.Unit(item)
	if err != nil {
		log.Errorf("Failed fetching Unit(%s): %v", item, err)
		sendError(rw, http.StatusInternalServerError, nil)
		return
	}

	if u == nil {
		sendError(rw, http.StatusNotFound, errors.New("unit does not exist"))
		return
	}

	err = ur.reg.DestroyUnit(item)
	if err != nil {
		log.Errorf("Failed destroying Unit(%s): %v", item, err)
		sendError(rw, http.StatusInternalServerError, nil)
		return
	}

	rw.WriteHeader(http.StatusNoContent)
}

func (ur *unitsResource) get(rw http.ResponseWriter, req *http.Request, item string) {
	u, err := ur.reg.Unit(item)
	if err != nil {
		log.Errorf("Failed fetching Unit(%s) from Registry: %v", item, err)
		sendError(rw, http.StatusInternalServerError, nil)
		return
	}

	if u == nil {
		sendError(rw, http.StatusNotFound, errors.New("unit does not exist"))
		return
	}

	su, err := ur.reg.ScheduledUnit(item)
	if err != nil {
		log.Errorf("Failed fetching ScheduledUnit(%s) from Registry: %v", item, err)
		sendError(rw, http.StatusInternalServerError, nil)
		return
	}

	s := schema.MapUnitToSchemaUnit(u, su)
	sendResponse(rw, http.StatusOK, *s)
}

func (ur *unitsResource) list(rw http.ResponseWriter, req *http.Request) {
	token, err := findNextPageToken(req.URL)
	if err != nil {
		sendError(rw, http.StatusBadRequest, err)
		return
	}

	if token == nil {
		def := DefaultPageToken()
		token = &def
	}

	page, err := getUnitPage(ur.reg, *token)
	if err != nil {
		log.Errorf("Failed fetching page of Units: %v", err)
		sendError(rw, http.StatusInternalServerError, nil)
		return
	}

	sendResponse(rw, http.StatusOK, page)
}

func getUnitPage(reg registry.Registry, tok PageToken) (*schema.UnitPage, error) {
	units, err := reg.Units()
	if err != nil {
		return nil, err
	}

	sUnits, err := reg.Schedule()
	if err != nil {
		return nil, err
	}

	sUnitMap := make(map[string]*job.ScheduledUnit)
	for _, sUnit := range sUnits {
		sUnit := sUnit
		sUnitMap[sUnit.Name] = &sUnit
	}

	items, next := extractUnitPageData(units, tok)
	page := schema.UnitPage{
		Units: make([]*schema.Unit, len(items)),
	}

	if next != nil {
		page.NextPageToken = next.Encode()
	}

	for i, u := range items {
		page.Units[i] = schema.MapUnitToSchemaUnit(&u, sUnitMap[u.Name])
	}

	return &page, nil
}

func extractUnitPageData(all []job.Unit, tok PageToken) (items []job.Unit, next *PageToken) {
	total := len(all)

	startIndex := int((tok.Page - 1) * tok.Limit)
	stopIndex := int(tok.Page * tok.Limit)

	if startIndex < total {
		if stopIndex > total {
			stopIndex = total
		} else {
			n := tok.Next()
			next = &n
		}

		items = all[startIndex:stopIndex]
	}

	return
}
<commit_msg>api: only set desired state if provided<commit_after>package api

import (
	"encoding/json"
	"errors"
	"fmt"
	"net/http"
	"path"

	log "github.com/coreos/fleet/Godeps/_workspace/src/github.com/golang/glog"

	"github.com/coreos/fleet/job"
	"github.com/coreos/fleet/registry"
	"github.com/coreos/fleet/schema"
	"github.com/coreos/fleet/unit"
)

func wireUpUnitsResource(mux *http.ServeMux, prefix string, reg registry.Registry) {
	base := path.Join(prefix, "units")
	ur := unitsResource{reg, base}
	mux.Handle(base, &ur)
	mux.Handle(base+"/", &ur)
}

type unitsResource struct {
	reg      registry.Registry
	basePath string
}

func (ur *unitsResource) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
	if isCollectionPath(ur.basePath, req.URL.Path) {
		switch req.Method {
		case "GET":
			ur.list(rw, req)
		default:
			sendError(rw, http.StatusMethodNotAllowed, errors.New("only GET supported against this resource"))
		}
	} else if item, ok := isItemPath(ur.basePath, req.URL.Path); ok {
		switch req.Method {
		case "GET":
			ur.get(rw, req, item)
		case "DELETE":
			ur.destroy(rw, req, item)
		case "PUT":
			ur.set(rw, req, item)
		default:
			sendError(rw, http.StatusMethodNotAllowed, errors.New("only GET, PUT and DELETE supported against this resource"))
		}
	} else {
		sendError(rw, http.StatusNotFound, nil)
	}
}

func (ur *unitsResource) set(rw http.ResponseWriter, req *http.Request, item string) {
	if validateContentType(req) != nil {
		sendError(rw, http.StatusNotAcceptable, errors.New("application/json is only supported Content-Type"))
		return
	}

	var su schema.Unit
	dec := json.NewDecoder(req.Body)
	err := dec.Decode(&su)
	if err != nil {
		sendError(rw, http.StatusBadRequest, fmt.Errorf("unable to decode body: %v", err))
		return
	}

	u, err := ur.reg.Unit(item)
	if err != nil {
		log.Errorf("Failed fetching Unit(%s) from Registry: %v", item, err)
		sendError(rw, http.StatusInternalServerError, nil)
		return
	}

	var uf *unit.UnitFile
	if len(su.Options) > 0 {
		uf = schema.MapSchemaUnitOptionsToUnitFile(su.Options)
	}

	// TODO(bcwaldon): Assert value of DesiredState is launched, loaded or inactive
	ds := job.JobState(su.DesiredState)

	if u != nil {
		ur.update(rw, u, ds)
	} else if uf != nil {
		ur.create(rw, item, ds, uf)
	} else {
		sendError(rw, http.StatusConflict, errors.New("unit does not exist and no fileContents provided"))
	}
}

func (ur *unitsResource) create(rw http.ResponseWriter, item string, ds job.JobState, uf *unit.UnitFile) {
	u := job.Unit{Name: item, Unit: *uf}
	if err := ur.reg.CreateUnit(&u); err != nil {
		log.Errorf("Failed creating Unit(%s) in Registry: %v", u.Name, err)
		sendError(rw, http.StatusInternalServerError, nil)
		return
	}

	if len(ds) > 0 {
		if err := ur.reg.SetUnitTargetState(u.Name, ds); err != nil {
			log.Errorf("Failed setting target state of Unit(%s): %v", u.Name, err)
			sendError(rw, http.StatusInternalServerError, nil)
			return
		}
	}

	rw.WriteHeader(http.StatusNoContent)
}

func (ur *unitsResource) update(rw http.ResponseWriter, u *job.Unit, ds job.JobState) {
	if err := ur.reg.SetUnitTargetState(u.Name, ds); err != nil {
		log.Errorf("Failed setting target state of Unit(%s): %v", u.Name, err)
		sendError(rw, http.StatusInternalServerError, nil)
		return
	}

	rw.WriteHeader(http.StatusNoContent)
}

func (ur *unitsResource) destroy(rw http.ResponseWriter, req *http.Request, item string) {
	u, err := ur.reg.Unit(item)
	if err != nil {
		log.Errorf("Failed fetching Unit(%s): %v", item, err)
		sendError(rw, http.StatusInternalServerError, nil)
		return
	}

	if u == nil {
		sendError(rw, http.StatusNotFound, errors.New("unit does not exist"))
		return
	}

	err = ur.reg.DestroyUnit(item)
	if err != nil {
		log.Errorf("Failed destroying Unit(%s): %v", item, err)
		sendError(rw, http.StatusInternalServerError, nil)
		return
	}

	rw.WriteHeader(http.StatusNoContent)
}

func (ur *unitsResource) get(rw http.ResponseWriter, req *http.Request, item string) {
	u, err := ur.reg.Unit(item)
	if err != nil {
		log.Errorf("Failed fetching Unit(%s) from Registry: %v", item, err)
		sendError(rw, http.StatusInternalServerError, nil)
		return
	}

	if u == nil {
		sendError(rw, http.StatusNotFound, errors.New("unit does not exist"))
		return
	}

	su, err := ur.reg.ScheduledUnit(item)
	if err != nil {
		log.Errorf("Failed fetching ScheduledUnit(%s) from Registry: %v", item, err)
		sendError(rw, http.StatusInternalServerError, nil)
		return
	}

	s := schema.MapUnitToSchemaUnit(u, su)
	sendResponse(rw, http.StatusOK, *s)
}

func (ur *unitsResource) list(rw http.ResponseWriter, req *http.Request) {
	token, err := findNextPageToken(req.URL)
	if err != nil {
		sendError(rw, http.StatusBadRequest, err)
		return
	}

	if token == nil {
		def := DefaultPageToken()
		token = &def
	}

	page, err := getUnitPage(ur.reg, *token)
	if err != nil {
		log.Errorf("Failed fetching page of Units: %v", err)
		sendError(rw, http.StatusInternalServerError, nil)
		return
	}

	sendResponse(rw, http.StatusOK, page)
}

func getUnitPage(reg registry.Registry, tok PageToken) (*schema.UnitPage, error) {
	units, err := reg.Units()
	if err != nil {
		return nil, err
	}

	sUnits, err := reg.Schedule()
	if err != nil {
		return nil, err
	}

	sUnitMap := make(map[string]*job.ScheduledUnit)
	for _, sUnit := range sUnits {
		sUnit := sUnit
		sUnitMap[sUnit.Name] = &sUnit
	}

	items, next := extractUnitPageData(units, tok)
	page := schema.UnitPage{
		Units: make([]*schema.Unit, len(items)),
	}

	if next != nil {
		page.NextPageToken = next.Encode()
	}

	for i, u := range items {
		page.Units[i] = schema.MapUnitToSchemaUnit(&u, sUnitMap[u.Name])
	}

	return &page, nil
}

func extractUnitPageData(all []job.Unit, tok PageToken) (items []job.Unit, next *PageToken) {
	total := len(all)

	startIndex := int((tok.Page - 1) * tok.Limit)
	stopIndex := int(tok.Page * tok.Limit)

	if startIndex < total {
		if stopIndex > total {
			stopIndex = total
		} else {
			n := tok.Next()
			next = &n
		}

		items = all[startIndex:stopIndex]
	}

	return
}
<|endoftext|>


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

package client

import (
	"github.com/juju/errors"

	"github.com/juju/juju/api/base"
	"github.com/juju/juju/process/api"
)

const processAPI = "Process"

type facadeCaller interface {
	FacadeCall(request string, params, response interface{}) error
}

// processClient provides methods for interacting with Juju's internal
// RPC API, relative to workload processes.
type processClient struct {
	base.ClientFacade
	facadeCaller
}

// NewProcessClient builds a new workload process API client.
func NewProcessClient(facade base.ClientFacade, caller facadeCaller) *processClient {
	return &processClient{facade, caller}
}

// RegisterProcesses calls the RegisterProcesses API server method.
func (c *processClient) RegisterProcesses(tag string, processes []api.ProcessInfo) ([]api.ProcessResult, error) {
	var result api.ProcessResults

	procArgs := make([]api.RegisterProcessArg, len(processes))
	for i, procInfo := range processes {
		procArg := api.RegisterProcessArg{UnitTag: tag, ProcessInfo: procInfo}
		procArgs[i] = procArg
	}

	args := api.RegisterProcessesArgs{Processes: procArgs}
	if err := c.FacadeCall("RegisterProcesses", &args, &result); err != nil {
		return nil, errors.Trace(err)
	}

	return result.Results, nil
}

// ListProcesses calls the ListProcesses API server method.
func (c *processClient) ListProcesses(tag string, ids ...string) ([]api.ListProcessResult, error) {
	var result api.ListProcessesResults

	args := api.ListProcessesArgs{UnitTag: tag, IDs: ids}
	if err := c.FacadeCall("ListProcesses", &args, &result); err != nil {
		return nil, errors.Trace(err)
	}

	return result.Results, nil
}

// SetProcessesStatus calls the SetProcessesStatus API server method.
func (c *processClient) SetProcessesStatus(tag, status string, ids ...string) error {
	statusArgs := make([]api.SetProcessStatusArg, len(ids))
	for i, id := range ids {
		procStatus := api.ProcStatus{Status: status}
		statusArgs[i] = api.SetProcessStatusArg{UnitTag: tag, ID: id, Status: procStatus}
	}

	args := api.SetProcessesStatusArgs{Args: statusArgs}
	return c.FacadeCall("SetProcessesStatus", &args, nil)
}

// UnregisterProcesses calls the UnregisterProcesses API server method.
func (c *processClient) UnregisterProcesses(tag string, ids ...string) error {
	args := api.UnregisterProcessesArgs{UnitTag: tag, IDs: ids}
	return c.FacadeCall("UnregisterProcesses", &args, nil)
}
<commit_msg>processClient -> ProcessClient<commit_after>// Copyright 2015 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package client

import (
	"github.com/juju/errors"

	"github.com/juju/juju/api/base"
	"github.com/juju/juju/process/api"
)

const processAPI = "Process"

type facadeCaller interface {
	FacadeCall(request string, params, response interface{}) error
}

// ProcessClient provides methods for interacting with Juju's internal
// RPC API, relative to workload processes.
type ProcessClient struct {
	base.ClientFacade
	facadeCaller
}

// NewProcessClient builds a new workload process API client.
func NewProcessClient(facade base.ClientFacade, caller facadeCaller) *ProcessClient {
	return &ProcessClient{facade, caller}
}

// RegisterProcesses calls the RegisterProcesses API server method.
func (c *ProcessClient) RegisterProcesses(tag string, processes []api.ProcessInfo) ([]api.ProcessResult, error) {
	var result api.ProcessResults

	procArgs := make([]api.RegisterProcessArg, len(processes))
	for i, procInfo := range processes {
		procArg := api.RegisterProcessArg{UnitTag: tag, ProcessInfo: procInfo}
		procArgs[i] = procArg
	}

	args := api.RegisterProcessesArgs{Processes: procArgs}
	if err := c.FacadeCall("RegisterProcesses", &args, &result); err != nil {
		return nil, errors.Trace(err)
	}

	return result.Results, nil
}

// ListProcesses calls the ListProcesses API server method.
func (c *ProcessClient) ListProcesses(tag string, ids ...string) ([]api.ListProcessResult, error) {
	var result api.ListProcessesResults

	args := api.ListProcessesArgs{UnitTag: tag, IDs: ids}
	if err := c.FacadeCall("ListProcesses", &args, &result); err != nil {
		return nil, errors.Trace(err)
	}

	return result.Results, nil
}

// SetProcessesStatus calls the SetProcessesStatus API server method.
func (c *ProcessClient) SetProcessesStatus(tag, status string, ids ...string) error {
	statusArgs := make([]api.SetProcessStatusArg, len(ids))
	for i, id := range ids {
		procStatus := api.ProcStatus{Status: status}
		statusArgs[i] = api.SetProcessStatusArg{UnitTag: tag, ID: id, Status: procStatus}
	}

	args := api.SetProcessesStatusArgs{Args: statusArgs}
	return c.FacadeCall("SetProcessesStatus", &args, nil)
}

// UnregisterProcesses calls the UnregisterProcesses API server method.
func (c *ProcessClient) UnregisterProcesses(tag string, ids ...string) error {
	args := api.UnregisterProcessesArgs{UnitTag: tag, IDs: ids}
	return c.FacadeCall("UnregisterProcesses", &args, nil)
}
<|endoftext|>


<commit_before>package provider

import (
	"github.com/jcelliott/lumber"

	"github.com/nanobox-io/golang-docker-client"
	"github.com/nanobox-io/nanobox/models"
	"github.com/nanobox-io/nanobox/util/provider"
	"github.com/nanobox-io/nanobox/util/dhcp"
	"github.com/nanobox-io/nanobox/util/locker"
	"github.com/nanobox-io/nanobox/util/display"
)

type Setup struct {}

func (setup Setup) Run() error {

	display.StartTask("preparing provider")

	// ensure we have an exclusive lock while working with the provider
	locker.GlobalLock()
	defer locker.GlobalUnlock()

	// create the provider (VM)
	if err := provider.Create(); err != nil {
		display.ErrorTask()
		return err
	}

	display.StopTask()
	display.StartTask("booting provider")

	// start the provider (VM)
	if err := provider.Start(); err != nil {
		display.ErrorTask()
		return err
	}

	// attach the network to the host stack
	if err := setup.setupNetwork(); err != nil {
		display.ErrorTask()
		return err
	}

	// fetch the docker env from the provider
	if err := provider.DockerEnv(); err != nil {
		display.ErrorTask()
		return err
	}

	// setup the docker client with the docker environment
	if err := docker.Initialize("env"); err != nil {
		display.ErrorTask()
		return err
	}

	display.StopTask()

	return nil
}

// setupNetwork attaches the provider network to the host stack
func (setup Setup) setupNetwork() error {
	// fetch the provider model
	model, _ := models.LoadProvider()

	// short-circuit if this is already done
	if model.HostIP != "" {
		return nil
	}

	// reserve an IP to be used for mounting
	mountIP, err := dhcp.ReserveGlobal()
	if err != nil {
		lumber.Error("provider:Setup:setupNetwork:dhcp.ReserveGlobal(): %s", err.Error())
		return err
	}

	// fetch the host ip from the provider
	hostIP, err := provider.HostIP()
	if err != nil {
		lumber.Error("provider:Setup:setupNetwork:provider.HostIP(): %s", err.Error())
		return err
	}

	// persist the IPs for later use
	model.MountIP = mountIP
	model.HostIP  = hostIP
	if err := model.Save(); err != nil {
		return err
	}

	// let's attach the mount IP to the provider
	if err := provider.AddIP(mountIP); err != nil {
		lumber.Error("provider:Setup:setupNetwork:provider.AddIP(%s): %s", mountIP, err.Error())
		return err
	}

	// now let's set the mount IP as the default route
	if err := provider.SetDefaultIP(mountIP); err != nil {
		lumber.Error("provider:Setup:setupNetwork:provider.SetDefaultIP(%s): %s", mountIP, err.Error())
		return err
	}

	return nil
}
<commit_msg>Layer in a pattern for error tracing and lumber tracing to coexist<commit_after>package provider

import (
	"github.com/jcelliott/lumber"

	"github.com/nanobox-io/golang-docker-client"
	"github.com/nanobox-io/nanobox/models"
	"github.com/nanobox-io/nanobox/util/provider"
	"github.com/nanobox-io/nanobox/util/dhcp"
	"github.com/nanobox-io/nanobox/util/locker"
	"github.com/nanobox-io/nanobox/util/display"
)

type Setup struct {}

// Run sets up the provider (launch VM, etc)
func (setup Setup) Run() error {
	locker.GlobalLock()
	defer locker.GlobalUnlock()

	display.OpenContext("Preparing Nanobox")

	// create the provider (VM)
	if err := provider.Create(); err != nil {
		lumber.Error("provider:Setup:Run:provider.Create(): %s", err.Error())
		return fmt.Errorf("failed to create the provider: %s", err.Error())
	}

	// start the provider (VM)
	if err := provider.Start(); err != nil {
		lumber.Error("provider:Setup:Run:provider.Start(): %s", err.Error())
		return fmt.Errorf("failed to start the provider: %s", err.Error())
	}

	// attach the network to the host stack
	if err := setup.setupNetwork(); err != nil {
		return fmt.Errorf("failed to setup the provider network: %s", err.Error())
	}

	// load the docker environment
	if err := provider.DockerEnv(); err != nil {
		lumber.Error("provider:Setup:Run:provider.DockerEnv(): %s", err.Error())
		return fmt.Errorf("failed to load the docker environment: %s", err.Error())
	}

	// initialize the docker client
	if err := docker.Initialize("env"); err != nil {
		lumber.Error("provider:Setup:Run:docker.Initialize(): %s", err.Error())
		return fmt.Errorf("failed to initialize the docker client: %s", err.Error())
	}

	display.CloseContext()

	return nil
}

// setupNetwork sets up the provider network
func (setup Setup) setupNetwork() error {
	display.StartTask("Joining virtual network")

	// fetch the provider model
	model, _ := models.LoadProvider()

	// short-circuit if this is already done
	if model.HostIP != "" {
		return nil
	}

	// reserve an IP to be used for mounting
	mountIP, err := dhcp.ReserveGlobal()
	if err != nil {
		lumber.Error("provider:Setup:setupNetwork:dhcp.ReserveGlobal(): %s", err.Error())
		return fmt.Errorf("failed to reserve a global IP: %s", err.Error())
	}

	// add the global IP to the provider
	if err := provider.AddIP(mountIP); err != nil {
		lumber.Error("provider:Setup:setupNetwork:provider.AddIP(%s): %s", mountIP, err.Error())
		return fmt.Errorf("failed to add IP to provider: %s", err.Error())
	}

	// tell the provider to set this IP as the default gateway
	if err := provider.SetDefaultIP(mountIP); err != nil {
		lumber.Error("provider:Setup:setupNetwork:provider.SetDefaultIP(%s): %s", mountIP, err.Error())
		return fmt.Errorf("failed to set a default gateway on the provider: %s", err.Error())
	}

	// retrieve the provider's Host IP
	hostIP, err := provider.HostIP()
	if err != nil {
		lumber.Error("provider:Setup:setupNetwork:provider.HostIP(): %s", err.Error())
		return fmt.Errorf("unable to retrieve the host IP from the provider: %s", err.Error())
	}

	// persist the IPs for later use
	model.MountIP = mountIP
	model.HostIP  = hostIP
	if err := model.Save(); err != nil {
		return fmt.Errorf("failed to persist the provider model: %s", err.Error())
	}

	display.CloseContext()

	return nil
}
<|endoftext|>


<commit_before>/*

Package base contains a number of base classes for common objects in boardgame.
Technically all of these base objects are fully optional, but in practice almost
every game will use them (or a class that embeds them).

*/
package base

import (
	"github.com/jkomoros/boardgame"
)

//SubState is a simple struct designed to be anonymously embedded in the
//boardgame.SubStates you create, so you don't have to implement SetState yourself.
type SubState struct {
	//Ugh it's really annoying to have to hold onto the same state in two
	//references...
	immutableState boardgame.ImmutableState
	state          boardgame.State
	ref            boardgame.StatePropertyRef
}

//SetState sets the State to the given state.
func (s *SubState) SetState(state boardgame.State) {
	s.state = state
}

//State returns the state set with SetState.
func (s *SubState) State() boardgame.State {
	return s.state
}

//SetImmutableState sets the ImmutableState to return.
func (s *SubState) SetImmutableState(state boardgame.ImmutableState) {
	s.immutableState = state
}

//ImmutableState returns the immutablestate set via SetImmutableState.
func (s *SubState) ImmutableState() boardgame.ImmutableState {
	return s.immutableState
}

//SetStatePropertyRef sets the ref to return from StatePropertyRef()
func (s *SubState) SetStatePropertyRef(ref boardgame.StatePropertyRef) {
	s.ref = ref
}

//StatePropertyRef returns the ref passed via SetStatePropertyRef()
func (s *SubState) StatePropertyRef() boardgame.StatePropertyRef {
	return s.ref
}

//ComponentValues is an optional convenience struct designed to be embedded
//anoymously in your component values to implement
//boardgame.ContainingComponent() and boardgame.SetContainingComponent()
//automatically.
type ComponentValues struct {
	c boardgame.Component
}

//ContainingComponent returns the component set via SetContainingComponent.
func (v *ComponentValues) ContainingComponent() boardgame.Component {
	return v.c
}

//SetContainingComponent sets the return value of ContainingComponent.
func (v *ComponentValues) SetContainingComponent(c boardgame.Component) {
	v.c = c
}
<commit_msg>base.SubState grows a PlayerIndex() convenience property. Part of #744.<commit_after>/*

Package base contains a number of base classes for common objects in boardgame.
Technically all of these base objects are fully optional, but in practice almost
every game will use them (or a class that embeds them).

*/
package base

import (
	"github.com/jkomoros/boardgame"
)

//SubState is a simple struct designed to be anonymously embedded in the
//boardgame.SubStates you create, so you don't have to implement SetState yourself.
type SubState struct {
	//Ugh it's really annoying to have to hold onto the same state in two
	//references...
	immutableState boardgame.ImmutableState
	state          boardgame.State
	ref            boardgame.StatePropertyRef
}

//SetState sets the State to the given state.
func (s *SubState) SetState(state boardgame.State) {
	s.state = state
}

//State returns the state set with SetState.
func (s *SubState) State() boardgame.State {
	return s.state
}

//SetImmutableState sets the ImmutableState to return.
func (s *SubState) SetImmutableState(state boardgame.ImmutableState) {
	s.immutableState = state
}

//ImmutableState returns the immutablestate set via SetImmutableState.
func (s *SubState) ImmutableState() boardgame.ImmutableState {
	return s.immutableState
}

//SetStatePropertyRef sets the ref to return from StatePropertyRef()
func (s *SubState) SetStatePropertyRef(ref boardgame.StatePropertyRef) {
	s.ref = ref
}

//StatePropertyRef returns the ref passed via SetStatePropertyRef()
func (s *SubState) StatePropertyRef() boardgame.StatePropertyRef {
	return s.ref
}

//PlayerIndex is a conveniece warpper that returns
//StatePropertyRef().PlayerIndex. Only really useful for when the SubState is of
//type PlayerState.
func (s *SubState) PlayerIndex() boardgame.PlayerIndex {
	return s.ref.PlayerIndex
}

//ComponentValues is an optional convenience struct designed to be embedded
//anoymously in your component values to implement
//boardgame.ContainingComponent() and boardgame.SetContainingComponent()
//automatically.
type ComponentValues struct {
	c boardgame.Component
}

//ContainingComponent returns the component set via SetContainingComponent.
func (v *ComponentValues) ContainingComponent() boardgame.Component {
	return v.c
}

//SetContainingComponent sets the return value of ContainingComponent.
func (v *ComponentValues) SetContainingComponent(c boardgame.Component) {
	v.c = c
}
<|endoftext|>


<commit_before>package imaginator

import (
	"time"

	"github.com/Symantec/Dominator/lib/image"
)

type BuildImageRequest struct {
	StreamName     string
	ExpiresIn      time.Duration
	GitBranch      string
	MaxSourceAge   time.Duration
	ReturnImage    bool
	StreamBuildLog bool
	Variables      map[string]string
}

type BuildImageResponse struct {
	Image       *image.Image
	ImageName   string
	BuildLog    []byte
	ErrorString string
}
<commit_msg>Add proto/imaginator.BuildImageRequest.DisableRecursiveBuild field.<commit_after>package imaginator

import (
	"time"

	"github.com/Symantec/Dominator/lib/image"
)

type BuildImageRequest struct {
	DisableRecursiveBuild bool
	ExpiresIn             time.Duration
	GitBranch             string
	MaxSourceAge          time.Duration
	ReturnImage           bool
	StreamBuildLog        bool
	StreamName            string
	Variables             map[string]string
}

type BuildImageResponse struct {
	Image       *image.Image
	ImageName   string
	BuildLog    []byte
	ErrorString string
}
<|endoftext|>