From 0bcc0ac9a70273163301ba5aa32068e71b4e4da9 Mon Sep 17 00:00:00 2001 From: David Chung Date: Wed, 1 Feb 2017 18:52:05 -0800 Subject: [PATCH 1/3] build container on release branches (#377) Signed-off-by: David Chung --- circle.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/circle.yml b/circle.yml index 92e818ee7..2bc515c30 100644 --- a/circle.yml +++ b/circle.yml @@ -41,8 +41,14 @@ test: - cd $WORKDIR && bash <(curl -s https://codecov.io/bash) deployment: + release: + branch: /release-.*/ + commands: + - docker login -e $DOCKER_HUB_EMAIL -u $DOCKER_HUB_USER -p $DOCKER_HUB_PASSWD + - DOCKER_PUSH=true DOCKER_TAG_LATEST=false DOCKER_TAG=$(echo $CIRCLE_BRANCH | awk -F - '{print $2}') DOCKER_BUILD_FLAGS="--rm=false" make build-docker docker: branch: master commands: - docker login -e $DOCKER_HUB_EMAIL -u $DOCKER_HUB_USER -p $DOCKER_HUB_PASSWD - DOCKER_PUSH=true DOCKER_TAG_LATEST=true DOCKER_TAG="master-$CIRCLE_BUILD_NUM" DOCKER_BUILD_FLAGS="--rm=false" make build-docker + \ No newline at end of file From df07546add74eca318086c2908a36f77fa686ebd Mon Sep 17 00:00:00 2001 From: David Chung Date: Thu, 2 Feb 2017 16:26:14 -0800 Subject: [PATCH 2/3] Clean shutdown of `infrakit plugin start --wait` (#379) Signed-off-by: David Chung --- cmd/cli/plugin.go | 74 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 71 insertions(+), 3 deletions(-) diff --git a/cmd/cli/plugin.go b/cmd/cli/plugin.go index 98488c211..bdf5bed37 100644 --- a/cmd/cli/plugin.go +++ b/cmd/cli/plugin.go @@ -7,6 +7,7 @@ import ( "strconv" "sync" "syscall" + "time" log "github.com/Sirupsen/logrus" "github.com/docker/infrakit/pkg/discovery" @@ -104,13 +105,34 @@ func pluginCommand(plugins func() discovery.Plugins) *cobra.Command { input = append(input, ch) } - var wait sync.WaitGroup + // This is the channel to send signal that plugins are stopped out of band so stop waiting. + noRunningPlugins := make(chan struct{}) + // This is the channel for completion of waiting. + waitDone := make(chan struct{}) + // This is the channel to stop scanning for running plugins. + pluginScanDone := make(chan struct{}) + var wait sync.WaitGroup if *doWait { wait.Add(1) + go func() { + wait.Wait() // wait for everyone to complete + close(waitDone) + }() + } + + // Now start all the plugins + started := []string{} + + // We do a count of the plugins running before we start. + var before, after = 0, 0 + + if m, err := plugins().List(); err != nil { + log.Warningln("Problem listing current plugins:", err, "continue.") + } else { + before = len(m) } - // now start all the plugins for _, pluginToStart := range args { fmt.Println("Starting up", pluginToStart) @@ -123,6 +145,8 @@ func pluginCommand(plugins func() discovery.Plugins) *cobra.Command { Plugin: plugin.Name(name), Started: func(config *types.Any) { fmt.Println(name, "started.") + + started = append(started, name) wait.Done() }, Error: func(config *types.Any, err error) { @@ -133,11 +157,55 @@ func pluginCommand(plugins func() discovery.Plugins) *cobra.Command { } } - wait.Wait() // wait for everyone to complete + if m, err := plugins().List(); err == nil { + after = len(m) + } + + // Here we scan the plugins. If we are starting up the plugins, wait a little bit + // for them to show up. Then we start scanning to see if the sockets are gone. + // If the sockets are gone, then we can safely exit. + if *doWait { + go func() { + interval := 5 * time.Second + + now := after + if now <= before { + // Here we have fewer plugins running then before. Wait a bit + time.Sleep(interval) + } + checkNow := time.Tick(interval) + for { + select { + case <-pluginScanDone: + log.Infoln("--wait mode: stop scanning.") + return + + case <-checkNow: + if m, err := plugins().List(); err == nil { + now = len(m) + } + if now == 0 { + log.Infoln("--wait mode: scan found no plugins.") + close(noRunningPlugins) + } + } + } + }() + } + + // Here we wait for either wait group to be done or if they are killed out of band. + select { + case <-waitDone: + log.Infoln("All plugins completed. Exiting.") + case <-noRunningPlugins: + log.Infoln("Plugins aren't running anymore. Exiting.") + } for _, monitor := range monitors { monitor.Stop() } + + close(pluginScanDone) return nil } From 30b3787ce0044c71557db0531c9cadb7ce1ed15a Mon Sep 17 00:00:00 2001 From: David Chung Date: Thu, 2 Feb 2017 19:22:22 -0800 Subject: [PATCH 3/3] Rename template function to avoid shadowing of `index` (#382) Signed-off-by: David Chung --- pkg/template/funcs.go | 6 +++--- pkg/template/funcs_test.go | 36 ++++++++++++++++---------------- pkg/template/integration_test.go | 28 +++++++++++++++++++++++++ 3 files changed, 49 insertions(+), 21 deletions(-) diff --git a/pkg/template/funcs.go b/pkg/template/funcs.go index 55205b80f..0e123185b 100644 --- a/pkg/template/funcs.go +++ b/pkg/template/funcs.go @@ -76,9 +76,9 @@ func UnixTime() interface{} { return time.Now().Unix() } -// Index returns the index of search in array. -1 if not found or array is not iterable. An optional true will +// IndexOf returns the index of search in array. -1 if not found or array is not iterable. An optional true will // turn on strict type check while by default string representations are used to compare values. -func Index(srch interface{}, array interface{}, strictOptional ...bool) int { +func IndexOf(srch interface{}, array interface{}, strictOptional ...bool) int { strict := false if len(strictOptional) > 0 { strict = strictOptional[0] @@ -153,6 +153,6 @@ func (t *Template) DefaultFuncs() map[string]interface{} { "lines": SplitLines, "to_json": ToJSON, "from_json": FromJSON, - "index": Index, + "index_of": IndexOf, } } diff --git a/pkg/template/funcs_test.go b/pkg/template/funcs_test.go index 120c2829f..7733e5c7b 100644 --- a/pkg/template/funcs_test.go +++ b/pkg/template/funcs_test.go @@ -281,29 +281,29 @@ func TestMapEncodeDecode(t *testing.T) { require.Equal(t, expect, actual) } -func TestIndex(t *testing.T) { - require.Equal(t, -1, Index("a", []string{"x", "y", "z"})) - require.Equal(t, 1, Index("y", []string{"x", "y", "z"})) - require.Equal(t, -1, Index(25, []string{"x", "y", "z"})) - require.Equal(t, -1, Index(25, 26)) - require.Equal(t, 1, Index("y", []string{"x", "y", "z"})) - require.Equal(t, 1, Index("y", []interface{}{"x", "y", "z"})) - require.Equal(t, 1, Index(1, []interface{}{0, 1, 2})) - require.Equal(t, 1, Index("1", []interface{}{0, 1, 2})) - require.Equal(t, 1, Index(1, []interface{}{0, "1", 2})) - require.Equal(t, -1, Index("1", []interface{}{0, 1, 2}, true)) // strict case type must match - require.Equal(t, 1, Index("1", []interface{}{0, "1", 2}, true)) // strict case type must match - require.Equal(t, -1, Index(1, []interface{}{0, "1", 2}, true)) // strict case type must match +func TestIndexOf(t *testing.T) { + require.Equal(t, -1, IndexOf("a", []string{"x", "y", "z"})) + require.Equal(t, 1, IndexOf("y", []string{"x", "y", "z"})) + require.Equal(t, -1, IndexOf(25, []string{"x", "y", "z"})) + require.Equal(t, -1, IndexOf(25, 26)) + require.Equal(t, 1, IndexOf("y", []string{"x", "y", "z"})) + require.Equal(t, 1, IndexOf("y", []interface{}{"x", "y", "z"})) + require.Equal(t, 1, IndexOf(1, []interface{}{0, 1, 2})) + require.Equal(t, 1, IndexOf("1", []interface{}{0, 1, 2})) + require.Equal(t, 1, IndexOf(1, []interface{}{0, "1", 2})) + require.Equal(t, -1, IndexOf("1", []interface{}{0, 1, 2}, true)) // strict case type must match + require.Equal(t, 1, IndexOf("1", []interface{}{0, "1", 2}, true)) // strict case type must match + require.Equal(t, -1, IndexOf(1, []interface{}{0, "1", 2}, true)) // strict case type must match v := "1" - require.Equal(t, 1, Index(&v, []interface{}{0, "1", 2})) - require.Equal(t, 1, Index(&v, []interface{}{0, &v, 2}, true)) - require.Equal(t, 1, Index(&v, []interface{}{0, &v, 2})) + require.Equal(t, 1, IndexOf(&v, []interface{}{0, "1", 2})) + require.Equal(t, 1, IndexOf(&v, []interface{}{0, &v, 2}, true)) + require.Equal(t, 1, IndexOf(&v, []interface{}{0, &v, 2})) a := "0" c := "2" - require.Equal(t, 1, Index("1", []*string{&a, &v, &c})) + require.Equal(t, 1, IndexOf("1", []*string{&a, &v, &c})) // This doesn't work because the type information is gone and we have just an address - require.Equal(t, -1, Index("1", []interface{}{0, &v, 2})) + require.Equal(t, -1, IndexOf("1", []interface{}{0, &v, 2})) } diff --git a/pkg/template/integration_test.go b/pkg/template/integration_test.go index 4691282d7..23002ad97 100644 --- a/pkg/template/integration_test.go +++ b/pkg/template/integration_test.go @@ -158,3 +158,31 @@ The message is {{str}} require.True(t, context.Bool) require.Equal(t, 23, context.invokes) // note this is private state not accessible in template } + +func TestIndexIndexOf(t *testing.T) { + + { + tt, err := NewTemplate("str://{{ index . 1 }}", Options{}) + require.NoError(t, err) + + view, err := tt.Render([]string{"a", "b", "c", "d"}) + require.NoError(t, err) + require.Equal(t, "b", view) + } + { + tt, err := NewTemplate(`str://{{ index_of "c" . }}`, Options{}) + require.NoError(t, err) + + view, err := tt.Render([]string{"a", "b", "c", "d"}) + require.NoError(t, err) + require.Equal(t, "2", view) + } + { + tt, err := NewTemplate(`str://{{ index . 0 | cat "index-" | nospace }}`, Options{}) + require.NoError(t, err) + + view, err := tt.Render([]string{"a", "b", "c", "d"}) + require.NoError(t, err) + require.Equal(t, "index-a", view) + } +}