Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Ruby for Iac

Ruby for Iac

Roppongi.rb#2の発表資料です

Genki Sugawara

November 02, 2016
Tweet

More Decks by Genki Sugawara

Other Decks in Technology

Transcript

  1. ίʔυԽྫᶃ: Security Group ec2 "vpc-XXXXXXXX" do security_group "default" do description

    "default VPC security group" ingress do permission :tcp, 22..22 do ip_ranges( "0.0.0.0/0", ) end
  2. ίʔυԽྫᶄ: IAM user "bob", :path => "/developer/" do groups( "Admin"

    ) policy "bob-policy" do {"Version"=>"2012-10-17", "Statement"=> [{"Action"=> ["s3:Get*",
  3. ίʔυԽྫ: MySQLϢʔβ user "scott", "%" do on "*.*" do grant

    "USAGE" end on "test.*" do grant "SELECT" grant "INSERT" end
  4. ྫ: Mappru • https://github.com/winebarrel/mappru vpc "vpc-12345678" do route_table "foo-rt" do

    subnets "subnet-12345678" route destination_cidr_block: "0.0.0.0/0", gateway_id: "igw-12345678" route destination_cidr_block: "192.168.100.101/32", network_interface_id: "eni-12345678"
  5. Apply: API→Hash require 'aws-sdk' resource = Aws::EC2::Resource.new rt = resource.route_tables.first

    p tr.routes #=> #<Aws::Resources::Batch \ # resources=[ # #<Aws::EC2::Route # route_table_id="rtb-xxxxxxxx", # destination_cidr_block="10.0.0.0/16">,
  6. Apply: API→Hash class Mappru::Exporter ... def export result = {}

    @resource.route_tables.each do |rt| vpc_id = rt.vpc_id name = rt.tags... result[vpc_id][name] = export_route_table(rt) end result end def export_route_table(rt) { route_table_id: rt.id, subnets: export_subnets(rt.associations), }
  7. Apply: API→Hash {"vpc-xxxxxxxx"=> {"foo"=>{:route_table_id=>"rtb-xxxxxxxx", :routes=>[], :subnets=>[]}, "bar"=> {:route_table_id=>"rtb-xxxxxxxx", :routes=> [{:destination_cidr_block=>"0.0.0.0/0",

    :gateway_id=>"igw-xxxxxxxx", :network_interface_id=>nil, :vpc_peering_connection_id=>nil, :nat_gateway_id=>nil}, {:destination_cidr_block=>"192.168.100.102/32", :gateway_id=>nil, :network_interface_id=>"eni-xxxxxxxx", :vpc_peering_connection_id=>nil, :nat_gateway_id=>nil}], :subnets=>["subnet-xxxxxxxx", "subnet-xxxxxxxx"]}}}
  8. Apply: DSL→Hash class Mappru::DSL::Context attr_reader :result def initialize(&block) @result =

    {} instance_eval(&block) end def vpc(vpc_id, &block) @result[vpc_id] = Mappru::DSL::Context::VPC.new(vpc_id, &block).result end end
  9. Apply: DSL→Hash class Mappru::DSL::Context::VPC attr_reader :result def initialize(vpc_id, &block) @vpc_id

    = vpc_id @result = {} instance_eval(&block) end def route_table(name, &block) @result[name] = Mappru::DSL::Context::VPC::RouteTable.new(@vpc_id, name, &block).result end end
  10. Apply: ൺֱɾAPIίʔϧ ΤΫεϙʔτͯ͠ class Mappru::Client def apply(file) expected = load_file(file)

    actual = Mappru::Exporter.export(@client, @options) walk_vpcs(expected, actual) end
  11. Apply: ൺֱɾAPIίʔϧ VPCΛൺֱͯ͠ def walk_vpcs(expected, actual) expected.each do |vpc_id, expected_rts|

    actual_rts = actual.delete(vpc_id) if actual_rts walk_vpc(vpc_id, expected_rts, actual_rts) end end end
  12. Apply: ൺֱɾAPIίʔϧ ࠩҟ͕͋ͬͨΒAPIΛͨͨ͘ def walk_vpc(vpc_id, expected, actual) expected.each do |rt_name,

    expected_rt| actual_rt = actual.delete(rt_name) unless actual_rt actual_rt = @driver.create_route_table( vpc_id, rt_name, expected_rt)
  13. Export: Hash→DSL class Mappru::DSL::Converter def convert output_vpcs(@exported) end ...(தུ)... def

    output_vpc(vpc_id, rt_by_name) route_tables = output_route_tables(rt_by_name).strip <<-EOS vpc #{vpc_id.inspect} do #{route_tables} end EOS end
  14. ͪͳDslhͱ͍͏΋ͷ͕͋Γ·ͯ͠ Dslh.eval do glossary do title "example glossary" GlossDiv {

    title "S" } end end # => {"glossary"=> # {"title"=>"example glossary", # "GlossDiv"=> # {"title"=>"S"}}}
  15. AWS؀ڥΛ࡞Δ KumogataͰVPCΛ࡞Δ template do AWSTemplateFormatVersion "2010-09-09" Resources do myVPC do

    Type "AWS::EC2::VPC" Properties do CidrBlock "10.0.0.0/16" EnableDnsSupport true EnableDnsHostnames true Tags [_{ Key "Name" Value "foo" }] end end # (ུ)
  16. AWS؀ڥΛ࡞Δ route_table ├── foo_private_az-a.rtbl ├── foo_private_az-c.rtbl └── foo_public.rtbl vpc "vpc-xxxxxxxx"

    do route_table "healthcare private az-a" do subnets "subnet-xxxxxxxx" route destination_cidr_block: "0.0.0.0/0", nat_gateway_id: ... route destination_cidr_block: "10.10.0.0/16", vpc_peering_connection_id: ...
  17. AWS؀ڥΛ࡞Δ IAMͷϩʔϧΛ࡞Δ iam ├── groups ├── policies ├── roles │

    ├── admin.iam ├── templates └── users ├── sugawara.iam role "admin", :path=>"/" do attached_managed_policies( "arn:aws:iam::aws:policy/AdministratorAccess"
  18. AWS؀ڥΛ࡞Δ IPΞυϨεͱ͔͸ม਺ʹ·ͱΊ·͢ OFFICE = %w(10.0.0.1/32 10.0.0.2/32) ec2 "vpc-xxxxxxxx" do security_group

    "rproxy" do description "rproxy" ingress do permission :tcp, 80..80 do ip_ranges( *OFFICE,
  19. AWS؀ڥΛ࡞Δ Itamae੔උ itamae ├── cookbooks │ ├── bind-utils │ ├──

    datadog │ ├── datadog-docker │ ├── dstat │ ... └── roles ├── app-internal ├── base ├── batch ...
  20. AWS؀ڥΛ࡞Δ Itamaeʹϩʔϧ΍ΫοΫϒοΫͱ͍͏ ࢓૊Έ͸ͳ͍ͷͰࣗલͰ࡞ΓࠐΈ… require 'pathname' module RecipeHelper ITAMAE_DIR = Pathname('..').expand_path(__FILE__)

    def include_role(name) recipe_file = 'default.rb' include_recipe ITAMAE_DIR.join('roles', name, recipe_file).to_s end def include_cookbook(name) recipe_file = 'default.rb' include_recipe ITAMAE_DIR.join('cookbooks', name, recipe_file).to_s end
  21. AWS؀ڥΛ࡞Δ cap itamae:apply • αʔό্͔ΒGitHubͷϦϙδτϦΛ tarballͱͯ͠औಘˠద༻ cap itamae:apply USL_LOCAL=1 •

    ϩʔΧϧ؀ڥͷϦϙδτϦσΟϨΫτϦΛ tarballͱͯ͠S3ʹΞοϓϩʔυ • αʔό্ͰS3͔ΒtaballΛμ΢ϯϩʔυˠద༻