github.com/cozy/cozy-stack@v0.0.0-20240603063001-31110fa4cae1/cmd/apps.go (about)

     1  package cmd
     2  
     3  // filesCmdGroup represents the instances command
     4  import (
     5  	"encoding/json"
     6  	"errors"
     7  	"fmt"
     8  	"os"
     9  	"text/tabwriter"
    10  
    11  	"github.com/cozy/cozy-stack/client"
    12  	"github.com/cozy/cozy-stack/model/app"
    13  	"github.com/cozy/cozy-stack/pkg/consts"
    14  	"github.com/spf13/cobra"
    15  )
    16  
    17  var (
    18  	flagAllDomains      bool
    19  	flagAppsDeactivated bool
    20  	flagSafeUpdate      bool
    21  )
    22  
    23  var (
    24  	flagKonnectorAccountID   string
    25  	flagKonnectorsParameters string
    26  )
    27  
    28  var (
    29  	flagKonnectorContext             string
    30  	flagKonnectorsShortMaintenance   bool
    31  	flagKonnectorsDisallowManualExec bool
    32  )
    33  
    34  var webappsCmdGroup = &cobra.Command{
    35  	Use:   "apps <command>",
    36  	Short: "Interact with the applications",
    37  	Long: `
    38  cozy-stack apps allows to interact with the cozy applications.
    39  
    40  It provides commands to install or update applications on
    41  a cozy.
    42  `,
    43  	RunE: func(cmd *cobra.Command, args []string) error {
    44  		return cmd.Usage()
    45  	},
    46  }
    47  
    48  var triggersCmdGroup = &cobra.Command{
    49  	Use:   "triggers <command>",
    50  	Short: "Interact with the triggers",
    51  	Long: `
    52  cozy-stack apps allows to interact with the cozy triggers.
    53  
    54  It provides command to run a specific trigger.
    55  `,
    56  	RunE: func(cmd *cobra.Command, args []string) error {
    57  		return cmd.Usage()
    58  	},
    59  }
    60  
    61  var installWebappCmd = &cobra.Command{
    62  	Use: "install <slug> [sourceurl]",
    63  	Short: `Install an application with the specified slug name
    64  from the given source URL.`,
    65  	Example: `
    66  $ cozy-stack apps install --domain cozy.localhost:8080 drive registry://drive/stable
    67  $ cozy-stack apps install banks 'git://github.com/cozy/cozy-banks.git#build'
    68  $ cozy-stack apps install myapp 'git+ssh://git@gitlab.example.net/team/myapp.git#build'
    69  `,
    70  	Long: "[Some schemes](https://docs.cozy.io/en/cozy-stack/apps/#sources) are allowed as `[sourceurl]`.",
    71  	RunE: func(cmd *cobra.Command, args []string) error {
    72  		return installApp(cmd, args, consts.Apps)
    73  	},
    74  }
    75  
    76  var updateWebappCmd = &cobra.Command{
    77  	Use:     "update <slug> [sourceurl]",
    78  	Short:   "Update the application with the specified slug name.",
    79  	Aliases: []string{"upgrade"},
    80  	RunE: func(cmd *cobra.Command, args []string) error {
    81  		return updateApp(cmd, args, consts.Apps)
    82  	},
    83  }
    84  
    85  var uninstallWebappCmd = &cobra.Command{
    86  	Use:     "uninstall <slug>",
    87  	Short:   "Uninstall the application with the specified slug name.",
    88  	Aliases: []string{"rm"},
    89  	RunE: func(cmd *cobra.Command, args []string) error {
    90  		return uninstallApp(cmd, args, consts.Apps)
    91  	},
    92  }
    93  
    94  var lsWebappsCmd = &cobra.Command{
    95  	Use:   "ls",
    96  	Short: "List the installed applications.",
    97  	RunE: func(cmd *cobra.Command, args []string) error {
    98  		return lsApps(cmd, args, consts.Apps)
    99  	},
   100  }
   101  
   102  var showWebappCmd = &cobra.Command{
   103  	Use:   "show <slug>",
   104  	Short: "Show the application attributes",
   105  	RunE: func(cmd *cobra.Command, args []string) error {
   106  		return showApp(cmd, args, consts.Apps)
   107  	},
   108  }
   109  
   110  var showWebappTriggersCmd = &cobra.Command{
   111  	Use:   "show-from-app <slug>",
   112  	Short: "Show the application triggers",
   113  	RunE: func(cmd *cobra.Command, args []string) error {
   114  		return showWebAppTriggers(cmd, args, consts.Apps)
   115  	},
   116  }
   117  
   118  var showKonnectorCmd = &cobra.Command{
   119  	Use:   "show <slug>",
   120  	Short: "Show the application attributes",
   121  	RunE: func(cmd *cobra.Command, args []string) error {
   122  		return showApp(cmd, args, consts.Konnectors)
   123  	},
   124  }
   125  
   126  var konnectorsCmdGroup = &cobra.Command{
   127  	Use:   "konnectors <command>",
   128  	Short: "Interact with the konnectors",
   129  	Long: `
   130  cozy-stack konnectors allows to interact with the cozy konnectors.
   131  
   132  It provides commands to install or update applications on
   133  a cozy.
   134  `,
   135  	RunE: func(cmd *cobra.Command, args []string) error {
   136  		return cmd.Usage()
   137  	},
   138  }
   139  
   140  var installKonnectorCmd = &cobra.Command{
   141  	Use: "install <slug> [sourceurl]",
   142  	Short: `Install a konnector with the specified slug name
   143  from the given source URL.`,
   144  	Long: `
   145  Install a konnector with the specified slug name. You can also provide the
   146  version number to install a specific release if you use the registry:// scheme.
   147  Following formats are accepted:
   148  	registry://<konnector>/<channel>/<version>
   149  	registry://<konnector>/<channel>
   150  	registry://<konnector>/<version>
   151  	registry://<konnector>
   152  
   153  If you provide a channel and a version, the channel is ignored.
   154  Default channel is stable.
   155  Default version is latest.
   156  `,
   157  	Example: `
   158  $ cozy-stack konnectors install --domain cozy.localhost:8080 trainline registry://trainline/stable/1.0.1
   159  $ cozy-stack konnectors install --domain cozy.localhost:8080 trainline registry://trainline/stable
   160  $ cozy-stack konnectors install --domain cozy.localhost:8080 trainline registry://trainline/1.2.0
   161  $ cozy-stack konnectors install --domain cozy.localhost:8080 trainline registry://trainline
   162  `,
   163  	RunE: func(cmd *cobra.Command, args []string) error {
   164  		return installApp(cmd, args, consts.Konnectors)
   165  	},
   166  }
   167  
   168  var updateKonnectorCmd = &cobra.Command{
   169  	Use:     "update <slug> [sourceurl]",
   170  	Short:   "Update the konnector with the specified slug name.",
   171  	Aliases: []string{"upgrade"},
   172  	RunE: func(cmd *cobra.Command, args []string) error {
   173  		return updateApp(cmd, args, consts.Konnectors)
   174  	},
   175  }
   176  
   177  var uninstallKonnectorCmd = &cobra.Command{
   178  	Use:     "uninstall <slug>",
   179  	Short:   "Uninstall the konnector with the specified slug name.",
   180  	Aliases: []string{"rm"},
   181  	RunE: func(cmd *cobra.Command, args []string) error {
   182  		return uninstallApp(cmd, args, consts.Konnectors)
   183  	},
   184  }
   185  
   186  var lsKonnectorsCmd = &cobra.Command{
   187  	Use:   "ls",
   188  	Short: "List the installed konnectors.",
   189  	RunE: func(cmd *cobra.Command, args []string) error {
   190  		return lsApps(cmd, args, consts.Konnectors)
   191  	},
   192  }
   193  
   194  var runKonnectorsCmd = &cobra.Command{
   195  	Use:   "run <slug>",
   196  	Short: "Run a konnector.",
   197  	Long:  "Run a konnector named with specified slug using the specified options.",
   198  	RunE: func(cmd *cobra.Command, args []string) error {
   199  		if flagDomain == "" {
   200  			errPrintfln("%s", errMissingDomain)
   201  			return cmd.Usage()
   202  		}
   203  		if len(args) < 1 {
   204  			return cmd.Usage()
   205  		}
   206  
   207  		slug := args[0]
   208  		c := newClient(flagDomain,
   209  			consts.Jobs+":POST:konnector:worker",
   210  			consts.Triggers,
   211  			consts.Files,
   212  			consts.Accounts,
   213  		)
   214  
   215  		ts, err := c.GetTriggers("konnector")
   216  		if err != nil {
   217  			return err
   218  		}
   219  
   220  		type localTrigger struct {
   221  			id        string
   222  			accountID string
   223  		}
   224  
   225  		var triggers []*localTrigger
   226  		for _, t := range ts {
   227  			var msg struct {
   228  				Slug    string `json:"konnector"`
   229  				Account string `json:"account"`
   230  			}
   231  			if err = json.Unmarshal(t.Attrs.Message, &msg); err != nil {
   232  				return err
   233  			}
   234  			if msg.Slug == slug {
   235  				triggers = append(triggers, &localTrigger{t.ID, msg.Account})
   236  			}
   237  		}
   238  
   239  		if len(triggers) == 0 {
   240  			return fmt.Errorf("Could not find a konnector %q: "+
   241  				"it may be installed but it is not activated (no related trigger)", slug)
   242  		}
   243  
   244  		var trigger *localTrigger
   245  		if len(triggers) > 1 || flagKonnectorAccountID != "" {
   246  			if flagKonnectorAccountID == "" {
   247  				return errors.New("Found multiple konnectors with different accounts: use the --account-id flag")
   248  			}
   249  			for _, t := range triggers {
   250  				if t.accountID == flagKonnectorAccountID {
   251  					trigger = t
   252  					break
   253  				}
   254  			}
   255  			if trigger == nil {
   256  				return fmt.Errorf("Could not find konnector linked to account with id %q",
   257  					flagKonnectorAccountID)
   258  			}
   259  		} else {
   260  			trigger = triggers[0]
   261  		}
   262  
   263  		j, err := c.TriggerLaunch(trigger.id)
   264  		if err != nil {
   265  			return err
   266  		}
   267  
   268  		json, err := json.MarshalIndent(j, "", "  ")
   269  		if err != nil {
   270  			return err
   271  		}
   272  
   273  		fmt.Println(string(json))
   274  		return nil
   275  	},
   276  }
   277  
   278  var listMaintenancesCmd = &cobra.Command{
   279  	Use:   "ls-maintenances",
   280  	Short: `List the konnectors in maintenance`,
   281  	RunE: func(cmd *cobra.Command, args []string) (err error) {
   282  		ac := newAdminClient()
   283  		list, err := ac.ListMaintenances(flagKonnectorContext)
   284  		if err != nil {
   285  			return err
   286  		}
   287  		for _, item := range list {
   288  			json, err := json.MarshalIndent(item, "", "  ")
   289  			if err != nil {
   290  				return err
   291  			}
   292  			fmt.Println(string(json))
   293  		}
   294  		return nil
   295  	},
   296  }
   297  
   298  var activateMaintenanceKonnectorsCmd = &cobra.Command{
   299  	Use:   "maintenance [slug]",
   300  	Short: `Activate the maintenance for the given konnector`,
   301  	RunE: func(cmd *cobra.Command, args []string) (err error) {
   302  		if len(args) != 1 {
   303  			return cmd.Help()
   304  		}
   305  
   306  		messages := make(map[string]interface{})
   307  		for {
   308  			locale := prompt("Locale (empty to abort):")
   309  			if locale == "" {
   310  				break
   311  			}
   312  			if len(locale) > 5 {
   313  				fmt.Fprintf(os.Stdout, "Invalid locale name: %q\n", locale)
   314  				continue
   315  			}
   316  			shortMessage := prompt("Short message:")
   317  			longMessage := prompt("Long message:")
   318  			messages[locale] = map[string]string{
   319  				"short_message": shortMessage,
   320  				"long_message":  longMessage,
   321  			}
   322  		}
   323  		opts := map[string]interface{}{
   324  			"flag_short_maintenance":    flagKonnectorsShortMaintenance,
   325  			"flag_disallow_manual_exec": flagKonnectorsDisallowManualExec,
   326  			"messages":                  messages,
   327  		}
   328  		ac := newAdminClient()
   329  		return ac.ActivateMaintenance(args[0], opts)
   330  	},
   331  }
   332  
   333  var deactivateMaintenanceKonnectorsCmd = &cobra.Command{
   334  	Use:   "deactivate-maintenance [slug]",
   335  	Short: `Deactivate maintenance for the given konnector`,
   336  	RunE: func(cmd *cobra.Command, args []string) (err error) {
   337  		if len(args) != 1 {
   338  			return cmd.Help()
   339  		}
   340  		ac := newAdminClient()
   341  		return ac.DeactivateMaintenance(args[0])
   342  	},
   343  }
   344  
   345  func installApp(cmd *cobra.Command, args []string, appType string) error {
   346  	if len(args) < 1 {
   347  		return cmd.Usage()
   348  	}
   349  	slug := args[0]
   350  	source := "registry://" + slug + "/stable"
   351  	if len(args) > 1 {
   352  		source = args[1]
   353  	}
   354  	if flagAllDomains {
   355  		return foreachDomains(func(in *client.Instance) error {
   356  			c := newClient(in.Attrs.Domain, appType)
   357  			_, err := c.InstallApp(&client.AppOptions{
   358  				AppType:     appType,
   359  				Slug:        slug,
   360  				SourceURL:   source,
   361  				Deactivated: flagAppsDeactivated,
   362  			})
   363  			if err != nil {
   364  				if err.Error() == app.ErrAlreadyExists.Error() {
   365  					return nil
   366  				}
   367  				return err
   368  			}
   369  			fmt.Fprintf(os.Stdout, "Application installed successfully on %s\n", in.Attrs.Domain)
   370  			return nil
   371  		})
   372  	}
   373  	if flagDomain == "" {
   374  		errPrintfln("%s", errMissingDomain)
   375  		return cmd.Usage()
   376  	}
   377  
   378  	var overridenParameters *json.RawMessage
   379  	if flagKonnectorsParameters != "" {
   380  		tmp := json.RawMessage(flagKonnectorsParameters)
   381  		overridenParameters = &tmp
   382  	}
   383  
   384  	c := newClient(flagDomain, appType)
   385  	manifest, err := c.InstallApp(&client.AppOptions{
   386  		AppType:     appType,
   387  		Slug:        slug,
   388  		SourceURL:   source,
   389  		Deactivated: flagAppsDeactivated,
   390  
   391  		OverridenParameters: overridenParameters,
   392  	})
   393  	if err != nil {
   394  		return err
   395  	}
   396  	fmt.Fprintf(os.Stdout, "%s (%s) has been installed on %s\n", slug, manifest.Attrs.Version, flagDomain)
   397  
   398  	return nil
   399  }
   400  
   401  func updateApp(cmd *cobra.Command, args []string, appType string) error {
   402  	if len(args) == 0 || len(args) > 2 {
   403  		return cmd.Usage()
   404  	}
   405  	var src string
   406  	if len(args) > 1 {
   407  		src = args[1]
   408  	}
   409  	if flagAllDomains {
   410  		return foreachDomains(func(in *client.Instance) error {
   411  			c := newClient(in.Attrs.Domain, appType)
   412  			_, err := c.UpdateApp(&client.AppOptions{
   413  				AppType:   appType,
   414  				Slug:      args[0],
   415  				SourceURL: src,
   416  			}, flagSafeUpdate)
   417  			if err != nil {
   418  				if err.Error() == app.ErrNotFound.Error() {
   419  					return nil
   420  				}
   421  				return err
   422  			}
   423  			fmt.Fprintf(os.Stdout, "Application updated successfully on %s\n", in.Attrs.Domain)
   424  			return nil
   425  		})
   426  	}
   427  	if flagDomain == "" {
   428  		errPrintfln("%s", errMissingDomain)
   429  		return cmd.Usage()
   430  	}
   431  
   432  	var overridenParameters *json.RawMessage
   433  	if flagKonnectorsParameters != "" {
   434  		tmp := json.RawMessage(flagKonnectorsParameters)
   435  		overridenParameters = &tmp
   436  	}
   437  
   438  	c := newClient(flagDomain, appType)
   439  	opts := &client.AppOptions{
   440  		AppType:   appType,
   441  		Slug:      args[0],
   442  		SourceURL: src,
   443  
   444  		OverridenParameters: overridenParameters,
   445  	}
   446  	manifest, err := c.GetApp(opts)
   447  	if err != nil {
   448  		return err
   449  	}
   450  	newManifest, err := c.UpdateApp(opts, flagSafeUpdate)
   451  	if err != nil {
   452  		return err
   453  	}
   454  	msg := "%s is already up-to-date at %s\n"
   455  	if app.IsMoreRecent(manifest.Attrs.Version, newManifest.Attrs.Version) {
   456  		msg = "%s has been upgraded to %s\n"
   457  	} else if app.IsMoreRecent(newManifest.Attrs.Version, manifest.Attrs.Version) {
   458  		msg = "%s has been downgraded to %s\n"
   459  	}
   460  	fmt.Fprintf(os.Stdout, msg, args[0], newManifest.Attrs.Version)
   461  
   462  	return nil
   463  }
   464  
   465  func uninstallApp(cmd *cobra.Command, args []string, appType string) error {
   466  	if len(args) != 1 {
   467  		return cmd.Usage()
   468  	}
   469  	if flagDomain == "" {
   470  		errPrintfln("%s", errMissingDomain)
   471  		return cmd.Usage()
   472  	}
   473  	c := newClient(flagDomain, appType)
   474  	manifest, err := c.UninstallApp(&client.AppOptions{
   475  		AppType: appType,
   476  		Slug:    args[0],
   477  	})
   478  	if err != nil {
   479  		return err
   480  	}
   481  	fmt.Fprintf(os.Stdout, "%s has been uninstalled\n", manifest.Attrs.Slug)
   482  	return nil
   483  }
   484  
   485  func showApp(cmd *cobra.Command, args []string, appType string) error {
   486  	if flagDomain == "" {
   487  		errPrintfln("%s", errMissingDomain)
   488  		return cmd.Usage()
   489  	}
   490  	if len(args) < 1 {
   491  		return cmd.Usage()
   492  	}
   493  	c := newClient(flagDomain, appType)
   494  	manifest, err := c.GetApp(&client.AppOptions{
   495  		Slug:    args[0],
   496  		AppType: appType,
   497  	})
   498  	if err != nil {
   499  		return err
   500  	}
   501  	json, err := json.MarshalIndent(manifest.Attrs, "", "  ")
   502  	if err != nil {
   503  		return err
   504  	}
   505  	fmt.Println(string(json))
   506  	return nil
   507  }
   508  
   509  func showWebAppTriggers(cmd *cobra.Command, args []string, appType string) error {
   510  	if flagDomain == "" {
   511  		errPrintfln("%s", errMissingDomain)
   512  		return cmd.Usage()
   513  	}
   514  	if len(args) < 1 {
   515  		return cmd.Usage()
   516  	}
   517  	c := newClient(flagDomain, appType, consts.Triggers)
   518  	manifest, err := c.GetApp(&client.AppOptions{
   519  		Slug:    args[0],
   520  		AppType: appType,
   521  	})
   522  	if err != nil {
   523  		return err
   524  	}
   525  
   526  	var triggerIDs []string
   527  	if manifest.Attrs.Services == nil {
   528  		fmt.Fprintf(os.Stdout, "No triggers\n")
   529  		return nil
   530  	}
   531  	for _, service := range *manifest.Attrs.Services {
   532  		if service.TriggerID == "" {
   533  			continue
   534  		}
   535  		triggerIDs = append(triggerIDs, service.TriggerID)
   536  	}
   537  	var triggers []*client.Trigger
   538  	var trigger *client.Trigger
   539  	for _, triggerID := range triggerIDs {
   540  		trigger, err = c.GetTrigger(triggerID)
   541  		if err != nil {
   542  			return err
   543  		}
   544  
   545  		triggers = append(triggers, trigger)
   546  	}
   547  	json, err := json.MarshalIndent(triggers, "", "  ")
   548  	if err != nil {
   549  		return err
   550  	}
   551  	fmt.Println(string(json))
   552  	return nil
   553  }
   554  
   555  var listTriggerCmd = &cobra.Command{
   556  	Use:     "ls",
   557  	Short:   `List triggers`,
   558  	Example: "$ cozy-stack triggers ls --domain cozy.localhost:8080",
   559  	RunE: func(cmd *cobra.Command, args []string) error {
   560  		if flagDomain == "" {
   561  			errPrintfln("%s", errMissingDomain)
   562  			return cmd.Usage()
   563  		}
   564  		c := newClient(flagDomain, consts.Triggers)
   565  		list, err := c.ListTriggers()
   566  		if err != nil {
   567  			return err
   568  		}
   569  		w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0)
   570  		for _, t := range list {
   571  			fmt.Fprintf(w, "%s\t%s\t%s\t%v\t%s\n",
   572  				t.ID,
   573  				t.Attrs.WorkerType,
   574  				t.Attrs.Type,
   575  				t.Attrs.Arguments,
   576  				t.Attrs.Debounce,
   577  			)
   578  		}
   579  		return w.Flush()
   580  	},
   581  }
   582  
   583  var launchTriggerCmd = &cobra.Command{
   584  	Use:     "launch [triggerId]",
   585  	Short:   `Creates a job from a specific trigger`,
   586  	Example: "$ cozy-stack triggers launch --domain cozy.localhost:8080 748f42b65aca8c99ec2492eb660d1891",
   587  	RunE:    launchTrigger,
   588  }
   589  
   590  func launchTrigger(cmd *cobra.Command, args []string) error {
   591  	if len(args) < 1 {
   592  		return cmd.Usage()
   593  	}
   594  	if flagDomain == "" {
   595  		errPrintfln("%s", errMissingDomain)
   596  		return cmd.Usage()
   597  	}
   598  
   599  	// Creates client
   600  	c := newClient(flagDomain, consts.Triggers)
   601  
   602  	// Creates job
   603  	j, err := c.TriggerLaunch(args[0])
   604  	if err != nil {
   605  		return err
   606  	}
   607  
   608  	// Print JSON
   609  	json, err := json.MarshalIndent(j, "", "  ")
   610  	if err != nil {
   611  		return err
   612  	}
   613  	fmt.Println(string(json))
   614  	return nil
   615  }
   616  
   617  func lsApps(cmd *cobra.Command, args []string, appType string) error {
   618  	if flagDomain == "" {
   619  		errPrintfln("%s", errMissingDomain)
   620  		return cmd.Usage()
   621  	}
   622  	c := newClient(flagDomain, appType)
   623  	manifests, err := c.ListApps(appType)
   624  	if err != nil {
   625  		return err
   626  	}
   627  	w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0)
   628  	for _, m := range manifests {
   629  		fmt.Fprintf(w, "%s\t%s\t%s\t%s\n",
   630  			m.Attrs.Slug,
   631  			m.Attrs.Source,
   632  			m.Attrs.Version,
   633  			m.Attrs.State,
   634  		)
   635  	}
   636  	return w.Flush()
   637  }
   638  
   639  func foreachDomains(predicate func(*client.Instance) error) error {
   640  	ac := newAdminClient()
   641  	list, err := ac.ListInstances()
   642  	if err != nil {
   643  		return nil
   644  	}
   645  	var hasErr bool
   646  	for _, i := range list {
   647  		if err = predicate(i); err != nil {
   648  			errPrintfln("%s: %s", i.Attrs.Domain, err)
   649  			hasErr = true
   650  		}
   651  	}
   652  	if hasErr {
   653  		return errors.New("At least one error occurred while executing this command")
   654  	}
   655  	return nil
   656  }
   657  
   658  func init() {
   659  	webappsCmdGroup.PersistentFlags().StringVar(&flagDomain, "domain", cozyDomain(), "specify the domain name of the instance")
   660  	webappsCmdGroup.PersistentFlags().BoolVar(&flagAllDomains, "all-domains", false, "work on all domains iteratively")
   661  
   662  	installWebappCmd.PersistentFlags().BoolVar(&flagAppsDeactivated, "ask-permissions", false, "specify that the application should not be activated after installation")
   663  	updateWebappCmd.PersistentFlags().BoolVar(&flagSafeUpdate, "safe", false, "do not upgrade if there are blocking changes")
   664  	updateKonnectorCmd.PersistentFlags().BoolVar(&flagSafeUpdate, "safe", false, "do not upgrade if there are blocking changes")
   665  
   666  	runKonnectorsCmd.PersistentFlags().StringVar(&flagKonnectorAccountID, "account-id", "", "specify the account ID to use for running the konnector")
   667  
   668  	listMaintenancesCmd.PersistentFlags().StringVar(&flagKonnectorContext, "context", "", "include konnectors in maintenance for apps registry of this context")
   669  	activateMaintenanceKonnectorsCmd.PersistentFlags().BoolVar(&flagKonnectorsShortMaintenance, "short", false, "specify a short maintenance")
   670  	activateMaintenanceKonnectorsCmd.PersistentFlags().BoolVar(&flagKonnectorsDisallowManualExec, "no-manual-exec", false, "specify a maintenance disallowing manual execution")
   671  
   672  	triggersCmdGroup.PersistentFlags().StringVar(&flagDomain, "domain", cozyDomain(), "specify the domain name of the instance")
   673  	triggersCmdGroup.AddCommand(launchTriggerCmd)
   674  	triggersCmdGroup.AddCommand(listTriggerCmd)
   675  	triggersCmdGroup.AddCommand(showWebappTriggersCmd)
   676  
   677  	webappsCmdGroup.AddCommand(lsWebappsCmd)
   678  	webappsCmdGroup.AddCommand(showWebappCmd)
   679  	webappsCmdGroup.AddCommand(installWebappCmd)
   680  	webappsCmdGroup.AddCommand(updateWebappCmd)
   681  	webappsCmdGroup.AddCommand(uninstallWebappCmd)
   682  
   683  	konnectorsCmdGroup.PersistentFlags().StringVar(&flagDomain, "domain", cozyDomain(), "specify the domain name of the instance")
   684  	konnectorsCmdGroup.PersistentFlags().StringVar(&flagKonnectorsParameters, "parameters", "", "override the parameters of the installed konnector")
   685  	konnectorsCmdGroup.PersistentFlags().BoolVar(&flagAllDomains, "all-domains", false, "work on all domains iteratively")
   686  
   687  	konnectorsCmdGroup.AddCommand(lsKonnectorsCmd)
   688  	konnectorsCmdGroup.AddCommand(showKonnectorCmd)
   689  	konnectorsCmdGroup.AddCommand(installKonnectorCmd)
   690  	konnectorsCmdGroup.AddCommand(updateKonnectorCmd)
   691  	konnectorsCmdGroup.AddCommand(uninstallKonnectorCmd)
   692  	konnectorsCmdGroup.AddCommand(runKonnectorsCmd)
   693  	konnectorsCmdGroup.AddCommand(listMaintenancesCmd)
   694  	konnectorsCmdGroup.AddCommand(activateMaintenanceKonnectorsCmd)
   695  	konnectorsCmdGroup.AddCommand(deactivateMaintenanceKonnectorsCmd)
   696  
   697  	RootCmd.AddCommand(triggersCmdGroup)
   698  	RootCmd.AddCommand(webappsCmdGroup)
   699  	RootCmd.AddCommand(konnectorsCmdGroup)
   700  }