package org.bitsofinfo.hazelcast.discovery.docker.swarm; import com.hazelcast.instance.AddressPicker; import com.hazelcast.logging.ILogger; import com.hazelcast.nio.Address; import java.net.URI; import java.nio.channels.ServerSocketChannel; /** * Custom AddressPicker that works for hazelcast instances running in swarm service instances * <p> * There are four JVM System properties to be defined: * <p> * - dockerNetworkNames = required, min one network: comma delimited list of relevant docker network names * that matching services must have a VIP on * <p> * - hazelcastPeerPort = optional, default 5701, the hazelcast port all service members are listening on * <p> * ONE or BOTH of the following can be defined: * <p> * - dockerServiceLabels = zero or more comma delimited service 'label=value' pairs to match. * If ANY match, that services' containers will be included in list of discovered containers * <p> * - dockerServiceNames = zero or more comma delimited service "names" to match. * If ANY match, that services' containers will be included in list of discovered containers * <p> * Another way to initiate this class is to pass above properties when creating a new {@link SwarmAddressPicker} * instance. This eliminates the need to pass properties in both hazelcast.xml (for setting up discovery) and with * JVM properties. * * @author bitsofinfo * @see <a href="https://github.com/hazelcast/hazelcast/issues/10801">Hazelcast GitHub Issue #10801</a> */ public class SwarmAddressPicker implements AddressPicker { public static final String PROP_DOCKER_NETWORK_NAMES = "dockerNetworkNames"; public static final String PROP_DOCKER_SERVICE_LABELS = "dockerServiceLabels"; public static final String PROP_DOCKER_SERVICE_NAMES = "dockerServiceNames"; public static final String PROP_HAZELCAST_PEER_PORT = "hazelcastPeerPort"; public static final String PROP_SWARM_MGR_URI = "swarmMgrUri"; public static final String PROP_SKIP_VERIFY_SSL = "skipVerifySsl"; private SwarmDiscoveryUtil swarmDiscoveryUtil = null; /** * Constructor */ public SwarmAddressPicker(final ILogger iLogger) { final String dockerNetworkNames = System.getProperty(PROP_DOCKER_NETWORK_NAMES); final String dockerServiceLabels = System.getProperty(PROP_DOCKER_SERVICE_LABELS); final String dockerServiceNames = System.getProperty(PROP_DOCKER_SERVICE_NAMES); final Integer hazelcastPeerPort = Integer.valueOf(System.getProperty(PROP_HAZELCAST_PEER_PORT)); String swarmMgrUri = System.getProperty(PROP_SWARM_MGR_URI); if (swarmMgrUri == null || swarmMgrUri.trim().isEmpty()) { swarmMgrUri = System.getenv("DOCKER_HOST"); } Boolean skipVerifySsl = false; if (System.getProperty(PROP_SKIP_VERIFY_SSL) != null) { skipVerifySsl = Boolean.valueOf(System.getProperty(PROP_SKIP_VERIFY_SSL)); } initialize(iLogger, dockerNetworkNames, dockerServiceLabels, dockerServiceNames, hazelcastPeerPort, swarmMgrUri, skipVerifySsl); } public SwarmAddressPicker(final ILogger iLogger, final String dockerNetworkNames, final String dockerServiceLabels, final String dockerServiceNames, final Integer hazelcastPeerPort) { String swarmMgrUri = System.getenv("DOCKER_HOST"); Boolean skipVerifySsl = false; initialize(iLogger, dockerNetworkNames, dockerServiceLabels, dockerServiceNames, hazelcastPeerPort, swarmMgrUri, skipVerifySsl); } private void initialize(final ILogger iLogger, final String dockerNetworkNames, final String dockerServiceLabels, final String dockerServiceNames, final Integer hazelcastPeerPort, final String swarmMgrUri, final Boolean skipVerifySsl) { final int port; if (hazelcastPeerPort != null) { port = hazelcastPeerPort; } else { port = 5701; } try { URI swarmMgr = null; if (swarmMgrUri == null || swarmMgrUri.trim().isEmpty()) { swarmMgr = new URI(System.getenv("DOCKER_HOST")); } this.swarmDiscoveryUtil = new SwarmDiscoveryUtil( this.getClass().getSimpleName(), dockerNetworkNames, dockerServiceLabels, dockerServiceNames, port, true, swarmMgr, skipVerifySsl, false, false ); } catch (final Exception e) { throw new RuntimeException( "SwarmAddressPicker: Error constructing SwarmDiscoveryUtil: " + e.getMessage(), e ); } } @Override public void pickAddress() throws Exception { // nothing to do, done in SwarmDiscoveryUtil above } @Override public Address getBindAddress() { return this.swarmDiscoveryUtil.getMyAddress(); } @Override public Address getPublicAddress() { return this.swarmDiscoveryUtil.getMyAddress(); } @Override public ServerSocketChannel getServerSocketChannel() { return this.swarmDiscoveryUtil.getServerSocketChannel(); } }