aws ec2 describe-instances
で JSON として取得する。
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. 殺したサーバーを一覧する