From f3d1f6a9ff8e73e1eb4f3df2fd0eb0f74518a5c3 Mon Sep 17 00:00:00 2001 From: amartynov Date: Tue, 1 Jul 2014 11:57:36 +0400 Subject: [PATCH] openstack and ec2 deploy_envs --- .../handler/deploy_envs/deploy_env.rb | 132 +++++++++++++ .../handler/deploy_envs/deploy_env_ec2.rb | 65 +++++++ .../handler/deploy_envs/deploy_env_factory.rb | 26 +++ .../deploy_envs/deploy_env_openstack.rb | 57 ++++++ .../handler/deploy_envs/deploy_env_static.rb | 20 ++ .../lib/devops-client/handler/handler.rb | 106 +---------- .../lib/devops-client/handler/input_utils.rb | 106 +++++++++++ .../lib/devops-client/handler/project.rb | 180 ++---------------- devops-client/lib/devops-client/version.rb | 2 +- 9 files changed, 425 insertions(+), 269 deletions(-) create mode 100644 devops-client/lib/devops-client/handler/deploy_envs/deploy_env.rb create mode 100644 devops-client/lib/devops-client/handler/deploy_envs/deploy_env_ec2.rb create mode 100644 devops-client/lib/devops-client/handler/deploy_envs/deploy_env_factory.rb create mode 100644 devops-client/lib/devops-client/handler/deploy_envs/deploy_env_openstack.rb create mode 100644 devops-client/lib/devops-client/handler/deploy_envs/deploy_env_static.rb create mode 100644 devops-client/lib/devops-client/handler/input_utils.rb 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 new file mode 100644 index 0000000..6fcbb4c --- /dev/null +++ b/devops-client/lib/devops-client/handler/deploy_envs/deploy_env.rb @@ -0,0 +1,132 @@ +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" + +class DeployEnv + + include InputUtils + + attr_accessor :options, :auth, :flavors, :flavors_table, :images, :images_table, :networks, :networks_table, :groups, :groups_table, :users, :users_table + + def set_parameter obj, key + if self.options[key].nil? + obj[key] = yield + else + obj[key] = self.options[key] + end + end + + def fill obj + yield(obj) if block_given? + + set_users(obj) + + unless self.options[:run_list].nil? + self.options[:run_list] = self.options[:run_list].split(",").map{|e| e.strip} + abort("Invalid run list: '#{self.options[:run_list].join(",")}'") unless DeployEnv.validate_run_list(self.options[:run_list]) + end + set_parameter obj, :run_list do + set_run_list_cmd + end + + unless self.options[:no_expires] + set_parameter obj, :expires do + s = enter_parameter_or_empty(I18n.t("options.project.create.expires") + ": ").strip + s.empty? ? nil : s + end + end + end + + def set_run_list_cmd + res = nil + begin + res = get_comma_separated_list(I18n.t("options.project.create.run_list") + ": ") + end until DeployEnv.validate_run_list(res) + res + end + + # 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"] + 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"] + 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]} + end + d[:users].add(self.options[:username]) + d[:users] = d[:users].to_a + end + + def self.validate_run_list run_list + return true if run_list.empty? + rl = /\Arole|recipe\[[\w-]+(::[\w-]+)?\]\Z/ + e = run_list.select {|l| (rl =~ l).nil?} + res = e.empty? + puts I18n.t("handler.project.create.run_list.invalid", :list => e.join(", ")) unless res + res + end + + +end diff --git a/devops-client/lib/devops-client/handler/deploy_envs/deploy_env_ec2.rb b/devops-client/lib/devops-client/handler/deploy_envs/deploy_env_ec2.rb new file mode 100644 index 0000000..12216df --- /dev/null +++ b/devops-client/lib/devops-client/handler/deploy_envs/deploy_env_ec2.rb @@ -0,0 +1,65 @@ +require "devops-client/handler/deploy_envs/deploy_env" + +class DeployEnvEc2 < DeployEnv + + NAME = "ec2" + + def initialize host, options, auth + @host = host + self.auth = auth + self.options = options + end + + def provider + NAME + end + + def fill obj + super(obj) do |o| + set_flavor(o) + set_image(o) + vpc_id = set_subnets(o) + set_groups(o, vpc_id) + end + end + + def set_subnets d + if self.networks.nil? + get_networks + end + unless self.options[:subnets].nil? + self.options[:subnets] = [ self.options[:subnets][0] ] + end + vpc_id = nil + set_parameter d, :subnets do + if self.networks.any? + num = choose_number_from_list(I18n.t("handler.project.create.subnet.ec2"), self.networks, self.networks_table, -1) + vpc_id = self.networks[num]["vpcId"] unless num == -1 + num == -1 ? [] : [ self.networks[num]["subnetId"] ] + else + [] + end + end + return vpc_id + end + + def get_groups vpcId + g = Group.new(@host, self.options) + g.auth = self.auth + p = ["group", "list", provider] + p.push vpcId if !vpcId.nil? + self.groups = g.list_handler(p) + self.groups_table = g.table + end + + def set_groups d, vpc_id + if self.groups.nil? + get_groups(vpc_id) + end + set_parameter d, :groups do + list = groups.keys + choose_indexes_from_list(I18n.t("options.project.create.groups"), list, self.groups_table, "default", list.index("default")).map{|i| list[i]} + end + end + +end diff --git a/devops-client/lib/devops-client/handler/deploy_envs/deploy_env_factory.rb b/devops-client/lib/devops-client/handler/deploy_envs/deploy_env_factory.rb new file mode 100644 index 0000000..f062711 --- /dev/null +++ b/devops-client/lib/devops-client/handler/deploy_envs/deploy_env_factory.rb @@ -0,0 +1,26 @@ +require "devops-client/handler/deploy_envs/deploy_env_static" +require "devops-client/handler/deploy_envs/deploy_env_ec2" +require "devops-client/handler/deploy_envs/deploy_env_openstack" + +class DeployEnvFactory + + @@envs = {} + + def self.create provider, host, options, auth + unless @@envs.key?(provider) + de = case provider + when DeployEnvStatic::NAME + DeployEnvStatic + when DeployEnvEc2::NAME + DeployEnvEc2 + when DeployEnvOpenstack::NAME + DeployEnvOpenstack + else + + end + @@envs[provider] = de.new(host, options, auth) + end + @@envs[provider] + end + +end diff --git a/devops-client/lib/devops-client/handler/deploy_envs/deploy_env_openstack.rb b/devops-client/lib/devops-client/handler/deploy_envs/deploy_env_openstack.rb new file mode 100644 index 0000000..e63fbab --- /dev/null +++ b/devops-client/lib/devops-client/handler/deploy_envs/deploy_env_openstack.rb @@ -0,0 +1,57 @@ +require "devops-client/handler/deploy_envs/deploy_env" + +class DeployEnvOpenstack < DeployEnv + + NAME = "openstack" + + def initialize host, options, auth + @host = host + self.auth = auth + self.options = options + end + + def provider + NAME + end + + def fill obj + super(obj) do |o| + set_flavor(o) + set_image(o) + set_subnets(o) + set_groups(o) + end + end + + def set_subnets d + networks, tn = nil, nil + if self.networks.nil? + get_networks + end + set_parameter d, :subnets do + s = [] + begin + s = choose_indexes_from_list(I18n.t("handler.project.create.subnet.openstack"), self.networks, self.networks_table).map{|i| self.networks[i]["name"]} + end while s.empty? + s + end + end + + def get_groups + g = Group.new(@host, self.options) + g.auth = self.auth + self.groups = g.list_handler(["group", "list", self.provider]) + self.groups_table = g.table + end + + def set_groups d + if self.groups.nil? + get_groups + end + set_parameter d, :groups do + list = groups.keys + choose_indexes_from_list(I18n.t("options.project.create.groups"), list, self.groups_table, "default", list.index("default")).map{|i| list[i]} + end + end + +end diff --git a/devops-client/lib/devops-client/handler/deploy_envs/deploy_env_static.rb b/devops-client/lib/devops-client/handler/deploy_envs/deploy_env_static.rb new file mode 100644 index 0000000..b70745d --- /dev/null +++ b/devops-client/lib/devops-client/handler/deploy_envs/deploy_env_static.rb @@ -0,0 +1,20 @@ +require "devops-client/handler/deploy_envs/deploy_env" + +class DeployEnvStatic < DeployEnv + + NAME = "static" + + def initialize options, auth + self.auth = auth + self.options = options + end + + def provider + NAME + end + + def fill obj + super(obj) + end + +end diff --git a/devops-client/lib/devops-client/handler/handler.rb b/devops-client/lib/devops-client/handler/handler.rb index 27ab4fa..e35f3a9 100644 --- a/devops-client/lib/devops-client/handler/handler.rb +++ b/devops-client/lib/devops-client/handler/handler.rb @@ -6,9 +6,12 @@ require "devops-client/options/common_options" require "uri" require "json" require "devops-client/i18n" +require "devops-client/handler/input_utils" class Handler + include InputUtils + attr_reader :options attr_writer :host attr_accessor :auth @@ -114,109 +117,6 @@ protected puts "\e[31m#{msg}\e[0m" end - def question str - return true if self.options[:no_ask] - if block_given? - yield - end - res = false - #system("stty raw -echo") - begin - print "#{str} (y/n): " - s = STDIN.gets.strip - if s == "y" - res = true - elsif s == "n" - res == false - else - raise ArgumentError.new - end - rescue ArgumentError - retry - end - #print "#{s}\n\r" - #system("stty -raw echo") - res - end - - def choose_image_cmd images, t=nil - abort(I18n.t("handler.error.list.empty", :name => "Image")) if images.empty? - if options[:image_id].nil? - images[ choose_number_from_list(I18n.t("headers.image"), images, t) ] - else - i = images.detect { |i| i["name"] == options[:image_id]} - abort("No such image") if i.nil? - return i - end - end - - def get_comma_separated_list msg - print msg - STDIN.gets.strip.split(",").map{|e| e.strip} - end - - def enter_parameter msg - str = enter_parameter_or_empty(msg) - raise ArgumentError.new if str.empty? - str - rescue ArgumentError - retry - end - - def enter_parameter_or_empty msg - print msg - return STDIN.gets.strip - end - - def choose_number_from_list title, list, table=nil, default=nil - i = 0 - if table.nil? - puts I18n.t("handler.message.choose", :name => title.downcase) + "\n" + list.map{|p| i += 1; "#{i}. #{p}"}.join("\n") - else - puts table - end - begin - print "#{title}: " - buf = STDIN.gets.strip - if buf.empty? and !default.nil? - return default - end - i = Integer buf - rescue ArgumentError - retry - end until i > 0 and i <= list.size - return i - 1 - end - - def choose_indexes_from_list title, list, table=nil, default=nil, defindex=nil - abort(I18n.t("handler.error.list.empty", :name => title)) if list.empty? - ar = nil - if table.nil? - i = 0 - print I18n.t("handler.message.choose", :name => title.downcase) + "\n#{list.map{|p| i += 1; "#{i}. #{p}"}.join("\n")}\n" - else - puts table - end - msg = if default.nil? - I18n.t("handler.message.choose_list", :name => title) - else - I18n.t("handler.message.choose_list_default", :name => title, :default => default) - end - begin - ar = get_comma_separated_list(msg).map do |g| - n = Integer g.strip - raise ArgumentError.new(I18n.t("handler.error.number.invalid")) if n < 1 or n > list.size - n - end - if ar.empty? and !default.nil? - return [ defindex ] - end - rescue ArgumentError - retry - end - ar.map{|i| i - 1} - end - def output case self.options[:format] when CommonOptions::TABLE_FORMAT diff --git a/devops-client/lib/devops-client/handler/input_utils.rb b/devops-client/lib/devops-client/handler/input_utils.rb new file mode 100644 index 0000000..74c85f4 --- /dev/null +++ b/devops-client/lib/devops-client/handler/input_utils.rb @@ -0,0 +1,106 @@ +module InputUtils + + def question str + return true if self.options[:no_ask] + if block_given? + yield + end + res = false + #system("stty raw -echo") + begin + print "#{str} (y/n): " + s = STDIN.gets.strip + if s == "y" + res = true + elsif s == "n" + res == false + else + raise ArgumentError.new + end + rescue ArgumentError + retry + end + #print "#{s}\n\r" + #system("stty -raw echo") + res + end + + def choose_image_cmd images, t=nil + abort(I18n.t("handler.error.list.empty", :name => "Image")) if images.empty? + if options[:image_id].nil? + images[ choose_number_from_list(I18n.t("headers.image"), images, t) ] + else + i = images.detect { |i| i["name"] == options[:image_id]} + abort("No such image") if i.nil? + return i + end + end + + def get_comma_separated_list msg + print msg + STDIN.gets.strip.split(",").map{|e| e.strip} + end + + def enter_parameter msg + str = enter_parameter_or_empty(msg) + raise ArgumentError.new if str.empty? + str + rescue ArgumentError + retry + end + + def enter_parameter_or_empty msg + print msg + return STDIN.gets.strip + end + + def choose_number_from_list title, list, table=nil, default=nil + i = 0 + if table.nil? + puts I18n.t("handler.message.choose", :name => title.downcase) + "\n" + list.map{|p| i += 1; "#{i}. #{p}"}.join("\n") + else + puts table + end + begin + print "#{title}: " + buf = STDIN.gets.strip + if buf.empty? and !default.nil? + return default + end + i = Integer buf + rescue ArgumentError + retry + end until i > 0 and i <= list.size + return i - 1 + end + + def choose_indexes_from_list title, list, table=nil, default=nil, defindex=nil + abort(I18n.t("handler.error.list.empty", :name => title)) if list.empty? + ar = nil + if table.nil? + i = 0 + print I18n.t("handler.message.choose", :name => title.downcase) + "\n#{list.map{|p| i += 1; "#{i}. #{p}"}.join("\n")}\n" + else + puts table + end + msg = if default.nil? + I18n.t("handler.message.choose_list", :name => title) + else + I18n.t("handler.message.choose_list_default", :name => title, :default => default) + end + begin + ar = get_comma_separated_list(msg).map do |g| + n = Integer g.strip + raise ArgumentError.new(I18n.t("handler.error.number.invalid")) if n < 1 or n > list.size + n + end + if ar.empty? and !default.nil? + return [ defindex ] + end + rescue ArgumentError + retry + end + ar.map{|i| i - 1} + end + +end diff --git a/devops-client/lib/devops-client/handler/project.rb b/devops-client/lib/devops-client/handler/project.rb index 020f72e..5bd15b6 100644 --- a/devops-client/lib/devops-client/handler/project.rb +++ b/devops-client/lib/devops-client/handler/project.rb @@ -8,6 +8,7 @@ require "devops-client/options/project_options" require "json" require "set" require "devops-client/output/project" +require "devops-client/handler/deploy_envs/deploy_env_factory" class Project < Handler @@ -244,7 +245,7 @@ class Project < Handler if run_list.empty? exit unless question(I18n.t("handler.project.run_list.empty")) else - exit unless Project.validate_run_list(run_list) + exit unless DeployEnv.validate_run_list(run_list) end put "/project/#{args[3]}/#{args[4]}/run_list", run_list end @@ -281,41 +282,10 @@ protected return p.list_handler(["provider", "list"]), p.table end - def get_images provider - img = Image.new(@host, self.def_options) - img.auth = self.auth - return img.list_handler(["image", "list", provider]), img.table - end - - def get_flavors provider - f = Flavor.new(@host, self.def_options) - f.auth = self.auth - return f.list_handler(["flavor", "list", provider]), f.table - end - - def get_groups provider, vpcId - g = Group.new(@host, self.def_options) - g.auth = self.auth - p = ["group", "list", provider] - p.push vpcId if !vpcId.nil? and provider == "ec2" - return g.list_handler(p), g.table - end - - def get_networks provider - n = Network.new(@host, self.def_options) - n.auth = self.auth - return n.list_handler(["network", "list", provider]), n.table - end - - def get_users - u = User.new(@host, self.def_options) - u.auth = self.auth - return u.list_handler, u.table - end - def create_project args, env_method_name, type=nil project_name = args[2] providers = {} + providers[:obj], providers[:table] = get_providers begin project = get_project_info_obj(project_name) puts_warn I18n.t("handler.project.exist", :project => project_name) @@ -351,12 +321,17 @@ protected set_identifier(d, names) set_provider(d, providers) - buf = providers[d[:provider]] - set_flavor(d, buf) - set_image(d, buf) - vpc_id = set_subnets(d, buf) - set_groups(d, buf, vpc_id) + de = DeployEnvFactory.create(d[:provider], @host, self.options, self.auth) + de.fill d + +=begin + unless d[:provider] == "static" + set_flavor(d, buf) + set_image(d, buf) + vpc_id = set_subnets(d, buf) + set_groups(d, buf, vpc_id) + end set_users(d, buf) unless self.options[:run_list].nil? @@ -373,6 +348,7 @@ protected s.empty? ? nil : s end end +=end d end @@ -391,7 +367,7 @@ protected unless self.options[:run_list].nil? self.options[:run_list] = self.options[:run_list].split(",").map{|e| e.strip} - abort("Invalid run list: '#{self.options[:run_list].join(",")}'") unless Project.validate_run_list(self.options[:run_list]) + abort("Invalid run list: '#{self.options[:run_list].join(",")}'") unless DeployEnv.validate_run_list(self.options[:run_list]) end set_parameter d, :run_list do set_run_list_cmd project, d[:identifier] @@ -424,114 +400,11 @@ protected end def set_provider d, providers - if providers[:obj].nil? - providers[:obj], providers[:table] = get_providers - providers[:obj].each{|p| providers[p] = {}} - end - set_parameter d, :provider do providers[:obj][ choose_number_from_list(I18n.t("headers.provider"), providers[:obj], providers[:table]) ] end end - def set_flavor d, buf - flavors, tf = nil, nil - if buf[:flavors].nil? - flavors, tf = get_flavors(d[:provider]) - add_object buf, :flavors, flavors, tf - else - flavors, tf = buf[:flavors][:obj], buf[:flavors][:table] - end - unless self.options[:flavor].nil? - f = 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(flavors, tf)["id"] - end - end - - def set_image d, buf - images, ti = nil, nil - if buf[:images].nil? - images, ti = get_images(d[:provider]) - add_object buf, :images, images, ti - else - images, ti = buf[:images][:obj], buf[:images][:table] - end - set_parameter d, :image do - choose_image_cmd(images, ti)["id"] - end - end - - def set_subnets d, buf - networks, tn = nil, nil - if buf[:networks].nil? - networks, tn = get_networks(d[:provider]) - add_object buf, :networks, networks, tn - else - networks, tn = buf[:networks][:obj], buf[:networks][:table] - end - unless self.options[:subnets].nil? - if "ec2" == d[:provider] - self.options[:subnets] = [ self.options[:subnets][0] ] - end - end - vpc_id = nil - set_parameter d, :subnets do - if "ec2" == d[:provider] - if networks.any? - num = choose_number_from_list(I18n.t("handler.project.create.subnet.ec2"), networks, tn, -1) - vpc_id = networks[num]["vpcId"] unless num == -1 - num == -1 ? [] : [ networks[num]["subnetId"] ] - else - [] - end - else - s = [] - begin - s = choose_indexes_from_list(I18n.t("handler.project.create.subnet.openstack"), networks, tn).map{|i| networks[i]["name"]} - end while s.empty? - s - end - end - return vpc_id - end - - def set_groups d, buf, vpc_id - groups, tg = nil, nil - if buf[:groups].nil? - groups, tg = get_groups(d[:provider], vpc_id) - add_object buf, :groups, groups, tg - else - groups, tg = buf[:groups][:obj], buf[:groups][:table] - end - set_parameter d, :groups do - list = groups.keys - choose_indexes_from_list(I18n.t("options.project.create.groups"), list, tg, "default", list.index("default")).map{|i| list[i]} - end - end - - def set_users d, buf - users, tu = nil, nil - if buf[:users].nil? - users, tu = get_users - add_object buf, :users, users, tu - else - users, tu = buf[:users][:obj], buf[:users][:table] - 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, tu).map{|i| list[i]} - end - d[:users].add(self.options[:username]) - d[:users] = d[:users].to_a - end - - def add_object tec, key, obj, table - tec[key] = {:obj => obj, :table => table} - end - def set_parameter obj, key if self.options[key].nil? obj[key] = yield @@ -540,12 +413,6 @@ protected end 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 - # returns project id def choose_project projects, table=nil abort(I18n.t("handler.project.list.empty")) if projects.empty? @@ -558,21 +425,4 @@ protected project_envs[ choose_number_from_list(I18n.t("headers.project_env"), project_envs, table) ] end - def set_run_list_cmd project, env - res = nil - begin - res = get_comma_separated_list(I18n.t("options.project.create.run_list") + ": ") - end until Project.validate_run_list(res) - res - end - - def self.validate_run_list run_list - return true if run_list.empty? - rl = /\Arole|recipe\[[\w-]+(::[\w-]+)?\]\Z/ - e = run_list.select {|l| (rl =~ l).nil?} - res = e.empty? - puts I18n.t("handler.project.create.run_list.invalid", :list => e.join(", ")) unless res - res - end - end diff --git a/devops-client/lib/devops-client/version.rb b/devops-client/lib/devops-client/version.rb index ab0ef1e..3a8fde7 100644 --- a/devops-client/lib/devops-client/version.rb +++ b/devops-client/lib/devops-client/version.rb @@ -1,3 +1,3 @@ module DevopsClient - VERSION = "2.1.30" + VERSION = "2.1.31" end