github.com/sleungcy-sap/cli@v7.1.0+incompatible/util/manifestparser/parser_test.go (about) 1 package manifestparser_test 2 3 import ( 4 "errors" 5 "io/ioutil" 6 "os" 7 "path/filepath" 8 9 "gopkg.in/yaml.v2" 10 11 . "code.cloudfoundry.org/cli/util/manifestparser" 12 13 "github.com/cloudfoundry/bosh-cli/director/template" 14 . "github.com/onsi/ginkgo" 15 . "github.com/onsi/gomega" 16 ) 17 18 var _ = Describe("ManifestParser", func() { 19 var parser ManifestParser 20 21 Describe("InterpolateAndParse", func() { 22 var ( 23 pathToManifest string 24 pathsToVarsFiles []string 25 vars []template.VarKV 26 27 executeErr error 28 parsedManifest Manifest 29 30 rawManifest []byte 31 ) 32 33 BeforeEach(func() { 34 tempFile, err := ioutil.TempFile("", "manifest-test-") 35 Expect(err).ToNot(HaveOccurred()) 36 Expect(tempFile.Close()).ToNot(HaveOccurred()) 37 pathToManifest = tempFile.Name() 38 vars = nil 39 40 pathsToVarsFiles = nil 41 }) 42 43 AfterEach(func() { 44 Expect(os.RemoveAll(pathToManifest)).ToNot(HaveOccurred()) 45 for _, path := range pathsToVarsFiles { 46 Expect(os.RemoveAll(path)).ToNot(HaveOccurred()) 47 } 48 }) 49 50 JustBeforeEach(func() { 51 parsedManifest, executeErr = parser.InterpolateAndParse(pathToManifest, pathsToVarsFiles, vars) 52 }) 53 54 When("the manifest does *not* need interpolation", func() { 55 BeforeEach(func() { 56 rawManifest = []byte(`--- 57 applications: 58 - name: spark 59 - name: flame 60 `) 61 err := ioutil.WriteFile(pathToManifest, rawManifest, 0666) 62 Expect(err).ToNot(HaveOccurred()) 63 }) 64 65 It("parses the manifest properly", func() { 66 Expect(executeErr).ToNot(HaveOccurred()) 67 68 Expect(parsedManifest).To(Equal(Manifest{ 69 PathToManifest: pathToManifest, 70 Applications: []Application{ 71 {Name: "spark", RemainingManifestFields: map[string]interface{}{}}, 72 {Name: "flame", RemainingManifestFields: map[string]interface{}{}}, 73 }, 74 })) 75 }) 76 }) 77 78 When("the manifest does not contain applications", func() { 79 BeforeEach(func() { 80 rawManifest = []byte(`--- 81 applications: 82 `) 83 err := ioutil.WriteFile(pathToManifest, rawManifest, 0666) 84 Expect(err).ToNot(HaveOccurred()) 85 }) 86 87 It("returns an error", func() { 88 Expect(executeErr).To(HaveOccurred()) 89 Expect(executeErr).To(MatchError(errors.New("Manifest must have at least one application."))) 90 }) 91 92 }) 93 94 When("the manifest contains variables that need interpolation", func() { 95 BeforeEach(func() { 96 rawManifest = []byte(`--- 97 applications: 98 - name: ((var1)) 99 - name: ((var2)) 100 `) 101 err := ioutil.WriteFile(pathToManifest, rawManifest, 0666) 102 Expect(err).ToNot(HaveOccurred()) 103 }) 104 105 When("only vars files are provided", func() { 106 var ( 107 varsDir string 108 ) 109 110 BeforeEach(func() { 111 var err error 112 varsDir, err = ioutil.TempDir("", "vars-test") 113 Expect(err).ToNot(HaveOccurred()) 114 115 varsFilePath1 := filepath.Join(varsDir, "vars-1") 116 err = ioutil.WriteFile(varsFilePath1, []byte("var1: spark"), 0666) 117 Expect(err).ToNot(HaveOccurred()) 118 119 varsFilePath2 := filepath.Join(varsDir, "vars-2") 120 err = ioutil.WriteFile(varsFilePath2, []byte("var2: flame"), 0666) 121 Expect(err).ToNot(HaveOccurred()) 122 123 pathsToVarsFiles = append(pathsToVarsFiles, varsFilePath1, varsFilePath2) 124 }) 125 126 AfterEach(func() { 127 Expect(os.RemoveAll(varsDir)).ToNot(HaveOccurred()) 128 }) 129 130 When("multiple values for the same variable(s) are provided", func() { 131 BeforeEach(func() { 132 varsFilePath1 := filepath.Join(varsDir, "vars-1") 133 err := ioutil.WriteFile(varsFilePath1, []byte("var1: garbageapp\nvar1: spark\nvar2: doesn't matter"), 0666) 134 Expect(err).ToNot(HaveOccurred()) 135 136 varsFilePath2 := filepath.Join(varsDir, "vars-2") 137 err = ioutil.WriteFile(varsFilePath2, []byte("var2: flame"), 0666) 138 Expect(err).ToNot(HaveOccurred()) 139 140 pathsToVarsFiles = append(pathsToVarsFiles, varsFilePath1, varsFilePath2) 141 }) 142 143 It("interpolates the placeholder values", func() { 144 Expect(executeErr).ToNot(HaveOccurred()) 145 Expect(parsedManifest.AppNames()).To(ConsistOf("spark", "flame")) 146 }) 147 }) 148 149 When("the provided files exists and contain valid yaml", func() { 150 It("interpolates the placeholder values", func() { 151 Expect(executeErr).ToNot(HaveOccurred()) 152 Expect(parsedManifest.AppNames()).To(ConsistOf("spark", "flame")) 153 }) 154 }) 155 156 When("a variable in the manifest is not provided in the vars file", func() { 157 BeforeEach(func() { 158 varsFilePath := filepath.Join(varsDir, "vars-1") 159 err := ioutil.WriteFile(varsFilePath, []byte("notvar: foo"), 0666) 160 Expect(err).ToNot(HaveOccurred()) 161 162 pathsToVarsFiles = []string{varsFilePath} 163 }) 164 165 It("returns an error", func() { 166 Expect(executeErr.Error()).To(Equal("Expected to find variables: var1, var2")) 167 }) 168 }) 169 170 When("the provided file path does not exist", func() { 171 BeforeEach(func() { 172 pathsToVarsFiles = []string{"garbagepath"} 173 }) 174 175 It("returns an error", func() { 176 Expect(executeErr).To(HaveOccurred()) 177 Expect(os.IsNotExist(executeErr)).To(BeTrue()) 178 }) 179 }) 180 181 When("the provided file is not a valid yaml file", func() { 182 BeforeEach(func() { 183 varsFilePath := filepath.Join(varsDir, "vars-1") 184 err := ioutil.WriteFile(varsFilePath, []byte(": bad"), 0666) 185 Expect(err).ToNot(HaveOccurred()) 186 187 pathsToVarsFiles = []string{varsFilePath} 188 }) 189 190 It("returns an error", func() { 191 Expect(executeErr).To(HaveOccurred()) 192 Expect(executeErr).To(MatchError(InvalidYAMLError{ 193 Err: errors.New("yaml: did not find expected key"), 194 })) 195 }) 196 }) 197 }) 198 199 When("only vars are provided", func() { 200 BeforeEach(func() { 201 vars = []template.VarKV{ 202 {Name: "var1", Value: "spark"}, 203 {Name: "var2", Value: "flame"}, 204 } 205 }) 206 207 It("interpolates the placeholder values", func() { 208 Expect(executeErr).ToNot(HaveOccurred()) 209 Expect(parsedManifest.AppNames()).To(ConsistOf("spark", "flame")) 210 }) 211 }) 212 213 When("vars and vars files are provided", func() { 214 var varsFilePath string 215 BeforeEach(func() { 216 tmp, err := ioutil.TempFile("", "util-manifest-varsilfe") 217 Expect(err).NotTo(HaveOccurred()) 218 Expect(tmp.Close()).NotTo(HaveOccurred()) 219 220 varsFilePath = tmp.Name() 221 err = ioutil.WriteFile(varsFilePath, []byte("var1: spark\nvar2: 12345"), 0666) 222 Expect(err).ToNot(HaveOccurred()) 223 224 pathsToVarsFiles = []string{varsFilePath} 225 vars = []template.VarKV{ 226 {Name: "var2", Value: "flame"}, 227 } 228 }) 229 230 AfterEach(func() { 231 Expect(os.RemoveAll(varsFilePath)).ToNot(HaveOccurred()) 232 }) 233 234 It("interpolates the placeholder values, prioritizing the vars flag", func() { 235 Expect(executeErr).ToNot(HaveOccurred()) 236 Expect(parsedManifest.AppNames()).To(ConsistOf("spark", "flame")) 237 }) 238 }) 239 }) 240 241 When("invalid yaml is passed", func() { 242 BeforeEach(func() { 243 rawManifest = []byte("\t\t") 244 err := ioutil.WriteFile(pathToManifest, rawManifest, 0666) 245 Expect(err).ToNot(HaveOccurred()) 246 }) 247 248 It("returns an error", func() { 249 Expect(executeErr).To(HaveOccurred()) 250 }) 251 }) 252 253 When("unmarshalling returns an error", func() { 254 BeforeEach(func() { 255 rawManifest = []byte(`--- 256 blah blah 257 `) 258 err := ioutil.WriteFile(pathToManifest, rawManifest, 0666) 259 Expect(err).ToNot(HaveOccurred()) 260 }) 261 262 It("returns an error", func() { 263 Expect(executeErr).To(HaveOccurred()) 264 Expect(executeErr).To(MatchError(&yaml.TypeError{})) 265 }) 266 }) 267 }) 268 269 Describe("MarshalManifest", func() { 270 It("marshals the manifest", func() { 271 manifest := Manifest{ 272 Applications: []Application{ 273 { 274 Name: "app-1", 275 Processes: []Process{ 276 { 277 Type: "web", 278 RemainingManifestFields: map[string]interface{}{"unknown-process-key": 2}, 279 }, 280 }, 281 RemainingManifestFields: map[string]interface{}{"unknown-key": 1}, 282 }, 283 }, 284 } 285 286 yaml, err := parser.MarshalManifest(manifest) 287 288 Expect(err).NotTo(HaveOccurred()) 289 Expect(yaml).To(MatchYAML(`applications: 290 - name: app-1 291 unknown-key: 1 292 processes: 293 - type: web 294 unknown-process-key: 2 295 `)) 296 }) 297 }) 298 })