This is an automated email from the ASF dual-hosted git repository.
heneveld pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/brooklyn-server.git
The following commit(s) were added to refs/heads/master by this push:
new 8f8eb59c08 allow byon/fixed-list config to be dynamic
8f8eb59c08 is described below
commit 8f8eb59c0845dd098df3e9cba95fc6d2322455a2
Author: Alex Heneveld <[email protected]>
AuthorDate: Mon Jul 15 11:42:17 2024 +0100
allow byon/fixed-list config to be dynamic
---
.../camp/brooklyn/ByonLocationsYamlTest.java | 70 +++-
.../location/byon/ByonLocationResolver.java | 354 ++++++++++++---------
2 files changed, 281 insertions(+), 143 deletions(-)
diff --git
a/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/ByonLocationsYamlTest.java
b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/ByonLocationsYamlTest.java
index d5cec29916..a57670015e 100644
---
a/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/ByonLocationsYamlTest.java
+++
b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/ByonLocationsYamlTest.java
@@ -21,6 +21,8 @@ package org.apache.brooklyn.camp.brooklyn;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNull;
+import java.util.Collections;
+import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -38,7 +40,7 @@ import
org.apache.brooklyn.location.byon.FixedListMachineProvisioningLocation;
import org.apache.brooklyn.location.ssh.SshMachineLocation;
import org.apache.brooklyn.location.winrm.WinRmMachineLocation;
import org.apache.brooklyn.test.Asserts;
-import org.apache.brooklyn.util.exceptions.Exceptions;
+import org.apache.brooklyn.util.collections.MutableList;
import org.apache.brooklyn.util.net.UserAndHostAndPort;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -97,6 +99,72 @@ public class ByonLocationsYamlTest extends AbstractYamlTest {
assertEquals(machine.getPrivateAddresses(),
ImmutableSet.of("10.0.0.1"));
}
+ @Test
+ @SuppressWarnings("unchecked")
+ public void testByonMachineResolvesDependentConfigForHost() throws
Exception {
+ String yaml = Joiner.on("\n").join(
+ "location:",
+ " byon:",
+ " hosts:",
+ " - $brooklyn:config(\"ip_address\")",
+ "services:",
+ "- type: org.apache.brooklyn.entity.stock.BasicApplication",
+ " brooklyn.config:",
+ " ip_address: 1.2.3.4"
+ );
+
+ Entity app = createStartWaitAndLogApplication(yaml);
+ FixedListMachineProvisioningLocation<SshMachineLocation> loc =
(FixedListMachineProvisioningLocation<SshMachineLocation>)
Iterables.get(app.getLocations(), 0);
+
+ Set<SshMachineLocation> machines = loc.getAvailable();
+ SshMachineLocation machine = Iterables.getOnlyElement(machines);
+ assertMachine(machine, UserAndHostAndPort.fromParts(machine.getUser(),
"1.2.3.4", 22), Collections.emptyMap());
+ }
+
+ @Test
+ @SuppressWarnings("unchecked")
+ public void testByonMachineResolvesDependentConfigForHosts() throws
Exception {
+ String yaml = Joiner.on("\n").join(
+ "location:",
+ " byon:",
+ " hosts: $brooklyn:config(\"ip_addresses\")",
+ "services:",
+ "- type: org.apache.brooklyn.entity.stock.BasicApplication",
+ " brooklyn.config:",
+ " ip_addresses: [ 1.2.3.4, { ssh: 1.2.3.5, user: Beth } ]"
+ );
+
+ Entity app = createStartWaitAndLogApplication(yaml);
+ FixedListMachineProvisioningLocation<SshMachineLocation> loc =
(FixedListMachineProvisioningLocation<SshMachineLocation>)
Iterables.get(app.getLocations(), 0);
+
+ List<SshMachineLocation> machines =
MutableList.copyOf(loc.getAvailable());
+ Asserts.assertSize(machines, 2);
+ assertMachine(machines.get(0),
UserAndHostAndPort.fromParts(machines.get(0).getUser(), "1.2.3.4", 22),
Collections.emptyMap());
+ assertMachine(machines.get(1), UserAndHostAndPort.fromParts("Beth",
"1.2.3.5", 22), Collections.emptyMap());
+ }
+
+ @Test
+ @SuppressWarnings("unchecked")
+ public void testByonMachineResolvesDependentConfigForUser() throws
Exception {
+ String yaml = Joiner.on("\n").join(
+ "location:",
+ " byon:",
+ " user: $brooklyn:config(\"uzer\")",
+ " hosts: [ 1.2.3.4 ]",
+ "services:",
+ "- type: org.apache.brooklyn.entity.stock.BasicApplication",
+ " brooklyn.config:",
+ " uzer: Beth"
+ );
+
+ Entity app = createStartWaitAndLogApplication(yaml);
+ FixedListMachineProvisioningLocation<SshMachineLocation> loc =
(FixedListMachineProvisioningLocation<SshMachineLocation>)
Iterables.get(app.getLocations(), 0);
+
+ Set<SshMachineLocation> machines = loc.getAvailable();
+ SshMachineLocation machine = Iterables.getOnlyElement(machines);
+ assertMachine(machine, UserAndHostAndPort.fromParts("Beth", "1.2.3.4",
22), Collections.emptyMap());
+ }
+
@Test
@SuppressWarnings("unchecked")
public void testByonWindowsMachine() throws Exception {
diff --git
a/core/src/main/java/org/apache/brooklyn/location/byon/ByonLocationResolver.java
b/core/src/main/java/org/apache/brooklyn/location/byon/ByonLocationResolver.java
index 40a998fb6b..ba361e38b6 100644
---
a/core/src/main/java/org/apache/brooklyn/location/byon/ByonLocationResolver.java
+++
b/core/src/main/java/org/apache/brooklyn/location/byon/ByonLocationResolver.java
@@ -24,23 +24,32 @@ import java.net.InetAddress;
import java.util.List;
import java.util.Locale;
import java.util.Map;
+import java.util.function.Supplier;
+import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.location.Location;
import org.apache.brooklyn.api.location.LocationRegistry;
import org.apache.brooklyn.api.location.LocationSpec;
import org.apache.brooklyn.api.location.MachineLocation;
+import org.apache.brooklyn.api.mgmt.ManagementContext;
import org.apache.brooklyn.config.ConfigKey;
import org.apache.brooklyn.core.config.ConfigKeys;
import org.apache.brooklyn.core.config.Sanitizer;
+import org.apache.brooklyn.core.entity.EntityInternal;
import org.apache.brooklyn.core.location.AbstractLocationResolver;
+import org.apache.brooklyn.core.mgmt.BrooklynTaskTags;
import org.apache.brooklyn.core.mgmt.internal.LocalLocationManager;
import org.apache.brooklyn.util.collections.MutableMap;
import org.apache.brooklyn.util.core.ClassLoaderUtils;
import org.apache.brooklyn.util.core.config.ConfigBag;
import org.apache.brooklyn.util.core.flags.TypeCoercions;
+import org.apache.brooklyn.util.core.task.DeferredSupplier;
+import org.apache.brooklyn.util.core.task.Tasks;
+import org.apache.brooklyn.util.exceptions.Exceptions;
import org.apache.brooklyn.util.net.UserAndHostAndPort;
import org.apache.brooklyn.util.text.WildcardGlobs;
import org.apache.brooklyn.util.text.WildcardGlobs.PhraseTreatment;
+import org.apache.commons.lang3.tuple.Pair;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -98,171 +107,232 @@ public class ByonLocationResolver extends
AbstractLocationResolver {
@Override
protected ConfigBag extractConfig(Map<?,?> locationFlags, String spec,
LocationRegistry registry) {
ConfigBag config = super.extractConfig(locationFlags, spec, registry);
+ new MachineSpecsExtractor(spec, config).setConfigKey(this);
+ return config;
+ }
- Object hosts = config.getStringKey("hosts");
- config.remove("hosts");
- String user = (String) config.getStringKey("user");
- Integer port = TypeCoercions.coerce(config.getStringKey("port"),
Integer.class);
- Class<? extends MachineLocation> locationClass =
getLocationClass(config.get(OS_FAMILY));
-
- MutableMap<String, Object> defaultProps = MutableMap.of();
- defaultProps.addIfNotNull("user", user);
- defaultProps.addIfNotNull("port", port);
-
- List<?> hostAddresses;
-
- if (hosts instanceof String) {
- if (((String) hosts).isEmpty()) {
- hostAddresses = ImmutableList.of();
- } else {
- hostAddresses =
WildcardGlobs.getGlobsAfterBraceExpansion("{"+hosts+"}",
- true /* numeric */, /* no quote support though */
PhraseTreatment.NOT_A_SPECIAL_CHAR, PhraseTreatment.NOT_A_SPECIAL_CHAR);
- }
- } else if (hosts instanceof Iterable) {
- hostAddresses = ImmutableList.copyOf((Iterable<?>)hosts);
- } else {
- throw new IllegalArgumentException("Invalid location '"+spec+"';
at least one host must be defined");
- }
- if (hostAddresses.isEmpty()) {
- throw new IllegalArgumentException("Invalid location '"+spec+"';
at least one host must be defined");
+ protected static class MachineSpecsExtractor implements
DeferredSupplier<List<LocationSpec<? extends MachineLocation>>> {
+ String spec;
+ ConfigBag config;
+
+ public MachineSpecsExtractor(String spec, ConfigBag config) {
+ this.spec = spec;
+ this.config = config;
}
-
- List<LocationSpec<? extends MachineLocation>> machineSpecs =
Lists.newArrayList();
- for (Object host : hostAddresses) {
- LocationSpec<? extends MachineLocation> machineSpec;
- if (host instanceof String) {
- machineSpec = parseMachine((String)host, locationClass,
defaultProps, spec);
- } else if (host instanceof Map) {
- machineSpec = parseMachine((Map<String, ?>)host,
locationClass, defaultProps, spec);
- } else {
- throw new IllegalArgumentException("Expected machine to be
String or Map, but was "+host.getClass().getName()+" ("+host+")");
+
+ /**
+ * the return value could theoretically change, which could cause
unusual behaviour, but it is created unmanaged, so it shouldn't cause leaks;
+ * and any other unusual behaviour the caller shouldn't be too
surprised about; we don't expect it to change often in any case
+ */
+ @Override
+ public List<LocationSpec<? extends MachineLocation>> get() {
+ Entity entity = BrooklynTaskTags.getContextEntity(Tasks.current());
+ if (entity == null) {
+ throw new IllegalStateException("BYON dynamic config can only
be resolved in the context of an entity task");
}
-
machineSpec.configureIfNotNull(LocalLocationManager.CREATE_UNMANAGED,
config.get(LocalLocationManager.CREATE_UNMANAGED));
- machineSpecs.add(machineSpec);
+ return extractConfigMachineSpecs(entity, ((EntityInternal)
entity).getManagementContext(), spec, config, false);
}
-
- config.put(FixedListMachineProvisioningLocation.MACHINE_SPECS,
machineSpecs);
- return config;
- }
-
- protected LocationSpec<? extends MachineLocation> parseMachine(Map<String,
?> vals, Class<? extends MachineLocation> locationClass, Map<String, ?>
defaults, String specForErrMsg) {
- Map<String, Object> valSanitized = Sanitizer.sanitize(vals);
- Map<String, Object> machineConfig = MutableMap.copyOf(vals);
-
- String osFamily = (String) machineConfig.remove(OS_FAMILY.getName());
- String ssh = (String) machineConfig.remove("ssh");
- String winrm = (String) machineConfig.remove("winrm");
- Map<Integer, String> tcpPortMappings = (Map<Integer, String>)
machineConfig.get("tcpPortMappings");
-
- checkArgument(ssh != null ^ winrm != null, "Must specify exactly one
of 'ssh' or 'winrm' for machine: %s", valSanitized);
-
- UserAndHostAndPort userAndHostAndPort;
- String host;
- int port;
- if (ssh != null) {
- userAndHostAndPort = parseUserAndHostAndPort(ssh, 22);
- } else {
- // TODO set to null and rely on the MachineLocation. If not then
make a dependency to WinRmMachineLocation and use its config key name.
- userAndHostAndPort = parseUserAndHostAndPort(winrm,
vals.get("winrm.useHttps") != null && (Boolean)vals.get("winrm.useHttps") ?
5986 : 5985);
- }
-
- // If there is a tcpPortMapping defined for the connection-port, then
use that for ssh/winrm machine
- port = userAndHostAndPort.getHostAndPort().getPort();
- if (tcpPortMappings != null && tcpPortMappings.containsKey(port)) {
- String override = tcpPortMappings.get(port);
- HostAndPort hostAndPortOverride = HostAndPort.fromString(override);
- if (!hostAndPortOverride.hasPort()) {
- throw new IllegalArgumentException("Invalid portMapping
('"+override+"') for port "+port+" in "+specForErrMsg);
+ public void setConfigKey(ByonLocationResolver resolver) {
+ ConfigBag configCopy = ConfigBag.newInstanceCopying(config);
+ try {
+ List<LocationSpec<? extends MachineLocation>>
machineSpecsResolvableEarly = extractConfigMachineSpecs(resolver,
resolver.managementContext, spec, config, true);
+ config.put(FixedListMachineProvisioningLocation.MACHINE_SPECS,
machineSpecsResolvableEarly);
+
+ } catch (UsesDeferredSupplier e) {
+ // dynamic - update the config the location gets
+ config.put((ConfigKey)
FixedListMachineProvisioningLocation.MACHINE_SPECS, this);
+ // but restore our local copy to the original one
+ config = configCopy;
}
- port = hostAndPortOverride.getPort();
- host = hostAndPortOverride.getHost().trim();
- } else {
- host = userAndHostAndPort.getHostAndPort().getHost().trim();
- }
-
- machineConfig.put("address", host);
- try {
- InetAddress.getByName(host);
- } catch (Exception e) {
- throw new IllegalArgumentException("Invalid host '"+host+"'
specified in '"+specForErrMsg+"': "+e);
}
- if (userAndHostAndPort.getUser() != null) {
- checkArgument(!vals.containsKey("user"), "Must not specify user
twice for machine: %s", valSanitized);
- machineConfig.put("user", userAndHostAndPort.getUser());
- }
- if (userAndHostAndPort.getHostAndPort().hasPort()) {
- checkArgument(!vals.containsKey("port"), "Must not specify port
twice for machine: %s", valSanitized);
- machineConfig.put("port", port);
+ protected static class UsesDeferredSupplier extends RuntimeException {}
+
+ protected <T> T resolveOrThrow(boolean dynamicAllowed, String key,
Class<T> type) {
+ Object v = config.getStringKey(key);
+ v = resolveOrThrow(dynamicAllowed, v);
+ return TypeCoercions.coerce(v, type);
}
- for (Map.Entry<String, ?> entry : defaults.entrySet()) {
- if (!machineConfig.containsKey(entry.getKey())) {
- machineConfig.put(entry.getKey(), entry.getValue());
+ protected Object resolveOrThrow(boolean dynamicAllowed, Object v) {
+ if (v instanceof DeferredSupplier) {
+ if (dynamicAllowed) throw new UsesDeferredSupplier();
+ v = ((DeferredSupplier)v).get();
}
+ return v;
}
-
- Class<? extends MachineLocation> locationClassHere = locationClass;
- if (osFamily != null) {
- locationClassHere = getLocationClass(osFamily);
+
+ // if dynamicAllowed, returns null if anything is can't be resolved;
+ // if not dynamicAllowed, throws if anything can't be resolved.
+ protected List<LocationSpec<? extends MachineLocation>>
extractConfigMachineSpecs(Object context, ManagementContext mgmt, String spec,
ConfigBag config, boolean dynamicAllowed) {
+ Object hosts = resolveOrThrow(dynamicAllowed, "hosts",
Object.class);
+
+ Class<? extends MachineLocation> locationClass;
+ MutableMap<String, Object> defaultProps = MutableMap.of();
+ config.remove("hosts");
+ String user = resolveOrThrow(dynamicAllowed, "user", String.class);
+ Integer port = resolveOrThrow(dynamicAllowed, "port",
Integer.class);
+ resolveOrThrow(dynamicAllowed, OS_FAMILY.getName(), Object.class);
+ locationClass = getLocationClass(mgmt, context,
config.get(OS_FAMILY));
+
+ defaultProps.addIfNotNull("user", user);
+ defaultProps.addIfNotNull("port", port);
+
+ List<?> hostAddresses;
+
+ if (hosts instanceof String) {
+ if (((String) hosts).isEmpty()) {
+ hostAddresses = ImmutableList.of();
+ } else {
+ hostAddresses =
WildcardGlobs.getGlobsAfterBraceExpansion("{" + hosts + "}",
+ true /* numeric */, /* no quote support though */
PhraseTreatment.NOT_A_SPECIAL_CHAR, PhraseTreatment.NOT_A_SPECIAL_CHAR);
+ }
+ } else if (hosts instanceof Iterable) {
+ hostAddresses = ImmutableList.copyOf((Iterable<?>) hosts);
+ } else {
+ throw new IllegalArgumentException("Invalid location '" + spec
+ "'; at least one host must be defined");
+ }
+ if (hostAddresses.isEmpty()) {
+ throw new IllegalArgumentException("Invalid location '" + spec
+ "'; at least one host must be defined");
+ }
+
+ List<LocationSpec<? extends MachineLocation>> machineSpecs =
Lists.newArrayList();
+ for (Object host : hostAddresses) {
+ host = resolveOrThrow(dynamicAllowed, host);
+
+ LocationSpec<? extends MachineLocation> machineSpec;
+ if (host instanceof String) {
+ machineSpec = parseMachine((String) host, locationClass,
defaultProps, spec);
+ } else if (host instanceof Map) {
+ machineSpec = parseMachine(mgmt, context, (Map<String, ?>)
host, locationClass, defaultProps, spec);
+ } else {
+ throw new IllegalArgumentException("Expected machine to be
String or Map, but was " + host.getClass().getName() + " (" + host + ")");
+ }
+
machineSpec.configureIfNotNull(LocalLocationManager.CREATE_UNMANAGED,
config.get(LocalLocationManager.CREATE_UNMANAGED));
+ machineSpecs.add(machineSpec);
+ }
+ return machineSpecs;
}
- return LocationSpec.create(locationClassHere).configure(machineConfig);
- }
+ private LocationSpec<? extends MachineLocation>
parseMachine(ManagementContext mgmt, Object context, Map<String, ?> vals,
Class<? extends MachineLocation> locationClass, Map<String, ?> defaults, String
specForErrMsg) {
+ Map<String, Object> valSanitized = Sanitizer.sanitize(vals);
+ Map<String, Object> machineConfig = MutableMap.copyOf(vals);
- private Class<? extends MachineLocation> getLocationClass(String osFamily)
{
- try {
+ String osFamily = (String)
machineConfig.remove(OS_FAMILY.getName());
+ String ssh = (String) machineConfig.remove("ssh");
+ String winrm = (String) machineConfig.remove("winrm");
+ Map<Integer, String> tcpPortMappings = (Map<Integer, String>)
machineConfig.get("tcpPortMappings");
+
+ checkArgument(ssh != null ^ winrm != null, "Must specify exactly
one of 'ssh' or 'winrm' for machine: %s", valSanitized);
+
+ UserAndHostAndPort userAndHostAndPort;
+ String host;
+ int port;
+ if (ssh != null) {
+ userAndHostAndPort = parseUserAndHostAndPort(ssh, 22);
+ } else {
+ // TODO set to null and rely on the MachineLocation. If not
then make a dependency to WinRmMachineLocation and use its config key name.
+ userAndHostAndPort = parseUserAndHostAndPort(winrm,
vals.get("winrm.useHttps") != null && (Boolean) vals.get("winrm.useHttps") ?
5986 : 5985);
+ }
+
+ // If there is a tcpPortMapping defined for the connection-port,
then use that for ssh/winrm machine
+ port = userAndHostAndPort.getHostAndPort().getPort();
+ if (tcpPortMappings != null && tcpPortMappings.containsKey(port)) {
+ String override = tcpPortMappings.get(port);
+ HostAndPort hostAndPortOverride =
HostAndPort.fromString(override);
+ if (!hostAndPortOverride.hasPort()) {
+ throw new IllegalArgumentException("Invalid portMapping
('" + override + "') for port " + port + " in " + specForErrMsg);
+ }
+ port = hostAndPortOverride.getPort();
+ host = hostAndPortOverride.getHost().trim();
+ } else {
+ host = userAndHostAndPort.getHostAndPort().getHost().trim();
+ }
+
+ machineConfig.put("address", host);
+ try {
+ InetAddress.getByName(host);
+ } catch (Exception e) {
+ throw new IllegalArgumentException("Invalid host '" + host +
"' specified in '" + specForErrMsg + "': " + e);
+ }
+
+ if (userAndHostAndPort.getUser() != null) {
+ checkArgument(!vals.containsKey("user"), "Must not specify
user twice for machine: %s", valSanitized);
+ machineConfig.put("user", userAndHostAndPort.getUser());
+ }
+ if (userAndHostAndPort.getHostAndPort().hasPort()) {
+ checkArgument(!vals.containsKey("port"), "Must not specify
port twice for machine: %s", valSanitized);
+ machineConfig.put("port", port);
+ }
+ for (Map.Entry<String, ?> entry : defaults.entrySet()) {
+ if (!machineConfig.containsKey(entry.getKey())) {
+ machineConfig.put(entry.getKey(), entry.getValue());
+ }
+ }
+
+ Class<? extends MachineLocation> locationClassHere = locationClass;
if (osFamily != null) {
- String className =
OS_TO_MACHINE_LOCATION_TYPE.get(osFamily.toLowerCase(Locale.ENGLISH));
- return new ClassLoaderUtils(this,
managementContext).loadClass(className).asSubclass(MachineLocation.class);
+ locationClassHere = getLocationClass(mgmt, context, osFamily);
}
- } catch (ClassNotFoundException ex) {}
- return null;
- }
- protected LocationSpec<? extends MachineLocation> parseMachine(String val,
Class<? extends MachineLocation> locationClass, Map<String, ?> defaults, String
specForErrMsg) {
- Map<String, Object> machineConfig = Maps.newLinkedHashMap();
-
- UserAndHostAndPort userAndHostAndPort = parseUserAndHostAndPort(val);
-
- String host = userAndHostAndPort.getHostAndPort().getHost().trim();
- machineConfig.put("address", host);
- try {
- InetAddress.getByName(host.trim());
- } catch (Exception e) {
- throw new IllegalArgumentException("Invalid host '"+host+"'
specified in '"+specForErrMsg+"': "+e);
+ return
LocationSpec.create(locationClassHere).configure(machineConfig);
}
-
- if (userAndHostAndPort.getUser() != null) {
- machineConfig.put("user", userAndHostAndPort.getUser());
- }
- if (userAndHostAndPort.getHostAndPort().hasPort()) {
- machineConfig.put("port",
userAndHostAndPort.getHostAndPort().getPort());
+
+ private Class<? extends MachineLocation>
getLocationClass(ManagementContext mgmt, Object context, String osFamily) {
+ try {
+ if (osFamily != null) {
+ String className =
OS_TO_MACHINE_LOCATION_TYPE.get(osFamily.toLowerCase(Locale.ENGLISH));
+ return new ClassLoaderUtils(context,
mgmt).loadClass(className).asSubclass(MachineLocation.class);
+ }
+ } catch (ClassNotFoundException ex) {
+ }
+ return null;
}
- for (Map.Entry<String, ?> entry : defaults.entrySet()) {
- if (!machineConfig.containsKey(entry.getKey())) {
- machineConfig.put(entry.getKey(), entry.getValue());
+
+ private LocationSpec<? extends MachineLocation> parseMachine(String
val, Class<? extends MachineLocation> locationClass, Map<String, ?> defaults,
String specForErrMsg) {
+ Map<String, Object> machineConfig = Maps.newLinkedHashMap();
+
+ UserAndHostAndPort userAndHostAndPort =
parseUserAndHostAndPort(val);
+
+ String host = userAndHostAndPort.getHostAndPort().getHost().trim();
+ machineConfig.put("address", host);
+ try {
+ InetAddress.getByName(host.trim());
+ } catch (Exception e) {
+ throw new IllegalArgumentException("Invalid host '" + host +
"' specified in '" + specForErrMsg + "': " + e);
+ }
+
+ if (userAndHostAndPort.getUser() != null) {
+ machineConfig.put("user", userAndHostAndPort.getUser());
+ }
+ if (userAndHostAndPort.getHostAndPort().hasPort()) {
+ machineConfig.put("port",
userAndHostAndPort.getHostAndPort().getPort());
}
+ for (Map.Entry<String, ?> entry : defaults.entrySet()) {
+ if (!machineConfig.containsKey(entry.getKey())) {
+ machineConfig.put(entry.getKey(), entry.getValue());
+ }
+ }
+
+ return LocationSpec.create(locationClass).configure(machineConfig);
}
- return LocationSpec.create(locationClass).configure(machineConfig);
- }
-
- private UserAndHostAndPort parseUserAndHostAndPort(String val) {
- String userPart = null;
- String hostPart = val;
- if (val.contains("@")) {
- userPart = val.substring(0, val.indexOf("@"));
- hostPart = val.substring(val.indexOf("@")+1);
+ private UserAndHostAndPort parseUserAndHostAndPort(String val) {
+ String userPart = null;
+ String hostPart = val;
+ if (val.contains("@")) {
+ userPart = val.substring(0, val.indexOf("@"));
+ hostPart = val.substring(val.indexOf("@") + 1);
+ }
+ return UserAndHostAndPort.fromParts(userPart,
HostAndPort.fromString(hostPart));
}
- return UserAndHostAndPort.fromParts(userPart,
HostAndPort.fromString(hostPart));
- }
-
- private UserAndHostAndPort parseUserAndHostAndPort(String val, int
defaultPort) {
- UserAndHostAndPort result = parseUserAndHostAndPort(val);
- if (!result.getHostAndPort().hasPort()) {
- result = UserAndHostAndPort.fromParts(result.getUser(),
result.getHostAndPort().getHost(), defaultPort);
+
+ private UserAndHostAndPort parseUserAndHostAndPort(String val, int
defaultPort) {
+ UserAndHostAndPort result = parseUserAndHostAndPort(val);
+ if (!result.getHostAndPort().hasPort()) {
+ result = UserAndHostAndPort.fromParts(result.getUser(),
result.getHostAndPort().getHost(), defaultPort);
+ }
+ return result;
}
- return result;
}
}