Skip to content

Instantly share code, notes, and snippets.

@dradtke
Created June 26, 2019 17:56
Show Gist options
  • Save dradtke/5562e1cab015c9dc3aff7ab4f9fba8c9 to your computer and use it in GitHub Desktop.
Save dradtke/5562e1cab015c9dc3aff7ab4f9fba8c9 to your computer and use it in GitHub Desktop.
Consul watch script for updating a Linode NodeBalancer's config
#!/usr/bin/env ruby
#
# This script is intended to be run as part of a Consul watch listening for services.
# It then uses Linode's API to remove nodes no longer available, and to add new ones.
#
require 'json'
require 'httparty'
BALANCER_NAME, CONFIG_PORT = ARGV
API_KEY = '...'
HEADERS = {"Authorization" => "Bearer #{API_KEY}"}
resp = HTTParty.get("https://api.linode.com/v4/nodebalancers", :headers => {"Authorization" => "Bearer #{API_KEY}"})
balancer = resp["data"].find do |node|
node["label"] == BALANCER_NAME
end
resp = HTTParty.get("https://api.linode.com/v4/nodebalancers/#{balancer["id"]}/configs", :headers => {"Authorization" => "Bearer #{API_KEY}"})
config = resp["data"].find do |node|
node["port"] == CONFIG_PORT.to_i
end
id_map = {}
resp = HTTParty.get("https://api.linode.com/v4/nodebalancers/#{balancer["id"]}/configs/#{config["id"]}/nodes", :headers => {"Authorization" => "Bearer #{API_KEY}"})
have = resp["data"].map do |node|
id_map[node["address"]] = node["id"]
node["address"]
end
want = JSON.load(STDIN).map do |service|
"#{service["Node"]["Address"]}:#{service["Service"]["Port"]}"
end
# remove old servers
(have - want).each do |addr|
puts "[-] #{addr}"
resp = HTTParty.delete("https://api.linode.com/v4/nodebalancers/#{balancer["id"]}/configs/#{config["id"]}/nodes/#{id_map[addr]}", :headers => {"Authorization" => "Bearer #{API_KEY}"})
if resp["errors"]
puts " errors found: #{resp["errors"]}"
end
end
# add new servers
(want - have).each do |addr|
puts "[+] #{addr}"
resp = HTTParty.post("https://api.linode.com/v4/nodebalancers/#{balancer["id"]}/configs/#{config["id"]}/nodes", :headers => {"Authorization" => "Bearer #{API_KEY}", "Content-Type" => "application/json"}, :body => {
:address => addr,
:label => `uuidgen`.strip.gsub('-', ''),
}.to_json)
if resp["errors"]
puts " errors found: #{response["errors"]}"
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment