class Kontena::Cli::Config
Helper
to access and update the CLI configuration file.
Also provides a “fake” config hash that behaves just like the file based config when ENV-variables are used instead of config file.
Constants
- TokenExpiredError
Attributes
Public Class Methods
# File lib/kontena/cli/config.rb, line 40 def initialize super @logger = Kontena.logger load_settings_from_config_file override_master_settings_from_env override_cloud_settings_from_env debug { "Configuration loaded with #{servers.count} servers and #{accounts.count} accounts." } debug { "Current master: #{current_server || '(not selected)'}" } debug { "Current grid: #{current_grid || '(not selected)'}" } debug { "Current account: #{current_account.nil? ? '(not selected)' : current_account.name}" } end
# File lib/kontena/cli/config.rb, line 33 def self.reset_instance Singleton.send :__init__, self self end
Public Instance Methods
List of configured accounts
@return [Array]
# File lib/kontena/cli/config.rb, line 300 def accounts @accounts ||= [] end
Add a new server to the configuration
@param [Hash] server_data
# File lib/kontena/cli/config.rb, line 307 def add_server(data) token = Token.new( access_token: data.delete('token'), refresh_token: data.delete('refresh_token'), expires_at: data.delete('token_expires_at'), parent_type: :master, parent_name: data['name'] || data[:name] ) server = Server.new(data.merge(token: token)) if (existing_index = find_server_index(server.name)) servers[existing_index] = server else servers << server end write end
Verifies access to existing configuration file
@return [Boolean]
# File lib/kontena/cli/config.rb, line 225 def config_file_available? File.exist?(config_filename) && File.readable?(config_filename) end
Return the configuration file path. You can override the default by using KONTENA_CONFIG environment variable.
@return [String] path
# File lib/kontena/cli/config.rb, line 275 def config_filename return @config_filename if @config_filename if ENV['KONTENA_CONFIG'] debug { "Using #{ENV['KONTENA_CONFIG']} as config file set through env KONTENA_CONFIG"} @config_filename = ENV['KONTENA_CONFIG'] else @config_filename = default_config_filename end end
# File lib/kontena/cli/config.rb, line 468 def current_account=(name) if name.nil? @current_account = nil elsif name == 'master' raise ArgumentError, "The master account can not be used as current account." else account = find_account(name.respond_to?(:name) ? name.name : name) if account @current_account = account else raise ArgumentError, "Account '#{name}' not found in configuration" end end end
Name of the currently selected grid. Can override using KONTENA_GRID environment variable.
@return [String, NilClass]
# File lib/kontena/cli/config.rb, line 450 def current_grid return ENV['KONTENA_GRID'] unless ENV['KONTENA_GRID'].to_s.empty? return nil unless current_master current_master.grid end
Set the current grid name.
@param [String] grid_name @raise [ArgumentError] if current master hasn't been selected
# File lib/kontena/cli/config.rb, line 460 def current_grid=(name) if current_master current_master.grid = name else raise ArgumentError, "Current master not selected, can't set grid." end end
Currently selected master's configuration data
@return [Server]
# File lib/kontena/cli/config.rb, line 371 def current_master return servers[@current_master_index] if @current_master_index return nil unless current_server @current_master_index = find_server_index(current_server) servers[@current_master_index] if @current_master_index end
Set the current master.
@param [String] server_name @raise [ArgumentError] if server by that name doesn't exist
# File lib/kontena/cli/config.rb, line 423 def current_master=(name) @current_master_index = nil if name.nil? self.current_server = nil else index = find_server_index(name.respond_to?(:name) ? name.name : name) if index self.current_server = servers[index].name else raise ArgumentError, "Server '#{name}' does not exist, can't add as current master." end end end
# File lib/kontena/cli/config.rb, line 55 def debug(&block) Kontena.logger.add(Logger::DEBUG, nil, 'CONFIG', &block) end
Generate the default configuration filename
# File lib/kontena/cli/config.rb, line 286 def default_config_filename File.join(Dir.home, '.krates.json') end
Default settings hash, used when configuration file does not exist.
@return [Hash]
# File lib/kontena/cli/config.rb, line 232 def default_settings debug { 'Configuration file not found, using default settings.' } { 'current_server' => 'default', 'servers' => [] } end
# File lib/kontena/cli/config.rb, line 133 def extract_token!(hash={}) Token.new( access_token: hash.delete('token'), refresh_token: hash.delete('refresh_token'), expires_at: hash.delete('token_expires_at').to_i ) end
# File lib/kontena/cli/config.rb, line 360 def find_account(name) accounts.find{|a| a['name'] == name.to_s} end
# File lib/kontena/cli/config.rb, line 364 def find_account_index(name) accounts.find_index{|a| a['name'] == name.to_s} end
Shortcut to find_server_by
(name: name)
@param [String] server_name @return [Server, NilClass]
# File lib/kontena/cli/config.rb, line 348 def find_server(name) find_server_by(name: name) end
Search the server list for a server by field(s) and value(s). @example
find_server_by(url: 'https://localhost', token: 'abcd')
@param [Hash] search_criteria @return [Server, NilClass]
# File lib/kontena/cli/config.rb, line 329 def find_server_by(criteria = {}) servers.find{|s| criteria.none? {|k,v| v != s[k]}} end
Shortcut to find_server_index_by
(name: name)
@param [String] server_name @return [Fixnum, NilClass]
# File lib/kontena/cli/config.rb, line 356 def find_server_index(name) find_server_index_by(name: name) end
Search the server list for a server by field(s) and value(s) and return its index.
@example
find_server_index(url: 'https://localhost')
@param [Hash] search_criteria @return [Fixnum, NilClass]
# File lib/kontena/cli/config.rb, line 340 def find_server_index_by(criteria = {}) servers.find_index{|s| criteria.none? {|k,v| v != s[k]}} end
# File lib/kontena/cli/config.rb, line 193 def kontena_account_data { name: 'kontena', url: ENV['KONTENA_CLOUD_URL'] || 'https://cloud-api.kontena.io', stacks_url: ENV['KONTENA_STACK_REGISTRY_URL'] || 'https://stacks.kontena.io', token_endpoint: ENV['AUTH_TOKEN_ENDPOINT'] || 'https://cloud-api.kontena.io/oauth2/token', authorization_endpoint: ENV['AUTH_AUTHORIZE_ENDPOINT'] || 'https://cloud.kontena.io/login/oauth/authorize', userinfo_endpoint: ENV['AUTH_USERINFO_ENDPOINT'] || 'https://cloud-api.kontena.io/user', token_post_content_type: ENV['AUTH_TOKEN_POST_CONTENT_TYPE'] || 'application/x-www-form-urlencoded', code_requires_basic_auth: ENV['AUTH_CODE_REQUIRES_BASIC_AUTH'].to_s == true, token_method: ENV['AUTH_TOKEN_METHOD'] || 'post', scope: ENV['AUTH_USERINFO_SCOPE'] || 'user', client_id: nil, stacks_read_authentication: ENV['KONTENA_STACK_REGISTRY_READ_AUTHENTICATION'].to_s == 'true' } end
Returns a cleaned up version of the kontena account data with only the token and name.
# File lib/kontena/cli/config.rb, line 484 def kontena_account_hash hash = { name: 'kontena' } acc = find_account('kontena') if acc && acc.token hash[:username] = acc.username if acc.username hash.merge!(acc.token.to_h) end hash end
Load configuration from default location ($HOME/.krates.json)
# File lib/kontena/cli/config.rb, line 142 def load_settings_from_config_file settings = config_file_available? ? parse_config_file : default_settings Array(settings['servers']).each do |server_data| if server_data['token'] token = extract_token!(server_data) token.parent_type = :master token.parent_name = server_data['name'] server = Server.new(server_data) server.token = token else server = Server.new(server_data) end server.account ||= 'master' if servers.find { |s| s['name'] == server.name} server.name = "#{server.name}-2" server.name.succ! until servers.find { |s| s['name'] == server.name }.nil? debug { "Renamed server to #{server.name} because a duplicate was found in config" } end servers << server end self.current_server = settings['current_server'] Array(settings['accounts']).each do |account_data| if account_data['token'] token = extract_token!(account_data) token.parent_type = :account token.parent_name = account_data['name'] account = Account.new(account_data) account.token = token else account = Account.new(account_data) end accounts << account end ka = find_account('kontena') if ka kontena_account_data.each {|k,v| ka[k] = v} else accounts << Account.new(kontena_account_data) end master_index = find_account_index('master') accounts.delete_at(master_index) if master_index accounts << Account.new(master_account_data) self.current_account = settings['current_account'] || 'kontena' end
# File lib/kontena/cli/config.rb, line 210 def master_account_data { name: 'master', token_endpoint: '/oauth2/token', authorization_endpoint: '/oauth2/authorize', userinfo_endpoint: '/v1/user', token_post_content_type: 'application/json', token_method: 'post', code_requires_basic_auth: false } end
Converts old style settings hash into modern one
@param [Hash] settings_hash @return [Hash] migrated_settings_hash
# File lib/kontena/cli/config.rb, line 244 def migrate_legacy_settings(settings) debug { "Migrating from legacy style configuration" } { 'current_server' => 'default', 'servers' => [ settings['server'].merge( 'name' => 'default', 'account' => 'kontena' ) ], 'accounts' => [ kontena_account_data ] } end
# File lib/kontena/cli/config.rb, line 103 def override_cloud_settings_from_env if ENV['KONTENA_CLOUD'] account = find_account(ENV['KONTENA_CLOUD']) if account debug { "Using cloud account #{ENV['KONTENA_CLOUD']} from config selected by env KONTENA_CLOUD" } self.current_account = account.name else debug { "Using new cloud account #{ENV['KONTENA_CLOUD']} from env" } account = Accout.new(kontena_account_data.merge(name: ENV['KONTENA_CLOUD'])) accounts << account end elsif current_account account = current_account end if account.nil? debug { 'No account data from config or env' } self.current_account = nil return end if ENV['KONTENA_CLOUD_TOKEN'] debug { 'Using cloud token from env KONTENA_CLOUD_TOKEN' } account.token ||= Token.new(parent_type: :account, parent_name: account.name) account.token.access_token = ENV['KONTENA_CLOUD_TOKEN'] account.token.refresh_token = nil account.token.expires_at = nil end end
# File lib/kontena/cli/config.rb, line 59 def override_master_settings_from_env if ENV['KONTENA_URL'] server = find_server_by(url: ENV['KONTENA_URL']) if server.nil? debug { 'Using new master url from env KONTENA_URL' } server = Server.new( url: ENV['KONTENA_URL'], name: ENV['KONTENA_MASTER'] || 'default' ) servers << server else debug { "Using master #{server.name} in config found via url in env KONTENA_URL" } end elsif ENV['KONTENA_MASTER'] server = find_server_by(name: ENV['KONTENA_MASTER']) if server debug { "Using master #{ENV['KONTENA_MASTER']} set via env KONTENA_MASTER" } end elsif current_master server = current_master end if server.nil? debug { 'Could not determine a master through config or env' } self.current_master = nil return else self.current_master = server.name end if ENV['KONTENA_GRID'] debug { "Using grid #{ENV['KONTENA_GRID']} from env KONTENA_GRID" } server.grid = ENV['KONTENA_GRID'] end if ENV['KONTENA_TOKEN'] debug { 'Using master token from env KONTENA_TOKEN' } server.token ||= Token.new(parent_type: :master, parent_name: server.name) server.token.access_token = ENV['KONTENA_TOKEN'] server.token.refresh_token = nil server.token.expires_at = nil end end
Read, parse and migrate the configuration file
@return [Hash] config_data
# File lib/kontena/cli/config.rb, line 261 def parse_config_file debug { "Loading configuration from #{config_filename}" } settings = JSON.load(File.read(config_filename)) if settings.has_key?('server') settings = migrate_legacy_settings(settings) else settings end end
Raises unless current account is selected.
@return [Account] current_account
@raise [ArgumentError] if no account is selected
# File lib/kontena/cli/config.rb, line 405 def require_current_account return @current_account if @current_account raise ArgumentError, "You are not logged into an authorization provider. Use: kontena cloud login" end
# File lib/kontena/cli/config.rb, line 410 def require_current_account_token account = require_current_account if !account || account.token.nil? || account.token.access_token.nil? raise ArgumentError, "You are not logged in to Kontena Cloud. Use: kontena cloud login" elsif account.token.expired? raise TokenExpiredError, "The cloud access token has expired and needs to be refreshed." unless cloud_client.refresh_token end end
Raises unless current grid is selected.
@return [String] current_grid_name @raise [ArgumentError] if no grid is selected
# File lib/kontena/cli/config.rb, line 441 def require_current_grid return current_grid if current_grid raise ArgumentError, "You have not selected a grid. Use: kontena grid" end
Raises unless current master is selected.
@return [Server] current_master
@raise [ArgumentError] if no account is selected
# File lib/kontena/cli/config.rb, line 396 def require_current_master return current_master if current_master raise ArgumentError, "You are not logged into a Kontena Master. Use: kontena master login" end
Raises unless current master has token.
@return [Token] current_master_token @raise [ArgumentError] if no token available
# File lib/kontena/cli/config.rb, line 382 def require_current_master_token require_current_master token = current_master.token if token && token.access_token return token unless token.expired? raise TokenExpiredError, "The access token has expired and needs to be refreshed." end raise ArgumentError, "You are not logged into a Kontena Master. Use: kontena master login" end
List of configured servers
@return [Array]
# File lib/kontena/cli/config.rb, line 293 def servers @servers ||= [] end
Generate a hash from the current configuration.
@return [Hash]
# File lib/kontena/cli/config.rb, line 497 def to_hash hash = { current_server: (self.current_server && find_server(self.current_server)) ? self.current_server : nil, current_account: self.current_account ? self.current_account.name : nil, servers: servers.map(&:to_h), accounts: accounts.reject{|a| a.name == 'master' || a.name == 'kontena'}.map(&:to_h) + [kontena_account_hash] } hash[:servers].each do |server| server.delete(:account) if server[:account] == 'master' end hash end
Generate a JSON string from the current configuration
@return [String]
# File lib/kontena/cli/config.rb, line 513 def to_json JSON.pretty_generate(to_hash) end
Write the current configuration to config file. Does nothing if using settings from environment variables.
# File lib/kontena/cli/config.rb, line 519 def write return nil if ENV['KONTENA_URL'] debug { "Writing configuration to #{config_filename}" } File.write(config_filename, to_json) end