# frozen_string_literal: true require 'config_server_agent/version' require 'net/http' require 'json' class ConfigServerAgent class Error < StandardError; end def initialize( auth0_client_id: ENV['AUTH0_CLIENT_ID'], auth0_client_secret: ENV['AUTH0_CLIENT_SECRET'], auth0_host: ENV['AUTH0_HOST'], config_server_audience: ENV['CONFIG_SERVER_AUDIENCE'], config_server_api_key: ENV['CONFIG_SERVER_API_KEY'], config_server_host: ENV['CONFIG_SERVER_HOST'], user_agent: "ConfigServerAgent/#{ConfigServerAgent::VERSION}", user_agent_comment: nil, token_ttl: 60 * 60 * 24 ) @auth0_client_id = auth0_client_id or raise ArgumentError, 'Missing auth0_client_id parameter' @auth0_client_secret = auth0_client_secret or raise ArgumentError, 'Missing auth0_client_secret parameter' @auth0_host = auth0_host or raise ArgumentError, 'Missing auth0_host parameter' @config_server_audience = config_server_audience or raise ArgumentError, 'Missing config_server_audience parameter' @config_server_api_key = config_server_api_key or raise ArgumentError, 'Missing config_server_api_key parameter' @config_server_host = config_server_host or raise ArgumentError, 'Missing config_server_host parameter' @config = nil @mutex = Mutex.new @user_agent = user_agent @user_agent += " (#{user_agent_comment})" if user_agent_comment @token_birthday = nil @token = nil @token_ttl = token_ttl end def get_config return @config if @config @mutex.synchronize do @config ||= get_request 'config_pack' end end def get_selected_config(area, item=nil, **options) if options[:ignore_cache] @config = nil end data = get_config.group_by { |x| x['area'] } raise Error, "Area is missing: #{area}" unless data.key? area if item data.fetch(area, []).find { |row_item| break row_item["value"] if row_item["name"] == item } else data.fetch(area, []) end end def set_config(values) raise Error, 'values not found' if values.empty? post_request('set_values', values) end def clear @config = nil end def notify_missing(area, missing) post_request 'notify_missing', area: area, name: missing end private def post_request(endpoint, data={}) url = URI "#{@config_server_host}/api/#{endpoint}" http = Net::HTTP.new url.host, url.port http.use_ssl = url.scheme == 'https' request = Net::HTTP::Post.new url configure_request request request.body = data.to_json JSON.parse http.request(request).read_body end def get_request(endpoint, data={}) url = URI "#{@config_server_host}/api/#{endpoint}" url.query = URI.encode_www_form data http = Net::HTTP.new url.host, url.port http.use_ssl = url.scheme == 'https' request = Net::HTTP::Get.new url configure_request request JSON.parse http.request(request).read_body end def configure_request(request) request['user-agent'] = @user_agent request['authorization'] = "Bearer #{get_token}" request['content-type'] = 'application/json' request['accept'] = 'application/json' request['api-key'] = @config_server_api_key end def get_token if @token.nil? or @token_timestamp.nil? or @token_timestamp <= Time.now.to_i url = URI "https://#{@auth0_host}/oauth/token" http = Net::HTTP.new url.host, url.port http.use_ssl = url.scheme == 'https' request = Net::HTTP::Post.new url request['user-agent'] = @user_agent request['content-type'] = 'application/json' request.body = { client_id: @auth0_client_id, client_secret: @auth0_client_secret, audience: @config_server_audience, grant_type: 'client_credentials', }.to_json response = http.request request @token = JSON.parse(response.read_body)["access_token"] or raise Error, "No token from #{@auth0_host}" @token_timestamp = Time.now.to_i + @token_ttl end @token rescue JSON::ParserError raise Error, "Invalid response from #{@auth0_host}" end end