adding env. variables in action function (#893)

* adding env. variables in action function

* adding newline
diff --git a/parsers/manifest_parser.go b/parsers/manifest_parser.go
index c275731..16036b2 100644
--- a/parsers/manifest_parser.go
+++ b/parsers/manifest_parser.go
@@ -513,21 +513,23 @@
 	var actionFilePath string
 	var zipFileName string
 	exec := new(whisk.Exec)
+	f := wskenv.InterpolateStringWithEnvVar(action.Function)
+	interpolatedActionFunction := f.(string)
 
 	// check if action function is pointing to an URL
 	// we do not support if function is pointing to remote directory
 	// therefore error out if there is a combination of http/https ending in a directory
-	if strings.HasPrefix(action.Function, HTTP) || strings.HasPrefix(action.Function, HTTPS) {
-		if len(path.Ext(action.Function)) == 0 {
+	if strings.HasPrefix(interpolatedActionFunction, HTTP) || strings.HasPrefix(interpolatedActionFunction, HTTPS) {
+		if len(path.Ext(interpolatedActionFunction)) == 0 {
 			err := wski18n.T(wski18n.ID_ERR_ACTION_FUNCTION_REMOTE_DIR_NOT_SUPPORTED_X_action_X_url_X,
 				map[string]interface{}{
 					wski18n.KEY_ACTION: action.Name,
-					wski18n.KEY_URL:    action.Function})
+					wski18n.KEY_URL:    interpolatedActionFunction})
 			return actionFilePath, nil, wskderrors.NewYAMLFileFormatError(manifestFilePath, err)
 		}
-		actionFilePath = action.Function
+		actionFilePath = interpolatedActionFunction
 	} else {
-		actionFilePath = strings.TrimRight(manifestFilePath, manifestFileName) + action.Function
+		actionFilePath = strings.TrimRight(manifestFilePath, manifestFileName) + interpolatedActionFunction
 	}
 
 	if utils.IsDirectory(actionFilePath) {
diff --git a/parsers/manifest_parser_test.go b/parsers/manifest_parser_test.go
index 087edb1..1ff08f3 100644
--- a/parsers/manifest_parser_test.go
+++ b/parsers/manifest_parser_test.go
@@ -53,9 +53,10 @@
 	TEST_MSG_ACTION_DOCKER_IMAGE_MISMATCH           = "Docker action image had a value mismatch."
 	TEST_MSG_ACTION_CODE_MISSING                    = "Action code is missing."
 	TEST_MSG_INVALID_ACTION_ANNOTATION              = "Action annotations are invalid"
+	TEST_MSG_ACTION_FUNCTION_PATH_MISSING           = "Action function path missing"
 
 	// local error messages
-	TEST_ERROR_MANIFEST_PARSE_FAILURE     = "Manifest [%s]: Failed to parse."
+	TEST_ERROR_MANIFEST_PARSE_FAILURE     = "Manifest [%s]: Failed to parse. Error: %s"
 	TEST_ERROR_MANIFEST_READ_FAILURE      = "Manifest [%s]: Failed to ReadFile()."
 	TEST_ERROR_MANIFEST_DATA_UNMARSHALL   = "Manifest [%s]: Failed to Unmarshall manifest."
 	TEST_ERROR_COMPOSE_ACTION_FAILURE     = "Manifest [%s]: Failed to compose actions."
@@ -77,7 +78,7 @@
 	p := NewYAMLParser()
 	m, err := p.ParseManifest(manifestFile)
 	if err != nil {
-		assert.Fail(t, fmt.Sprintf(TEST_ERROR_MANIFEST_PARSE_FAILURE, manifestFile))
+		assert.Fail(t, fmt.Sprintf(TEST_ERROR_MANIFEST_PARSE_FAILURE, manifestFile, err.Error()))
 	}
 	return p, m, err
 }
@@ -936,6 +937,25 @@
 	}
 }
 
+func TestComposeActionsForEnvVariableInFunction(t *testing.T) {
+	os.Setenv("OPENWHISK_FUNCTION_FILE", "../src/integration/helloworld/actions/hello.js")
+	os.Setenv("OPENWHISK_FUNCTION_PYTHON", "../src/integration/helloworld/actions/hello")
+	os.Setenv("OPENWHISK_FUNCTION_GITHUB", "raw.githubusercontent.com/apache/incubator-openwhisk-wskdeploy/master/tests/src/integration/helloworld/actions/hello")
+
+	file := "../tests/dat/manifest_data_compose_actions_for_function_with_env_variable.yaml"
+	p, m, _ := testLoadParseManifest(t, file)
+
+	actions, err := p.ComposeActionsFromAllPackages(m, m.Filepath, whisk.KeyValue{})
+	assert.Nil(t, err, fmt.Sprintf(TEST_ERROR_COMPOSE_ACTION_FAILURE, file))
+
+	for _, action := range actions {
+		assert.NotNil(t, action.Action.Code, fmt.Sprintf(TEST_MSG_ACTION_FUNCTION_PATH_MISSING))
+	}
+	os.Unsetenv("OPENWHISK_FUNCTION_FILE")
+	os.Unsetenv("OPENWHISK_FUNCTION_PYTHON")
+	os.Unsetenv("OPENWHISK_FUNCTION_GITHUB")
+}
+
 // Test 14: validate manifest_parser.ComposeActions() method
 func TestComposeActionsForLimits(t *testing.T) {
 
diff --git a/tests/dat/manifest_data_compose_actions_for_function_with_env_variable.yaml b/tests/dat/manifest_data_compose_actions_for_function_with_env_variable.yaml
new file mode 100644
index 0000000..5756bf0
--- /dev/null
+++ b/tests/dat/manifest_data_compose_actions_for_function_with_env_variable.yaml
@@ -0,0 +1,18 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more contributor
+# license agreements; and to You under the Apache License, Version 2.0.
+#
+
+packages:
+    helloworld:
+        actions:
+            hello1:
+                function: ${OPENWHISK_FUNCTION_FILE}
+                runtime: nodejs:6
+            hello2:
+                function: $OPENWHISK_FUNCTION_FILE
+                runtime: nodejs:6
+            hello3:
+                function: ${OPENWHISK_FUNCTION_PYTHON}.py
+            hello4:
+                function: https://${OPENWHISK_FUNCTION_GITHUB}.js