github.com/rakutentech/cli@v6.12.5-0.20151006231303-24468b65536e+incompatible/cf/commands/service/migrate_service_instances.go (about)

     1  package service
     2  
     3  import (
     4  	"fmt"
     5  
     6  	. "github.com/cloudfoundry/cli/cf/i18n"
     7  	"github.com/cloudfoundry/cli/flags"
     8  	"github.com/cloudfoundry/cli/flags/flag"
     9  
    10  	"github.com/cloudfoundry/cli/cf/api"
    11  	"github.com/cloudfoundry/cli/cf/api/resources"
    12  	"github.com/cloudfoundry/cli/cf/command_registry"
    13  	"github.com/cloudfoundry/cli/cf/configuration/core_config"
    14  	"github.com/cloudfoundry/cli/cf/errors"
    15  	"github.com/cloudfoundry/cli/cf/requirements"
    16  	"github.com/cloudfoundry/cli/cf/terminal"
    17  )
    18  
    19  type MigrateServiceInstances struct {
    20  	ui          terminal.UI
    21  	configRepo  core_config.Reader
    22  	serviceRepo api.ServiceRepository
    23  }
    24  
    25  func init() {
    26  	command_registry.Register(&MigrateServiceInstances{})
    27  }
    28  
    29  func (cmd *MigrateServiceInstances) MetaData() command_registry.CommandMetadata {
    30  	fs := make(map[string]flags.FlagSet)
    31  	fs["f"] = &cliFlags.BoolFlag{Name: "f", Usage: T("Force migration without confirmation")}
    32  
    33  	return command_registry.CommandMetadata{
    34  		Name:        "migrate-service-instances",
    35  		Description: T("Migrate service instances from one service plan to another"),
    36  		Usage:       T("CF_NAME migrate-service-instances v1_SERVICE v1_PROVIDER v1_PLAN v2_SERVICE v2_PLAN\n\n") + migrateServiceInstanceWarning(),
    37  		Flags:       fs,
    38  	}
    39  }
    40  
    41  func (cmd *MigrateServiceInstances) Requirements(requirementsFactory requirements.Factory, fc flags.FlagContext) (reqs []requirements.Requirement, err error) {
    42  	if len(fc.Args()) != 5 {
    43  		cmd.ui.Failed(T("Incorrect Usage. Requires v1_SERVICE v1_PROVIDER v1_PLAN v2_SERVICE v2_PLAN as arguments\n\n") + command_registry.Commands.CommandUsage("migrate-service-instances"))
    44  	}
    45  
    46  	reqs = []requirements.Requirement{
    47  		requirementsFactory.NewLoginRequirement(),
    48  	}
    49  	return
    50  }
    51  
    52  func (cmd *MigrateServiceInstances) SetDependency(deps command_registry.Dependency, pluginCall bool) command_registry.Command {
    53  	cmd.ui = deps.Ui
    54  	cmd.configRepo = deps.Config
    55  	cmd.serviceRepo = deps.RepoLocator.GetServiceRepository()
    56  	return cmd
    57  }
    58  
    59  func migrateServiceInstanceWarning() string {
    60  	return T("WARNING: This operation is internal to Cloud Foundry; service brokers will not be contacted and resources for service instances will not be altered. The primary use case for this operation is to replace a service broker which implements the v1 Service Broker API with a broker which implements the v2 API by remapping service instances from v1 plans to v2 plans.  We recommend making the v1 plan private or shutting down the v1 broker to prevent additional instances from being created. Once service instances have been migrated, the v1 services and plans can be removed from Cloud Foundry.")
    61  }
    62  
    63  func (cmd *MigrateServiceInstances) Execute(c flags.FlagContext) {
    64  	v1 := resources.ServicePlanDescription{
    65  		ServiceLabel:    c.Args()[0],
    66  		ServiceProvider: c.Args()[1],
    67  		ServicePlanName: c.Args()[2],
    68  	}
    69  	v2 := resources.ServicePlanDescription{
    70  		ServiceLabel:    c.Args()[3],
    71  		ServicePlanName: c.Args()[4],
    72  	}
    73  	force := c.Bool("f")
    74  
    75  	v1Guid, apiErr := cmd.serviceRepo.FindServicePlanByDescription(v1)
    76  	switch apiErr.(type) {
    77  	case nil:
    78  	case *errors.ModelNotFoundError:
    79  		cmd.ui.Failed(T("Plan {{.ServicePlanName}} cannot be found",
    80  			map[string]interface{}{
    81  				"ServicePlanName": terminal.EntityNameColor(v1.String()),
    82  			}))
    83  		return
    84  	default:
    85  		cmd.ui.Failed(apiErr.Error())
    86  		return
    87  	}
    88  
    89  	v2Guid, apiErr := cmd.serviceRepo.FindServicePlanByDescription(v2)
    90  	switch apiErr.(type) {
    91  	case nil:
    92  	case *errors.ModelNotFoundError:
    93  		cmd.ui.Failed(T("Plan {{.ServicePlanName}} cannot be found",
    94  			map[string]interface{}{
    95  				"ServicePlanName": terminal.EntityNameColor(v2.String()),
    96  			}))
    97  		return
    98  	default:
    99  		cmd.ui.Failed(apiErr.Error())
   100  		return
   101  	}
   102  
   103  	count, apiErr := cmd.serviceRepo.GetServiceInstanceCountForServicePlan(v1Guid)
   104  	if apiErr != nil {
   105  		cmd.ui.Failed(apiErr.Error())
   106  		return
   107  	} else if count == 0 {
   108  		cmd.ui.Failed(T("Plan {{.ServicePlanName}} has no service instances to migrate", map[string]interface{}{"ServicePlanName": terminal.EntityNameColor(v1.String())}))
   109  		return
   110  	}
   111  
   112  	cmd.ui.Warn(migrateServiceInstanceWarning())
   113  
   114  	serviceInstancesPhrase := pluralizeServiceInstances(count)
   115  
   116  	if !force {
   117  		response := cmd.ui.Confirm(
   118  			T("Really migrate {{.ServiceInstanceDescription}} from plan {{.OldServicePlanName}} to {{.NewServicePlanName}}?>",
   119  				map[string]interface{}{
   120  					"ServiceInstanceDescription": serviceInstancesPhrase,
   121  					"OldServicePlanName":         terminal.EntityNameColor(v1.String()),
   122  					"NewServicePlanName":         terminal.EntityNameColor(v2.String()),
   123  				}))
   124  		if !response {
   125  			return
   126  		}
   127  	}
   128  
   129  	cmd.ui.Say(T("Attempting to migrate {{.ServiceInstanceDescription}}...", map[string]interface{}{"ServiceInstanceDescription": serviceInstancesPhrase}))
   130  
   131  	changedCount, apiErr := cmd.serviceRepo.MigrateServicePlanFromV1ToV2(v1Guid, v2Guid)
   132  	if apiErr != nil {
   133  		cmd.ui.Failed(apiErr.Error())
   134  	}
   135  
   136  	cmd.ui.Say(T("{{.CountOfServices}} migrated.", map[string]interface{}{"CountOfServices": pluralizeServiceInstances(changedCount)}))
   137  	cmd.ui.Ok()
   138  
   139  	return
   140  }
   141  
   142  func pluralizeServiceInstances(count int) string {
   143  	var phrase string
   144  	if count == 1 {
   145  		phrase = T("service instance")
   146  	} else {
   147  		phrase = T("service instances")
   148  	}
   149  
   150  	return fmt.Sprintf("%d %s", count, phrase)
   151  }