Skip to content

Commit 825645d

Browse files
authored
Merge pull request #73 from fluxcd/ignore-charts-etc
Screen files, and output only those updated
2 parents 8894a7e + 05832c5 commit 825645d

File tree

6 files changed

+224
-26
lines changed

6 files changed

+224
-26
lines changed

pkg/update/filereader.go

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
/*
2+
Copyright 2020, 2021 The Flux authors
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package update
18+
19+
import (
20+
"bytes"
21+
"fmt"
22+
"io/ioutil"
23+
"os"
24+
"path/filepath"
25+
26+
"sigs.k8s.io/kustomize/kyaml/kio"
27+
"sigs.k8s.io/kustomize/kyaml/kio/kioutil"
28+
"sigs.k8s.io/kustomize/kyaml/yaml"
29+
)
30+
31+
// ScreeningReader is a kio.Reader that includes only files that are
32+
// pertinent to automation. In practice this means looking for a
33+
// particular token in each file, and ignoring those files without the
34+
// token. This avoids most problematic cases -- e.g., templates in a
35+
// Helm chart, which won't parse as YAML -- and cheaply filters for
36+
// only those files that need processing.
37+
type ScreeningLocalReader struct {
38+
Token string
39+
Path string
40+
41+
// This records the relative path of each file that passed
42+
// screening (i.e., contained the token), but couldn't be parsed.
43+
ProblemFiles []string
44+
}
45+
46+
// Read scans the .Path recursively for files that contain .Token, and
47+
// parses any that do. It applies the filename annotation used by
48+
// [`kio.LocalPackageWriter`](https://godoc.org/sigs.k8s.io/kustomize/kyaml/kio#LocalPackageWriter)
49+
// so that the same will write files back to their original
50+
// location. The implementation follows that of
51+
// [LocalPackageReader.Read](https://godoc.org/sigs.k8s.io/kustomize/kyaml/kio#LocalPackageReader.Read),
52+
// adapting lightly (mainly to leave features out).
53+
func (r *ScreeningLocalReader) Read() ([]*yaml.RNode, error) {
54+
if r.Path == "" {
55+
return nil, fmt.Errorf("must supply path to scan for files")
56+
}
57+
58+
root, err := filepath.Abs(r.Path)
59+
if err != nil {
60+
return nil, fmt.Errorf("path field cannot be made absolute: %w", err)
61+
}
62+
63+
// For the filename annotation, I want a directory for filenames
64+
// to be relative to; but I don't know whether path is a directory
65+
// or file yetm so this must wait until the body of the filepath.Walk.
66+
var relativePath string
67+
68+
tokenbytes := []byte(r.Token)
69+
70+
var result []*yaml.RNode
71+
err = filepath.Walk(root, func(p string, info os.FileInfo, err error) error {
72+
if err != nil {
73+
return fmt.Errorf("walking path for files: %w", err)
74+
}
75+
76+
if p == root {
77+
if info.IsDir() {
78+
relativePath = p
79+
return nil // keep walking
80+
}
81+
relativePath = filepath.Dir(p)
82+
}
83+
84+
if info.IsDir() {
85+
return nil
86+
}
87+
88+
if ext := filepath.Ext(p); ext != ".yaml" && ext != ".yml" {
89+
return nil
90+
}
91+
92+
// To check for the token, I need the file contents. This
93+
// assumes the file is encoded as UTF8.
94+
filebytes, err := ioutil.ReadFile(p)
95+
if err != nil {
96+
return fmt.Errorf("reading YAML file: %w", err)
97+
}
98+
99+
if !bytes.Contains(filebytes, tokenbytes) {
100+
return nil
101+
}
102+
103+
path, err := filepath.Rel(relativePath, p)
104+
if err != nil {
105+
return fmt.Errorf("relativising path: %w", err)
106+
}
107+
annotations := map[string]string{
108+
kioutil.PathAnnotation: path,
109+
}
110+
111+
rdr := &kio.ByteReader{
112+
Reader: bytes.NewBuffer(filebytes),
113+
SetAnnotations: annotations,
114+
}
115+
116+
nodes, err := rdr.Read()
117+
// Having screened the file and decided it's worth examining,
118+
// an error at this point is most unfortunate. However, it
119+
// doesn't need to be the end of the matter; we can record
120+
// this file as problematic, and continue.
121+
if err != nil {
122+
r.ProblemFiles = append(r.ProblemFiles, path)
123+
return nil
124+
}
125+
result = append(result, nodes...)
126+
return nil
127+
})
128+
129+
return result, err
130+
}

pkg/update/filereader_test.go

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/*
2+
Copyright 2020, 2021 The Flux authors
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package update
18+
19+
import (
20+
. "github.com/onsi/ginkgo"
21+
. "github.com/onsi/gomega"
22+
"sigs.k8s.io/kustomize/kyaml/kio/kioutil"
23+
)
24+
25+
var _ = Describe("load YAMLs with ScreeningLocalReader", func() {
26+
It("loads only the YAMLs containing the token", func() {
27+
r := ScreeningLocalReader{
28+
Path: "testdata/setters/original",
29+
Token: "$imagepolicy",
30+
}
31+
nodes, err := r.Read()
32+
Expect(err).ToNot(HaveOccurred())
33+
// the test fixture has three files that contain the marker:
34+
// - otherns.yaml
35+
// - marked.yaml
36+
// - kustomization.yaml
37+
Expect(len(nodes)).To(Equal(3))
38+
filesSeen := map[string]struct{}{}
39+
for i := range nodes {
40+
path, _, err := kioutil.GetFileAnnotations(nodes[i])
41+
Expect(err).ToNot(HaveOccurred())
42+
filesSeen[path] = struct{}{}
43+
}
44+
Expect(filesSeen).To(Equal(map[string]struct{}{
45+
"marked.yaml": struct{}{},
46+
"kustomization.yaml": struct{}{},
47+
"otherns.yaml": struct{}{},
48+
}))
49+
})
50+
})

pkg/update/setters.go

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,19 @@
1+
/*
2+
Copyright 2020, 2021 The Flux authors
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
117
package update
218

319
import (
@@ -36,6 +52,9 @@ func resetSchema() {
3652
openapi.SuppressBuiltInSchemaUse()
3753
}
3854

55+
// UpdateWithSetters takes all YAML files from `inpath`, updates any
56+
// that contain an "in scope" image policy marker, and writes files it
57+
// updated (and only those files) back to `outpath`.
3958
func UpdateWithSetters(inpath, outpath string, policies []imagev1alpha1_reflect.ImagePolicy) error {
4059
// the OpenAPI schema is a package variable in kyaml/openapi. In
4160
// lieu of being able to isolate invocations (per
@@ -104,9 +123,9 @@ func UpdateWithSetters(inpath, outpath string, policies []imagev1alpha1_reflect.
104123
}
105124

106125
// get ready with the reader and writer
107-
reader := &kio.LocalPackageReader{
108-
PackagePath: inpath,
109-
IncludeSubpackages: true,
126+
reader := &ScreeningLocalReader{
127+
Path: inpath,
128+
Token: fmt.Sprintf("%q", SetterShortHand),
110129
}
111130
writer := &kio.LocalPackageWriter{
112131
PackagePath: outpath,
@@ -115,7 +134,12 @@ func UpdateWithSetters(inpath, outpath string, policies []imagev1alpha1_reflect.
115134
pipeline := kio.Pipeline{
116135
Inputs: []kio.Reader{reader},
117136
Outputs: []kio.Writer{writer},
118-
Filters: []kio.Filter{kio.FilterAll(&setters2.Set{SetAll: true})},
137+
Filters: []kio.Filter{
138+
setters2.SetAll( // run the enclosed single-node setters2.Filter on all nodes,
139+
// and only include those in files that changed in the output
140+
&setters2.Set{SetAll: true}, // set all images that are in the constructed schema
141+
),
142+
},
119143
}
120144

121145
// go!

pkg/update/testdata/setters/expected/otherns.yaml

Lines changed: 0 additions & 11 deletions
This file was deleted.

pkg/update/testdata/setters/expected/unmarked.yaml

Lines changed: 0 additions & 11 deletions
This file was deleted.

pkg/update/update_test.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,19 @@
1+
/*
2+
Copyright 2020, 2021 The Flux authors
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
117
package update
218

319
import (

0 commit comments

Comments
 (0)