require 'kontena/cli/common' require 'kontena/stacks_client' class Helper include Kontena::Cli::Common def client_config require 'json' config_file = File.expand_path('~/.krates.json') if(File.exist?(config_file)) JSON.parse(File.read(config_file)) else {} end rescue => ex logger.debug ex {} end def current_grid client_config['servers'].find { |s| s['name'] == client_config['current_server']}['grid'] rescue => ex logger.debug ex nil end def current_master_name client_config['current_server'] end def grids client.get("grids")['grids'].map{|grid| grid['id']} rescue => ex logger.debug ex [] end def nodes client.get("grids/#{current_grid}/nodes")['nodes'].map{|node| node['name']} rescue [] end def stacks stacks = client.get("grids/#{current_grid}/stacks")['stacks'] results = [] results.push stacks.map{|s| s['name']} results.delete('null') results rescue => ex logger.debug ex [] end def stack_registry_usable? return false if current_account.nil? || current_account.stacks_url.nil? return false if current_account.stacks_read_authentication && current_account.token.nil? || current_account.token.access_token.nil? true end def stacks_client Kontena::StacksClient.new(current_account.stacks_url, current_account.token, read_requires_token: current_account.stacks_read_authentication) end def registry_stacks(query = '') return [] unless stack_registry_usable? results = stacks_client.search(query).map { |s| s['stack'] } if results.empty? && !query.empty? # this is here because old stack registry does not return anything for "org/" results = stacks_client.search('').map { |s| s['stack'] }.select { |s| s.start_with?(query) } end results rescue => ex logger.debug ex [] end def registry_stack_versions(stackname) return [] unless stack_registry_usable? logger.debug stackname.inspect stacks_client.versions(stackname).map { |v| [stackname, v['version']].join(':') } rescue => ex logger.debug ex [] end def services services = client.get("grids/#{current_grid}/services")['services'] results = [] results.push services.map{ |s| stack = s['stack']['id'].split('/').last if stack != 'null' "#{stack}/#{s['name']}" else s['name'] end } results rescue => ex logger.debug ex [] end def containers results = [] client.get("grids/#{current_grid}/services")['services'].each do |service| containers = client.get("services/#{service['id']}/containers")['containers'] results.push(containers.map{|c| c['name'] }) results.push(containers.map{|c| c['id'] }) end results rescue => ex logger.debug ex [] end def yml_services require 'yaml' if File.exist?('kontena.yml') yaml = YAML.safe_load(File.read('kontena.yml'), [], [], true, 'kontena.yml') services = yaml['services'] services.keys end rescue => ex logger.debug ex [] end def directories(word) if word && File.directory?(word) && !word.end_with?('/') ['%s/' % word] else Dir[File.join('.', '%s*' % word)].select { |file| File.directory?(file) }.map { |file| '%s/' % file.sub('./', '') } end end def yml_files(word) if word && File.directory?(word) && word.end_with?('/') glob = File.join(word, '*.{yml,yaml}') else glob = File.join('.', '%s*.{yml,yaml}' % word) end Dir[glob].map { |file| file.sub('./', '') } + directories(word) rescue => ex logger.debug ex [] end def master_names client_config['servers'].map{|s| s['name']} rescue => ex logger.debug ex [] end def subcommand_tree(cmd = nil, base = nil) puts "#{cmd} ".strip if base.has_subcommands? base.recognised_subcommands.each do |sc| subcommand_tree("#{cmd} #{sc.names.first}", sc.subcommand_class) end end end end helper = Helper.new words = ARGV if words.first == '--subcommand-tree' require 'kontena/main_command' helper.subcommand_tree("kontena", Kontena::MainCommand) exit 0 end words.delete_at(0) helper.logger.debug { "Completing #{words.inspect}" } begin completion = [] completion.push %w(cloud grid service stack vault certificate node master vpn registry container etcd external-registry whoami plugin version) if words.size < 2 if words.size > 0 case words[0] when 'plugin' completion.clear sub_commands = %w(list search install uninstall) if words[1] completion.push(sub_commands) unless (sub_commands + %w(ls)).include?(words[1]) else completion.push sub_commands end when 'etcd' completion.clear sub_commands = %w(get set mkdir list rm) if words[1] completion.push(sub_commands) unless (sub_commands + %w(ls)).include?(words[1]) else completion.push sub_commands end when 'registry' completion.clear sub_commands = %w(create remove) if words[1] completion.push(sub_commands) unless (sub_commands + %w(rm)).include?(words[1]) else completion.push sub_commands end when 'grid' completion.clear sub_commands = %w(add-user audit-log create current list user remove show use) if words[1] && words[1] == 'use' completion.push helper.grids.reject { |g| g == helper.current_grid } elsif words[1] && %w(update show remove env cloud-config health).include?(words[1]) completion.push helper.grids else completion.push sub_commands end when 'node' completion.clear sub_commands = %w(list show remove) if words[1] && sub_commands.include?(words[1]) completion.push helper.nodes else completion.push sub_commands end when 'master' completion.clear sub_commands = %w(list use user current remove config login logout token join audit-log init-cloud) if words[1] && words[1] == 'use' completion.push helper.master_names.reject { |n| n == helper.current_master_name } elsif words[1] && %w(remove rm).include?(words[1]) completion.push helper.master_names elsif words[1] && words[1] == 'user' users_sub_commands = %w(invite list role) if words[2] == 'role' role_subcommands = %w(add remove) if !words[3] || !(role_subcommands + %w(rm)).include?(words[3]) completion.push role_subcommands end else completion.push users_sub_commands end elsif words[1] && ['config', 'cfg'].include?(words[1]) config_sub_commands = %(set get dump load import export unset) completion.push config_sub_commands elsif words[1] && words[1] == 'token' token_sub_commands = %(list remove show current create) completion.push token_sub_commands elsif words[1] completion.push(sub_commands) unless (sub_commands + %w(ls rm)).include?(words[1]) else completion.push sub_commands end when 'cloud' completion.clear sub_commands = %w(login logout master) if words[1] && words[1] == 'master' cloud_master_sub_commands = %(list remove add show update) completion.push cloud_master_sub_commands elsif words[1] completion.push(sub_commands) unless (sub_commands + %w(ls rm)).include?(words[1]) else completion.push sub_commands end when 'service' completion.clear sub_commands = %w(containers create remove deploy list logs restart scale show start stats stop update monitor env secret link unlink) if words[1] && sub_commands.include?(words[1]) completion.push helper.services else completion.push sub_commands end when 'container' completion.clear sub_commands = %w(exec inspect logs) if words[1] && sub_commands.include?(words[1]) completion.push helper.containers else completion.push sub_commands end when 'vpn' completion.clear completion.push %w(config create remove) when 'external-registry' completion.clear completion.push %w(add list remove) when 'stack' completion.clear sub_commands = %w(build install upgrade deploy start stop remove restart list logs monitor show registry inspect validate) if words[1] if words[1] == 'registry' || words[1] == 'reg' registry_sub_commands = %(push pull search show remove make-public make-private create) if words[2] if words[2] == 'push' completion.push helper.yml_files(words[3]) elsif %w(pull search show remove rm make-public make-private).include?(words[2]) && words[4].nil? completion.push helper.registry_stacks(words[3].to_s) else completion.push registry_sub_commands end else completion.push registry_sub_commands end elsif %w(install validate build).include?(words[1]) completion.push helper.yml_files(words[2]) if words[1] == 'install' completion.push helper.registry_stacks(words[2].to_s) end elsif words[1] == 'upgrade' if words[3] completion.push helper.yml_files(words[4]) completion.push helper.registry_stacks(words[4].to_s) else completion.push helper.stacks end elsif %w(deploy start stop remove rm restart logs monitor show inspect).include?(words[1]) completion.push helper.stacks else completion.push(sub_commands) unless (sub_commands + %w(rm ls)).include?(words[1]) end else completion.push sub_commands end end end rescue => ex helper.logger.debug ex end helper.logger.debug { "Returning completions: #{completion.inspect}" } puts completion