Skip to content

Commit 47320e9

Browse files
author
Paulo Gomes
authored
Merge pull request #520 from pjbgf/test
Add validation to TargetPath and ValuesKey
2 parents 2195310 + 3cd330c commit 47320e9

File tree

7 files changed

+202
-47
lines changed

7 files changed

+202
-47
lines changed

api/v2beta1/reference_types.go

+6
Original file line numberDiff line numberDiff line change
@@ -59,12 +59,18 @@ type ValuesReference struct {
5959

6060
// ValuesKey is the data key where the values.yaml or a specific value can be
6161
// found at. Defaults to 'values.yaml'.
62+
// When set, must be a valid Data Key, consisting of alphanumeric characters,
63+
// '-', '_' or '.'.
64+
// +kubebuilder:validation:MaxLength=253
65+
// +kubebuilder:validation:Pattern=`^[\-._a-zA-Z0-9]+$`
6266
// +optional
6367
ValuesKey string `json:"valuesKey,omitempty"`
6468

6569
// TargetPath is the YAML dot notation path the value should be merged at. When
6670
// set, the ValuesKey is expected to be a single flat value. Defaults to 'None',
6771
// which results in the values getting merged at the root.
72+
// +kubebuilder:validation:MaxLength=250
73+
// +kubebuilder:validation:Pattern=`^([a-zA-Z0-9_\-.\\\/]|\[[0-9]{1,5}\])+$`
6874
// +optional
6975
TargetPath string `json:"targetPath,omitempty"`
7076

config/crd/bases/helm.toolkit.fluxcd.io_helmreleases.yaml

+6
Original file line numberDiff line numberDiff line change
@@ -697,10 +697,16 @@ spec:
697697
should be merged at. When set, the ValuesKey is expected to
698698
be a single flat value. Defaults to 'None', which results
699699
in the values getting merged at the root.
700+
maxLength: 250
701+
pattern: ^([a-zA-Z0-9_\-.\\\/]|\[[0-9]{1,5}\])+$
700702
type: string
701703
valuesKey:
702704
description: ValuesKey is the data key where the values.yaml
703705
or a specific value can be found at. Defaults to 'values.yaml'.
706+
When set, must be a valid Data Key, consisting of alphanumeric
707+
characters, '-', '_' or '.'.
708+
maxLength: 253
709+
pattern: ^[\-._a-zA-Z0-9]+$
704710
type: string
705711
required:
706712
- kind

controllers/helmrelease_controller_test.go

+168
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,17 @@ package controllers
1919
import (
2020
"context"
2121
"reflect"
22+
"strings"
2223
"testing"
24+
"time"
2325

2426
"github.com/go-logr/logr"
2527
"helm.sh/helm/v3/pkg/chartutil"
2628
corev1 "k8s.io/api/core/v1"
2729
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
2830
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2931
"k8s.io/apimachinery/pkg/runtime"
32+
"sigs.k8s.io/controller-runtime/pkg/client"
3033
"sigs.k8s.io/controller-runtime/pkg/client/fake"
3134
"sigs.k8s.io/yaml"
3235

@@ -278,6 +281,171 @@ invalid`,
278281
}
279282
}
280283

284+
func TestValuesReferenceValidation(t *testing.T) {
285+
tests := []struct {
286+
name string
287+
references []v2.ValuesReference
288+
wantErr bool
289+
}{
290+
{
291+
name: "valid ValuesKey",
292+
references: []v2.ValuesReference{
293+
{
294+
Kind: "Secret",
295+
Name: "values",
296+
ValuesKey: "any-key_na.me",
297+
},
298+
},
299+
wantErr: false,
300+
},
301+
{
302+
name: "valid ValuesKey: empty",
303+
references: []v2.ValuesReference{
304+
{
305+
Kind: "Secret",
306+
Name: "values",
307+
ValuesKey: "",
308+
},
309+
},
310+
wantErr: false,
311+
},
312+
{
313+
name: "valid ValuesKey: long",
314+
references: []v2.ValuesReference{
315+
{
316+
Kind: "Secret",
317+
Name: "values",
318+
ValuesKey: strings.Repeat("a", 253),
319+
},
320+
},
321+
wantErr: false,
322+
},
323+
{
324+
name: "invalid ValuesKey",
325+
references: []v2.ValuesReference{
326+
{
327+
Kind: "Secret",
328+
Name: "values",
329+
ValuesKey: "a($&^%b",
330+
},
331+
},
332+
wantErr: true,
333+
},
334+
{
335+
name: "invalid ValuesKey: too long",
336+
references: []v2.ValuesReference{
337+
{
338+
Kind: "Secret",
339+
Name: "values",
340+
ValuesKey: strings.Repeat("a", 254),
341+
},
342+
},
343+
wantErr: true,
344+
},
345+
{
346+
name: "valid target path: empty",
347+
references: []v2.ValuesReference{
348+
{
349+
Kind: "Secret",
350+
Name: "values",
351+
TargetPath: "",
352+
},
353+
},
354+
wantErr: false,
355+
},
356+
{
357+
name: "valid target path",
358+
references: []v2.ValuesReference{
359+
{
360+
Kind: "Secret",
361+
Name: "values",
362+
TargetPath: "list_with.nested-values.and.index[0]",
363+
},
364+
},
365+
wantErr: false,
366+
},
367+
{
368+
name: "valid target path: long",
369+
references: []v2.ValuesReference{
370+
{
371+
Kind: "Secret",
372+
Name: "values",
373+
TargetPath: strings.Repeat("a", 250),
374+
},
375+
},
376+
wantErr: false,
377+
},
378+
{
379+
name: "invalid target path: too long",
380+
references: []v2.ValuesReference{
381+
{
382+
Kind: "Secret",
383+
Name: "values",
384+
TargetPath: strings.Repeat("a", 251),
385+
},
386+
},
387+
wantErr: true,
388+
},
389+
{
390+
name: "invalid target path: opened index",
391+
references: []v2.ValuesReference{
392+
{
393+
Kind: "Secret",
394+
Name: "values",
395+
ValuesKey: "single",
396+
TargetPath: "a[",
397+
},
398+
},
399+
wantErr: true,
400+
},
401+
{
402+
name: "invalid target path: incorrect index syntax",
403+
references: []v2.ValuesReference{
404+
{
405+
Kind: "Secret",
406+
Name: "values",
407+
ValuesKey: "single",
408+
TargetPath: "a]0[",
409+
},
410+
},
411+
wantErr: true,
412+
},
413+
}
414+
415+
for _, tt := range tests {
416+
t.Run(tt.name, func(t *testing.T) {
417+
var values *apiextensionsv1.JSON
418+
v, _ := yaml.YAMLToJSON([]byte("values"))
419+
values = &apiextensionsv1.JSON{Raw: v}
420+
421+
hr := v2.HelmRelease{
422+
ObjectMeta: metav1.ObjectMeta{
423+
Name: "test",
424+
Namespace: "default",
425+
},
426+
Spec: v2.HelmReleaseSpec{
427+
Interval: metav1.Duration{Duration: 5 * time.Minute},
428+
Chart: v2.HelmChartTemplate{
429+
Spec: v2.HelmChartTemplateSpec{
430+
SourceRef: v2.CrossNamespaceObjectReference{
431+
Name: "something",
432+
},
433+
},
434+
},
435+
ValuesFrom: tt.references,
436+
Values: values,
437+
},
438+
}
439+
440+
err := k8sClient.Create(context.TODO(), &hr, client.DryRunAll)
441+
if (err != nil) != tt.wantErr {
442+
t.Errorf("composeValues() error = %v, wantErr %v", err, tt.wantErr)
443+
return
444+
}
445+
})
446+
}
447+
}
448+
281449
func valuesSecret(name string, data map[string][]byte) *corev1.Secret {
282450
return &corev1.Secret{
283451
ObjectMeta: metav1.ObjectMeta{Name: name},

controllers/suite_test.go

+19-38
Original file line numberDiff line numberDiff line change
@@ -17,67 +17,48 @@ limitations under the License.
1717
package controllers
1818

1919
import (
20+
"fmt"
21+
"os"
2022
"path/filepath"
2123
"testing"
2224

23-
. "github.com/onsi/ginkgo"
24-
. "github.com/onsi/gomega"
25+
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
2526
"k8s.io/client-go/kubernetes/scheme"
2627
"k8s.io/client-go/rest"
2728
"sigs.k8s.io/controller-runtime/pkg/client"
2829
"sigs.k8s.io/controller-runtime/pkg/envtest"
29-
"sigs.k8s.io/controller-runtime/pkg/envtest/printer"
30-
logf "sigs.k8s.io/controller-runtime/pkg/log"
31-
"sigs.k8s.io/controller-runtime/pkg/log/zap"
3230

3331
"github.com/fluxcd/helm-controller/api/v2beta1"
3432
// +kubebuilder:scaffold:imports
3533
)
3634

37-
// These tests use Ginkgo (BDD-style Go testing framework). Refer to
38-
// http://onsi.github.io/ginkgo/ to learn more about Ginkgo.
39-
4035
var cfg *rest.Config
4136
var k8sClient client.Client
4237
var testEnv *envtest.Environment
4338

44-
func TestAPIs(t *testing.T) {
45-
RegisterFailHandler(Fail)
46-
47-
RunSpecsWithDefaultAndCustomReporters(t,
48-
"Controller Suite",
49-
[]Reporter{printer.NewlineReporter{}})
50-
}
51-
52-
var _ = BeforeSuite(func(done Done) {
53-
logf.SetLogger(
54-
zap.New(zap.WriteTo(GinkgoWriter), zap.UseDevMode(true)),
55-
)
56-
57-
By("bootstrapping test environment")
39+
func TestMain(m *testing.M) {
5840
testEnv = &envtest.Environment{
5941
CRDDirectoryPaths: []string{filepath.Join("..", "config", "crd", "bases")},
6042
}
6143

6244
var err error
6345
cfg, err = testEnv.Start()
64-
Expect(err).ToNot(HaveOccurred())
65-
Expect(cfg).ToNot(BeNil())
66-
67-
err = v2beta1.AddToScheme(scheme.Scheme)
68-
Expect(err).NotTo(HaveOccurred())
69-
70-
// +kubebuilder:scaffold:scheme
46+
if err != nil {
47+
panic(fmt.Errorf("failed to start testenv: %v", err))
48+
}
7149

50+
utilruntime.Must(v2beta1.AddToScheme(scheme.Scheme))
7251
k8sClient, err = client.New(cfg, client.Options{Scheme: scheme.Scheme})
73-
Expect(err).ToNot(HaveOccurred())
74-
Expect(k8sClient).ToNot(BeNil())
52+
if err != nil {
53+
panic(fmt.Errorf("failed to create k8s client: %v", err))
54+
}
7555

76-
close(done)
77-
}, 60)
56+
code := m.Run()
7857

79-
var _ = AfterSuite(func() {
80-
By("tearing down the test environment")
81-
err := testEnv.Stop()
82-
Expect(err).ToNot(HaveOccurred())
83-
})
58+
err = testEnv.Stop()
59+
if err != nil {
60+
panic(fmt.Errorf("failed to stop testenv: %v", err))
61+
}
62+
63+
os.Exit(code)
64+
}

docs/api/helmrelease.md

+3-1
Original file line numberDiff line numberDiff line change
@@ -2092,7 +2092,9 @@ string
20922092
<td>
20932093
<em>(Optional)</em>
20942094
<p>ValuesKey is the data key where the values.yaml or a specific value can be
2095-
found at. Defaults to &lsquo;values.yaml&rsquo;.</p>
2095+
found at. Defaults to &lsquo;values.yaml&rsquo;.
2096+
When set, must be a valid Data Key, consisting of alphanumeric characters,
2097+
&lsquo;-&rsquo;, &lsquo;_&rsquo; or &lsquo;.&rsquo;.</p>
20962098
</td>
20972099
</tr>
20982100
<tr>

go.mod

-3
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ require (
1313
github.com/fluxcd/source-controller/api v0.25.9
1414
github.com/go-logr/logr v1.2.3
1515
github.com/hashicorp/go-retryablehttp v0.7.1
16-
github.com/onsi/ginkgo v1.16.5
1716
github.com/onsi/gomega v1.19.0
1817
github.com/spf13/pflag v1.0.5
1918
helm.sh/helm/v3 v3.9.0
@@ -120,7 +119,6 @@ require (
120119
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect
121120
github.com/morikuni/aec v1.0.0 // indirect
122121
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
123-
github.com/nxadm/tail v1.4.8 // indirect
124122
github.com/opencontainers/go-digest v1.0.0 // indirect
125123
github.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799 // indirect
126124
github.com/peterbourgon/diskv v2.0.1+incompatible // indirect
@@ -157,7 +155,6 @@ require (
157155
google.golang.org/grpc v1.43.0 // indirect
158156
google.golang.org/protobuf v1.28.0 // indirect
159157
gopkg.in/inf.v0 v0.9.1 // indirect
160-
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
161158
gopkg.in/yaml.v2 v2.4.0 // indirect
162159
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
163160
k8s.io/apiserver v0.24.1 // indirect

go.sum

-5
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,6 @@ github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG
259259
github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs=
260260
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
261261
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
262-
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
263262
github.com/gobuffalo/logger v1.0.6 h1:nnZNpxYo0zx+Aj9RfMPBm+x9zAU2OayFh/xrAWi34HU=
264263
github.com/gobuffalo/logger v1.0.6/go.mod h1:J31TBEHR1QLV2683OXTAItYIg8pv2JMHnF/quuAbMjs=
265264
github.com/gobuffalo/packd v1.0.1 h1:U2wXfRr4E9DH8IdsDLlRFwTZTK7hLfq9qT/QHXGVe/0=
@@ -550,7 +549,6 @@ github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+
550549
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
551550
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
552551
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
553-
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
554552
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
555553
github.com/olekukonko/tablewriter v0.0.4/go.mod h1:zq6QwlOf5SlnkVbMSr5EoBv3636FWnp+qbPhuoO21uA=
556554
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
@@ -559,7 +557,6 @@ github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+W
559557
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
560558
github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
561559
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
562-
github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
563560
github.com/onsi/ginkgo/v2 v2.1.3 h1:e/3Cwtogj0HA+25nMP1jCMDIf8RtRYbGwGGuBIFztkc=
564561
github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
565562
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
@@ -933,7 +930,6 @@ golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7w
933930
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
934931
golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
935932
golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
936-
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
937933
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
938934
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
939935
golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -1034,7 +1030,6 @@ golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82u
10341030
golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
10351031
golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
10361032
golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
1037-
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
10381033
golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
10391034
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
10401035
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=

0 commit comments

Comments
 (0)