github.com/splunk/dan1-qbec@v0.7.3/internal/commands/validate_test.go (about) 1 /* 2 Copyright 2019 Splunk Inc. 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 commands 18 19 import ( 20 "fmt" 21 "regexp" 22 "testing" 23 24 "github.com/splunk/qbec/internal/remote/k8smeta" 25 "github.com/stretchr/testify/assert" 26 "github.com/stretchr/testify/require" 27 "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" 28 "k8s.io/apimachinery/pkg/runtime/schema" 29 ) 30 31 type v struct{} 32 33 func (v *v) Validate(obj *unstructured.Unstructured) []error { 34 if obj.GetName() == "svc2-cm" { 35 return []error{fmt.Errorf("bad config map")} 36 } 37 return nil 38 } 39 40 func factory(gvk schema.GroupVersionKind) (k8smeta.Validator, error) { 41 if gvk.Kind == "PodSecurityPolicy" { 42 return nil, k8smeta.ErrSchemaNotFound 43 } 44 return &v{}, nil 45 } 46 47 func TestValidateAll(t *testing.T) { 48 s := newScaffold(t) 49 defer s.reset() 50 s.client.validatorFunc = factory 51 err := s.executeCommand("validate", "dev") 52 require.NotNil(t, err) 53 s.assertOutputLineMatch(regexp.MustCompile(`✔ ClusterRole::allow-root-psp-policy is valid`)) 54 s.assertOutputLineMatch(regexp.MustCompile(`\? PodSecurityPolicy::100-default: no schema found, cannot validate`)) 55 s.assertOutputLineMatch(regexp.MustCompile(`✘ ConfigMap:bar-system:svc2-cm is invalid`)) 56 s.assertOutputLineMatch(regexp.MustCompile(`- bad config map`)) 57 } 58 59 func TestValidateSilent(t *testing.T) { 60 s := newScaffold(t) 61 defer s.reset() 62 s.client.validatorFunc = factory 63 err := s.executeCommand("validate", "dev", "--silent") 64 require.NotNil(t, err) 65 s.assertOutputLineNoMatch(regexp.MustCompile(`✔ ClusterRole::allow-root-psp-policy is valid`)) 66 s.assertOutputLineNoMatch(regexp.MustCompile(`\? PodSecurityPolicy::100-default: no schema found, cannot validate`)) 67 s.assertOutputLineMatch(regexp.MustCompile(`✘ ConfigMap:bar-system:svc2-cm is invalid`)) 68 s.assertOutputLineMatch(regexp.MustCompile(`- bad config map`)) 69 } 70 71 func TestValidateNegative(t *testing.T) { 72 tests := []struct { 73 name string 74 args []string 75 init func(s *scaffold) 76 asserter func(s *scaffold, err error) 77 dir string 78 }{ 79 { 80 name: "no env", 81 args: []string{"validate"}, 82 asserter: func(s *scaffold, err error) { 83 a := assert.New(s.t) 84 a.True(isUsageError(err)) 85 a.Equal("exactly one environment required", err.Error()) 86 }, 87 }, 88 { 89 name: "2 envs", 90 args: []string{"validate", "dev", "prod"}, 91 asserter: func(s *scaffold, err error) { 92 a := assert.New(s.t) 93 a.True(isUsageError(err)) 94 a.Equal("exactly one environment required", err.Error()) 95 }, 96 }, 97 { 98 name: "bad env", 99 args: []string{"validate", "foo"}, 100 asserter: func(s *scaffold, err error) { 101 a := assert.New(s.t) 102 a.False(isUsageError(err)) 103 a.Equal(`invalid environment "foo"`, err.Error()) 104 }, 105 }, 106 { 107 name: "bad component", 108 args: []string{"validate", "dev", "-c", "foo"}, 109 asserter: func(s *scaffold, err error) { 110 a := assert.New(s.t) 111 a.False(isUsageError(err)) 112 a.Equal(`specified components: bad component reference(s): foo`, err.Error()) 113 }, 114 }, 115 { 116 name: "bad filters", 117 args: []string{"validate", "dev", "-c", "svc1-cm", "-C", "svc2-cm"}, 118 asserter: func(s *scaffold, err error) { 119 a := assert.New(s.t) 120 a.True(isUsageError(err)) 121 a.Equal(`cannot include as well as exclude components, specify one or the other`, err.Error()) 122 }, 123 }, 124 { 125 name: "duplicate objects", 126 dir: "testdata/dups", 127 args: []string{"validate", "dev"}, 128 asserter: func(s *scaffold, err error) { 129 a := assert.New(s.t) 130 a.True(IsRuntimeError(err)) 131 a.Equal(`duplicate objects ConfigMap cm1 (component: x) and ConfigMap cm1 (component: y)`, err.Error()) 132 }, 133 }, 134 { 135 name: "duplicate objects even with filters", 136 dir: "testdata/dups", 137 args: []string{"validate", "dev", "-K", "configmap"}, 138 asserter: func(s *scaffold, err error) { 139 a := assert.New(s.t) 140 a.True(IsRuntimeError(err)) 141 a.Equal(`duplicate objects ConfigMap cm1 (component: x) and ConfigMap cm1 (component: y)`, err.Error()) 142 }, 143 }, 144 { 145 name: "baseline", 146 args: []string{"validate", "_"}, 147 asserter: func(s *scaffold, err error) { 148 a := assert.New(s.t) 149 a.True(isUsageError(err)) 150 a.Equal(`cannot validate baseline environment, use a real environment`, err.Error()) 151 }, 152 }, 153 { 154 name: "errors", 155 args: []string{"validate", "dev"}, 156 init: func(s *scaffold) { 157 s.client.validatorFunc = func(gvk schema.GroupVersionKind) (k8smeta.Validator, error) { 158 return nil, fmt.Errorf("no validator for you") 159 } 160 }, 161 asserter: func(s *scaffold, err error) { 162 a := assert.New(s.t) 163 a.False(isUsageError(err)) 164 a.Contains(err.Error(), "no validator for you") 165 }, 166 }, 167 } 168 169 for _, test := range tests { 170 t.Run(test.name, func(t *testing.T) { 171 s := newCustomScaffold(t, test.dir) 172 defer s.reset() 173 s.client.validatorFunc = factory 174 if test.init != nil { 175 test.init(s) 176 } 177 err := s.executeCommand(test.args...) 178 require.NotNil(t, err) 179 test.asserter(s, err) 180 }) 181 } 182 }