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

     1  package service_test
     2  
     3  import (
     4  	"fmt"
     5  	"io/ioutil"
     6  	"os"
     7  
     8  	"github.com/cloudfoundry/cli/cf/actors/service_builder/fakes"
     9  	"github.com/cloudfoundry/cli/cf/configuration/core_config"
    10  	"github.com/cloudfoundry/cli/cf/errors"
    11  	"github.com/cloudfoundry/cli/cf/models"
    12  	"github.com/cloudfoundry/cli/generic"
    13  
    14  	testapi "github.com/cloudfoundry/cli/cf/api/fakes"
    15  	testcmd "github.com/cloudfoundry/cli/testhelpers/commands"
    16  	testconfig "github.com/cloudfoundry/cli/testhelpers/configuration"
    17  	testreq "github.com/cloudfoundry/cli/testhelpers/requirements"
    18  	testterm "github.com/cloudfoundry/cli/testhelpers/terminal"
    19  
    20  	"github.com/cloudfoundry/cli/cf/command_registry"
    21  
    22  	. "github.com/onsi/ginkgo"
    23  	. "github.com/onsi/gomega"
    24  
    25  	. "github.com/cloudfoundry/cli/testhelpers/matchers"
    26  )
    27  
    28  var _ = Describe("create-service command", func() {
    29  	var (
    30  		ui                  *testterm.FakeUI
    31  		config              core_config.Repository
    32  		requirementsFactory *testreq.FakeReqFactory
    33  		serviceRepo         *testapi.FakeServiceRepo
    34  		serviceBuilder      *fakes.FakeServiceBuilder
    35  
    36  		offering1 models.ServiceOffering
    37  		offering2 models.ServiceOffering
    38  		deps      command_registry.Dependency
    39  	)
    40  
    41  	updateCommandDependency := func(pluginCall bool) {
    42  		deps.Ui = ui
    43  		deps.Config = config
    44  		deps.RepoLocator = deps.RepoLocator.SetServiceRepository(serviceRepo)
    45  		deps.ServiceBuilder = serviceBuilder
    46  		command_registry.Commands.SetCommand(command_registry.Commands.FindCommand("create-service").SetDependency(deps, pluginCall))
    47  	}
    48  
    49  	BeforeEach(func() {
    50  		ui = &testterm.FakeUI{}
    51  		config = testconfig.NewRepositoryWithDefaults()
    52  		requirementsFactory = &testreq.FakeReqFactory{LoginSuccess: true, TargetedSpaceSuccess: true}
    53  		serviceRepo = &testapi.FakeServiceRepo{}
    54  		serviceBuilder = &fakes.FakeServiceBuilder{}
    55  
    56  		offering1 = models.ServiceOffering{}
    57  		offering1.Label = "cleardb"
    58  		offering1.Plans = []models.ServicePlanFields{{
    59  			Name: "spark",
    60  			Guid: "cleardb-spark-guid",
    61  			Free: true,
    62  		}, {
    63  			Name: "expensive",
    64  			Guid: "luxury-guid",
    65  			Free: false,
    66  		}}
    67  
    68  		offering2 = models.ServiceOffering{}
    69  		offering2.Label = "postgres"
    70  
    71  		serviceBuilder.GetServicesByNameForSpaceWithPlansReturns(models.ServiceOfferings([]models.ServiceOffering{offering1, offering2}), nil)
    72  	})
    73  
    74  	var callCreateService = func(args []string) bool {
    75  		return testcmd.RunCliCommand("create-service", args, requirementsFactory, updateCommandDependency, false)
    76  	}
    77  
    78  	Describe("requirements", func() {
    79  		It("passes when logged in and a space is targeted", func() {
    80  			Expect(callCreateService([]string{"cleardb", "spark", "my-cleardb-service"})).To(BeTrue())
    81  		})
    82  
    83  		It("fails when not logged in", func() {
    84  			requirementsFactory.LoginSuccess = false
    85  			Expect(callCreateService([]string{"cleardb", "spark", "my-cleardb-service"})).To(BeFalse())
    86  		})
    87  
    88  		It("fails when a space is not targeted", func() {
    89  			requirementsFactory.TargetedSpaceSuccess = false
    90  			Expect(callCreateService([]string{"cleardb", "spark", "my-cleardb-service"})).To(BeFalse())
    91  		})
    92  	})
    93  
    94  	It("successfully creates a service", func() {
    95  		callCreateService([]string{"cleardb", "spark", "my-cleardb-service"})
    96  
    97  		spaceGuid, serviceName := serviceBuilder.GetServicesByNameForSpaceWithPlansArgsForCall(0)
    98  		Expect(spaceGuid).To(Equal(config.SpaceFields().Guid))
    99  		Expect(serviceName).To(Equal("cleardb"))
   100  		Expect(ui.Outputs).To(ContainSubstrings(
   101  			[]string{"Creating service instance", "my-cleardb-service", "my-org", "my-space", "my-user"},
   102  			[]string{"OK"},
   103  		))
   104  		Expect(serviceRepo.CreateServiceInstanceArgs.Name).To(Equal("my-cleardb-service"))
   105  		Expect(serviceRepo.CreateServiceInstanceArgs.PlanGuid).To(Equal("cleardb-spark-guid"))
   106  	})
   107  
   108  	Context("when passing in tags", func() {
   109  		It("sucessfully creates a service and passes the tags as json", func() {
   110  			callCreateService([]string{"cleardb", "spark", "my-cleardb-service", "-t", "tag1, tag2,tag3,  tag4"})
   111  
   112  			Expect(ui.Outputs).To(ContainSubstrings(
   113  				[]string{"Creating service instance", "my-cleardb-service", "my-org", "my-space", "my-user"},
   114  				[]string{"OK"},
   115  			))
   116  			Expect(serviceRepo.CreateServiceInstanceArgs.Tags).To(ConsistOf("tag1", "tag2", "tag3", "tag4"))
   117  		})
   118  	})
   119  
   120  	Context("when passing arbitrary params", func() {
   121  		Context("as a json string", func() {
   122  			It("successfully creates a service and passes the params as a json string", func() {
   123  				callCreateService([]string{"cleardb", "spark", "my-cleardb-service", "-c", `{"foo": "bar"}`})
   124  
   125  				Expect(ui.Outputs).To(ContainSubstrings(
   126  					[]string{"Creating service instance", "my-cleardb-service", "my-org", "my-space", "my-user"},
   127  					[]string{"OK"},
   128  				))
   129  				Expect(serviceRepo.CreateServiceInstanceArgs.Params).To(Equal(map[string]interface{}{"foo": "bar"}))
   130  			})
   131  
   132  			Context("that are not valid json", func() {
   133  				It("returns an error to the UI", func() {
   134  					callCreateService([]string{"cleardb", "spark", "my-cleardb-service", "-c", `bad-json`})
   135  
   136  					Expect(ui.Outputs).To(ContainSubstrings(
   137  						[]string{"FAILED"},
   138  						[]string{"Invalid configuration provided for -c flag. Please provide a valid JSON object or path to a file containing a valid JSON object."},
   139  					))
   140  				})
   141  			})
   142  		})
   143  
   144  		Context("as a file that contains json", func() {
   145  			var jsonFile *os.File
   146  			var params string
   147  
   148  			BeforeEach(func() {
   149  				params = "{\"foo\": \"bar\"}"
   150  			})
   151  
   152  			AfterEach(func() {
   153  				if jsonFile != nil {
   154  					jsonFile.Close()
   155  					os.Remove(jsonFile.Name())
   156  				}
   157  			})
   158  
   159  			JustBeforeEach(func() {
   160  				var err error
   161  				jsonFile, err = ioutil.TempFile("", "")
   162  				Expect(err).ToNot(HaveOccurred())
   163  
   164  				err = ioutil.WriteFile(jsonFile.Name(), []byte(params), os.ModePerm)
   165  				Expect(err).NotTo(HaveOccurred())
   166  			})
   167  
   168  			It("successfully creates a service and passes the params as a json", func() {
   169  				callCreateService([]string{"cleardb", "spark", "my-cleardb-service", "-c", jsonFile.Name()})
   170  
   171  				Expect(ui.Outputs).To(ContainSubstrings(
   172  					[]string{"Creating service instance", "my-cleardb-service", "my-org", "my-space", "my-user"},
   173  					[]string{"OK"},
   174  				))
   175  				Expect(serviceRepo.CreateServiceInstanceArgs.Params).To(Equal(map[string]interface{}{"foo": "bar"}))
   176  			})
   177  
   178  			Context("that are not valid json", func() {
   179  				BeforeEach(func() {
   180  					params = "bad-json"
   181  				})
   182  
   183  				It("returns an error to the UI", func() {
   184  					callCreateService([]string{"cleardb", "spark", "my-cleardb-service", "-c", jsonFile.Name()})
   185  
   186  					Expect(ui.Outputs).To(ContainSubstrings(
   187  						[]string{"FAILED"},
   188  						[]string{"Invalid configuration provided for -c flag. Please provide a valid JSON object or path to a file containing a valid JSON object."},
   189  					))
   190  				})
   191  			})
   192  		})
   193  	})
   194  
   195  	Context("when service creation is asynchronous", func() {
   196  		var serviceInstance models.ServiceInstance
   197  
   198  		BeforeEach(func() {
   199  			serviceInstance = models.ServiceInstance{
   200  				ServiceInstanceFields: models.ServiceInstanceFields{
   201  					Name: "my-cleardb-service",
   202  					LastOperation: models.LastOperationFields{
   203  						Type:        "create",
   204  						State:       "in progress",
   205  						Description: "fake service instance description",
   206  					},
   207  				},
   208  			}
   209  			serviceRepo.FindInstanceByNameMap = generic.NewMap()
   210  			serviceRepo.FindInstanceByNameMap.Set("my-cleardb-service", serviceInstance)
   211  		})
   212  
   213  		It("successfully starts async service creation", func() {
   214  			callCreateService([]string{"cleardb", "spark", "my-cleardb-service"})
   215  
   216  			spaceGuid, serviceName := serviceBuilder.GetServicesByNameForSpaceWithPlansArgsForCall(0)
   217  			Expect(spaceGuid).To(Equal(config.SpaceFields().Guid))
   218  			Expect(serviceName).To(Equal("cleardb"))
   219  
   220  			creatingServiceMessage := fmt.Sprintf("Create in progress. Use 'cf services' or 'cf service %s' to check operation status.", serviceInstance.ServiceInstanceFields.Name)
   221  
   222  			Expect(ui.Outputs).To(ContainSubstrings(
   223  				[]string{"Creating service instance", "my-cleardb-service", "my-org", "my-space", "my-user"},
   224  				[]string{"OK"},
   225  				[]string{creatingServiceMessage},
   226  			))
   227  			Expect(serviceRepo.CreateServiceInstanceArgs.Name).To(Equal("my-cleardb-service"))
   228  			Expect(serviceRepo.CreateServiceInstanceArgs.PlanGuid).To(Equal("cleardb-spark-guid"))
   229  		})
   230  
   231  		It("fails when service instance could is created but cannot be found", func() {
   232  			serviceRepo.FindInstanceByNameErr = true
   233  			callCreateService([]string{"cleardb", "spark", "fake-service-instance-name"})
   234  
   235  			Expect(ui.Outputs).To(ContainSubstrings(
   236  				[]string{"Creating service instance fake-service-instance-name in org my-org / space my-space as my-user..."},
   237  				[]string{"FAILED"},
   238  				[]string{"Error finding instance"}))
   239  		})
   240  	})
   241  
   242  	Describe("warning the user about paid services", func() {
   243  		It("does not warn the user when the service is free", func() {
   244  			callCreateService([]string{"cleardb", "spark", "my-free-cleardb-service"})
   245  			Expect(ui.Outputs).To(ContainSubstrings(
   246  				[]string{"Creating service instance", "my-free-cleardb-service", "my-org", "my-space", "my-user"},
   247  				[]string{"OK"},
   248  			))
   249  			Expect(ui.Outputs).NotTo(ContainSubstrings([]string{"will incurr a cost"}))
   250  		})
   251  
   252  		It("warns the user when the service is not free", func() {
   253  			callCreateService([]string{"cleardb", "expensive", "my-expensive-cleardb-service"})
   254  			Expect(ui.Outputs).To(ContainSubstrings(
   255  				[]string{"Creating service instance", "my-expensive-cleardb-service", "my-org", "my-space", "my-user"},
   256  				[]string{"OK"},
   257  				[]string{"Attention: The plan `expensive` of service `cleardb` is not free.  The instance `my-expensive-cleardb-service` will incur a cost.  Contact your administrator if you think this is in error."},
   258  			))
   259  		})
   260  	})
   261  
   262  	It("warns the user when the service already exists with the same service plan", func() {
   263  		serviceRepo.CreateServiceInstanceReturns.Error = errors.NewModelAlreadyExistsError("Service", "my-cleardb-service")
   264  
   265  		callCreateService([]string{"cleardb", "spark", "my-cleardb-service"})
   266  
   267  		Expect(ui.Outputs).To(ContainSubstrings(
   268  			[]string{"Creating service instance", "my-cleardb-service"},
   269  			[]string{"OK"},
   270  			[]string{"my-cleardb-service", "already exists"},
   271  		))
   272  		Expect(serviceRepo.CreateServiceInstanceArgs.Name).To(Equal("my-cleardb-service"))
   273  		Expect(serviceRepo.CreateServiceInstanceArgs.PlanGuid).To(Equal("cleardb-spark-guid"))
   274  	})
   275  
   276  	Context("When there are multiple services with the same label", func() {
   277  		It("finds the plan even if it has to search multiple services", func() {
   278  			offering2.Label = "cleardb"
   279  
   280  			serviceRepo.CreateServiceInstanceReturns.Error = errors.NewModelAlreadyExistsError("Service", "my-cleardb-service")
   281  			callCreateService([]string{"cleardb", "spark", "my-cleardb-service"})
   282  
   283  			Expect(ui.Outputs).To(ContainSubstrings(
   284  				[]string{"Creating service instance", "my-cleardb-service", "my-org", "my-space", "my-user"},
   285  				[]string{"OK"},
   286  			))
   287  			Expect(serviceRepo.CreateServiceInstanceArgs.Name).To(Equal("my-cleardb-service"))
   288  			Expect(serviceRepo.CreateServiceInstanceArgs.PlanGuid).To(Equal("cleardb-spark-guid"))
   289  		})
   290  	})
   291  })