Add tests for CLI flags

This includes various bug fixes, especially around the area of missing
names for `<kind>/<name>` formats.

Signed-off-by: Hidde Beydals <hello@hidde.co>
pull/604/head
Hidde Beydals 4 years ago
parent 3c1793b6c5
commit 996bfe87ff

@ -76,10 +76,10 @@ flux create helmrelease [name] [flags]
-h, --help help for helmrelease
--release-name string name used for the Helm release, defaults to a composition of '[<target-namespace>-]<HelmRelease-name>'
--service-account string the name of the service account to impersonate when reconciling this HelmRelease
--source helmChartSource source that contains the chart in the format '<kind>/<name>',where kind can be one of: (HelmRepository, GitRepository, Bucket)
--source helmChartSource source that contains the chart in the format '<kind>/<name>', where kind must be one of: (HelmRepository, GitRepository, Bucket)
--target-namespace string namespace to install this release, defaults to the HelmRelease namespace
--values string local path to the values.yaml file
--values-from helmReleaseValuesFrom Kubernetes object reference that contains the values.yaml data key in the format '<kind>/<name>',where kind can be one of: (Secret, ConfigMap)
--values-from helmReleaseValuesFrom Kubernetes object reference that contains the values.yaml data key in the format '<kind>/<name>', where kind must be one of: (Secret, ConfigMap)
```
### Options inherited from parent commands

@ -53,7 +53,7 @@ flux create kustomization [name] [flags]
--path safeRelativePath path to the directory containing a kustomization.yaml file (default ./)
--prune enable garbage collection
--service-account string the name of the service account to impersonate when reconciling this Kustomization
--source kustomizationSource source that contains the Kubernetes manifests in the format '[<kind>/]<name>',where kind can be one of: (GitRepository, Bucket), if kind is not specified it defaults to GitRepository
--source kustomizationSource source that contains the Kubernetes manifests in the format '[<kind>/]<name>', where kind must be one of: (GitRepository, Bucket), if kind is not specified it defaults to GitRepository
--target-namespace string overrides the namespace of all Kustomization objects reconciled by this Kustomization
--validation string validate the manifests before applying them on the cluster, can be 'client' or 'server'
```

@ -0,0 +1,45 @@
/*
Copyright 2020 The Flux authors
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 flags
import (
"testing"
)
func TestArch_Set(t *testing.T) {
tests := []struct {
name string
str string
expect string
expectErr bool
}{
{"supported", "amd64", "amd64", false},
{"unsupported", "unsupported", "", true},
{"empty", "", "", true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
var a Arch
if err := a.Set(tt.str); (err != nil) != tt.expectErr {
t.Errorf("Set() error = %v, expectErr %v", err, tt.expectErr)
}
if str := a.String(); str != tt.expect {
t.Errorf("Set() = %v, expect %v", str, tt.expect)
}
})
}
}

@ -32,6 +32,10 @@ func (d *DecryptionProvider) String() string {
}
func (d *DecryptionProvider) Set(str string) error {
if strings.TrimSpace(str) == "" {
return fmt.Errorf("no decryption provider given, must be one of: %s",
strings.Join(supportedDecryptionProviders, ", "))
}
if !utils.ContainsItemString(supportedDecryptionProviders, str) {
return fmt.Errorf("unsupported decryption provider '%s', must be one of: %s",
str, strings.Join(supportedDecryptionProviders, ", "))

@ -0,0 +1,45 @@
/*
Copyright 2020 The Flux authors
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 flags
import (
"testing"
)
func TestDecryptionProvider_Set(t *testing.T) {
tests := []struct {
name string
str string
expect string
expectErr bool
}{
{"supported", "sops", "sops", false},
{"unsupported", "unsupported", "", true},
{"empty", "", "", true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
var p DecryptionProvider
if err := p.Set(tt.str); (err != nil) != tt.expectErr {
t.Errorf("Set() error = %v, expectErr %v", err, tt.expectErr)
}
if str := p.String(); str != tt.expect {
t.Errorf("Set() = %v, expect %v", str, tt.expect)
}
})
}
}

@ -45,7 +45,7 @@ func (c *ECDSACurve) Set(str string) error {
*c = ECDSACurve{v}
return nil
}
return fmt.Errorf("unsupported curve '%s', should be one of: %s", str, strings.Join(ecdsaCurves(), ", "))
return fmt.Errorf("unsupported curve '%s', must be one of: %s", str, strings.Join(ecdsaCurves(), ", "))
}
func (c *ECDSACurve) Type() string {

@ -0,0 +1,45 @@
/*
Copyright 2020 The Flux authors
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 flags
import (
"testing"
)
func TestECDSACurve_Set(t *testing.T) {
tests := []struct {
name string
str string
expect string
expectErr bool
}{
{"supported", "p256", "p256", false},
{"unsupported", "unsupported", "", true},
{"empty", "", "", true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
var c ECDSACurve
if err := c.Set(tt.str); (err != nil) != tt.expectErr {
t.Errorf("Set() error = %v, expectErr %v", err, tt.expectErr)
}
if str := c.String(); str != tt.expect {
t.Errorf("Set() = %v, expect %v", str, tt.expect)
}
})
}
}

@ -31,42 +31,42 @@ type HelmChartSource struct {
Name string
}
func (h *HelmChartSource) String() string {
if h.Name == "" {
func (s *HelmChartSource) String() string {
if s.Name == "" {
return ""
}
return fmt.Sprintf("%s/%s", h.Kind, h.Name)
return fmt.Sprintf("%s/%s", s.Kind, s.Name)
}
func (h *HelmChartSource) Set(str string) error {
func (s *HelmChartSource) Set(str string) error {
if strings.TrimSpace(str) == "" {
return fmt.Errorf("no helm chart source given, please specify %s",
h.Description())
s.Description())
}
sourceKind, sourceName := utils.ParseObjectKindName(str)
if sourceKind == "" {
if sourceKind == "" || sourceName == "" {
return fmt.Errorf("invalid helm chart source '%s', must be in format <kind>/<name>", str)
}
if !utils.ContainsItemString(supportedHelmChartSourceKinds, sourceKind) {
return fmt.Errorf("source kind '%s' is not supported, can be one of: %s",
return fmt.Errorf("source kind '%s' is not supported, must be one of: %s",
sourceKind, strings.Join(supportedHelmChartSourceKinds, ", "))
}
h.Name = sourceName
h.Kind = sourceKind
s.Name = sourceName
s.Kind = sourceKind
return nil
}
func (h *HelmChartSource) Type() string {
func (s *HelmChartSource) Type() string {
return "helmChartSource"
}
func (h *HelmChartSource) Description() string {
func (s *HelmChartSource) Description() string {
return fmt.Sprintf(
"source that contains the chart in the format '<kind>/<name>',"+
"where kind can be one of: (%s)",
"source that contains the chart in the format '<kind>/<name>', "+
"where kind must be one of: (%s)",
strings.Join(supportedHelmChartSourceKinds, ", "),
)
}

@ -0,0 +1,50 @@
/*
Copyright 2020 The Flux authors
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 flags
import (
"fmt"
"testing"
sourcev1 "github.com/fluxcd/source-controller/api/v1beta1"
)
func TestHelmChartSource_Set(t *testing.T) {
tests := []struct {
name string
str string
expect string
expectErr bool
}{
{"supported", fmt.Sprintf("%s/foo", sourcev1.HelmRepositoryKind), fmt.Sprintf("%s/foo", sourcev1.HelmRepositoryKind), false},
{"unsupported", "Unsupported/kind", "", true},
{"invalid format", sourcev1.HelmRepositoryKind, "", true},
{"missing name", fmt.Sprintf("%s/", sourcev1.HelmRepositoryKind), "", true},
{"empty", "", "", true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
var s HelmChartSource
if err := s.Set(tt.str); (err != nil) != tt.expectErr {
t.Errorf("Set() error = %v, expectErr %v", err, tt.expectErr)
}
if str := s.String(); str != tt.expect {
t.Errorf("Set() = %v, expect %v", str, tt.expect)
}
})
}
}

@ -30,17 +30,17 @@ type HelmReleaseValuesFrom struct {
Name string
}
func (h *HelmReleaseValuesFrom) String() string {
if h.Name == "" {
func (v *HelmReleaseValuesFrom) String() string {
if v.Name == "" {
return ""
}
return fmt.Sprintf("%s/%s", h.Kind, h.Name)
return fmt.Sprintf("%s/%s", v.Kind, v.Name)
}
func (h *HelmReleaseValuesFrom) Set(str string) error {
func (v *HelmReleaseValuesFrom) Set(str string) error {
if strings.TrimSpace(str) == "" {
return fmt.Errorf("no values given, please specify %s",
h.Description())
v.Description())
}
sourceKind, sourceName := utils.ParseObjectKindName(str)
@ -48,24 +48,24 @@ func (h *HelmReleaseValuesFrom) Set(str string) error {
return fmt.Errorf("invalid Kubernetes object reference '%s', must be in format <kind>/<name>", str)
}
if !utils.ContainsItemString(supportedHelmReleaseValuesFromKinds, sourceKind) {
return fmt.Errorf("reference kind '%s' is not supported, can be one of: %s",
return fmt.Errorf("reference kind '%s' is not supported, must be one of: %s",
sourceKind, strings.Join(supportedHelmReleaseValuesFromKinds, ", "))
}
h.Name = sourceName
h.Kind = sourceKind
v.Name = sourceName
v.Kind = sourceKind
return nil
}
func (h *HelmReleaseValuesFrom) Type() string {
func (v *HelmReleaseValuesFrom) Type() string {
return "helmReleaseValuesFrom"
}
func (h *HelmReleaseValuesFrom) Description() string {
func (v *HelmReleaseValuesFrom) Description() string {
return fmt.Sprintf(
"Kubernetes object reference that contains the values.yaml data key in the format '<kind>/<name>',"+
"where kind can be one of: (%s)",
"Kubernetes object reference that contains the values.yaml data key in the format '<kind>/<name>', "+
"where kind must be one of: (%s)",
strings.Join(supportedHelmReleaseValuesFromKinds, ", "),
)
}

@ -0,0 +1,46 @@
/*
Copyright 2020 The Flux authors
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 flags
import (
"testing"
)
func TestHelmReleaseValuesFrom_Set(t *testing.T) {
tests := []struct {
name string
str string
expect string
expectErr bool
}{
{"supported", "Secret/foo", "Secret/foo", false},
{"unsupported", "Unsupported/kind", "", true},
{"invalid format", "Secret", "", true},
{"empty", "", "", true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
var h HelmReleaseValuesFrom
if err := h.Set(tt.str); (err != nil) != tt.expectErr {
t.Errorf("Set() error = %v, expectErr %v", err, tt.expectErr)
}
if str := h.String(); str != tt.expect {
t.Errorf("Set() = %v, expect %v", str, tt.expect)
}
})
}
}

@ -31,42 +31,48 @@ type KustomizationSource struct {
Name string
}
func (k *KustomizationSource) String() string {
if k.Name == "" {
func (s *KustomizationSource) String() string {
if s.Name == "" {
return ""
}
return fmt.Sprintf("%s/%s", k.Kind, k.Name)
return fmt.Sprintf("%s/%s", s.Kind, s.Name)
}
func (k *KustomizationSource) Set(str string) error {
func (s *KustomizationSource) Set(str string) error {
if strings.TrimSpace(str) == "" {
return fmt.Errorf("no kustomization source given, please specify %s",
k.Description())
return fmt.Errorf("no Kustomization source given, please specify %s",
s.Description())
}
sourceKind, sourceName := utils.ParseObjectKindName(str)
if sourceName == "" {
return fmt.Errorf("no name given for source of kind '%s'", sourceKind)
}
if sourceKind == "" {
if utils.ContainsItemString(supportedKustomizationSourceKinds, sourceName) {
return fmt.Errorf("no name given for source of kind '%s'", sourceName)
}
sourceKind = sourcev1.GitRepositoryKind
}
if !utils.ContainsItemString(supportedKustomizationSourceKinds, sourceKind) {
return fmt.Errorf("source kind '%s' is not supported, can be one of: %s",
return fmt.Errorf("source kind '%s' is not supported, must be one of: %s",
sourceKind, strings.Join(supportedKustomizationSourceKinds, ", "))
}
k.Name = sourceName
k.Kind = sourceKind
s.Name = sourceName
s.Kind = sourceKind
return nil
}
func (k *KustomizationSource) Type() string {
func (s *KustomizationSource) Type() string {
return "kustomizationSource"
}
func (k *KustomizationSource) Description() string {
func (s *KustomizationSource) Description() string {
return fmt.Sprintf(
"source that contains the Kubernetes manifests in the format '[<kind>/]<name>',"+
"where kind can be one of: (%s), if kind is not specified it defaults to GitRepository",
"source that contains the Kubernetes manifests in the format '[<kind>/]<name>', "+
"where kind must be one of: (%s), if kind is not specified it defaults to GitRepository",
strings.Join(supportedKustomizationSourceKinds, ", "),
)
}

@ -0,0 +1,50 @@
/*
Copyright 2020 The Flux authors
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 flags
import (
"fmt"
"testing"
sourcev1 "github.com/fluxcd/source-controller/api/v1beta1"
)
func TestKustomizationSource_Set(t *testing.T) {
tests := []struct {
name string
str string
expect string
expectErr bool
}{
{"supported", fmt.Sprintf("%s/foo", sourcev1.GitRepositoryKind), fmt.Sprintf("%s/foo", sourcev1.GitRepositoryKind), false},
{"default kind", "foo", fmt.Sprintf("%s/foo", sourcev1.GitRepositoryKind), false},
{"unsupported", "Unsupported/kind", "", true},
{"missing name", fmt.Sprintf("%s/", sourcev1.GitRepositoryKind), "", true},
{"empty", "", "", true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
var s KustomizationSource
if err := s.Set(tt.str); (err != nil) != tt.expectErr {
t.Errorf("Set() error = %v, expectErr %v", err, tt.expectErr)
}
if str := s.String(); str != tt.expect {
t.Errorf("Set() = %v, expect %v", str, tt.expect)
}
})
}
}

@ -0,0 +1,45 @@
/*
Copyright 2020 The Flux authors
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 flags
import (
"testing"
)
func TestLogLevel_Set(t *testing.T) {
tests := []struct {
name string
str string
expect string
expectErr bool
}{
{"supported", "info", "info", false},
{"unsupported", "unsupported", "", true},
{"empty", "", "", true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
var l LogLevel
if err := l.Set(tt.str); (err != nil) != tt.expectErr {
t.Errorf("Set() error = %v, expectErr %v", err, tt.expectErr)
}
if str := l.String(); str != tt.expect {
t.Errorf("Set() = %v, expect %v", str, tt.expect)
}
})
}
}

@ -0,0 +1,45 @@
/*
Copyright 2020 The Flux authors
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 flags
import (
"testing"
)
func TestPublicKeyAlgorithm_Set(t *testing.T) {
tests := []struct {
name string
str string
expect string
expectErr bool
}{
{"supported", "rsa", "rsa", false},
{"unsupported", "unsupported", "", true},
{"empty", "", "", true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
var a PublicKeyAlgorithm
if err := a.Set(tt.str); (err != nil) != tt.expectErr {
t.Errorf("Set() error = %v, expectErr %v", err, tt.expectErr)
}
if str := a.String(); str != tt.expect {
t.Errorf("Set() = %v, expect %v", str, tt.expect)
}
})
}
}

@ -39,8 +39,8 @@ func (b *RSAKeyBits) Set(str string) error {
if err != nil {
return err
}
if bits%8 != 0 {
return fmt.Errorf("RSA key bit size should be a multiples of 8")
if bits == 0 || bits%8 != 0 {
return fmt.Errorf("RSA key bit size must be a multiples of 8")
}
*b = RSAKeyBits(bits)
return nil

@ -0,0 +1,46 @@
/*
Copyright 2020 The Flux authors
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 flags
import (
"testing"
)
func TestRSAKeyBits_Set(t *testing.T) {
tests := []struct {
name string
str string
expect string
expectErr bool
}{
{"supported", "4096", "4096", false},
{"empty (default)", "", "2048", false},
{"unsupported", "0", "0", true},
{"unsupported", "123", "0", true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
var b RSAKeyBits
if err := b.Set(tt.str); (err != nil) != tt.expectErr {
t.Errorf("Set() error = %v, expectErr %v", err, tt.expectErr)
}
if str := b.String(); str != tt.expect {
t.Errorf("Set() = %v, expect %v", str, tt.expect)
}
})
}
}

@ -28,29 +28,28 @@ var supportedSourceBucketProviders = []string{sourcev1.GenericBucketProvider, so
type SourceBucketProvider string
func (s *SourceBucketProvider) String() string {
return string(*s)
func (p *SourceBucketProvider) String() string {
return string(*p)
}
func (s *SourceBucketProvider) Set(str string) error {
func (p *SourceBucketProvider) Set(str string) error {
if strings.TrimSpace(str) == "" {
return fmt.Errorf("no source bucket provider given, please specify %s",
s.Description())
p.Description())
}
if !utils.ContainsItemString(supportedSourceBucketProviders, str) {
return fmt.Errorf("source bucket provider '%s' is not supported, can be one of: %v",
return fmt.Errorf("source bucket provider '%s' is not supported, must be one of: %v",
str, strings.Join(supportedSourceBucketProviders, ", "))
}
*p = SourceBucketProvider(str)
return nil
}
func (s *SourceBucketProvider) Type() string {
func (p *SourceBucketProvider) Type() string {
return "sourceBucketProvider"
}
func (s *SourceBucketProvider) Description() string {
func (p *SourceBucketProvider) Description() string {
return fmt.Sprintf(
"the S3 compatible storage provider name, available options are: (%s)",
strings.Join(supportedSourceBucketProviders, ", "),

@ -0,0 +1,47 @@
/*
Copyright 2020 The Flux authors
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 flags
import (
"testing"
sourcev1 "github.com/fluxcd/source-controller/api/v1beta1"
)
func TestSourceBucketProvider_Set(t *testing.T) {
tests := []struct {
name string
str string
expect string
expectErr bool
}{
{"supported", sourcev1.GenericBucketProvider, sourcev1.GenericBucketProvider, false},
{"unsupported", "unsupported", "", true},
{"empty", "", "", true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
var s SourceBucketProvider
if err := s.Set(tt.str); (err != nil) != tt.expectErr {
t.Errorf("Set() error = %v, expectErr %v", err, tt.expectErr)
}
if str := s.String(); str != tt.expect {
t.Errorf("Set() = %v, expect %v", str, tt.expect)
}
})
}
}

@ -237,7 +237,6 @@ func ParseObjectKindName(input string) (string, string) {
if len(parts) == 2 {
kind, name = parts[0], parts[1]
}
return kind, name
}

Loading…
Cancel
Save