├── .gitignore ├── LICENSE ├── README.md ├── buildspec.yml ├── codebuild ├── build_roadworker.bash ├── cleanup.bash ├── install_rvm.bash └── rvmrc ├── lambda_function.py ├── roadwork └── tf ├── .gitignore ├── README.md ├── codebuild-project.json.tpl ├── codebuild.tf ├── roadworker-lambda.tf ├── terraform.tfvars └── variables.tf /.gitignore: -------------------------------------------------------------------------------- 1 | # IDEA + Terraform 2 | .idea 3 | *.zip 4 | *.pem 5 | terraform.tfstate.backup 6 | terraform.tfstate 7 | 8 | # Byte-compiled / optimized / DLL files 9 | __pycache__/ 10 | *.py[cod] 11 | *$py.class 12 | 13 | # C extensions 14 | *.so 15 | 16 | # Distribution / packaging 17 | .Python 18 | env/ 19 | build/ 20 | develop-eggs/ 21 | dist/ 22 | downloads/ 23 | eggs/ 24 | .eggs/ 25 | lib/ 26 | lib64/ 27 | parts/ 28 | sdist/ 29 | var/ 30 | *.egg-info/ 31 | .installed.cfg 32 | *.egg 33 | 34 | # PyInstaller 35 | # Usually these files are written by a python script from a template 36 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 37 | *.manifest 38 | *.spec 39 | 40 | # Installer logs 41 | pip-log.txt 42 | pip-delete-this-directory.txt 43 | 44 | # Unit test / coverage reports 45 | htmlcov/ 46 | .tox/ 47 | .coverage 48 | .coverage.* 49 | .cache 50 | nosetests.xml 51 | coverage.xml 52 | *,cover 53 | .hypothesis/ 54 | 55 | # Translations 56 | *.mo 57 | *.pot 58 | 59 | # Django stuff: 60 | *.log 61 | local_settings.py 62 | 63 | # Flask stuff: 64 | instance/ 65 | .webassets-cache 66 | 67 | # Scrapy stuff: 68 | .scrapy 69 | 70 | # Sphinx documentation 71 | docs/_build/ 72 | 73 | # PyBuilder 74 | target/ 75 | 76 | # IPython Notebook 77 | .ipynb_checkpoints 78 | 79 | # pyenv 80 | .python-version 81 | 82 | # celery beat schedule file 83 | celerybeat-schedule 84 | 85 | # dotenv 86 | .env 87 | 88 | # virtualenv 89 | venv/ 90 | ENV/ 91 | 92 | # Spyder project settings 93 | .spyderproject 94 | 95 | # Rope project settings 96 | .ropeproject 97 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Running roadworker in AWS Lambda to backup Route 53 2 | 3 | Cheap and low-maintenance solution to back up Route53 to S3 using AWS Lambda. 4 | 5 | ![Dashsoft](https://dashsoft.dk/static/images/logo.png "Dashsoft logo") 6 | 7 | Blog post: [Backing up Route53 with Ruby and Lambda](https://dashsoft.dk/da/blog/Route53_Lambda_Backups/) 8 | 9 | Website: [https://dashsoft.dk](https://dashsoft.dk) 10 | 11 | 12 | ## Installing 13 | 14 | ### Prerequisites 15 | 16 | [Download](https://releases.hashicorp.com/terraform/) and copy terraform to a bin directory in your path. The version 17 | should be 0.7.13 or higher — as we are going to need support for 18 | [Lambda Environment Variables](https://aws.amazon.com/about-aws/whats-new/2016/11/aws-lambda-supports-environment-variables/). 19 | Also make sure that you have an updated version of the [AWS CLI](https://aws.amazon.com/cli/) (version 1.11.28 or higher - 20 | more recent than re:Invent 2016 as we need support for CodeBuild). 21 | 22 | The [Getting Started](https://www.terraform.io/intro/getting-started/install.html) guide for Terraform and the 23 | [Getting Started](http://docs.aws.amazon.com/cli/latest/userguide/cli-chap-welcome.html) chapter for the AWS CLI might be helpful. 24 | 25 | ### Building the Lambda code 26 | 27 | First, we need to create the Lambda zip file containing Roadworker installed in a Ruby environment by making a 28 | CodeBuild project and running a build. 29 | 30 | Clone the GitHub repository [dashsoftaps/lambda-roadworker](https://github.com/dashsoftaps/lambda-roadworker) 31 | 32 | CodeBuild requires a few resources: An IAM Role that allows CodeBuild to output CloudWatch Logs and gives permission 33 | to write to an S3 bucket. Also: An S3 bucket for the Lambda zip file, which I will reuse for the backups. 34 | 35 | I have turned on versioning and also lifecycle management on the bucket to purge old backups after a year and purge 36 | non-current versions after a month. 37 | 38 | The bucket name is specified in the [tf/terraform.tfvars](../master/tf/terraform.tfvars) file. It should be changed from 39 | _hennings-roadworker-backup-bucket_ to something that is appropriately and unique for your account. 40 | 41 | Also compare the [Build Environment Reference for AWS CodeBuild](docs.aws.amazon.com/codebuild/latest/userguide/build-env-ref.html#build-env-ref-available) with 42 | [the current lambda environment](http://docs.aws.amazon.com/lambda/latest/dg/current-supported-versions.html "Lambda 43 | Execution Environment and Available Libraries") to make sure that the 44 | `codebuild_image` are compatible with the Lambda execution environment. 45 | 46 | Now create the necessary infrastructure with Terraform. Usually, I've already 47 | [configured an profile with the AWS CLI](http://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html#cli-multiple-profiles) 48 | and set it up in an ```AWS_PROFILE``` environment variable, but there's now a wide range of options for safely managing 49 | and providing AWS credentials ([AWS Vault](https://github.com/99designs/aws-vault), 50 | [awsudo](https://github.com/makethunder/awsudo), [instance 51 | profiles](http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html)) 52 | 53 | Change directory to `tf` to create the bucket and the policies. Cautious SysAdmins should probably run `terraform plan` 54 | to review which resource that Terraform is about to create before running the `terraform apply` command: 55 | 56 | ``` 57 | $ cd tf 58 | $ terraform apply 59 | ``` 60 | 61 | Terraform will run for a while and create 10 resources. Terraform does not yet support creating CodeBuild projects 62 | natively (there is a [work-in-progress pull request](https://github.com/hashicorp/terraform/pull/10633), so support 63 | should not be too far away). Until it is supported, the AWS CLI will have to be used to create the project and start 64 | the build: 65 | 66 | ``` 67 | $ aws codebuild create-project --cli-input-json file://codebuild-project.json 68 | $ aws codebuild start-build --project-name lambda-roadworker 69 | ``` 70 | 71 | The software that is being build by the CodeBuild project is specified in the [buildspec.yml](../master/buildspec.yml) file. 72 | 73 | Follow the build phase of CodeBuild in the AWS Console. 74 | 75 | If everything goes well, then the status of the build should end as Succeeded and a zipfile named LambdaRoadworker.zip 76 | should exist in the bucket. 77 | 78 | ### Deploying the Lambda function 79 | 80 | Running the RoadWorker Lambda function also requires a few resources: Mainly a Lambda function, a scheduled 81 | [cloudwatch event rule](https://www.terraform.io/docs/providers/aws/r/cloudwatch_event_rule.html) and a few resources 82 | to connect the function and the event rule and allow the event rule to call the Lambda function. 83 | 84 | For the event rule, I’ve chosen a schedule that triggers the backup every 6 hours. 85 | 86 | Compared to the previous run, an additional argument needs to be passed to deploy the Lambda function. Run a Terraform 87 | plan to review the Lambda function and associated resources that are to be created: 88 | 89 | ``` 90 | # terraform plan -var 'with_lambda=1' 91 | ``` 92 | 93 | Create the resources with: 94 | 95 | ``` 96 | # terraform apply -var 'with_lambda=1' 97 | ``` 98 | 99 | There's now a terraform.tfstate file in the directory. If you ever want to change or modify the infrastructure that 100 | you just created, then you need to save- and manage this file. 101 | 102 | There's a range of options for doing this - see the Terraform documentation on 103 | [Remote State](https://www.terraform.io/docs/state/remote/index.html) or consider using 104 | [Terragrunt](https://blog.gruntwork.io/add-automatic-remote-state-locking-and-configuration-to-terraform-with-terragrunt-656a57565a4d). 105 | 106 | Losing a Terraform state file is usually a pretty bad thing, but in this case, only a handful of resources is created. 107 | If you should lose the state file, then just delete the resources in the console (the Lambda function 108 | RoadworkerRoute53Backup, the IAM Roles prefixed with LambdaRoadworker and possibly the S3 bucket and CodeBuild 109 | project) and re-create them with Terraform. 110 | 111 | ### Testing the Lambda function 112 | 113 | The easiest way to test the Lambda function would be to go to the Lambda page in the AWS Console, find and choose the 114 | function RoadworkerRoute53Backup, select _Test function_ on the _Actions_ drop-down, choose _Scheduled Event_ in the 115 | _Sample event list_ and then _Save and test_ - before verifying that the Execution result section shows success. 116 | 117 | You could also just use the AWS CLI to invoke the function: 118 | 119 | ``` 120 | $ aws lambda invoke -function-name RoadworkerRoute53Backup /dev/null 121 | ``` 122 | 123 | If the function runs successfully, then you should find a timestamped backup file in the S3 bucket. 124 | 125 | ### Restoring backups 126 | 127 | Restoring or validating backups can be done from any server og PC with access to update Route53. Install roadworker 128 | locally and download the needed backup file from S3. 129 | 130 | See the [Roadworker github page](https://github.com/winebarrel/roadworker) for additional documentation on which 131 | arguments to use to test- and restore backup files. 132 | 133 | 134 | ## Alternate approaches and various improvements 135 | 136 | ### Backup results should be monitored 137 | 138 | Monitoring tools and preferences certainly differs across organizations. An AWS-centric approach would be to publish 139 | the return codes and the size of the backup file as custom CloudWatch metrics using either 140 | [AWS CLI](http://docs.aws.amazon.com/cli/latest/reference/cloudwatch/put-metric-data.html) 141 | or [boto3](http://boto3.readthedocs.io/en/latest/reference/services/cloudwatch.html#CloudWatch.Client.put_metric_data). 142 | 143 | An alternative to explicitly publishing metrics would be to print out the size of the backup file from the 144 | [python lambda handler](../master/lambda_function.py) in a format that's recognizable. It'll end up in the 145 | Lambda Cloudwatch logstream where it could be picked up and published as a metric by 146 | a [Cloudwatch Logs metric filter](https://www.terraform.io/docs/providers/aws/r/cloudwatch_log_metric_filter.html). 147 | 148 | The AWS documentations has [more information about how to filter 149 | and monitor log data](http://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/MonitoringLogData.html). 150 | 151 | Add [CloudWatch Alarms](https://www.terraform.io/docs/providers/aws/r/cloudwatch_metric_alarm.html) to the Terraform 152 | script that checks the lambda- and custom metric to make sure that the backup runs with the frequency that you expect, 153 | that the backup file isn't suspiciously small and that the Lambda function doesn't have failed invocations. 154 | 155 | ### Use Traveling Ruby 156 | 157 | Figure out how to add unsupported native gems to [Traveling Ruby](http://phusion.github.io/traveling-ruby/). One drawback 158 | of Traveling Ruby is that it supports a limited set of Ruby versions. It is debatable if shaving off a few extra MB's 159 | are worth the effort and ease of building on rvm. 160 | 161 | ### Backup based on CloudTrail events instead of scheduled 162 | 163 | Could the backup be triggered to run only when changes have been made to Route53. Triggered by a Route53 CloudTrail event? 164 | 165 | It does raise the question about how to handle when there is a lot of changes (during restore of a zone, for instance). 166 | 167 | Perhaps a combination, where Route53 CloudTrail events (representing changes to Route53) were put on a SQS queue and a 168 | scheduled job polled the queue every few minutes and only did a backup when there were items in the queue and then 169 | subsequently emptied the queue. That might ensure that a restore of a zone with hundreds of records won't generate 170 | hundreds of backups. 171 | 172 | ### Replace CodeBuild with Docker? 173 | 174 | There's now [a docker image of Amazon Linux](https://hub.docker.com/_/amazonlinux/) that might be usable for 175 | compiling/assembling software to go into Lambda functions without using CodeBuild. 176 | 177 | Here's [the obligatory Jeff Barr blog post](https://aws.amazon.com/blogs/aws/new-amazon-linux-container-image-for-cloud-and-on-premises-workloads/). 178 | 179 | The official Docker image is Amazon Linux 2016.09, but it's not the officially sanctioned Lambda environment 180 | (amzn-ami-hvm-2016.03.3.x86_64-gp2). Regardless, it might produce binaries that are "compatible enough" to work. 181 | -------------------------------------------------------------------------------- /buildspec.yml: -------------------------------------------------------------------------------- 1 | version: 0.1 2 | 3 | phases: 4 | install: 5 | commands: 6 | - yum -y groupinstall "Development Tools" 7 | - yum -y install libpcap-devel.x86_64 libtool libyaml-devel 8 | - gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 9 | - mkdir -p /var/task 10 | pre_build: 11 | commands: 12 | - bash codebuild/install_rvm.bash 13 | - cp codebuild/cleanup.bash /tmp/ 14 | build: 15 | commands: 16 | - echo Build started on `date` 17 | - bash codebuild/build_roadworker.bash 18 | post_build: 19 | commands: 20 | - mv /var/task/rvm . 21 | - cp codebuild/rvmrc .rvmrc 22 | - echo Build completed on `date` 23 | artifacts: 24 | files: 25 | - .rvmrc 26 | - rvm/**/* 27 | - roadwork 28 | - lambda_function.py 29 | -------------------------------------------------------------------------------- /codebuild/build_roadworker.bash: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Installs roadworker in /var/task/ 4 | # 5 | source /var/task/rvm/scripts/rvm 6 | 7 | rvm requirements run 8 | 9 | rvm pkg install libyaml 10 | rvm install ruby 2.3 --default 11 | 12 | gem install roadworker -v '~> 0.5.7.beta3' 13 | 14 | ( cd /var/task ; bash /tmp/cleanup.bash ) 15 | -------------------------------------------------------------------------------- /codebuild/cleanup.bash: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | rvm/bin/rvm cleanup all 4 | 5 | # Remove tests 6 | rm -rf rvm/rubies/ruby-*/lib/ruby/gems/*/gems/*/test 7 | rm -rf rvm/rubies/ruby-*/lib/ruby/gems/*/gems/*/benchmark 8 | rm -rf rvm/gems/ruby-*/gems/*/test 9 | rm -rf rvm/gems/ruby-*/gems/*/tests 10 | rm -rf rvm/gems/ruby-*/gems/*/spec 11 | 12 | rm -rf rvm/gems/ruby-*/doc 13 | 14 | rm -f rvm/gems/ruby-*/gems/*/TODO 15 | rm -f rvm/gems/ruby-*/gems/*/README* 16 | rm -f rvm/gems/ruby-*/gems/*/CHANGE* 17 | rm -f rvm/gems/ruby-*/gems/*/Change* 18 | rm -f rvm/gems/ruby-*/gems/*/COPYING* 19 | rm -f rvm/gems/ruby-*/gems/*/LICENSE* 20 | rm -f rvm/gems/ruby-*/gems/*/MIT-LICENSE* 21 | rm -f rvm/gems/ruby-*/gems/*/*.txt 22 | rm -f rvm/gems/ruby-*/gems/*/*.md 23 | rm -f rvm/gems/ruby-*/gems/*/*.rdoc 24 | 25 | rm -rf rvm/gems/ruby-*/gems/*/doc 26 | rm -rf rvm/gems/ruby-*/gems/*/docs 27 | rm -rf rvm/gems/ruby-*/gems/*/example 28 | rm -rf rvm/gems/ruby-*/gems/*/examples 29 | rm -rf rvm/gems/ruby-*/gems/*/sample 30 | rm -rf rvm/gems/ruby-*/gems/*/doc-api 31 | 32 | find rvm -name '*.md' | xargs rm -f 33 | find rvm -name '.gitignore' | xargs rm -f 34 | find rvm -name '.travis.yml' | xargs rm -f 35 | 36 | find rvm -name '*.java' | xargs rm -f 37 | find rvm -name '*.class' | xargs rm -f 38 | 39 | rm -rf rvm/patches 40 | rm -rf rvm/gems/cache 41 | rm -rf rvm/gems/ruby-*/cache 42 | rm -rf rvm/gem-cache 43 | 44 | rm -f rvm/rubies/ruby-*/lib/ruby/*/*/enc/cp949* 45 | rm -f rvm/rubies/ruby-*/lib/ruby/*/*/enc/euc_* 46 | rm -f rvm/rubies/ruby-*/lib/ruby/*/*/enc/shift_jis* 47 | rm -f rvm/rubies/ruby-*/lib/ruby/*/*/enc/koi8_* 48 | rm -f rvm/rubies/ruby-*/lib/ruby/*/*/enc/emacs* 49 | rm -f rvm/rubies/ruby-*/lib/ruby/*/*/enc/gb* 50 | rm -f rvm/rubies/ruby-*/lib/ruby/*/*/enc/big5* 51 | rm -rf rvm/rubies/ruby-*/lib/ruby/*/*/enc/trans 52 | 53 | # static library & stripping 54 | rm -f rvm/rubies/ruby-*/lib/libruby-static.a 55 | strip rvm/rubies/ruby-*/lib/libruby.so.* 56 | find . -type f -name '*.so' | xargs -n1 strip 57 | 58 | # rdoc 59 | rm -rf rvm/rubies/ruby-*/lib/ruby/*/rdoc 60 | 61 | # rakefiles 62 | rm -f rvm/gems/ruby-*/gems/*/Rakefile 63 | rm -f rvm/rubies/ruby-*/lib/ruby/gems/*/gems/*/Rakefile 64 | 65 | # Remove misc unnecessary files 66 | rm -rf rvm/gems/ruby-*/gems/*/.gitignore 67 | rm -rf rvm/gems/ruby-*/gems/*/.travis.yml 68 | rm -rf rvm/contrib 69 | rm -rf rvm/patchsets 70 | rm -rf rvm/man 71 | find rvm/rubies/ruby-*/include -type f -name "*.h" | xargs rm -f 72 | find rvm/gems/ruby-*/gems/*/ext -type f -name "*.o" | xargs rm -f 73 | find rvm/gems/ruby-*/gems/*/ext -type f -name "*.h" | xargs rm -f 74 | find rvm/gems/ruby-*/gems/*/ext -type f -name "*.c" | xargs rm -f 75 | find rvm/gems/ruby-*/gems/*/ext -type f -name "mkmf.log" | xargs rm -f 76 | find rvm/gems/ruby-*/gems/*/ext -type f -name "Makefile" | xargs rm -f 77 | 78 | mkdir rvm/tmp 79 | 80 | exit 0 81 | -------------------------------------------------------------------------------- /codebuild/install_rvm.bash: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Installs rvm in /var/task/rvm 4 | # 5 | curl -sSL https://get.rvm.io | bash -s stable --path /var/task/rvm 6 | -------------------------------------------------------------------------------- /codebuild/rvmrc: -------------------------------------------------------------------------------- 1 | rvm_tmp_path=/tmp/rvm/tmp -------------------------------------------------------------------------------- /lambda_function.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | 3 | import os 4 | import commands 5 | import datetime 6 | import boto3 7 | 8 | s3bucket = os.environ["S3BUCKET"] 9 | s3prefix = os.environ["S3PREFIX"] if "S3PREFIX" in os.environ else '' 10 | datestring = datetime.datetime.now().strftime("%Y-%m-%d") 11 | 12 | def lambda_handler(event, context): 13 | s3 = boto3.resource('s3') 14 | print(commands.getstatusoutput('./roadwork -e -o /tmp/Roadworker.rb')) 15 | key = '%s%s_Roadworker.rb' % (s3prefix, datestring) 16 | print("Uploading to: %s" % key) 17 | s3.Object(s3bucket, key).upload_file('/tmp/Roadworker.rb') 18 | backup_size = os.path.getsize("/tmp/Roadworker.rb") 19 | print("Route53BackupSize:%d" % backup_size) 20 | -------------------------------------------------------------------------------- /roadwork: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$LAMBDA_TASK_ROOT/rvm/usr/lib 5 | 6 | source "$LAMBDA_TASK_ROOT/rvm/scripts/rvm" 7 | 8 | rvm use 2.3 --quiet 9 | 10 | exec roadwork $* 11 | -------------------------------------------------------------------------------- /tf/.gitignore: -------------------------------------------------------------------------------- 1 | codebuild-project.json 2 | -------------------------------------------------------------------------------- /tf/README.md: -------------------------------------------------------------------------------- 1 | aws codebuild create-project --cli-input-json file://codebuild-project.json 2 | 3 | aws codebuild start-build --project-name lambda-roadworker 4 | -------------------------------------------------------------------------------- /tf/codebuild-project.json.tpl: -------------------------------------------------------------------------------- 1 | { 2 | "name": "lambda-roadworker", 3 | "description": "Building lambda-roadworker source from github repo", 4 | "source": { 5 | "type": "GITHUB", 6 | "location": "https://github.com/dashsoftaps/lambda-roadworker.git" 7 | }, 8 | "artifacts": { 9 | "type": "S3", 10 | "location": "${s3bucketname}", 11 | "namespaceType": "NONE", 12 | "name": "LambdaRoadworker.zip", 13 | "packaging": "ZIP" 14 | }, 15 | "environment": { 16 | "type": "LINUX_CONTAINER", 17 | "image": "${codebuild_image}", 18 | "computeType": "BUILD_GENERAL1_SMALL", 19 | "environmentVariables": [] 20 | }, 21 | "serviceRole": "LambdaRoadworkerCodebuildRole", 22 | "timeoutInMinutes": 30, 23 | "tags": [] 24 | } 25 | -------------------------------------------------------------------------------- /tf/codebuild.tf: -------------------------------------------------------------------------------- 1 | # 2 | # Codebuild resources 3 | # 4 | 5 | provider "aws" { 6 | region = "${var.region}" 7 | } 8 | 9 | resource "aws_s3_bucket" "backupbucket" { 10 | bucket = "${var.s3bucketname}" 11 | 12 | versioning { 13 | enabled = true 14 | } 15 | 16 | lifecycle_rule { 17 | id = "route53backups" 18 | prefix = "${var.s3prefix}/" 19 | enabled = true 20 | 21 | noncurrent_version_expiration { 22 | days = 30 23 | } 24 | 25 | expiration { 26 | days = 366 27 | } 28 | } 29 | 30 | tags { 31 | Name = "Route53BackupBucket" 32 | Description = "Backup bucket for Route53 using github.com/winebarrel/roadworker - utilized by lambda function" 33 | } 34 | } 35 | 36 | data "template_file" "project-json" { 37 | template = "${file("${path.module}/codebuild-project.json.tpl")}" 38 | 39 | vars { 40 | s3bucketname = "${var.s3bucketname}" 41 | codebuild_image = "${var.codebuild_image}" 42 | } 43 | } 44 | 45 | resource "null_resource" "local" { 46 | triggers { 47 | template = "${data.template_file.project-json.rendered}" 48 | } 49 | 50 | provisioner "local-exec" { 51 | command = "echo '${data.template_file.project-json.rendered}' > ${var.filename}" 52 | } 53 | } 54 | 55 | resource "aws_iam_role" "codebuild" { 56 | name = "LambdaRoadworkerCodebuildRole" 57 | assume_role_policy = <