Class: Hiera::Backend::Consul_backend
- Inherits:
-
Object
- Object
- Hiera::Backend::Consul_backend
- Defined in:
- lib/hiera/backend/consul_backend.rb
Class Attribute Summary collapse
-
.api_version ⇒ Object
readonly
Returns the value of attribute api_version.
Instance Attribute Summary collapse
-
#consul ⇒ Object
readonly
Returns the value of attribute consul.
-
#host ⇒ Object
readonly
Returns the value of attribute host.
Instance Method Summary collapse
- #build_cache! ⇒ Object
-
#cache_node(key, node, node_hash) ⇒ Object
Store the value of a particular node.
- #cache_service(key) ⇒ Object
- #config_ssl! ⇒ Object
- #consul_fallback ⇒ Object
- #filter_paths(paths, key) ⇒ Object
-
#initialize ⇒ Consul_backend
constructor
A new instance of Consul_backend.
- #lookup(key, scope, order_override, _resolution_type) ⇒ Object
- #parse_hosts! ⇒ Object
- #parse_result(res) ⇒ Object
- #query_service(key) ⇒ Object
- #query_services ⇒ Object
- #request(httpreq) ⇒ Object
- #resolve_paths(key, scope, order_override) ⇒ Object
- #setup_consul ⇒ Object
- #ssl_cert! ⇒ Object
- #ssl_key! ⇒ Object
- #ssl_store! ⇒ Object
- #ssl_verify! ⇒ Object
- #store ⇒ Object
-
#token(path) ⇒ Object
Token is passed only when querying kv store.
- #update_cache(key, value, property, node) ⇒ Object
- #use_ssl! ⇒ Object
- #verify_config! ⇒ Object
- #wrapquery(path) ⇒ Object
Constructor Details
#initialize ⇒ Consul_backend
Returns a new instance of Consul_backend.
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
# File 'lib/hiera/backend/consul_backend.rb', line 21 def initialize begin @config = Config[:consul] rescue StandardError => e raise ConfigurationError, "[hiera-consul]: config cannot be read: #{e}" end verify_config! parse_hosts! @consul = setup_consul use_ssl! @cache = {} build_cache! end |
Class Attribute Details
.api_version ⇒ Object (readonly)
Returns the value of attribute api_version.
16 17 18 |
# File 'lib/hiera/backend/consul_backend.rb', line 16 def api_version @api_version end |
Instance Attribute Details
#consul ⇒ Object (readonly)
Returns the value of attribute consul.
19 20 21 |
# File 'lib/hiera/backend/consul_backend.rb', line 19 def consul @consul end |
#host ⇒ Object (readonly)
Returns the value of attribute host.
19 20 21 |
# File 'lib/hiera/backend/consul_backend.rb', line 19 def host @host end |
Instance Method Details
#build_cache! ⇒ Object
239 240 241 242 243 244 245 246 247 248 |
# File 'lib/hiera/backend/consul_backend.rb', line 239 def build_cache! services = query_services return nil unless services.is_a? Hash services.each do |key, _| cache_service(key) end debug("Cache: #{@cache}") end |
#cache_node(key, node, node_hash) ⇒ Object
Store the value of a particular node
261 262 263 264 265 266 267 |
# File 'lib/hiera/backend/consul_backend.rb', line 261 def cache_node(key, node, node_hash) node_hash.each do |property, value| next if property == 'ServiceID' update_cache(key, value, property, node) end end |
#cache_service(key) ⇒ Object
250 251 252 253 254 255 256 257 258 |
# File 'lib/hiera/backend/consul_backend.rb', line 250 def cache_service(key) service = query_service(key) return nil unless service.is_a?(Array) service.each do |node_hash| node = node_hash['Node'] cache_node(key, node, node_hash) end end |
#config_ssl! ⇒ Object
113 114 115 116 117 118 119 120 121 |
# File 'lib/hiera/backend/consul_backend.rb', line 113 def config_ssl! msg = '[hiera-consul]: use_ssl is enabled but no ssl_cert is set' fail msg unless @config[:ssl_cert] ssl_verify! ssl_store! ssl_key! ssl_cert! end |
#consul_fallback ⇒ Object
99 100 101 102 |
# File 'lib/hiera/backend/consul_backend.rb', line 99 def consul_fallback debug "Could not reach #{@host}, retrying with #{@hosts.first}" setup_consul end |
#filter_paths(paths, key) ⇒ Object
153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 |
# File 'lib/hiera/backend/consul_backend.rb', line 153 def filter_paths(paths, key) paths.reduce([]) do |acc, path| if "#{path}/#{key}".match('//') # Check that we are not looking somewhere that will make hiera # crash subsequent lookups debug("The specified path #{path}/#{key} is malformed, skipping") elsif path !~ %r{^/v\d/(catalog|kv)/} # We only support querying the catalog or the kv store debug("We only support queries to catalog and kv and you asked #{path}, skipping") else acc << path end acc end end |
#lookup(key, scope, order_override, _resolution_type) ⇒ Object
38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
# File 'lib/hiera/backend/consul_backend.rb', line 38 def lookup(key, scope, order_override, _resolution_type) answer = nil paths = resolve_paths(key, scope, order_override) paths.unshift(order_override) if order_override filtered_paths = filter_paths(paths, key) filtered_paths.each do |path| return @cache[key] if path == 'services' && @cache.key?(key) debug("Lookup #{path}/#{key} on #{@host}:#{@config[:port]}") answer = wrapquery("#{path}/#{key}") break if answer end answer end |
#parse_hosts! ⇒ Object
79 80 81 82 83 84 85 86 |
# File 'lib/hiera/backend/consul_backend.rb', line 79 def parse_hosts! @hosts = if @config[:host].is_a?(String) [@config[:host]] else @config[:host] end end |
#parse_result(res) ⇒ Object
169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 |
# File 'lib/hiera/backend/consul_backend.rb', line 169 def parse_result(res) # Consul always returns an array res_array = JSON.parse(res) # See if we are a k/v return or a catalog return unless res_array.length > 0 debug('Jumped as array empty') return nil end if res_array.first.include? 'Value' Base64.decode64(res_array.first['Value']) else res_array end end |
#query_service(key) ⇒ Object
233 234 235 236 237 |
# File 'lib/hiera/backend/consul_backend.rb', line 233 def query_service(key) path = "/#{self.class.api_version}/catalog/service/#{key}" debug("Querying #{path}") wrapquery(path) end |
#query_services ⇒ Object
227 228 229 230 231 |
# File 'lib/hiera/backend/consul_backend.rb', line 227 def query_services path = "/#{self.class.api_version}/catalog/services" debug("Querying #{@host}#{path}") wrapquery(path) end |
#request(httpreq) ⇒ Object
214 215 216 217 218 219 220 221 222 223 224 225 |
# File 'lib/hiera/backend/consul_backend.rb', line 214 def request(httpreq) @consul.request(httpreq) rescue Timeout::Error, Errno::EINVAL, Errno::ECONNRESET, EOFError, Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError, Net::ProtocolError, Errno::ECONNREFUSED => e if @hosts.length >= 1 consul_fallback retry else debug('Could not connect to Consul') raise Exception, e. unless @config[:failure] == 'graceful' return nil end end |
#resolve_paths(key, scope, order_override) ⇒ Object
58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
# File 'lib/hiera/backend/consul_backend.rb', line 58 def resolve_paths(key, scope, order_override) if @config[:base] Backend.datasources(scope, order_override) do |source| url = "#{@config[:base]}/#{source}" Backend.parse_string(url, scope, 'key' => key) end elsif @config[:paths] @config[:paths].map { |p| Backend.parse_string(p, scope, 'key' => key) } else probable_source = @config[:base] ? :base : :paths raise ConfigurationError, "[hiera-consul]: There is an issue with your hierarchy. Please check #{probable_source} configuration" exit 1 end end |
#setup_consul ⇒ Object
88 89 90 91 92 93 94 95 96 97 |
# File 'lib/hiera/backend/consul_backend.rb', line 88 def setup_consul fail '[hiera-consul]: No consul server is available' if @hosts.empty? @host = @hosts.shift debug "Trying #{@host}" @consul = Net::HTTP.new(@host, @config[:port]) @consul.read_timeout = @config[:http_read_timeout] || 10 @consul.open_timeout = @config[:http_connect_timeout] || 10 @consul end |
#ssl_cert! ⇒ Object
148 149 150 151 |
# File 'lib/hiera/backend/consul_backend.rb', line 148 def ssl_cert! debug("ssl_cert: #{File.(@config[:ssl_cert])}") @consul.cert = OpenSSL::X509::Certificate.new(File.read(@config[:ssl_cert])) end |
#ssl_key! ⇒ Object
143 144 145 146 |
# File 'lib/hiera/backend/consul_backend.rb', line 143 def ssl_key! debug("ssl_key: #{File.(@config[:ssl_key])}") @consul.key = OpenSSL::PKey::RSA.new(File.read(@config[:ssl_key])) end |
#ssl_store! ⇒ Object
137 138 139 140 141 |
# File 'lib/hiera/backend/consul_backend.rb', line 137 def ssl_store! @store = OpenSSL::X509::Store.new @store.add_cert(OpenSSL::X509::Certificate.new(File.read(@config[:ssl_ca_cert]))) @consul.cert_store = @store end |
#ssl_verify! ⇒ Object
123 124 125 126 127 128 129 |
# File 'lib/hiera/backend/consul_backend.rb', line 123 def ssl_verify! if @config[:ssl_verify] @consul.verify_mode = OpenSSL::SSL::VERIFY_PEER else @consul.verify_mode = OpenSSL::SSL::VERIFY_NONE end end |
#store ⇒ Object
131 132 133 134 135 |
# File 'lib/hiera/backend/consul_backend.rb', line 131 def store return @store if @store ssl_store! @store end |
#token(path) ⇒ Object
Token is passed only when querying kv store
210 211 212 |
# File 'lib/hiera/backend/consul_backend.rb', line 210 def token(path) "?token=#{@config[:token]}" if @config[:token] && path =~ %r{^/v\d/kv/} end |
#update_cache(key, value, property, node) ⇒ Object
269 270 271 272 273 274 275 276 277 278 279 280 281 |
# File 'lib/hiera/backend/consul_backend.rb', line 269 def update_cache(key, value, property, node) @cache["#{key}_#{property}_#{node}"] = value unless property == 'Node' if @cache.key?("#{key}_#{property}") @cache["#{key}_#{property}_array"].push(value) else # Value of the first registered node @cache["#{key}_#{property}"] = value # Values of all nodes @cache["#{key}_#{property}_array"] = [value] end end |
#use_ssl! ⇒ Object
104 105 106 107 108 109 110 111 |
# File 'lib/hiera/backend/consul_backend.rb', line 104 def use_ssl! if @config[:use_ssl] @consul.use_ssl = true config_ssl! else @consul.use_ssl = false end end |
#verify_config! ⇒ Object
73 74 75 76 77 |
# File 'lib/hiera/backend/consul_backend.rb', line 73 def verify_config! return true if @config[:host] && @config[:port] && (@config[:paths] || @config[:base]) raise ConfigurationError, '[hiera-consul]: Missing minimum configuration, please check hiera.yaml' end |
#wrapquery(path) ⇒ Object
186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 |
# File 'lib/hiera/backend/consul_backend.rb', line 186 def wrapquery(path) httpreq = Net::HTTP::Get.new("#{path}#{token(path)}") result = request(httpreq) if result.nil? debug('No response from any server') return nil end unless result.is_a?(Net::HTTPSuccess) debug("HTTP response code was #{result.code}") return nil end if result.body == 'null' debug('Jumped as consul null is not valid') return nil end debug("Answer was #{result.body}") parse_result(result.body) end |