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  }