From 0477e1980cf535acd9176ea3e357902537c93e82 Mon Sep 17 00:00:00 2001 From: Jesse Duarte Date: Thu, 21 Aug 2014 15:18:59 -0700 Subject: [PATCH] Initial commit --- LICENSE.txt | 63 ++++ NOTICE.txt | 5 + README.md | 232 +++++++++++- integration-tests.xml | 39 ++ pom.xml | 117 ++++++ .../java/com/amazonaws/ant/AWSAntTask.java | 88 +++++ .../CreateBeanstalkApplicationTask.java | 83 +++++ .../CreateBeanstalkEnvironmentTask.java | 300 ++++++++++++++++ .../DeployAppToBeanstalkTask.java | 207 +++++++++++ .../TerminateBeanstalkEnvironmentTask.java | 65 ++++ .../amazonaws/ant/s3/CreateS3BucketTask.java | 71 ++++ .../ant/s3/DownloadFileFromS3Task.java | 179 ++++++++++ .../ant/s3/UploadFileSetToS3Task.java | 149 ++++++++ src/main/resources/taskdefs.xml | 15 + src/main/resources/test-taskdefs.xml | 13 + .../java/com/amazonaws/ant/AWSTestUtils.java | 114 ++++++ .../amazonaws/ant/AssertFileEqualsTask.java | 72 ++++ .../CleanUpBeanstalkTestsTask.java | 68 ++++ .../DeleteBeanstalkApplicationTask.java | 43 +++ .../DeployAppToBeanstalkTests.java | 334 ++++++++++++++++++ .../SetUpBeanstalkTestsTask.java | 49 +++ ...TestSuccessfulBeanstalkDeploymentTask.java | 60 ++++ .../amazonaws/ant/s3/CleanUpS3TestsTask.java | 70 ++++ .../ant/s3/DownloadFromS3TaskTests.java | 113 ++++++ .../amazonaws/ant/s3/SetUpS3TestsTask.java | 47 +++ .../ant/s3/UploadFileSetToS3TaskTests.java | 129 +++++++ test.war | Bin 0 -> 4606 bytes 27 files changed, 2723 insertions(+), 2 deletions(-) create mode 100644 LICENSE.txt create mode 100644 NOTICE.txt create mode 100644 integration-tests.xml create mode 100644 pom.xml create mode 100644 src/main/java/com/amazonaws/ant/AWSAntTask.java create mode 100644 src/main/java/com/amazonaws/ant/elasticbeanstalk/CreateBeanstalkApplicationTask.java create mode 100644 src/main/java/com/amazonaws/ant/elasticbeanstalk/CreateBeanstalkEnvironmentTask.java create mode 100644 src/main/java/com/amazonaws/ant/elasticbeanstalk/DeployAppToBeanstalkTask.java create mode 100644 src/main/java/com/amazonaws/ant/elasticbeanstalk/TerminateBeanstalkEnvironmentTask.java create mode 100644 src/main/java/com/amazonaws/ant/s3/CreateS3BucketTask.java create mode 100644 src/main/java/com/amazonaws/ant/s3/DownloadFileFromS3Task.java create mode 100644 src/main/java/com/amazonaws/ant/s3/UploadFileSetToS3Task.java create mode 100644 src/main/resources/taskdefs.xml create mode 100644 src/main/resources/test-taskdefs.xml create mode 100644 src/test/java/com/amazonaws/ant/AWSTestUtils.java create mode 100644 src/test/java/com/amazonaws/ant/AssertFileEqualsTask.java create mode 100644 src/test/java/com/amazonaws/ant/elasticbeanstalk/CleanUpBeanstalkTestsTask.java create mode 100644 src/test/java/com/amazonaws/ant/elasticbeanstalk/DeleteBeanstalkApplicationTask.java create mode 100644 src/test/java/com/amazonaws/ant/elasticbeanstalk/DeployAppToBeanstalkTests.java create mode 100644 src/test/java/com/amazonaws/ant/elasticbeanstalk/SetUpBeanstalkTestsTask.java create mode 100644 src/test/java/com/amazonaws/ant/elasticbeanstalk/TestSuccessfulBeanstalkDeploymentTask.java create mode 100644 src/test/java/com/amazonaws/ant/s3/CleanUpS3TestsTask.java create mode 100644 src/test/java/com/amazonaws/ant/s3/DownloadFromS3TaskTests.java create mode 100644 src/test/java/com/amazonaws/ant/s3/SetUpS3TestsTask.java create mode 100644 src/test/java/com/amazonaws/ant/s3/UploadFileSetToS3TaskTests.java create mode 100644 test.war diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..a053504 --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,63 @@ +Apache License +Version 2.0, January 2004 + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + +"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + +"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + +"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + +"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + +"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + +"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + +"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + +"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + +"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + +"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + + 1. You must give any other recipients of the Work or Derivative Works a copy of this License; and + 2. You must cause any modified files to carry prominent notices stating that You changed the files; and + 3. You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and + 4. If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. + +You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +Note: Other license terms may apply to certain, identified software files contained within or distributed with the accompanying software if such terms are included in the directory containing the accompanying software. Such other license terms will then apply in lieu of the terms of the software license above. + +JSON processing code subject to the JSON License from JSON.org: + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +The Software shall be used for Good, not Evil. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/NOTICE.txt b/NOTICE.txt new file mode 100644 index 0000000..8a4d1af --- /dev/null +++ b/NOTICE.txt @@ -0,0 +1,5 @@ +AWS SDK for Java +Copyright 2010-2014 Amazon.com, Inc. or its affiliates. All Rights Reserved. + +This product includes software developed by +Amazon Technologies, Inc (http://www.amazon.com/). \ No newline at end of file diff --git a/README.md b/README.md index 8beb8ad..e0d6422 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,230 @@ -aws-ant-tasks -============= +AWS Java Ant Tasks +================== + +Usage Information +----------------- + +This project uses the AWS SDK for Java to create helpful Ant tasks for developers to incorporate into their builds. +You can use these tasks to make your build process simpler and to automate the process of deployment. +To use the tasks, all you need to do is call taskdef, targeting "taskdefs.xml" in the jar. +``` + +``` +The tasks will then be ready for you to call throughout the rest of the buildfile. For some usage examples, check out the integration-tests.xml. Read ahead for some more in-depth documentation. +Note that all tasks have two optional fields: `awsAccessKeyId` and `awsSecretKey`. You can use these to specify your AWS credentials, or you can leave them blank. If you leave them blank, the tasks will defer to the default credential chain, which looks for your credentials in the following places, in this order: + Environment Variables - AWS_ACCESS_KEY_ID and AWS_SECRET_KEY + Java System Properties - aws.accessKeyId and aws.secretKey + Credential profiles file at the default location (~/.aws/credentials) shared by all AWS SDKs and the AWS CLI + Instance profile credentials delivered through the Amazon EC2 metadata service +If no valid credentials are found after looking in all 5 places, the task will default to anonymous access, which is likely to lead to errors. + +S3 task usage guide +=================== + +Create bucket task +------------------ + +Defined in taskdefs.xml as `create-bucket` +The only required parameter here is the name of the bucket. Make sure it follows the rules of a bucket name and isn't taken, or an exception will be thrown. +``` + +``` + +Upload to bucket task +--------------------- +Defined in taskdefs.xml as `upload-to-s3` +Upload to bucket + +This uses Ant's fileset strategy. This makes it easy to specify either a single file or a fileset, which can use pattern sets. If you specify the keyPrefix parameter, then all files in the fileset will have that prefixed to their key in S3. Read up on Ant's filesets here. + +Available attributes: + +| Attribute | Description | Required? | +|----------------|------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| awsAccessKeyId | Your AWS Access Key credential | No. If not specified, the task will defer to the default credential chain. | +| awsSecretKey | Your AWS Secret Key credential | No. If not specified, the task will defer to the default | +| bucketName | The name of your bucket in S3 | Yes. | +| keyPrefix | A prefix to append to the beginning of all keys. | No. If specified, the keys of the files you upload will be of the format: keyPrefix+fileName | +| continueOnFail | Whether to continue uploading files if one file in the fileset fails to upload. Defaults to "false". | No. Defaults to "false". If set to "true", the task will continue to upload the rest of the files in the set, even if one fails to upload. If left "false", an exception will be thrown if one file fails to upload. | + +Nested elements: + +Nested [filesets](https://ant.apache.org/manual/Types/fileset.html). At least one is required. Every file included in the fileset will be uploaded to S3. + +Some examples: + +Uploading one file: +``` + + + +``` + +Uploading a set of files: +``` + + + +``` + +Uploading a set of files, continuing if one happens to fail: +``` + + + +``` + +Download from bucket task +------------------------- + +Two major options for use here: To download a single file, specify a key, and if you want, a target file. If the target file is specified, the object from S3 will be downloaded to that file. If not specified, the name of the file will be equal to the key. + +To download multiple files, specify a prefix and a target directory. All files that begin with the prefix will download to the target directory. Their names will be equal to their key names. + +Available attributes: + +| Attribute | Description | Required? | +|----------------|-----------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------| +| awsAccessKeyId | Your AWS Access Key credential | No. If not specified, the task will defer to the default credential chain. | +| awsSecretKey | Your AWS Secret Key credential | No. If not specified, the task will defer to the default credential chain. | +| bucketName | The name of your bucket in S3 | Yes. | +| key | If downloading one single S3 object, the key of the S3 Object you want to download. | If you want to download single file. Otherwise, it cannot be set. | +| file | If downloading one single S3 object, the absolute path of the file where the object will be downloaded to. | No. Can only be set if you are downloading a single file (i.e. if key is specified).| +| keyPrefix | If downloading multiple S3 objects, this specifies the prefix the keys of the objects you're downloading should have. | If you want to download mutliple files. Otherwise, it cannot be set. | +| dir | If downloading multiple S3 objects, the target directory to download them to. | Yes, if you are downloading multiple files (i.e. if "keyPrefix" is specified). | + + +Some examples: + + +Downloading one file to a target file: +``` + +``` + +Result: Downloads object with key "mykey.txt" in bucket "mybucketname" to "targetfile.txt". +(Note that in Ant, any relative paths resolve based on the project's basedir) + +Downloading one file without a target file: +``` + +``` +Result: Downloads object with key "mykey.txt" in bucket "mybucketname" to "mykey.txt" + +Downloading several files: +``` + +``` +Result: Downloads all objects whose keys begin with "myprefix/" to "~/targetdir/", with file names equal to their keys. + + AWS Elastic Beanstalk Task usage guide +====================================== + +Create Application task +----------------------- + +Sets up an application in AWS Elastic Beanstalk. Two attributes, both required: Application name and description. Parameters: + +| Attribute | Description | Required? | +|------------------------|----------------------------------------------------------|----------------------------------------------------------------------------| +| awsAccessKeyId | Your AWS Access Key credential | No. If not specified, the task will defer to the default credential chain. | +| awsSecretKey | Your AWS Secret Key credential | No. If not specified, the task will defer to the default credential chain. | +| applicationName | The name of your AWS Elastic Beanstalk Application | Yes | +| applicationDescription | A description for your AWS Elastic Beanstalk application | Yes | + +Nested elements: +None + +Example code: + +``` + +``` + + Create Environment task + ----------------------- + +Creates an environment for your Application to run in. This task just creates the sample environment--to run your own application you will have to update this environment with the Deploy task. +Parameters: + +| Attribute | Description | Required? | +|-----------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------| +| awsAccessKeyId | Your AWS Access Key credential | No. If not specified, the task will defer to the default credential chain. | +| awsSecretKey | Your AWS Secret Key credential | No. If not specified, the task will defer to the default credential chain. | +| applicationName | The name of the application to attach this environment to | Yes | +| environmentName | The name of this environment | Yes | +| environmentDescription| A description of this environment | Yes | +| solutionStackName | The solution stack of this environment. Must match one of the available solution stack names. | Yes | +| tierName | Name of this environment's tier. | Conditional: If one of tierName, tierType, tierVersion is set, then they must all be set | +| tierType | Type of this environment's tier | Conditional: If one of tierName, tierType, tierversion is set, then they must all be set | +| tierVersion | Version of this environment's tier | Conditional: If one of tierName, tierType, tierVersion is set, then they must all be set | +| cnamePrefix | CNAME prefix for this environment, will be prefixed to this environment's URL if specified. Must be between 4-23 characters, contain only letters, numbers, and hyphens, and not begin or end with a hyphen. | No | +| versionLabel | Version of the application | No | + +Nested elements: + +Nested Settings. A setting is a wrapper for an [Option Value](http://docs.aws.amazon.com/elasticbeanstalk/latest/dg/command-options.html), and similarly has three fields: namespace, optionName, and value + +Example code: Simple web service: + +``` + + + + + + + + + + + +``` + +Deploy Application task +----------------------- + +This task creates a new version of your application with an application file you've specified, then updates the environment to the new version. You can either specify an application file that you've already uploaded in S3, or you can upload a local application file to S3. + Parameters: + +| Attribute | Description | Required? | +|------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------| +| awsAccessKeyId | Your AWS Access Key credential | No. If not specified, the task will defer to the default credential chain. | +| awsSecretKey | Your AWS Secret Key credential | No. If not specified, the task will defer to the default credential chain. | +| bucketName | This is either: The name of the bucket you want to upload your application file to, or the bucket your application is already in. Either way , it must be a valid bucket that you have access to. | Yes. | +| versionLabel | New version label for the deployed application version | Yes. | +| versionDescription | Description of the new version of this application | Yes. | +| applicationName | The name of the application to attach the new version to. | Yes. | +| environmentName | The name of the environment to update | Yes. | +| key | The key of your application file in S3 | Conditional. Either this, or file must be set. | +| file | The local file to upload to S3 and set as your application file | Conditional. Either this, or key must be set. | + +Example code specifying a file you've already uploaded to S3: +``` + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..ef1ac57 --- /dev/null +++ b/pom.xml @@ -0,0 +1,117 @@ + + 4.0.0 + + com.amazonaws + aws-java-sdk-ant-tasks + 1.0.0-SNAPSHOT + jar + + aws-java-sdk-ant-tasks + http://aws.amazon.com/sdkforjava/ + + + UTF-8 + 1.6 + + + + + junit + junit + 4.8.1 + test + + + com.amazonaws + aws-java-sdk + 1.8.4 + + + org.apache.ant + ant + 1.9.4 + + + commons-io + commons-io + 2.4 + + + + + + maven-jar-plugin + 2.3.2 + + + default-jar + package + + jar + test-jar + + + + + ${jdk.level} + ${jdk.level} + + + + maven-compiler-plugin + 2.3.2 + + ${jdk.level} + ${jdk.level} + + + + org.apache.maven.plugins + maven-shade-plugin + 2.2 + + + package + + shade + + + false + + + com.amazonaws:aws-java-sdk + commons-io:* + commons-logging:* + commons-codec:commons-codec + com.fasterxml.jackson.core:* + org.apache.httpcomponents:* + joda-time:joda-time + + + + + + + + org.apache.maven.plugins + maven-antrun-plugin + 1.7 + + + integration-test + + + + + + + + run + + + + + + + diff --git a/src/main/java/com/amazonaws/ant/AWSAntTask.java b/src/main/java/com/amazonaws/ant/AWSAntTask.java new file mode 100644 index 0000000..a15f9c7 --- /dev/null +++ b/src/main/java/com/amazonaws/ant/AWSAntTask.java @@ -0,0 +1,88 @@ +/* + * Copyright 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file 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 com.amazonaws.ant; + +import java.lang.reflect.Constructor; + +import org.apache.tools.ant.Task; + +import com.amazonaws.AmazonWebServiceClient; +import com.amazonaws.auth.AWSCredentials; +import com.amazonaws.auth.BasicAWSCredentials; + +/** + * Base class for AWS-related Ant tasks. Handles all shared logic. + * + * @author jesduart + * + */ +public abstract class AWSAntTask extends Task { + + protected String awsAccessKeyId; + protected String awsSecretKey; + + /** + * Sets AWS Access Key. + * + * @param awsAccessKeyId + * The AWS Access key to set. Only use for testing or with public + * accounts, for a private account use a properties file or + * environment variable + */ + public void setAWSAccessKeyId(String awsAccessKeyId) { + this.awsAccessKeyId = awsAccessKeyId; + } + + /** + * Sets AWS Secret Key. + * + * @param awsSecretKey + * The AWS Secret key to set. Only use for testing or with public + * accounts, for a private account use a credentials file or + * environment variable + */ + public void setAWSSecretKey(String awsSecretKey) { + this.awsSecretKey = awsSecretKey; + } + + /** + * Returns a web service client of the specified class. Uses your + * credentials if they are specified, otherwise the credentials used will be + * according to the standard credential chain(Environment variables, Java + * System Properties, credential profiles file, instance profile + * credentials) + * + * @param clientClass + * The class of the web service client returned + * @return The web service client specified + */ + public T createClient( + Class clientClass) { + try { + if (awsSecretKey != null && awsAccessKeyId != null) { + Constructor constructor = clientClass + .getConstructor(AWSCredentials.class); + return constructor.newInstance(new BasicAWSCredentials( + awsAccessKeyId, awsSecretKey)); + } + Constructor constructor = clientClass.getConstructor(); + return constructor.newInstance(); + } catch (Exception e) { + throw new RuntimeException("Unable to create client: " + + e.getMessage(), e); + } + } + +} diff --git a/src/main/java/com/amazonaws/ant/elasticbeanstalk/CreateBeanstalkApplicationTask.java b/src/main/java/com/amazonaws/ant/elasticbeanstalk/CreateBeanstalkApplicationTask.java new file mode 100644 index 0000000..0281811 --- /dev/null +++ b/src/main/java/com/amazonaws/ant/elasticbeanstalk/CreateBeanstalkApplicationTask.java @@ -0,0 +1,83 @@ +/* + * Copyright 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file 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 com.amazonaws.ant.elasticbeanstalk; + +import org.apache.tools.ant.BuildException; + +import com.amazonaws.ant.AWSAntTask; +import com.amazonaws.services.elasticbeanstalk.AWSElasticBeanstalkClient; +import com.amazonaws.services.elasticbeanstalk.model.CreateApplicationRequest; + +/** + * Ant Task for creating an Elastic Beanstalk application. + * + * @author jesduart + */ +public class CreateBeanstalkApplicationTask extends AWSAntTask { + String applicationDescription; + String applicationName; + + /** + * Specify name of this application + * + * @param applicationName + * Name of this application + */ + public void setApplicationName(String applicationName) { + this.applicationName = applicationName; + } + + /** + * Specify the description of your beanstalk application + * + * @param applicationDescription + * Description of this application + */ + public void setApplicationDescription(String applicationDescription) { + this.applicationDescription = applicationDescription; + } + + public void checkParams() { + boolean areMissingParams = false; + StringBuilder errors = new StringBuilder(""); + if (applicationDescription == null) { + areMissingParams = true; + errors.append("Missing parameter: applicationDescription is required \n"); + } + if (applicationName == null) { + areMissingParams = true; + errors.append("Missing parameter: applicationName is required \n"); + } + if (areMissingParams) { + throw new BuildException(errors.toString()); + } + } + + public void execute() { + checkParams(); + AWSElasticBeanstalkClient client = createClient(AWSElasticBeanstalkClient.class); + CreateApplicationRequest request = new CreateApplicationRequest( + applicationName).withDescription(applicationDescription); + System.out.println("Creating application " + applicationName + "..."); + try { + client.createApplication(request); + } catch (Exception e) { + throw new BuildException( + "Exception while attempting to create application: " + + e.getMessage(), e); + } + System.out.println("Application created successfully"); + } +} diff --git a/src/main/java/com/amazonaws/ant/elasticbeanstalk/CreateBeanstalkEnvironmentTask.java b/src/main/java/com/amazonaws/ant/elasticbeanstalk/CreateBeanstalkEnvironmentTask.java new file mode 100644 index 0000000..2cdb978 --- /dev/null +++ b/src/main/java/com/amazonaws/ant/elasticbeanstalk/CreateBeanstalkEnvironmentTask.java @@ -0,0 +1,300 @@ +/* + * Copyright 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file 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 com.amazonaws.ant.elasticbeanstalk; + +import java.util.LinkedList; +import java.util.List; +import java.util.Vector; + +import org.apache.tools.ant.BuildException; + +import com.amazonaws.ant.AWSAntTask; +import com.amazonaws.services.elasticbeanstalk.AWSElasticBeanstalkClient; +import com.amazonaws.services.elasticbeanstalk.model.CheckDNSAvailabilityRequest; +import com.amazonaws.services.elasticbeanstalk.model.CheckDNSAvailabilityResult; +import com.amazonaws.services.elasticbeanstalk.model.ConfigurationOptionSetting; +import com.amazonaws.services.elasticbeanstalk.model.CreateEnvironmentRequest; +import com.amazonaws.services.elasticbeanstalk.model.CreateEnvironmentResult; +import com.amazonaws.services.elasticbeanstalk.model.EnvironmentTier; + +/** + * Task for creating an elastic beanstalk environment + * + * @author jesduart + * + */ +public class CreateBeanstalkEnvironmentTask extends AWSAntTask { + + private String applicationName; + private String versionLabel; + private String cnamePrefix; + private String environmentName; + private String environmentDescription; + private String solutionStackName; + private String tierName; + private String tierType; + private String tierVersion; + private Vector settings = new Vector(); + + /** + * Specify the application to associate with this environment. Required. + * + * @param applicationName + * The name of the application to associate with this environment + */ + public void setApplicationName(String applicationName) { + this.applicationName = applicationName; + } + + /** + * Specify the version to associate with this environment. Not required. + * + * @param versionLabel + * the label of the version to associate with this environment + */ + public void setVersionLabel(String versionLabel) { + this.versionLabel = versionLabel; + } + + /** + * Specify the CNAME prefix of this application. Must be between 4-23 + * characters, contain only letters, numbers, and hypens, and not begin or + * end with a hyphen. Not required. + * + * @param cnameprefix + * The CNAME of this application; will be used in the application + * URL + */ + public void setCnamePrefix(String cnamePrefix) { + this.cnamePrefix = cnamePrefix; + } + + /** + * Specify the name of this environment. Required. + * + * @param environmentName + * The name of this environment + */ + public void setEnvironmentName(String environmentName) { + this.environmentName = environmentName; + } + + /** + * Specify the description of this environment. Required + * + * @param environmentDescription + * The description of this environment + */ + public void setEnvironmentDescription(String environmentDescription) { + this.environmentDescription = environmentDescription; + } + + /** + * Specify the solution stack of this environment. Required. + * + * @param solutionStackName + * The solution stack name of this environment + */ + public void setSolutionStackName(String solutionStackName) { + this.solutionStackName = solutionStackName; + } + + /** + * The name of the tier of this environment. Conditionally required; if you + * are specifying a tier, then tierType, tierName, and tierVersion must all + * be set. + * + * @param tier + * The tier name of this environment + */ + public void setTierName(String tierName) { + this.tierName = tierName; + } + + /** + * The version of the tier of this environment.Conditionally required; if + * you are specifying a tier, then tierType, tierName, and tierVersion must + * all be set. + * + * @param tierVersion + * The tier version of this environment + */ + public void setTierVersion(String tierVersion) { + this.tierVersion = tierVersion; + } + + /** + * Specify the type of the tier. Conditionally required; if you are + * specifying a tier, then tierType, tierName, and tierVersion must all be + * set. + * + * @param tierType + * The type of the this environments tier + */ + public void setTierType(String tierType) { + this.tierType = tierType; + } + + /** + * Adds an option setting for this environment only after it has been + * configured within an Ant call + * + * @param setting + * The preconfigured option setting to add + */ + public void addConfiguredSetting(Setting setting) { + settings.add(setting); + } + + private void checkParams() { + StringBuilder errors = new StringBuilder(""); + boolean areMissingParams = false; + + if (environmentName == null) { + areMissingParams = true; + errors.append("Missing parameter: environmentName is required \n"); + } + if (environmentDescription == null) { + areMissingParams = true; + errors.append("Missing parameter: environmentDescription is required \n"); + } + if (solutionStackName == null) { + areMissingParams = true; + errors.append("Missing parameter: solutionStackName is required \n"); + } + if (applicationName == null) { + areMissingParams = true; + errors.append("Missing parameter: applicationName is required \n"); + } + if (!(tierName == null && tierType == null && tierVersion == null) + && (tierName == null || tierType == null || tierVersion == null)) { + areMissingParams = true; + errors.append("Invalid paramater configuration: If one of tierName, tierType, and tierVersion is set, then they must all be set. \n"); + } + if (areMissingParams) { + throw new BuildException(errors.toString()); + } + } + + public void execute() { + checkParams(); + AWSElasticBeanstalkClient client = createClient(AWSElasticBeanstalkClient.class); + CreateEnvironmentRequest eRequest = new CreateEnvironmentRequest( + applicationName, environmentName) + .withDescription(environmentDescription) + .withVersionLabel(versionLabel) + .withSolutionStackName(solutionStackName); + if (!(tierName == null || tierType == null || tierVersion == null)) { + eRequest.setTier(new EnvironmentTier().withName(tierName) + .withType(tierType).withVersion(tierVersion)); + } + + if (cnamePrefix != null) { + CheckDNSAvailabilityResult dnsResult = client + .checkDNSAvailability(new CheckDNSAvailabilityRequest( + cnamePrefix)); + if (!dnsResult.isAvailable()) { + throw new BuildException("The specified CNAME " + cnamePrefix + + " was not available"); + } + eRequest.setCNAMEPrefix(cnamePrefix); + } + List optionSettings = new LinkedList(); + for (Setting setting : settings) { + optionSettings.add(new ConfigurationOptionSetting(setting + .getNamespace(), setting.getOptionName(), setting + .getValue())); + } + if (optionSettings.size() > 0) { + eRequest.setOptionSettings(optionSettings); + } + System.out.println("Creating environment " + environmentName + "..."); + String cNAME = ""; + try { + CreateEnvironmentResult result = client.createEnvironment(eRequest); + if ((cNAME = result.getCNAME()) == null) { + System.out + .println("Create environment request submitted. The environment configuration does not support a CNAME."); + } else { + System.out + .println("Create environment request submitted. When the environment is finished launching, your deployment will be available at " + + cNAME); + } + } catch (Exception e) { + throw new BuildException( + "Exception while attempting to create environment: " + + e.getMessage(), e); + } + + } + + /** + * Wrapper for an environment option setting, to be used as a nested element + * + * @author jesduart + * + */ + public static class Setting { + private String namespace; + private String optionName; + private String value; + + public Setting() { + // required by Ant + } + + public String getNamespace() { + return namespace; + } + + /** + * specify namespace of this option setting. Required. + * + * @param namespace + * The namespace of this option setting + */ + public void setNamespace(String namespace) { + this.namespace = namespace; + } + + public String getOptionName() { + return optionName; + } + + /** + * Specify the option name of this option setting. Required. + * + * @param optionName + * The name of the option to set. + */ + public void setOptionName(String optionName) { + this.optionName = optionName; + } + + public String getValue() { + return value; + } + + /** + * Specify the value of this option setting. Required. + * + * @param value + * The value for this option setting + */ + public void setValue(String value) { + this.value = value; + } + } +} diff --git a/src/main/java/com/amazonaws/ant/elasticbeanstalk/DeployAppToBeanstalkTask.java b/src/main/java/com/amazonaws/ant/elasticbeanstalk/DeployAppToBeanstalkTask.java new file mode 100644 index 0000000..e498349 --- /dev/null +++ b/src/main/java/com/amazonaws/ant/elasticbeanstalk/DeployAppToBeanstalkTask.java @@ -0,0 +1,207 @@ +/* + * Copyright 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file 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 com.amazonaws.ant.elasticbeanstalk; + +import java.io.File; + +import org.apache.tools.ant.BuildException; + +import com.amazonaws.ant.AWSAntTask; +import com.amazonaws.auth.BasicAWSCredentials; +import com.amazonaws.services.elasticbeanstalk.AWSElasticBeanstalkClient; +import com.amazonaws.services.elasticbeanstalk.model.CreateApplicationVersionRequest; +import com.amazonaws.services.elasticbeanstalk.model.S3Location; +import com.amazonaws.services.elasticbeanstalk.model.UpdateEnvironmentRequest; +import com.amazonaws.services.s3.transfer.TransferManager; +import com.amazonaws.services.s3.transfer.Upload; + +/** + * A task for deploying an application to beanstalk. To use this app, you must + * have an existing application and environment in beanstalk. This task will + * create a new version of your application and update the environment. + * + * @author jesduart + * + */ +public class DeployAppToBeanstalkTask extends AWSAntTask { + + private String bucketName; + private String key; + private String versionLabel; + private String versionDescription; + private String applicationName; + private String environmentName; + private File file; + + /** + * Specify the name of the bucket in S3 to upload your application file to. + * Optional + * + * @param bucketName + * The name of the bucket in S3 to upload your application file + * to. Must be a valid bucket that you have access permission to. + */ + public void setBucketName(String bucketName) { + this.bucketName = bucketName; + } + + /** + * Specify the application file (WAR, ZIP, etc) to upload to S3. This will + * be the file attached to the new version of this application. Optional; if + * not specified you must specify a file in S3 to use. + * + * @param file + * The file containing your application + */ + public void setFile(File file) { + this.file = file; + } + + /** + * Specify the key of the application file in S3. Conditionally required. + * You can either upload a file to S3 to use as your application file, or + * you can specify a file already in S3. If you are uploading a file, this + * field is not required--if not set, the key will be the same as the file + * name. If you are specifying a file in S3, this field must be set, and + * must be a valid key in S3. + * + * @param key + */ + public void setKey(String key) { + this.key = key; + } + + /** + * Specify the label of the new version. Required. + * + * @param versionLabel + * What you want to name the new version of this application + */ + public void setVersionLabel(String versionLabel) { + this.versionLabel = versionLabel; + } + + /** + * The description of the new version of the application. Required + * + * @param versionDescription + * A description of the new application version + */ + public void setVersionDescription(String versionDescription) { + this.versionDescription = versionDescription; + } + + /** + * The name of the application you are updating. Must be an application in + * beanstalk that exists. Required. + * + * @param applicationName + * The name of the application in beanstalk that you want to + * update. + */ + public void setApplicationName(String applicationName) { + this.applicationName = applicationName; + } + + /** + * The nam eof the environment you are updating. Must be an environment in + * beanstalk that exists and is in the "Ready" state. Required. + * + * @param environmentName + */ + public void setEnvironmentName(String environmentName) { + this.environmentName = environmentName; + } + + private void checkParams() { + StringBuilder errors = new StringBuilder(""); + boolean areMissingParams = false; + if (bucketName == null) { + areMissingParams = true; + errors.append("Missing parameter: bucketName is required. \n"); + } + + if (key == null && file == null) { + areMissingParams = true; + errors.append("Error in parameter configuration: Either key or file must be set. You must specify an application in S3 or your own application to upload to S3."); + } + if (versionLabel == null) { + areMissingParams = true; + errors.append("Missing parameter: versionLabel is required \n"); + } + if (versionDescription == null) { + areMissingParams = true; + errors.append("Missing parameter: versionDescription is required \n"); + } + if (applicationName == null) { + areMissingParams = true; + errors.append("Missing parameter: applicationName is required \n"); + } + if (environmentName == null) { + areMissingParams = true; + errors.append("Missing parameter: environmentName is required \n"); + } + if (areMissingParams) { + throw new BuildException(errors.toString()); + } + } + + public void execute() { + checkParams(); + AWSElasticBeanstalkClient client = createClient(AWSElasticBeanstalkClient.class); + + CreateApplicationVersionRequest vRequest = new CreateApplicationVersionRequest( + applicationName, versionLabel); + vRequest.setDescription(versionDescription); + String s3key = key == null ? file.getName() : key; + if (file != null) { + TransferManager tm; + if (awsSecretKey != null && awsAccessKeyId != null) { + tm = new TransferManager(new BasicAWSCredentials( + awsAccessKeyId, awsSecretKey)); + } else { + tm = new TransferManager(); + } + System.out.println("Uploading file " + file.getName() + " to S3"); + try { + Upload u = tm.upload(bucketName, s3key, file); + u.waitForCompletion(); + } catch (Exception e) { + throw new BuildException("Error when trying to upload file: " + + e.getMessage(), e); + } + System.out.println("Upload successful"); + } + vRequest.setSourceBundle(new S3Location(bucketName, s3key)); + System.out.println("Creating application version " + versionLabel + + "..."); + try { + client.createApplicationVersion(vRequest); + } catch (Exception e) { + throw new BuildException( + "Exception while attempting to create application version: " + + e.getMessage(), e); + } + System.out.println("Application version successfully created"); + + System.out.println("Updating environment..."); + UpdateEnvironmentRequest updateRequest = new UpdateEnvironmentRequest() + .withEnvironmentName(environmentName).withVersionLabel( + versionLabel); + client.updateEnvironment(updateRequest); + System.out.println("Update environment request submitted"); + } + +} diff --git a/src/main/java/com/amazonaws/ant/elasticbeanstalk/TerminateBeanstalkEnvironmentTask.java b/src/main/java/com/amazonaws/ant/elasticbeanstalk/TerminateBeanstalkEnvironmentTask.java new file mode 100644 index 0000000..c4d9eae --- /dev/null +++ b/src/main/java/com/amazonaws/ant/elasticbeanstalk/TerminateBeanstalkEnvironmentTask.java @@ -0,0 +1,65 @@ +/* + * Copyright 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file 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 com.amazonaws.ant.elasticbeanstalk; + +import org.apache.tools.ant.BuildException; + +import com.amazonaws.ant.AWSAntTask; +import com.amazonaws.services.elasticbeanstalk.AWSElasticBeanstalkClient; +import com.amazonaws.services.elasticbeanstalk.model.TerminateEnvironmentRequest; + +/** + * This task will terminate a beanstalk environment + * + * @author jesduart + * + */ +public class TerminateBeanstalkEnvironmentTask extends AWSAntTask { + + private String environmentName; + + /** + * Set the name of the environment. Required + * + * @param environmentName + * The environment to terminate. + */ + public void setEnvironmentName(String environmentName) { + this.environmentName = environmentName; + } + + private void checkParams() { + if (environmentName == null) { + throw new BuildException( + "Missing parameter: environmentName is required"); + } + } + + public void execute() { + System.out + .println("Terminating environment " + environmentName + "..."); + checkParams(); + AWSElasticBeanstalkClient bcClient = createClient(AWSElasticBeanstalkClient.class); + try { + bcClient.terminateEnvironment(new TerminateEnvironmentRequest() + .withEnvironmentName(environmentName)); + } catch (Exception e) { + throw new BuildException("Could not terminate environment " + + e.getMessage(), e); + } + System.out + .println("The request to terminate the environment has been submitted."); + } +} diff --git a/src/main/java/com/amazonaws/ant/s3/CreateS3BucketTask.java b/src/main/java/com/amazonaws/ant/s3/CreateS3BucketTask.java new file mode 100644 index 0000000..98cb36b --- /dev/null +++ b/src/main/java/com/amazonaws/ant/s3/CreateS3BucketTask.java @@ -0,0 +1,71 @@ +/* + * Copyright 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file 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 com.amazonaws.ant.s3; + +import org.apache.tools.ant.BuildException; + +import com.amazonaws.AmazonClientException; +import com.amazonaws.AmazonServiceException; +import com.amazonaws.ant.AWSAntTask; +import com.amazonaws.services.s3.AmazonS3Client; + +/** + * ANT Task for creating a bucket in S3. Specify the name of your bucket, and it + * will be created. + */ +public class CreateS3BucketTask extends AWSAntTask { + + private String bucketName; + + /** + * Specify the name of the S3 bucket to create + * + * @param bucketName + * The desired named of the S3 bucket. Must be valid and not + * taken. + */ + public void setBucketName(String bucketName) { + this.bucketName = bucketName; + } + + public void checkParams() { + if (bucketName == null) { + throw new BuildException( + "Missing parameter: bucketName must be set."); + } + } + + public void execute() { + AmazonS3Client client = createClient(AmazonS3Client.class); + try { + System.out.println("Creating bucket with name " + bucketName + + "..."); + client.createBucket(bucketName); + System.out + .println("Bucket " + bucketName + " successfuly created."); + } catch (AmazonServiceException ase) { + throw new BuildException( + "AmazonServiceException: Errors in S3 while processing request." + + ase.getMessage()); + } catch (AmazonClientException ace) { + throw new BuildException( + "AmazonClientException: Errors encountered in the client while" + + " making the request or handling the response. " + + ace.getMessage()); + } catch (Exception e) { + throw new BuildException(e.getMessage()); + } + } +} diff --git a/src/main/java/com/amazonaws/ant/s3/DownloadFileFromS3Task.java b/src/main/java/com/amazonaws/ant/s3/DownloadFileFromS3Task.java new file mode 100644 index 0000000..a16afd8 --- /dev/null +++ b/src/main/java/com/amazonaws/ant/s3/DownloadFileFromS3Task.java @@ -0,0 +1,179 @@ +/* + * Copyright 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file 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 com.amazonaws.ant.s3; + +import java.io.File; +import java.io.IOException; +import java.util.Iterator; + +import org.apache.tools.ant.BuildException; + +import com.amazonaws.ant.AWSAntTask; +import com.amazonaws.services.s3.AmazonS3; +import com.amazonaws.services.s3.AmazonS3Client; +import com.amazonaws.services.s3.model.GetObjectRequest; +import com.amazonaws.services.s3.model.ObjectListing; +import com.amazonaws.services.s3.model.S3ObjectSummary; + +/** + * Ant task for Downloading a file from a specified bucket in S3. You have two + * main options for downloading. You may either specify a key and download the + * file in your bucket in S3 with that key (To a target file if you wish to + * specify it), or specify a prefix and download all files from your bucket in + * S3 with that prefix to a specified directory. + */ +public class DownloadFileFromS3Task extends AWSAntTask { + private String bucketName; + private String dir; + private String key; + private String keyPrefix; + private File file; + + /** + * Specify the name of your S3 bucket + * + * @param bucketName + * The name of the bucket in S3 to download the file from. An + * exception will be thrown if it doesn't exist. + */ + public void setBucketName(String bucketName) { + this.bucketName = bucketName; + } + + /** + * Specify the key to download + * + * @param key + * The key of the file you want to download + */ + public void setKey(String key) { + this.key = key; + } + + /** + * Specify your key prefix. If set, you must also specify a directory. + * + * @param keyPrefix + * All files in your bucket in S3 whose keys begin with these + * prefix will be downloaded to a specified directory + */ + public void setKeyPrefix(String keyPrefix) { + this.keyPrefix = keyPrefix; + } + + /** + * Set the name of the file to download to + * + * @param file + * Optional. If set, the data from S3 will be stored in a file + * with this name. Otherwise, the name of the file will be the + * same as the key. The file should not already exist. + */ + public void setFile(File file) { + this.file = file; + } + + /** + * If you download files based on a prefix, then you must specify a + * directory to download the files to. + * + * @param dir + * The directory to download your files to + */ + public void setDir(String dir) { + this.dir = dir; + } + + public void checkParams() { + boolean areMalformedParams = false; + StringBuilder errors = new StringBuilder(""); + if (bucketName == null) { + areMalformedParams = true; + errors.append("Missing parameter: bucketName is required. \n"); + } + if (key != null && keyPrefix != null) { + areMalformedParams = true; + errors.append("key and keyPrefix cannot both be set. You either want to download a single file, or all files with a certain prefix. \n"); + } + if (key == null && keyPrefix == null) { + areMalformedParams = true; + errors.append("Either key or keyPrefix must be set \n"); + } + if (keyPrefix != null && file != null) { + areMalformedParams = true; + errors.append("keyPrefix and fileName cannot both be set. If KeyPrefix is set, all files with your prefix will be downloaded as their keys. \n"); + } + if (keyPrefix != null && dir == null) { + areMalformedParams = true; + errors.append("If keyPrefix is set, then dir must be set to specify what directory to download the files to. \n"); + } + if (areMalformedParams) { + throw new BuildException(errors.toString()); + } + } + + private void downloadObjectToFile(AmazonS3 client, File file, String key) { + System.out.println("Downloading S3Object with key " + key + + " from bucket " + bucketName + " to file " + file + "..."); + try { + if (file.getParentFile() != null) { + file.getParentFile().mkdirs(); + } + file.createNewFile(); + } catch (IOException e) { + throw new BuildException( + "IOException while attempting to create new file: " + + e.getMessage()); + } + try { + client.getObject(new GetObjectRequest(bucketName, key), file); + } catch (Exception e) { + throw new BuildException( + "Exception while trying to download object: " + + e.getMessage(), e); + } + System.out.println("Download successful"); + } + + public void execute() { + AmazonS3Client client = createClient(AmazonS3Client.class); + if (key != null) { + File targetFile = file == null ? new File(key) : file; + downloadObjectToFile(client, targetFile, key); + } else { + ObjectListing objectListing = client.listObjects(bucketName); + + while (true) { + for (Iterator iterator = objectListing.getObjectSummaries() + .iterator(); iterator.hasNext();) { + S3ObjectSummary objectSummary = (S3ObjectSummary) iterator + .next(); + String key = objectSummary.getKey(); + if (key.startsWith(keyPrefix)) { + downloadObjectToFile(client, new File(dir + + File.pathSeparator + key), key); + } + } + + if (objectListing.isTruncated()) { + objectListing = client + .listNextBatchOfObjects(objectListing); + } else { + break; + } + } + } + } +} diff --git a/src/main/java/com/amazonaws/ant/s3/UploadFileSetToS3Task.java b/src/main/java/com/amazonaws/ant/s3/UploadFileSetToS3Task.java new file mode 100644 index 0000000..8fc3e94 --- /dev/null +++ b/src/main/java/com/amazonaws/ant/s3/UploadFileSetToS3Task.java @@ -0,0 +1,149 @@ +/* + * Copyright 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file 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 com.amazonaws.ant.s3; + +import java.io.File; +import java.util.Vector; + +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.DirectoryScanner; +import org.apache.tools.ant.types.FileSet; + +import com.amazonaws.ant.AWSAntTask; +import com.amazonaws.auth.BasicAWSCredentials; +import com.amazonaws.services.s3.transfer.TransferManager; +import com.amazonaws.services.s3.transfer.Upload; + +/** + * ANT Task for deploying a fileset or filesets to S3. + * + * @author jesduart + * + */ +public class UploadFileSetToS3Task extends AWSAntTask { + private Vector filesets = new Vector(); + private String bucketName; + private String keyPrefix; + private boolean continueOnFail = false; + + /** + * Specify a fileset to be deployed + * + * @param fileset + * A fileset, whose files will all be deployed to S3 + */ + public void addFileset(FileSet fileset) { + filesets.add(fileset); + } + + /** + * Specify the name of your S3 bucket + * + * @param bucketName + * The name of the bucket in S3 to store the files in. An + * exception will be thrown if it doesn't exist. + */ + public void setBucketName(String bucketName) { + this.bucketName = bucketName; + } + + /** + * Specify the prefix to your files in this upload. This is optional + * + * @param keyPrefix + * If specified, all of your files in the fileset will have this + * prefixed to their key. For example, you can name this + * "myfiles/", and if you upload myfile.txt, its key in S3 will + * be myfiles/myfile.txt. + */ + public void setKeyPrefix(String keyPrefix) { + this.keyPrefix = keyPrefix; + } + + /** + * Specify whether you want to continue uploading your fileset if the upload + * of one file fails. False by default. + * + * @param continueOnFail + * If true, the task will continue to upload files from the + * fileset if any single files fails to upload. Otherwise, one + * file + */ + public void setContinueOnFail(String continueOnFail) { + this.continueOnFail = new Boolean(continueOnFail); + } + + /** + * Verifies that all necessary parameters were set + */ + private void checkParameters() { + StringBuilder errors = new StringBuilder(""); + boolean areMalformedParams = false; + if (bucketName == null) { + areMalformedParams = true; + errors.append("Missing parameter: bucketname is required"); + } + if (filesets.size() < 1) { + areMalformedParams = true; + errors.append("Missing parameter: you must specify at least one fileset"); + } + if (areMalformedParams) { + throw new BuildException(errors.toString()); + } + } + + /** + * Uploads files to S3 + */ + public void execute() { + checkParameters(); + TransferManager tm; + if (awsSecretKey != null && awsAccessKeyId != null) { + tm = new TransferManager(new BasicAWSCredentials(awsAccessKeyId, + awsSecretKey)); + } else { + tm = new TransferManager(); + } + for (FileSet fs : filesets) { + DirectoryScanner ds = fs.getDirectoryScanner(getProject()); + String[] includedFiles = ds.getIncludedFiles(); + try { + for (String s : includedFiles) { + File base = ds.getBasedir(); + File file = new File(base, s); + String key = keyPrefix + file.getName(); + try { + System.out.println("Uploading file " + file.getName() + + "..."); + Upload u = tm.upload(bucketName, key, file); + u.waitForCompletion(); + System.out.println("Upload succesful"); + } catch (Exception e) { + if (!continueOnFail) { + throw new BuildException( + "Error. The file that failed to upload was: " + + file.getName(), e); + } else { + System.err.println("The file " + file.getName() + + " failed to upload. Continuing..."); + } + } + } + } finally { + tm.shutdownNow(); + } + } + } +} diff --git a/src/main/resources/taskdefs.xml b/src/main/resources/taskdefs.xml new file mode 100644 index 0000000..6b2f179 --- /dev/null +++ b/src/main/resources/taskdefs.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/test-taskdefs.xml b/src/main/resources/test-taskdefs.xml new file mode 100644 index 0000000..0c67998 --- /dev/null +++ b/src/main/resources/test-taskdefs.xml @@ -0,0 +1,13 @@ + + + + + + + + + \ No newline at end of file diff --git a/src/test/java/com/amazonaws/ant/AWSTestUtils.java b/src/test/java/com/amazonaws/ant/AWSTestUtils.java new file mode 100644 index 0000000..a719b33 --- /dev/null +++ b/src/test/java/com/amazonaws/ant/AWSTestUtils.java @@ -0,0 +1,114 @@ +/* + * Copyright 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file 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 com.amazonaws.ant; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.PrintWriter; +import java.util.Iterator; +import java.util.List; +import java.util.Random; + +import com.amazonaws.services.elasticbeanstalk.AWSElasticBeanstalkClient; +import com.amazonaws.services.elasticbeanstalk.model.DescribeEnvironmentsRequest; +import com.amazonaws.services.elasticbeanstalk.model.EnvironmentDescription; +import com.amazonaws.services.elasticbeanstalk.model.EnvironmentHealth; +import com.amazonaws.services.elasticbeanstalk.model.EnvironmentStatus; +import com.amazonaws.services.s3.AmazonS3Client; +import com.amazonaws.services.s3.model.ObjectListing; +import com.amazonaws.services.s3.model.S3ObjectSummary; + +public class AWSTestUtils { + + public static void emptyAndDeleteBucket(AmazonS3Client client, + String bucketName) { + ObjectListing objectListing = client.listObjects(bucketName); + + while (true) { + for (Iterator iterator = objectListing.getObjectSummaries() + .iterator(); iterator.hasNext();) { + S3ObjectSummary objectSummary = (S3ObjectSummary) iterator + .next(); + client.deleteObject(bucketName, objectSummary.getKey()); + } + + if (objectListing.isTruncated()) { + objectListing = client.listNextBatchOfObjects(objectListing); + } else { + break; + } + } + client.deleteBucket(bucketName); + } + + public static File createRandomFile(String prefix, String suffix) + throws IOException { + File file = File.createTempFile(prefix, suffix); + writeRandomLinesToFile(file); + return file; + } + + public static void writeRandomLinesToFile(File file) + throws FileNotFoundException { + PrintWriter writer = new PrintWriter(file); + Random random = new Random(); + int randInt = random.nextInt(100) + 1; + for (int i = 0; i <= randInt; i++) { + writer.println(random.nextInt(100) + 1); + } + writer.close(); + } + + public static void waitForEnvironmentToTransitionToStateAndHealth( + String environmentName, EnvironmentStatus state, + EnvironmentHealth health, AWSElasticBeanstalkClient bcClient) + throws InterruptedException { + System.out.println("Waiting for instance " + environmentName + + " to transition to " + state + "/" + health); + + int count = 0; + while (true) { + Thread.sleep(1000 * 30); + if (count++ > 100) { + throw new RuntimeException("Environment " + environmentName + + " never transitioned to " + state + "/" + health); + } + + List environments = bcClient + .describeEnvironments( + new DescribeEnvironmentsRequest() + .withEnvironmentNames(environmentName)) + .getEnvironments(); + + if (environments.size() == 0) { + System.out + .println("No environments with that name were found."); + return; + } + + EnvironmentDescription environment = environments.get(0); + System.out.println(" - " + environment.getStatus() + "/" + + environment.getHealth()); + if (environment.getStatus().equalsIgnoreCase(state.toString()) == false) + continue; + if (health != null + && environment.getHealth().equalsIgnoreCase( + health.toString()) == false) + continue; + return; + } + } +} diff --git a/src/test/java/com/amazonaws/ant/AssertFileEqualsTask.java b/src/test/java/com/amazonaws/ant/AssertFileEqualsTask.java new file mode 100644 index 0000000..a462a59 --- /dev/null +++ b/src/test/java/com/amazonaws/ant/AssertFileEqualsTask.java @@ -0,0 +1,72 @@ +/* + * Copyright 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file 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 com.amazonaws.ant; + +import java.io.File; +import java.io.IOException; + +import org.apache.commons.io.FileUtils; +import org.apache.tools.ant.BuildException; + +import com.amazonaws.ant.AWSAntTask; + +public class AssertFileEqualsTask extends AWSAntTask { + + private String firstFile; + + public void setFirstFile(String firstFile) { + this.firstFile = firstFile; + } + + private String secondFile; + + public void setSecondFile(String secondFile) { + this.secondFile = secondFile; + } + + private void checkParams() { + if (firstFile == null) { + throw new BuildException("First file must be specified"); + } + if (secondFile == null) { + throw new BuildException("Second file must be specified"); + } + + } + + public void execute() { + checkParams(); + File file1 = new File(firstFile); + if (!file1.exists()) { + throw new BuildException("The file " + firstFile + "does not exist"); + } + File file2 = new File(secondFile); + if (!file2.exists()) { + throw new BuildException("The file " + secondFile + + "does not exist"); + } + + try { + if (!FileUtils.contentEquals(file1, file2)) { + throw new BuildException( + "The two input files are not equal in content"); + } + } catch (IOException e) { + throw new BuildException( + "IOException while trying to compare content of files: " + + e.getMessage()); + } + } +} diff --git a/src/test/java/com/amazonaws/ant/elasticbeanstalk/CleanUpBeanstalkTestsTask.java b/src/test/java/com/amazonaws/ant/elasticbeanstalk/CleanUpBeanstalkTestsTask.java new file mode 100644 index 0000000..010ea33 --- /dev/null +++ b/src/test/java/com/amazonaws/ant/elasticbeanstalk/CleanUpBeanstalkTestsTask.java @@ -0,0 +1,68 @@ +/* + * Copyright 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file 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 com.amazonaws.ant.elasticbeanstalk; + +import org.apache.tools.ant.BuildException; + +import com.amazonaws.ant.AWSAntTask; +import com.amazonaws.ant.AWSTestUtils; +import com.amazonaws.services.identitymanagement.AmazonIdentityManagementClient; +import com.amazonaws.services.identitymanagement.model.DeleteInstanceProfileRequest; +import com.amazonaws.services.identitymanagement.model.RemoveRoleFromInstanceProfileRequest; +import com.amazonaws.services.s3.AmazonS3Client; + +public class CleanUpBeanstalkTestsTask extends AWSAntTask { + + private static final String INSTANCEPROFILE_ROLE = "aws-elasticbeanstalk-ec2-role"; + private String instanceProfile; + private String bucketName; + + public void setInstanceProfile(String instanceProfile) { + this.instanceProfile = instanceProfile; + } + + public void setBucketName(String bucketName) { + this.bucketName = bucketName; + } + + public void checkParams() { + boolean areMissingParams = false; + StringBuffer errors = new StringBuffer(""); + if (instanceProfile == null) { + areMissingParams = true; + errors.append("Missing parameter: instanceProfile must be set. \n"); + } + if (bucketName == null) { + areMissingParams = true; + errors.append("Missing parameter: bucketName must be set. \n"); + } + if (areMissingParams) { + throw new BuildException(errors.toString()); + } + } + + public void execute() { + AmazonIdentityManagementClient iamClient = createClient(AmazonIdentityManagementClient.class); + iamClient + .removeRoleFromInstanceProfile(new RemoveRoleFromInstanceProfileRequest() + .withRoleName(INSTANCEPROFILE_ROLE) + .withInstanceProfileName(instanceProfile)); + iamClient.deleteInstanceProfile(new DeleteInstanceProfileRequest() + .withInstanceProfileName(instanceProfile)); + AmazonS3Client client = createClient(AmazonS3Client.class); + + AWSTestUtils.emptyAndDeleteBucket(client, bucketName); + } +} diff --git a/src/test/java/com/amazonaws/ant/elasticbeanstalk/DeleteBeanstalkApplicationTask.java b/src/test/java/com/amazonaws/ant/elasticbeanstalk/DeleteBeanstalkApplicationTask.java new file mode 100644 index 0000000..0bab625 --- /dev/null +++ b/src/test/java/com/amazonaws/ant/elasticbeanstalk/DeleteBeanstalkApplicationTask.java @@ -0,0 +1,43 @@ +/* + * Copyright 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file 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 com.amazonaws.ant.elasticbeanstalk; + +import org.apache.tools.ant.BuildException; + +import com.amazonaws.ant.AWSAntTask; +import com.amazonaws.services.elasticbeanstalk.AWSElasticBeanstalkClient; +import com.amazonaws.services.elasticbeanstalk.model.DeleteApplicationRequest; + +public class DeleteBeanstalkApplicationTask extends AWSAntTask { + + private String applicationName; + + public void setApplicationName(String applicationName) { + this.applicationName = applicationName; + } + + private void checkParams() { + if (applicationName == null) { + throw new BuildException( + "Missing parameter: applicationName is required"); + } + } + + public void execute() { + checkParams(); + AWSElasticBeanstalkClient bcClient = createClient(AWSElasticBeanstalkClient.class); + bcClient.deleteApplication(new DeleteApplicationRequest(applicationName)); + } +} diff --git a/src/test/java/com/amazonaws/ant/elasticbeanstalk/DeployAppToBeanstalkTests.java b/src/test/java/com/amazonaws/ant/elasticbeanstalk/DeployAppToBeanstalkTests.java new file mode 100644 index 0000000..53416e8 --- /dev/null +++ b/src/test/java/com/amazonaws/ant/elasticbeanstalk/DeployAppToBeanstalkTests.java @@ -0,0 +1,334 @@ +/* + * Copyright 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file 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 com.amazonaws.ant.elasticbeanstalk; + +import static org.junit.Assert.*; + +import java.io.File; + +import org.junit.After; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +import com.amazonaws.ant.AWSTestUtils; +import com.amazonaws.ant.elasticbeanstalk.CreateBeanstalkApplicationTask; +import com.amazonaws.ant.elasticbeanstalk.CreateBeanstalkEnvironmentTask; +import com.amazonaws.ant.elasticbeanstalk.DeployAppToBeanstalkTask; +import com.amazonaws.ant.elasticbeanstalk.CreateBeanstalkEnvironmentTask.Setting; +import com.amazonaws.services.elasticbeanstalk.AWSElasticBeanstalkClient; +import com.amazonaws.services.elasticbeanstalk.model.EnvironmentHealth; +import com.amazonaws.services.elasticbeanstalk.model.EnvironmentStatus; +import com.amazonaws.services.elasticbeanstalk.model.ApplicationDescription; +import com.amazonaws.services.elasticbeanstalk.model.ApplicationVersionDescription; +import com.amazonaws.services.elasticbeanstalk.model.DeleteApplicationRequest; +import com.amazonaws.services.elasticbeanstalk.model.DescribeApplicationVersionsResult; +import com.amazonaws.services.elasticbeanstalk.model.DescribeApplicationsResult; +import com.amazonaws.services.elasticbeanstalk.model.DescribeEnvironmentsRequest; +import com.amazonaws.services.elasticbeanstalk.model.EnvironmentDescription; +import com.amazonaws.services.elasticbeanstalk.model.TerminateEnvironmentRequest; +import com.amazonaws.services.identitymanagement.AmazonIdentityManagementClient; +import com.amazonaws.services.identitymanagement.model.AddRoleToInstanceProfileRequest; +import com.amazonaws.services.identitymanagement.model.CreateInstanceProfileRequest; +import com.amazonaws.services.identitymanagement.model.DeleteInstanceProfileRequest; +import com.amazonaws.services.identitymanagement.model.RemoveRoleFromInstanceProfileRequest; +import com.amazonaws.services.s3.AmazonS3Client; + +public class DeployAppToBeanstalkTests { + + private static final String TEST_APPNAME = "AntTaskTestBeanstalkApplicationName"; + private static final String TEST_APPDESC = "AntTaskTestBeanstalkApplication Description"; + private static final String TEST_VERSIONLABEL = "Version1"; + private static final String TEST_VERSIONDESC = "Test description for Version 1"; + private static final String TEST_CNAMEPREFIX = "testdeployapptobeanstalk"; + private static final String TEST_ENVIRONMENTNAME = "tst" + + System.currentTimeMillis(); + private static final String TEST_ENVIRONMENTDESC = "Test description for environment"; + private static final String TEST_SOLUTIONSTACKNAME = "64bit Amazon Linux running Tomcat 6"; + private static final String BUCKET_NAME = "deployapptobeanstalktestbucket"; + private static final String KEY = "test/test.war"; + private static final String WAR_FILE = System.getProperty("user.dir") + + "/test.war"; + private static final String TEST_INSTANCEPROFILE_NAMESPACE = "aws:autoscaling:launchconfiguration"; + private static final String INSTANCEPROFILE_OPTIONNAME = "IamInstanceProfile"; + private static final String TEST_INSTANCEPROFILE_VALUE = "ElasticBeanstalkProfile"; + private static final String SQSD_NAMESPACE = "aws:elasticbeanstalk:sqsd"; + private static final String WORKERQUEUEURL_OPTIONNAME = "WorkerQueueURL"; + private static final String TEST_WORKERQUEUEURL_VALUE = "http://sqsd.elasticbeanstalk.us-east-1.amazon.com"; + private static final String HTTPPATH_OPTIONNAME = "HttpPath"; + private static final String TEST_HTTPPATH_VALUE = "/"; + private static final String MIMETYPE_OPTIONNAME = "MimeType"; + private static final String TEST_MIMETYPE_VALUE = "application/json"; + private static final String HTTPCONNECTIONS_OPTIONNAME = "HttpConnections"; + private static final String TEST_HTTPCONNECTIONS_VALUE = "75"; + private static final String CONNECTTIMEOUT_OPTIONNAME = "ConnectTimeout"; + private static final String TEST_CONNECTTIMEOUT_VALUE = "10"; + private static final String INACTIVITYTIMEOUT_OPTIONNAME = "InactivityTimeout"; + private static final String TEST_INACTIVITYTIMEOUT_VALUE = "10"; + private static final String VISIBILITYTIMEOUT_OPTIONNAME = "VisibilityTimeout"; + private static final String TEST_VISIBILITYTIMEOUT_VALUE = "60"; + private static final String RETENTIONPERIOD_OPTIONNAME = "RetentionPeriod"; + private static final String TEST_RETENTIONPERIOD_VALUE = "345600"; + private static final String WORKER_TIER = "Worker"; + private static final String TEST_TIERTYPE = "SQS/HTTP"; + private static final String TEST_WORKERVERSION = "1.0"; + + private static AmazonS3Client s3Client; + private static AWSElasticBeanstalkClient bcClient; + private static AmazonIdentityManagementClient iamClient; + + @BeforeClass + public static void setUp() throws InterruptedException { + bcClient = new AWSElasticBeanstalkClient(); + s3Client = new AmazonS3Client(); + s3Client.createBucket(BUCKET_NAME); + bcClient = new AWSElasticBeanstalkClient(); + iamClient = new AmazonIdentityManagementClient(); + iamClient.createInstanceProfile(new CreateInstanceProfileRequest() + .withInstanceProfileName(TEST_INSTANCEPROFILE_VALUE)); + iamClient + .addRoleToInstanceProfile(new AddRoleToInstanceProfileRequest() + .withRoleName("aws-elasticbeanstalk-ec2-role") + .withInstanceProfileName(TEST_INSTANCEPROFILE_VALUE)); + } + + @Test + public void testExecuteWebService() { + s3Client.putObject(BUCKET_NAME, KEY, new File(WAR_FILE)); + CreateBeanstalkApplicationTask createAppTask = new CreateBeanstalkApplicationTask(); + CreateBeanstalkEnvironmentTask createEnvTask = new CreateBeanstalkEnvironmentTask(); + DeployAppToBeanstalkTask deployTask = new DeployAppToBeanstalkTask(); + deployTask.setApplicationName(TEST_APPNAME); + createAppTask.setApplicationDescription(TEST_APPDESC); + deployTask.setVersionLabel(TEST_VERSIONLABEL); + deployTask.setVersionDescription(TEST_VERSIONDESC); + deployTask.setBucketName(BUCKET_NAME); + deployTask.setKey(KEY); + createEnvTask.setCnamePrefix(TEST_CNAMEPREFIX); + deployTask.setEnvironmentName(TEST_ENVIRONMENTNAME); + createEnvTask.setEnvironmentDescription(TEST_ENVIRONMENTDESC); + Setting setting = new Setting(); + setting.setNamespace(TEST_INSTANCEPROFILE_NAMESPACE); + setting.setOptionName(INSTANCEPROFILE_OPTIONNAME); + setting.setValue(TEST_INSTANCEPROFILE_VALUE); + createEnvTask.addConfiguredSetting(setting); + createEnvTask.setSolutionStackName(TEST_SOLUTIONSTACKNAME); + createAppTask.setApplicationName(TEST_APPNAME); + createEnvTask.setEnvironmentName(TEST_ENVIRONMENTNAME); + createEnvTask.setApplicationName(TEST_APPNAME); + createAppTask.execute(); + createEnvTask.execute(); + try { + AWSTestUtils.waitForEnvironmentToTransitionToStateAndHealth( + TEST_ENVIRONMENTNAME, EnvironmentStatus.Ready, null, + bcClient); + } catch (Exception e) { + System.out.println(e.getMessage()); + fail(); + } + deployTask.execute(); + DescribeApplicationsResult appResult = bcClient.describeApplications(); + boolean appNameFound = false; + for (ApplicationDescription appdesc : appResult.getApplications()) { + if (appdesc.getApplicationName().equals(TEST_APPNAME)) { + appNameFound = true; + assertTrue(appdesc.getDescription().equals(TEST_APPDESC)); + break; + } + } + assertTrue(appNameFound); + boolean appDescFound = false; + DescribeApplicationVersionsResult verResult = bcClient + .describeApplicationVersions(); + for (ApplicationVersionDescription verdesc : verResult + .getApplicationVersions()) { + if (verdesc.getVersionLabel().equals(TEST_VERSIONLABEL)) { + appDescFound = true; + assertTrue(verdesc.getDescription().equals(TEST_VERSIONDESC)); + break; + } + } + assertTrue(appDescFound); + try { + AWSTestUtils.waitForEnvironmentToTransitionToStateAndHealth( + TEST_ENVIRONMENTNAME, EnvironmentStatus.Ready, + EnvironmentHealth.Green, bcClient); + } catch (Exception e) { + System.out.println(e.getMessage()); + fail(); + } + assertTrue(bcClient.describeEnvironments().getEnvironments().size() > 0); + EnvironmentDescription environment = bcClient + .describeEnvironments( + new DescribeEnvironmentsRequest() + .withEnvironmentNames(TEST_ENVIRONMENTNAME)) + .getEnvironments().get(0); + assertEquals(TEST_ENVIRONMENTDESC, environment.getDescription()); + assertTrue(environment.getCNAME().startsWith(TEST_CNAMEPREFIX)); + assertEquals(TEST_SOLUTIONSTACKNAME, environment.getSolutionStackName()); + } + + @Test + public void testExecuteWorkerTier() { + s3Client.putObject(BUCKET_NAME, KEY, new File(WAR_FILE)); + CreateBeanstalkApplicationTask createAppTask = new CreateBeanstalkApplicationTask(); + CreateBeanstalkEnvironmentTask createEnvTask = new CreateBeanstalkEnvironmentTask(); + DeployAppToBeanstalkTask deployTask = new DeployAppToBeanstalkTask(); + deployTask.setApplicationName(TEST_APPNAME); + createAppTask.setApplicationDescription(TEST_APPDESC); + deployTask.setVersionLabel(TEST_VERSIONLABEL); + deployTask.setVersionDescription(TEST_VERSIONDESC); + deployTask.setBucketName(BUCKET_NAME); + deployTask.setKey(KEY); + deployTask.setEnvironmentName(TEST_ENVIRONMENTNAME); + createEnvTask.setEnvironmentDescription(TEST_ENVIRONMENTDESC); + createEnvTask.setSolutionStackName(TEST_SOLUTIONSTACKNAME); + Setting setting = new Setting(); + setting.setNamespace(TEST_INSTANCEPROFILE_NAMESPACE); + setting.setOptionName(INSTANCEPROFILE_OPTIONNAME); + setting.setValue(TEST_INSTANCEPROFILE_VALUE); + createEnvTask.addConfiguredSetting(setting); + setting = new Setting(); + setting.setNamespace(SQSD_NAMESPACE); + setting.setOptionName(WORKERQUEUEURL_OPTIONNAME); + setting.setValue(TEST_WORKERQUEUEURL_VALUE); + createEnvTask.addConfiguredSetting(setting); + setting = new Setting(); + setting.setNamespace(SQSD_NAMESPACE); + setting.setOptionName(HTTPPATH_OPTIONNAME); + setting.setValue(TEST_HTTPPATH_VALUE); + createEnvTask.addConfiguredSetting(setting); + setting = new Setting(); + setting.setNamespace(SQSD_NAMESPACE); + setting.setOptionName(MIMETYPE_OPTIONNAME); + setting.setValue(TEST_MIMETYPE_VALUE); + createEnvTask.addConfiguredSetting(setting); + setting = new Setting(); + setting.setNamespace(SQSD_NAMESPACE); + setting.setOptionName(HTTPCONNECTIONS_OPTIONNAME); + setting.setValue(TEST_HTTPCONNECTIONS_VALUE); + createEnvTask.addConfiguredSetting(setting); + setting = new Setting(); + setting.setNamespace(SQSD_NAMESPACE); + setting.setOptionName(CONNECTTIMEOUT_OPTIONNAME); + setting.setValue(TEST_CONNECTTIMEOUT_VALUE); + createEnvTask.addConfiguredSetting(setting); + setting = new Setting(); + setting.setNamespace(SQSD_NAMESPACE); + setting.setOptionName(INACTIVITYTIMEOUT_OPTIONNAME); + setting.setValue(TEST_INACTIVITYTIMEOUT_VALUE); + createEnvTask.addConfiguredSetting(setting); + setting = new Setting(); + setting.setNamespace(SQSD_NAMESPACE); + setting.setOptionName(VISIBILITYTIMEOUT_OPTIONNAME); + setting.setValue(TEST_VISIBILITYTIMEOUT_VALUE); + createEnvTask.addConfiguredSetting(setting); + setting = new Setting(); + setting.setNamespace(SQSD_NAMESPACE); + setting.setOptionName(RETENTIONPERIOD_OPTIONNAME); + setting.setValue(TEST_RETENTIONPERIOD_VALUE); + createEnvTask.addConfiguredSetting(setting); + createEnvTask.setTierName(WORKER_TIER); + createEnvTask.setTierType(TEST_TIERTYPE); + createEnvTask.setTierVersion(TEST_WORKERVERSION); + createAppTask.setApplicationName(TEST_APPNAME); + createEnvTask.setEnvironmentName(TEST_ENVIRONMENTNAME); + createEnvTask.setApplicationName(TEST_APPNAME); + createAppTask.execute(); + createEnvTask.execute(); + try { + AWSTestUtils.waitForEnvironmentToTransitionToStateAndHealth( + TEST_ENVIRONMENTNAME, EnvironmentStatus.Ready, null, + bcClient); + } catch (Exception e) { + System.out.println(e.getMessage()); + fail(); + } + deployTask.execute(); + DescribeApplicationsResult appResult = bcClient.describeApplications(); + boolean appNameFound = false; + for (ApplicationDescription appdesc : appResult.getApplications()) { + if (appdesc.getApplicationName().equals(TEST_APPNAME)) { + appNameFound = true; + assertTrue(appdesc.getDescription().equals(TEST_APPDESC)); + break; + } + } + assertTrue(appNameFound); + boolean appDescFound = false; + DescribeApplicationVersionsResult verResult = bcClient + .describeApplicationVersions(); + for (ApplicationVersionDescription verdesc : verResult + .getApplicationVersions()) { + if (verdesc.getVersionLabel().equals(TEST_VERSIONLABEL)) { + appDescFound = true; + assertTrue(verdesc.getDescription().equals(TEST_VERSIONDESC)); + break; + } + } + assertTrue(appDescFound); + try { + AWSTestUtils.waitForEnvironmentToTransitionToStateAndHealth( + TEST_ENVIRONMENTNAME, EnvironmentStatus.Ready, null, + bcClient); + } catch (Exception e) { + System.out.println(e.getMessage()); + fail(); + } + assertTrue(bcClient.describeEnvironments().getEnvironments().size() > 0); + EnvironmentDescription environment = bcClient + .describeEnvironments( + new DescribeEnvironmentsRequest() + .withEnvironmentNames(TEST_ENVIRONMENTNAME)) + .getEnvironments().get(0); + assertEquals(TEST_ENVIRONMENTDESC, environment.getDescription()); + assertEquals(TEST_SOLUTIONSTACKNAME, environment.getSolutionStackName()); + } + + @AfterClass + public static void tearDownAfterClass() throws InterruptedException { + iamClient + .removeRoleFromInstanceProfile(new RemoveRoleFromInstanceProfileRequest() + .withRoleName("aws-elasticbeanstalk-ec2-role") + .withInstanceProfileName(TEST_INSTANCEPROFILE_VALUE)); + iamClient.deleteInstanceProfile(new DeleteInstanceProfileRequest() + .withInstanceProfileName(TEST_INSTANCEPROFILE_VALUE)); + AWSTestUtils.emptyAndDeleteBucket(s3Client, BUCKET_NAME); + } + + @After + public void tearDown() throws InterruptedException { + bcClient.terminateEnvironment(new TerminateEnvironmentRequest() + .withEnvironmentName(TEST_ENVIRONMENTNAME)); + AWSTestUtils.waitForEnvironmentToTransitionToStateAndHealth( + TEST_ENVIRONMENTNAME, EnvironmentStatus.Terminated, null, + bcClient); + bcClient.deleteApplication(new DeleteApplicationRequest(TEST_APPNAME)); + while (true) { + DescribeApplicationsResult appResult = bcClient + .describeApplications(); + boolean appNameFound = false; + for (ApplicationDescription appdesc : appResult.getApplications()) { + if (appdesc.getApplicationName().equals(TEST_APPNAME)) { + appNameFound = true; + break; + } + } + if (!appNameFound) { + break; + } + } + } +} diff --git a/src/test/java/com/amazonaws/ant/elasticbeanstalk/SetUpBeanstalkTestsTask.java b/src/test/java/com/amazonaws/ant/elasticbeanstalk/SetUpBeanstalkTestsTask.java new file mode 100644 index 0000000..5cfb7ff --- /dev/null +++ b/src/test/java/com/amazonaws/ant/elasticbeanstalk/SetUpBeanstalkTestsTask.java @@ -0,0 +1,49 @@ +/* + * Copyright 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file 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 com.amazonaws.ant.elasticbeanstalk; + +import org.apache.tools.ant.BuildException; + +import com.amazonaws.ant.AWSAntTask; +import com.amazonaws.services.identitymanagement.AmazonIdentityManagementClient; +import com.amazonaws.services.identitymanagement.model.AddRoleToInstanceProfileRequest; +import com.amazonaws.services.identitymanagement.model.CreateInstanceProfileRequest; + +public class SetUpBeanstalkTestsTask extends AWSAntTask { + + private static final String INSTANCEPROFILE_ROLE = "aws-elasticbeanstalk-ec2-role"; + private String instanceProfile; + + public void setInstanceProfile(String instanceProfile) { + this.instanceProfile = instanceProfile; + } + + public void checkParams() { + if (instanceProfile == null) { + throw new BuildException( + "Missingparameter: instanceProfile is required"); + } + } + + public void execute() { + AmazonIdentityManagementClient iamClient = createClient(AmazonIdentityManagementClient.class); + iamClient.createInstanceProfile(new CreateInstanceProfileRequest() + .withInstanceProfileName(instanceProfile)); + iamClient + .addRoleToInstanceProfile(new AddRoleToInstanceProfileRequest() + .withRoleName(INSTANCEPROFILE_ROLE) + .withInstanceProfileName(instanceProfile)); + } +} diff --git a/src/test/java/com/amazonaws/ant/elasticbeanstalk/TestSuccessfulBeanstalkDeploymentTask.java b/src/test/java/com/amazonaws/ant/elasticbeanstalk/TestSuccessfulBeanstalkDeploymentTask.java new file mode 100644 index 0000000..e10cd23 --- /dev/null +++ b/src/test/java/com/amazonaws/ant/elasticbeanstalk/TestSuccessfulBeanstalkDeploymentTask.java @@ -0,0 +1,60 @@ +/* + * Copyright 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file 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 com.amazonaws.ant.elasticbeanstalk; + +import org.apache.tools.ant.BuildException; + +import com.amazonaws.ant.AWSAntTask; +import com.amazonaws.ant.AWSTestUtils; +import com.amazonaws.services.elasticbeanstalk.AWSElasticBeanstalkClient; +import com.amazonaws.services.elasticbeanstalk.model.DescribeEnvironmentsRequest; +import com.amazonaws.services.elasticbeanstalk.model.DescribeEnvironmentsResult; +import com.amazonaws.services.elasticbeanstalk.model.EnvironmentStatus; + +public class TestSuccessfulBeanstalkDeploymentTask extends AWSAntTask { + + private String environmentName; + + public void setEnvironmentName(String environmentName) { + this.environmentName = environmentName; + } + + private void checkParams() { + if (environmentName == null) { + throw new BuildException( + "Missing parameter: environmentName is required"); + } + } + + public void execute() { + checkParams(); + AWSElasticBeanstalkClient bcClient = createClient(AWSElasticBeanstalkClient.class); + DescribeEnvironmentsRequest deRequest = new DescribeEnvironmentsRequest() + .withEnvironmentNames(environmentName); + DescribeEnvironmentsResult result = bcClient + .describeEnvironments(deRequest); + if (result.getEnvironments().size() < 1) { + throw new BuildException( + "No environments found with the specified name " + + environmentName); + } + try { + AWSTestUtils.waitForEnvironmentToTransitionToStateAndHealth( + environmentName, EnvironmentStatus.Ready, null, bcClient); + } catch (InterruptedException e) { + throw new BuildException(e.getMessage()); + } + } +} diff --git a/src/test/java/com/amazonaws/ant/s3/CleanUpS3TestsTask.java b/src/test/java/com/amazonaws/ant/s3/CleanUpS3TestsTask.java new file mode 100644 index 0000000..f107ac6 --- /dev/null +++ b/src/test/java/com/amazonaws/ant/s3/CleanUpS3TestsTask.java @@ -0,0 +1,70 @@ +/* + * Copyright 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file 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 com.amazonaws.ant.s3; + +import java.io.File; + +import org.apache.tools.ant.BuildException; + +import com.amazonaws.ant.AWSAntTask; +import com.amazonaws.ant.AWSTestUtils; +import com.amazonaws.services.s3.AmazonS3Client; + +public class CleanUpS3TestsTask extends AWSAntTask { + private String firstFile; + + public void setFirstFile(String firstFile) { + this.firstFile = firstFile; + } + + private String secondFile; + + public void setSecondFile(String secondFile) { + this.secondFile = secondFile; + } + + private String bucketName; + + public void setBucketName(String bucketName) { + this.bucketName = bucketName; + } + + private void checkParams() { + if (firstFile == null) { + throw new BuildException("File must be set"); + } + if (secondFile == null) { + throw new BuildException("Second file must be set"); + } + if (bucketName == null) { + throw new BuildException("Bucket name must be set"); + } + } + + public void execute() { + checkParams(); + File file1 = new File(firstFile); + if (file1 != null && file1.exists()) { + file1.delete(); + } + File file2 = new File(secondFile); + if (file2 != null && file2.exists()) { + file2.delete(); + } + AmazonS3Client client = createClient(AmazonS3Client.class); + + AWSTestUtils.emptyAndDeleteBucket(client, bucketName); + } +} diff --git a/src/test/java/com/amazonaws/ant/s3/DownloadFromS3TaskTests.java b/src/test/java/com/amazonaws/ant/s3/DownloadFromS3TaskTests.java new file mode 100644 index 0000000..e345716 --- /dev/null +++ b/src/test/java/com/amazonaws/ant/s3/DownloadFromS3TaskTests.java @@ -0,0 +1,113 @@ +/* + * Copyright 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file 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 com.amazonaws.ant.s3; + +import static org.junit.Assert.*; + +import java.io.File; +import java.io.IOException; + +import org.apache.commons.io.FileUtils; +import org.apache.tools.ant.Project; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +import com.amazonaws.ant.AWSTestUtils; +import com.amazonaws.ant.s3.DownloadFileFromS3Task; +import com.amazonaws.services.s3.AmazonS3Client; + +public class DownloadFromS3TaskTests { + private static final String RES_FILE = "res"; + private static final String TEST_FILE_3 = "test3"; + private static final String TEST_FILE_2 = "test2"; + private static final String TEST_FILE_1 = "test"; + private static final String BUCKET_NAME = "deployfilesettos3testbucket"; + private static final String KEY_PREFIX = "deployfilesettos3test/"; + private static final String TESTFILE_SUFFIX = ".txt"; + private static final String USER_DIR = System.getProperty("user.dir"); + private static final String DIR = USER_DIR + File.pathSeparator + + KEY_PREFIX; + private static File testFile1, testFile2, testFile3; + private static AmazonS3Client client; + private File resFile1, resFile2, resFile3; + + @BeforeClass + public static void setUp() throws IOException { + testFile1 = AWSTestUtils.createRandomFile(TEST_FILE_1, TESTFILE_SUFFIX); + testFile2 = AWSTestUtils.createRandomFile(TEST_FILE_2, TESTFILE_SUFFIX); + testFile3 = AWSTestUtils.createRandomFile(TEST_FILE_3, TESTFILE_SUFFIX); + client = new AmazonS3Client(); + client.createBucket(BUCKET_NAME); + client.putObject(BUCKET_NAME, KEY_PREFIX + testFile1.getName(), + testFile1); + client.putObject(BUCKET_NAME, KEY_PREFIX + testFile2.getName(), + testFile2); + client.putObject(BUCKET_NAME, KEY_PREFIX + testFile3.getName(), + testFile3); + } + + @Test + public void testDownloadSingleFile() throws IOException { + DownloadFileFromS3Task task = new DownloadFileFromS3Task(); + task.setProject(new Project()); + task.setBucketName(BUCKET_NAME); + task.setKey(KEY_PREFIX + testFile1.getName()); + resFile1 = File.createTempFile(RES_FILE, TESTFILE_SUFFIX); + resFile1.createNewFile(); + task.setFile(resFile1); + task.execute(); + assertTrue(FileUtils.contentEquals(testFile1, resFile1)); + } + + @Test + public void testDownloadFilesWithPrefix() throws IOException { + DownloadFileFromS3Task task = new DownloadFileFromS3Task(); + task.setProject(new Project()); + task.setBucketName(BUCKET_NAME); + task.setKeyPrefix(KEY_PREFIX); + task.setDir(USER_DIR); + resFile1 = new File(DIR + testFile1.getName()); + resFile2 = new File(DIR + testFile2.getName()); + resFile3 = new File(DIR + testFile3.getName()); + task.execute(); + assertTrue(FileUtils.contentEquals(testFile1, resFile1)); + assertTrue(FileUtils.contentEquals(testFile2, resFile2)); + assertTrue(FileUtils.contentEquals(testFile3, resFile3)); + } + + @After + public void tearDown() throws IOException { + if (resFile1 != null) { + resFile1.delete(); + } + if (resFile2 != null) { + resFile2.delete(); + } + if (resFile3 != null) { + resFile3.delete(); + } + FileUtils.deleteDirectory(new File(DIR)); + } + + @AfterClass + public static void tearDownAfterClass() { + AWSTestUtils.emptyAndDeleteBucket(client, BUCKET_NAME); + testFile1.delete(); + testFile2.delete(); + testFile3.delete(); + } +} diff --git a/src/test/java/com/amazonaws/ant/s3/SetUpS3TestsTask.java b/src/test/java/com/amazonaws/ant/s3/SetUpS3TestsTask.java new file mode 100644 index 0000000..2f8a800 --- /dev/null +++ b/src/test/java/com/amazonaws/ant/s3/SetUpS3TestsTask.java @@ -0,0 +1,47 @@ +/* + * Copyright 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file 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 com.amazonaws.ant.s3; + +import java.io.File; + +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.Task; + +import com.amazonaws.ant.AWSTestUtils; + +public class SetUpS3TestsTask extends Task { + + private File file; + + public void setFile(File file) { + this.file = file; + } + + private void checkParams() { + if (file == null) { + throw new BuildException("Missing parameter: File is required"); + } + } + + public void execute() { + checkParams(); + try { + file.createNewFile(); + AWSTestUtils.writeRandomLinesToFile(file); + } catch (Exception e) { + throw new BuildException("Error setting up s3 tests.", e); + } + } +} diff --git a/src/test/java/com/amazonaws/ant/s3/UploadFileSetToS3TaskTests.java b/src/test/java/com/amazonaws/ant/s3/UploadFileSetToS3TaskTests.java new file mode 100644 index 0000000..795bc4f --- /dev/null +++ b/src/test/java/com/amazonaws/ant/s3/UploadFileSetToS3TaskTests.java @@ -0,0 +1,129 @@ +/* + * Copyright 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file 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 com.amazonaws.ant.s3; + +import static org.junit.Assert.*; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; + +import org.apache.tools.ant.Project; +import org.apache.tools.ant.types.FileSet; +import org.apache.commons.io.FileUtils; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +import com.amazonaws.ant.AWSTestUtils; +import com.amazonaws.ant.s3.UploadFileSetToS3Task; +import com.amazonaws.services.s3.AmazonS3Client; +import com.amazonaws.services.s3.model.GetObjectRequest; + +public class UploadFileSetToS3TaskTests { + + private static final String RES_FILE_3 = "res3"; + private static final String RES_FILE_2 = "res2"; + private static final String RES_FILE_1 = "res"; + private static final String TESTFILE_SUFFIX = ".txt"; + private static final String TEST_FILE_3 = "test3"; + private static final String TEST_FILE_2 = "test2"; + private static final String TEST_FILE_1 = "test"; + private static final String BUCKET_NAME = "deployfilesettos3testbucket"; + private static final String KEY_PREFIX = "deployfilesettos3test/"; + private static AmazonS3Client client; + private static String fileName1, fileName2, fileName3; + private static File testFile1, testFile2, testFile3; + private File resFile1, resFile2, resFile3; + + @BeforeClass + public static void setUp() throws IOException { + testFile1 = AWSTestUtils.createRandomFile(TEST_FILE_1, TESTFILE_SUFFIX); + testFile2 = AWSTestUtils.createRandomFile(TEST_FILE_2, TESTFILE_SUFFIX); + testFile3 = AWSTestUtils.createRandomFile(TEST_FILE_3, TESTFILE_SUFFIX); + fileName1 = testFile1.getName(); + fileName2 = testFile2.getName(); + fileName3 = testFile3.getName(); + + client = new AmazonS3Client(); + client.createBucket(BUCKET_NAME); + } + + @Test + public void testExecuteSingleFile() throws FileNotFoundException, + IOException { + UploadFileSetToS3Task task = new UploadFileSetToS3Task(); + task.setProject(new Project()); + FileSet fileset = new FileSet(); + fileset.setDir(testFile1.getParentFile()); + fileset.setFile(testFile1); + task.addFileset(fileset); + task.setBucketName(BUCKET_NAME); + task.setKeyPrefix(KEY_PREFIX); + task.execute(); + resFile1 = File.createTempFile(RES_FILE_1, TESTFILE_SUFFIX); + client.getObject(new GetObjectRequest(BUCKET_NAME, KEY_PREFIX + + fileName1), resFile1); + assertTrue(FileUtils.contentEquals(testFile1, resFile1)); + } + + @Test + public void testExecuteMultipleFiles() throws IOException { + UploadFileSetToS3Task task = new UploadFileSetToS3Task(); + task.setProject(new Project()); + FileSet fileset = new FileSet(); + fileset.setDir(testFile1.getParentFile()); + fileset.setIncludes("*.txt"); + task.addFileset(fileset); + task.setBucketName(BUCKET_NAME); + task.setKeyPrefix(KEY_PREFIX); + task.execute(); + resFile1 = File.createTempFile(RES_FILE_1, TESTFILE_SUFFIX); + resFile2 = File.createTempFile(RES_FILE_2, TESTFILE_SUFFIX); + resFile3 = File.createTempFile(RES_FILE_3, TESTFILE_SUFFIX); + client.getObject(new GetObjectRequest(BUCKET_NAME, KEY_PREFIX + + fileName1), resFile1); + client.getObject(new GetObjectRequest(BUCKET_NAME, KEY_PREFIX + + fileName2), resFile2); + client.getObject(new GetObjectRequest(BUCKET_NAME, KEY_PREFIX + + fileName3), resFile3); + assertTrue(FileUtils.contentEquals(testFile1, resFile1)); + assertTrue(FileUtils.contentEquals(testFile1, resFile1)); + assertTrue(FileUtils.contentEquals(testFile1, resFile1)); + } + + @After + public void tearDown() { + + if (resFile1 != null) { + resFile1.delete(); + } + if (resFile2 != null) { + resFile2.delete(); + } + if (resFile3 != null) { + resFile3.delete(); + } + } + + @AfterClass + public static void tearDownAfterClass() { + AWSTestUtils.emptyAndDeleteBucket(client, BUCKET_NAME); + testFile1.delete(); + testFile2.delete(); + testFile3.delete(); + } +} diff --git a/test.war b/test.war new file mode 100644 index 0000000000000000000000000000000000000000..0a127e6bd1f6991c32f591e577b42a50210c60f7 GIT binary patch literal 4606 zcmaKv2{@Ep8^@nnjKR!Awi4pCGj_>ZgOFupmy9ftrIBSOCQFRTPO_vdq3lVrB(i7A zzEqTK*(+X@-lXIky{~wEeczeud7g94b^q`CKj+MI&iNVYL7?=&R?~|7A^)@U&y5a% z0$5E`HE|sSEy*7p0ATn}C>+qFhEA@7>&{X`U8xrf_4*ZxRWs1h(ljxZz-oQMc6I9O ziA(e&^~6Pcx_ZlurC!KR%y@Na?Ds^U)bBZI21J4cx>xltSEWT6GwT_f5O0gBy~ln= zOd`982?%{wxnR9dEdH_yQ6HnkqV$XjQLHMT;y=q>t|C?a@&f<{lz&@?Q~g+Is{eGp z?HT}1?TKRC6?G18M<6&7B>#6b$8VzDE_>LWyI|+!xJ$R!3u2cJ?_&RdB5A3SE^gFp zJ2v1yO%LCT6XAsbz%v>E5ZIM&+w_i&la6@2yTs4$V@%%|GpjMGLdXc-NZ1PM0SUxX zI%!=R@rO@DxVp{_vt#&pY0FWE!O;lyul#}2QEbQ7KvxnSdly6#+2w91-Bx_AI!bsV zYf~Ta18lp$@E~U!RJ)E{{(B^MGBe=QBM$d#Pwl=qG%A6*gG^ntwXGW8iou0Ah zQl^fzA=>a91eY#ZqVm~J6M@j4{*pXI!9h!AM1W(lfcbEDBz$Nz@|6Aqbm4=|7f97w zgJ+4ZB&MdfUIa0Z!s3x957|SOI>8ziSP6K`vP1dzfqdb@!PDcTcQF-z81qyG-2ljZmQSQ^@>w**Ekh%-L9eeReHIFMsbcj z0*gwn>b?h0)c)au&MrCmA_X62CcWemA)|G@2GuhOHIP{qE-4_$Z^$K;l7eQ?9i)7# zJMG3CVwNgTOL?zaWsOa9&4}0}4vw6kV7Q5^pWnQviE`(SkZgGZ*#%3 z;Uu#HiyXk%-wS-XN(taDOad{?8lup+7PP`0aaXcXO$Kj&0zN=-`^&tXd zew-3N#!aO;qpzmKi3^-@4G`n8=Se^L#>eWCAGSZ}Wp~<_7n(9Ih&HXZA2PukftfmF zO!0R%)kAIbFZ(i3QmVmM^PC+M938490>IyFD^4+cANu$QjIOK%66z6(ri7GDYc}G; z@sX8_E4Vh4lCo4Cg{7(E#DfofPlUW&C?mG9jnR!~DV7vk1h?F)$6<;N%MTkz(nqgQ zv=OKSD!P?cUu8K3YG`~x{b3@AOw1!CQvws8upRizd`?;`*GQXnmo2L7w4i_VWxOq@ zw=hDb_5jHD|3gf@6J1s^?%xg(o+Ae&n$e*&}czY1hPsh69?? zIQb*j0%^Bjb@!Ge$I)JbxCLQfCeby0vGuAXmQd z+IzjCti5Q-Vl8mXyeDdYTk6A{|Er~aYn@FSrfjDpO%KvPedd<E`FP6H z!^hm6NL+R4rK~etIqW}w>0xr#pVG+9#S;r zhV#c^frsvoMjC@J;OjK#y?O> zSP^Z(ySns&R^V}PoSJM(zjG<)cNb29rp5alD$RmtbkayTuktJB zc+8CV>At5mFN@1l884cmw~)p~b?92YQ;9m-kMJs_?^9-;!)gx}%>MZ@n@@iO*x zp=U$b`br69;h;m*Py+Y)@O2b}6MJ`=v*@Ww8WdO3XY~z-jj{TF4@3Sp*v(w(UT}wc zF;R!%pG|}4?sm?ODBj*};bm^wc*;E)8UJQuA$YZt{MGQab>E-nwn&0HB-8?K*|E3N~fe zeoPS1TF&YD1i||X7C<8+DRcmgj*f;Q zB{h|Xh7RVc3XXSAU8NSM3|g9I}(L^ znfT!wkR%mr86LiU5sa~>C1Q-3li&+rFb_{9Jz0%MW|P!NKMR8d@qWl$q{m<5$f$e%h8X<{R0b>xmZX z@!3+nc6N_3lU2NWSWZ{YS;kmUFdv=j2cSq-cnP6={lbNlM?hApm+uKzd*^bL=Gg1_ z65&pw0BSDy65PAyznD+1!Y#5IWup9exA5$>^{WPD=5Qg84Nk8uODsm zDW8jDmPLrmL4N;7!dKW@7@Xm@Cy(4;PNQtrn~1|)yf`+{NZ5EVL|8V?_l-XD^@H`v zrnacF{Ur^-oRiv=z&9n$?e<32NgVdV>*76aWXBs6 zrY_uwi^u@CR(_oYh~|pOBOuFWV@xR*A%a0f-wAAtK45|gGvj_@d;Q@e*}+F=)P&{a z5}60e0O``9q`8}46^KG1Fs7Q&#QrotUA!VRg_raN#0{#1=iLqW%E#QkRC+zgh1;4P z87-++(3NphN@OsIIXW{W%3bCIdNWLe_zveFsUy}7{`9$mA9hpg>%!ySr|*DpP7#;; z#134LcCMKh{h!syTWzC;WJF^MQ=L(tVLroCMS&XNXkTVAr<$E9vma~x9mwYJuzLaM zxU!V*tpAN7CY#7*v!)((_L63F`Qz>e_Cuax}PK&YObfpwF+(dGtTX~b~{G;uoUMokBxNaUQdTEX9_o@FQ zX2uY7bq+0g&93<|2{Ki})3GU*X=`lB4bo>;tbsUjww`tVvaDfJoXCO`_6a$*K6r%a z=FaN3QJuPvRi*VZtXQZ|cmBnR`#>9V%&!Tg@m)-!!n^kFQP|Ufbe3sFi*`}}NXe5; zf3=UbK)RLSZzzKkv(P#^m?Y^NEd!qyLx+yYJUWemf4TFUR834qqmVNWV9X=4ihsDm z=*NtFmPeVba<>w)wKisa8heO86h6;9oNU}zS7r1kw2Kn*>Z0ATq!T?Vwh=rG>zZ%| z`HOTN8syS=bp@96PV!o^sf9dyv|z)Z2fR8DO-8O390-1>kGmI)U?j@(f+y??CT^un zs2yG}xoU~eLZ)P9mg*W9^@p8@V>)3IbXfiwTAgsSu$r|N!LH@V9#IW0?qyb7e?*KM zln)s*TWxV)GIkn1_1ch>pw9785CP@i|KvK4@<0SEGMazmEK?AbP?Z0@sEc?JNNBS~eeQ5dW%aPau`~mCQvu12q_DyndldpU0YhIS#c~19<+bx%9RJzKt2BDJ$ zqOyhuXKoC8_=KK!eqFL)kfiQ^Ek4(%C^SdoHS1%|(m0|ZcMOE&;zJX29%BRJe(9iW zn33tIHS>IILn!qwi}H|rlFB?gI(UZ3&Kxpt*$~t#Gn+~q)rJB?6d$kg2--S4ut;Zj zVN%+Uhjbo14U_E`D66!1#4KN*16F*}C&#~J>Flbr_}#Zf&qJ<&3HxqQ+k@21r<87V zQAI`k#oNF9e#lsu=gJdGlz0l|51%t&zB_Wz03C)*yG$O`56XBYp+p;hOt*_e)o<{< zf%I)H#WlZ|X9n05BI9AA5c7xQtnx`U8_NWv`UM-4Kr@&3iy5!({w1s(_Lg2O!KK)kJooBE2 zE$ZFLqrEH7-weFtf3I?jf_IdjROK%w-WL6yinnFi