You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@openwhisk.apache.org by GitBox <gi...@apache.org> on 2018/03/28 21:24:41 UTC

[GitHub] pritidesai closed pull request #828: Extend export to support project with dependencies

pritidesai closed pull request #828: Extend export to support project with dependencies
URL: https://github.com/apache/incubator-openwhisk-wskdeploy/pull/828
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

diff --git a/cmd/export.go b/cmd/export.go
index 437fb4f2..3585da51 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 88f8d9f0..9cfa6732 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 f96ebc14..6c644922 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 c136dfed..c65896f3 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 17755a99..abcbc3ab 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 00000000..2f3e530e
--- /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 00000000..b0dcfb8f
--- /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 00000000..446d90b2
--- /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 00000000..e9dab41e
--- /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 00000000..eaa68346
--- /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 858b2b57..4023c10d 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 25ceb062..3677f90f 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


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services