| /* |
| * 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 deployers |
| |
| import ( |
| "github.com/apache/openwhisk-client-go/whisk" |
| "github.com/apache/openwhisk-wskdeploy/parsers" |
| "github.com/apache/openwhisk-wskdeploy/utils" |
| "github.com/apache/openwhisk-wskdeploy/wskenv" |
| "github.com/apache/openwhisk-wskdeploy/wski18n" |
| "github.com/apache/openwhisk-wskdeploy/wskprint" |
| ) |
| |
| type DeploymentReader struct { |
| serviceDeployer *ServiceDeployer |
| DeploymentDescriptor *parsers.YAML |
| } |
| |
| func NewDeploymentReader(serviceDeployer *ServiceDeployer) *DeploymentReader { |
| var dep DeploymentReader |
| dep.serviceDeployer = serviceDeployer |
| |
| return &dep |
| } |
| |
| // Wrapper parser to handle yaml dir |
| func (reader *DeploymentReader) HandleYaml() error { |
| |
| dep := reader.serviceDeployer |
| |
| deploymentParser := parsers.NewYAMLParser() |
| deployment, err := deploymentParser.ParseDeployment(dep.DeploymentPath) |
| reader.DeploymentDescriptor = deployment |
| |
| return err |
| } |
| |
| // Update entities with deployment settings |
| func (reader *DeploymentReader) BindAssets() error { |
| |
| var paramsCLI interface{} |
| var err error |
| |
| // check if any inputs/parameters are specified in CLI using --param or --param-file |
| // store params in Key/value pairs |
| if len(utils.Flags.Param) > 0 { |
| paramsCLI, err = utils.GetJSONFromStrings(utils.Flags.Param, false) |
| if err != nil { |
| return err |
| } |
| } |
| |
| if err := reader.bindPackageInputsAndAnnotations(paramsCLI); err != nil { |
| return err |
| } |
| if err := reader.bindActionInputsAndAnnotations(paramsCLI); err != nil { |
| return err |
| } |
| if err := reader.bindTriggerInputsAndAnnotations(paramsCLI); err != nil { |
| return err |
| } |
| |
| return nil |
| } |
| |
| func (reader *DeploymentReader) getPackageMap() map[string]parsers.Package { |
| packMap := make(map[string]parsers.Package) |
| |
| // Create local packages list from Deployment file for us to iterate over |
| // either from top-level or under project schema |
| if len(reader.DeploymentDescriptor.GetProject().Packages) == 0 { |
| |
| if len(reader.DeploymentDescriptor.Packages) > 0 { |
| infoMsg := wski18n.T( |
| wski18n.ID_DEBUG_PACKAGES_FOUND_UNDER_ROOT_X_path_X, |
| map[string]interface{}{ |
| wski18n.KEY_PATH: reader.DeploymentDescriptor.Filepath}) |
| wskprint.PrintlnOpenWhiskTrace(utils.Flags.Trace, infoMsg) |
| for packName, depPacks := range reader.DeploymentDescriptor.Packages { |
| depPacks.Packagename = packName |
| packMap[packName] = depPacks |
| } |
| } |
| } else { |
| |
| infoMsg := wski18n.T( |
| wski18n.ID_DEBUG_PACKAGES_FOUND_UNDER_PROJECT_X_path_X_name_X, |
| map[string]interface{}{ |
| wski18n.KEY_PATH: reader.DeploymentDescriptor.Filepath, |
| wski18n.KEY_NAME: reader.DeploymentDescriptor.GetProject().Name}) |
| wskprint.PrintlnOpenWhiskTrace(utils.Flags.Trace, infoMsg) |
| |
| for packName, depPacks := range reader.DeploymentDescriptor.GetProject().Packages { |
| depPacks.Packagename = packName |
| packMap[packName] = depPacks |
| } |
| } |
| |
| return packMap |
| } |
| |
| func (reader *DeploymentReader) getListOfParameters(inputs map[string]parsers.Parameter) whisk.KeyValueArr { |
| keyValArr := make(whisk.KeyValueArr, 0) |
| for name, input := range inputs { |
| var keyVal whisk.KeyValue |
| keyVal.Key = name |
| keyVal.Value = wskenv.InterpolateStringWithEnvVar(input.Value) |
| keyValArr = append(keyValArr, keyVal) |
| } |
| return keyValArr |
| } |
| |
| func (reader *DeploymentReader) getListOfAnnotations(inputs map[string]interface{}) whisk.KeyValueArr { |
| keyValArr := make(whisk.KeyValueArr, 0) |
| for name, input := range inputs { |
| var keyVal whisk.KeyValue |
| keyVal.Key = name |
| keyVal.Value = wskenv.InterpolateStringWithEnvVar(input) |
| keyValArr = append(keyValArr, keyVal) |
| } |
| return keyValArr |
| } |
| |
| func (reader *DeploymentReader) bindPackageInputsAndAnnotations(paramsCLI interface{}) error { |
| |
| // retrieve "packages" list from depl. file; either at top-level or under "Project" schema |
| packMap := reader.getPackageMap() |
| |
| for packName, pack := range packMap { |
| |
| serviceDeployPack := reader.serviceDeployer.Deployment.Packages[packName] |
| |
| if serviceDeployPack == nil { |
| displayEntityNotFoundInDeploymentWarning(parsers.YAML_KEY_PACKAGE, packName) |
| break |
| } |
| |
| displayEntityFoundInDeploymentTrace(parsers.YAML_KEY_PACKAGE, packName) |
| |
| if len(pack.Inputs) > 0 { |
| |
| keyValArr := reader.getListOfParameters(pack.Inputs) |
| |
| depParams := make(map[string]whisk.KeyValue) |
| for _, kv := range keyValArr { |
| depParams[kv.Key] = kv |
| } |
| |
| for _, keyVal := range serviceDeployPack.Package.Parameters { |
| if _, exists := depParams[keyVal.Key]; !exists { |
| keyValArr = append(keyValArr, keyVal) |
| } |
| } |
| |
| packageInputs := make(whisk.KeyValueArr, 0) |
| |
| if paramsCLI != nil { |
| for _, kv := range keyValArr { |
| // check if this particular input is specified on CLI |
| if v, ok := paramsCLI.(map[string]interface{})[kv.Key]; ok { |
| kv.Value = wskenv.ConvertSingleName(v.(string)) |
| } |
| packageInputs = append(packageInputs, kv) |
| } |
| } else { |
| packageInputs = keyValArr |
| } |
| |
| serviceDeployPack.Package.Parameters = packageInputs |
| } |
| |
| if len(pack.Annotations) > 0 { |
| |
| keyValArr := reader.getListOfAnnotations(pack.Annotations) |
| |
| // iterate over each annotation from deployment file |
| for _, keyVal := range serviceDeployPack.Package.Annotations { |
| if _, exists := pack.Annotations[keyVal.Key]; !exists { |
| keyValArr = append(keyValArr, keyVal) |
| } |
| } |
| |
| serviceDeployPack.Package.Annotations = keyValArr |
| } |
| } |
| return nil |
| } |
| |
| func (reader *DeploymentReader) bindActionInputsAndAnnotations(paramsCLI interface{}) error { |
| |
| // retrieve "packages" list from depl. file; either at top-level or under "Project" schema |
| packMap := reader.getPackageMap() |
| |
| for packName, pack := range packMap { |
| |
| serviceDeployPack := reader.serviceDeployer.Deployment.Packages[packName] |
| |
| if serviceDeployPack == nil { |
| displayEntityNotFoundInDeploymentWarning(parsers.YAML_KEY_PACKAGE, packName) |
| break |
| } |
| |
| for actionName, action := range pack.Actions { |
| |
| keyValArr := make(whisk.KeyValueArr, 0) |
| |
| if len(action.Inputs) > 0 { |
| keyValArr = reader.getListOfParameters(action.Inputs) |
| |
| if wskAction, exists := serviceDeployPack.Actions[actionName]; exists { |
| |
| displayEntityFoundInDeploymentTrace(parsers.YAML_KEY_ACTION, actionName) |
| |
| depParams := make(map[string]whisk.KeyValue) |
| for _, kv := range keyValArr { |
| depParams[kv.Key] = kv |
| } |
| |
| for _, keyVal := range wskAction.Action.Parameters { |
| if _, exists := depParams[keyVal.Key]; !exists { |
| keyValArr = append(keyValArr, keyVal) |
| } |
| } |
| |
| actionInputs := make(whisk.KeyValueArr, 0) |
| |
| if paramsCLI != nil { |
| for _, kv := range keyValArr { |
| // check if this particular input is specified on CLI |
| if v, ok := paramsCLI.(map[string]interface{})[kv.Key]; ok { |
| kv.Value = wskenv.ConvertSingleName(v.(string)) |
| } |
| actionInputs = append(actionInputs, kv) |
| } |
| } else { |
| actionInputs = keyValArr |
| } |
| |
| wskAction.Action.Parameters = actionInputs |
| } else { |
| displayEntityNotFoundInDeploymentWarning(parsers.YAML_KEY_ACTION, actionName) |
| } |
| } |
| |
| if len(action.Annotations) > 0 { |
| |
| keyValArr = reader.getListOfAnnotations(action.Annotations) |
| |
| if wskAction, exists := serviceDeployPack.Actions[actionName]; exists { |
| |
| displayEntityFoundInDeploymentTrace(parsers.YAML_KEY_ACTION, actionName) |
| |
| for _, keyVal := range wskAction.Action.Annotations { |
| if _, exists := action.Annotations[keyVal.Key]; !exists { |
| keyValArr = append(keyValArr, keyVal) |
| } |
| } |
| wskAction.Action.Annotations = keyValArr |
| } else { |
| displayEntityNotFoundInDeploymentWarning(parsers.YAML_KEY_ACTION, actionName) |
| } |
| } |
| } |
| } |
| return nil |
| } |
| |
| func (reader *DeploymentReader) bindTriggerInputsAndAnnotations(paramsCLI interface{}) error { |
| |
| // retrieve "packages" list from depl. file; either at top-level or under "Project" schema |
| packMap := reader.getPackageMap() |
| |
| // go through all packages in our local package map |
| for _, pack := range packMap { |
| serviceDeployment := reader.serviceDeployer.Deployment |
| |
| // for each Deployment file Trigger found in the current package |
| for triggerName, trigger := range pack.Triggers { |
| |
| // If the Deployment file trigger has Input values we will attempt to bind them |
| if len(trigger.Inputs) > 0 { |
| keyValArr := reader.getListOfParameters(trigger.Inputs) |
| |
| // See if a matching Trigger (name) exists in manifest |
| if wskTrigger, exists := serviceDeployment.Triggers[triggerName]; exists { |
| |
| displayEntityFoundInDeploymentTrace(parsers.YAML_KEY_TRIGGER, triggerName) |
| |
| depParams := make(map[string]whisk.KeyValue) |
| for _, kv := range keyValArr { |
| depParams[kv.Key] = kv |
| } |
| |
| for _, keyVal := range wskTrigger.Parameters { |
| // TODO() verify logic and add Verbose/trace say "found" or "not found" |
| if _, exists := depParams[keyVal.Key]; !exists { |
| displayEntityFoundInDeploymentTrace( |
| parsers.YAML_KEY_ANNOTATION, keyVal.Key) |
| keyValArr = append(keyValArr, keyVal) |
| } |
| } |
| |
| triggerInputs := make(whisk.KeyValueArr, 0) |
| |
| if paramsCLI != nil { |
| for _, kv := range keyValArr { |
| // check if this particular input is specified on CLI |
| if v, ok := paramsCLI.(map[string]interface{})[kv.Key]; ok { |
| kv.Value = wskenv.ConvertSingleName(v.(string)) |
| } |
| triggerInputs = append(triggerInputs, kv) |
| } |
| } else { |
| triggerInputs = keyValArr |
| } |
| |
| wskTrigger.Parameters = triggerInputs |
| } else { |
| displayEntityNotFoundInDeploymentWarning(parsers.YAML_KEY_TRIGGER, triggerName) |
| } |
| } |
| |
| if len(trigger.Annotations) > 0 { |
| |
| keyValArr := reader.getListOfAnnotations(trigger.Annotations) |
| |
| if wskTrigger, exists := serviceDeployment.Triggers[triggerName]; exists { |
| |
| displayEntityFoundInDeploymentTrace(parsers.YAML_KEY_TRIGGER, triggerName) |
| |
| for _, keyVal := range wskTrigger.Annotations { |
| if _, exists := trigger.Annotations[keyVal.Key]; !exists { |
| keyValArr = append(keyValArr, keyVal) |
| } |
| } |
| wskTrigger.Annotations = keyValArr |
| } else { |
| displayEntityNotFoundInDeploymentWarning(parsers.YAML_KEY_TRIGGER, triggerName) |
| } |
| } |
| |
| } |
| |
| } |
| return nil |
| } |
| |
| func displayEntityNotFoundInDeploymentWarning(entityType string, entityName string) { |
| warnMsg := wski18n.T( |
| wski18n.ID_WARN_DEPLOYMENT_NAME_NOT_FOUND_X_key_X_name_X, |
| map[string]interface{}{ |
| wski18n.KEY_KEY: entityType, |
| wski18n.KEY_NAME: entityName}) |
| wskprint.PrintOpenWhiskWarning(warnMsg) |
| } |
| |
| func displayEntityFoundInDeploymentTrace(entityType string, entityName string) { |
| infoMsg := wski18n.T( |
| wski18n.ID_DEBUG_DEPLOYMENT_NAME_FOUND_X_key_X_name_X, |
| map[string]interface{}{ |
| wski18n.KEY_KEY: entityType, |
| wski18n.KEY_NAME: entityName}) |
| wskprint.PrintlnOpenWhiskTrace(utils.Flags.Trace, infoMsg) |
| } |