in parsers/manifest_parser.go [638:770]
func (dm *YAMLParser) readActionFunction(manifestFilePath string, manifestFileName string, action Action) (string, *whisk.Exec, error) {
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(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: interpolatedActionFunction})
return actionFilePath, nil, wskderrors.NewYAMLFileFormatError(manifestFilePath, err)
}
actionFilePath = interpolatedActionFunction
} else {
actionFilePath = strings.TrimRight(manifestFilePath, manifestFileName) + interpolatedActionFunction
}
if utils.IsDirectory(actionFilePath) {
zipFileName = actionFilePath + "." + runtimes.ZIP_FILE_EXTENSION
err := utils.NewZipWriter(actionFilePath, zipFileName, action.Include, action.Exclude, filepath.Dir(manifestFilePath)).Zip()
if err != nil {
return actionFilePath, nil, err
}
defer os.Remove(zipFileName)
actionFilePath = zipFileName
}
action.Function = actionFilePath
// determine extension of the given action source file
ext := filepath.Ext(actionFilePath)
// drop the "." from file extension
if len(ext) > 0 && ext[0] == '.' {
ext = ext[1:]
}
// determine default runtime for the given file extension
var kind string
r := runtimes.FileExtensionRuntimeKindMap[ext]
kind = runtimes.DefaultRunTimes[r]
if err := dm.validateActionFunction(manifestFileName, action, ext, kind); err != nil {
return actionFilePath, nil, err
}
exec.Kind = kind
dat, err := utils.Read(actionFilePath)
if err != nil {
return actionFilePath, nil, err
}
code := string(dat)
if ext == runtimes.ZIP_FILE_EXTENSION || ext == runtimes.JAR_FILE_EXTENSION {
code = base64.StdEncoding.EncodeToString([]byte(dat))
}
exec.Code = &code
/*
* Action.Runtime
* Perform few checks if action runtime is specified in manifest YAML file
* (1) Check if specified runtime is one of the supported runtimes by OpenWhisk server
* (2) Check if specified runtime is consistent with action source file extensions
* Set the action runtime to match with the source file extension, if wskdeploy is not invoked in strict mode
*/
if len(action.Runtime) != 0 {
if runtimes.CheckExistRuntime(action.Runtime, runtimes.SupportedRunTimes) {
// for zip actions, rely on the runtimes from the manifest file as it can not be derived from the action source file extension
// pick runtime from manifest file if its supported by OpenWhisk server
if ext == runtimes.ZIP_FILE_EXTENSION {
exec.Kind = action.Runtime
} else {
if runtimes.CheckRuntimeConsistencyWithFileExtension(ext, action.Runtime) {
exec.Kind = action.Runtime
} else {
warnStr := wski18n.T(wski18n.ID_ERR_RUNTIME_MISMATCH_X_runtime_X_ext_X_action_X,
map[string]interface{}{
wski18n.KEY_RUNTIME: action.Runtime,
wski18n.KEY_EXTENSION: ext,
wski18n.KEY_ACTION: action.Name})
wskprint.PrintOpenWhiskWarning(warnStr)
// even if runtime is not consistent with file extension, deploy action with specified runtime in strict mode
if utils.Flags.Strict {
exec.Kind = action.Runtime
} else {
warnStr := wski18n.T(wski18n.ID_WARN_RUNTIME_CHANGED_X_runtime_X_action_X,
map[string]interface{}{
wski18n.KEY_RUNTIME: exec.Kind,
wski18n.KEY_ACTION: action.Name})
wskprint.PrintOpenWhiskWarning(warnStr)
}
}
}
} else {
warnStr := wski18n.T(wski18n.ID_ERR_RUNTIME_INVALID_X_runtime_X_action_X,
map[string]interface{}{
wski18n.KEY_RUNTIME: action.Runtime,
wski18n.KEY_ACTION: action.Name})
wskprint.PrintOpenWhiskWarning(warnStr)
if ext == runtimes.ZIP_FILE_EXTENSION {
// for zip action, error out if specified runtime is not supported by
// OpenWhisk server
return actionFilePath, nil, wskderrors.NewInvalidRuntimeError(warnStr,
manifestFileName,
action.Name,
action.Runtime,
runtimes.ListOfSupportedRuntimes(runtimes.SupportedRunTimes))
} else {
if utils.Flags.Strict {
exec.Kind = action.Runtime
} else {
warnStr := wski18n.T(wski18n.ID_WARN_RUNTIME_CHANGED_X_runtime_X_action_X,
map[string]interface{}{
wski18n.KEY_RUNTIME: exec.Kind,
wski18n.KEY_ACTION: action.Name})
wskprint.PrintOpenWhiskWarning(warnStr)
}
}
}
}
// we can specify the name of the action entry point using main
if len(action.Main) != 0 {
exec.Main = action.Main
}
return actionFilePath, exec, nil
}