mirror of https://github.com/apache/jclouds.git
Merge pull request #1301 from jclouds/dynect-zone
finished zone support for dynect
This commit is contained in:
commit
79f7ba0b55
|
@ -18,8 +18,10 @@
|
|||
*/
|
||||
package org.jclouds.dynect.v3;
|
||||
|
||||
import org.jclouds.dynect.v3.domain.Job;
|
||||
import org.jclouds.dynect.v3.features.SessionApi;
|
||||
import org.jclouds.dynect.v3.features.ZoneApi;
|
||||
import org.jclouds.javax.annotation.Nullable;
|
||||
import org.jclouds.rest.annotations.Delegate;
|
||||
|
||||
/**
|
||||
|
@ -32,6 +34,15 @@ import org.jclouds.rest.annotations.Delegate;
|
|||
* @author Adrian Cole
|
||||
*/
|
||||
public interface DynECTApi {
|
||||
/**
|
||||
* returns the current status of a job.
|
||||
*
|
||||
* @param jobId
|
||||
* The ID of the job
|
||||
* @return null, if not found
|
||||
*/
|
||||
@Nullable
|
||||
Job getJob(long jobId);
|
||||
|
||||
/**
|
||||
* Provides synchronous access to Session features.
|
||||
|
|
|
@ -20,12 +20,24 @@ package org.jclouds.dynect.v3;
|
|||
|
||||
import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
|
||||
|
||||
import javax.inject.Named;
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.PathParam;
|
||||
import javax.ws.rs.Produces;
|
||||
|
||||
import org.jclouds.Fallbacks.NullOnNotFoundOr404;
|
||||
import org.jclouds.dynect.v3.domain.Job;
|
||||
import org.jclouds.dynect.v3.features.SessionAsyncApi;
|
||||
import org.jclouds.dynect.v3.features.ZoneAsyncApi;
|
||||
import org.jclouds.dynect.v3.filters.SessionManager;
|
||||
import org.jclouds.rest.annotations.Delegate;
|
||||
import org.jclouds.rest.annotations.Fallback;
|
||||
import org.jclouds.rest.annotations.Headers;
|
||||
import org.jclouds.rest.annotations.RequestFilters;
|
||||
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
|
||||
/**
|
||||
* Provides access to DynECT Managed DNS through the API2 api
|
||||
|
@ -35,10 +47,19 @@ import org.jclouds.rest.annotations.Headers;
|
|||
* @see <a href="https://manage.dynect.net/help/docs/api2/rest/" />
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
// required for all calls
|
||||
@Produces(APPLICATION_JSON)
|
||||
@Headers(keys = "API-Version", values = "{jclouds.api-version}")
|
||||
public interface DynECTAsyncApi {
|
||||
/**
|
||||
* @see DynECTApi#getJob
|
||||
*/
|
||||
@Named("GetJob")
|
||||
@GET
|
||||
@Path("/Job/{jobId}")
|
||||
@Produces(APPLICATION_JSON)
|
||||
@RequestFilters(SessionManager.class)
|
||||
@Headers(keys = "API-Version", values = "{jclouds.api-version}")
|
||||
@Fallback(NullOnNotFoundOr404.class)
|
||||
@Consumes(APPLICATION_JSON)
|
||||
ListenableFuture<Job> getJob(@PathParam("jobId") long jobId);
|
||||
|
||||
/**
|
||||
* Provides asynchronous access to Session features.
|
||||
|
|
|
@ -29,8 +29,10 @@ import org.jclouds.dynect.v3.features.SessionAsyncApi;
|
|||
import org.jclouds.dynect.v3.features.ZoneApi;
|
||||
import org.jclouds.dynect.v3.features.ZoneAsyncApi;
|
||||
import org.jclouds.dynect.v3.filters.SessionManager;
|
||||
import org.jclouds.dynect.v3.handlers.GetJobRedirectionRetryHandler;
|
||||
import org.jclouds.http.HttpRetryHandler;
|
||||
import org.jclouds.http.annotation.ClientError;
|
||||
import org.jclouds.http.handlers.RedirectionRetryHandler;
|
||||
import org.jclouds.rest.ConfiguresRestClient;
|
||||
import org.jclouds.rest.config.RestClientModule;
|
||||
|
||||
|
@ -61,6 +63,7 @@ public class DynECTRestClientModule extends RestClientModule<DynECTApi, DynECTAs
|
|||
protected void configure() {
|
||||
// binding explicitly ensures singleton despite multiple linked bindings
|
||||
bind(SessionManager.class);
|
||||
bind(RedirectionRetryHandler.class).to(GetJobRedirectionRetryHandler.class);
|
||||
super.configure();
|
||||
// Bind apis that are used directly vs via DynECTApi
|
||||
bindHttpApi(binder(), SessionApi.class, SessionAsyncApi.class);
|
||||
|
|
|
@ -0,0 +1,161 @@
|
|||
/**
|
||||
* 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, String 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.dynect.v3.domain;
|
||||
|
||||
import static com.google.common.base.Objects.equal;
|
||||
import static com.google.common.base.Objects.toStringHelper;
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import javax.inject.Named;
|
||||
|
||||
import org.jclouds.dynect.v3.domain.Zone.SerialStyle;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Objects;
|
||||
|
||||
/**
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
public final class CreatePrimaryZone {
|
||||
// persisted via path param
|
||||
private final transient String fqdn;
|
||||
@Named("rname")
|
||||
private final String contact;
|
||||
@Named("serial_style")
|
||||
private final SerialStyle serialStyle;
|
||||
@Named("ttl")
|
||||
private final int defaultTTL;
|
||||
|
||||
private CreatePrimaryZone(String fqdn, String contact, SerialStyle serialStyle, int defaultTTL) {
|
||||
this.fqdn = checkNotNull(fqdn, "fqdn");
|
||||
this.contact = checkNotNull(contact, "contact for %s", fqdn);
|
||||
this.defaultTTL = checkNotNull(defaultTTL, "defaultTTL for %s", fqdn);
|
||||
this.serialStyle = checkNotNull(serialStyle, "serialStyle for %s", serialStyle);
|
||||
}
|
||||
|
||||
/**
|
||||
* The fqdn of the zone to create
|
||||
*/
|
||||
public String getFQDN() {
|
||||
return fqdn;
|
||||
}
|
||||
|
||||
/**
|
||||
* The administrative contact or {@code rname} for the {@code SOA} record.
|
||||
*/
|
||||
public String getContact() {
|
||||
return contact;
|
||||
}
|
||||
|
||||
/**
|
||||
* Default TTL (in seconds) for records in the zone. Defaults to 3600.
|
||||
*/
|
||||
public int getDefaultTTL() {
|
||||
return defaultTTL;
|
||||
}
|
||||
|
||||
/**
|
||||
* The style of the zone's serial. Defaults to {@link SerialStyle#INCREMENT}.
|
||||
*/
|
||||
public SerialStyle getSerialStyle() {
|
||||
return serialStyle;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hashCode(fqdn, contact);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null || getClass() != obj.getClass())
|
||||
return false;
|
||||
CreatePrimaryZone that = CreatePrimaryZone.class.cast(obj);
|
||||
return equal(this.fqdn, that.fqdn) && equal(this.contact, that.contact);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return toStringHelper(this).omitNullValues().add("fqdn", fqdn).add("contact", contact)
|
||||
.add("defaultTTL", defaultTTL).add("serialStyle", serialStyle).toString();
|
||||
}
|
||||
|
||||
public static Builder builder() {
|
||||
return new Builder();
|
||||
}
|
||||
|
||||
public Builder toBuilder() {
|
||||
return builder().from(this);
|
||||
}
|
||||
|
||||
public final static class Builder {
|
||||
private String fqdn;
|
||||
private String contact;
|
||||
private int defaultTTL = 3600;
|
||||
private SerialStyle serialStyle = SerialStyle.INCREMENT;
|
||||
|
||||
/**
|
||||
* @see CreatePrimaryZone#getFQDN()
|
||||
*/
|
||||
public Builder fqdn(String fqdn) {
|
||||
this.fqdn = fqdn;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see CreatePrimaryZone#getContact()
|
||||
*/
|
||||
public Builder contact(String contact) {
|
||||
this.contact = contact;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see CreatePrimaryZone#getDefaultTTL()
|
||||
*/
|
||||
public Builder defaultTTL(int defaultTTL) {
|
||||
this.defaultTTL = defaultTTL;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see CreatePrimaryZone#getSerialStyle()
|
||||
*/
|
||||
public Builder serialStyle(SerialStyle serialStyle) {
|
||||
this.serialStyle = serialStyle;
|
||||
return this;
|
||||
}
|
||||
|
||||
public CreatePrimaryZone build() {
|
||||
return new CreatePrimaryZone(fqdn, contact, serialStyle, defaultTTL);
|
||||
}
|
||||
|
||||
public Builder from(CreatePrimaryZone in) {
|
||||
return this.fqdn(in.fqdn).contact(in.contact).serialStyle(in.serialStyle).defaultTTL(in.defaultTTL);
|
||||
}
|
||||
}
|
||||
|
||||
public static final class ToFQDN implements Function<Object, String> {
|
||||
public String apply(Object in) {
|
||||
return CreatePrimaryZone.class.cast(in).getFQDN();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,99 @@
|
|||
/**
|
||||
* 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.dynect.v3.domain;
|
||||
|
||||
import static com.google.common.base.Objects.equal;
|
||||
import static com.google.common.base.Objects.toStringHelper;
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import java.beans.ConstructorProperties;
|
||||
|
||||
import javax.inject.Named;
|
||||
|
||||
import com.google.common.base.Objects;
|
||||
|
||||
/**
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
public final class Job {
|
||||
|
||||
@Named("job_id")
|
||||
private final long id;
|
||||
private final Status status;
|
||||
|
||||
@ConstructorProperties({ "job_id", "status" })
|
||||
private Job(long id, Status status) {
|
||||
this.id = checkNotNull(id, "id");
|
||||
this.status = checkNotNull(status, "status for %s", id);
|
||||
}
|
||||
|
||||
/**
|
||||
* The ID of the job.
|
||||
*/
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* The current status of the job.
|
||||
*/
|
||||
public Status getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public enum Status {
|
||||
SUCCESS, FAILURE, UNRECOGNIZED;
|
||||
|
||||
public static Status fromValue(String status) {
|
||||
try {
|
||||
return valueOf(checkNotNull(status, "status").toUpperCase());
|
||||
} catch (IllegalArgumentException e) {
|
||||
return UNRECOGNIZED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hashCode(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null || getClass() != obj.getClass())
|
||||
return false;
|
||||
Job that = Job.class.cast(obj);
|
||||
return equal(this.id, that.id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return toStringHelper(this).add("id", id).add("status", status).toString();
|
||||
}
|
||||
|
||||
public static Job success(long id) {
|
||||
return new Job(id, Status.SUCCESS);
|
||||
}
|
||||
|
||||
public static Job failure(long id) {
|
||||
return new Job(id, Status.FAILURE);
|
||||
}
|
||||
}
|
|
@ -34,7 +34,7 @@ import com.google.common.base.Objects;
|
|||
*/
|
||||
public final class Zone {
|
||||
|
||||
private final String name;
|
||||
private final String fqdn;
|
||||
@Named("zone_type")
|
||||
private final Type type;
|
||||
private final int serial;
|
||||
|
@ -92,18 +92,18 @@ public final class Zone {
|
|||
}
|
||||
|
||||
@ConstructorProperties({ "zone", "zone_type", "serial", "serial_style" })
|
||||
private Zone(String name, Type type, int serial, SerialStyle serialStyle) {
|
||||
this.name = checkNotNull(name, "name");
|
||||
this.type = checkNotNull(type, "type for %s", name);
|
||||
this.serial = checkNotNull(serial, "serial for %s", name);
|
||||
private Zone(String fqdn, Type type, int serial, SerialStyle serialStyle) {
|
||||
this.fqdn = checkNotNull(fqdn, "fqdn");
|
||||
this.type = checkNotNull(type, "type for %s", fqdn);
|
||||
this.serial = checkNotNull(serial, "serial for %s", fqdn);
|
||||
this.serialStyle = checkNotNull(serialStyle, "serialStyle for %s", serialStyle);
|
||||
}
|
||||
|
||||
/**
|
||||
* The name of the requested zone
|
||||
* The fqdn of the requested zone
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
public String getFQDN() {
|
||||
return fqdn;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -129,7 +129,7 @@ public final class Zone {
|
|||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hashCode(name, type);
|
||||
return Objects.hashCode(fqdn, type);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -139,12 +139,12 @@ public final class Zone {
|
|||
if (obj == null || getClass() != obj.getClass())
|
||||
return false;
|
||||
Zone that = Zone.class.cast(obj);
|
||||
return equal(this.name, that.name) && equal(this.type, that.type);
|
||||
return equal(this.fqdn, that.fqdn) && equal(this.type, that.type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return toStringHelper(this).omitNullValues().add("name", name).add("type", type).add("serial", serial)
|
||||
return toStringHelper(this).omitNullValues().add("fqdn", fqdn).add("type", type).add("serial", serial)
|
||||
.add("serialStyle", serialStyle).toString();
|
||||
}
|
||||
|
||||
|
@ -157,16 +157,16 @@ public final class Zone {
|
|||
}
|
||||
|
||||
public final static class Builder {
|
||||
private String name;
|
||||
private String fqdn;
|
||||
private Type type;
|
||||
private int serial;
|
||||
private SerialStyle serialStyle;
|
||||
|
||||
/**
|
||||
* @see Zone#getName()
|
||||
* @see Zone#getFQDN()
|
||||
*/
|
||||
public Builder name(String name) {
|
||||
this.name = name;
|
||||
public Builder fqdn(String fqdn) {
|
||||
this.fqdn = fqdn;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -195,11 +195,11 @@ public final class Zone {
|
|||
}
|
||||
|
||||
public Zone build() {
|
||||
return new Zone(name, type, serial, serialStyle);
|
||||
return new Zone(fqdn, type, serial, serialStyle);
|
||||
}
|
||||
|
||||
public Builder from(Zone in) {
|
||||
return this.name(in.name).type(in.type).serial(in.serial).serialStyle(in.serialStyle);
|
||||
return this.fqdn(in.fqdn).type(in.type).serial(in.serial).serialStyle(in.serialStyle);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -18,7 +18,10 @@
|
|||
*/
|
||||
package org.jclouds.dynect.v3.features;
|
||||
|
||||
import org.jclouds.dynect.v3.domain.CreatePrimaryZone;
|
||||
import org.jclouds.dynect.v3.domain.Job;
|
||||
import org.jclouds.dynect.v3.domain.Zone;
|
||||
import org.jclouds.dynect.v3.domain.Zone.SerialStyle;
|
||||
import org.jclouds.javax.annotation.Nullable;
|
||||
|
||||
import com.google.common.collect.FluentIterable;
|
||||
|
@ -34,14 +37,69 @@ public interface ZoneApi {
|
|||
FluentIterable<String> list();
|
||||
|
||||
/**
|
||||
* Retrieves information about the specified zone, including its nameserver
|
||||
* configuration
|
||||
* Creates a new primary zone.
|
||||
*
|
||||
* @param name
|
||||
* name of the zone to get information about. ex
|
||||
* {@code Z1PA6795UKMFR9}
|
||||
* @param zone
|
||||
* required parameters to create the zone.
|
||||
* @return unpublished zone
|
||||
*/
|
||||
Zone create(CreatePrimaryZone zone);
|
||||
|
||||
/**
|
||||
* Creates a new primary zone with one hour default TTL and
|
||||
* {@link SerialStyle#INCREMENT}
|
||||
*
|
||||
* @param fqdn
|
||||
* fqdn of the zone to create {@ex. jclouds.org}
|
||||
* @param contact
|
||||
* email address of the contact
|
||||
* @return unpublished zone
|
||||
*/
|
||||
Zone createWithContact(String fqdn, String contact);
|
||||
|
||||
/**
|
||||
* Retrieves information about the specified zone.
|
||||
*
|
||||
* @param fqdn
|
||||
* fqdn of the zone to get information about. ex
|
||||
* {@code jclouds.org}
|
||||
* @return null if not found
|
||||
*/
|
||||
@Nullable
|
||||
Zone get(String name);
|
||||
Zone get(String fqdn);
|
||||
|
||||
/**
|
||||
* deletes the specified zone.
|
||||
*
|
||||
* @param fqdn
|
||||
* fqdn of the zone to delete ex {@code jclouds.org}
|
||||
* @return null if not found
|
||||
*/
|
||||
@Nullable
|
||||
Job delete(String fqdn);
|
||||
|
||||
/**
|
||||
* Publishes the current zone
|
||||
*
|
||||
* @param fqdn
|
||||
* fqdn of the zone to publish. ex
|
||||
* {@code jclouds.org}
|
||||
*/
|
||||
Zone publish(String fqdn);
|
||||
|
||||
/**
|
||||
* freezes the specified zone.
|
||||
*
|
||||
* @param fqdn
|
||||
* fqdn of the zone to freeze ex {@code jclouds.org}
|
||||
*/
|
||||
Job freeze(String fqdn);
|
||||
|
||||
/**
|
||||
* thaws the specified zone.
|
||||
*
|
||||
* @param fqdn
|
||||
* fqdn of the zone to thaw ex {@code jclouds.org}
|
||||
*/
|
||||
Job thaw(String fqdn);
|
||||
}
|
|
@ -21,20 +21,32 @@ package org.jclouds.dynect.v3.features;
|
|||
import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
|
||||
|
||||
import javax.inject.Named;
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.DELETE;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.POST;
|
||||
import javax.ws.rs.PUT;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.PathParam;
|
||||
import javax.ws.rs.Produces;
|
||||
|
||||
import org.jclouds.Fallbacks.NullOnNotFoundOr404;
|
||||
import org.jclouds.dynect.v3.domain.CreatePrimaryZone;
|
||||
import org.jclouds.dynect.v3.domain.CreatePrimaryZone.ToFQDN;
|
||||
import org.jclouds.dynect.v3.domain.Job;
|
||||
import org.jclouds.dynect.v3.domain.Zone;
|
||||
import org.jclouds.dynect.v3.filters.SessionManager;
|
||||
import org.jclouds.dynect.v3.functions.ExtractNames;
|
||||
import org.jclouds.rest.annotations.BinderParam;
|
||||
import org.jclouds.rest.annotations.Fallback;
|
||||
import org.jclouds.rest.annotations.Headers;
|
||||
import org.jclouds.rest.annotations.ParamParser;
|
||||
import org.jclouds.rest.annotations.Payload;
|
||||
import org.jclouds.rest.annotations.PayloadParam;
|
||||
import org.jclouds.rest.annotations.RequestFilters;
|
||||
import org.jclouds.rest.annotations.SelectJson;
|
||||
import org.jclouds.rest.annotations.Transform;
|
||||
import org.jclouds.rest.binders.BindToJsonPayload;
|
||||
|
||||
import com.google.common.collect.FluentIterable;
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
|
@ -56,19 +68,79 @@ public interface ZoneAsyncApi {
|
|||
/**
|
||||
* @see ZoneApi#list
|
||||
*/
|
||||
@Named("GET:ZoneList")
|
||||
@Named("ListZones")
|
||||
@GET
|
||||
@SelectJson("data")
|
||||
@Transform(ExtractNames.class)
|
||||
ListenableFuture<FluentIterable<String>> list();
|
||||
|
||||
|
||||
/**
|
||||
* @see ZoneApi#isValid
|
||||
* @see ZoneApi#get
|
||||
*/
|
||||
@Named("GET:Zone")
|
||||
@Named("GetZone")
|
||||
@GET
|
||||
@Path("/{name}")
|
||||
@Path("/{fqdn}")
|
||||
@SelectJson("data")
|
||||
@Fallback(NullOnNotFoundOr404.class)
|
||||
ListenableFuture<Zone> get(@PathParam("name") String name);
|
||||
ListenableFuture<Zone> get(@PathParam("fqdn") String fqdn);
|
||||
|
||||
/**
|
||||
* @see ZoneApi#create
|
||||
*/
|
||||
@Named("CreatePrimaryZone")
|
||||
@POST
|
||||
@Path("/{fqdn}")
|
||||
@SelectJson("data")
|
||||
ListenableFuture<Zone> create(
|
||||
@PathParam("fqdn") @ParamParser(ToFQDN.class) @BinderParam(BindToJsonPayload.class) CreatePrimaryZone createZone);
|
||||
|
||||
/**
|
||||
* @see ZoneApi#createWithContact
|
||||
*/
|
||||
@Named("CreatePrimaryZone")
|
||||
@POST
|
||||
@Payload("%7B\"rname\":\"{contact}\",\"serial_style\":\"increment\",\"ttl\":3600%7D")
|
||||
@Path("/{fqdn}")
|
||||
@SelectJson("data")
|
||||
ListenableFuture<Zone> createWithContact(@PathParam("fqdn") String fqdn, @PayloadParam("contact") String contact);
|
||||
|
||||
/**
|
||||
* @see ZoneApi#delete
|
||||
*/
|
||||
@Named("DeleteZone")
|
||||
@DELETE
|
||||
@Path("/{fqdn}")
|
||||
@Fallback(NullOnNotFoundOr404.class)
|
||||
@Consumes(APPLICATION_JSON)
|
||||
ListenableFuture<Job> delete(@PathParam("fqdn") String fqdn);
|
||||
|
||||
/**
|
||||
* @see ZoneApi#publish
|
||||
*/
|
||||
@Named("PublishZone")
|
||||
@PUT
|
||||
@Payload("{\"publish\":true}")
|
||||
@Path("/{fqdn}")
|
||||
@SelectJson("data")
|
||||
ListenableFuture<Zone> publish(@PathParam("fqdn") String fqdn);
|
||||
|
||||
/**
|
||||
* @see ZoneApi#freeze
|
||||
*/
|
||||
@Named("FreezeZone")
|
||||
@PUT
|
||||
@Path("/{fqdn}")
|
||||
@Payload("{\"freeze\":true}")
|
||||
@Consumes(APPLICATION_JSON)
|
||||
ListenableFuture<Job> freeze(@PathParam("fqdn") String fqdn);
|
||||
|
||||
/**
|
||||
* @see ZoneApi#thaw
|
||||
*/
|
||||
@Named("ThawZone")
|
||||
@PUT
|
||||
@Path("/{fqdn}")
|
||||
@Payload("{\"thaw\":true}")
|
||||
@Consumes(APPLICATION_JSON)
|
||||
ListenableFuture<Job> thaw(@PathParam("fqdn") String fqdn);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
/**
|
||||
* 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.dynect.v3.handlers;
|
||||
|
||||
import static com.google.common.net.HttpHeaders.LOCATION;
|
||||
import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.http.HttpCommand;
|
||||
import org.jclouds.http.HttpRequest;
|
||||
import org.jclouds.http.HttpResponse;
|
||||
import org.jclouds.http.handlers.BackoffLimitedRetryHandler;
|
||||
import org.jclouds.http.handlers.RedirectionRetryHandler;
|
||||
import org.jclouds.io.Payload;
|
||||
import org.jclouds.io.Payloads;
|
||||
|
||||
/**
|
||||
* if the redirection URL is a Job, do not replay the original request; just get
|
||||
* the job.
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Singleton
|
||||
public class GetJobRedirectionRetryHandler extends RedirectionRetryHandler {
|
||||
|
||||
private final Payload emptyPayload;
|
||||
|
||||
@Inject
|
||||
protected GetJobRedirectionRetryHandler(BackoffLimitedRetryHandler backoffHandler) {
|
||||
super(backoffHandler);
|
||||
this.emptyPayload = Payloads.newPayload(new byte[]{});
|
||||
this.emptyPayload.getContentMetadata().setContentType(APPLICATION_JSON);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldRetryRequest(HttpCommand command, HttpResponse response) {
|
||||
String location = response.getFirstHeaderOrNull(LOCATION);
|
||||
if (location != null && location.indexOf("Job") != -1) {
|
||||
HttpRequest getRequest = command.getCurrentRequest().toBuilder()
|
||||
.method("GET")
|
||||
.payload(emptyPayload).build();
|
||||
command.setCurrentRequest(getRequest);
|
||||
}
|
||||
return super.shouldRetryRequest(command, response);
|
||||
}
|
||||
}
|
|
@ -18,12 +18,15 @@
|
|||
*/
|
||||
package org.jclouds.dynect.v3.features;
|
||||
|
||||
import static com.google.common.net.HttpHeaders.ACCEPT;
|
||||
import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
|
||||
import static org.testng.Assert.assertEquals;
|
||||
import static org.testng.Assert.assertNull;
|
||||
|
||||
import org.jclouds.dynect.v3.DynECTApi;
|
||||
import org.jclouds.dynect.v3.domain.CreatePrimaryZone;
|
||||
import org.jclouds.dynect.v3.internal.BaseDynECTApiExpectTest;
|
||||
import org.jclouds.dynect.v3.parse.DeleteZoneResponseTest;
|
||||
import org.jclouds.dynect.v3.parse.GetZoneResponseTest;
|
||||
import org.jclouds.dynect.v3.parse.ListZonesResponseTest;
|
||||
import org.jclouds.http.HttpRequest;
|
||||
|
@ -35,7 +38,6 @@ import org.testng.annotations.Test;
|
|||
*/
|
||||
@Test(groups = "unit", testName = "ZoneApiExpectTest")
|
||||
public class ZoneApiExpectTest extends BaseDynECTApiExpectTest {
|
||||
|
||||
HttpRequest get = HttpRequest.builder().method("GET")
|
||||
.endpoint("https://api2.dynect.net/REST/Zone/jclouds.org")
|
||||
.addHeader("API-Version", "3.3.7")
|
||||
|
@ -51,8 +53,30 @@ public class ZoneApiExpectTest extends BaseDynECTApiExpectTest {
|
|||
assertEquals(success.getZoneApi().get("jclouds.org").toString(),
|
||||
new GetZoneResponseTest().expected().toString());
|
||||
}
|
||||
|
||||
HttpRequest create = HttpRequest.builder().method("POST")
|
||||
.endpoint("https://api2.dynect.net/REST/Zone/jclouds.org")
|
||||
.addHeader("API-Version", "3.3.7")
|
||||
.addHeader("Auth-Token", authToken)
|
||||
.payload(stringPayload("{\"rname\":\"jimmy@jclouds.org\",\"serial_style\":\"increment\",\"ttl\":3600}"))
|
||||
.build();
|
||||
|
||||
public void testGetWhenResponseError2401() {
|
||||
public void testCreateWhenResponseIs2xx() {
|
||||
DynECTApi success = requestsSendResponses(createSession, createSessionResponse, create, getResponse);
|
||||
assertEquals(success.getZoneApi().create(CreatePrimaryZone.builder()
|
||||
.fqdn("jclouds.org")
|
||||
.contact("jimmy@jclouds.org")
|
||||
.build()).toString(),
|
||||
new GetZoneResponseTest().expected().toString());
|
||||
}
|
||||
|
||||
public void testCreateWithContactWhenResponseIs2xx() {
|
||||
DynECTApi success = requestsSendResponses(createSession, createSessionResponse, create, getResponse);
|
||||
assertEquals(success.getZoneApi().createWithContact("jclouds.org", "jimmy@jclouds.org").toString(),
|
||||
new GetZoneResponseTest().expected().toString());
|
||||
}
|
||||
|
||||
public void testGetWhenResponseIs404() {
|
||||
DynECTApi fail = requestsSendResponses(createSession, createSessionResponse, get, notFound);
|
||||
assertNull(fail.getZoneApi().get("jclouds.org"));
|
||||
}
|
||||
|
@ -72,4 +96,67 @@ public class ZoneApiExpectTest extends BaseDynECTApiExpectTest {
|
|||
assertEquals(success.getZoneApi().list().toString(),
|
||||
new ListZonesResponseTest().expected().toString());
|
||||
}
|
||||
|
||||
HttpRequest delete = HttpRequest.builder().method("DELETE")
|
||||
.endpoint("https://api2.dynect.net/REST/Zone/jclouds.org")
|
||||
.addHeader("API-Version", "3.3.7")
|
||||
.addHeader(ACCEPT, APPLICATION_JSON)
|
||||
.addHeader("Auth-Token", authToken)
|
||||
.payload(emptyJsonPayload())
|
||||
.build();
|
||||
|
||||
HttpResponse deleteResponse = HttpResponse.builder().statusCode(200)
|
||||
.payload(payloadFromResourceWithContentType("/delete_zone.json", APPLICATION_JSON)).build();
|
||||
|
||||
public void testDeleteWhenResponseIs2xx() {
|
||||
DynECTApi success = requestsSendResponses(createSession, createSessionResponse, delete, deleteResponse);
|
||||
assertEquals(success.getZoneApi().delete("jclouds.org").toString(),
|
||||
new DeleteZoneResponseTest().expected().toString());
|
||||
}
|
||||
|
||||
public void testDeleteWhenResponseIs404() {
|
||||
DynECTApi fail = requestsSendResponses(createSession, createSessionResponse, delete, notFound);
|
||||
assertNull(fail.getZoneApi().delete("jclouds.org"));
|
||||
}
|
||||
|
||||
HttpRequest publish = HttpRequest.builder().method("PUT")
|
||||
.endpoint("https://api2.dynect.net/REST/Zone/jclouds.org")
|
||||
.addHeader("API-Version", "3.3.7")
|
||||
.addHeader("Auth-Token", authToken)
|
||||
.payload(stringPayload("{\"publish\":true}"))
|
||||
.build();
|
||||
|
||||
public void testPublishWhenResponseIs2xx() {
|
||||
DynECTApi success = requestsSendResponses(createSession, createSessionResponse, publish, getResponse);
|
||||
assertEquals(success.getZoneApi().publish("jclouds.org").toString(),
|
||||
new GetZoneResponseTest().expected().toString());
|
||||
}
|
||||
|
||||
HttpRequest freeze = HttpRequest.builder().method("PUT")
|
||||
.endpoint("https://api2.dynect.net/REST/Zone/jclouds.org")
|
||||
.addHeader("API-Version", "3.3.7")
|
||||
.addHeader(ACCEPT, APPLICATION_JSON)
|
||||
.addHeader("Auth-Token", authToken)
|
||||
.payload(stringPayload("{\"freeze\":true}"))
|
||||
.build();
|
||||
|
||||
public void testFreezeWhenResponseIs2xx() {
|
||||
DynECTApi success = requestsSendResponses(createSession, createSessionResponse, freeze, deleteResponse);
|
||||
assertEquals(success.getZoneApi().freeze("jclouds.org").toString(),
|
||||
new DeleteZoneResponseTest().expected().toString());
|
||||
}
|
||||
|
||||
HttpRequest thaw = HttpRequest.builder().method("PUT")
|
||||
.endpoint("https://api2.dynect.net/REST/Zone/jclouds.org")
|
||||
.addHeader("API-Version", "3.3.7")
|
||||
.addHeader(ACCEPT, APPLICATION_JSON)
|
||||
.addHeader("Auth-Token", authToken)
|
||||
.payload(stringPayload("{\"thaw\":true}"))
|
||||
.build();
|
||||
|
||||
public void testThawWhenResponseIs2xx() {
|
||||
DynECTApi success = requestsSendResponses(createSession, createSessionResponse, thaw, deleteResponse);
|
||||
assertEquals(success.getZoneApi().thaw("jclouds.org").toString(),
|
||||
new DeleteZoneResponseTest().expected().toString());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,10 +20,15 @@ package org.jclouds.dynect.v3.features;
|
|||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static java.util.logging.Logger.getAnonymousLogger;
|
||||
import static org.testng.Assert.assertEquals;
|
||||
import static org.testng.Assert.assertNull;
|
||||
|
||||
import org.jclouds.JcloudsVersion;
|
||||
import org.jclouds.dynect.v3.domain.Job;
|
||||
import org.jclouds.dynect.v3.domain.Job.Status;
|
||||
import org.jclouds.dynect.v3.domain.Zone;
|
||||
import org.jclouds.dynect.v3.internal.BaseDynECTApiLiveTest;
|
||||
import org.testng.annotations.AfterClass;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
@ -35,7 +40,7 @@ import com.google.common.collect.ImmutableList;
|
|||
public class ZoneApiLiveTest extends BaseDynECTApiLiveTest {
|
||||
|
||||
private void checkZone(Zone zone) {
|
||||
checkNotNull(zone.getName(), "Name cannot be null for a Zone: %s", zone);
|
||||
checkNotNull(zone.getFQDN(), "FQDN cannot be null for a Zone: %s", zone);
|
||||
checkNotNull(zone.getSerial(), "Serial cannot be null for a Zone: %s", zone);
|
||||
}
|
||||
|
||||
|
@ -44,19 +49,74 @@ public class ZoneApiLiveTest extends BaseDynECTApiLiveTest {
|
|||
ImmutableList<String> zones = api().list().toList();
|
||||
getAnonymousLogger().info("zones: " + zones.size());
|
||||
|
||||
for (String zoneName : zones) {
|
||||
Zone zone = api().get(zoneName);
|
||||
checkNotNull(zone, "zone was null for Zone: %s", zoneName);
|
||||
for (String fqdn : zones) {
|
||||
Zone zone = api().get(fqdn);
|
||||
checkNotNull(zone, "zone was null for Zone: %s", fqdn);
|
||||
checkZone(zone);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetZoneWhenNotFound() {
|
||||
assertNull(api().get("AAAAAAAAAAAAAAAA"));
|
||||
assertNull(api().get("AAAAAAAAAAAAAAAA.foo.com"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteZoneWhenNotFound() {
|
||||
assertNull(api().delete("AAAAAAAAAAAAAAAA.foo.com"));
|
||||
}
|
||||
|
||||
String fqdn = System.getProperty("user.name").replace('.', '-') + ".zone.dynecttest.jclouds.org";
|
||||
String contact = JcloudsVersion.get() + "@jclouds.org";
|
||||
|
||||
@Test
|
||||
public void testCreateZone() {
|
||||
Zone zone = api().createWithContact(fqdn, contact);
|
||||
checkNotNull(zone, "unable to create zone %s", fqdn);
|
||||
getAnonymousLogger().info("created zone: " + zone);
|
||||
checkZone(zone);
|
||||
}
|
||||
|
||||
@Test(dependsOnMethods = "testCreateZone")
|
||||
public void testPublishZone() {
|
||||
Zone zone = api().publish(fqdn);
|
||||
checkNotNull(zone, "unable to publish zone %s", fqdn);
|
||||
getAnonymousLogger().info("published zone: " + zone);
|
||||
checkZone(zone);
|
||||
}
|
||||
|
||||
@Test(dependsOnMethods = "testPublishZone")
|
||||
public void testFreezeZone() {
|
||||
Job job = api().freeze(fqdn);
|
||||
assertEquals(job.getStatus(), Status.SUCCESS);
|
||||
assertEquals(context.getApi().getJob(job.getId()), job);
|
||||
// TODO: determine how to prove it is frozen
|
||||
}
|
||||
|
||||
@Test(dependsOnMethods = "testFreezeZone")
|
||||
public void testThawZone() {
|
||||
Job job = api().thaw(fqdn);
|
||||
assertEquals(job.getStatus(), Status.SUCCESS);
|
||||
assertEquals(context.getApi().getJob(job.getId()), job);
|
||||
// TODO: determine how to prove it is thawed
|
||||
}
|
||||
|
||||
@Test(dependsOnMethods = "testThawZone")
|
||||
public void testDeleteZone() {
|
||||
Job job = api().delete(fqdn);
|
||||
assertEquals(job.getStatus(), Status.SUCCESS);
|
||||
assertEquals(context.getApi().getJob(job.getId()), job);
|
||||
assertNull(api().get(fqdn), "job " + job + " didn't delete zone" + fqdn);
|
||||
}
|
||||
|
||||
protected ZoneApi api() {
|
||||
return context.getApi().getZoneApi();
|
||||
}
|
||||
|
||||
@Override
|
||||
@AfterClass(groups = "live")
|
||||
protected void tearDownContext() {
|
||||
api().delete(fqdn);
|
||||
super.tearDownContext();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,70 @@
|
|||
/**
|
||||
* 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.dynect.v3.handlers;
|
||||
|
||||
import static com.google.common.net.HttpHeaders.ACCEPT;
|
||||
import static com.google.common.net.HttpHeaders.LOCATION;
|
||||
import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
|
||||
|
||||
import org.jclouds.dynect.v3.DynECTApi;
|
||||
import org.jclouds.dynect.v3.internal.BaseDynECTApiExpectTest;
|
||||
import org.jclouds.http.HttpRequest;
|
||||
import org.jclouds.http.HttpResponse;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Test(groups = "unit", testName = "GetJobRedirectionRetryHandlerExpectTest")
|
||||
public class GetJobRedirectionRetryHandlerExpectTest extends BaseDynECTApiExpectTest {
|
||||
|
||||
public void testRedirectOnJobLocationSwitchesToGETAndNoPayload() {
|
||||
|
||||
HttpRequest thaw = HttpRequest.builder().method("PUT")
|
||||
.endpoint("https://api2.dynect.net/REST/Zone/jclouds.org")
|
||||
.addHeader("API-Version", "3.3.7")
|
||||
.addHeader(ACCEPT, APPLICATION_JSON)
|
||||
.addHeader("Auth-Token", authToken)
|
||||
.payload(stringPayload("{\"thaw\":true}"))
|
||||
.build();
|
||||
|
||||
HttpResponse redirectResponse = HttpResponse.builder()
|
||||
.statusCode(317)
|
||||
.addHeader(LOCATION, "https://api2.dynect.net/REST/Job/1234")
|
||||
.build();
|
||||
|
||||
HttpRequest job = HttpRequest.builder().method("GET")
|
||||
.endpoint("https://api2.dynect.net/REST/Job/1234")
|
||||
.addHeader("API-Version", "3.3.7")
|
||||
.addHeader(ACCEPT, APPLICATION_JSON)
|
||||
.addHeader("Auth-Token", authToken)
|
||||
.payload(emptyJsonPayload())
|
||||
.build();
|
||||
|
||||
HttpResponse success = HttpResponse.builder().statusCode(200)
|
||||
.payload(payloadFromResourceWithContentType("/delete_zone.json", APPLICATION_JSON)).build();
|
||||
|
||||
DynECTApi apiThatRedirects = requestsSendResponses(createSession, createSessionResponse, thaw, redirectResponse,
|
||||
job, success);
|
||||
|
||||
apiThatRedirects.getZoneApi().thaw("jclouds.org");
|
||||
|
||||
}
|
||||
}
|
|
@ -44,6 +44,12 @@ public class BaseDynECTExpectTest<T> extends BaseRestApiExpectTest<T> {
|
|||
return p;
|
||||
}
|
||||
|
||||
public static Payload stringPayload(String json) {
|
||||
Payload p = Payloads.newPayload(json);
|
||||
p.getContentMetadata().setContentType(APPLICATION_JSON);
|
||||
return p;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected HttpRequestComparisonType compareHttpRequestAsType(HttpRequest input) {
|
||||
return HttpRequestComparisonType.JSON;
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
/**
|
||||
* 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.dynect.v3.parse;
|
||||
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
|
||||
import org.jclouds.dynect.v3.domain.Job;
|
||||
import org.jclouds.dynect.v3.internal.BaseDynECTParseTest;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
/**
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Test(groups = "unit")
|
||||
public class DeleteZoneResponseTest extends BaseDynECTParseTest<Job> {
|
||||
|
||||
@Override
|
||||
public String resource() {
|
||||
return "/delete_zone.json";
|
||||
}
|
||||
|
||||
@Override
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
public Job expected() {
|
||||
return Job.success(262989027l);
|
||||
}
|
||||
}
|
|
@ -44,6 +44,6 @@ public class GetZoneResponseTest extends BaseDynECTParseTest<Zone> {
|
|||
@SelectJson("data")
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
public Zone expected() {
|
||||
return Zone.builder().type(PRIMARY).serialStyle(INCREMENT).serial(5).name("jclouds.org").build();
|
||||
return Zone.builder().type(PRIMARY).serialStyle(INCREMENT).serial(5).fqdn("jclouds.org").build();
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
{"status": "success", "data": {}, "job_id": 262989027, "msgs": [{"INFO": "remove: Zone removed", "SOURCE": "BLL", "ERR_CD": null, "LVL": "INFO"}]}
|
Loading…
Reference in New Issue