class Ruboty::Kanjo::Actions::AWS

Constants

INSTANCE_TYPES
ONE_HOUR

Public Instance Methods

billing() click to toggle source
# File lib/ruboty/kanjo/actions/aws.rb, line 29
def billing
  services = list_services

  prices = {}
  prices['Total'] = get_price

  services.each do |service|
    prices[service] = get_price(service)
  end

  message.reply(table(prices), code: true)
end
get_price(service = nil) click to toggle source
# File lib/ruboty/kanjo/actions/aws.rb, line 94
def get_price(service = nil)
  now = Time.now

  dimensions = [
    { name: 'Currency', value: 'USD' }
  ]

  dimensions.push(name: 'ServiceName', value: service) if service

  resp = cloudwatch.get_metric_statistics(
    namespace: 'AWS/Billing',
    metric_name: 'EstimatedCharges',
    dimensions: dimensions,
    start_time: now - ONE_HOUR,
    end_time: now,
    statistics: ['Maximum'],
    period: 60,
    unit: 'None'
  )

  resp.datapoints.last&.maximum
end
list_services() click to toggle source
# File lib/ruboty/kanjo/actions/aws.rb, line 75
def list_services
  resp = cloudwatch.list_metrics(
    namespace: 'AWS/Billing',
    metric_name: 'EstimatedCharges',
    dimensions: [
      { name: 'Currency', value: 'USD' }
    ]
  )

  services = []
  resp.metrics.each do |metric|
    metric.dimensions.each do |dimension|
      services.push(dimension.value) if dimension.name == 'ServiceName'
    end
  end

  services
end
spot_instance() click to toggle source
# File lib/ruboty/kanjo/actions/aws.rb, line 42
def spot_instance
  az = message[:availability_zone]
  types = message[:instances].split(/\s*,\s*/)

  types = types.keep_if { |type| INSTANCE_TYPES.include?(type) }

  if types.empty?
    message.reply('Not available instance types')
    return
  end

  unless availability_zones.include?(az)
    message.reply('Availability zone is invalid')
    return
  end

  res = ec2.describe_spot_price_history({
    dry_run: false,
    start_time: Time.now,
    end_time: Time.now,
    instance_types: types,
    availability_zone: az,
    max_results: 5,
  })

  prices = {}
  res.spot_price_history.sort_by(&:instance_type).each do |history|
    prices[history.instance_type + ' '+ history.product_description] = "#{history.spot_price} USD"
  end

  message.reply(table(prices), code: true)
end

Private Instance Methods

availability_zones() click to toggle source
# File lib/ruboty/kanjo/actions/aws.rb, line 127
def availability_zones
  ec2.describe_availability_zones.availability_zones.map(&:zone_name)
end
cloudwatch() click to toggle source
# File lib/ruboty/kanjo/actions/aws.rb, line 119
def cloudwatch
  @cloudwatch ||= Aws::CloudWatch::Client.new(region: 'us-east-1')
end
ec2() click to toggle source
# File lib/ruboty/kanjo/actions/aws.rb, line 123
def ec2
  @ec2 ||= Aws::EC2::Client.new()
end
table(data) click to toggle source
# File lib/ruboty/kanjo/actions/aws.rb, line 131
def table(data)
  col = data.keys.map(&:size).max

  lines = []
  data.each_pair do |key, val|
    lines.push("#{key.ljust(col)} : #{val}")
  end

  lines.join("\n")
end