c4se記:さっちゃんですよ☆

.。oO(さっちゃんですよヾ(〃l _ l)ノ゙☆)

.。oO(此のblogは、主に音樂考察Programming に分類されますよ。ヾ(〃l _ l)ノ゙♬♪♡)

音樂は SoundCloud に公開中です。

考察は現在は主に Cosense で公表中です。

Programming は GitHub で開發中です。

AWS EC2インスタンスの一覧を.ssh/config形式で吐く (Crystalで)

aws ec2 describe-instancesJSON として取得する。

JSON.mapping で Crystal の class に対応させる。

よしなに。

#!/usr/bin/env crystal run

require "json"

module Instances
  class Tag
    JSON.mapping(
      value: {type: String, key: "Value"},
      key: {type: String, key: "Key"},
    )
  end

  class Instance
    JSON.mapping(
      private_ip_address: {type: String, key: "PrivateIpAddress", nilable: true},
      tags: {type: Array(Tag), key: "Tags", nilable: true},
    )
  end

  class Reservation
    JSON.mapping(
      instances: {type: Array(Instance), key: "Instances"},
    )
  end

  class Instances
    JSON.mapping(
      reservations: {type: Array(Reservation), key: "Reservations"},
    )
  end
end

instances = Instances::Instances.from_json(`aws ec2 describe-instances --profile example-production --output json`)
hosts = instances
  .reservations
  .flat_map(&.instances)
  .map { |instance| {instance.private_ip_address, instance.tags.try(&.find { |tag| tag.key == "Name" }).try(&.value)} }
  .select { |private_ip_address, name| private_ip_address && name }
  .map { |private_ip_address, name| "Host #{name}\n  HostName #{private_ip_address}" }
  .join("\n")
puts hosts
config = File.read("#{ENV["HOME"]}/.ssh/config", "UTF-8")
config += "\n### EXAMPLE BEGIN ###\n### EXAMPLE END ###" unless config =~ %r(^### EXAMPLE BEGIN ###\n.+^### EXAMPLE END ###$)m
config = config.sub(%r(^### EXAMPLE BEGIN ###\n.+^### EXAMPLE END ###$)m, "\n### EXAMPLE BEGIN ###\n#{hosts}\n### EXAMPLE END ###")
File.write("#{ENV["HOME"]}/.ssh/config", config, File::DEFAULT_CREATE_MODE, "UTF-8")

# vim:set ft=crystal:

cf. 殺したサーバーを一覧する