You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openwhisk.apache.org by pd...@apache.org on 2018/03/14 21:23:01 UTC

[incubator-openwhisk-wskdeploy] branch master updated: Add support to export binary (zip and jar) actions (#790)

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 4209ba9  Add support to export binary (zip and jar) actions (#790)
4209ba9 is described below

commit 4209ba99a9ec1dbfa2d9ba815d49c4c4cf54e5d3
Author: kpavel <kp...@il.ibm.com>
AuthorDate: Wed Mar 14 23:22:59 2018 +0200

    Add support to export binary (zip and jar) actions (#790)
    
    * Add support to export binary (zip and jar) actions
    
    * Fix i18n resources issues
    
    * Fixes error when empty api map passed to manifest
    
    * Fixes error when empty api map passed to manifest
---
 cmd/export.go                    | 84 +++++++++++++++++++++++++++++++---------
 parsers/manifest_parser.go       |  5 ++-
 utils/fileoperations.go          | 16 ++++++++
 wski18n/i18n_ids.go              |  4 ++
 wski18n/i18n_resources.go        | 56 +++++++++++++--------------
 wski18n/resources/en_US.all.json |  8 ++++
 6 files changed, 124 insertions(+), 49 deletions(-)

diff --git a/cmd/export.go b/cmd/export.go
index ede3ba0..1f8655c 100644
--- a/cmd/export.go
+++ b/cmd/export.go
@@ -18,6 +18,7 @@
 package cmd
 
 import (
+	"encoding/base64"
 	"errors"
 	"fmt"
 	"os"
@@ -29,6 +30,7 @@ import (
 	"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"
 	"github.com/spf13/cobra"
 )
 
@@ -88,34 +90,20 @@ func ExportAction(actionName string, packageName string, maniyaml *parsers.YAML)
 		pkg.Sequences[wskAction.Name] = *seq
 	} else {
 		parsedAction := *maniyaml.ComposeParsersAction(*wskAction)
-
-		// get the action file extension according to action kind (e.g. js for nodejs)
-		ext := utils.FileRuntimeExtensionsMap[wskAction.Exec.Kind]
-
 		manifestDir := filepath.Dir(utils.Flags.ManifestPath)
 
 		// store function file under action package name subdirectory in the specified manifest folder
 		functionDir := filepath.Join(manifestDir, packageName)
 		os.MkdirAll(functionDir, os.ModePerm)
 
-		// store function in manifest under path relative to manifest root
-		functionFile := filepath.Join(packageName, wskAction.Name) + "." + ext
-		parsedAction.Function = functionFile
-
-		// create function file at the full path
-		functionFile = filepath.Join(manifestDir, functionFile)
-		f, err := os.Create(functionFile)
+		// save code file at the full path
+		filename, err := saveCode(*wskAction, functionDir)
 		if err != nil {
-			return wskderrors.NewFileReadError(functionFile, err.Error())
+			return err
 		}
 
-		defer f.Close()
-
-		// store action function in the filesystem next to the manifest.yml
-		// TODO: consider to name files by namespace + action to make function file names unique
-		if wskAction.Exec.Code != nil {
-			f.Write([]byte(*wskAction.Exec.Code))
-		}
+		// store function in manifest under path relative to manifest root
+		parsedAction.Function = filepath.Join(packageName, filename)
 		pkg.Actions[wskAction.Name] = parsedAction
 	}
 
@@ -275,6 +263,64 @@ func ExportCmdImp(cmd *cobra.Command, args []string) error {
 	return nil
 }
 
+const (
+	JAVA_EXT = ".jar"
+	ZIP_EXT  = ".zip"
+	BLACKBOX = "blackbox"
+	JAVA     = "java"
+)
+
+func getBinaryKindExtension(runtime string) (extension string) {
+	switch strings.ToLower(runtime) {
+	case JAVA:
+		extension = JAVA_EXT
+	default:
+		extension = ZIP_EXT
+	}
+
+	return extension
+}
+
+func saveCode(action whisk.Action, directory string) (string, error) {
+	var code string
+	var runtime string
+	var exec whisk.Exec
+
+	exec = *action.Exec
+	runtime = strings.Split(exec.Kind, ":")[0]
+
+	if strings.ToLower(runtime) == BLACKBOX {
+		return "", wskderrors.NewInvalidRuntimeError(wski18n.T(wski18n.ID_ERR_CANT_SAVE_DOCKER_RUNTIME),
+			directory, action.Name, BLACKBOX, utils.ListOfSupportedRuntimes(utils.SupportedRunTimes))
+	}
+
+	if exec.Code != nil {
+		code = *exec.Code
+	}
+
+	var filename = ""
+	if *exec.Binary {
+		decoded, _ := base64.StdEncoding.DecodeString(code)
+		code = string(decoded)
+
+		filename = action.Name + getBinaryKindExtension(runtime)
+	} else {
+		filename = action.Name + "." + utils.FileRuntimeExtensionsMap[action.Exec.Kind]
+	}
+
+	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
+	}
+
+	return filename, nil
+}
+
 func init() {
 	RootCmd.AddCommand(exportCmd)
 }
diff --git a/parsers/manifest_parser.go b/parsers/manifest_parser.go
index 3a626e7..9a831c8 100644
--- a/parsers/manifest_parser.go
+++ b/parsers/manifest_parser.go
@@ -20,12 +20,13 @@ package parsers
 import (
 	"encoding/base64"
 	"errors"
-	"gopkg.in/yaml.v2"
 	"io/ioutil"
 	"os"
 	"path"
 	"strings"
 
+	"gopkg.in/yaml.v2"
+
 	"github.com/apache/incubator-openwhisk-client-go/whisk"
 	"github.com/apache/incubator-openwhisk-wskdeploy/utils"
 	"github.com/apache/incubator-openwhisk-wskdeploy/wskderrors"
@@ -994,7 +995,7 @@ func (dm *YAMLParser) ComposeApiRecordsFromAllPackages(client *whisk.Config, man
 func (dm *YAMLParser) ComposeApiRecords(client *whisk.Config, packageName string, pkg Package, manifestPath string) ([]*whisk.ApiCreateRequest, error) {
 	var requests []*whisk.ApiCreateRequest = make([]*whisk.ApiCreateRequest, 0)
 
-	if pkg.Apis != nil {
+	if pkg.Apis != nil && len(pkg.Apis) != 0 {
 		// verify APIGW_ACCESS_TOKEN is set before composing APIs
 		// until this point, we dont know whether APIs are specified in manifest or not
 		if len(client.ApigwAccessToken) == 0 {
diff --git a/utils/fileoperations.go b/utils/fileoperations.go
index 7838641..1c3d5b9 100644
--- a/utils/fileoperations.go
+++ b/utils/fileoperations.go
@@ -127,3 +127,19 @@ func WriteProps(path string, props map[string]string) error {
 	}
 	return nil
 }
+
+func WriteFile(filename string, content string) error {
+	file, err := os.Create(filename)
+
+	if err != nil {
+		return err
+	}
+
+	defer file.Close()
+
+	if _, err = file.WriteString(content); err != nil {
+		return err
+	}
+
+	return nil
+}
diff --git a/wski18n/i18n_ids.go b/wski18n/i18n_ids.go
index 9d9e7c7..1c081b9 100644
--- a/wski18n/i18n_ids.go
+++ b/wski18n/i18n_ids.go
@@ -180,6 +180,8 @@ const (
 	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"
 
 	// Server-side Errors (wskdeploy as an Action)
 	ID_ERR_JSON_MISSING_KEY_CMD = "msg_err_json_missing_cmd_key"
@@ -254,6 +256,8 @@ var I18N_ID_SET = [](string){
 	ID_ERR_RUNTIMES_GET_X_err_X,
 	ID_ERR_URL_INVALID_X_urltype_X_url_X_filetype_X,
 	ID_ERR_URL_MALFORMED_X_urltype_X_url_X,
+	ID_ERR_CANT_SAVE_DOCKER_RUNTIME,
+	ID_ERR_FILE_ALREADY_EXISTS,
 	ID_MSG_COMMAND_USING_X_cmd_X_filetype_X_path_X,
 	ID_MSG_CONFIG_INFO_APIHOST_X_host_X_source_X,
 	ID_MSG_CONFIG_INFO_AUTHKEY_X_source_X,
diff --git a/wski18n/i18n_resources.go b/wski18n/i18n_resources.go
index 5652ab1..0d5bd79 100644
--- a/wski18n/i18n_resources.go
+++ b/wski18n/i18n_resources.go
@@ -92,12 +92,12 @@ func wski18nResourcesDe_deAllJson() (*asset, error) {
 		return nil, err
 	}
 
-	info := bindataFileInfo{name: "wski18n/resources/de_DE.all.json", size: 0, mode: os.FileMode(420), modTime: time.Unix(1520374115, 0)}
+	info := bindataFileInfo{name: "wski18n/resources/de_DE.all.json", size: 0, mode: os.FileMode(438), modTime: time.Unix(1517928990, 0)}
 	a := &asset{bytes: bytes, info: info}
 	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\x1c\x70\x08\xb0\x38\xe4\x2e\x69\xbb\xd7\x26\x1b\xec\x26\x17\x14\xe9\x42\xa1\xc5\xb1\xcd\x5a\x22\x05\x92\xb2\xe3\x1a\xfe\xee\x87\xe1\x1f\x49\xf6\x2e\x25\xad\xd3\xe2\xf2\xa6\x6e\x38\x9c\xf9\xcd\x90\xfc\x71\x66\xa8\x7c\x7a\x04\xb0\x7f\x04\x00\xf0\x58\xf0\xc7\x2f\xe0\x71\x65\x96\x79\xad\x71\x21\xbe\xe4\xa8\xb5\xd2\x8f\x67\x7e\xd4\x6a [...]
+var _wski18nResourcesEn_usAllJson = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xc4\x5b\x6d\x8f\xdb\xb6\xb2\xfe\x9e\x5f\x31\x08\x2e\x90\x16\x70\x94\xb4\x17\x17\xb8\x08\xb0\x38\xc8\x69\xd2\x76\x4f\x9b\x6c\xb0\x9b\x9c\xa0\x48\x17\x0a\x2d\x8e\x6d\xd6\x12\x29\x90\x94\x1d\xd7\xf0\x7f\x3f\x18\xbe\x48\xb2\x77\x29\x69\x9d\x16\x27\x5f\xea\x86\xc3\x99\x67\x86\xe4\xc3\x99\xa1\xf2\xe9\x11\xc0\xfe\x11\x00\xc0\x63\xc1\x1f\xbf\x80\xc7\x95\x59\xe6\xb5\xc6\x85\xf8\x92\xa3\xd6\x4a\x3f\x9e\xf9\x51\xab [...]
 
 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: 13905, mode: os.FileMode(420), modTime: time.Unix(1520557776, 0)}
+	info := bindataFileInfo{name: "wski18n/resources/en_US.all.json", size: 14092, mode: os.FileMode(438), modTime: time.Unix(1520952786, 0)}
 	a := &asset{bytes: bytes, info: info}
 	return a, nil
 }
@@ -132,7 +132,7 @@ func wski18nResourcesEs_esAllJson() (*asset, error) {
 		return nil, err
 	}
 
-	info := bindataFileInfo{name: "wski18n/resources/es_ES.all.json", size: 0, mode: os.FileMode(420), modTime: time.Unix(1520374115, 0)}
+	info := bindataFileInfo{name: "wski18n/resources/es_ES.all.json", size: 0, mode: os.FileMode(438), modTime: time.Unix(1517928990, 0)}
 	a := &asset{bytes: bytes, info: info}
 	return a, nil
 }
@@ -152,7 +152,7 @@ func wski18nResourcesFr_frAllJson() (*asset, error) {
 		return nil, err
 	}
 
-	info := bindataFileInfo{name: "wski18n/resources/fr_FR.all.json", size: 101, mode: os.FileMode(420), modTime: time.Unix(1520374115, 0)}
+	info := bindataFileInfo{name: "wski18n/resources/fr_FR.all.json", size: 101, mode: os.FileMode(438), modTime: time.Unix(1517928990, 0)}
 	a := &asset{bytes: bytes, info: info}
 	return a, nil
 }
@@ -172,7 +172,7 @@ func wski18nResourcesIt_itAllJson() (*asset, error) {
 		return nil, err
 	}
 
-	info := bindataFileInfo{name: "wski18n/resources/it_IT.all.json", size: 0, mode: os.FileMode(420), modTime: time.Unix(1520374115, 0)}
+	info := bindataFileInfo{name: "wski18n/resources/it_IT.all.json", size: 0, mode: os.FileMode(438), modTime: time.Unix(1517928990, 0)}
 	a := &asset{bytes: bytes, info: info}
 	return a, nil
 }
@@ -192,7 +192,7 @@ func wski18nResourcesJa_jaAllJson() (*asset, error) {
 		return nil, err
 	}
 
-	info := bindataFileInfo{name: "wski18n/resources/ja_JA.all.json", size: 0, mode: os.FileMode(420), modTime: time.Unix(1520374115, 0)}
+	info := bindataFileInfo{name: "wski18n/resources/ja_JA.all.json", size: 0, mode: os.FileMode(438), modTime: time.Unix(1517928990, 0)}
 	a := &asset{bytes: bytes, info: info}
 	return a, nil
 }
@@ -212,7 +212,7 @@ func wski18nResourcesKo_krAllJson() (*asset, error) {
 		return nil, err
 	}
 
-	info := bindataFileInfo{name: "wski18n/resources/ko_KR.all.json", size: 0, mode: os.FileMode(420), modTime: time.Unix(1520374115, 0)}
+	info := bindataFileInfo{name: "wski18n/resources/ko_KR.all.json", size: 0, mode: os.FileMode(438), modTime: time.Unix(1517928990, 0)}
 	a := &asset{bytes: bytes, info: info}
 	return a, nil
 }
@@ -232,7 +232,7 @@ func wski18nResourcesPt_brAllJson() (*asset, error) {
 		return nil, err
 	}
 
-	info := bindataFileInfo{name: "wski18n/resources/pt_BR.all.json", size: 0, mode: os.FileMode(420), modTime: time.Unix(1520374115, 0)}
+	info := bindataFileInfo{name: "wski18n/resources/pt_BR.all.json", size: 0, mode: os.FileMode(438), modTime: time.Unix(1517928990, 0)}
 	a := &asset{bytes: bytes, info: info}
 	return a, nil
 }
@@ -252,7 +252,7 @@ func wski18nResourcesZh_hansAllJson() (*asset, error) {
 		return nil, err
 	}
 
-	info := bindataFileInfo{name: "wski18n/resources/zh_Hans.all.json", size: 0, mode: os.FileMode(420), modTime: time.Unix(1520374115, 0)}
+	info := bindataFileInfo{name: "wski18n/resources/zh_Hans.all.json", size: 0, mode: os.FileMode(438), modTime: time.Unix(1517928990, 0)}
 	a := &asset{bytes: bytes, info: info}
 	return a, nil
 }
@@ -272,7 +272,7 @@ func wski18nResourcesZh_hantAllJson() (*asset, error) {
 		return nil, err
 	}
 
-	info := bindataFileInfo{name: "wski18n/resources/zh_Hant.all.json", size: 0, mode: os.FileMode(420), modTime: time.Unix(1520374115, 0)}
+	info := bindataFileInfo{name: "wski18n/resources/zh_Hant.all.json", size: 0, mode: os.FileMode(438), modTime: time.Unix(1517928990, 0)}
 	a := &asset{bytes: bytes, info: info}
 	return a, nil
 }
@@ -329,14 +329,14 @@ func AssetNames() []string {
 
 // _bindata is a table, holding each asset generator, mapped to its name.
 var _bindata = map[string]func() (*asset, error){
-	"wski18n/resources/de_DE.all.json":   wski18nResourcesDe_deAllJson,
-	"wski18n/resources/en_US.all.json":   wski18nResourcesEn_usAllJson,
-	"wski18n/resources/es_ES.all.json":   wski18nResourcesEs_esAllJson,
-	"wski18n/resources/fr_FR.all.json":   wski18nResourcesFr_frAllJson,
-	"wski18n/resources/it_IT.all.json":   wski18nResourcesIt_itAllJson,
-	"wski18n/resources/ja_JA.all.json":   wski18nResourcesJa_jaAllJson,
-	"wski18n/resources/ko_KR.all.json":   wski18nResourcesKo_krAllJson,
-	"wski18n/resources/pt_BR.all.json":   wski18nResourcesPt_brAllJson,
+	"wski18n/resources/de_DE.all.json": wski18nResourcesDe_deAllJson,
+	"wski18n/resources/en_US.all.json": wski18nResourcesEn_usAllJson,
+	"wski18n/resources/es_ES.all.json": wski18nResourcesEs_esAllJson,
+	"wski18n/resources/fr_FR.all.json": wski18nResourcesFr_frAllJson,
+	"wski18n/resources/it_IT.all.json": wski18nResourcesIt_itAllJson,
+	"wski18n/resources/ja_JA.all.json": wski18nResourcesJa_jaAllJson,
+	"wski18n/resources/ko_KR.all.json": wski18nResourcesKo_krAllJson,
+	"wski18n/resources/pt_BR.all.json": wski18nResourcesPt_brAllJson,
 	"wski18n/resources/zh_Hans.all.json": wski18nResourcesZh_hansAllJson,
 	"wski18n/resources/zh_Hant.all.json": wski18nResourcesZh_hantAllJson,
 }
@@ -380,18 +380,17 @@ type bintree struct {
 	Func     func() (*asset, error)
 	Children map[string]*bintree
 }
-
 var _bintree = &bintree{nil, map[string]*bintree{
 	"wski18n": &bintree{nil, map[string]*bintree{
 		"resources": &bintree{nil, map[string]*bintree{
-			"de_DE.all.json":   &bintree{wski18nResourcesDe_deAllJson, map[string]*bintree{}},
-			"en_US.all.json":   &bintree{wski18nResourcesEn_usAllJson, map[string]*bintree{}},
-			"es_ES.all.json":   &bintree{wski18nResourcesEs_esAllJson, map[string]*bintree{}},
-			"fr_FR.all.json":   &bintree{wski18nResourcesFr_frAllJson, map[string]*bintree{}},
-			"it_IT.all.json":   &bintree{wski18nResourcesIt_itAllJson, map[string]*bintree{}},
-			"ja_JA.all.json":   &bintree{wski18nResourcesJa_jaAllJson, map[string]*bintree{}},
-			"ko_KR.all.json":   &bintree{wski18nResourcesKo_krAllJson, map[string]*bintree{}},
-			"pt_BR.all.json":   &bintree{wski18nResourcesPt_brAllJson, map[string]*bintree{}},
+			"de_DE.all.json": &bintree{wski18nResourcesDe_deAllJson, map[string]*bintree{}},
+			"en_US.all.json": &bintree{wski18nResourcesEn_usAllJson, map[string]*bintree{}},
+			"es_ES.all.json": &bintree{wski18nResourcesEs_esAllJson, map[string]*bintree{}},
+			"fr_FR.all.json": &bintree{wski18nResourcesFr_frAllJson, map[string]*bintree{}},
+			"it_IT.all.json": &bintree{wski18nResourcesIt_itAllJson, map[string]*bintree{}},
+			"ja_JA.all.json": &bintree{wski18nResourcesJa_jaAllJson, map[string]*bintree{}},
+			"ko_KR.all.json": &bintree{wski18nResourcesKo_krAllJson, map[string]*bintree{}},
+			"pt_BR.all.json": &bintree{wski18nResourcesPt_brAllJson, map[string]*bintree{}},
 			"zh_Hans.all.json": &bintree{wski18nResourcesZh_hansAllJson, map[string]*bintree{}},
 			"zh_Hant.all.json": &bintree{wski18nResourcesZh_hantAllJson, map[string]*bintree{}},
 		}},
@@ -444,3 +443,4 @@ func _filePath(dir, name string) string {
 	cannonicalName := strings.Replace(name, "\\", "/", -1)
 	return filepath.Join(append([]string{dir}, strings.Split(cannonicalName, "/")...)...)
 }
+
diff --git a/wski18n/resources/en_US.all.json b/wski18n/resources/en_US.all.json
index 51b3808..6d3cabf 100644
--- a/wski18n/resources/en_US.all.json
+++ b/wski18n/resources/en_US.all.json
@@ -324,6 +324,14 @@
     "translation": "Action [{{.action}}] has function pointing to remote directory [{{.url}}], such actions are not supported."
   },
   {
+    "id": "msg_err_cant_save_docker",
+    "translation": "Cannot save Docker images."
+  },
+  {
+    "id": "msg_err_file_already_exists",
+    "translation": "File already exists."
+  },
+  {
     "id": "WARNINGS",
     "translation": "================= WARNINGS ==================="
   },

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