terrafying-components 1.4.3 → 1.4.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
 - data/lib/hash/merge_with_arrays.rb +7 -0
 - data/lib/terrafying/components.rb +10 -0
 - data/lib/terrafying/components/auditd.rb +158 -0
 - data/lib/terrafying/components/ca.rb +55 -0
 - data/lib/terrafying/components/dynamicset.rb +229 -0
 - data/lib/terrafying/components/endpoint.rb +96 -0
 - data/lib/terrafying/components/endpointservice.rb +63 -0
 - data/lib/terrafying/components/ignition.rb +117 -0
 - data/lib/terrafying/components/instance.rb +112 -0
 - data/lib/terrafying/components/instanceprofile.rb +81 -0
 - data/lib/terrafying/components/letsencrypt.rb +146 -0
 - data/lib/terrafying/components/loadbalancer.rb +159 -0
 - data/lib/terrafying/components/ports.rb +35 -0
 - data/lib/terrafying/components/selfsignedca.rb +171 -0
 - data/lib/terrafying/components/service.rb +148 -0
 - data/lib/terrafying/components/staticset.rb +153 -0
 - data/lib/terrafying/components/subnet.rb +105 -0
 - data/lib/terrafying/components/support/deregister-vpn +48 -0
 - data/lib/terrafying/components/support/register-vpn +46 -0
 - data/lib/terrafying/components/templates/ignition.yaml +115 -0
 - data/lib/terrafying/components/usable.rb +129 -0
 - data/lib/terrafying/components/version.rb +5 -0
 - data/lib/terrafying/components/vpc.rb +417 -0
 - data/lib/terrafying/components/vpn.rb +358 -0
 - data/lib/terrafying/components/zone.rb +144 -0
 - metadata +28 -31
 
| 
         @@ -0,0 +1,96 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
             
     | 
| 
      
 2 
     | 
    
         
            +
            require 'terrafying/components/loadbalancer'
         
     | 
| 
      
 3 
     | 
    
         
            +
            require 'terrafying/components/usable'
         
     | 
| 
      
 4 
     | 
    
         
            +
            require 'terrafying/components/vpc'
         
     | 
| 
      
 5 
     | 
    
         
            +
            require 'terrafying/generator'
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
            module Terrafying
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
              module Components
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                class Endpoint < Terrafying::Context
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                  attr_reader :security_group
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                  include Usable
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                  def self.create_in(vpc, name, options={})
         
     | 
| 
      
 18 
     | 
    
         
            +
                    Endpoint.new.create_in(vpc, name, options)
         
     | 
| 
      
 19 
     | 
    
         
            +
                  end
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
                  def initialize
         
     | 
| 
      
 22 
     | 
    
         
            +
                    super
         
     | 
| 
      
 23 
     | 
    
         
            +
                  end
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                  def create_in(vpc, name, options={})
         
     | 
| 
      
 26 
     | 
    
         
            +
                    options = {
         
     | 
| 
      
 27 
     | 
    
         
            +
                      auto_accept: true,
         
     | 
| 
      
 28 
     | 
    
         
            +
                      subnets: vpc.subnets.fetch(:private, []),
         
     | 
| 
      
 29 
     | 
    
         
            +
                      private_dns: false,
         
     | 
| 
      
 30 
     | 
    
         
            +
                      dns_name: name,
         
     | 
| 
      
 31 
     | 
    
         
            +
                      tags: {},
         
     | 
| 
      
 32 
     | 
    
         
            +
                    }.merge(options)
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                    ident = "#{tf_safe(vpc.name)}-#{name}"
         
     | 
| 
      
 35 
     | 
    
         
            +
                    @name = name
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
                    if options[:service]
         
     | 
| 
      
 38 
     | 
    
         
            +
                      service_name = options[:service].service_name
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
                      @ports = options[:service].load_balancer.ports
         
     | 
| 
      
 41 
     | 
    
         
            +
                    elsif options[:service_name]
         
     | 
| 
      
 42 
     | 
    
         
            +
                      service_name = options[:service_name]
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
                      if options[:service_name].start_with?("com.amazonaws")
         
     | 
| 
      
 45 
     | 
    
         
            +
                        @ports = enrich_ports([443])
         
     | 
| 
      
 46 
     | 
    
         
            +
                      else
         
     | 
| 
      
 47 
     | 
    
         
            +
                        endpoint_service = aws.endpoint_service_by_name(options[:service_name])
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
                        target_groups = endpoint_service.network_load_balancer_arns.map { |arn|
         
     | 
| 
      
 50 
     | 
    
         
            +
                          aws.target_groups_by_lb(arn)
         
     | 
| 
      
 51 
     | 
    
         
            +
                        }.flatten
         
     | 
| 
      
 52 
     | 
    
         
            +
             
     | 
| 
      
 53 
     | 
    
         
            +
                        @ports = enrich_ports(target_groups.map(&:port))
         
     | 
| 
      
 54 
     | 
    
         
            +
                      end
         
     | 
| 
      
 55 
     | 
    
         
            +
                    elsif options[:source]
         
     | 
| 
      
 56 
     | 
    
         
            +
                      if options[:source].is_a?(VPC)
         
     | 
| 
      
 57 
     | 
    
         
            +
                        source = { vpc: options[:source], name: name }
         
     | 
| 
      
 58 
     | 
    
         
            +
                      else
         
     | 
| 
      
 59 
     | 
    
         
            +
                        source = options[:source]
         
     | 
| 
      
 60 
     | 
    
         
            +
                      end
         
     | 
| 
      
 61 
     | 
    
         
            +
             
     | 
| 
      
 62 
     | 
    
         
            +
                      lb = LoadBalancer.find_in(source[:vpc], source[:name])
         
     | 
| 
      
 63 
     | 
    
         
            +
             
     | 
| 
      
 64 
     | 
    
         
            +
                      @ports = lb.ports
         
     | 
| 
      
 65 
     | 
    
         
            +
                      service_name = aws.endpoint_service_by_lb_arn(lb.id).service_name
         
     | 
| 
      
 66 
     | 
    
         
            +
                    else
         
     | 
| 
      
 67 
     | 
    
         
            +
                      raise "You need to pass either a service_name or source option to create an endpoint"
         
     | 
| 
      
 68 
     | 
    
         
            +
                    end
         
     | 
| 
      
 69 
     | 
    
         
            +
             
     | 
| 
      
 70 
     | 
    
         
            +
                    @security_group = resource :aws_security_group, ident, {
         
     | 
| 
      
 71 
     | 
    
         
            +
                                                 name: "endpoint-#{ident}",
         
     | 
| 
      
 72 
     | 
    
         
            +
                                                 description: "Describe the ingress and egress of the endpoint #{ident}",
         
     | 
| 
      
 73 
     | 
    
         
            +
                                                 tags: options[:tags],
         
     | 
| 
      
 74 
     | 
    
         
            +
                                                 vpc_id: vpc.id,
         
     | 
| 
      
 75 
     | 
    
         
            +
                                               }
         
     | 
| 
      
 76 
     | 
    
         
            +
             
     | 
| 
      
 77 
     | 
    
         
            +
                    resource :aws_vpc_endpoint, ident, {
         
     | 
| 
      
 78 
     | 
    
         
            +
                               vpc_id: vpc.id,
         
     | 
| 
      
 79 
     | 
    
         
            +
                               service_name: service_name,
         
     | 
| 
      
 80 
     | 
    
         
            +
                               vpc_endpoint_type: "Interface",
         
     | 
| 
      
 81 
     | 
    
         
            +
                               security_group_ids: [ @security_group ],
         
     | 
| 
      
 82 
     | 
    
         
            +
                               auto_accept: options[:auto_accept],
         
     | 
| 
      
 83 
     | 
    
         
            +
                               subnet_ids: options[:subnets].map(&:id),
         
     | 
| 
      
 84 
     | 
    
         
            +
                               private_dns_enabled: options[:private_dns],
         
     | 
| 
      
 85 
     | 
    
         
            +
                             }
         
     | 
| 
      
 86 
     | 
    
         
            +
             
     | 
| 
      
 87 
     | 
    
         
            +
                    vpc.zone.add_cname_in(self, options[:dns_name], output_of(:aws_vpc_endpoint, ident, "dns_entry.0.dns_name"))
         
     | 
| 
      
 88 
     | 
    
         
            +
             
     | 
| 
      
 89 
     | 
    
         
            +
                    self
         
     | 
| 
      
 90 
     | 
    
         
            +
                  end
         
     | 
| 
      
 91 
     | 
    
         
            +
             
     | 
| 
      
 92 
     | 
    
         
            +
                end
         
     | 
| 
      
 93 
     | 
    
         
            +
             
     | 
| 
      
 94 
     | 
    
         
            +
              end
         
     | 
| 
      
 95 
     | 
    
         
            +
             
     | 
| 
      
 96 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,63 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
             
     | 
| 
      
 2 
     | 
    
         
            +
            require 'terrafying/generator'
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            module Terrafying
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
              module Components
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
                class EndpointService < Terrafying::Context
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                  attr_reader :name, :load_balancer, :service_name
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                  def self.create_for(load_balancer, name, options={})
         
     | 
| 
      
 13 
     | 
    
         
            +
                    EndpointService.new.create_for(load_balancer, name, options)
         
     | 
| 
      
 14 
     | 
    
         
            +
                  end
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                  def self.find(service_name)
         
     | 
| 
      
 17 
     | 
    
         
            +
                    EndpointService.new.find(service_name)
         
     | 
| 
      
 18 
     | 
    
         
            +
                  end
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                  def initialize
         
     | 
| 
      
 21 
     | 
    
         
            +
                    super
         
     | 
| 
      
 22 
     | 
    
         
            +
                  end
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                  def find(service_name)
         
     | 
| 
      
 25 
     | 
    
         
            +
                    raise 'unimplemented'
         
     | 
| 
      
 26 
     | 
    
         
            +
                  end
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
                  def create_for(load_balancer, name, options={})
         
     | 
| 
      
 29 
     | 
    
         
            +
                    options = {
         
     | 
| 
      
 30 
     | 
    
         
            +
                      acceptance_required: true,
         
     | 
| 
      
 31 
     | 
    
         
            +
                      allowed_principals: [
         
     | 
| 
      
 32 
     | 
    
         
            +
                        "arn:aws:iam::#{aws.account_id}:root",
         
     | 
| 
      
 33 
     | 
    
         
            +
                      ],
         
     | 
| 
      
 34 
     | 
    
         
            +
                    }.merge(options)
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
                    if ! load_balancer or load_balancer.type != "network"
         
     | 
| 
      
 37 
     | 
    
         
            +
                      raise "The load balancer needs to be a network load balancer"
         
     | 
| 
      
 38 
     | 
    
         
            +
                    end
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
                    @name = name
         
     | 
| 
      
 41 
     | 
    
         
            +
                    @load_balancer = load_balancer
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
                    resource :aws_vpc_endpoint_service, name, {
         
     | 
| 
      
 44 
     | 
    
         
            +
                               acceptance_required: options[:acceptance_required],
         
     | 
| 
      
 45 
     | 
    
         
            +
                               allowed_principals: options[:allowed_principals],
         
     | 
| 
      
 46 
     | 
    
         
            +
                               network_load_balancer_arns: [load_balancer.id],
         
     | 
| 
      
 47 
     | 
    
         
            +
                             }
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
                    @service_name = output_of(:aws_vpc_endpoint_service, name, "service_name")
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
                    self
         
     | 
| 
      
 52 
     | 
    
         
            +
                  end
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
      
 54 
     | 
    
         
            +
                  def expose_in(vpc, options={})
         
     | 
| 
      
 55 
     | 
    
         
            +
                    name = options.fetch(:name, @name)
         
     | 
| 
      
 56 
     | 
    
         
            +
                    add! Endpoint.create_in(vpc, name, options.merge({ service: self }))
         
     | 
| 
      
 57 
     | 
    
         
            +
                  end
         
     | 
| 
      
 58 
     | 
    
         
            +
             
     | 
| 
      
 59 
     | 
    
         
            +
                end
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
      
 61 
     | 
    
         
            +
              end
         
     | 
| 
      
 62 
     | 
    
         
            +
             
     | 
| 
      
 63 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,117 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'erb'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'ostruct'
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            module Terrafying
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
              module Components
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
                class Ignition
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                  UNIT_REQUIRED_KEYS = [:name]
         
     | 
| 
      
 11 
     | 
    
         
            +
                  FILE_REQUIRED_KEYS = [:path, :mode, :contents]
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                  def self.container_unit(name, image, options={})
         
     | 
| 
      
 14 
     | 
    
         
            +
                    options = {
         
     | 
| 
      
 15 
     | 
    
         
            +
                      volumes: [],
         
     | 
| 
      
 16 
     | 
    
         
            +
                      environment_variables: [],
         
     | 
| 
      
 17 
     | 
    
         
            +
                      arguments: [],
         
     | 
| 
      
 18 
     | 
    
         
            +
                      require_units: [],
         
     | 
| 
      
 19 
     | 
    
         
            +
                      host_networking: false,
         
     | 
| 
      
 20 
     | 
    
         
            +
                      privileged: false,
         
     | 
| 
      
 21 
     | 
    
         
            +
                    }.merge(options)
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                    if options[:require_units].count > 0
         
     | 
| 
      
 24 
     | 
    
         
            +
                      require_units = options[:require_units].join(" ")
         
     | 
| 
      
 25 
     | 
    
         
            +
                      require = <<EOF
         
     | 
| 
      
 26 
     | 
    
         
            +
            After=#{require_units}
         
     | 
| 
      
 27 
     | 
    
         
            +
            Requires=#{require_units}
         
     | 
| 
      
 28 
     | 
    
         
            +
            EOF
         
     | 
| 
      
 29 
     | 
    
         
            +
                    end
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
                    docker_options = []
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
                    if options[:environment_variables].count > 0
         
     | 
| 
      
 34 
     | 
    
         
            +
                      docker_options += options[:environment_variables].map { |var|
         
     | 
| 
      
 35 
     | 
    
         
            +
                        "-e #{var}"
         
     | 
| 
      
 36 
     | 
    
         
            +
                      }
         
     | 
| 
      
 37 
     | 
    
         
            +
                    end
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
                    if options[:volumes].count > 0
         
     | 
| 
      
 40 
     | 
    
         
            +
                      docker_options += options[:volumes].map { |volume|
         
     | 
| 
      
 41 
     | 
    
         
            +
                        "-v #{volume}"
         
     | 
| 
      
 42 
     | 
    
         
            +
                      }
         
     | 
| 
      
 43 
     | 
    
         
            +
                    end
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
                    if options[:host_networking]
         
     | 
| 
      
 46 
     | 
    
         
            +
                      docker_options << "--net=host"
         
     | 
| 
      
 47 
     | 
    
         
            +
                    end
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
                    if options[:privileged]
         
     | 
| 
      
 50 
     | 
    
         
            +
                      docker_options << "--privileged"
         
     | 
| 
      
 51 
     | 
    
         
            +
                    end
         
     | 
| 
      
 52 
     | 
    
         
            +
             
     | 
| 
      
 53 
     | 
    
         
            +
                    docker_options_str = " \\\n" + docker_options.join(" \\\n")
         
     | 
| 
      
 54 
     | 
    
         
            +
             
     | 
| 
      
 55 
     | 
    
         
            +
                    if options[:arguments].count > 0
         
     | 
| 
      
 56 
     | 
    
         
            +
                      arguments = " \\\n" + options[:arguments].join(" \\\n")
         
     | 
| 
      
 57 
     | 
    
         
            +
                    end
         
     | 
| 
      
 58 
     | 
    
         
            +
             
     | 
| 
      
 59 
     | 
    
         
            +
                    {
         
     | 
| 
      
 60 
     | 
    
         
            +
                      name: "#{name}.service",
         
     | 
| 
      
 61 
     | 
    
         
            +
                      contents: <<EOF
         
     | 
| 
      
 62 
     | 
    
         
            +
            [Install]
         
     | 
| 
      
 63 
     | 
    
         
            +
            WantedBy=multi-user.target
         
     | 
| 
      
 64 
     | 
    
         
            +
             
     | 
| 
      
 65 
     | 
    
         
            +
            [Unit]
         
     | 
| 
      
 66 
     | 
    
         
            +
            Description=#{name}
         
     | 
| 
      
 67 
     | 
    
         
            +
            #{require}
         
     | 
| 
      
 68 
     | 
    
         
            +
             
     | 
| 
      
 69 
     | 
    
         
            +
            [Service]
         
     | 
| 
      
 70 
     | 
    
         
            +
            ExecStartPre=-/usr/bin/docker rm -f #{name}
         
     | 
| 
      
 71 
     | 
    
         
            +
            ExecStart=/usr/bin/docker run --name #{name} #{docker_options_str} \
         
     | 
| 
      
 72 
     | 
    
         
            +
            #{image} #{arguments}
         
     | 
| 
      
 73 
     | 
    
         
            +
            Restart=always
         
     | 
| 
      
 74 
     | 
    
         
            +
            RestartSec=30
         
     | 
| 
      
 75 
     | 
    
         
            +
             
     | 
| 
      
 76 
     | 
    
         
            +
            EOF
         
     | 
| 
      
 77 
     | 
    
         
            +
                    }
         
     | 
| 
      
 78 
     | 
    
         
            +
                  end
         
     | 
| 
      
 79 
     | 
    
         
            +
             
     | 
| 
      
 80 
     | 
    
         
            +
                  def self.generate(options={})
         
     | 
| 
      
 81 
     | 
    
         
            +
                    options = {
         
     | 
| 
      
 82 
     | 
    
         
            +
                      keypairs: [],
         
     | 
| 
      
 83 
     | 
    
         
            +
                      volumes: [],
         
     | 
| 
      
 84 
     | 
    
         
            +
                      files: [],
         
     | 
| 
      
 85 
     | 
    
         
            +
                      units: [],
         
     | 
| 
      
 86 
     | 
    
         
            +
                      ssh_group: "cloud",
         
     | 
| 
      
 87 
     | 
    
         
            +
                      disable_update_engine: false,
         
     | 
| 
      
 88 
     | 
    
         
            +
                      region: Terrafying::Generator.aws.region,
         
     | 
| 
      
 89 
     | 
    
         
            +
                    }.merge(options)
         
     | 
| 
      
 90 
     | 
    
         
            +
             
     | 
| 
      
 91 
     | 
    
         
            +
                    if ! options[:units].all? { |u| UNIT_REQUIRED_KEYS.all? { |key| u.has_key?(key) } }
         
     | 
| 
      
 92 
     | 
    
         
            +
                      raise "All units require the following keys: #{UNIT_REQUIRED_KEYS}"
         
     | 
| 
      
 93 
     | 
    
         
            +
                    end
         
     | 
| 
      
 94 
     | 
    
         
            +
             
     | 
| 
      
 95 
     | 
    
         
            +
                    if ! options[:units].all? { |u| u.has_key?(:contents) || u.has_key?(:dropins) }
         
     | 
| 
      
 96 
     | 
    
         
            +
                      raise "All units have to have contents and/or dropins"
         
     | 
| 
      
 97 
     | 
    
         
            +
                    end
         
     | 
| 
      
 98 
     | 
    
         
            +
             
     | 
| 
      
 99 
     | 
    
         
            +
                    if ! options[:files].all? { |f| FILE_REQUIRED_KEYS.all? { |key| f.has_key?(key) } }
         
     | 
| 
      
 100 
     | 
    
         
            +
                      raise "All files require the following keys: #{FILE_REQUIRED_KEYS}"
         
     | 
| 
      
 101 
     | 
    
         
            +
                    end
         
     | 
| 
      
 102 
     | 
    
         
            +
             
     | 
| 
      
 103 
     | 
    
         
            +
                    options[:cas] = options[:keypairs].map { |kp| kp[:ca] }.sort.uniq
         
     | 
| 
      
 104 
     | 
    
         
            +
             
     | 
| 
      
 105 
     | 
    
         
            +
                    erb_path = File.join(File.dirname(__FILE__), "templates/ignition.yaml")
         
     | 
| 
      
 106 
     | 
    
         
            +
                    erb = ERB.new(IO.read(erb_path))
         
     | 
| 
      
 107 
     | 
    
         
            +
             
     | 
| 
      
 108 
     | 
    
         
            +
                    yaml = erb.result(OpenStruct.new(options).instance_eval { binding })
         
     | 
| 
      
 109 
     | 
    
         
            +
             
     | 
| 
      
 110 
     | 
    
         
            +
                    Terrafying::Util.to_ignition(yaml)
         
     | 
| 
      
 111 
     | 
    
         
            +
                  end
         
     | 
| 
      
 112 
     | 
    
         
            +
             
     | 
| 
      
 113 
     | 
    
         
            +
                end
         
     | 
| 
      
 114 
     | 
    
         
            +
             
     | 
| 
      
 115 
     | 
    
         
            +
              end
         
     | 
| 
      
 116 
     | 
    
         
            +
             
     | 
| 
      
 117 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,112 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
             
     | 
| 
      
 2 
     | 
    
         
            +
            require 'terrafying/components/usable'
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            module Terrafying
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
              module Components
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
                class Instance < Terrafying::Context
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                  attr_reader :id, :name, :ip_address, :subnet
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                  include Usable
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                  def self.create_in(vpc, name, options={})
         
     | 
| 
      
 15 
     | 
    
         
            +
                    Instance.new.create_in vpc, name, options
         
     | 
| 
      
 16 
     | 
    
         
            +
                  end
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                  def self.find_in(vpc, name)
         
     | 
| 
      
 19 
     | 
    
         
            +
                    Instance.new.find_in vpc, name
         
     | 
| 
      
 20 
     | 
    
         
            +
                  end
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                  def initialize()
         
     | 
| 
      
 23 
     | 
    
         
            +
                    super
         
     | 
| 
      
 24 
     | 
    
         
            +
                  end
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
                  def find_in(vpc, name)
         
     | 
| 
      
 27 
     | 
    
         
            +
                    raise 'unimplemented'
         
     | 
| 
      
 28 
     | 
    
         
            +
                  end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
                  def create_in(vpc, name, options={})
         
     | 
| 
      
 31 
     | 
    
         
            +
                    options = {
         
     | 
| 
      
 32 
     | 
    
         
            +
                      public: false,
         
     | 
| 
      
 33 
     | 
    
         
            +
                      instance_type: "t2.micro",
         
     | 
| 
      
 34 
     | 
    
         
            +
                      instance_profile: nil,
         
     | 
| 
      
 35 
     | 
    
         
            +
                      ports: [],
         
     | 
| 
      
 36 
     | 
    
         
            +
                      tags: {},
         
     | 
| 
      
 37 
     | 
    
         
            +
                      security_groups: [],
         
     | 
| 
      
 38 
     | 
    
         
            +
                      depends_on: [],
         
     | 
| 
      
 39 
     | 
    
         
            +
                    }.merge(options)
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
                    ident = "#{tf_safe(vpc.name)}-#{name}"
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
                    @name = name
         
     | 
| 
      
 44 
     | 
    
         
            +
                    @ports = enrich_ports(options[:ports])
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
                    @security_group = resource :aws_security_group, ident, {
         
     | 
| 
      
 47 
     | 
    
         
            +
                                                 name: "instance-#{ident}",
         
     | 
| 
      
 48 
     | 
    
         
            +
                                                 description: "Describe the ingress and egress of the instance #{ident}",
         
     | 
| 
      
 49 
     | 
    
         
            +
                                                 tags: options[:tags],
         
     | 
| 
      
 50 
     | 
    
         
            +
                                                 vpc_id: vpc.id,
         
     | 
| 
      
 51 
     | 
    
         
            +
                                                 egress: [
         
     | 
| 
      
 52 
     | 
    
         
            +
                                                   {
         
     | 
| 
      
 53 
     | 
    
         
            +
                                                     from_port: 0,
         
     | 
| 
      
 54 
     | 
    
         
            +
                                                     to_port: 0,
         
     | 
| 
      
 55 
     | 
    
         
            +
                                                     protocol: -1,
         
     | 
| 
      
 56 
     | 
    
         
            +
                                                     cidr_blocks: ["0.0.0.0/0"],
         
     | 
| 
      
 57 
     | 
    
         
            +
                                                   }
         
     | 
| 
      
 58 
     | 
    
         
            +
                                                 ],
         
     | 
| 
      
 59 
     | 
    
         
            +
                                               }
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
      
 61 
     | 
    
         
            +
                    path_mtu_setup!
         
     | 
| 
      
 62 
     | 
    
         
            +
             
     | 
| 
      
 63 
     | 
    
         
            +
                    if options.has_key? :ip_address
         
     | 
| 
      
 64 
     | 
    
         
            +
                      lifecycle = {
         
     | 
| 
      
 65 
     | 
    
         
            +
                        lifecycle: { create_before_destroy: false },
         
     | 
| 
      
 66 
     | 
    
         
            +
                      }
         
     | 
| 
      
 67 
     | 
    
         
            +
                    else
         
     | 
| 
      
 68 
     | 
    
         
            +
                      lifecycle = {
         
     | 
| 
      
 69 
     | 
    
         
            +
                        lifecycle: { create_before_destroy: true },
         
     | 
| 
      
 70 
     | 
    
         
            +
                      }
         
     | 
| 
      
 71 
     | 
    
         
            +
                    end
         
     | 
| 
      
 72 
     | 
    
         
            +
             
     | 
| 
      
 73 
     | 
    
         
            +
                    if options.has_key? :subnet
         
     | 
| 
      
 74 
     | 
    
         
            +
                      @subnet = options[:subnet]
         
     | 
| 
      
 75 
     | 
    
         
            +
                    else
         
     | 
| 
      
 76 
     | 
    
         
            +
                      subnets = options.fetch(:subnets, vpc.subnets[:private])
         
     | 
| 
      
 77 
     | 
    
         
            +
                      # pick something consistent but not just the first subnet
         
     | 
| 
      
 78 
     | 
    
         
            +
                      subnet_index = XXhash.xxh32(ident) % subnets.count
         
     | 
| 
      
 79 
     | 
    
         
            +
                      @subnet = subnets[subnet_index]
         
     | 
| 
      
 80 
     | 
    
         
            +
                    end
         
     | 
| 
      
 81 
     | 
    
         
            +
             
     | 
| 
      
 82 
     | 
    
         
            +
                    @id = resource :aws_instance, ident, {
         
     | 
| 
      
 83 
     | 
    
         
            +
                                     ami: options[:ami],
         
     | 
| 
      
 84 
     | 
    
         
            +
                                     instance_type: options[:instance_type],
         
     | 
| 
      
 85 
     | 
    
         
            +
                                     iam_instance_profile: options[:instance_profile] && options[:instance_profile].id,
         
     | 
| 
      
 86 
     | 
    
         
            +
                                     subnet_id: @subnet.id,
         
     | 
| 
      
 87 
     | 
    
         
            +
                                     associate_public_ip_address: options[:public],
         
     | 
| 
      
 88 
     | 
    
         
            +
                                     root_block_device: {
         
     | 
| 
      
 89 
     | 
    
         
            +
                                       volume_type: 'gp2',
         
     | 
| 
      
 90 
     | 
    
         
            +
                                       volume_size: 32,
         
     | 
| 
      
 91 
     | 
    
         
            +
                                     },
         
     | 
| 
      
 92 
     | 
    
         
            +
                                     tags: {
         
     | 
| 
      
 93 
     | 
    
         
            +
                                       'Name' => ident,
         
     | 
| 
      
 94 
     | 
    
         
            +
                                     }.merge(options[:tags]),
         
     | 
| 
      
 95 
     | 
    
         
            +
                                     vpc_security_group_ids: [
         
     | 
| 
      
 96 
     | 
    
         
            +
                                       vpc.internal_ssh_security_group,
         
     | 
| 
      
 97 
     | 
    
         
            +
                                     ].push(*options[:security_groups]),
         
     | 
| 
      
 98 
     | 
    
         
            +
                                     user_data: options[:user_data],
         
     | 
| 
      
 99 
     | 
    
         
            +
                                     lifecycle: {
         
     | 
| 
      
 100 
     | 
    
         
            +
                                       create_before_destroy: true,
         
     | 
| 
      
 101 
     | 
    
         
            +
                                     },
         
     | 
| 
      
 102 
     | 
    
         
            +
                                     depends_on: options[:depends_on],
         
     | 
| 
      
 103 
     | 
    
         
            +
                                   }.merge(options[:ip_address] ? { private_ip: options[:ip_address] } : {}).merge(lifecycle)
         
     | 
| 
      
 104 
     | 
    
         
            +
             
     | 
| 
      
 105 
     | 
    
         
            +
                    @ip_address = output_of(:aws_instance, ident, options[:public] ? :public_ip : :private_ip)
         
     | 
| 
      
 106 
     | 
    
         
            +
             
     | 
| 
      
 107 
     | 
    
         
            +
                    self
         
     | 
| 
      
 108 
     | 
    
         
            +
                  end
         
     | 
| 
      
 109 
     | 
    
         
            +
             
     | 
| 
      
 110 
     | 
    
         
            +
                end
         
     | 
| 
      
 111 
     | 
    
         
            +
              end
         
     | 
| 
      
 112 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,81 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
             
     | 
| 
      
 2 
     | 
    
         
            +
            module Terrafying
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
              module Components
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
                class InstanceProfile < Terrafying::Context
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
                  attr_reader :id
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                  def self.create(name, options={})
         
     | 
| 
      
 11 
     | 
    
         
            +
                    InstanceProfile.new.create name, options
         
     | 
| 
      
 12 
     | 
    
         
            +
                  end
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                  def self.find(name)
         
     | 
| 
      
 15 
     | 
    
         
            +
                    InstanceProfile.new.find name
         
     | 
| 
      
 16 
     | 
    
         
            +
                  end
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                  def initialize()
         
     | 
| 
      
 19 
     | 
    
         
            +
                    super
         
     | 
| 
      
 20 
     | 
    
         
            +
                  end
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                  def find(name)
         
     | 
| 
      
 23 
     | 
    
         
            +
                    raise 'unimplemented'
         
     | 
| 
      
 24 
     | 
    
         
            +
                  end
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
                  def create(name, options={})
         
     | 
| 
      
 27 
     | 
    
         
            +
                    options = {
         
     | 
| 
      
 28 
     | 
    
         
            +
                      statements: [],
         
     | 
| 
      
 29 
     | 
    
         
            +
                    }.merge(options)
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
                    resource :aws_iam_role, name, {
         
     | 
| 
      
 32 
     | 
    
         
            +
                               name: name,
         
     | 
| 
      
 33 
     | 
    
         
            +
                               assume_role_policy: JSON.pretty_generate(
         
     | 
| 
      
 34 
     | 
    
         
            +
                                 {
         
     | 
| 
      
 35 
     | 
    
         
            +
                                   Version: "2012-10-17",
         
     | 
| 
      
 36 
     | 
    
         
            +
                                   Statement: [
         
     | 
| 
      
 37 
     | 
    
         
            +
                                     {
         
     | 
| 
      
 38 
     | 
    
         
            +
                                       Effect: "Allow",
         
     | 
| 
      
 39 
     | 
    
         
            +
                                       Principal: { "Service": "ec2.amazonaws.com"},
         
     | 
| 
      
 40 
     | 
    
         
            +
                                       Action: "sts:AssumeRole"
         
     | 
| 
      
 41 
     | 
    
         
            +
                                     }
         
     | 
| 
      
 42 
     | 
    
         
            +
                                   ]
         
     | 
| 
      
 43 
     | 
    
         
            +
                                 }
         
     | 
| 
      
 44 
     | 
    
         
            +
                               )
         
     | 
| 
      
 45 
     | 
    
         
            +
                             }
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
                    resource :aws_iam_role_policy, name, {
         
     | 
| 
      
 48 
     | 
    
         
            +
                               name: name,
         
     | 
| 
      
 49 
     | 
    
         
            +
                               policy: JSON.pretty_generate(
         
     | 
| 
      
 50 
     | 
    
         
            +
                                 {
         
     | 
| 
      
 51 
     | 
    
         
            +
                                   Version: "2012-10-17",
         
     | 
| 
      
 52 
     | 
    
         
            +
                                   Statement: [
         
     | 
| 
      
 53 
     | 
    
         
            +
                                     {
         
     | 
| 
      
 54 
     | 
    
         
            +
                                       Sid: "Stmt1442396947000",
         
     | 
| 
      
 55 
     | 
    
         
            +
                                       Effect: "Allow",
         
     | 
| 
      
 56 
     | 
    
         
            +
                                       Action: [
         
     | 
| 
      
 57 
     | 
    
         
            +
                                         "iam:GetGroup",
         
     | 
| 
      
 58 
     | 
    
         
            +
                                         "iam:GetSSHPublicKey",
         
     | 
| 
      
 59 
     | 
    
         
            +
                                         "iam:GetUser",
         
     | 
| 
      
 60 
     | 
    
         
            +
                                         "iam:ListSSHPublicKeys"
         
     | 
| 
      
 61 
     | 
    
         
            +
                                       ],
         
     | 
| 
      
 62 
     | 
    
         
            +
                                       Resource: [
         
     | 
| 
      
 63 
     | 
    
         
            +
                                         "arn:aws:iam::*"
         
     | 
| 
      
 64 
     | 
    
         
            +
                                       ]
         
     | 
| 
      
 65 
     | 
    
         
            +
                                     }
         
     | 
| 
      
 66 
     | 
    
         
            +
                                   ].push(*options[:statements])
         
     | 
| 
      
 67 
     | 
    
         
            +
                                 }
         
     | 
| 
      
 68 
     | 
    
         
            +
                               ),
         
     | 
| 
      
 69 
     | 
    
         
            +
                               role: output_of(:aws_iam_role, name, :name)
         
     | 
| 
      
 70 
     | 
    
         
            +
                             }
         
     | 
| 
      
 71 
     | 
    
         
            +
             
     | 
| 
      
 72 
     | 
    
         
            +
                    @id = resource :aws_iam_instance_profile, name, {
         
     | 
| 
      
 73 
     | 
    
         
            +
                                     name: name,
         
     | 
| 
      
 74 
     | 
    
         
            +
                                     role: output_of(:aws_iam_role, name, :name),
         
     | 
| 
      
 75 
     | 
    
         
            +
                                   }
         
     | 
| 
      
 76 
     | 
    
         
            +
             
     | 
| 
      
 77 
     | 
    
         
            +
                    self
         
     | 
| 
      
 78 
     | 
    
         
            +
                  end
         
     | 
| 
      
 79 
     | 
    
         
            +
                end
         
     | 
| 
      
 80 
     | 
    
         
            +
              end
         
     | 
| 
      
 81 
     | 
    
         
            +
            end
         
     |