5. 服务绑定

Service Broker 可以通过服务绑定向服务实例的使用者提供信息。 服务绑定通常用于向应用程序公开服务实例资源的凭据。spring-doc.cadn.net.cn

如果bindablefield 设置为true对于 Service Catalog 中的任何计划,Service Broker 必须提供ServiceInstanceBindingService接口。 否则,平台不会调用 Service Broker 的绑定方法,并且可以使用此接口的默认实现。 每个方法都接收一个 Java 对象参数,该参数包含来自平台的请求的所有详细信息,并返回一个 Java 对象值,该值向平台提供作的详细信息。spring-doc.cadn.net.cn

服务绑定的 create 和 delete作可以同步或异步执行。spring-doc.cadn.net.cn

  • 当 Service Broker 同步创建或删除服务绑定时,相应的接口方法应仅在作成功完成或发生故障时阻止并返回对平台的响应。spring-doc.cadn.net.cn

  • 异步执行作时,Service Broker 可以在作完成之前向平台返回响应,并在响应中指示作正在进行中。 当指示异步作时,平台会轮询 Service Broker 以获取作的状态。spring-doc.cadn.net.cn

5.1. 服务绑定创建

Service Broker 必须提供createServiceInstanceBinding()方法。spring-doc.cadn.net.cn

支持两种类型的绑定:spring-doc.cadn.net.cn

此方法的响应允许返回两种 Java 对象类型之一,以反映支持的两种类型的绑定。spring-doc.cadn.net.cn

Service Broker 可以为所有绑定请求生成一组凭据,也可以为每个绑定请求提供唯一凭据。spring-doc.cadn.net.cn

5.1.1. 事件注册中心

您可以使用事件进一步自定义服务绑定创建。 为此,请执行以下作:spring-doc.cadn.net.cn

  1. 自动装配CreateServiceInstanceBindingEventFlowRegistry豆。spring-doc.cadn.net.cn

  2. 使用addInitializationFlow(),addCompletionFlow()addErrorFlow()方法注册自定义反应流,以便在创建服务绑定的各个阶段运行。spring-doc.cadn.net.cn

5.2. 服务绑定删除

Service Broker 必须提供deleteServiceInstanceBinding()方法。spring-doc.cadn.net.cn

在 create作中预置的任何凭证都应由 delete作取消预置。spring-doc.cadn.net.cn

5.2.1. 事件注册表

您可以使用事件进一步自定义服务绑定删除。 为此,请执行以下作: .自动装配DeleteServiceInstanceBindingEventFlowRegistry豆。spring-doc.cadn.net.cn

  1. 使用addInitializationFlow(),addCompletionFlow()addErrorFlow()注册自定义反应流的方法,以便在删除服务绑定的各个阶段运行。spring-doc.cadn.net.cn

5.3. 服务绑定作状态检索

如果任何创建或删除作可以向平台返回异步“operation in progress”响应,则 Service Broker 必须提供getLastOperation()方法。否则,平台永远不会调用此方法,并且可以使用接口中的默认实现。spring-doc.cadn.net.cn

平台会轮询 Service Broker 的此方法,以查找正在进行异步作的服务实例,直到 Service Broker 指示作已成功完成或发生故障。spring-doc.cadn.net.cn

5.3.1. 事件注册中心

您可以使用事件进一步自定义服务绑定上次作请求。 为此,请执行以下作: .自动装配AsyncOperationServiceInstanceBindingEventFlowRegistry豆。spring-doc.cadn.net.cn

  1. 使用addInitializationFlow(),addCompletionFlow()addErrorFlow()方法注册自定义反应流,以便在上次作检索的各个阶段运行。spring-doc.cadn.net.cn

5.4. 服务绑定检索

如果bindings_retrievablefield 设置为true在服务目录中,服务目录必须提供getServiceInstanceBinding()方法。 否则,平台永远不会调用此方法,并且可以使用接口中的默认实现。spring-doc.cadn.net.cn

Service Broker 负责维护支持检索作所需的任何服务绑定状态。spring-doc.cadn.net.cn

5.5. 示例实现

以下示例实现服务绑定:spring-doc.cadn.net.cn

package com.example.servicebroker;

import reactor.core.publisher.Mono;

import org.springframework.cloud.servicebroker.model.binding.CreateServiceInstanceAppBindingResponse;
import org.springframework.cloud.servicebroker.model.binding.CreateServiceInstanceBindingRequest;
import org.springframework.cloud.servicebroker.model.binding.CreateServiceInstanceBindingResponse;
import org.springframework.cloud.servicebroker.model.binding.DeleteServiceInstanceBindingRequest;
import org.springframework.cloud.servicebroker.model.binding.DeleteServiceInstanceBindingResponse;
import org.springframework.cloud.servicebroker.model.binding.GetServiceInstanceAppBindingResponse;
import org.springframework.cloud.servicebroker.model.binding.GetServiceInstanceBindingRequest;
import org.springframework.cloud.servicebroker.model.binding.GetServiceInstanceBindingResponse;
import org.springframework.cloud.servicebroker.service.ServiceInstanceBindingService;
import org.springframework.stereotype.Service;

@Service
public class ExampleServiceBindingService implements ServiceInstanceBindingService {

	@Override
	public Mono<CreateServiceInstanceBindingResponse> createServiceInstanceBinding(CreateServiceInstanceBindingRequest request) {
		String serviceInstanceId = request.getServiceInstanceId();
		String bindingId = request.getBindingId();

		//
		// create credentials and store for later retrieval
		//

		String url = new String(/* build a URL to access the service instance */);
		String bindingUsername = new String(/* create a user */);
		String bindingPassword = new String(/* create a password */);

		CreateServiceInstanceBindingResponse response = CreateServiceInstanceAppBindingResponse.builder()
				.credentials("url", url)
				.credentials("username", bindingUsername)
				.credentials("password", bindingPassword)
				.bindingExisted(false)
				.async(true)
				.build();

		return Mono.just(response);
	}

	@Override
	public Mono<DeleteServiceInstanceBindingResponse> deleteServiceInstanceBinding(DeleteServiceInstanceBindingRequest request) {
		String serviceInstanceId = request.getServiceInstanceId();
		String bindingId = request.getBindingId();

		//
		// delete any binding-specific credentials
		//

		return Mono.just(DeleteServiceInstanceBindingResponse.builder()
				.async(true)
				.build());
	}

	@Override
	public Mono<GetServiceInstanceBindingResponse> getServiceInstanceBinding(GetServiceInstanceBindingRequest request) {
		String serviceInstanceId = request.getServiceInstanceId();
		String bindingId = request.getBindingId();

		//
		// retrieve the details of the specified service binding
		//

		String url = new String(/* retrieved URL */);
		String bindingUsername = new String(/* retrieved user */);
		String bindingPassword = new String(/* retrieved password */);

		GetServiceInstanceBindingResponse response = GetServiceInstanceAppBindingResponse.builder()
				.credentials("username", bindingUsername)
				.credentials("password", bindingPassword)
				.credentials("url", url)
				.build();

		return Mono.just(response);
	}
}

5.6. Example Event Flow Configuration

There are multiple ways to configure service binding event flows. One option is to autowire one or more registries and interact with the registry directly. Another option is to define beans for specific flows. These beans are automatically identified and added to the appropriate registry. A final option is to declare a new registry bean. However, be aware that defining a new registry bean overrides the provided auto-configuration.spring-doc.cadn.net.cn

5.6.1. Option 1: Autowire Registries

The following example configures service binding event flows:spring-doc.cadn.net.cn

package com.example.servicebroker;

import reactor.core.publisher.Mono;

import org.springframework.cloud.servicebroker.model.binding.CreateServiceInstanceBindingRequest;
import org.springframework.cloud.servicebroker.model.binding.CreateServiceInstanceBindingResponse;
import org.springframework.cloud.servicebroker.model.binding.DeleteServiceInstanceBindingRequest;
import org.springframework.cloud.servicebroker.model.binding.DeleteServiceInstanceBindingResponse;
import org.springframework.cloud.servicebroker.model.binding.GetLastServiceBindingOperationRequest;
import org.springframework.cloud.servicebroker.model.binding.GetLastServiceBindingOperationResponse;
import org.springframework.cloud.servicebroker.service.events.AsyncOperationServiceInstanceBindingEventFlowRegistry;
import org.springframework.cloud.servicebroker.service.events.CreateServiceInstanceBindingEventFlowRegistry;
import org.springframework.cloud.servicebroker.service.events.DeleteServiceInstanceBindingEventFlowRegistry;
import org.springframework.cloud.servicebroker.service.events.flows.AsyncOperationServiceInstanceBindingCompletionFlow;
import org.springframework.cloud.servicebroker.service.events.flows.AsyncOperationServiceInstanceBindingErrorFlow;
import org.springframework.cloud.servicebroker.service.events.flows.AsyncOperationServiceInstanceBindingInitializationFlow;
import org.springframework.cloud.servicebroker.service.events.flows.CreateServiceInstanceBindingCompletionFlow;
import org.springframework.cloud.servicebroker.service.events.flows.CreateServiceInstanceBindingErrorFlow;
import org.springframework.cloud.servicebroker.service.events.flows.CreateServiceInstanceBindingInitializationFlow;
import org.springframework.cloud.servicebroker.service.events.flows.DeleteServiceInstanceBindingCompletionFlow;
import org.springframework.cloud.servicebroker.service.events.flows.DeleteServiceInstanceBindingErrorFlow;
import org.springframework.cloud.servicebroker.service.events.flows.DeleteServiceInstanceBindingInitializationFlow;
import org.springframework.context.annotation.Configuration;

@Configuration
public class ExampleServiceBindingEventFlowsConfiguration {

	private final CreateServiceInstanceBindingEventFlowRegistry createRegistry;

	private final DeleteServiceInstanceBindingEventFlowRegistry deleteRegistry;

	private final AsyncOperationServiceInstanceBindingEventFlowRegistry asyncRegistry;

	public ExampleServiceBindingEventFlowsConfiguration(
			CreateServiceInstanceBindingEventFlowRegistry createRegistry,
			DeleteServiceInstanceBindingEventFlowRegistry deleteRegistry,
			AsyncOperationServiceInstanceBindingEventFlowRegistry asyncRegistry) {
		this.createRegistry = createRegistry;
		this.deleteRegistry = deleteRegistry;
		this.asyncRegistry = asyncRegistry;

		prepareCreateEventFlows()
				.then(prepareDeleteEventFlows())
				.then(prepareLastOperationEventFlows())
				.subscribe();
	}

	private Mono<Void> prepareCreateEventFlows() {
		return Mono.just(createRegistry)
				.map(registry -> registry.addInitializationFlow(new CreateServiceInstanceBindingInitializationFlow() {
					@Override
					public Mono<Void> initialize(CreateServiceInstanceBindingRequest request) {
						//
						// do something before the instance is created
						//
						return Mono.empty();
					}
				})
						.then(registry.addCompletionFlow(new CreateServiceInstanceBindingCompletionFlow() {
							@Override
							public Mono<Void> complete(CreateServiceInstanceBindingRequest request,
													   CreateServiceInstanceBindingResponse response) {
								//
								// do something after the instance is created
								//
								return Mono.empty();
							}
						}))
						.then(registry.addErrorFlow(new CreateServiceInstanceBindingErrorFlow() {
							@Override
							public Mono<Void> error(CreateServiceInstanceBindingRequest request, Throwable t) {
								//
								// do something if an error occurs while creating an instance
								//
								return Mono.empty();
							}
						})))
				.then();
	}

	private Mono<Void> prepareDeleteEventFlows() {
		return Mono.just(deleteRegistry)
				.map(registry -> registry.addInitializationFlow(new DeleteServiceInstanceBindingInitializationFlow() {
					@Override
					public Mono<Void> initialize(DeleteServiceInstanceBindingRequest request) {
						//
						// do something before the instance is deleted
						//
						return Mono.empty();
					}
				})
						.then(registry.addCompletionFlow(new DeleteServiceInstanceBindingCompletionFlow() {
							@Override
							public Mono<Void> complete(DeleteServiceInstanceBindingRequest request,
													   DeleteServiceInstanceBindingResponse response) {
								//
								// do something after the instance is deleted
								//
								return Mono.empty();
							}
						}))
						.then(registry.addErrorFlow(new DeleteServiceInstanceBindingErrorFlow() {
							@Override
							public Mono<Void> error(DeleteServiceInstanceBindingRequest request, Throwable t) {
								//
								// do something if an error occurs while deleting an instance
								//
								return Mono.empty();
							}
						})))
				.then();
	}

	private Mono<Void> prepareLastOperationEventFlows() {
		return Mono.just(asyncRegistry)
				.map(registry -> registry.addInitializationFlow(new AsyncOperationServiceInstanceBindingInitializationFlow() {
					@Override
					public Mono<Void> initialize(GetLastServiceBindingOperationRequest request) {
						//
						// do something before the instance is deleted
						//
						return Mono.empty();
					}
				})
						.then(registry.addCompletionFlow(new AsyncOperationServiceInstanceBindingCompletionFlow() {
							@Override
							public Mono<Void> complete(GetLastServiceBindingOperationRequest request,
									GetLastServiceBindingOperationResponse response) {
								//
								// do something after the instance is deleted
								//
								return Mono.empty();
							}
						}))
						.then(registry.addErrorFlow(new AsyncOperationServiceInstanceBindingErrorFlow() {
							public Mono<Void> error(GetLastServiceBindingOperationRequest request, Throwable t) {
								//
								// do something if an error occurs while deleting an instance
								//
								return Mono.empty();
							}
						})))
				.then();
	}

}

5.6.2. Option 2: Event Flow Beans

Optionally, you can configure beans for the individual flows, as follows:spring-doc.cadn.net.cn

package com.example.servicebroker;

import reactor.core.publisher.Mono;

import org.springframework.cloud.servicebroker.model.binding.CreateServiceInstanceBindingRequest;
import org.springframework.cloud.servicebroker.model.binding.CreateServiceInstanceBindingResponse;
import org.springframework.cloud.servicebroker.model.binding.DeleteServiceInstanceBindingRequest;
import org.springframework.cloud.servicebroker.model.binding.DeleteServiceInstanceBindingResponse;
import org.springframework.cloud.servicebroker.model.binding.GetLastServiceBindingOperationRequest;
import org.springframework.cloud.servicebroker.model.binding.GetLastServiceBindingOperationResponse;
import org.springframework.cloud.servicebroker.service.events.flows.AsyncOperationServiceInstanceBindingCompletionFlow;
import org.springframework.cloud.servicebroker.service.events.flows.AsyncOperationServiceInstanceBindingErrorFlow;
import org.springframework.cloud.servicebroker.service.events.flows.AsyncOperationServiceInstanceBindingInitializationFlow;
import org.springframework.cloud.servicebroker.service.events.flows.CreateServiceInstanceBindingCompletionFlow;
import org.springframework.cloud.servicebroker.service.events.flows.CreateServiceInstanceBindingErrorFlow;
import org.springframework.cloud.servicebroker.service.events.flows.CreateServiceInstanceBindingInitializationFlow;
import org.springframework.cloud.servicebroker.service.events.flows.DeleteServiceInstanceBindingCompletionFlow;
import org.springframework.cloud.servicebroker.service.events.flows.DeleteServiceInstanceBindingErrorFlow;
import org.springframework.cloud.servicebroker.service.events.flows.DeleteServiceInstanceBindingInitializationFlow;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class ExampleServiceBindingEventFlowsConfiguration2 {

	//
	// Create Service Instance Binding flows
	//

	@Bean
	public CreateServiceInstanceBindingInitializationFlow createServiceInstanceBindingInitializationFlow() {
		return new CreateServiceInstanceBindingInitializationFlow() {
			@Override
			public Mono<Void> initialize(CreateServiceInstanceBindingRequest request) {
				//
				// do something before the service instance binding completes
				//
				return Mono.empty();
			}
		};
	}

	@Bean
	public CreateServiceInstanceBindingCompletionFlow createServiceInstanceBindingCompletionFlow() {
		return new CreateServiceInstanceBindingCompletionFlow() {
			@Override
			public Mono<Void> complete(CreateServiceInstanceBindingRequest request,
					CreateServiceInstanceBindingResponse response) {
				//
				// do something after the service instance binding completes
				//
				return Mono.empty();
			}
		};
	}

	@Bean
	public CreateServiceInstanceBindingErrorFlow createServiceInstanceBindingErrorFlow() {
		return new CreateServiceInstanceBindingErrorFlow() {
			@Override
			public Mono<Void> error(CreateServiceInstanceBindingRequest request, Throwable t) {
				//
				// do something if an error occurs while creating a service instance binding
				//
				return Mono.empty();
			}
		};
	}

	//
	// Delete Service Instance Binding flows
	//

	@Bean
	public DeleteServiceInstanceBindingInitializationFlow deleteServiceInstanceBindingInitializationFlow() {
		return new DeleteServiceInstanceBindingInitializationFlow() {
			@Override
			public Mono<Void> initialize(DeleteServiceInstanceBindingRequest request) {
				//
				// do something before the service instance binding is deleted
				//
				return Mono.empty();
			}
		};
	}

	@Bean
	public DeleteServiceInstanceBindingCompletionFlow deleteServiceInstanceBindingCompletionFlow() {
		return new DeleteServiceInstanceBindingCompletionFlow() {
			@Override
			public Mono<Void> complete(DeleteServiceInstanceBindingRequest request,
					DeleteServiceInstanceBindingResponse response) {
				//
				// do something after the service instance binding is deleted
				//
				return Mono.empty();
			}
		};
	}

	@Bean
	public DeleteServiceInstanceBindingErrorFlow deleteServiceInstanceBindingErrorFlow() {
		return new DeleteServiceInstanceBindingErrorFlow() {
			@Override
			public Mono<Void> error(DeleteServiceInstanceBindingRequest request, Throwable t) {
				//
				// do something if an error occurs while deleting a service instance binding
				//
				return Mono.empty();
			}
		};
	}

	//
	// Get Last Service Instance Binding Operation flows
	//

	@Bean
	public AsyncOperationServiceInstanceBindingInitializationFlow getLastOperationServiceInstanceBindingInitializationFlow() {
		return new AsyncOperationServiceInstanceBindingInitializationFlow() {
			@Override
			public Mono<Void> initialize(GetLastServiceBindingOperationRequest request) {
				//
				// do something before getting the last operation
				//
				return Mono.empty();
			}
		};
	}

	@Bean
	public AsyncOperationServiceInstanceBindingCompletionFlow getLastOperationServiceInstanceBindingCompletionFlow() {
		return new AsyncOperationServiceInstanceBindingCompletionFlow() {
			@Override
			public Mono<Void> complete(GetLastServiceBindingOperationRequest request,
					GetLastServiceBindingOperationResponse response) {
				//
				// do something after getting the last operation
				//
				return Mono.empty();
			}
		};
	}

	@Bean
	public AsyncOperationServiceInstanceBindingErrorFlow getLastOperationServiceInstanceBindingErrorFlow() {
		return new AsyncOperationServiceInstanceBindingErrorFlow() {
			@Override
			public Mono<Void> error(GetLastServiceBindingOperationRequest request, Throwable t) {
				//
				// do something if an error occurs while getting the last operation
				//
				return Mono.empty();
			}
		};
	}
}