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

     1  package service
     2  
     3  import (
     4  	"strings"
     5  
     6  	"github.com/cloudfoundry/cli/cf/actors/service_builder"
     7  	"github.com/cloudfoundry/cli/cf/api"
     8  	"github.com/cloudfoundry/cli/cf/command_registry"
     9  	"github.com/cloudfoundry/cli/cf/configuration/core_config"
    10  	"github.com/cloudfoundry/cli/cf/errors"
    11  	. "github.com/cloudfoundry/cli/cf/i18n"
    12  	"github.com/cloudfoundry/cli/cf/models"
    13  	"github.com/cloudfoundry/cli/cf/requirements"
    14  	"github.com/cloudfoundry/cli/cf/terminal"
    15  	"github.com/cloudfoundry/cli/cf/ui_helpers"
    16  	"github.com/cloudfoundry/cli/flags"
    17  	"github.com/cloudfoundry/cli/flags/flag"
    18  	"github.com/cloudfoundry/cli/json"
    19  )
    20  
    21  type CreateService struct {
    22  	ui             terminal.UI
    23  	config         core_config.Reader
    24  	serviceRepo    api.ServiceRepository
    25  	serviceBuilder service_builder.ServiceBuilder
    26  }
    27  
    28  func init() {
    29  	command_registry.Register(&CreateService{})
    30  }
    31  
    32  func (cmd *CreateService) MetaData() command_registry.CommandMetadata {
    33  	fs := make(map[string]flags.FlagSet)
    34  	fs["c"] = &cliFlags.StringFlag{Name: "c", Usage: T("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.")}
    35  	fs["t"] = &cliFlags.StringFlag{Name: "t", Usage: T("User provided tags")}
    36  
    37  	baseUsage := T("CF_NAME create-service SERVICE PLAN SERVICE_INSTANCE [-c PARAMETERS_AS_JSON] [-t TAGS]")
    38  	paramsUsage := T(`   Optionally provide service-specific configuration parameters in a valid JSON object in-line:
    39  
    40     CF_NAME create-service SERVICE PLAN SERVICE_INSTANCE -c '{"name":"value","name":"value"}'
    41  
    42     Optionally provide a file containing service-specific configuration parameters in a valid JSON object.
    43     The path to the parameters file can be an absolute or relative path to a file:
    44  
    45     CF_NAME create-service SERVICE_INSTANCE -c PATH_TO_FILE
    46  
    47     Example of valid JSON object:
    48     {
    49        "cluster_nodes": {
    50           "count": 5,
    51           "memory_mb": 1024
    52        }
    53     }`)
    54  	exampleUsage := T(`EXAMPLE:
    55     Linux/Mac:
    56        CF_NAME create-service db-service silver -c '{"ram_gb":4}'
    57  
    58     Windows Command Line:
    59        CF_NAME create-service db-service silver -c "{\"ram_gb\":4}"
    60  
    61     Windows PowerShell:
    62        CF_NAME create-service db-service silver -c '{\"ram_gb\":4}'
    63  
    64     CF_NAME create-service db-service silver mydb -c ~/workspace/tmp/instance_config.json
    65  
    66     CF_NAME create-service dbaas silver mydb -t "list, of, tags"`)
    67  	tipsUsage := T(`TIP:
    68     Use 'CF_NAME create-user-provided-service' to make user-provided services available to cf apps`)
    69  	return command_registry.CommandMetadata{
    70  		Name:        "create-service",
    71  		ShortName:   "cs",
    72  		Description: T("Create a service instance"),
    73  		Usage:       strings.Join([]string{baseUsage, paramsUsage, exampleUsage, tipsUsage}, "\n\n"),
    74  		Flags:       fs,
    75  	}
    76  }
    77  
    78  func (cmd *CreateService) Requirements(requirementsFactory requirements.Factory, fc flags.FlagContext) (reqs []requirements.Requirement, err error) {
    79  	if len(fc.Args()) != 3 {
    80  		cmd.ui.Failed(T("Incorrect Usage. Requires service, service plan, service instance as arguments\n\n") + command_registry.Commands.CommandUsage("create-service"))
    81  	}
    82  
    83  	reqs = []requirements.Requirement{
    84  		requirementsFactory.NewLoginRequirement(),
    85  		requirementsFactory.NewTargetedSpaceRequirement(),
    86  	}
    87  
    88  	return
    89  }
    90  
    91  func (cmd *CreateService) SetDependency(deps command_registry.Dependency, pluginCall bool) command_registry.Command {
    92  	cmd.ui = deps.Ui
    93  	cmd.config = deps.Config
    94  	cmd.serviceRepo = deps.RepoLocator.GetServiceRepository()
    95  	cmd.serviceBuilder = deps.ServiceBuilder
    96  	return cmd
    97  }
    98  
    99  func (cmd *CreateService) Execute(c flags.FlagContext) {
   100  	serviceName := c.Args()[0]
   101  	planName := c.Args()[1]
   102  	serviceInstanceName := c.Args()[2]
   103  	params := c.String("c")
   104  	tags := c.String("t")
   105  
   106  	tagsList := ui_helpers.ParseTags(tags)
   107  
   108  	paramsMap, err := json.ParseJsonFromFileOrString(params)
   109  	if err != nil {
   110  		cmd.ui.Failed(T("Invalid configuration provided for -c flag. Please provide a valid JSON object or path to a file containing a valid JSON object."))
   111  	}
   112  
   113  	cmd.ui.Say(T("Creating service instance {{.ServiceName}} in org {{.OrgName}} / space {{.SpaceName}} as {{.CurrentUser}}...",
   114  		map[string]interface{}{
   115  			"ServiceName": terminal.EntityNameColor(serviceInstanceName),
   116  			"OrgName":     terminal.EntityNameColor(cmd.config.OrganizationFields().Name),
   117  			"SpaceName":   terminal.EntityNameColor(cmd.config.SpaceFields().Name),
   118  			"CurrentUser": terminal.EntityNameColor(cmd.config.Username()),
   119  		}))
   120  
   121  	plan, err := cmd.CreateService(serviceName, planName, serviceInstanceName, paramsMap, tagsList)
   122  
   123  	switch err.(type) {
   124  	case nil:
   125  		err := printSuccessMessageForServiceInstance(serviceInstanceName, cmd.serviceRepo, cmd.ui)
   126  		if err != nil {
   127  			cmd.ui.Failed(err.Error())
   128  		}
   129  
   130  		if !plan.Free {
   131  			cmd.ui.Say("")
   132  			cmd.ui.Say(T("Attention: The plan `{{.PlanName}}` of service `{{.ServiceName}}` is not free.  The instance `{{.ServiceInstanceName}}` will incur a cost.  Contact your administrator if you think this is in error.",
   133  				map[string]interface{}{
   134  					"PlanName":            terminal.EntityNameColor(plan.Name),
   135  					"ServiceName":         terminal.EntityNameColor(serviceName),
   136  					"ServiceInstanceName": terminal.EntityNameColor(serviceInstanceName),
   137  				}))
   138  			cmd.ui.Say("")
   139  		}
   140  	case *errors.ModelAlreadyExistsError:
   141  		cmd.ui.Ok()
   142  		cmd.ui.Warn(err.Error())
   143  	default:
   144  		cmd.ui.Failed(err.Error())
   145  	}
   146  }
   147  
   148  func (cmd CreateService) CreateService(serviceName, planName, serviceInstanceName string, params map[string]interface{}, tags []string) (models.ServicePlanFields, error) {
   149  	offerings, apiErr := cmd.serviceBuilder.GetServicesByNameForSpaceWithPlans(cmd.config.SpaceFields().Guid, serviceName)
   150  	if apiErr != nil {
   151  		return models.ServicePlanFields{}, apiErr
   152  	}
   153  
   154  	plan, apiErr := findPlanFromOfferings(offerings, planName)
   155  	if apiErr != nil {
   156  		return plan, apiErr
   157  	}
   158  
   159  	apiErr = cmd.serviceRepo.CreateServiceInstance(serviceInstanceName, plan.Guid, params, tags)
   160  	return plan, apiErr
   161  }
   162  
   163  func findPlanFromOfferings(offerings models.ServiceOfferings, name string) (plan models.ServicePlanFields, err error) {
   164  	for _, offering := range offerings {
   165  		for _, plan := range offering.Plans {
   166  			if name == plan.Name {
   167  				return plan, nil
   168  			}
   169  		}
   170  	}
   171  
   172  	err = errors.New(T("Could not find plan with name {{.ServicePlanName}}",
   173  		map[string]interface{}{"ServicePlanName": name},
   174  	))
   175  	return
   176  }