You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openwhisk.apache.org by mr...@apache.org on 2018/04/10 20:28:19 UTC
[incubator-openwhisk-wskdeploy] branch master updated: Refactoring
ManifestReader (#863)
This is an automated email from the ASF dual-hosted git repository.
mrutkowski 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 de4e3d8 Refactoring ManifestReader (#863)
de4e3d8 is described below
commit de4e3d80046ef691d91c4bf24b462c39916f5195
Author: Priti Desai <pd...@us.ibm.com>
AuthorDate: Tue Apr 10 13:28:16 2018 -0700
Refactoring ManifestReader (#863)
* cleaning up manifestreader
* adding error messages to wski18n
* adding integration test on actions
* Adding trigger tests
* adding error message for trigger
* adding rule test
* fixing integration test
* fixing integration test
* integration test fix
* dropping doc on errors
---
cmd/root.go | 16 +-
deployers/manifestreader.go | 290 ++++++++-----------
deployers/manifestreader_test.go | 319 ++++++++++++++++++++-
deployers/servicedeployer.go | 2 -
parsers/manifest_parser.go | 6 +-
tests/dat/manifest_validate_action_all.yaml | 43 +++
tests/dat/manifest_validate_dependencies.yaml | 42 +++
.../dat/manifest_validate_dependencies_bogus.yaml | 42 +++
...st_validate_package_inputs_and_annotations.yaml | 37 +++
tests/dat/manifest_validate_rules_bogus.yaml | 41 +++
tests/dat/manifest_validate_sequences_bogus.yaml | 38 +++
tests/dat/manifest_validate_triggers_bogus.yaml | 33 +++
utils/dependencies.go | 10 +
utils/gitreader.go | 1 -
wski18n/i18n_ids.go | 47 +--
wski18n/i18n_resources.go | 4 +-
wski18n/resources/en_US.all.json | 24 ++
17 files changed, 777 insertions(+), 218 deletions(-)
diff --git a/cmd/root.go b/cmd/root.go
index 77b2e03..4d665dd 100644
--- a/cmd/root.go
+++ b/cmd/root.go
@@ -150,7 +150,7 @@ func loadDefaultDeploymentFileFromProjectPath(command string, projectPath string
} else if _, err := os.Stat(path.Join(projectPath, utils.DeploymentFileNameYml)); err == nil {
utils.Flags.DeploymentPath = path.Join(projectPath, utils.DeploymentFileNameYml)
}
- displayCommandUsingFilenameMessage(command, wski18n.DEPLOYMENT_FILE, utils.Flags.ManifestPath)
+ displayCommandUsingFilenameMessage(command, wski18n.DEPLOYMENT_FILE, utils.Flags.DeploymentPath)
return nil
}
@@ -167,14 +167,19 @@ func Deploy() error {
projectPath, _ := filepath.Abs(project_Path)
// If manifest filename is not provided, attempt to load default manifests from project path
+ // default manifests are manifest.yaml and manifest.yml
+ // return failure if none of the default manifest files were found
if utils.Flags.ManifestPath == "" {
if err := loadDefaultManifestFileFromProjectPath(wski18n.CMD_DEPLOY, projectPath); err != nil {
return err
}
}
+ // If deployment filename is not provided, attempt to load default deployment files from project path
+ // default deployments are deployment.yaml and deployment.yml
+ // continue processing manifest file, even if none of the default
+ // deployment files were found as deployment files are optional
if utils.Flags.DeploymentPath == "" {
-
if err := loadDefaultDeploymentFileFromProjectPath(wski18n.CMD_DEPLOY, projectPath); err != nil {
return err
}
@@ -182,7 +187,9 @@ func Deploy() error {
if utils.MayExists(utils.Flags.ManifestPath) {
+ // Create an instance of ServiceDeployer
var deployer = deployers.NewServiceDeployer()
+ // Set Project Path, Manifest Path, and Deployment Path of ServiceDeployer
deployer.ProjectPath = projectPath
deployer.ManifestPath = utils.Flags.ManifestPath
deployer.DeploymentPath = utils.Flags.DeploymentPath
@@ -191,6 +198,7 @@ func Deploy() error {
// master record of any dependency that has been downloaded
deployer.DependencyMaster = make(map[string]utils.DependencyRecord)
+ // Read credentials from Configuration file, manifest file or deployment file
clientConfig, error := deployers.NewWhiskConfig(
utils.Flags.CfgFile,
utils.Flags.DeploymentPath,
@@ -210,14 +218,14 @@ func Deploy() error {
// The auth, apihost and namespace have been chosen, so that we can check the supported runtimes here.
setSupportedRuntimes(clientConfig.Host)
+ // Construct Deployment Plan
err := deployer.ConstructDeploymentPlan()
-
if err != nil {
return err
}
+ // Deploy all OW entities
err = deployer.Deploy()
-
if err != nil {
return err
} else {
diff --git a/deployers/manifestreader.go b/deployers/manifestreader.go
index 1f9171d..c19fd68 100644
--- a/deployers/manifestreader.go
+++ b/deployers/manifestreader.go
@@ -18,13 +18,14 @@
package deployers
import (
- "errors"
"strings"
+ "fmt"
"github.com/apache/incubator-openwhisk-client-go/whisk"
"github.com/apache/incubator-openwhisk-wskdeploy/parsers"
"github.com/apache/incubator-openwhisk-wskdeploy/utils"
"github.com/apache/incubator-openwhisk-wskdeploy/wskderrors"
+ "github.com/apache/incubator-openwhisk-wskdeploy/wski18n"
)
var clientConfig *whisk.Config
@@ -58,32 +59,31 @@ func (reader *ManifestReader) InitPackages(manifestParser *parsers.YAMLParser, m
return err
}
reader.SetPackages(packages)
-
return nil
}
// Wrapper parser to handle yaml dir
-func (deployer *ManifestReader) HandleYaml(sdeployer *ServiceDeployer, manifestParser *parsers.YAMLParser, manifest *parsers.YAML, managedAnnotations whisk.KeyValue) error {
+func (reader *ManifestReader) HandleYaml(sdeployer *ServiceDeployer, manifestParser *parsers.YAMLParser, manifest *parsers.YAML, managedAnnotations whisk.KeyValue) error {
var err error
var manifestName = manifest.Filepath
- deps, err := manifestParser.ComposeDependenciesFromAllPackages(manifest, deployer.serviceDeployer.ProjectPath, deployer.serviceDeployer.ManifestPath, managedAnnotations)
+ deps, err := manifestParser.ComposeDependenciesFromAllPackages(manifest, reader.serviceDeployer.ProjectPath, reader.serviceDeployer.ManifestPath, managedAnnotations)
if err != nil {
return wskderrors.NewYAMLFileFormatError(manifestName, err)
}
- actions, err := manifestParser.ComposeActionsFromAllPackages(manifest, deployer.serviceDeployer.ManifestPath, managedAnnotations)
+ actions, err := manifestParser.ComposeActionsFromAllPackages(manifest, reader.serviceDeployer.ManifestPath, managedAnnotations)
if err != nil {
return wskderrors.NewYAMLFileFormatError(manifestName, err)
}
- sequences, err := manifestParser.ComposeSequencesFromAllPackages(deployer.serviceDeployer.ClientConfig.Namespace, manifest, deployer.serviceDeployer.ManifestPath, managedAnnotations)
+ sequences, err := manifestParser.ComposeSequencesFromAllPackages(reader.serviceDeployer.ClientConfig.Namespace, manifest, reader.serviceDeployer.ManifestPath, managedAnnotations)
if err != nil {
return wskderrors.NewYAMLFileFormatError(manifestName, err)
}
- triggers, err := manifestParser.ComposeTriggersFromAllPackages(manifest, deployer.serviceDeployer.ManifestPath, managedAnnotations)
+ triggers, err := manifestParser.ComposeTriggersFromAllPackages(manifest, reader.serviceDeployer.ManifestPath, managedAnnotations)
if err != nil {
return wskderrors.NewYAMLFileFormatError(manifestName, err)
}
@@ -93,37 +93,37 @@ func (deployer *ManifestReader) HandleYaml(sdeployer *ServiceDeployer, manifestP
return wskderrors.NewYAMLFileFormatError(manifestName, err)
}
- apis, err := manifestParser.ComposeApiRecordsFromAllPackages(deployer.serviceDeployer.ClientConfig, manifest)
+ apis, err := manifestParser.ComposeApiRecordsFromAllPackages(reader.serviceDeployer.ClientConfig, manifest)
if err != nil {
return wskderrors.NewYAMLFileFormatError(manifestName, err)
}
- err = deployer.SetDependencies(deps)
+ err = reader.SetDependencies(deps)
if err != nil {
return wskderrors.NewYAMLFileFormatError(manifestName, err)
}
- err = deployer.SetActions(actions)
+ err = reader.SetActions(actions)
if err != nil {
return wskderrors.NewYAMLFileFormatError(manifestName, err)
}
- err = deployer.SetSequences(sequences)
+ err = reader.SetSequences(sequences)
if err != nil {
return wskderrors.NewYAMLFileFormatError(manifestName, err)
}
- err = deployer.SetTriggers(triggers)
+ err = reader.SetTriggers(triggers)
if err != nil {
return wskderrors.NewYAMLFileFormatError(manifestName, err)
}
- err = deployer.SetRules(rules)
+ err = reader.SetRules(rules)
if err != nil {
return wskderrors.NewYAMLFileFormatError(manifestName, err)
}
- err = deployer.SetApis(apis)
+ err = reader.SetApis(apis)
if err != nil {
return wskderrors.NewYAMLFileFormatError(manifestName, err)
}
@@ -131,36 +131,6 @@ func (deployer *ManifestReader) HandleYaml(sdeployer *ServiceDeployer, manifestP
return nil
}
-func (reader *ManifestReader) SetDependencies(deps map[string]utils.DependencyRecord) error {
- for name, dep := range deps {
- n := strings.Split(name, ":")
- depName := n[1]
- if depName == "" {
- return nil
- }
- if !dep.IsBinding && !reader.IsUndeploy {
- if _, exists := reader.serviceDeployer.DependencyMaster[depName]; !exists {
- // dependency
- gitReader := utils.NewGitReader(depName, dep)
- err := gitReader.CloneDependency()
- if err != nil {
- return wskderrors.NewYAMLFileFormatError(depName, err)
- }
- } 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.
- }
- }
-
- // store in two places (one local to package to preserve relationship, one in master record to check for conflics
- reader.serviceDeployer.Deployment.Packages[dep.Packagename].Dependencies[depName] = dep
- reader.serviceDeployer.DependencyMaster[depName] = dep
-
- }
-
- return nil
-}
-
func (reader *ManifestReader) SetPackages(packages map[string]*whisk.Package) error {
dep := reader.serviceDeployer
@@ -169,13 +139,6 @@ func (reader *ManifestReader) SetPackages(packages map[string]*whisk.Package) er
defer dep.mt.Unlock()
for _, pkg := range packages {
- _, exist := dep.Deployment.Packages[pkg.Name]
- if exist {
- // TODO(): i18n of error message (or create a new named error)
- // TODO(): Is there a better way to handle an existing dependency of same name?
- err := errors.New("Package [" + pkg.Name + "] exists already.")
- return wskderrors.NewYAMLParserErr(reader.serviceDeployer.ManifestPath, err)
- }
newPack := NewDeploymentPackage()
newPack.Package = pkg
dep.Deployment.Packages[pkg.Name] = newPack
@@ -183,126 +146,78 @@ func (reader *ManifestReader) SetPackages(packages map[string]*whisk.Package) er
return nil
}
-func (reader *ManifestReader) SetActions(actions []utils.ActionRecord) error {
+func (reader *ManifestReader) SetDependencies(deps map[string]utils.DependencyRecord) error {
dep := reader.serviceDeployer
dep.mt.Lock()
defer dep.mt.Unlock()
- for _, manifestAction := range actions {
- existAction, exists := reader.serviceDeployer.Deployment.Packages[manifestAction.Packagename].Actions[manifestAction.Action.Name]
-
- if exists == true {
- if existAction.Filepath == manifestAction.Filepath || manifestAction.Filepath == "" {
- // we're adding a filesystem detected action so just updated code and filepath if needed
- if manifestAction.Action.Exec.Kind != "" {
- existAction.Action.Exec.Kind = manifestAction.Action.Exec.Kind
- }
-
- if manifestAction.Action.Exec.Code != nil {
- code := *manifestAction.Action.Exec.Code
- if code != "" {
- existAction.Action.Exec.Code = manifestAction.Action.Exec.Code
- }
- }
-
- existAction.Action.Annotations = manifestAction.Action.Annotations
- existAction.Action.Limits = manifestAction.Action.Limits
- existAction.Action.Parameters = manifestAction.Action.Parameters
- existAction.Action.Version = manifestAction.Action.Version
-
- if manifestAction.Filepath != "" {
- existAction.Filepath = manifestAction.Filepath
- }
-
- err := reader.checkAction(existAction)
- if err != nil {
- return wskderrors.NewFileReadError(manifestAction.Filepath, err)
+ for name, dependency := range deps {
+ // name is <packagename>:<dependencylabel>
+ depName := strings.Split(name, ":")[1]
+ if len(depName) == 0 {
+ return nil
+ }
+ if !dependency.IsBinding && !reader.IsUndeploy {
+ if _, exists := dep.DependencyMaster[depName]; exists {
+ if !utils.CompareDependencyRecords(dep.DependencyMaster[depName], dependency) {
+ location := strings.Join([]string{dep.DependencyMaster[depName].Location, dependency.Location}, ",")
+ errmsg := wski18n.T(wski18n.ID_ERR_DEPENDENCIES_WITH_SAME_LABEL_X_dependency_X_location_X,
+ map[string]interface{}{wski18n.KEY_DEPENDENCY: depName,
+ wski18n.KEY_LOCATION: location})
+ return wskderrors.NewYAMLParserErr(dep.ManifestPath, errmsg)
}
-
- } else {
- // Action exists, but references two different sources
- // TODO(): i18n of error message (or create a new named error)
- err := errors.New("Conflict detected for action named [" +
- existAction.Action.Name + "].\nFound two locations for source file: [" +
- existAction.Filepath + "] and [" + manifestAction.Filepath + "]")
- return wskderrors.NewYAMLParserErr(reader.serviceDeployer.ManifestPath, err)
}
- } else {
- // not a new action so update the action in the package
- err := reader.checkAction(manifestAction)
+ gitReader := utils.NewGitReader(depName, dependency)
+ err := gitReader.CloneDependency()
if err != nil {
- return wskderrors.NewFileReadError(manifestAction.Filepath, err)
+ return err
}
- reader.serviceDeployer.Deployment.Packages[manifestAction.Packagename].Actions[manifestAction.Action.Name] = manifestAction
}
+ // store in two places (one local to package to preserve relationship, one in master record to check for conflics
+ dep.Deployment.Packages[dependency.Packagename].Dependencies[depName] = dependency
+ dep.DependencyMaster[depName] = dependency
}
return nil
}
-// TODO create named errors
-// Check action record before deploying it
-// action record is created by reading and composing action elements from manifest file
-// Action.kind is mandatory which is set to
-// (1) action runtime for an action and (2) set to "sequence" for a sequence
-// Also, action executable code should be specified for any action
-func (reader *ManifestReader) checkAction(action utils.ActionRecord) error {
- if action.Action.Exec.Kind == "" {
- // TODO(): i18n of error message (or create a new named error)
- err := errors.New("Action [" + action.Action.Name + "] has no kind set.")
- return wskderrors.NewYAMLParserErr(reader.serviceDeployer.ManifestPath, err)
- }
+func (reader *ManifestReader) SetActions(actions []utils.ActionRecord) error {
- if action.Action.Exec.Code != nil {
- code := *action.Action.Exec.Code
- if code == "" && action.Action.Exec.Kind != parsers.YAML_KEY_SEQUENCE {
- // TODO(): i18n of error message (or create a new named error)
- err := errors.New("Action [" + action.Action.Name + "] has no source code.")
- return wskderrors.NewYAMLParserErr(reader.serviceDeployer.ManifestPath, err)
+ dep := reader.serviceDeployer
+
+ dep.mt.Lock()
+ defer dep.mt.Unlock()
+
+ for _, manifestAction := range actions {
+ err := reader.checkAction(manifestAction)
+ if err != nil {
+ return err
}
+ dep.Deployment.Packages[manifestAction.Packagename].Actions[manifestAction.Action.Name] = manifestAction
}
-
return nil
}
-func (reader *ManifestReader) SetSequences(actions []utils.ActionRecord) error {
+func (reader *ManifestReader) SetSequences(sequences []utils.ActionRecord) error {
dep := reader.serviceDeployer
dep.mt.Lock()
defer dep.mt.Unlock()
- for _, seqAction := range actions {
- // check if the sequence action is exist in actions
- // If the sequence action exists in actions, return error
- _, exists := reader.serviceDeployer.Deployment.Packages[seqAction.Packagename].Actions[seqAction.Action.Name]
- if exists == true {
- // TODO(798): i18n of error message (or create a new named error)
- err := errors.New("Sequence action's name [" +
- seqAction.Action.Name + "] is already used by an action.")
+ for _, sequence := range sequences {
+ // If the sequence name matches with any of the actions defined, return error
+ if _, exists := dep.Deployment.Packages[sequence.Packagename].Actions[sequence.Action.Name]; exists {
+ err := wski18n.T(wski18n.ID_ERR_SEQUENCE_HAVING_SAME_NAME_AS_ACTION_X_action_X,
+ map[string]interface{}{wski18n.KEY_SEQUENCE: sequence.Action.Name})
return wskderrors.NewYAMLParserErr(reader.serviceDeployer.ManifestPath, err)
}
- existAction, exists := reader.serviceDeployer.Deployment.Packages[seqAction.Packagename].Sequences[seqAction.Action.Name]
-
- if exists == true {
- existAction.Action.Annotations = seqAction.Action.Annotations
- existAction.Action.Exec.Kind = "sequence"
- existAction.Action.Exec.Components = seqAction.Action.Exec.Components
- existAction.Action.Publish = seqAction.Action.Publish
- existAction.Action.Namespace = seqAction.Action.Namespace
- existAction.Action.Limits = seqAction.Action.Limits
- existAction.Action.Parameters = seqAction.Action.Parameters
- existAction.Action.Version = seqAction.Action.Version
- } else {
- // not a new action so update the action in the package
- err := reader.checkAction(seqAction)
- if err != nil {
- // TODO() Need a better error type here
- return wskderrors.NewFileReadError(seqAction.Filepath, err)
- }
- reader.serviceDeployer.Deployment.Packages[seqAction.Packagename].Sequences[seqAction.Action.Name] = seqAction
+ err := reader.checkAction(sequence)
+ if err != nil {
+ return err
}
+ dep.Deployment.Packages[sequence.Packagename].Sequences[sequence.Action.Name] = sequence
}
return nil
@@ -317,19 +232,29 @@ func (reader *ManifestReader) SetTriggers(triggers []*whisk.Trigger) error {
defer dep.mt.Unlock()
for _, trigger := range triggers {
- existTrigger, exist := dep.Deployment.Triggers[trigger.Name]
- if exist {
- existTrigger.Name = trigger.Name
- existTrigger.ActivationId = trigger.ActivationId
- existTrigger.Namespace = trigger.Namespace
- existTrigger.Annotations = trigger.Annotations
- existTrigger.Version = trigger.Version
- existTrigger.Parameters = trigger.Parameters
- existTrigger.Publish = trigger.Publish
- } else {
- dep.Deployment.Triggers[trigger.Name] = trigger
+ if _, exists := dep.Deployment.Triggers[trigger.Name]; exists {
+ var feed string
+ var existingFeed string
+ for _, a := range dep.Deployment.Triggers[trigger.Name].Annotations {
+ if a.Key == parsers.YAML_KEY_FEED {
+ existingFeed = a.Value.(string)
+ }
+ }
+ for _, a := range trigger.Annotations {
+ if a.Key == parsers.YAML_KEY_FEED {
+ feed = a.Value.(string)
+ }
+ }
+ if feed != existingFeed {
+ feed = fmt.Sprintf("%q", feed)
+ existingFeed = fmt.Sprintf("%q", existingFeed)
+ err := wski18n.T(wski18n.ID_ERR_CONFLICTING_TRIGGERS_ACROSS_PACKAGES_X_trigger_X_feed_X,
+ map[string]interface{}{wski18n.KEY_TRIGGER: trigger.Name,
+ wski18n.KEY_TRIGGER_FEED: strings.Join([]string{feed, existingFeed}, ", ")})
+ return wskderrors.NewYAMLParserErr(reader.serviceDeployer.ManifestPath, err)
+ }
}
-
+ dep.Deployment.Triggers[trigger.Name] = trigger
}
return nil
}
@@ -341,19 +266,24 @@ func (reader *ManifestReader) SetRules(rules []*whisk.Rule) error {
defer dep.mt.Unlock()
for _, rule := range rules {
- existRule, exist := dep.Deployment.Rules[rule.Name]
- if exist {
- existRule.Name = rule.Name
- existRule.Publish = rule.Publish
- existRule.Version = rule.Version
- existRule.Namespace = rule.Namespace
- existRule.Action = rule.Action
- existRule.Trigger = rule.Trigger
- existRule.Status = rule.Status
- } else {
- dep.Deployment.Rules[rule.Name] = rule
+ if _, exists := dep.Deployment.Rules[rule.Name]; exists {
+ action := rule.Action.(string)
+ existingAction := dep.Deployment.Rules[rule.Name].Action.(string)
+ trigger := rule.Trigger.(string)
+ existingTrigger := dep.Deployment.Rules[rule.Name].Trigger.(string)
+ if action != existingAction || trigger != existingTrigger {
+ action = fmt.Sprintf("%q", action)
+ existingAction = fmt.Sprintf("%q", existingAction)
+ trigger = fmt.Sprintf("%q", trigger)
+ existingTrigger = fmt.Sprintf("%q", existingTrigger)
+ err := wski18n.T(wski18n.ID_ERR_CONFLICTING_RULES_ACROSS_PACKAGES_X_rule_X_action_X_trigger_X,
+ map[string]interface{}{wski18n.KEY_RULE: rule.Name,
+ wski18n.KEY_TRIGGER: strings.Join([]string{trigger, existingTrigger}, ", "),
+ wski18n.KEY_ACTION: strings.Join([]string{action, existingAction}, ", ")})
+ return wskderrors.NewYAMLParserErr(reader.serviceDeployer.ManifestPath, err)
+ }
}
-
+ dep.Deployment.Rules[rule.Name] = rule
}
return nil
}
@@ -365,13 +295,31 @@ func (reader *ManifestReader) SetApis(ar []*whisk.ApiCreateRequest) error {
defer dep.mt.Unlock()
for _, api := range ar {
- existApi, exist := dep.Deployment.Apis[api.ApiDoc.Action.Name]
- if exist {
- existApi.ApiDoc.ApiName = api.ApiDoc.ApiName
- } else {
- dep.Deployment.Apis[api.ApiDoc.Action.Name] = api
- }
+ dep.Deployment.Apis[api.ApiDoc.Action.Name] = api
+ }
+ return nil
+}
+// Check action record before deploying it
+// action record is created by reading and composing action elements from manifest file
+// Action.kind is mandatory which is set to
+// (1) action runtime for an action and (2) set to "sequence" for a sequence
+// Also, action executable code should be specified for any action
+func (reader *ManifestReader) checkAction(action utils.ActionRecord) error {
+ if action.Action.Exec.Kind == "" {
+ err := wski18n.T(wski18n.ID_ERR_ACTION_WITHOUT_KIND_X_action_X,
+ map[string]interface{}{wski18n.KEY_ACTION: action.Action.Name})
+ return wskderrors.NewYAMLParserErr(reader.serviceDeployer.ManifestPath, err)
+ }
+
+ if action.Action.Exec.Code != nil {
+ code := *action.Action.Exec.Code
+ if code == "" && action.Action.Exec.Kind != parsers.YAML_KEY_SEQUENCE {
+ err := wski18n.T(wski18n.ID_ERR_ACTION_WITHOUT_SOURCE_X_action_X,
+ map[string]interface{}{wski18n.KEY_ACTION: action.Action.Name})
+ return wskderrors.NewYAMLParserErr(reader.serviceDeployer.ManifestPath, err)
+ }
}
+
return nil
}
diff --git a/deployers/manifestreader_test.go b/deployers/manifestreader_test.go
index 7d5acbc..bf2e439 100644
--- a/deployers/manifestreader_test.go
+++ b/deployers/manifestreader_test.go
@@ -20,38 +20,327 @@
package deployers
import (
+ "fmt"
+ "testing"
+
"github.com/apache/incubator-openwhisk-client-go/whisk"
"github.com/apache/incubator-openwhisk-wskdeploy/parsers"
"github.com/apache/incubator-openwhisk-wskdeploy/utils"
"github.com/apache/incubator-openwhisk-wskdeploy/wskprint"
"github.com/stretchr/testify/assert"
- "testing"
)
var mr *ManifestReader
var ps *parsers.YAMLParser
var ms *parsers.YAML
-func init() {
+const (
+ // local error messages
+ TEST_ERROR_BUILD_SERVICE_DEPLOYER = "Manifest [%s]: Failed to build service deployer."
+ TEST_ERROR_MANIFEST_PARSE_FAILURE = "Manifest [%s]: Failed to parse."
+ TEST_ERROR_MANIFEST_SET_PACKAGES = "Manifest [%s]: Failed to set packages."
+ TEST_ERROR_FAILED_TO_REPORT_ERROR = "Manifest [%s]: Failed to report parser error."
+ TEST_ERROR_MANIFEST_SET_ANNOTATION = "[%s]: Failed to set Annotation value."
+ TEST_ERROR_MANIFEST_SET_INPUT_PARAMETER = "[%s]: Failed to set input Parameter value."
+ TEST_ERROR_MANIFEST_SET_PUBLISH = "Package [%s]: Failed to set publish."
+ TEST_ERROR_MANIFEST_SET_DEPENDENCIES = "Package [%s]: Failed to set dependencies."
+ TEST_ERROR_MANIFEST_SET_ACTION_CODE = "Action [%s]: Failed to set action code."
+ TEST_ERROR_MANIFEST_SET_ACTION_KIND = "Action [%s]: Failed to set action kind."
+ TEST_ERROR_MANIFEST_SET_ACTION_WEB = "Action [%s]: Failed to set web action."
+ TEST_ERROR_MANIFEST_SET_ACTION_CONDUCTOR = "Action [%s]: Failed to set conductor action."
+ TEST_ERROR_MANIFEST_SET_ACTION_IMAGE = "Action [%s]: Failed to set action image."
+)
+func init() {
// Setup "trace" flag for unit tests based upon "go test" -v flag
utils.Flags.Trace = wskprint.DetectGoTestVerbose()
-
- sd = NewServiceDeployer()
- sd.ManifestPath = manifest_file
- mr = NewManifestReader(sd)
- ps = parsers.NewYAMLParser()
- ms, _ = ps.ParseManifest(manifest_file)
}
-// Test could parse Manifest file successfully
-func TestManifestReader_ParseManifest(t *testing.T) {
- _, _, err := mr.ParseManifest()
- assert.Equal(t, err, nil, "New ManifestReader failed")
+func buildServiceDeployer(manifestFile string) (*ServiceDeployer, error) {
+ deploymentFile := ""
+ var deployer = NewServiceDeployer()
+ deployer.ManifestPath = manifestFile
+ deployer.DeploymentPath = deploymentFile
+ deployer.Preview = utils.Flags.Preview
+
+ deployer.DependencyMaster = make(map[string]utils.DependencyRecord)
+
+ config := whisk.Config{
+ Namespace: "test",
+ AuthToken: "user:pass",
+ Host: "host",
+ ApigwAccessToken: "token",
+ }
+ deployer.ClientConfig = &config
+
+ op, error := utils.ParseOpenWhisk(deployer.ClientConfig.Host)
+ if error == nil {
+ utils.SupportedRunTimes = utils.ConvertToMap(op)
+ utils.DefaultRunTimes = utils.DefaultRuntimes(op)
+ utils.FileExtensionRuntimeKindMap = utils.FileExtensionRuntimes(op)
+ utils.FileRuntimeExtensionsMap = utils.FileRuntimeExtensions(op)
+ }
+
+ return deployer, nil
}
-// Test could Init root package successfully.
func TestManifestReader_InitPackages(t *testing.T) {
- err := mr.InitPackages(ps, ms, whisk.KeyValue{})
- assert.Equal(t, err, nil, "Init Root Package failed")
+ manifestFile := "../tests/dat/manifest_validate_package_inputs_and_annotations.yaml"
+ deployer, err := buildServiceDeployer(manifestFile)
+ assert.Nil(t, err, fmt.Sprintf(TEST_ERROR_BUILD_SERVICE_DEPLOYER, manifestFile))
+
+ var manifestReader = NewManifestReader(deployer)
+ manifestReader.IsUndeploy = false
+ manifest, manifestParser, err := manifestReader.ParseManifest()
+ assert.Nil(t, err, fmt.Sprintf(TEST_ERROR_MANIFEST_PARSE_FAILURE, manifestFile))
+
+ err = manifestReader.InitPackages(manifestParser, manifest, whisk.KeyValue{})
+ assert.Nil(t, err, fmt.Sprintf(TEST_ERROR_MANIFEST_SET_PACKAGES, manifestFile))
+ assert.Equal(t, 3, len(deployer.Deployment.Packages), fmt.Sprintf(TEST_ERROR_MANIFEST_SET_PACKAGES, manifestFile, ""))
+
+ expectedParametersAndAnnotations := 0
+
+ for packageName, pack := range deployer.Deployment.Packages {
+ switch packageName {
+ case "helloworld1":
+ expectedParametersAndAnnotations = 0
+ assert.False(t, *pack.Package.Publish, fmt.Sprintf(TEST_ERROR_MANIFEST_SET_PUBLISH, packageName))
+ case "helloworld2":
+ expectedParametersAndAnnotations = 1
+ for _, param := range pack.Package.Parameters {
+ switch param.Key {
+ case "helloworld_input1":
+ assert.Equal(t, "value1", param.Value,
+ fmt.Sprintf(TEST_ERROR_MANIFEST_SET_INPUT_PARAMETER, packageName))
+ }
+ }
+ for _, annotation := range pack.Package.Annotations {
+ switch annotation.Key {
+ case "helloworld_annotation1":
+ assert.Equal(t, "value1", annotation.Value,
+ fmt.Sprintf(TEST_ERROR_MANIFEST_SET_ANNOTATION, packageName))
+ }
+ }
+ assert.False(t, *pack.Package.Publish, fmt.Sprintf(TEST_ERROR_MANIFEST_SET_PUBLISH, packageName))
+ case "helloworld3":
+ expectedParametersAndAnnotations = 2
+ for _, param := range pack.Package.Parameters {
+ switch param.Key {
+ case "helloworld_input1":
+ assert.Equal(t, "value1", param.Value,
+ fmt.Sprintf(TEST_ERROR_MANIFEST_SET_INPUT_PARAMETER, packageName))
+ case "helloworld_input2":
+ assert.Equal(t, "value2", param.Value,
+ fmt.Sprintf(TEST_ERROR_MANIFEST_SET_INPUT_PARAMETER, packageName))
+ }
+ }
+ for _, annotation := range pack.Package.Annotations {
+ switch annotation.Key {
+ case "helloworld_annotation1":
+ assert.Equal(t, "value1", annotation.Value,
+ fmt.Sprintf(TEST_ERROR_MANIFEST_SET_ANNOTATION, packageName))
+ case "helloworld_annotation2":
+ assert.Equal(t, "value2", annotation.Value,
+ fmt.Sprintf(TEST_ERROR_MANIFEST_SET_ANNOTATION, packageName))
+ }
+ }
+ assert.True(t, *pack.Package.Publish, fmt.Sprintf(TEST_ERROR_MANIFEST_SET_PUBLISH, packageName))
+ }
+ assert.Equal(t, expectedParametersAndAnnotations, len(pack.Package.Parameters),
+ fmt.Sprintf(TEST_ERROR_MANIFEST_SET_INPUT_PARAMETER, packageName))
+ assert.Equal(t, expectedParametersAndAnnotations, len(pack.Package.Annotations),
+ fmt.Sprintf(TEST_ERROR_MANIFEST_SET_ANNOTATION, packageName))
+ }
+}
+
+func TestManifestReader_SetDependencies(t *testing.T) {
+ manifestFile := "../tests/dat/manifest_validate_dependencies.yaml"
+ deployer, err := buildServiceDeployer(manifestFile)
+ assert.Nil(t, err, fmt.Sprintf(TEST_ERROR_BUILD_SERVICE_DEPLOYER, manifestFile))
+
+ var manifestReader = NewManifestReader(deployer)
+ manifestReader.IsUndeploy = false
+ manifest, manifestParser, err := manifestReader.ParseManifest()
+ assert.Nil(t, err, fmt.Sprintf(TEST_ERROR_MANIFEST_PARSE_FAILURE, manifestFile))
+
+ err = manifestReader.InitPackages(manifestParser, manifest, whisk.KeyValue{})
+ assert.Nil(t, err, fmt.Sprintf(TEST_ERROR_MANIFEST_SET_PACKAGES, manifestFile))
+
+ err = manifestReader.HandleYaml(deployer, manifestParser, manifest, whisk.KeyValue{})
+ assert.Nil(t, err, fmt.Sprintf(TEST_ERROR_MANIFEST_PARSE_FAILURE, manifestFile))
+
+ expectedLocationHelloWorlds := "https://github.com/apache/incubator-openwhisk-test/packages/helloworlds"
+ expectedLocationHelloWhisk := "https://github.com/apache/incubator-openwhisk-test/packages/hellowhisk"
+ expectedLocationUtils := "/whisk.system/utils"
+
+ for pkgName, pkg := range deployer.Deployment.Packages {
+ switch pkgName {
+ case "helloworld1":
+ for depName, dep := range pkg.Dependencies {
+ switch depName {
+ case "dependency1":
+ case "helloworlds":
+ assert.Equal(t, expectedLocationHelloWorlds, dep.Location,
+ fmt.Sprintf(TEST_ERROR_MANIFEST_SET_DEPENDENCIES, pkgName))
+ case "dependency2":
+ assert.Equal(t, expectedLocationHelloWhisk, dep.Location,
+ fmt.Sprintf(TEST_ERROR_MANIFEST_SET_DEPENDENCIES, pkgName))
+ case "dependency3":
+ assert.Equal(t, expectedLocationUtils, dep.Location,
+ fmt.Sprintf(TEST_ERROR_MANIFEST_SET_DEPENDENCIES, pkgName))
+ }
+ }
+
+ case "helloworld2":
+ for depName, dep := range pkg.Dependencies {
+ switch depName {
+ case "helloworlds":
+ case "dependency1":
+ case "dependency4":
+ assert.Equal(t, expectedLocationHelloWorlds, dep.Location,
+ fmt.Sprintf(TEST_ERROR_MANIFEST_SET_DEPENDENCIES, pkgName))
+ case "dependency5":
+ assert.Equal(t, expectedLocationHelloWhisk, dep.Location,
+ fmt.Sprintf(TEST_ERROR_MANIFEST_SET_DEPENDENCIES, pkgName))
+ case "dependency6":
+ assert.Equal(t, expectedLocationUtils, dep.Location,
+ fmt.Sprintf(TEST_ERROR_MANIFEST_SET_DEPENDENCIES, pkgName))
+ }
+ }
+ }
+ }
+}
+
+func TestManifestReader_SetDependencies_Bogus(t *testing.T) {
+ manifestFile := "../tests/dat/manifest_validate_dependencies_bogus.yaml"
+ deployer, err := buildServiceDeployer(manifestFile)
+ assert.Nil(t, err, fmt.Sprintf(TEST_ERROR_BUILD_SERVICE_DEPLOYER, manifestFile))
+
+ var manifestReader = NewManifestReader(deployer)
+ manifestReader.IsUndeploy = false
+ manifest, manifestParser, err := manifestReader.ParseManifest()
+ assert.Nil(t, err, fmt.Sprintf(TEST_ERROR_MANIFEST_PARSE_FAILURE, manifestFile))
+
+ err = manifestReader.InitPackages(manifestParser, manifest, whisk.KeyValue{})
+ assert.Nil(t, err, fmt.Sprintf(TEST_ERROR_MANIFEST_SET_PACKAGES, manifestFile))
+
+ err = manifestReader.HandleYaml(deployer, manifestParser, manifest, whisk.KeyValue{})
+ assert.NotNil(t, err, fmt.Sprintf(TEST_ERROR_FAILED_TO_REPORT_ERROR, manifestFile))
+}
+
+func TestManifestReader_SetActions(t *testing.T) {
+ manifestFile := "../tests/dat/manifest_validate_action_all.yaml"
+ deployer, err := buildServiceDeployer(manifestFile)
+ assert.Nil(t, err, fmt.Sprintf(TEST_ERROR_BUILD_SERVICE_DEPLOYER, manifestFile))
+
+ var manifestReader = NewManifestReader(deployer)
+ manifestReader.IsUndeploy = false
+ manifest, manifestParser, err := manifestReader.ParseManifest()
+ assert.Nil(t, err, fmt.Sprintf(TEST_ERROR_MANIFEST_PARSE_FAILURE, manifestFile))
+
+ err = manifestReader.InitPackages(manifestParser, manifest, whisk.KeyValue{})
+ assert.Nil(t, err, fmt.Sprintf(TEST_ERROR_MANIFEST_SET_PACKAGES, manifestFile))
+
+ err = manifestReader.HandleYaml(deployer, manifestParser, manifest, whisk.KeyValue{})
+ assert.Nil(t, err, fmt.Sprintf(TEST_ERROR_MANIFEST_PARSE_FAILURE, manifestFile))
+
+ expectedRuntime := "nodejs:6"
+ expectedImage := "openwhisk/skeleton"
+
+ for actionName, action := range deployer.Deployment.Packages["helloworld"].Actions {
+ switch actionName {
+ case "helloworld1":
+ case "helloworld2":
+ assert.NotEmpty(t, action.Action.Exec.Code,
+ fmt.Sprintf(TEST_ERROR_MANIFEST_SET_ACTION_CODE, actionName))
+ assert.Equal(t, expectedRuntime, action.Action.Exec.Kind,
+ fmt.Sprintf(TEST_ERROR_MANIFEST_SET_ACTION_KIND, actionName))
+ case "helloworld3":
+ for _, param := range action.Action.Parameters {
+ switch param.Key {
+ case "parameter1":
+ assert.Equal(t, "value1", param.Value,
+ fmt.Sprintf(TEST_ERROR_MANIFEST_SET_INPUT_PARAMETER, actionName))
+ case "parameter2":
+ assert.Equal(t, "value2", param.Value,
+ fmt.Sprintf(TEST_ERROR_MANIFEST_SET_INPUT_PARAMETER, actionName))
+ }
+ }
+ for _, annotation := range action.Action.Annotations {
+ switch annotation.Key {
+ case "annotation1":
+ assert.Equal(t, "value1", annotation.Value,
+ fmt.Sprintf(TEST_ERROR_MANIFEST_SET_ANNOTATION, actionName))
+ case "annotation2":
+ assert.Equal(t, "value2", annotation.Value,
+ fmt.Sprintf(TEST_ERROR_MANIFEST_SET_ANNOTATION, actionName))
+ }
+ }
+ case "helloworld4":
+ assert.True(t, action.Action.WebAction(),
+ fmt.Sprintf(TEST_ERROR_MANIFEST_SET_ACTION_WEB, actionName))
+ case "helloworld5":
+ for _, annotation := range action.Action.Annotations {
+ switch annotation.Key {
+ case "conductor":
+ assert.True(t, annotation.Value.(bool),
+ fmt.Sprintf(TEST_ERROR_MANIFEST_SET_ACTION_CONDUCTOR, actionName))
+ }
+ }
+ case "helloworld6":
+ assert.Equal(t, expectedImage, action.Action.Exec.Image,
+ fmt.Sprintf(TEST_ERROR_MANIFEST_SET_ACTION_IMAGE, actionName))
+ }
+ }
+}
+
+func TestManifestReader_SetSequences_Bogus(t *testing.T) {
+ manifestFile := "../tests/dat/manifest_validate_sequences_bogus.yaml"
+ deployer, err := buildServiceDeployer(manifestFile)
+ assert.Nil(t, err, fmt.Sprintf(TEST_ERROR_BUILD_SERVICE_DEPLOYER, manifestFile))
+
+ var manifestReader = NewManifestReader(deployer)
+ manifestReader.IsUndeploy = false
+ manifest, manifestParser, err := manifestReader.ParseManifest()
+ assert.Nil(t, err, fmt.Sprintf(TEST_ERROR_MANIFEST_PARSE_FAILURE, manifestFile))
+
+ err = manifestReader.InitPackages(manifestParser, manifest, whisk.KeyValue{})
+ assert.Nil(t, err, fmt.Sprintf(TEST_ERROR_MANIFEST_SET_PACKAGES, manifestFile))
+
+ err = manifestReader.HandleYaml(deployer, manifestParser, manifest, whisk.KeyValue{})
+ assert.NotNil(t, err, fmt.Sprintf(TEST_ERROR_FAILED_TO_REPORT_ERROR, manifestFile))
+}
+
+func TestManifestReader_SetTriggers_Bogus(t *testing.T) {
+ manifestFile := "../tests/dat/manifest_validate_triggers_bogus.yaml"
+ deployer, err := buildServiceDeployer(manifestFile)
+ assert.Nil(t, err, fmt.Sprintf(TEST_ERROR_BUILD_SERVICE_DEPLOYER, manifestFile))
+
+ var manifestReader = NewManifestReader(deployer)
+ manifestReader.IsUndeploy = false
+ manifest, manifestParser, err := manifestReader.ParseManifest()
+ assert.Nil(t, err, fmt.Sprintf(TEST_ERROR_MANIFEST_PARSE_FAILURE, manifestFile))
+
+ err = manifestReader.InitPackages(manifestParser, manifest, whisk.KeyValue{})
+ assert.Nil(t, err, fmt.Sprintf(TEST_ERROR_MANIFEST_SET_PACKAGES, manifestFile))
+
+ err = manifestReader.HandleYaml(deployer, manifestParser, manifest, whisk.KeyValue{})
+ assert.NotNil(t, err, fmt.Sprintf(TEST_ERROR_FAILED_TO_REPORT_ERROR, manifestFile))
+}
+
+func TestManifestReader_SetRules_Bogus(t *testing.T) {
+ manifestFile := "../tests/dat/manifest_validate_rules_bogus.yaml"
+ deployer, err := buildServiceDeployer(manifestFile)
+ assert.Nil(t, err, fmt.Sprintf(TEST_ERROR_BUILD_SERVICE_DEPLOYER, manifestFile))
+
+ var manifestReader = NewManifestReader(deployer)
+ manifestReader.IsUndeploy = false
+ manifest, manifestParser, err := manifestReader.ParseManifest()
+ assert.Nil(t, err, fmt.Sprintf(TEST_ERROR_MANIFEST_PARSE_FAILURE, manifestFile))
+
+ err = manifestReader.InitPackages(manifestParser, manifest, whisk.KeyValue{})
+ assert.Nil(t, err, fmt.Sprintf(TEST_ERROR_MANIFEST_SET_PACKAGES, manifestFile))
+
+ err = manifestReader.HandleYaml(deployer, manifestParser, manifest, whisk.KeyValue{})
+ assert.NotNil(t, err, fmt.Sprintf(TEST_ERROR_FAILED_TO_REPORT_ERROR, manifestFile))
}
diff --git a/deployers/servicedeployer.go b/deployers/servicedeployer.go
index e35fe96..d3a9894 100644
--- a/deployers/servicedeployer.go
+++ b/deployers/servicedeployer.go
@@ -1570,8 +1570,6 @@ func (deployer *ServiceDeployer) getDependentDeployer(depName string, depRecord
depServiceDeployer.Client = deployer.Client
depServiceDeployer.ClientConfig = deployer.ClientConfig
- depServiceDeployer.DependencyMaster = deployer.DependencyMaster
-
// share the master dependency list
depServiceDeployer.DependencyMaster = deployer.DependencyMaster
diff --git a/parsers/manifest_parser.go b/parsers/manifest_parser.go
index c63e4dd..3403820 100644
--- a/parsers/manifest_parser.go
+++ b/parsers/manifest_parser.go
@@ -20,14 +20,12 @@ package parsers
import (
"encoding/base64"
"errors"
+ "gopkg.in/yaml.v2"
"io/ioutil"
"os"
"path"
- "strings"
-
- "gopkg.in/yaml.v2"
-
"path/filepath"
+ "strings"
"github.com/apache/incubator-openwhisk-client-go/whisk"
"github.com/apache/incubator-openwhisk-wskdeploy/utils"
diff --git a/tests/dat/manifest_validate_action_all.yaml b/tests/dat/manifest_validate_action_all.yaml
new file mode 100644
index 0000000..8faf05f
--- /dev/null
+++ b/tests/dat/manifest_validate_action_all.yaml
@@ -0,0 +1,43 @@
+#
+# 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.
+#
+
+packages:
+ helloworld:
+ actions:
+ helloworld1:
+ function: actions/hello.js
+ helloworld2:
+ code: const main = ({ msg }) => { console.log(msg); return {msg}; }
+ runtime: nodejs:6
+ helloworld3:
+ function: actions/hello.js
+ annotations:
+ annotation1: value1
+ annotation2: value2
+ inputs:
+ parameter1: value1
+ parameter2: value2
+ helloworld4:
+ function: actions/hello.js
+ web: true
+ helloworld5:
+ function: actions/hello.js
+ conductor: true
+ helloworld6:
+ function: actions/hello.js
+ docker: openwhisk/skeleton
+
+
diff --git a/tests/dat/manifest_validate_dependencies.yaml b/tests/dat/manifest_validate_dependencies.yaml
new file mode 100644
index 0000000..300cdad
--- /dev/null
+++ b/tests/dat/manifest_validate_dependencies.yaml
@@ -0,0 +1,42 @@
+#
+# 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.
+#
+
+packages:
+ helloworld1:
+ dependencies:
+ helloworlds:
+ location: github.com/apache/incubator-openwhisk-test/packages/helloworlds
+ dependency1:
+ location: github.com/apache/incubator-openwhisk-test/packages/helloworlds
+ dependency2:
+ location: github.com/apache/incubator-openwhisk-test/packages/hellowhisk
+ dependency3:
+ location: /whisk.system/utils
+ helloworld2:
+ dependencies:
+ helloworlds:
+ location: github.com/apache/incubator-openwhisk-test/packages/helloworlds
+ dependency1:
+ location: github.com/apache/incubator-openwhisk-test/packages/helloworlds
+ dependency4:
+ location: github.com/apache/incubator-openwhisk-test/packages/helloworlds
+ dependency5:
+ location: github.com/apache/incubator-openwhisk-test/packages/hellowhisk
+ dependency6:
+ location: /whisk.system/utils
+
+
+
diff --git a/tests/dat/manifest_validate_dependencies_bogus.yaml b/tests/dat/manifest_validate_dependencies_bogus.yaml
new file mode 100644
index 0000000..f75c3b1
--- /dev/null
+++ b/tests/dat/manifest_validate_dependencies_bogus.yaml
@@ -0,0 +1,42 @@
+#
+# 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.
+#
+
+packages:
+ helloworld1:
+ dependencies:
+ helloworlds:
+ location: github.com/apache/incubator-openwhisk-test/packages/helloworlds
+ dependency1:
+ location: github.com/apache/incubator-openwhisk-test/packages/helloworlds
+ dependency2:
+ location: github.com/apache/incubator-openwhisk-test/packages/hellowhisk
+ dependency3:
+ location: /whisk.system/utils
+ helloworld2:
+ dependencies:
+ helloworlds:
+ location: github.com/apache/incubator-openwhisk-test/packages/helloworlds
+ dependency1:
+ location: github.com/apache/incubator-openwhisk-test/packages/hellowhisk
+ dependency4:
+ location: github.com/apache/incubator-openwhisk-test/packages/helloworlds
+ dependency5:
+ location: github.com/apache/incubator-openwhisk-test/packages/hellowhisk
+ dependency6:
+ location: /whisk.system/utils
+
+
+
diff --git a/tests/dat/manifest_validate_package_inputs_and_annotations.yaml b/tests/dat/manifest_validate_package_inputs_and_annotations.yaml
new file mode 100644
index 0000000..ea5f253
--- /dev/null
+++ b/tests/dat/manifest_validate_package_inputs_and_annotations.yaml
@@ -0,0 +1,37 @@
+#
+# 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.
+#
+
+packages:
+ helloworld1:
+ license: Apache-2.0
+ helloworld2:
+ version: 2.0.0
+ license: MIT
+ inputs:
+ helloworld_input1: value1
+ annotations:
+ helloworld_annotation1: value1
+ helloworld3:
+ version: 3.0.0
+ license: GPL-3.0
+ inputs:
+ helloworld_input1: value1
+ helloworld_input2: value2
+ annotations:
+ helloworld_annotation1: value1
+ helloworld_annotation2: value2
+ public: true
+
diff --git a/tests/dat/manifest_validate_rules_bogus.yaml b/tests/dat/manifest_validate_rules_bogus.yaml
new file mode 100644
index 0000000..587929f
--- /dev/null
+++ b/tests/dat/manifest_validate_rules_bogus.yaml
@@ -0,0 +1,41 @@
+#
+# 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.
+#
+
+packages:
+ helloworld1:
+ actions:
+ hello:
+ function: actions/hello.js
+ triggers:
+ trigger1:
+ rules:
+ rule1:
+ trigger: trigger1
+ action: hello
+ helloworld2:
+ actions:
+ hello:
+ function: actions/hello.js
+ triggers:
+ trigger2:
+ rules:
+ rule1:
+ trigger: trigger2
+ action: hello
+ rule2:
+ trigger: trigger2
+ action: hello
+
diff --git a/tests/dat/manifest_validate_sequences_bogus.yaml b/tests/dat/manifest_validate_sequences_bogus.yaml
new file mode 100644
index 0000000..4d5425d
--- /dev/null
+++ b/tests/dat/manifest_validate_sequences_bogus.yaml
@@ -0,0 +1,38 @@
+#
+# 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.
+#
+
+packages:
+ helloworld:
+ actions:
+ hello:
+ function: actions/hello.js
+ runtime: nodejs:6
+ helloWithParams:
+ function: actions/hello.js
+ runtime: nodejs:6
+ inputs:
+ name: Amy
+ place: Paris
+ helloWithParams1:
+ function: actions/hello.js
+ runtime: nodejs:6
+ inputs:
+ name: Amy
+ place: Paris
+ sequences:
+ hello:
+ actions: helloWithParams, helloWithParams1
+
diff --git a/tests/dat/manifest_validate_triggers_bogus.yaml b/tests/dat/manifest_validate_triggers_bogus.yaml
new file mode 100644
index 0000000..2b3b2c2
--- /dev/null
+++ b/tests/dat/manifest_validate_triggers_bogus.yaml
@@ -0,0 +1,33 @@
+#
+# 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.
+#
+
+packages:
+ helloworld1:
+ actions:
+ hello:
+ function: actions/hello.js
+ triggers:
+ trigger1:
+ trigger2:
+ helloworld2:
+ actions:
+ hello:
+ function: actions/hello.js
+ triggers:
+ trigger1:
+ trigger2:
+ feed: /whisk.system/alarms/alarm
+
diff --git a/utils/dependencies.go b/utils/dependencies.go
index 9f1dd08..eba29b8 100644
--- a/utils/dependencies.go
+++ b/utils/dependencies.go
@@ -88,3 +88,13 @@ func LocationIsGithub(location string) bool {
paths := strings.SplitN(removeProtocol(location), "/", 2)
return strings.Contains(paths[0], GITHUB)
}
+
+func CompareDependencyRecords(d1 DependencyRecord, d2 DependencyRecord) bool {
+ if (d1.Location == d2.Location) && (d1.Version == d2.Version) {
+ return true
+ }
+ if (d1.BaseRepo == d2.BaseRepo) && (d1.SubFolder == d2.SubFolder) && (d1.Version == d2.Version) {
+ return true
+ }
+ return false
+}
diff --git a/utils/gitreader.go b/utils/gitreader.go
index 9d9c84b..741da88 100644
--- a/utils/gitreader.go
+++ b/utils/gitreader.go
@@ -129,6 +129,5 @@ func (reader *GitReader) CloneDependency() error {
}
os.Rename(rootDir, depPath)
-
return nil
}
diff --git a/wski18n/i18n_ids.go b/wski18n/i18n_ids.go
index eae4a0b..9807f0d 100644
--- a/wski18n/i18n_ids.go
+++ b/wski18n/i18n_ids.go
@@ -78,6 +78,9 @@ const (
KEY_DEPENDENCY = "dependency"
KEY_LOCATION = "location"
KEY_SEQUENCE = "sequence"
+ KEY_TRIGGER = "trigger"
+ KEY_TRIGGER_FEED = "feed"
+ KEY_RULE = "rule"
)
// DO NOT TRANSLATE
@@ -163,25 +166,31 @@ const (
ID_MSG_MANAGED_FOUND_DELETED_X_key_X_name_X_project_X = "msg_managed_found_deleted_entity"
// Errors
- ID_ERR_DEPENDENCY_UNKNOWN_TYPE = "msg_err_dependency_unknown_type"
- ID_ERR_ENTITY_CREATE_X_key_X_err_X_code_X = "msg_err_entity_create"
- ID_ERR_ENTITY_DELETE_X_key_X_err_X_code_X = "msg_err_entity_delete"
- ID_ERR_FEED_INVOKE_X_err_X_code_X = "msg_err_feed_invoke"
- ID_ERR_KEY_MISSING_X_key_X = "msg_err_key_missing_mandatory"
- ID_ERR_MANIFEST_FILE_NOT_FOUND_X_path_X = "msg_err_manifest_not_found"
- ID_ERR_NAME_MISMATCH_X_key_X_dname_X_dpath_X_mname_X_moath_X = "msg_err_name_mismatch"
- ID_ERR_RUNTIME_INVALID_X_runtime_X_action_X = "msg_err_runtime_invalid"
- ID_ERR_RUNTIME_MISMATCH_X_runtime_X_ext_X_action_X = "msg_err_runtime_mismatch"
- ID_ERR_RUNTIMES_GET_X_err_X = "msg_err_runtimes_get"
- ID_ERR_RUNTIME_ACTION_SOURCE_NOT_SUPPORTED_X_ext_X_action_X = "msg_err_runtime_action_source_not_supported"
- ID_ERR_URL_INVALID_X_urltype_X_url_X_filetype_X = "msg_err_url_invalid"
- ID_ERR_URL_MALFORMED_X_urltype_X_url_X = "msg_err_url_malformed"
- ID_ERR_API_MISSING_ACTION_OR_SEQUENCE_X_action_or_sequence_X_api_X = "msg_err_api_missing_action_or_sequence"
- ID_ERR_ACTION_INVALID_X_action_X = "msg_err_action_invalid"
- ID_ERR_ACTION_MISSING_RUNTIME_WITH_CODE_X_action_X = "msg_err_action_missing_runtime_with_code"
- ID_ERR_ACTION_FUNCTION_REMOTE_DIR_NOT_SUPPORTED_X_action_X_url_X = "msg_err_action_function_remote_dir_not_supported"
- ID_ERR_CANT_SAVE_DOCKER_RUNTIME = "msg_err_cant_save_docker"
- ID_ERR_FILE_ALREADY_EXISTS = "msg_err_file_already_exists"
+ ID_ERR_DEPENDENCY_UNKNOWN_TYPE = "msg_err_dependency_unknown_type"
+ ID_ERR_ENTITY_CREATE_X_key_X_err_X_code_X = "msg_err_entity_create"
+ ID_ERR_ENTITY_DELETE_X_key_X_err_X_code_X = "msg_err_entity_delete"
+ ID_ERR_FEED_INVOKE_X_err_X_code_X = "msg_err_feed_invoke"
+ ID_ERR_KEY_MISSING_X_key_X = "msg_err_key_missing_mandatory"
+ ID_ERR_MANIFEST_FILE_NOT_FOUND_X_path_X = "msg_err_manifest_not_found"
+ ID_ERR_NAME_MISMATCH_X_key_X_dname_X_dpath_X_mname_X_moath_X = "msg_err_name_mismatch"
+ ID_ERR_RUNTIME_INVALID_X_runtime_X_action_X = "msg_err_runtime_invalid"
+ ID_ERR_RUNTIME_MISMATCH_X_runtime_X_ext_X_action_X = "msg_err_runtime_mismatch"
+ ID_ERR_RUNTIMES_GET_X_err_X = "msg_err_runtimes_get"
+ ID_ERR_RUNTIME_ACTION_SOURCE_NOT_SUPPORTED_X_ext_X_action_X = "msg_err_runtime_action_source_not_supported"
+ ID_ERR_URL_INVALID_X_urltype_X_url_X_filetype_X = "msg_err_url_invalid"
+ ID_ERR_URL_MALFORMED_X_urltype_X_url_X = "msg_err_url_malformed"
+ ID_ERR_API_MISSING_ACTION_OR_SEQUENCE_X_action_or_sequence_X_api_X = "msg_err_api_missing_action_or_sequence"
+ ID_ERR_ACTION_INVALID_X_action_X = "msg_err_action_invalid"
+ ID_ERR_ACTION_MISSING_RUNTIME_WITH_CODE_X_action_X = "msg_err_action_missing_runtime_with_code"
+ ID_ERR_ACTION_FUNCTION_REMOTE_DIR_NOT_SUPPORTED_X_action_X_url_X = "msg_err_action_function_remote_dir_not_supported"
+ ID_ERR_CANT_SAVE_DOCKER_RUNTIME = "msg_err_cant_save_docker"
+ ID_ERR_FILE_ALREADY_EXISTS = "msg_err_file_already_exists"
+ ID_ERR_DEPENDENCIES_WITH_SAME_LABEL_X_dependency_X_location_X = "msg_err_different_dependencies_with_same_label"
+ ID_ERR_ACTION_WITHOUT_KIND_X_action_X = "msg_err_action_without_kind"
+ ID_ERR_ACTION_WITHOUT_SOURCE_X_action_X = "msg_err_action_without_source"
+ ID_ERR_SEQUENCE_HAVING_SAME_NAME_AS_ACTION_X_action_X = "msg_err_sequence_having_same_name_as_action"
+ ID_ERR_CONFLICTING_TRIGGERS_ACROSS_PACKAGES_X_trigger_X_feed_X = "msg_err_conflicting_triggers_across_packages"
+ ID_ERR_CONFLICTING_RULES_ACROSS_PACKAGES_X_rule_X_action_X_trigger_X = "msg_err_conflicting_rules_across_packages"
// Server-side Errors (wskdeploy as an Action)
ID_ERR_JSON_MISSING_KEY_CMD = "msg_err_json_missing_cmd_key"
diff --git a/wski18n/i18n_resources.go b/wski18n/i18n_resources.go
index e77a8f5..030d962 100755
--- a/wski18n/i18n_resources.go
+++ b/wski18n/i18n_resources.go
@@ -97,7 +97,7 @@ func wski18nResourcesDe_deAllJson() (*asset, error) {
return a, nil
}
-var _wski18nResourcesEn_usAllJson = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xc4\x5b\x6f\x8f\xdb\x36\xd2\x7f\x9f\x4f\x31\x08\x1e\x20\x2d\xe0\x28\x69\x1f\x3c\xc0\x83\x00\x79\x91\x6b\xd2\x76\xaf\x4d\x36\xd8\xcd\x5e\x50\xe4\x16\x0a\x2d\x8d\x6d\xd6\x12\xa9\x23\x29\x3b\xae\xe1\xef\x7e\x98\x21\xf5\xc7\xde\xa5\xa4\x75\xda\xbb\xbe\xa9\xbb\x1c\xce\xfc\x66\x38\x9c\x7f\x54\x3f\x3d\x02\xd8\x3f\x02\x00\x78\x2c\xf3\xc7\x2f\xe0\x71\x69\x97\x69\x65\x70\x21\xbf\xa4\x68\x8c\x36\x8f\x67\x7e\xd5\x19 [...]
+var _wski18nResourcesEn_usAllJson = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xc4\x5b\x5f\x8f\xdb\x36\x12\x7f\xcf\xa7\x18\x04\x07\xa4\x05\x1c\x6d\xda\xc3\x01\x87\x00\x79\xc8\x35\x69\x9b\x6b\x93\x0d\x76\x93\x0b\x8a\xdc\x42\xa1\xa5\xb1\xcd\x5a\x22\x75\x24\x65\xc7\x5d\xec\x77\x3f\xcc\x90\x94\x64\xaf\xf5\xc7\x4e\x7a\x97\x97\x68\x97\xe4\xcc\x6f\x86\xc3\xf9\x47\xee\xc7\x07\x00\xb7\x0f\x00\x00\x1e\xca\xfc\xe1\x53\x78\x58\xda\x65\x5a\x19\x5c\xc8\xcf\x29\x1a\xa3\xcd\xc3\x99\x1f\x75\x46\x28 [...]
func wski18nResourcesEn_usAllJsonBytes() ([]byte, error) {
return bindataRead(
@@ -112,7 +112,7 @@ func wski18nResourcesEn_usAllJson() (*asset, error) {
return nil, err
}
- info := bindataFileInfo{name: "wski18n/resources/en_US.all.json", size: 14286, mode: os.FileMode(420), modTime: time.Unix(1523039220, 0)}
+ info := bindataFileInfo{name: "wski18n/resources/en_US.all.json", size: 15831, mode: os.FileMode(420), modTime: time.Unix(1523315322, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
diff --git a/wski18n/resources/en_US.all.json b/wski18n/resources/en_US.all.json
index f765820..5b32270 100644
--- a/wski18n/resources/en_US.all.json
+++ b/wski18n/resources/en_US.all.json
@@ -316,6 +316,30 @@
"translation": "File already exists."
},
{
+ "id": "msg_err_different_dependencies_with_same_label",
+ "translation": "One single dependency [{{.dependency}}] has two different locations [{{.location}}]. This kind of specification is not supported. Please update the dependency label [{{.dependency}}] in the manifest file to point to same location or create two separate labels for two different locations."
+ },
+ {
+ "id": "msg_err_action_without_kind",
+ "translation": "Action [{{.action}}] has no kind set."
+ },
+ {
+ "id": "msg_err_action_without_code",
+ "translation": "Action [{{.action}}] has no source code."
+ },
+ {
+ "id": "msg_err_sequence_having_same_name_as_action",
+ "translation": "Sequence [{{.sequence}}] is already defined as an action under the same package. Actions and sequences can not have same name in a single package."
+ },
+ {
+ "id": "msg_err_conflicting_triggers_across_packages",
+ "translation": "One single trigger [{{.trigger}}] is defined with multiple feeds [{{.feed}}]. Triggers are created directly under the namespace, its not possible to have triggers with same name but different feeds. Please update trigger names in manifest file."
+ },
+ {
+ "id": "msg_err_conflicting_rules_across_packages",
+ "translation": "One single rule [{{.rule}}] is defined with different actions [{{.action}}] and/or triggers [{{.trigger}}]. Rules are created directly under the namespace, its not possible to have rules with same name but associated with different actions/triggers. Please update rule names in manifest file."
+ },
+ {
"id": "WARNINGS",
"translation": "================= WARNINGS ==================="
},
--
To stop receiving notification emails like this one, please contact
mrutkowski@apache.org.