github.com/splunk/dan1-qbec@v0.7.3/internal/model/app_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 model 18 19 import ( 20 "bytes" 21 "os" 22 "path/filepath" 23 "testing" 24 25 "github.com/splunk/qbec/internal/sio" 26 "github.com/stretchr/testify/assert" 27 "github.com/stretchr/testify/require" 28 ) 29 30 func setPwd(t *testing.T, dir string) func() { 31 wd, err := os.Getwd() 32 require.Nil(t, err) 33 p, err := filepath.Abs(dir) 34 require.Nil(t, err) 35 err = os.Chdir(p) 36 require.Nil(t, err) 37 return func() { 38 err = os.Chdir(wd) 39 require.Nil(t, err) 40 } 41 } 42 43 func TestAppSimple(t *testing.T) { 44 reset := setPwd(t, "../../examples/test-app") 45 defer reset() 46 app, err := NewApp("qbec.yaml", "") 47 require.Nil(t, err) 48 a := assert.New(t) 49 a.Equal("example1", app.Name()) 50 a.Equal(2, len(app.inner.Spec.Environments)) 51 a.Contains(app.inner.Spec.Environments, "dev") 52 a.Contains(app.inner.Spec.Environments, "prod") 53 a.Equal(4, len(app.allComponents)) 54 a.Equal(3, len(app.defaultComponents)) 55 a.Contains(app.allComponents, "service2") 56 a.NotContains(app.defaultComponents, "service2") 57 58 comps, err := app.ComponentsForEnvironment("_", nil, nil) 59 require.Nil(t, err) 60 require.Equal(t, 3, len(comps)) 61 a.Equal("cluster-objects", comps[0].Name) 62 a.Equal("service1", comps[1].Name) 63 a.Equal("test-job", comps[2].Name) 64 65 comps, err = app.ComponentsForEnvironment("dev", nil, nil) 66 require.Nil(t, err) 67 require.Equal(t, 3, len(comps)) 68 a.Equal("cluster-objects", comps[0].Name) 69 a.Equal("service2", comps[1].Name) 70 a.Equal("test-job", comps[2].Name) 71 72 comps, err = app.ComponentsForEnvironment("prod", nil, nil) 73 require.Nil(t, err) 74 require.Equal(t, 4, len(comps)) 75 a.Equal("cluster-objects", comps[0].Name) 76 a.Equal("service1", comps[1].Name) 77 a.Equal("service2", comps[2].Name) 78 a.Equal("test-job", comps[3].Name) 79 80 comps, err = app.ComponentsForEnvironment("dev", nil, []string{"service2"}) 81 require.Nil(t, err) 82 require.Equal(t, 2, len(comps)) 83 a.Equal("cluster-objects", comps[0].Name) 84 a.Equal("test-job", comps[1].Name) 85 86 comps, err = app.ComponentsForEnvironment("dev", []string{"service2"}, nil) 87 require.Nil(t, err) 88 require.Equal(t, 1, len(comps)) 89 a.Equal("service2", comps[0].Name) 90 91 comps, err = app.ComponentsForEnvironment("dev", []string{"service1"}, nil) 92 require.Nil(t, err) 93 require.Equal(t, 0, len(comps)) 94 95 a.EqualValues(map[string]interface{}{ 96 "externalFoo": "bar", 97 }, app.DeclaredVars()) 98 99 a.EqualValues(map[string]interface{}{ 100 "tlaFoo": true, 101 }, app.DeclaredTopLevelVars()) 102 103 u, err := app.ServerURL("dev") 104 require.Nil(t, err) 105 a.Equal("https://dev-server", u) 106 a.Equal("default", app.DefaultNamespace("dev")) 107 a.Equal("", app.Tag()) 108 109 _, err = app.ServerURL("devx") 110 require.NotNil(t, err) 111 a.Equal(`invalid environment "devx"`, err.Error()) 112 113 a.Equal("params.libsonnet", app.ParamsFile()) 114 a.Equal("pp.jsonnet", app.PostProcessor()) 115 a.EqualValues([]string{"lib"}, app.LibPaths()) 116 } 117 118 func TestAppWarnings(t *testing.T) { 119 o, c := sio.Output, sio.EnableColors 120 defer func() { 121 sio.Output = o 122 sio.EnableColors = c 123 }() 124 sio.EnableColors = false 125 reset := setPwd(t, "./testdata/bad-app") 126 defer reset() 127 app, err := NewApp("app-warn.yaml", "foobar") 128 require.Nil(t, err) 129 130 a := assert.New(t) 131 buf := bytes.NewBuffer(nil) 132 sio.Output = buf 133 comps, err := app.ComponentsForEnvironment("dev", nil, nil) 134 require.Nil(t, err) 135 a.Equal(2, len(comps)) 136 a.Contains(buf.String(), "component b included from dev is already included by default") 137 138 buf = bytes.NewBuffer(nil) 139 sio.Output = buf 140 _, err = app.ComponentsForEnvironment("prod", nil, nil) 141 require.Nil(t, err) 142 a.Contains(buf.String(), "[warn] component a excluded from prod is already excluded by default") 143 144 a.Equal("foobar", app.Tag()) 145 a.Equal("default-foobar", app.DefaultNamespace("dev")) 146 } 147 148 func TestAppComponentLoadNegative(t *testing.T) { 149 reset := setPwd(t, "../../examples/test-app") 150 defer reset() 151 app, err := NewApp("qbec.yaml", "") 152 require.Nil(t, err) 153 a := assert.New(t) 154 155 _, err = app.ComponentsForEnvironment("stage", nil, nil) 156 require.NotNil(t, err) 157 a.Equal(`invalid environment "stage"`, err.Error()) 158 159 _, err = app.ComponentsForEnvironment("dev", []string{"d"}, nil) 160 require.NotNil(t, err) 161 a.Equal(`specified components: bad component reference(s): d`, err.Error()) 162 163 _, err = app.ComponentsForEnvironment("dev", nil, []string{"d"}) 164 require.NotNil(t, err) 165 a.Equal(`specified components: bad component reference(s): d`, err.Error()) 166 167 _, err = app.ComponentsForEnvironment("dev", []string{"a"}, []string{"b"}) 168 require.NotNil(t, err) 169 a.Equal(`cannot include as well as exclude components, specify one or the other`, err.Error()) 170 } 171 172 func TestAppNegative(t *testing.T) { 173 reset := setPwd(t, "./testdata/bad-app") 174 defer reset() 175 176 tests := []struct { 177 tag string 178 file string 179 asserter func(t *testing.T, err error) 180 }{ 181 { 182 file: "non-existent.yaml", 183 asserter: func(t *testing.T, err error) { 184 assert.Contains(t, err.Error(), "no such file or directory") 185 }, 186 }, 187 { 188 file: "bad-yaml.yaml", 189 asserter: func(t *testing.T, err error) { 190 assert.Contains(t, err.Error(), "converting YAML to JSON") 191 }, 192 }, 193 { 194 file: "bad-comp-exclude.yaml", 195 asserter: func(t *testing.T, err error) { 196 assert.Contains(t, err.Error(), "default exclusions: bad component reference(s): d") 197 }, 198 }, 199 { 200 file: "bad-env-exclude.yaml", 201 asserter: func(t *testing.T, err error) { 202 assert.Contains(t, err.Error(), "dev exclusions: bad component reference(s): d") 203 }, 204 }, 205 { 206 file: "bad-env-include.yaml", 207 asserter: func(t *testing.T, err error) { 208 assert.Contains(t, err.Error(), "dev inclusions: bad component reference(s): d") 209 }, 210 }, 211 { 212 file: "bad-env-include-exclude.yaml", 213 asserter: func(t *testing.T, err error) { 214 assert.Contains(t, err.Error(), "env dev: component c present in both include and exclude sections") 215 }, 216 }, 217 { 218 file: "bad-baseline-env.yaml", 219 asserter: func(t *testing.T, err error) { 220 assert.Contains(t, err.Error(), "cannot use _ as an environment name since it has a special meaning") 221 }, 222 }, 223 { 224 file: "bad-comps.yaml", 225 asserter: func(t *testing.T, err error) { 226 assert.Contains(t, err.Error(), "duplicate component a, found bad-comps/a.json and bad-comps/a.yaml") 227 }, 228 }, 229 { 230 file: "bad-app-name.yaml", 231 asserter: func(t *testing.T, err error) { 232 assert.Contains(t, err.Error(), "metadata.name in body should match") 233 }, 234 }, 235 { 236 file: "bad-env-name.yaml", 237 asserter: func(t *testing.T, err error) { 238 assert.Contains(t, err.Error(), "invalid environment foo/bar, must match") 239 }, 240 }, 241 { 242 file: "bad-dup-tla.yaml", 243 asserter: func(t *testing.T, err error) { 244 assert.Contains(t, err.Error(), "duplicate top-level variable foo") 245 }, 246 }, 247 { 248 file: "bad-dup-ext.yaml", 249 asserter: func(t *testing.T, err error) { 250 assert.Contains(t, err.Error(), "duplicate external variable foo") 251 }, 252 }, 253 { 254 file: "app-warn.yaml", 255 tag: "-foobar", 256 asserter: func(t *testing.T, err error) { 257 assert.Contains(t, err.Error(), "invalid tag name '-foobar', must match") 258 }, 259 }, 260 } 261 262 for _, test := range tests { 263 t.Run(test.file, func(t *testing.T) { 264 _, err := NewApp(test.file, test.tag) 265 require.NotNil(t, err) 266 test.asserter(t, err) 267 }) 268 } 269 }