You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openwhisk.apache.org by da...@apache.org on 2017/09/20 03:22:25 UTC
[incubator-openwhisk-wskdeploy] branch master updated: Adding
support for packages in manifest (#519)
This is an automated email from the ASF dual-hosted git repository.
daisyguo pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-openwhisk-wskdeploy.git
The following commit(s) were added to refs/heads/master by this push:
new e6987dd Adding support for packages in manifest (#519)
e6987dd is described below
commit e6987dddc5fc61c76f9eac187bac8b6d1bf037fe
Author: Priti Desai <pd...@us.ibm.com>
AuthorDate: Tue Sep 19 20:22:23 2017 -0700
Adding support for packages in manifest (#519)
* Adding support for packages in manifest file
* Adding deployment file
* Adding more changes
* Adding integration test
---
deployers/manifestreader.go | 160 +++++++-------
deployers/servicedeployer.go | 1 -
parsers/manifest_parser.go | 233 +++++++++++++++------
parsers/manifest_parser_test.go | 102 +++++++--
parsers/yamlparser.go | 1 +
.../actions/hello.jar | Bin 0 -> 1053 bytes
.../validate-packages-in-manifest/actions/hello.js | 26 +++
.../validate-packages-in-manifest/actions/hello.py | 23 ++
.../validate-packages-in-manifest/deployment.yaml | 26 +++
.../validate-packages-in-manifest/manifest.yaml | 112 ++++++++++
.../validate-packages-in-manifest_test.go | 40 ++++
11 files changed, 562 insertions(+), 162 deletions(-)
diff --git a/deployers/manifestreader.go b/deployers/manifestreader.go
index 4f409e6..0a8ec28 100644
--- a/deployers/manifestreader.go
+++ b/deployers/manifestreader.go
@@ -46,18 +46,18 @@ func (deployer *ManifestReader) ParseManifest() (*parsers.ManifestYAML, *parsers
manifestParser := parsers.NewYAMLParser()
manifest, err := manifestParser.ParseManifest(dep.ManifestPath)
- if err != nil {
- return manifest, manifestParser, utils.NewInputYamlFileError(err.Error())
- }
+ if err != nil {
+ return manifest, manifestParser, utils.NewInputYamlFileError(err.Error())
+ }
return manifest, manifestParser, nil
}
func (reader *ManifestReader) InitRootPackage(manifestParser *parsers.YAMLParser, manifest *parsers.ManifestYAML) error {
- packg, err := manifestParser.ComposePackage(manifest, reader.serviceDeployer.ManifestPath)
+ packages, err := manifestParser.ComposeAllPackages(manifest, reader.serviceDeployer.ManifestPath)
if err != nil {
- return utils.NewInputYamlFormatError(err.Error())
- }
- reader.SetPackage(packg)
+ return utils.NewInputYamlFormatError(err.Error())
+ }
+ reader.SetPackage(packages)
return nil
}
@@ -65,66 +65,66 @@ func (reader *ManifestReader) InitRootPackage(manifestParser *parsers.YAMLParser
// Wrapper parser to handle yaml dir
func (deployer *ManifestReader) HandleYaml(sdeployer *ServiceDeployer, manifestParser *parsers.YAMLParser, manifest *parsers.ManifestYAML) error {
- var err error
+ var err error
deps, err := manifestParser.ComposeDependencies(manifest, deployer.serviceDeployer.ProjectPath, deployer.serviceDeployer.ManifestPath)
- if err != nil {
- return utils.NewInputYamlFormatError(err.Error())
- }
+ if err != nil {
+ return utils.NewInputYamlFormatError(err.Error())
+ }
- actions, err := manifestParser.ComposeActions(manifest, deployer.serviceDeployer.ManifestPath)
- if err != nil {
- return utils.NewInputYamlFormatError(err.Error())
- }
+ actions, err := manifestParser.ComposeActionsFromAllPackages(manifest, deployer.serviceDeployer.ManifestPath)
+ if err != nil {
+ return utils.NewInputYamlFormatError(err.Error())
+ }
- sequences, err := manifestParser.ComposeSequences(deployer.serviceDeployer.ClientConfig.Namespace, manifest)
+ sequences, err := manifestParser.ComposeSequencesFromAllPackages(deployer.serviceDeployer.ClientConfig.Namespace, manifest)
if err != nil {
- return utils.NewInputYamlFormatError(err.Error())
- }
+ return utils.NewInputYamlFormatError(err.Error())
+ }
- triggers, err := manifestParser.ComposeTriggers(manifest, deployer.serviceDeployer.ManifestPath)
- if err != nil {
- return utils.NewInputYamlFormatError(err.Error())
- }
+ triggers, err := manifestParser.ComposeTriggersFromAllPackages(manifest, deployer.serviceDeployer.ManifestPath)
+ if err != nil {
+ return utils.NewInputYamlFormatError(err.Error())
+ }
- rules, err := manifestParser.ComposeRules(manifest)
- if err != nil {
- return utils.NewInputYamlFormatError(err.Error())
- }
+ rules, err := manifestParser.ComposeRulesFromAllPackages(manifest)
+ if err != nil {
+ return utils.NewInputYamlFormatError(err.Error())
+ }
- apis, err := manifestParser.ComposeApiRecords(manifest)
- if err != nil {
- return utils.NewInputYamlFormatError(err.Error())
- }
+ apis, err := manifestParser.ComposeApiRecordsFromAllPackages(manifest)
+ if err != nil {
+ return utils.NewInputYamlFormatError(err.Error())
+ }
err = deployer.SetDependencies(deps)
- if err != nil {
- return utils.NewInputYamlFormatError(err.Error())
- }
+ if err != nil {
+ return utils.NewInputYamlFormatError(err.Error())
+ }
err = deployer.SetActions(actions)
- if err != nil {
- return utils.NewInputYamlFormatError(err.Error())
- }
+ if err != nil {
+ return utils.NewInputYamlFormatError(err.Error())
+ }
err = deployer.SetSequences(sequences)
- if err != nil {
- return utils.NewInputYamlFormatError(err.Error())
- }
+ if err != nil {
+ return utils.NewInputYamlFormatError(err.Error())
+ }
err = deployer.SetTriggers(triggers)
- if err != nil {
- return utils.NewInputYamlFormatError(err.Error())
- }
+ if err != nil {
+ return utils.NewInputYamlFormatError(err.Error())
+ }
err = deployer.SetRules(rules)
- if err != nil {
- return utils.NewInputYamlFormatError(err.Error())
- }
+ if err != nil {
+ return utils.NewInputYamlFormatError(err.Error())
+ }
err = deployer.SetApis(apis)
- if err != nil {
- return utils.NewInputYamlFormatError(err.Error())
- }
+ if err != nil {
+ return utils.NewInputYamlFormatError(err.Error())
+ }
return nil
@@ -137,9 +137,9 @@ func (reader *ManifestReader) SetDependencies(deps map[string]utils.DependencyRe
// dependency
gitReader := utils.NewGitReader(depName, dep)
err := gitReader.CloneDependency()
- if err != nil {
- return utils.NewInputYamlFormatError(err.Error())
- }
+ if err != nil {
+ return utils.NewInputYamlFormatError(err.Error())
+ }
} else {
// TODO: we should do a check to make sure this dependency is compatible with an already installed one.
// If not, we should throw dependency mismatch error.
@@ -155,32 +155,34 @@ func (reader *ManifestReader) SetDependencies(deps map[string]utils.DependencyRe
return nil
}
-func (reader *ManifestReader) SetPackage(pkg *whisk.Package) error {
+func (reader *ManifestReader) SetPackage(packages map[string]*whisk.Package) error {
dep := reader.serviceDeployer
dep.mt.Lock()
defer dep.mt.Unlock()
- depPkg, exist := dep.Deployment.Packages[pkg.Name]
- if exist {
- if dep.IsDefault == true {
- existPkg := depPkg.Package
- existPkg.Annotations = pkg.Annotations
- existPkg.Namespace = pkg.Namespace
- existPkg.Parameters = pkg.Parameters
- existPkg.Publish = pkg.Publish
- existPkg.Version = pkg.Version
-
- dep.Deployment.Packages[pkg.Name].Package = existPkg
- return nil
- } else {
- return errors.New("Package " + pkg.Name + "exists twice")
+
+ for _, pkg := range packages {
+ depPkg, exist := dep.Deployment.Packages[pkg.Name]
+ if exist {
+ if dep.IsDefault == true {
+ existPkg := depPkg.Package
+ existPkg.Annotations = pkg.Annotations
+ existPkg.Namespace = pkg.Namespace
+ existPkg.Parameters = pkg.Parameters
+ existPkg.Publish = pkg.Publish
+ existPkg.Version = pkg.Version
+
+ dep.Deployment.Packages[pkg.Name].Package = existPkg
+ return nil
+ } else {
+ return errors.New("Package " + pkg.Name + "exists twice")
+ }
}
+ newPack := NewDeploymentPackage()
+ newPack.Package = pkg
+ dep.Deployment.Packages[pkg.Name] = newPack
}
-
- newPack := NewDeploymentPackage()
- newPack.Package = pkg
- dep.Deployment.Packages[pkg.Name] = newPack
return nil
}
@@ -218,9 +220,9 @@ func (reader *ManifestReader) SetActions(actions []utils.ActionRecord) error {
}
err := reader.checkAction(existAction)
- if err != nil {
- return utils.NewInputYamlFormatError(err.Error())
- }
+ if err != nil {
+ return utils.NewInputYamlFormatError(err.Error())
+ }
} else {
// Action exists, but references two different sources
@@ -229,9 +231,9 @@ func (reader *ManifestReader) SetActions(actions []utils.ActionRecord) error {
} else {
// not a new action so update the action in the package
err := reader.checkAction(manifestAction)
- if err != nil {
- return utils.NewInputYamlFormatError(err.Error())
- }
+ if err != nil {
+ return utils.NewInputYamlFormatError(err.Error())
+ }
reader.serviceDeployer.Deployment.Packages[manifestAction.Packagename].Actions[manifestAction.Action.Name] = manifestAction
}
}
@@ -287,9 +289,9 @@ func (reader *ManifestReader) SetSequences(actions []utils.ActionRecord) error {
} else {
// not a new action so update the action in the package
err := reader.checkAction(seqAction)
- if err != nil {
- return utils.NewInputYamlFormatError(err.Error())
- }
+ if err != nil {
+ return utils.NewInputYamlFormatError(err.Error())
+ }
reader.serviceDeployer.Deployment.Packages[seqAction.Packagename].Sequences[seqAction.Action.Name] = seqAction
}
}
diff --git a/deployers/servicedeployer.go b/deployers/servicedeployer.go
index 32dd4ca..ac57c2d 100644
--- a/deployers/servicedeployer.go
+++ b/deployers/servicedeployer.go
@@ -129,7 +129,6 @@ func (deployer *ServiceDeployer) ConstructDeploymentPlan() error {
if err != nil {
return err
}
-
fileReader.SetFileActions(fileActions)
}
diff --git a/parsers/manifest_parser.go b/parsers/manifest_parser.go
index f926aec..720e336 100644
--- a/parsers/manifest_parser.go
+++ b/parsers/manifest_parser.go
@@ -43,8 +43,8 @@ func ReadOrCreateManifest() (*ManifestYAML, error) {
dat, _ := ioutil.ReadFile(utils.ManifestFileNameYaml)
err := NewYAMLParser().Unmarshal(dat, &maniyaml)
if err != nil {
- return &maniyaml, utils.NewInputYamlFileError(err.Error())
- }
+ return &maniyaml, utils.NewInputYamlFileError(err.Error())
+ }
}
return &maniyaml, nil
}
@@ -52,18 +52,18 @@ func ReadOrCreateManifest() (*ManifestYAML, error) {
// Serialize manifest to local file
func Write(manifest *ManifestYAML, filename string) error {
output, err := NewYAMLParser().Marshal(manifest)
- if err != nil {
- return utils.NewInputYamlFormatError(err.Error())
- }
+ if err != nil {
+ return utils.NewInputYamlFormatError(err.Error())
+ }
f, err := os.Create(filename)
- if err != nil {
- return utils.NewInputYamlFileError(err.Error())
- }
+ if err != nil {
+ return utils.NewInputYamlFileError(err.Error())
+ }
defer f.Close()
f.Write(output)
- return nil
+ return nil
}
func (dm *YAMLParser) Unmarshal(input []byte, manifest *ManifestYAML) error {
@@ -89,14 +89,14 @@ func (dm *YAMLParser) ParseManifest(manifestPath string) (*ManifestYAML, error)
content, err := utils.Read(manifestPath)
if err != nil {
- return &maniyaml, utils.NewInputYamlFileError(err.Error())
- }
+ return &maniyaml, utils.NewInputYamlFileError(err.Error())
+ }
err = mm.Unmarshal(content, &maniyaml)
- if err != nil {
- lines, msgs := dm.convertErrorToLinesMsgs(err.Error())
- return &maniyaml, utils.NewParserErr(manifestPath, lines, msgs)
- }
+ if err != nil {
+ lines, msgs := dm.convertErrorToLinesMsgs(err.Error())
+ return &maniyaml, utils.NewParserErr(manifestPath, lines, msgs)
+ }
maniyaml.Filepath = manifestPath
return &maniyaml, nil
}
@@ -164,20 +164,39 @@ func (dm *YAMLParser) ComposeDependencies(mani *ManifestYAML, projectPath string
return depMap, nil
}
-// Is we consider multi pacakge in one yaml?
-func (dm *YAMLParser) ComposePackage(mani *ManifestYAML, filePath string) (*whisk.Package, error) {
- var errorParser error
+func (dm *YAMLParser) ComposeAllPackages(manifest *ManifestYAML, filePath string) (map[string]*whisk.Package, error) {
+ packages := map[string]*whisk.Package{}
+ if manifest.Package.Packagename != "" {
+ s, err := dm.ComposePackage(manifest.Package, manifest.Package.Packagename, filePath)
+ if err == nil {
+ packages[manifest.Package.Packagename] = s
+ } else {
+ return nil, err
+ }
+ } else if manifest.Packages != nil {
+ for n, p := range manifest.Packages {
+ s, err := dm.ComposePackage(p, n, filePath)
+ if err == nil {
+ packages[n] = s
+ } else {
+ return nil, err
+ }
+ }
+ }
+ return packages, nil
+}
- //mani := dm.ParseManifest(manipath)
+func (dm *YAMLParser) ComposePackage(pkg Package, packageName string, filePath string) (*whisk.Package, error) {
+ var errorParser error
pag := &whisk.Package{}
- pag.Name = mani.Package.Packagename
+ pag.Name = packageName
//The namespace for this package is absent, so we use default guest here.
- pag.Namespace = mani.Package.Namespace
+ pag.Namespace = pkg.Namespace
pub := false
pag.Publish = &pub
keyValArr := make(whisk.KeyValueArr, 0)
- for name, param := range mani.Package.Inputs {
+ for name, param := range pkg.Inputs {
var keyVal whisk.KeyValue
keyVal.Key = name
@@ -198,9 +217,26 @@ func (dm *YAMLParser) ComposePackage(mani *ManifestYAML, filePath string) (*whis
return pag, nil
}
-func (dm *YAMLParser) ComposeSequences(namespace string, mani *ManifestYAML) ([]utils.ActionRecord, error) {
+func (dm *YAMLParser) ComposeSequencesFromAllPackages(namespace string, mani *ManifestYAML) (ar []utils.ActionRecord, err error) {
var s1 []utils.ActionRecord = make([]utils.ActionRecord, 0)
- for key, sequence := range mani.Package.Sequences {
+ if mani.Package.Packagename != "" {
+ return dm.ComposeSequences(namespace, mani.Package.Sequences, mani.Package.Packagename)
+ } else if mani.Packages != nil {
+ for n, p := range mani.Packages {
+ s, err := dm.ComposeSequences(namespace, p.Sequences, n)
+ if err == nil {
+ s1 = append(s1, s...)
+ } else {
+ return nil, err
+ }
+ }
+ }
+ return s1, nil
+}
+
+func (dm *YAMLParser) ComposeSequences(namespace string, sequences map[string]Sequence, packageName string) ([]utils.ActionRecord, error) {
+ var s1 []utils.ActionRecord = make([]utils.ActionRecord, 0)
+ for key, sequence := range sequences {
wskaction := new(whisk.Action)
wskaction.Exec = new(whisk.Exec)
wskaction.Exec.Kind = "sequence"
@@ -208,11 +244,9 @@ func (dm *YAMLParser) ComposeSequences(namespace string, mani *ManifestYAML) ([]
var components []string
for _, a := range actionList {
-
act := strings.TrimSpace(a)
-
- if !strings.ContainsRune(act, '/') && !strings.HasPrefix(act, mani.Package.Packagename+"/") {
- act = path.Join(mani.Package.Packagename, act)
+ if !strings.ContainsRune(act, '/') && !strings.HasPrefix(act, packageName +"/") {
+ act = path.Join(packageName, act)
}
components = append(components, path.Join("/"+namespace, act))
}
@@ -236,19 +270,36 @@ func (dm *YAMLParser) ComposeSequences(namespace string, mani *ManifestYAML) ([]
wskaction.Annotations = keyValArr
}
- record := utils.ActionRecord{wskaction, mani.Package.Packagename, key}
+ record := utils.ActionRecord{Action: wskaction, Packagename: packageName, Filepath: key}
s1 = append(s1, record)
}
return s1, nil
}
-func (dm *YAMLParser) ComposeActions(mani *ManifestYAML, manipath string) (ar []utils.ActionRecord, err error) {
+func (dm *YAMLParser) ComposeActionsFromAllPackages(manifest *ManifestYAML, filePath string) ([]utils.ActionRecord, error) {
+ var s1 []utils.ActionRecord = make([]utils.ActionRecord, 0)
+ if manifest.Package.Packagename != "" {
+ return dm.ComposeActions(filePath, manifest.Package.Actions, manifest.Package.Packagename)
+ } else if manifest.Packages != nil {
+ for n, p := range manifest.Packages {
+ a, err := dm.ComposeActions(filePath, p.Actions, n)
+ if err == nil {
+ s1 = append(s1, a...)
+ } else {
+ return nil, err
+ }
+ }
+ }
+ return s1, nil
+}
+
+func (dm *YAMLParser) ComposeActions(filePath string, actions map[string]Action, packageName string) ([]utils.ActionRecord, error) {
var errorParser error
var s1 []utils.ActionRecord = make([]utils.ActionRecord, 0)
- for key, action := range mani.Package.Actions {
- splitmanipath := strings.Split(manipath, string(os.PathSeparator))
+ for key, action := range actions {
+ splitFilePath := strings.Split(filePath, string(os.PathSeparator))
//set action.Function to action.Location
//because Location is deprecated in Action entity
if action.Function == "" && action.Location != "" {
@@ -260,11 +311,14 @@ func (dm *YAMLParser) ComposeActions(mani *ManifestYAML, manipath string) (ar []
wskaction.Exec = new(whisk.Exec)
if action.Function != "" {
- filePath := strings.TrimRight(manipath, splitmanipath[len(splitmanipath)-1]) + action.Function
+ filePath := strings.TrimRight(filePath, splitFilePath[len(splitFilePath)-1]) + action.Function
if utils.IsDirectory(filePath) {
zipName := filePath + ".zip"
- err = utils.NewZipWritter(filePath, zipName).Zip()
+ err := utils.NewZipWritter(filePath, zipName).Zip()
+ if err != nil {
+ return nil, err
+ }
defer os.Remove(zipName)
// To do: support docker and main entry as did by go cli?
wskaction.Exec, err = utils.GetExec(zipName, action.Runtime, false, "")
@@ -287,8 +341,8 @@ func (dm *YAMLParser) ComposeActions(mani *ManifestYAML, manipath string) (ar []
kind = "java"
default:
kind = "nodejs:6"
- errStr := wski18n.T("Unsupported runtime type, set to nodejs")
- whisk.Debug(whisk.DbgWarn, errStr)
+ errStr := wski18n.T("Unsupported runtime type, set to nodejs")
+ whisk.Debug(whisk.DbgWarn, errStr)
//add the user input kind here
}
@@ -296,9 +350,9 @@ func (dm *YAMLParser) ComposeActions(mani *ManifestYAML, manipath string) (ar []
action.Function = filePath
dat, err := utils.Read(filePath)
- if err != nil {
- return s1, err
- }
+ if err != nil {
+ return s1, err
+ }
code := string(dat)
if ext == ".zip" || ext == ".jar" {
code = base64.StdEncoding.EncodeToString([]byte(dat))
@@ -315,13 +369,13 @@ func (dm *YAMLParser) ComposeActions(mani *ManifestYAML, manipath string) (ar []
if utils.CheckExistRuntime(action.Runtime, utils.Rts) {
wskaction.Exec.Kind = action.Runtime
} else {
- errStr := wski18n.T("the runtime is not supported by Openwhisk platform.\n")
- whisk.Debug(whisk.DbgWarn, errStr)
+ errStr := wski18n.T("the runtime is not supported by Openwhisk platform.\n")
+ whisk.Debug(whisk.DbgWarn, errStr)
}
} else {
- errStr := wski18n.T("wskdeploy has chosen a particular runtime for the action.\n")
- whisk.Debug(whisk.DbgWarn, errStr)
- }
+ errStr := wski18n.T("wskdeploy has chosen a particular runtime for the action.\n")
+ whisk.Debug(whisk.DbgWarn, errStr)
+ }
// we can specify the name of the action entry point using main
if action.Main != "" {
@@ -333,7 +387,7 @@ func (dm *YAMLParser) ComposeActions(mani *ManifestYAML, manipath string) (ar []
var keyVal whisk.KeyValue
keyVal.Key = name
- keyVal.Value, errorParser = ResolveParameter(name, ¶m, manipath)
+ keyVal.Value, errorParser = ResolveParameter(name, ¶m, filePath)
if errorParser != nil {
return nil, errorParser
@@ -343,7 +397,6 @@ func (dm *YAMLParser) ComposeActions(mani *ManifestYAML, manipath string) (ar []
keyValArr = append(keyValArr, keyVal)
}
}
-
if len(keyValArr) > 0 {
wskaction.Parameters = keyValArr
}
@@ -360,29 +413,44 @@ func (dm *YAMLParser) ComposeActions(mani *ManifestYAML, manipath string) (ar []
// only set the webaction when the annotations are not empty.
if action.Webexport == "true" {
//wskaction.Annotations = keyValArr
- wskaction.Annotations, err = utils.WebAction("yes", keyValArr, action.Name, false)
- if err != nil {
- return s1, err
- }
+ wskaction.Annotations, errorParser = utils.WebAction("yes", keyValArr, action.Name, false)
+ if errorParser != nil {
+ return s1, errorParser
+ }
}
wskaction.Name = key
pub := false
wskaction.Publish = &pub
- record := utils.ActionRecord{wskaction, mani.Package.Packagename, action.Function}
+ record := utils.ActionRecord{Action: wskaction, Packagename: packageName, Filepath: action.Function}
s1 = append(s1, record)
-
}
return s1, nil
}
-func (dm *YAMLParser) ComposeTriggers(manifest *ManifestYAML, filePath string) ([]*whisk.Trigger, error) {
+func (dm *YAMLParser) ComposeTriggersFromAllPackages(manifest *ManifestYAML, filePath string) ([]*whisk.Trigger, error) {
+ var triggers []*whisk.Trigger = make([]*whisk.Trigger, 0)
+ if manifest.Package.Packagename != "" {
+ return dm.ComposeTriggers(filePath, manifest.Package)
+ } else if manifest.Packages != nil {
+ for _, p := range manifest.Packages {
+ t, err := dm.ComposeTriggers(filePath, p)
+ if err == nil {
+ triggers = append(triggers, t...)
+ } else {
+ return nil, err
+ }
+ }
+ }
+ return triggers, nil
+}
+
+func (dm *YAMLParser) ComposeTriggers(filePath string, pkg Package) ([]*whisk.Trigger, error) {
var errorParser error
var t1 []*whisk.Trigger = make([]*whisk.Trigger, 0)
- pkg := manifest.Package
for _, trigger := range pkg.GetTriggerList() {
wsktrigger := new(whisk.Trigger)
wsktrigger.Name = trigger.Name
@@ -436,29 +504,56 @@ func (dm *YAMLParser) ComposeTriggers(manifest *ManifestYAML, filePath string) (
return t1, nil
}
-func (dm *YAMLParser) ComposeRules(manifest *ManifestYAML) ([]*whisk.Rule, error) {
+func (dm *YAMLParser) ComposeRulesFromAllPackages(manifest *ManifestYAML) ([]*whisk.Rule, error) {
+ var rules []*whisk.Rule = make([]*whisk.Rule, 0)
+ if manifest.Package.Packagename != "" {
+ return dm.ComposeRules(manifest.Package, manifest.Package.Packagename)
+ } else if manifest.Packages != nil {
+ for n, p := range manifest.Packages {
+ r, err := dm.ComposeRules(p, n)
+ if err == nil {
+ rules = append(rules, r...)
+ } else {
+ return nil, err
+ }
+ }
+ }
+ return rules, nil
+}
+
+func (dm *YAMLParser) ComposeRules(pkg Package, packageName string) ([]*whisk.Rule, error) {
var r1 []*whisk.Rule = make([]*whisk.Rule, 0)
- pkg := manifest.Package
for _, rule := range pkg.GetRuleList() {
wskrule := rule.ComposeWskRule()
-
act := strings.TrimSpace(wskrule.Action.(string))
-
- if !strings.ContainsRune(act, '/') && !strings.HasPrefix(act, pkg.Packagename+"/") {
- act = path.Join(pkg.Packagename, act)
+ if !strings.ContainsRune(act, '/') && !strings.HasPrefix(act, packageName+"/") {
+ act = path.Join(packageName, act)
}
-
wskrule.Action = act
-
r1 = append(r1, wskrule)
}
-
return r1, nil
}
-func (dm *YAMLParser) ComposeApiRecords(manifest *ManifestYAML) ([]*whisk.ApiCreateRequest, error) {
- pkg := manifest.Package
+func (dm *YAMLParser) ComposeApiRecordsFromAllPackages(manifest *ManifestYAML) ([]*whisk.ApiCreateRequest, error) {
+ var requests []*whisk.ApiCreateRequest = make([]*whisk.ApiCreateRequest, 0)
+ if manifest.Package.Packagename != "" {
+ return dm.ComposeApiRecords(manifest.Package)
+ } else if manifest.Packages != nil {
+ for _, p := range manifest.Packages {
+ r, err := dm.ComposeApiRecords(p)
+ if err == nil {
+ requests = append(requests, r...)
+ } else {
+ return nil, err
+ }
+ }
+ }
+ return requests, nil
+}
+
+func (dm *YAMLParser) ComposeApiRecords(pkg Package) ([]*whisk.ApiCreateRequest, error) {
var acq []*whisk.ApiCreateRequest = make([]*whisk.ApiCreateRequest, 0)
apis := pkg.GetApis()
for _, api := range apis {
@@ -539,8 +634,8 @@ func ResolveParamTypeFromValue(value interface{}, filePath string) (string, erro
// TODO(): We have information to display to user on an error or warning here
// TODO(): specifically, we have the parameter name, its value to show on error/warning
// TODO(): perhaps this is a different Class of error? e.g., ErrorParameterMismatchError
- lines := []string{"Line Unknown"}
- msgs := []string{"Parameter value is not a known type. ["+actualType+"]"}
+ lines := []string{"Line Unknown"}
+ msgs := []string{"Parameter value is not a known type. [" + actualType + "]"}
err = utils.NewParserErr(filePath, lines, msgs)
}
} else {
@@ -598,8 +693,8 @@ func ResolveParameter(paramName string, param *Parameter, filePath string) (inte
// if we do not have a value or default, but have a type, find its default and use it for the value
if param.Type != "" && !isValidParameterType(param.Type) {
- lines := []string{"Line Unknown"}
- msgs := []string{"Invalid Type for parameter. ["+param.Type+"]"}
+ lines := []string{"Line Unknown"}
+ msgs := []string{"Invalid Type for parameter. [" + param.Type + "]"}
return value, utils.NewParserErr(filePath, lines, msgs)
} else if param.Type == "" {
param.Type = tempType
diff --git a/parsers/manifest_parser_test.go b/parsers/manifest_parser_test.go
index 8858f0f..0dfffcf 100644
--- a/parsers/manifest_parser_test.go
+++ b/parsers/manifest_parser_test.go
@@ -485,7 +485,7 @@ func TestComposeActionsForImplicitRuntimes(t *testing.T) {
// read and parse manifest.yaml file
p := NewYAMLParser()
m, _ := p.ParseManifest(tmpfile.Name())
- actions, err := p.ComposeActions(m, tmpfile.Name())
+ actions, err := p.ComposeActionsFromAllPackages(m, tmpfile.Name())
var expectedResult string
if err == nil {
for i := 0; i < len(actions); i++ {
@@ -527,7 +527,7 @@ func TestComposeActionsForInvalidRuntime(t *testing.T) {
// read and parse manifest.yaml file
p := NewYAMLParser()
m, _ := p.ParseManifest(tmpfile.Name())
- _, err := p.ComposeActions(m, tmpfile.Name())
+ _, err := p.ComposeActionsFromAllPackages(m, tmpfile.Name())
// (TODO) uncomment the following test case after issue #307 is fixed
// (TODO) its failing right now as we are lacking check on invalid runtime
// assert.NotNil(t, err, "Invalid runtime, ComposeActions should report an error")
@@ -546,7 +546,7 @@ func TestComposeActionsForSingleLineParams(t *testing.T) {
// read and parse manifest.yaml file
p := NewYAMLParser()
m, _ := p.ParseManifest(manifestFile)
- actions, err := p.ComposeActions(m, manifestFile)
+ actions, err := p.ComposeActionsFromAllPackages(m, manifestFile)
if err == nil {
// assert that the actions variable has only one action
@@ -631,7 +631,7 @@ func TestComposeActionsForMultiLineParams(t *testing.T) {
// read and parse manifest.yaml file
p := NewYAMLParser()
m, _ := p.ParseManifest(manifestFile)
- actions, err := p.ComposeActions(m, manifestFile)
+ actions, err := p.ComposeActionsFromAllPackages(m, manifestFile)
if err == nil {
// assert that the actions variable has only one action
@@ -711,7 +711,7 @@ func TestComposeActionsForFunction(t *testing.T) {
// read and parse manifest.yaml file
p := NewYAMLParser()
m, _ := p.ParseManifest(tmpfile.Name())
- actions, err := p.ComposeActions(m, tmpfile.Name())
+ actions, err := p.ComposeActionsFromAllPackages(m, tmpfile.Name())
var expectedResult, actualResult string
if err == nil {
for i := 0; i < len(actions); i++ {
@@ -796,7 +796,7 @@ func TestComposeActionsForWebActions(t *testing.T) {
// read and parse manifest.yaml file
p := NewYAMLParser()
m, _ := p.ParseManifest(tmpfile.Name())
- actions, err := p.ComposeActions(m, tmpfile.Name())
+ actions, err := p.ComposeActionsFromAllPackages(m, tmpfile.Name())
if err == nil {
for i := 0; i < len(actions); i++ {
if actions[i].Action.Name == "hello" {
@@ -906,10 +906,12 @@ func TestComposePackage(t *testing.T) {
// read and parse manifest.yaml file
p := NewYAMLParser()
m, _ := p.ParseManifest(tmpfile.Name())
- pkg, err := p.ComposePackage(m, tmpfile.Name())
+ pkg, err := p.ComposeAllPackages(m, tmpfile.Name())
if err == nil {
- assert.Equal(t, "helloworld", pkg.Name, "Failed to get package name")
- assert.Equal(t, "default", pkg.Namespace, "Failed to get package namespace")
+ n := "helloworld"
+ assert.NotNil(t, pkg[n], "Failed to get the whole package")
+ assert.Equal(t, n, pkg[n].Name, "Failed to get package name")
+ assert.Equal(t, "default", pkg[n].Namespace, "Failed to get package namespace")
} else {
assert.Fail(t, "Failed to compose package")
}
@@ -934,7 +936,7 @@ func TestComposeSequences(t *testing.T) {
// read and parse manifest.yaml file
p := NewYAMLParser()
m, _ := p.ParseManifest(tmpfile.Name())
- seqList, err := p.ComposeSequences("", m)
+ seqList, err := p.ComposeSequencesFromAllPackages("", m)
if err != nil {
assert.Fail(t, "Failed to compose sequences")
}
@@ -981,7 +983,7 @@ func TestComposeTriggers(t *testing.T) {
// read and parse manifest.yaml file
p := NewYAMLParser()
m, _ := p.ParseManifest(tmpfile.Name())
- triggerList, err := p.ComposeTriggers(m, tmpfile.Name())
+ triggerList, err := p.ComposeTriggersFromAllPackages(m, tmpfile.Name())
if err != nil {
assert.Fail(t, "Failed to compose trigger")
}
@@ -1020,7 +1022,7 @@ func TestComposeRules(t *testing.T) {
// read and parse manifest.yaml file
p := NewYAMLParser()
m, _ := p.ParseManifest(tmpfile.Name())
- ruleList, err := p.ComposeRules(m)
+ ruleList, err := p.ComposeRulesFromAllPackages(m)
if err != nil {
assert.Fail(t, "Failed to compose rules")
}
@@ -1066,7 +1068,7 @@ func TestComposeApiRecords(t *testing.T) {
// read and parse manifest.yaml file
p := NewYAMLParser()
m, _ := p.ParseManifest(tmpfile.Name())
- apiList, err := p.ComposeApiRecords(m)
+ apiList, err := p.ComposeApiRecordsFromAllPackages(m)
if err != nil {
assert.Fail(t, "Failed to compose api records")
}
@@ -1221,4 +1223,78 @@ func TestMissingRootValueManifestYaml(t *testing.T) {
_, err = p.ParseManifest(tmpfile.Name())
assert.NotNil(t, err)
assert.Contains(t, err.Error(), "field actions not found in struct parsers.ManifestYAML: Line 1, its neighbour lines, or the lines on the same level")
+
+}
+
+// validate manifest_parser:Unmarshal() method for package in manifest YAML
+// validate that manifest_parser is able to read and parse the manifest data
+func TestUnmarshalForPackages(t *testing.T) {
+ data := `
+packages:
+ package1:
+ actions:
+ helloNodejs:
+ function: actions/hello.js
+ runtime: nodejs:6
+ package2:
+ actions:
+ helloPython:
+ function: actions/hello.py
+ runtime: python`
+ // set the zero value of struct ManifestYAML
+ m := ManifestYAML{}
+ // Unmarshal reads/parses manifest data and sets the values of ManifestYAML
+ // And returns an error if parsing a manifest data fails
+ err := NewYAMLParser().Unmarshal([]byte(data), &m)
+ if err == nil {
+ expectedResult := string(2)
+ actualResult := string(len(m.Packages))
+ assert.Equal(t, expectedResult, actualResult, "Expected 2 packages but got " + actualResult)
+ // we have two packages
+ // package name should be "helloNodejs" and "helloPython"
+ for k, v := range m.Packages {
+ switch k {
+ case "package1":
+ assert.Equal(t, "package1", k, "Expected package name package1 but got " + k)
+ expectedResult = string(1)
+ actualResult = string(len(v.Actions))
+ assert.Equal(t, expectedResult, actualResult, "Expected 1 but got " + actualResult)
+ // get the action payload from the map of actions which is stored in
+ // ManifestYAML.Package.Actions with the type of map[string]Action
+ actionName := "helloNodejs"
+ if action, ok := v.Actions[actionName]; ok {
+ // location/function of an action should be "actions/hello.js"
+ expectedResult = "actions/hello.js"
+ actualResult = action.Function
+ assert.Equal(t, expectedResult, actualResult, "Expected action function " + expectedResult + " but got " + actualResult)
+ // runtime of an action should be "nodejs:6"
+ expectedResult = "nodejs:6"
+ actualResult = action.Runtime
+ assert.Equal(t, expectedResult, actualResult, "Expected action runtime " + expectedResult + " but got " + actualResult)
+ } else {
+ t.Error("Action named " + actionName + " does not exist.")
+ }
+ case "package2":
+ assert.Equal(t, "package2", k, "Expected package name package2 but got " + k)
+ expectedResult = string(1)
+ actualResult = string(len(v.Actions))
+ assert.Equal(t, expectedResult, actualResult, "Expected 1 but got " + actualResult)
+ // get the action payload from the map of actions which is stored in
+ // ManifestYAML.Package.Actions with the type of map[string]Action
+ actionName := "helloPython"
+ if action, ok := v.Actions[actionName]; ok {
+ // location/function of an action should be "actions/hello.js"
+ expectedResult = "actions/hello.py"
+ actualResult = action.Function
+ assert.Equal(t, expectedResult, actualResult, "Expected action function " + expectedResult + " but got " + actualResult)
+ // runtime of an action should be "python"
+ expectedResult = "python"
+ actualResult = action.Runtime
+ assert.Equal(t, expectedResult, actualResult, "Expected action runtime " + expectedResult + " but got " + actualResult)
+ } else {
+ t.Error("Action named " + actionName + " does not exist.")
+ }
+ }
+ }
+ }
}
diff --git a/parsers/yamlparser.go b/parsers/yamlparser.go
index 2005801..a856396 100644
--- a/parsers/yamlparser.go
+++ b/parsers/yamlparser.go
@@ -173,6 +173,7 @@ type DeploymentYAML struct {
type ManifestYAML struct {
Package Package `yaml:"package"` //used in both manifest.yaml and deployment.yaml
+ Packages map[string]Package `yaml:"packages"`
Filepath string //file path of the yaml file
}
diff --git a/tests/src/integration/validate-packages-in-manifest/actions/hello.jar b/tests/src/integration/validate-packages-in-manifest/actions/hello.jar
new file mode 100644
index 0000000..4b4e55c
Binary files /dev/null and b/tests/src/integration/validate-packages-in-manifest/actions/hello.jar differ
diff --git a/tests/src/integration/validate-packages-in-manifest/actions/hello.js b/tests/src/integration/validate-packages-in-manifest/actions/hello.js
new file mode 100644
index 0000000..25fdafb
--- /dev/null
+++ b/tests/src/integration/validate-packages-in-manifest/actions/hello.js
@@ -0,0 +1,26 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * Return a simple greeting message for the whole world.
+ */
+function main(params) {
+ msg = "Hello, " + params.name + " from " + params.place;
+ console.log(msg)
+ return { payload: msg };
+}
+
diff --git a/tests/src/integration/validate-packages-in-manifest/actions/hello.py b/tests/src/integration/validate-packages-in-manifest/actions/hello.py
new file mode 100644
index 0000000..44c3bd1
--- /dev/null
+++ b/tests/src/integration/validate-packages-in-manifest/actions/hello.py
@@ -0,0 +1,23 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# * this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# * the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+def main(args):
+ name = args.get("name", "stranger")
+ greeting = "Hello " + name + "!"
+ print(greeting)
+ return {"greeting": greeting}
+
diff --git a/tests/src/integration/validate-packages-in-manifest/deployment.yaml b/tests/src/integration/validate-packages-in-manifest/deployment.yaml
new file mode 100644
index 0000000..5ee0f75
--- /dev/null
+++ b/tests/src/integration/validate-packages-in-manifest/deployment.yaml
@@ -0,0 +1,26 @@
+application:
+ name: IntegrationTest
+ packages:
+ packageNodeJS:
+ actions:
+ helloNodejs-1:
+ inputs:
+ name: Amy
+ place: Paris
+ helloNodejs-3:
+ inputs:
+ name: Arthur
+ place: Hawaii
+ packagePython:
+ actions:
+ helloPython-1:
+ inputs:
+ name: Henry
+ helloPython-2:
+ inputs:
+ name: Alex
+ packageJava:
+ actions:
+ helloJava-1:
+ inputs:
+ name: Bob
diff --git a/tests/src/integration/validate-packages-in-manifest/manifest.yaml b/tests/src/integration/validate-packages-in-manifest/manifest.yaml
new file mode 100644
index 0000000..81679f6
--- /dev/null
+++ b/tests/src/integration/validate-packages-in-manifest/manifest.yaml
@@ -0,0 +1,112 @@
+packages:
+ packageNodeJS:
+ actions:
+ helloNodejs-1:
+ function: actions/hello.js
+ runtime: nodejs:6
+ inputs:
+ name:
+ type: string
+ description: name of a person
+ place:
+ type: string
+ description: location of a person
+ outputs:
+ payload:
+ type: string
+ description: a simple greeting message, Hello World!
+ helloNodejs-2:
+ function: actions/hello.js
+ runtime: nodejs:6
+ helloNodejs-3:
+ function: actions/hello.js
+ runtime: nodejs:6
+ inputs:
+ name:
+ type: string
+ description: name of a person
+ place:
+ type: string
+ description: location of a person
+ sequences:
+ helloworldnodejs-series:
+ actions: helloNodejs-1, helloNodejs-2, helloNodejs-3
+ triggers:
+ triggerNodeJS:
+ rules:
+ ruleNodeJS:
+ trigger: triggerNodeJS
+ action: helloworldnodejs-series
+ packagePython:
+ actions:
+ helloPython-1:
+ function: actions/hello.py
+ runtime: python
+ inputs:
+ name:
+ type: string
+ description: name of a person
+ outputs:
+ payload:
+ type: string
+ description: a simple greeting message, Hello Henry!
+ helloPython-2:
+ function: actions/hello.py
+ runtime: python
+ inputs:
+ name:
+ type: string
+ description: name of a person
+ outputs:
+ payload:
+ type: string
+ description: a simple greeting message, Hello Alex!
+ helloPython-3:
+ function: actions/hello.py
+ runtime: python
+ sequences:
+ helloworldpython-series:
+ actions: helloPython-1, helloPython-2, helloPython-3
+ triggers:
+ triggerPython:
+ rules:
+ rulePython:
+ trigger: triggerPython
+ action: helloworldpython-series
+ packageJava:
+ actions:
+ helloJava-1:
+ function: actions/hello.jar
+ runtime: java
+ main: Hello
+ inputs:
+ name:
+ type: string
+ description: name of a person
+ outputs:
+ payload:
+ type: string
+ description: a simple greeting message, Hello Bob!
+ helloJava-2:
+ function: actions/hello.jar
+ runtime: java
+ main: Hello
+ helloJava-3:
+ function: actions/hello.jar
+ runtime: java
+ main: Hello
+ triggers:
+ triggerJava:
+ rules:
+ ruleJava:
+ trigger: triggerJava
+ action: helloJava-1
+ packageBuggy:
+ actions:
+ helloJava-1:
+ function: actions/hello.jar
+ runtime: java
+ main: Hello
+ triggers:
+ triggerJava:
+
diff --git a/tests/src/integration/validate-packages-in-manifest/validate-packages-in-manifest_test.go b/tests/src/integration/validate-packages-in-manifest/validate-packages-in-manifest_test.go
new file mode 100644
index 0000000..08c2e56
--- /dev/null
+++ b/tests/src/integration/validate-packages-in-manifest/validate-packages-in-manifest_test.go
@@ -0,0 +1,40 @@
+// +build integration
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package tests
+
+import (
+ "github.com/apache/incubator-openwhisk-wskdeploy/tests/src/integration/common"
+ "github.com/stretchr/testify/assert"
+ "os"
+ "testing"
+)
+
+func TestPackagesInManifest(t *testing.T) {
+ wskdeploy := common.NewWskdeploy()
+ _, err := wskdeploy.Deploy(manifestPath, deploymentPath)
+ assert.Equal(t, nil, err, "Failed to deploy based on the manifest and deployment files.")
+ _, err = wskdeploy.Undeploy(manifestPath, deploymentPath)
+ assert.Equal(t, nil, err, "Failed to undeploy based on the manifest and deployment files.")
+}
+
+var (
+ manifestPath = os.Getenv("GOPATH") + "/src/github.com/apache/incubator-openwhisk-wskdeploy/tests/src/integration/validate-packages-in-manifest/manifest.yaml"
+ deploymentPath = os.Getenv("GOPATH") + "/src/github.com/apache/incubator-openwhisk-wskdeploy/tests/src/integration/validate-packages-in-manifest/deployment.yaml"
+)
--
To stop receiving notification emails like this one, please contact
['"commits@openwhisk.apache.org" <co...@openwhisk.apache.org>'].