Add an InternetGatewayApi to AWSEC2Api.

This is a follow-up to https://github.com/jclouds/jclouds/pull/1091
and particularly the comment at
https://github.com/jclouds/jclouds/pull/1091#issuecomment-299202429:

I have been trying this out and I think we will need to extend it for
practical purposes; if you want to create a VPC and subnet and then
deploy a machine on to it, you also need to jump through a few other
hoops apart from creating the subnet:

 - modify the subnet attributes to permit auto-assign public
   IP ("ModifySubnetAttribute")
 - create an Internet Gateway on the VPC ("CreateInternetGateway")
 - get and then modify the routing table of the subnet to add a public
   (0.0.0.0/0) route through the newly added gateway ("CreateRoute" and
   friends)

There are three AWS APIs needed for the above, an `InternetGatewayApi`,
a `RouteTableApi` and a method in the subnet API, I guess, for modifying
attributes on subnets. This PR contains the `InternetGatewayApi`.
This commit is contained in:
Geoff Macartney 2017-05-04 17:34:37 +01:00 committed by Ignasi Barrera
parent 89ae3b4fa6
commit cff2f87e11
20 changed files with 1243 additions and 0 deletions

View File

@ -21,6 +21,7 @@ import org.jclouds.aws.ec2.features.AWSInstanceApi;
import org.jclouds.aws.ec2.features.AWSKeyPairApi;
import org.jclouds.aws.ec2.features.AWSSecurityGroupApi;
import org.jclouds.aws.ec2.features.AWSSubnetApi;
import org.jclouds.aws.ec2.features.InternetGatewayApi;
import org.jclouds.aws.ec2.features.MonitoringApi;
import org.jclouds.aws.ec2.features.PlacementGroupApi;
import org.jclouds.aws.ec2.features.SpotInstanceApi;
@ -132,4 +133,19 @@ public interface AWSEC2Api extends EC2Api {
@Delegate
Optional<? extends AWSSubnetApi> getAWSSubnetApiForRegion(
@EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region);
/**
* Provides synchronous access to InternetGateway services.
*/
@Delegate
Optional<? extends InternetGatewayApi> getInternetGatewayApi();
/**
* Provides synchronous access to InternetGateway services in a given region.
*/
@Delegate
Optional<? extends InternetGatewayApi> getInternetGatewayApiForRegion(
@EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region
);
}

View File

@ -0,0 +1,32 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF 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.aws.ec2.binders;
import org.jclouds.aws.util.AWSUtils;
import org.jclouds.http.HttpRequest;
import org.jclouds.rest.Binder;
/**
* Binds the String [] to form parameters named with InternetGatewayId.index
*/
public class BindInternetGatewayIdsToIndexedFormParams implements Binder {
@Override
public <R extends HttpRequest> R bindToRequest(R request, Object input) {
return AWSUtils.indexStringArrayToFormValuesWithPrefix(request, "InternetGatewayId", input);
}
}

View File

@ -0,0 +1,83 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF 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.aws.ec2.domain;
import java.util.List;
import java.util.Map;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.json.SerializedNames;
import com.google.auto.value.AutoValue;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
/**
* Amazon EC2 Internet Gateway.
*
* @see <a href="http://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_InternetGateway.html" >doc</a>
*/
@AutoValue
public abstract class InternetGateway {
@Nullable
public abstract String id();
@Nullable
public abstract List<InternetGatewayAttachment> attachmentSet();
@Nullable
public abstract Map<String, String> tags();
@SerializedNames({"internetGatewayId", "attachmentSet", "tagSet"})
public static InternetGateway create(String id, List<InternetGatewayAttachment> attachmentSet,
Map<String, String> tags) {
return builder()
.id(id)
.attachmentSet(attachmentSet)
.tags(tags)
.build();
}
InternetGateway() {}
public static Builder builder() {
return new AutoValue_InternetGateway.Builder();
}
@AutoValue.Builder
public abstract static class Builder {
public abstract Builder id(String id);
public abstract Builder attachmentSet(List<InternetGatewayAttachment> attachmentSet);
public abstract Builder tags(Map<String, String> tags);
@Nullable abstract List<InternetGatewayAttachment> attachmentSet();
@Nullable abstract Map<String, String> tags();
abstract InternetGateway autoBuild();
public InternetGateway build() {
tags(tags() != null ? ImmutableMap.copyOf(tags()) : ImmutableMap.<String, String>of());
attachmentSet(attachmentSet() != null
? ImmutableList.copyOf(attachmentSet()) : ImmutableList.<InternetGatewayAttachment>of());
return autoBuild();
}
}
}

View File

@ -0,0 +1,75 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF 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.aws.ec2.domain;
import org.jclouds.javax.annotation.Nullable;
import com.google.auto.value.AutoValue;
/**
* Amazon EC2 Internet Gateway attachment to VPC.
*
* @see <a href="http://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_InternetGatewayAttachment.html" >doc</a>
*/
@AutoValue
public abstract class InternetGatewayAttachment {
public enum State {
UNRECOGNIZED,
ATTACHING,
ATTACHED,
AVAILABLE,
DETATCHING,
DETATCHED;
public String value() {
return name().toLowerCase();
}
public static State fromValue(String v) {
try {
return valueOf(v.toUpperCase());
} catch (IllegalArgumentException e) {
return UNRECOGNIZED;
}
}
}
@Nullable
public abstract State state();
@Nullable
public abstract String vpcId();
InternetGatewayAttachment() {}
public static Builder builder() {
return new AutoValue_InternetGatewayAttachment.Builder();
}
@AutoValue.Builder
public abstract static class Builder {
public abstract Builder state(State state);
public abstract Builder vpcId(String vpcId);
public abstract InternetGatewayAttachment build();
}
}

View File

@ -0,0 +1,205 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF 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.aws.ec2.features;
import static org.jclouds.aws.reference.FormParameters.ACTION;
import javax.inject.Named;
import javax.ws.rs.FormParam;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import org.jclouds.Fallbacks.EmptyFluentIterableOnNotFoundOr404;
import org.jclouds.Fallbacks.FalseOnNotFoundOr404;
import org.jclouds.aws.ec2.binders.BindInternetGatewayIdsToIndexedFormParams;
import org.jclouds.aws.ec2.domain.InternetGateway;
import org.jclouds.aws.ec2.options.InternetGatewayOptions;
import org.jclouds.aws.ec2.xml.DescribeInternetGatewaysResponseHandler;
import org.jclouds.aws.ec2.xml.InternetGatewayHandler;
import org.jclouds.aws.ec2.xml.ReturnValueHandler;
import org.jclouds.aws.filters.FormSigner;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.location.functions.RegionToEndpointOrProviderIfNull;
import org.jclouds.rest.annotations.BinderParam;
import org.jclouds.rest.annotations.EndpointParam;
import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.FormParams;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.VirtualHost;
import org.jclouds.rest.annotations.XMLResponseParser;
import com.google.common.collect.FluentIterable;
/**
* Provides access to InternetGateway Services.
*
* @see <a href="http://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_InternetGateway.html">InternetGateway docs</a>
* <p/>
*/
@RequestFilters(FormSigner.class)
@VirtualHost
@Path("/")
public interface InternetGatewayApi {
/**
* Detaches an {@link InternetGateway} from a {@link org.jclouds.aws.ec2.domain.VPC}
*
* @param region Region where the VPC exists
* @param internetGatewayId ID of the gateway to detach
* @param vpcId The ID of the VPC
*/
@Named("DetachInternetGateway")
@POST
@FormParams(keys = ACTION, values = "DetachInternetGateway")
@XMLResponseParser(ReturnValueHandler.class)
@Fallback(FalseOnNotFoundOr404.class)
Boolean detachInternetGateway(
@EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
@FormParam("InternetGatewayId") String internetGatewayId,
@FormParam("VpcId") String vpcId);
/**
* Detaches an {@link InternetGateway} from a {@link org.jclouds.aws.ec2.domain.VPC}, supplying options.
*
* @param region Region where the VPC exists
* @param internetGatewayId ID of the gateway to detach
* @param vpcId The ID of the VPC
* @param options Options for the request
*/
@Named("DetachInternetGateway")
@POST
@FormParams(keys = ACTION, values = "DetachInternetGateway")
@XMLResponseParser(ReturnValueHandler.class)
@Fallback(FalseOnNotFoundOr404.class)
Boolean detachInternetGateway(
@EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
@FormParam("InternetGatewayId") String internetGatewayId,
@FormParam("VpcId") String vpcId,
InternetGatewayOptions options);
/**
* Attaches an {@link InternetGateway} to a {@link org.jclouds.aws.ec2.domain.VPC}
*
* @param region Region where the VPC exists
* @param internetGatewayId ID of the gateway to attach
* @param vpcId The ID of the VPC
*/
@Named("AttachInternetGateway")
@POST
@FormParams(keys = ACTION, values = "AttachInternetGateway")
@XMLResponseParser(ReturnValueHandler.class)
@Fallback(FalseOnNotFoundOr404.class)
Boolean attachInternetGateway(
@EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
@FormParam("InternetGatewayId") String internetGatewayId,
@FormParam("VpcId") String vpcId);
/**
* Attaches an {@link InternetGateway} to a {@link org.jclouds.aws.ec2.domain.VPC}, supplying options.
*
* @param region Region where the VPC exists
* @param internetGatewayId ID of the gateway to attach
* @param vpcId The ID of the VPC
* @param options Options for the request
*/
@Named("AttachInternetGateway")
@POST
@FormParams(keys = ACTION, values = "AttachInternetGateway")
@XMLResponseParser(ReturnValueHandler.class)
@Fallback(FalseOnNotFoundOr404.class)
Boolean attachInternetGateway(
@EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
@FormParam("InternetGatewayId") String internetGatewayId,
@FormParam("VpcId") String vpcId,
InternetGatewayOptions options);
/**
* Creates an {@link InternetGateway}
*
* @param region The region to create the gateway in.
*/
@Named("CreateInternetGateway")
@POST
@FormParams(keys = ACTION, values = "CreateInternetGateway")
@XMLResponseParser(InternetGatewayHandler.class)
InternetGateway createInternetGateway(
@EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region);
/**
* Creates an {@link InternetGateway}, supplying options.
*
* @param region The region to create the gateway in
* @param options Options for the request
*/
@Named("CreateInternetGateway")
@POST
@FormParams(keys = ACTION, values = "CreateInternetGateway")
@XMLResponseParser(InternetGatewayHandler.class)
InternetGateway createInternetGateway(
@EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
InternetGatewayOptions options);
/**
* Deletes an {@code InternetGateway}.
*
* @param region gateways are tied to the Region where its files are located within Amazon S3.
* @param internetGatewayId The gateway ID.
*/
@Named("DeleteInternetGateway")
@POST
@FormParams(keys = ACTION, values = "DeleteInternetGateway")
@XMLResponseParser(ReturnValueHandler.class)
@Fallback(FalseOnNotFoundOr404.class)
boolean deleteInternetGateway(
@EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
@FormParam("InternetGatewayId") String internetGatewayId);
/**
* Deletes an {@code InternetGateway}, supplying options.
*
* @param region gateways are tied to the Region where its files are located within Amazon S3.
* @param internetGatewayId The gateway ID.
* @param options Options for the request
*/
@Named("DeleteInternetGateway")
@POST
@FormParams(keys = ACTION, values = "DeleteInternetGateway")
@XMLResponseParser(ReturnValueHandler.class)
@Fallback(FalseOnNotFoundOr404.class)
boolean deleteInternetGateway(
@EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
@FormParam("InternetGatewayId") String internetGatewayId,
InternetGatewayOptions options);
/**
* Describes {@link InternetGateway}s.
*
* @return InternetGateways or empty if there are none.
*
* @param region The region to search for gateways.
* @param internetGatewayIds Optional list of known gateway ids to restrict the search
*/
@Named("DescribeInternetGateways")
@POST
@FormParams(keys = ACTION, values = "DescribeInternetGateways")
@XMLResponseParser(DescribeInternetGatewaysResponseHandler.class)
@Fallback(EmptyFluentIterableOnNotFoundOr404.class)
FluentIterable<InternetGateway> describeInternetGatewaysInRegion(
@EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
@BinderParam(BindInternetGatewayIdsToIndexedFormParams.class) String... internetGatewayIds);
}

View File

@ -0,0 +1,64 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF 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.aws.ec2.options;
import org.jclouds.ec2.options.internal.BaseEC2RequestOptions;
/**
* Contains options supported in the Form API for the InternetGateway operations. <h2>
* Usage</h2> The recommended way to instantiate such an object is to statically import
* InternetGatewayOptions.Builder.* and invoke a static creation method followed by an instance mutator
* (if needed):
* <p/>
* <code>
* import static org.jclouds.ec2.options.InternetGatewayOptions.Builder.*
* <p/>
* EC2Api connection = // get connection
* Future<Set<ImageMetadata>> images =
* connection.getInternetGatewayApi().get().createInternetGateway(region, dryRun());
* <code>
*
* @see <a
* href="http://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_CreateInternetGateway.html"
* />
*/
public class InternetGatewayOptions extends BaseEC2RequestOptions {
public static final InternetGatewayOptions NONE = new InternetGatewayOptions();
/**
* Checks whether you have the required permissions for the action, without actually making the request, and provides an error response.
*/
public InternetGatewayOptions dryRun() {
formParameters.put("DryRun", "true");
return this;
}
public boolean isDryRun() {
return getFirstFormOrNull("DryRun") != null;
}
public static class Builder {
/**
* @see InternetGatewayOptions#dryRun()
*/
public static InternetGatewayOptions dryRun() {
InternetGatewayOptions options = new InternetGatewayOptions();
return options.dryRun();
}
}
}

View File

@ -0,0 +1,84 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF 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.aws.ec2.xml;
import static org.jclouds.util.SaxUtils.equalsOrSuffix;
import org.jclouds.aws.ec2.domain.InternetGateway;
import org.jclouds.http.functions.ParseSax;
import org.xml.sax.Attributes;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSet.Builder;
import com.google.inject.Inject;
/**
* @see <a href="http://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeVpcs.html">xml</a>
*/
public class DescribeInternetGatewaysResponseHandler extends
ParseSax.HandlerForGeneratedRequestWithResult<FluentIterable<InternetGateway>> {
private final InternetGatewayHandler gatewayHandler;
private boolean inAttachmentSet;
private boolean inTagSet;
private Builder<InternetGateway> gateways = ImmutableSet.builder();
@Inject
DescribeInternetGatewaysResponseHandler(InternetGatewayHandler gatewayHandler) {
this.gatewayHandler = gatewayHandler;
}
@Override
public FluentIterable<InternetGateway> getResult() {
try {
return FluentIterable.from(gateways.build());
} finally {
gateways = ImmutableSet.builder();
}
}
@Override
public void startElement(String url, String name, String qName, Attributes attributes) {
if (equalsOrSuffix(qName, "attachmentSet")) {
inAttachmentSet = true;
} else if (equalsOrSuffix(qName, "tagSet")) {
inTagSet = true;
}
gatewayHandler.startElement(url, name, qName, attributes);
}
@Override
public void endElement(String uri, String name, String qName) {
if (equalsOrSuffix(qName, "attachmentSet")) {
inAttachmentSet = false;
gatewayHandler.endElement(uri, name, qName);
} else if (equalsOrSuffix(qName, "tagSet")) {
inTagSet = false;
gatewayHandler.endElement(uri, name, qName);
} else if (equalsOrSuffix(qName, "item") && !inTagSet && !inAttachmentSet) {
gateways.add(gatewayHandler.getResult());
} else {
gatewayHandler.endElement(uri, name, qName);
}
}
@Override
public void characters(char[] ch, int start, int length) {
gatewayHandler.characters(ch, start, length);
}
}

View File

@ -0,0 +1,70 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF 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.aws.ec2.xml;
import java.util.List;
import org.jclouds.aws.ec2.domain.InternetGatewayAttachment;
import org.jclouds.http.functions.ParseSax;
import org.xml.sax.Attributes;
import com.google.common.collect.Lists;
public class InternetGatewayAttachmentSetHandler extends ParseSax.HandlerWithResult<List<InternetGatewayAttachment>> {
private StringBuilder currentText = new StringBuilder();
private List<InternetGatewayAttachment> result = Lists.newArrayList();
private InternetGatewayAttachment.Builder itemBuilder;
@Override
public void startElement(String uri, String name, String qName, Attributes attrs) {
currentText.setLength(0);
if (qName.equalsIgnoreCase("item")) {
itemBuilder = InternetGatewayAttachment.builder();
}
}
@Override
public void endElement(String uri, String name, String qName) {
if (itemBuilder == null) {
return;
}
if (qName.equalsIgnoreCase("item")) {
result.add(itemBuilder.build());
itemBuilder = null;
} else if (qName.equalsIgnoreCase("vpcId")) {
itemBuilder.vpcId(currentText.toString());
} else if (qName.equalsIgnoreCase("state")) {
itemBuilder.state(InternetGatewayAttachment.State.valueOf(currentText.toString().toUpperCase()));
}
}
@Override
public List<InternetGatewayAttachment> getResult() {
try {
return result;
} finally {
result = Lists.newArrayList();
}
}
@Override
public void characters(char[] ch, int start, int length) {
currentText.append(ch, start, length);
}
}

View File

@ -0,0 +1,100 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF 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.aws.ec2.xml;
import static org.jclouds.util.SaxUtils.currentOrNull;
import static org.jclouds.util.SaxUtils.equalsOrSuffix;
import javax.inject.Inject;
import org.jclouds.aws.ec2.domain.InternetGateway;
import org.jclouds.ec2.xml.TagSetHandler;
import org.jclouds.http.functions.ParseSax;
import org.xml.sax.Attributes;
/**
* @see <a href="http://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_InternetGateway.html">InternetGateway docs</a>
*/
public class InternetGatewayHandler extends ParseSax.HandlerForGeneratedRequestWithResult<InternetGateway> {
private StringBuilder currentText = new StringBuilder();
private InternetGateway.Builder builder = InternetGateway.builder();
private final TagSetHandler tagSetHandler;
private final InternetGatewayAttachmentSetHandler attachmentSetHandler;
private boolean inTagSet;
private boolean inAttachmentSet;
@Inject
InternetGatewayHandler(TagSetHandler tagSetHandler, InternetGatewayAttachmentSetHandler attachmentHandler) {
this.tagSetHandler = tagSetHandler;
this.attachmentSetHandler = attachmentHandler;
}
@Override
public InternetGateway getResult() {
try {
return builder.build();
} finally {
builder = InternetGateway.builder();
}
}
@Override
public void startElement(String uri, String name, String qName, Attributes attrs) {
currentText.setLength(0);
if (equalsOrSuffix(qName, "tagSet")) {
inTagSet = true;
}
if (equalsOrSuffix(qName, "attachmentSet")) {
inAttachmentSet = true;
}
if (inTagSet) {
tagSetHandler.startElement(uri, name, qName, attrs);
} else if (inAttachmentSet) {
attachmentSetHandler.startElement(uri, name, qName, attrs);
}
}
@Override
public void endElement(String uri, String name, String qName) {
if (equalsOrSuffix(qName, "tagSet")) {
inTagSet = false;
builder.tags(tagSetHandler.getResult());
} else if (equalsOrSuffix(qName, "attachmentSet")) {
inAttachmentSet = false;
builder.attachmentSet(attachmentSetHandler.getResult());
} else if (inTagSet) {
tagSetHandler.endElement(uri, name, qName);
} else if (inAttachmentSet) {
attachmentSetHandler.endElement(uri, name, qName);
} else if (equalsOrSuffix(qName, "internetGatewayId")) {
builder.id(currentOrNull(currentText));
}
currentText.setLength(0);
}
@Override
public void characters(char[] ch, int start, int length) {
if (inTagSet) {
tagSetHandler.characters(ch, start, length);
} else if (inAttachmentSet) {
attachmentSetHandler.characters(ch, start, length);
} else {
currentText.append(ch, start, length);
}
}
}

View File

@ -0,0 +1,162 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF 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.aws.ec2.features;
import static java.util.logging.Logger.getAnonymousLogger;
import static org.jclouds.aws.ec2.options.InternetGatewayOptions.Builder.dryRun;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertNotEquals;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertTrue;
import java.util.List;
import java.util.Random;
import org.jclouds.apis.BaseApiLiveTest;
import org.jclouds.aws.AWSResponseException;
import org.jclouds.aws.ec2.AWSEC2Api;
import org.jclouds.aws.ec2.domain.InternetGateway;
import org.jclouds.aws.ec2.domain.InternetGatewayAttachment;
import org.jclouds.aws.ec2.domain.VPC;
import org.jclouds.aws.ec2.options.CreateVpcOptions;
import org.jclouds.aws.ec2.options.InternetGatewayOptions;
import org.jclouds.ec2.features.TagApi;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
/**
* Tests behavior of {@link InternetGatewayApi}
*/
@Test(groups = "live")
public class InternetGatewayApiLiveTest extends BaseApiLiveTest<AWSEC2Api> {
private static final String TEST_REGION = "eu-west-1";
public InternetGatewayApiLiveTest() {
provider = "aws-ec2";
}
private InternetGatewayApi gwClient;
private TagApi tagger;
private VPCApi vpcClient;
private VPC vpc;
private InternetGateway gateway;
private String simpleName = InternetGatewayApiLiveTest.class.getSimpleName() + new Random().nextInt(10000);
@BeforeClass(groups = {"integration", "live"})
public void setupContext() {
gwClient = api.getInternetGatewayApiForRegion(TEST_REGION).get();
vpcClient = api.getVPCApi().get();
tagger = api.getTagApiForRegion(TEST_REGION).get();
}
@Test
public void testCreate() {
gateway = gwClient.createInternetGateway(TEST_REGION, InternetGatewayOptions.NONE);
assertNotNull(gateway, "Gateway was not successfully created");
assertEquals(gateway.tags().size(), 0, "Freshly created gateway has tags");
assertEquals(gateway.attachmentSet().size(), 0, "Freshly created gateway is attached");
tagger.applyToResources(ImmutableMap.of("Name", simpleName), ImmutableList.of(gateway.id()));
getAnonymousLogger().info("Created gateway " + simpleName + " with id " + gateway.id());
}
@Test(dependsOnMethods = "testCreate")
public void testAttach() {
vpc = vpcClient.createVpc(TEST_REGION, "10.20.30.0/24", CreateVpcOptions.NONE);
assertNotNull(vpc, "Failed to create VPC to test attachments");
tagger.applyToResources(ImmutableMap.of("Name", simpleName), ImmutableList.of(vpc.id()));
final Boolean attached = gwClient.attachInternetGateway(TEST_REGION, gateway.id(), vpc.id());
assertTrue(attached, "Gateway " + gateway.id() + " failed to attach to VPC " + vpc.id());
}
@Test(dependsOnMethods = "testAttach")
public void testGetAndVerifyAttach() {
getAnonymousLogger().info("Testing retrieval of gateway " + simpleName);
FluentIterable<InternetGateway> gateways = gwClient.describeInternetGatewaysInRegion(TEST_REGION, gateway.id());
final ImmutableList<InternetGateway> internetGateways = gateways.toList();
getAnonymousLogger().info("Gateway count " + internetGateways.size());
assertTrue(internetGateways.size() == 1, "Failed to retrieve list with expected gateway " + gateway.id());
final InternetGateway gw = internetGateways.get(0);
getAnonymousLogger().info("Found gateway " + gw.id() + " with " + gw.tags().size() + " tags");
assertEquals(gw.tags().get("Name"), simpleName);
final List<InternetGatewayAttachment> attachments = gw.attachmentSet();
assertEquals(attachments.size(), 1, "Gateway " + gateway.id() + " has no attachments, should have " + vpc.id());
final String attached = attachments.get(0).vpcId();
assertEquals(attached, vpc.id(), "Gateway " + gateway.id() + " attached to " + attached + " not " + vpc.id());
}
@Test(dependsOnMethods = "testGetAndVerifyAttach")
public void testDetach() {
final Boolean detached = gwClient.detachInternetGateway(TEST_REGION, gateway.id(), vpc.id());
assertTrue(detached, "Gateway " + gateway.id() + " was not detached from VPC " + vpc.id());
}
@Test(dependsOnMethods = "testDetach")
public void testListAndVerifyResultsOfDetach() {
FluentIterable<InternetGateway> gateways = gwClient.describeInternetGatewaysInRegion(TEST_REGION);
final ImmutableList<InternetGateway> asList = gateways.toList();
assertFalse(asList.isEmpty());
boolean found = false;
for (InternetGateway gw : asList) {
if (gw.id().equals(gateway.id())) {
found = true;
assertEquals(gw.attachmentSet().size(), 0, "Gateway " + gw.id() + " is attached to " + gw.attachmentSet());
}
}
assertTrue(found, "Could not find gateway " + gateway.id() + " in result of list");
}
@Test(dependsOnMethods = "testListAndVerifyResultsOfDetach", alwaysRun = true)
public void testDelete() {
if (gateway != null) {
assertTrue(gwClient.deleteInternetGateway(TEST_REGION, gateway.id()));
}
if (vpc != null) {
assertTrue(vpcClient.deleteVpc(TEST_REGION, vpc.id()));
}
}
@Test
public void testWithOptions() {
FluentIterable<InternetGateway> before = gwClient.describeInternetGatewaysInRegion(TEST_REGION);
try {
gwClient.createInternetGateway(TEST_REGION, dryRun());
} catch (AWSResponseException e) {
assertEquals(e.getError().getCode(), "DryRunOperation", "Expected DryRunOperation but got " + e.getError());
}
FluentIterable<InternetGateway> after = gwClient.describeInternetGatewaysInRegion(TEST_REGION);
assertNotEquals(before, after, "Dry run 'CreateInternetGateway' operation modified live account");
}
}

View File

@ -0,0 +1,211 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF 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.aws.ec2.features;
import static org.jclouds.aws.ec2.options.InternetGatewayOptions.Builder.dryRun;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertTrue;
import java.util.List;
import org.jclouds.aws.AWSResponseException;
import org.jclouds.aws.ec2.domain.InternetGateway;
import org.jclouds.aws.ec2.domain.InternetGatewayAttachment;
import org.jclouds.aws.ec2.internal.BaseAWSEC2ApiMockTest;
import org.jclouds.aws.ec2.options.InternetGatewayOptions;
import org.testng.annotations.Test;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import com.squareup.okhttp.mockwebserver.MockResponse;
@Test(groups = "unit", testName = "InternetGatewayApiMockTest", singleThreaded = true)
public class InternetGatewayApiMockTest extends BaseAWSEC2ApiMockTest {
public void createInternetGateway() throws Exception {
enqueueRegions(DEFAULT_REGION);
enqueueXml(DEFAULT_REGION, "/create_internet_gateway.xml");
InternetGateway result = gatewayApi().createInternetGateway(DEFAULT_REGION, InternetGatewayOptions.NONE);
assertNotNull(result, "Failed to create InternetGateway object");
assertEquals(result.id(), "igw-fada7c9c", "Gateway id does not match mock data: " + result.id());
assertPosted(DEFAULT_REGION, "Action=DescribeRegions");
assertPosted(DEFAULT_REGION, "Action=CreateInternetGateway");
}
public void attachInternetGateway() throws Exception {
enqueueRegions(DEFAULT_REGION);
enqueueXml(DEFAULT_REGION, "/attach_internet_gateway.xml");
final Boolean attached = gatewayApi().attachInternetGateway(DEFAULT_REGION, "igw-fada7c9c", "vpc-6250b91b");
assertTrue(attached, "Failed to attach InternetGateway");
assertPosted(DEFAULT_REGION, "Action=DescribeRegions");
assertPosted(DEFAULT_REGION, "Action=AttachInternetGateway&InternetGatewayId=igw-fada7c9c&VpcId=vpc-6250b91b");
}
public void attachInternetGatewayFail() throws Exception {
enqueueRegions(DEFAULT_REGION);
enqueueXml(DEFAULT_REGION, "/attach_internet_gateway_failed.xml");
final Boolean attached = gatewayApi().attachInternetGateway(DEFAULT_REGION, "igw-fada7c9c", "vpc-6250b91b");
assertFalse(attached, "Gateway reported as created despite failure response");
assertPosted(DEFAULT_REGION, "Action=DescribeRegions");
assertPosted(DEFAULT_REGION, "Action=AttachInternetGateway&InternetGatewayId=igw-fada7c9c&VpcId=vpc-6250b91b");
}
public void attachInternetGatewayNotFound() throws Exception {
enqueueRegions(DEFAULT_REGION);
enqueue(DEFAULT_REGION, new MockResponse().setResponseCode(404));
final Boolean attached = gatewayApi().attachInternetGateway(DEFAULT_REGION, "igw-fada7c9c", "vpc-6250b91b");
assertFalse(attached, "Somehow attached gateway despite NotFound response");
assertPosted(DEFAULT_REGION, "Action=DescribeRegions");
assertPosted(DEFAULT_REGION, "Action=AttachInternetGateway&InternetGatewayId=igw-fada7c9c&VpcId=vpc-6250b91b");
}
public void detachInternetGateway() throws Exception {
enqueueRegions(DEFAULT_REGION);
enqueueXml(DEFAULT_REGION, "/detach_internet_gateway.xml");
final Boolean detached = gatewayApi().detachInternetGateway(DEFAULT_REGION, "igw-fada7c9c", "vpc-6250b91b");
assertTrue(detached, "Gateway not successfully detached");
assertPosted(DEFAULT_REGION, "Action=DescribeRegions");
assertPosted(DEFAULT_REGION, "Action=DetachInternetGateway&InternetGatewayId=igw-fada7c9c&VpcId=vpc-6250b91b");
}
public void detachInternetGatewayNotFound() throws Exception {
enqueueRegions(DEFAULT_REGION);
enqueue(DEFAULT_REGION, new MockResponse().setResponseCode(404));
final Boolean detached = gatewayApi().detachInternetGateway(DEFAULT_REGION, "igw-fada7c9c", "vpc-6250b91b");
assertFalse(detached, "Non-existent gateway somehow successfully detached");
assertPosted(DEFAULT_REGION, "Action=DescribeRegions");
assertPosted(DEFAULT_REGION, "Action=DetachInternetGateway&InternetGatewayId=igw-fada7c9c&VpcId=vpc-6250b91b");
}
public void getInternetGateway() throws Exception {
enqueueRegions(DEFAULT_REGION);
enqueueXml(DEFAULT_REGION, "/get_internet_gateway.xml");
final String igwId = "igw-fada7c9c";
final FluentIterable<InternetGateway> internetGateways =
gatewayApi().describeInternetGatewaysInRegion(DEFAULT_REGION, igwId);
final ImmutableList<InternetGateway> gateways = internetGateways.toList();
assertEquals(gateways.size(), 1);
assertEquals(gateways.get(0).id(), igwId);
assertEquals(gateways.get(0).tags().get("Name"), "get_internet_gateway_test");
assertPosted(DEFAULT_REGION, "Action=DescribeRegions");
assertPosted(DEFAULT_REGION, "Action=DescribeInternetGateways&InternetGatewayId.1=igw-fada7c9c");
}
public void getInternetGatewayNotFound() throws Exception {
enqueueRegions(DEFAULT_REGION);
enqueue(DEFAULT_REGION, new MockResponse().setResponseCode(404));
final String igwId = "igw-fada7c9c";
final FluentIterable<InternetGateway> internetGateways =
gatewayApi().describeInternetGatewaysInRegion(DEFAULT_REGION, igwId);
final ImmutableList<InternetGateway> gateways = internetGateways.toList();
assertEquals(gateways.size(), 0);
assertPosted(DEFAULT_REGION, "Action=DescribeRegions");
assertPosted(DEFAULT_REGION, "Action=DescribeInternetGateways&InternetGatewayId.1=igw-fada7c9c");
}
public void describeInternetGateways() throws Exception {
enqueueRegions(DEFAULT_REGION);
enqueueXml(DEFAULT_REGION, "/describe_internet_gateways.xml");
final FluentIterable<InternetGateway> internetGateways =
gatewayApi().describeInternetGatewaysInRegion(DEFAULT_REGION);
final List<InternetGateway> gateways = Lists.newArrayList(internetGateways.toList());
assertEquals(gateways.size(), 3);
final ImmutableMap<String, InternetGateway> asMap =
ImmutableMap.of(gateways.get(0).id(), gateways.get(0),
gateways.get(1).id(), gateways.get(1),
gateways.get(2).id(), gateways.get(2));
assertEquals(asMap.get("igw-fada7c9c").tags().get("Name"), "describe_internet_gateways_test");
final InternetGatewayAttachment gw6bca130c = asMap.get("igw-6bca130c").attachmentSet().iterator().next();
assertEquals(gw6bca130c.vpcId(), "vpc-a13d29c6");
assertEquals(gw6bca130c.state(), InternetGatewayAttachment.State.AVAILABLE);
assertPosted(DEFAULT_REGION, "Action=DescribeRegions");
assertPosted(DEFAULT_REGION, "Action=DescribeInternetGateways");
}
public void deleteInternetGateway() throws Exception {
enqueueRegions(DEFAULT_REGION);
enqueueXml(DEFAULT_REGION, "/delete_internet_gateway.xml");
final boolean deleted = gatewayApi().deleteInternetGateway(DEFAULT_REGION, "igw-fada7c9c");
assertTrue(deleted, "Failed to delete gateway");
assertPosted(DEFAULT_REGION, "Action=DescribeRegions");
assertPosted(DEFAULT_REGION, "Action=DeleteInternetGateway&InternetGatewayId=igw-fada7c9c");
}
public void deleteInternetGatewayNotFound() throws Exception {
enqueueRegions(DEFAULT_REGION);
enqueue(DEFAULT_REGION, new MockResponse().setResponseCode(404));
final boolean deleted = gatewayApi().deleteInternetGateway(DEFAULT_REGION, "igw-fada7c9c");
assertFalse(deleted, "Somehow deleted a gateway that does not exist");
assertPosted(DEFAULT_REGION, "Action=DescribeRegions");
assertPosted(DEFAULT_REGION, "Action=DeleteInternetGateway&InternetGatewayId=igw-fada7c9c");
}
@Test
public void testWithOptions() throws Exception {
enqueueRegions(DEFAULT_REGION);
enqueueXml(DEFAULT_REGION, "/create_internet_gateway_dry_run.xml");
try {
gatewayApi().createInternetGateway(DEFAULT_REGION, dryRun());
} catch (AWSResponseException e) {
assertEquals(e.getError().getCode(), "DryRunOperation", "Expected DryRunOperation but got " + e.getError());
}
assertPosted(DEFAULT_REGION, "Action=DescribeRegions");
assertPosted(DEFAULT_REGION, "Action=CreateInternetGateway&DryRun=true");
}
private InternetGatewayApi gatewayApi() {
return api().getInternetGatewayApi().get();
}
}

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<AttachInternetGatewayResponse xmlns="http://ec2.amazonaws.com/doc/2012-06-01/">
<requestId>87565c19-59bf-4f71-8f9a-9dcfec2b6640</requestId>
<return>true</return>
</AttachInternetGatewayResponse>

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<AttachInternetGatewayResponse xmlns="http://ec2.amazonaws.com/doc/2012-06-01/">
<requestId>87565c19-59bf-4f71-8f9a-9dcfec2b6640</requestId>
<return>false</return>
</AttachInternetGatewayResponse>

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<CreateInternetGatewayResponse xmlns="http://ec2.amazonaws.com/doc/2012-06-01/">
<requestId>85c22645-f966-4025-9cb3-64bb5c833a54</requestId>
<internetGateway>
<internetGatewayId>igw-fada7c9c</internetGatewayId>
<attachmentSet/>
<tagSet/>
</internetGateway>
</CreateInternetGatewayResponse>

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Errors>
<Error>
<Code>DryRunOperation</Code>
<Message>Request would have succeeded, but DryRun flag is set.</Message>
</Error>
</Errors>
<RequestID>344ef005-e34b-42fb-a334-1180fe317e7c</RequestID>
</Response>

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<DeleteInternetGatewayResponse xmlns="http://ec2.amazonaws.com/doc/2012-06-01/">
<requestId>de1da0ea-085f-4783-b270-af5338060497</requestId>
<return>true</return>
</DeleteInternetGatewayResponse>

View File

@ -0,0 +1,37 @@
<?xml version="1.0" encoding="UTF-8"?>
<DescribeInternetGatewaysResponse xmlns="http://ec2.amazonaws.com/doc/2012-06-01/">
<requestId>3ed08c74-7a82-48b1-96d6-58ec1a41e560</requestId>
<internetGatewaySet>
<item>
<internetGatewayId>igw-fada7c9c</internetGatewayId>
<attachmentSet/>
<tagSet>
<item>
<key>Name</key>
<value>describe_internet_gateways_test</value>
</item>
</tagSet>
</item>
<item>
<internetGatewayId>igw-6bca130c</internetGatewayId>
<attachmentSet>
<item>
<vpcId>vpc-a13d29c6</vpcId>
<state>available</state>
</item>
</attachmentSet>
<tagSet/>
</item>
<item>
<internetGatewayId>igw-d09a79b6</internetGatewayId>
<attachmentSet>
<item>
<vpcId>vpc-17587171</vpcId>
<state>available</state>
</item>
</attachmentSet>
<tagSet/>
</item>
</internetGatewaySet>
</DescribeInternetGatewaysResponse>

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<DetachInternetGatewayResponse xmlns="http://ec2.amazonaws.com/doc/2012-06-01/">
<requestId>3aa4e5fb-2395-4560-bd0d-d229bdc75391</requestId>
<return>true</return>
</DetachInternetGatewayResponse>

View File

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<DescribeInternetGatewaysResponse xmlns="http://ec2.amazonaws.com/doc/2012-06-01/">
<requestId>b4064e62-7923-4559-8b7c-d8e6b4174d48</requestId>
<internetGatewaySet>
<item>
<internetGatewayId>igw-fada7c9c</internetGatewayId>
<attachmentSet>
<item>
<vpcId>vpc-6250b91b</vpcId>
<state>available</state>
</item>
</attachmentSet>
<tagSet>
<item>
<key>Name</key>
<value>get_internet_gateway_test</value>
</item>
</tagSet>
</item>
</internetGatewaySet>
</DescribeInternetGatewaysResponse>

View File

@ -0,0 +1,42 @@
<?xml version="1.0"?>
<configuration scan="false">
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<file>target/test-data/jclouds.log</file>
<encoder>
<Pattern>%d %-5p [%c] [%thread] %m%n</Pattern>
</encoder>
</appender>
<appender name="WIREFILE" class="ch.qos.logback.core.FileAppender">
<file>target/test-data/jclouds-wire.log</file>
<encoder>
<Pattern>%d %-5p [%c] [%thread] %m%n</Pattern>
</encoder>
</appender>
<appender name="COMPUTEFILE" class="ch.qos.logback.core.FileAppender">
<file>target/test-data/jclouds-compute.log</file>
<encoder>
<Pattern>%d %-5p [%c] [%thread] %m%n</Pattern>
</encoder>
</appender>
<logger name="org.jclouds">
<level value="DEBUG" />
<appender-ref ref="FILE" />
</logger>
<logger name="jclouds.compute">
<level value="DEBUG" />
<appender-ref ref="COMPUTEFILE" />
</logger>
<logger name="jclouds.wire">
<level value="DEBUG" />
<appender-ref ref="WIREFILE" />
</logger>
<logger name="jclouds.headers">
<level value="DEBUG" />
<appender-ref ref="WIREFILE" />
</logger>
<root>
<level value="INFO" />
</root>
</configuration>