Issue 309: support CRUD on instances, w/incidental security group fns

This commit is contained in:
Adrian Cole 2012-07-25 22:42:05 -07:00
parent 4ef5d60ce6
commit 0bc602a3d2
30 changed files with 2117 additions and 259 deletions

View File

@ -0,0 +1,79 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.rds.binders;
import static com.google.common.base.Preconditions.checkNotNull;
import org.jclouds.http.HttpRequest;
import org.jclouds.rds.domain.InstanceRequest;
import com.google.common.collect.ImmutableMultimap;
/**
*
* @see <a
* href="http://docs.amazonwebservices.com/AmazonRDS/latest/APIReference/API_CreateDBInstance.html"
* >doc</a>
*
* @author Adrian Cole
*/
public class BindInstanceRequestToFormParams implements org.jclouds.rest.Binder {
/**
* {@inheritDoc}
*/
@SuppressWarnings("unchecked")
@Override
public <R extends HttpRequest> R bindToRequest(R request, Object input) {
InstanceRequest instanceRequest = InstanceRequest.class.cast(checkNotNull(input, "instanceRequest must be set!"));
ImmutableMultimap.Builder<String, String> formParameters = ImmutableMultimap.builder();
formParameters.put("AllocatedStorage", instanceRequest.getAllocatedStorageGB() + "");
formParameters.put("AutoMinorVersionUpgrade", instanceRequest.isAutoMinorVersionUpgrade() + "");
formParameters.put("BackupRetentionPeriod", instanceRequest.getBackupRetentionPeriod() + "");
if (instanceRequest.getCharacterSet().isPresent())
formParameters.put("CharacterSetName", instanceRequest.getCharacterSet().get());
formParameters.put("DBInstanceClass", instanceRequest.getInstanceClass());
if (instanceRequest.getName().isPresent())
formParameters.put("DBName", instanceRequest.getName().get());
if (instanceRequest.getParameterGroup().isPresent())
formParameters.put("DBParameterGroupName", instanceRequest.getParameterGroup().get());
int groupIndex = 1;
for (String securityGroup : instanceRequest.getSecurityGroups())
formParameters.put("DBSecurityGroups.member." + groupIndex++, securityGroup);
if (instanceRequest.getSubnetGroup().isPresent())
formParameters.put("DBSubnetGroupName", instanceRequest.getSubnetGroup().get());
formParameters.put("Engine", instanceRequest.getEngine());
if (instanceRequest.getEngineVersion().isPresent())
formParameters.put("EngineVersion", instanceRequest.getEngineVersion().get());
if (instanceRequest.getLicenseModel().isPresent())
formParameters.put("LicenseModel", instanceRequest.getLicenseModel().get());
formParameters.put("MasterUserPassword", instanceRequest.getMasterPassword());
formParameters.put("MasterUsername", instanceRequest.getMasterUsername());
if (instanceRequest.getOptionGroup().isPresent())
formParameters.put("OptionGroupName", instanceRequest.getOptionGroup().get());
if (instanceRequest.getPort().isPresent())
formParameters.put("Port", instanceRequest.getPort().get().toString());
return (R) request.toBuilder().replaceFormParams(formParameters.build()).build();
}
}

View File

@ -0,0 +1,151 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.rds.domain;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.base.CaseFormat;
import com.google.common.base.Objects;
/**
*
* @author Adrian Cole
*/
public class Authorization {
/**
* Status of a source of traffic to the security group
*/
public static enum Status {
AUTHORIZING, AUTHORIZED, REVOKING, UNRECOGNIZED;
public String value() {
return name().toLowerCase();
}
@Override
public String toString() {
return value();
}
public static Status fromValue(String status) {
try {
return valueOf(CaseFormat.LOWER_HYPHEN.to(CaseFormat.UPPER_UNDERSCORE, checkNotNull(status, "status")));
} catch (IllegalArgumentException e) {
return UNRECOGNIZED;
}
}
}
public static Builder<?> builder() {
return new ConcreteBuilder();
}
public Builder<?> toBuilder() {
return new ConcreteBuilder().fromAuthorization(this);
}
public static abstract class Builder<T extends Builder<T>> {
protected abstract T self();
protected String rawStatus;
protected Status status;
/**
* @see Authorization#getRawStatus()
*/
public T rawStatus(String rawStatus) {
this.rawStatus = rawStatus;
return self();
}
/**
* @see Authorization#getStatus()
*/
public T status(Status status) {
this.status = status;
return self();
}
public T fromAuthorization(Authorization in) {
return this.rawStatus(in.getRawStatus()).status(in.getStatus());
}
}
private static class ConcreteBuilder extends Builder<ConcreteBuilder> {
@Override
protected ConcreteBuilder self() {
return this;
}
}
protected final String rawStatus;
protected final Status status;
protected Authorization(String rawStatus, Status status) {
this.rawStatus = checkNotNull(rawStatus, "rawStatus");
this.status = checkNotNull(status, "status");
}
/**
* Specifies the status of the authorization.
*/
public Status getStatus() {
return status;
}
/**
* Specifies the status of the authorization.
*/
public String getRawStatus() {
return rawStatus;
}
/**
* {@inheritDoc}
*/
@Override
public int hashCode() {
return Objects.hashCode(rawStatus);
}
/**
* {@inheritDoc}
*/
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Authorization other = (Authorization) obj;
return Objects.equal(this.rawStatus, other.rawStatus);
}
/**
* {@inheritDoc}
*/
@Override
public String toString() {
return Objects.toStringHelper(this).omitNullValues().add("status", rawStatus).toString();
}
}

View File

@ -31,7 +31,7 @@ import com.google.common.base.Optional;
*
* @author Adrian Cole
*/
public class EC2SecurityGroup {
public class EC2SecurityGroup extends Authorization {
public static Builder builder() {
return new Builder();
@ -41,12 +41,11 @@ public class EC2SecurityGroup {
return new Builder().fromEC2SecurityGroup(this);
}
public static class Builder {
public static class Builder extends Authorization.Builder<Builder> {
protected Optional<String> id = Optional.absent();
protected String name;
protected String ownerId;
protected String status;
/**
* @see EC2SecurityGroup#getId()
@ -72,33 +71,29 @@ public class EC2SecurityGroup {
return this;
}
/**
* @see EC2SecurityGroup#getStatus()
*/
public Builder status(String status) {
this.status = status;
return this;
}
public EC2SecurityGroup build() {
return new EC2SecurityGroup(id, name, ownerId, status);
return new EC2SecurityGroup(id, name, ownerId, rawStatus, status);
}
public Builder fromEC2SecurityGroup(EC2SecurityGroup in) {
return this.id(in.getId().orNull()).name(in.getName()).ownerId(in.getOwnerId()).status(in.getStatus());
return fromAuthorization(in).id(in.getId().orNull()).name(in.getName()).ownerId(in.getOwnerId());
}
@Override
protected Builder self() {
return this;
}
}
protected final Optional<String> id;
protected final String name;
protected final String ownerId;
protected final String status;
protected EC2SecurityGroup(Optional<String> id, String name, String ownerId, String status) {
protected EC2SecurityGroup(Optional<String> id, String name, String ownerId, String rawStatus, Status status) {
super(rawStatus, status);
this.id = checkNotNull(id, "id");
this.name = checkNotNull(name, "name");
this.ownerId = checkNotNull(ownerId, "ownerId");
this.status = checkNotNull(status, "status");
}
/**
@ -122,13 +117,6 @@ public class EC2SecurityGroup {
return ownerId;
}
/**
* Provides the status of the EC2 security group.
*/
public String getStatus() {
return status;
}
/**
* {@inheritDoc}
*/
@ -159,7 +147,7 @@ public class EC2SecurityGroup {
@Override
public String toString() {
return Objects.toStringHelper(this).omitNullValues().add("id", id.orNull()).add("name", name)
.add("ownerId", ownerId).add("status", status).toString();
.add("ownerId", ownerId).add("status", rawStatus).toString();
}
}

View File

@ -29,7 +29,7 @@ import com.google.common.base.Objects;
*
* @author Adrian Cole
*/
public class IPRange {
public class IPRange extends Authorization {
public static Builder builder() {
return new Builder();
@ -39,42 +39,37 @@ public class IPRange {
return new Builder().fromIPRange(this);
}
public static class Builder {
public static class Builder extends Authorization.Builder<Builder> {
protected String cidrIp;
protected String status;
/**
* @see IPRange#getAvailabilityZone()
* @see IPRange#getCidrIp()
*/
public Builder cidrIp(String cidrIp) {
this.cidrIp = cidrIp;
return this;
}
/**
* @see IPRange#getStatus()
*/
public Builder status(String status) {
this.status = status;
return this;
}
public IPRange build() {
return new IPRange(cidrIp, status);
return new IPRange(cidrIp, rawStatus, status);
}
public Builder fromIPRange(IPRange in) {
return this.cidrIp(in.getCIDRIP()).status(in.getStatus());
return fromAuthorization(in).cidrIp(in.getCIDRIP());
}
@Override
protected Builder self() {
return this;
}
}
protected final String cidrIp;
protected final String status;
protected IPRange(String cidrIp, String status) {
protected IPRange(String cidrIp, String rawStatus, Status status) {
super(rawStatus, status);
this.cidrIp = checkNotNull(cidrIp, "cidrIp");
this.status = checkNotNull(status, "status");
}
/**
@ -84,19 +79,12 @@ public class IPRange {
return cidrIp;
}
/**
* Specifies the status of the IP range.
*/
public String getStatus() {
return status;
}
/**
* {@inheritDoc}
*/
@Override
public int hashCode() {
return Objects.hashCode(cidrIp, status);
return Objects.hashCode(cidrIp, rawStatus);
}
/**
@ -111,7 +99,7 @@ public class IPRange {
if (getClass() != obj.getClass())
return false;
IPRange other = IPRange.class.cast(obj);
return Objects.equal(this.cidrIp, other.cidrIp) && Objects.equal(this.status, other.status);
return Objects.equal(this.cidrIp, other.cidrIp) && Objects.equal(this.rawStatus, other.rawStatus);
}
/**
@ -119,8 +107,7 @@ public class IPRange {
*/
@Override
public String toString() {
return Objects.toStringHelper(this).omitNullValues().add("cidrIp", cidrIp)
.add("status", status).toString();
return Objects.toStringHelper(this).omitNullValues().add("cidrIp", cidrIp).add("status", rawStatus).toString();
}
}

View File

@ -23,6 +23,9 @@ import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Date;
import java.util.Map;
import org.jclouds.rds.domain.internal.BaseInstance;
import com.google.common.base.CaseFormat;
import com.google.common.base.Objects;
import com.google.common.base.Optional;
import com.google.common.collect.ImmutableMap;
@ -57,7 +60,41 @@ import com.google.common.net.HostAndPort;
*
* @author Adrian Cole
*/
public class Instance {
public class Instance extends BaseInstance {
public static enum Status {
/**
* the instance is in the process of being created
*/
CREATING,
/**
* the instance is available
*/
AVAILABLE, STORAGE_FULL, INCOMPATIBLE_OPTION_GROUP, INCOMPATIBLE_PARAMETERS, INCOMPATIBLE_RESTORE, FAILED,
/**
* the instance is deleting
*/
DELETING, UNRECOGNIZED;
public String value() {
return name().toLowerCase();
}
@Override
public String toString() {
return value();
}
public static Status fromValue(String status) {
try {
return valueOf(CaseFormat.LOWER_HYPHEN.to(CaseFormat.UPPER_UNDERSCORE, checkNotNull(status, "status")));
} catch (IllegalArgumentException e) {
return UNRECOGNIZED;
}
}
}
public static Builder<?> builder() {
return new ConcreteBuilder();
}
@ -66,22 +103,17 @@ public class Instance {
return new ConcreteBuilder().fromInstance(this);
}
public static abstract class Builder<T extends Builder<T>> {
protected abstract T self();
public static abstract class Builder<T extends Builder<T>> extends BaseInstance.Builder<T> {
protected String id;
protected Optional<String> name = Optional.absent();
protected String instanceClass;
protected HostAndPort endpoint;
protected String status;
protected String availabilityZone;
protected boolean multiAZ;
protected String engine;
protected Optional<HostAndPort> endpoint = Optional.absent();
protected String engineVersion;
protected String rawStatus;
protected Status status;
protected Optional<Date> createdTime = Optional.absent();
protected String licenseModel;
protected String masterUsername;
protected int allocatedStorageGB;
protected Date createdTime;
protected Optional<String> availabilityZone = Optional.absent();
protected boolean multiAZ;
protected Optional<SubnetGroup> subnetGroup = Optional.absent();
protected ImmutableMap.Builder<String, String> securityGroupNameToStatus = ImmutableMap
.<String, String> builder();
@ -94,62 +126,30 @@ public class Instance {
return self();
}
/**
* @see Instance#getName()
*/
public T name(String name) {
this.name = Optional.fromNullable(name);
return self();
}
/**
* @see Instance#getInstanceClass()
*/
public T instanceClass(String instanceClass) {
this.instanceClass = instanceClass;
return self();
}
/**
* @see Instance#getEndpoint()
*/
public T endpoint(HostAndPort endpoint) {
this.endpoint = endpoint;
this.endpoint = Optional.fromNullable(endpoint);
return self();
}
/**
* @see Instance#getRawStatus()
*/
public T rawStatus(String rawStatus) {
this.rawStatus = rawStatus;
return self();
}
/**
* @see Instance#getStatus()
*/
public T status(String status) {
public T status(Status status) {
this.status = status;
return self();
}
/**
* @see Instance#getAvailabilityZone()
*/
public T availabilityZone(String availabilityZone) {
this.availabilityZone = availabilityZone;
return self();
}
/**
* @see Instance#isMultiAZ()
*/
public T multiAZ(boolean multiAZ) {
this.multiAZ = multiAZ;
return self();
}
/**
* @see Instance#getEngine()
*/
public T engine(String engine) {
this.engine = engine;
return self();
}
/**
* @see Instance#getEngineVersion()
*/
@ -166,27 +166,27 @@ public class Instance {
return self();
}
/**
* @see Instance#getMasterUsername()
*/
public T masterUsername(String masterUsername) {
this.masterUsername = masterUsername;
return self();
}
/**
* @see Instance#getAllocatedStorageGB()
*/
public T allocatedStorageGB(int allocatedStorageGB) {
this.allocatedStorageGB = allocatedStorageGB;
return self();
}
/**
* @see Instance#getCreatedTime()
*/
public T createdTime(Date createdTime) {
this.createdTime = createdTime;
this.createdTime = Optional.fromNullable(createdTime);
return self();
}
/**
* @see Instance#getAvailabilityZone()
*/
public T availabilityZone(String availabilityZone) {
this.availabilityZone = Optional.fromNullable(availabilityZone);
return self();
}
/**
* @see Instance#isMultiAZ()
*/
public T multiAZ(boolean multiAZ) {
this.multiAZ = multiAZ;
return self();
}
@ -216,18 +216,16 @@ public class Instance {
}
public Instance build() {
return new Instance(id, name, instanceClass, endpoint, status, availabilityZone, multiAZ, engine,
return new Instance(id, name, instanceClass, endpoint, rawStatus, status, availabilityZone, multiAZ, engine,
engineVersion, licenseModel, masterUsername, allocatedStorageGB, createdTime, subnetGroup,
securityGroupNameToStatus.build());
}
public T fromInstance(Instance in) {
return this.id(in.getId()).name(in.getName().orNull()).instanceClass(in.getInstanceClass())
.endpoint(in.getEndpoint()).status(in.getStatus()).availabilityZone(in.getAvailabilityZone())
.multiAZ(in.isMultiAZ()).engine(in.getEngine()).engineVersion(in.getEngineVersion())
.licenseModel(in.getLicenseModel()).masterUsername(in.getMasterUsername())
.allocatedStorageGB(in.getAllocatedStorageGB()).createdTime(in.getCreatedTime())
.subnetGroup(in.getSubnetGroup().orNull())
return fromBaseInstance(in).id(in.getId()).endpoint(in.getEndpoint().orNull()).status(in.getStatus())
.createdTime(in.getCreatedTime().orNull()).engineVersion(in.getEngineVersion())
.licenseModel(in.getLicenseModel()).availabilityZone(in.getAvailabilityZone().orNull())
.multiAZ(in.isMultiAZ()).subnetGroup(in.getSubnetGroup().orNull())
.securityGroupNameToStatus(in.getSecurityGroupNameToStatus());
}
}
@ -240,37 +238,30 @@ public class Instance {
}
protected final String id;
protected final Optional<String> name;
protected final String instanceClass;
protected final HostAndPort endpoint;
protected final String status;
protected final String availabilityZone;
protected final boolean multiAZ;
protected final String engine;
protected final Optional<HostAndPort> endpoint;
protected final String rawStatus;
protected final Status status;
protected final Optional<Date> createdTime;
protected final String engineVersion;
protected final String licenseModel;
protected final String masterUsername;
protected int allocatedStorageGB;
protected final Date createdTime;
protected final Optional<String> availabilityZone;
protected final boolean multiAZ;
protected final Optional<SubnetGroup> subnetGroup;
protected final Map<String, String> securityGroupNameToStatus;
protected Instance(String id, Optional<String> name, String instanceClass, HostAndPort endpoint, String status,
String availabilityZone, boolean multiAZ, String engine, String engineVersion, String licenseModel,
String masterUsername, int allocatedStorageGB, Date createdTime, Optional<SubnetGroup> subnetGroup,
Map<String, String> securityGroupNameToStatus) {
protected Instance(String id, Optional<String> name, String instanceClass, Optional<HostAndPort> endpoint,
String rawStatus, Status status, Optional<String> availabilityZone, boolean multiAZ, String engine,
String engineVersion, String licenseModel, String masterUsername, int allocatedStorageGB,
Optional<Date> createdTime, Optional<SubnetGroup> subnetGroup, Map<String, String> securityGroupNameToStatus) {
super(name, instanceClass, engine, masterUsername, allocatedStorageGB);
this.id = checkNotNull(id, "id");
this.name = checkNotNull(name, "name of %s", id);
this.endpoint = checkNotNull(endpoint, "endpoint of %s", id);
this.status = checkNotNull(status, "status of %s", id);
this.instanceClass = checkNotNull(instanceClass, "instanceClass of %s", id);
this.availabilityZone = checkNotNull(availabilityZone, "availabilityZone of %s", id);
this.multiAZ = multiAZ;
this.engine = checkNotNull(engine, "engine of %s", id);
this.endpoint = checkNotNull(endpoint, "endpoint of %s", id);
this.rawStatus = checkNotNull(rawStatus, "rawStatus of %s", id);
this.status = checkNotNull(status, "status of %s", id);
this.engineVersion = checkNotNull(engineVersion, "engineVersion of %s", id);
this.licenseModel = checkNotNull(licenseModel, "licenseModel of %s", id);
this.masterUsername = checkNotNull(masterUsername, "masterUsername of %s", id);
this.allocatedStorageGB = allocatedStorageGB;
this.createdTime = checkNotNull(createdTime, "createdTime of %s", id);
this.subnetGroup = checkNotNull(subnetGroup, "subnetGroup of %s", id);
this.securityGroupNameToStatus = ImmutableMap.copyOf(checkNotNull(securityGroupNameToStatus,
@ -285,63 +276,33 @@ public class Instance {
return id;
}
/**
* The meaning of this parameter differs according to the database engine you use.
*
* <h4>MySQL</h4>
*
* Contains the name of the initial database of this instance that was provided at create time,
* if one was specified when the DB Instance was created. This same name is returned for the life
* of the DB Instance.
*
* <h4>Oracle</h4>
*
* Contains the Oracle System ID (SID) of the created DB Instance.
*/
public Optional<String> getName() {
return name;
}
/**
* Specifies the current state of this database.
*/
public String getStatus() {
public Status getStatus() {
return status;
}
/**
* Contains the name of the compute and memory capacity class of the DB Instance.
* Specifies the current state of this database unparsed.
*/
public String getInstanceClass() {
return instanceClass;
public String getRawStatus() {
return rawStatus;
}
/**
* Specifies the connection endpoint.
* Specifies the connection endpoint, or absent if the database is in {@link Status#CREATING} or {@link Status#DELETING} states
*/
public HostAndPort getEndpoint() {
public Optional<HostAndPort> getEndpoint() {
return endpoint;
}
/**
* Specifies the name of the Availability Zone the DB Instance is located in.
* Provides the date and time the DB Instance was created, or absent if the database is in
* {@code creating} state
*/
public String getAvailabilityZone() {
return availabilityZone;
}
/**
* Specifies the name of the Availability Zone the DB Instance is located in.
*/
public boolean isMultiAZ() {
return multiAZ;
}
/**
* Provides the name of the database engine to be used for this DB Instance.
*/
public String getEngine() {
return engine;
public Optional<Date> getCreatedTime() {
return createdTime;
}
/**
@ -359,24 +320,18 @@ public class Instance {
}
/**
* Contains the master username for the DB Instance.
* Specifies the name of the Availability Zone the DB Instance is located in, or absent if the
* database is in {@code creating} state
*/
public String getMasterUsername() {
return masterUsername;
public Optional<String> getAvailabilityZone() {
return availabilityZone;
}
/**
* Specifies the allocated storage size specified in gigabytes.
* Specifies the name of the Availability Zone the DB Instance is located in.
*/
public int getAllocatedStorageGB() {
return allocatedStorageGB;
}
/**
* Provides the date and time the DB Instance was created.
*/
public Date getCreatedTime() {
return createdTime;
public boolean isMultiAZ() {
return multiAZ;
}
/**
@ -394,27 +349,19 @@ public class Instance {
return securityGroupNameToStatus;
}
/**
* {@inheritDoc}
*/
@Override
public int hashCode() {
return Objects.hashCode(id, createdTime);
return Objects.hashCode(id);
}
/**
* {@inheritDoc}
*/
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
if (obj == null || getClass() != obj.getClass())
return false;
if (getClass() != obj.getClass())
return false;
Instance other = (Instance) obj;
return Objects.equal(this.id, other.id) && Objects.equal(this.createdTime, other.createdTime);
Instance that = Instance.class.cast(obj);
return Objects.equal(this.id, that.id);
}
/**
@ -423,11 +370,11 @@ public class Instance {
@Override
public String toString() {
return Objects.toStringHelper(this).omitNullValues().add("id", id).add("name", name.orNull())
.add("instanceClass", instanceClass).add("endpoint", endpoint).add("status", status)
.add("availabilityZone", availabilityZone).add("multiAZ", multiAZ).add("engine", engine)
.add("instanceClass", instanceClass).add("endpoint", endpoint.orNull()).add("status", rawStatus)
.add("availabilityZone", availabilityZone.orNull()).add("multiAZ", multiAZ).add("engine", engine)
.add("engineVersion", engineVersion).add("licenseModel", licenseModel)
.add("masterUsername", masterUsername).add("allocatedStorageGB", allocatedStorageGB)
.add("createdTime", createdTime).add("subnetGroup", subnetGroup.orNull())
.add("createdTime", createdTime.orNull()).add("subnetGroup", subnetGroup.orNull())
.add("securityGroupNameToStatus", securityGroupNameToStatus).toString();
}

View File

@ -0,0 +1,374 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.rds.domain;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Set;
import org.jclouds.rds.domain.internal.BaseInstance;
import com.google.common.base.Objects.ToStringHelper;
import com.google.common.base.Optional;
import com.google.common.collect.ImmutableSet;
/**
* Parameters used to create a new {@link Instance}
*
* @see <a
* href="http://docs.amazonwebservices.com/AmazonRDS/latest/APIReference/API_CreateDBInstance.html"
* >doc</a>
*
* @author Adrian Cole
*/
public class InstanceRequest extends BaseInstance {
public static Builder<?> builder() {
return new ConcreteBuilder();
}
public Builder<?> toBuilder() {
return new ConcreteBuilder().fromInstance(this);
}
public static abstract class Builder<T extends Builder<T>> extends BaseInstance.Builder<T> {
protected Optional<String> engineVersion = Optional.absent();
protected Optional<String> licenseModel = Optional.absent();
protected Optional<Integer> port = Optional.absent();
protected Optional<String> characterSet = Optional.absent();
protected int backupRetentionPeriod = 1;
protected Optional<String> optionGroup = Optional.absent();
protected Optional<String> parameterGroup = Optional.absent();
protected boolean autoMinorVersionUpgrade = true;
protected Optional<String> subnetGroup = Optional.absent();
protected ImmutableSet.Builder<String> securityGroups = ImmutableSet.<String> builder();
protected String masterPassword;
/**
* @see InstanceRequest#getEngineVersion()
*/
public T engineVersion(String engineVersion) {
this.engineVersion = Optional.fromNullable(engineVersion);
return self();
}
/**
* @see InstanceRequest#getLicenseModel()
*/
public T licenseModel(String licenseModel) {
this.licenseModel = Optional.fromNullable(licenseModel);
return self();
}
/**
* @see InstanceRequest#getPort()
*/
public T port(Integer port) {
this.port = Optional.fromNullable(port);
return self();
}
/**
* @see InstanceRequest#getCharacterSet()
*/
public T characterSet(String characterSet) {
this.characterSet = Optional.fromNullable(characterSet);
return self();
}
/**
* @see InstanceRequest#getBackupRetentionPeriod()
*/
public T backupRetentionPeriod(int backupRetentionPeriod) {
this.backupRetentionPeriod = backupRetentionPeriod;
return self();
}
/**
* @see InstanceRequest#getOptionGroup()
*/
public T optionGroup(String optionGroup) {
this.optionGroup = Optional.fromNullable(optionGroup);
return self();
}
/**
* @see InstanceRequest#getParameterGroup()
*/
public T parameterGroup(String parameterGroup) {
this.parameterGroup = Optional.fromNullable(parameterGroup);
return self();
}
/**
* @see InstanceRequest#isAutoMinorVersionUpgrade()
*/
public T autoMinorVersionUpgrade(boolean autoMinorVersionUpgrade) {
this.autoMinorVersionUpgrade = autoMinorVersionUpgrade;
return self();
}
/**
* @see InstanceRequest#getSubnetGroup()
*/
public T subnetGroup(String subnetGroup) {
this.subnetGroup = Optional.fromNullable(subnetGroup);
return self();
}
/**
* @see InstanceRequest#getSecurityGroups()
*/
public T securityGroups(Iterable<String> securityGroups) {
this.securityGroups.addAll(checkNotNull(securityGroups, "securityGroups"));
return self();
}
/**
* @see InstanceRequest#getSecurityGroups()
*/
public T securityGroups(String securityGroupName) {
this.securityGroups.add(checkNotNull(securityGroupName, "securityGroupName"));
return self();
}
/**
* @see InstanceRequest#getMasterPassword()
*/
public T masterPassword(String masterPassword) {
this.masterPassword = checkNotNull(masterPassword, "masterPassword");
return self();
}
public InstanceRequest build() {
return new InstanceRequest(name, instanceClass, port, characterSet, optionGroup, parameterGroup,
autoMinorVersionUpgrade, engine, engineVersion, licenseModel, masterUsername, allocatedStorageGB,
backupRetentionPeriod, subnetGroup, securityGroups.build(), masterPassword);
}
public T fromInstance(InstanceRequest in) {
return fromBaseInstance(in).engineVersion(in.getEngineVersion().orNull())
.licenseModel(in.getLicenseModel().orNull()).port(in.getPort().orNull())
.characterSet(in.getCharacterSet().orNull()).backupRetentionPeriod(in.getBackupRetentionPeriod())
.optionGroup(in.getOptionGroup().orNull()).parameterGroup(in.getParameterGroup().orNull())
.autoMinorVersionUpgrade(in.isAutoMinorVersionUpgrade()).subnetGroup(in.getSubnetGroup().orNull())
.securityGroups(in.getSecurityGroups());
}
}
private static class ConcreteBuilder extends Builder<ConcreteBuilder> {
@Override
protected ConcreteBuilder self() {
return this;
}
}
protected final Optional<String> engineVersion;
protected final Optional<String> licenseModel;
protected final Optional<Integer> port;
protected final Optional<String> characterSet;
protected final int backupRetentionPeriod;
protected final Optional<String> optionGroup;
protected final Optional<String> parameterGroup;
protected final boolean autoMinorVersionUpgrade;
protected final Optional<String> subnetGroup;
protected final Set<String> securityGroups;
protected final String masterPassword;
protected InstanceRequest(Optional<String> name, String instanceClass, Optional<Integer> port,
Optional<String> characterSet, Optional<String> optionGroup, Optional<String> parameterGroup,
boolean autoMinorVersionUpgrade, String engine, Optional<String> engineVersion,
Optional<String> licenseModel, String masterUsername, int allocatedStorageGB, int backupRetentionPeriod,
Optional<String> subnetGroup, Iterable<String> securityGroups, String masterPassword) {
super(name, instanceClass, engine, masterUsername, allocatedStorageGB);
this.engineVersion = checkNotNull(engineVersion, "engineVersion");
this.licenseModel = checkNotNull(licenseModel, "licenseModel");
this.optionGroup = checkNotNull(optionGroup, "optionGroup");
this.parameterGroup = checkNotNull(parameterGroup, "parameterGroup");
this.autoMinorVersionUpgrade = autoMinorVersionUpgrade;
this.port = checkNotNull(port, "port");
this.characterSet = checkNotNull(characterSet, "characterSet");
this.backupRetentionPeriod = checkNotNull(backupRetentionPeriod, "backupRetentionPeriod");
this.subnetGroup = checkNotNull(subnetGroup, "subnetGroup");
this.securityGroups = ImmutableSet.copyOf(checkNotNull(securityGroups, "securityGroups"));
this.masterPassword = checkNotNull(masterPassword, "masterPassword");
}
/**
* The version number of the database engine to use.
*
* MySQL
*
* Example: 5.1.42
*
* Oracle
*
* Example: 11.2.0.2.v2
*
* SQL Server
*
* Example: 10.50.2789.0.v1
*
*/
public Optional<String> getEngineVersion() {
return engineVersion;
}
/**
* License model information for this DB Instance.
*
* Valid values: license-included | bring-your-own-license | general-public-license
*/
public Optional<String> getLicenseModel() {
return licenseModel;
}
/**
* For supported engines, indicates that the DB Instance should be associated with the specified
* CharacterSet.
*/
public Optional<String> getCharacterSet() {
return characterSet;
}
/**
* The port number on which the database accepts connections.
* <table>
* <tr>
* <td>Engine</td>
* <td>Default</td>
* <td>Range</td>
* </tr>
* <tr>
* <td>MySQL</td>
* <td>3306</td>
* <td>1150-65535</td>
* </tr>
* <tr>
* <td>Oracle</td>
* <td>1521</td>
* <td>1150-65535</td>
* </tr>
* <tr>
* <td>SQL Server</td>
* <td>1433</td>
* <td>1150-65535 except for 1434 and 3389</td>
* </tr>
* </table>
*/
public Optional<Integer> getPort() {
return port;
}
/**
* The number of days for which automated backups are retained. Setting this parameter to a
* positive number enables backups. Setting this parameter to 0 disables automated backups.
*
*
* <h4>Constraints</h4>
*
* Must be a value from 0 to 8 Cannot be set to 0 if the DB Instance is a master instance with
* read replicas
*
* @return value which defaults to {@code 1}
*/
public int getBackupRetentionPeriod() {
return backupRetentionPeriod;
}
/**
* Indicates that the DB Instance should be associated with the specified option group.
*/
public Optional<String> getOptionGroup() {
return optionGroup;
}
/**
* The name of the DB Parameter Group to associate with this DB instance. If this argument is
* omitted, the default DBParameterGroup for the specified engine will be used.
*
* <h4>Constraints</h4>
*
* Must be 1 to 255 alphanumeric characters First character must be a letter Cannot end with a
* hyphen or contain two consecutive hyphens
*/
public Optional<String> getParameterGroup() {
return parameterGroup;
}
/**
* Indicates that minor engine upgrades will be applied automatically to the DB Instance during
* the maintenance window.
*
* @return value defaulting to {@code true}
*/
public boolean isAutoMinorVersionUpgrade() {
return autoMinorVersionUpgrade;
}
/**
* A DB Subnet Group to associate with this DB Instance.
*
* If there is no DB Subnet Group, then it is a non-VPC DB instance.
*/
public Optional<String> getSubnetGroup() {
return subnetGroup;
}
/**
* A list of DB Security Groups to associate with this DB Instance.
*
* Default: The default DB Security Group for the database engine.
*/
public Set<String> getSecurityGroups() {
return securityGroups;
}
/**
* The password for the master database user.
*
* MySQL
*
* Constraints: Must contain from 8 to 41 alphanumeric characters.
*
* Oracle
*
* Constraints: Must contain from 8 to 30 alphanumeric characters.
*
* SQL Server
*
* Constraints: Must contain from 8 to 128 alphanumeric characters.
*/
public String getMasterPassword() {
return masterPassword;
}
/**
* {@inheritDoc}
*/
@Override
protected ToStringHelper string() {
return super.string().add("engineVersion", engineVersion.orNull()).add("licenseModel", licenseModel.orNull())
.add("port", port.orNull()).add("characterSet", characterSet.orNull()).add("optionGroup", optionGroup)
.add("parameterGroup", parameterGroup).add("autoMinorVersionUpgrade", autoMinorVersionUpgrade)
.add("backupRetentionPeriod", backupRetentionPeriod).add("subnetGroup", subnetGroup.orNull())
.add("securityGroups", securityGroups);
}
}

View File

@ -23,8 +23,8 @@ import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Set;
import com.google.common.base.Objects;
import com.google.common.base.Optional;
import com.google.common.base.Objects.ToStringHelper;
import com.google.common.base.Optional;
import com.google.common.collect.ImmutableSet;
/**
@ -52,7 +52,6 @@ import com.google.common.collect.ImmutableSet;
* @author Adrian Cole
*/
public class SecurityGroup {
public static Builder<?> builder() {
return new ConcreteBuilder();
}

View File

@ -0,0 +1,205 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.rds.domain.internal;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.base.Objects;
import com.google.common.base.Objects.ToStringHelper;
import com.google.common.base.Optional;
/**
*
* @author Adrian Cole
*/
public class BaseInstance {
public static Builder<?> builder() {
return new ConcreteBuilder();
}
public Builder<?> toBuilder() {
return new ConcreteBuilder().fromBaseInstance(this);
}
public static abstract class Builder<T extends Builder<T>> {
protected abstract T self();
protected Optional<String> name = Optional.absent();
protected String instanceClass;
protected String engine;
protected String masterUsername;
protected int allocatedStorageGB;
/**
* @see BaseInstance#getName()
*/
public T name(String name) {
this.name = Optional.fromNullable(name);
return self();
}
/**
* @see BaseInstance#getInstanceClass()
*/
public T instanceClass(String instanceClass) {
this.instanceClass = instanceClass;
return self();
}
/**
* @see BaseInstance#getEngine()
*/
public T engine(String engine) {
this.engine = engine;
return self();
}
/**
* @see BaseInstance#getMasterUsername()
*/
public T masterUsername(String masterUsername) {
this.masterUsername = masterUsername;
return self();
}
/**
* @see BaseInstance#getAllocatedStorageGB()
*/
public T allocatedStorageGB(int allocatedStorageGB) {
this.allocatedStorageGB = allocatedStorageGB;
return self();
}
public BaseInstance build() {
return new BaseInstance(name, instanceClass, engine, masterUsername, allocatedStorageGB);
}
public T fromBaseInstance(BaseInstance in) {
return this.name(in.getName().orNull()).instanceClass(in.getInstanceClass()).engine(in.getEngine())
.masterUsername(in.getMasterUsername()).allocatedStorageGB(in.getAllocatedStorageGB());
}
}
private static class ConcreteBuilder extends Builder<ConcreteBuilder> {
@Override
protected ConcreteBuilder self() {
return this;
}
}
protected final Optional<String> name;
protected final String instanceClass;
protected final String engine;
protected final String masterUsername;
protected int allocatedStorageGB;
protected BaseInstance(Optional<String> name, String instanceClass, String engine, String masterUsername,
int allocatedStorageGB) {
this.name = checkNotNull(name, "name");
this.instanceClass = checkNotNull(instanceClass, "instanceClass");
this.engine = checkNotNull(engine, "engine");
this.masterUsername = checkNotNull(masterUsername, "masterUsername");
this.allocatedStorageGB = allocatedStorageGB;
}
/**
* The meaning of this parameter differs according to the database engine you use.
*
* <h4>MySQL</h4>
*
* Contains the name of the initial database of this instance that was provided at create time,
* if one was specified when the DB BaseInstance was created. This same name is returned for the
* life of the DB BaseInstance.
*
* <h4>Oracle</h4>
*
* Contains the Oracle System ID (SID) of the created DB BaseInstance.
*/
public Optional<String> getName() {
return name;
}
/**
* Contains the name of the compute and memory capacity class of the DB BaseInstance.
*/
public String getInstanceClass() {
return instanceClass;
}
/**
* Provides the name of the database engine to be used for this DB BaseInstance.
*/
public String getEngine() {
return engine;
}
/**
* Contains the master username for the DB BaseInstance.
*/
public String getMasterUsername() {
return masterUsername;
}
/**
* Specifies the allocated storage size specified in gigabytes.
*/
public int getAllocatedStorageGB() {
return allocatedStorageGB;
}
/**
* {@inheritDoc}
*/
@Override
public int hashCode() {
return Objects.hashCode(name.orNull(), instanceClass, engine, masterUsername, allocatedStorageGB);
}
/**
* {@inheritDoc}
*/
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
BaseInstance other = (BaseInstance) obj;
return Objects.equal(this.name, other.name) && Objects.equal(this.instanceClass, other.instanceClass)
&& Objects.equal(this.engine, other.engine) && Objects.equal(this.masterUsername, other.masterUsername)
&& Objects.equal(this.allocatedStorageGB, other.allocatedStorageGB);
}
/**
* {@inheritDoc}
*/
@Override
public String toString() {
return string().toString();
}
protected ToStringHelper string() {
return Objects.toStringHelper(this).omitNullValues().add("name", name.orNull()).add("instanceClass", instanceClass)
.add("engine", engine).add("masterUsername", masterUsername)
.add("allocatedStorageGB", allocatedStorageGB);
}
}

View File

@ -25,6 +25,7 @@ import org.jclouds.collect.PagedIterable;
import org.jclouds.concurrent.Timeout;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.rds.domain.Instance;
import org.jclouds.rds.domain.InstanceRequest;
import org.jclouds.rds.options.ListInstancesOptions;
/**
@ -37,6 +38,41 @@ import org.jclouds.rds.options.ListInstancesOptions;
*/
@Timeout(duration = 30, timeUnit = TimeUnit.SECONDS)
public interface InstanceApi {
/**
* Creates a new DB instance in a random, system-chosen Availability Zone in the endpoint's
* region.
*
* @param id
* unique id of the new instance
* @param instanceRequest
* parameters to create the instance with
* @return new instance being created
*/
Instance create(String id, InstanceRequest instanceRequest);
/**
* Creates a new DB instance in the specified {@code availabilityZone}
*
* @param id
* unique id of the new instance
* @param instanceRequest
* parameters to create the instance with
* @param availabilityZone
* The EC2 Availability Zone that the database instance will be created in
* @return new instance being created
*/
Instance createInAvailabilityZone(String id, InstanceRequest instanceRequest, String availabilityZone);
/**
* Creates a Multi-AZ deployment. This is not compatible with Microsoft SQL Server.
*
* @param id
* unique id of the new instance
* @param instanceRequest
* parameters to create the instance with
* @return new instance being created
*/
Instance createMultiAZ(String id, InstanceRequest instanceRequest);
/**
* Retrieves information about the specified instance.
@ -72,20 +108,38 @@ public interface InstanceApi {
PagedIterable<Instance> list();
/**
* Deletes the specified Instance.
* Deletes the specified Instance, skipping final snapshot.
*
* <p/>
* The DeleteDBInstance API deletes a previously provisioned RDS instance. A successful response
* from the web service indicates the request was received correctly. If a final DBSnapshot is
* requested the status of the RDS instance will be "deleting" until the DBSnapshot is created.
* DescribeDBInstance is used to monitor the status of this operation. This cannot be canceled or
* from the web service indicates the request was received correctly. This cannot be canceled or
* reverted once submitted.
*
*
* @param id
* The DB Instance identifier for the DB Instance to be deleted. This parameter isn't
* case sensitive.
* @return final state of instance or null if not found
*/
void delete(String id);
Instance delete(String id);
/**
* Deletes the specified Instance.
*
* <p/>
* The DeleteDBInstance API deletes a previously provisioned RDS instance. A successful response
* from the web service indicates the request was received correctly. The status of the RDS
* instance will be "deleting" until the DBSnapshot is created. DescribeDBInstance is used to
* monitor the status of this operation. This cannot be canceled or reverted once submitted.
*
*
* @param id
* The DB Instance identifier for the DB Instance to be deleted. This parameter isn't
* case sensitive.
* @param snapshotId
* The DBSnapshotIdentifier of the new DBSnapshot created when SkipFinalSnapshot is set
* to false.
* @return final state of instance or null if not found
*/
Instance deleteAndSaveSnapshot(String id, String snapshotId);
}

View File

@ -27,11 +27,15 @@ import javax.ws.rs.Path;
import org.jclouds.aws.filters.FormSigner;
import org.jclouds.collect.IterableWithMarker;
import org.jclouds.collect.PagedIterable;
import org.jclouds.rds.binders.BindInstanceRequestToFormParams;
import org.jclouds.rds.domain.Instance;
import org.jclouds.rds.domain.InstanceRequest;
import org.jclouds.rds.functions.InstancesToPagedIterable;
import org.jclouds.rds.functions.ReturnNullOnStateDeletingNotFoundOr404;
import org.jclouds.rds.options.ListInstancesOptions;
import org.jclouds.rds.xml.DescribeDBInstancesResultHandler;
import org.jclouds.rds.xml.InstanceHandler;
import org.jclouds.rest.annotations.BinderParam;
import org.jclouds.rest.annotations.ExceptionParser;
import org.jclouds.rest.annotations.FormParams;
import org.jclouds.rest.annotations.RequestFilters;
@ -39,7 +43,6 @@ import org.jclouds.rest.annotations.Transform;
import org.jclouds.rest.annotations.VirtualHost;
import org.jclouds.rest.annotations.XMLResponseParser;
import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404;
import org.jclouds.rest.functions.ReturnVoidOnNotFoundOr404;
import com.google.common.util.concurrent.ListenableFuture;
@ -47,14 +50,43 @@ import com.google.common.util.concurrent.ListenableFuture;
* Provides access to Amazon RDS via the Query API
* <p/>
*
* @see <a href="http://docs.amazonwebservices.com/AmazonRDS/latest/APIReference"
* >doc</a>
* @see <a href="http://docs.amazonwebservices.com/AmazonRDS/latest/APIReference" >doc</a>
* @see InstanceApi
* @author Adrian Cole
*/
@RequestFilters(FormSigner.class)
@VirtualHost
public interface InstanceAsyncApi {
/**
* @see InstanceApi#create
*/
@POST
@Path("/")
@XMLResponseParser(InstanceHandler.class)
@FormParams(keys = ACTION, values = "CreateDBInstance")
ListenableFuture<Instance> create(@FormParam("DBInstanceIdentifier") String id,
@BinderParam(BindInstanceRequestToFormParams.class) InstanceRequest instanceRequest);
/**
* @see InstanceApi#createInAvailabilityZone
*/
@POST
@Path("/")
@XMLResponseParser(InstanceHandler.class)
@FormParams(keys = ACTION, values = "CreateDBInstance")
ListenableFuture<Instance> createInAvailabilityZone(@FormParam("DBInstanceIdentifier") String id,
@BinderParam(BindInstanceRequestToFormParams.class) InstanceRequest instanceRequest,
@FormParam("AvailabilityZone") String availabilityZone);
/**
* @see InstanceApi#createMultiAZ
*/
@POST
@Path("/")
@XMLResponseParser(InstanceHandler.class)
@FormParams(keys = { ACTION, "MultiAZ" }, values = { "CreateDBInstance", "true" })
ListenableFuture<Instance> createMultiAZ(@FormParam("DBInstanceIdentifier") String id,
@BinderParam(BindInstanceRequestToFormParams.class) InstanceRequest instanceRequest);
/**
* @see InstanceApi#get()
@ -90,7 +122,19 @@ public interface InstanceAsyncApi {
*/
@POST
@Path("/")
@ExceptionParser(ReturnVoidOnNotFoundOr404.class)
@XMLResponseParser(InstanceHandler.class)
@ExceptionParser(ReturnNullOnStateDeletingNotFoundOr404.class)
@FormParams(keys = { ACTION, "SkipFinalSnapshot" }, values = { "DeleteDBInstance", "true" })
ListenableFuture<Instance> delete(@FormParam("DBInstanceIdentifier") String id);
/**
* @see InstanceApi#deleteAndSaveSnapshot
*/
@POST
@Path("/")
@XMLResponseParser(InstanceHandler.class)
@ExceptionParser(ReturnNullOnStateDeletingNotFoundOr404.class)
@FormParams(keys = ACTION, values = "DeleteDBInstance")
ListenableFuture<Void> delete(@FormParam("DBInstanceIdentifier") String id);
ListenableFuture<Instance> deleteAndSaveSnapshot(@FormParam("DBInstanceIdentifier") String id,
@FormParam("FinalDBSnapshotIdentifier") String snapshotId);
}

View File

@ -37,6 +37,38 @@ import org.jclouds.rds.options.ListSecurityGroupsOptions;
*/
@Timeout(duration = 30, timeUnit = TimeUnit.SECONDS)
public interface SecurityGroupApi {
/**
* Creates a new DB Security Group. DB Security Groups control access to a DB Instance.
*
* @param name
* The name for the DB Security Group. This value is stored as a lowercase string.
*
* Constraints: Must contain no more than 255 alphanumeric characters or hyphens. Must
* not be "Default".
* @param description
* The description for the DB Security Group.
*
* @return the new security group
*/
SecurityGroup createWithNameAndDescription(String name, String description);
/**
* Creates a new DB Security Group. DB Security Groups control access to a DB Instance.
*
* @param vpcId
* The Id of VPC. Indicates which VPC this DB Security Group should belong to. Must be
* specified to create a DB Security Group for a VPC; may not be specified otherwise.
*
* @param name
* The name for the DB Security Group. This value is stored as a lowercase string.
*
* Constraints: Must contain no more than 255 alphanumeric characters or hyphens. Must
* not be "Default".
* @param description
* The description for the DB Security Group.
* @return the new security group
*/
SecurityGroup createInVPCWithNameAndDescription(String vpcId, String name, String description);
/**
* Retrieves information about the specified {@link SecurityGroup}.
@ -68,6 +100,93 @@ public interface SecurityGroupApi {
*/
PagedIterable<SecurityGroup> list();
/**
* Enables ingress to a DBSecurityGroup to an IP range, if the application accessing your
* database is running on the Internet.
*
* @param name
* The name of the DB Security Group to add authorization to.
* @param CIDR
* The IP range to authorize.
* @return updated security group, noting the authorization status may not be complete
*/
SecurityGroup authorizeIngressToIPRange(String name, String CIDR);
/**
* Enables ingress to a DBSecurityGroup if the application using the database is running on EC2
* instances.
*
* <h4>Note</h4>
*
* You cannot authorize ingress from an EC2 security group in one Region to an Amazon RDS DB
* Instance in another.
*
* @param name
* The name of the DB Security Group to add authorization to.
* @param ec2SecurityGroupName
* Name of the EC2 Security Group to authorize.
* @param ec2SecurityGroupOwnerId
* AWS Account Number of the owner of the EC2 Security Group specified in the
* EC2SecurityGroupName parameter. The AWS Access Key ID is not an acceptable value.
* @return updated security group, noting the authorization status may not be complete
*/
SecurityGroup authorizeIngressToEC2SecurityGroupOfOwner(String name, String ec2SecurityGroupName,
String ec2SecurityGroupOwnerId);
/**
* Enables ingress to a DBSecurityGroup if the application using the database is running on VPC
* instances.
*
* <h4>Note</h4>
*
* You cannot authorize ingress from a VPC security group in one VPC to an Amazon RDS DB Instance
* in another.
*
* @param name
* The name of the DB Security Group to add authorization to.
* @param vpcSecurityGroupId
* Id of the EC2 Security Group to authorize.
* @return updated security group, noting the authorization status may not be complete
*/
SecurityGroup authorizeIngressToVPCSecurityGroup(String name, String vpcSecurityGroupId);
/**
* Revokes ingress from a DBSecurityGroup for previously authorized IP range.
*
* @param name
* The name of the DB Security Group to revoke ingress from.
* @param CIDR
* The IP range to revoke.
* @return updated security group, noting the authorization status may not be complete
*/
SecurityGroup revokeIngressFromIPRange(String name, String CIDR);
/**
* Revokes ingress from a DBSecurityGroup for previously authorized EC2 Security Group.
*
* @param name
* The name of the DB Security Group to revoke ingress from.
* @param ec2SecurityGroupName
* Name of the EC2 Security Group to revoke.
* @param ec2SecurityGroupOwnerId
* AWS Account Number of the owner of the EC2 Security Group specified in the
* EC2SecurityGroupName parameter. The AWS Access Key ID is not an acceptable value.
* @return updated security group, noting the authorization status may not be complete
*/
SecurityGroup revokeIngressFromEC2SecurityGroupOfOwner(String name, String ec2SecurityGroupName,
String ec2SecurityGroupOwnerId);
/**
* Revokes ingress from a DBSecurityGroup for previously authorized VPC Security Group.
*
* @param name
* The name of the DB Security Group to revoke ingress from.
* @param vpcSecurityGroupId
* Id of the EC2 Security Group to revoke.
* @return updated security group, noting the authorization status may not be complete
*/
SecurityGroup revokeIngressFromVPCSecurityGroup(String name, String vpcSecurityGroupId);
/**
* Deletes a DB security group.
*

View File

@ -47,14 +47,32 @@ import com.google.common.util.concurrent.ListenableFuture;
* Provides access to Amazon RDS via the Query API
* <p/>
*
* @see <a href="http://docs.amazonwebservices.com/AmazonRDS/latest/APIReference"
* >doc</a>
* @see <a href="http://docs.amazonwebservices.com/AmazonRDS/latest/APIReference" >doc</a>
* @see SecurityGroupApi
* @author Adrian Cole
*/
@RequestFilters(FormSigner.class)
@VirtualHost
public interface SecurityGroupAsyncApi {
/**
* @see SecurityGroupApi#createWithNameAndDescription
*/
@POST
@Path("/")
@XMLResponseParser(SecurityGroupHandler.class)
@FormParams(keys = ACTION, values = "CreateDBSecurityGroup")
ListenableFuture<SecurityGroup> createWithNameAndDescription(@FormParam("DBSecurityGroupName") String name,
@FormParam("DBSecurityGroupDescription") String description);
/**
* @see SecurityGroupApi#createInVPCWithNameAndDescription
*/
@POST
@Path("/")
@XMLResponseParser(SecurityGroupHandler.class)
@FormParams(keys = ACTION, values = "CreateDBSecurityGroup")
ListenableFuture<SecurityGroup> createInVPCWithNameAndDescription(@FormParam("EC2VpcId") String vpcId,
@FormParam("DBSecurityGroupName") String name, @FormParam("DBSecurityGroupDescription") String description);
/**
* @see SecurityGroupApi#get()
@ -85,6 +103,71 @@ public interface SecurityGroupAsyncApi {
@FormParams(keys = "Action", values = "DescribeDBSecurityGroups")
ListenableFuture<IterableWithMarker<SecurityGroup>> list(ListSecurityGroupsOptions options);
/**
* @see SecurityGroupApi#authorizeIngressToIPRange
*/
@POST
@Path("/")
@XMLResponseParser(SecurityGroupHandler.class)
@FormParams(keys = ACTION, values = "AuthorizeDBSecurityGroupIngress")
ListenableFuture<SecurityGroup> authorizeIngressToIPRange(@FormParam("DBSecurityGroupName") String name,
@FormParam("CIDRIP") String CIDR);
/**
* @see SecurityGroupApi#authorizeIngressToEC2SecurityGroupOfOwner
*/
@POST
@Path("/")
@XMLResponseParser(SecurityGroupHandler.class)
@FormParams(keys = ACTION, values = "AuthorizeDBSecurityGroupIngress")
ListenableFuture<SecurityGroup> authorizeIngressToEC2SecurityGroupOfOwner(
@FormParam("DBSecurityGroupName") String name,
@FormParam("EC2SecurityGroupName") String ec2SecurityGroupName,
@FormParam("EC2SecurityGroupOwnerId") String ec2SecurityGroupOwnerId);
/**
* @see SecurityGroupApi#authorizeIngressToVPCSecurityGroup
*/
@POST
@Path("/")
@XMLResponseParser(SecurityGroupHandler.class)
@FormParams(keys = ACTION, values = "AuthorizeDBSecurityGroupIngress")
ListenableFuture<SecurityGroup> authorizeIngressToVPCSecurityGroup(@FormParam("DBSecurityGroupName") String name,
@FormParam("EC2SecurityGroupId") String vpcSecurityGroupId);
/**
* @see SecurityGroupApi#revokeIngressFromIPRange
*/
@POST
@Path("/")
@XMLResponseParser(SecurityGroupHandler.class)
@FormParams(keys = ACTION, values = "RevokeDBSecurityGroupIngress")
ListenableFuture<SecurityGroup> revokeIngressFromIPRange(@FormParam("DBSecurityGroupName") String name,
@FormParam("CIDRIP") String CIDR);
/**
* @see SecurityGroupApi#revokeIngressFromEC2SecurityGroupOfOwner
*/
@POST
@Path("/")
@XMLResponseParser(SecurityGroupHandler.class)
@FormParams(keys = ACTION, values = "RevokeDBSecurityGroupIngress")
ListenableFuture<SecurityGroup> revokeIngressFromEC2SecurityGroupOfOwner(
@FormParam("DBSecurityGroupName") String name,
@FormParam("EC2SecurityGroupName") String ec2SecurityGroupName,
@FormParam("EC2SecurityGroupOwnerId") String ec2SecurityGroupOwnerId);
/**
* @see SecurityGroupApi#revokeIngressFromVPCSecurityGroup
*/
@POST
@Path("/")
@XMLResponseParser(SecurityGroupHandler.class)
@FormParams(keys = ACTION, values = "RevokeDBSecurityGroupIngress")
ListenableFuture<SecurityGroup> revokeIngressFromVPCSecurityGroup(@FormParam("DBSecurityGroupName") String name,
@FormParam("EC2SecurityGroupId") String vpcSecurityGroupId);
/**
* @see SecurityGroupApi#delete()
*/

View File

@ -0,0 +1,51 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.rds.functions;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.jclouds.aws.AWSResponseException;
import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404;
import com.google.common.base.Function;
/**
* it is ok to have a db instance already in the process of deleting
*/
@Singleton
public class ReturnNullOnStateDeletingNotFoundOr404 implements Function<Exception, Object> {
private ReturnNullOnNotFoundOr404 rto404;
@Inject
private ReturnNullOnStateDeletingNotFoundOr404(ReturnNullOnNotFoundOr404 rto404) {
this.rto404 = rto404;
}
public Object apply(Exception from) {
if (from instanceof AWSResponseException) {
AWSResponseException e = AWSResponseException.class.cast(from);
if (e.getError().getCode().equals("InvalidDBInstanceState")
&& e.getError().getMessage().contains("has state: deleting"))
return null;
}
return rto404.apply(from);
}
}

View File

@ -21,8 +21,9 @@ package org.jclouds.rds.xml;
import static org.jclouds.util.SaxUtils.currentOrNull;
import static org.jclouds.util.SaxUtils.equalsOrSuffix;
import org.jclouds.rds.domain.EC2SecurityGroup;
import org.jclouds.http.functions.ParseSax;
import org.jclouds.rds.domain.Authorization.Status;
import org.jclouds.rds.domain.EC2SecurityGroup;
import org.xml.sax.SAXException;
/**
@ -61,7 +62,9 @@ public class EC2SecurityGroupHandler extends ParseSax.HandlerForGeneratedRequest
} else if (equalsOrSuffix(qName, "EC2SecurityGroupOwnerId")) {
builder.ownerId(currentOrNull(currentText));
} else if (equalsOrSuffix(qName, "Status")) {
builder.status(currentOrNull(currentText));
String rawStatus = currentOrNull(currentText);
builder.rawStatus(rawStatus);
builder.status(Status.fromValue(rawStatus));
}
currentText = new StringBuilder();
}

View File

@ -21,8 +21,9 @@ package org.jclouds.rds.xml;
import static org.jclouds.util.SaxUtils.currentOrNull;
import static org.jclouds.util.SaxUtils.equalsOrSuffix;
import org.jclouds.rds.domain.IPRange;
import org.jclouds.http.functions.ParseSax;
import org.jclouds.rds.domain.Authorization.Status;
import org.jclouds.rds.domain.IPRange;
import org.xml.sax.SAXException;
/**
@ -57,7 +58,9 @@ public class IPRangeHandler extends ParseSax.HandlerForGeneratedRequestWithResul
if (equalsOrSuffix(qName, "CIDRIP")) {
builder.cidrIp(currentOrNull(currentText));
} else if (equalsOrSuffix(qName, "Status")) {
builder.status(currentOrNull(currentText));
String rawStatus = currentOrNull(currentText);
builder.rawStatus(rawStatus);
builder.status(Status.fromValue(rawStatus));
}
currentText = new StringBuilder();
}

View File

@ -94,9 +94,11 @@ public class InstanceHandler extends ParseSax.HandlerForGeneratedRequestWithResu
@Override
public void endElement(String uri, String name, String qName) throws SAXException {
if (equalsOrSuffix(qName, "SubnetGroup")) {
if (equalsOrSuffix(qName, "DBSubnetGroup")) {
builder.subnetGroup(subnetGroupHandler.getResult());
inSubnetGroup = false;
} else if (inSubnetGroup) {
subnetGroupHandler.endElement(uri, name, qName);
} else if (equalsOrSuffix(qName, "DBInstanceIdentifier")) {
builder.id(currentOrNull(currentText));
} else if (equalsOrSuffix(qName, "InstanceCreateTime")) {
@ -106,13 +108,17 @@ public class InstanceHandler extends ParseSax.HandlerForGeneratedRequestWithResu
} else if (equalsOrSuffix(qName, "AllocatedStorage")) {
builder.allocatedStorageGB(Integer.parseInt(currentOrNull(currentText)));
} else if (equalsOrSuffix(qName, "DBInstanceStatus")) {
builder.status(currentOrNull(currentText));
String rawStatus = currentOrNull(currentText);
builder.rawStatus(rawStatus);
builder.status(Instance.Status.fromValue(rawStatus));
} else if (equalsOrSuffix(qName, "Address")) {
address = currentOrNull(currentText);
} else if (equalsOrSuffix(qName, "Port")) {
port = Integer.valueOf(currentOrNull(currentText));
} else if (equalsOrSuffix(qName, "Endpoint")) {
builder.endpoint(HostAndPort.fromParts(address, port));
// sometimes in deleting state, address is null while port isn't
if (address != null && port != null)
builder.endpoint(HostAndPort.fromParts(address, port));
address = null;
port = null;
} else if (equalsOrSuffix(qName, "DBSecurityGroupName")) {
@ -139,8 +145,6 @@ public class InstanceHandler extends ParseSax.HandlerForGeneratedRequestWithResu
builder.licenseModel(currentOrNull(currentText));
} else if (equalsOrSuffix(qName, "MasterUsername")) {
builder.masterUsername(currentOrNull(currentText));
} else if (inSubnetGroup) {
subnetGroupHandler.endElement(uri, name, qName);
}
currentText = new StringBuilder();
}

View File

@ -27,6 +27,7 @@ import java.util.TimeZone;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse;
import org.jclouds.rds.RDSApi;
import org.jclouds.rds.domain.InstanceRequest;
import org.jclouds.rds.internal.BaseRDSApiExpectTest;
import org.jclouds.rds.parse.DescribeDBInstancesResponseTest;
import org.jclouds.rds.parse.GetInstanceResponseTest;
@ -193,9 +194,10 @@ public class InstanceApiExpectTest extends BaseRDSApiExpectTest {
payloadFromStringWithContentType(
"Action=DeleteDBInstance" +
"&DBInstanceIdentifier=id" +
"&Signature=3UFxv5zaG%2B3dZRAhinJZ10De0LAxkJtr3Nb6kfspC7w%3D" +
"&Signature=Kag9creOPsl%2BslM1J0fNzWIzo1LrF4ycnOI21v%2Bl6VM%3D" +
"&SignatureMethod=HmacSHA256" +
"&SignatureVersion=2" +
"&SkipFinalSnapshot=true" +
"&Timestamp=2009-11-08T15%3A54%3A08.897Z" +
"&Version=2012-04-23" +
"&AWSAccessKeyId=identity",
@ -204,7 +206,8 @@ public class InstanceApiExpectTest extends BaseRDSApiExpectTest {
public void testDeleteWhenResponseIs2xx() throws Exception {
HttpResponse deleteResponse = HttpResponse.builder().statusCode(200).build();
HttpResponse deleteResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResourceWithContentType("/delete_instance.xml", "text/xml")).build();
RDSApi apiWhenExist = requestSendsResponse(delete, deleteResponse);
@ -219,4 +222,116 @@ public class InstanceApiExpectTest extends BaseRDSApiExpectTest {
apiWhenDontExist.getInstanceApi().delete("id");
}
public void testDeleteWhenInvalidStateDeleting() throws Exception {
HttpResponse deleteResponse = HttpResponse.builder().statusCode(400).message("HTTP/1.1 400 Bad Request")
.payload(payloadFromResourceWithContentType("/invalid_state.xml", "text/xml")).build();
RDSApi apiWhenDeleting = requestSendsResponse(delete, deleteResponse);
apiWhenDeleting.getInstanceApi().delete("id");
}
public void testDeleteAndSaveSnapshotWhenResponseIs2xx() throws Exception {
HttpRequest delete = HttpRequest.builder().method("POST")
.endpoint("https://rds.us-east-1.amazonaws.com/")
.addHeader("Host", "rds.us-east-1.amazonaws.com")
.payload(
payloadFromStringWithContentType(
"Action=DeleteDBInstance" +
"&DBInstanceIdentifier=id" +
"&FinalDBSnapshotIdentifier=snap" +
"&Signature=aKuG1%2FYbZAzUFdAZTjke1LYRfR5JU86UxDt%2BtwdPJwE%3D" +
"&SignatureMethod=HmacSHA256" +
"&SignatureVersion=2" +
"&Timestamp=2009-11-08T15%3A54%3A08.897Z" +
"&Version=2012-04-23" +
"&AWSAccessKeyId=identity",
"application/x-www-form-urlencoded"))
.build();
HttpResponse deleteResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResourceWithContentType("/delete_instance.xml", "text/xml")).build();
RDSApi apiWhenExist = requestSendsResponse(delete, deleteResponse);
apiWhenExist.getInstanceApi().deleteAndSaveSnapshot("id", "snap");
}
public void testCreateWithMinumumParamsWhenResponseIs2xx() throws Exception {
HttpRequest create = HttpRequest.builder()
.method("POST")
.endpoint("https://rds.us-east-1.amazonaws.com/")
.addHeader("Host", "rds.us-east-1.amazonaws.com")
.payload(
payloadFromStringWithContentType(
"Action=CreateDBInstance" +
"&AllocatedStorage=5" +
"&AutoMinorVersionUpgrade=true" +
"&BackupRetentionPeriod=1" +
"&DBInstanceClass=db.t1.micro" +
"&DBInstanceIdentifier=SimCoProd01" +
"&Engine=mysql" +
"&MasterUserPassword=Password01" +
"&MasterUsername=master" +
"&Signature=TecIUViW09soXGFT3kAXcW2dhsK6fY2cNykLpzLJtvk%3D" +
"&SignatureMethod=HmacSHA256" +
"&SignatureVersion=2" +
"&Timestamp=2009-11-08T15%3A54%3A08.897Z" +
"&Version=2012-04-23" +
"&AWSAccessKeyId=identity",
"application/x-www-form-urlencoded"))
.build();
HttpResponse createResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResourceWithContentType("/create_instance.xml", "text/xml")).build();
RDSApi apiWhenExist = requestSendsResponse(create, createResponse);
apiWhenExist.getInstanceApi().create("SimCoProd01", InstanceRequest.builder()
.engine("mysql")
.masterUsername("master")
.masterPassword("Password01")
.allocatedStorageGB(5)
.instanceClass("db.t1.micro").build());
}
public void testCreateWithOptionalParamsWhenResponseIs2xx() throws Exception {
HttpRequest create = HttpRequest.builder()
.method("POST")
.endpoint("https://rds.us-east-1.amazonaws.com/")
.addHeader("Host", "rds.us-east-1.amazonaws.com")
.payload(
payloadFromStringWithContentType(
"Action=CreateDBInstance" +
"&AllocatedStorage=10" +
"&AutoMinorVersionUpgrade=true" +
"&BackupRetentionPeriod=1" +
"&DBInstanceClass=db.m1.large" +
"&DBInstanceIdentifier=SimCoProd01" +
"&DBSubnetGroupName=dbSubnetgroup01" +
"&Engine=mysql" +
"&MasterUserPassword=Password01" +
"&MasterUsername=master" +
"&Signature=kfDFp50sxBkSlZd%2Bv8G9u6%2BFdZ133BEVcIRGwwoa8%2Fs%3D" +
"&SignatureMethod=HmacSHA256" +
"&SignatureVersion=2" +
"&Timestamp=2009-11-08T15%3A54%3A08.897Z" +
"&Version=2012-04-23" +
"&AWSAccessKeyId=identity",
"application/x-www-form-urlencoded"))
.build();
HttpResponse createResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResourceWithContentType("/create_instance.xml", "text/xml")).build();
RDSApi apiWhenExist = requestSendsResponse(create, createResponse);
apiWhenExist.getInstanceApi().create("SimCoProd01", InstanceRequest.builder()
.engine("mysql")
.masterPassword("Password01")
.allocatedStorageGB(10)
.masterUsername("master")
.instanceClass("db.m1.large")
.subnetGroup("dbSubnetgroup01").build());
}
}

View File

@ -19,27 +19,172 @@
package org.jclouds.rds.features;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotEquals;
import static org.testng.Assert.assertTrue;
import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;
import javax.annotation.Nullable;
import org.jclouds.collect.IterableWithMarker;
import org.jclouds.predicates.InetSocketAddressConnect;
import org.jclouds.predicates.RetryablePredicate;
import org.jclouds.rds.domain.Authorization;
import org.jclouds.rds.domain.Authorization.Status;
import org.jclouds.rds.domain.Instance;
import org.jclouds.rds.domain.InstanceRequest;
import org.jclouds.rds.domain.SecurityGroup;
import org.jclouds.rds.internal.BaseRDSApiLiveTest;
import org.jclouds.rds.options.ListInstancesOptions;
import org.testng.Assert;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import com.google.common.net.HostAndPort;
/**
* @author Adrian Cole
*/
@Test(groups = "live", testName = "InstanceApiLiveTest")
public class InstanceApiLiveTest extends BaseRDSApiLiveTest {
public static final String INSTANCE = (System.getProperty("user.name") + "-jclouds-instance").toLowerCase();
private RetryablePredicate<HostAndPort> socketTester;
private RetryablePredicate<Instance> instanceAvailable;
private RetryablePredicate<Instance> instanceGone;
private SecurityGroup securityGroup;
@BeforeClass(groups = "live")
@Override
public void setupContext() {
super.setupContext();
securityGroup = createSecurityGroupAndAuthorizeIngressToAll(INSTANCE);
socketTester = new RetryablePredicate<HostAndPort>(new InetSocketAddressConnect(), 180, 1, 1, TimeUnit.SECONDS);
instanceAvailable = new RetryablePredicate<Instance>(new Predicate<Instance>() {
@Override
public boolean apply(Instance input) {
return api().get(input.getId()).getStatus() == Instance.Status.AVAILABLE;
}
}, 600, 5, 5, TimeUnit.SECONDS);
instanceGone = new RetryablePredicate<Instance>(new Predicate<Instance>() {
@Override
public boolean apply(Instance input) {
return api().get(input.getId()) == null;
}
}, 600, 5, 5, TimeUnit.SECONDS);
}
private SecurityGroup createSecurityGroupAndAuthorizeIngressToAll(String name) {
RetryablePredicate<SecurityGroup> ipRangesAuthorized = new RetryablePredicate<SecurityGroup>(
new Predicate<SecurityGroup>() {
@Override
public boolean apply(SecurityGroup input) {
return Iterables.all(sgApi().get(input.getName()).getIPRanges(), new Predicate<Authorization>() {
@Override
public boolean apply(@Nullable Authorization i2) {
return i2.getStatus() == Status.AUTHORIZED;
}
});
}
}, 30000, 100, 500, TimeUnit.MILLISECONDS);
try {
SecurityGroup securityGroup = sgApi().createWithNameAndDescription(name, "jclouds");
Logger.getAnonymousLogger().info("created securityGroup: " + securityGroup);
// we could look up our IP address alternatively
securityGroup = sgApi().authorizeIngressToIPRange(name, "0.0.0.0/0");
assertTrue(ipRangesAuthorized.apply(securityGroup), securityGroup.toString());
securityGroup = sgApi().get(securityGroup.getName());
Logger.getAnonymousLogger().info("ip range authorized: " + securityGroup);
return securityGroup;
} catch (RuntimeException e) {
sgApi().delete(name);
throw e;
}
}
private Instance instance;
public void testCreateInstance() {
Instance newInstance = api().create(
INSTANCE,
InstanceRequest.builder()
.instanceClass("db.t1.micro")
.allocatedStorageGB(5)
.securityGroups(securityGroup.getName())
.name("jclouds")
.engine("mysql")
.masterUsername("master").masterPassword("Password01")
.backupRetentionPeriod(0).build());
instance = newInstance;
Logger.getAnonymousLogger().info("created instance: " + instance);
assertEquals(instance.getId(), INSTANCE);
assertEquals(instance.getName().get(), "jclouds");
checkInstance(newInstance);
assertTrue(instanceAvailable.apply(newInstance), newInstance.toString());
instance = api().get(newInstance.getId());
Logger.getAnonymousLogger().info("instance available: " + instance);
}
@Test(dependsOnMethods = "testCreateInstance")
protected void testPortResponds() {
assertTrue(socketTester.apply(instance.getEndpoint().get()), instance.toString());
Logger.getAnonymousLogger().info("instance reachable on: " + instance.getEndpoint().get());
}
@Test(dependsOnMethods = "testPortResponds")
public void testDeleteInstance() {
instance = api().delete(instance.getId());
assertTrue(instanceGone.apply(instance), instance.toString());
Logger.getAnonymousLogger().info("instance deleted: " + instance);
}
@Override
@AfterClass(groups = "live")
protected void tearDownContext() {
try {
api().delete(INSTANCE);
} finally {
sgApi().delete(INSTANCE);
}
super.tearDownContext();
}
private void checkInstance(Instance instance) {
checkNotNull(instance.getId(), "Id cannot be null for a Instance: %s", instance);
checkNotNull(instance.getStatus(), "Status cannot be null for a Instance: %s", instance);
assertNotEquals(instance.getStatus(), Instance.Status.UNRECOGNIZED,
"Status cannot be UNRECOGNIZED for a Instance: " + instance);
checkNotNull(instance.getCreatedTime(), "CreatedTime cannot be null for a Instance: %s", instance);
checkNotNull(instance.getName(), "While Name can be null for a Instance, its Optional wrapper cannot: %s",
instance);
checkNotNull(instance.getSubnetGroup(),
"While SubnetGroup can be null for a Instance, its Optional wrapper cannot: %s", instance);
// TODO: other checks
@ -70,4 +215,8 @@ public class InstanceApiLiveTest extends BaseRDSApiLiveTest {
protected InstanceApi api() {
return context.getApi().getInstanceApi();
}
protected SecurityGroupApi sgApi() {
return context.getApi().getSecurityGroupApi();
}
}

View File

@ -46,6 +46,61 @@ public class SecurityGroupApiExpectTest extends BaseRDSApiExpectTest {
TimeZone.setDefault(TimeZone.getTimeZone("America/Los_Angeles"));
}
public void testCreateWithNameAndDescriptionWhenResponseIs2xx() throws Exception {
HttpRequest create = HttpRequest.builder()
.method("POST")
.endpoint("https://rds.us-east-1.amazonaws.com/")
.addHeader("Host", "rds.us-east-1.amazonaws.com")
.payload(
payloadFromStringWithContentType(
"Action=CreateDBSecurityGroup" +
"&DBSecurityGroupDescription=My%20new%20DBSecurityGroup" +
"&DBSecurityGroupName=mydbsecuritygroup" +
"&Signature=ZJ0F0Y5veTPir5NWc7KhmHp7cYIijAxKQFikPHJzzBI%3D" +
"&SignatureMethod=HmacSHA256" +
"&SignatureVersion=2" +
"&Timestamp=2009-11-08T15%3A54%3A08.897Z" +
"&Version=2012-04-23" +
"&AWSAccessKeyId=identity",
"application/x-www-form-urlencoded"))
.build();
HttpResponse createResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResourceWithContentType("/create_securitygroup.xml", "text/xml")).build();
RDSApi apiWhenExist = requestSendsResponse(create, createResponse);
apiWhenExist.getSecurityGroupApi().createWithNameAndDescription("mydbsecuritygroup", "My new DBSecurityGroup");
}
public void testCreateInVPCWithNameAndDescriptionWhenResponseIs2xx() throws Exception {
HttpRequest create = HttpRequest.builder()
.method("POST")
.endpoint("https://rds.us-east-1.amazonaws.com/")
.addHeader("Host", "rds.us-east-1.amazonaws.com")
.payload(
payloadFromStringWithContentType(
"Action=CreateDBSecurityGroup" +
"&DBSecurityGroupDescription=My%20new%20DBSecurityGroup" +
"&DBSecurityGroupName=mydbsecuritygroup" +
"&EC2VpcId=vpc-1a2b3c4d" +
"&Signature=8MXHQRkGSKb0TzCKRIlDN9ymruqzY%2FQKgLMXoxYcqFI%3D" +
"&SignatureMethod=HmacSHA256" +
"&SignatureVersion=2" +
"&Timestamp=2009-11-08T15%3A54%3A08.897Z" +
"&Version=2012-04-23" +
"&AWSAccessKeyId=identity",
"application/x-www-form-urlencoded"))
.build();
HttpResponse createResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResourceWithContentType("/create_securitygroup.xml", "text/xml")).build();
RDSApi apiWhenExist = requestSendsResponse(create, createResponse);
apiWhenExist.getSecurityGroupApi().createInVPCWithNameAndDescription("vpc-1a2b3c4d", "mydbsecuritygroup", "My new DBSecurityGroup");
}
HttpRequest get = HttpRequest.builder()
.method("POST")
.endpoint("https://rds.us-east-1.amazonaws.com/")
@ -185,6 +240,171 @@ public class SecurityGroupApiExpectTest extends BaseRDSApiExpectTest {
new DescribeDBSecurityGroupsResponseTest().expected().toString());
}
public void testAuthorizeIngressToIPRangeWhenResponseIs2xx() throws Exception {
HttpRequest authorize = HttpRequest.builder()
.method("POST")
.endpoint("https://rds.us-east-1.amazonaws.com/")
.addHeader("Host", "rds.us-east-1.amazonaws.com")
.payload(
payloadFromStringWithContentType(
"Action=AuthorizeDBSecurityGroupIngress" +
"&CIDRIP=0.0.0.0%2F0" +
"&DBSecurityGroupName=mydbsecuritygroup" +
"&Signature=Wk06HjnbFH5j%2FyfguUK6p3ZJU9kpYPgOlN9IGctLVSk%3D" +
"&SignatureMethod=HmacSHA256" +
"&SignatureVersion=2" +
"&Timestamp=2009-11-08T15%3A54%3A08.897Z" +
"&Version=2012-04-23" +
"&AWSAccessKeyId=identity",
"application/x-www-form-urlencoded"))
.build();
HttpResponse authorizeResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResourceWithContentType("/authorize_securitygroup.xml", "text/xml")).build();
RDSApi apiWhenExist = requestSendsResponse(authorize, authorizeResponse);
apiWhenExist.getSecurityGroupApi().authorizeIngressToIPRange("mydbsecuritygroup", "0.0.0.0/0");
}
public void testAuthorizeIngressToEC2SecurityGroupOfOwnerWhenResponseIs2xx() throws Exception {
HttpRequest authorize = HttpRequest.builder()
.method("POST")
.endpoint("https://rds.us-east-1.amazonaws.com/")
.addHeader("Host", "rds.us-east-1.amazonaws.com")
.payload(
payloadFromStringWithContentType(
"Action=AuthorizeDBSecurityGroupIngress" +
"&DBSecurityGroupName=mydbsecuritygroup" +
"&EC2SecurityGroupName=myec2securitygroup" +
"&EC2SecurityGroupOwnerId=054794666394" +
"&Signature=MM%2B8ccK7Mh%2BWLS4qA1NUyOqtkjC1ICXug8wcEyD4a6c%3D" +
"&SignatureMethod=HmacSHA256" +
"&SignatureVersion=2" +
"&Timestamp=2009-11-08T15%3A54%3A08.897Z" +
"&Version=2012-04-23" +
"&AWSAccessKeyId=identity",
"application/x-www-form-urlencoded"))
.build();
HttpResponse authorizeResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResourceWithContentType("/authorize_securitygroup.xml", "text/xml")).build();
RDSApi apiWhenExist = requestSendsResponse(authorize, authorizeResponse);
apiWhenExist.getSecurityGroupApi().authorizeIngressToEC2SecurityGroupOfOwner("mydbsecuritygroup", "myec2securitygroup", "054794666394");
}
public void testAuthorizeIngressToVPCSecurityGroupWhenResponseIs2xx() throws Exception {
HttpRequest authorize = HttpRequest.builder()
.method("POST")
.endpoint("https://rds.us-east-1.amazonaws.com/")
.addHeader("Host", "rds.us-east-1.amazonaws.com")
.payload(
payloadFromStringWithContentType(
"Action=AuthorizeDBSecurityGroupIngress" +
"&DBSecurityGroupName=mydbsecuritygroup" +
"&EC2SecurityGroupId=sg-1312321312" +
"&Signature=o31Wey%2FwliTbHJoxdF7KGqIJwSM6pfqzkjIYio3XNGs%3D" +
"&SignatureMethod=HmacSHA256" +
"&SignatureVersion=2" +
"&Timestamp=2009-11-08T15%3A54%3A08.897Z" +
"&Version=2012-04-23" +
"&AWSAccessKeyId=identity",
"application/x-www-form-urlencoded"))
.build();
HttpResponse authorizeResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResourceWithContentType("/authorize_securitygroup.xml", "text/xml")).build();
RDSApi apiWhenExist = requestSendsResponse(authorize, authorizeResponse);
apiWhenExist.getSecurityGroupApi().authorizeIngressToVPCSecurityGroup("mydbsecuritygroup", "sg-1312321312");
}
public void testRevokeIngressFromIPRangeWhenResponseIs2xx() throws Exception {
HttpRequest revoke = HttpRequest.builder()
.method("POST")
.endpoint("https://rds.us-east-1.amazonaws.com/")
.addHeader("Host", "rds.us-east-1.amazonaws.com")
.payload(
payloadFromStringWithContentType(
"Action=RevokeDBSecurityGroupIngress" +
"&CIDRIP=0.0.0.0%2F0" +
"&DBSecurityGroupName=mydbsecuritygroup" +
"&Signature=YD1%2BzKmoWyYCmqWq1X9f%2FVj6UC7UnkwkPf%2BA5urnz%2BE%3D" +
"&SignatureMethod=HmacSHA256" +
"&SignatureVersion=2" +
"&Timestamp=2009-11-08T15%3A54%3A08.897Z" +
"&Version=2012-04-23" +
"&AWSAccessKeyId=identity",
"application/x-www-form-urlencoded"))
.build();
HttpResponse revokeResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResourceWithContentType("/revoke_securitygroup.xml", "text/xml")).build();
RDSApi apiWhenExist = requestSendsResponse(revoke, revokeResponse);
apiWhenExist.getSecurityGroupApi().revokeIngressFromIPRange("mydbsecuritygroup", "0.0.0.0/0");
}
public void testRevokeIngressFromEC2SecurityGroupOfOwnerWhenResponseIs2xx() throws Exception {
HttpRequest revoke = HttpRequest.builder()
.method("POST")
.endpoint("https://rds.us-east-1.amazonaws.com/")
.addHeader("Host", "rds.us-east-1.amazonaws.com")
.payload(
payloadFromStringWithContentType(
"Action=RevokeDBSecurityGroupIngress" +
"&DBSecurityGroupName=mydbsecuritygroup" +
"&EC2SecurityGroupName=myec2securitygroup" +
"&EC2SecurityGroupOwnerId=054794666394" +
"&Signature=OknWXceQDAgmZBNzDdhxjaOJI48hYrnFJDOySBc4Qy4%3D" +
"&SignatureMethod=HmacSHA256" +
"&SignatureVersion=2" +
"&Timestamp=2009-11-08T15%3A54%3A08.897Z" +
"&Version=2012-04-23" +
"&AWSAccessKeyId=identity",
"application/x-www-form-urlencoded"))
.build();
HttpResponse revokeResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResourceWithContentType("/revoke_securitygroup.xml", "text/xml")).build();
RDSApi apiWhenExist = requestSendsResponse(revoke, revokeResponse);
apiWhenExist.getSecurityGroupApi().revokeIngressFromEC2SecurityGroupOfOwner("mydbsecuritygroup", "myec2securitygroup", "054794666394");
}
public void testRevokeIngressFromVPCSecurityGroupWhenResponseIs2xx() throws Exception {
HttpRequest revoke = HttpRequest.builder()
.method("POST")
.endpoint("https://rds.us-east-1.amazonaws.com/")
.addHeader("Host", "rds.us-east-1.amazonaws.com")
.payload(
payloadFromStringWithContentType(
"Action=RevokeDBSecurityGroupIngress" +
"&DBSecurityGroupName=mydbsecuritygroup" +
"&EC2SecurityGroupId=sg-1312321312" +
"&Signature=YI2oGYI%2BCx4DGYx43WH%2FehW6CWe6X6wEipsp5zPySzw%3D" +
"&SignatureMethod=HmacSHA256" +
"&SignatureVersion=2" +
"&Timestamp=2009-11-08T15%3A54%3A08.897Z" +
"&Version=2012-04-23" +
"&AWSAccessKeyId=identity",
"application/x-www-form-urlencoded"))
.build();
HttpResponse revokeResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResourceWithContentType("/revoke_securitygroup.xml", "text/xml")).build();
RDSApi apiWhenExist = requestSendsResponse(revoke, revokeResponse);
apiWhenExist.getSecurityGroupApi().revokeIngressFromVPCSecurityGroup("mydbsecuritygroup", "sg-1312321312");
}
HttpRequest delete = HttpRequest.builder()
.method("POST")
.endpoint("https://rds.us-east-1.amazonaws.com/")

View File

@ -19,15 +19,28 @@
package org.jclouds.rds.features;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;
import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;
import javax.annotation.Nullable;
import org.jclouds.collect.IterableWithMarker;
import org.jclouds.predicates.RetryablePredicate;
import org.jclouds.rds.domain.Authorization;
import org.jclouds.rds.domain.Authorization.Status;
import org.jclouds.rds.domain.EC2SecurityGroup;
import org.jclouds.rds.domain.SecurityGroup;
import org.jclouds.rds.internal.BaseRDSApiLiveTest;
import org.jclouds.rds.options.ListSecurityGroupsOptions;
import org.testng.Assert;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
/**
@ -35,19 +48,102 @@ import com.google.common.collect.Iterables;
*/
@Test(groups = "live", testName = "SecurityGroupApiLiveTest")
public class SecurityGroupApiLiveTest extends BaseRDSApiLiveTest {
public static final String SECURITYGROUP = (System.getProperty("user.name") + "-jclouds-securityGroup")
.toLowerCase();
private RetryablePredicate<SecurityGroup> ipRangesAuthorized;
private RetryablePredicate<SecurityGroup> ipRangesRevoked;
@BeforeClass(groups = "live")
@Override
public void setupContext() {
super.setupContext();
ipRangesAuthorized = new RetryablePredicate<SecurityGroup>(new Predicate<SecurityGroup>() {
@Override
public boolean apply(SecurityGroup input) {
return Iterables.all(api().get(input.getName()).getIPRanges(), new Predicate<Authorization>() {
@Override
public boolean apply(@Nullable Authorization i2) {
return i2.getStatus() == Status.AUTHORIZED;
}
});
}
}, 30000, 100, 500, TimeUnit.MILLISECONDS);
ipRangesRevoked = new RetryablePredicate<SecurityGroup>(new Predicate<SecurityGroup>() {
@Override
public boolean apply(SecurityGroup input) {
return api().get(input.getName()).getIPRanges().size() == 0;
}
}, 30000, 100, 500, TimeUnit.MILLISECONDS);
}
private SecurityGroup securityGroup;
public void testCreateSecurityGroup() {
SecurityGroup newSecurityGroup = api().createWithNameAndDescription(SECURITYGROUP, "jclouds");
securityGroup = newSecurityGroup;
Logger.getAnonymousLogger().info("created securityGroup: " + securityGroup);
assertEquals(securityGroup.getName(), SECURITYGROUP);
assertEquals(securityGroup.getDescription(), "jclouds");
checkSecurityGroup(newSecurityGroup);
}
@Test(dependsOnMethods = "testCreateSecurityGroup")
protected void testAuthorizeIPRange() {
securityGroup = api().authorizeIngressToIPRange(SECURITYGROUP, "0.0.0.0/0");
assertTrue(ipRangesAuthorized.apply(securityGroup), securityGroup.toString());
securityGroup = api().get(securityGroup.getName());
Logger.getAnonymousLogger().info("ip range authorized: " + securityGroup);
}
@Test(dependsOnMethods = "testAuthorizeIPRange")
protected void testRevokeIPRange() {
securityGroup = api().revokeIngressFromIPRange(SECURITYGROUP, "0.0.0.0/0");
assertTrue(ipRangesRevoked.apply(securityGroup), securityGroup.toString());
securityGroup = api().get(securityGroup.getName());
Logger.getAnonymousLogger().info("ip range revoked: " + securityGroup);
}
@Test(dependsOnMethods = "testRevokeIPRange")
public void testDeleteSecurityGroup() {
api().delete(securityGroup.getName());
// TODO block and determine the state of a deleted securityGroup
Logger.getAnonymousLogger().info("securityGroup deleted: " + securityGroup);
}
@Override
@AfterClass(groups = "live")
protected void tearDownContext() {
api().delete(SECURITYGROUP);
super.tearDownContext();
}
static void checkSecurityGroup(SecurityGroup securityGroup) {
checkNotNull(securityGroup.getName(), "Name cannot be null for a SecurityGroup: %s", securityGroup);
checkNotNull(securityGroup.getDescription(), "Description cannot be null for a SecurityGroup: %s", securityGroup);
checkNotNull(securityGroup.getOwnerId(), "OwnerId cannot be null for a SecurityGroup: %s", securityGroup);
checkNotNull(securityGroup.getVpcId(), "VpcId cannot be null for a SecurityGroup: %s", securityGroup);
checkNotNull(securityGroup.getDescription(), "Description cannot be null for a SecurityGroup: %s", securityGroup);
checkNotNull(securityGroup.getOwnerId(), "OwnerId cannot be null for a SecurityGroup: %s", securityGroup);
checkNotNull(securityGroup.getVpcId(), "VpcId cannot be null for a SecurityGroup: %s", securityGroup);
for (EC2SecurityGroup security : securityGroup.getEC2SecurityGroups()) {
checkEC2SecurityGroup(security);
}
}
static void checkEC2SecurityGroup(EC2SecurityGroup security) {
checkNotNull(security.getId(), "Id can be null for a SecurityGroup, but its Optional Wrapper cannot: %s", security);
checkNotNull(security.getId(), "Id can be null for a SecurityGroup, but its Optional Wrapper cannot: %s",
security);
checkNotNull(security.getStatus(), "Status cannot be null for a SecurityGroup: %s", security);
checkNotNull(security.getName(), "Name cannot be null for a SecurityGroup: %s", security);
checkNotNull(security.getOwnerId(), "Name cannot be null for a SecurityGroup: %s", security);

View File

@ -60,7 +60,8 @@ public class DescribeDBInstancesResponseTest extends BaseHandlerTest {
.engine("mysql")
.multiAZ(false)
.licenseModel("general-public-license")
.status("available")
.rawStatus("available")
.status(Instance.Status.AVAILABLE)
.engineVersion("5.1.50")
.endpoint(HostAndPort.fromParts("simcoprod01.cu7u2t4uz396.us-east-1.rds.amazonaws.com", 3306))
.id("simcoprod01")

View File

@ -25,6 +25,7 @@ import java.io.InputStream;
import org.jclouds.collect.IterableWithMarker;
import org.jclouds.collect.IterableWithMarkers;
import org.jclouds.http.functions.BaseHandlerTest;
import org.jclouds.rds.domain.Authorization.Status;
import org.jclouds.rds.domain.EC2SecurityGroup;
import org.jclouds.rds.domain.IPRange;
import org.jclouds.rds.domain.SecurityGroup;
@ -56,17 +57,24 @@ public class DescribeDBSecurityGroupsResponseTest extends BaseHandlerTest {
return IterableWithMarkers.from(ImmutableSet.<SecurityGroup>builder()
.add(SecurityGroup.builder()
.ec2SecurityGroup(EC2SecurityGroup.builder()
.status("authorized")
.rawStatus("authorized")
.status(Status.AUTHORIZED)
.name("myec2securitygroup")
.ownerId("054794666394").build())
.description("default")
.ipRange(IPRange.builder().cidrIp("127.0.0.1/30").status("authorized").build())
.ipRange(IPRange.builder()
.cidrIp("127.0.0.1/30")
.rawStatus("authorized")
.status(Status.AUTHORIZED).build())
.ownerId("621567473609")
.name("default")
.vpcId("vpc-1ab2c3d4").build())
.add(SecurityGroup.builder()
.description("My new DBSecurityGroup")
.ipRange(IPRange.builder().cidrIp("192.168.1.1/24").status("authorized").build())
.ipRange(IPRange.builder()
.cidrIp("192.168.1.1/24")
.rawStatus("authorized")
.status(Status.AUTHORIZED).build())
.ownerId("621567473609")
.name("mydbsecuritygroup")
.vpcId("vpc-1ab2c3d5").build())

View File

@ -55,7 +55,8 @@ public class GetInstanceResponseTest extends BaseHandlerTest {
.engine("mysql")
.multiAZ(false)
.licenseModel("general-public-license")
.status("available")
.rawStatus("available")
.status(Instance.Status.AVAILABLE)
.engineVersion("5.1.50")
.endpoint(HostAndPort.fromParts("simcoprod01.cu7u2t4uz396.us-east-1.rds.amazonaws.com", 3306))
.id("simcoprod01")

View File

@ -23,6 +23,7 @@ import static org.testng.Assert.assertEquals;
import java.io.InputStream;
import org.jclouds.http.functions.BaseHandlerTest;
import org.jclouds.rds.domain.Authorization.Status;
import org.jclouds.rds.domain.EC2SecurityGroup;
import org.jclouds.rds.domain.IPRange;
import org.jclouds.rds.domain.SecurityGroup;
@ -50,11 +51,15 @@ public class GetSecurityGroupResponseTest extends BaseHandlerTest {
public SecurityGroup expected() {
return SecurityGroup.builder()
.ec2SecurityGroup(EC2SecurityGroup.builder()
.status("authorized")
.rawStatus("authorized")
.status(Status.AUTHORIZED)
.name("myec2securitygroup")
.ownerId("054794666394").build())
.description("default")
.ipRange(IPRange.builder().cidrIp("127.0.0.1/30").status("authorized").build())
.ipRange(IPRange.builder()
.cidrIp("127.0.0.1/30")
.rawStatus("authorized")
.status(Status.AUTHORIZED).build())
.ownerId("621567473609")
.name("default")
.vpcId("vpc-1ab2c3d4").build();

View File

@ -0,0 +1,20 @@
<AuthorizeDBSecurityGroupIngressResponse xmlns="http://rds.amazonaws.com/doc/2012-04-23/">
<AuthorizeDBSecurityGroupIngressResult>
<DBSecurityGroup>
<EC2SecurityGroups/>
<DBSecurityGroupDescription>My new DBSecurityGroup</DBSecurityGroupDescription>
<IPRanges>
<IPRange>
<CIDRIP>192.168.1.1/24</CIDRIP>
<Status>authorizing</Status>
</IPRange>
</IPRanges>
<OwnerId>621567473609</OwnerId>
<DBSecurityGroupName>mydbsecuritygroup</DBSecurityGroupName>
<VpcId>vpc-1ab2c3d4</VpcId>
</DBSecurityGroup>
</AuthorizeDBSecurityGroupIngressResult>
<ResponseMetadata>
<RequestId>d9799197-bf2d-11de-b88d-993294bf1c81</RequestId>
</ResponseMetadata>
</AuthorizeDBSecurityGroupIngressResponse>

View File

@ -0,0 +1,67 @@
<CreateDBInstanceResponse xmlns="http://rds.amazonaws.com/doc/2012-04-23/">
<CreateDBInstanceResult>
<DBInstance>
<ReadReplicaDBInstanceIdentifiers/>
<Engine>mysql</Engine>
<PendingModifiedValues>
<MasterUserPassword>****</MasterUserPassword>
</PendingModifiedValues>
<BackupRetentionPeriod>1</BackupRetentionPeriod>
<MultiAZ>false</MultiAZ>
<LicenseModel>general-public-license</LicenseModel>
<DBSubnetGroup>
<VpcId>990524496922</VpcId>
<SubnetGroupStatus>Complete</SubnetGroupStatus>
<DBSubnetGroupDescription>description</DBSubnetGroupDescription>
<DBSubnetGroupName>subnet_grp1</DBSubnetGroupName>
<Subnets>
<Subnet>
<SubnetStatus>Active</SubnetStatus>
<SubnetIdentifier>subnet-7c5b4115</SubnetIdentifier>
<SubnetAvailabilityZone>
<Name>us-east-1c</Name>
</SubnetAvailabilityZone>
</Subnet>
<Subnet>
<SubnetStatus>Active</SubnetStatus>
<SubnetIdentifier>subnet-7b5b4112</SubnetIdentifier>
<SubnetAvailabilityZone>
<Name>us-east-1b</Name>
</SubnetAvailabilityZone>
</Subnet>
<Subnet>
<SubnetStatus>Active</SubnetStatus>
<SubnetIdentifier>subnet-3ea6bd57</SubnetIdentifier>
<SubnetAvailabilityZone>
<Name>us-east-1d</Name>
</SubnetAvailabilityZone>
</Subnet>
</Subnets>
</DBSubnetGroup>
<DBInstanceStatus>creating</DBInstanceStatus>
<EngineVersion>5.1.50</EngineVersion>
<DBInstanceIdentifier>simcoprod01</DBInstanceIdentifier>
<DBParameterGroups>
<DBParameterGroup>
<ParameterApplyStatus>in-sync</ParameterApplyStatus>
<DBParameterGroupName>default.mysql5.1</DBParameterGroupName>
</DBParameterGroup>
</DBParameterGroups>
<DBSecurityGroups>
<DBSecurityGroup>
<Status>active</Status>
<DBSecurityGroupName>default</DBSecurityGroupName>
</DBSecurityGroup>
</DBSecurityGroups>
<PreferredBackupWindow>00:00-00:30</PreferredBackupWindow>
<AutoMinorVersionUpgrade>true</AutoMinorVersionUpgrade>
<PreferredMaintenanceWindow>sat:07:30-sat:08:00</PreferredMaintenanceWindow>
<AllocatedStorage>10</AllocatedStorage>
<DBInstanceClass>db.m1.large</DBInstanceClass>
<MasterUsername>master</MasterUsername>
</DBInstance>
</CreateDBInstanceResult>
<ResponseMetadata>
<RequestId>2e5d4270-8501-11e0-bd9b-a7b1ece36d51</RequestId>
</ResponseMetadata>
</CreateDBInstanceResponse>

View File

@ -0,0 +1,15 @@
<CreateDBSecurityGroupResponse xmlns="http://rds.amazonaws.com/doc/2012-04-23/">
<CreateDBSecurityGroupResult>
<DBSecurityGroup>
<EC2SecurityGroups/>
<DBSecurityGroupDescription>My new DBSecurityGroup</DBSecurityGroupDescription>
<IPRanges/>
<OwnerId>565419523791</OwnerId>
<DBSecurityGroupName>mydbsecuritygroup</DBSecurityGroupName>
<VpcId>vpc-1a2b3c4d</VpcId>
</DBSecurityGroup>
</CreateDBSecurityGroupResult>
<ResponseMetadata>
<RequestId>ed662948-a57b-11df-9e38-7ffab86c801f</RequestId>
</ResponseMetadata>
</CreateDBSecurityGroupResponse>

View File

@ -0,0 +1,42 @@
<DeleteDBInstanceResponse xmlns="http://rds.amazonaws.com/doc/2012-04-23/">
<DeleteDBInstanceResult>
<DBInstance>
<ReadReplicaDBInstanceIdentifiers/>
<LatestRestorableTime>2011-05-23T07:15:00Z</LatestRestorableTime>
<Engine>mysql</Engine>
<PendingModifiedValues/>
<BackupRetentionPeriod>1</BackupRetentionPeriod>
<MultiAZ>false</MultiAZ>
<LicenseModel>general-public-license</LicenseModel>
<DBInstanceStatus>deleting</DBInstanceStatus>
<EngineVersion>5.1.50</EngineVersion>
<Endpoint>
<Port>3306</Port>
</Endpoint>
<DBInstanceIdentifier>myrestoreddbinstance</DBInstanceIdentifier>
<DBParameterGroups>
<DBParameterGroup>
<ParameterApplyStatus>in-sync</ParameterApplyStatus>
<DBParameterGroupName>default.mysql5.1</DBParameterGroupName>
</DBParameterGroup>
</DBParameterGroups>
<DBSecurityGroups>
<DBSecurityGroup>
<Status>active</Status>
<DBSecurityGroupName>default</DBSecurityGroupName>
</DBSecurityGroup>
</DBSecurityGroups>
<PreferredBackupWindow>00:00-00:30</PreferredBackupWindow>
<AutoMinorVersionUpgrade>true</AutoMinorVersionUpgrade>
<PreferredMaintenanceWindow>sat:07:30-sat:08:00</PreferredMaintenanceWindow>
<AvailabilityZone>us-east-1d</AvailabilityZone>
<InstanceCreateTime>2011-05-23T06:52:48.255Z</InstanceCreateTime>
<AllocatedStorage>10</AllocatedStorage>
<DBInstanceClass>db.m1.large</DBInstanceClass>
<MasterUsername>master</MasterUsername>
</DBInstance>
</DeleteDBInstanceResult>
<ResponseMetadata>
<RequestId>03ea4ae8-850d-11e0-90aa-eb648410240d</RequestId>
</ResponseMetadata>
</DeleteDBInstanceResponse>

View File

@ -0,0 +1,8 @@
<ErrorResponse xmlns="http://rds.amazonaws.com/doc/2012-04-23/">
<Error>
<Type>Sender</Type>
<Code>InvalidDBInstanceState</Code>
<Message>Can only delete db instances with state in: available, failed, storage-full, incompatible-option-group, incompatible-parameters, incompatible-restore, incompatible-network. Instance adriancole-jclouds has state: deleting.</Message>
</Error>
<RequestId>77db43a3-d6d2-11e1-aaa2-59d4ca8d1ef6</RequestId>
</ErrorResponse>

View File

@ -0,0 +1,20 @@
<RevokeDBSecurityGroupIngressResponse xmlns="http://rds.amazonaws.com/doc/2012-04-23/">
<RevokeDBSecurityGroupIngressResult>
<DBSecurityGroup>
<EC2SecurityGroups/>
<DBSecurityGroupDescription>My new DBSecurityGroup</DBSecurityGroupDescription>
<IPRanges>
<IPRange>
<CIDRIP>192.168.1.1/24</CIDRIP>
<Status>revoking</Status>
</IPRange>
</IPRanges>
<OwnerId>621567473609</OwnerId>
<DBSecurityGroupName>mydbsecuritygroup</DBSecurityGroupName>
<VpcId>vpc-1ab2c3d4</VpcId>
</DBSecurityGroup>
</RevokeDBSecurityGroupIngressResult>
<ResponseMetadata>
<RequestId>beecb8ac-bf5a-11de-9f9f-53d6aee22de9</RequestId>
</ResponseMetadata>
</RevokeDBSecurityGroupIngressResponse>