diff --git a/devops-client/lib/devops-client/handler/bootstrap_templates.rb b/devops-client/lib/devops-client/handler/bootstrap_templates.rb index c00c6d5..65a4df5 100644 --- a/devops-client/lib/devops-client/handler/bootstrap_templates.rb +++ b/devops-client/lib/devops-client/handler/bootstrap_templates.rb @@ -5,26 +5,23 @@ require "devops-client/output/bootstrap_templates" class BootstrapTemplates < Handler - include Output::BootstrapTemplates + output_with Output::BootstrapTemplates def initialize(host, def_options={}) - self.host = host - self.options = def_options + @host, @options = host, def_options @options_parser = BootstrapTemplatesOptions.new(ARGV, def_options) end def handle case ARGV[1] when "list" - self.options = @options_parser.list_options - list_handler @options_parser.args + @options, @args = @options_parser.parse_options_for!(:list) + list_handler output - else - @options_parser.invalid_command end end - def list_handler args + def list_handler @list = get("/templates") end diff --git a/devops-client/lib/devops-client/handler/deploy.rb b/devops-client/lib/devops-client/handler/deploy.rb index b35ba97..6213bc2 100644 --- a/devops-client/lib/devops-client/handler/deploy.rb +++ b/devops-client/lib/devops-client/handler/deploy.rb @@ -9,12 +9,11 @@ class Deploy < Handler @options_parser = DeployOptions.new(ARGV, def_options) end + # couldn't be replaced with processors approach right now (DeployOptions doesn't use .commands method) def handle if ARGV.size > 1 self.options = @options_parser.deploy_options deploy_handler @options_parser.args - else - @options_parser.invalid_command end end @@ -23,7 +22,7 @@ class Deploy < Handler names = args[1..-1] if names.empty? @options_parser.invalid_deploy_command - abort(r) + abort() end post_chunk("/deploy", :names => names, :tags => tags) end diff --git a/devops-client/lib/devops-client/handler/deploy_envs/deploy_env.rb b/devops-client/lib/devops-client/handler/deploy_envs/deploy_env.rb index 6fcbb4c..e12c6cf 100644 --- a/devops-client/lib/devops-client/handler/deploy_envs/deploy_env.rb +++ b/devops-client/lib/devops-client/handler/deploy_envs/deploy_env.rb @@ -1,15 +1,17 @@ -require "devops-client/handler/image" -require "devops-client/handler/flavor" -require "devops-client/handler/network" -require "devops-client/handler/group" -require "devops-client/handler/user" -require "devops-client/handler/input_utils" +require "devops-client/handler/helpers/input_utils" +require "devops-client/handler/helpers/resources_selector" class DeployEnv include InputUtils - attr_accessor :options, :auth, :flavors, :flavors_table, :images, :images_table, :networks, :networks_table, :groups, :groups_table, :users, :users_table + attr_accessor :options, :auth + + def initialize host, options, auth + @host = host + self.auth = auth + self.options = options + end def set_parameter obj, key if self.options[key].nil? @@ -50,70 +52,20 @@ class DeployEnv # flavors commands def set_flavor d - if self.flavors.nil? - get_flavors - end - unless self.options[:flavor].nil? - f = self.flavors.detect { |f| f["id"] == self.options[:flavor] } - abort(I18n.t("handler.project.create.flavor.not_found")) if f.nil? - end set_parameter d, :flavor do - choose_flavor_cmd(self.flavors, self.flavors_table)["id"] + resources_selector.select_available_flavor(provider: self.provider) end end - def get_flavors - f = Flavor.new(@host, self.options) - f.auth = self.auth - self.flavors = f.list_handler(["flavor", "list", self.provider]) - self.flavors_table = f.table - end - - # returns flavor hash - def choose_flavor_cmd flavors, table=nil - abort(I18n.t("handler.flavor.list.empty")) if flavors.empty? - flavors[ choose_number_from_list(I18n.t("headers.flavor"), flavors.map{|f| "#{f["id"]}. #{f["name"]} - #{f["ram"]}, #{f["disk"]}, #{f["v_cpus"]} CPU"}.join("\n"), table) ] - end - - # images commands - def get_images - img = Image.new(@host, self.options) - img.auth = self.auth - self.images = img.list_handler(["image", "list", self.provider]) - self.images_table = img.table - end - def set_image d - images, ti = nil, nil - if self.images.nil? - get_images - end set_parameter d, :image do - choose_image_cmd(self.images, self.images_table)["id"] + resources_selector.select_available_image(provider: self.provider) end end - def get_networks - n = Network.new(@host, self.options) - n.auth = self.auth - self.networks = n.list_handler(["network", "list", self.provider]) - self.networks_table = n.table - end - - def get_users - u = User.new(@host, self.options) - u.auth = self.auth - self.users = u.list_handler - self.users_table = u.table - end - def set_users d - if self.users.nil? - get_users - end set_parameter d, :users do - list = users.map{|u| u["id"]} - Set.new choose_indexes_from_list(I18n.t("handler.project.create.user"), list, self.users_table).map{|i| list[i]} + Set.new(resources_selector.select_available_users) end d[:users].add(self.options[:username]) d[:users] = d[:users].to_a @@ -128,5 +80,15 @@ class DeployEnv res end + private + + def resources_selector + @resources_selector ||= Helpers::ResourcesSelector.new(fetcher) + end + + def fetcher + @fetcher ||= Helpers::ResourcesFetcher.new(host: @host, handler_object_options: @options, auth: @auth) + end + end diff --git a/devops-client/lib/devops-client/handler/filter.rb b/devops-client/lib/devops-client/handler/filter.rb index d22bb83..45a5fbc 100644 --- a/devops-client/lib/devops-client/handler/filter.rb +++ b/devops-client/lib/devops-client/handler/filter.rb @@ -5,15 +5,13 @@ require "devops-client/output/filters" class Filter < Handler - attr_accessor :def_options + output_with Output::Filters def initialize(host, def_options) self.host = host - self.def_options = def_options @options_parser = FilterOptions.new(ARGV, def_options) end - include Output::Filters def handle case ARGV[1] @@ -44,8 +42,6 @@ class Filter < Handler @options_parser.invalid_image_command abort("Invalid image parameter: #{ARGV[2]}, it should be 'add' or 'delete' or 'list'") end - else - @options_parser.invalid_command end end diff --git a/devops-client/lib/devops-client/handler/flavor.rb b/devops-client/lib/devops-client/handler/flavor.rb index b618e12..a39d0e4 100644 --- a/devops-client/lib/devops-client/handler/flavor.rb +++ b/devops-client/lib/devops-client/handler/flavor.rb @@ -5,33 +5,30 @@ require "devops-client/output/flavors" class Flavor < Handler - include Output::Flavors + output_with Output::Flavors def initialize(host, def_options={}) - self.host = host - self.options = def_options + @host, @options = host, def_options @options_parser = FlavorOptions.new(ARGV, def_options) end def handle case ARGV[1] when "list" - self.options = @options_parser.list_options - list_handler @options_parser.args + @options, @args = @options_parser.parse_options_for!(:list) + list_handler output - else - @options_parser.invalid_command end end - def list_handler args - r = inspect_parameters @options_parser.list_params, args[2] + def list_handler(provider=nil) + provider ||= @args[2] + r = inspect_parameters @options_parser.list_params, provider unless r.nil? @options_parser.invalid_list_command abort(r) end - @provider = args[2] - @list = get("/flavors/#{args[2]}").sort!{|x,y| x["id"] <=> y["id"]} + @list = get("/flavors/#{provider}").sort!{|x,y| x["id"] <=> y["id"]} end end diff --git a/devops-client/lib/devops-client/handler/group.rb b/devops-client/lib/devops-client/handler/group.rb index da7af35..87c87ff 100644 --- a/devops-client/lib/devops-client/handler/group.rb +++ b/devops-client/lib/devops-client/handler/group.rb @@ -5,35 +5,31 @@ require "devops-client/output/groups" class Group < Handler - include Output::Groups + output_with Output::Groups def initialize(host, def_options={}) - self.host = host - self.options = def_options + @host, @options = host, def_options @options_parser = GroupOptions.new(ARGV, def_options) end def handle case ARGV[1] when "list" - self.options = @options_parser.list_options - list_handler @options_parser.args + @options, @args = @options_parser.parse_options_for!(:list) + list_handler(@args[2], @args[3]) output - else - @options_parser.invalid_command end end - def list_handler args - r = inspect_parameters @options_parser.list_params, args[2] + def list_handler(provider=nil, vpc_id=nil) + r = inspect_parameters @options_parser.list_params, provider unless r.nil? @options_parser.invalid_list_command abort(r) end - @provider = args[2] p = {} - p["vpc-id"] = args[3] unless args[3].nil? - @list = get("/groups/#{args[2]}", p) + p["vpc-id"] = vpc_id unless vpc_id.nil? + @list = get("/groups/#{provider}", p) end end diff --git a/devops-client/lib/devops-client/handler/handler.rb b/devops-client/lib/devops-client/handler/handler.rb index c28af08..18f6d14 100644 --- a/devops-client/lib/devops-client/handler/handler.rb +++ b/devops-client/lib/devops-client/handler/handler.rb @@ -6,11 +6,19 @@ require "devops-client/options/common_options" require "uri" require "json" require "devops-client/i18n" -require "devops-client/handler/input_utils" +require "devops-client/handler/helpers/input_utils" +require "devops-client/handler/helpers/colored_output_utils" +require "devops-client/handler/helpers/http_utils" +require "devops-client/handler/helpers/outputtable" +require "devops-client/handler/helpers/resources_fetcher" +require "devops-client/handler/helpers/resources_selector" class Handler include InputUtils + include ColoredOutputUtils + include HttpUtils + include Outputtable attr_reader :options attr_writer :host @@ -34,152 +42,14 @@ class Handler @options = o end - def get_chunk path, params={} - submit do |http| - http.get(create_url(path), convert_params(params)) do |chunk| - puts chunk - end - end - "" - end - - def get path, params={} - get_with_headers path, params, self.headers("Content-Type") - end - - def get_with_headers path, params={}, headers={} - submit do |http| - http.get(create_url(path), convert_params(params), headers) - end - end - - def post path, params={} - self.post_body(path, params.to_json) - end - - def post_body path, body - post_body_with_headers path, body, self.headers - end - - def post_chunk_body path, body, json=true - h = (json ? self.headers : self.headers("Content-Type", "Accept")) - submit do |http| - buf = "" - resp = http.post(create_url(path), body, h) do |chunk| - puts chunk - buf = chunk - end - if resp.ok? - status = check_status(buf) - exit(status) unless status == 0 - end - resp - end - "" - end - - def post_chunk path, params={} - self.post_chunk_body path, params.to_json - end - - def post_body_with_headers path, body='', headers={} - submit do |http| - http.post(create_url(path), body, headers) - end - end - - def delete path, params={} - delete_body path, params.to_json - end - - def delete_body path, body - submit do |http| - http.delete(create_url(path), body, self.headers) - end - end - - def put path, params={} - put_body path, params.to_json - end - - def put_body path, body - submit do |http| - http.put(create_url(path), body, self.headers) - end - end - protected - def puts_warn msg - puts "\e[33m#{msg}\e[0m" + + def resources_selector + @resources_selector ||= Helpers::ResourcesSelector.new(fetcher) end - def puts_error msg - puts "\e[31m#{msg}\e[0m" - end - - def output - case self.options[:format] - when CommonOptions::TABLE_FORMAT - table - when CommonOptions::JSON_FORMAT - json - when CommonOptions::CSV_FORMAT - csv - end - end - - def update_object_from_file object_class, object_id, file - unless File.exists?(file) - @options_parser.invalid_update_command - abort I18n.t("handler.error.file.not_exist", :file => file) - end - update_object_from_json object_class, object_id, File.read(file) - end - - def update_object_from_json object_class, object_id, json - put_body "/#{object_class}/#{object_id}", json - rescue NotFound => e - post_body "/#{object_class}", json - end - - def create_url path - a = [self.options[:api], path] - a.unshift(self.options[:prefix]) unless self.options[:prefix].nil? - p = "" - a.each{|e| p << (e.start_with?("/") ? e : "/" + e)} - URI.join(self.host, p).to_s - end - - def submit - http = HTTPClient.new - http.receive_timeout = 0 - http.send_timeout = 0 - http.set_auth(nil, self.username, self.password) - res = yield http - if res.ok? - return (res.contenttype.include?("application/json") ? JSON.parse(res.body) : res.body) - end - case res.status - when 404 - raise NotFound.new(extract_message(res)) - when 400 - raise InvalidQuery.new(extract_message(res)) - when 401 - e = extract_message(res) - e = I18n.t("handler.error.unauthorized") if (e.nil? or e.strip.empty?) - raise DevopsException.new(e) - else - raise DevopsException.new(extract_message(res)) - end - end - - def extract_message result - return nil if result.body.nil? - result.contenttype.include?("application/json") ? JSON.parse(result.body)["message"] : result.body - end - - def convert_params params - params_filter(params.select{|k,v| k != :cmd and !v.nil?}).join("&") + def fetcher + @fetcher ||= Helpers::ResourcesFetcher.new(host: @host, handler_object_options: @options, auth: @auth) end def params_filter params @@ -214,19 +84,6 @@ protected nil end - def headers *exclude - h = { - "Accept" => "application/json", - "Content-Type" => "application/json; charset=UTF-8" - } - - h["Accept-Language"] = I18n.lang - exclude.each do |key| - h.delete(key) - end - h - end - def check_status status r = status.scan(/--\sStatus:\s([0-9]{1,5})\s--/i)[0] if r.nil? diff --git a/devops-client/lib/devops-client/handler/handler_factory.rb b/devops-client/lib/devops-client/handler/handler_factory.rb index d938ede..03ac0a4 100644 --- a/devops-client/lib/devops-client/handler/handler_factory.rb +++ b/devops-client/lib/devops-client/handler/handler_factory.rb @@ -44,6 +44,12 @@ class HandlerFactory when "templates" require "devops-client/handler/bootstrap_templates" BootstrapTemplates + when "stack_template" + require "devops-client/handler/stack_template" + StackTemplate + when "stack" + require "devops-client/handler/stack" + Stack else require "devops-client/options/main" Main.new(ARGV, def_options).info diff --git a/devops-client/lib/devops-client/handler/helpers/colored_output_utils.rb b/devops-client/lib/devops-client/handler/helpers/colored_output_utils.rb new file mode 100644 index 0000000..f70fb7e --- /dev/null +++ b/devops-client/lib/devops-client/handler/helpers/colored_output_utils.rb @@ -0,0 +1,9 @@ +module ColoredOutputUtils + def puts_warn msg + puts "\e[33m#{msg}\e[0m" + end + + def puts_error msg + puts "\e[31m#{msg}\e[0m" + end +end \ No newline at end of file diff --git a/devops-client/lib/devops-client/handler/helpers/http_utils.rb b/devops-client/lib/devops-client/handler/helpers/http_utils.rb new file mode 100644 index 0000000..49cd16c --- /dev/null +++ b/devops-client/lib/devops-client/handler/helpers/http_utils.rb @@ -0,0 +1,145 @@ +module HttpUtils + def get_chunk path, params={} + submit do |http| + http.get(create_url(path), convert_params(params)) do |chunk| + puts chunk + end + end + "" + end + + def get path, params={} + get_with_headers path, params, self.headers("Content-Type") + end + + def get_with_headers path, params={}, headers={} + submit do |http| + http.get(create_url(path), convert_params(params), headers) + end + end + + def post path, params={} + self.post_body(path, params.to_json) + end + + def post_body path, body + post_body_with_headers path, body, self.headers + end + + def post_chunk_body path, body, json=true + h = (json ? self.headers : self.headers("Content-Type", "Accept")) + submit do |http| + buf = "" + resp = http.post(create_url(path), body, h) do |chunk| + puts chunk + buf = chunk + end + if resp.ok? + status = check_status(buf) + exit(status) unless status == 0 + end + resp + end + "" + end + + def post_chunk path, params={} + self.post_chunk_body path, params.to_json + end + + def post_body_with_headers path, body='', headers={} + submit do |http| + http.post(create_url(path), body, headers) + end + end + + def delete path, params={} + delete_body path, params.to_json + end + + def delete_body path, body + submit do |http| + http.delete(create_url(path), body, self.headers) + end + end + + def put path, params={} + put_body path, params.to_json + end + + def put_body path, body + submit do |http| + http.put(create_url(path), body, self.headers) + end + end + + protected + + def update_object_from_file object_class, object_id, file + unless File.exists?(file) + @options_parser.invalid_update_command + abort I18n.t("handler.error.file.not_exist", :file => file) + end + update_object_from_json object_class, object_id, File.read(file) + end + + def update_object_from_json object_class, object_id, json + put_body "/#{object_class}/#{object_id}", json + rescue NotFound => e + post_body "/#{object_class}", json + end + + def create_url path + a = [self.options[:api], path] + a.unshift(self.options[:prefix]) unless self.options[:prefix].nil? + p = "" + a.each{|e| p << (e.start_with?("/") ? e : "/" + e)} + URI.join(self.host, p).to_s + end + + def submit + http = HTTPClient.new + http.receive_timeout = 0 + http.send_timeout = 0 + http.set_auth(nil, self.username, self.password) + res = yield http + if res.ok? + return (res.contenttype.include?("application/json") ? JSON.parse(res.body) : res.body) + end + case res.status + when 404 + raise NotFound.new(extract_message(res)) + when 400 + raise InvalidQuery.new(extract_message(res)) + when 401 + e = extract_message(res) + e = I18n.t("handler.error.unauthorized") if (e.nil? or e.strip.empty?) + raise DevopsException.new(e) + else + raise DevopsException.new(extract_message(res)) + end + end + + def headers *exclude + h = { + "Accept" => "application/json", + "Content-Type" => "application/json; charset=UTF-8" + } + + h["Accept-Language"] = I18n.lang + exclude.each do |key| + h.delete(key) + end + h + end + + def extract_message result + return nil if result.body.nil? + result.contenttype.include?("application/json") ? JSON.parse(result.body)["message"] : result.body + end + + def convert_params params + params_filter(params.select{|k,v| k != :cmd and !v.nil?}).join("&") + end + +end \ No newline at end of file diff --git a/devops-client/lib/devops-client/handler/input_utils.rb b/devops-client/lib/devops-client/handler/helpers/input_utils.rb similarity index 82% rename from devops-client/lib/devops-client/handler/input_utils.rb rename to devops-client/lib/devops-client/handler/helpers/input_utils.rb index 74c85f4..3324cbd 100644 --- a/devops-client/lib/devops-client/handler/input_utils.rb +++ b/devops-client/lib/devops-client/handler/helpers/input_utils.rb @@ -41,6 +41,19 @@ module InputUtils STDIN.gets.strip.split(",").map{|e| e.strip} end + def ask_for_file_and_get_contents(ask_msg, error_message=nil) + filepath = enter_parameter(msg) + get_file_contents(filepath, error_message) + end + + def get_file_contents(filepath, error_message=nil) + begin + File.read(filepath) + rescue Errno::ENOENT => e + abort(error_message || 'Wrong file path') + end + end + def enter_parameter msg str = enter_parameter_or_empty(msg) raise ArgumentError.new if str.empty? @@ -54,6 +67,15 @@ module InputUtils return STDIN.gets.strip end + def enter_hash(msg, more_question = 'Add one more key?') + puts(msg) + hash = {} + while question(more_question) + hash[enter_parameter('Key: ')] = enter_parameter('Value: ') + end + hash + end + def choose_number_from_list title, list, table=nil, default=nil i = 0 if table.nil? diff --git a/devops-client/lib/devops-client/handler/helpers/outputtable.rb b/devops-client/lib/devops-client/handler/helpers/outputtable.rb new file mode 100644 index 0000000..9414054 --- /dev/null +++ b/devops-client/lib/devops-client/handler/helpers/outputtable.rb @@ -0,0 +1,33 @@ +module Outputtable + + def data_to_output + @list || @show + end + + def additional_output_options + {} + end + + def outputter + raise 'You should use "output_with" method to define outputter' unless defined?(outputter_class) + @outputter ||= outputter_class.new(data_to_output, options, additional_output_options) + end + + def output + outputter.output + end + + + def self.included(base) + base.extend(ClassMethods) + end + + module ClassMethods + def output_with(klass) + define_method :outputter_class do + klass + end + end + end + +end \ No newline at end of file diff --git a/devops-client/lib/devops-client/handler/helpers/resources_fetcher.rb b/devops-client/lib/devops-client/handler/helpers/resources_fetcher.rb new file mode 100644 index 0000000..5e50ade --- /dev/null +++ b/devops-client/lib/devops-client/handler/helpers/resources_fetcher.rb @@ -0,0 +1,41 @@ +require 'devops-client/helpers/string_helper' + +# fetches resources list along with table +module Helpers + class ResourcesFetcher + + def initialize(options) + @host = options.fetch(:host) + @handler_object_options = options.fetch(:handler_object_options) + @auth = options.fetch(:auth) + end + + def fetch(collection_name, *args) + build_handler(collection_name).list_handler(*args) + end + + def fetch_with_table(collection_name, *args) + handler = build_handler(collection_name) + [handler.list_handler(*args), handler.outputter.table] + end + + private + + def build_handler(collection_name) + require_handler_file(collection_name) + + handler = resource_handler_klass(collection_name).new(@host, @handler_object_options) + handler.auth = @auth + handler + end + + def require_handler_file(collection_name) + require "devops-client/handler/#{collection_name}" + end + + def resource_handler_klass(collection_name) + class_name = StringHelper.camelize(collection_name) + Object.const_get(class_name) + end + end +end \ No newline at end of file diff --git a/devops-client/lib/devops-client/handler/helpers/resources_selector.rb b/devops-client/lib/devops-client/handler/helpers/resources_selector.rb new file mode 100644 index 0000000..1b2ed8e --- /dev/null +++ b/devops-client/lib/devops-client/handler/helpers/resources_selector.rb @@ -0,0 +1,101 @@ +require 'devops-client/handler/helpers/resources_fetcher' +require 'devops-client/handler/helpers/input_utils' + +module Helpers + class ResourcesSelector + + include InputUtils + + # fetcher_instance_or_attrs should be: + # instance of ResourcesFetcher + # OR + # hash with these keys: + # :host + # :handler_object_options + # :auth + def initialize(fetcher_instance_or_attrs) + if fetcher_instance_or_attrs.is_a?(ResourcesFetcher) + @fetcher = fetcher_instance_or_attrs + else + @fetcher = ResourcesFetcher.new(fetcher_instance_or_attrs) + end + end + + def select_available_provider(options={}) + providers, table = @fetcher.fetch_with_table('provider') + # somewhy returns provider name as String. + select_item_from_table(I18n.t("headers.provider"), providers, table) + end + + def select_available_project(options={}) + projects, table = @fetcher.fetch_with_table('project') + project = select_item_from_table(I18n.t("headers.project"), projects, table) + project['name'] + end + + def select_available_stack_template(options={}) + stack_templates, table = @fetcher.fetch_with_table('stack_template', options[:provider]) + stack_template = select_item_from_table(I18n.t("headers.stack_template"), stack_templates, table) + stack_template['id'] + end + + def select_available_flavor(options={}) + flavors, table = @fetcher.fetch_with_table('flavor', options[:provider]) + abort(I18n.t("handler.flavor.list.empty")) if flavors.empty? + + flavors_descriptions = flavors.map {|f| "#{f["id"]}. #{f["name"]} - #{f["ram"]}, #{f["disk"]}, #{f["v_cpus"]} CPU"} + index = choose_number_from_list(I18n.t("headers.flavor"), flavors_descriptions, table) + + flavors[index]['id'] + end + + def select_available_image(options={}) + images, table = @fetcher.fetch_with_table('image', options[:provider]) + image = select_item_from_table(I18n.t("headers.image"), images, table) + image['id'] + end + + def select_available_network(options={}) + networks, table = @fetcher.fetch_with_table('network', options[:provider]) + table_title = options[:table_title] || I18n.t("headers.network") + + selected_networks = select_items_from_table(table_title, networks, table) + selected_networks.map {|network| network['name']} + end + + def select_available_users(options={}) + title = options[:table_title] || I18n.t("handler.project.create.user") + users, table = @fetcher.fetch_with_table('user') + + users = select_items_from_table(title, users, table) + users.map {|user| user['id']} + end + + def select_available_groups(options={}) + title = options[:table_title] || I18n.t("options.project.create.groups") + groups, table = @fetcher.fetch_with_table('group', options[:provider], options[:vpc_id]) + + # somewhy groups returned as a hash, not array + groups_array = [] + groups.each do |group_id, group_attrs| + group_attrs['id'] = group_id + groups_array << group_attrs + end + + default_index = groups_array.index {|t| t['id'] == 'default'} + select_items_from_table(title, groups_array, table, default: 'default', default_index: default_index) + end + + private + + def select_item_from_table(title, items, table) + items[ choose_number_from_list(title, items, table) ] + end + + def select_items_from_table(title, items, table, options={}) + indexes = choose_indexes_from_list(title, items, table, options[:default], options[:default_index]) + items.values_at(*indexes) + end + + end +end \ No newline at end of file diff --git a/devops-client/lib/devops-client/handler/image.rb b/devops-client/lib/devops-client/handler/image.rb index 800da6e..fbd8165 100644 --- a/devops-client/lib/devops-client/handler/image.rb +++ b/devops-client/lib/devops-client/handler/image.rb @@ -1,4 +1,3 @@ -require "devops-client/handler/provider" require "devops-client/handler/handler" require "devops-client/options/image_options" require "devops-client/output/image" @@ -6,61 +5,53 @@ require "devops-client/handler/bootstrap_templates" class Image < Handler - include Output::Image + output_with Output::Image def initialize(host, def_options={}) - self.host = host - self.options = def_options + # QUESTION: + # why we set @options variable here while we always reset it in #handle method? + @host, @options = host, def_options @options_parser = ImageOptions.new(ARGV, def_options) end def handle - case ARGV[1] - when "list" - self.options = @options_parser.list_options - list_handler @options_parser.args + current_command = ARGV[1].to_sym + @options, @args = @options_parser.parse_options_for!(current_command) + case current_command + when :list + list_handler output - when "show" - self.options = @options_parser.show_options - show_handler @options_parser.args + when :show + show_handler output - when "create" - self.options = @options_parser.create_options + when :create create_handler - when "delete" - self.options = @options_parser.delete_options - delete_handler @options_parser.args - when "update" - self.options = @options_parser.update_options - update_handler @options_parser.args - else - @options_parser.invalid_command + when :delete + delete_handler + when :update + update_handler end end - def get_providers - p = Provider.new(@host, self.options) - p.auth = self.auth - return p.list_handler(["provider", "list"]), p.table - end - def get_templates bt = BootstrapTemplates.new(@host, self.options) bt.auth = self.auth - list = bt.list_handler(["templates", "list"]) + list = bt.list_handler return list, nil if list.empty? return list, bt.table end def create_handler - providers, table = get_providers - provider = (self.options[:provider].nil? ? providers[ choose_number_from_list(I18n.t("headers.provider"), providers, table) ] : self.options[:provider]) - provider_images provider - q = { "provider" => provider } + q = {} + q[:provider] = options[:provider] || resources_selector.select_available_provider + provider_images(q[:provider]) + + # QUESTION: + # why we select image in create image handler? image = nil if options[:image_id].nil? - image = choose_image_cmd(@list, self.table) + image = choose_image_cmd(@list, self.outputter.table) else image = @list.detect{|i| i["id"] == options[:image_id]} abort("Invalid image id '#{options[:image_id]}'") if image.nil? @@ -68,11 +59,7 @@ class Image < Handler q["name"] = image["name"] q["id"] = image["id"] - if options[:ssh_username].nil? - q["remote_user"] = enter_parameter(I18n.t("handler.image.create.ssh_user") + ": ") - else - q["remote_user"] = options[:ssh_username] - end + q["remote_user"] = options[:ssh_username] || enter_parameter(I18n.t("handler.image.create.ssh_user") + ": ") q["bootstrap_template"] = if options[:bootstrap_template].nil? and options[:no_bootstrap_template] == false bt, bt_t = get_templates @@ -80,6 +67,8 @@ class Image < Handler puts I18n.t("handler.image.create.template_empty") nil else + # QUESTION: + # what does this '-1' mean? i = choose_number_from_list(I18n.t("handler.image.create.template"), bt, bt_t, -1) if i == -1 nil @@ -94,53 +83,55 @@ class Image < Handler post_body "/image", json if question(I18n.t("handler.image.question.create")){puts json} end - def list_handler args - if args[2].nil? - @provider = false - @list = get("/images") - elsif args[2] == "provider" and (args[3] == "ec2" || args[3] == "openstack") - provider_images args[3] - elsif args[2] == "ec2" || args[2] == "openstack" - @provider = false - @list = get("/images", :provider => args[2]) + def list_handler(provider=nil) + provider ||= @options[:given_provider] + @list = if provider + provider_images(provider) + else + get("/images") + end + end + + def provider_images provider + if Providers.has_functionality?(provider, :images) + @list = get("/images/provider/#{provider}") else @options_parser.invalid_list_command abort() end end - def provider_images p - @provider = true - @list = get("/images/provider/#{p}") - end - - def show_handler args - r = inspect_parameters @options_parser.show_params, args[2] + def show_handler + id = @args[2] + r = inspect_parameters @options_parser.show_params, id unless r.nil? @options_parser.invalid_show_command abort(r) end - @show = get "/image/#{args[2]}" + @show = get "/image/#{id}" end - def delete_handler args - r = inspect_parameters @options_parser.delete_params, args[2] + def delete_handler + id = @args[2] + r = inspect_parameters @options_parser.delete_params, id unless r.nil? @options_parser.invalid_delete_command abort(r) end - if question(I18n.t("handler.image.question.delete", :name => args[2])) - delete "/image/#{args[2]}" + if question(I18n.t("handler.image.question.delete", :name => id)) + delete "/image/#{id}" end end - def update_handler args - r = inspect_parameters @options_parser.update_params, args[2], args[3] + # QUESTION: + # what does inspect_parameters do and what do args[2] and args[3] actually mean? + def update_handler + r = inspect_parameters @options_parser.update_params, @args[2], @args[3] unless r.nil? @options_parser.invalid_update_command abort(r) end - update_object_from_file "image", args[2], args[3] + update_object_from_file "image", @args[2], @args[3] end end diff --git a/devops-client/lib/devops-client/handler/key.rb b/devops-client/lib/devops-client/handler/key.rb index 41443ab..d582110 100644 --- a/devops-client/lib/devops-client/handler/key.rb +++ b/devops-client/lib/devops-client/handler/key.rb @@ -4,55 +4,52 @@ require "json" require "devops-client/output/key" class Key < Handler - include Output::Key + + output_with Output::Key def initialize(host, def_options={}) - self.host = host - self.options = def_options + @host, @options = host, def_options @options_parser = KeyOptions.new(ARGV, def_options) end def handle - case ARGV[1] - when "list" - self.options = @options_parser.list_options + current_command = ARGV[1].to_sym + @options, @args = @options_parser.parse_options_for!(current_command) + case current_command + when :list list_handler output - when "add" - self.options = @options_parser.add_options - add_handler @options_parser.args - when "delete" - self.options = @options_parser.delete_options - delete_handler @options_parser.args - else - @options_parser.invalid_command + when :delete + delete_handler + when :add + add_handler end end - def add_handler args - r = inspect_parameters @options_parser.add_params, args[2], args[3] + def add_handler + r = inspect_parameters @options_parser.add_params, @args[2], @args[3] unless r.nil? @options_parser.invalid_add_command abort(r) end - content = File.read(args[3]) + content = File.read(@args[3]) q = { - "key_name" => args[2], - "file_name" => File.basename(args[3]), + "key_name" => @args[2], + "file_name" => File.basename(@args[3]), "content" => content } post "/key", q end - def delete_handler args - r = inspect_parameters @options_parser.delete_params, args[2] + def delete_handler + r = inspect_parameters @options_parser.delete_params, @args[2] unless r.nil? @options_parser.invalid_delete_command abort(r) end - if question(I18n.t("handler.key.question.delete", :name => args[2])) - delete "/key/#{args[2]}" + if question(I18n.t("handler.key.question.delete", :name => @args[2])) + delete "/key/#{@args[2]}" end end diff --git a/devops-client/lib/devops-client/handler/network.rb b/devops-client/lib/devops-client/handler/network.rb index a973502..4a79e7e 100644 --- a/devops-client/lib/devops-client/handler/network.rb +++ b/devops-client/lib/devops-client/handler/network.rb @@ -5,33 +5,30 @@ require "devops-client/output/network" class Network < Handler - include Output::Network + output_with Output::Network def initialize(host, def_options={}) - self.host = host - self.options = def_options + @host, @options = host, def_options @options_parser = NetworkOptions.new(ARGV, def_options) end def handle - case ARGV[1] - when "list" - self.options = @options_parser.list_options - list_handler @options_parser.args + current_command = ARGV[1].to_sym + @options, @args = @options_parser.parse_options_for!(current_command) + case current_command + when :list + list_handler(@args[2]) output - else - @options_parser.invalid_command end end - def list_handler args - r = inspect_parameters @options_parser.list_params, args[2] + def list_handler(provider=nil) + r = inspect_parameters @options_parser.list_params, provider unless r.nil? @options_parser.invalid_list_command abort(r) end - @provider = args[2] - @list = get("/networks/#{args[2]}").sort!{|x,y| x["name"] <=> y["name"]} + @list = get("/networks/#{provider}").sort!{|x,y| x["name"] <=> y["name"]} end end diff --git a/devops-client/lib/devops-client/handler/project.rb b/devops-client/lib/devops-client/handler/project.rb index 5bd15b6..30ee118 100644 --- a/devops-client/lib/devops-client/handler/project.rb +++ b/devops-client/lib/devops-client/handler/project.rb @@ -11,14 +11,13 @@ require "devops-client/output/project" require "devops-client/handler/deploy_envs/deploy_env_factory" class Project < Handler - attr_accessor :def_options - include Output::Project + output_with Output::Project - def initialize(host, def_options) + def initialize(host, def_options={}) self.host = host - self.def_options = def_options + self.def_options = self.options = def_options @options_parser = ProjectOptions.new(ARGV, def_options) end @@ -276,16 +275,10 @@ protected get("/project/#{project_id}") end - def get_providers - p = Provider.new(@host, self.def_options) - p.auth = self.auth - return p.list_handler(["provider", "list"]), p.table - end - def create_project args, env_method_name, type=nil project_name = args[2] providers = {} - providers[:obj], providers[:table] = get_providers + providers[:obj], providers[:table] = fetcher.fetch_with_table('provider') begin project = get_project_info_obj(project_name) puts_warn I18n.t("handler.project.exist", :project => project_name) @@ -425,4 +418,18 @@ protected project_envs[ choose_number_from_list(I18n.t("headers.project_env"), project_envs, table) ] end + def data_to_output + @list || @show || @servers || @test + end + + def additional_output_options + output_type = case ARGV[1] + when 'servers', 'test', 'show' + ARGV[1].to_sym + else + :list + end + {output_type: output_type} + end + end diff --git a/devops-client/lib/devops-client/handler/provider.rb b/devops-client/lib/devops-client/handler/provider.rb index fdd74fb..3f15699 100644 --- a/devops-client/lib/devops-client/handler/provider.rb +++ b/devops-client/lib/devops-client/handler/provider.rb @@ -4,26 +4,24 @@ require "devops-client/output/provider" class Provider < Handler - include Output::Provider + output_with Output::Provider def initialize(host, def_options={}) - self.host = host - self.options = def_options + @host, @options = host, def_options @options_parser = ProviderOptions.new(ARGV, def_options) end def handle - case ARGV[1] - when "list" - self.options = @options_parser.list_options - list_handler @options_parser.args + current_command = ARGV[1].to_sym + @options, @args = @options_parser.parse_options_for!(current_command) + case current_command + when :list + list_handler output - else - @options_parser.invalid_command end end - def list_handler args + def list_handler r = inspect_parameters @options_parser.list_params unless r.nil? @options_parser.invalid_list_command diff --git a/devops-client/lib/devops-client/handler/script.rb b/devops-client/lib/devops-client/handler/script.rb index cb87f8a..1ae8af4 100644 --- a/devops-client/lib/devops-client/handler/script.rb +++ b/devops-client/lib/devops-client/handler/script.rb @@ -3,82 +3,77 @@ require "devops-client/options/script_options" require "devops-client/output/script" class Script < Handler - include Output::Script + + output_with Output::Script def initialize(host, def_options={}) - self.host = host - self.options = def_options + @host, @options = host, def_options @options_parser = ScriptOptions.new(ARGV, def_options) end def handle - case ARGV[1] - when "list" - self.options = @options_parser.list_options - list_handler @options_parser.args + current_command = ARGV[1].to_sym + @options, @args = @options_parser.parse_options_for!(current_command) + case current_command + when :list + list_handler output - when "add" - self.options = @options_parser.add_options - add_handler @options_parser.args - when "run" - self.options = @options_parser.run_options - run_handler @options_parser.args - when "delete" - self.options = @options_parser.delete_options - delete_handler @options_parser.args - when "command" - self.options = @options_parser.command_options - command_handler @options_parser.args - else - @options_parser.invalid_command + when :delete + delete_handler + when :update + update_handler + when :command + command_handler + when :run + run_handler end end - def command_handler args - r = inspect_parameters @options_parser.command_params, args[2], args[3] + def command_handler + r = inspect_parameters @options_parser.command_params, @args[2], @args[3] unless r.nil? - @options_parser.invalid_command_command + @options_parser.invalid_command abort(r) end - post_chunk_body "/script/command/#{args[2]}", args[3], false + post_chunk_body "/script/command/#{@args[2]}", @args[3], false end - def list_handler args + def list_handler @list = get("/scripts") end - def add_handler args - r = inspect_parameters @options_parser.add_params, args[2], args[3] + def add_handler + r = inspect_parameters @options_parser.add_params, @args[2], @args[3] unless r.nil? @options_parser.invalid_add_command abort(r) end - abort("File '#{args[3]}' does not exist") unless File.exists?(args[3]) - put_body "/script/#{args[2]}", File.read(args[3]) + abort("File '#{@args[3]}' does not exist") unless File.exists?(@args[3]) + put_body "/script/#{@args[2]}", File.read(@args[3]) end - def delete_handler args - r = inspect_parameters @options_parser.delete_params, args[2] + def delete_handler + r = inspect_parameters @options_parser.delete_params, @args[2] unless r.nil? @options_parser.invalid_delete_command abort(r) end - if question(I18n.t("handler.script.question.delete", :name => args[2])) - delete "/script/#{args[2]}" + if question(I18n.t("handler.script.question.delete", :name => @args[2])) + delete "/script/#{@args[2]}" end end - def run_handler args - r = inspect_parameters @options_parser.run_params, args[2], args[3] + def run_handler + r = inspect_parameters @options_parser.run_params, @args[2], @args[3] unless r.nil? @options_parser.invalid_run_command abort(r) end q = { - :nodes => args[3..-1] + :nodes => @args[3..-1] } q[:params] = self.options[:params] unless self.options[:params].nil? - post_chunk "/script/run/#{args[2]}", q + post_chunk "/script/run/#{@args[2]}", q end end diff --git a/devops-client/lib/devops-client/handler/server.rb b/devops-client/lib/devops-client/handler/server.rb index 4f63d9b..982e6b1 100644 --- a/devops-client/lib/devops-client/handler/server.rb +++ b/devops-client/lib/devops-client/handler/server.rb @@ -5,83 +5,71 @@ require "devops-client/handler/project" class Server < Handler - include Output::Server + output_with Output::Server def initialize(host, def_options={}) - self.host = host - self.options = def_options + @host, @options = host, def_options @options_parser = ServerOptions.new(ARGV, def_options) end def handle - case ARGV[1] - when "list" - self.options = @options_parser.list_options - list_handler @options_parser.args + current_command = ARGV[1].to_sym + @options, @args = @options_parser.parse_options_for!(current_command) + case current_command + when :list + list_handler output - when "bootstrap" - self.options = @options_parser.bootstrap_options - bootstrap_handler @options_parser.args - when "create" - self.options = @options_parser.create_options - create_handler @options_parser.args - when "delete" - self.options = @options_parser.delete_options - delete_handler @options_parser.args - when "show" - self.options = @options_parser.show_options - show_handler @options_parser.args + when :show + show_handler output - when "sync" - self.options = @options_parser.sync_options + when :create + create_handler + when :delete + delete_handler + when :bootstrap + bootstrap_handler + when :sync sync_handler - when "pause" - self.options = @options_parser.pause_options - pause_handler @options_parser.args - when "unpause" - self.options = @options_parser.unpause_options - unpause_handler @options_parser.args - when "reserve" - self.options = @options_parser.reserve_options - reserve_handler @options_parser.args - when "unreserve" - self.options = @options_parser.unreserve_options - unreserve_handler @options_parser.args - when "add" - self.options = @options_parser.add_options - add_static_handler @options_parser.args - else - @options_parser.invalid_command + when :pause + pause_handler + when :unpause + unpause_handler + when :reserve + reserve_handler + when :unreserve + unreserve_handler + when :add + add_static_handler end end - def list_handler args - if args[2].nil? + def list_handler + if @args[2].nil? @list = get("/servers") return @list end - self.options[:type] = args[2] - @list = case args[2] + self.options[:type] = @args[2] + @list = case @args[2] when "chef" get("/servers/chef").map {|l| {"chef_node_name" => l}} when "ec2", "openstack", "static" - get("/servers/#{args[2]}") + get("/servers/#{@args[2]}") else @options_parser.invalid_list_command - abort("Invlid argument '#{args[2]}'") + abort("Invlid argument '#{@args[2]}'") end end - def create_handler args - r = inspect_parameters @options_parser.create_params, args[2], args[3] + def create_handler + r = inspect_parameters @options_parser.create_params, @args[2], @args[3] unless r.nil? @options_parser.invalid_create_command abort(r) end q = { - :project => args[2], - :deploy_env => args[3] + :project => @args[2], + :deploy_env => @args[3] } [:key, :without_bootstrap, :name, :groups, :force].each do |k| @@ -91,8 +79,8 @@ class Server < Handler post_chunk "/server", q end - def delete_handler args - args[2..-1].each do |name| + def delete_handler + @args[2..-1].each do |name| r = inspect_parameters @options_parser.delete_params, name unless r.nil? @options_parser.invalid_delete_command @@ -109,23 +97,23 @@ class Server < Handler "" end - def show_handler args - r = inspect_parameters @options_parser.show_params, args[2] + def show_handler + r = inspect_parameters @options_parser.show_params, @args[2] unless r.nil? @options_parser.invalid_show_command abort r end - @show = get("/server/#{args[2]}") + @show = get("/server/#{@args[2]}") end - def bootstrap_handler args - r = inspect_parameters @options_parser.bootstrap_params, args[2] + def bootstrap_handler + r = inspect_parameters @options_parser.bootstrap_params, @args[2] unless r.nil? @options_parser.invalid_bootstrap_command abort(r) end q = { - :instance_id => args[2] + :instance_id => @args[2] } [:name, :bootstrap_template, :run_list].each do |k| q[k] = self.options[k] unless self.options[k].nil? @@ -136,57 +124,57 @@ class Server < Handler post_chunk "/server/bootstrap", q end - def add_static_handler args # add --public-ip -k - r = inspect_parameters @options_parser.add_params, args[2], args[3], args[4], args[5], args[6] + def add_static_handler # add --public-ip -k + r = inspect_parameters @options_parser.add_params, @args[2], @args[3], @args[4], @args[5], @args[6] unless r.nil? @options_parser.invalid_add_command abort(r) end q = { - :project => args[2], - :deploy_env => args[3], - :private_ip => args[4], - :remote_user => args[5], - :key => args[6] + :project => @args[2], + :deploy_env => @args[3], + :private_ip => @args[4], + :remote_user => @args[5], + :key => @args[6] } q[:public_ip] = self.options[:public_ip] unless self.options[:public_ip].nil? post "/server/add", q end - def pause_handler args - r = inspect_parameters @options_parser.pause_params, args[2] + def pause_handler + r = inspect_parameters @options_parser.pause_params, @args[2] unless r.nil? @options_parser.invalid_pause_command abort(r) end - post "/server/#{args[2]}/pause", options + post "/server/#{@args[2]}/pause", options end - def unpause_handler args - r = inspect_parameters @options_parser.unpause_params, args[2] + def unpause_handler + r = inspect_parameters @options_parser.unpause_params, @args[2] unless r.nil? @options_parser.invalid_unpause_command abort(r) end - post "/server/#{args[2]}/unpause", options + post "/server/#{@args[2]}/unpause", options end - def reserve_handler args - r = inspect_parameters @options_parser.reserve_params, args[2] + def reserve_handler + r = inspect_parameters @options_parser.reserve_params, @args[2] unless r.nil? @options_parser.invalid_reserve_command abort(r) end - post "/server/#{args[2]}/reserve", options + post "/server/#{@args[2]}/reserve", options end - def unreserve_handler args - r = inspect_parameters @options_parser.unreserve_params, args[2] + def unreserve_handler + r = inspect_parameters @options_parser.unreserve_params, @args[2] unless r.nil? @options_parser.invalid_unreserve_command abort(r) end - post "/server/#{args[2]}/unreserve", options + post "/server/#{@args[2]}/unreserve", options end end diff --git a/devops-client/lib/devops-client/handler/stack.rb b/devops-client/lib/devops-client/handler/stack.rb new file mode 100644 index 0000000..ef16309 --- /dev/null +++ b/devops-client/lib/devops-client/handler/stack.rb @@ -0,0 +1,89 @@ +require 'devops-client/handler/handler' + +require 'devops-client/options/stack_options' +require 'devops-client/output/stack' + +class Stack < Handler + + output_with Output::Stack + + def initialize(host, def_options={}) + @host = host + @options_parser = StackOptions.new(ARGV, def_options) + end + + def handle + current_command = ARGV[1].to_sym + @options, @args = @options_parser.parse_options_for!(current_command) + case current_command + when :list + list_handler + output + when :show + show_handler + output + when :create + create_handler + when :delete + delete_handler + end + end + + def create_handler + q = {} + + q[:provider] = options[:provider] || resources_selector.select_available_provider + q[:id] = options[:id] || enter_parameter(I18n.t('handler.stack.create.id')) + q[:project] = options[:project] || resources_selector.select_available_project + q[:deploy_env] = options[:deploy_env] || enter_parameter(I18n.t('handler.stack.create.deploy_env')) + q[:stack_template] = options[:stack_template] || resources_selector.select_available_stack_template(provider: q[:provider]) + q[:parameters] = options[:parameters] || enter_hash(I18n.t('handler.stack.create.parameters')) + + json = JSON.pretty_generate(q) + if question(I18n.t("handler.stack.question.create")) {puts json} + post_body "/stack", json + end + end + + def list_handler + @list = if @options[:given_provider] + provider_stacks(@options[:given_provider]) + else + get("/stacks") + end + end + + def show_handler + stack_id = @args[2] + r = inspect_parameters(@options_parser.show_params, stack_id) + unless r.nil? + @options_parser.invalid_show_command + abort(r) + end + @show = get "/stack/#{stack_id}" + end + + def delete_handler + stack_id = @args[2] + r = inspect_parameters(@options_parser.delete_params, stack_id) + unless r.nil? + @options_parser.invalid_delete_command + abort(r) + end + if question(I18n.t("handler.stack.question.delete", name: stack_id)) + delete "/stack/#{stack_id}" + end + end + + private + + def provider_stacks(provider) + if Providers.has_functionality?(provider, :stacks) + get("/stacks/provider/#{provider}") + else + @options_parser.invalid_list_command + abort() + end + end + +end diff --git a/devops-client/lib/devops-client/handler/stack_template.rb b/devops-client/lib/devops-client/handler/stack_template.rb new file mode 100644 index 0000000..7a8d9c1 --- /dev/null +++ b/devops-client/lib/devops-client/handler/stack_template.rb @@ -0,0 +1,89 @@ +require "devops-client/handler/handler" +require "devops-client/handler/provider" +require "devops-client/options/stack_template_options" +require "devops-client/output/stack_template" +# require 'devops-client/helpers/select_available' + +class StackTemplate < Handler + + output_with Output::StackTemplate + + def initialize(host, def_options={}) + @host, @options = host, def_options + @options_parser = StackTemplateOptions.new(ARGV, def_options) + end + + def handle + current_command = ARGV[1].to_sym + @options, @args = @options_parser.parse_options_for!(current_command) + case current_command + when :list + list_handler + output + when :show + show_handler + output + when :create + create_handler + when :delete + delete_handler + end + end + + def create_handler + q = {} + q[:provider] = options[:provider] || resources_selector.select_available_provider + q[:id] = options[:id] || enter_parameter(I18n.t('handler.stack_template.create.id')) + + filepath = options[:template_file] || enter_parameter(I18n.t('handler.stack_template.create.template_file')) + q[:template_body] = get_file_contents(filepath) + + json = JSON.pretty_generate(q) + post_body('/stack_template', json) if question(I18n.t('handler.stack_template.question.create')){puts json} + end + + def list_handler(provider=nil) + provider ||= @options[:given_provider] + @list = get_stack_templates(provider) + end + + def get_stack_templates(provider=nil) + if provider + provider_stack_templates(provider) + else + get("/stack_templates") + end + end + + + def show_handler + r = inspect_parameters @options_parser.show_params, @args[2] + unless r.nil? + @options_parser.invalid_show_command + abort(r) + end + @show = get "/stack_template/#{@args[2]}" + end + + def delete_handler + r = inspect_parameters(@options_parser.delete_params, @args[2]) + unless r.nil? + @options_parser.invalid_delete_command + abort(r) + end + if question(I18n.t("handler.stack_template.question.delete", name: @args[2])) + delete "/stack_template/#{@args[2]}" + end + end + + def provider_stack_templates(provider) + if Providers.has_functionality?(provider, :stack_templates) + @provider = true + @list = get("/stack_templates/provider/#{provider}") + else + @options_parser.invalid_list_command + abort() + end + end + +end diff --git a/devops-client/lib/devops-client/handler/tag.rb b/devops-client/lib/devops-client/handler/tag.rb index f4ebb75..92bfcec 100644 --- a/devops-client/lib/devops-client/handler/tag.rb +++ b/devops-client/lib/devops-client/handler/tag.rb @@ -4,58 +4,55 @@ require "json" require "devops-client/output/tag" class Tag < Handler - include Output::Tag + + output_with Output::Tag def initialize(host, def_options={}) - self.host = host - self.options = def_options + @host, @options = host, def_options @options_parser = TagOptions.new(ARGV, def_options) end def handle - case ARGV[1] - when "list" - self.options = @options_parser.list_options - list_handler @options_parser.args + current_command = ARGV[1].to_sym + @options, @args = @options_parser.parse_options_for!(current_command) + case current_command + when :list + list_handler output - when "create" - self.options = @options_parser.create_options - create_handler @options_parser.args - when "delete" - self.options = @options_parser.delete_options - delete_handler @options_parser.args - else - @options_parser.invalid_command + when :create + create_handler + when :delete + delete_handler end end - def list_handler args - r = inspect_parameters @options_parser.list_params, args[2] + def list_handler + r = inspect_parameters @options_parser.list_params, @args[2] unless r.nil? @options_parser.invalid_list_command abort(r) end - @list = get("/tags/#{args[2]}") + @list = get("/tags/#{@args[2]}") end - def create_handler args - if args.length == 3 + def create_handler + if @args.length == 3 @options_parser.invalid_create_command abort() end - node = args[2] - tags = args[3..-1] + node = @args[2] + tags = @args[3..-1] post "/tags/#{node}", tags end - def delete_handler args - if args.length == 3 + def delete_handler + if @args.length == 3 @options_parser.invalid_delete_command abort() end - node = args[2] - tags = args[3..-1] + node = @args[2] + tags = @args[3..-1] if question(I18n.t("handler.user.question.delete", :name => tags.join("', '"), :node => node)) delete "/tags/#{node}", tags diff --git a/devops-client/lib/devops-client/handler/user.rb b/devops-client/lib/devops-client/handler/user.rb index 36a4a89..a2e994e 100644 --- a/devops-client/lib/devops-client/handler/user.rb +++ b/devops-client/lib/devops-client/handler/user.rb @@ -3,37 +3,31 @@ require "devops-client/options/user_options" require "devops-client/output/user" class User < Handler - include Output::User + + output_with Output::User def initialize(host, def_options={}) - self.host = host - self.options = def_options + @host, @options = host, def_options @options_parser = UserOptions.new(ARGV, def_options) end def handle - case ARGV[1] - when "list" - self.options = @options_parser.list_options + current_command = ARGV[1].to_sym + @options, @args = @options_parser.parse_options_for!(current_command) + case current_command + when :list list_handler output - when "create" - self.options = @options_parser.create_options - create_handler @options_parser.args - when "delete" - self.options = @options_parser.delete_options - delete_handler @options_parser.args - when "grant" - self.options = @options_parser.grant_options - grant_handler @options_parser.args - when "password" - self.options = @options_parser.password_options - password_handler @options_parser.args - when "email" - self.options = @options_parser.email_options - email_handler @options_parser.args - else - @options_parser.invalid_command + when :create + create_handler + when :delete + delete_handler + when :grant + grant_handler + when :password + password_handler + when :email + email_handler end end @@ -41,76 +35,76 @@ class User < Handler @list = get("/users") end - def create_handler args - r = inspect_parameters @options_parser.create_params, args[2], args[3] + def create_handler + r = inspect_parameters @options_parser.create_params, @args[2], @args[3] unless r.nil? @options_parser.invalid_create_command abort(r) end - password = self.options[:new_password] || enter_password(args[2]) + password = self.options[:new_password] || enter_password(@args[2]) q = { - "username" => args[2], + "username" => @args[2], "password" => password, - "email" => args[3] + "email" => @args[3] } post "/user", q end - def delete_handler args - r = inspect_parameters @options_parser.delete_params, args[2] + def delete_handler + r = inspect_parameters @options_parser.delete_params, @args[2] unless r.nil? @options_parser.invalid_delete_command abort(r) end - if question(I18n.t("handler.user.question.delete", :name => args[2])) - delete "/user/#{args[2]}" + if question(I18n.t("handler.user.question.delete", :name => @args[2])) + delete "/user/#{@args[2]}" end end - def password_handler args - r = inspect_parameters @options_parser.password_params, args[2] + def password_handler + r = inspect_parameters @options_parser.password_params, @args[2] unless r.nil? @options_parser.invalid_password_command abort(r) end - password = enter_password(args[2]) + password = enter_password(@args[2]) q = { "password" => password } - put "/user/#{args[2]}/password", q + put "/user/#{@args[2]}/password", q end - def email_handler args - r = inspect_parameters @options_parser.email_params, args[2], args[3] + def email_handler + r = inspect_parameters @options_parser.email_params, @args[2], @args[3] unless r.nil? @options_parser.invalid_email_command abort(r) end q = { - "email" => args[3] + "email" => @args[3] } - put "/user/#{args[2]}/email", q + put "/user/#{@args[2]}/email", q end - def grant_handler args - r = inspect_parameters @options_parser.grant_params, args[2], args[3], args[4] + def grant_handler + r = inspect_parameters @options_parser.grant_params, @args[2], @args[3], @args[4] unless r.nil? @options_parser.invalid_grant_command abort(r) end - args[3] = '' if args[3].nil? + @args[3] = '' if @args[3].nil? q = { - 'cmd' => args[3], - 'privileges' => args[4] + 'cmd' => @args[3], + 'privileges' => @args[4] } - put "/user/#{args[2]}", q + put "/user/#{@args[2]}", q end def enter_password user diff --git a/devops-client/lib/devops-client/helpers/string_helper.rb b/devops-client/lib/devops-client/helpers/string_helper.rb new file mode 100644 index 0000000..829078b --- /dev/null +++ b/devops-client/lib/devops-client/helpers/string_helper.rb @@ -0,0 +1,35 @@ +module StringHelper + extend self + + # from Rails' ActiveSupport + def underscore(string) + string.gsub(/::/, '/'). + gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2'). + gsub(/([a-z\d])([A-Z])/,'\1_\2'). + tr("-", "_"). + downcase + end + + def underscore_class(klass, without_ancestors=true) + class_name = if without_ancestors + klass.to_s.split('::').last + else + klass.to_s + end + StringHelper.underscore(class_name) + end + + # from Rails' ActiveSupport + def camelize(term) + string = term.to_s + string = string.sub(/^[a-z\d]*/) { $&.capitalize } + string.gsub!(/(?:_|(\/))([a-z\d]*)/i) { "#{$1}#{$2.capitalize}" } + string.gsub!(/\//, '::') + string + end + + # rough simplification + def pluralize(string) + "#{string}s" + end +end \ No newline at end of file diff --git a/devops-client/lib/devops-client/options/common_options.rb b/devops-client/lib/devops-client/options/common_options.rb index 7a5c1fb..95bfc1f 100644 --- a/devops-client/lib/devops-client/options/common_options.rb +++ b/devops-client/lib/devops-client/options/common_options.rb @@ -1,7 +1,9 @@ require "devops-client/version" +require "devops-client/options/helpers/extendable" require "devops-client/options/helpers/devops_options_parser" class CommonOptions + extend Options::Helpers::Extendable attr_accessor :header, :args, :default_options attr_writer :banner_header @@ -17,6 +19,10 @@ class CommonOptions end def self.commands *cmds + define_method :available_commands do + cmds + end + cmds.each do |cmd| if cmd.is_a?(Hash) key = cmd.keys[0] @@ -101,6 +107,18 @@ class CommonOptions end end + # returns [options, args] because they are always needed together + # will exit if operation is unsupported + def parse_options_for!(command) + # available_commands method is defined dinamically in .commands method + if available_commands.include?(command) + options = send("#{command}_options") + [options, args] + else + invalid_command + end + end + def error_banner "\t#{self.header}:\n\t#{self.banners.join("\t")}\n" end diff --git a/devops-client/lib/devops-client/options/flavor_options.rb b/devops-client/lib/devops-client/options/flavor_options.rb index b977ffc..e298cd4 100644 --- a/devops-client/lib/devops-client/options/flavor_options.rb +++ b/devops-client/lib/devops-client/options/flavor_options.rb @@ -12,4 +12,8 @@ class FlavorOptions < CommonOptions self.list_params = ["PROVIDER"] end + extend_options_method :list_options do |options| + options[:given_provider] = args[2] if args[2] + end + end diff --git a/devops-client/lib/devops-client/options/group_options.rb b/devops-client/lib/devops-client/options/group_options.rb index 5e1e91a..fa23881 100644 --- a/devops-client/lib/devops-client/options/group_options.rb +++ b/devops-client/lib/devops-client/options/group_options.rb @@ -12,4 +12,8 @@ class GroupOptions < CommonOptions self.list_params = ["PROVIDER", "[VPC-ID]"] end + extend_options_method :list_options do |options| + options[:given_provider] = args[2] if args[2] + end + end diff --git a/devops-client/lib/devops-client/options/helpers/extendable.rb b/devops-client/lib/devops-client/options/helpers/extendable.rb new file mode 100644 index 0000000..d38765f --- /dev/null +++ b/devops-client/lib/devops-client/options/helpers/extendable.rb @@ -0,0 +1,34 @@ +module Options + module Helpers + module Extendable + + # In Options classes (like StackTemplateOptions) method list_options + # is defined dynamically, that's why if we'd like to extend their functionality + # we can't use _super_, we should use aliasing. + # So I created this helper to hide and DRY syntatic noise. + # + # USAGE EXAMPLE: + # extend_options_method :list_options do |options| + # if args[2] == "provider" and args[3] + # options[:given_provider] = args[3] + # elsif args[2] + # options[:given_provider] = args[2] + # end + # end + # + # here 'options' is a result of default list_options method. + + def extend_options_method(method_name, &block) + old_method_name = "old_#{method_name}" + alias_method old_method_name, method_name + + define_method(method_name) do + options_hash = send(old_method_name) + instance_exec(options_hash, &block) + options_hash + end + end + + end + end +end \ No newline at end of file diff --git a/devops-client/lib/devops-client/options/image_options.rb b/devops-client/lib/devops-client/options/image_options.rb index abe2638..df737ad 100644 --- a/devops-client/lib/devops-client/options/image_options.rb +++ b/devops-client/lib/devops-client/options/image_options.rb @@ -26,4 +26,12 @@ class ImageOptions < CommonOptions end end + extend_options_method :list_options do |options| + if args[2] == "provider" and args[3] + options[:given_provider] = args[3] + elsif args[2] + options[:given_provider] = args[2] + end + end + end diff --git a/devops-client/lib/devops-client/options/network_options.rb b/devops-client/lib/devops-client/options/network_options.rb index 1a1a508..8e527b9 100644 --- a/devops-client/lib/devops-client/options/network_options.rb +++ b/devops-client/lib/devops-client/options/network_options.rb @@ -12,5 +12,9 @@ class NetworkOptions < CommonOptions self.list_params = ["PROVIDER"] end + extend_options_method :list_options do |options| + options[:given_provider] = args[2] if args[2] + end + end diff --git a/devops-client/lib/devops-client/options/project_options.rb b/devops-client/lib/devops-client/options/project_options.rb index 8e25aa2..c6591ca 100644 --- a/devops-client/lib/devops-client/options/project_options.rb +++ b/devops-client/lib/devops-client/options/project_options.rb @@ -62,7 +62,9 @@ class ProjectOptions < CommonOptions # abort("File '#{file}' does not exist") unless File.exist?(file) # options[:file] = file # end + end + end def user_add_options diff --git a/devops-client/lib/devops-client/options/stack_options.rb b/devops-client/lib/devops-client/options/stack_options.rb new file mode 100644 index 0000000..f824002 --- /dev/null +++ b/devops-client/lib/devops-client/options/stack_options.rb @@ -0,0 +1,49 @@ +require "devops-client/options/common_options" + +class StackOptions < CommonOptions + + commands :create, :delete, :list, :show + + def initialize args, def_options + super(args, def_options) + self.header = I18n.t("headers.stack") + self.banner_header = "stack" + self.list_params = ["[provider]", "[ec2|openstack]"] + self.show_params = ["STACK"] + self.delete_params = ["STACK"] + end + + def create_options + self.options do |parser, options| + parser.banner << self.create_banner + + parser.recognize_option_value(:provider, 'stack') + parser.recognize_option_value(:id, 'stack') + parser.recognize_option_value(:project, 'stack') + parser.recognize_option_value(:deploy_env, 'stack') + parser.recognize_option_value(:stack_template, 'stack') + + parser.recognize_option_value(:parameters, 'stack') do |parameters| + begin + hash = JSON.parse(parameters) + options[:parameters] = hash + rescue JSON::ParserError + raise ArgumentError.new('Should be proper JSON string') + end + end + + end + end + + # QUESTION: + # Should we check options logic here, or in Handler, or in separate class? + + extend_options_method :list_options do |options| + if args[2] == "provider" and args[3] + options[:given_provider] = args[3] + elsif args[2] + options[:given_provider] = args[2] + end + end + +end diff --git a/devops-client/lib/devops-client/options/stack_template_options.rb b/devops-client/lib/devops-client/options/stack_template_options.rb new file mode 100644 index 0000000..67f8498 --- /dev/null +++ b/devops-client/lib/devops-client/options/stack_template_options.rb @@ -0,0 +1,34 @@ +require "devops-client/options/common_options" + +class StackTemplateOptions < CommonOptions + + commands :create, :delete, :list, :show + + def initialize args, def_options + super(args, def_options) + self.header = I18n.t("headers.stack_template") + self.banner_header = "stack_template" + self.list_params = ["[provider]", "[ec2|openstack]"] + self.show_params = ["STACK_TEMPLATE"] + self.delete_params = ["STACK_TEMPLATE"] + end + + def create_options + self.options do |parser, options| + parser.banner << self.create_banner + + parser.recognize_option_value(:provider, 'stack_template', default: nil) + parser.recognize_option_value(:id, 'stack_template') + parser.recognize_option_value(:template_file, 'stack_template') + end + end + + extend_options_method :list_options do |options| + if args[2] == "provider" and args[3] + options[:given_provider] = args[3] + elsif args[2] + options[:given_provider] = args[2] + end + end + +end diff --git a/devops-client/lib/devops-client/output/base.rb b/devops-client/lib/devops-client/output/base.rb index 9b1fc61..b7049bb 100644 --- a/devops-client/lib/devops-client/output/base.rb +++ b/devops-client/lib/devops-client/output/base.rb @@ -3,7 +3,49 @@ require "csv" require "json" module Output - module Base + class Base + + attr_reader :options + + # QUESTION: + # Earlier I use additional parameter "output_type". Now I use + # detecting output_type from data_to_output.class: + # Array means we are outputting list command, + # Hash or something other - we are outputting show command. + # Is this OK? + + def initialize(data_to_output, command_line_options={}, additional_options={}) + @data, @options, @additional_options = data_to_output, command_line_options, additional_options + end + + def output + case options[:format] + when CommonOptions::TABLE_FORMAT + table + when CommonOptions::JSON_FORMAT + json + when CommonOptions::CSV_FORMAT + csv + end + end + + def json + JSON.pretty_generate(@data) + end + + private + + def output_type + @data.kind_of?(Array) ? :list : :show + end + + def outputting_list? + output_type == :list + end + + def with_num? + outputting_list? + end def create_table headers, rows, title=nil, with_num=true, separator=false return nil if headers.nil? or rows.nil? @@ -37,5 +79,14 @@ module Output c.string end + def headers_and_rows(records, fields_to_output) + headers = fields_to_output.map { |field| I18n.t("output.table_header.#{field}") } + rows = records.map do |record| + fields_to_output.map { |field| record[field] } + end + + [headers, rows] + end + end end diff --git a/devops-client/lib/devops-client/output/bootstrap_templates.rb b/devops-client/lib/devops-client/output/bootstrap_templates.rb index 712878e..b1ffeef 100644 --- a/devops-client/lib/devops-client/output/bootstrap_templates.rb +++ b/devops-client/lib/devops-client/output/bootstrap_templates.rb @@ -1,23 +1,18 @@ require "devops-client/output/base" module Output - module BootstrapTemplates - include Base + class BootstrapTemplates < Base def table - headers, rows = create(@list) + headers, rows = create(@data) create_table(headers, rows, I18n.t("output.title.bootstrap_template.list")) end def csv - headers, rows = create(@list) + headers, rows = create(@data) create_csv(headers, rows) end - def json - JSON.pretty_generate @list - end - private def create list abort I18n.t("output.not_found.bootstrap_template.list") if list.nil? or list.empty? diff --git a/devops-client/lib/devops-client/output/concerns/has_provider.rb b/devops-client/lib/devops-client/output/concerns/has_provider.rb new file mode 100644 index 0000000..02366bd --- /dev/null +++ b/devops-client/lib/devops-client/output/concerns/has_provider.rb @@ -0,0 +1,9 @@ +module Output + module Concerns + module HasProvider + def provider_given? + !@options[:given_provider].nil? + end + end + end +end \ No newline at end of file diff --git a/devops-client/lib/devops-client/output/filters.rb b/devops-client/lib/devops-client/output/filters.rb index f39b9d6..7f6c9a9 100644 --- a/devops-client/lib/devops-client/output/filters.rb +++ b/devops-client/lib/devops-client/output/filters.rb @@ -1,23 +1,18 @@ require "devops-client/output/base" module Output - module Filters - include Base + class Filters < Base def table - headers, rows = create(@list) + headers, rows = create(@data) create_table(headers, rows, I18n.t("output.title.filter.list")) end def csv - headers, rows = create(@list) + headers, rows = create(@data) create_csv(headers, rows) end - def json - JSON.pretty_generate @list - end - private def create list abort(I18n.t("output.not_found.filter.list")) if list.nil? or list.empty? diff --git a/devops-client/lib/devops-client/output/flavors.rb b/devops-client/lib/devops-client/output/flavors.rb index 00cc9a8..ffb56a9 100644 --- a/devops-client/lib/devops-client/output/flavors.rb +++ b/devops-client/lib/devops-client/output/flavors.rb @@ -1,23 +1,20 @@ require "devops-client/output/base" +require "devops-client/output/concerns/has_provider" module Output - module Flavors - include Base + class Flavors < Base + include Concerns::HasProvider def table - headers, rows = create(@list, @provider) + headers, rows = create(@data, @options[:given_provider]) create_table(headers, rows, I18n.t("output.title.flavor.list")) end def csv - headers, rows = create(@list, @provider) + headers, rows = create(@data, @options[:given_provider]) create_csv(headers, rows) end - def json - JSON.pretty_generate @list - end - private def create list, provider abort(I18n.t("output.not_found.flavor.list")) if list.nil? or list.empty? diff --git a/devops-client/lib/devops-client/output/groups.rb b/devops-client/lib/devops-client/output/groups.rb index da393a6..3f1e447 100644 --- a/devops-client/lib/devops-client/output/groups.rb +++ b/devops-client/lib/devops-client/output/groups.rb @@ -1,23 +1,18 @@ require "devops-client/output/base" module Output - module Groups - include Base + class Groups < Base def table - headers, rows = create(@list) + headers, rows = create(@data) create_table(headers, rows, I18n.t("output.title.group.list"), true, true) end def csv - headers, rows = create(@list) + headers, rows = create(@data) create_csv(headers, rows) end - def json - JSON.pretty_generate @list - end - private def create list abort(I18n.t("output.not_found.group.list")) if list.nil? or list.empty? diff --git a/devops-client/lib/devops-client/output/image.rb b/devops-client/lib/devops-client/output/image.rb index 27779d2..8c16081 100644 --- a/devops-client/lib/devops-client/output/image.rb +++ b/devops-client/lib/devops-client/output/image.rb @@ -1,42 +1,30 @@ require "devops-client/output/base" +require "devops-client/output/concerns/has_provider" module Output - module Image - include Base + class Image < Base + include Concerns::HasProvider def table title, headers, rows = nil, nil, nil - with_num = if !@list.nil? + if outputting_list? title = I18n.t("output.title.image.list") - headers, rows = create_list(@list, @provider) - true - elsif !@show.nil? - title = I18n.t("output.title.image.show", :id => @show["id"]) - headers, rows = create_show @show - false + headers, rows = create_list(@data, provider_given?) + else + title = I18n.t("output.title.image.show", :id => @data["id"]) + headers, rows = create_show end - create_table headers, rows, title, with_num + create_table headers, rows, title, with_num? end def csv title, headers, rows = nil, nil, nil - with_num = if !@list.nil? - headers, rows = create_list(@list, @provider) - true - elsif !@show.nil? - headers, rows = create_show @show - false + if !@data.nil? + headers, rows = create_list(@data, provider_given?) + elsif !@data.nil? + headers, rows = create_show end - create_csv headers, rows, with_num - end - - def json - JSON.pretty_generate( case ARGV[1] - when "list" - @list - when "show" - @show - end) + create_csv headers, rows, with_num? end private @@ -63,8 +51,8 @@ module Output return headers, rows end - def create_show show - rows = [ [ show["id"], show["name"], show["bootstrap_template"], show["remote_user"], show["provider"] ] ] + def create_show + rows = [ [ @data["id"], @data["name"], @data["bootstrap_template"], @data["remote_user"], @data["provider"] ] ] headers = [ I18n.t("output.table_header.id"), I18n.t("output.table_header.name"), diff --git a/devops-client/lib/devops-client/output/key.rb b/devops-client/lib/devops-client/output/key.rb index 9865c55..cf9c853 100644 --- a/devops-client/lib/devops-client/output/key.rb +++ b/devops-client/lib/devops-client/output/key.rb @@ -1,27 +1,19 @@ require "devops-client/output/base" module Output - module Key - include Base + class Key < Base def table title = I18n.t("output.title.key.list") - headers, rows = create(@list) + headers, rows = create(@data) create_table headers, rows, title end def csv - headers, rows = create(@list) + headers, rows = create(@data) create_csv headers, rows end - def json - JSON.pretty_generate( case ARGV[1] - when "list" - @list - end) - end - private def create list abort(I18n.t("output.not_found.key.list")) if list.nil? or list.empty? diff --git a/devops-client/lib/devops-client/output/network.rb b/devops-client/lib/devops-client/output/network.rb index 7609391..da39491 100644 --- a/devops-client/lib/devops-client/output/network.rb +++ b/devops-client/lib/devops-client/output/network.rb @@ -1,23 +1,21 @@ require "devops-client/output/base" +require "devops-client/output/concerns/has_provider" module Output - module Network - include Base + class Network < Base + include Concerns::HasProvider + def table - headers, rows = create(@list, @provider) + headers, rows = create(@data, @options[:given_provider]) create_table(headers, rows, I18n.t("output.title.network.list")) end def csv - headers, rows = create(@list, @provider) + headers, rows = create(@data, @options[:given_provider]) create_csv(headers, rows) end - def json - JSON.pretty_generate @list - end - private def create list, provider headers = nil diff --git a/devops-client/lib/devops-client/output/project.rb b/devops-client/lib/devops-client/output/project.rb index e6b060b..6c847b9 100644 --- a/devops-client/lib/devops-client/output/project.rb +++ b/devops-client/lib/devops-client/output/project.rb @@ -1,63 +1,48 @@ require "devops-client/output/base" module Output - module Project - include Base + class Project < Base NODE_HEADER = "Node number" SUBPROJECT_HEADER = "Subproject" def table - title, = nil - with_num, with_separator = true, false - headers, rows = if !@list.nil? + title = nil + with_separator = false + headers, rows = case @additional_options[:output_type] + when :list title = I18n.t("output.title.project.list") - create_list(@list) - elsif !@show.nil? - title = I18n.t("output.title.project.show", :name => @show["name"]) - with_num = false + create_list(@data) + when :show + title = I18n.t("output.title.project.show", :name => @data["name"]) with_separator = true - create_show(@show) - elsif !@servers.nil? + create_show(@data) + when :server title = ARGV[2] title += " " + ARGV[3] unless ARGV[3].nil? title = I18n.t("output.title.project.servers", :title => title) - create_servers(@servers) - elsif !@test.nil? - with_num = false + create_servers(@data) + when :test title = I18n.t("output.title.project.test", :project => ARGV[2], :env => ARGV[3]) - create_test(@test) + create_test(@data) end - create_table(headers, rows, title, with_num, with_separator) + create_table(headers, rows, title, with_num?, with_separator) end def csv with_num = true - headers, rows = if !@list.nil? - create_list(@list) - elsif !@show.nil? + headers, rows = case @additional_options[:output_type] + when :list + create_list(@data) + when :show with_num = false - create_show(@show) - elsif !@servers.nil? - create_servers(@servers) - elsif !@test.nil? - with_num = false - create_test(@test) + create_show(@data) + when :servers + create_servers(@data) + when :test + create_test(@data) end - create_csv(headers, rows, with_num) - end - - def json - JSON.pretty_generate(case ARGV[1] - when "list" - @list.map {|l| l["name"]} - when "show" - @show - when "servers" - @servers - when "test" - @test - end) + create_csv(headers, rows, with_num?) end private @@ -90,7 +75,16 @@ module Output ] else show["deploy_envs"].each do |de| - rows.push [ show["name"], de["identifier"], de["image"], de["flavor"], de["run_list"].join("\n"), de["groups"].join("\n"), de["subnets"].join("\n"), de["users"].join("\n") ] + rows.push [ + show["name"], + de["identifier"], + de["image"], + de["flavor"], + (de["run_list"] || []).join("\n"), + (de["groups"] || []).join("\n"), + (de["subnets"] || []).join("\n"), + (de["users"] || []).join("\n") + ] end [ I18n.t("output.table_header.id"), diff --git a/devops-client/lib/devops-client/output/provider.rb b/devops-client/lib/devops-client/output/provider.rb index bbbc9fb..cd7ab16 100644 --- a/devops-client/lib/devops-client/output/provider.rb +++ b/devops-client/lib/devops-client/output/provider.rb @@ -1,32 +1,29 @@ require "devops-client/output/base" module Output - module Provider - include Base + class Provider < Base def table - headers, rows = create(@list) + headers, rows = create create_table(headers, rows, I18n.t("output.title.provider.list")) end def csv - headers, rows = create(@list) + headers, rows = create create_csv(headers, rows) end - def json - JSON.pretty_generate @list - end + private - private - def create list - abort(I18n.t("output.not_found.provider.list")) if list.empty? + def create + abort(I18n.t("output.not_found.provider.list")) if @data.empty? headers = [ I18n.t("output.table_header.provider") ] rows = [] - list.each do |l| + @data.each do |l| rows.push [ l ] end return headers, rows end + end end diff --git a/devops-client/lib/devops-client/output/script.rb b/devops-client/lib/devops-client/output/script.rb index 8dc0669..5190df9 100644 --- a/devops-client/lib/devops-client/output/script.rb +++ b/devops-client/lib/devops-client/output/script.rb @@ -1,26 +1,18 @@ require "devops-client/output/base" module Output - module Script - include Base + class Script < Base def table - headers, rows = create(@list) + headers, rows = create(@data) create_table(headers, rows, I18n.t("output.title.script.list")) end def csv - headers, rows = create(@list) + headers, rows = create(@data) create_csv(headers, rows) end - def json - JSON.pretty_generate( case ARGV[1] - when "list" - @list - end) - end - private def create list rows = [] diff --git a/devops-client/lib/devops-client/output/server.rb b/devops-client/lib/devops-client/output/server.rb index 97b4691..940679c 100644 --- a/devops-client/lib/devops-client/output/server.rb +++ b/devops-client/lib/devops-client/output/server.rb @@ -1,12 +1,11 @@ require "devops-client/output/base" module Output - module Server - include Base + class Server < Base def table title = nil - headers, rows = if !@list.nil? + headers, rows = if outputting_list? case options[:type] when "chef" title = I18n.t("output.title.server.chef") @@ -17,34 +16,26 @@ module Output else title = I18n.t("output.title.server.list") end - create_list(@list) - elsif !@show.nil? - title = I18n.t("output.title.server.show", :name => @show["chef_node_name"]) - create_show(@show) + create_list + else + title = I18n.t("output.title.server.show", :name => @data["chef_node_name"]) + create_show end create_table headers, rows, title end def csv - headers, rows = if !@list.nil? - create_list(@list) - elsif !@show.nil? - create_show(@show) + headers, rows = if outputting_list? + create_list + else + create_show end create_csv headers, rows end - def json - JSON.pretty_generate(case ARGV[1] - when "list" - @list - when "show" - @show - end) - end - private - def create_list list + def create_list + list = @data abort(I18n.t("output.not_found.server.list")) if list.empty? rows, keys = [], nil headers = case options[:type] @@ -97,7 +88,7 @@ module Output return headers, rows end - def create_show show + def create_show rows = [] headers = [ I18n.t("output.table_header.instance_id"), @@ -112,7 +103,7 @@ module Output ] keys = ["id", "chef_node_name", "project", "deploy_env", "provider", "remote_user", "private_ip", "created_at", "created_by"] row = [] - keys.each{|k| row.push show[k]} + keys.each{|k| row.push @data[k]} rows.push row return headers, rows end diff --git a/devops-client/lib/devops-client/output/stack.rb b/devops-client/lib/devops-client/output/stack.rb new file mode 100644 index 0000000..e87d5ec --- /dev/null +++ b/devops-client/lib/devops-client/output/stack.rb @@ -0,0 +1,44 @@ +require "devops-client/output/base" +require "devops-client/output/concerns/has_provider" + +module Output + class Stack < Base + include Concerns::HasProvider + + def table + if outputting_list? + title = I18n.t("output.title.stack.list") + headers, rows = create_list + else + title = I18n.t("output.title.stack.show", id: @data["id"]) + headers, rows = create_show + end + create_table(headers, rows, title, with_num?) + end + + def csv + if outputting_list? + headers, rows = create_list + else + headers, rows = create_show + end + create_csv(headers, rows, with_num?) + end + + private + + def create_list + abort(I18n.t("output.not_found.stack.list")) if @data.empty? + + fields_to_output = %w(id deploy_env stack_template) + fields_to_output << 'provider' unless provider_given? + + headers_and_rows(@data, fields_to_output) + end + + def create_show + headers_and_rows([@data], %w(id deploy_env stack_template cloud_stack_id)) + end + + end +end diff --git a/devops-client/lib/devops-client/output/stack_template.rb b/devops-client/lib/devops-client/output/stack_template.rb new file mode 100644 index 0000000..8c99dab --- /dev/null +++ b/devops-client/lib/devops-client/output/stack_template.rb @@ -0,0 +1,57 @@ +require "devops-client/output/base" + +module Output + class StackTemplate < Base + + def table + if outputting_list? + title = I18n.t("output.title.stack_template.list") + headers, rows = create_list + else + title = I18n.t("output.title.stack_template.show", :id => @data["id"]) + headers, rows = create_show + end + create_table headers, rows, title, with_num? + end + + def csv + if outputting_list? + headers, rows = create_list + else + headers, rows = create_show + end + create_csv headers, rows, with_num? + end + + def json + JSON.pretty_generate(@data) + end + + private + # Note: shouldn't be in Base class + def provider_given? + !@options[:given_provider].nil? + end + + def create_list + abort(I18n.t("output.not_found.stack_template.list")) if @data.empty? + + fields_to_output = %w(id) + fields_to_output << 'provider' unless provider_given? + + headers_and_rows(@data, fields_to_output) + end + + def create_show + rows = [ [ @data["id"], @data["provider"], @data["template_url"], @data["template_body"] ] ] + headers = [ + I18n.t("output.table_header.id"), + I18n.t("output.table_header.provider"), + I18n.t("output.table_header.template_url"), + I18n.t("output.table_header.template_body") + ] + return headers, rows + end + + end +end diff --git a/devops-client/lib/devops-client/output/tag.rb b/devops-client/lib/devops-client/output/tag.rb index 4c26fc5..24ef4f9 100644 --- a/devops-client/lib/devops-client/output/tag.rb +++ b/devops-client/lib/devops-client/output/tag.rb @@ -1,21 +1,20 @@ require "devops-client/output/base" module Output - module Tag - include Base + class Tag < Base def table - headers, rows = create(@list) + headers, rows = create(@data) create_table(headers, rows, I18n.t("output.title.tag.list")) end def csv - headers, rows = create(@list) + headers, rows = create(@data) create_csv(headers, rows) end def json - JSON.pretty_generate @list + JSON.pretty_generate @data end private diff --git a/devops-client/lib/devops-client/output/user.rb b/devops-client/lib/devops-client/output/user.rb index df9ebe2..038a070 100644 --- a/devops-client/lib/devops-client/output/user.rb +++ b/devops-client/lib/devops-client/output/user.rb @@ -1,13 +1,12 @@ require "devops-client/output/base" module Output - module User - include Base + class User < Base def table title, headers = nil, nil rows, with_num = create_subheader, false - rows += create_rows(@list) + rows += create_rows headers = [ "", "", @@ -15,23 +14,16 @@ module Output {:value => I18n.t("output.table_header.privileges"), :colspan => 12, :alignment => :center } ] - create_table headers, rows, I18n.t("output.title.user.list"), with_num, true + create_table headers, rows, I18n.t("output.title.users.list"), with_num, true end + private def csv - rows = create_rows(@list) + rows = create_rows(@data) headers = create_subheader create_csv headers, rows end - def json - JSON.pretty_generate( case ARGV[1] - when "list" - @list - end) - end - - private def create_subheader [ [ I18n.t("output.table_header.number"), @@ -52,10 +44,10 @@ module Output ] ] end - def create_rows list - abort(I18n.t("output.not_found.user.list")) if list.nil? or list.empty? + def create_rows + abort(I18n.t("output.not_found.user.list")) if @data.nil? or @data.empty? rows = [] - list.each_with_index do |l, i| + @data.each_with_index do |l, i| next if l["privileges"].nil? flavor = "#{l["privileges"]["flavor"]}" diff --git a/devops-client/locales/en.yml b/devops-client/locales/en.yml index 1ac1eeb..49fc21e 100644 --- a/devops-client/locales/en.yml +++ b/devops-client/locales/en.yml @@ -26,6 +26,7 @@ en: headers: flavor: "Flavor" template: "Bootstrap template" + bootstrap_template: "Bootstrap template" deploy: "Deploy" filters: "Filters" group: "Security groups" @@ -34,11 +35,14 @@ en: network: "Network" project: "Project" project_env: "Project environment" + deploy_env: "Deploy environment" provider: "Provider" server: "Server" script: "Script" tag: "Tag" user: "User" + stack: "Stack" + stack_template: "Stack template" handler: flavor: list: @@ -98,6 +102,21 @@ en: server: question: delete: "Are you sure to delete server '%{name}'?" + stack_template: + create: + id: "Id: " + template_file: "Path to file with template json: " + question: + create: "Are you sure to create stack template?" + delete: "Are you sure to delete stack template '%{name}'?" + stack: + create: + id: "Id: " + deploy_env: "Deploy env: " + parameters: "Please input parameters hash: " + question: + create: "Are you sure to create stack?" + delete: "Are you sure to delete stack '%{name}'?" message: choose_list_default: "Choose %{name} (comma separated), like 1,2,3 or empty for default value '%{default}': " choose_list: "Choose %{name} (comma separated), like 1,2,3: " @@ -167,6 +186,10 @@ en: keypair: "Keypair" created_at: "Created at" created_by: "Created by" + template_url: "Template url" + template_body: "Template body" + stack_template: "Stack Template" + cloud_stack_id: "Cloud Stack id" title: flavor: list: "Flavors" @@ -202,6 +225,12 @@ en: list: "Tags" users: list: "Users" + stack_template: + list: "Stack Templates" + show: "Stack Template" + stack: + list: "Stacks" + show: "Stack" not_found: flavor: list: "No flavor found" @@ -230,6 +259,12 @@ en: list: "No tags found" user: list: "No users found" + stack_template: + list: "No stack templates found" + show: "There isn't such stack template" + stack: + list: "No stacks found" + show: "There isn't such stack" options: usage: "Usage: %{cmd} command [options]" commands: "Commands" @@ -266,9 +301,6 @@ en: deploy_env: "Delete user from deploy environment" deploy: servers: "Servers list (comma separated) for deploy" - script: - run: - params: "Script arguments (comma separated list)" descriptions: deploy: tag: 'Tag names, comma separated list' @@ -335,4 +367,3 @@ en: template_file: Stack template file user: new_password: New user password -