Skip to content

Commit 9e463c2

Browse files
XenoPhexsuprajanarasimhan
authored andcommitted
replace v7 push manifest interpolation with manifestparser interpolation
- Since the push needs more information from the manifest than the raw bytes, the manifestparser.Parser will be used to store and transport that data to Conceptualize. [#162558994] Signed-off-by: Supraja Narasimhan <[email protected]>
1 parent e07de62 commit 9e463c2

10 files changed

+359
-39
lines changed

command/translatableerror/convert_to_translatable_error.go

+7
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
"code.cloudfoundry.org/cli/util/clissh/ssherror"
1313
"code.cloudfoundry.org/cli/util/download"
1414
"code.cloudfoundry.org/cli/util/manifest"
15+
"code.cloudfoundry.org/cli/util/manifestparser"
1516
log "github.com/sirupsen/logrus"
1617
)
1718

@@ -196,6 +197,12 @@ func ConvertToTranslatableError(err error) error {
196197
case manifest.InterpolationError:
197198
return InterpolationError(e)
198199

200+
// ManifestParser Errors
201+
case manifestparser.InterpolationError:
202+
return InterpolationError(e)
203+
case manifestparser.InvalidYAMLError:
204+
return InvalidYAMLError(e)
205+
199206
// Plugin Execution Errors
200207
case pluginerror.RawHTTPStatusError:
201208
return DownloadPluginHTTPError{Message: e.Status}

command/translatableerror/convert_to_translatable_error_test.go

+9
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313
"code.cloudfoundry.org/cli/util/clissh/ssherror"
1414
"code.cloudfoundry.org/cli/util/download"
1515
"code.cloudfoundry.org/cli/util/manifest"
16+
"code.cloudfoundry.org/cli/util/manifestparser"
1617
. "github.com/onsi/ginkgo"
1718
. "github.com/onsi/ginkgo/extensions/table"
1819
. "github.com/onsi/gomega"
@@ -394,6 +395,14 @@ var _ = Describe("ConvertToTranslatableError", func() {
394395
manifest.InterpolationError{Err: errors.New("an-error")},
395396
InterpolationError{Err: errors.New("an-error")}),
396397

398+
Entry("manifestparser.InterpolationError -> InterpolationError",
399+
manifestparser.InterpolationError{Err: errors.New("an-error")},
400+
InterpolationError{Err: errors.New("an-error")}),
401+
402+
Entry("manifestparser.InvalidYAMLError -> InvalidYAMLError",
403+
manifestparser.InvalidYAMLError{Err: errors.New("an-error")},
404+
InvalidYAMLError{Err: errors.New("an-error")}),
405+
397406
// Plugin Errors
398407
Entry("pluginerror.RawHTTPStatusError -> DownloadPluginHTTPError",
399408
pluginerror.RawHTTPStatusError{Status: "some status"},
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package translatableerror
2+
3+
type InvalidYAMLError struct {
4+
Err error
5+
}
6+
7+
func (e InvalidYAMLError) Error() string {
8+
return "The option --vars-file expects a valid YAML file. {{.ErrorMessage}}"
9+
}
10+
11+
func (e InvalidYAMLError) Translate(translate func(string, ...interface{}) string) string {
12+
return translate(e.Error(), map[string]interface{}{
13+
"ErrorMessage": e.Err.Error(),
14+
})
15+
}

command/v7/push_command.go

+15-11
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import (
1515
"code.cloudfoundry.org/cli/command/translatableerror"
1616
v6shared "code.cloudfoundry.org/cli/command/v6/shared"
1717
"code.cloudfoundry.org/cli/command/v7/shared"
18-
"code.cloudfoundry.org/cli/util/manifest"
18+
"code.cloudfoundry.org/cli/util/manifestparser"
1919
"code.cloudfoundry.org/cli/util/progressbar"
2020

2121
"github.com/cloudfoundry/bosh-cli/director/template"
@@ -125,6 +125,13 @@ func (cmd PushCommand) Execute(args []string) error {
125125
return err
126126
}
127127

128+
var manifest []byte
129+
if !cmd.NoManifest {
130+
if manifest, err = cmd.readManifest(); err != nil {
131+
return err
132+
}
133+
}
134+
128135
overrides, err := cmd.GetFlagOverrides()
129136
if err != nil {
130137
return err
@@ -144,13 +151,6 @@ func (cmd PushCommand) Execute(args []string) error {
144151

145152
cmd.UI.DisplayText("Getting app info...")
146153

147-
var manifest []byte
148-
if !cmd.NoManifest {
149-
if manifest, err = cmd.readManifest(); err != nil {
150-
return err
151-
}
152-
}
153-
154154
log.Info("generating the app state")
155155
pushState, warnings, err := cmd.Actor.Conceptualize(
156156
cmd.RequiredArgs.AppName,
@@ -350,22 +350,26 @@ func (cmd PushCommand) readManifest() ([]byte, error) {
350350
pathsToVarsFiles = append(pathsToVarsFiles, string(varfilepath))
351351
}
352352

353+
parser := manifestparser.NewParser()
354+
353355
if len(cmd.PathToManifest) != 0 {
354356
log.WithField("manifestPath", cmd.PathToManifest).Debug("reading '-f' provided manifest")
355-
return manifest.ReadAndInterpolateRawManifest(string(cmd.PathToManifest), pathsToVarsFiles, cmd.Vars)
357+
err := parser.InterpolateAndParse(string(cmd.PathToManifest), pathsToVarsFiles, cmd.Vars)
358+
return parser.FullRawManifest(), err
356359
}
357360

358361
pathToManifest := filepath.Join(cmd.PWD, "manifest.yml")
359362
log.WithField("manifestPath", pathToManifest).Debug("path to manifest")
360363

361-
interpolatedManifest, err := manifest.ReadAndInterpolateRawManifest(pathToManifest, pathsToVarsFiles, cmd.Vars)
364+
err := parser.InterpolateAndParse(pathToManifest, pathsToVarsFiles, cmd.Vars)
362365
if err != nil && !os.IsNotExist(err) {
363366
log.Errorln("reading manifest:", err)
364367
return nil, err
365368
} else if os.IsNotExist(err) {
366369
log.Debug("no manifest exists")
367370
}
368-
return interpolatedManifest, nil
371+
372+
return parser.FullRawManifest(), nil
369373
}
370374

371375
func (cmd PushCommand) GetFlagOverrides() (v7pushaction.FlagOverrides, error) {

command/v7/push_command_test.go

+10-10
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,7 @@ var _ = Describe("push Command", func() {
243243
var yamlContents []byte
244244

245245
BeforeEach(func() {
246-
yamlContents = []byte(`---\n- banana`)
246+
yamlContents = []byte("---\napplications:\n- name: banana")
247247
pathToYAMLFile := filepath.Join(tempDir, "manifest.yml")
248248
err := ioutil.WriteFile(pathToYAMLFile, yamlContents, 0644)
249249
Expect(err).ToNot(HaveOccurred())
@@ -284,7 +284,7 @@ var _ = Describe("push Command", func() {
284284
var yamlContents []byte
285285

286286
BeforeEach(func() {
287-
yamlContents = []byte(`---\n- banana`)
287+
yamlContents = []byte("---\napplications:\n- name: banana")
288288
pathToYAMLFile := filepath.Join(tempDir, "manifest.yml")
289289
err := ioutil.WriteFile(pathToYAMLFile, yamlContents, 0644)
290290
Expect(err).ToNot(HaveOccurred())
@@ -313,11 +313,11 @@ var _ = Describe("push Command", func() {
313313
When("--vars-files are specified", func() {
314314
var yamlContents []byte
315315
var varFileContents []byte
316-
var interpolatedManifest []byte
316+
var expectedManifest []byte
317317

318318
BeforeEach(func() {
319-
interpolatedManifest = yamlUnmarshalMarshal([]byte("---\n- var: turtle"))
320-
yamlContents = []byte("---\n- var: ((put-var-here))")
319+
expectedManifest = yamlUnmarshalMarshal([]byte("---\napplications:\n- name: turtle"))
320+
yamlContents = []byte("---\napplications:\n- name: ((put-var-here))")
321321
pathToYAMLFile := filepath.Join(tempDir, "manifest.yml")
322322
err := ioutil.WriteFile(pathToYAMLFile, yamlContents, 0644)
323323
Expect(err).ToNot(HaveOccurred())
@@ -336,17 +336,17 @@ var _ = Describe("push Command", func() {
336336
Expect(executeErr).ToNot(HaveOccurred())
337337
Expect(fakeActor.ConceptualizeCallCount()).To(Equal(1))
338338
_, _, _, _, _, manifest := fakeActor.ConceptualizeArgsForCall(0)
339-
Expect(manifest).To(Equal(interpolatedManifest))
339+
Expect(manifest).To(Equal(expectedManifest))
340340
})
341341
})
342342

343343
When("The --var flag is provided", func() {
344344
var yamlContents []byte
345-
var interpolatedManifest []byte
345+
var expectedManifest []byte
346346

347347
BeforeEach(func() {
348-
interpolatedManifest = yamlUnmarshalMarshal([]byte("---\n- var: turtle"))
349-
yamlContents = []byte("---\n- var: ((put-var-here))")
348+
expectedManifest = yamlUnmarshalMarshal([]byte("---\napplications:\n- name: turtle"))
349+
yamlContents = []byte("---\napplications:\n- name: ((put-var-here))")
350350
pathToYAMLFile := filepath.Join(tempDir, "manifest.yml")
351351
err := ioutil.WriteFile(pathToYAMLFile, yamlContents, 0644)
352352
Expect(err).ToNot(HaveOccurred())
@@ -360,7 +360,7 @@ var _ = Describe("push Command", func() {
360360
Expect(executeErr).ToNot(HaveOccurred())
361361
Expect(fakeActor.ConceptualizeCallCount()).To(Equal(1))
362362
_, _, _, _, _, manifest := fakeActor.ConceptualizeArgsForCall(0)
363-
Expect(manifest).To(Equal(interpolatedManifest))
363+
Expect(manifest).To(Equal(expectedManifest))
364364
})
365365
})
366366
})

util/manifestparser/application.go

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package manifestparser
2+
3+
type Application struct {
4+
Name string `yaml:"name"`
5+
}
+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package manifestparser
2+
3+
import (
4+
"fmt"
5+
"strings"
6+
)
7+
8+
type InterpolationError struct {
9+
Err error
10+
}
11+
12+
func (e InterpolationError) Error() string {
13+
return fmt.Sprint(strings.Replace(e.Err.Error(), "\n", ", ", -1))
14+
}
+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package manifestparser
2+
3+
import "fmt"
4+
5+
type InvalidYAMLError struct {
6+
Err error
7+
}
8+
9+
func (e InvalidYAMLError) Error() string {
10+
return fmt.Sprintf("The option --vars-file expects a valid YAML file. %s", e.Err)
11+
}

util/manifestparser/parser.go

+66-18
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,10 @@ import (
44
"errors"
55
"io/ioutil"
66

7+
"github.com/cloudfoundry/bosh-cli/director/template"
78
yaml "gopkg.in/yaml.v2"
89
)
910

10-
type Application struct {
11-
Name string `yaml:"name"`
12-
}
13-
1411
type Parser struct {
1512
PathToManifest string
1613

@@ -28,30 +25,50 @@ func (parser *Parser) Parse(manifestPath string) error {
2825
if err != nil {
2926
return err
3027
}
31-
parser.rawManifest = bytes
32-
33-
var raw struct {
34-
Applications []Application `yaml:"applications"`
35-
}
28+
return parser.parse(bytes)
29+
}
3630

37-
err = yaml.Unmarshal(bytes, &raw)
31+
// InterpolateAndParse reads the manifest at the provided paths, interpolates
32+
// variables if a vars file is provided, and sets the current manifest to the
33+
// resulting manifest.
34+
func (parser *Parser) InterpolateAndParse(pathToManifest string, pathsToVarsFiles []string, vars []template.VarKV) error {
35+
rawManifest, err := ioutil.ReadFile(pathToManifest)
3836
if err != nil {
3937
return err
4038
}
4139

42-
parser.Applications = raw.Applications
40+
tpl := template.NewTemplate(rawManifest)
41+
fileVars := template.StaticVariables{}
4342

44-
if len(parser.Applications) == 0 {
45-
return errors.New("must have at least one application")
46-
}
43+
for _, path := range pathsToVarsFiles {
44+
rawVarsFile, ioerr := ioutil.ReadFile(path)
45+
if ioerr != nil {
46+
return ioerr
47+
}
4748

48-
for _, application := range parser.Applications {
49-
if application.Name == "" {
50-
return errors.New("Found an application with no name specified")
49+
var sv template.StaticVariables
50+
51+
err = yaml.Unmarshal(rawVarsFile, &sv)
52+
if err != nil {
53+
return InvalidYAMLError{Err: err}
54+
}
55+
56+
for k, v := range sv {
57+
fileVars[k] = v
5158
}
5259
}
5360

54-
return nil
61+
for _, kv := range vars {
62+
fileVars[kv.Name] = kv.Value
63+
}
64+
65+
rawManifest, err = tpl.Evaluate(fileVars, nil, template.EvaluateOpts{ExpectAllKeys: true})
66+
if err != nil {
67+
return InterpolationError{Err: err}
68+
}
69+
70+
parser.PathToManifest = pathToManifest
71+
return parser.parse(rawManifest)
5572
}
5673

5774
func (parser Parser) AppNames() []string {
@@ -62,6 +79,37 @@ func (parser Parser) AppNames() []string {
6279
return names
6380
}
6481

82+
func (parser Parser) FullRawManifest() []byte {
83+
return parser.rawManifest
84+
}
85+
6586
func (parser Parser) RawManifest(_ string) ([]byte, error) {
6687
return parser.rawManifest, nil
6788
}
89+
90+
func (parser *Parser) parse(manifestBytes []byte) error {
91+
parser.rawManifest = manifestBytes
92+
93+
var raw struct {
94+
Applications []Application `yaml:"applications"`
95+
}
96+
97+
err := yaml.Unmarshal(manifestBytes, &raw)
98+
if err != nil {
99+
return err
100+
}
101+
102+
parser.Applications = raw.Applications
103+
104+
if len(parser.Applications) == 0 {
105+
return errors.New("must have at least one application")
106+
}
107+
108+
for _, application := range parser.Applications {
109+
if application.Name == "" {
110+
return errors.New("Found an application with no name specified")
111+
}
112+
}
113+
114+
return nil
115+
}

0 commit comments

Comments
 (0)