github.com/orange-cloudfoundry/cli@v7.1.0+incompatible/command/v6/update_service_command.go (about)

     1  package v6
     2  
     3  import (
     4  	"code.cloudfoundry.org/cli/actor/actionerror"
     5  	"code.cloudfoundry.org/cli/actor/sharedaction"
     6  	"code.cloudfoundry.org/cli/actor/v2action"
     7  	"code.cloudfoundry.org/cli/actor/v2action/composite"
     8  	"code.cloudfoundry.org/cli/api/cloudcontroller/ccversion"
     9  	"code.cloudfoundry.org/cli/command"
    10  	"code.cloudfoundry.org/cli/command/flag"
    11  	"code.cloudfoundry.org/cli/command/translatableerror"
    12  	"code.cloudfoundry.org/cli/command/v6/shared"
    13  )
    14  
    15  //go:generate counterfeiter . UpdateServiceActor
    16  
    17  type UpdateServiceActor interface {
    18  	CloudControllerAPIVersion() string
    19  	GetServiceInstanceByNameAndSpace(name string, spaceGUID string) (v2action.ServiceInstance, v2action.Warnings, error)
    20  	UpgradeServiceInstance(serviceInstance v2action.ServiceInstance) (v2action.Warnings, error)
    21  }
    22  
    23  type textData map[string]interface{}
    24  
    25  type UpdateServiceCommand struct {
    26  	RequiredArgs     flag.ServiceInstance `positional-args:"yes"`
    27  	ParametersAsJSON flag.Path            `short:"c" description:"Valid JSON object containing service-specific configuration parameters, provided either in-line or in a file. For a list of supported configuration parameters, see documentation for the particular service offering."`
    28  	Plan             string               `short:"p" description:"Change service plan for a service instance"`
    29  	Tags             string               `short:"t" description:"User provided tags"`
    30  	usage            interface{}          `usage:"CF_NAME update-service SERVICE_INSTANCE [-p NEW_PLAN] [-c PARAMETERS_AS_JSON] [-t TAGS] [--upgrade]\n\n   Optionally provide service-specific configuration parameters in a valid JSON object in-line:\n   CF_NAME update-service SERVICE_INSTANCE -c '{\"name\":\"value\",\"name\":\"value\"}'\n\n   Optionally provide a file containing service-specific configuration parameters in a valid JSON object. \n   The path to the parameters file can be an absolute or relative path to a file:\n   CF_NAME update-service SERVICE_INSTANCE -c PATH_TO_FILE\n\n   Example of valid JSON object:\n   {\n      \"cluster_nodes\": {\n         \"count\": 5,\n         \"memory_mb\": 1024\n      }\n   }\n\n   Optionally provide a list of comma-delimited tags that will be written to the VCAP_SERVICES environment variable for any bound applications.\n\nEXAMPLES:\n   CF_NAME update-service mydb -p gold\n   CF_NAME update-service mydb -c '{\"ram_gb\":4}'\n   CF_NAME update-service mydb -c ~/workspace/tmp/instance_config.json\n   CF_NAME update-service mydb -t \"list, of, tags\"\n   CF_NAME update-service mydb --upgrade\n   CF_NAME update-service mydb --upgrade --force"`
    31  	relatedCommands  interface{}          `related_commands:"rename-service, services, update-user-provided-service"`
    32  	Upgrade          bool                 `short:"u" long:"upgrade" description:"Upgrade the service instance to the latest version of the service plan available. It cannot be combined with flags: -c, -p, -t."`
    33  	ForceUpgrade     bool                 `short:"f" long:"force" description:"Force the upgrade to the latest available version of the service plan. It can only be used with: -u, --upgrade."`
    34  
    35  	UI          command.UI
    36  	Actor       UpdateServiceActor
    37  	SharedActor command.SharedActor
    38  	Config      command.Config
    39  }
    40  
    41  func (cmd *UpdateServiceCommand) Setup(config command.Config, ui command.UI) error {
    42  	cmd.UI = ui
    43  	cmd.Config = config
    44  
    45  	cmd.SharedActor = sharedaction.NewActor(config)
    46  
    47  	ccClient, uaaClient, err := shared.GetNewClientsAndConnectToCF(config, ui)
    48  	if err != nil {
    49  		return err
    50  	}
    51  
    52  	baseActor := v2action.NewActor(ccClient, uaaClient, config)
    53  	cmd.Actor = &composite.UpdateServiceInstanceCompositeActor{
    54  		GetAPIVersionActor:                        baseActor,
    55  		GetServicePlanActor:                       baseActor,
    56  		GetServiceInstanceActor:                   baseActor,
    57  		UpdateServiceInstanceMaintenanceInfoActor: baseActor,
    58  	}
    59  
    60  	return nil
    61  }
    62  
    63  func (cmd *UpdateServiceCommand) Execute(args []string) error {
    64  
    65  	if !cmd.Upgrade {
    66  		return translatableerror.UnrefactoredCommandError{}
    67  	}
    68  
    69  	if len(args) > 0 {
    70  		return translatableerror.TooManyArgumentsError{
    71  			ExtraArgument: args[0],
    72  		}
    73  	}
    74  
    75  	if err := cmd.validateArgumentCombination(); err != nil {
    76  		return err
    77  	}
    78  
    79  	if err := command.MinimumCCAPIVersionCheck(cmd.Actor.CloudControllerAPIVersion(), ccversion.MinVersionUpdateServiceInstanceMaintenanceInfoV2, "Option '--upgrade'"); err != nil {
    80  		return err
    81  	}
    82  
    83  	if err := cmd.SharedActor.CheckTarget(true, true); err != nil {
    84  		return err
    85  	}
    86  
    87  	instance, warnings, err := cmd.Actor.GetServiceInstanceByNameAndSpace(cmd.RequiredArgs.ServiceInstance, cmd.Config.TargetedSpace().GUID)
    88  	cmd.UI.DisplayWarnings(warnings)
    89  	if err != nil {
    90  		return err
    91  	}
    92  
    93  	proceed, err := cmd.promptForUpgrade()
    94  	if err != nil {
    95  		return err
    96  	}
    97  
    98  	if !proceed {
    99  		cmd.UI.DisplayText("Update cancelled")
   100  		return nil
   101  	}
   102  
   103  	return cmd.performUpgrade(instance)
   104  }
   105  
   106  func (cmd *UpdateServiceCommand) promptForUpgrade() (bool, error) {
   107  	if cmd.ForceUpgrade {
   108  		return true, nil
   109  	}
   110  
   111  	var serviceName = textData{"ServiceName": cmd.RequiredArgs.ServiceInstance}
   112  
   113  	cmd.UI.DisplayTextWithFlavor("You are about to update {{.ServiceName}}.", serviceName)
   114  	cmd.UI.DisplayText("Warning: This operation may be long running and will block further operations on the service until complete.")
   115  
   116  	return cmd.UI.DisplayBoolPrompt(false, "Really update service {{.ServiceName}}?", serviceName)
   117  }
   118  
   119  func (cmd *UpdateServiceCommand) performUpgrade(instance v2action.ServiceInstance) error {
   120  	currentUserName, err := cmd.Config.CurrentUserName()
   121  	if err != nil {
   122  		return err
   123  	}
   124  
   125  	cmd.printUpdatingServiceInstanceMessage(instance.Name, currentUserName)
   126  
   127  	warnings, err := cmd.Actor.UpgradeServiceInstance(instance)
   128  	cmd.UI.DisplayWarnings(warnings)
   129  	if err != nil {
   130  		if castedErr, ok := err.(actionerror.ServiceUpgradeNotAvailableError); ok {
   131  			return decorateUpgradeNotAvailableErrorWithTip(castedErr, instance)
   132  		}
   133  		return err
   134  	}
   135  
   136  	cmd.UI.DisplayOK()
   137  	return nil
   138  }
   139  
   140  func decorateUpgradeNotAvailableErrorWithTip(castedErr actionerror.ServiceUpgradeNotAvailableError, instance v2action.ServiceInstance) error {
   141  	return translatableerror.TipDecoratorError{
   142  		BaseError: castedErr,
   143  		Tip:       "To find out if upgrade is available run `cf service {{.ServiceName}}`.",
   144  		TipKeys: map[string]interface{}{
   145  			"ServiceName": instance.Name,
   146  		},
   147  	}
   148  }
   149  
   150  func (cmd *UpdateServiceCommand) printUpdatingServiceInstanceMessage(serviceInstanceName, currentUserName string) {
   151  	cmd.UI.DisplayTextWithFlavor("Updating service instance {{.ServiceName}} as {{.UserName}}...",
   152  		map[string]interface{}{
   153  			"ServiceName": serviceInstanceName,
   154  			"UserName":    currentUserName,
   155  		})
   156  }
   157  
   158  func (cmd *UpdateServiceCommand) validateArgumentCombination() error {
   159  	if cmd.Tags != "" || cmd.ParametersAsJSON != "" || cmd.Plan != "" {
   160  		return translatableerror.ArgumentCombinationError{
   161  			Args: []string{"--upgrade", "-t", "-c", "-p"},
   162  		}
   163  	}
   164  
   165  	return nil
   166  }