Issue 388: added adminPassword to Image and NodeMetadata, and corrected runScript process to use them

This commit is contained in:
Adrian Cole 2010-10-26 20:19:34 -07:00
parent a9fe466614
commit b4ad8fed1f
8 changed files with 154 additions and 71 deletions

View File

@ -31,8 +31,8 @@ import org.jclouds.scriptbuilder.domain.OsFamily;
import org.jclouds.scriptbuilder.domain.Statement; import org.jclouds.scriptbuilder.domain.Statement;
import org.jclouds.ssh.ExecResponse; import org.jclouds.ssh.ExecResponse;
import org.jclouds.ssh.SshClient; import org.jclouds.ssh.SshClient;
import org.jclouds.util.Utils;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
/** /**
@ -77,8 +77,9 @@ public class InitAndStartScriptOnNode implements SshCallable<ExecResponse> {
protected ExecResponse runCommand(String command) { protected ExecResponse runCommand(String command) {
ExecResponse returnVal; ExecResponse returnVal;
logger.debug(">> running [%s] as %s@%s", command.replace(node.getCredentials().credential, "XXXXX"), node logger.debug(">> running [%s] as %s@%s", command.replace(node.getAdminPassword() != null ? node
.getCredentials().identity, Iterables.get(node.getPublicAddresses(), 0)); .getAdminPassword() : "XXXXX", "XXXXX"), node.getCredentials().identity, Iterables.get(node
.getPublicAddresses(), 0));
returnVal = ssh.exec(command); returnVal = ssh.exec(command);
return returnVal; return returnVal;
} }
@ -89,15 +90,15 @@ public class InitAndStartScriptOnNode implements SshCallable<ExecResponse> {
this.ssh = checkNotNull(ssh, "ssh"); this.ssh = checkNotNull(ssh, "ssh");
} }
protected String execScriptAsRoot(String action) { @VisibleForTesting
public String execScriptAsRoot(String action) {
String command; String command;
if (node.getCredentials().identity.equals("root")) { if (node.getCredentials().identity.equals("root")) {
command = "./" + init.getInstanceName() + " " + action; command = "./" + init.getInstanceName() + " " + action;
} else if (Utils.isPrivateKeyCredential(node.getCredentials())) { } else if (node.getAdminPassword() != null) {
command = "sudo ./" + init.getInstanceName() + " " + action; command = String.format("echo '%s'|sudo -S ./%s %s", node.getAdminPassword(), init.getInstanceName(), action);
} else { } else {
command = String.format("echo '%s'|sudo -S ./%s %s", node.getCredentials().credential, init.getInstanceName(), command = "sudo ./" + init.getInstanceName() + " " + action;
action);
} }
return command; return command;
} }

View File

@ -19,6 +19,8 @@
package org.jclouds.compute.domain; package org.jclouds.compute.domain;
import javax.annotation.Nullable;
import org.jclouds.compute.domain.internal.ImageImpl; import org.jclouds.compute.domain.internal.ImageImpl;
import org.jclouds.domain.Credentials; import org.jclouds.domain.Credentials;
@ -48,6 +50,17 @@ public interface Image extends ComputeMetadata {
*/ */
String getDescription(); String getDescription();
/**
* secures access to root with a password. This password is required to access either the console
* or run sudo as root.
* <p/>
* ex. {@code echo 'password' |sudo -S command}
*
* @return root or console password, if configured, or null.
*/
@Nullable
String getAdminPassword();
/** /**
* Default credentials for the current image * Default credentials for the current image
*/ */

View File

@ -37,6 +37,8 @@ public class ImageBuilder extends ComputeMetadataBuilder {
private OperatingSystem operatingSystem; private OperatingSystem operatingSystem;
private String version; private String version;
private String description; private String description;
@Nullable
private String adminPassword;
private Credentials defaultCredentials; private Credentials defaultCredentials;
public ImageBuilder() { public ImageBuilder() {
@ -58,6 +60,11 @@ public class ImageBuilder extends ComputeMetadataBuilder {
return this; return this;
} }
public ImageBuilder adminPassword(@Nullable String adminPassword) {
this.adminPassword = adminPassword;
return this;
}
public ImageBuilder defaultCredentials(@Nullable Credentials defaultCredentials) { public ImageBuilder defaultCredentials(@Nullable Credentials defaultCredentials) {
this.defaultCredentials = defaultCredentials; this.defaultCredentials = defaultCredentials;
return this; return this;
@ -101,7 +108,14 @@ public class ImageBuilder extends ComputeMetadataBuilder {
@Override @Override
public Image build() { public Image build() {
return new ImageImpl(providerId, name, id, location, uri, userMetadata, operatingSystem, description, version, return new ImageImpl(providerId, name, id, location, uri, userMetadata, operatingSystem, description, version,
defaultCredentials); adminPassword, defaultCredentials);
}
public static ImageBuilder fromImage(Image image) {
return new ImageBuilder().providerId(image.getProviderId()).name(image.getName()).id(image.getId()).location(
image.getLocation()).uri(image.getUri()).userMetadata(image.getUserMetadata()).version(
image.getVersion()).description(image.getDescription()).operatingSystem(image.getOperatingSystem())
.adminPassword(image.getAdminPassword()).defaultCredentials(image.getDefaultCredentials());
} }
} }

View File

@ -75,6 +75,17 @@ public interface NodeMetadata extends ComputeMetadata {
*/ */
int getLoginPort(); int getLoginPort();
/**
* secures access to root with a password. This password is required to access either the console
* or run sudo as root.
* <p/>
* ex. {@code echo 'password' |sudo -S command}
*
* @return root or console password, if configured, or null.
*/
@Nullable
String getAdminPassword();
/** /**
* If possible, these are returned upon all detail requests. However, it is often the case that * If possible, these are returned upon all detail requests. However, it is often the case that
* credentials are only available at "run" time. * credentials are only available at "run" time.

View File

@ -42,6 +42,8 @@ public class NodeMetadataBuilder extends ComputeMetadataBuilder {
private Set<String> publicAddresses = Sets.newLinkedHashSet(); private Set<String> publicAddresses = Sets.newLinkedHashSet();
private Set<String> privateAddresses = Sets.newLinkedHashSet(); private Set<String> privateAddresses = Sets.newLinkedHashSet();
@Nullable @Nullable
private String adminPassword;
@Nullable
private Credentials credentials; private Credentials credentials;
@Nullable @Nullable
private String tag; private String tag;
@ -82,6 +84,11 @@ public class NodeMetadataBuilder extends ComputeMetadataBuilder {
return this; return this;
} }
public NodeMetadataBuilder adminPassword(@Nullable String adminPassword) {
this.adminPassword = adminPassword;
return this;
}
public NodeMetadataBuilder tag(@Nullable String tag) { public NodeMetadataBuilder tag(@Nullable String tag) {
this.tag = tag; this.tag = tag;
return this; return this;
@ -140,15 +147,16 @@ public class NodeMetadataBuilder extends ComputeMetadataBuilder {
@Override @Override
public NodeMetadata build() { public NodeMetadata build() {
return new NodeMetadataImpl(providerId, name, id, location, uri, userMetadata, tag, hardware, imageId, os, state, return new NodeMetadataImpl(providerId, name, id, location, uri, userMetadata, tag, hardware, imageId, os, state,
loginPort, publicAddresses, privateAddresses, credentials); loginPort, publicAddresses, privateAddresses, adminPassword, credentials);
} }
public static NodeMetadataBuilder fromNodeMetadata(NodeMetadata node) { public static NodeMetadataBuilder fromNodeMetadata(NodeMetadata node) {
return new NodeMetadataBuilder().providerId(node.getProviderId()).name(node.getName()).id(node.getId()) return new NodeMetadataBuilder().providerId(node.getProviderId()).name(node.getName()).id(node.getId()).location(
.location(node.getLocation()).uri(node.getUri()).userMetadata(node.getUserMetadata()).tag(node.getTag()) node.getLocation()).uri(node.getUri()).userMetadata(node.getUserMetadata()).tag(node.getTag()).hardware(
.hardware(node.getHardware()).imageId(node.getImageId()).operatingSystem(node.getOperatingSystem()) node.getHardware()).imageId(node.getImageId()).operatingSystem(node.getOperatingSystem()).state(
.state(node.getState()).loginPort(node.getLoginPort()).publicAddresses(node.getPublicAddresses()) node.getState()).loginPort(node.getLoginPort()).publicAddresses(node.getPublicAddresses())
.privateAddresses(node.getPrivateAddresses()).credentials(node.getCredentials()); .privateAddresses(node.getPrivateAddresses()).adminPassword(node.getAdminPassword()).credentials(
node.getCredentials());
} }
} }

View File

@ -43,15 +43,18 @@ public class ImageImpl extends ComputeMetadataImpl implements Image {
private final OperatingSystem operatingSystem; private final OperatingSystem operatingSystem;
private final String version; private final String version;
private final String description; private final String description;
@Nullable
private final String adminPassword;
private final Credentials defaultCredentials; private final Credentials defaultCredentials;
public ImageImpl(String providerId, String name, String id, Location location, URI uri, public ImageImpl(String providerId, String name, String id, Location location, URI uri,
Map<String, String> userMetadata, OperatingSystem operatingSystem, String description, Map<String, String> userMetadata, OperatingSystem operatingSystem, String description,
@Nullable String version, @Nullable Credentials defaultCredentials) { @Nullable String version, @Nullable String adminPassword, @Nullable Credentials defaultCredentials) {
super(ComputeType.IMAGE, providerId, name, id, location, uri, userMetadata); super(ComputeType.IMAGE, providerId, name, id, location, uri, userMetadata);
this.operatingSystem = checkNotNull(operatingSystem, "operatingSystem"); this.operatingSystem = checkNotNull(operatingSystem, "operatingSystem");
this.version = version; this.version = version;
this.description = checkNotNull(description, "description"); this.description = checkNotNull(description, "description");
this.adminPassword = adminPassword;
this.defaultCredentials = defaultCredentials; this.defaultCredentials = defaultCredentials;
} }
@ -87,6 +90,14 @@ public class ImageImpl extends ComputeMetadataImpl implements Image {
return defaultCredentials; return defaultCredentials;
} }
/**
* {@inheritDoc}
*/
@Override
public String getAdminPassword() {
return adminPassword;
}
@Override @Override
public String toString() { public String toString() {
return "[id=" + getId() + ", name=" + getName() + ", operatingSystem=" + operatingSystem + ", description=" return "[id=" + getId() + ", name=" + getName() + ", operatingSystem=" + operatingSystem + ", description="
@ -99,6 +110,7 @@ public class ImageImpl extends ComputeMetadataImpl implements Image {
public int hashCode() { public int hashCode() {
final int prime = 31; final int prime = 31;
int result = super.hashCode(); int result = super.hashCode();
result = prime * result + ((adminPassword == null) ? 0 : adminPassword.hashCode());
result = prime * result + ((defaultCredentials == null) ? 0 : defaultCredentials.hashCode()); result = prime * result + ((defaultCredentials == null) ? 0 : defaultCredentials.hashCode());
result = prime * result + ((description == null) ? 0 : description.hashCode()); result = prime * result + ((description == null) ? 0 : description.hashCode());
result = prime * result + ((operatingSystem == null) ? 0 : operatingSystem.hashCode()); result = prime * result + ((operatingSystem == null) ? 0 : operatingSystem.hashCode());
@ -115,6 +127,11 @@ public class ImageImpl extends ComputeMetadataImpl implements Image {
if (getClass() != obj.getClass()) if (getClass() != obj.getClass())
return false; return false;
ImageImpl other = (ImageImpl) obj; ImageImpl other = (ImageImpl) obj;
if (adminPassword == null) {
if (other.adminPassword != null)
return false;
} else if (!adminPassword.equals(other.adminPassword))
return false;
if (defaultCredentials == null) { if (defaultCredentials == null) {
if (other.defaultCredentials != null) if (other.defaultCredentials != null)
return false; return false;

View File

@ -51,6 +51,8 @@ public class NodeMetadataImpl extends ComputeMetadataImpl implements NodeMetadat
private final Set<String> publicAddresses; private final Set<String> publicAddresses;
private final Set<String> privateAddresses; private final Set<String> privateAddresses;
@Nullable @Nullable
private final String adminPassword;
@Nullable
private final Credentials credentials; private final Credentials credentials;
@Nullable @Nullable
private final String tag; private final String tag;
@ -62,9 +64,10 @@ public class NodeMetadataImpl extends ComputeMetadataImpl implements NodeMetadat
private final OperatingSystem os; private final OperatingSystem os;
public NodeMetadataImpl(String providerId, String name, String id, Location location, URI uri, public NodeMetadataImpl(String providerId, String name, String id, Location location, URI uri,
Map<String, String> userMetadata, @Nullable String tag, @Nullable Hardware hardware, @Nullable String imageId, Map<String, String> userMetadata, @Nullable String tag, @Nullable Hardware hardware,
@Nullable OperatingSystem os, NodeState state, int loginPort, Iterable<String> publicAddresses, @Nullable String imageId, @Nullable OperatingSystem os, NodeState state, int loginPort,
Iterable<String> privateAddresses, @Nullable Credentials credentials) { Iterable<String> publicAddresses, Iterable<String> privateAddresses, @Nullable String adminPassword,
@Nullable Credentials credentials) {
super(ComputeType.NODE, providerId, name, id, location, uri, userMetadata); super(ComputeType.NODE, providerId, name, id, location, uri, userMetadata);
this.tag = tag; this.tag = tag;
this.hardware = hardware; this.hardware = hardware;
@ -74,6 +77,7 @@ public class NodeMetadataImpl extends ComputeMetadataImpl implements NodeMetadat
this.loginPort = loginPort; this.loginPort = loginPort;
this.publicAddresses = ImmutableSet.copyOf(checkNotNull(publicAddresses, "publicAddresses")); this.publicAddresses = ImmutableSet.copyOf(checkNotNull(publicAddresses, "publicAddresses"));
this.privateAddresses = ImmutableSet.copyOf(checkNotNull(privateAddresses, "privateAddresses")); this.privateAddresses = ImmutableSet.copyOf(checkNotNull(privateAddresses, "privateAddresses"));
this.adminPassword = adminPassword;
this.credentials = credentials; this.credentials = credentials;
} }
@ -93,6 +97,14 @@ public class NodeMetadataImpl extends ComputeMetadataImpl implements NodeMetadat
return hardware; return hardware;
} }
/**
* {@inheritDoc}
*/
@Override
public String getAdminPassword() {
return adminPassword;
}
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@ -153,10 +165,10 @@ public class NodeMetadataImpl extends ComputeMetadataImpl implements NodeMetadat
public String toString() { public String toString() {
return "[id=" + getId() + ", providerId=" + getProviderId() + ", tag=" + getTag() + ", name=" + getName() return "[id=" + getId() + ", providerId=" + getProviderId() + ", tag=" + getTag() + ", name=" + getName()
+ ", location=" + getLocation() + ", uri=" + getUri() + ", imageId=" + getImageId() + ", os=" + ", location=" + getLocation() + ", uri=" + getUri() + ", imageId=" + getImageId() + ", os="
+ getOperatingSystem() + ", state=" + getState() + ", loginPort=" + getLoginPort() + ", privateAddresses=" + getOperatingSystem() + ", state=" + getState() + ", loginPort=" + getLoginPort()
+ privateAddresses + ", publicAddresses=" + publicAddresses + ", hardware=" + getHardware() + ", privateAddresses=" + privateAddresses + ", publicAddresses=" + publicAddresses + ", hardware="
+ ", loginUser=" + ((credentials != null) ? credentials.identity : null) + ", userMetadata=" + getHardware() + ", loginUser=" + ((credentials != null) ? credentials.identity : null)
+ getUserMetadata() + "]"; + ", userMetadata=" + getUserMetadata() + "]";
} }
@Override @Override
@ -170,6 +182,7 @@ public class NodeMetadataImpl extends ComputeMetadataImpl implements NodeMetadat
result = prime * result + ((imageId == null) ? 0 : imageId.hashCode()); result = prime * result + ((imageId == null) ? 0 : imageId.hashCode());
result = prime * result + ((hardware == null) ? 0 : hardware.hashCode()); result = prime * result + ((hardware == null) ? 0 : hardware.hashCode());
result = prime * result + ((os == null) ? 0 : os.hashCode()); result = prime * result + ((os == null) ? 0 : os.hashCode());
result = prime * result + ((adminPassword == null) ? 0 : adminPassword.hashCode());
result = prime * result + ((credentials == null) ? 0 : credentials.hashCode()); result = prime * result + ((credentials == null) ? 0 : credentials.hashCode());
return result; return result;
} }
@ -215,6 +228,11 @@ public class NodeMetadataImpl extends ComputeMetadataImpl implements NodeMetadat
return false; return false;
} else if (!os.equals(other.os)) } else if (!os.equals(other.os))
return false; return false;
if (adminPassword == null) {
if (other.adminPassword != null)
return false;
} else if (!adminPassword.equals(other.adminPassword))
return false;
if (credentials == null) { if (credentials == null) {
if (other.credentials != null) if (other.credentials != null)
return false; return false;

View File

@ -158,8 +158,8 @@ public abstract class BaseComputeServiceLiveTest {
if (context != null) if (context != null)
context.close(); context.close();
Properties props = setupProperties(); Properties props = setupProperties();
context = new ComputeServiceContextFactory().createContext(provider, context = new ComputeServiceContextFactory().createContext(provider, ImmutableSet.of(new Log4JLoggingModule(),
ImmutableSet.of(new Log4JLoggingModule(), getSshModule()), props); getSshModule()), props);
client = context.getComputeService(); client = context.getComputeService();
} }
@ -170,8 +170,8 @@ public abstract class BaseComputeServiceLiveTest {
public void testCorrectAuthException() throws Exception { public void testCorrectAuthException() throws Exception {
ComputeServiceContext context = null; ComputeServiceContext context = null;
try { try {
context = new ComputeServiceContextFactory().createContext(provider, "MOMMA", "MIA", context = new ComputeServiceContextFactory().createContext(provider, "MOMMA", "MIA", ImmutableSet
ImmutableSet.<Module> of(new Log4JLoggingModule())); .<Module> of(new Log4JLoggingModule()));
context.getComputeService().listNodes(); context.getComputeService().listNodes();
} catch (AuthorizationException e) { } catch (AuthorizationException e) {
throw e; throw e;
@ -310,8 +310,8 @@ public abstract class BaseComputeServiceLiveTest {
protected void checkOsMatchesTemplate(NodeMetadata node) { protected void checkOsMatchesTemplate(NodeMetadata node) {
if (node.getOperatingSystem() != null) if (node.getOperatingSystem() != null)
assert node.getOperatingSystem().getFamily().equals(template.getImage().getOperatingSystem().getFamily()) : String assert node.getOperatingSystem().getFamily().equals(template.getImage().getOperatingSystem().getFamily()) : String
.format("expecting family %s but got %s", template.getImage().getOperatingSystem().getFamily(), .format("expecting family %s but got %s", template.getImage().getOperatingSystem().getFamily(), node
node.getOperatingSystem()); .getOperatingSystem());
} }
void assertLocationSameOrChild(Location test, Location expected) { void assertLocationSameOrChild(Location test, Location expected) {
@ -358,7 +358,8 @@ public abstract class BaseComputeServiceLiveTest {
assertNotNull(node.getTag()); assertNotNull(node.getTag());
assertEquals(node.getTag(), tag); assertEquals(node.getTag(), tag);
assertEquals(node.getState(), NodeState.RUNNING); assertEquals(node.getState(), NodeState.RUNNING);
assertEquals(context.getCredentialStore().get(node.getId()), node.getCredentials()); Credentials fromStore = context.getCredentialStore().get(node.getId());
assertEquals(fromStore, node.getCredentials());
assert node.getPublicAddresses().size() >= 1 || node.getPrivateAddresses().size() >= 1 : "no ips in" + node; assert node.getPublicAddresses().size() >= 1 || node.getPrivateAddresses().size() >= 1 : "no ips in" + node;
assertNotNull(node.getCredentials()); assertNotNull(node.getCredentials());
if (node.getCredentials().identity != null) { if (node.getCredentials().identity != null) {
@ -375,8 +376,8 @@ public abstract class BaseComputeServiceLiveTest {
@Test(enabled = true, dependsOnMethods = "testCreateAnotherNodeWithANewContextToEnsureSharedMemIsntRequired") @Test(enabled = true, dependsOnMethods = "testCreateAnotherNodeWithANewContextToEnsureSharedMemIsntRequired")
public void testGet() throws Exception { public void testGet() throws Exception {
Map<String, ? extends NodeMetadata> metadataMap = newLinkedHashMap(uniqueIndex( Map<String, ? extends NodeMetadata> metadataMap = newLinkedHashMap(uniqueIndex(filter(client
filter(client.listNodesDetailsMatching(all()), and(withTag(tag), not(TERMINATED))), .listNodesDetailsMatching(all()), and(withTag(tag), not(TERMINATED))),
new Function<NodeMetadata, String>() { new Function<NodeMetadata, String>() {
@Override @Override