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 32a02ed  Multiple Project Management, adding sync command, and 
undeploy just using Project Name   (#816)
32a02ed is described below

commit 32a02ed0318dcefe33e866186e81f66e347124a1
Author: Priti Desai <pde...@us.ibm.com>
AuthorDate: Tue Mar 27 13:34:33 2018 -0700

    Multiple Project Management, adding sync command, and undeploy just using 
Project Name   (#816)
    
    * Adding first set of changes to add deps annotations
    
    * fixing unit test
    
    * adding integration test
    
    * updating go client version
    
    * adding check ond dependencies under whisk.system
    
    * fixing integration test
    
    * introducing sync command
    
    * creating subroutine for common piece of code
    
    * adding preview support for sync
    
    * Adding more integration test
    
    * adding support for undeploy with projectname (wip)
    
    * adding preview on undeploy with project name (wip)
    
    * adding preview on triggers
    
    * disabling one integration test case
    
    * preview actions and packages with undeploy
    
    * Sync undeploy with preview
    
    * undeploy dependencies
    
    * undeploy dependencies if not used by any other project
    
    * adding preview undeploy deps
    
    * adding sync description in wski18
    
    * fixing preview for rules
    
    * adding more comments in project reader
    
    * updating alternate command, renaming ma, replacing hardcoded strings
---
 Godeps/Godeps.json                                 |   4 +-
 cmd/root.go                                        |  29 +-
 cmd/sync.go                                        |  42 +++
 deployers/manifestreader.go                        |  16 +-
 deployers/projectreader.go                         | 360 +++++++++++++++++++++
 deployers/servicedeployer.go                       | 147 +++++++--
 parsers/manifest_parser.go                         |  20 +-
 parsers/manifest_parser_test.go                    |   2 +-
 tests/src/integration/common/wskdeploy.go          |   8 +-
 .../06-manifest-with-dependency.yaml               |  40 +++
 .../07-manifest-with-single-dependency.yaml        |  29 ++
 ...manifest-with-dependencies-on-whisk-system.yaml |  29 ++
 .../managed-deployment/managed-deployment_test.go  |  48 ++-
 utils/flags.go                                     |   1 +
 utils/managedannotations.go                        |  48 ++-
 wski18n/i18n_ids.go                                |   6 +
 wski18n/i18n_resources.go                          |  38 +--
 wski18n/resources/en_US.all.json                   |   8 +
 18 files changed, 782 insertions(+), 93 deletions(-)

diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json
index a7ba4c5..80631ab 100644
--- a/Godeps/Godeps.json
+++ b/Godeps/Godeps.json
@@ -105,11 +105,11 @@
                },
                {
                        "ImportPath": 
"github.com/apache/incubator-openwhisk-client-go/whisk",
-                       "Rev": "717bc3a1638460e069e411e9a8bf0ea5c97f1efa"
+                       "Rev": "1759868a61729708a8ab1a6de1b409d6e2aea00a"
                },
                {
                        "ImportPath": 
"github.com/apache/incubator-openwhisk-client-go/wski18n",
-                       "Rev": "717bc3a1638460e069e411e9a8bf0ea5c97f1efa"
+                       "Rev": "1759868a61729708a8ab1a6de1b409d6e2aea00a"
                },
                {
                        "ImportPath": "github.com/pelletier/go-buffruneio",
diff --git a/cmd/root.go b/cmd/root.go
index 0f93674..77b2e03 100644
--- a/cmd/root.go
+++ b/cmd/root.go
@@ -239,6 +239,34 @@ func Undeploy() error {
        whisk.SetVerbose(utils.Flags.Verbose)
        whisk.SetDebug(utils.Flags.Trace)
 
+       if len(utils.Flags.ProjectName) != 0 {
+               var deployer = deployers.NewServiceDeployer()
+               deployer.Preview = utils.Flags.Preview
+
+               clientConfig, error := 
deployers.NewWhiskConfig(utils.Flags.CfgFile, "", "")
+               if error != nil {
+                       return error
+               }
+
+               whiskClient, error := deployers.CreateNewClient(clientConfig)
+               if error != nil {
+                       return error
+               }
+
+               deployer.Client = whiskClient
+               deployer.ClientConfig = clientConfig
+
+               // The auth, apihost and namespace have been chosen, so that we 
can check the supported runtimes here.
+               setSupportedRuntimes(clientConfig.Host)
+
+               err := deployer.UnDeployProject()
+               if err != nil {
+                       return err
+               }
+
+               return nil
+       }
+
        project_Path := strings.TrimSpace(utils.Flags.ProjectPath)
        if len(project_Path) == 0 {
                project_Path = utils.DEFAULT_PROJECT_PATH
@@ -294,7 +322,6 @@ func Undeploy() error {
                } else {
                        return nil
                }
-
        } else {
                errString := 
wski18n.T(wski18n.ID_ERR_MANIFEST_FILE_NOT_FOUND_X_path_X,
                        map[string]interface{}{wski18n.KEY_PATH: 
utils.Flags.ManifestPath})
diff --git a/cmd/sync.go b/cmd/sync.go
new file mode 100644
index 0000000..4e1279c
--- /dev/null
+++ b/cmd/sync.go
@@ -0,0 +1,42 @@
+/*
+ * 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 cmd
+
+import (
+       "github.com/apache/incubator-openwhisk-wskdeploy/utils"
+       "github.com/apache/incubator-openwhisk-wskdeploy/wski18n"
+       "github.com/spf13/cobra"
+)
+
+// sync represents the mechanism to sync OpenWhisk projects between client and 
server
+var syncCmd = &cobra.Command{
+       Use:        "sync",
+       SuggestFor: []string{"update"},
+       Short:      wski18n.T(wski18n.ID_CMD_DESC_SHORT_SYNC),
+       Long:       wski18n.T(wski18n.ID_CMD_DESC_LONG_SYNC),
+       RunE:       SyncCmdImp,
+}
+
+func SyncCmdImp(cmd *cobra.Command, args []string) error {
+       utils.Flags.Sync = true
+       return Deploy()
+}
+
+func init() {
+       RootCmd.AddCommand(syncCmd)
+}
diff --git a/deployers/manifestreader.go b/deployers/manifestreader.go
index fa54116..c9f0268 100644
--- a/deployers/manifestreader.go
+++ b/deployers/manifestreader.go
@@ -52,8 +52,8 @@ func (deployer *ManifestReader) ParseManifest() 
(*parsers.YAML, *parsers.YAMLPar
        return manifest, manifestParser, nil
 }
 
-func (reader *ManifestReader) InitPackages(manifestParser *parsers.YAMLParser, 
manifest *parsers.YAML, ma whisk.KeyValue) error {
-       packages, err := manifestParser.ComposeAllPackages(manifest, 
reader.serviceDeployer.ManifestPath, ma)
+func (reader *ManifestReader) InitPackages(manifestParser *parsers.YAMLParser, 
manifest *parsers.YAML, managedAnnotations whisk.KeyValue) error {
+       packages, err := manifestParser.ComposeAllPackages(manifest, 
reader.serviceDeployer.ManifestPath, managedAnnotations)
        if err != nil {
                return err
        }
@@ -63,32 +63,32 @@ func (reader *ManifestReader) InitPackages(manifestParser 
*parsers.YAMLParser, m
 }
 
 // Wrapper parser to handle yaml dir
-func (deployer *ManifestReader) HandleYaml(sdeployer *ServiceDeployer, 
manifestParser *parsers.YAMLParser, manifest *parsers.YAML, ma whisk.KeyValue) 
error {
+func (deployer *ManifestReader) HandleYaml(sdeployer *ServiceDeployer, 
manifestParser *parsers.YAMLParser, manifest *parsers.YAML, managedAnnotations 
whisk.KeyValue) error {
 
        var err error
        var manifestName = manifest.Filepath
 
-       deps, err := 
manifestParser.ComposeDependenciesFromAllPackages(manifest, 
deployer.serviceDeployer.ProjectPath, deployer.serviceDeployer.ManifestPath)
+       deps, err := 
manifestParser.ComposeDependenciesFromAllPackages(manifest, 
deployer.serviceDeployer.ProjectPath, deployer.serviceDeployer.ManifestPath, 
managedAnnotations)
        if err != nil {
                return wskderrors.NewYAMLFileFormatError(manifestName, err)
        }
 
-       actions, err := manifestParser.ComposeActionsFromAllPackages(manifest, 
deployer.serviceDeployer.ManifestPath, ma)
+       actions, err := manifestParser.ComposeActionsFromAllPackages(manifest, 
deployer.serviceDeployer.ManifestPath, managedAnnotations)
        if err != nil {
                return wskderrors.NewYAMLFileFormatError(manifestName, err)
        }
 
-       sequences, err := 
manifestParser.ComposeSequencesFromAllPackages(deployer.serviceDeployer.ClientConfig.Namespace,
 manifest, ma)
+       sequences, err := 
manifestParser.ComposeSequencesFromAllPackages(deployer.serviceDeployer.ClientConfig.Namespace,
 manifest, managedAnnotations)
        if err != nil {
                return wskderrors.NewYAMLFileFormatError(manifestName, err)
        }
 
-       triggers, err := 
manifestParser.ComposeTriggersFromAllPackages(manifest, 
deployer.serviceDeployer.ManifestPath, ma)
+       triggers, err := 
manifestParser.ComposeTriggersFromAllPackages(manifest, 
deployer.serviceDeployer.ManifestPath, managedAnnotations)
        if err != nil {
                return wskderrors.NewYAMLFileFormatError(manifestName, err)
        }
 
-       rules, err := manifestParser.ComposeRulesFromAllPackages(manifest, ma)
+       rules, err := manifestParser.ComposeRulesFromAllPackages(manifest, 
managedAnnotations)
        if err != nil {
                return wskderrors.NewYAMLFileFormatError(manifestName, err)
        }
diff --git a/deployers/projectreader.go b/deployers/projectreader.go
new file mode 100644
index 0000000..84ee979
--- /dev/null
+++ b/deployers/projectreader.go
@@ -0,0 +1,360 @@
+/*
+ * 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 (
+       "net/http"
+       "strings"
+
+       "github.com/apache/incubator-openwhisk-client-go/whisk"
+       "github.com/apache/incubator-openwhisk-wskdeploy/parsers"
+       "github.com/apache/incubator-openwhisk-wskdeploy/utils"
+       "github.com/apache/incubator-openwhisk-wskdeploy/wski18n"
+)
+
+func (deployer *ServiceDeployer) UnDeployProjectAssets() error {
+
+       // calculate all the project entities such as packages, actions, 
sequences,
+       // triggers, and rules based on the project name in "whisk-managed" 
annotation
+       deployer.SetProjectAssets(utils.Flags.ProjectName)
+       // calculate all the dependencies based on the project name
+       projectDeps, err := 
deployer.SetProjectDependencies(utils.Flags.ProjectName)
+       if err != nil {
+               return err
+       }
+
+       // show preview of which all OpenWhisk entities will be deployed
+       if utils.Flags.Preview {
+               deployer.printDeploymentAssets(deployer.Deployment)
+               for _, deps := range projectDeps {
+                       deployer.printDeploymentAssets(deps)
+               }
+               return nil
+       }
+
+       // now, undeploy all those project dependencies if not used by
+       // any other project or packages
+       for _, deps := range projectDeps {
+               if err := deployer.unDeployAssets(deps); err != nil {
+                       return err
+               }
+       }
+
+       // undeploy all the project entities
+       return deployer.unDeployAssets(deployer.Deployment)
+
+       return nil
+}
+
+// based on the project name set in "whisk-managed" annotation
+// calculate and determine list of packages, actions, sequences, rules and 
triggers
+func (deployer *ServiceDeployer) SetProjectAssets(projectName string) error {
+
+       if err := deployer.SetProjectPackages(projectName); err != nil {
+               return err
+       }
+
+       if err := deployer.SetPackageActionsAndSequences(projectName); err != 
nil {
+               return err
+       }
+
+       if err := deployer.SetProjectTriggers(projectName); err != nil {
+               return err
+       }
+
+       if err := deployer.SetProjectRules(projectName); err != nil {
+               return err
+       }
+
+       if err := deployer.SetProjectApis(projectName); err != nil {
+               return err
+       }
+
+       return nil
+}
+
+// check if project name matches with the one in "whisk-managed" annotation
+func (deployer *ServiceDeployer) isManagedEntity(a interface{}, projectName 
string) bool {
+       if a != nil {
+               ta := a.(map[string]interface{})
+               if ta[utils.OW_PROJECT_NAME] == projectName {
+                       return true
+               }
+       }
+       return false
+}
+
+// get an instance of *whisk.Package for the specified package name
+func (deployer *ServiceDeployer) getPackage(packageName string) 
(*DeploymentPackage, error) {
+       var err error
+       var p *whisk.Package
+       var response *http.Response
+       err = retry(DEFAULT_ATTEMPTS, DEFAULT_INTERVAL, func() error {
+               p, response, err = deployer.Client.Packages.Get(packageName)
+               return err
+       })
+       if err != nil {
+               return nil, createWhiskClientError(err.(*whisk.WskError), 
response, parsers.YAML_KEY_PACKAGE, false)
+       }
+       newPack := NewDeploymentPackage()
+       newPack.Package = p
+       return newPack, nil
+
+}
+
+// capture all the packages with "whisk-managed" annotations and matching 
project name
+func (deployer *ServiceDeployer) SetProjectPackages(projectName string) error {
+       // retrieve a list of all the packages available under the namespace
+       listOfPackages, _, err := 
deployer.Client.Packages.List(&whisk.PackageListOptions{})
+       if err != nil {
+               return nil
+       }
+       for _, pkg := range listOfPackages {
+               if 
deployer.isManagedEntity(pkg.Annotations.GetValue(utils.MANAGED), projectName) {
+                       p, err := deployer.getPackage(pkg.Name)
+                       if err != nil {
+                               return err
+                       }
+                       deployer.Deployment.Packages[pkg.Name] = p
+               }
+       }
+
+       return nil
+}
+
+// get a list of actions/sequences of a given package name
+func (deployer *ServiceDeployer) getPackageActionsAndSequences(packageName 
string, projectName string) (map[string]utils.ActionRecord, 
map[string]utils.ActionRecord, error) {
+       listOfActions := make(map[string]utils.ActionRecord, 0)
+       listOfSequences := make(map[string]utils.ActionRecord, 0)
+
+       actions, _, err := deployer.Client.Actions.List(packageName, 
&whisk.ActionListOptions{})
+       if err != nil {
+               return listOfActions, listOfSequences, err
+       }
+       for _, action := range actions {
+               if 
deployer.isManagedEntity(action.Annotations.GetValue(utils.MANAGED), 
projectName) {
+                       var a *whisk.Action
+                       var response *http.Response
+                       err = retry(DEFAULT_ATTEMPTS, DEFAULT_INTERVAL, func() 
error {
+                               a, response, err = 
deployer.Client.Actions.Get(packageName+parsers.PATH_SEPARATOR+action.Name, 
false)
+                               return err
+                       })
+                       if err != nil {
+                               return listOfActions, listOfSequences, 
createWhiskClientError(err.(*whisk.WskError), response, 
parsers.YAML_KEY_ACTION, false)
+                       }
+                       ar := utils.ActionRecord{Action: a, Packagename: 
packageName}
+                       if a.Exec.Kind == parsers.YAML_KEY_SEQUENCE {
+                               listOfSequences[action.Name] = ar
+                       } else {
+                               listOfActions[action.Name] = ar
+                       }
+               }
+       }
+       return listOfActions, listOfSequences, err
+}
+
+// capture all the actions/sequences with "whisk-managed" annotations and 
matching project name
+func (deployer *ServiceDeployer) SetPackageActionsAndSequences(projectName 
string) error {
+       for _, pkg := range deployer.Deployment.Packages {
+               a, s, err := 
deployer.getPackageActionsAndSequences(pkg.Package.Name, projectName)
+               if err != nil {
+                       return err
+               }
+               deployer.Deployment.Packages[pkg.Package.Name].Actions = a
+               deployer.Deployment.Packages[pkg.Package.Name].Sequences = s
+       }
+       return nil
+}
+
+// get a list of triggers from a given project name
+func (deployer *ServiceDeployer) getProjectTriggers(projectName string) 
(map[string]*whisk.Trigger, error) {
+       triggers := make(map[string]*whisk.Trigger, 0)
+       listOfTriggers, _, err := 
deployer.Client.Triggers.List(&whisk.TriggerListOptions{})
+       if err != nil {
+               return triggers, nil
+       }
+       for _, trigger := range listOfTriggers {
+               if 
deployer.isManagedEntity(trigger.Annotations.GetValue(utils.MANAGED), 
projectName) {
+                       var t *whisk.Trigger
+                       var response *http.Response
+                       err = retry(DEFAULT_ATTEMPTS, DEFAULT_INTERVAL, func() 
error {
+                               t, response, err = 
deployer.Client.Triggers.Get(trigger.Name)
+                               return err
+                       })
+                       if err != nil {
+                               return triggers, 
createWhiskClientError(err.(*whisk.WskError), response, 
parsers.YAML_KEY_TRIGGER, false)
+                       }
+                       triggers[trigger.Name] = t
+               }
+       }
+       return triggers, nil
+}
+
+// capture all the triggers with "whisk-managed" annotations and matching 
project name
+func (deployer *ServiceDeployer) SetProjectTriggers(projectName string) error {
+       t, err := deployer.getProjectTriggers(projectName)
+       if err != nil {
+               return err
+       }
+       deployer.Deployment.Triggers = t
+       return nil
+}
+
+// get a list of rules from a given project name
+func (deployer *ServiceDeployer) getProjectRules(projectName string) 
(map[string]*whisk.Rule, error) {
+       rules := make(map[string]*whisk.Rule, 0)
+       listOfRules, _, err := 
deployer.Client.Rules.List(&whisk.RuleListOptions{})
+       if err != nil {
+               return rules, nil
+       }
+       for _, rule := range listOfRules {
+               if 
deployer.isManagedEntity(rule.Annotations.GetValue(utils.MANAGED), projectName) 
{
+                       var r *whisk.Rule
+                       var response *http.Response
+                       err = retry(DEFAULT_ATTEMPTS, DEFAULT_INTERVAL, func() 
error {
+                               r, response, err = 
deployer.Client.Rules.Get(rule.Name)
+                               return err
+                       })
+                       if err != nil {
+                               return rules, 
createWhiskClientError(err.(*whisk.WskError), response, parsers.YAML_KEY_RULE, 
false)
+                       }
+                       rules[rule.Name] = r
+               }
+       }
+       return rules, nil
+}
+
+// capture all the rules with "whisk-managed" annotations and matching project 
name
+func (deployer *ServiceDeployer) SetProjectRules(projectName string) error {
+       r, err := deployer.getProjectRules(projectName)
+       if err != nil {
+               return err
+       }
+       deployer.Deployment.Rules = r
+       return nil
+}
+
+// "whisk-manged" annotation stores package name with namespace such as
+// /<namespace>/<package name>
+// parse this kind of structure to determine package name
+func (deployer *ServiceDeployer) filterPackageName(name string) string {
+       s := strings.SplitAfterN(name, "/", 3)
+       if len(s) == 3 && len(s[2]) != 0 {
+               return s[2]
+       }
+       return ""
+}
+
+// determine if any other package on the server is using the dependent package
+func (deployer *ServiceDeployer) isPackageUsedByOtherPackages(projectName 
string, depPackageName string) bool {
+       // retrieve a list of packages on the server
+       listOfPackages, _, err := 
deployer.Client.Packages.List(&whisk.PackageListOptions{})
+       if err != nil {
+               return false
+       }
+       for _, pkg := range listOfPackages {
+               if a := pkg.Annotations.GetValue(utils.MANAGED); a != nil {
+                       ta := a.(map[string]interface{})
+                       // compare project names of the given package and other 
packages from server
+                       // we want to skip comparing packages from the same 
project
+                       if ta[utils.OW_PROJECT_NAME] != projectName {
+                               d := 
a.(map[string]interface{})[utils.OW_PROJECT_DEPS]
+                               listOfDeps := d.([]interface{})
+                               // iterate over a list of dependencies of a 
package
+                               // to determine whether it has listed the 
dependent package as its dependency as well
+                               // in such case, we dont want to undeploy 
dependent package if its used by any other package
+                               for _, dep := range listOfDeps {
+                                       name := 
deployer.filterPackageName(dep.(map[string]interface{})[wski18n.KEY_KEY].(string))
+                                       if name == depPackageName {
+                                               return true
+                                       }
+
+                               }
+
+                       }
+
+               }
+       }
+       return false
+}
+
+// derive a map of dependent packages using "whisk-managed" annotation
+// "whisk-managed" annotation has a list of dependent packages in "projectDeps"
+// projectDeps is a list of key value pairs with its own "whisk-managed" 
annotation
+// for a given package, get the list of dependent packages
+// for each dependent package, determine whether any other package is using it 
or not
+// if not, collect a list of actions, sequences, triggers, and rules of the 
dependent package
+// and delete them in order following by deleting the package itself
+func (deployer *ServiceDeployer) SetProjectDependencies(projectName string) 
([]*DeploymentProject, error) {
+       projectDependencies := make([]*DeploymentProject, 0)
+       // iterate over each package in a given project
+       for _, pkg := range deployer.Deployment.Packages {
+               // get the "whisk-managed" annotation
+               if a := pkg.Package.Annotations.GetValue(utils.MANAGED); a != 
nil {
+                       // read the list of dependencies from "projectDeps"
+                       d := a.(map[string]interface{})[utils.OW_PROJECT_DEPS]
+                       listOfDeps := d.([]interface{})
+                       // iterate over a list of dependencies
+                       for _, dep := range listOfDeps {
+                               // dependent package name is in form of 
"/<namespace>/<package-name>
+                               // filter it to derive the package name
+                               name := 
deployer.filterPackageName(dep.(map[string]interface{})[wski18n.KEY_KEY].(string))
+                               // undeploy dependent package if its not used 
by any other package
+                               if 
!deployer.isPackageUsedByOtherPackages(projectName, name) {
+                                       // get the *whisk.Package object for 
the given dependent package
+                                       p, err := deployer.getPackage(name)
+                                       if err != nil {
+                                               return projectDependencies, err
+                                       }
+                                       // construct a new DeploymentProject 
for each dependency
+                                       depProject := NewDeploymentProject()
+                                       depProject.Packages[p.Package.Name] = p
+                                       // Now, get the project name of 
dependent package so that
+                                       // we can get other entities from that 
project
+                                       pa := 
p.Package.Annotations.GetValue(utils.MANAGED)
+                                       depProjectName := 
(pa.(map[string]interface{})[utils.OW_PROJECT_NAME]).(string)
+                                       // get a list of actions and sequences 
of a dependent package
+                                       actions, sequences, err := 
deployer.getPackageActionsAndSequences(p.Package.Name, depProjectName)
+                                       if err != nil {
+                                               return projectDependencies, err
+                                       }
+                                       
depProject.Packages[p.Package.Name].Actions = actions
+                                       
depProject.Packages[p.Package.Name].Sequences = sequences
+                                       // get a list of triggers of a 
dependent project
+                                       t, err := 
deployer.getProjectTriggers(depProjectName)
+                                       if err != nil {
+                                               return projectDependencies, err
+                                       }
+                                       depProject.Triggers = t
+                                       // get a list of rules of a dependent 
project
+                                       r, err := 
deployer.getProjectRules(depProjectName)
+                                       if err != nil {
+                                               return projectDependencies, err
+                                       }
+                                       depProject.Rules = r
+                                       projectDependencies = 
append(projectDependencies, depProject)
+                               }
+                       }
+               }
+       }
+       return projectDependencies, nil
+}
+
+func (deployer *ServiceDeployer) SetProjectApis(projectName string) error {
+       return nil
+}
diff --git a/deployers/servicedeployer.go b/deployers/servicedeployer.go
index 023e18e..2d417b0 100644
--- a/deployers/servicedeployer.go
+++ b/deployers/servicedeployer.go
@@ -139,7 +139,7 @@ func (deployer *ServiceDeployer) ConstructDeploymentPlan() 
error {
        // Generate Managed Annotations if its marked as a Managed Deployment
        // Managed deployments are the ones when OpenWhisk entities are 
deployed with command line flag --managed.
        // Which results in a hidden annotation in every OpenWhisk entity in 
manifest file.
-       if utils.Flags.Managed {
+       if utils.Flags.Managed || utils.Flags.Sync {
                // OpenWhisk entities are annotated with Project Name and 
therefore
                // Project Name in manifest/deployment file is mandatory for 
managed deployments
                if deployer.ProjectName == "" {
@@ -309,7 +309,7 @@ func (deployer *ServiceDeployer) deployAssets() error {
        // refresh previously deployed project entities, delete the assets 
which is no longer part of the project
        // i.e. in a subsequent managed deployment of the same project minus 
few OpenWhisk entities
        // from the manifest file must result in undeployment of those deleted 
entities
-       if utils.Flags.Managed {
+       if utils.Flags.Managed || utils.Flags.Sync {
                if err := 
deployer.RefreshManagedEntities(deployer.ManagedAnnotation); err != nil {
                        errString := 
wski18n.T(wski18n.ID_MSG_MANAGED_UNDEPLOYMENT_FAILED)
                        whisk.Debug(whisk.DbgError, errString)
@@ -436,6 +436,9 @@ func (deployer *ServiceDeployer) 
RefreshManagedEntities(maValue whisk.KeyValue)
                return err
        }
 
+       if err := deployer.RefreshManagedPackagesWithDependencies(ma); err != 
nil {
+               return err
+       }
        return nil
 
 }
@@ -612,6 +615,74 @@ func (deployer *ServiceDeployer) RefreshManagedPackages(ma 
map[string]interface{
                        }
                }
        }
+
+       return nil
+}
+
+func (deployer *ServiceDeployer) appendDepAnnotation(list whisk.KeyValueArr, 
pkg *whisk.Package) whisk.KeyValueArr {
+       depExists := false
+       if a := pkg.Annotations.GetValue(utils.MANAGED); a != nil {
+               //append annotations from this package to deps
+               pkgName := parsers.PATH_SEPARATOR + pkg.Namespace + 
parsers.PATH_SEPARATOR + pkg.Name
+               for _, dep := range list {
+                       if dep.Key == pkgName {
+                               depExists = true
+                       }
+               }
+               if !depExists {
+                       list = append(list, whisk.KeyValue{Key: pkgName, Value: 
a.(map[string]interface{})})
+               }
+       }
+       return list
+}
+
+func (deployer *ServiceDeployer) RefreshManagedPackagesWithDependencies(ma 
map[string]interface{}) error {
+       // iterate over each package from the given project
+       for _, p := range deployer.Deployment.Packages {
+               dependencyAnnotations := make(whisk.KeyValueArr, 0)
+               // iterate over the list of dependencies of the package
+               // dependencies could be labeled same as dependent package name
+               // for example, "helloworld" where the package it depends on is 
also called "helloworld"
+               // dependencies could be labeled different from the dependent 
package name
+               // for example, "custom-helloworld" where the package it 
depends on it called "helloworld"
+               for n := range p.Dependencies {
+                       // find the package using dependency label
+                       pkg, _, err := deployer.Client.Packages.Get(n)
+                       if err != nil {
+                               return err
+                       }
+                       // if dependency label (custom-helloworld) is different 
from the dependent package name,
+                       // it must have binding set to the original package 
("helloworld")
+                       if len(pkg.Binding.Name) != 0 {
+                               // having dependency on packages under 
/whisk.system is treated in a different way
+                               // in which dependent package under 
/whisk.system are not modified to add managed annotation
+                               // and parent package does not show this 
dependency in its managed annotation
+                               // because whisk.system packages comes 
pre-packaged and deployed with OpenWhisk server and not
+                               // deployed along with application deployments.
+                               // (TODO) here, we are only finding a package 
with its name as Get method
+                               // (TODO) does not support looking under 
different/seperate namespace
+                               // (TODO) we could add support to sync 
dependencies from different namespaces in future
+                               if pkg.Binding.Namespace != utils.WHISK_SYSTEM {
+                                       // get the original package to retrieve 
its managed annotations
+                                       pkg, _, err := 
deployer.Client.Packages.Get(pkg.Binding.Name)
+                                       if err != nil {
+                                               return err
+                                       }
+                                       dependencyAnnotations = 
deployer.appendDepAnnotation(dependencyAnnotations, pkg)
+                               }
+                       } else {
+                               dependencyAnnotations = 
deployer.appendDepAnnotation(dependencyAnnotations, pkg)
+                       }
+               }
+               updatedAnnotation, err := utils.AddDependentAnnotation(ma, 
dependencyAnnotations)
+               if err != nil {
+                       return err
+               }
+               p.Package.Annotations.AddOrReplace(&updatedAnnotation)
+       }
+       if err := deployer.DeployPackages(); err != nil {
+               return err
+       }
        return nil
 }
 
@@ -935,6 +1006,13 @@ func (deployer *ServiceDeployer) UnDeploy(verifiedPlan 
*DeploymentProject) error
        return nil
 }
 
+func (deployer *ServiceDeployer) UnDeployProject() error {
+       if err := deployer.UnDeployProjectAssets(); err != nil {
+               return err
+       }
+       return nil
+}
+
 func (deployer *ServiceDeployer) unDeployAssets(verifiedPlan 
*DeploymentProject) error {
        if err := deployer.UnDeployApis(verifiedPlan); err != nil {
                return err
@@ -1355,10 +1433,10 @@ func (deployer *ServiceDeployer) 
printDeploymentAssets(assets *DeploymentProject
        wskprint.PrintlnOpenWhiskOutput("         ____      ___                 
  _    _ _     _     _\n        /\\   \\    / _ \\ _ __   ___ _ __ | |  | | |__ 
(_)___| | __\n   /\\  /__\\   \\  | | | | '_ \\ / _ \\ '_ \\| |  | | '_ \\| / 
__| |/ /\n  /  \\____ \\  /  | |_| | |_) |  __/ | | | |/\\| | | | | \\__ \\   
<\n  \\   \\  /  \\/    \\___/| .__/ \\___|_| |_|__/\\__|_| |_|_|___/_|\\_\\ \n 
  \\___\\/              |_|\n")
 
        // TODO() review format
-       wskprint.PrintlnOpenWhiskOutput("Packages:")
+       
wskprint.PrintlnOpenWhiskOutput(strings.Title(parsers.YAML_KEY_PACKAGES) + ":")
        for _, pack := range assets.Packages {
-               wskprint.PrintlnOpenWhiskOutput("Name: " + pack.Package.Name)
-               wskprint.PrintlnOpenWhiskOutput("    bindings: ")
+               wskprint.PrintlnOpenWhiskOutput(strings.Title(wski18n.KEY_NAME) 
+ ": " + pack.Package.Name)
+               wskprint.PrintlnOpenWhiskOutput("    " + wski18n.KEY_BINDINGS + 
": ")
                for _, p := range pack.Package.Parameters {
                        jsonValue, err := utils.PrettyJSON(p.Value)
                        if err != nil {
@@ -1368,19 +1446,25 @@ func (deployer *ServiceDeployer) 
printDeploymentAssets(assets *DeploymentProject
                        }
                }
 
+               wskprint.PrintlnOpenWhiskOutput("    " + 
parsers.YAML_KEY_ANNOTATION + ": ")
+               for _, p := range pack.Package.Annotations {
+                       fmt.Printf("        - %s : %v\n", p.Key, p.Value)
+
+               }
+
                for key, dep := range pack.Dependencies {
-                       wskprint.PrintlnOpenWhiskOutput("  * dependency: " + 
key)
-                       wskprint.PrintlnOpenWhiskOutput("    location: " + 
dep.Location)
+                       wskprint.PrintlnOpenWhiskOutput("  * " + 
wski18n.KEY_DEPENDENCY + ": " + key)
+                       wskprint.PrintlnOpenWhiskOutput("    " + 
wski18n.KEY_LOCATION + ": " + dep.Location)
                        if !dep.IsBinding {
-                               wskprint.PrintlnOpenWhiskOutput("    local 
path: " + dep.ProjectPath)
+                               wskprint.PrintlnOpenWhiskOutput("    " + 
wski18n.KEY_PATH + ": " + dep.ProjectPath)
                        }
                }
 
                wskprint.PrintlnOpenWhiskOutput("")
 
                for _, action := range pack.Actions {
-                       wskprint.PrintlnOpenWhiskOutput("  * action: " + 
action.Action.Name)
-                       wskprint.PrintlnOpenWhiskOutput("    bindings: ")
+                       wskprint.PrintlnOpenWhiskOutput("  * " + 
parsers.YAML_KEY_ACTION + ": " + action.Action.Name)
+                       wskprint.PrintlnOpenWhiskOutput("    " + 
wski18n.KEY_BINDINGS + ": ")
                        for _, p := range action.Action.Parameters {
 
                                if reflect.TypeOf(p.Value).Kind() == 
reflect.Map {
@@ -1405,7 +1489,7 @@ func (deployer *ServiceDeployer) 
printDeploymentAssets(assets *DeploymentProject
                                }
 
                        }
-                       wskprint.PrintlnOpenWhiskOutput("    annotations: ")
+                       wskprint.PrintlnOpenWhiskOutput("    " + 
parsers.YAML_KEY_ANNOTATION + ": ")
                        for _, p := range action.Action.Annotations {
                                fmt.Printf("        - %s : %v\n", p.Key, 
p.Value)
 
@@ -1414,16 +1498,21 @@ func (deployer *ServiceDeployer) 
printDeploymentAssets(assets *DeploymentProject
 
                wskprint.PrintlnOpenWhiskOutput("")
                for _, action := range pack.Sequences {
-                       wskprint.PrintlnOpenWhiskOutput("  * sequence: " + 
action.Action.Name)
+                       wskprint.PrintlnOpenWhiskOutput("  * " + 
parsers.YAML_KEY_SEQUENCE + ": " + action.Action.Name)
+                       wskprint.PrintlnOpenWhiskOutput("    " + 
parsers.YAML_KEY_ANNOTATION + ": ")
+                       for _, p := range action.Action.Annotations {
+                               fmt.Printf("        - %s : %v\n", p.Key, 
p.Value)
+
+                       }
                }
 
                wskprint.PrintlnOpenWhiskOutput("")
        }
 
-       wskprint.PrintlnOpenWhiskOutput("Triggers:")
+       wskprint.PrintlnOpenWhiskOutput(wski18n.TRIGGERS + ":")
        for _, trigger := range assets.Triggers {
-               wskprint.PrintlnOpenWhiskOutput("* trigger: " + trigger.Name)
-               wskprint.PrintlnOpenWhiskOutput("    bindings: ")
+               wskprint.PrintlnOpenWhiskOutput("* " + parsers.YAML_KEY_TRIGGER 
+ ": " + trigger.Name)
+               wskprint.PrintlnOpenWhiskOutput("    " + wski18n.KEY_BINDINGS + 
": ")
 
                for _, p := range trigger.Parameters {
                        jsonValue, err := utils.PrettyJSON(p.Value)
@@ -1434,21 +1523,31 @@ func (deployer *ServiceDeployer) 
printDeploymentAssets(assets *DeploymentProject
                        }
                }
 
-               wskprint.PrintlnOpenWhiskOutput("    annotations: ")
+               wskprint.PrintlnOpenWhiskOutput("    " + 
parsers.YAML_KEY_ANNOTATION + ": ")
                for _, p := range trigger.Annotations {
+                       fmt.Printf("        - %s : %v\n", p.Key, p.Value)
 
-                       value := "?"
-                       if str, ok := p.Value.(string); ok {
-                               value = str
-                       }
-                       wskprint.PrintlnOpenWhiskOutput("        - name: " + 
p.Key + " value: " + value)
                }
        }
 
-       wskprint.PrintlnOpenWhiskOutput("\n Rules")
+       wskprint.PrintlnOpenWhiskOutput("\n" + wski18n.RULES)
        for _, rule := range assets.Rules {
-               wskprint.PrintlnOpenWhiskOutput("* rule: " + rule.Name)
-               wskprint.PrintlnOpenWhiskOutput("    - trigger: " + 
rule.Trigger.(string) + "\n    - action: " + rule.Action.(string))
+               wskprint.PrintlnOpenWhiskOutput("* " + parsers.YAML_KEY_RULE + 
": " + rule.Name)
+               wskprint.PrintlnOpenWhiskOutput("    " + 
parsers.YAML_KEY_ANNOTATION + ": ")
+               for _, p := range rule.Annotations {
+                       fmt.Printf("        - %s : %v\n", p.Key, p.Value)
+
+               }
+               if reflect.TypeOf(rule.Trigger).Kind() == reflect.String {
+                       wskprint.PrintlnOpenWhiskOutput("    - " + 
parsers.YAML_KEY_TRIGGER + ": " + rule.Trigger.(string) + "\n    - " + 
parsers.YAML_KEY_ACTION + ": " + rule.Action.(string))
+               } else if reflect.TypeOf(rule.Trigger).Kind() == reflect.Map {
+                       trigger := rule.Trigger.(map[string]interface{})
+                       triggerName := trigger["path"].(string) + 
parsers.PATH_SEPARATOR + trigger["name"].(string)
+                       action := rule.Action.(map[string]interface{})
+                       actionName := action["path"].(string) + 
parsers.PATH_SEPARATOR + action["name"].(string)
+                       wskprint.PrintlnOpenWhiskOutput("    - " + 
parsers.YAML_KEY_TRIGGER + ": " + triggerName + "\n    - " + 
parsers.YAML_KEY_ACTION + ": " + actionName)
+               }
+
        }
 
        wskprint.PrintlnOpenWhiskOutput("")
diff --git a/parsers/manifest_parser.go b/parsers/manifest_parser.go
index 763dcbc..88f8d9f 100644
--- a/parsers/manifest_parser.go
+++ b/parsers/manifest_parser.go
@@ -141,7 +141,7 @@ func (dm *YAMLParser) composeAnnotations(annotations 
map[string]interface{}) whi
        return listOfAnnotations
 }
 
-func (dm *YAMLParser) ComposeDependenciesFromAllPackages(manifest *YAML, 
projectPath string, filePath string) (map[string]utils.DependencyRecord, error) 
{
+func (dm *YAMLParser) ComposeDependenciesFromAllPackages(manifest *YAML, 
projectPath string, filePath string, ma whisk.KeyValue) 
(map[string]utils.DependencyRecord, error) {
        dependencies := make(map[string]utils.DependencyRecord)
        packages := make(map[string]Package)
 
@@ -152,7 +152,7 @@ func (dm *YAMLParser) 
ComposeDependenciesFromAllPackages(manifest *YAML, project
        }
 
        for n, p := range packages {
-               d, err := dm.ComposeDependencies(p, projectPath, filePath, n)
+               d, err := dm.ComposeDependencies(p, projectPath, filePath, n, 
ma)
                if err == nil {
                        for k, v := range d {
                                dependencies[k] = v
@@ -164,7 +164,7 @@ func (dm *YAMLParser) 
ComposeDependenciesFromAllPackages(manifest *YAML, project
        return dependencies, nil
 }
 
-func (dm *YAMLParser) ComposeDependencies(pkg Package, projectPath string, 
filePath string, packageName string) (map[string]utils.DependencyRecord, error) 
{
+func (dm *YAMLParser) ComposeDependencies(pkg Package, projectPath string, 
filePath string, packageName string, ma whisk.KeyValue) 
(map[string]utils.DependencyRecord, error) {
 
        depMap := make(map[string]utils.DependencyRecord)
        for key, dependency := range pkg.Dependencies {
@@ -201,6 +201,10 @@ func (dm *YAMLParser) ComposeDependencies(pkg Package, 
projectPath string, fileP
 
                annotations := dm.composeAnnotations(dependency.Annotations)
 
+               if utils.Flags.Managed || utils.Flags.Sync {
+                       annotations = append(annotations, ma)
+               }
+
                packDir := path.Join(projectPath, 
strings.Title(YAML_KEY_PACKAGES))
                depName := packageName + ":" + key
                depMap[depName] = utils.NewDependencyRecord(packDir, 
packageName, location, version, inputs, annotations, isBinding)
@@ -308,7 +312,7 @@ func (dm *YAMLParser) ComposePackage(pkg Package, 
packageName string, filePath s
        }
 
        // add Managed Annotations if this is Managed Deployment
-       if utils.Flags.Managed {
+       if utils.Flags.Managed || utils.Flags.Sync {
                pag.Annotations = append(pag.Annotations, ma)
        }
 
@@ -383,7 +387,7 @@ func (dm *YAMLParser) ComposeSequences(namespace string, 
sequences map[string]Se
                }
 
                // appending managed annotations if its a managed deployment
-               if utils.Flags.Managed {
+               if utils.Flags.Managed || utils.Flags.Sync {
                        wskaction.Annotations = append(wskaction.Annotations, 
ma)
                }
 
@@ -756,7 +760,7 @@ func (dm *YAMLParser) ComposeActions(manifestFilePath 
string, actions map[string
                }
 
                // add managed annotations if its marked as managed deployment
-               if utils.Flags.Managed {
+               if utils.Flags.Managed || utils.Flags.Sync {
                        wskaction.Annotations = append(wskaction.Annotations, 
ma)
                }
 
@@ -864,7 +868,7 @@ func (dm *YAMLParser) ComposeTriggers(filePath string, pkg 
Package, ma whisk.Key
                }
 
                // add managed annotations if its a managed deployment
-               if utils.Flags.Managed {
+               if utils.Flags.Managed || utils.Flags.Sync {
                        wsktrigger.Annotations = append(wsktrigger.Annotations, 
ma)
                }
 
@@ -917,7 +921,7 @@ func (dm *YAMLParser) ComposeRules(pkg Package, packageName 
string, ma whisk.Key
                }
 
                // add managed annotations if its a managed deployment
-               if utils.Flags.Managed {
+               if utils.Flags.Managed || utils.Flags.Sync {
                        wskrule.Annotations = append(wskrule.Annotations, ma)
                }
 
diff --git a/parsers/manifest_parser_test.go b/parsers/manifest_parser_test.go
index bc6948e..f96ebc1 100644
--- a/parsers/manifest_parser_test.go
+++ b/parsers/manifest_parser_test.go
@@ -1332,7 +1332,7 @@ func TestComposeDependencies(t *testing.T) {
        file := "../tests/dat/manifest_data_compose_dependencies.yaml"
        p, m, _ := testLoadParseManifest(t, file)
 
-       depdList, err := p.ComposeDependenciesFromAllPackages(m, 
"/project_folder", m.Filepath)
+       depdList, err := p.ComposeDependenciesFromAllPackages(m, 
"/project_folder", m.Filepath, whisk.KeyValue{})
        assert.Nil(t, err, fmt.Sprintf(TEST_ERROR_COMPOSE_DEPENDENCY_FAILURE, 
file))
 
        assert.Equal(t, 3, len(depdList), "Failed to get rules")
diff --git a/tests/src/integration/common/wskdeploy.go 
b/tests/src/integration/common/wskdeploy.go
index 2eb18e5..17755a9 100644
--- a/tests/src/integration/common/wskdeploy.go
+++ b/tests/src/integration/common/wskdeploy.go
@@ -167,15 +167,11 @@ func (wskdeploy *Wskdeploy) 
UndeployManifestPathOnly(manifestpath string) (strin
 }
 
 func (Wskdeploy *Wskdeploy) ManagedDeployment(manifestPath string, 
deploymentPath string) (string, error) {
-       return Wskdeploy.RunCommand("-m", manifestPath, "-d", deploymentPath, 
"--managed")
+       return Wskdeploy.RunCommand("sync", "-m", manifestPath, "-d", 
deploymentPath)
 }
 
 func (Wskdeploy *Wskdeploy) HeadlessManagedDeployment(manifestPath string, 
deploymentPath string, name string) (string, error) {
-       return Wskdeploy.RunCommand("-m", manifestPath, "-d", deploymentPath, 
"--managed", "--projectname", name)
-}
-
-func (Wskdeploy *Wskdeploy) ManagedUndeployment(manifestPath string, 
deploymentPath string) (string, error) {
-       return Wskdeploy.RunCommand("undeploy", "-m", manifestPath, "-d", 
deploymentPath, "--managed")
+       return Wskdeploy.RunCommand("sync", "-m", manifestPath, "-d", 
deploymentPath, "--projectname", name)
 }
 
 // This method is only for testing
diff --git 
a/tests/src/integration/managed-deployment/06-manifest-with-dependency.yaml 
b/tests/src/integration/managed-deployment/06-manifest-with-dependency.yaml
new file mode 100644
index 0000000..0cbe848
--- /dev/null
+++ b/tests/src/integration/managed-deployment/06-manifest-with-dependency.yaml
@@ -0,0 +1,40 @@
+#
+# 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.
+#
+
+project:
+    name: MyManagedProjectWithDependency
+    packages:
+        Extension1:
+            dependencies:
+                helloworlds:
+                    location: 
github.com/pritidesai/incubator-openwhisk-test/packages/helloworlds
+                custom-hellowhisk:
+                    location: 
github.com/pritidesai/incubator-openwhisk-test/packages/hellowhisk
+                custom-helloworlds:
+                    location: 
github.com/pritidesai/incubator-openwhisk-test/packages/helloworlds
+            sequences:
+                helloworld-sequence:
+                   actions: custom-helloworlds/hello-js, 
custom-hellowhisk/greeting, helloworlds/hello-js
+            triggers:
+                trigger1:
+                trigger2:
+            rules:
+                rule1:
+                    trigger: trigger1
+                    action: helloworld-sequence
+                rule2:
+                    trigger: trigger2
+                    action: custom-helloworlds/helloworld-js
diff --git 
a/tests/src/integration/managed-deployment/07-manifest-with-single-dependency.yaml
 
b/tests/src/integration/managed-deployment/07-manifest-with-single-dependency.yaml
new file mode 100644
index 0000000..903fd0e
--- /dev/null
+++ 
b/tests/src/integration/managed-deployment/07-manifest-with-single-dependency.yaml
@@ -0,0 +1,29 @@
+#
+# 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.
+#
+
+project:
+    name: MyManagedProjectWithSingleDependency
+    packages:
+        Extension2:
+            dependencies:
+                helloworlds:
+                    location: 
github.com/pritidesai/incubator-openwhisk-test/packages/helloworlds
+            triggers:
+                triggerInExtension2:
+            rules:
+                ruleInExtension2:
+                    trigger: triggerInExtension2
+                    action: helloworlds/helloworld-js
diff --git 
a/tests/src/integration/managed-deployment/08-manifest-with-dependencies-on-whisk-system.yaml
 
b/tests/src/integration/managed-deployment/08-manifest-with-dependencies-on-whisk-system.yaml
new file mode 100644
index 0000000..612feeb
--- /dev/null
+++ 
b/tests/src/integration/managed-deployment/08-manifest-with-dependencies-on-whisk-system.yaml
@@ -0,0 +1,29 @@
+#
+# 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.
+#
+
+project:
+    name: MyManagedProjectWithWhiskSystemDependency
+    packages:
+        Extension3:
+            dependencies:
+                whiskUtility:
+                    location: /whisk.system/utils
+            triggers:
+                triggerInExtension3:
+            rules:
+                ruleInExtension3:
+                    trigger: triggerInExtension3
+                    action: whiskUtility/sort
diff --git 
a/tests/src/integration/managed-deployment/managed-deployment_test.go 
b/tests/src/integration/managed-deployment/managed-deployment_test.go
index 119296d..475ab71 100644
--- a/tests/src/integration/managed-deployment/managed-deployment_test.go
+++ b/tests/src/integration/managed-deployment/managed-deployment_test.go
@@ -27,41 +27,61 @@ import (
        "github.com/stretchr/testify/assert"
 )
 
+const PATH = 
"/src/github.com/apache/incubator-openwhisk-wskdeploy/tests/src/integration/managed-deployment/"
+
 func TestManagedDeployment(t *testing.T) {
-       path := 
"/src/github.com/apache/incubator-openwhisk-wskdeploy/tests/src/integration/managed-deployment/"
-       manifestPath := os.Getenv("GOPATH") + path + "manifest.yaml"
+       manifestPath := os.Getenv("GOPATH") + PATH + "manifest.yaml"
        deploymentPath := ""
        wskdeploy := common.NewWskdeploy()
        _, err := wskdeploy.ManagedDeployment(manifestPath, deploymentPath)
        assert.Equal(t, nil, err, "Failed to deploy based on the manifest and 
deployment files.")
 
-       manifestPath = os.Getenv("GOPATH") + path + 
"00-manifest-minus-second-package.yaml"
-       wskdeploy = common.NewWskdeploy()
+       manifestPath = os.Getenv("GOPATH") + PATH + 
"00-manifest-minus-second-package.yaml"
        _, err = wskdeploy.ManagedDeployment(manifestPath, deploymentPath)
        assert.Equal(t, nil, err, "Failed to deploy based on the manifest and 
deployment files.")
 
-       manifestPath = os.Getenv("GOPATH") + path + 
"01-manifest-minus-sequence-2.yaml"
-       wskdeploy = common.NewWskdeploy()
+       manifestPath = os.Getenv("GOPATH") + PATH + 
"01-manifest-minus-sequence-2.yaml"
        _, err = wskdeploy.ManagedDeployment(manifestPath, deploymentPath)
        assert.Equal(t, nil, err, "Failed to deploy based on the manifest and 
deployment files.")
 
-       manifestPath = os.Getenv("GOPATH") + path + 
"02-manifest-minus-action-3.yaml"
-       wskdeploy = common.NewWskdeploy()
+       manifestPath = os.Getenv("GOPATH") + PATH + 
"02-manifest-minus-action-3.yaml"
        _, err = wskdeploy.ManagedDeployment(manifestPath, deploymentPath)
        assert.Equal(t, nil, err, "Failed to deploy based on the manifest and 
deployment files.")
 
-       manifestPath = os.Getenv("GOPATH") + path + 
"03-manifest-minus-trigger.yaml"
-       wskdeploy = common.NewWskdeploy()
+       manifestPath = os.Getenv("GOPATH") + PATH + 
"03-manifest-minus-trigger.yaml"
        _, err = wskdeploy.ManagedDeployment(manifestPath, deploymentPath)
        assert.Equal(t, nil, err, "Failed to deploy based on the manifest and 
deployment files.")
 
-       manifestPath = os.Getenv("GOPATH") + path + 
"04-manifest-minus-package.yaml"
-       wskdeploy = common.NewWskdeploy()
+       manifestPath = os.Getenv("GOPATH") + PATH + 
"04-manifest-minus-package.yaml"
        _, err = wskdeploy.ManagedDeployment(manifestPath, deploymentPath)
        assert.Equal(t, nil, err, "Failed to deploy based on the manifest and 
deployment files.")
 
-       manifestPath = os.Getenv("GOPATH") + path + "05-manifest-headless.yaml"
-       wskdeploy = common.NewWskdeploy()
+       manifestPath = os.Getenv("GOPATH") + PATH + "05-manifest-headless.yaml"
        _, err = wskdeploy.HeadlessManagedDeployment(manifestPath, 
deploymentPath, "Headless Managed")
        assert.Equal(t, nil, err, "Failed to deploy based on the manifest and 
deployment files.")
+       _, err = wskdeploy.Undeploy(manifestPath, deploymentPath)
+       assert.Equal(t, nil, err, "Failed to deploy based on the manifest and 
deployment files.")
+
+}
+
+func TestManagedDeploymentWithDependency(t *testing.T) {
+       manifestPath := os.Getenv("GOPATH") + PATH + 
"06-manifest-with-dependency.yaml"
+       deploymentPath := ""
+       wskdeploy := common.NewWskdeploy()
+       _, err := wskdeploy.ManagedDeployment(manifestPath, deploymentPath)
+       assert.Equal(t, nil, err, "Failed to deploy based on the manifest and 
deployment files.")
+       _, err = wskdeploy.Undeploy(manifestPath, deploymentPath)
+       assert.Equal(t, nil, err, "Failed to deploy based on the manifest and 
deployment files.")
+
+       manifestPath = os.Getenv("GOPATH") + PATH + 
"07-manifest-with-single-dependency.yaml"
+       _, err = wskdeploy.ManagedDeployment(manifestPath, deploymentPath)
+       assert.Equal(t, nil, err, "Failed to deploy based on the manifest and 
deployment files.")
+       _, err = wskdeploy.Undeploy(manifestPath, deploymentPath)
+       assert.Equal(t, nil, err, "Failed to deploy based on the manifest and 
deployment files.")
+
+       //manifestPath = os.Getenv("GOPATH") + PATH + 
"08-manifest-with-dependencies-on-whisk-system.yaml"
+       //_, err = wskdeploy.ManagedDeployment(manifestPath, deploymentPath)
+       //assert.Equal(t, nil, err, "Failed to deploy based on the manifest and 
deployment files.")
+       //_, err = wskdeploy.Undeploy(manifestPath, deploymentPath)
+       //assert.Equal(t, nil, err, "Failed to deploy based on the manifest and 
deployment files.")
 }
diff --git a/utils/flags.go b/utils/flags.go
index 278527e..7d42cde 100644
--- a/utils/flags.go
+++ b/utils/flags.go
@@ -42,6 +42,7 @@ type WskDeployFlags struct {
        ApigwAccessToken string
        Verbose          bool
        Trace            bool
+       Sync             bool
 }
 
 func (flags *WskDeployFlags) Format() string {
diff --git a/utils/managedannotations.go b/utils/managedannotations.go
index fa0781e..858b2b5 100644
--- a/utils/managedannotations.go
+++ b/utils/managedannotations.go
@@ -35,17 +35,20 @@ import (
  */
 
 const (
-       MANAGED         = "managed"
+       MANAGED         = "whisk-managed"
        OPENWHISK       = "OpenWhisk"
        NULL            = "golang\000"
-       OW_PROJECT_NAME = "__OW_PROJECT_NAME"
-       OW_PROJECT_HASH = "__OW_PROJECT_HASH"
+       OW_PROJECT_NAME = "projectName"
+       OW_PROJECT_HASH = "projectHash"
+       OW_PROJECT_DEPS = "projectDeps"
+       OW_File         = "file"
 )
 
 type ManagedAnnotation struct {
-       ProjectName string `json:"__OW_PROJECT_NAME"`
-       ProjectHash string `json:"__OW_PROJECT_HASH"`
-       File        string `json:"__OW_FILE"`
+       ProjectName string            `json:"projectName"`
+       ProjectHash string            `json:"projectHash"`
+       File        string            `json:"file"`
+       Deps        whisk.KeyValueArr `json:"projectDeps"`
 }
 
 // Project Hash is generated based on the following formula:
@@ -100,13 +103,38 @@ func GenerateManagedAnnotation(projectName string, 
filePath string) (whisk.KeyVa
                ProjectName: projectName,
                ProjectHash: projectHash,
                File:        filePath,
+               Deps:        make(whisk.KeyValueArr, 0),
        }
-       ma, err := json.Marshal(m)
+       ma, err := structToJson(m)
        if err != nil {
                return managedAnnotation, err
        }
-       var a interface{}
-       err = json.Unmarshal(ma, &a)
-       managedAnnotation = whisk.KeyValue{Key: MANAGED, Value: 
a.(map[string]interface{})}
+       managedAnnotation = whisk.KeyValue{Key: MANAGED, Value: ma}
        return managedAnnotation, nil
 }
+
+func AddDependentAnnotation(existingAnnotation map[string]interface{}, 
dependencyAnnotations whisk.KeyValueArr) (whisk.KeyValue, error) {
+       managedAnnotation := whisk.KeyValue{}
+       m := ManagedAnnotation{
+               ProjectName: existingAnnotation[OW_PROJECT_NAME].(string),
+               ProjectHash: existingAnnotation[OW_PROJECT_HASH].(string),
+               File:        existingAnnotation[OW_File].(string),
+               Deps:        dependencyAnnotations,
+       }
+       ma, err := structToJson(m)
+       if err != nil {
+               return managedAnnotation, err
+       }
+       managedAnnotation = whisk.KeyValue{Key: MANAGED, Value: ma}
+       return managedAnnotation, nil
+}
+
+func structToJson(m ManagedAnnotation) (map[string]interface{}, error) {
+       ma, err := json.Marshal(m)
+       if err != nil {
+               return nil, err
+       }
+       var a interface{}
+       json.Unmarshal(ma, &a)
+       return a.(map[string]interface{}), nil
+}
diff --git a/wski18n/i18n_ids.go b/wski18n/i18n_ids.go
index 12807b5..25ceb06 100644
--- a/wski18n/i18n_ids.go
+++ b/wski18n/i18n_ids.go
@@ -40,6 +40,7 @@ const (
        CMD_DEPLOY         = "deploy"
        CMD_UNDEPLOY       = "undeploy"
        CMD_SYNC           = "sync"
+       TRIGGERS           = "Triggers"
 )
 
 // DO NOT TRANSLATE
@@ -72,6 +73,9 @@ const (
        KEY_API             = "api"
        KEY_URL             = "url"
        KEY_PACKAGE         = "package"
+       KEY_BINDINGS        = "bindings"
+       KEY_DEPENDENCY      = "dependency"
+       KEY_LOCATION        = "location"
 )
 
 // DO NOT TRANSLATE
@@ -86,9 +90,11 @@ const (
        // Cobra command descriptions
        ID_CMD_DESC_LONG_REPORT   = "msg_cmd_desc_long_report"
        ID_CMD_DESC_LONG_ROOT     = "msg_cmd_desc_long_root"
+       ID_CMD_DESC_LONG_SYNC     = "msg_cmd_desc_long_sync"
        ID_CMD_DESC_SHORT_REPORT  = "msg_cmd_desc_short_report"
        ID_CMD_DESC_SHORT_ROOT    = "msg_cmd_desc_short_root"
        ID_CMD_DESC_SHORT_VERSION = "msg_cmd_desc_short_version"
+       ID_CMD_DESC_SHORT_SYNC    = "msg_cmd_desc_short_sync"
 
        // Cobra Flag messages
        ID_CMD_FLAG_API_HOST    = "msg_cmd_flag_api_host"
diff --git a/wski18n/i18n_resources.go b/wski18n/i18n_resources.go
index b22c917..a28d6b9 100644
--- a/wski18n/i18n_resources.go
+++ b/wski18n/i18n_resources.go
@@ -97,7 +97,7 @@ func wski18nResourcesDe_deAllJson() (*asset, error) {
        return a, nil
 }
 
-var _wski18nResourcesEn_usAllJson = 
[]byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xc4\x5b\x5f\x8f\xdb\x36\x12\x7f\xcf\xa7\x18\x04\x07\xa4\x05\x1c\x25\xed\xe1\x80\x43\x80\x7d\xc8\x35\x69\xbb\xd7\x26\x1b\xec\x26\x17\x14\xb9\x85\x42\x8b\x63\x9b\xb5\x44\x0a\x24\x65\xc7\x35\xfc\xdd\x0f\xc3\x3f\x92\xec\x5d\x4a\x5a\xa7\xc5\xe5\xa5\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\x26
 [...]
+var _wski18nResourcesEn_usAllJson = 
[]byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xc4\x5b\x6d\x8f\xdb\x36\xf2\x7f\x9f\x4f\x31\x08\xfe\x40\x5a\xc0\x51\xd2\xfe\x71\xc0\x21\x40\x5e\xe4\x9a\xb4\xdd\x6b\x93\x0d\x76\xb3\x17\x14\xb9\x85\x42\x4b\x63\x9b\xb5\x44\x0a\x24\x65\xc7\x35\xfc\xdd\x0f\x33\xa4\x1e\xec\x5d\x4a\x5a\xa7\xbd\xeb\x9b\xf3\x2d\x87\x33\xbf\x79\xe0\x70\x66\xa8\x7c\x7a\x04\xb0\x7f\x04\x00\xf0\x58\xe6\x8f\x5f\xc0\xe3\xd2\x2e\xd3\xca\xe0\x42\x7e\x49\xd1\x18\x6d\x1e\xcf\xfc\xaa\x33
 [...]
 
 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: 
13551, mode: os.FileMode(420), modTime: time.Unix(1521501471, 0)}
+       info := bindataFileInfo{name: "wski18n/resources/en_US.all.json", size: 
13874, mode: os.FileMode(420), modTime: time.Unix(1522158494, 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 512d758..9824ddb 100644
--- a/wski18n/resources/en_US.all.json
+++ b/wski18n/resources/en_US.all.json
@@ -36,6 +36,14 @@
     "translation": "Print the version number of wskdeploy"
   },
   {
+    "id": "msg_cmd_desc_short_sync",
+    "translation": "A tool to sync your OpenWhisk packages between client and 
server."
+  },
+  {
+    "id": "msg_cmd_desc_long_sync",
+    "translation": "A tool to sync deployment and undeployment of openwhisk 
packages using a manifest and optional deployment files using YAML."
+  },
+  {
     "id": "msg_cmd_flag_api_host",
     "translation": "whisk API `HOST`"
   },

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

Reply via email to