Skip to content

Commit 15c1419

Browse files
author
Michelle Noorali
authored
Merge pull request helm#2457 from michelleN/hooks-bug
fix(tiller): track hooks in multi-def manifests
2 parents 5d3f3fd + 6bfb08a commit 15c1419

File tree

3 files changed

+196
-99
lines changed

3 files changed

+196
-99
lines changed

pkg/tiller/hooks.go

+98-45
Original file line numberDiff line numberDiff line change
@@ -51,96 +51,149 @@ type manifest struct {
5151
head *util.SimpleHead
5252
}
5353

54-
// sortManifests takes a map of filename/YAML contents and sorts them into hook types.
54+
type result struct {
55+
hooks []*release.Hook
56+
generic []manifest
57+
}
58+
59+
type manifestFile struct {
60+
entries map[string]string
61+
path string
62+
apis chartutil.VersionSet
63+
}
64+
65+
// sortManifests takes a map of filename/YAML contents, splits the file
66+
// by manifest entries, and sorts the entries into hook types.
5567
//
5668
// The resulting hooks struct will be populated with all of the generated hooks.
5769
// Any file that does not declare one of the hook types will be placed in the
5870
// 'generic' bucket.
5971
//
60-
// To determine hook type, this looks for a YAML structure like this:
61-
//
62-
// kind: SomeKind
63-
// apiVersion: v1
64-
// metadata:
65-
// annotations:
66-
// helm.sh/hook: pre-install
67-
//
68-
// Where HOOK_NAME is one of the known hooks.
69-
//
70-
// If a file declares more than one hook, it will be copied into all of the applicable
71-
// hook buckets. (Note: label keys are not unique within the labels section).
72-
//
7372
// Files that do not parse into the expected format are simply placed into a map and
7473
// returned.
7574
func sortManifests(files map[string]string, apis chartutil.VersionSet, sort SortOrder) ([]*release.Hook, []manifest, error) {
76-
hs := []*release.Hook{}
77-
generic := []manifest{}
75+
result := &result{}
76+
77+
for filePath, c := range files {
7878

79-
for n, c := range files {
8079
// Skip partials. We could return these as a separate map, but there doesn't
8180
// seem to be any need for that at this time.
82-
if strings.HasPrefix(path.Base(n), "_") {
81+
if strings.HasPrefix(path.Base(filePath), "_") {
8382
continue
8483
}
85-
// Skip empty files, and log this.
84+
// Skip empty files and log this.
8685
if len(strings.TrimSpace(c)) == 0 {
87-
log.Printf("info: manifest %q is empty. Skipping.", n)
86+
log.Printf("info: manifest %q is empty. Skipping.", filePath)
8887
continue
8988
}
9089

91-
var sh util.SimpleHead
92-
err := yaml.Unmarshal([]byte(c), &sh)
90+
manifestFile := &manifestFile{
91+
entries: util.SplitManifests(c),
92+
path: filePath,
93+
apis: apis,
94+
}
95+
96+
if err := manifestFile.sort(result); err != nil {
97+
return result.hooks, result.generic, err
98+
}
99+
}
100+
101+
return result.hooks, sortByKind(result.generic, sort), nil
102+
}
103+
104+
// sort takes a manifestFile object which may contain multiple resource definition
105+
// entries and sorts each entry by hook types, and saves the resulting hooks and
106+
// generic manifests (or non-hooks) to the result struct.
107+
//
108+
// To determine hook type, it looks for a YAML structure like this:
109+
//
110+
// kind: SomeKind
111+
// apiVersion: v1
112+
// metadata:
113+
// annotations:
114+
// helm.sh/hook: pre-install
115+
//
116+
func (file *manifestFile) sort(result *result) error {
117+
for _, m := range file.entries {
118+
var entry util.SimpleHead
119+
err := yaml.Unmarshal([]byte(m), &entry)
93120

94121
if err != nil {
95-
e := fmt.Errorf("YAML parse error on %s: %s", n, err)
96-
return hs, generic, e
122+
e := fmt.Errorf("YAML parse error on %s: %s", file.path, err)
123+
return e
97124
}
98125

99-
if sh.Version != "" && !apis.Has(sh.Version) {
100-
return hs, generic, fmt.Errorf("apiVersion %q in %s is not available", sh.Version, n)
126+
if entry.Version != "" && !file.apis.Has(entry.Version) {
127+
return fmt.Errorf("apiVersion %q in %s is not available", entry.Version, file.path)
101128
}
102129

103-
if sh.Metadata == nil || sh.Metadata.Annotations == nil || len(sh.Metadata.Annotations) == 0 {
104-
generic = append(generic, manifest{name: n, content: c, head: &sh})
130+
if !hasAnyAnnotation(entry) {
131+
result.generic = append(result.generic, manifest{
132+
name: file.path,
133+
content: m,
134+
head: &entry,
135+
})
105136
continue
106137
}
107138

108-
hookTypes, ok := sh.Metadata.Annotations[hooks.HookAnno]
139+
hookTypes, ok := entry.Metadata.Annotations[hooks.HookAnno]
109140
if !ok {
110-
generic = append(generic, manifest{name: n, content: c, head: &sh})
141+
result.generic = append(result.generic, manifest{
142+
name: file.path,
143+
content: m,
144+
head: &entry,
145+
})
111146
continue
112147
}
113148

114-
hws, _ := sh.Metadata.Annotations[hooks.HookWeightAnno]
115-
hw, err := strconv.Atoi(hws)
116-
if err != nil {
117-
hw = 0
118-
}
149+
hw := calculateHookWeight(entry)
119150

120151
h := &release.Hook{
121-
Name: sh.Metadata.Name,
122-
Kind: sh.Kind,
123-
Path: n,
124-
Manifest: c,
152+
Name: entry.Metadata.Name,
153+
Kind: entry.Kind,
154+
Path: file.path,
155+
Manifest: m,
125156
Events: []release.Hook_Event{},
126-
Weight: int32(hw),
157+
Weight: hw,
127158
}
128159

129-
isHook := false
160+
isKnownHook := false
130161
for _, hookType := range strings.Split(hookTypes, ",") {
131162
hookType = strings.ToLower(strings.TrimSpace(hookType))
132163
e, ok := events[hookType]
133164
if ok {
134-
isHook = true
165+
isKnownHook = true
135166
h.Events = append(h.Events, e)
136167
}
137168
}
138169

139-
if !isHook {
170+
if !isKnownHook {
140171
log.Printf("info: skipping unknown hook: %q", hookTypes)
141172
continue
142173
}
143-
hs = append(hs, h)
174+
175+
result.hooks = append(result.hooks, h)
176+
}
177+
178+
return nil
179+
}
180+
181+
func hasAnyAnnotation(entry util.SimpleHead) bool {
182+
if entry.Metadata == nil ||
183+
entry.Metadata.Annotations == nil ||
184+
len(entry.Metadata.Annotations) == 0 {
185+
return false
144186
}
145-
return hs, sortByKind(generic, sort), nil
187+
188+
return true
189+
}
190+
191+
func calculateHookWeight(entry util.SimpleHead) int32 {
192+
hws, _ := entry.Metadata.Annotations[hooks.HookWeightAnno]
193+
hw, err := strconv.Atoi(hws)
194+
if err != nil {
195+
hw = 0
196+
}
197+
198+
return int32(hw)
146199
}

0 commit comments

Comments
 (0)