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 }