github.com/arunkumar7540/cli@v6.45.0+incompatible/util/manifestparser/parser.go (about) 1 package manifestparser 2 3 import ( 4 "errors" 5 "io/ioutil" 6 "os" 7 "path/filepath" 8 9 "github.com/cloudfoundry/bosh-cli/director/template" 10 "gopkg.in/yaml.v2" 11 ) 12 13 type Parser struct { 14 PathToManifest string 15 16 Applications []Application 17 18 rawManifest []byte 19 20 validators []validatorFunc 21 22 hasParsed bool 23 } 24 25 func NewParser() *Parser { 26 parser := new(Parser) 27 28 return parser 29 } 30 31 func (parser Parser) AppNames() []string { 32 var names []string 33 for _, app := range parser.Applications { 34 names = append(names, app.Name) 35 } 36 return names 37 } 38 39 func (parser *Parser) Apps(appName string) ([]Application, error) { 40 if appName == "" { 41 return parser.Applications, nil 42 } 43 for _, app := range parser.Applications { 44 if app.Name == appName { 45 return []Application{app}, nil 46 } 47 } 48 return nil, AppNotInManifestError{Name: appName} 49 } 50 51 func (parser Parser) ContainsManifest() bool { 52 return parser.hasParsed 53 } 54 55 func (parser Parser) ContainsMultipleApps() bool { 56 return len(parser.Applications) > 1 57 } 58 59 func (parser Parser) ContainsPrivateDockerImages() bool { 60 for _, app := range parser.Applications { 61 if app.Docker != nil && app.Docker.Username != "" { 62 return true 63 } 64 } 65 return false 66 } 67 68 func (parser Parser) FullRawManifest() []byte { 69 return parser.rawManifest 70 } 71 72 func (parser *Parser) GetPathToManifest() string { 73 return parser.PathToManifest 74 } 75 76 // InterpolateAndParse reads the manifest at the provided paths, interpolates 77 // variables if a vars file is provided, and sets the current manifest to the 78 // resulting manifest. 79 func (parser *Parser) InterpolateAndParse(pathToManifest string, pathsToVarsFiles []string, vars []template.VarKV) error { 80 rawManifest, err := ioutil.ReadFile(pathToManifest) 81 if err != nil { 82 return err 83 } 84 85 tpl := template.NewTemplate(rawManifest) 86 fileVars := template.StaticVariables{} 87 88 for _, path := range pathsToVarsFiles { 89 rawVarsFile, ioerr := ioutil.ReadFile(path) 90 if ioerr != nil { 91 return ioerr 92 } 93 94 var sv template.StaticVariables 95 96 err = yaml.Unmarshal(rawVarsFile, &sv) 97 if err != nil { 98 return InvalidYAMLError{Err: err} 99 } 100 101 for k, v := range sv { 102 fileVars[k] = v 103 } 104 } 105 106 for _, kv := range vars { 107 fileVars[kv.Name] = kv.Value 108 } 109 110 rawManifest, err = tpl.Evaluate(fileVars, nil, template.EvaluateOpts{ExpectAllKeys: true}) 111 if err != nil { 112 return InterpolationError{Err: err} 113 } 114 115 parser.PathToManifest = pathToManifest 116 return parser.parse(rawManifest) 117 } 118 119 func (parser Parser) RawAppManifest(appName string) ([]byte, error) { 120 var appManifest manifest 121 for _, app := range parser.Applications { 122 if app.Name == appName { 123 appManifest.Applications = []Application{app} 124 return yaml.Marshal(appManifest) 125 } 126 } 127 return nil, AppNotInManifestError{Name: appName} 128 } 129 130 func (parser *Parser) parse(manifestBytes []byte) error { 131 parser.rawManifest = manifestBytes 132 pathToManifest := parser.GetPathToManifest() 133 var raw manifest 134 135 err := yaml.Unmarshal(manifestBytes, &raw) 136 if err != nil { 137 return err 138 } 139 140 parser.Applications = raw.Applications 141 142 if len(parser.Applications) == 0 { 143 return errors.New("must have at least one application") 144 } 145 146 for index, application := range parser.Applications { 147 if application.Name == "" { 148 return errors.New("Found an application with no name specified") 149 } 150 151 if application.Path == "" { 152 continue 153 } 154 155 var finalPath = application.Path 156 if !filepath.IsAbs(finalPath) { 157 finalPath = filepath.Join(filepath.Dir(pathToManifest), finalPath) 158 } 159 finalPath, err = filepath.EvalSymlinks(finalPath) 160 if err != nil { 161 if os.IsNotExist(err) { 162 return InvalidManifestApplicationPathError{ 163 Path: application.Path, 164 } 165 } 166 return err 167 } 168 parser.Applications[index].Path = finalPath 169 170 } 171 parser.hasParsed = true 172 return nil 173 }