github.com/cloudfoundry/cli@v7.1.0+incompatible/cf/api/service_keys_test.go (about)

     1  package api_test
     2  
     3  import (
     4  	"net/http"
     5  	"time"
     6  
     7  	"code.cloudfoundry.org/cli/cf/terminal/terminalfakes"
     8  	testconfig "code.cloudfoundry.org/cli/cf/util/testhelpers/configuration"
     9  	testnet "code.cloudfoundry.org/cli/cf/util/testhelpers/net"
    10  	"github.com/onsi/gomega/ghttp"
    11  
    12  	"code.cloudfoundry.org/cli/cf/configuration/coreconfig"
    13  	"code.cloudfoundry.org/cli/cf/errors"
    14  	"code.cloudfoundry.org/cli/cf/models"
    15  	"code.cloudfoundry.org/cli/cf/net"
    16  
    17  	. "code.cloudfoundry.org/cli/cf/api"
    18  
    19  	"code.cloudfoundry.org/cli/cf/trace/tracefakes"
    20  	. "github.com/onsi/ginkgo"
    21  	. "github.com/onsi/gomega"
    22  )
    23  
    24  var _ = Describe("Service Keys Repo", func() {
    25  	var (
    26  		ccServer   *ghttp.Server
    27  		configRepo coreconfig.ReadWriter
    28  		repo       ServiceKeyRepository
    29  	)
    30  
    31  	BeforeEach(func() {
    32  		configRepo = testconfig.NewRepositoryWithDefaults()
    33  		configRepo.SetAccessToken("BEARER my_access_token")
    34  
    35  		ccServer = ghttp.NewServer()
    36  		configRepo.SetAPIEndpoint(ccServer.URL())
    37  
    38  		gateway := net.NewCloudControllerGateway(configRepo, time.Now, new(terminalfakes.FakeUI), new(tracefakes.FakePrinter), "")
    39  		repo = NewCloudControllerServiceKeyRepository(configRepo, gateway)
    40  	})
    41  
    42  	AfterEach(func() {
    43  		ccServer.Close()
    44  	})
    45  
    46  	Describe("CreateServiceKey", func() {
    47  		It("tries to create the service key", func() {
    48  			ccServer.AppendHandlers(
    49  				ghttp.CombineHandlers(
    50  					ghttp.VerifyRequest("POST", "/v2/service_keys"),
    51  					ghttp.RespondWith(http.StatusCreated, nil),
    52  					ghttp.VerifyJSON(`{"service_instance_guid": "fake-instance-guid", "name": "fake-key-name"}`),
    53  				),
    54  			)
    55  
    56  			err := repo.CreateServiceKey("fake-instance-guid", "fake-key-name", nil)
    57  			Expect(err).NotTo(HaveOccurred())
    58  			Expect(ccServer.ReceivedRequests()).To(HaveLen(1))
    59  		})
    60  
    61  		Context("when the service key exists", func() {
    62  			BeforeEach(func() {
    63  				ccServer.AppendHandlers(
    64  					ghttp.CombineHandlers(
    65  						ghttp.VerifyRequest("POST", "/v2/service_keys"),
    66  						ghttp.RespondWith(http.StatusBadRequest, `{"code":360001,"description":"The service key name is taken: exist-service-key"}`),
    67  					),
    68  				)
    69  			})
    70  
    71  			It("returns a ModelAlreadyExistsError", func() {
    72  				err := repo.CreateServiceKey("fake-instance-guid", "exist-service-key", nil)
    73  				Expect(err).To(BeAssignableToTypeOf(&errors.ModelAlreadyExistsError{}))
    74  			})
    75  		})
    76  
    77  		Context("when the CLI user is not a space developer or admin", func() {
    78  			BeforeEach(func() {
    79  				ccServer.AppendHandlers(
    80  					ghttp.CombineHandlers(
    81  						ghttp.VerifyRequest("POST", "/v2/service_keys"),
    82  						ghttp.RespondWith(http.StatusBadRequest, `{"code":10003,"description":"You are not authorized to perform the requested action"}`),
    83  					),
    84  				)
    85  			})
    86  
    87  			It("returns a NotAuthorizedError when CLI user is not the space developer or admin", func() {
    88  				err := repo.CreateServiceKey("fake-instance-guid", "fake-service-key", nil)
    89  				Expect(err).To(HaveOccurred())
    90  				Expect(err.Error()).To(ContainSubstring("You are not authorized to perform the requested action"))
    91  			})
    92  		})
    93  
    94  		Context("when there are parameters", func() {
    95  			BeforeEach(func() {
    96  				ccServer.AppendHandlers(
    97  					ghttp.CombineHandlers(
    98  						ghttp.VerifyRequest("POST", "/v2/service_keys"),
    99  						ghttp.RespondWith(http.StatusCreated, nil),
   100  						ghttp.VerifyJSON(`{"service_instance_guid":"fake-instance-guid","name":"fake-service-key","parameters": {"data": "hello"}}`),
   101  					),
   102  				)
   103  			})
   104  
   105  			It("includes any provided parameters", func() {
   106  				paramsMap := make(map[string]interface{})
   107  				paramsMap["data"] = "hello"
   108  
   109  				err := repo.CreateServiceKey("fake-instance-guid", "fake-service-key", paramsMap)
   110  				Expect(err).NotTo(HaveOccurred())
   111  				Expect(ccServer.ReceivedRequests()).To(HaveLen(1))
   112  			})
   113  
   114  			It("returns any serialization errors", func() {
   115  				paramsMap := make(map[string]interface{})
   116  				paramsMap["data"] = make(chan bool)
   117  
   118  				err := repo.CreateServiceKey("instance-name", "plan-guid", paramsMap)
   119  				Expect(err).To(MatchError("json: unsupported type: chan bool"))
   120  			})
   121  		})
   122  	})
   123  
   124  	Describe("ListServiceKeys", func() {
   125  		Context("when no service key is found", func() {
   126  			BeforeEach(func() {
   127  				ccServer.AppendHandlers(
   128  					ghttp.CombineHandlers(
   129  						ghttp.VerifyRequest("GET", "/v2/service_instances/fake-instance-guid/service_keys"),
   130  						ghttp.RespondWith(http.StatusOK, `{"resources": []}`),
   131  					),
   132  				)
   133  			})
   134  
   135  			It("returns an empty result", func() {
   136  				serviceKeys, err := repo.ListServiceKeys("fake-instance-guid")
   137  				Expect(ccServer.ReceivedRequests()).To(HaveLen(1))
   138  				Expect(err).NotTo(HaveOccurred())
   139  				Expect(serviceKeys).To(HaveLen(0))
   140  			})
   141  		})
   142  
   143  		Context("when service keys are found", func() {
   144  			BeforeEach(func() {
   145  				ccServer.AppendHandlers(
   146  					ghttp.CombineHandlers(
   147  						ghttp.VerifyRequest("GET", "/v2/service_instances/fake-instance-guid/service_keys"),
   148  						ghttp.RespondWith(http.StatusOK, serviceKeysResponse),
   149  					),
   150  				)
   151  			})
   152  
   153  			It("returns the service keys", func() {
   154  				serviceKeys, err := repo.ListServiceKeys("fake-instance-guid")
   155  				Expect(err).NotTo(HaveOccurred())
   156  				Expect(serviceKeys).To(HaveLen(2))
   157  
   158  				Expect(serviceKeys[0].Fields.GUID).To(Equal("fake-service-key-guid-1"))
   159  				Expect(serviceKeys[0].Fields.URL).To(Equal("/v2/service_keys/fake-guid-1"))
   160  				Expect(serviceKeys[0].Fields.Name).To(Equal("fake-service-key-name-1"))
   161  				Expect(serviceKeys[0].Fields.ServiceInstanceGUID).To(Equal("fake-service-instance-guid-1"))
   162  				Expect(serviceKeys[0].Fields.ServiceInstanceURL).To(Equal("http://fake/service/instance/url/1"))
   163  
   164  				Expect(serviceKeys[0].Credentials).To(HaveKeyWithValue("username", "fake-username-1"))
   165  				Expect(serviceKeys[0].Credentials).To(HaveKeyWithValue("password", "fake-password-1"))
   166  				Expect(serviceKeys[0].Credentials).To(HaveKeyWithValue("host", "fake-host-1"))
   167  				Expect(serviceKeys[0].Credentials).To(HaveKeyWithValue("port", float64(3306)))
   168  				Expect(serviceKeys[0].Credentials).To(HaveKeyWithValue("database", "fake-db-name-1"))
   169  				Expect(serviceKeys[0].Credentials).To(HaveKeyWithValue("uri", "mysql://fake-user-1:fake-password-1@fake-host-1:3306/fake-db-name-1"))
   170  
   171  				Expect(serviceKeys[1].Fields.GUID).To(Equal("fake-service-key-guid-2"))
   172  				Expect(serviceKeys[1].Fields.URL).To(Equal("/v2/service_keys/fake-guid-2"))
   173  				Expect(serviceKeys[1].Fields.Name).To(Equal("fake-service-key-name-2"))
   174  				Expect(serviceKeys[1].Fields.ServiceInstanceGUID).To(Equal("fake-service-instance-guid-2"))
   175  				Expect(serviceKeys[1].Fields.ServiceInstanceURL).To(Equal("http://fake/service/instance/url/1"))
   176  
   177  				Expect(serviceKeys[1].Credentials).To(HaveKeyWithValue("username", "fake-username-2"))
   178  				Expect(serviceKeys[1].Credentials).To(HaveKeyWithValue("password", "fake-password-2"))
   179  				Expect(serviceKeys[1].Credentials).To(HaveKeyWithValue("host", "fake-host-2"))
   180  				Expect(serviceKeys[1].Credentials).To(HaveKeyWithValue("port", float64(3306)))
   181  				Expect(serviceKeys[1].Credentials).To(HaveKeyWithValue("database", "fake-db-name-2"))
   182  				Expect(serviceKeys[1].Credentials).To(HaveKeyWithValue("uri", "mysql://fake-user-2:fake-password-2@fake-host-2:3306/fake-db-name-2"))
   183  			})
   184  		})
   185  
   186  		Context("when the server responds with 403", func() {
   187  			BeforeEach(func() {
   188  				ccServer.AppendHandlers(
   189  					ghttp.CombineHandlers(
   190  						ghttp.VerifyRequest("GET", "/v2/service_instances/fake-instance-guid/service_keys"),
   191  						ghttp.RespondWith(http.StatusForbidden, `{
   192  						"code": 10003,
   193  						"description": "You are not authorized to perform the requested action",
   194  						"error_code": "CF-NotAuthorized"
   195  					}`),
   196  					),
   197  				)
   198  			})
   199  
   200  			It("returns a NotAuthorizedError", func() {
   201  				_, err := repo.ListServiceKeys("fake-instance-guid")
   202  				Expect(err).To(BeAssignableToTypeOf(&errors.NotAuthorizedError{}))
   203  			})
   204  		})
   205  	})
   206  
   207  	Describe("GetServiceKey", func() {
   208  		Context("when the service key is found", func() {
   209  			BeforeEach(func() {
   210  				ccServer.AppendHandlers(
   211  					ghttp.CombineHandlers(
   212  						ghttp.VerifyRequest("GET", "/v2/service_instances/fake-instance-guid/service_keys", "q=name:fake-service-key-name"),
   213  						ghttp.RespondWith(http.StatusOK, serviceKeyDetailResponse),
   214  					),
   215  				)
   216  			})
   217  
   218  			It("returns service key detail", func() {
   219  				serviceKey, err := repo.GetServiceKey("fake-instance-guid", "fake-service-key-name")
   220  				Expect(err).NotTo(HaveOccurred())
   221  
   222  				Expect(serviceKey.Fields.GUID).To(Equal("fake-service-key-guid"))
   223  				Expect(serviceKey.Fields.URL).To(Equal("/v2/service_keys/fake-guid"))
   224  				Expect(serviceKey.Fields.Name).To(Equal("fake-service-key-name"))
   225  				Expect(serviceKey.Fields.ServiceInstanceGUID).To(Equal("fake-service-instance-guid"))
   226  				Expect(serviceKey.Fields.ServiceInstanceURL).To(Equal("http://fake/service/instance/url"))
   227  
   228  				Expect(serviceKey.Credentials).To(HaveKeyWithValue("username", "fake-username"))
   229  				Expect(serviceKey.Credentials).To(HaveKeyWithValue("password", "fake-password"))
   230  				Expect(serviceKey.Credentials).To(HaveKeyWithValue("host", "fake-host"))
   231  				Expect(serviceKey.Credentials).To(HaveKeyWithValue("port", float64(3306)))
   232  				Expect(serviceKey.Credentials).To(HaveKeyWithValue("database", "fake-db-name"))
   233  				Expect(serviceKey.Credentials).To(HaveKeyWithValue("uri", "mysql://fake-user:fake-password@fake-host:3306/fake-db-name"))
   234  			})
   235  		})
   236  
   237  		Context("when the service key is not found", func() {
   238  			BeforeEach(func() {
   239  				ccServer.AppendHandlers(
   240  					ghttp.CombineHandlers(
   241  						ghttp.VerifyRequest("GET", "/v2/service_instances/fake-instance-guid/service_keys", "q=name:non-exist-key-name"),
   242  						ghttp.RespondWith(http.StatusOK, `{"resources": []}`),
   243  					),
   244  				)
   245  			})
   246  
   247  			It("returns an empty service key", func() {
   248  				serviceKey, err := repo.GetServiceKey("fake-instance-guid", "non-exist-key-name")
   249  				Expect(err).NotTo(HaveOccurred())
   250  				Expect(serviceKey).To(Equal(models.ServiceKey{}))
   251  			})
   252  		})
   253  
   254  		Context("when the server responds with 403", func() {
   255  			BeforeEach(func() {
   256  				ccServer.AppendHandlers(
   257  					ghttp.CombineHandlers(
   258  						ghttp.VerifyRequest("GET", "/v2/service_instances/fake-instance-guid/service_keys", "q=name:fake-service-key-name"),
   259  						ghttp.RespondWith(http.StatusForbidden, `{
   260  						"code": 10003,
   261  						"description": "You are not authorized to perform the requested action",
   262  						"error_code": "CF-NotAuthorized"
   263  					}`),
   264  					),
   265  				)
   266  			})
   267  
   268  			It("returns a NotAuthorizedError", func() {
   269  				_, err := repo.GetServiceKey("fake-instance-guid", "fake-service-key-name")
   270  				Expect(err).To(BeAssignableToTypeOf(&errors.NotAuthorizedError{}))
   271  			})
   272  		})
   273  	})
   274  
   275  	Describe("DeleteServiceKey", func() {
   276  		It("deletes service key successfully", func() {
   277  			ccServer.AppendHandlers(
   278  				ghttp.VerifyRequest("DELETE", "/v2/service_keys/fake-service-key-guid"),
   279  				ghttp.RespondWith(http.StatusOK, nil),
   280  			)
   281  
   282  			err := repo.DeleteServiceKey("fake-service-key-guid")
   283  			Expect(err).NotTo(HaveOccurred())
   284  			Expect(ccServer.ReceivedRequests()).To(HaveLen(1))
   285  		})
   286  	})
   287  })
   288  
   289  var serviceKeysResponse = `{
   290  "resources": [
   291  	{
   292  			"metadata": {
   293  				"guid": "fake-service-key-guid-1",
   294  				"url": "/v2/service_keys/fake-guid-1",
   295  				"created_at": "2015-01-13T18:52:08+00:00",
   296  				"updated_at": null
   297  			},
   298  			"entity": {
   299  				"name": "fake-service-key-name-1",
   300  				"service_instance_guid":"fake-service-instance-guid-1",
   301  				"service_instance_url":"http://fake/service/instance/url/1",
   302  				"credentials": {
   303  					"username": "fake-username-1",
   304  					"password": "fake-password-1",
   305  					"host": "fake-host-1",
   306  					"port": 3306,
   307  					"database": "fake-db-name-1",
   308  					"uri": "mysql://fake-user-1:fake-password-1@fake-host-1:3306/fake-db-name-1"
   309  				}
   310  			}
   311  		},
   312  		{
   313  			"metadata": {
   314  				"guid": "fake-service-key-guid-2",
   315  				"url": "/v2/service_keys/fake-guid-2",
   316  				"created_at": "2015-01-13T18:52:08+00:00",
   317  				"updated_at": null
   318  			},
   319  			"entity": {
   320  				"name": "fake-service-key-name-2",
   321  				"service_instance_guid":"fake-service-instance-guid-2",
   322  				"service_instance_url":"http://fake/service/instance/url/1",
   323  				"credentials": {
   324  					"username": "fake-username-2",
   325  					"password": "fake-password-2",
   326  					"host": "fake-host-2",
   327  					"port": 3306,
   328  					"database": "fake-db-name-2",
   329  					"uri": "mysql://fake-user-2:fake-password-2@fake-host-2:3306/fake-db-name-2"
   330  				}
   331  			}
   332  		}
   333  ]}`
   334  
   335  var serviceKeyDetailResponse = `{
   336  "resources": [
   337  	{
   338  			"metadata": {
   339  				"guid": "fake-service-key-guid",
   340  				"url": "/v2/service_keys/fake-guid",
   341  				"created_at": "2015-01-13T18:52:08+00:00",
   342  				"updated_at": null
   343  			},
   344  			"entity": {
   345  				"name": "fake-service-key-name",
   346  				"service_instance_guid":"fake-service-instance-guid",
   347  				"service_instance_url":"http://fake/service/instance/url",
   348  				"credentials": {
   349  					"username": "fake-username",
   350  					"password": "fake-password",
   351  					"host": "fake-host",
   352  					"port": 3306,
   353  					"database": "fake-db-name",
   354  					"uri": "mysql://fake-user:fake-password@fake-host:3306/fake-db-name"
   355  				}
   356  			}
   357  	}]
   358  }`
   359  
   360  var notAuthorizedResponse = testnet.TestResponse{Status: http.StatusForbidden, Body: `{
   361  		"code": 10003,
   362  		"description": "You are not authorized to perform the requested action",
   363  		"error_code": "CF-NotAuthorized"
   364  	}`,
   365  }