openwhisk-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From pde...@apache.org
Subject [incubator-openwhisk-wskdeploy] branch master updated: Extend export to support project with dependencies (#828)
Date Wed, 28 Mar 2018 21:24:42 GMT
This is an automated email from the ASF dual-hosted git repository.

pdesai 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 e6daeea  Extend export to support project with dependencies (#828)
e6daeea is described below

commit e6daeeafae8339a8e4a3dd9ecb28bf5db0a576a2
Author: kpavel <kpavel@il.ibm.com>
AuthorDate: Thu Mar 29 00:24:40 2018 +0300

    Extend export to support project with dependencies (#828)
    
    * Resolves #730
    
    - Provides support to export projects with dependencies
    - Optimizes rule export (leveraging added rule annotations)
    - Adds MANAGED annotation to dependencies in OW package bindings
    
    * bug fix
    
    * Added integration tests for export
    
    * bug fix
    
    * bug fix
    
    * added undeployments to export test case
    
    * minor bug fixes
    
    * change export attribute ProjectPath to ProjectName
---
 cmd/export.go                                   | 149 +++++++++++++++---------
 parsers/manifest_parser.go                      |   3 +-
 parsers/manifest_parser_test.go                 |  11 +-
 parsers/yamlparser.go                           |   7 ++
 tests/src/integration/common/wskdeploy.go       |  19 ++-
 tests/src/integration/export/export_test.go     |  72 ++++++++++++
 tests/src/integration/export/manifest_ext.yaml  |  35 ++++++
 tests/src/integration/export/manifest_lib1.yaml |  35 ++++++
 tests/src/integration/export/manifest_lib2.yaml |  35 ++++++
 tests/src/integration/export/src/greeting.js    |  11 ++
 utils/managedannotations.go                     |   3 +-
 wski18n/i18n_ids.go                             |   1 +
 12 files changed, 313 insertions(+), 68 deletions(-)

diff --git a/cmd/export.go b/cmd/export.go
index 437fb4f..3585da5 100644
--- a/cmd/export.go
+++ b/cmd/export.go
@@ -44,18 +44,7 @@ var exportCmd = &cobra.Command{
 
 var config *whisk.Config
 
-func ExportRule(wskRule whisk.Rule, pkgName string, maniyaml *parsers.YAML) {
-	if maniyaml.Packages[pkgName].Rules == nil {
-		pkg := maniyaml.Packages[pkgName]
-		pkg.Rules = make(map[string]parsers.Rule)
-		maniyaml.Packages[pkgName] = pkg
-	}
-
-	// export rule to manifest
-	maniyaml.Packages[pkgName].Rules[wskRule.Name] = *maniyaml.ComposeParsersRule(wskRule)
-}
-
-func ExportAction(actionName string, packageName string, maniyaml *parsers.YAML) error {
+func ExportAction(actionName string, packageName string, maniyaml *parsers.YAML, targetManifest
string) error {
 
 	pkg := maniyaml.Packages[packageName]
 	if pkg.Actions == nil {
@@ -71,7 +60,7 @@ func ExportAction(actionName string, packageName string, maniyaml *parsers.YAML)
 		seq := new(parsers.Sequence)
 		for _, component := range wskAction.Exec.Components {
 			// must ommit namespace from seq component name
-			ExportAction(strings.SplitN(component, "/", 3)[2], packageName, maniyaml)
+			ExportAction(strings.SplitN(component, "/", 3)[2], packageName, maniyaml, targetManifest)
 			slices := strings.Split(component, "/")
 
 			// save in the seq list only action names
@@ -90,7 +79,7 @@ func ExportAction(actionName string, packageName string, maniyaml *parsers.YAML)
 		pkg.Sequences[wskAction.Name] = *seq
 	} else {
 		parsedAction := *maniyaml.ComposeParsersAction(*wskAction)
-		manifestDir := filepath.Dir(utils.Flags.ManifestPath)
+		manifestDir := filepath.Dir(targetManifest)
 
 		// store function file under action package name subdirectory in the specified manifest
folder
 		functionDir := filepath.Join(manifestDir, packageName)
@@ -111,24 +100,18 @@ func ExportAction(actionName string, packageName string, maniyaml *parsers.YAML)
 	return nil
 }
 
-func ExportCmdImp(cmd *cobra.Command, args []string) error {
-
-	projectName := utils.Flags.ProjectPath
+func exportProject(projectName string, targetManifest string) error {
 	maniyaml := &parsers.YAML{}
 	maniyaml.Project.Name = projectName
 
-	config, _ = deployers.NewWhiskConfig(wskpropsPath, utils.Flags.DeploymentPath, utils.Flags.ManifestPath)
-	client, _ = deployers.CreateNewClient(config)
-
-	// Init supported runtimes and action files extensions maps
-	setSupportedRuntimes(config.Host)
-
 	// Get the list of packages in your namespace
 	packages, _, err := client.Packages.List(&whisk.PackageListOptions{})
 	if err != nil {
 		return err
 	}
 
+	var bindings = make(map[string]whisk.Binding)
+
 	// iterate over each package to find managed annotations
 	// check if "managed" annotation is attached to a package
 	// add to export when managed project name matches with the
@@ -141,6 +124,12 @@ func ExportCmdImp(cmd *cobra.Command, args []string) error {
 			// we have found a package which is part of the current project
 			if pa[utils.OW_PROJECT_NAME] == projectName {
 
+				// check if the package is dependency
+				if pkg.Annotations.GetValue(wski18n.BINDING) != nil {
+					bindings[pkg.Name] = *pkg.Binding
+					continue
+				}
+
 				if maniyaml.Packages == nil {
 					maniyaml.Packages = make(map[string]parsers.Package)
 				}
@@ -172,7 +161,7 @@ func ExportCmdImp(cmd *cobra.Command, args []string) error {
 						if aa[utils.OW_PROJECT_NAME] == projectName {
 							actionName := strings.Join([]string{pkg.Name, action.Name}, "/")
 							// export action to file system
-							err = ExportAction(actionName, pkg.Name, maniyaml)
+							err = ExportAction(actionName, pkg.Name, maniyaml, targetManifest)
 							if err != nil {
 								return err
 							}
@@ -220,49 +209,101 @@ func ExportCmdImp(cmd *cobra.Command, args []string) error {
 		return err
 	}
 
-	// TODO: can be simplifyed once OW permits to add annotation to rules
-	// iterate over the list of rules to determine whether any of them is part of
-	// managed trigger -> action set for specified managed project. if yes, add to manifest
+	// iterate over the list of rules to determine whether any of them is part of the manage
dproject
 	for _, rule := range rules {
 		// get rule from OW
 		wskRule, _, _ := client.Rules.Get(rule.Name)
-		ruleAction := wskRule.Action.(map[string]interface{})["name"].(string)
-		ruleTrigger := wskRule.Trigger.(map[string]interface{})["name"].(string)
-
-		// can be simplified once rules moved to top level next to triggers
-		for pkgName := range maniyaml.Packages {
-			if maniyaml.Packages[pkgName].Namespace == wskRule.Namespace {
-				// iterate over all managed triggers in manifest
-				for _, trigger := range maniyaml.Packages[pkgName].Triggers {
-					// check that managed trigger equals to rule trigger
-					if ruleTrigger == trigger.Name && trigger.Namespace == wskRule.Namespace {
-						// check that there a managed action (or sequence action) equals to rule action
-						for _, action := range maniyaml.Packages[pkgName].Actions {
-							if action.Name == ruleAction {
-								// export rule to manifest
-								ExportRule(*wskRule, pkgName, maniyaml)
-							}
-						}
+		// rule has attached managed annotation
+		if a := wskRule.Annotations.GetValue(utils.MANAGED); a != nil {
+			// decode the JSON blob and retrieve __OW_PROJECT_NAME
+			ta := a.(map[string]interface{})
+			if ta[utils.OW_PROJECT_NAME] == projectName {
 
-						// check that there a managed sequence action with name matching the rule action
-						for name := range maniyaml.Packages[pkgName].Sequences {
-							if name == ruleAction {
-								// export rule to manifest
-								ExportRule(*wskRule, pkgName, maniyaml)
-							}
+				for pkgName := range maniyaml.Packages {
+					if maniyaml.Packages[pkgName].Namespace == wskRule.Namespace {
+						if maniyaml.Packages[pkgName].Rules == nil {
+							pkg := maniyaml.Packages[pkgName]
+							pkg.Rules = make(map[string]parsers.Rule)
+							maniyaml.Packages[pkgName] = pkg
 						}
+
+						// export rule to manifest
+						maniyaml.Packages[pkgName].Rules[wskRule.Name] = *maniyaml.ComposeParsersRule(*wskRule)
 					}
 				}
 			}
 		}
+
+	}
+
+	// adding dependencies to the first package
+	for pkgName := range maniyaml.Packages {
+		for bPkg, binding := range bindings {
+			if maniyaml.Packages[pkgName].Dependencies == nil {
+				pkg := maniyaml.Packages[pkgName]
+				pkg.Dependencies = make(map[string]parsers.Dependency)
+				maniyaml.Packages[pkgName] = pkg
+			}
+			maniyaml.Packages[pkgName].Dependencies[bPkg] = *maniyaml.ComposeParsersDependency(binding)
+		}
+
+		break
+	}
+
+	// find exported manifest parent directory
+	manifestDir := filepath.Dir(utils.Flags.ManifestPath)
+	os.MkdirAll(manifestDir, os.ModePerm)
+
+	// export manifest to file
+	parsers.Write(maniyaml, targetManifest)
+	fmt.Println("Manifest exported to: " + targetManifest)
+
+	// create dependencies directory if not exists
+	depDir := filepath.Join(manifestDir, "dependencies")
+
+	if len(bindings) > 0 {
+		fmt.Println("Exporting project dependencies to " + depDir)
 	}
 
-	parsers.Write(maniyaml, utils.Flags.ManifestPath)
-	fmt.Println("Manifest exported to: " + utils.Flags.ManifestPath)
+	// now export dependencies to their own manifests
+	for _, binding := range bindings {
+		pkg, _, err := client.Packages.Get(binding.Name)
+		if err != nil {
+			return err
+		}
+
+		if a := pkg.Annotations.GetValue(utils.MANAGED); a != nil {
+			// decode the JSON blob and retrieve __OW_PROJECT_NAME
+			pa := a.(map[string]interface{})
+
+			os.MkdirAll(depDir, os.ModePerm)
+			depManifestPath := filepath.Join(depDir, pa[utils.OW_PROJECT_NAME].(string)+".yaml")
+
+			// export the whole project as dependency
+			err := exportProject(pa[utils.OW_PROJECT_NAME].(string), depManifestPath)
+			if err != nil {
+				return err
+			}
+		} else {
+			// showing warning to notify user that exported manifest dependent on unmanaged library
which can't be exported
+			fmt.Println("Warning! Dependency package " + binding.Name + " currently unmanaged by any
project. Unable to export this package")
+		}
+	}
 
 	return nil
 }
 
+func ExportCmdImp(cmd *cobra.Command, args []string) error {
+
+	config, _ = deployers.NewWhiskConfig(wskpropsPath, utils.Flags.DeploymentPath, utils.Flags.ManifestPath)
+	client, _ = deployers.CreateNewClient(config)
+
+	// Init supported runtimes and action files extensions maps
+	setSupportedRuntimes(config.Host)
+
+	return exportProject(utils.Flags.ProjectName, utils.Flags.ManifestPath)
+}
+
 const (
 	JAVA_EXT = ".jar"
 	ZIP_EXT  = ".zip"
@@ -310,10 +351,6 @@ func saveCode(action whisk.Action, directory string) (string, error)
{
 
 	path := filepath.Join(directory, filename)
 
-	if utils.FileExists(path) {
-		return "", wskderrors.NewFileReadError(path, wski18n.T(wski18n.ID_ERR_FILE_ALREADY_EXISTS))
-	}
-
 	if err := utils.WriteFile(path, code); err != nil {
 		return "", err
 	}
diff --git a/parsers/manifest_parser.go b/parsers/manifest_parser.go
index 88f8d9f..9cfa673 100644
--- a/parsers/manifest_parser.go
+++ b/parsers/manifest_parser.go
@@ -27,13 +27,14 @@ import (
 
 	"gopkg.in/yaml.v2"
 
+	"path/filepath"
+
 	"github.com/apache/incubator-openwhisk-client-go/whisk"
 	"github.com/apache/incubator-openwhisk-wskdeploy/utils"
 	"github.com/apache/incubator-openwhisk-wskdeploy/wskderrors"
 	"github.com/apache/incubator-openwhisk-wskdeploy/wskenv"
 	"github.com/apache/incubator-openwhisk-wskdeploy/wski18n"
 	"github.com/apache/incubator-openwhisk-wskdeploy/wskprint"
-	"path/filepath"
 )
 
 const (
diff --git a/parsers/manifest_parser_test.go b/parsers/manifest_parser_test.go
index f96ebc1..6c64492 100644
--- a/parsers/manifest_parser_test.go
+++ b/parsers/manifest_parser_test.go
@@ -21,11 +21,6 @@ package parsers
 
 import (
 	"fmt"
-	"github.com/apache/incubator-openwhisk-client-go/whisk"
-	"github.com/apache/incubator-openwhisk-wskdeploy/utils"
-	"github.com/apache/incubator-openwhisk-wskdeploy/wskderrors"
-	"github.com/apache/incubator-openwhisk-wskdeploy/wskprint"
-	"github.com/stretchr/testify/assert"
 	"io/ioutil"
 	"os"
 	"path/filepath"
@@ -33,6 +28,12 @@ import (
 	"strconv"
 	"strings"
 	"testing"
+
+	"github.com/apache/incubator-openwhisk-client-go/whisk"
+	"github.com/apache/incubator-openwhisk-wskdeploy/utils"
+	"github.com/apache/incubator-openwhisk-wskdeploy/wskderrors"
+	"github.com/apache/incubator-openwhisk-wskdeploy/wskprint"
+	"github.com/stretchr/testify/assert"
 )
 
 const (
diff --git a/parsers/yamlparser.go b/parsers/yamlparser.go
index c136dfe..c65896f 100644
--- a/parsers/yamlparser.go
+++ b/parsers/yamlparser.go
@@ -416,6 +416,13 @@ func (yaml *YAML) ComposeParsersTrigger(wsktrg whisk.Trigger) *Trigger
{
 	return trigger
 }
 
+func (yaml *YAML) ComposeParsersDependency(binding whisk.Binding) *Dependency {
+	dependency := new(Dependency)
+	dependency.Location = "/" + binding.Namespace + "/" + binding.Name
+
+	return dependency
+}
+
 func (yaml *YAML) ComposeParsersRule(wskrule whisk.Rule) *Rule {
 	rule := new(Rule)
 	rule.Name = wskrule.Name
diff --git a/tests/src/integration/common/wskdeploy.go b/tests/src/integration/common/wskdeploy.go
index 17755a9..abcbc3a 100644
--- a/tests/src/integration/common/wskdeploy.go
+++ b/tests/src/integration/common/wskdeploy.go
@@ -21,17 +21,18 @@ import (
 	"bytes"
 	"errors"
 	"fmt"
+	"os"
+	"os/exec"
+	"path"
+	"path/filepath"
+	"strings"
+
 	"github.com/apache/incubator-openwhisk-client-go/whisk"
 	"github.com/apache/incubator-openwhisk-wskdeploy/deployers"
 	"github.com/apache/incubator-openwhisk-wskdeploy/utils"
 	"github.com/apache/incubator-openwhisk-wskdeploy/wskderrors"
 	"github.com/fatih/color"
 	"github.com/mattn/go-colorable"
-	"os"
-	"os/exec"
-	"path"
-	"path/filepath"
-	"strings"
 )
 
 const (
@@ -166,6 +167,10 @@ func (wskdeploy *Wskdeploy) UndeployManifestPathOnly(manifestpath string)
(strin
 	return wskdeploy.RunCommand("undeploy", "-m", manifestpath)
 }
 
+func (Wskdeploy *Wskdeploy) ManagedDeploymentOnlyManifest(manifestPath string) (string, error)
{
+	return Wskdeploy.RunCommand("sync", "-m", manifestPath)
+}
+
 func (Wskdeploy *Wskdeploy) ManagedDeployment(manifestPath string, deploymentPath string)
(string, error) {
 	return Wskdeploy.RunCommand("sync", "-m", manifestPath, "-d", deploymentPath)
 }
@@ -174,6 +179,10 @@ func (Wskdeploy *Wskdeploy) HeadlessManagedDeployment(manifestPath string,
deplo
 	return Wskdeploy.RunCommand("sync", "-m", manifestPath, "-d", deploymentPath, "--projectname",
name)
 }
 
+func (wskdeploy *Wskdeploy) ExportProject(projectName string, targetManifestPath string)
(string, error) {
+	return wskdeploy.RunCommand("export", "-m", targetManifestPath, "--projectname", projectName)
+}
+
 // This method is only for testing
 // This method will mock a construction of deployment plan, creating all the memory objects
 // This method CANNOT be used for real deployment!
diff --git a/tests/src/integration/export/export_test.go b/tests/src/integration/export/export_test.go
new file mode 100644
index 0000000..2f3e530
--- /dev/null
+++ b/tests/src/integration/export/export_test.go
@@ -0,0 +1,72 @@
+// +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 (
+	"os"
+	"testing"
+
+	"github.com/apache/incubator-openwhisk-wskdeploy/tests/src/integration/common"
+	"github.com/stretchr/testify/assert"
+)
+
+func TestExport(t *testing.T) {
+	projectName := "EXT_PROJECT"
+	wskdeploy := common.NewWskdeploy()
+
+	_, err := wskdeploy.ManagedDeploymentOnlyManifest(manifestLib1Path)
+	assert.Equal(t, nil, err, "Failed to deploy the lib1 manifest file.")
+
+	_, err = wskdeploy.ManagedDeploymentOnlyManifest(manifestLib2Path)
+	assert.Equal(t, nil, err, "Failed to deploy the lib2 manifest file.")
+
+	_, err = wskdeploy.ManagedDeploymentOnlyManifest(manifestExtPath)
+	assert.Equal(t, nil, err, "Failed to deploy the ext manifest file.")
+
+	_, err = wskdeploy.ExportProject(projectName, targetManifestPath)
+	assert.Equal(t, nil, err, "Failed to export project.")
+
+	_, err = os.Stat(targetManifestPath)
+	assert.Equal(t, nil, err, "Missing exported manifest file")
+
+	_, err = os.Stat(targetManifestFolder + "dependencies/lib1.yaml")
+	assert.Equal(t, nil, err, "Missing exported dependencies lib1 manifest")
+
+	_, err = os.Stat(targetManifestFolder + "dependencies/lib1_package/lib1_greeting1.js")
+	assert.Equal(t, nil, err, "Missing exported dependencies lib1 resources")
+
+	_, err = wskdeploy.UndeployManifestPathOnly(manifestExtPath)
+	assert.Equal(t, nil, err, "Failed to undeploy the ext.")
+
+	_, err = wskdeploy.UndeployManifestPathOnly(manifestLib2Path)
+	assert.Equal(t, nil, err, "Failed to undeploy the lib1.")
+
+	_, err = wskdeploy.UndeployManifestPathOnly(manifestLib1Path)
+	assert.Equal(t, nil, err, "Failed to undeploy the lib2.")
+}
+
+var (
+	manifestLib1Path = os.Getenv("GOPATH") + "/src/github.com/apache/incubator-openwhisk-wskdeploy/tests/src/integration/export/manifest_lib1.yaml"
+	manifestLib2Path = os.Getenv("GOPATH") + "/src/github.com/apache/incubator-openwhisk-wskdeploy/tests/src/integration/export/manifest_lib2.yaml"
+	manifestExtPath  = os.Getenv("GOPATH") + "/src/github.com/apache/incubator-openwhisk-wskdeploy/tests/src/integration/export/manifest_ext.yaml"
+
+	targetManifestFolder = os.Getenv("GOPATH") + "/src/github.com/apache/incubator-openwhisk-wskdeploy/tests/src/integration/export/tmp/"
+	targetManifestPath   = targetManifestFolder + "manifest.yaml"
+)
diff --git a/tests/src/integration/export/manifest_ext.yaml b/tests/src/integration/export/manifest_ext.yaml
new file mode 100644
index 0000000..b0dcfb8
--- /dev/null
+++ b/tests/src/integration/export/manifest_ext.yaml
@@ -0,0 +1,35 @@
+#
+# 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.
+#
+
+project:
+  name: EXT_PROJECT
+packages:
+  EXT_PACKAGE:
+      dependencies:
+        ext_lib1_bind:
+          location: /_/lib1_package
+        ext_lib2_bind:
+          location: /_/lib2_package
+      triggers:
+        trigger_ext1:
+        trigger_ext2:
+      rules:
+        rule_ext1:
+          trigger: trigger_ext1
+          action: ext_lib1_bind/lib1_greeting1
+        rule_ext2:
+          trigger: trigger_ext2
+          action: ext_lib2_bind/lib2_greeting1
diff --git a/tests/src/integration/export/manifest_lib1.yaml b/tests/src/integration/export/manifest_lib1.yaml
new file mode 100644
index 0000000..446d90b
--- /dev/null
+++ b/tests/src/integration/export/manifest_lib1.yaml
@@ -0,0 +1,35 @@
+#
+# 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.
+#
+
+project:
+  name: lib1
+packages:
+  lib1_package:
+      version: 1.0
+      license: Apache-2.0
+      actions:
+        lib1_greeting1:
+          version: 1.0
+          function: src/greeting.js
+          runtime: nodejs:6
+        lib1_greeting2:
+          version: 1.0
+          function: src/greeting.js
+          runtime: nodejs:6
+        lib1_greeting3:
+          version: 1.0
+          function: src/greeting.js
+          runtime: nodejs:6
diff --git a/tests/src/integration/export/manifest_lib2.yaml b/tests/src/integration/export/manifest_lib2.yaml
new file mode 100644
index 0000000..e9dab41
--- /dev/null
+++ b/tests/src/integration/export/manifest_lib2.yaml
@@ -0,0 +1,35 @@
+#
+# 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.
+#
+
+project:
+  name: lib2
+packages:
+  lib2_package:
+      version: 1.0
+      license: Apache-2.0
+      actions:
+        lib2_greeting1:
+          version: 1.0
+          function: src/greeting.js
+          runtime: nodejs:6
+        lib2_greeting2:
+          version: 1.0
+          function: src/greeting.js
+          runtime: nodejs:6
+        lib2_greeting3:
+          version: 1.0
+          function: src/greeting.js
+          runtime: nodejs:6
diff --git a/tests/src/integration/export/src/greeting.js b/tests/src/integration/export/src/greeting.js
new file mode 100644
index 0000000..eaa6834
--- /dev/null
+++ b/tests/src/integration/export/src/greeting.js
@@ -0,0 +1,11 @@
+/**
+ * Return a simple greeting message for someone.
+ *
+ * @param name A person's name.
+ * @param place Where the person is from.
+ */
+function main(params) {
+    var name = params.name || params.payload || 'stranger';
+    var place = params.place || 'somewhere';
+    return {payload:  'Hello, ' + name + ' from ' + place + '!'};
+}
diff --git a/utils/managedannotations.go b/utils/managedannotations.go
index 858b2b5..4023c10 100644
--- a/utils/managedannotations.go
+++ b/utils/managedannotations.go
@@ -21,8 +21,9 @@ import (
 	"crypto/sha1"
 	"encoding/json"
 	"fmt"
-	"github.com/apache/incubator-openwhisk-client-go/whisk"
 	"os"
+
+	"github.com/apache/incubator-openwhisk-client-go/whisk"
 )
 
 /*
diff --git a/wski18n/i18n_ids.go b/wski18n/i18n_ids.go
index 25ceb06..3677f90 100644
--- a/wski18n/i18n_ids.go
+++ b/wski18n/i18n_ids.go
@@ -41,6 +41,7 @@ const (
 	CMD_UNDEPLOY       = "undeploy"
 	CMD_SYNC           = "sync"
 	TRIGGERS           = "Triggers"
+	BINDING            = "binding"
 )
 
 // DO NOT TRANSLATE

-- 
To stop receiving notification emails like this one, please contact
pdesai@apache.org.

Mime
View raw message