feat(hooks): Adds weighted hooks
closes #2136 * Adds new annotation `helm.sh/hookWeight` * Sorts executing hooks of similar kind in ascending order * There is no upper or lower bounds on the weights
This commit is contained in:
parent
ea61ace808
commit
05d0fcb774
|
@ -23,6 +23,9 @@ import (
|
|||
// HookAnno is the label name for a hook
|
||||
const HookAnno = "helm.sh/hook"
|
||||
|
||||
// HookWeightAnno is the label name for a hook weight
|
||||
const HookWeightAnno = "helm.sh/hookWeight"
|
||||
|
||||
// Types of hooks
|
||||
const (
|
||||
PreInstall = "pre-install"
|
||||
|
|
|
@ -100,6 +100,8 @@ type Hook struct {
|
|||
Events []Hook_Event `protobuf:"varint,5,rep,packed,name=events,enum=hapi.release.Hook_Event" json:"events,omitempty"`
|
||||
// LastRun indicates the date/time this was last run.
|
||||
LastRun *google_protobuf.Timestamp `protobuf:"bytes,6,opt,name=last_run,json=lastRun" json:"last_run,omitempty"`
|
||||
// Weight indicates the sort order for execution among similar Hook types
|
||||
Weight int `protobuf:"bytes,7,opt,name=weight" json:"weight,omitempty"`
|
||||
}
|
||||
|
||||
func (m *Hook) Reset() { *m = Hook{} }
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
Copyright 2016 The Kubernetes Authors All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package tiller
|
||||
|
||||
import (
|
||||
"sort"
|
||||
|
||||
"k8s.io/helm/pkg/proto/hapi/release"
|
||||
)
|
||||
|
||||
// sortByHookWeight does an in-place sort of hooks by their supplied weight.
|
||||
func sortByHookWeight(hooks []*release.Hook) []*release.Hook {
|
||||
hs := newHookWeightSorter(hooks)
|
||||
sort.Sort(hs)
|
||||
return hs.hooks
|
||||
}
|
||||
|
||||
type hookWeightSorter struct {
|
||||
hooks []*release.Hook
|
||||
}
|
||||
|
||||
func newHookWeightSorter(h []*release.Hook) *hookWeightSorter {
|
||||
return &hookWeightSorter{
|
||||
hooks: h,
|
||||
}
|
||||
}
|
||||
|
||||
func (hs *hookWeightSorter) Len() int { return len(hs.hooks) }
|
||||
|
||||
func (hs *hookWeightSorter) Swap(i, j int) {
|
||||
hs.hooks[i], hs.hooks[j] = hs.hooks[j], hs.hooks[i]
|
||||
}
|
||||
|
||||
func (hs *hookWeightSorter) Less(i, j int) bool {
|
||||
if hs.hooks[i].Weight == hs.hooks[j].Weight {
|
||||
return hs.hooks[i].Name < hs.hooks[j].Name
|
||||
}
|
||||
return hs.hooks[i].Weight < hs.hooks[j].Weight
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
Copyright 2017 The Kubernetes Authors All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package tiller
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"k8s.io/helm/pkg/proto/hapi/release"
|
||||
)
|
||||
|
||||
func TestHookSorter(t *testing.T) {
|
||||
hooks := []*release.Hook{
|
||||
{
|
||||
Name: "g",
|
||||
Kind: "pre-install",
|
||||
Weight: 99,
|
||||
},
|
||||
{
|
||||
Name: "f",
|
||||
Kind: "pre-install",
|
||||
Weight: 3,
|
||||
},
|
||||
{
|
||||
Name: "b",
|
||||
Kind: "pre-install",
|
||||
Weight: -3,
|
||||
},
|
||||
{
|
||||
Name: "e",
|
||||
Kind: "pre-install",
|
||||
Weight: 3,
|
||||
},
|
||||
{
|
||||
Name: "a",
|
||||
Kind: "pre-install",
|
||||
Weight: -10,
|
||||
},
|
||||
{
|
||||
Name: "c",
|
||||
Kind: "pre-install",
|
||||
Weight: 0,
|
||||
},
|
||||
{
|
||||
Name: "d",
|
||||
Kind: "pre-install",
|
||||
Weight: 3,
|
||||
},
|
||||
}
|
||||
|
||||
res := sortByHookWeight(hooks)
|
||||
got := ""
|
||||
expect := "abcdefg"
|
||||
for _, r := range res {
|
||||
got += r.Name
|
||||
}
|
||||
if got != expect {
|
||||
t.Errorf("Expected %q, got %q", expect, got)
|
||||
}
|
||||
}
|
|
@ -20,6 +20,7 @@ import (
|
|||
"fmt"
|
||||
"log"
|
||||
"path"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/ghodss/yaml"
|
||||
|
@ -109,12 +110,21 @@ func sortManifests(files map[string]string, apis chartutil.VersionSet, sort Sort
|
|||
generic = append(generic, manifest{name: n, content: c, head: &sh})
|
||||
continue
|
||||
}
|
||||
|
||||
hw := 0
|
||||
hws, _ := sh.Metadata.Annotations[hooks.HookWeightAnno]
|
||||
hw, err = strconv.Atoi(hws)
|
||||
if err != nil {
|
||||
hw = 0
|
||||
}
|
||||
|
||||
h := &release.Hook{
|
||||
Name: sh.Metadata.Name,
|
||||
Kind: sh.Kind,
|
||||
Path: n,
|
||||
Manifest: c,
|
||||
Events: []release.Hook_Event{},
|
||||
Weight: hw,
|
||||
}
|
||||
|
||||
isHook := false
|
||||
|
|
|
@ -911,17 +911,18 @@ func (s *ReleaseServer) execHook(hs []*release.Hook, name, namespace, hook strin
|
|||
}
|
||||
|
||||
log.Printf("Executing %s hooks for %s", hook, name)
|
||||
executingHooks := []*release.Hook{}
|
||||
for _, h := range hs {
|
||||
found := false
|
||||
for _, e := range h.Events {
|
||||
if e == code {
|
||||
found = true
|
||||
executingHooks = append(executingHooks, h)
|
||||
}
|
||||
}
|
||||
// If this doesn't implement the hook, skip it.
|
||||
if !found {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
executingHooks = sortByHookWeight(executingHooks)
|
||||
|
||||
for _, h := range executingHooks {
|
||||
|
||||
b := bytes.NewBufferString(h.Manifest)
|
||||
if err := kubeCli.Create(namespace, b, timeout, false); err != nil {
|
||||
|
@ -937,6 +938,7 @@ func (s *ReleaseServer) execHook(hs []*release.Hook, name, namespace, hook strin
|
|||
}
|
||||
h.LastRun = timeconv.Now()
|
||||
}
|
||||
|
||||
log.Printf("Hooks complete for %s %s", hook, name)
|
||||
return nil
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue