get.porter.sh/porter@v1.3.0/cmd/porter/installations.go (about)

     1  package main
     2  
     3  import (
     4  	"get.porter.sh/porter/pkg/porter"
     5  	"github.com/spf13/cobra"
     6  	"github.com/spf13/pflag"
     7  )
     8  
     9  func buildInstallationCommands(p *porter.Porter) *cobra.Command {
    10  	cmd := &cobra.Command{
    11  		Use:     "installations",
    12  		Aliases: []string{"inst", "installation"},
    13  		Short:   "Installation commands",
    14  		Long:    "Commands for working with installations of a bundle",
    15  	}
    16  	cmd.Annotations = map[string]string{
    17  		"group": "resource",
    18  	}
    19  
    20  	cmd.AddCommand(buildInstallationsListCommand(p))
    21  	cmd.AddCommand(buildInstallationShowCommand(p))
    22  	cmd.AddCommand(buildInstallationApplyCommand(p))
    23  	cmd.AddCommand(buildInstallationOutputsCommands(p))
    24  	cmd.AddCommand(buildInstallationDeleteCommand(p))
    25  	cmd.AddCommand(buildInstallationLogCommands(p))
    26  	cmd.AddCommand(buildInstallationRunsCommands(p))
    27  	cmd.AddCommand(buildInstallationInstallCommand(p))
    28  	cmd.AddCommand(buildInstallationUpgradeCommand(p))
    29  	cmd.AddCommand(buildInstallationInvokeCommand(p))
    30  	cmd.AddCommand(buildInstallationUninstallCommand(p))
    31  
    32  	return cmd
    33  }
    34  
    35  func buildInstallationsListCommand(p *porter.Porter) *cobra.Command {
    36  	opts := porter.ListOptions{}
    37  
    38  	cmd := &cobra.Command{
    39  		Use:   "list",
    40  		Short: "List installed bundles",
    41  		Long: `List all bundles installed by Porter.
    42  
    43  A listing of bundles currently installed by Porter will be provided, along with metadata such as creation time, last action, last status, etc.
    44  Optionally filters the results name, which returns all results whose name contain the provided query.
    45  The results may also be filtered by associated labels and the namespace in which the installation is defined.
    46  
    47  Optional output formats include json and yaml.`,
    48  		Example: `  porter installations list
    49    porter installations list -o json
    50    porter installations list --all-namespaces,
    51    porter installations list --label owner=myname --namespace dev
    52    porter installations list --name myapp
    53    porter installations list --skip 2 --limit 2`,
    54  		PreRunE: func(cmd *cobra.Command, args []string) error {
    55  			return opts.Validate()
    56  		},
    57  		RunE: func(cmd *cobra.Command, args []string) error {
    58  			return p.PrintInstallations(cmd.Context(), opts)
    59  		},
    60  	}
    61  
    62  	f := cmd.Flags()
    63  	f.StringVarP(&opts.Namespace, "namespace", "n", "",
    64  		"Filter the installations by namespace. Defaults to the global namespace.")
    65  	f.BoolVar(&opts.AllNamespaces, "all-namespaces", false,
    66  		"Include all namespaces in the results.")
    67  	f.StringVar(&opts.Name, "name", "",
    68  		"Filter the installations where the name contains the specified substring.")
    69  	f.StringSliceVarP(&opts.Labels, "label", "l", nil,
    70  		"Filter the installations by a label formatted as: KEY=VALUE. May be specified multiple times.")
    71  	f.StringVarP(&opts.RawFormat, "output", "o", "plaintext",
    72  		"Specify an output format.  Allowed values: plaintext, json, yaml")
    73  	f.Int64Var(&opts.Skip, "skip", 0,
    74  		"Skip the number of installations by a certain amount. Defaults to 0.")
    75  	f.Int64Var(&opts.Limit, "limit", 0,
    76  		"Limit the number of installations by a certain amount. Defaults to 0.")
    77  	f.StringVar(&opts.FieldSelector, "field-selector", "", "Selector (field query) to filter on, supports '=' (e.g. --field-selector bundle.version=0.2.0,status.action=install). All fields from the json output are supported.")
    78  
    79  	return cmd
    80  }
    81  
    82  func buildInstallationShowCommand(p *porter.Porter) *cobra.Command {
    83  	opts := porter.ShowOptions{}
    84  
    85  	cmd := cobra.Command{
    86  		Use:   "show [INSTALLATION]",
    87  		Short: "Show an installation of a bundle",
    88  		Long:  "Displays info relating to an installation of a bundle, including status and a listing of outputs.",
    89  		Example: `  porter installation show
    90    porter installation show another-bundle
    91  
    92  Optional output formats include json and yaml.
    93  `,
    94  		PreRunE: func(cmd *cobra.Command, args []string) error {
    95  			return opts.Validate(args, p.Context)
    96  		},
    97  		RunE: func(cmd *cobra.Command, args []string) error {
    98  			return p.ShowInstallation(cmd.Context(), opts)
    99  		},
   100  	}
   101  
   102  	f := cmd.Flags()
   103  	f.StringVarP(&opts.Namespace, "namespace", "n", "",
   104  		"Namespace in which the installation is defined. Defaults to the global namespace.")
   105  	f.StringVarP(&opts.RawFormat, "output", "o", "plaintext",
   106  		"Specify an output format.  Allowed values: plaintext, json, yaml")
   107  
   108  	return &cmd
   109  }
   110  
   111  func buildInstallationApplyCommand(p *porter.Porter) *cobra.Command {
   112  	opts := porter.ApplyOptions{}
   113  
   114  	cmd := cobra.Command{
   115  		Use:   "apply FILE",
   116  		Short: "Apply changes to an installation",
   117  		Long: `Apply changes from the specified file to an installation. If the installation doesn't already exist, it is created.
   118  The installation's bundle is automatically executed if changes are detected.
   119  
   120  When the namespace is not set in the file, the current namespace is used.
   121  
   122  You can use the show command to create the initial file:
   123    porter installation show mybuns --output yaml > mybuns.yaml
   124  `,
   125  		Example: `  porter installation apply myapp.yaml
   126    porter installation apply myapp.yaml --dry-run
   127    porter installation apply myapp.yaml --force`,
   128  		PreRunE: func(cmd *cobra.Command, args []string) error {
   129  			return opts.Validate(p.Context, args)
   130  		},
   131  		RunE: func(cmd *cobra.Command, args []string) error {
   132  			return p.InstallationApply(cmd.Context(), opts)
   133  		},
   134  	}
   135  
   136  	f := cmd.Flags()
   137  	f.StringVarP(&opts.Namespace, "namespace", "n", "",
   138  		"Namespace in which the installation is defined. Defaults to the namespace defined in the file.")
   139  	f.BoolVar(&opts.Force, "force", false,
   140  		"Force the bundle to be executed when no changes are detected.")
   141  	f.BoolVar(&opts.DryRun, "dry-run", false,
   142  		"Evaluate if the bundle would be executed based on the changes in the file.")
   143  	return &cmd
   144  }
   145  
   146  func buildInstallationDeleteCommand(p *porter.Porter) *cobra.Command {
   147  	opts := porter.DeleteOptions{}
   148  
   149  	cmd := cobra.Command{
   150  		Use:   "delete [INSTALLATION]",
   151  		Short: "Delete an installation",
   152  		Long:  "Deletes all records and outputs associated with an installation",
   153  		Example: `  porter installation delete
   154    porter installation delete wordpress
   155    porter installation delete --force
   156  `,
   157  		PreRunE: func(cmd *cobra.Command, args []string) error {
   158  			return opts.Validate(args, p.Context)
   159  		},
   160  		RunE: func(cmd *cobra.Command, args []string) error {
   161  			return p.DeleteInstallation(cmd.Context(), opts)
   162  		},
   163  	}
   164  
   165  	f := cmd.Flags()
   166  	f.StringVarP(&opts.Namespace, "namespace", "n", "",
   167  		"Namespace in which the installation is defined. Defaults to the global namespace.")
   168  	f.BoolVar(&opts.Force, "force", false,
   169  		"Force a delete the installation, regardless of last completed action")
   170  
   171  	return &cmd
   172  }
   173  
   174  func buildInstallationRunsCommands(p *porter.Porter) *cobra.Command {
   175  	cmd := &cobra.Command{
   176  		Use:     "runs",
   177  		Aliases: []string{"run"},
   178  		Short:   "Commands for working with runs of an Installation",
   179  		Long:    "Commands for working with runs of an Installation",
   180  	}
   181  
   182  	cmd.AddCommand(buildInstallationRunsListCommand(p))
   183  
   184  	return cmd
   185  }
   186  
   187  func buildInstallationRunsListCommand(p *porter.Porter) *cobra.Command {
   188  	opts := porter.RunListOptions{}
   189  
   190  	cmd := cobra.Command{
   191  		Use:   "list",
   192  		Short: "List runs of an Installation",
   193  		Long:  "List runs of an Installation",
   194  		Example: `  porter installations runs list [NAME] [--namespace NAMESPACE] [--output FORMAT]
   195  
   196    porter installations runs list myapp --namespace dev
   197  
   198  `,
   199  		PreRunE: func(cmd *cobra.Command, args []string) error {
   200  			return opts.Validate(args, p.Context)
   201  		},
   202  		RunE: func(cmd *cobra.Command, args []string) error {
   203  			return p.PrintInstallationRuns(cmd.Context(), opts)
   204  		},
   205  	}
   206  
   207  	f := cmd.Flags()
   208  	f.StringVarP(&opts.Namespace, "namespace", "n", "",
   209  		"Namespace in which the installation is defined. Defaults to the global namespace.")
   210  	f.StringVarP(&opts.RawFormat, "output", "o", "plaintext",
   211  		"Specify an output format.  Allowed values: plaintext, json, yaml")
   212  
   213  	return &cmd
   214  }
   215  
   216  func buildInstallationInstallCommand(p *porter.Porter) *cobra.Command {
   217  	opts := porter.NewInstallOptions()
   218  	cmd := &cobra.Command{
   219  		Use:   "install [INSTALLATION]",
   220  		Short: "Create a new installation of a bundle",
   221  		Long: `Create a new installation of a bundle.
   222  
   223  The first argument is the name of the installation to create. This defaults to the name of the bundle.
   224  
   225  Once a bundle has been successfully installed, the install action cannot be repeated. This is a precaution to avoid accidentally overwriting an existing installation. If you need to re-run install, which is common when authoring a bundle, you can use the --force flag to by-pass this check.
   226  
   227  Porter uses the docker driver as the default runtime for executing a bundle image, but an alternate driver may be supplied via '--driver/-d' or the PORTER_RUNTIME_DRIVER environment variable.
   228  For example, the 'debug' driver may be specified, which simply logs the info given to it and then exits.
   229  
   230  The docker driver runs the bundle container using the local Docker host. To use a remote Docker host, set the following environment variables:
   231    DOCKER_HOST (required)
   232    DOCKER_TLS_VERIFY (optional)
   233    DOCKER_CERT_PATH (optional)
   234  `,
   235  		Example: `  porter installation install
   236    porter installation install MyAppFromReference --reference ghcr.io/getporter/examples/kubernetes:v0.2.0 --namespace dev
   237    porter installation install --reference localhost:5000/ghcr.io/getporter/examples/kubernetes:v0.2.0 --insecure-registry --force
   238    porter installation install MyAppInDev --file myapp/bundle.json
   239    porter installation install --parameter-set azure --param test-mode=true --param header-color=blue
   240    porter installation install --credential-set azure --credential-set kubernetes
   241    porter installation install --driver debug
   242    porter installation install --label env=dev --label owner=myuser
   243  `,
   244  		PreRunE: func(cmd *cobra.Command, args []string) error {
   245  			return opts.Validate(cmd.Context(), args, p)
   246  		},
   247  		RunE: func(cmd *cobra.Command, args []string) error {
   248  			return p.InstallBundle(cmd.Context(), opts)
   249  		},
   250  	}
   251  
   252  	f := cmd.Flags()
   253  	addBundleDefinitionFlags(f, &opts.BundleDefinitionOptions)
   254  	f.StringVarP(&opts.Namespace, "namespace", "n", "",
   255  		"Create the installation in the specified namespace. Defaults to the global namespace.")
   256  	f.StringSliceVarP(&opts.Labels, "label", "l", nil,
   257  		"Associate the specified labels with the installation. May be specified multiple times.")
   258  	f.BoolVar(&opts.VerifyBundleBeforeExecution, "verify-bundle", false, "Verify the bundle signature before executing")
   259  	addBundleActionFlags(f, opts)
   260  
   261  	// Allow configuring the --driver flag with runtime-driver, to avoid conflicts with other commands
   262  	cmd.Flag("driver").Annotations = map[string][]string{
   263  		"viper-key": {"runtime-driver"},
   264  	}
   265  	return cmd
   266  }
   267  
   268  func buildInstallationUpgradeCommand(p *porter.Porter) *cobra.Command {
   269  	opts := porter.NewUpgradeOptions()
   270  	cmd := &cobra.Command{
   271  		Use:   "upgrade [INSTALLATION]",
   272  		Short: "Upgrade an installation",
   273  		Long: `Upgrade an installation.
   274  
   275  The first argument is the installation name to upgrade. This defaults to the name of the bundle.
   276  
   277  Porter uses the docker driver as the default runtime for executing a bundle image, but an alternate driver may be supplied via '--driver/-d' or the PORTER_RUNTIME_DRIVER environment variable.
   278  For example, the 'debug' driver may be specified, which simply logs the info given to it and then exits.
   279  
   280  The docker driver runs the bundle container using the local Docker host. To use a remote Docker host, set the following environment variables:
   281    DOCKER_HOST (required)
   282    DOCKER_TLS_VERIFY (optional)
   283    DOCKER_CERT_PATH (optional)
   284  `,
   285  		Example: `  porter installation upgrade --version 0.2.0
   286    porter installation upgrade --reference ghcr.io/getporter/examples/kubernetes:v0.2.0
   287    porter installation upgrade --reference localhost:5000/ghcr.io/getporter/examples/kubernetes:v0.2.0 --insecure-registry --force
   288    porter installation upgrade MyAppInDev --file myapp/bundle.json
   289    porter installation upgrade --parameter-set azure --param test-mode=true --param header-color=blue
   290    porter installation upgrade --credential-set azure --credential-set kubernetes
   291    porter installation upgrade --driver debug
   292  `,
   293  		PreRunE: func(cmd *cobra.Command, args []string) error {
   294  			return opts.Validate(cmd.Context(), args, p)
   295  		},
   296  		RunE: func(cmd *cobra.Command, args []string) error {
   297  			return p.UpgradeBundle(cmd.Context(), opts)
   298  		},
   299  	}
   300  
   301  	f := cmd.Flags()
   302  	addBundleDefinitionFlags(f, &opts.BundleDefinitionOptions)
   303  	f.StringVarP(&opts.Namespace, "namespace", "n", "",
   304  		"Namespace of the specified installation. Defaults to the global namespace.")
   305  	f.StringVar(&opts.Version, "version", "",
   306  		"Version to which the installation should be upgraded. This represents the version of the bundle, which assumes the convention of setting the bundle tag to its version.")
   307  	f.BoolVar(&opts.ForceUpgrade, "force-upgrade", false,
   308  		"Force the upgrade to run even if the current installation is marked as failed.")
   309  	addBundleActionFlags(f, opts)
   310  
   311  	// Allow configuring the --driver flag with runtime-driver, to avoid conflicts with other commands
   312  	cmd.Flag("driver").Annotations = map[string][]string{
   313  		"viper-key": {"runtime-driver"},
   314  	}
   315  	return cmd
   316  }
   317  
   318  func buildInstallationInvokeCommand(p *porter.Porter) *cobra.Command {
   319  	opts := porter.NewInvokeOptions()
   320  	cmd := &cobra.Command{
   321  		Use:   "invoke [INSTALLATION] --action ACTION",
   322  		Short: "Invoke a custom action on an installation",
   323  		Long: `Invoke a custom action on an installation.
   324  
   325  The first argument is the installation name upon which to invoke the action. This defaults to the name of the bundle.
   326  
   327  Porter uses the docker driver as the default runtime for executing a bundle image, but an alternate driver may be supplied via '--driver/-d' or the PORTER_RUNTIME_DRIVER environment variable.
   328  For example, the 'debug' driver may be specified, which simply logs the info given to it and then exits.
   329  
   330  The docker driver runs the bundle container using the local Docker host. To use a remote Docker host, set the following environment variables:
   331    DOCKER_HOST (required)
   332    DOCKER_TLS_VERIFY (optional)
   333    DOCKER_CERT_PATH (optional)
   334  `,
   335  		Example: `  porter installation invoke --action ACTION
   336    porter installation invoke --reference ghcr.io/getporter/examples/kubernetes:v0.2.0
   337    porter installation invoke --reference localhost:5000/ghcr.io/getporter/examples/kubernetes:v0.2.0 --insecure-registry --force
   338    porter installation invoke --action ACTION MyAppInDev --file myapp/bundle.json
   339    porter installation invoke --action ACTION  --parameter-set azure --param test-mode=true --param header-color=blue
   340    porter installation invoke --action ACTION --credential-set azure --credential-set kubernetes
   341    porter installation invoke --action ACTION --driver debug
   342  `,
   343  		PreRunE: func(cmd *cobra.Command, args []string) error {
   344  			return opts.Validate(cmd.Context(), args, p)
   345  		},
   346  		RunE: func(cmd *cobra.Command, args []string) error {
   347  			return p.InvokeBundle(cmd.Context(), opts)
   348  		},
   349  	}
   350  
   351  	f := cmd.Flags()
   352  	f.StringVar(&opts.Action, "action", "",
   353  		"Custom action name to invoke.")
   354  	f.StringVarP(&opts.Namespace, "namespace", "n", "",
   355  		"Namespace of the specified installation. Defaults to the global namespace.")
   356  	addBundleDefinitionFlags(f, &opts.BundleDefinitionOptions)
   357  	addBundleActionFlags(f, opts)
   358  
   359  	// Allow configuring the --driver flag with runtime-driver, to avoid conflicts with other commands
   360  	cmd.Flag("driver").Annotations = map[string][]string{
   361  		"viper-key": {"runtime-driver"},
   362  	}
   363  	return cmd
   364  }
   365  
   366  func buildInstallationUninstallCommand(p *porter.Porter) *cobra.Command {
   367  	opts := porter.NewUninstallOptions()
   368  	cmd := &cobra.Command{
   369  		Use:   "uninstall [INSTALLATION]",
   370  		Short: "Uninstall an installation",
   371  		Long: `Uninstall an installation
   372  
   373  The first argument is the installation name to uninstall. This defaults to the name of the bundle.
   374  
   375  Porter uses the docker driver as the default runtime for executing a bundle image, but an alternate driver may be supplied via '--driver/-d'' or the PORTER_RUNTIME_DRIVER environment variable.
   376  For example, the 'debug' driver may be specified, which simply logs the info given to it and then exits.
   377  
   378  The docker driver runs the bundle container using the local Docker host. To use a remote Docker host, set the following environment variables:
   379    DOCKER_HOST (required)
   380    DOCKER_TLS_VERIFY (optional)
   381    DOCKER_CERT_PATH (optional)
   382  `,
   383  		Example: `  porter installation uninstall
   384    porter installation uninstall --reference ghcr.io/getporter/examples/kubernetes:v0.2.0
   385    porter installation uninstall --reference localhost:5000/ghcr.io/getporter/examples/kubernetes:v0.2.0 --insecure-registry --force
   386    porter installation uninstall MyAppInDev --file myapp/bundle.json
   387    porter installation uninstall --parameter-set azure --param test-mode=true --param header-color=blue
   388    porter installation uninstall --credential-set azure --credential-set kubernetes
   389    porter installation uninstall --driver debug
   390    porter installation uninstall --delete
   391    porter installation uninstall --force-delete
   392  `,
   393  		PreRunE: func(cmd *cobra.Command, args []string) error {
   394  			return opts.Validate(cmd.Context(), args, p)
   395  		},
   396  		RunE: func(cmd *cobra.Command, args []string) error {
   397  			return p.UninstallBundle(cmd.Context(), opts)
   398  		},
   399  	}
   400  
   401  	f := cmd.Flags()
   402  	f.BoolVar(&opts.Delete, "delete", false,
   403  		"Delete all records associated with the installation, assuming the uninstall action succeeds")
   404  	f.BoolVar(&opts.ForceDelete, "force-delete", false,
   405  		"UNSAFE. Delete all records associated with the installation, even if uninstall fails. This is intended for cleaning up test data and is not recommended for production environments.")
   406  	f.StringVarP(&opts.Namespace, "namespace", "n", "",
   407  		"Namespace of the specified installation. Defaults to the global namespace.")
   408  	addBundleDefinitionFlags(f, &opts.BundleDefinitionOptions)
   409  	addBundleActionFlags(f, opts)
   410  
   411  	// Allow configuring the --driver flag with runtime-driver, to avoid conflicts with other commands
   412  	cmd.Flag("driver").Annotations = map[string][]string{
   413  		"viper-key": {"runtime-driver"},
   414  	}
   415  	return cmd
   416  }
   417  
   418  // Add flags for command that execute a bundle (install, upgrade, invoke and uninstall)
   419  func addBundleActionFlags(f *pflag.FlagSet, actionOpts porter.BundleAction) {
   420  	opts := actionOpts.GetOptions()
   421  	addBundlePullFlags(f, &opts.BundlePullOptions)
   422  	f.BoolVar(&opts.AllowDockerHostAccess, "allow-docker-host-access", false,
   423  		"Controls if the bundle should have access to the host's Docker daemon with elevated privileges. See https://porter.sh/configuration/#allow-docker-host-access for the full implications of this flag.")
   424  	f.StringArrayVar(&opts.HostVolumeMounts, "mount-host-volume", nil, "Mount a host volume into the bundle. Format is <host path>:<container path>[:<option>]. May be specified multiple times. Option can be ro (read-only), rw (read-write), default is ro.")
   425  	f.BoolVar(&opts.NoLogs, "no-logs", false,
   426  		"Do not persist the bundle execution logs")
   427  	f.StringArrayVarP(&opts.ParameterSets, "parameter-set", "p", nil,
   428  		"Parameter sets to use when running the bundle. It should be a named set of parameters and may be specified multiple times.")
   429  	f.StringArrayVar(&opts.Params, "param", nil,
   430  		"Define an individual parameter in the form NAME=VALUE. Overrides parameters otherwise set via --parameter-set. May be specified multiple times.")
   431  	f.StringArrayVarP(&opts.CredentialIdentifiers, "credential-set", "c", nil,
   432  		"Credential sets to use when running the bundle. It should be a named set of credentials and may be specified multiple times.")
   433  	f.StringVarP(&opts.Driver, "driver", "d", porter.DefaultDriver,
   434  		"Specify a driver to use. Allowed values: docker, debug")
   435  	f.BoolVar(&opts.DebugMode, "debug", false,
   436  		"Run the bundle in debug mode.")
   437  
   438  	// Gracefully support any renamed flags
   439  	f.StringArrayVar(&opts.CredentialIdentifiers, "cred", nil, "DEPRECATED")
   440  	_ = f.MarkDeprecated("cred", "please use credential-set instead.")
   441  }