mirror of https://github.com/apache/jclouds.git
fix for issue if SL machine has multiple credentials registered
now just pick the best one. it matters only when we are going to log in to a machine. the only time the problem has been observed has been with pre-existing machines set up outwith jclouds with multiple password.
This commit is contained in:
parent
b96c66dbce
commit
0248931cc1
|
@ -18,10 +18,12 @@ package org.jclouds.softlayer.compute.functions;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
import static com.google.common.collect.FluentIterable.from;
|
import static com.google.common.collect.FluentIterable.from;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
@ -34,20 +36,26 @@ import org.jclouds.compute.functions.GroupNamingConvention;
|
||||||
import org.jclouds.domain.Location;
|
import org.jclouds.domain.Location;
|
||||||
import org.jclouds.domain.LoginCredentials;
|
import org.jclouds.domain.LoginCredentials;
|
||||||
import org.jclouds.location.predicates.LocationPredicates;
|
import org.jclouds.location.predicates.LocationPredicates;
|
||||||
|
import org.jclouds.logging.Logger;
|
||||||
import org.jclouds.softlayer.domain.Password;
|
import org.jclouds.softlayer.domain.Password;
|
||||||
import org.jclouds.softlayer.domain.TagReference;
|
import org.jclouds.softlayer.domain.TagReference;
|
||||||
import org.jclouds.softlayer.domain.VirtualGuest;
|
import org.jclouds.softlayer.domain.VirtualGuest;
|
||||||
|
|
||||||
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
import com.google.common.base.Function;
|
import com.google.common.base.Function;
|
||||||
import com.google.common.base.Supplier;
|
import com.google.common.base.Supplier;
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
|
import com.google.common.collect.Sets;
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
public class VirtualGuestToNodeMetadata implements Function<VirtualGuest, NodeMetadata> {
|
public class VirtualGuestToNodeMetadata implements Function<VirtualGuest, NodeMetadata> {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
protected Logger logger = Logger.NULL;
|
||||||
|
|
||||||
public static final Map<VirtualGuest.State, Status> serverStateToNodeStatus = ImmutableMap
|
public static final Map<VirtualGuest.State, Status> serverStateToNodeStatus = ImmutableMap
|
||||||
.<VirtualGuest.State, Status> builder().put(VirtualGuest.State.HALTED, Status.PENDING)
|
.<VirtualGuest.State, Status> builder().put(VirtualGuest.State.HALTED, Status.PENDING)
|
||||||
.put(VirtualGuest.State.PAUSED, Status.SUSPENDED).put(VirtualGuest.State.RUNNING, Status.RUNNING)
|
.put(VirtualGuest.State.PAUSED, Status.SUSPENDED).put(VirtualGuest.State.RUNNING, Status.RUNNING)
|
||||||
|
@ -95,7 +103,7 @@ public class VirtualGuestToNodeMetadata implements Function<VirtualGuest, NodeMe
|
||||||
builder.privateAddresses(ImmutableSet.of(from.getPrimaryBackendIpAddress()));
|
builder.privateAddresses(ImmutableSet.of(from.getPrimaryBackendIpAddress()));
|
||||||
// TODO simplify once we move domain classes to AutoValue
|
// TODO simplify once we move domain classes to AutoValue
|
||||||
if (from.getOperatingSystem() != null && from.getOperatingSystem().getPasswords() != null && !from.getOperatingSystem().getPasswords().isEmpty()) {
|
if (from.getOperatingSystem() != null && from.getOperatingSystem().getPasswords() != null && !from.getOperatingSystem().getPasswords().isEmpty()) {
|
||||||
Password password = Iterables.getOnlyElement(from.getOperatingSystem().getPasswords());
|
Password password = getBestPassword(from.getOperatingSystem().getPasswords(), from);
|
||||||
builder.credentials(LoginCredentials.builder().identity(password.getUsername()).credential(password.getPassword()).build());
|
builder.credentials(LoginCredentials.builder().identity(password.getUsername()).credential(password.getPassword()).build());
|
||||||
}
|
}
|
||||||
if (from.getTagReferences() != null && !from.getTagReferences().isEmpty()) {
|
if (from.getTagReferences() != null && !from.getTagReferences().isEmpty()) {
|
||||||
|
@ -110,4 +118,48 @@ public class VirtualGuestToNodeMetadata implements Function<VirtualGuest, NodeMe
|
||||||
return builder.build();
|
return builder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
Password getBestPassword(Set<Password> passwords, VirtualGuest context) {
|
||||||
|
if (passwords == null || passwords.isEmpty()) {
|
||||||
|
throw new IllegalStateException("No credentials declared for " + context);
|
||||||
|
}
|
||||||
|
if (passwords.size() == 1) {
|
||||||
|
// usual path
|
||||||
|
return Iterables.getOnlyElement(passwords);
|
||||||
|
}
|
||||||
|
// in some setups a there may be multiple passwords; pick the best
|
||||||
|
Password bestPassword = null;
|
||||||
|
Set<Password> alternates = Sets.newLinkedHashSet();
|
||||||
|
int bestScore = -1;
|
||||||
|
for (Password p : passwords) {
|
||||||
|
int score = -1;
|
||||||
|
if ("root".equals(p.getUsername())) score = 10;
|
||||||
|
else if ("root".equalsIgnoreCase(p.getUsername())) score = 4;
|
||||||
|
else if ("ubuntu".equals(p.getUsername())) score = 8;
|
||||||
|
else if ("ubuntu".equalsIgnoreCase(p.getUsername())) score = 3;
|
||||||
|
else if ("administrator".equals(p.getUsername())) score = 5;
|
||||||
|
else if ("administrator".equalsIgnoreCase(p.getUsername())) score = 2;
|
||||||
|
else if (p.getUsername() != null && p.getUsername().length() > 1) score = 1;
|
||||||
|
|
||||||
|
if (score > 0) {
|
||||||
|
if (score > bestScore) {
|
||||||
|
bestPassword = p;
|
||||||
|
alternates.clear();
|
||||||
|
bestScore = score;
|
||||||
|
} else if (score == bestScore) {
|
||||||
|
alternates.add(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (bestPassword == null) {
|
||||||
|
throw new IllegalStateException("No valid credentials available for " + context + "; found: " + passwords);
|
||||||
|
}
|
||||||
|
if (!alternates.isEmpty()) {
|
||||||
|
logger.warn("Multiple credentials for " + bestPassword.getUsername() + "@" + context + "; using first declared " + bestPassword + " and ignoring " + alternates);
|
||||||
|
} else {
|
||||||
|
logger.debug("Multiple credentials for " + context + "; using preferred username " + bestPassword.getUsername());
|
||||||
|
}
|
||||||
|
return bestPassword;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@ package org.jclouds.softlayer.compute.functions;
|
||||||
import static org.testng.Assert.assertEquals;
|
import static org.testng.Assert.assertEquals;
|
||||||
import static org.testng.Assert.assertNotNull;
|
import static org.testng.Assert.assertNotNull;
|
||||||
import static org.testng.Assert.assertTrue;
|
import static org.testng.Assert.assertTrue;
|
||||||
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.jclouds.compute.domain.NodeMetadata;
|
import org.jclouds.compute.domain.NodeMetadata;
|
||||||
|
@ -29,6 +30,7 @@ import org.jclouds.domain.LocationBuilder;
|
||||||
import org.jclouds.domain.LocationScope;
|
import org.jclouds.domain.LocationScope;
|
||||||
import org.jclouds.softlayer.domain.Datacenter;
|
import org.jclouds.softlayer.domain.Datacenter;
|
||||||
import org.jclouds.softlayer.domain.OperatingSystem;
|
import org.jclouds.softlayer.domain.OperatingSystem;
|
||||||
|
import org.jclouds.softlayer.domain.Password;
|
||||||
import org.jclouds.softlayer.domain.PowerState;
|
import org.jclouds.softlayer.domain.PowerState;
|
||||||
import org.jclouds.softlayer.domain.SoftwareDescription;
|
import org.jclouds.softlayer.domain.SoftwareDescription;
|
||||||
import org.jclouds.softlayer.domain.SoftwareLicense;
|
import org.jclouds.softlayer.domain.SoftwareLicense;
|
||||||
|
@ -39,6 +41,7 @@ import com.google.common.base.Supplier;
|
||||||
import com.google.common.base.Suppliers;
|
import com.google.common.base.Suppliers;
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
|
import com.google.common.collect.Sets;
|
||||||
import com.google.inject.Guice;
|
import com.google.inject.Guice;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -100,4 +103,56 @@ public class VirtualGuestToNodeMetadataTest {
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test(expectedExceptions = { IllegalStateException.class })
|
||||||
|
public void testGetBestPasswordNone() {
|
||||||
|
Set<Password> passwords = Sets.newLinkedHashSet();
|
||||||
|
VirtualGuestToNodeMetadata f = new VirtualGuestToNodeMetadata(locationSupplier, namingConvention,
|
||||||
|
virtualGuestToImage, virtualGuestToHardware);
|
||||||
|
f.getBestPassword(passwords, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetBestPasswordOneRoot() {
|
||||||
|
Set<Password> passwords = Sets.newLinkedHashSet();
|
||||||
|
passwords.add(new Password(1, "root", "pass"));
|
||||||
|
VirtualGuestToNodeMetadata f = new VirtualGuestToNodeMetadata(locationSupplier, namingConvention,
|
||||||
|
virtualGuestToImage, virtualGuestToHardware);
|
||||||
|
Password best = f.getBestPassword(passwords, null);
|
||||||
|
assertEquals(best.getUsername(), "root");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetBestPasswordOneNonRoot() {
|
||||||
|
Set<Password> passwords = Sets.newLinkedHashSet();
|
||||||
|
passwords.add(new Password(1, "nonroot", "word"));
|
||||||
|
VirtualGuestToNodeMetadata f = new VirtualGuestToNodeMetadata(locationSupplier, namingConvention,
|
||||||
|
virtualGuestToImage, virtualGuestToHardware);
|
||||||
|
Password best = f.getBestPassword(passwords, null);
|
||||||
|
assertEquals(best.getUsername(), "nonroot");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetBestPasswordTwoDifferent() {
|
||||||
|
Set<Password> passwords = Sets.newLinkedHashSet();
|
||||||
|
passwords.add(new Password(1, "nonroot", "word"));
|
||||||
|
passwords.add(new Password(2, "root", "pass"));
|
||||||
|
VirtualGuestToNodeMetadata f = new VirtualGuestToNodeMetadata(locationSupplier, namingConvention,
|
||||||
|
virtualGuestToImage, virtualGuestToHardware);
|
||||||
|
Password best = f.getBestPassword(passwords, null);
|
||||||
|
assertEquals(best.getUsername(), "root");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetBestPasswordTwoSame() {
|
||||||
|
Set<Password> passwords = Sets.newLinkedHashSet();
|
||||||
|
passwords.add(new Password(1, "root", "word"));
|
||||||
|
passwords.add(new Password(2, "root", "pass"));
|
||||||
|
VirtualGuestToNodeMetadata f = new VirtualGuestToNodeMetadata(locationSupplier, namingConvention,
|
||||||
|
virtualGuestToImage, virtualGuestToHardware);
|
||||||
|
Password best = f.getBestPassword(passwords, null);
|
||||||
|
assertEquals(best.getUsername(), "root");
|
||||||
|
// should take the first
|
||||||
|
assertEquals(best.getPassword(), "word");
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue