github.com/mook-as/cf-cli@v7.0.0-beta.28.0.20200120190804-b91c115fae48+incompatible/command/v6/update_user_provided_service_command.go (about)

     1  package v6
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"code.cloudfoundry.org/cli/actor/sharedaction"
     7  	"code.cloudfoundry.org/cli/actor/v2action"
     8  	"code.cloudfoundry.org/cli/command"
     9  	"code.cloudfoundry.org/cli/command/flag"
    10  	"code.cloudfoundry.org/cli/command/translatableerror"
    11  	"code.cloudfoundry.org/cli/command/v6/shared"
    12  )
    13  
    14  //go:generate counterfeiter . UpdateUserProvidedServiceActor
    15  
    16  type UpdateUserProvidedServiceActor interface {
    17  	GetServiceInstanceByNameAndSpace(name string, spaceGUID string) (v2action.ServiceInstance, v2action.Warnings, error)
    18  	UpdateUserProvidedServiceInstance(guid string, instance v2action.UserProvidedServiceInstance) (v2action.Warnings, error)
    19  }
    20  
    21  type UpdateUserProvidedServiceCommand struct {
    22  	RequiredArgs    flag.ServiceInstance   `positional-args:"yes"`
    23  	SyslogDrainURL  flag.OptionalString    `short:"l" description:"URL to which logs for bound applications will be streamed"`
    24  	Credentials     flag.CredentialsOrJSON `short:"p" description:"Credentials, provided inline or in a file, to be exposed in the VCAP_SERVICES environment variable for bound applications. Provided credentials will override existing credentials."`
    25  	RouteServiceURL flag.OptionalString    `short:"r" description:"URL to which requests for bound routes will be forwarded. Scheme for this URL must be https"`
    26  	Tags            flag.Tags              `short:"t" description:"User provided tags"`
    27  	usage           interface{}            `usage:"CF_NAME update-user-provided-service SERVICE_INSTANCE [-p CREDENTIALS] [-l SYSLOG_DRAIN_URL] [-r ROUTE_SERVICE_URL] [-t TAGS]\n\n   Pass comma separated credential parameter names to enable interactive mode:\n   CF_NAME update-user-provided-service SERVICE_INSTANCE -p \"comma, separated, parameter, names\"\n\n   Pass credential parameters as JSON to create a service non-interactively:\n   CF_NAME update-user-provided-service SERVICE_INSTANCE -p '{\"key1\":\"value1\",\"key2\":\"value2\"}'\n\n   Specify a path to a file containing JSON:\n   CF_NAME update-user-provided-service SERVICE_INSTANCE -p PATH_TO_FILE\n\nEXAMPLES:\n   CF_NAME update-user-provided-service my-db-mine -p '{\"username\":\"admin\", \"password\":\"pa55woRD\"}'\n   CF_NAME update-user-provided-service my-db-mine -p /path/to/credentials.json\n   CF_NAME create-user-provided-service my-db-mine -t \"list, of, tags\"\n   CF_NAME update-user-provided-service my-drain-service -l syslog://example.com\n   CF_NAME update-user-provided-service my-route-service -r https://example.com"`
    28  	relatedCommands interface{}            `related_commands:"rename-service, services, update-service"`
    29  
    30  	UI          command.UI
    31  	Config      command.Config
    32  	SharedActor command.SharedActor
    33  	Actor       UpdateUserProvidedServiceActor
    34  }
    35  
    36  func (cmd *UpdateUserProvidedServiceCommand) Setup(config command.Config, ui command.UI) error {
    37  	cmd.UI = ui
    38  	cmd.Config = config
    39  	cmd.SharedActor = sharedaction.NewActor(config)
    40  
    41  	ccClient, uaaClient, err := shared.GetNewClientsAndConnectToCF(config, ui)
    42  	if err != nil {
    43  		return err
    44  	}
    45  	cmd.Actor = v2action.NewActor(ccClient, uaaClient, config)
    46  
    47  	return nil
    48  }
    49  
    50  func (cmd *UpdateUserProvidedServiceCommand) Execute(args []string) error {
    51  	if len(args) > 0 {
    52  		return translatableerror.TooManyArgumentsError{
    53  			ExtraArgument: args[0],
    54  		}
    55  	}
    56  
    57  	if err := cmd.SharedActor.CheckTarget(true, true); err != nil {
    58  		return err
    59  	}
    60  
    61  	serviceInstance, err := cmd.findServiceInstance()
    62  	if err != nil {
    63  		return err
    64  	}
    65  
    66  	if ok := cmd.atLeastOneFlagProvided(); !ok {
    67  		return nil
    68  	}
    69  
    70  	if err := cmd.maybePromptUserForCredentials(); err != nil {
    71  		return err
    72  	}
    73  
    74  	if err := cmd.displayPreUpdateMessage(); err != nil {
    75  		return err
    76  	}
    77  
    78  	warnings, err := cmd.Actor.UpdateUserProvidedServiceInstance(serviceInstance.GUID, cmd.prepareUpdate())
    79  	cmd.UI.DisplayWarnings(warnings)
    80  	if err != nil {
    81  		return err
    82  	}
    83  
    84  	cmd.UI.DisplayOK()
    85  	cmd.UI.DisplayText("TIP: Use 'cf restage' for any bound apps to ensure your env variable changes take effect")
    86  
    87  	return nil
    88  }
    89  
    90  func (cmd *UpdateUserProvidedServiceCommand) findServiceInstance() (v2action.ServiceInstance, error) {
    91  	serviceInstance, warnings, err := cmd.Actor.GetServiceInstanceByNameAndSpace(cmd.RequiredArgs.ServiceInstance, cmd.Config.TargetedSpace().GUID)
    92  	cmd.UI.DisplayWarnings(warnings)
    93  	if err != nil {
    94  		return v2action.ServiceInstance{}, err
    95  	}
    96  
    97  	if !serviceInstance.IsUserProvided() {
    98  		return v2action.ServiceInstance{}, fmt.Errorf("The service instance '%s' is not user-provided", cmd.RequiredArgs.ServiceInstance)
    99  	}
   100  
   101  	return serviceInstance, nil
   102  }
   103  
   104  func (cmd *UpdateUserProvidedServiceCommand) displayPreUpdateMessage() error {
   105  	user, err := cmd.Config.CurrentUser()
   106  	if err != nil {
   107  		return err
   108  	}
   109  
   110  	cmd.UI.DisplayTextWithFlavor("Updating user provided service {{.ServiceInstance}} in org {{.Org}} / space {{.Space}} as {{.User}}...",
   111  		map[string]interface{}{
   112  			"ServiceInstance": cmd.RequiredArgs.ServiceInstance,
   113  			"Org":             cmd.Config.TargetedOrganization().Name,
   114  			"Space":           cmd.Config.TargetedSpace().Name,
   115  			"User":            user.Name,
   116  		})
   117  
   118  	return nil
   119  }
   120  
   121  func (cmd *UpdateUserProvidedServiceCommand) prepareUpdate() v2action.UserProvidedServiceInstance {
   122  	var instanceChanges v2action.UserProvidedServiceInstance
   123  	if cmd.Tags.IsSet {
   124  		instanceChanges = instanceChanges.WithTags(cmd.Tags.Value)
   125  	}
   126  	if cmd.RouteServiceURL.IsSet {
   127  		instanceChanges = instanceChanges.WithRouteServiceURL(cmd.RouteServiceURL.Value)
   128  	}
   129  	if cmd.SyslogDrainURL.IsSet {
   130  		instanceChanges = instanceChanges.WithSyslogDrainURL(cmd.SyslogDrainURL.Value)
   131  	}
   132  	if cmd.Credentials.IsSet {
   133  		instanceChanges = instanceChanges.WithCredentials(cmd.Credentials.Value)
   134  	}
   135  
   136  	return instanceChanges
   137  }
   138  
   139  func (cmd *UpdateUserProvidedServiceCommand) atLeastOneFlagProvided() bool {
   140  	if !cmd.SyslogDrainURL.IsSet && !cmd.RouteServiceURL.IsSet && !cmd.Tags.IsSet && !cmd.Credentials.IsSet {
   141  		cmd.UI.DisplayText("No flags specified. No changes were made.")
   142  		cmd.UI.DisplayOK()
   143  		return false
   144  	}
   145  
   146  	return true
   147  }
   148  
   149  func (cmd *UpdateUserProvidedServiceCommand) maybePromptUserForCredentials() error {
   150  	if len(cmd.Credentials.UserPromptCredentials) > 0 {
   151  		cmd.Credentials.Value = make(map[string]interface{})
   152  
   153  		for _, key := range cmd.Credentials.UserPromptCredentials {
   154  			var err error
   155  			cmd.Credentials.Value[key], err = cmd.UI.DisplayPasswordPrompt(key)
   156  			if err != nil {
   157  				return err
   158  			}
   159  		}
   160  	}
   161  
   162  	return nil
   163  }