Implement Service Broker with Spring Boot #cf_tokyo

48
Implement Service Broker with Spring Boot Toshiaki Maki (@making) Sr. Solutions Architect @Pivotal 20160601 Cloud Foundry Tokyo Meetup #2

Transcript of Implement Service Broker with Spring Boot #cf_tokyo

Implement  Service  Broker  with  Spring  Boot

Toshiaki  Maki  (@making)Sr.  Solutions  Architect  @Pivotal2016-‐‑‒06-‐‑‒01  Cloud  Foundry  Tokyo  Meetup #2

Who  am  I  ?•Toshiaki  Maki  (@making)•https://blog.ik.am•Sr.  Solutions  Architect•Spring  Framework  enthusiast

SpringFramework徹底⼊入⾨門(Coming  Soon?)

パーフェクトJava  EE(Coming  Soon?)

Today's  Topic•Service  Broker  Overview•Spring  Boot  Overview•Implement  Service  Broker

with  Spring  Boot

Service  Broker  Overview

Services  in  Cloud  FoundryApplication

Service  Broker

Service  Instance

User  Provided  Service

Managed  ServicesMySQL

RedisRabbitMQ ex.)  Oracle  DB

create-‐‑‒user-‐‑‒provided-‐‑‒servicecreate-‐‑‒service

bind-‐‑‒service

marketplace

Services  in  Cloud  FoundryApplication

Service  Broker

Service  Instance

User  Provided  Service

Managed  ServicesMySQL

RedisRabbitMQ ex.)  Oracle  DB

create-‐‑‒user-‐‑‒provided-‐‑‒servicecreate-‐‑‒service

bind-‐‑‒service

marketplace

👇

7  APIs  in  Service  Broker• GET  /v2/catalog• PUT  /v2/service_̲instances/:instance_̲id• PATCH  /v2/service_̲instances/:instance_̲id• DELETE  /v2/service_̲instances/:instance_̲id• PUT  /v2/service_̲instances/:instance_̲id/service_̲bindings/:binding_̲id• DELETE  /v2/service_̲instances/:instance_̲id/service_̲bindings/:binding_̲id• GET  /v2/service_̲instances/:instance_̲id/last_̲operation

API  Overview (create  service)

Cloud  Controller

Service

cf create-service PUT/v2/service_̲instances/:instance_̲id

Service  Broker

cf delete-service DELETE/v2/service_̲instances/:instance_̲id

API  Overview  (bind  service)

Cloud  Controller

Service

cf bind-service PUT/v2/service_̲instances/:instance_̲id

/service_̲bindings/:binding_̲id

Service  Broker

cf unbind-service DELETE/v2/service_̲instances/:instance_̲id

/service_̲bindings/:binding_̲id

Spring  Boot  Overview

Spring  Boot• Super  Easy  Framework  in  Java

start.spring.io

start.spring.io

start.spring.io

👈

@SpringBootApplication@RestControllerpublic class DemoApplication {

public static void main(String[] args) {SpringBootApplication.run(

DemoApplication.class, args);}@GetMapping("/")String hello() {

return "Hello World";}

}

@SpringBootApplication@RestControllerpublic class DemoApplication {

public static void main(String[] args) {SpringBootApplication.run(

DemoApplication.class, args);}@GetMapping("/")String hello() {

return "Hello World";}

}

@SpringBootApplication@RestControllerpublic class DemoApplication {

public static void main(String[] args) {SpringBootApplication.run(

DemoApplication.class, args);}@GetMapping("/")String hello() {

return "Hello World!";}

}

Implement  Service  Brokerwith  Spring  Boot

API  Overview

Cloud  Controller

Service

cf create-service PUT/v2/service_̲instances/:instance_̲id

Service  Broker

cf delete-service DELETE/v2/service_̲instances/:instance_̲id

Implement  APIs

@SpringBootApplication @RestControllerpublic class FakeServiceBroker {

// ...@GetMapping("/v2/catalog")CatalogResponse showCatalog() {/*...*/}

@PutMapping("/v2/service_instances/{instanceId}")CreateResponse createServiceInstance(

@PathVariable String instanceId, @RequestBody CreateRequest req) {/*...*/}

@PutMapping("/v2/service_instances/{instanceId}/service_bindings/{bindingId}")BindResponse createServiceBinding(

@PathVariable String instanceId ,@PathVariable String bindingId , @RequestBody BindRequest req) {/*...*/}

// ...}

@SpringBootApplication @RestControllerpublic class FakeServiceBroker {

// ...@GetMapping("/v2/catalog")CatalogResponse showCatalog() {/*...*/}

@PutMapping("/v2/service_instances/{instanceId}")CreateResponse createServiceInstance(

@PathVariable String instanceId, @RequestBody CreateRequest req) {/*...*/}

@PutMapping("/v2/service_instances/{instanceId}/service_bindings/{bindingId}")BindResponse createServiceBinding(

@PathVariable String instanceId ,@PathVariable String bindingId , @RequestBody BindRequest req) {/*...*/}

// ...}

A lot  ofparameters

Need  to  handle  Exceptions  ...

@SpringBootApplication @RestControllerpublic class FakeServiceBroker {

// ...@GetMapping("/v2/catalog")Map<String, Object> showCatalog() {/*...*/}

@PutMapping("/v2/service_instances/{instanceId}")Map<String, Object> createServiceInstance(

@PathVariable String instanceId, @RequestBody Map<String, Object> req) {/*...*/}

@PutMapping("/v2/service_instances/{instanceId}/service_bindings/{bindingId}")Map<String, Object> createServiceBinding(

@PathVariable String instanceId ,@PathVariable String bindingId , @RequestBody Map<String, Object> req) {/*...*/}

// ...}

There  is  a convenient  way

😎

Spring  Cloud  CloudFoundry Service  Broker

<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-cloudfoundry-

service-broker</artifactId><version>1.0.0.RC3</version>

</dependency>https://github.com/spring-­‐cloud/spring-­‐cloud-­‐cloudfoundry-­‐service-­‐broker

Service  Broker  API  Version: 2.8 (cf-‐‑‒release  v226+)

ServiceInstanceController

ServiceInstanceService

@PutMappingcreateServiceInstance

createServiceInstance

ServiceInstanceController

ServiceInstanceService

@PutMappingcreateServiceInstance

createServiceInstance

Provided You  implement

@Componentpublic class FakeServiceInstanceService

implements ServiceInstanceService {public CreateServiceInstanceResponse createServiceInstance(

CreateServiceInstanceRequest req) {String serviceInstanceId = req.getServiceInstanceId();// ...return new CreateServiceInstanceResponse();

}

public GetLastServiceOperationResponse getLastOperation(GetLastServiceOperationRequest req) {/* ... */}

public DeleteServiceInstanceResponse deleteServiceInstance(DeleteServiceInstanceRequest req) {/* ... */}

public UpdateServiceInstanceResponse updateServiceInstance(UpdateServiceInstanceRequest req) {/* ... */}}

@Componentpublic class FakeServiceInstanceService

implements ServiceInstanceService {public CreateServiceInstanceResponse createServiceInstance(

CreateServiceInstanceRequest req) {String serviceInstanceId = req.getServiceInstanceId();// ...return new CreateServiceInstanceResponse();

}

public GetLastServiceOperationResponse getLastOperation(GetLastServiceOperationRequest req) {/* ... */}

public DeleteServiceInstanceResponse deleteServiceInstance(DeleteServiceInstanceRequest req) {/* ... */}

public UpdateServiceInstanceResponse updateServiceInstance(UpdateServiceInstanceRequest req) {/* ... */}}

Corresponds  toPUT  /v2/service_̲instances/:instance_̲id

@Componentpublic class FakeServiceInstanceBindingService

implements ServiceInstanceBindingService {public CreateServiceInstanceBindingResponse createServiceInstanceBinding(

CreateServiceInstanceBindingRequest req) {String serviceInstanceId = req.getServiceInstanceId();String bindingId = req.getBindingId();// ...Map<String, Object> credentials = new HashMap<String, Object>() {{put("url", "...");put("username", "...");put("password", "...");

}};return new CreateServiceInstanceAppBindingResponse()

.withCredentials(credentials);}public void deleteServiceInstanceBinding(

DeleteServiceInstanceBindingRequest req) {// ...

}}

@Componentpublic class FakeServiceInstanceBindingService

implements ServiceInstanceBindingService {public CreateServiceInstanceBindingResponse createServiceInstanceBinding(

CreateServiceInstanceBindingRequest req) {String serviceInstanceId = req.getServiceInstanceId();String bindingId = req.getBindingId();// ...Map<String, Object> credentials = new HashMap<String, Object>() {{put("url", "...");put("username", "...");put("password", "...");

}};return new CreateServiceInstanceAppBindingResponse()

.withCredentials(credentials);}public void deleteServiceInstanceBinding(

DeleteServiceInstanceBindingRequest req) {// ...

}}

Corresponds  toPUT  /v2/service_̲instances/:instance_̲id

/service_̲bindings/:binding_̲id

@SpringBootApplicationpublic class FakeServiceBroker {

public static void main(String[] args) {SpringBootApplication.run(

FakeServiceBroker.class, args);}@BeanCatalog catalog() {

return new Catalog(singletonList(new ServiceDefinition(

"fake-broker","p-fake","A fake service broker", ...)));

}}

@SpringBootApplicationpublic class FakeServiceBroker {

public static void main(String[] args) {SpringBootApplication.run(

FakeServiceBroker.class, args);}@BeanCatalog catalog() {

return new Catalog(singletonList(new ServiceDefinition(

"fake-broker","p-fake","A fake service broker", ...)));

}}

Corresponds  to  GET  /v2/catalog

Authentication  Configuration

security.user.name=fakesecurity.user.password=fake

application.properties

https://github.com/making/fake-‐‑‒service-‐‑‒broker

Pivotal  Cloud  Foundry  for  Local  Developmenthttps://docs.pivotal.io/pcf-‐‑‒dev/

Deploy  Service  Brokerto  Cloud  Foundry

$ ./mvnw clean package$ cf push fake -p target/fake-1.0.0-SNAPSHOT.jar$ curl http://fake.local.pcfdev.io/v2/catalog

Enable  Service  Broker

$ cf create-service-broker p-fake fake fake ¥http://fake.local.pcfdev.io

$ cf enable-service-access p-fake

Service  Name Username Password

Enable  Service  Broker

$ cf create-service-broker p-fake fake fake ¥http://fake.cfapp.io

Enable  Service  Broker

$ cf create-service-broker p-fake fake fake ¥http://fake.cfapp.io

Server error, status code: 403, error code: 10003, message: You are not authorized to

perform the requested action😫

$ cf create-service-broker p-fake fake fake ¥http://fake.cfapps.io ¥--space-scoped

Enable  Service  Broker(Space  Scoped)

CF  CLI  6.16.0+

p-fake free A fake service broker

🙌

Create  &  Bind  Service

$ cf create-service p-fake free fake$ cf bind-service demo fake

References• https://github.com/spring-‐‑‒cloud/spring-‐‑‒cloud-‐‑‒cloudfoundry-‐‑‒service-‐‑‒broker• https://github.com/spring-‐‑‒cloud-‐‑‒samples/cloudfoundry-‐‑‒service-‐‑‒broker

• https://github.com/making/fake-‐‑‒service-‐‑‒broker• https://github.com/making/caffeine-‐‑‒broker

• https://github.com/pivotal-‐‑‒cf/brokerapi (similar  project  in  Golang)

Announcehttp://pivotal-‐‑‒japan.connpass.com

Pivotal  Japan  Technical  Meetup2016/06/29(Wed)  18:30-‐‑‒