BrooklynAccessUtils { public static HostAndPort getBrooklynAccessibleAddress(Entity entity, int port) { String host; EntityInternal entityInternal = (EntityInternal) entity; PortForwardManager pfw = entity.getConfig(PORT_FORWARDING_MANAGER); if (pfw == null) { log.trace("No PortForwardManager, using default"); pfw = (PortForwardManager) entityInternal.getManagementContext().getLocationRegistry().getLocationManaged(PortForwardManagerLocationResolver.PFM_GLOBAL_SPEC); } Collection<Location> ll = entity.getLocations(); synchronized (BrooklynAccessUtils.class) { for (MachineLocation machine : Iterables.filter(ll, MachineLocation.class)) { HostAndPort hp = pfw.lookup(machine, port); if (hp!=null) { log.debug("BrooklynAccessUtils found port-forwarded address {} for entity {}, port {}, using machine {}", new Object[] {hp, entity, port, machine}); return hp; } } Maybe<SupportsPortForwarding> supportPortForwardingLoc = Machines.findUniqueElement(ll, SupportsPortForwarding.class); if (supportPortForwardingLoc.isPresent()) { Cidr source = entity.getConfig(MANAGEMENT_ACCESS_CIDR); SupportsPortForwarding loc = supportPortForwardingLoc.get(); if (source!=null) { log.debug("BrooklynAccessUtils requesting new port-forwarding rule to access "+port+" on "+entity+" (at "+loc+", enabled for "+source+")"); HostAndPort hp = loc.getSocketEndpointFor(source, port); if (hp!=null) { log.debug("BrooklynAccessUtils created port-forwarded address {} for entity {}, port {}, using {}", new Object[] {hp, entity, port, loc}); return hp; } } else { log.warn("No "+MANAGEMENT_ACCESS_CIDR.getName()+" configured for "+entity+", so cannot forward " +"port "+port+" "+"even though "+PORT_FORWARDING_MANAGER.getName()+" was supplied, and " +"have location supporting port forwarding "+loc); } } } host = entity.getAttribute(Attributes.HOSTNAME); if (host!=null) return HostAndPort.fromParts(host, port); throw new IllegalStateException("Cannot find way to access port "+port+" on "+entity+" from Brooklyn (no host.name)"); }  static HostAndPort getBrooklynAccessibleAddress(Entity entity, int port); static String getResolvedAddress(Entity entity, SshMachineLocation origin, String hostnameTarget); static Supplier<String> resolvedAddressSupplier(final Entity entity, final SshMachineLocation origin, final String hostnameTarget); static final ConfigKey<PortForwardManager> PORT_FORWARDING_MANAGER; static final ConfigKey<Cidr> MANAGEMENT_ACCESS_CIDR; }
@Test public void testBrooklynAccessibleAddressFindsPreexistingMapping() throws Exception { final int privatePort = 8080; final String publicNatIp = "1.2.3.4"; final int publicNatPort = 12000; SshMachineLocation machine = mgmt.getLocationManager().createLocation(LocationSpec.create(SshMachineLocation.class) .configure(SshMachineLocation.TCP_PORT_MAPPINGS, ImmutableMap.of(privatePort, publicNatIp+":"+publicNatPort))); entity = app.createAndManageChild(EntitySpec.create(TestEntity.class) .configure(BrooklynAccessUtils.PORT_FORWARDING_MANAGER, pfm) .location(machine)); assertEquals(BrooklynAccessUtils.getBrooklynAccessibleAddress(entity, privatePort), HostAndPort.fromParts(publicNatIp, publicNatPort)); }
@Test public void testBrooklynAccessibleAddressFindsPreexistingMappingFromDefaultPFM() throws Exception { final int privatePort = 8080; final String publicNatIp = "1.2.3.4"; final int publicNatPort = 12000; SshMachineLocation machine = mgmt.getLocationManager().createLocation(LocationSpec.create(SshMachineLocation.class) .configure(SshMachineLocation.TCP_PORT_MAPPINGS, ImmutableMap.of(privatePort, publicNatIp+":"+publicNatPort))); entity = app.createAndManageChild(EntitySpec.create(TestEntity.class) .location(machine)); assertEquals(BrooklynAccessUtils.getBrooklynAccessibleAddress(entity, privatePort), HostAndPort.fromParts(publicNatIp, publicNatPort)); }
@Test public void testBrooklynAccessibleAddressUsesPrivateHostPortIfNoMapping() throws Exception { final String privateIp = "127.1.2.3"; final int privatePort = 8080; SshMachineLocation machine = mgmt.getLocationManager().createLocation(LocationSpec.create(SshMachineLocation.class)); entity = app.createAndManageChild(EntitySpec.create(TestEntity.class) .configure(BrooklynAccessUtils.PORT_FORWARDING_MANAGER, pfm) .location(machine)); entity.sensors().set(Attributes.HOSTNAME, privateIp); assertEquals(BrooklynAccessUtils.getBrooklynAccessibleAddress(entity, privatePort), HostAndPort.fromParts(privateIp, privatePort)); }
@Test public void testBrooklynAccessibleAddressFailsIfNoMappingAndNoHostname() throws Exception { final int privatePort = 8080; SshMachineLocation machine = mgmt.getLocationManager().createLocation(LocationSpec.create(SshMachineLocation.class)); entity = app.createAndManageChild(EntitySpec.create(TestEntity.class) .configure(BrooklynAccessUtils.PORT_FORWARDING_MANAGER, pfm) .location(machine)); try { BrooklynAccessUtils.getBrooklynAccessibleAddress(entity, privatePort); fail(); } catch (IllegalStateException e) { if (!e.toString().contains("no host.name")) throw e; } }
@Test public void testBrooklynAccessibleAddressRequestsNewPortForwarding() throws Exception { final int privatePort = 8080; RecordingSupportsPortForwarding machine = mgmt.getLocationManager().createLocation(LocationSpec.create(RecordingSupportsPortForwarding.class)); entity = app.createAndManageChild(EntitySpec.create(TestEntity.class) .configure(BrooklynAccessUtils.PORT_FORWARDING_MANAGER, pfm) .configure(BrooklynAccessUtils.MANAGEMENT_ACCESS_CIDR, Cidr.UNIVERSAL) .location(machine)); HostAndPort result = BrooklynAccessUtils.getBrooklynAccessibleAddress(entity, privatePort); HostAndPort portForwarded = machine.mappings.get(privatePort); assertNotNull(portForwarded); assertEquals(result, portForwarded); }