This is an automated email from the ASF dual-hosted git repository.

mrutkowski 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 e9d3d02  Remove unnecessary rule changes (#661)
e9d3d02 is described below

commit e9d3d02e8af221cc05464c148a30da2d4a536899
Author: Vincent <[email protected]>
AuthorDate: Thu Nov 30 18:44:16 2017 -0500

    Remove unnecessary rule changes (#661)
    
    A rule is enabled when it is created. There is no need to activate it.
    A rule is able to delete no matter it is active or inactive. This PR
    removes the unnecessary rule changes when creating and deleting a rule.
    
    In addition, the order to undeploy assets needs to be changed to avoid
    concurrency issue as well. All the entity creation and deletion need to
    be retried if conflict is returned.
---
 deployers/servicedeployer.go | 214 ++++++++++++++++++++++++++++++++-----------
 1 file changed, 159 insertions(+), 55 deletions(-)

diff --git a/deployers/servicedeployer.go b/deployers/servicedeployer.go
index 7bcb74d..cc9c619 100644
--- a/deployers/servicedeployer.go
+++ b/deployers/servicedeployer.go
@@ -31,6 +31,14 @@ import (
        "github.com/apache/incubator-openwhisk-wskdeploy/utils"
        "github.com/apache/incubator-openwhisk-wskdeploy/wski18n"
        "reflect"
+    "time"
+)
+
+const (
+    CONFLICT_CODE = 153
+    CONFLICT_MESSAGE = "Concurrent modification to resource detected"
+    DEFAULT_ATTEMPTS = 3
+    DEFAULT_INTERVAL = 1 * time.Second
 )
 
 type DeploymentProject struct {
@@ -506,7 +514,12 @@ func (deployer *ServiceDeployer) 
RefreshManagedActions(packageName string, ma ma
                                        " from the current project {{.project}} 
in manifest file which is being undeployed.\n",
                                        map[string]interface{}{"action": 
actionName, "project": aa[utils.OW_PROJECT_NAME]})
                                whisk.Debug(whisk.DbgInfo, output)
-                               _, err := 
deployer.Client.Actions.Delete(actionName)
+                var err error
+                err = retry(DEFAULT_ATTEMPTS, DEFAULT_INTERVAL, func() error {
+                    _, err := deployer.Client.Actions.Delete(actionName)
+                    return err
+                })
+
                                if err != nil {
                                        return err
                                }
@@ -538,7 +551,12 @@ func (deployer *ServiceDeployer) RefreshManagedTriggers(ma 
map[string]interface{
                                        " from the current project {{.project}} 
in manifest file which is being undeployed.\n",
                                        map[string]interface{}{"trigger": 
trigger.Name, "project": ma[utils.OW_PROJECT_NAME]})
                                whisk.Debug(whisk.DbgInfo, output)
-                               _, _, err := 
deployer.Client.Triggers.Delete(trigger.Name)
+                var err error
+                err = retry(DEFAULT_ATTEMPTS, DEFAULT_INTERVAL, func() error {
+                    _, _, err := deployer.Client.Triggers.Delete(trigger.Name)
+                    return err
+                })
+
                                if err != nil {
                                        return err
                                }
@@ -579,7 +597,12 @@ func (deployer *ServiceDeployer) RefreshManagedPackages(ma 
map[string]interface{
                                        " from the current project {{.project}} 
in manifest file which is being undeployed.\n",
                                        map[string]interface{}{"package": 
pkg.Name, "project": pa[utils.OW_PROJECT_NAME]})
                                whisk.Debug(whisk.DbgInfo, output)
-                               _, err := 
deployer.Client.Packages.Delete(pkg.Name)
+                var err error
+                err = retry(DEFAULT_ATTEMPTS, DEFAULT_INTERVAL, func() error {
+                    _, err := deployer.Client.Packages.Delete(pkg.Name)
+                    return err
+                })
+
                                if err != nil {
                                        return err
                                }
@@ -674,7 +697,12 @@ func (deployer *ServiceDeployer) createBinding(packa 
*whisk.BindingPackage) erro
        output := wski18n.T("Deploying package binding {{.output}} ...",
                map[string]interface{}{"output": packa.Name})
        whisk.Debug(whisk.DbgInfo, output)
-       _, _, err := deployer.Client.Packages.Insert(packa, true)
+    var err error
+    err = retry(DEFAULT_ATTEMPTS, DEFAULT_INTERVAL, func() error {
+        _, _, err := deployer.Client.Packages.Insert(packa, true)
+        return err
+    })
+
        if err != nil {
                wskErr := err.(*whisk.WskError)
                errString := wski18n.T("Got error creating package binding with 
error message: {{.err}} and error code: {{.code}}.\n",
@@ -693,7 +721,11 @@ func (deployer *ServiceDeployer) createPackage(packa 
*whisk.Package) error {
        output := wski18n.T("Deploying package {{.output}} ...",
                map[string]interface{}{"output": packa.Name})
        whisk.Debug(whisk.DbgInfo, output)
-       _, _, err := deployer.Client.Packages.Insert(packa, true)
+    var err error
+    err = retry(DEFAULT_ATTEMPTS, DEFAULT_INTERVAL, func() error {
+        _, _, err := deployer.Client.Packages.Insert(packa, true)
+        return err
+    })
        if err != nil {
                wskErr := err.(*whisk.WskError)
                errString := wski18n.T("Got error creating package with error 
message: {{.err}} and error code: {{.code}}.\n",
@@ -712,7 +744,11 @@ func (deployer *ServiceDeployer) createTrigger(trigger 
*whisk.Trigger) error {
        output := wski18n.T("Deploying trigger {{.output}} ...",
                map[string]interface{}{"output": trigger.Name})
        whisk.Debug(whisk.DbgInfo, output)
-       _, _, err := deployer.Client.Triggers.Insert(trigger, true)
+    var err error
+    err = retry(DEFAULT_ATTEMPTS, DEFAULT_INTERVAL, func() error {
+        _, _, err := deployer.Client.Triggers.Insert(trigger, true)
+        return err
+    })
        if err != nil {
                wskErr := err.(*whisk.WskError)
                errString := wski18n.T("Got error creating trigger with error 
message: {{.err}} and error code: {{.code}}.\n",
@@ -762,7 +798,11 @@ func (deployer *ServiceDeployer) createFeedAction(trigger 
*whisk.Trigger, feedNa
                deployer.deleteFeedAction(trigger, feedName)
        }
 
-       _, _, err := deployer.Client.Triggers.Insert(t, true)
+    var err error
+    err = retry(DEFAULT_ATTEMPTS, DEFAULT_INTERVAL, func() error {
+        _, _, err := deployer.Client.Triggers.Insert(t, true)
+        return err
+    })
        if err != nil {
                wskErr := err.(*whisk.WskError)
                errString := wski18n.T("Got error creating trigger with error 
message: {{.err}} and error code: {{.code}}.\n",
@@ -778,12 +818,21 @@ func (deployer *ServiceDeployer) createFeedAction(trigger 
*whisk.Trigger, feedNa
 
                namespace := deployer.Client.Namespace
                deployer.Client.Namespace = qName.Namespace
-               _, _, err = deployer.Client.Actions.Invoke(qName.EntityName, 
params, true, false)
+        err = retry(DEFAULT_ATTEMPTS, DEFAULT_INTERVAL, func() error {
+            _, _, err = deployer.Client.Actions.Invoke(qName.EntityName, 
params, true, false)
+            return err
+        })
                deployer.Client.Namespace = namespace
 
                if err != nil {
                        // Remove the created trigger
                        deployer.Client.Triggers.Delete(trigger.Name)
+
+            retry(DEFAULT_ATTEMPTS, DEFAULT_INTERVAL, func() error {
+                _, _, err := deployer.Client.Triggers.Delete(trigger.Name)
+                return err
+            })
+
                        wskErr := err.(*whisk.WskError)
                        errString := wski18n.T("Got error creating trigger feed 
with error message: {{.err}} and error code: {{.code}}.\n",
                                map[string]interface{}{"err": wskErr.Error(), 
"code": strconv.Itoa(wskErr.ExitCode)})
@@ -815,7 +864,12 @@ func (deployer *ServiceDeployer) createRule(rule 
*whisk.Rule) error {
                map[string]interface{}{"output": rule.Name})
        whisk.Debug(whisk.DbgInfo, output)
 
-       _, _, err := deployer.Client.Rules.Insert(rule, true)
+    var err error
+    err = retry(DEFAULT_ATTEMPTS, DEFAULT_INTERVAL, func() error {
+        _, _, err := deployer.Client.Rules.Insert(rule, true)
+        return err
+    })
+
        if err != nil {
                wskErr := err.(*whisk.WskError)
                errString := wski18n.T("Got error creating rule with error 
message: {{.err}} and error code: {{.code}}.\n",
@@ -824,14 +878,6 @@ func (deployer *ServiceDeployer) createRule(rule 
*whisk.Rule) error {
                return utils.NewWhiskClientError(wskErr.Error(), 
wskErr.ExitCode)
        }
 
-       _, _, err = deployer.Client.Rules.SetState(rule.Name, "active")
-       if err != nil {
-               wskErr := err.(*whisk.WskError)
-               errString := wski18n.T("Got error setting the status of rule 
with error message: {{.err}} and error code: {{.code}}.\n",
-                       map[string]interface{}{"err": wskErr.Error(), "code": 
strconv.Itoa(wskErr.ExitCode)})
-               whisk.Debug(whisk.DbgError, errString)
-               return utils.NewWhiskClientError(wskErr.Error(), 
wskErr.ExitCode)
-       }
        output = wski18n.T("Rule {{.output}} has been successfully deployed.\n",
                map[string]interface{}{"output": rule.Name})
        whisk.Debug(whisk.DbgInfo, output)
@@ -849,7 +895,12 @@ func (deployer *ServiceDeployer) createAction(pkgname 
string, action *whisk.Acti
                map[string]interface{}{"output": action.Name})
        whisk.Debug(whisk.DbgInfo, output)
 
-       _, _, err := deployer.Client.Actions.Insert(action, true)
+    var err error
+    err = retry(DEFAULT_ATTEMPTS, DEFAULT_INTERVAL, func() error {
+        _, _, err := deployer.Client.Actions.Insert(action, true)
+        return err
+    })
+
        if err != nil {
                wskErr := err.(*whisk.WskError)
                errString := wski18n.T("Got error creating action with error 
message: {{.err}} and error code: {{.code}}.\n",
@@ -866,7 +917,12 @@ func (deployer *ServiceDeployer) createAction(pkgname 
string, action *whisk.Acti
 
 // create api (API Gateway functionality)
 func (deployer *ServiceDeployer) createApi(api *whisk.ApiCreateRequest) error {
-       _, _, err := deployer.Client.Apis.Insert(api, nil, true)
+    var err error
+    err = retry(DEFAULT_ATTEMPTS, DEFAULT_INTERVAL, func() error {
+        _, _, err := deployer.Client.Apis.Insert(api, nil, true)
+        return err
+    })
+
        if err != nil {
                wskErr := err.(*whisk.WskError)
                errString := wski18n.T("Got error creating api with error 
message: {{.err}} and error code: {{.code}}.\n",
@@ -923,21 +979,21 @@ func (deployer *ServiceDeployer) UnDeploy(verifiedPlan 
*DeploymentProject) error
 
 func (deployer *ServiceDeployer) unDeployAssets(verifiedPlan 
*DeploymentProject) error {
 
-       if err := deployer.UnDeployActions(verifiedPlan); err != nil {
-               return err
-       }
+    if err := deployer.UnDeployRules(verifiedPlan); err != nil {
+        return err
+    }
+
+    if err := deployer.UnDeployTriggers(verifiedPlan); err != nil {
+        return err
+    }
 
        if err := deployer.UnDeploySequences(verifiedPlan); err != nil {
                return err
        }
 
-       if err := deployer.UnDeployTriggers(verifiedPlan); err != nil {
-               return err
-       }
-
-       if err := deployer.UnDeployRules(verifiedPlan); err != nil {
-               return err
-       }
+    if err := deployer.UnDeployActions(verifiedPlan); err != nil {
+        return err
+    }
 
        if err := deployer.UnDeployPackages(verifiedPlan); err != nil {
                return err
@@ -959,7 +1015,11 @@ func (deployer *ServiceDeployer) UnDeployDependencies() 
error {
                        whisk.Debug(whisk.DbgInfo, output)
 
                        if depRecord.IsBinding {
-                               _, err := 
deployer.Client.Packages.Delete(depName)
+                var err error
+                err = retry(DEFAULT_ATTEMPTS, DEFAULT_INTERVAL, func() error {
+                    _, err := deployer.Client.Packages.Delete(depName)
+                    return err
+                })
                                if err != nil {
                                        return err
                                }
@@ -978,7 +1038,11 @@ func (deployer *ServiceDeployer) UnDeployDependencies() 
error {
                                // delete binding pkg if the origin package 
name is different
                                if depServiceDeployer.RootPackageName != 
depName {
                                        if _, _, ok := 
deployer.Client.Packages.Get(depName); ok == nil {
-                                               _, err := 
deployer.Client.Packages.Delete(depName)
+                        var err error
+                        err = retry(DEFAULT_ATTEMPTS, DEFAULT_INTERVAL, func() 
error {
+                            _, err := deployer.Client.Packages.Delete(depName)
+                            return err
+                        })
                                                if err != nil {
                                                        wskErr := 
err.(*whisk.WskError)
                                                        errString := 
wski18n.T("Got error deleting binding package with error message: {{.err}} and 
error code: {{.code}}.\n",
@@ -1080,7 +1144,12 @@ func (deployer *ServiceDeployer) deletePackage(packa 
*whisk.Package) error {
                map[string]interface{}{"package": packa.Name})
        whisk.Debug(whisk.DbgInfo, output)
        if _, _, ok := deployer.Client.Packages.Get(packa.Name); ok == nil {
-               _, err := deployer.Client.Packages.Delete(packa.Name)
+        var err error
+        err = retry(DEFAULT_ATTEMPTS, DEFAULT_INTERVAL, func() error {
+            _, err := deployer.Client.Packages.Delete(packa.Name)
+            return err
+        })
+
                if err != nil {
                        wskErr := err.(*whisk.WskError)
                        errString := wski18n.T("Got error deleting package with 
error message: {{.err}} and error code: {{.code}}.\n",
@@ -1096,7 +1165,13 @@ func (deployer *ServiceDeployer) deleteTrigger(trigger 
*whisk.Trigger) error {
        output := wski18n.T("Removing trigger {{.trigger}} ...",
                map[string]interface{}{"trigger": trigger.Name})
        whisk.Debug(whisk.DbgInfo, output)
-       _, _, err := deployer.Client.Triggers.Delete(trigger.Name)
+
+    var err error
+    err = retry(DEFAULT_ATTEMPTS, DEFAULT_INTERVAL, func() error {
+        _, _, err := deployer.Client.Triggers.Delete(trigger.Name)
+        return err
+    })
+
        if err != nil {
                wskErr := err.(*whisk.WskError)
                errString := wski18n.T("Got error deleting trigger with error 
message: {{.err}} and error code: {{.code}}.\n",
@@ -1130,7 +1205,11 @@ func (deployer *ServiceDeployer) 
deleteFeedAction(trigger *whisk.Trigger, feedNa
 
        namespace := deployer.Client.Namespace
        deployer.Client.Namespace = qName.Namespace
-       _, _, err = deployer.Client.Actions.Invoke(qName.EntityName, 
parameters, true, true)
+    err = retry(DEFAULT_ATTEMPTS, DEFAULT_INTERVAL, func() error {
+        _, _, err := deployer.Client.Actions.Invoke(qName.EntityName, 
parameters, true, true)
+        return err
+    })
+
        deployer.Client.Namespace = namespace
 
        if err != nil {
@@ -1142,8 +1221,12 @@ func (deployer *ServiceDeployer) 
deleteFeedAction(trigger *whisk.Trigger, feedNa
 
        } else {
                trigger.Parameters = nil
+        var err error
+        err = retry(DEFAULT_ATTEMPTS, DEFAULT_INTERVAL, func() error {
+            _, _, err := deployer.Client.Triggers.Delete(trigger.Name)
+            return err
+        })
 
-               _, _, err := deployer.Client.Triggers.Delete(trigger.Name)
                if err != nil {
                        wskErr := err.(*whisk.WskError)
                        errString := wski18n.T("Got error deleting trigger with 
error message: {{.err}} and error code: {{.code}}.\n",
@@ -1160,26 +1243,20 @@ func (deployer *ServiceDeployer) deleteRule(rule 
*whisk.Rule) error {
        output := wski18n.T("Removing rule {{.rule}} ...",
                map[string]interface{}{"rule": rule.Name})
        whisk.Debug(whisk.DbgInfo, output)
-       _, _, err := deployer.Client.Rules.SetState(rule.Name, "inactive")
-
-       if err != nil {
-               wskErr := err.(*whisk.WskError)
-               errString := wski18n.T("Got error setting the status of rule 
with error message: {{.err}} and error code: {{.code}}.\n",
-                       map[string]interface{}{"err": wskErr.Error(), "code": 
strconv.Itoa(wskErr.ExitCode)})
-               whisk.Debug(whisk.DbgError, errString)
-               return utils.NewWhiskClientError(wskErr.Error(), 
wskErr.ExitCode)
-       } else {
 
-               _, err = deployer.Client.Rules.Delete(rule.Name)
-
-               if err != nil {
-                       wskErr := err.(*whisk.WskError)
-                       errString := wski18n.T("Got error deleting rule with 
error message: {{.err}} and error code: {{.code}}.\n",
-                               map[string]interface{}{"err": wskErr.Error(), 
"code": strconv.Itoa(wskErr.ExitCode)})
-                       whisk.Debug(whisk.DbgError, errString)
-                       return utils.NewWhiskClientError(wskErr.Error(), 
wskErr.ExitCode)
-               }
-       }
+    var err error
+    err = retry(DEFAULT_ATTEMPTS, DEFAULT_INTERVAL, func() error {
+        _, err := deployer.Client.Rules.Delete(rule.Name)
+        return err
+    })
+
+    if err != nil {
+        wskErr := err.(*whisk.WskError)
+        errString := wski18n.T("Got error deleting rule with error message: 
{{.err}} and error code: {{.code}}.\n",
+            map[string]interface{}{"err": wskErr.Error(), "code": 
strconv.Itoa(wskErr.ExitCode)})
+        whisk.Debug(whisk.DbgError, errString)
+        return utils.NewWhiskClientError(wskErr.Error(), wskErr.ExitCode)
+    }
        output = wski18n.T("Rule {{.rule}} has been removed.\n",
                map[string]interface{}{"rule": rule.Name})
        whisk.Debug(whisk.DbgInfo, output)
@@ -1199,7 +1276,12 @@ func (deployer *ServiceDeployer) deleteAction(pkgname 
string, action *whisk.Acti
        whisk.Debug(whisk.DbgInfo, output)
 
        if _, _, ok := deployer.Client.Actions.Get(action.Name); ok == nil {
-               _, err := deployer.Client.Actions.Delete(action.Name)
+        var err error
+        err = retry(DEFAULT_ATTEMPTS, DEFAULT_INTERVAL, func() error {
+            _, err := deployer.Client.Actions.Delete(action.Name)
+            return err
+        })
+
                if err != nil {
                        wskErr := err.(*whisk.WskError)
                        errString := wski18n.T("Got error deleting action with 
error message: {{.err}} and error code: {{.code}}.\n",
@@ -1215,6 +1297,28 @@ func (deployer *ServiceDeployer) deleteAction(pkgname 
string, action *whisk.Acti
        return nil
 }
 
+func retry(attempts int, sleep time.Duration, callback func() error) error {
+    var err error
+    for i := 0; ; i++ {
+        err = callback()
+        if i >= (attempts - 1) {
+            break
+        }
+        if err != nil {
+            wskErr := err.(*whisk.WskError)
+            if wskErr.ExitCode == CONFLICT_CODE && 
strings.Contains(wskErr.Error(), CONFLICT_MESSAGE) {
+                time.Sleep(sleep)
+                whisk.Debug(whisk.DbgError, "Retrying [%s] after error: %s\n", 
strconv.Itoa(i + 1), err)
+            } else {
+                return err
+            }
+        } else {
+            return err
+        }
+    }
+    return err
+}
+
 // from whisk go client
 func (deployer *ServiceDeployer) getQualifiedName(name string, namespace 
string) string {
        if strings.HasPrefix(name, "/") {

-- 
To stop receiving notification emails like this one, please contact
['"[email protected]" <[email protected]>'].

Reply via email to