Add new provider for backend status checks

Haproxy backend status check remains the default provider. Adding
new one for basic HTTP checks so it could be possible to use
external non-haproxy load balancers. After this we can make provider
for haproxy_backend_status in our manifests conditional, based on
whether we have external balancer or not.

Partial-bug: #1522749

Change-Id: I77921fba265da29332ddd05f371eb84bb1825d8b
This commit is contained in:
Aleksandr Didenko 2015-12-14 18:18:17 +01:00
parent d883f34981
commit 30c4b62c09
4 changed files with 160 additions and 0 deletions

View File

@ -7,6 +7,8 @@ require 'uri'
Puppet::Type.type(:haproxy_backend_status).provide(:haproxy) do
desc 'Wait for HAProxy backend to become online'
defaultfor :osfamily => :linux
# get the raw csv value using one of the methods
# retry if operations fails
# @return [String]

View File

@ -0,0 +1,65 @@
require 'net/https'
require 'uri'
require 'openssl'
Puppet::Type.type(:haproxy_backend_status).provide(:http) do
desc 'Wait for HTTP backend to become online'
# get the current backend status value
# @return [:up, :down, :absent, :present]
def ensure
debug 'Call: ensure'
out = status
debug "Return: #{out}"
out
end
# get backend status based on HTTP reply
# @return [:up, :down, :present, :absent]
def status
status = get_url
return :absent unless status
return :present if [:present, :absent].include? @resource[:ensure]
return :up if status.kind_of? Net::HTTPSuccess or status.kind_of? Net::HTTPRedirection
return :down if status.kind_of? Net::HTTPServerError or status.kind_of? Net::HTTPClientError
:present
end
# check backend using HTTP request
# @return [false, Net::HTTP Constant]
def get_url
begin
uri = URI.parse(@resource[:url])
http = Net::HTTP.new(uri.host, uri.port)
if @resource[:url].start_with?('https')
http.use_ssl = true
case @resource[:ssl_verify_mode]
when 'none'
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
when 'peer'
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
end
end
request = Net::HTTP::Get.new(uri.request_uri)
http.request(request)
rescue Exception => e
debug "Got error while checking backend: #{e}"
false
end
end
# wait for backend status to change into specified value
# @param value [:up, :down]
def ensure=(value)
debug "Call: ensure=(#{value})"
debug "Waiting for backend: '#{@resource[:name]}' to change its status to: '#{value}'"
@resource[:count].times do
if self.status == value
return true
end
sleep @resource[:step]
end
fail "Timeout waiting for backend: '#{@resource[:name]}' status to become: '#{value}' after #{@resource[:count] * @resource[:step]} seconds!"
end
end

View File

@ -47,6 +47,15 @@ Puppet::Type.newtype(:haproxy_backend_status) do
end
end
newparam(:ssl_verify_mode) do
desc 'HTTPS SSL verify mode. Defaults to `default` which means built-in default.'
newvalues('none', 'peer', 'default')
defaultto 'default'
munge do |value|
value.to_s
end
end
def validate
unless self[:socket].nil? ^ self[:url].nil?
raise 'You should give either url or socket to get HAProxy status and not both!'

View File

@ -0,0 +1,84 @@
require 'puppet'
require 'net/http'
describe Puppet::Type.type(:haproxy_backend_status).provider(:http) do
let (:resource) do
Puppet::Type::Haproxy_backend_status.new(
{
:name => 'test',
:url => 'http://10.10.10.5:5000/',
:provider => 'http'
}
)
end
let (:http_100) do
Net::HTTPContinue.new('1.1', '100', 'Continue')
end
let (:http_200) do
Net::HTTPOK.new('1.1', '200', 'OK')
end
let (:http_404) do
Net::HTTPNotFound.new('1.1', '404', 'Not Found')
end
let (:http_302) do
Net::HTTPFound.new('1.1', '302', 'Found')
end
let (:http_503) do
Net::HTTPServiceUnavailable.new('1.1', '503', 'Service Unavailable')
end
let (:provider) do
provider = resource.provider
if ENV['SPEC_PUPPET_DEBUG']
class << provider
def debug(msg)
puts msg
end
end
end
provider
end
it 'should return :up for running backend (HTTP 200)' do
resource[:name] = 'test-up'
provider.stubs(:get_url).returns(http_200)
expect(provider.ensure).to eq(:up)
end
it 'should return :up for running backend (HTTP 302)' do
resource[:name] = 'test-up'
provider.stubs(:get_url).returns(http_302)
expect(provider.ensure).to eq(:up)
end
it 'should return :down for broken backend (HTTP 404)' do
resource[:name] = 'test-down'
provider.stubs(:get_url).returns(http_404)
expect(provider.ensure).to eq(:down)
end
it 'should return :down for broken backend (HTTP 503)' do
resource[:name] = 'test-down'
provider.stubs(:get_url).returns(http_503)
expect(provider.ensure).to eq(:down)
end
it 'should return :present for weird backend (HTTP 100)' do
resource[:name] = 'test-up'
provider.stubs(:get_url).returns(http_100)
expect(provider.ensure).to eq(:present)
end
it 'should return :absent for missing backend (conection refused)' do
resource[:name] = 'test-absent'
provider.stubs(:get_url).returns(false)
expect(provider.ensure).to eq(:absent)
end
end