├── .gitignore ├── .rspec ├── .rubocop.yml ├── .travis.yml ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── Gemfile ├── Guardfile ├── LICENSE ├── README.md ├── Rakefile ├── bin └── terraforming ├── contrib └── zsh-completion │ └── _terraforming ├── lib ├── terraforming.rb └── terraforming │ ├── cli.rb │ ├── resource │ ├── alb.rb │ ├── auto_scaling_group.rb │ ├── cloud_watch_alarm.rb │ ├── db_parameter_group.rb │ ├── db_security_group.rb │ ├── db_subnet_group.rb │ ├── dynamo_db.rb │ ├── ec2.rb │ ├── efs_file_system.rb │ ├── eip.rb │ ├── elasti_cache_cluster.rb │ ├── elasti_cache_subnet_group.rb │ ├── elb.rb │ ├── iam_group.rb │ ├── iam_group_membership.rb │ ├── iam_group_policy.rb │ ├── iam_instance_profile.rb │ ├── iam_policy.rb │ ├── iam_policy_attachment.rb │ ├── iam_role.rb │ ├── iam_role_policy.rb │ ├── iam_user.rb │ ├── iam_user_policy.rb │ ├── internet_gateway.rb │ ├── kms_alias.rb │ ├── kms_key.rb │ ├── launch_configuration.rb │ ├── nat_gateway.rb │ ├── network_acl.rb │ ├── network_interface.rb │ ├── rds.rb │ ├── redshift.rb │ ├── route53_record.rb │ ├── route53_zone.rb │ ├── route_table.rb │ ├── route_table_association.rb │ ├── s3.rb │ ├── security_group.rb │ ├── sns_topic.rb │ ├── sns_topic_subscription.rb │ ├── sqs.rb │ ├── subnet.rb │ ├── vpc.rb │ └── vpn_gateway.rb │ ├── template │ └── tf │ │ ├── alb.erb │ │ ├── auto_scaling_group.erb │ │ ├── cloud_watch_alarm.erb │ │ ├── db_parameter_group.erb │ │ ├── db_security_group.erb │ │ ├── db_subnet_group.erb │ │ ├── dynamo_db.erb │ │ ├── ec2.erb │ │ ├── eip.erb │ │ ├── elasti_cache_cluster.erb │ │ ├── elasti_cache_subnet_group.erb │ │ ├── elastic_file_system.erb │ │ ├── elb.erb │ │ ├── iam_group.erb │ │ ├── iam_group_membership.erb │ │ ├── iam_group_policy.erb │ │ ├── iam_instance_profile.erb │ │ ├── iam_policy.erb │ │ ├── iam_policy_attachment.erb │ │ ├── iam_role.erb │ │ ├── iam_role_policy.erb │ │ ├── iam_user.erb │ │ ├── iam_user_policy.erb │ │ ├── internet_gateway.erb │ │ ├── kms_alias.erb │ │ ├── kms_key.erb │ │ ├── launch_configuration.erb │ │ ├── nat_gateway.erb │ │ ├── network_acl.erb │ │ ├── network_interface.erb │ │ ├── rds.erb │ │ ├── redshift.erb │ │ ├── route53_record.erb │ │ ├── route53_zone.erb │ │ ├── route_table.erb │ │ ├── route_table_association.erb │ │ ├── s3.erb │ │ ├── security_group.erb │ │ ├── sns_topic.erb │ │ ├── sns_topic_subscription.erb │ │ ├── sqs.erb │ │ ├── subnet.erb │ │ ├── vpc.erb │ │ └── vpn_gateway.erb │ ├── util.rb │ └── version.rb ├── script ├── console ├── generate └── setup ├── spec ├── fixtures │ └── terraform.tfstate ├── lib │ ├── terraforming │ │ ├── cli_spec.rb │ │ └── resource │ │ │ ├── alb_spec.rb │ │ │ ├── auto_scaling_group_spec.rb │ │ │ ├── cloud_watch_alarm_spec.rb │ │ │ ├── db_parameter_group_spec.rb │ │ │ ├── db_security_group_spec.rb │ │ │ ├── db_subnet_group_spec.rb │ │ │ ├── dynamo_db_spec.rb │ │ │ ├── ec2_spec.rb │ │ │ ├── efs_file_system_spec.rb │ │ │ ├── eip_spec.rb │ │ │ ├── elasti_cache_cluster_spec.rb │ │ │ ├── elasti_cache_subnet_group_spec.rb │ │ │ ├── elb_spec.rb │ │ │ ├── iam_group_membership_spec.rb │ │ │ ├── iam_group_policy_spec.rb │ │ │ ├── iam_group_spec.rb │ │ │ ├── iam_instance_profile_spec.rb │ │ │ ├── iam_policy_attachment_spec.rb │ │ │ ├── iam_policy_spec.rb │ │ │ ├── iam_role_policy_spec.rb │ │ │ ├── iam_role_spec.rb │ │ │ ├── iam_user_policy_spec.rb │ │ │ ├── iam_user_spec.rb │ │ │ ├── internet_gateway_spec.rb │ │ │ ├── kms_alias_spec.rb │ │ │ ├── kms_key_spec.rb │ │ │ ├── launch_configuration_spec.rb │ │ │ ├── nat_gateway_spec.rb │ │ │ ├── network_acl_spec.rb │ │ │ ├── network_interface_spec.rb │ │ │ ├── rds_spec.rb │ │ │ ├── redshift_spec.rb │ │ │ ├── route53_record_spec.rb │ │ │ ├── route53_zone_spec.rb │ │ │ ├── route_table_association_spec.rb │ │ │ ├── route_table_spec.rb │ │ │ ├── s3_spec.rb │ │ │ ├── security_group_spec.rb │ │ │ ├── sns_topic_spec.rb │ │ │ ├── sns_topic_subscription_spec.rb │ │ │ ├── sqs_spec.rb │ │ │ ├── subnet_spec.rb │ │ │ ├── vpc_spec.rb │ │ │ └── vpn_gateway_spec.rb │ └── terraforming_spec.rb └── spec_helper.rb ├── templates ├── resource.erb.erb ├── resource.rb.erb └── resource_spec.rb.erb └── terraforming.gemspec /.gitignore: -------------------------------------------------------------------------------- 1 | /.bundle/ 2 | /.yardoc 3 | /Gemfile.lock 4 | /_yardoc/ 5 | /coverage/ 6 | /doc/ 7 | /pkg/ 8 | /spec/reports/ 9 | /tmp/ 10 | -------------------------------------------------------------------------------- /.rspec: -------------------------------------------------------------------------------- 1 | --format doc 2 | --color 3 | -------------------------------------------------------------------------------- /.rubocop.yml: -------------------------------------------------------------------------------- 1 | Metrics/AbcSize: 2 | Enabled: false 3 | 4 | Metrics/ClassLength: 5 | Enabled: false 6 | 7 | Metrics/CyclomaticComplexity: 8 | Enabled: false 9 | 10 | Metrics/LineLength: 11 | Max: 140 12 | Exclude: 13 | - "spec/**/*" 14 | 15 | # Offense count: 42 16 | # Configuration parameters: CountComments. 17 | Metrics/MethodLength: 18 | Enabled: false 19 | 20 | Metrics/ModuleLength: 21 | Enabled: false 22 | 23 | Style/BracesAroundHashParameters: 24 | Enabled: false 25 | 26 | Style/Documentation: 27 | Enabled: false 28 | 29 | Style/EachWithObject: 30 | Enabled: false 31 | 32 | Style/HashSyntax: 33 | Exclude: 34 | - 'Rakefile' 35 | 36 | # TODO: check again 37 | Style/IndentArray: 38 | Enabled: false 39 | 40 | # TODO: check again 41 | Style/IndentHash: 42 | Enabled: false 43 | 44 | Style/LineEndConcatenation: 45 | Enabled: false 46 | 47 | Style/MutableConstant: 48 | Enabled: false 49 | 50 | Style/NumericLiterals: 51 | Enabled: false 52 | 53 | Style/ParallelAssignment: 54 | Enabled: false 55 | 56 | Style/RedundantSelf: 57 | Enabled: false 58 | 59 | # TODO: check again (force to %r literal) 60 | Style/RegexpLiteral: 61 | Enabled: true 62 | 63 | Style/StringLiterals: 64 | Enabled: false 65 | 66 | Style/SymbolProc: 67 | Enabled: false 68 | 69 | Style/TrailingCommaInLiteral: 70 | Enabled: false 71 | 72 | Style/UnneededPercentQ: 73 | Enabled: false 74 | 75 | Style/CollectionMethods: 76 | PreferredMethods: 77 | collect: "map" 78 | collect!: "map!" 79 | inject: "inject" 80 | detect: "find" 81 | find_all: "select" 82 | 83 | Style/PerlBackrefs: 84 | Enabled: false 85 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: ruby 2 | rvm: 3 | # https://www.ruby-lang.org/en/downloads/branches/ 4 | - 2.6 5 | - 2.5 6 | - 2.4 7 | # macOS system Ruby is Ruby 2.3 8 | - 2.3 9 | env: 10 | matrix: 11 | - OJ=0 12 | - OJ=1 13 | branches: 14 | only: 15 | - master 16 | before_script: 17 | - if [[ $OJ -eq 1 ]]; then gem install oj; fi 18 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Code of Conduct 2 | 3 | As contributors and maintainers of this project, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities. 4 | 5 | We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, age, or religion. 6 | 7 | Examples of unacceptable behavior by participants include the use of sexual language or imagery, derogatory comments or personal attacks, trolling, public or private harassment, insults, or other unprofessional conduct. 8 | 9 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct. Project maintainers who do not follow the Code of Conduct may be removed from the project team. 10 | 11 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by opening an issue or contacting one or more of the project maintainers. 12 | 13 | This Code of Conduct is adapted from the [Contributor Covenant](http:contributor-covenant.org), version 1.0.0, available at [http://contributor-covenant.org/version/1/0/0/](http://contributor-covenant.org/version/1/0/0/) 14 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | I love pull requests from everyone! By the way, I have a favor to ask you with your contribution :bow: 4 | 5 | ## Reporting issue 6 | 7 | - Please write your ... 8 | - platform (macOS, Linux, Windows, ...) 9 | - Ruby version 10 | - Terraforming version 11 | - Terraform version (if `terraform plan` failed) 12 | - executed command and error message (if any) 13 | 14 | ## Making changes 15 | 16 | - Currently, this gem supports only __AWS__ resources. Other providers are supported as separated gems. 17 | - Datadog: [terraforming-datadog](https://github.com/dtan4/terraforming-datadog) 18 | - DNSimple: [terraforming-dnsimple](https://github.com/dtan4/terraforming-dnsimple) 19 | - Do not bump gem version in your pull request. 20 | - Please follow the coding style of _existing_ code. Most of trivial rules can be checked by [RuboCop](https://github.com/bbatsov/rubocop) ([`rubocop.yml`](https://github.com/dtan4/terraforming/blob/master/.rubocop.yml)). 21 | - Coding style is checked automatically by [SideCI](https://sideci.com) right after creating pull request. If there is error, SideCI comments at the point error occured. 22 | - Please write tests for your changes. All tests are written with [RSpec](http://rspec.info/). 23 | 24 | ## Adding new resource 25 | 26 | - Class name must match to Terraforming's resource name without `aws_` prefix, and be a complete resource name. 27 | - e.g. `aws_iam_group_membership`: `IAMGroupMembership` 28 | - Yes, I know that some of resources I added a long ago don't follow to this rule... 29 | - File name must also match to Terraforming's resource name without `aws_` prefix. 30 | - e.g. `aws_iam_group_membership`: `iam_group_membership.rb` 31 | - Command name should be abbreviation. 32 | - e.g. `aws_iam_group_membership`: `iamgp` 33 | - Please check generation result by executing `terraform plan` with real resources. There should be NO diff with generated `.tf` and `.tfstate`. 34 | 35 | `script/generate` generates new resource code / test skeletons. 36 | 37 | ```bash 38 | $ script/generate ec2 39 | ==> Generate ec2.rb 40 | ==> Generate ec2_spec.rb 41 | ==> Generate ec2.erb 42 | 43 | Add below code by hand. 44 | 45 | lib/terraforming.rb: 46 | 47 | require "terraforming/resource/ec2" 48 | 49 | lib/terraforming/cli.rb: 50 | 51 | module Terraforming 52 | class CLI < Thor 53 | 54 | # Subcommand name should be acronym. 55 | desc "ec2", "Ec2" 56 | def ec2 57 | execute(Terraforming::Resource::Ec2, options) 58 | end 59 | 60 | spec/lib/terraforming/cli_spec.rb: 61 | 62 | module Terraforming 63 | describe CLI do 64 | context "resources" do 65 | describe "ec2" do 66 | let(:klass) { Terraforming::Resource::Ec2 67 | let(:command) { :ec2 } 68 | 69 | it_behaves_like "CLI examples" 70 | end 71 | ``` 72 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | # Specify your gem's dependencies in terraforming.gemspec 4 | gemspec 5 | 6 | group :development do 7 | gem "guard" 8 | gem "guard-rspec" 9 | 10 | if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new("2.2.0") 11 | gem "listen", "~> 3.1.0" 12 | else 13 | gem "listen", "< 3.1.0" 14 | end 15 | 16 | gem "rubocop" 17 | 18 | gem "terminal-notifier-guard" 19 | end 20 | -------------------------------------------------------------------------------- /Guardfile: -------------------------------------------------------------------------------- 1 | guard :rspec, cmd: "bundle exec rspec" do 2 | require "guard/rspec/dsl" 3 | dsl = Guard::RSpec::Dsl.new(self) 4 | 5 | rspec = dsl.rspec 6 | watch(rspec.spec_helper) { rspec.spec_dir } 7 | watch(rspec.spec_support) { rspec.spec_dir } 8 | watch(rspec.spec_files) 9 | 10 | ruby = dsl.ruby 11 | dsl.watch_spec_files_for(ruby.lib_files) 12 | end 13 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015-2016 Daisuke Fujita 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require "bundler/gem_tasks" 2 | require "rspec/core/rake_task" 3 | 4 | RSpec::Core::RakeTask.new(:spec) 5 | 6 | task :default => :spec 7 | -------------------------------------------------------------------------------- /bin/terraforming: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | require "terraforming" 4 | 5 | Terraforming::CLI.start(ARGV) 6 | -------------------------------------------------------------------------------- /contrib/zsh-completion/_terraforming: -------------------------------------------------------------------------------- 1 | #compdef terraforming 2 | 3 | function _terraforming() { 4 | local context curcontext=$curcontext state line 5 | typeset -A opt_args 6 | local ret=1 7 | 8 | _arguments -C \ 9 | '1: :__terraforming_sub_commands' \ 10 | '*:: :->args' \ 11 | && ret=0 12 | 13 | case $state in 14 | (args) 15 | case $words[1] in 16 | (help) 17 | _arguments -C \ 18 | '1: :__terraforming_sub_commands' \ 19 | '(-)*:: :->null_state' \ 20 | && ret=0 21 | ;; 22 | (*) 23 | _arguments -C \ 24 | '--merge=[(TFSTATE) tfstate file to merge]:tfstate file to merge:_files' \ 25 | '--overwrite[Overwrite existing tfstate]' \ 26 | '--no-overwrite[Do not overwrite existing tfstate]' \ 27 | '--tfstate[Generate tfstate]' \ 28 | '--no-tfstate[Do not generate tfstate]' \ 29 | '--profile[(PROFILE) AWS credentials profile]:AWS credentials profile:__profiles' \ 30 | && ret=0 31 | ;; 32 | esac 33 | ;; 34 | esac 35 | 36 | return ret 37 | } 38 | 39 | __terraforming_sub_commands() { 40 | local -a _c 41 | 42 | _c=( 43 | "${(@f)$(terraforming --help \ 44 | | grep ' terraforming' \ 45 | | sed -E 's/^ terraforming //g' \ 46 | | sed -E 's/ *(\[COMMAND\])? *# /:/g')}" 47 | ) 48 | 49 | _describe -t commands terraforming_sub_commands _c 50 | } 51 | 52 | __profiles() { 53 | local _profile_path="${HOME}/.aws/credentials" 54 | local -a _profiles 55 | 56 | _profiles=( 57 | ${(@f)"$(_call_program profiles \ 58 | "grep -E '^\[.*\]$' "$_profile_path" \ 59 | | sed -e 's/\[//' -e 's/\]//'")"} 60 | ) 61 | 62 | _describe -t profiles Profiles _profiles 63 | } 64 | 65 | _terraforming "$@" 66 | -------------------------------------------------------------------------------- /lib/terraforming.rb: -------------------------------------------------------------------------------- 1 | require "aws-sdk-autoscaling" 2 | require "aws-sdk-cloudwatch" 3 | require "aws-sdk-dynamodb" 4 | require "aws-sdk-ec2" 5 | require "aws-sdk-efs" 6 | require "aws-sdk-elasticache" 7 | require "aws-sdk-elasticloadbalancing" 8 | require "aws-sdk-elasticloadbalancingv2" 9 | require "aws-sdk-iam" 10 | require "aws-sdk-kms" 11 | require "aws-sdk-rds" 12 | require "aws-sdk-redshift" 13 | require "aws-sdk-route53" 14 | require "aws-sdk-s3" 15 | require "aws-sdk-sns" 16 | require "aws-sdk-sqs" 17 | 18 | require "erb" 19 | require "multi_json" 20 | require "thor" 21 | require "zlib" 22 | 23 | require "terraforming/util" 24 | require "terraforming/version" 25 | 26 | require "terraforming/cli" 27 | require "terraforming/resource/alb" 28 | require "terraforming/resource/auto_scaling_group" 29 | require "terraforming/resource/cloud_watch_alarm" 30 | require "terraforming/resource/db_parameter_group" 31 | require "terraforming/resource/db_security_group" 32 | require "terraforming/resource/db_subnet_group" 33 | require "terraforming/resource/dynamo_db" 34 | require "terraforming/resource/ec2" 35 | require "terraforming/resource/eip" 36 | require "terraforming/resource/elasti_cache_cluster" 37 | require "terraforming/resource/elasti_cache_subnet_group" 38 | require "terraforming/resource/efs_file_system" 39 | require "terraforming/resource/elb" 40 | require "terraforming/resource/iam_group" 41 | require "terraforming/resource/iam_group_membership" 42 | require "terraforming/resource/iam_group_policy" 43 | require "terraforming/resource/iam_instance_profile" 44 | require "terraforming/resource/iam_policy" 45 | require "terraforming/resource/iam_policy_attachment" 46 | require "terraforming/resource/iam_role" 47 | require "terraforming/resource/iam_role_policy" 48 | require "terraforming/resource/iam_user" 49 | require "terraforming/resource/iam_user_policy" 50 | require "terraforming/resource/kms_alias" 51 | require "terraforming/resource/kms_key" 52 | require "terraforming/resource/launch_configuration" 53 | require "terraforming/resource/internet_gateway" 54 | require "terraforming/resource/nat_gateway" 55 | require "terraforming/resource/network_acl" 56 | require "terraforming/resource/network_interface" 57 | require "terraforming/resource/rds" 58 | require "terraforming/resource/redshift" 59 | require "terraforming/resource/route_table" 60 | require "terraforming/resource/route_table_association" 61 | require "terraforming/resource/route53_record" 62 | require "terraforming/resource/route53_zone" 63 | require "terraforming/resource/s3" 64 | require "terraforming/resource/security_group" 65 | require "terraforming/resource/subnet" 66 | require "terraforming/resource/sqs" 67 | require "terraforming/resource/vpc" 68 | require "terraforming/resource/vpn_gateway" 69 | require "terraforming/resource/sns_topic" 70 | require "terraforming/resource/sns_topic_subscription" 71 | -------------------------------------------------------------------------------- /lib/terraforming/resource/alb.rb: -------------------------------------------------------------------------------- 1 | module Terraforming 2 | module Resource 3 | class ALB 4 | include Terraforming::Util 5 | 6 | def self.tf(client: Aws::ElasticLoadBalancingV2::Client.new) 7 | self.new(client).tf 8 | end 9 | 10 | def self.tfstate(client: Aws::ElasticLoadBalancingV2::Client.new) 11 | self.new(client).tfstate 12 | end 13 | 14 | def initialize(client) 15 | @client = client 16 | end 17 | 18 | def tf 19 | apply_template(@client, "tf/alb") 20 | end 21 | 22 | def tfstate 23 | load_balancers.inject({}) do |resources, load_balancer| 24 | load_balancer_attributes = load_balancer_attributes_of(load_balancer) 25 | attributes = { 26 | "dns_name" => load_balancer.dns_name, 27 | "enable_deletion_protection" => load_balancer_attributes["deletion_protection.enabled"].to_s, 28 | "id" => load_balancer.load_balancer_arn, 29 | "idle_timeout" => load_balancer_attributes["idle_timeout.timeout_seconds"].to_s, 30 | "internal" => internal?(load_balancer).to_s, 31 | "name" => load_balancer.load_balancer_name, 32 | "security_groups.#" => load_balancer.security_groups.length.to_s, 33 | "subnets.#" => load_balancer.availability_zones.length.to_s, 34 | "zone_id" => load_balancer.canonical_hosted_zone_id, 35 | } 36 | 37 | attributes.merge!(access_logs_attributes_of(load_balancer_attributes)) 38 | attributes.merge!(tag_attributes_of(load_balancer)) 39 | 40 | resources["aws_alb.#{module_name_of(load_balancer)}"] = { 41 | "type" => "aws_alb", 42 | "primary" => { 43 | "id" => load_balancer.load_balancer_arn, 44 | "attributes" => attributes 45 | } 46 | } 47 | 48 | resources 49 | end 50 | end 51 | 52 | private 53 | 54 | def access_logs_attributes_of(load_balancer_attributes) 55 | { 56 | "access_logs.#" => "1", 57 | "access_logs.0.bucket" => load_balancer_attributes["access_logs.s3.bucket"], 58 | "access_logs.0.enabled" => load_balancer_attributes["access_logs.s3.enabled"].to_s, 59 | "access_logs.0.prefix" => load_balancer_attributes["access_logs.s3.prefix"], 60 | } 61 | end 62 | 63 | def internal?(load_balancer) 64 | load_balancer.scheme == "internal" 65 | end 66 | 67 | def load_balancers 68 | @client.describe_load_balancers.load_balancers 69 | end 70 | 71 | def load_balancer_attributes_of(load_balancer) 72 | @client.describe_load_balancer_attributes(load_balancer_arn: load_balancer.load_balancer_arn).attributes.inject({}) do |result, attribute| 73 | result[attribute.key] = attribute.value 74 | result 75 | end 76 | end 77 | 78 | def module_name_of(load_balancer) 79 | normalize_module_name(load_balancer.load_balancer_name) 80 | end 81 | 82 | def tag_attributes_of(load_balancer) 83 | tags = tags_of(load_balancer) 84 | attributes = { "tags.%" => tags.length.to_s } 85 | 86 | tags.each do |tag| 87 | attributes["tags.#{tag.key}"] = tag.value 88 | end 89 | 90 | attributes 91 | end 92 | 93 | def tags_of(load_balancer) 94 | @client.describe_tags(resource_arns: [load_balancer.load_balancer_arn]).tag_descriptions.first.tags 95 | end 96 | end 97 | end 98 | end 99 | -------------------------------------------------------------------------------- /lib/terraforming/resource/auto_scaling_group.rb: -------------------------------------------------------------------------------- 1 | module Terraforming 2 | module Resource 3 | class AutoScalingGroup 4 | include Terraforming::Util 5 | 6 | def self.tf(client: Aws::AutoScaling::Client.new) 7 | self.new(client).tf 8 | end 9 | 10 | def self.tfstate(client: Aws::AutoScaling::Client.new) 11 | self.new(client).tfstate 12 | end 13 | 14 | def initialize(client) 15 | @client = client 16 | end 17 | 18 | def tf 19 | apply_template(@client, "tf/auto_scaling_group") 20 | end 21 | 22 | def tfstate 23 | auto_scaling_groups.inject({}) do |resources, group| 24 | vpc_zone_specified = vpc_zone_specified?(group) 25 | 26 | attributes = { 27 | "availability_zones.#" => vpc_zone_specified ? "0" : group.availability_zones.length.to_s, 28 | "default_cooldown" => "300", 29 | "desired_capacity" => group.desired_capacity.to_s, 30 | "health_check_grace_period" => group.health_check_grace_period.to_s, 31 | "health_check_type" => group.health_check_type, 32 | "id" => group.auto_scaling_group_name, 33 | "launch_configuration" => group.launch_configuration_name, 34 | "load_balancers.#" => "0", 35 | "max_size" => group.max_size.to_s, 36 | "min_size" => group.min_size.to_s, 37 | "name" => group.auto_scaling_group_name, 38 | "tag.#" => group.tags.length.to_s, 39 | "termination_policies.#" => "0", 40 | "vpc_zone_identifier.#" => vpc_zone_specified ? vpc_zone_identifier_of(group).length.to_s : "0", 41 | } 42 | 43 | group.tags.each do |tag| 44 | hashcode = tag_hashcode_of(tag) 45 | attributes.merge!({ 46 | "tag.#{hashcode}.key" => tag.key, 47 | "tag.#{hashcode}.propagate_at_launch" => tag.propagate_at_launch.to_s, 48 | "tag.#{hashcode}.value" => tag.value, 49 | }) 50 | end 51 | 52 | resources["aws_autoscaling_group.#{module_name_of(group)}"] = { 53 | "type" => "aws_autoscaling_group", 54 | "primary" => { 55 | "id" => group.auto_scaling_group_name, 56 | "attributes" => attributes, 57 | "meta" => { 58 | "schema_version" => "1" 59 | } 60 | } 61 | } 62 | 63 | resources 64 | end 65 | end 66 | 67 | private 68 | 69 | def auto_scaling_groups 70 | @client.describe_auto_scaling_groups.map(&:auto_scaling_groups).flatten 71 | end 72 | 73 | def module_name_of(group) 74 | normalize_module_name(group.auto_scaling_group_name) 75 | end 76 | 77 | def tag_hashcode_of(tag) 78 | Zlib.crc32("#{tag.key}-#{tag.value}-#{tag.propagate_at_launch}-") 79 | end 80 | 81 | def vpc_zone_identifier_of(group) 82 | group.vpc_zone_identifier.split(",") 83 | end 84 | 85 | def vpc_zone_specified?(group) 86 | group.vpc_zone_identifier && !vpc_zone_identifier_of(group).empty? 87 | end 88 | end 89 | end 90 | end 91 | -------------------------------------------------------------------------------- /lib/terraforming/resource/cloud_watch_alarm.rb: -------------------------------------------------------------------------------- 1 | module Terraforming 2 | module Resource 3 | class CloudWatchAlarm 4 | include Terraforming::Util 5 | 6 | def self.tf(client: Aws::CloudWatch::Client.new) 7 | self.new(client).tf 8 | end 9 | 10 | def self.tfstate(client: Aws::CloudWatch::Client.new) 11 | self.new(client).tfstate 12 | end 13 | 14 | def initialize(client) 15 | @client = client 16 | end 17 | 18 | def tf 19 | apply_template(@client, "tf/cloud_watch_alarm") 20 | end 21 | 22 | def tfstate 23 | alarms.inject({}) do |resources, alarm| 24 | resources["aws_cloudwatch_metric_alarm.#{module_name_of(alarm)}"] = { 25 | "type" => "aws_cloudwatch_metric_alarm", 26 | "primary" => { 27 | "id" => alarm.alarm_name, 28 | "attributes" => alarm_attributes(alarm) 29 | } 30 | } 31 | resources 32 | end 33 | end 34 | 35 | private 36 | 37 | def alarm_attributes(alarm) 38 | attributes = { 39 | "actions_enabled" => alarm.actions_enabled.to_s, 40 | "alarm_description" => sanitize(alarm.alarm_description), 41 | "alarm_name" => alarm.alarm_name, 42 | "comparison_operator" => alarm.comparison_operator, 43 | "evaluation_periods" => alarm.evaluation_periods.to_s, 44 | "id" => alarm.alarm_name, 45 | "metric_name" => alarm.metric_name, 46 | "namespace" => alarm.namespace, 47 | "period" => alarm.period.to_s, 48 | "statistic" => alarm.statistic, 49 | "threshold" => alarm.threshold.to_s, 50 | "unit" => sanitize(alarm.unit) 51 | } 52 | add_checksummed_attributes(attributes, alarm) 53 | end 54 | 55 | def alarms 56 | @client.describe_alarms.map(&:metric_alarms).flatten 57 | end 58 | 59 | def module_name_of(alarm) 60 | normalize_module_name(alarm.alarm_name) 61 | end 62 | 63 | def sanitize(argument) 64 | argument.nil? ? "" : argument 65 | end 66 | 67 | def add_checksummed_attributes(attributes, alarm) 68 | %w(insufficient_data_actions alarm_actions ok_actions dimensions).each do |action| 69 | attribute = alarm.send(action.to_sym) 70 | attributes["#{action}.#"] = attribute.size.to_s 71 | attribute.each do |attr| 72 | if attr.is_a? String 73 | checksum = Zlib.crc32(attr) 74 | value = attr 75 | else 76 | checksum = attr.name 77 | value = attr.value 78 | end 79 | attributes["#{action}.#{checksum}"] = value 80 | end 81 | end 82 | 83 | attributes 84 | end 85 | end 86 | end 87 | end 88 | -------------------------------------------------------------------------------- /lib/terraforming/resource/db_parameter_group.rb: -------------------------------------------------------------------------------- 1 | module Terraforming 2 | module Resource 3 | class DBParameterGroup 4 | include Terraforming::Util 5 | 6 | def self.tf(client: Aws::RDS::Client.new) 7 | self.new(client).tf 8 | end 9 | 10 | def self.tfstate(client: Aws::RDS::Client.new) 11 | self.new(client).tfstate 12 | end 13 | 14 | def initialize(client) 15 | @client = client 16 | end 17 | 18 | def tf 19 | apply_template(@client, "tf/db_parameter_group") 20 | end 21 | 22 | def tfstate 23 | db_parameter_groups.inject({}) do |resources, parameter_group| 24 | attributes = { 25 | "description" => parameter_group.description, 26 | "family" => parameter_group.db_parameter_group_family, 27 | "id" => parameter_group.db_parameter_group_name, 28 | "name" => parameter_group.db_parameter_group_name, 29 | "parameter.#" => db_parameters_in(parameter_group).length.to_s 30 | } 31 | resources["aws_db_parameter_group.#{module_name_of(parameter_group)}"] = { 32 | "type" => "aws_db_parameter_group", 33 | "primary" => { 34 | "id" => parameter_group.db_parameter_group_name, 35 | "attributes" => attributes 36 | } 37 | } 38 | 39 | resources 40 | end 41 | end 42 | 43 | private 44 | 45 | def db_parameter_groups 46 | @client.describe_db_parameter_groups.map(&:db_parameter_groups).flatten 47 | end 48 | 49 | def db_parameters_in(parameter_group) 50 | @client.describe_db_parameters(db_parameter_group_name: parameter_group.db_parameter_group_name).map(&:parameters).flatten 51 | end 52 | 53 | def module_name_of(parameter_group) 54 | normalize_module_name(parameter_group.db_parameter_group_name) 55 | end 56 | end 57 | end 58 | end 59 | -------------------------------------------------------------------------------- /lib/terraforming/resource/db_security_group.rb: -------------------------------------------------------------------------------- 1 | module Terraforming 2 | module Resource 3 | class DBSecurityGroup 4 | include Terraforming::Util 5 | 6 | def self.tf(client: Aws::RDS::Client.new) 7 | self.new(client).tf 8 | end 9 | 10 | def self.tfstate(client: Aws::RDS::Client.new) 11 | self.new(client).tfstate 12 | end 13 | 14 | def initialize(client) 15 | @client = client 16 | end 17 | 18 | def tf 19 | apply_template(@client, "tf/db_security_group") 20 | end 21 | 22 | def tfstate 23 | db_security_groups.inject({}) do |resources, security_group| 24 | attributes = { 25 | "db_subnet_group_name" => security_group.db_security_group_name, 26 | "id" => security_group.db_security_group_name, 27 | "ingress.#" => ingresses_of(security_group).length.to_s, 28 | "name" => security_group.db_security_group_name, 29 | } 30 | resources["aws_db_security_group.#{module_name_of(security_group)}"] = { 31 | "type" => "aws_db_security_group", 32 | "primary" => { 33 | "id" => security_group.db_security_group_name, 34 | "attributes" => attributes 35 | } 36 | } 37 | 38 | resources 39 | end 40 | end 41 | 42 | private 43 | 44 | def ingresses_of(security_group) 45 | security_group.ec2_security_groups + security_group.ip_ranges 46 | end 47 | 48 | def db_security_groups 49 | @client.describe_db_security_groups.map(&:db_security_groups).flatten.select { |sg| !ingresses_of(sg).empty? } 50 | end 51 | 52 | def module_name_of(security_group) 53 | normalize_module_name(security_group.db_security_group_name) 54 | end 55 | end 56 | end 57 | end 58 | -------------------------------------------------------------------------------- /lib/terraforming/resource/db_subnet_group.rb: -------------------------------------------------------------------------------- 1 | module Terraforming 2 | module Resource 3 | class DBSubnetGroup 4 | include Terraforming::Util 5 | 6 | def self.tf(client: Aws::RDS::Client.new) 7 | self.new(client).tf 8 | end 9 | 10 | def self.tfstate(client: Aws::RDS::Client.new) 11 | self.new(client).tfstate 12 | end 13 | 14 | def initialize(client) 15 | @client = client 16 | end 17 | 18 | def tf 19 | apply_template(@client, "tf/db_subnet_group") 20 | end 21 | 22 | def tfstate 23 | db_subnet_groups.inject({}) do |resources, subnet_group| 24 | attributes = { 25 | "description" => subnet_group.db_subnet_group_description, 26 | "name" => subnet_group.db_subnet_group_name, 27 | "subnet_ids.#" => subnet_group.subnets.length.to_s 28 | } 29 | resources["aws_db_subnet_group.#{module_name_of(subnet_group)}"] = { 30 | "type" => "aws_db_subnet_group", 31 | "primary" => { 32 | "id" => subnet_group.db_subnet_group_name, 33 | "attributes" => attributes 34 | } 35 | } 36 | 37 | resources 38 | end 39 | end 40 | 41 | private 42 | 43 | def db_subnet_groups 44 | @client.describe_db_subnet_groups.map(&:db_subnet_groups).flatten 45 | end 46 | 47 | def module_name_of(subnet_group) 48 | normalize_module_name(subnet_group.db_subnet_group_name) 49 | end 50 | end 51 | end 52 | end 53 | -------------------------------------------------------------------------------- /lib/terraforming/resource/efs_file_system.rb: -------------------------------------------------------------------------------- 1 | module Terraforming 2 | module Resource 3 | class EFSFileSystem 4 | include Terraforming::Util 5 | 6 | def self.tf(client: Aws::EFS::Client.new) 7 | self.new(client).tf 8 | end 9 | 10 | def self.tfstate(client: Aws::EFS::Client.new) 11 | self.new(client).tfstate 12 | end 13 | 14 | def initialize(client) 15 | @client = client 16 | end 17 | 18 | def tf 19 | apply_template(@client, "tf/elastic_file_system") 20 | end 21 | 22 | def tfstate 23 | file_systems.inject({}) do |resources, efs| 24 | attributes = { 25 | "creation_token" => efs.creation_token, 26 | "id" => efs.file_system_id, 27 | "performance_mode" => efs.performance_mode, 28 | "tags.%" => "1", 29 | "tags.Name" => efs.name, 30 | } 31 | 32 | resources["aws_efs_file_system.#{module_name_of(efs)}"] = { 33 | "type" => "aws_efs_file_system", 34 | "depends_on" => [], 35 | "primary" => { 36 | "id" => efs.file_system_id, 37 | "attributes" => attributes, 38 | "meta" => {}, 39 | "tainted" => false, 40 | }, 41 | "deposed" => [], 42 | "provider" => "aws", 43 | } 44 | 45 | resources 46 | end 47 | end 48 | 49 | private 50 | 51 | def file_systems 52 | @client.describe_file_systems.data.file_systems.flatten 53 | end 54 | 55 | def module_name_of(efs) 56 | normalize_module_name(efs.file_system_id) 57 | end 58 | end 59 | end 60 | end 61 | -------------------------------------------------------------------------------- /lib/terraforming/resource/eip.rb: -------------------------------------------------------------------------------- 1 | module Terraforming 2 | module Resource 3 | class EIP 4 | include Terraforming::Util 5 | 6 | def self.tf(client: Aws::EC2::Client.new) 7 | self.new(client).tf 8 | end 9 | 10 | def self.tfstate(client: Aws::EC2::Client.new) 11 | self.new(client).tfstate 12 | end 13 | 14 | def initialize(client) 15 | @client = client 16 | end 17 | 18 | def tf 19 | apply_template(@client, "tf/eip") 20 | end 21 | 22 | def tfstate 23 | eips.inject({}) do |resources, addr| 24 | attributes = { 25 | "association_id" => addr.association_id, 26 | "domain" => addr.domain, 27 | "id" => vpc?(addr) ? addr.allocation_id : addr.public_ip, 28 | "instance" => addr.instance_id, 29 | "network_interface" => addr.network_interface_id, 30 | "private_ip" => addr.private_ip_address, 31 | "public_ip" => addr.public_ip, 32 | "vpc" => vpc?(addr).to_s, 33 | } 34 | attributes.delete_if { |_k, v| v.nil? } 35 | resources["aws_eip.#{module_name_of(addr)}"] = { 36 | "type" => "aws_eip", 37 | "primary" => { 38 | "id" => vpc?(addr) ? addr.allocation_id : addr.public_ip, 39 | "attributes" => attributes 40 | } 41 | } 42 | 43 | resources 44 | end 45 | end 46 | 47 | private 48 | 49 | def eips 50 | @client.describe_addresses.map(&:addresses).flatten 51 | end 52 | 53 | def vpc?(addr) 54 | addr.domain.eql?("vpc") 55 | end 56 | 57 | def module_name_of(addr) 58 | if vpc?(addr) 59 | normalize_module_name(addr.allocation_id) 60 | else 61 | normalize_module_name(addr.public_ip) 62 | end 63 | end 64 | end 65 | end 66 | end 67 | -------------------------------------------------------------------------------- /lib/terraforming/resource/elasti_cache_cluster.rb: -------------------------------------------------------------------------------- 1 | module Terraforming 2 | module Resource 3 | class ElastiCacheCluster 4 | include Terraforming::Util 5 | 6 | def self.tf(client: Aws::ElastiCache::Client.new) 7 | self.new(client).tf 8 | end 9 | 10 | def self.tfstate(client: Aws::ElastiCache::Client.new) 11 | self.new(client).tfstate 12 | end 13 | 14 | def initialize(client) 15 | @client = client 16 | end 17 | 18 | def tf 19 | apply_template(@client, "tf/elasti_cache_cluster") 20 | end 21 | 22 | def tfstate 23 | cache_clusters.inject({}) do |resources, cache_cluster| 24 | attributes = { 25 | "cache_nodes.#" => cache_cluster.cache_nodes.length.to_s, 26 | "cluster_id" => cache_cluster.cache_cluster_id, 27 | "engine" => cache_cluster.engine, 28 | "engine_version" => cache_cluster.engine_version, 29 | "id" => cache_cluster.cache_cluster_id, 30 | "node_type" => cache_cluster.cache_node_type, 31 | "num_cache_nodes" => "1", 32 | "parameter_group_name" => cache_cluster.cache_parameter_group.cache_parameter_group_name, 33 | "security_group_ids.#" => security_group_ids_of(cache_cluster).length.to_s, 34 | "security_group_names.#" => security_group_names_of(cache_cluster).length.to_s, 35 | "subnet_group_name" => cache_cluster.cache_subnet_group_name, 36 | "tags.#" => "0", 37 | } 38 | 39 | attributes["port"] = if cache_cluster.configuration_endpoint 40 | cache_cluster.configuration_endpoint.port.to_s 41 | else 42 | cache_cluster.cache_nodes[0].endpoint.port.to_s 43 | end 44 | 45 | if cache_cluster.notification_configuration 46 | attributes["notification_topic_arn"] = cache_cluster.notification_configuration.topic_arn 47 | end 48 | 49 | resources["aws_elasticache_cluster.#{module_name_of(cache_cluster)}"] = { 50 | "type" => "aws_elasticache_cluster", 51 | "primary" => { 52 | "id" => cache_cluster.cache_cluster_id, 53 | "attributes" => attributes 54 | } 55 | } 56 | 57 | resources 58 | end 59 | end 60 | 61 | private 62 | 63 | def cache_clusters 64 | @client.describe_cache_clusters(show_cache_node_info: true).map(&:cache_clusters).flatten 65 | end 66 | 67 | def cluster_in_vpc?(cache_cluster) 68 | cache_cluster.cache_security_groups.empty? 69 | end 70 | 71 | def security_group_ids_of(cache_cluster) 72 | cache_cluster.security_groups.map { |sg| sg.security_group_id } 73 | end 74 | 75 | def security_group_names_of(cache_cluster) 76 | cache_cluster.cache_security_groups.map { |sg| sg.cache_security_group_name } 77 | end 78 | 79 | def module_name_of(cache_cluster) 80 | normalize_module_name(cache_cluster.cache_cluster_id) 81 | end 82 | end 83 | end 84 | end 85 | -------------------------------------------------------------------------------- /lib/terraforming/resource/elasti_cache_subnet_group.rb: -------------------------------------------------------------------------------- 1 | module Terraforming 2 | module Resource 3 | class ElastiCacheSubnetGroup 4 | include Terraforming::Util 5 | 6 | def self.tf(client: Aws::ElastiCache::Client.new) 7 | self.new(client).tf 8 | end 9 | 10 | def self.tfstate(client: Aws::ElastiCache::Client.new) 11 | self.new(client).tfstate 12 | end 13 | 14 | def initialize(client) 15 | @client = client 16 | end 17 | 18 | def tf 19 | apply_template(@client, "tf/elasti_cache_subnet_group") 20 | end 21 | 22 | def tfstate 23 | cache_subnet_groups.inject({}) do |resources, cache_subnet_group| 24 | attributes = { 25 | "description" => cache_subnet_group.cache_subnet_group_description, 26 | "name" => cache_subnet_group.cache_subnet_group_name, 27 | "subnet_ids.#" => subnet_ids_of(cache_subnet_group).length.to_s, 28 | } 29 | resources["aws_elasticache_subnet_group.#{module_name_of(cache_subnet_group)}"] = { 30 | "type" => "aws_elasticache_subnet_group", 31 | "primary" => { 32 | "id" => cache_subnet_group.cache_subnet_group_name, 33 | "attributes" => attributes 34 | } 35 | } 36 | 37 | resources 38 | end 39 | end 40 | 41 | private 42 | 43 | def cache_subnet_groups 44 | @client.describe_cache_subnet_groups.map(&:cache_subnet_groups).flatten 45 | end 46 | 47 | def subnet_ids_of(cache_subnet_group) 48 | cache_subnet_group.subnets.map { |sn| sn.subnet_identifier } 49 | end 50 | 51 | def module_name_of(cache_subnet_group) 52 | normalize_module_name(cache_subnet_group.cache_subnet_group_name) 53 | end 54 | end 55 | end 56 | end 57 | -------------------------------------------------------------------------------- /lib/terraforming/resource/iam_group.rb: -------------------------------------------------------------------------------- 1 | module Terraforming 2 | module Resource 3 | class IAMGroup 4 | include Terraforming::Util 5 | 6 | def self.tf(client: Aws::IAM::Client.new) 7 | self.new(client).tf 8 | end 9 | 10 | def self.tfstate(client: Aws::IAM::Client.new) 11 | self.new(client).tfstate 12 | end 13 | 14 | def initialize(client) 15 | @client = client 16 | end 17 | 18 | def tf 19 | apply_template(@client, "tf/iam_group") 20 | end 21 | 22 | def tfstate 23 | iam_groups.inject({}) do |resources, group| 24 | attributes = { 25 | "arn" => group.arn, 26 | "id" => group.group_name, 27 | "name" => group.group_name, 28 | "path" => group.path, 29 | "unique_id" => group.group_id, 30 | } 31 | resources["aws_iam_group.#{module_name_of(group)}"] = { 32 | "type" => "aws_iam_group", 33 | "primary" => { 34 | "id" => group.group_name, 35 | "attributes" => attributes 36 | } 37 | } 38 | 39 | resources 40 | end 41 | end 42 | 43 | private 44 | 45 | def iam_groups 46 | @client.list_groups.map(&:groups).flatten 47 | end 48 | 49 | def module_name_of(group) 50 | normalize_module_name(group.group_name) 51 | end 52 | end 53 | end 54 | end 55 | -------------------------------------------------------------------------------- /lib/terraforming/resource/iam_group_membership.rb: -------------------------------------------------------------------------------- 1 | module Terraforming 2 | module Resource 3 | class IAMGroupMembership 4 | include Terraforming::Util 5 | 6 | def self.tf(client: Aws::IAM::Client.new) 7 | self.new(client).tf 8 | end 9 | 10 | def self.tfstate(client: Aws::IAM::Client.new) 11 | self.new(client).tfstate 12 | end 13 | 14 | def initialize(client) 15 | @client = client 16 | end 17 | 18 | def tf 19 | apply_template(@client, "tf/iam_group_membership") 20 | end 21 | 22 | def tfstate 23 | iam_groups.inject({}) do |resources, group| 24 | membership_name = membership_name_of(group) 25 | 26 | attributes = { 27 | "group" => group.group_name, 28 | "id" => membership_name, 29 | "name" => membership_name, 30 | "users.#" => group_members_of(group).length.to_s, 31 | } 32 | resources["aws_iam_group_membership.#{module_name_of(group)}"] = { 33 | "type" => "aws_iam_group_membership", 34 | "primary" => { 35 | "id" => membership_name, 36 | "attributes" => attributes 37 | } 38 | } 39 | 40 | resources 41 | end 42 | end 43 | 44 | private 45 | 46 | def group_members_of(group) 47 | @client.get_group(group_name: group.group_name).map(&:users).flatten.map(&:user_name) 48 | end 49 | 50 | def iam_groups 51 | @client.list_groups.map(&:groups).flatten 52 | end 53 | 54 | def membership_name_of(group) 55 | "#{group.group_name}-group-membership" 56 | end 57 | 58 | def module_name_of(group) 59 | normalize_module_name(group.group_name) 60 | end 61 | end 62 | end 63 | end 64 | -------------------------------------------------------------------------------- /lib/terraforming/resource/iam_group_policy.rb: -------------------------------------------------------------------------------- 1 | module Terraforming 2 | module Resource 3 | class IAMGroupPolicy 4 | include Terraforming::Util 5 | 6 | def self.tf(client: Aws::IAM::Client.new) 7 | self.new(client).tf 8 | end 9 | 10 | def self.tfstate(client: Aws::IAM::Client.new) 11 | self.new(client).tfstate 12 | end 13 | 14 | def initialize(client) 15 | @client = client 16 | end 17 | 18 | def tf 19 | apply_template(@client, "tf/iam_group_policy") 20 | end 21 | 22 | def tfstate 23 | iam_group_policies.inject({}) do |resources, policy| 24 | attributes = { 25 | "group" => policy.group_name, 26 | "id" => iam_group_policy_id_of(policy), 27 | "name" => policy.policy_name, 28 | "policy" => prettify_policy(policy.policy_document, breakline: true, unescape: true) 29 | } 30 | resources["aws_iam_group_policy.#{unique_name(policy)}"] = { 31 | "type" => "aws_iam_group_policy", 32 | "primary" => { 33 | "id" => iam_group_policy_id_of(policy), 34 | "attributes" => attributes 35 | } 36 | } 37 | 38 | resources 39 | end 40 | end 41 | 42 | private 43 | 44 | def unique_name(policy) 45 | "#{normalize_module_name(policy.group_name)}_#{normalize_module_name(policy.policy_name)}" 46 | end 47 | 48 | def iam_group_policy_id_of(policy) 49 | "#{policy.group_name}:#{policy.policy_name}" 50 | end 51 | 52 | def iam_groups 53 | @client.list_groups.map(&:groups).flatten 54 | end 55 | 56 | def iam_group_policy_names_in(group) 57 | @client.list_group_policies(group_name: group.group_name).policy_names 58 | end 59 | 60 | def iam_group_policy_of(group, policy_name) 61 | @client.get_group_policy(group_name: group.group_name, policy_name: policy_name) 62 | end 63 | 64 | def iam_group_policies 65 | iam_groups.map do |group| 66 | iam_group_policy_names_in(group).map { |policy_name| iam_group_policy_of(group, policy_name) } 67 | end.flatten 68 | end 69 | end 70 | end 71 | end 72 | -------------------------------------------------------------------------------- /lib/terraforming/resource/iam_instance_profile.rb: -------------------------------------------------------------------------------- 1 | module Terraforming 2 | module Resource 3 | class IAMInstanceProfile 4 | include Terraforming::Util 5 | 6 | def self.tf(client: Aws::IAM::Client.new) 7 | self.new(client).tf 8 | end 9 | 10 | def self.tfstate(client: Aws::IAM::Client.new) 11 | self.new(client).tfstate 12 | end 13 | 14 | def initialize(client) 15 | @client = client 16 | end 17 | 18 | def tf 19 | apply_template(@client, "tf/iam_instance_profile") 20 | end 21 | 22 | def tfstate 23 | iam_instance_profiles.inject({}) do |resources, profile| 24 | attributes = { 25 | "arn" => profile.arn, 26 | "id" => profile.instance_profile_name, 27 | "name" => profile.instance_profile_name, 28 | "path" => profile.path, 29 | "role" => profile.roles[0].role_name, 30 | "roles.#" => profile.roles.length.to_s, 31 | } 32 | resources["aws_iam_instance_profile.#{module_name_of(profile)}"] = { 33 | "type" => "aws_iam_instance_profile", 34 | "primary" => { 35 | "id" => profile.instance_profile_name, 36 | "attributes" => attributes 37 | } 38 | } 39 | 40 | resources 41 | end 42 | end 43 | 44 | private 45 | 46 | def iam_instance_profiles 47 | @client.list_instance_profiles.map(&:instance_profiles).flatten 48 | end 49 | 50 | def module_name_of(profile) 51 | normalize_module_name(profile.instance_profile_name) 52 | end 53 | end 54 | end 55 | end 56 | -------------------------------------------------------------------------------- /lib/terraforming/resource/iam_policy.rb: -------------------------------------------------------------------------------- 1 | module Terraforming 2 | module Resource 3 | class IAMPolicy 4 | include Terraforming::Util 5 | 6 | def self.tf(client: Aws::IAM::Client.new) 7 | self.new(client).tf 8 | end 9 | 10 | def self.tfstate(client: Aws::IAM::Client.new) 11 | self.new(client).tfstate 12 | end 13 | 14 | def initialize(client) 15 | @client = client 16 | end 17 | 18 | def tf 19 | apply_template(@client, "tf/iam_policy") 20 | end 21 | 22 | def tfstate 23 | iam_policies.inject({}) do |resources, policy| 24 | version = iam_policy_version_of(policy) 25 | attributes = { 26 | "id" => policy.arn, 27 | "name" => policy.policy_name, 28 | "path" => policy.path, 29 | "description" => iam_policy_description(policy), 30 | "policy" => prettify_policy(version.document, breakline: true, unescape: true), 31 | } 32 | resources["aws_iam_policy.#{module_name_of(policy)}"] = { 33 | "type" => "aws_iam_policy", 34 | "primary" => { 35 | "id" => policy.arn, 36 | "attributes" => attributes 37 | } 38 | } 39 | 40 | resources 41 | end 42 | end 43 | 44 | private 45 | 46 | def iam_policies 47 | @client.list_policies(scope: "Local").map(&:policies).flatten 48 | end 49 | 50 | def iam_policy_description(policy) 51 | @client.get_policy(policy_arn: policy.arn).policy.description 52 | end 53 | 54 | def iam_policy_version_of(policy) 55 | @client.get_policy_version(policy_arn: policy.arn, version_id: policy.default_version_id).policy_version 56 | end 57 | 58 | def module_name_of(policy) 59 | normalize_module_name(policy.policy_name) 60 | end 61 | end 62 | end 63 | end 64 | -------------------------------------------------------------------------------- /lib/terraforming/resource/iam_policy_attachment.rb: -------------------------------------------------------------------------------- 1 | module Terraforming 2 | module Resource 3 | class IAMPolicyAttachment 4 | include Terraforming::Util 5 | 6 | def self.tf(client: Aws::IAM::Client.new) 7 | self.new(client).tf 8 | end 9 | 10 | def self.tfstate(client: Aws::IAM::Client.new) 11 | self.new(client).tfstate 12 | end 13 | 14 | def initialize(client) 15 | @client = client 16 | end 17 | 18 | def tf 19 | apply_template(@client, "tf/iam_policy_attachment") 20 | end 21 | 22 | def tfstate 23 | iam_policy_attachments.inject({}) do |resources, policy_attachment| 24 | attributes = { 25 | "id" => policy_attachment[:name], 26 | "name" => policy_attachment[:name], 27 | "policy_arn" => policy_attachment[:arn], 28 | "groups.#" => policy_attachment[:entities].policy_groups.length.to_s, 29 | "users.#" => policy_attachment[:entities].policy_users.length.to_s, 30 | "roles.#" => policy_attachment[:entities].policy_roles.length.to_s, 31 | } 32 | resources["aws_iam_policy_attachment.#{module_name_of(policy_attachment)}"] = { 33 | "type" => "aws_iam_policy_attachment", 34 | "primary" => { 35 | "id" => policy_attachment[:name], 36 | "attributes" => attributes 37 | } 38 | } 39 | 40 | resources 41 | end 42 | end 43 | 44 | private 45 | 46 | def attachment_name_from(policy) 47 | "#{policy.policy_name}-policy-attachment" 48 | end 49 | 50 | def entities_for_policy(policy) 51 | # list_entities_for_policy is a weird one: the response class 52 | # has three different member variables that we need to 53 | # paginate through altogether. 54 | result = Aws::IAM::Types::ListEntitiesForPolicyResponse.new 55 | result.policy_groups = [] 56 | result.policy_users = [] 57 | result.policy_roles = [] 58 | @client.list_entities_for_policy(policy_arn: policy.arn).each do |resp| 59 | result.policy_groups += resp.policy_groups 60 | result.policy_users += resp.policy_users 61 | result.policy_roles += resp.policy_roles 62 | end 63 | 64 | result 65 | end 66 | 67 | def iam_policies 68 | @client.list_policies(scope: "All", only_attached: true).map(&:policies).flatten 69 | end 70 | 71 | def iam_policy_attachments 72 | iam_policies.map do |policy| 73 | { 74 | arn: policy.arn, 75 | entities: entities_for_policy(policy), 76 | name: attachment_name_from(policy), 77 | } 78 | end 79 | end 80 | 81 | def module_name_of(policy_attachment) 82 | normalize_module_name(policy_attachment[:name]) 83 | end 84 | end 85 | end 86 | end 87 | -------------------------------------------------------------------------------- /lib/terraforming/resource/iam_role.rb: -------------------------------------------------------------------------------- 1 | module Terraforming 2 | module Resource 3 | class IAMRole 4 | include Terraforming::Util 5 | 6 | def self.tf(client: Aws::IAM::Client.new) 7 | self.new(client).tf 8 | end 9 | 10 | def self.tfstate(client: Aws::IAM::Client.new) 11 | self.new(client).tfstate 12 | end 13 | 14 | def initialize(client) 15 | @client = client 16 | end 17 | 18 | def tf 19 | apply_template(@client, "tf/iam_role") 20 | end 21 | 22 | def tfstate 23 | iam_roles.inject({}) do |resources, role| 24 | attributes = { 25 | "arn" => role.arn, 26 | "assume_role_policy" => 27 | prettify_policy(role.assume_role_policy_document, breakline: true, unescape: true), 28 | "id" => role.role_name, 29 | "name" => role.role_name, 30 | "path" => role.path, 31 | "unique_id" => role.role_id, 32 | } 33 | resources["aws_iam_role.#{module_name_of(role)}"] = { 34 | "type" => "aws_iam_role", 35 | "primary" => { 36 | "id" => role.role_name, 37 | "attributes" => attributes 38 | } 39 | } 40 | 41 | resources 42 | end 43 | end 44 | 45 | private 46 | 47 | def iam_roles 48 | @client.list_roles.map(&:roles).flatten 49 | end 50 | 51 | def module_name_of(role) 52 | normalize_module_name(role.role_name) 53 | end 54 | end 55 | end 56 | end 57 | -------------------------------------------------------------------------------- /lib/terraforming/resource/iam_role_policy.rb: -------------------------------------------------------------------------------- 1 | module Terraforming 2 | module Resource 3 | class IAMRolePolicy 4 | include Terraforming::Util 5 | 6 | def self.tf(client: Aws::IAM::Client.new) 7 | self.new(client).tf 8 | end 9 | 10 | def self.tfstate(client: Aws::IAM::Client.new) 11 | self.new(client).tfstate 12 | end 13 | 14 | def initialize(client) 15 | @client = client 16 | end 17 | 18 | def tf 19 | apply_template(@client, "tf/iam_role_policy") 20 | end 21 | 22 | def tfstate 23 | iam_role_policies.inject({}) do |resources, policy| 24 | attributes = { 25 | "id" => iam_role_policy_id_of(policy), 26 | "name" => policy.policy_name, 27 | "policy" => prettify_policy(policy.policy_document, breakline: true, unescape: true), 28 | "role" => policy.role_name, 29 | } 30 | resources["aws_iam_role_policy.#{unique_name(policy)}"] = { 31 | "type" => "aws_iam_role_policy", 32 | "primary" => { 33 | "id" => iam_role_policy_id_of(policy), 34 | "attributes" => attributes 35 | } 36 | } 37 | 38 | resources 39 | end 40 | end 41 | 42 | private 43 | 44 | def unique_name(policy) 45 | "#{normalize_module_name(policy.role_name)}_#{normalize_module_name(policy.policy_name)}" 46 | end 47 | 48 | def iam_role_policy_id_of(policy) 49 | "#{policy.role_name}:#{policy.policy_name}" 50 | end 51 | 52 | def iam_roles 53 | @client.list_roles.map(&:roles).flatten 54 | end 55 | 56 | def iam_role_policy_names_in(role) 57 | @client.list_role_policies(role_name: role.role_name).policy_names 58 | end 59 | 60 | def iam_role_policy_of(role, policy_name) 61 | @client.get_role_policy(role_name: role.role_name, policy_name: policy_name) 62 | end 63 | 64 | def iam_role_policies 65 | iam_roles.map do |role| 66 | iam_role_policy_names_in(role).map { |policy_name| iam_role_policy_of(role, policy_name) } 67 | end.flatten 68 | end 69 | end 70 | end 71 | end 72 | -------------------------------------------------------------------------------- /lib/terraforming/resource/iam_user.rb: -------------------------------------------------------------------------------- 1 | module Terraforming 2 | module Resource 3 | class IAMUser 4 | include Terraforming::Util 5 | 6 | def self.tf(client: Aws::IAM::Client.new) 7 | self.new(client).tf 8 | end 9 | 10 | def self.tfstate(client: Aws::IAM::Client.new) 11 | self.new(client).tfstate 12 | end 13 | 14 | def initialize(client) 15 | @client = client 16 | end 17 | 18 | def tf 19 | apply_template(@client, "tf/iam_user") 20 | end 21 | 22 | def tfstate 23 | iam_users.inject({}) do |resources, user| 24 | attributes = { 25 | "arn" => user.arn, 26 | "id" => user.user_name, 27 | "name" => user.user_name, 28 | "path" => user.path, 29 | "unique_id" => user.user_id, 30 | "force_destroy" => "false", 31 | } 32 | resources["aws_iam_user.#{module_name_of(user)}"] = { 33 | "type" => "aws_iam_user", 34 | "primary" => { 35 | "id" => user.user_name, 36 | "attributes" => attributes, 37 | } 38 | } 39 | 40 | resources 41 | end 42 | end 43 | 44 | private 45 | 46 | def iam_users 47 | @client.list_users.map(&:users).flatten 48 | end 49 | 50 | def module_name_of(user) 51 | normalize_module_name(user.user_name) 52 | end 53 | end 54 | end 55 | end 56 | -------------------------------------------------------------------------------- /lib/terraforming/resource/iam_user_policy.rb: -------------------------------------------------------------------------------- 1 | module Terraforming 2 | module Resource 3 | class IAMUserPolicy 4 | include Terraforming::Util 5 | 6 | def self.tf(client: Aws::IAM::Client.new) 7 | self.new(client).tf 8 | end 9 | 10 | def self.tfstate(client: Aws::IAM::Client.new) 11 | self.new(client).tfstate 12 | end 13 | 14 | def initialize(client) 15 | @client = client 16 | end 17 | 18 | def tf 19 | apply_template(@client, "tf/iam_user_policy") 20 | end 21 | 22 | def tfstate 23 | iam_user_policies.inject({}) do |resources, policy| 24 | attributes = { 25 | "id" => iam_user_policy_id_of(policy), 26 | "name" => policy.policy_name, 27 | "policy" => prettify_policy(policy.policy_document, breakline: true, unescape: true), 28 | "user" => policy.user_name, 29 | } 30 | resources["aws_iam_user_policy.#{unique_name(policy)}"] = { 31 | "type" => "aws_iam_user_policy", 32 | "primary" => { 33 | "id" => iam_user_policy_id_of(policy), 34 | "attributes" => attributes 35 | } 36 | } 37 | 38 | resources 39 | end 40 | end 41 | 42 | private 43 | 44 | def unique_name(policy) 45 | "#{normalize_module_name(policy.user_name)}_#{normalize_module_name(policy.policy_name)}" 46 | end 47 | 48 | def iam_user_policy_id_of(policy) 49 | "#{policy.user_name}:#{policy.policy_name}" 50 | end 51 | 52 | def iam_users 53 | @client.list_users.map(&:users).flatten 54 | end 55 | 56 | def iam_user_policy_names_in(user) 57 | @client.list_user_policies(user_name: user.user_name).policy_names 58 | end 59 | 60 | def iam_user_policy_of(user, policy_name) 61 | @client.get_user_policy(user_name: user.user_name, policy_name: policy_name) 62 | end 63 | 64 | def iam_user_policies 65 | iam_users.map do |user| 66 | iam_user_policy_names_in(user).map { |policy_name| iam_user_policy_of(user, policy_name) } 67 | end.flatten 68 | end 69 | end 70 | end 71 | end 72 | -------------------------------------------------------------------------------- /lib/terraforming/resource/internet_gateway.rb: -------------------------------------------------------------------------------- 1 | module Terraforming 2 | module Resource 3 | class InternetGateway 4 | include Terraforming::Util 5 | 6 | def self.tf(client: Aws::EC2::Client.new) 7 | self.new(client).tf 8 | end 9 | 10 | def self.tfstate(client: Aws::EC2::Client.new) 11 | self.new(client).tfstate 12 | end 13 | 14 | def initialize(client) 15 | @client = client 16 | end 17 | 18 | def tf 19 | apply_template(@client, "tf/internet_gateway") 20 | end 21 | 22 | def tfstate 23 | internet_gateways.inject({}) do |resources, internet_gateway| 24 | next resources if internet_gateway.attachments.empty? 25 | 26 | attributes = { 27 | "id" => internet_gateway.internet_gateway_id, 28 | "vpc_id" => internet_gateway.attachments[0].vpc_id, 29 | "tags.#" => internet_gateway.tags.length.to_s, 30 | } 31 | resources["aws_internet_gateway.#{module_name_of(internet_gateway)}"] = { 32 | "type" => "aws_internet_gateway", 33 | "primary" => { 34 | "id" => internet_gateway.internet_gateway_id, 35 | "attributes" => attributes 36 | } 37 | } 38 | 39 | resources 40 | end 41 | end 42 | 43 | private 44 | 45 | def internet_gateways 46 | @client.describe_internet_gateways.map(&:internet_gateways).flatten 47 | end 48 | 49 | def module_name_of(internet_gateway) 50 | normalize_module_name(name_from_tag(internet_gateway, internet_gateway.internet_gateway_id)) 51 | end 52 | end 53 | end 54 | end 55 | -------------------------------------------------------------------------------- /lib/terraforming/resource/kms_alias.rb: -------------------------------------------------------------------------------- 1 | module Terraforming 2 | module Resource 3 | class KMSAlias 4 | include Terraforming::Util 5 | 6 | def self.tf(client: Aws::KMS::Client.new) 7 | self.new(client).tf 8 | end 9 | 10 | def self.tfstate(client: Aws::KMS::Client.new) 11 | self.new(client).tfstate 12 | end 13 | 14 | def initialize(client) 15 | @client = client 16 | end 17 | 18 | def tf 19 | apply_template(@client, "tf/kms_alias") 20 | end 21 | 22 | def tfstate 23 | aliases.inject({}) do |resources, als| 24 | resources["aws_kms_alias.#{module_name_of(als)}"] = { 25 | "type" => "aws_kms_alias", 26 | "primary" => { 27 | "id" => als.alias_name, 28 | "attributes" => { 29 | "arn" => als.alias_arn, 30 | "id" => als.alias_name, 31 | "name" => als.alias_name, 32 | "target_key_id" => als.target_key_id, 33 | }, 34 | }, 35 | } 36 | resources 37 | end 38 | end 39 | 40 | private 41 | 42 | def aliases 43 | @client.list_aliases.aliases.reject { |als| managed_master_key_alias?(als) } 44 | end 45 | 46 | def managed_master_key_alias?(als) 47 | als.alias_name =~ %r{\Aalias/aws/} 48 | end 49 | 50 | def module_name_of(als) 51 | normalize_module_name(als.alias_name.gsub(%r{\Aalias/}, "")) 52 | end 53 | end 54 | end 55 | end 56 | -------------------------------------------------------------------------------- /lib/terraforming/resource/kms_key.rb: -------------------------------------------------------------------------------- 1 | module Terraforming 2 | module Resource 3 | class KMSKey 4 | include Terraforming::Util 5 | 6 | def self.tf(client: Aws::KMS::Client.new) 7 | self.new(client).tf 8 | end 9 | 10 | def self.tfstate(client: Aws::KMS::Client.new) 11 | self.new(client).tfstate 12 | end 13 | 14 | def initialize(client) 15 | @client = client 16 | end 17 | 18 | def tf 19 | apply_template(@client, "tf/kms_key") 20 | end 21 | 22 | def tfstate 23 | keys.inject({}) do |resources, key| 24 | resources["aws_kms_key.#{module_name_of(key)}"] = { 25 | "type" => "aws_kms_key", 26 | "primary" => { 27 | "id" => key.key_id, 28 | "attributes" => { 29 | "arn" => key.arn, 30 | "description" => key.description, 31 | "enable_key_rotation" => key_rotation_status_of(key).key_rotation_enabled.to_s, 32 | "id" => key.key_id, 33 | "is_enabled" => key.enabled.to_s, 34 | "key_id" => key.key_id, 35 | "key_usage" => key.key_usage, 36 | "policy" => key_policy_of(key), 37 | }, 38 | }, 39 | } 40 | resources 41 | end 42 | end 43 | 44 | private 45 | 46 | def aliases 47 | @aliases ||= @client.list_aliases.aliases 48 | end 49 | 50 | def keys 51 | @client 52 | .list_keys 53 | .keys 54 | .reject { |key| managed_master_key?(key) } 55 | .map { |key| @client.describe_key(key_id: key.key_id) } 56 | .map(&:key_metadata) 57 | .reject { |metadata| metadata.origin == "EXTERNAL" } # external origin key is not supoprted by Terraform 58 | end 59 | 60 | def key_policy_of(key) 61 | policies = @client.list_key_policies(key_id: key.key_id).policy_names 62 | 63 | return "" if policies.empty? 64 | 65 | @client.get_key_policy(key_id: key.key_id, policy_name: policies[0]).policy 66 | end 67 | 68 | def key_rotation_status_of(key) 69 | @client.get_key_rotation_status(key_id: key.key_id) 70 | end 71 | 72 | def managed_master_key?(key) 73 | !aliases.select { |a| a.target_key_id == key.key_id && a.alias_name =~ %r{\Aalias/aws/} }.empty? 74 | end 75 | 76 | def module_name_of(key) 77 | normalize_module_name(key.key_id) 78 | end 79 | end 80 | end 81 | end 82 | -------------------------------------------------------------------------------- /lib/terraforming/resource/launch_configuration.rb: -------------------------------------------------------------------------------- 1 | module Terraforming 2 | module Resource 3 | class LaunchConfiguration 4 | include Terraforming::Util 5 | 6 | def self.tf(client: Aws::AutoScaling::Client.new) 7 | self.new(client).tf 8 | end 9 | 10 | def self.tfstate(client: Aws::AutoScaling::Client.new) 11 | self.new(client).tfstate 12 | end 13 | 14 | def initialize(client) 15 | @client = client 16 | end 17 | 18 | def tf 19 | apply_template(@client, "tf/launch_configuration") 20 | end 21 | 22 | def tfstate 23 | launch_configurations.inject({}) do |resources, lc| 24 | attributes = { 25 | "name" => lc.launch_configuration_name, 26 | "image_id" => lc.image_id, 27 | "instance_type" => lc.instance_type, 28 | "key_name" => lc.key_name, 29 | "security_groups.#" => lc.security_groups.length.to_s, 30 | "associate_public_ip_address" => lc.associate_public_ip_address.to_s, 31 | "user_data" => lc.user_data, 32 | "enable_monitoring" => lc.instance_monitoring.enabled.to_s, 33 | "ebs_optimized" => lc.ebs_optimized.to_s, 34 | "root_block_device.#" => root_block_device_count(lc).to_s, 35 | "ebs_block_device.#" => ebs_block_device_count(lc).to_s, 36 | "ephemeral_block_device.#" => ephemeral_block_device_count(lc).to_s 37 | } 38 | 39 | lc.security_groups.each do |sg| 40 | hash = hash_security_group(sg) 41 | attributes["security_groups.#{hash}"] = sg 42 | end 43 | 44 | attributes["iam_instance_profile"] = lc.iam_instance_profile if lc.iam_instance_profile 45 | attributes["spot_price"] = lc.spot_price if lc.spot_price 46 | attributes["placement_tenancy"] = lc.placement_tenancy if lc.placement_tenancy 47 | 48 | resources["aws_launch_configuration.#{module_name_of(lc)}"] = { 49 | "type" => "aws_launch_configuration", 50 | "primary" => { 51 | "id" => lc.launch_configuration_name, 52 | "attributes" => attributes 53 | } 54 | } 55 | 56 | resources 57 | end 58 | end 59 | 60 | private 61 | 62 | # Taken from http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/device_naming.html 63 | def root_block_device?(block_device) 64 | %w(/dev/sda1 /dev/xvda).include? block_device.device_name 65 | end 66 | 67 | def root_block_device_count(launch_configuration) 68 | launch_configuration.block_device_mappings.select do |volume| 69 | root_block_device?(volume) 70 | end.length 71 | end 72 | 73 | def ebs_block_device?(block_device) 74 | block_device.virtual_name.nil? && block_device.ebs 75 | end 76 | 77 | def ebs_block_device_count(launch_configuration) 78 | launch_configuration.block_device_mappings.select do |volume| 79 | ebs_block_device?(volume) && !root_block_device?(volume) 80 | end.length 81 | end 82 | 83 | def ephemeral_block_device?(block_device) 84 | block_device.virtual_name != nil 85 | end 86 | 87 | def ephemeral_block_device_count(launch_configuration) 88 | launch_configuration.block_device_mappings.select do |volume| 89 | ephemeral_block_device?(volume) 90 | end.length 91 | end 92 | 93 | def hash_security_group(name) 94 | Zlib.crc32(name) 95 | end 96 | 97 | def launch_configurations 98 | @client.describe_launch_configurations.map(&:launch_configurations).flatten 99 | end 100 | 101 | def module_name_of(launch_configuration) 102 | normalize_module_name(launch_configuration.launch_configuration_name) 103 | end 104 | end 105 | end 106 | end 107 | -------------------------------------------------------------------------------- /lib/terraforming/resource/nat_gateway.rb: -------------------------------------------------------------------------------- 1 | module Terraforming 2 | module Resource 3 | class NATGateway 4 | include Terraforming::Util 5 | 6 | def self.tf(client: Aws::EC2::Client.new) 7 | self.new(client).tf 8 | end 9 | 10 | def self.tfstate(client: Aws::EC2::Client.new) 11 | self.new(client).tfstate 12 | end 13 | 14 | def initialize(client) 15 | @client = client 16 | end 17 | 18 | def tf 19 | apply_template(@client, "tf/nat_gateway") 20 | end 21 | 22 | def tfstate 23 | nat_gateways.inject({}) do |resources, nat_gateway| 24 | next resources if nat_gateway.nat_gateway_addresses.empty? 25 | 26 | attributes = { 27 | "id" => nat_gateway.nat_gateway_id, 28 | "allocation_id" => nat_gateway.nat_gateway_addresses[0].allocation_id, 29 | "subnet_id" => nat_gateway.subnet_id, 30 | "network_inferface_id" => nat_gateway.nat_gateway_addresses[0].network_interface_id, 31 | "private_ip" => nat_gateway.nat_gateway_addresses[0].private_ip, 32 | "public_ip" => nat_gateway.nat_gateway_addresses[0].public_ip, 33 | } 34 | resources["aws_nat_gateway.#{module_name_of(nat_gateway)}"] = { 35 | "type" => "aws_nat_gateway", 36 | "primary" => { 37 | "id" => nat_gateway.nat_gateway_id, 38 | "attributes" => attributes 39 | } 40 | } 41 | 42 | resources 43 | end 44 | end 45 | 46 | private 47 | 48 | def nat_gateways 49 | @client.describe_nat_gateways.nat_gateways 50 | end 51 | 52 | def module_name_of(nat_gateway) 53 | normalize_module_name(nat_gateway.nat_gateway_id) 54 | end 55 | end 56 | end 57 | end 58 | -------------------------------------------------------------------------------- /lib/terraforming/resource/network_acl.rb: -------------------------------------------------------------------------------- 1 | module Terraforming 2 | module Resource 3 | class NetworkACL 4 | include Terraforming::Util 5 | 6 | def self.tf(client: Aws::EC2::Client.new) 7 | self.new(client).tf 8 | end 9 | 10 | def self.tfstate(client: Aws::EC2::Client.new) 11 | self.new(client).tfstate 12 | end 13 | 14 | def initialize(client) 15 | @client = client 16 | end 17 | 18 | def tf 19 | apply_template(@client, "tf/network_acl") 20 | end 21 | 22 | def tfstate 23 | network_acls.inject({}) do |resources, network_acl| 24 | attributes = { 25 | "egress.#" => egresses_of(network_acl).length.to_s, 26 | "id" => network_acl.network_acl_id, 27 | "ingress.#" => ingresses_of(network_acl).length.to_s, 28 | "subnet_ids.#" => subnet_ids_of(network_acl).length.to_s, 29 | "tags.#" => network_acl.tags.length.to_s, 30 | "vpc_id" => network_acl.vpc_id, 31 | } 32 | resources["aws_network_acl.#{module_name_of(network_acl)}"] = { 33 | "type" => "aws_network_acl", 34 | "primary" => { 35 | "id" => network_acl.network_acl_id, 36 | "attributes" => attributes 37 | } 38 | } 39 | 40 | resources 41 | end 42 | end 43 | 44 | private 45 | 46 | def default_entry?(entry) 47 | entry.rule_number == default_rule_number 48 | end 49 | 50 | def default_rule_number 51 | 32767 52 | end 53 | 54 | def egresses_of(network_acl) 55 | network_acl.entries.select { |entry| entry.egress && !default_entry?(entry) } 56 | end 57 | 58 | def from_port_of(entry) 59 | entry.port_range ? entry.port_range.from : 0 60 | end 61 | 62 | def ingresses_of(network_acl) 63 | network_acl.entries.select { |entry| !entry.egress && !default_entry?(entry) } 64 | end 65 | 66 | def module_name_of(network_acl) 67 | normalize_module_name(name_from_tag(network_acl, network_acl.network_acl_id)) 68 | end 69 | 70 | def network_acls 71 | @client.describe_network_acls.map(&:network_acls).flatten 72 | end 73 | 74 | def subnet_ids_of(network_acl) 75 | network_acl.associations.map { |association| association.subnet_id } 76 | end 77 | 78 | def to_port_of(entry) 79 | entry.port_range ? entry.port_range.to : 0 80 | end 81 | end 82 | end 83 | end 84 | -------------------------------------------------------------------------------- /lib/terraforming/resource/network_interface.rb: -------------------------------------------------------------------------------- 1 | module Terraforming 2 | module Resource 3 | class NetworkInterface 4 | include Terraforming::Util 5 | 6 | def self.tf(client: Aws::EC2::Client.new) 7 | self.new(client).tf 8 | end 9 | 10 | def self.tfstate(client: Aws::EC2::Client.new) 11 | self.new(client).tfstate 12 | end 13 | 14 | def initialize(client) 15 | @client = client 16 | end 17 | 18 | def tf 19 | apply_template(@client, "tf/network_interface") 20 | end 21 | 22 | def tfstate 23 | network_interfaces.inject({}) do |resources, network_interface| 24 | attributes = { 25 | "attachment.#" => attachment_of(network_interface) ? "1" : "0", 26 | "id" => network_interface.network_interface_id, 27 | "private_ips.#" => private_ips_of(network_interface).length.to_s, 28 | "security_groups.#" => security_groups_of(network_interface).length.to_s, 29 | "source_dest_check" => network_interface.source_dest_check.to_s, 30 | "subnet_id" => network_interface.subnet_id, 31 | "tags.#" => network_interface.tag_set.length.to_s, 32 | } 33 | resources["aws_network_interface.#{module_name_of(network_interface)}"] = { 34 | "type" => "aws_network_interface", 35 | "primary" => { 36 | "id" => network_interface.network_interface_id, 37 | "attributes" => attributes 38 | } 39 | } 40 | 41 | resources 42 | end 43 | end 44 | 45 | private 46 | 47 | def attachment_of(network_interface) 48 | network_interface.attachment 49 | end 50 | 51 | def private_ips_of(network_interface) 52 | network_interface.private_ip_addresses.map { |addr| addr.private_ip_address } 53 | end 54 | 55 | def security_groups_of(network_interface) 56 | network_interface.groups.map { |group| group.group_id } 57 | end 58 | 59 | def module_name_of(network_interface) 60 | network_interface.network_interface_id 61 | end 62 | 63 | def network_interfaces 64 | @client.describe_network_interfaces.map(&:network_interfaces).flatten 65 | end 66 | end 67 | end 68 | end 69 | -------------------------------------------------------------------------------- /lib/terraforming/resource/rds.rb: -------------------------------------------------------------------------------- 1 | module Terraforming 2 | module Resource 3 | class RDS 4 | include Terraforming::Util 5 | 6 | def self.tf(client: Aws::RDS::Client.new) 7 | self.new(client).tf 8 | end 9 | 10 | def self.tfstate(client: Aws::RDS::Client.new) 11 | self.new(client).tfstate 12 | end 13 | 14 | def initialize(client) 15 | @client = client 16 | end 17 | 18 | def tf 19 | apply_template(@client, "tf/rds") 20 | end 21 | 22 | def tfstate 23 | db_instances.inject({}) do |resources, instance| 24 | attributes = { 25 | "address" => instance.endpoint.address, 26 | "allocated_storage" => instance.allocated_storage.to_s, 27 | "availability_zone" => instance.availability_zone, 28 | "backup_retention_period" => instance.backup_retention_period.to_s, 29 | "backup_window" => instance.preferred_backup_window, 30 | "db_subnet_group_name" => instance.db_subnet_group ? instance.db_subnet_group.db_subnet_group_name : "", 31 | "endpoint" => instance.endpoint.address, 32 | "engine" => instance.engine, 33 | "engine_version" => instance.engine_version, 34 | "final_snapshot_identifier" => "#{instance.db_instance_identifier}-final", 35 | "id" => instance.db_instance_identifier, 36 | "identifier" => instance.db_instance_identifier, 37 | "instance_class" => instance.db_instance_class, 38 | "maintenance_window" => instance.preferred_maintenance_window, 39 | "multi_az" => instance.multi_az.to_s, 40 | "name" => instance.db_name, 41 | "parameter_group_name" => instance.db_parameter_groups[0].db_parameter_group_name, 42 | "password" => "xxxxxxxx", 43 | "port" => instance.endpoint.port.to_s, 44 | "publicly_accessible" => instance.publicly_accessible.to_s, 45 | "security_group_names.#" => instance.db_security_groups.length.to_s, 46 | "status" => instance.db_instance_status, 47 | "storage_type" => instance.storage_type, 48 | "username" => instance.master_username, 49 | "vpc_security_group_ids.#" => instance.vpc_security_groups.length.to_s, 50 | } 51 | resources["aws_db_instance.#{module_name_of(instance)}"] = { 52 | "type" => "aws_db_instance", 53 | "primary" => { 54 | "id" => instance.db_instance_identifier, 55 | "attributes" => attributes 56 | } 57 | } 58 | 59 | resources 60 | end 61 | end 62 | 63 | private 64 | 65 | def db_instances 66 | @client.describe_db_instances.map(&:db_instances).flatten 67 | end 68 | 69 | def module_name_of(instance) 70 | normalize_module_name(instance.db_instance_identifier) 71 | end 72 | end 73 | end 74 | end 75 | -------------------------------------------------------------------------------- /lib/terraforming/resource/redshift.rb: -------------------------------------------------------------------------------- 1 | module Terraforming 2 | module Resource 3 | class Redshift 4 | include Terraforming::Util 5 | 6 | def self.tf(client: Aws::Redshift::Client.new) 7 | self.new(client).tf 8 | end 9 | 10 | def self.tfstate(client: Aws::Redshift::Client.new) 11 | self.new(client).tfstate 12 | end 13 | 14 | def initialize(client) 15 | @client = client 16 | end 17 | 18 | def tf 19 | apply_template(@client, "tf/redshift") 20 | end 21 | 22 | def tfstate 23 | clusters.inject({}) do |resources, cluster| 24 | attributes = { 25 | "cluster_identifier" => cluster.cluster_identifier, 26 | "cluster_type" => cluster.number_of_nodes == 1 ? "single-node" : "multi-node", 27 | "node_type" => cluster.node_type, 28 | "master_password" => "xxxxxxxx", 29 | "master_username" => cluster.master_username, 30 | "availability_zone" => cluster.availability_zone, 31 | "preferred_maintenance_window" => cluster.preferred_maintenance_window, 32 | "cluster_parameter_group_name" => cluster.cluster_parameter_groups[0].parameter_group_name, 33 | "automated_snapshot_retention_period" => cluster.automated_snapshot_retention_period.to_s, 34 | "port" => cluster.endpoint.port.to_s, 35 | "cluster_version" => cluster.cluster_version, 36 | "allow_version_upgrade" => cluster.allow_version_upgrade.to_s, 37 | "number_of_nodes" => cluster.number_of_nodes.to_s, 38 | "publicly_accessible" => cluster.publicly_accessible.to_s, 39 | "encrypted" => cluster.encrypted.to_s, 40 | "skip_final_snapshot" => "true", 41 | } 42 | attributes["database_name"] = cluster.db_name if cluster.db_name 43 | 44 | resources["aws_redshift_cluster.#{module_name_of(cluster)}"] = { 45 | "type" => "aws_redshift_cluster", 46 | "primary" => { 47 | "id" => cluster.cluster_identifier, 48 | "attributes" => attributes 49 | } 50 | } 51 | 52 | resources 53 | end 54 | end 55 | 56 | private 57 | 58 | def clusters 59 | @client.describe_clusters.map(&:clusters).flatten 60 | end 61 | 62 | def module_name_of(cluster) 63 | normalize_module_name(cluster.cluster_identifier) 64 | end 65 | end 66 | end 67 | end 68 | -------------------------------------------------------------------------------- /lib/terraforming/resource/route53_record.rb: -------------------------------------------------------------------------------- 1 | module Terraforming 2 | module Resource 3 | class Route53Record 4 | include Terraforming::Util 5 | 6 | def self.tf(client: Aws::Route53::Client.new) 7 | self.new(client).tf 8 | end 9 | 10 | def self.tfstate(client: Aws::Route53::Client.new) 11 | self.new(client).tfstate 12 | end 13 | 14 | def initialize(client) 15 | @client = client 16 | end 17 | 18 | def tf 19 | apply_template(@client, "tf/route53_record") 20 | end 21 | 22 | def tfstate 23 | records.inject({}) do |resources, r| 24 | record, zone_id = r[:record], r[:zone_id] 25 | counter = r[:counter] 26 | record_id = record_id_of(record, zone_id) 27 | 28 | attributes = { 29 | "id" => record_id, 30 | "name" => name_of(record.name.gsub(/\\052/, '*')), 31 | "type" => record.type, 32 | "zone_id" => zone_id, 33 | } 34 | 35 | attributes["alias.#"] = "1" if record.alias_target 36 | attributes["records.#"] = record.resource_records.length.to_s unless record.resource_records.empty? 37 | attributes["ttl"] = record.ttl.to_s if record.ttl 38 | attributes["weight"] = record.weight ? record.weight.to_s : "-1" 39 | attributes["region"] = record.region if record.region 40 | 41 | if record.geo_location 42 | attributes["continent"] = record.geo_location.continent_code if record.geo_location.continent_code 43 | attributes["country"] = record.geo_location.country_code if record.geo_location.country_code 44 | attributes["subdivision"] = record.geo_location.subdivision_code if record.geo_location.subdivision_code 45 | end 46 | 47 | if record.failover 48 | attributes["failover_routing_policy.#"] = "1" 49 | attributes["failover_routing_policy.0.type"] = record.failover 50 | end 51 | 52 | attributes["set_identifier"] = record.set_identifier if record.set_identifier 53 | attributes["health_check_id"] = record.health_check_id if record.health_check_id 54 | 55 | resources["aws_route53_record.#{module_name_of(record, counter)}"] = { 56 | "type" => "aws_route53_record", 57 | "primary" => { 58 | "id" => record_id, 59 | "attributes" => attributes, 60 | } 61 | } 62 | 63 | resources 64 | end 65 | end 66 | 67 | private 68 | 69 | def hosted_zones 70 | @client.list_hosted_zones.map(&:hosted_zones).flatten 71 | end 72 | 73 | def record_id_of(record, zone_id) 74 | "#{zone_id}_#{name_of(record.name.gsub(/\\052/, '*'))}_#{record.type}" 75 | end 76 | 77 | def record_sets_of(hosted_zone) 78 | @client.list_resource_record_sets(hosted_zone_id: zone_id_of(hosted_zone)).map do |response| 79 | response.data.resource_record_sets 80 | end.flatten 81 | end 82 | 83 | def records 84 | to_return = hosted_zones.map do |hosted_zone| 85 | record_sets_of(hosted_zone).map { |record| { record: record, zone_id: zone_id_of(hosted_zone) } } 86 | end.flatten 87 | count = {} 88 | dups = to_return.group_by { |record| module_name_of(record[:record], nil) }.select { |_, v| v.size > 1 }.map(&:first) 89 | to_return.each do |r| 90 | module_name = module_name_of(r[:record], nil) 91 | next unless dups.include?(module_name) 92 | count[module_name] = count[module_name] ? count[module_name] + 1 : 0 93 | r[:counter] = count[module_name] 94 | end 95 | to_return 96 | end 97 | 98 | # TODO(dtan4): change method name... 99 | def name_of(dns_name) 100 | dns_name.gsub(/\.\z/, "") 101 | end 102 | 103 | def module_name_of(record, counter) 104 | normalize_module_name(name_of(record.name.gsub(/\\052/, 'wildcard')) + "-" + record.type + (!counter.nil? ? "-" + counter.to_s : "")) 105 | end 106 | 107 | def zone_id_of(hosted_zone) 108 | hosted_zone.id.gsub(%r{\A/hostedzone/}, "") 109 | end 110 | end 111 | end 112 | end 113 | -------------------------------------------------------------------------------- /lib/terraforming/resource/route53_zone.rb: -------------------------------------------------------------------------------- 1 | module Terraforming 2 | module Resource 3 | class Route53Zone 4 | include Terraforming::Util 5 | 6 | def self.tf(client: Aws::Route53::Client.new) 7 | self.new(client).tf 8 | end 9 | 10 | def self.tfstate(client: Aws::Route53::Client.new) 11 | self.new(client).tfstate 12 | end 13 | 14 | def initialize(client) 15 | @client = client 16 | end 17 | 18 | def tf 19 | apply_template(@client, "tf/route53_zone") 20 | end 21 | 22 | def tfstate 23 | hosted_zones.inject({}) do |resources, hosted_zone| 24 | zone_id = zone_id_of(hosted_zone) 25 | vpc = vpc_of(hosted_zone) 26 | 27 | attributes = { 28 | "comment" => comment_of(hosted_zone), 29 | "id" => zone_id, 30 | "name" => name_of(hosted_zone), 31 | "name_servers.#" => name_servers_of(hosted_zone).length.to_s, 32 | "tags.#" => tags_of(hosted_zone).length.to_s, 33 | "vpc_id" => vpc ? vpc.vpc_id : "", 34 | "vpc_region" => vpc ? vpc.vpc_region : "", 35 | "zone_id" => zone_id, 36 | } 37 | resources["aws_route53_zone.#{module_name_of(hosted_zone)}"] = { 38 | "type" => "aws_route53_zone", 39 | "primary" => { 40 | "id" => zone_id, 41 | "attributes" => attributes, 42 | } 43 | } 44 | 45 | resources 46 | end 47 | end 48 | 49 | private 50 | 51 | def hosted_zones 52 | @client.list_hosted_zones.map(&:hosted_zones).flatten.map { |hosted_zone| @client.get_hosted_zone(id: hosted_zone.id) } 53 | end 54 | 55 | def tags_of(hosted_zone) 56 | @client.list_tags_for_resource(resource_type: "hostedzone", resource_id: zone_id_of(hosted_zone)).resource_tag_set.tags 57 | end 58 | 59 | def comment_of(hosted_zone) 60 | hosted_zone.hosted_zone.config.comment 61 | end 62 | 63 | def name_of(hosted_zone) 64 | hosted_zone.hosted_zone.name.gsub(/\.\z/, "") 65 | end 66 | 67 | def name_servers_of(hosted_zone) 68 | delegation_set = hosted_zone.delegation_set 69 | delegation_set ? delegation_set.name_servers : [] 70 | end 71 | 72 | def module_name_of(hosted_zone) 73 | normalize_module_name(name_of(hosted_zone)) << "-#{private_hosted_zone?(hosted_zone) ? 'private' : 'public'}" 74 | end 75 | 76 | def private_hosted_zone?(hosted_zone) 77 | hosted_zone.hosted_zone.config.private_zone 78 | end 79 | 80 | def vpc_of(hosted_zone) 81 | hosted_zone.vp_cs[0] 82 | end 83 | 84 | def zone_id_of(hosted_zone) 85 | hosted_zone.hosted_zone.id.gsub(%r{\A/hostedzone/}, "") 86 | end 87 | end 88 | end 89 | end 90 | -------------------------------------------------------------------------------- /lib/terraforming/resource/route_table.rb: -------------------------------------------------------------------------------- 1 | module Terraforming 2 | module Resource 3 | class RouteTable 4 | include Terraforming::Util 5 | 6 | def self.tf(client: Aws::EC2::Client.new) 7 | self.new(client).tf 8 | end 9 | 10 | def self.tfstate(client: Aws::EC2::Client.new) 11 | self.new(client).tfstate 12 | end 13 | 14 | def initialize(client) 15 | @client = client 16 | end 17 | 18 | def tf 19 | apply_template(@client, "tf/route_table") 20 | end 21 | 22 | def tfstate 23 | route_tables.inject({}) do |resources, route_table| 24 | attributes = { 25 | "id" => route_table.route_table_id, 26 | "vpc_id" => route_table.vpc_id, 27 | } 28 | 29 | attributes.merge!(tags_attributes_of(route_table)) 30 | attributes.merge!(routes_attributes_of(route_table)) 31 | attributes.merge!(propagating_vgws_attributes_of(route_table)) 32 | 33 | resources["aws_route_table.#{module_name_of(route_table)}"] = { 34 | "type" => "aws_route_table", 35 | "primary" => { 36 | "id" => route_table.route_table_id, 37 | "attributes" => attributes 38 | } 39 | } 40 | 41 | resources 42 | end 43 | end 44 | 45 | private 46 | 47 | def routes_of(route_table) 48 | route_table.routes.reject do |route| 49 | route.gateway_id.to_s == 'local' || 50 | route.origin.to_s == 'EnableVgwRoutePropagation' || 51 | route.destination_prefix_list_id 52 | end 53 | end 54 | 55 | def module_name_of(route_table) 56 | normalize_module_name(name_from_tag(route_table, route_table.route_table_id)) 57 | end 58 | 59 | def route_tables 60 | @client.describe_route_tables.map(&:route_tables).flatten 61 | end 62 | 63 | def routes_attributes_of(route_table) 64 | routes = routes_of(route_table) 65 | attributes = { "route.#" => routes.length.to_s } 66 | 67 | routes.each do |route| 68 | attributes.merge!(route_attributes_of(route)) 69 | end 70 | 71 | attributes 72 | end 73 | 74 | def route_attributes_of(route) 75 | hashcode = route_hashcode_of(route) 76 | attributes = { 77 | "route.#{hashcode}.cidr_block" => route.destination_cidr_block.to_s, 78 | "route.#{hashcode}.gateway_id" => route.gateway_id.to_s, 79 | "route.#{hashcode}.instance_id" => route.instance_id.to_s, 80 | "route.#{hashcode}.network_interface_id" => route.network_interface_id.to_s, 81 | "route.#{hashcode}.vpc_peering_connection_id" => route.vpc_peering_connection_id.to_s 82 | } 83 | 84 | attributes 85 | end 86 | 87 | def route_hashcode_of(route) 88 | string = "#{route.destination_cidr_block}-#{route.gateway_id}-" 89 | instance_set = !route.instance_id.nil? && route.instance_id != '' 90 | 91 | string << route.instance_id.to_s if instance_set 92 | string << route.vpc_peering_connection_id.to_s 93 | string << route.network_interface_id.to_s unless instance_set 94 | 95 | Zlib.crc32(string) 96 | end 97 | 98 | def propagaving_vgws_of(route_table) 99 | route_table.propagating_vgws.map(&:gateway_id).map(&:to_s) 100 | end 101 | 102 | def propagating_vgws_attributes_of(route_table) 103 | vgws = propagaving_vgws_of(route_table) 104 | attributes = { "propagating_vgws.#" => vgws.length.to_s } 105 | 106 | vgws.each do |gateway_id| 107 | hashcode = Zlib.crc32(gateway_id) 108 | attributes["propagating_vgws.#{hashcode}"] = gateway_id 109 | end 110 | 111 | attributes 112 | end 113 | 114 | def tags_attributes_of(route_table) 115 | tags = route_table.tags 116 | attributes = { "tags.#" => tags.length.to_s } 117 | tags.each { |tag| attributes["tags.#{tag.key}"] = tag.value } 118 | attributes 119 | end 120 | end 121 | end 122 | end 123 | -------------------------------------------------------------------------------- /lib/terraforming/resource/route_table_association.rb: -------------------------------------------------------------------------------- 1 | module Terraforming 2 | module Resource 3 | class RouteTableAssociation 4 | include Terraforming::Util 5 | 6 | def self.tf(client: Aws::EC2::Client.new) 7 | self.new(client).tf 8 | end 9 | 10 | def self.tfstate(client: Aws::EC2::Client.new) 11 | self.new(client).tfstate 12 | end 13 | 14 | def initialize(client) 15 | @client = client 16 | end 17 | 18 | def tf 19 | apply_template(@client, "tf/route_table_association") 20 | end 21 | 22 | def tfstate 23 | resources = {} 24 | route_tables.each do |route_table| 25 | associations_of(route_table).each do |assoc| 26 | attributes = { 27 | "id" => assoc.route_table_association_id, 28 | "route_table_id" => assoc.route_table_id, 29 | "subnet_id" => assoc.subnet_id, 30 | } 31 | 32 | resources["aws_route_table_association.#{module_name_of(route_table, assoc)}"] = { 33 | "type" => "aws_route_table_association", 34 | "primary" => { 35 | "id" => assoc.route_table_association_id, 36 | "attributes" => attributes 37 | } 38 | } 39 | end 40 | end 41 | resources 42 | end 43 | 44 | private 45 | 46 | def associations_of(route_table) 47 | route_table.associations.reject { |association| association.subnet_id.nil? } 48 | end 49 | 50 | def module_name_of(route_table, assoc) 51 | normalize_module_name(name_from_tag(route_table, route_table.route_table_id) + '-' + assoc.route_table_association_id) 52 | end 53 | 54 | def route_tables 55 | @client.describe_route_tables.map(&:route_tables).flatten 56 | end 57 | end 58 | end 59 | end 60 | -------------------------------------------------------------------------------- /lib/terraforming/resource/s3.rb: -------------------------------------------------------------------------------- 1 | module Terraforming 2 | module Resource 3 | class S3 4 | include Terraforming::Util 5 | 6 | def self.tf(client: Aws::S3::Client.new) 7 | self.new(client).tf 8 | end 9 | 10 | def self.tfstate(client: Aws::S3::Client.new) 11 | self.new(client).tfstate 12 | end 13 | 14 | def initialize(client) 15 | @client = client 16 | end 17 | 18 | def tf 19 | apply_template(@client, "tf/s3") 20 | end 21 | 22 | def tfstate 23 | buckets.inject({}) do |resources, bucket| 24 | bucket_policy = bucket_policy_of(bucket) 25 | resources["aws_s3_bucket.#{module_name_of(bucket)}"] = { 26 | "type" => "aws_s3_bucket", 27 | "primary" => { 28 | "id" => bucket.name, 29 | "attributes" => { 30 | "acl" => "private", 31 | "bucket" => bucket.name, 32 | "force_destroy" => "false", 33 | "id" => bucket.name, 34 | "policy" => bucket_policy ? bucket_policy.policy.read : "", 35 | } 36 | } 37 | } 38 | 39 | resources 40 | end 41 | end 42 | 43 | private 44 | 45 | def bucket_location_of(bucket) 46 | @client.get_bucket_location(bucket: bucket.name).location_constraint 47 | end 48 | 49 | def bucket_policy_of(bucket) 50 | @client.get_bucket_policy(bucket: bucket.name) 51 | rescue Aws::S3::Errors::NoSuchBucketPolicy 52 | nil 53 | end 54 | 55 | def buckets 56 | @client.list_buckets.map(&:buckets).flatten.select { |bucket| same_region?(bucket) } 57 | end 58 | 59 | def module_name_of(bucket) 60 | normalize_module_name(bucket.name) 61 | end 62 | 63 | def same_region?(bucket) 64 | bucket_location = bucket_location_of(bucket) 65 | (bucket_location == @client.config.region) || (bucket_location == "" && @client.config.region == "us-east-1") 66 | end 67 | end 68 | end 69 | end 70 | -------------------------------------------------------------------------------- /lib/terraforming/resource/sns_topic.rb: -------------------------------------------------------------------------------- 1 | module Terraforming 2 | module Resource 3 | class SNSTopic 4 | include Terraforming::Util 5 | 6 | def self.tf(client: Aws::SNS::Client.new) 7 | self.new(client).tf 8 | end 9 | 10 | def self.tfstate(client: Aws::SNS::Client.new) 11 | self.new(client).tfstate 12 | end 13 | 14 | def initialize(client) 15 | @client = client 16 | end 17 | 18 | def tf 19 | apply_template(@client, "tf/sns_topic") 20 | end 21 | 22 | def tfstate 23 | topics.inject({}) do |resources, topic| 24 | attributes = { 25 | "name" => module_name_of(topic), 26 | "id" => topic["TopicArn"], 27 | "arn" => topic["TopicArn"], 28 | "display_name" => topic["DisplayName"], 29 | "policy" => topic.key?("Policy") ? topic["Policy"] : "", 30 | "delivery_policy" => topic.key?("DeliveryPolicy") ? topic["DeliveryPolicy"] : "" 31 | } 32 | resources["aws_sns_topic.#{module_name_of(topic)}"] = { 33 | "type" => "aws_sns_topic", 34 | "primary" => { 35 | "id" => topic["TopicArn"], 36 | "attributes" => attributes 37 | } 38 | } 39 | 40 | resources 41 | end 42 | end 43 | 44 | private 45 | 46 | def topics 47 | topic_arns.map do |topic_arn| 48 | attributes = @client.get_topic_attributes({ 49 | topic_arn: topic_arn, 50 | }).attributes 51 | attributes["TopicArn"] = topic_arn 52 | attributes 53 | end 54 | end 55 | 56 | def topic_arns 57 | token = "" 58 | arns = [] 59 | 60 | loop do 61 | resp = @client.list_topics(next_token: token) 62 | arns += resp.topics.map(&:topic_arn).flatten 63 | token = resp.next_token 64 | break if token.nil? 65 | end 66 | 67 | arns 68 | end 69 | 70 | def module_name_of(topic) 71 | normalize_module_name(topic["TopicArn"].split(":").last) 72 | end 73 | end 74 | end 75 | end 76 | -------------------------------------------------------------------------------- /lib/terraforming/resource/sns_topic_subscription.rb: -------------------------------------------------------------------------------- 1 | module Terraforming 2 | module Resource 3 | class SNSTopicSubscription 4 | include Terraforming::Util 5 | 6 | def self.tf(client: Aws::SNS::Client.new) 7 | self.new(client).tf 8 | end 9 | 10 | def self.tfstate(client: Aws::SNS::Client.new) 11 | self.new(client).tfstate 12 | end 13 | 14 | def initialize(client) 15 | @client = client 16 | end 17 | 18 | def tf 19 | apply_template(@client, "tf/sns_topic_subscription") 20 | end 21 | 22 | def tfstate 23 | subscriptions.reject { |x| x["Protocol"].include?("email") } 24 | .inject({}) do |resources, subscription| 25 | attributes = { 26 | "id" => subscription["SubscriptionArn"], 27 | "topic_arn" => subscription["TopicArn"], 28 | "protocol" => subscription["Protocol"], 29 | "endpoint" => subscription["Endpoint"], 30 | "raw_message_delivery" => 31 | subscription.key?("RawMessageDelivery") ? subscription["RawMessageDelivery"] : "false", 32 | "confirmation_timeout_in_minutes" => 33 | subscription.key?("ConfirmationTimeoutInMinutes") ? subscription["ConfirmationTimeoutInMinutes"] : "1", 34 | "endpoint_auto_confirms" => 35 | subscription.key?("EndpointAutoConfirms") ? subscription["EndpointAutoConfirms"] : "false" 36 | } 37 | resources["aws_sns_topic_subscription.#{module_name_of(subscription)}"] = { 38 | "type" => "aws_sns_topic_subscription", 39 | "primary" => { 40 | "id" => subscription["SubscriptionArn"], 41 | "attributes" => attributes 42 | } 43 | } 44 | 45 | resources 46 | end 47 | end 48 | 49 | private 50 | 51 | def subscriptions 52 | subscription_arns.map do |subscription_arn| 53 | # check explicitly for an issue with some subscriptions that returns ARN=PendingConfirmation 54 | next if subscription_arn == "PendingConfirmation" 55 | 56 | attributes = @client.get_subscription_attributes({ 57 | subscription_arn: subscription_arn, 58 | }).attributes 59 | attributes["SubscriptionArn"] = subscription_arn 60 | attributes 61 | end.compact 62 | end 63 | 64 | def subscription_arns 65 | token = "" 66 | arns = [] 67 | 68 | loop do 69 | resp = @client.list_subscriptions(next_token: token) 70 | arns += resp.subscriptions.map(&:subscription_arn).flatten 71 | token = resp.next_token 72 | break if token.nil? 73 | end 74 | 75 | arns 76 | end 77 | 78 | def module_name_of(subscription) 79 | normalize_module_name(subscription["SubscriptionArn"].split(":").last) 80 | end 81 | end 82 | end 83 | end 84 | -------------------------------------------------------------------------------- /lib/terraforming/resource/sqs.rb: -------------------------------------------------------------------------------- 1 | module Terraforming 2 | module Resource 3 | class SQS 4 | include Terraforming::Util 5 | 6 | def self.tf(client: Aws::SQS::Client.new) 7 | self.new(client).tf 8 | end 9 | 10 | def self.tfstate(client: Aws::SQS::Client.new) 11 | self.new(client).tfstate 12 | end 13 | 14 | def initialize(client) 15 | @client = client 16 | end 17 | 18 | def tf 19 | apply_template(@client, "tf/sqs") 20 | end 21 | 22 | def tfstate 23 | queues.inject({}) do |resources, queue| 24 | attributes = { 25 | "name" => module_name_of(queue), 26 | "id" => queue["QueueUrl"], 27 | "arn" => queue["QueueArn"], 28 | "visibility_timeout_seconds" => queue["VisibilityTimeout"], 29 | "message_retention_seconds" => queue["MessageRetentionPeriod"], 30 | "max_message_size" => queue["MaximumMessageSize"], 31 | "delay_seconds" => queue["DelaySeconds"], 32 | "receive_wait_time_seconds" => queue["ReceiveMessageWaitTimeSeconds"], 33 | "policy" => queue.key?("Policy") ? queue["Policy"] : "", 34 | "redrive_policy" => queue.key?("RedrivePolicy") ? queue["RedrivePolicy"] : "", 35 | } 36 | resources["aws_sqs_queue.#{module_name_of(queue)}"] = { 37 | "type" => "aws_sqs_queue", 38 | "primary" => { 39 | "id" => queue["QueueUrl"], 40 | "attributes" => attributes, 41 | } 42 | } 43 | 44 | resources 45 | end 46 | end 47 | 48 | private 49 | 50 | def queues 51 | queue_urls.map do |queue_url| 52 | attributes = @client.get_queue_attributes({ 53 | queue_url: queue_url, 54 | attribute_names: ["All"], 55 | }).attributes 56 | attributes["QueueUrl"] = queue_url 57 | attributes 58 | end 59 | end 60 | 61 | def queue_urls 62 | @client.list_queues.map(&:queue_urls).flatten 63 | end 64 | 65 | def module_name_of(queue) 66 | normalize_module_name(queue["QueueArn"].split(":").last) 67 | end 68 | end 69 | end 70 | end 71 | -------------------------------------------------------------------------------- /lib/terraforming/resource/subnet.rb: -------------------------------------------------------------------------------- 1 | module Terraforming 2 | module Resource 3 | class Subnet 4 | include Terraforming::Util 5 | 6 | def self.tf(client: Aws::EC2::Client.new) 7 | self.new(client).tf 8 | end 9 | 10 | def self.tfstate(client: Aws::EC2::Client.new) 11 | self.new(client).tfstate 12 | end 13 | 14 | def initialize(client) 15 | @client = client 16 | end 17 | 18 | def tf 19 | apply_template(@client, "tf/subnet") 20 | end 21 | 22 | def tfstate 23 | subnets.inject({}) do |resources, subnet| 24 | attributes = { 25 | "availability_zone" => subnet.availability_zone, 26 | "cidr_block" => subnet.cidr_block, 27 | "id" => subnet.subnet_id, 28 | "map_public_ip_on_launch" => subnet.map_public_ip_on_launch.to_s, 29 | "tags.#" => subnet.tags.length.to_s, 30 | "vpc_id" => subnet.vpc_id, 31 | } 32 | resources["aws_subnet.#{module_name_of(subnet)}"] = { 33 | "type" => "aws_subnet", 34 | "primary" => { 35 | "id" => subnet.subnet_id, 36 | "attributes" => attributes 37 | } 38 | } 39 | 40 | resources 41 | end 42 | end 43 | 44 | private 45 | 46 | def subnets 47 | @client.describe_subnets.map(&:subnets).flatten 48 | end 49 | 50 | def module_name_of(subnet) 51 | normalize_module_name("#{subnet.subnet_id}-#{name_from_tag(subnet, subnet.subnet_id)}") 52 | end 53 | end 54 | end 55 | end 56 | -------------------------------------------------------------------------------- /lib/terraforming/resource/vpc.rb: -------------------------------------------------------------------------------- 1 | module Terraforming 2 | module Resource 3 | class VPC 4 | include Terraforming::Util 5 | 6 | def self.tf(client: Aws::EC2::Client.new) 7 | self.new(client).tf 8 | end 9 | 10 | def self.tfstate(client: Aws::EC2::Client.new) 11 | self.new(client).tfstate 12 | end 13 | 14 | def initialize(client) 15 | @client = client 16 | end 17 | 18 | def tf 19 | apply_template(@client, "tf/vpc") 20 | end 21 | 22 | def tfstate 23 | vpcs.inject({}) do |resources, vpc| 24 | attributes = { 25 | "cidr_block" => vpc.cidr_block, 26 | "enable_dns_hostnames" => enable_dns_hostnames?(vpc).to_s, 27 | "enable_dns_support" => enable_dns_support?(vpc).to_s, 28 | "id" => vpc.vpc_id, 29 | "instance_tenancy" => vpc.instance_tenancy, 30 | "tags.#" => vpc.tags.length.to_s, 31 | } 32 | resources["aws_vpc.#{module_name_of(vpc)}"] = { 33 | "type" => "aws_vpc", 34 | "primary" => { 35 | "id" => vpc.vpc_id, 36 | "attributes" => attributes 37 | } 38 | } 39 | 40 | resources 41 | end 42 | end 43 | 44 | private 45 | 46 | def enable_dns_hostnames?(vpc) 47 | vpc_attribute(vpc, :enableDnsHostnames).enable_dns_hostnames.value 48 | end 49 | 50 | def enable_dns_support?(vpc) 51 | vpc_attribute(vpc, :enableDnsSupport).enable_dns_support.value 52 | end 53 | 54 | def module_name_of(vpc) 55 | normalize_module_name(name_from_tag(vpc, vpc.vpc_id)) 56 | end 57 | 58 | def vpcs 59 | @client.describe_vpcs.map(&:vpcs).flatten 60 | end 61 | 62 | def vpc_attribute(vpc, attribute) 63 | @client.describe_vpc_attribute(vpc_id: vpc.vpc_id, attribute: attribute) 64 | end 65 | end 66 | end 67 | end 68 | -------------------------------------------------------------------------------- /lib/terraforming/resource/vpn_gateway.rb: -------------------------------------------------------------------------------- 1 | module Terraforming 2 | module Resource 3 | class VPNGateway 4 | include Terraforming::Util 5 | 6 | def self.tf(client: Aws::EC2::Client.new) 7 | self.new(client).tf 8 | end 9 | 10 | def self.tfstate(client: Aws::EC2::Client.new) 11 | self.new(client).tfstate 12 | end 13 | 14 | def initialize(client) 15 | @client = client 16 | end 17 | 18 | def tf 19 | apply_template(@client, "tf/vpn_gateway") 20 | end 21 | 22 | def tfstate 23 | vpn_gateways.inject({}) do |resources, vpn_gateway| 24 | next resources if vpn_gateway.vpc_attachments.empty? 25 | 26 | attributes = { 27 | "id" => vpn_gateway.vpn_gateway_id, 28 | "vpc_id" => vpn_gateway.vpc_attachments[0].vpc_id, 29 | "availability_zone" => vpn_gateway.availability_zone, 30 | "tags.#" => vpn_gateway.tags.length.to_s, 31 | } 32 | resources["aws_vpn_gateway.#{module_name_of(vpn_gateway)}"] = { 33 | "type" => "aws_vpn_gateway", 34 | "primary" => { 35 | "id" => vpn_gateway.vpn_gateway_id, 36 | "attributes" => attributes 37 | } 38 | } 39 | 40 | resources 41 | end 42 | end 43 | 44 | private 45 | 46 | def vpn_gateways 47 | @client.describe_vpn_gateways.map(&:vpn_gateways).flatten 48 | end 49 | 50 | def module_name_of(vpn_gateway) 51 | normalize_module_name(name_from_tag(vpn_gateway, vpn_gateway.vpn_gateway_id)) 52 | end 53 | end 54 | end 55 | end 56 | -------------------------------------------------------------------------------- /lib/terraforming/template/tf/alb.erb: -------------------------------------------------------------------------------- 1 | <% load_balancers.each do |load_balancer| -%> 2 | <%- load_balancer_attributes = load_balancer_attributes_of(load_balancer) -%> 3 | <%- tags = tags_of(load_balancer) -%> 4 | resource "aws_alb" "<%= module_name_of(load_balancer) %>" { 5 | idle_timeout = <%= load_balancer_attributes["idle_timeout.timeout_seconds"] %> 6 | internal = <%= internal?(load_balancer).to_s %> 7 | name = "<%= load_balancer.load_balancer_name %>" 8 | security_groups = <%= load_balancer.security_groups.inspect %> 9 | subnets = <%= load_balancer.availability_zones.map { |az| az.subnet_id }.inspect %> 10 | 11 | enable_deletion_protection = <%= load_balancer_attributes["deletion_protection.enabled"].to_s %> 12 | 13 | <%- if load_balancer_attributes["access_logs.s3.enabled"] == "true" -%> 14 | access_logs { 15 | bucket = "<%= load_balancer_attributes["access_logs.s3.bucket"] %>" 16 | enabled = <%= load_balancer_attributes["access_logs.s3.enabled"] %> 17 | prefix = "<%= load_balancer_attributes["access_logs.s3.prefix"] %>" 18 | } 19 | 20 | <%- end -%> 21 | tags { 22 | <% tags.each do |tag| -%> 23 | "<%= tag.key %>" = "<%= tag.value %>" 24 | <% end -%> 25 | } 26 | } 27 | 28 | <% end -%> 29 | -------------------------------------------------------------------------------- /lib/terraforming/template/tf/auto_scaling_group.erb: -------------------------------------------------------------------------------- 1 | <% auto_scaling_groups.each do |group| -%> 2 | <%- vpc_zone_specified = vpc_zone_specified?(group) -%> 3 | resource "aws_autoscaling_group" "<%= module_name_of(group) %>" { 4 | <%- unless vpc_zone_specified -%> 5 | availability_zones = <%= group.availability_zones.inspect %> 6 | <%- end -%> 7 | desired_capacity = <%= group.desired_capacity %> 8 | health_check_grace_period = <%= group.health_check_grace_period %> 9 | health_check_type = "<%= group.health_check_type %>" 10 | launch_configuration = "<%= group.launch_configuration_name %>" 11 | max_size = <%= group.max_size %> 12 | min_size = <%= group.min_size %> 13 | name = "<%= group.auto_scaling_group_name %>" 14 | <%- if vpc_zone_specified -%> 15 | vpc_zone_identifier = <%= vpc_zone_identifier_of(group).inspect %> 16 | <%- end -%> 17 | 18 | <% group.tags.each do |tag| -%> 19 | tag { 20 | key = "<%= tag.key %>" 21 | value = "<%= tag.value %>" 22 | propagate_at_launch = <%= tag.propagate_at_launch.to_s %> 23 | } 24 | 25 | <% end -%> 26 | } 27 | 28 | <% end -%> 29 | -------------------------------------------------------------------------------- /lib/terraforming/template/tf/cloud_watch_alarm.erb: -------------------------------------------------------------------------------- 1 | <% alarms.each do |alarm| -%> 2 | resource "aws_cloudwatch_metric_alarm" "<%= normalize_module_name(alarm.alarm_name) %>" { 3 | alarm_name = "<%= alarm.alarm_name %>" 4 | comparison_operator = "<%= alarm.comparison_operator %>" 5 | evaluation_periods = "<%= alarm.evaluation_periods %>" 6 | metric_name = "<%= alarm.metric_name %>" 7 | namespace = "<%= alarm.namespace %>" 8 | period = "<%= alarm.period %>" 9 | statistic = "<%= alarm.statistic %>" 10 | threshold = "<%= alarm.threshold %>" 11 | alarm_description = "<%= alarm.alarm_description %>" 12 | <%- unless alarm.ok_actions.empty? -%> 13 | ok_actions = <%= alarm.ok_actions %> 14 | <%- end -%> 15 | <%- unless alarm.alarm_actions.empty? -%> 16 | alarm_actions = <%= alarm.alarm_actions %> 17 | <%- end -%> 18 | <%- unless alarm.actions_enabled -%> 19 | actions_enabled = <%= alarm.actions_enabled %> 20 | <%- end -%> 21 | <%- unless alarm.dimensions.empty? -%> 22 | dimensions { 23 | <% alarm.dimensions.each do |dimension| -%> 24 | <%= dimension.name %> = "<%= dimension.value %>" 25 | <% end -%> 26 | } 27 | <%- end -%> 28 | <%- unless alarm.insufficient_data_actions.empty? -%> 29 | insufficient_data_actions = <%= alarm.insufficient_data_actions %> 30 | <%- end -%> 31 | } 32 | 33 | <%- end -%> 34 | -------------------------------------------------------------------------------- /lib/terraforming/template/tf/db_parameter_group.erb: -------------------------------------------------------------------------------- 1 | <% db_parameter_groups.each do |parameter_group| -%> 2 | resource "aws_db_parameter_group" "<%= module_name_of(parameter_group) %>" { 3 | name = "<%= parameter_group.db_parameter_group_name %>" 4 | family = "<%= parameter_group.db_parameter_group_family %>" 5 | description = "<%= parameter_group.description %>" 6 | 7 | <% db_parameters_in(parameter_group).each do |parameter| -%> 8 | parameter { 9 | name = "<%= parameter.parameter_name %>" 10 | value = "<%= parameter.parameter_value || '' %>" 11 | apply_method = "<%= parameter.apply_method || 'immediate' %>" 12 | } 13 | 14 | <% end -%> 15 | } 16 | 17 | <% end -%> 18 | -------------------------------------------------------------------------------- /lib/terraforming/template/tf/db_security_group.erb: -------------------------------------------------------------------------------- 1 | <% db_security_groups.each do |security_group| -%> 2 | resource "aws_db_security_group" "<%= module_name_of(security_group) %>" { 3 | name = "<%= security_group.db_security_group_name %>" 4 | description = "<%= security_group.db_security_group_description %>" 5 | 6 | <% security_group.ip_ranges.each do |cidr| -%> 7 | ingress { 8 | cidr = "<%= cidr.cidrip %>" 9 | security_group_name = "" 10 | security_group_id = "" 11 | security_group_owner_id = "" 12 | } 13 | 14 | <% end -%> 15 | <% security_group.ec2_security_groups.each do |ec2_sg| -%> 16 | ingress { 17 | cidr = "" 18 | security_group_name = "<%= ec2_sg.ec2_security_group_name %>" 19 | security_group_id = "<%= ec2_sg.ec2_security_group_id %>" 20 | security_group_owner_id = "<%= ec2_sg.ec2_security_group_owner_id %>" 21 | } 22 | 23 | <% end -%> 24 | } 25 | 26 | <% end -%> 27 | -------------------------------------------------------------------------------- /lib/terraforming/template/tf/db_subnet_group.erb: -------------------------------------------------------------------------------- 1 | <% db_subnet_groups.each do |subnet_group| -%> 2 | resource "aws_db_subnet_group" "<%= module_name_of(subnet_group) %>" { 3 | name = "<%= subnet_group.db_subnet_group_name %>" 4 | description = "<%= subnet_group.db_subnet_group_description %>" 5 | subnet_ids = <%= subnet_group.subnets.map { |subnet| subnet.subnet_identifier }.inspect %> 6 | } 7 | 8 | <% end -%> 9 | -------------------------------------------------------------------------------- /lib/terraforming/template/tf/dynamo_db.erb: -------------------------------------------------------------------------------- 1 | <%- tables.each do |table| -%> 2 | resource "aws_dynamodb_table" "<%= table.table_name -%>" { 3 | name = "<%= table.table_name -%>" 4 | read_capacity = <%= table.provisioned_throughput.read_capacity_units %> 5 | write_capacity = <%= table.provisioned_throughput.write_capacity_units %> 6 | <%- table.key_schema.each do |key| -%> 7 | <%= key.key_type.downcase -%>_key = <%= key.attribute_name.inspect %> 8 | <%- end %> 9 | <%- table.attribute_definitions.each do |attribute| -%> 10 | attribute { 11 | name = "<%= attribute.attribute_name -%>" 12 | type = "<%= attribute.attribute_type -%>" 13 | } 14 | <%- end -%> 15 | <%- ttl_values(table).each do |attr| -%> 16 | ttl { 17 | attribute_name = <%= attr.inspect %> 18 | enabled = true 19 | } 20 | <%- end -%> 21 | <%- Array(table.global_secondary_indexes).each do |index| -%> 22 | global_secondary_index { 23 | name = "<%= index.index_name -%>" 24 | <%- index.key_schema.each do |key| -%> 25 | <%= key.key_type.downcase -%>_key = "<%= key.attribute_name -%>" 26 | <%- end -%> 27 | read_capacity = <%= index.provisioned_throughput.read_capacity_units %> 28 | write_capacity = <%= index.provisioned_throughput.write_capacity_units %> 29 | projection_type = "<%= index.projection.projection_type %>" 30 | <%- keys = index.projection.non_key_attributes -%> 31 | <%- if Array(keys).size > 0 -%> 32 | non_key_attributes = <%= keys.inspect -%> 33 | <%- end %> 34 | } 35 | <%- end -%> 36 | <%- Array(table.local_secondary_indexes).each do |index| -%> 37 | local_secondary_index { 38 | name = "<%= index.index_name -%>" 39 | <%- index.key_schema.each do |key| -%> 40 | <%- if key.key_type.downcase == "range" -%> 41 | <%= key.key_type.downcase -%>_key = "<%= key.attribute_name -%>" 42 | <%- end -%> 43 | <%- end -%> 44 | projection_type = "<%= index.projection.projection_type -%>" 45 | <%- keys = index.projection.non_key_attributes -%> 46 | <%- if Array(keys).size > 0 -%> 47 | non_key_attributes = <%= keys.inspect -%> 48 | <%- end %> 49 | } 50 | <%- end -%> 51 | <%- tags(table).each do |tag| -%> 52 | tags { 53 | <%= tag.key %> = "<%= tag.value -%>" 54 | } 55 | <%- end -%> 56 | <%- if table.stream_specification -%> 57 | stream_enabled = <%= table.stream_specification.stream_enabled %> 58 | stream_view_type = <%= table.stream_specification.stream_view_type.inspect %> 59 | <%- end -%> 60 | <%- if table.sse_description -%> 61 | server_side_encryption { 62 | enabled = true 63 | } 64 | <%- end -%> 65 | } 66 | <%- end -%> -------------------------------------------------------------------------------- /lib/terraforming/template/tf/ec2.erb: -------------------------------------------------------------------------------- 1 | <% instances.each do |instance| -%> 2 | resource "aws_instance" "<%= module_name_of(instance) %>" { 3 | ami = "<%= instance.image_id %>" 4 | availability_zone = "<%= instance.placement.availability_zone %>" 5 | ebs_optimized = <%= instance.ebs_optimized %> 6 | instance_type = "<%= instance.instance_type %>" 7 | <%- unless instance.placement.group_name.empty? -%> 8 | placement_group = "<%= instance.placement.group_name %>" 9 | <%- end -%> 10 | monitoring = <%= monitoring_state(instance) %> 11 | key_name = "<%= instance.key_name %>" 12 | <%- if in_vpc?(instance) -%> 13 | subnet_id = "<%= instance.subnet_id %>" 14 | vpc_security_group_ids = <%= instance.security_groups.map { |sg| sg.group_id }.inspect %> 15 | <%- else -%> 16 | security_groups = <%= instance.security_groups.map { |sg| sg.group_name }.inspect %> 17 | <%- end -%> 18 | associate_public_ip_address = <%= associate_public_ip?(instance) %> 19 | private_ip = "<%= instance.private_ip_address %>" 20 | <%- if instance.source_dest_check -%> 21 | source_dest_check = <%= instance.source_dest_check %> 22 | <%- end -%> 23 | 24 | <% block_devices_of(instance).each do |block_device| -%> 25 | <%- mapping = block_device_mapping_of(instance, block_device.volume_id) -%> 26 | <%- if root_block_device?(mapping, instance) -%> 27 | root_block_device { 28 | volume_type = "<%= block_device.volume_type %>" 29 | volume_size = <%= block_device.size %> 30 | delete_on_termination = <%= mapping.ebs.delete_on_termination %> 31 | <%- if block_device.volume_type == "io1" && block_device.iops -%> 32 | iops = <%= block_device.iops %> 33 | <%- end -%> 34 | } 35 | <%- else -%> 36 | ebs_block_device { 37 | device_name = "<%= mapping.device_name %>" 38 | snapshot_id = "<%= block_device.snapshot_id %>" 39 | volume_type = "<%= block_device.volume_type %>" 40 | volume_size = <%= block_device.size %> 41 | delete_on_termination = <%= mapping.ebs.delete_on_termination %> 42 | <%- if block_device.volume_type == "io1" && block_device.iops -%> 43 | iops = <%= block_device.iops %> 44 | <%- end -%> 45 | } 46 | <% end -%> 47 | 48 | <% end -%> 49 | tags { 50 | <% instance.tags.each do |tag| -%> 51 | "<%= tag.key %>" = "<%= tag.value %>" 52 | <% end -%> 53 | } 54 | } 55 | 56 | <% end -%> 57 | -------------------------------------------------------------------------------- /lib/terraforming/template/tf/eip.erb: -------------------------------------------------------------------------------- 1 | <% eips.each do |addr| -%> 2 | resource "aws_eip" "<%= module_name_of(addr) %>" { 3 | <% if addr.instance_id -%> 4 | instance = "<%= addr.instance_id %>" 5 | <% elsif addr.network_interface_id -%> 6 | network_interface = "<%= addr.network_interface_id %>" 7 | <% end -%> 8 | vpc = <%= vpc?(addr) %> 9 | } 10 | 11 | <% end -%> 12 | -------------------------------------------------------------------------------- /lib/terraforming/template/tf/elasti_cache_cluster.erb: -------------------------------------------------------------------------------- 1 | <% cache_clusters.each do |cache_cluster| -%> 2 | resource "aws_elasticache_cluster" "<%= module_name_of(cache_cluster) %>" { 3 | cluster_id = "<%= cache_cluster.cache_cluster_id %>" 4 | engine = "<%= cache_cluster.engine %>" 5 | engine_version = "<%= cache_cluster.engine_version %>" 6 | node_type = "<%= cache_cluster.cache_node_type %>" 7 | num_cache_nodes = <%= cache_cluster.num_cache_nodes %> 8 | parameter_group_name = "<%= cache_cluster.cache_parameter_group.cache_parameter_group_name %>" 9 | <%- if cache_cluster.configuration_endpoint -%> 10 | port = <%= cache_cluster.configuration_endpoint.port %> 11 | <%- else -%> 12 | port = <%= cache_cluster.cache_nodes[0].endpoint.port %> 13 | <%- end -%> 14 | <%- if cluster_in_vpc?(cache_cluster) -%> 15 | subnet_group_name = "<%= cache_cluster.cache_subnet_group_name %>" 16 | security_group_ids = <%= security_group_ids_of(cache_cluster).inspect %> 17 | <%- else -%> 18 | security_group_names = <%= security_group_names_of(cache_cluster).inspect %> 19 | <%- end -%> 20 | <%- if cache_cluster.notification_configuration -%> 21 | notification_topic_arn = "<%= cache_cluster.notification_configuration.topic_arn %>" 22 | <%- end -%> 23 | } 24 | 25 | <% end -%> 26 | -------------------------------------------------------------------------------- /lib/terraforming/template/tf/elasti_cache_subnet_group.erb: -------------------------------------------------------------------------------- 1 | <% cache_subnet_groups.each do |cache_subnet_group| -%> 2 | resource "aws_elasticache_subnet_group" "<%= module_name_of(cache_subnet_group) %>" { 3 | name = "<%= cache_subnet_group.cache_subnet_group_name %>" 4 | description = "<%= cache_subnet_group.cache_subnet_group_description %>" 5 | subnet_ids = <%= subnet_ids_of(cache_subnet_group).inspect %> 6 | } 7 | 8 | <% end -%> 9 | -------------------------------------------------------------------------------- /lib/terraforming/template/tf/elastic_file_system.erb: -------------------------------------------------------------------------------- 1 | <% file_systems.each_with_index do |efs, idx| -%> 2 | resource "aws_efs_file_system" "<%= module_name_of(efs) %>" { 3 | <% if efs.creation_token -%> 4 | creation_token = "<%= efs.creation_token %>" 5 | <% end -%> 6 | <% if efs.file_system_id -%> 7 | file_system_id = "<%= efs.file_system_id %>" 8 | <% end -%> 9 | <% if efs.performance_mode -%> 10 | performance_mode = "<%= efs.performance_mode %>" 11 | <% end -%> 12 | <% if efs.name -%> 13 | tags { 14 | Name = "<%= efs.name %>" 15 | } 16 | <% end -%> 17 | } 18 | <% end -%> 19 | -------------------------------------------------------------------------------- /lib/terraforming/template/tf/elb.erb: -------------------------------------------------------------------------------- 1 | <% load_balancers.each do |load_balancer| -%> 2 | <%- load_balancer_attributes = load_balancer_attributes_of(load_balancer) -%> 3 | resource "aws_elb" "<%= module_name_of(load_balancer) %>" { 4 | name = "<%= load_balancer.load_balancer_name %>" 5 | <%- if vpc_elb?(load_balancer) -%> 6 | subnets = <%= load_balancer.subnets.inspect %> 7 | <%- else -%> 8 | availability_zones = <%= load_balancer.availability_zones.inspect %> 9 | <%- end -%> 10 | security_groups = <%= load_balancer.security_groups.inspect %> 11 | instances = <%= load_balancer.instances.map { |instance| instance.instance_id }.inspect %> 12 | cross_zone_load_balancing = <%= load_balancer_attributes.cross_zone_load_balancing.enabled %> 13 | idle_timeout = <%= load_balancer_attributes.connection_settings.idle_timeout %> 14 | connection_draining = <%= load_balancer_attributes.connection_draining.enabled %> 15 | connection_draining_timeout = <%= load_balancer_attributes.connection_draining.timeout %> 16 | internal = <%= internal?(load_balancer).to_s %> 17 | 18 | <%- if load_balancer_attributes.access_log.enabled -%> 19 | access_logs { 20 | bucket = "<%= load_balancer_attributes.access_log.s3_bucket_name %>" 21 | bucket_prefix = "<%= load_balancer_attributes.access_log.s3_bucket_prefix %>" 22 | interval = <%= load_balancer_attributes.access_log.emit_interval %> 23 | } 24 | 25 | <%- end -%> 26 | <% load_balancer.listener_descriptions.map { |ld| ld.listener }.map do |listener| -%> 27 | listener { 28 | instance_port = <%= listener.instance_port %> 29 | instance_protocol = "<%= listener.instance_protocol.downcase %>" 30 | lb_port = <%= listener.load_balancer_port %> 31 | lb_protocol = "<%= listener.protocol.downcase %>" 32 | ssl_certificate_id = "<%= listener.ssl_certificate_id %>" 33 | } 34 | 35 | <% end -%> 36 | health_check { 37 | healthy_threshold = <%= load_balancer.health_check.healthy_threshold %> 38 | unhealthy_threshold = <%= load_balancer.health_check.unhealthy_threshold %> 39 | interval = <%= load_balancer.health_check.interval %> 40 | target = "<%= load_balancer.health_check.target %>" 41 | timeout = <%= load_balancer.health_check.timeout %> 42 | } 43 | 44 | tags { 45 | <% @client.describe_tags(load_balancer_names: [load_balancer.load_balancer_name]).tag_descriptions.first.tags.each do |tag| -%> 46 | "<%= tag.key %>" = "<%= tag.value %>" 47 | <% end -%> 48 | } 49 | } 50 | 51 | <% end -%> 52 | -------------------------------------------------------------------------------- /lib/terraforming/template/tf/iam_group.erb: -------------------------------------------------------------------------------- 1 | <% iam_groups.each do |group| -%> 2 | resource "aws_iam_group" "<%= module_name_of(group) %>" { 3 | name = "<%= group.group_name %>" 4 | path = "<%= group.path %>" 5 | } 6 | 7 | <% end -%> 8 | -------------------------------------------------------------------------------- /lib/terraforming/template/tf/iam_group_membership.erb: -------------------------------------------------------------------------------- 1 | <% iam_groups.each do |group| -%> 2 | resource "aws_iam_group_membership" "<%= module_name_of(group) %>" { 3 | name = "<%= membership_name_of(group) %>" 4 | users = <%= group_members_of(group).inspect %> 5 | group = "<%= group.group_name %>" 6 | } 7 | 8 | <% end -%> 9 | -------------------------------------------------------------------------------- /lib/terraforming/template/tf/iam_group_policy.erb: -------------------------------------------------------------------------------- 1 | <% iam_group_policies.each do |policy| -%> 2 | resource "aws_iam_group_policy" "<%= unique_name(policy) %>" { 3 | name = "<%= policy.policy_name %>" 4 | group = "<%= policy.group_name %>" 5 | policy = < 7 | POLICY 8 | } 9 | 10 | <% end -%> 11 | -------------------------------------------------------------------------------- /lib/terraforming/template/tf/iam_instance_profile.erb: -------------------------------------------------------------------------------- 1 | <% iam_instance_profiles.each do |profile| -%> 2 | resource "aws_iam_instance_profile" "<%= module_name_of(profile) %>" { 3 | name = "<%= profile.instance_profile_name %>" 4 | path = "<%= profile.path %>" 5 | <%- if profile.roles[0] != nil -%> 6 | role = "<%= profile.roles[0].role_name %>" 7 | <%- end -%> 8 | } 9 | 10 | <% end -%> 11 | -------------------------------------------------------------------------------- /lib/terraforming/template/tf/iam_policy.erb: -------------------------------------------------------------------------------- 1 | <% iam_policies.each do |policy| -%> 2 | <%- version = iam_policy_version_of(policy) -%> 3 | resource "aws_iam_policy" "<%= module_name_of(policy) %>" { 4 | name = "<%= policy.policy_name %>" 5 | path = "<%= policy.path %>" 6 | description = "<%= iam_policy_description(policy) %>" 7 | policy = < 9 | POLICY 10 | } 11 | 12 | <% end -%> 13 | -------------------------------------------------------------------------------- /lib/terraforming/template/tf/iam_policy_attachment.erb: -------------------------------------------------------------------------------- 1 | <% iam_policy_attachments.each do |policy_attachment| -%> 2 | resource "aws_iam_policy_attachment" "<%= module_name_of(policy_attachment) %>" { 3 | name = "<%= policy_attachment[:name] %>" 4 | policy_arn = "<%= policy_attachment[:arn] %>" 5 | groups = <%= policy_attachment[:entities].policy_groups.map(&:group_name).inspect %> 6 | users = <%= policy_attachment[:entities].policy_users.map(&:user_name).inspect %> 7 | roles = <%= policy_attachment[:entities].policy_roles.map(&:role_name).inspect %> 8 | } 9 | 10 | <% end -%> 11 | -------------------------------------------------------------------------------- /lib/terraforming/template/tf/iam_role.erb: -------------------------------------------------------------------------------- 1 | <% iam_roles.each do |role| -%> 2 | resource "aws_iam_role" "<%= module_name_of(role) %>" { 3 | name = "<%= role.role_name %>" 4 | path = "<%= role.path %>" 5 | assume_role_policy = < 7 | POLICY 8 | } 9 | 10 | <% end -%> 11 | -------------------------------------------------------------------------------- /lib/terraforming/template/tf/iam_role_policy.erb: -------------------------------------------------------------------------------- 1 | <% iam_role_policies.each do |policy| -%> 2 | resource "aws_iam_role_policy" "<%= unique_name(policy) %>" { 3 | name = "<%= policy.policy_name %>" 4 | role = "<%= policy.role_name %>" 5 | policy = < 7 | POLICY 8 | } 9 | 10 | <% end -%> 11 | -------------------------------------------------------------------------------- /lib/terraforming/template/tf/iam_user.erb: -------------------------------------------------------------------------------- 1 | <% iam_users.each do |user| -%> 2 | resource "aws_iam_user" "<%= module_name_of(user) %>" { 3 | name = "<%= user.user_name %>" 4 | path = "<%= user.path %>" 5 | } 6 | 7 | <% end -%> 8 | -------------------------------------------------------------------------------- /lib/terraforming/template/tf/iam_user_policy.erb: -------------------------------------------------------------------------------- 1 | <% iam_user_policies.each do |policy| -%> 2 | resource "aws_iam_user_policy" "<%= unique_name(policy) %>" { 3 | name = "<%= policy.policy_name %>" 4 | user = "<%= policy.user_name %>" 5 | policy = < 7 | POLICY 8 | } 9 | 10 | <% end -%> 11 | -------------------------------------------------------------------------------- /lib/terraforming/template/tf/internet_gateway.erb: -------------------------------------------------------------------------------- 1 | <% internet_gateways.each do |internet_gateway| -%> 2 | <% unless internet_gateway.attachments.empty? -%> 3 | resource "aws_internet_gateway" "<%= module_name_of(internet_gateway) %>" { 4 | vpc_id = "<%= internet_gateway.attachments[0].vpc_id %>" 5 | 6 | tags { 7 | <% internet_gateway.tags.each do |tag| -%> 8 | "<%= tag.key %>" = "<%= tag.value %>" 9 | <% end -%> 10 | } 11 | } 12 | 13 | <% end -%> 14 | <% end -%> 15 | -------------------------------------------------------------------------------- /lib/terraforming/template/tf/kms_alias.erb: -------------------------------------------------------------------------------- 1 | <% aliases.each do |als| -%> 2 | resource "aws_kms_alias" "<%= module_name_of(als) %>" { 3 | name = "<%= als.alias_name %>" 4 | target_key_id = "<%= als.target_key_id %>" 5 | } 6 | 7 | <% end -%> 8 | -------------------------------------------------------------------------------- /lib/terraforming/template/tf/kms_key.erb: -------------------------------------------------------------------------------- 1 | <% keys.each do |key| -%> 2 | resource "aws_kms_key" "<%= module_name_of(key) %>" { 3 | description = "<%= key.description %>" 4 | key_usage = "<%= key.key_usage %>" 5 | is_enabled = <%= key.enabled %> 6 | enable_key_rotation = <%= key_rotation_status_of(key).key_rotation_enabled %> 7 | 8 | policy = < 10 | POLICY 11 | } 12 | 13 | <% end -%> 14 | -------------------------------------------------------------------------------- /lib/terraforming/template/tf/launch_configuration.erb: -------------------------------------------------------------------------------- 1 | <% launch_configurations.each do |launch_configuration| -%> 2 | resource "aws_launch_configuration" "<%= module_name_of(launch_configuration) %>" { 3 | name = "<%= launch_configuration.launch_configuration_name %>" 4 | image_id = "<%= launch_configuration.image_id %>" 5 | instance_type = "<%= launch_configuration.instance_type %>" 6 | <%- if launch_configuration.iam_instance_profile -%> 7 | iam_instance_profile = "<%= launch_configuration.iam_instance_profile %>" 8 | <%- end -%> 9 | <%- unless launch_configuration.key_name.empty? -%> 10 | key_name = "<%= launch_configuration.key_name %>" 11 | <%- end -%> 12 | security_groups = <%= launch_configuration.security_groups.map { |sg| sg }.inspect %> 13 | <%- unless launch_configuration.associate_public_ip_address.nil? -%> 14 | associate_public_ip_address = <%= launch_configuration.associate_public_ip_address %> 15 | <%- end -%> 16 | <%- unless launch_configuration.user_data.empty? -%> 17 | user_data = "<%= launch_configuration.user_data %>" 18 | <%- end -%> 19 | enable_monitoring = <%= launch_configuration.instance_monitoring.enabled %> 20 | ebs_optimized = <%= launch_configuration.ebs_optimized %> 21 | <%- if launch_configuration.spot_price -%> 22 | spot_price = "<%= launch_configuration.spot_price %>" 23 | <%- end -%> 24 | <%- if launch_configuration.placement_tenancy -%> 25 | placement_tenancy = "<%= launch_configuration.placement_tenancy %>" 26 | <%- end -%> 27 | 28 | <% launch_configuration.block_device_mappings.each do |block_device| -%> 29 | <%- if root_block_device?(block_device) -%> 30 | root_block_device { 31 | <%- if ebs_block_device?(block_device) -%> 32 | volume_type = "<%= block_device.ebs.volume_type %>" 33 | volume_size = <%= block_device.ebs.volume_size %> 34 | <%- if block_device.ebs.iops -%> 35 | iops = <%= block_device.ebs.iops %> 36 | <%- end -%> 37 | delete_on_termination = <%= block_device.ebs.delete_on_termination %> 38 | <%- end -%> 39 | } 40 | 41 | <%- elsif ebs_block_device?(block_device) -%> 42 | ebs_block_device { 43 | device_name = "<%= block_device.device_name %>" 44 | <%- if block_device.ebs.snapshot_id -%> 45 | snapshot_id = "<%= block_device.ebs.snapshot_id %>" 46 | <%- end -%> 47 | volume_type = "<%= block_device.ebs.volume_type %>" 48 | volume_size = <%= block_device.ebs.volume_size %> 49 | <%- if block_device.ebs.iops -%> 50 | iops = <%= block_device.ebs.iops %> 51 | <%- end -%> 52 | delete_on_termination = <%= block_device.ebs.delete_on_termination %> 53 | <%- if block_device.ebs.encrypted -%> 54 | encrypted = <%= block_device.ebs.encrypted %> 55 | <%- end -%> 56 | } 57 | 58 | <%- elsif ephemeral_block_device?(block_device) -%> 59 | ephemeral_block_device { 60 | device_name = "<%= block_device.device_name %>" 61 | virtual_name = "<%= block_device.virtual_name %>" 62 | } 63 | 64 | <%- end -%> 65 | <%- end -%> 66 | } 67 | 68 | <%- end -%> 69 | -------------------------------------------------------------------------------- /lib/terraforming/template/tf/nat_gateway.erb: -------------------------------------------------------------------------------- 1 | <% nat_gateways.each do |nat_gateway| -%> 2 | <% unless nat_gateway.nat_gateway_addresses.empty? -%> 3 | resource "aws_nat_gateway" "<%= module_name_of(nat_gateway) %>" { 4 | allocation_id = "<%= nat_gateway.nat_gateway_addresses[0].allocation_id %>" 5 | subnet_id = "<%= nat_gateway.subnet_id %>" 6 | } 7 | 8 | <% end -%> 9 | <% end -%> 10 | -------------------------------------------------------------------------------- /lib/terraforming/template/tf/network_acl.erb: -------------------------------------------------------------------------------- 1 | <% network_acls.each do |network_acl| -%> 2 | resource "aws_network_acl" "<%= module_name_of(network_acl) %>" { 3 | vpc_id = "<%= network_acl.vpc_id %>" 4 | subnet_ids = <%= subnet_ids_of(network_acl).inspect %> 5 | 6 | <% ingresses_of(network_acl).each do |ingress| -%> 7 | ingress { 8 | from_port = <%= from_port_of(ingress) %> 9 | to_port = <%= to_port_of(ingress) %> 10 | rule_no = <%= ingress.rule_number %> 11 | action = "<%= ingress.rule_action %>" 12 | protocol = "<%= ingress.protocol %>" 13 | cidr_block = "<%= ingress.cidr_block %>" 14 | <%- if ingress.icmp_type_code -%> 15 | icmp_code = "<%= ingress.icmp_type_code.code %>" 16 | icmp_type = "<%= ingress.icmp_type_code.type %>" 17 | <%- end -%> 18 | } 19 | 20 | <% end -%> 21 | <% egresses_of(network_acl).each do |egress| -%> 22 | egress { 23 | from_port = <%= from_port_of(egress) %> 24 | to_port = <%= to_port_of(egress) %> 25 | rule_no = <%= egress.rule_number %> 26 | action = "<%= egress.rule_action %>" 27 | protocol = "<%= egress.protocol %>" 28 | cidr_block = "<%= egress.cidr_block %>" 29 | <%- if egress.icmp_type_code -%> 30 | icmp_code = "<%= egress.icmp_type_code.code %>" 31 | icmp_type = "<%= egress.icmp_type_code.type %>" 32 | <%- end -%> 33 | } 34 | 35 | <% end -%> 36 | tags { 37 | <% network_acl.tags.each do |tag| -%> 38 | "<%= tag.key %>" = "<%= tag.value %>" 39 | <% end -%> 40 | } 41 | } 42 | 43 | <% end -%> 44 | -------------------------------------------------------------------------------- /lib/terraforming/template/tf/network_interface.erb: -------------------------------------------------------------------------------- 1 | <% network_interfaces.each do |network_interface| -%> 2 | resource "aws_network_interface" "<%= module_name_of(network_interface) %>" { 3 | subnet_id = "<%= network_interface.subnet_id %>" 4 | private_ips = <%= private_ips_of(network_interface).inspect %> 5 | security_groups = <%= security_groups_of(network_interface).inspect %> 6 | source_dest_check = <%= network_interface.source_dest_check %> 7 | <% if network_interface.attachment && network_interface.attachment.instance_id -%> 8 | attachment { 9 | instance = "<%= network_interface.attachment.instance_id %>" 10 | device_index = <%= network_interface.attachment.device_index %> 11 | } 12 | <% end -%> 13 | <% if network_interface.tag_set.length > 0 -%> 14 | tags { 15 | <% network_interface.tag_set.each do |tag| -%> 16 | "<%= tag.key %>" = "<%= tag.value %>" 17 | <% end -%> 18 | } 19 | <% end -%> 20 | } 21 | 22 | <% end -%> 23 | -------------------------------------------------------------------------------- /lib/terraforming/template/tf/rds.erb: -------------------------------------------------------------------------------- 1 | <% db_instances.each do |instance| -%> 2 | resource "aws_db_instance" "<%= instance.db_instance_identifier %>" { 3 | identifier = "<%= module_name_of(instance) %>" 4 | allocated_storage = <%= instance.allocated_storage %> 5 | storage_type = "<%= instance.storage_type %>" 6 | engine = "<%= instance.engine %>" 7 | engine_version = "<%= instance.engine_version %>" 8 | instance_class = "<%= instance.db_instance_class %>" 9 | name = "<%= instance.db_name %>" 10 | username = "<%= instance.master_username %>" 11 | password = "xxxxxxxx" 12 | port = <%= instance.endpoint.port %> 13 | publicly_accessible = <%= instance.publicly_accessible %> 14 | availability_zone = "<%= instance.availability_zone %>" 15 | security_group_names = <%= instance.db_security_groups.map { |sg| sg.db_security_group_name }.inspect %> 16 | vpc_security_group_ids = <%= instance.vpc_security_groups.map { |sg| sg.vpc_security_group_id }.inspect %> 17 | db_subnet_group_name = "<%= instance.db_subnet_group ? instance.db_subnet_group.db_subnet_group_name : "" %>" 18 | parameter_group_name = "<%= instance.db_parameter_groups[0].db_parameter_group_name %>" 19 | multi_az = <%= instance.multi_az %> 20 | backup_retention_period = <%= instance.backup_retention_period %> 21 | backup_window = "<%= instance.preferred_backup_window %>" 22 | maintenance_window = "<%= instance.preferred_maintenance_window %>" 23 | final_snapshot_identifier = "<%= instance.db_instance_identifier %>-final" 24 | } 25 | <% end -%> 26 | -------------------------------------------------------------------------------- /lib/terraforming/template/tf/redshift.erb: -------------------------------------------------------------------------------- 1 | <% clusters.each do |cluster| -%> 2 | resource "aws_redshift_cluster" "<%= module_name_of(cluster) %>" { 3 | cluster_identifier = "<%= cluster.cluster_identifier %>" 4 | <%- if cluster.db_name -%> 5 | database_name = "<%= cluster.db_name %>" 6 | <%- end -%> 7 | cluster_type = "<%= cluster.number_of_nodes == 1 ? "single-node" : "multi-node" %>" 8 | node_type = "<%= cluster.node_type %>" 9 | master_password = "xxxxxxxx" 10 | master_username = "<%= cluster.master_username %>" 11 | availability_zone = "<%= cluster.availability_zone %>" 12 | preferred_maintenance_window = "<%= cluster.preferred_maintenance_window %>" 13 | cluster_parameter_group_name = "<%= cluster.cluster_parameter_groups[0].parameter_group_name %>" 14 | automated_snapshot_retention_period = "<%= cluster.automated_snapshot_retention_period %>" 15 | port = "<%= cluster.endpoint.port %>" 16 | cluster_version = "<%= cluster.cluster_version %>" 17 | allow_version_upgrade = "<%= cluster.allow_version_upgrade %>" 18 | number_of_nodes = "<%= cluster.number_of_nodes %>" 19 | publicly_accessible = "<%= cluster.publicly_accessible %>" 20 | encrypted = "<%= cluster.encrypted %>" 21 | skip_final_snapshot = "true" 22 | } 23 | <% end -%> 24 | -------------------------------------------------------------------------------- /lib/terraforming/template/tf/route53_record.erb: -------------------------------------------------------------------------------- 1 | <% records.each do |r| -%> 2 | <%- record, zone_id = r[:record], r[:zone_id] -%> 3 | <%- counter = r[:counter] -%> 4 | resource "aws_route53_record" "<%= module_name_of(record, counter) %>" { 5 | zone_id = "<%= zone_id %>" 6 | name = "<%= name_of(record.name.sub(/\\052/, '*')) %>" 7 | type = "<%= record.type %>" 8 | <%- unless record.resource_records.empty? -%> 9 | records = <%= record.resource_records.map(&:value).to_s %> 10 | <%- end -%> 11 | <%- if record.ttl -%> 12 | ttl = "<%= record.ttl %>" 13 | <%- end -%> 14 | <%- if record.weight -%> 15 | weighted_routing_policy { 16 | weight = <%= record.weight %> 17 | } 18 | <%- end -%> 19 | <%- if record.region -%> 20 | latency_routing_policy { 21 | region = "<%= record.region %>" 22 | } 23 | <%- end -%> 24 | <%- if record.geo_location -%> 25 | 26 | geolocation_routing_policy { 27 | <%- if record.geo_location.continent_code -%> 28 | continent = "<%= record.geo_location.continent_code %>" 29 | <%- end -%> 30 | <%- if record.geo_location.country_code -%> 31 | country = "<%= record.geo_location.country_code %>" 32 | <%- end -%> 33 | <%- if record.geo_location.subdivision_code -%> 34 | subdivision = "<%= record.geo_location.subdivision_code %>" 35 | <%- end -%> 36 | } 37 | <%- end -%> 38 | <%- if record.set_identifier -%> 39 | set_identifier = "<%= record.set_identifier %>" 40 | <%- end -%> 41 | <%- if record.health_check_id -%> 42 | health_check_id = "<%= record.health_check_id %>" 43 | <%- end -%> 44 | <%- if record.failover -%> 45 | 46 | failover_routing_policy { 47 | type = "<%= record.failover %>" 48 | } 49 | <%- end -%> 50 | 51 | <%- if record.alias_target -%> 52 | alias { 53 | name = "<%= name_of(record.alias_target.dns_name) 54 | %>" 55 | zone_id = "<%= record.alias_target.hosted_zone_id %>" 56 | evaluate_target_health = <%= record.alias_target.evaluate_target_health %> 57 | } 58 | <%- end -%> 59 | } 60 | 61 | <% end -%> 62 | -------------------------------------------------------------------------------- /lib/terraforming/template/tf/route53_zone.erb: -------------------------------------------------------------------------------- 1 | <% hosted_zones.each do |hosted_zone| -%> 2 | resource "aws_route53_zone" "<%= module_name_of(hosted_zone) %>" { 3 | name = "<%= name_of(hosted_zone) %>" 4 | comment = "<%= comment_of(hosted_zone) %>" 5 | <%- if private_hosted_zone?(hosted_zone) -%> 6 | <%- vpc = vpc_of(hosted_zone) -%> 7 | vpc_id = "<%= vpc.vpc_id %>" 8 | vpc_region = "<%= vpc.vpc_region %>" 9 | <%- end -%> 10 | 11 | tags { 12 | <% tags_of(hosted_zone).each do |tag| -%> 13 | "<%= tag.key %>" = "<%= tag.value %>" 14 | <% end -%> 15 | } 16 | } 17 | 18 | <% end -%> 19 | -------------------------------------------------------------------------------- /lib/terraforming/template/tf/route_table.erb: -------------------------------------------------------------------------------- 1 | <% route_tables.each do |route_table| -%> 2 | resource "aws_route_table" "<%= module_name_of(route_table) %>" { 3 | vpc_id = "<%= route_table.vpc_id %>" 4 | 5 | <% routes_of(route_table).each do |route| -%> 6 | route { 7 | cidr_block = "<%= route.destination_cidr_block %>" 8 | <% if route.gateway_id -%> 9 | gateway_id = "<%= route.gateway_id %>" 10 | <% end -%> 11 | <% if route.instance_id -%> 12 | instance_id = "<%= route.instance_id %>" 13 | <% end -%> 14 | <% if route.vpc_peering_connection_id -%> 15 | vpc_peering_connection_id = "<%= route.vpc_peering_connection_id %>" 16 | <% end -%> 17 | <% if route.network_interface_id -%> 18 | network_interface_id = "<%= route.network_interface_id %>" 19 | <% end -%> 20 | } 21 | 22 | <% end -%> 23 | <% if route_table.propagating_vgws.any? -%> 24 | propagating_vgws = <%= propagaving_vgws_of(route_table).inspect %> 25 | 26 | <% end -%> 27 | tags { 28 | <% route_table.tags.each do |tag| -%> 29 | "<%= tag.key %>" = "<%= tag.value %>" 30 | <% end -%> 31 | } 32 | } 33 | 34 | <% end -%> 35 | -------------------------------------------------------------------------------- /lib/terraforming/template/tf/route_table_association.erb: -------------------------------------------------------------------------------- 1 | <% route_tables.each do |route_table| -%> 2 | <% associations_of(route_table).each do |assoc| -%> 3 | resource "aws_route_table_association" "<%= module_name_of(route_table, assoc) %>" { 4 | route_table_id = "<%= assoc.route_table_id %>" 5 | subnet_id = "<%= assoc.subnet_id %>" 6 | } 7 | 8 | <% end -%> 9 | <% end -%> 10 | -------------------------------------------------------------------------------- /lib/terraforming/template/tf/s3.erb: -------------------------------------------------------------------------------- 1 | <% buckets.each do |bucket| -%> 2 | resource "aws_s3_bucket" "<%= module_name_of(bucket) %>" { 3 | bucket = "<%= bucket.name %>" 4 | acl = "private" 5 | <%- unless (policy = bucket_policy_of(bucket)).nil? -%> 6 | policy = < 8 | POLICY 9 | <%- end -%> 10 | } 11 | 12 | <% end -%> 13 | -------------------------------------------------------------------------------- /lib/terraforming/template/tf/security_group.erb: -------------------------------------------------------------------------------- 1 | <% security_groups.each do |security_group| -%> 2 | resource "aws_security_group" "<%= module_name_of(security_group) %>" { 3 | name = "<%= security_group.group_name %>" 4 | description = "<%= security_group.description %>" 5 | vpc_id = "<%= security_group.vpc_id || '' %>" 6 | 7 | <% dedup_permissions(security_group.ip_permissions, security_group.group_id).each do |permission| -%> 8 | <%- security_groups = security_groups_in(permission, security_group).reject { |group_name| group_name == security_group.group_name }.reject { |group_id| group_id == security_group.group_id } -%> 9 | ingress { 10 | from_port = <%= permission.from_port || 0 %> 11 | to_port = <%= permission.to_port || 0 %> 12 | protocol = "<%= permission.ip_protocol %>" 13 | <%- if permission.prefix_list_ids.length > 0 -%> 14 | prefix_list_ids = <%= permission.prefix_list_ids.map { |range| range.prefix_list_id }.inspect %> 15 | <%- end -%> 16 | <%- if permission.ip_ranges.length > 0 -%> 17 | cidr_blocks = <%= permission.ip_ranges.map { |range| range.cidr_ip }.inspect %> 18 | <%- end -%> 19 | <%- if permission.ipv_6_ranges.length > 0 -%> 20 | ipv6_cidr_blocks = <%= permission.ipv_6_ranges.map { |range| range.cidr_ipv_6 }.inspect %> 21 | <%- end -%> 22 | <%- if permission.user_id_group_pairs.length > 0 -%> 23 | <%- self_referenced = self_referenced_permission?(security_group, permission) -%> 24 | security_groups = <%= security_groups.inspect %> 25 | self = <%= self_referenced %> 26 | <%- end -%> 27 | } 28 | 29 | <% end -%> 30 | 31 | <% dedup_permissions(security_group.ip_permissions_egress, security_group.group_id).each do |permission| -%> 32 | egress { 33 | from_port = <%= permission.from_port || 0 %> 34 | to_port = <%= permission.to_port || 0 %> 35 | protocol = "<%= permission.ip_protocol %>" 36 | <%- if permission.prefix_list_ids.length > 0 -%> 37 | prefix_list_ids = <%= permission.prefix_list_ids.map { |range| range.prefix_list_id }.inspect %> 38 | <%- end -%> 39 | <%- if permission.ip_ranges.length > 0 -%> 40 | cidr_blocks = <%= permission.ip_ranges.map { |range| range.cidr_ip }.inspect %> 41 | <%- end -%> 42 | <%- if permission.ipv_6_ranges.length > 0 -%> 43 | ipv6_cidr_blocks = <%= permission.ipv_6_ranges.map { |range| range.cidr_ipv_6 }.inspect %> 44 | <%- end -%> 45 | <%- if permission.user_id_group_pairs.length > 0 -%> 46 | <%- self_referenced = self_referenced_permission?(security_group, permission) -%> 47 | security_groups = <%= security_groups_in(permission, security_group).reject { |group_id| group_id == security_group.group_id }.inspect %> 48 | self = <%= self_referenced %> 49 | <%- end -%> 50 | } 51 | 52 | <% end -%> 53 | <% if security_group.tags.length > 0 -%> 54 | tags { 55 | <% security_group.tags.each do |tag| -%> 56 | "<%= tag.key %>" = "<%= tag.value %>" 57 | <% end -%> 58 | } 59 | <% end -%> 60 | } 61 | 62 | <% end -%> 63 | -------------------------------------------------------------------------------- /lib/terraforming/template/tf/sns_topic.erb: -------------------------------------------------------------------------------- 1 | <% topics.each do |topic| -%> 2 | resource "aws_sns_topic" "<%= module_name_of(topic) %>" { 3 | name = "<%= module_name_of(topic) %>" 4 | display_name = "<%= topic["DisplayName"] %>" 5 | <% if topic.key? "Policy" -%> 6 | policy = < 8 | POLICY 9 | <% end -%> 10 | <% if topic.key? "DeliveryPolicy" -%> 11 | delivery_policy = < 13 | POLICY 14 | <% end -%> 15 | } 16 | 17 | <% end -%> 18 | -------------------------------------------------------------------------------- /lib/terraforming/template/tf/sns_topic_subscription.erb: -------------------------------------------------------------------------------- 1 | <% subscriptions.each do |subscription| -%> 2 | <% if subscription["Protocol"].include?("email") -%> 3 | /* 4 | <% end -%> 5 | resource "aws_sns_topic_subscription" "<%= module_name_of(subscription) %>" { 6 | topic_arn = "<%= subscription["TopicArn"] %>" 7 | protocol = "<%= subscription["Protocol"] %>" 8 | endpoint = "<%= subscription["Endpoint"] %>" 9 | <% if subscription.key? "RawMessageDelivery" -%> 10 | raw_message_delivery = "<%= subscription["RawMessageDelivery"] %>" 11 | <% end -%> 12 | <% if subscription.key? "ConfirmationTimeoutInMinutes" %> 13 | confirmation_timeout_in_minutes = "<%= subscription["ConfirmationTimeoutInMinutes"] %>" 14 | <% end -%> 15 | <% if subscription.key? "EndpointAutoConfirms" %> 16 | endpoint_auto_confirms = "<%= subscription["EndpointAutoConfirms"] %>" 17 | <% end -%> 18 | } 19 | <% if subscription["Protocol"].include?("email") -%> 20 | */ 21 | <% end -%> 22 | 23 | <% end -%> 24 | -------------------------------------------------------------------------------- /lib/terraforming/template/tf/sqs.erb: -------------------------------------------------------------------------------- 1 | <% queues.each do |queue| -%> 2 | resource "aws_sqs_queue" "<%= module_name_of(queue) %>" { 3 | name = "<%= module_name_of(queue) %>" 4 | visibility_timeout_seconds = <%= queue["VisibilityTimeout"] %> 5 | message_retention_seconds = <%= queue["MessageRetentionPeriod"] %> 6 | max_message_size = <%= queue["MaximumMessageSize"] %> 7 | delay_seconds = <%= queue["DelaySeconds"] %> 8 | receive_wait_time_seconds = <%= queue["ReceiveMessageWaitTimeSeconds"] %> 9 | <% if queue.key? "Policy" -%> 10 | policy = < 12 | POLICY 13 | <% end -%> 14 | <% if queue.key? "RedrivePolicy" -%> 15 | redrive_policy = < 17 | POLICY 18 | <% end -%> 19 | } 20 | 21 | <% end -%> 22 | -------------------------------------------------------------------------------- /lib/terraforming/template/tf/subnet.erb: -------------------------------------------------------------------------------- 1 | <% subnets.each do |subnet| -%> 2 | resource "aws_subnet" "<%= module_name_of(subnet) %>" { 3 | vpc_id = "<%= subnet.vpc_id %>" 4 | cidr_block = "<%= subnet.cidr_block %>" 5 | availability_zone = "<%= subnet.availability_zone %>" 6 | map_public_ip_on_launch = <%= subnet.map_public_ip_on_launch %> 7 | 8 | tags { 9 | <% subnet.tags.each do |tag| -%> 10 | "<%= tag.key %>" = "<%= tag.value %>" 11 | <% end -%> 12 | } 13 | } 14 | 15 | <% end -%> 16 | -------------------------------------------------------------------------------- /lib/terraforming/template/tf/vpc.erb: -------------------------------------------------------------------------------- 1 | <% vpcs.each do |vpc| -%> 2 | resource "aws_vpc" "<%= module_name_of(vpc) %>" { 3 | cidr_block = "<%= vpc.cidr_block %>" 4 | enable_dns_hostnames = <%= enable_dns_hostnames?(vpc) %> 5 | enable_dns_support = <%= enable_dns_support?(vpc) %> 6 | instance_tenancy = "<%= vpc.instance_tenancy %>" 7 | 8 | tags { 9 | <% vpc.tags.each do |tag| -%> 10 | "<%= tag.key %>" = "<%= tag.value %>" 11 | <% end -%> 12 | } 13 | } 14 | 15 | <% end -%> 16 | -------------------------------------------------------------------------------- /lib/terraforming/template/tf/vpn_gateway.erb: -------------------------------------------------------------------------------- 1 | <% vpn_gateways.each do |vpn_gateway| -%> 2 | <% unless vpn_gateway.vpc_attachments.empty? -%> 3 | resource "aws_vpn_gateway" "<%= module_name_of(vpn_gateway) %>" { 4 | vpc_id = "<%= vpn_gateway.vpc_attachments[0].vpc_id %>" 5 | availability_zone = "<%= vpn_gateway.availability_zone %>" 6 | tags { 7 | <% vpn_gateway.tags.each do |tag| -%> 8 | "<%= tag.key %>" = "<%= tag.value %>" 9 | <% end -%> 10 | } 11 | } 12 | 13 | <% end -%> 14 | <% end -%> 15 | -------------------------------------------------------------------------------- /lib/terraforming/util.rb: -------------------------------------------------------------------------------- 1 | module Terraforming 2 | module Util 3 | def apply_template(client, erb) 4 | ERB.new(open(template_path(erb)).read, nil, "-").result(binding) 5 | end 6 | 7 | def name_from_tag(resource, default_name) 8 | name_tag = resource.tags.find { |tag| tag.key == "Name" } 9 | name_tag ? name_tag.value : default_name 10 | end 11 | 12 | def normalize_module_name(name) 13 | name.gsub(/[^a-zA-Z0-9_-]/, "-") 14 | end 15 | 16 | def template_path(template_name) 17 | File.join(File.expand_path(File.dirname(__FILE__)), "template", template_name) << ".erb" 18 | end 19 | 20 | def prettify_policy(document, breakline: false, unescape: false) 21 | json = JSON.pretty_generate(JSON.parse(unescape ? CGI.unescape(document) : document)) 22 | 23 | if breakline 24 | json[-1] != "\n" ? json << "\n" : json 25 | else 26 | json.strip 27 | end 28 | end 29 | end 30 | end 31 | -------------------------------------------------------------------------------- /lib/terraforming/version.rb: -------------------------------------------------------------------------------- 1 | module Terraforming 2 | VERSION = "0.18.0" 3 | end 4 | -------------------------------------------------------------------------------- /script/console: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | require "bundler/setup" 4 | require "terraforming" 5 | 6 | # You can add fixtures and/or initialization code here to make experimenting 7 | # with your gem easier. You can also use a different console, if you like. 8 | 9 | # (If you use this, don't forget to add pry to your Gemfile!) 10 | # require "pry" 11 | # Pry.start 12 | 13 | require "irb" 14 | IRB.start 15 | -------------------------------------------------------------------------------- /script/generate: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | require "erb" 4 | 5 | USAGE = <<-EOS 6 | Usage: script/generate RESOURCE 7 | RESOURCE must be snake_case 8 | 9 | Example: 10 | script/generate EC2 11 | EOS 12 | 13 | def camelize(string) 14 | string 15 | .sub(/^[a-z\d]*/) { |match| match.capitalize } 16 | .gsub(%r{(?:_|(/))([a-z\d]*)}i) { "#{$1}#{$2.capitalize}" } 17 | .gsub('/'.freeze, '::'.freeze) 18 | end 19 | 20 | def generate_resource_erb(resource) 21 | template = File.join("templates", "resource.erb.erb") 22 | ERB.new(open(template).read, nil, "-").result(binding) 23 | end 24 | 25 | def generate_resource_rb(resource) 26 | template = File.expand_path(File.join("templates", "resource.rb.erb")) 27 | ERB.new(open(template).read, nil, "-").result(binding) 28 | end 29 | 30 | def generate_resource_spec_rb(resource) 31 | template = File.join("templates", "resource_spec.rb.erb") 32 | ERB.new(open(template).read, nil, "-").result(binding) 33 | end 34 | 35 | def humanize(string) 36 | string 37 | .sub(/\A_+/, ''.freeze) 38 | .sub(/_id\z/, ''.freeze) 39 | .tr('_'.freeze, ' '.freeze) 40 | .gsub(/([a-z\d]*)/i) { |match| match.downcase } 41 | .split(" ") 42 | .map { |w| w[0].upcase + w[1..-1] } 43 | .join(" ") 44 | end 45 | 46 | 47 | 48 | if ARGV.length != 1 49 | $stderr.puts USAGE 50 | exit 1 51 | end 52 | 53 | resource = ARGV[0] 54 | 55 | puts "==> Generate #{resource}.rb" 56 | resource_rb = generate_resource_rb(resource) 57 | File.open(File.join("lib", "terraforming", "resource", "#{resource}.rb"), "w+") { |f| f.write(resource_rb) } 58 | 59 | puts "==> Generate #{resource}_spec.rb" 60 | resource_spec_rb = generate_resource_spec_rb(resource) 61 | File.open(File.join("spec", "lib", "terraforming", "resource", "#{resource}_spec.rb"), "w+") { |f| f.write(resource_spec_rb) } 62 | 63 | puts "==> Generate #{resource}.erb" 64 | resource_erb = generate_resource_erb(resource) 65 | File.open(File.join("lib", "terraforming", "template", "tf", "#{resource}.erb"), "w+") { |f| f.write(resource_erb) } 66 | 67 | puts <<-EOS 68 | 69 | Add below code by hand. 70 | 71 | lib/terraforming.rb: 72 | 73 | require "terraforming/resource/#{resource}" 74 | 75 | lib/terraforming/cli.rb: 76 | 77 | module Terraforming 78 | class CLI < Thor 79 | 80 | # Subcommand name should be acronym. 81 | desc "#{resource}", "#{humanize(resource)}" 82 | def #{resource} 83 | execute(Terraforming::Resource::#{camelize(resource)}, options) 84 | end 85 | 86 | spec/lib/terraforming/cli_spec.rb: 87 | 88 | module Terraforming 89 | describe CLI do 90 | context "resources" do 91 | describe "#{resource}" do 92 | let(:klass) { Terraforming::Resource::#{camelize(resource)} } 93 | let(:command) { :#{resource} } 94 | 95 | it_behaves_like "CLI examples" 96 | end 97 | EOS 98 | -------------------------------------------------------------------------------- /script/setup: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -euo pipefail 3 | IFS=$'\n\t' 4 | 5 | bundle install 6 | 7 | # Do any other automated setup that you need to do here 8 | -------------------------------------------------------------------------------- /spec/fixtures/terraform.tfstate: -------------------------------------------------------------------------------- 1 | { 2 | "version": 1, 3 | "serial": 88, 4 | "remote": { 5 | "type": "s3", 6 | "config": { 7 | "bucket": "terraforming-tfstate", 8 | "key": "tf" 9 | } 10 | }, 11 | "modules": [ 12 | { 13 | "path": [ 14 | "root" 15 | ], 16 | "outputs": {}, 17 | "resources": { 18 | "aws_elb.hogehoge": { 19 | "type": "aws_elb", 20 | "primary": { 21 | "id": "hogehoge", 22 | "attributes": { 23 | "availability_zones.#": "2", 24 | "connection_draining": "true", 25 | "connection_draining_timeout": "300", 26 | "cross_zone_load_balancing": "true", 27 | "dns_name": "hoge-12345678.ap-northeast-1.elb.amazonaws.com", 28 | "health_check.#": "1", 29 | "id": "hogehoge", 30 | "idle_timeout": "60", 31 | "instances.#": "1", 32 | "listener.#": "1", 33 | "name": "hoge", 34 | "security_groups.#": "2", 35 | "source_security_group": "default", 36 | "subnets.#": "2" 37 | } 38 | } 39 | } 40 | } 41 | } 42 | ] 43 | } 44 | -------------------------------------------------------------------------------- /spec/lib/terraforming/resource/db_security_group_spec.rb: -------------------------------------------------------------------------------- 1 | require "spec_helper" 2 | 3 | module Terraforming 4 | module Resource 5 | describe DBSecurityGroup do 6 | let(:client) do 7 | Aws::RDS::Client.new(stub_responses: true) 8 | end 9 | 10 | let(:db_security_groups) do 11 | [ 12 | { 13 | ip_ranges: [], 14 | owner_id: "123456789012", 15 | db_security_group_description: "default", 16 | ec2_security_groups: [ 17 | { 18 | status: "authorized", 19 | ec2_security_group_name: "default", 20 | ec2_security_group_owner_id: "123456789012", 21 | ec2_security_group_id: "sg-1234abcd" 22 | } 23 | ], 24 | db_security_group_name: "default" 25 | }, 26 | { 27 | ip_ranges: [ 28 | { 29 | status: "authorized", 30 | cidrip: "0.0.0.0/0" 31 | } 32 | ], 33 | owner_id: "3456789012", 34 | db_security_group_description: "foobar group", 35 | ec2_security_groups: [ 36 | { 37 | status: "authorized", 38 | ec2_security_group_name: "foobar", 39 | ec2_security_group_owner_id: "3456789012", 40 | ec2_security_group_id: "sg-5678efgh" 41 | } 42 | ], 43 | db_security_group_name: "sgfoobar" 44 | }, 45 | { 46 | ip_ranges: [], 47 | owner_id: "123456789012", 48 | db_security_group_description: "empty", 49 | ec2_security_groups: [], 50 | db_security_group_name: "empty" 51 | }, 52 | ] 53 | end 54 | 55 | before do 56 | client.stub_responses(:describe_db_security_groups, db_security_groups: db_security_groups) 57 | end 58 | 59 | describe ".tf" do 60 | it "should generate tf" do 61 | expect(described_class.tf(client: client)).to eq <<-EOS 62 | resource "aws_db_security_group" "default" { 63 | name = "default" 64 | description = "default" 65 | 66 | ingress { 67 | cidr = "" 68 | security_group_name = "default" 69 | security_group_id = "sg-1234abcd" 70 | security_group_owner_id = "123456789012" 71 | } 72 | 73 | } 74 | 75 | resource "aws_db_security_group" "sgfoobar" { 76 | name = "sgfoobar" 77 | description = "foobar group" 78 | 79 | ingress { 80 | cidr = "0.0.0.0/0" 81 | security_group_name = "" 82 | security_group_id = "" 83 | security_group_owner_id = "" 84 | } 85 | 86 | ingress { 87 | cidr = "" 88 | security_group_name = "foobar" 89 | security_group_id = "sg-5678efgh" 90 | security_group_owner_id = "3456789012" 91 | } 92 | 93 | } 94 | 95 | EOS 96 | end 97 | end 98 | 99 | describe ".tfstate" do 100 | it "should generate tfstate" do 101 | expect(described_class.tfstate(client: client)).to eq({ 102 | "aws_db_security_group.default" => { 103 | "type" => "aws_db_security_group", 104 | "primary" => { 105 | "id" => "default", 106 | "attributes" => { 107 | "db_subnet_group_name" => "default", 108 | "id" => "default", 109 | "ingress.#" => "1", 110 | "name" => "default", 111 | } 112 | } 113 | }, 114 | "aws_db_security_group.sgfoobar" => { 115 | "type" => "aws_db_security_group", 116 | "primary" => { 117 | "id" => "sgfoobar", 118 | "attributes" => { 119 | "db_subnet_group_name" => "sgfoobar", 120 | "id" => "sgfoobar", 121 | "ingress.#" => "2", 122 | "name" => "sgfoobar", 123 | } 124 | } 125 | } 126 | }) 127 | end 128 | end 129 | end 130 | end 131 | end 132 | -------------------------------------------------------------------------------- /spec/lib/terraforming/resource/db_subnet_group_spec.rb: -------------------------------------------------------------------------------- 1 | require "spec_helper" 2 | 3 | module Terraforming 4 | module Resource 5 | describe DBSubnetGroup do 6 | let(:client) do 7 | Aws::RDS::Client.new(stub_responses: true) 8 | end 9 | 10 | let(:db_subnet_groups) do 11 | [ 12 | { 13 | subnets: [ 14 | { 15 | subnet_status: "Active", 16 | subnet_identifier: "subnet-1234abcd", 17 | subnet_availability_zone: { 18 | name: "ap-northeast-1c" 19 | } 20 | }, 21 | { 22 | subnet_status: "Active", 23 | subnet_identifier: "subnet-5678efgh", 24 | subnet_availability_zone: { 25 | name: "ap-northeast-1b" 26 | } 27 | } 28 | ], 29 | db_subnet_group_name: "hoge", 30 | vpc_id: "vpc-1234abcd", 31 | db_subnet_group_description: "DB subnet group hoge", 32 | subnet_group_status: "Complete" 33 | }, 34 | { 35 | subnets: [ 36 | { 37 | subnet_status: "Active", 38 | subnet_identifier: "subnet-9012ijkl", 39 | subnet_availability_zone: { 40 | name: "ap-northeast-1b" 41 | } 42 | }, 43 | { 44 | subnet_status: "Active", 45 | subnet_identifier: "subnet-3456mnop", 46 | subnet_availability_zone: { 47 | name: "ap-northeast-1c" 48 | } 49 | } 50 | ], 51 | db_subnet_group_name: "fuga", 52 | vpc_id: "vpc-5678efgh", 53 | db_subnet_group_description: "DB subnet group fuga", 54 | subnet_group_status: "Complete" 55 | } 56 | ] 57 | end 58 | 59 | before do 60 | client.stub_responses(:describe_db_subnet_groups, db_subnet_groups: db_subnet_groups) 61 | end 62 | 63 | describe ".tf" do 64 | it "should generate tf" do 65 | expect(described_class.tf(client: client)).to eq <<-EOS 66 | resource "aws_db_subnet_group" "hoge" { 67 | name = "hoge" 68 | description = "DB subnet group hoge" 69 | subnet_ids = ["subnet-1234abcd", "subnet-5678efgh"] 70 | } 71 | 72 | resource "aws_db_subnet_group" "fuga" { 73 | name = "fuga" 74 | description = "DB subnet group fuga" 75 | subnet_ids = ["subnet-9012ijkl", "subnet-3456mnop"] 76 | } 77 | 78 | EOS 79 | end 80 | end 81 | 82 | describe ".tfstate" do 83 | it "should generate tfstate" do 84 | expect(described_class.tfstate(client: client)).to eq({ 85 | "aws_db_subnet_group.hoge" => { 86 | "type" => "aws_db_subnet_group", 87 | "primary" => { 88 | "id" => "hoge", 89 | "attributes" => { 90 | "description" => "DB subnet group hoge", 91 | "name" => "hoge", 92 | "subnet_ids.#" => "2", 93 | } 94 | } 95 | }, 96 | "aws_db_subnet_group.fuga" => { 97 | "type" => "aws_db_subnet_group", 98 | "primary" => { 99 | "id" => "fuga", 100 | "attributes" => { 101 | "description" => "DB subnet group fuga", 102 | "name" => "fuga", 103 | "subnet_ids.#" => "2", 104 | } 105 | } 106 | } 107 | 108 | }) 109 | end 110 | end 111 | end 112 | end 113 | end 114 | -------------------------------------------------------------------------------- /spec/lib/terraforming/resource/efs_file_system_spec.rb: -------------------------------------------------------------------------------- 1 | require "spec_helper" 2 | 3 | module Terraforming 4 | module Resource 5 | describe EFSFileSystem do 6 | let(:client) do 7 | Aws::EFS::Client.new(stub_responses: true) 8 | end 9 | 10 | let(:efs_description_0) do 11 | { 12 | creation_time: Time.parse("2016-11-01 11:30:00 -0700"), 13 | creation_token: "console-1234abcd-1234-abcd-a123-d34db33f0000", 14 | file_system_id: "fs-0000abcd", 15 | life_cycle_state: "available", 16 | name: "efs_name_0", 17 | number_of_mount_targets: 3, 18 | owner_id: "999999999999", 19 | performance_mode: "generalPurpose", 20 | size_in_bytes: { value: 6144 }, 21 | tags: [], 22 | } 23 | end 24 | 25 | let(:efs_description_1) do 26 | { 27 | creation_time: Time.parse("2016-10-24 11:42:21 -0700"), 28 | creation_token: "console-0000abcd-4321-dcba-a123-d34db33f0000", 29 | file_system_id: "fs-abcd1234", 30 | life_cycle_state: "available", 31 | name: "efs_name_1", 32 | number_of_mount_targets: 3, 33 | owner_id: "999999999999", 34 | performance_mode: "generalPurpose", 35 | size_in_bytes: { value: 23481234 }, 36 | tags: [], 37 | } 38 | end 39 | 40 | before do 41 | client.stub_responses(:describe_file_systems, file_systems: [efs_description_0, efs_description_1]) 42 | end 43 | 44 | describe ".tf" do 45 | it "should generate tf" do 46 | expect(described_class.tf(client: client)).to eq <<-EOS 47 | resource "aws_efs_file_system" "fs-0000abcd" { 48 | creation_token = "console-1234abcd-1234-abcd-a123-d34db33f0000" 49 | file_system_id = "fs-0000abcd" 50 | performance_mode = "generalPurpose" 51 | tags { 52 | Name = "efs_name_0" 53 | } 54 | } 55 | resource "aws_efs_file_system" "fs-abcd1234" { 56 | creation_token = "console-0000abcd-4321-dcba-a123-d34db33f0000" 57 | file_system_id = "fs-abcd1234" 58 | performance_mode = "generalPurpose" 59 | tags { 60 | Name = "efs_name_1" 61 | } 62 | } 63 | EOS 64 | end 65 | end 66 | 67 | describe ".tfstate" do 68 | it "should generate tfstate" do 69 | expect(described_class.tfstate(client: client)).to eq({ 70 | "aws_efs_file_system.fs-0000abcd" => { 71 | "type" => "aws_efs_file_system", 72 | "depends_on" => [], 73 | "primary" => { 74 | "id" => "fs-0000abcd", 75 | "meta" => {}, 76 | "tainted" => false, 77 | "attributes" => { 78 | "creation_token" => "console-1234abcd-1234-abcd-a123-d34db33f0000", 79 | "id" => "fs-0000abcd", 80 | "performance_mode" => "generalPurpose", 81 | "tags.%" => "1", 82 | "tags.Name" => "efs_name_0" 83 | }, 84 | }, 85 | "deposed" => [], 86 | "provider" => "aws", 87 | }, 88 | "aws_efs_file_system.fs-abcd1234" => { 89 | "type" => "aws_efs_file_system", 90 | "depends_on" => [], 91 | "primary" => { 92 | "id" => "fs-abcd1234", 93 | "meta" => {}, 94 | "tainted" => false, 95 | "attributes" => { 96 | "creation_token" => "console-0000abcd-4321-dcba-a123-d34db33f0000", 97 | "id" => "fs-abcd1234", 98 | "performance_mode" => "generalPurpose", 99 | "tags.%" => "1", 100 | "tags.Name" => "efs_name_1" 101 | }, 102 | }, 103 | "deposed" => [], 104 | "provider" => "aws", 105 | } 106 | }) 107 | end 108 | end 109 | end 110 | end 111 | end 112 | -------------------------------------------------------------------------------- /spec/lib/terraforming/resource/elasti_cache_subnet_group_spec.rb: -------------------------------------------------------------------------------- 1 | require "spec_helper" 2 | 3 | module Terraforming 4 | module Resource 5 | describe ElastiCacheSubnetGroup do 6 | let(:client) do 7 | Aws::ElastiCache::Client.new(stub_responses: true) 8 | end 9 | 10 | let(:cache_subnet_groups) do 11 | [ 12 | { 13 | cache_subnet_group_name: "hoge", 14 | cache_subnet_group_description: "Group for hoge", 15 | vpc_id: "vpc-1234abcd", 16 | subnets: [ 17 | { 18 | subnet_identifier: "subnet-1234abcd", 19 | subnet_availability_zone: { name: "ap-northeast-1b" } 20 | } 21 | ] 22 | }, 23 | { 24 | cache_subnet_group_name: "fuga", 25 | cache_subnet_group_description: "Group for fuga", 26 | vpc_id: "vpc-5678efgh", 27 | subnets: [ 28 | { 29 | subnet_identifier: "subnet-5678efgh", 30 | subnet_availability_zone: { name: "ap-northeast-1b" } 31 | } 32 | ] 33 | } 34 | ] 35 | end 36 | 37 | before do 38 | client.stub_responses(:describe_cache_subnet_groups, cache_subnet_groups: cache_subnet_groups) 39 | end 40 | 41 | describe ".tf" do 42 | it "should generate tf" do 43 | expect(described_class.tf(client: client)).to eq <<-EOS 44 | resource "aws_elasticache_subnet_group" "hoge" { 45 | name = "hoge" 46 | description = "Group for hoge" 47 | subnet_ids = ["subnet-1234abcd"] 48 | } 49 | 50 | resource "aws_elasticache_subnet_group" "fuga" { 51 | name = "fuga" 52 | description = "Group for fuga" 53 | subnet_ids = ["subnet-5678efgh"] 54 | } 55 | 56 | EOS 57 | end 58 | end 59 | 60 | describe ".tfstate" do 61 | it "should generate tfstate" do 62 | expect(described_class.tfstate(client: client)).to eq({ 63 | "aws_elasticache_subnet_group.hoge" => { 64 | "type" => "aws_elasticache_subnet_group", 65 | "primary" => { 66 | "id" => "hoge", 67 | "attributes" => { 68 | "description" => "Group for hoge", 69 | "name" => "hoge", 70 | "subnet_ids.#" => "1", 71 | } 72 | } 73 | }, 74 | "aws_elasticache_subnet_group.fuga" => { 75 | "type" => "aws_elasticache_subnet_group", 76 | "primary" => { 77 | "id" => "fuga", 78 | "attributes" => { 79 | "description" => "Group for fuga", 80 | "name" => "fuga", 81 | "subnet_ids.#" => "1", 82 | } 83 | } 84 | }, 85 | }) 86 | end 87 | end 88 | end 89 | end 90 | end 91 | -------------------------------------------------------------------------------- /spec/lib/terraforming/resource/iam_group_membership_spec.rb: -------------------------------------------------------------------------------- 1 | require "spec_helper" 2 | 3 | module Terraforming 4 | module Resource 5 | describe IAMGroupMembership do 6 | let(:client) do 7 | Aws::IAM::Client.new(stub_responses: true) 8 | end 9 | 10 | let(:groups) do 11 | [ 12 | { 13 | path: "/", 14 | group_name: "hoge", 15 | group_id: "ABCDEFGHIJKLMN1234567", 16 | arn: "arn:aws:iam::123456789012:group/hoge", 17 | create_date: Time.parse("2015-04-01 12:34:56 UTC"), 18 | }, 19 | { 20 | path: "/system/", 21 | group_name: "fuga", 22 | group_id: "OPQRSTUVWXYZA8901234", 23 | arn: "arn:aws:iam::345678901234:group/fuga", 24 | create_date: Time.parse("2015-05-01 12:34:56 UTC"), 25 | }, 26 | ] 27 | end 28 | 29 | let(:hoge_group) do 30 | { 31 | path: "/", 32 | group_name: "hoge", 33 | group_id: "ABCDEFGHIJKLMN1234567", 34 | arn: "arn:aws:iam::123456789012:group/hoge", 35 | create_date: Time.parse("2015-04-01 12:34:56 UTC"), 36 | } 37 | end 38 | 39 | let(:hoge_users) do 40 | [ 41 | { 42 | path: "/", 43 | user_name: "foo", 44 | user_id: "ABCDEFGHIJKLMN1234567", 45 | arn: "arn:aws:iam::123456789012:user/foo", 46 | create_date: Time.parse("2015-04-01 12:34:56 UTC"), 47 | password_last_used: Time.parse("2015-04-01 15:00:00 UTC"), 48 | }, 49 | ] 50 | end 51 | 52 | let(:fuga_group) do 53 | { 54 | path: "/system/", 55 | group_name: "fuga", 56 | group_id: "OPQRSTUVWXYZA8901234", 57 | arn: "arn:aws:iam::345678901234:group/fuga", 58 | create_date: Time.parse("2015-05-01 12:34:56 UTC"), 59 | } 60 | end 61 | 62 | let(:fuga_users) do 63 | [ 64 | { 65 | path: "/system/", 66 | user_name: "bar", 67 | user_id: "OPQRSTUVWXYZA8901234", 68 | arn: "arn:aws:iam::345678901234:user/bar", 69 | create_date: Time.parse("2015-05-01 12:34:56 UTC"), 70 | password_last_used: Time.parse("2015-05-01 15:00:00 UTC"), 71 | }, 72 | ] 73 | end 74 | 75 | before do 76 | client.stub_responses(:list_groups, groups: groups) 77 | client.stub_responses(:get_group, [{ group: hoge_group, users: hoge_users }, { group: fuga_group, users: fuga_users }]) 78 | end 79 | 80 | describe ".tf" do 81 | it "should generate tf" do 82 | expect(described_class.tf(client: client)).to eq <<-EOS 83 | resource "aws_iam_group_membership" "hoge" { 84 | name = "hoge-group-membership" 85 | users = ["foo"] 86 | group = "hoge" 87 | } 88 | 89 | resource "aws_iam_group_membership" "fuga" { 90 | name = "fuga-group-membership" 91 | users = ["bar"] 92 | group = "fuga" 93 | } 94 | 95 | EOS 96 | end 97 | end 98 | 99 | describe ".tfstate" do 100 | it "should generate tfstate" do 101 | expect(described_class.tfstate(client: client)).to eq({ 102 | "aws_iam_group_membership.hoge" => { 103 | "type" => "aws_iam_group_membership", 104 | "primary" => { 105 | "id" => "hoge-group-membership", 106 | "attributes" => { 107 | "group" => "hoge", 108 | "id" => "hoge-group-membership", 109 | "name" => "hoge-group-membership", 110 | "users.#" => "1", 111 | } 112 | } 113 | }, 114 | "aws_iam_group_membership.fuga" => { 115 | "type" => "aws_iam_group_membership", 116 | "primary" => { 117 | "id" => "fuga-group-membership", 118 | "attributes" => { 119 | "group" => "fuga", 120 | "id" => "fuga-group-membership", 121 | "name" => "fuga-group-membership", 122 | "users.#" => "1", 123 | } 124 | } 125 | }, 126 | }) 127 | end 128 | end 129 | end 130 | end 131 | end 132 | -------------------------------------------------------------------------------- /spec/lib/terraforming/resource/iam_group_spec.rb: -------------------------------------------------------------------------------- 1 | require "spec_helper" 2 | 3 | module Terraforming 4 | module Resource 5 | describe IAMGroup do 6 | let(:client) do 7 | Aws::IAM::Client.new(stub_responses: true) 8 | end 9 | 10 | let(:groups) do 11 | [ 12 | { 13 | path: "/", 14 | group_name: "hoge", 15 | group_id: "ABCDEFGHIJKLMN1234567", 16 | arn: "arn:aws:iam::123456789012:group/hoge", 17 | create_date: Time.parse("2015-04-01 12:34:56 UTC"), 18 | }, 19 | { 20 | path: "/system/", 21 | group_name: "fuga", 22 | group_id: "OPQRSTUVWXYZA8901234", 23 | arn: "arn:aws:iam::345678901234:group/fuga", 24 | create_date: Time.parse("2015-05-01 12:34:56 UTC"), 25 | }, 26 | ] 27 | end 28 | 29 | before do 30 | client.stub_responses(:list_groups, [{ 31 | groups: [groups[0]], 32 | is_truncated: true, 33 | marker: 'marker' 34 | }, { 35 | groups: [groups[1]], 36 | is_truncated: false, 37 | marker: nil 38 | }]) 39 | end 40 | 41 | describe ".tf" do 42 | it "should generate tf" do 43 | expect(described_class.tf(client: client)).to eq <<-EOS 44 | resource "aws_iam_group" "hoge" { 45 | name = "hoge" 46 | path = "/" 47 | } 48 | 49 | resource "aws_iam_group" "fuga" { 50 | name = "fuga" 51 | path = "/system/" 52 | } 53 | 54 | EOS 55 | end 56 | end 57 | 58 | describe ".tfstate" do 59 | it "should generate tfstate" do 60 | expect(described_class.tfstate(client: client)).to eq({ 61 | "aws_iam_group.hoge" => { 62 | "type" => "aws_iam_group", 63 | "primary" => { 64 | "id" => "hoge", 65 | "attributes" => { 66 | "arn" => "arn:aws:iam::123456789012:group/hoge", 67 | "id" => "hoge", 68 | "name" => "hoge", 69 | "path" => "/", 70 | "unique_id" => "ABCDEFGHIJKLMN1234567", 71 | } 72 | } 73 | }, 74 | "aws_iam_group.fuga" => { 75 | "type" => "aws_iam_group", 76 | "primary" => { 77 | "id" => "fuga", 78 | "attributes" => { 79 | "arn" => "arn:aws:iam::345678901234:group/fuga", 80 | "id" => "fuga", 81 | "name" => "fuga", 82 | "path" => "/system/", 83 | "unique_id" => "OPQRSTUVWXYZA8901234", 84 | } 85 | } 86 | }, 87 | }) 88 | end 89 | end 90 | end 91 | end 92 | end 93 | -------------------------------------------------------------------------------- /spec/lib/terraforming/resource/iam_instance_profile_spec.rb: -------------------------------------------------------------------------------- 1 | require "spec_helper" 2 | 3 | module Terraforming 4 | module Resource 5 | describe IAMInstanceProfile do 6 | let(:client) do 7 | Aws::IAM::Client.new(stub_responses: true) 8 | end 9 | 10 | let(:instance_profiles) do 11 | [ 12 | { 13 | path: "/", 14 | instance_profile_name: "hoge_profile", 15 | instance_profile_id: "ABCDEFGHIJKLMN1234567", 16 | arn: "arn:aws:iam::123456789012:instance-profile/hoge_profile", 17 | create_date: Time.parse("2015-04-01 12:34:56 UTC"), 18 | roles: [ 19 | { 20 | path: "/", 21 | role_name: "hoge_role", 22 | role_id: "ABCDEFGHIJKLMN1234567", 23 | arn: "arn:aws:iam::123456789012:role/hoge_role", 24 | create_date: Time.parse("2015-04-01 12:34:56 UTC"), 25 | assume_role_policy_document: "%7B%22Version%22%3A%222008-10-17%22%2C%22Statement%22%3A%5B%7B%22Sid%22%3A%22%22%2C%22Effect%22%3A%22Allow%22%2C%22Principal%22%3A%7B%22Service%22%3A%22ec2.amazonaws.com%22%7D%2C%22Action%22%3A%22sts%3AAssumeRole%22%7D%5D%7D", 26 | }, 27 | ], 28 | } 29 | ] 30 | end 31 | 32 | before do 33 | client.stub_responses(:list_instance_profiles, instance_profiles: instance_profiles) 34 | end 35 | 36 | describe ".tf" do 37 | it "should generate tf" do 38 | expect(described_class.tf(client: client)).to eq <<-EOS 39 | resource "aws_iam_instance_profile" "hoge_profile" { 40 | name = "hoge_profile" 41 | path = "/" 42 | role = "hoge_role" 43 | } 44 | 45 | EOS 46 | end 47 | end 48 | 49 | describe ".tfstate" do 50 | it "should generate tfstate" do 51 | expect(described_class.tfstate(client: client)).to eq({ 52 | "aws_iam_instance_profile.hoge_profile" => { 53 | "type" => "aws_iam_instance_profile", 54 | "primary" => { 55 | "id" => "hoge_profile", 56 | "attributes" => { 57 | "arn" => "arn:aws:iam::123456789012:instance-profile/hoge_profile", 58 | "id" => "hoge_profile", 59 | "name" => "hoge_profile", 60 | "path" => "/", 61 | "role" => "hoge_role", 62 | "roles.#" => "1", 63 | } 64 | } 65 | } 66 | }) 67 | end 68 | end 69 | end 70 | end 71 | end 72 | -------------------------------------------------------------------------------- /spec/lib/terraforming/resource/iam_role_spec.rb: -------------------------------------------------------------------------------- 1 | require "spec_helper" 2 | 3 | module Terraforming 4 | module Resource 5 | describe IAMRole do 6 | let(:client) do 7 | Aws::IAM::Client.new(stub_responses: true) 8 | end 9 | 10 | let(:roles) do 11 | [ 12 | { 13 | path: "/", 14 | role_name: "hoge_role", 15 | role_id: "ABCDEFGHIJKLMN1234567", 16 | arn: "arn:aws:iam::123456789012:role/hoge_role", 17 | create_date: Time.parse("2015-04-01 12:34:56 UTC"), 18 | assume_role_policy_document: "%7B%22Version%22%3A%222008-10-17%22%2C%22Statement%22%3A%5B%7B%22Sid%22%3A%22%22%2C%22Effect%22%3A%22Allow%22%2C%22Principal%22%3A%7B%22Service%22%3A%22ec2.amazonaws.com%22%7D%2C%22Action%22%3A%22sts%3AAssumeRole%22%7D%5D%7D", 19 | }, 20 | { 21 | path: "/system/", 22 | role_name: "fuga_role", 23 | role_id: "OPQRSTUVWXYZA8901234", 24 | arn: "arn:aws:iam::345678901234:role/fuga_role", 25 | create_date: Time.parse("2015-05-01 12:34:56 UTC"), 26 | assume_role_policy_document: "%7B%22Version%22%3A%222008-10-17%22%2C%22Statement%22%3A%5B%7B%22Sid%22%3A%221%22%2C%22Effect%22%3A%22Allow%22%2C%22Principal%22%3A%7B%22Service%22%3A%22elastictranscoder.amazonaws.com%22%7D%2C%22Action%22%3A%22sts%3AAssumeRole%22%7D%5D%7D", 27 | }, 28 | ] 29 | end 30 | 31 | before do 32 | client.stub_responses(:list_roles, roles: roles) 33 | end 34 | 35 | describe ".tf" do 36 | it "should generate tf" do 37 | expect(described_class.tf(client: client)).to eq <<-EOS 38 | resource "aws_iam_role" "hoge_role" { 39 | name = "hoge_role" 40 | path = "/" 41 | assume_role_policy = < { 86 | "type" => "aws_iam_role", 87 | "primary" => { 88 | "id" => "hoge_role", 89 | "attributes" => { 90 | "arn" => "arn:aws:iam::123456789012:role/hoge_role", 91 | "assume_role_policy" => "{\n \"Version\": \"2008-10-17\",\n \"Statement\": [\n {\n \"Sid\": \"\",\n \"Effect\": \"Allow\",\n \"Principal\": {\n \"Service\": \"ec2.amazonaws.com\"\n },\n \"Action\": \"sts:AssumeRole\"\n }\n ]\n}\n", 92 | "id" => "hoge_role", 93 | "name" => "hoge_role", 94 | "path" => "/", 95 | "unique_id" => "ABCDEFGHIJKLMN1234567", 96 | } 97 | } 98 | }, 99 | "aws_iam_role.fuga_role" => { 100 | "type" => "aws_iam_role", 101 | "primary" => { 102 | "id" => "fuga_role", 103 | "attributes" => { 104 | "arn" => "arn:aws:iam::345678901234:role/fuga_role", 105 | "assume_role_policy" => "{\n \"Version\": \"2008-10-17\",\n \"Statement\": [\n {\n \"Sid\": \"1\",\n \"Effect\": \"Allow\",\n \"Principal\": {\n \"Service\": \"elastictranscoder.amazonaws.com\"\n },\n \"Action\": \"sts:AssumeRole\"\n }\n ]\n}\n", 106 | "id" => "fuga_role", 107 | "name" => "fuga_role", 108 | "path" => "/system/", 109 | "unique_id" => "OPQRSTUVWXYZA8901234", 110 | } 111 | } 112 | }, 113 | }) 114 | end 115 | end 116 | end 117 | end 118 | end 119 | -------------------------------------------------------------------------------- /spec/lib/terraforming/resource/iam_user_spec.rb: -------------------------------------------------------------------------------- 1 | require "spec_helper" 2 | 3 | module Terraforming 4 | module Resource 5 | describe IAMUser do 6 | let(:client) do 7 | Aws::IAM::Client.new(stub_responses: true) 8 | end 9 | 10 | let(:users) do 11 | [ 12 | { 13 | path: "/", 14 | user_name: "hoge", 15 | user_id: "ABCDEFGHIJKLMN1234567", 16 | arn: "arn:aws:iam::123456789012:user/hoge", 17 | create_date: Time.parse("2015-04-01 12:34:56 UTC"), 18 | password_last_used: Time.parse("2015-04-01 15:00:00 UTC"), 19 | }, 20 | { 21 | path: "/system/", 22 | user_name: "fuga.piyo", 23 | user_id: "OPQRSTUVWXYZA8901234", 24 | arn: "arn:aws:iam::345678901234:user/fuga", 25 | create_date: Time.parse("2015-05-01 12:34:56 UTC"), 26 | password_last_used: Time.parse("2015-05-01 15:00:00 UTC"), 27 | }, 28 | ] 29 | end 30 | 31 | before do 32 | client.stub_responses(:list_users, users: users) 33 | end 34 | 35 | describe ".tf" do 36 | it "should generate tf" do 37 | expect(described_class.tf(client: client)).to eq <<-EOS 38 | resource "aws_iam_user" "hoge" { 39 | name = "hoge" 40 | path = "/" 41 | } 42 | 43 | resource "aws_iam_user" "fuga-piyo" { 44 | name = "fuga.piyo" 45 | path = "/system/" 46 | } 47 | 48 | EOS 49 | end 50 | end 51 | 52 | describe ".tfstate" do 53 | it "should generate tfstate" do 54 | expect(described_class.tfstate(client: client)).to eq({ 55 | "aws_iam_user.hoge" => { 56 | "type" => "aws_iam_user", 57 | "primary" => { 58 | "id" => "hoge", 59 | "attributes" => { 60 | "arn" => "arn:aws:iam::123456789012:user/hoge", 61 | "id" => "hoge", 62 | "name" => "hoge", 63 | "path" => "/", 64 | "unique_id" => "ABCDEFGHIJKLMN1234567", 65 | "force_destroy" => "false", 66 | } 67 | } 68 | }, 69 | "aws_iam_user.fuga-piyo" => { 70 | "type" => "aws_iam_user", 71 | "primary" => { 72 | "id" => "fuga.piyo", 73 | "attributes" => { 74 | "arn" => "arn:aws:iam::345678901234:user/fuga", 75 | "id" => "fuga.piyo", 76 | "name" => "fuga.piyo", 77 | "path" => "/system/", 78 | "unique_id" => "OPQRSTUVWXYZA8901234", 79 | "force_destroy" => "false", 80 | } 81 | } 82 | }, 83 | }) 84 | end 85 | end 86 | end 87 | end 88 | end 89 | -------------------------------------------------------------------------------- /spec/lib/terraforming/resource/internet_gateway_spec.rb: -------------------------------------------------------------------------------- 1 | require "spec_helper" 2 | 3 | module Terraforming 4 | module Resource 5 | describe InternetGateway do 6 | let(:client) do 7 | Aws::EC2::Client.new(stub_responses: true) 8 | end 9 | 10 | let(:internet_gateways) do 11 | [ 12 | { 13 | internet_gateway_id: "igw-1234abcd", 14 | attachments: [ 15 | vpc_id: "vpc-1234abcd", 16 | state: "available" 17 | ], 18 | tags: [], 19 | }, 20 | { 21 | internet_gateway_id: "igw-5678efgh", 22 | attachments: [ 23 | vpc_id: "vpc-5678efgh", 24 | state: "available" 25 | ], 26 | tags: [ 27 | { 28 | key: "Name", 29 | value: "test" 30 | } 31 | ] 32 | } 33 | ] 34 | end 35 | 36 | before do 37 | client.stub_responses(:describe_internet_gateways, internet_gateways: internet_gateways) 38 | end 39 | 40 | describe ".tf" do 41 | it "should generate tf" do 42 | expect(described_class.tf(client: client)).to eq <<-EOS 43 | resource "aws_internet_gateway" "igw-1234abcd" { 44 | vpc_id = "vpc-1234abcd" 45 | 46 | tags { 47 | } 48 | } 49 | 50 | resource "aws_internet_gateway" "test" { 51 | vpc_id = "vpc-5678efgh" 52 | 53 | tags { 54 | "Name" = "test" 55 | } 56 | } 57 | 58 | EOS 59 | end 60 | end 61 | 62 | describe ".tfstate" do 63 | it "should generate tfstate" do 64 | expect(described_class.tfstate(client: client)).to eq({ 65 | "aws_internet_gateway.igw-1234abcd" => { 66 | "type" => "aws_internet_gateway", 67 | "primary" => { 68 | "id" => "igw-1234abcd", 69 | "attributes" => { 70 | "id" => "igw-1234abcd", 71 | "vpc_id" => "vpc-1234abcd", 72 | "tags.#" => "0", 73 | } 74 | } 75 | }, 76 | "aws_internet_gateway.test" => { 77 | "type" => "aws_internet_gateway", 78 | "primary" => { 79 | "id" => "igw-5678efgh", 80 | "attributes" => { 81 | "id" => "igw-5678efgh", 82 | "vpc_id" => "vpc-5678efgh", 83 | "tags.#" => "1", 84 | } 85 | } 86 | }, 87 | }) 88 | end 89 | end 90 | end 91 | end 92 | end 93 | -------------------------------------------------------------------------------- /spec/lib/terraforming/resource/kms_alias_spec.rb: -------------------------------------------------------------------------------- 1 | require "spec_helper" 2 | 3 | module Terraforming 4 | module Resource 5 | describe KMSAlias do 6 | let(:client) do 7 | Aws::KMS::Client.new(stub_responses: true) 8 | end 9 | 10 | let(:aliases) do 11 | [ 12 | { 13 | alias_name: "alias/aws/acm", 14 | alias_arn: "arn:aws:kms:ap-northeast-1:123456789012:alias/aws/acm", 15 | target_key_id: "12ab34cd-56ef-12ab-34cd-12ab34cd56ef" 16 | }, 17 | { 18 | alias_name: "alias/hoge", 19 | alias_arn: "arn:aws:kms:ap-northeast-1:123456789012:alias/hoge", 20 | target_key_id: "1234abcd-12ab-34cd-56ef-1234567890ab" 21 | }, 22 | { 23 | alias_name: "alias/fuga", 24 | alias_arn: "arn:aws:kms:ap-northeast-1:123456789012:alias/fuga", 25 | target_key_id: "abcd1234-ab12-cd34-ef56-abcdef123456" 26 | }, 27 | ] 28 | end 29 | 30 | before do 31 | client.stub_responses(:list_aliases, aliases: aliases) 32 | end 33 | 34 | describe ".tf" do 35 | it "should generate tf" do 36 | expect(described_class.tf(client: client)).to eq <<-EOS 37 | resource "aws_kms_alias" "hoge" { 38 | name = "alias/hoge" 39 | target_key_id = "1234abcd-12ab-34cd-56ef-1234567890ab" 40 | } 41 | 42 | resource "aws_kms_alias" "fuga" { 43 | name = "alias/fuga" 44 | target_key_id = "abcd1234-ab12-cd34-ef56-abcdef123456" 45 | } 46 | 47 | EOS 48 | end 49 | end 50 | 51 | describe ".tfstate" do 52 | it "should generate tfstate" do 53 | expect(described_class.tfstate(client: client)).to eq({ 54 | "aws_kms_alias.hoge" => { 55 | "type" => "aws_kms_alias", 56 | "primary" => { 57 | "id" => "alias/hoge", 58 | "attributes" => { 59 | "arn" => "arn:aws:kms:ap-northeast-1:123456789012:alias/hoge", 60 | "id" => "alias/hoge", 61 | "name" => "alias/hoge", 62 | "target_key_id" => "1234abcd-12ab-34cd-56ef-1234567890ab", 63 | } 64 | } 65 | }, 66 | "aws_kms_alias.fuga" => { 67 | "type" => "aws_kms_alias", 68 | "primary" => { 69 | "id" => "alias/fuga", 70 | "attributes" => { 71 | "arn" => "arn:aws:kms:ap-northeast-1:123456789012:alias/fuga", 72 | "id" => "alias/fuga", 73 | "name" => "alias/fuga", 74 | "target_key_id" => "abcd1234-ab12-cd34-ef56-abcdef123456", 75 | } 76 | } 77 | } 78 | }) 79 | end 80 | end 81 | end 82 | end 83 | end 84 | -------------------------------------------------------------------------------- /spec/lib/terraforming/resource/nat_gateway_spec.rb: -------------------------------------------------------------------------------- 1 | require "spec_helper" 2 | 3 | module Terraforming 4 | module Resource 5 | describe NATGateway do 6 | let(:client) do 7 | Aws::EC2::Client.new(stub_responses: true) 8 | end 9 | 10 | let(:nat_gateways) do 11 | [ 12 | { 13 | nat_gateway_id: "nat-0c5b68b2c4d64e037", 14 | subnet_id: "subnet-cd5645f7", 15 | nat_gateway_addresses: [ 16 | allocation_id: "eipalloc-b02a3c79", 17 | network_interface_id: "eni-03d4046f", 18 | private_ip: "10.0.3.6", 19 | public_ip: "52.5.3.67", 20 | ] 21 | }, 22 | { 23 | nat_gateway_id: "nat-0c5b68b2c4d64ea12", 24 | subnet_id: "subnet-cd564c9e", 25 | nat_gateway_addresses: [ 26 | allocation_id: "eipalloc-a03a3c79", 27 | network_interface_id: "eni-b6e4046f", 28 | private_ip: "10.0.4.6", 29 | public_ip: "54.4.5.68", 30 | ] 31 | } 32 | ] 33 | end 34 | 35 | before do 36 | client.stub_responses(:describe_nat_gateways, nat_gateways: nat_gateways) 37 | end 38 | 39 | describe ".tf" do 40 | it "should generate tf" do 41 | expect(described_class.tf(client: client)).to eq <<-EOS 42 | resource "aws_nat_gateway" "nat-0c5b68b2c4d64e037" { 43 | allocation_id = "eipalloc-b02a3c79" 44 | subnet_id = "subnet-cd5645f7" 45 | } 46 | 47 | resource "aws_nat_gateway" "nat-0c5b68b2c4d64ea12" { 48 | allocation_id = "eipalloc-a03a3c79" 49 | subnet_id = "subnet-cd564c9e" 50 | } 51 | 52 | EOS 53 | end 54 | end 55 | 56 | describe ".tfstate" do 57 | it "should generate tfstate" do 58 | expect(described_class.tfstate(client: client)).to eq({ 59 | "aws_nat_gateway.nat-0c5b68b2c4d64e037" => { 60 | "type" => "aws_nat_gateway", 61 | "primary" => { 62 | "id" => "nat-0c5b68b2c4d64e037", 63 | "attributes" => { 64 | "id" => "nat-0c5b68b2c4d64e037", 65 | "allocation_id" => "eipalloc-b02a3c79", 66 | "subnet_id" => "subnet-cd5645f7", 67 | "network_inferface_id" => "eni-03d4046f", 68 | "private_ip" => "10.0.3.6", 69 | "public_ip" => "52.5.3.67", 70 | } 71 | } 72 | }, 73 | "aws_nat_gateway.nat-0c5b68b2c4d64ea12" => { 74 | "type" => "aws_nat_gateway", 75 | "primary" => { 76 | "id" => "nat-0c5b68b2c4d64ea12", 77 | "attributes" => { 78 | "id" => "nat-0c5b68b2c4d64ea12", 79 | "allocation_id" => "eipalloc-a03a3c79", 80 | "subnet_id" => "subnet-cd564c9e", 81 | "network_inferface_id" => "eni-b6e4046f", 82 | "private_ip" => "10.0.4.6", 83 | "public_ip" => "54.4.5.68", 84 | } 85 | } 86 | }, 87 | }) 88 | end 89 | end 90 | end 91 | end 92 | end 93 | -------------------------------------------------------------------------------- /spec/lib/terraforming/resource/sns_topic_subscription_spec.rb: -------------------------------------------------------------------------------- 1 | require "spec_helper" 2 | 3 | module Terraforming 4 | module Resource 5 | describe SNSTopicSubscription do 6 | let(:client) do 7 | Aws::SNS::Client.new(stub_responses: true) 8 | end 9 | 10 | let(:subscriptions) do 11 | [ 12 | Aws::SNS::Types::Subscription.new(subscription_arn: "arn:aws:sns:us-west-2:012345678901:a-cool-topic:000ff1ce-dead-beef-f00d-ea7food5a1d1"), 13 | Aws::SNS::Types::Subscription.new(subscription_arn: "PendingConfirmation") 14 | ] 15 | end 16 | 17 | let(:attributes_regular) do 18 | { 19 | "Endpoint" => "arn:aws:sqs:us-west-2:012345678901:a-cool-queue", 20 | "Protocol" => "sqs", 21 | "RawMessageDelivery" => "false", 22 | "ConfirmationWasAuthenticated" => "true", 23 | "Owner" => "012345678901", 24 | "SubscriptionArn" => "arn:aws:sns:us-west-2:012345678901:a-cool-topic:000ff1ce-dead-beef-f00d-ea7food5a1d1", 25 | "TopicArn" => "arn:aws:sns:us-west-2:012345678901:a-cool-topic" 26 | } 27 | end 28 | 29 | let(:attributes_email) do 30 | { 31 | "Endpoint" => "arn:aws:sqs:us-west-2:012345678901:a-cool-queue", 32 | "Protocol" => "email-json", 33 | "RawMessageDelivery" => "false", 34 | "ConfirmationWasAuthenticated" => "true", 35 | "Owner" => "012345678901", 36 | "SubscriptionArn" => "arn:aws:sns:us-west-2:012345678901:a-cool-topic:000ff1ce-dead-beef-f00d-ea7food5a1d1", 37 | "TopicArn" => "arn:aws:sns:us-west-2:012345678901:a-cool-topic" 38 | } 39 | end 40 | 41 | before do 42 | client.stub_responses(:list_subscriptions, subscriptions: subscriptions) 43 | client.stub_responses(:get_subscription_attributes, attributes: attributes_regular) 44 | end 45 | 46 | describe ".tf" do 47 | it "should generate tf for non-email subscriptions" do 48 | expect(described_class.tf(client: client)).to eq <<-EOS 49 | resource "aws_sns_topic_subscription" "000ff1ce-dead-beef-f00d-ea7food5a1d1" { 50 | topic_arn = "arn:aws:sns:us-west-2:012345678901:a-cool-topic" 51 | protocol = "sqs" 52 | endpoint = "arn:aws:sqs:us-west-2:012345678901:a-cool-queue" 53 | raw_message_delivery = "false" 54 | } 55 | 56 | EOS 57 | end 58 | it "should generate commented tf for email subscriptions" do 59 | client.stub_responses(:get_subscription_attributes, attributes: attributes_email) 60 | expect(described_class.tf(client: client)).to eq <<-EOS 61 | /* 62 | resource "aws_sns_topic_subscription" "000ff1ce-dead-beef-f00d-ea7food5a1d1" { 63 | topic_arn = "arn:aws:sns:us-west-2:012345678901:a-cool-topic" 64 | protocol = "email-json" 65 | endpoint = "arn:aws:sqs:us-west-2:012345678901:a-cool-queue" 66 | raw_message_delivery = "false" 67 | } 68 | */ 69 | 70 | EOS 71 | end 72 | end 73 | 74 | describe ".tfstate" do 75 | it "should generate tfstate" do 76 | expect(described_class.tfstate(client: client)).to eq({ 77 | "aws_sns_topic_subscription.000ff1ce-dead-beef-f00d-ea7food5a1d1" => { 78 | "type" => "aws_sns_topic_subscription", 79 | "primary" => { 80 | "id" => "arn:aws:sns:us-west-2:012345678901:a-cool-topic:000ff1ce-dead-beef-f00d-ea7food5a1d1", 81 | "attributes" => { 82 | "id" => "arn:aws:sns:us-west-2:012345678901:a-cool-topic:000ff1ce-dead-beef-f00d-ea7food5a1d1", 83 | "topic_arn" => "arn:aws:sns:us-west-2:012345678901:a-cool-topic", 84 | "protocol" => "sqs", 85 | "endpoint" => "arn:aws:sqs:us-west-2:012345678901:a-cool-queue", 86 | "raw_message_delivery" => "false", 87 | "confirmation_timeout_in_minutes" => "1", 88 | "endpoint_auto_confirms" => "false" 89 | }, 90 | }, 91 | } 92 | }) 93 | end 94 | end 95 | end 96 | end 97 | end 98 | -------------------------------------------------------------------------------- /spec/lib/terraforming/resource/subnet_spec.rb: -------------------------------------------------------------------------------- 1 | require "spec_helper" 2 | 3 | module Terraforming 4 | module Resource 5 | describe Subnet do 6 | let(:client) do 7 | Aws::EC2::Client.new(stub_responses: true) 8 | end 9 | 10 | let(:subnets) do 11 | [ 12 | { 13 | subnet_id: "subnet-1234abcd", 14 | state: "available", 15 | vpc_id: "vpc-1234abcd", 16 | cidr_block: "10.0.8.0/21", 17 | available_ip_address_count: 1000, 18 | availability_zone: "ap-northeast-1c", 19 | default_for_az: false, 20 | map_public_ip_on_launch: false, 21 | tags: [ 22 | { key: "Name", value: "hoge" } 23 | ] 24 | }, 25 | { 26 | subnet_id: "subnet-5678efgh", 27 | state: "available", 28 | vpc_id: "vpc-5678efgh", 29 | cidr_block: "10.0.8.0/21", 30 | available_ip_address_count: 2000, 31 | availability_zone: "ap-northeast-1c", 32 | default_for_az: false, 33 | map_public_ip_on_launch: false, 34 | tags: [ 35 | { key: "Name", value: "fuga" } 36 | ] 37 | } 38 | ] 39 | end 40 | 41 | before do 42 | client.stub_responses(:describe_subnets, subnets: subnets) 43 | end 44 | 45 | describe ".tf" do 46 | it "should generate tf" do 47 | expect(described_class.tf(client: client)).to eq <<-EOS 48 | resource "aws_subnet" "subnet-1234abcd-hoge" { 49 | vpc_id = "vpc-1234abcd" 50 | cidr_block = "10.0.8.0/21" 51 | availability_zone = "ap-northeast-1c" 52 | map_public_ip_on_launch = false 53 | 54 | tags { 55 | "Name" = "hoge" 56 | } 57 | } 58 | 59 | resource "aws_subnet" "subnet-5678efgh-fuga" { 60 | vpc_id = "vpc-5678efgh" 61 | cidr_block = "10.0.8.0/21" 62 | availability_zone = "ap-northeast-1c" 63 | map_public_ip_on_launch = false 64 | 65 | tags { 66 | "Name" = "fuga" 67 | } 68 | } 69 | 70 | EOS 71 | end 72 | end 73 | 74 | describe ".tfstate" do 75 | it "should generate tfstate" do 76 | expect(described_class.tfstate(client: client)).to eq({ 77 | "aws_subnet.subnet-1234abcd-hoge" => { 78 | "type" => "aws_subnet", 79 | "primary" => { 80 | "id" => "subnet-1234abcd", 81 | "attributes" => { 82 | "availability_zone" => "ap-northeast-1c", 83 | "cidr_block" => "10.0.8.0/21", 84 | "id" => "subnet-1234abcd", 85 | "map_public_ip_on_launch" => "false", 86 | "tags.#" => "1", 87 | "vpc_id" => "vpc-1234abcd" 88 | } 89 | } 90 | }, 91 | "aws_subnet.subnet-5678efgh-fuga" => { 92 | "type" => "aws_subnet", 93 | "primary" => { 94 | "id" => "subnet-5678efgh", 95 | "attributes" => { 96 | "availability_zone" => "ap-northeast-1c", 97 | "cidr_block" => "10.0.8.0/21", 98 | "id" => "subnet-5678efgh", 99 | "map_public_ip_on_launch" => "false", 100 | "tags.#" => "1", 101 | "vpc_id" => "vpc-5678efgh" 102 | } 103 | } 104 | }, 105 | }) 106 | end 107 | end 108 | end 109 | end 110 | end 111 | -------------------------------------------------------------------------------- /spec/lib/terraforming/resource/vpc_spec.rb: -------------------------------------------------------------------------------- 1 | require "spec_helper" 2 | 3 | module Terraforming 4 | module Resource 5 | describe VPC do 6 | let(:client) do 7 | Aws::EC2::Client.new(stub_responses: true) 8 | end 9 | 10 | let(:vpcs) do 11 | [ 12 | { 13 | vpc_id: "vpc-1234abcd", 14 | state: "available", 15 | cidr_block: "10.0.0.0/16", 16 | dhcp_options_id: "dopt-1234abcd", 17 | tags: [ 18 | { 19 | key: "Name", 20 | value: "hoge" 21 | } 22 | ], 23 | instance_tenancy: "default", 24 | is_default: false 25 | }, 26 | { 27 | vpc_id: "vpc-5678efgh", 28 | state: "available", 29 | cidr_block: "10.0.0.0/16", 30 | dhcp_options_id: "dopt-5678efgh", 31 | tags: [ 32 | { 33 | key: "Name", 34 | value: "fuga" 35 | } 36 | ], 37 | instance_tenancy: "default", 38 | is_default: false 39 | } 40 | ] 41 | end 42 | 43 | before do 44 | client.stub_responses(:describe_vpcs, vpcs: vpcs) 45 | 46 | attr_stub_responses = [] 47 | 48 | %w(vpc-1234abcd vpc-5678efgh).each do |_vpc_id| 49 | %i(enable_dns_hostnames enable_dns_support).each do |attr| 50 | attr_stub_responses << { attr => { value: true } } 51 | end 52 | end 53 | 54 | client.stub_responses(:describe_vpc_attribute, attr_stub_responses) 55 | end 56 | 57 | describe ".tf" do 58 | it "should generate tf" do 59 | expect(described_class.tf(client: client)).to eq <<-EOS 60 | resource "aws_vpc" "hoge" { 61 | cidr_block = "10.0.0.0/16" 62 | enable_dns_hostnames = true 63 | enable_dns_support = true 64 | instance_tenancy = "default" 65 | 66 | tags { 67 | "Name" = "hoge" 68 | } 69 | } 70 | 71 | resource "aws_vpc" "fuga" { 72 | cidr_block = "10.0.0.0/16" 73 | enable_dns_hostnames = true 74 | enable_dns_support = true 75 | instance_tenancy = "default" 76 | 77 | tags { 78 | "Name" = "fuga" 79 | } 80 | } 81 | 82 | EOS 83 | end 84 | end 85 | 86 | describe ".tfstate" do 87 | it "should generate tfstate" do 88 | expect(described_class.tfstate(client: client)).to eq({ 89 | "aws_vpc.hoge" => { 90 | "type" => "aws_vpc", 91 | "primary" => { 92 | "id" => "vpc-1234abcd", 93 | "attributes" => { 94 | "cidr_block" => "10.0.0.0/16", 95 | "enable_dns_hostnames" => "true", 96 | "enable_dns_support" => "true", 97 | "id" => "vpc-1234abcd", 98 | "instance_tenancy" => "default", 99 | "tags.#" => "1", 100 | } 101 | } 102 | }, 103 | "aws_vpc.fuga" => { 104 | "type" => "aws_vpc", 105 | "primary" => { 106 | "id" => "vpc-5678efgh", 107 | "attributes" => { 108 | "cidr_block" => "10.0.0.0/16", 109 | "enable_dns_hostnames" => "true", 110 | "enable_dns_support" => "true", 111 | "id" => "vpc-5678efgh", 112 | "instance_tenancy" => "default", 113 | "tags.#" => "1", 114 | } 115 | } 116 | }, 117 | }) 118 | end 119 | end 120 | end 121 | end 122 | end 123 | -------------------------------------------------------------------------------- /spec/lib/terraforming/resource/vpn_gateway_spec.rb: -------------------------------------------------------------------------------- 1 | require "spec_helper" 2 | 3 | module Terraforming 4 | module Resource 5 | describe VPNGateway do 6 | let(:client) do 7 | Aws::EC2::Client.new(stub_responses: true) 8 | end 9 | 10 | let(:vpn_gateways) do 11 | [ 12 | { 13 | vpn_gateway_id: "vgw-1234abcd", 14 | vpc_attachments: [ 15 | vpc_id: "vpc-1234abcd", 16 | state: "available" 17 | ], 18 | availability_zone: "us-east-1c", 19 | tags: [], 20 | }, 21 | { 22 | vpn_gateway_id: "vgw-5678efgh", 23 | vpc_attachments: [ 24 | vpc_id: "vpc-5678efgh", 25 | state: "available" 26 | ], 27 | availability_zone: "us-east-1d", 28 | tags: [ 29 | { 30 | key: "Name", 31 | value: "test" 32 | } 33 | ] 34 | } 35 | ] 36 | end 37 | 38 | before do 39 | client.stub_responses(:describe_vpn_gateways, vpn_gateways: vpn_gateways) 40 | end 41 | 42 | describe ".tf" do 43 | it "should generate tf" do 44 | expect(described_class.tf(client: client)).to eq <<-EOS 45 | resource "aws_vpn_gateway" "vgw-1234abcd" { 46 | vpc_id = "vpc-1234abcd" 47 | availability_zone = "us-east-1c" 48 | tags { 49 | } 50 | } 51 | 52 | resource "aws_vpn_gateway" "test" { 53 | vpc_id = "vpc-5678efgh" 54 | availability_zone = "us-east-1d" 55 | tags { 56 | "Name" = "test" 57 | } 58 | } 59 | 60 | EOS 61 | end 62 | end 63 | 64 | describe ".tfstate" do 65 | it "should generate tfstate" do 66 | expect(described_class.tfstate(client: client)).to eq({ 67 | "aws_vpn_gateway.vgw-1234abcd" => { 68 | "type" => "aws_vpn_gateway", 69 | "primary" => { 70 | "id" => "vgw-1234abcd", 71 | "attributes" => { 72 | "id" => "vgw-1234abcd", 73 | "vpc_id" => "vpc-1234abcd", 74 | "availability_zone" => "us-east-1c", 75 | "tags.#" => "0", 76 | } 77 | } 78 | }, 79 | "aws_vpn_gateway.test" => { 80 | "type" => "aws_vpn_gateway", 81 | "primary" => { 82 | "id" => "vgw-5678efgh", 83 | "attributes" => { 84 | "id" => "vgw-5678efgh", 85 | "vpc_id" => "vpc-5678efgh", 86 | "availability_zone" => "us-east-1d", 87 | "tags.#" => "1", 88 | } 89 | } 90 | }, 91 | }) 92 | end 93 | end 94 | end 95 | end 96 | end 97 | -------------------------------------------------------------------------------- /spec/lib/terraforming_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe Terraforming do 4 | it 'has a version number' do 5 | expect(Terraforming::VERSION).not_to be nil 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /spec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | require "coveralls" 2 | require "simplecov" 3 | 4 | SimpleCov.start do 5 | add_filter "lib/terraforming.rb" 6 | add_filter "lib/terraforming/version.rb" 7 | 8 | formatter SimpleCov::Formatter::MultiFormatter.new([ 9 | Coveralls::SimpleCov::Formatter, 10 | SimpleCov::Formatter::HTMLFormatter, 11 | ]) 12 | end 13 | 14 | $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__) 15 | require 'terraforming' 16 | 17 | require 'tempfile' 18 | require 'time' 19 | 20 | def fixture_path(fixture_name) 21 | File.join(File.dirname(__FILE__), "fixtures", fixture_name) 22 | end 23 | 24 | def tfstate_fixture_path 25 | fixture_path("terraform.tfstate") 26 | end 27 | 28 | def tfstate_fixture 29 | JSON.parse(open(tfstate_fixture_path).read) 30 | end 31 | -------------------------------------------------------------------------------- /templates/resource.erb.erb: -------------------------------------------------------------------------------- 1 | resource "aws_<%= resource %>" "resource_name" { 2 | 3 | } 4 | -------------------------------------------------------------------------------- /templates/resource.rb.erb: -------------------------------------------------------------------------------- 1 | module Terraforming 2 | module Resource 3 | class <%= camelize(resource) %> 4 | include Terraforming::Util 5 | 6 | # TODO: Select appropriate Client class from here: 7 | # http://docs.aws.amazon.com/sdkforruby/api/index.html 8 | def self.tf(client: Aws::SomeResource::Client.new) 9 | self.new(client).tf 10 | end 11 | 12 | # TODO: Select appropriate Client class from here: 13 | # http://docs.aws.amazon.com/sdkforruby/api/index.html 14 | def self.tfstate(client: Aws::SomeResource::Client.new) 15 | self.new(client).tfstate 16 | end 17 | 18 | def initialize(client) 19 | @client = client 20 | end 21 | 22 | def tf 23 | apply_template(@client, "tf/<%= resource %>") 24 | end 25 | 26 | def tfstate 27 | 28 | end 29 | end 30 | end 31 | end 32 | -------------------------------------------------------------------------------- /templates/resource_spec.rb.erb: -------------------------------------------------------------------------------- 1 | require "spec_helper" 2 | 3 | module Terraforming 4 | module Resource 5 | describe <%= camelize(resource) %> do 6 | let(:client) do 7 | # TODO: Select appropriate Client class from here: 8 | # http://docs.aws.amazon.com/sdkforruby/api/index.html 9 | Aws::SomeResource::Client.new(stub_responses: true) 10 | end 11 | 12 | describe ".tf" do 13 | xit "should generate tf" do 14 | expect(described_class.tf(client: client)).to eq <<-EOS 15 | resource "aws_<%= resource %>" "resource_name" { 16 | 17 | } 18 | 19 | EOS 20 | end 21 | end 22 | 23 | describe ".tfstate" do 24 | xit "should generate tfstate" do 25 | expect(described_class.tfstate(client: client)).to eq({ 26 | "aws_<%= resource %>.resource_name" => { 27 | "type" => "aws_<%= resource %>", 28 | "primary" => { 29 | "id" => "", 30 | "attributes" => { 31 | } 32 | } 33 | } 34 | }) 35 | end 36 | end 37 | end 38 | end 39 | end 40 | -------------------------------------------------------------------------------- /terraforming.gemspec: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | lib = File.expand_path('../lib', __FILE__) 3 | $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) 4 | require 'terraforming/version' 5 | 6 | Gem::Specification.new do |spec| 7 | spec.name = "terraforming" 8 | spec.version = Terraforming::VERSION 9 | spec.authors = ["Daisuke Fujita"] 10 | spec.email = ["dtanshi45@gmail.com"] 11 | 12 | spec.summary = %q{Export existing AWS resources to Terraform style (tf, tfstate)} 13 | spec.description = %q{Export existing AWS resources to Terraform style (tf, tfstate)} 14 | spec.homepage = "https://github.com/dtan4/terraforming" 15 | spec.license = "MIT" 16 | 17 | spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) } 18 | spec.bindir = "bin" 19 | spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) } 20 | spec.require_paths = ["lib"] 21 | 22 | spec.add_dependency "aws-sdk-autoscaling", "~> 1" 23 | spec.add_dependency "aws-sdk-cloudwatch", "~> 1" 24 | spec.add_dependency "aws-sdk-dynamodb", "~> 1.18" 25 | spec.add_dependency "aws-sdk-ec2", "~> 1" 26 | spec.add_dependency "aws-sdk-efs", "~> 1", ">= 1.13.0" 27 | spec.add_dependency "aws-sdk-elasticache", "~> 1" 28 | spec.add_dependency "aws-sdk-elasticloadbalancing", "~> 1" 29 | spec.add_dependency "aws-sdk-elasticloadbalancingv2", "~> 1" 30 | spec.add_dependency "aws-sdk-iam", "~> 1" 31 | spec.add_dependency "aws-sdk-kms", "~> 1" 32 | spec.add_dependency "aws-sdk-rds", "~> 1" 33 | spec.add_dependency "aws-sdk-redshift", "~> 1" 34 | spec.add_dependency "aws-sdk-route53", "~> 1" 35 | spec.add_dependency "aws-sdk-s3", "~> 1" 36 | spec.add_dependency "aws-sdk-sns", "~> 1" 37 | spec.add_dependency "aws-sdk-sqs", "~> 1" 38 | spec.add_dependency "multi_json", "~> 1.12.1" 39 | spec.add_dependency "thor" 40 | 41 | spec.add_development_dependency "coveralls", "~> 0.8.13" 42 | spec.add_development_dependency "rake" 43 | spec.add_development_dependency "rspec", "~> 3.2" 44 | spec.add_development_dependency "simplecov", "~> 0.14.1" 45 | end 46 | --------------------------------------------------------------------------------