gce_command.rb 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. require 'thor'
  2. require 'securerandom'
  3. require 'fileutils'
  4. require_relative 'gce_helper'
  5. require_relative 'launch_helper'
  6. require_relative 'ansible_helper'
  7. module OpenShift
  8. module Ops
  9. class GceCommand < Thor
  10. # WARNING: we do not currently support environments with hyphens in the name
  11. SUPPORTED_ENVS = %w(prod stg int tint kint test jint)
  12. option :type, :required => true, :enum => LaunchHelper.get_gce_host_types,
  13. :desc => 'The host type of the new instances.'
  14. option :env, :required => true, :aliases => '-e', :enum => SUPPORTED_ENVS,
  15. :desc => 'The environment of the new instances.'
  16. option :count, :default => 1, :aliases => '-c', :type => :numeric,
  17. :desc => 'The number of instances to create'
  18. option :tag, :type => :array,
  19. :desc => 'The tag(s) to add to the new instances. Allowed characters are letters, numbers, and hyphens.'
  20. desc "launch", "Launches instances."
  21. def launch()
  22. # Expand all of the instance names so that we have a complete array
  23. names = []
  24. options[:count].times { names << "#{options[:env]}-#{options[:type]}-#{SecureRandom.hex(5)}" }
  25. ah = AnsibleHelper.for_gce()
  26. # GCE specific configs
  27. ah.extra_vars['oo_new_inst_names'] = names
  28. ah.extra_vars['oo_new_inst_tags'] = options[:tag]
  29. ah.extra_vars['oo_env'] = options[:env]
  30. # Add a created by tag
  31. ah.extra_vars['oo_new_inst_tags'] = [] if ah.extra_vars['oo_new_inst_tags'].nil?
  32. ah.extra_vars['oo_new_inst_tags'] << "created-by-#{ENV['USER']}"
  33. ah.extra_vars['oo_new_inst_tags'] << GceHelper.generate_env_tag(options[:env])
  34. ah.extra_vars['oo_new_inst_tags'] << GceHelper.generate_host_type_tag(options[:type])
  35. ah.extra_vars['oo_new_inst_tags'] << GceHelper.generate_env_host_type_tag(options[:env], options[:type])
  36. puts
  37. puts 'Creating instance(s) in GCE...'
  38. ah.ignore_bug_6407
  39. ah.run_playbook("playbooks/gce/#{options[:type]}/launch.yml")
  40. end
  41. option :name, :required => false, :type => :string,
  42. :desc => 'The name of the instance to configure.'
  43. option :env, :required => false, :aliases => '-e', :enum => SUPPORTED_ENVS,
  44. :desc => 'The environment of the new instances.'
  45. option :type, :required => false, :enum => LaunchHelper.get_gce_host_types,
  46. :desc => 'The type of the instances to configure.'
  47. desc "config", 'Configures instances.'
  48. def config()
  49. ah = AnsibleHelper.for_gce()
  50. abort 'Error: you can\'t specify both --name and --type' unless options[:type].nil? || options[:name].nil?
  51. abort 'Error: you can\'t specify both --name and --env' unless options[:env].nil? || options[:name].nil?
  52. host_type = nil
  53. if options[:name]
  54. details = GceHelper.get_host_details(options[:name])
  55. ah.extra_vars['oo_host_group_exp'] = options[:name]
  56. ah.extra_vars['oo_env'] = details['env']
  57. host_type = details['host-type']
  58. elsif options[:type] && options[:env]
  59. oo_env_host_type_tag = GceHelper.generate_env_host_type_tag_name(options[:env], options[:type])
  60. ah.extra_vars['oo_host_group_exp'] = "groups['#{oo_env_host_type_tag}']"
  61. ah.extra_vars['oo_env'] = options[:env]
  62. host_type = options[:type]
  63. else
  64. abort 'Error: you need to specify either --name or (--type and --env)'
  65. end
  66. puts
  67. puts "Configuring #{options[:type]} instance(s) in GCE..."
  68. ah.ignore_bug_6407
  69. ah.run_playbook("playbooks/gce/#{host_type}/config.yml")
  70. end
  71. option :name, :required => false, :type => :string,
  72. :desc => 'The name of the instance to terminate.'
  73. option :env, :required => false, :aliases => '-e', :enum => SUPPORTED_ENVS,
  74. :desc => 'The environment of the new instances.'
  75. option :type, :required => false, :enum => LaunchHelper.get_gce_host_types,
  76. :desc => 'The type of the instances to configure.'
  77. option :confirm, :required => false, :type => :boolean,
  78. :desc => 'Terminate without interactive confirmation'
  79. desc "terminate", 'Terminate instances'
  80. def terminate()
  81. ah = AnsibleHelper.for_gce()
  82. abort 'Error: you can\'t specify both --name and --type' unless options[:type].nil? || options[:name].nil?
  83. abort 'Error: you can\'t specify both --name and --env' unless options[:env].nil? || options[:name].nil?
  84. host_type = nil
  85. if options[:name]
  86. details = GceHelper.get_host_details(options[:name])
  87. ah.extra_vars['oo_host_group_exp'] = options[:name]
  88. ah.extra_vars['oo_env'] = details['env']
  89. host_type = details['host-type']
  90. elsif options[:type] && options[:env]
  91. oo_env_host_type_tag = GceHelper.generate_env_host_type_tag_name(options[:env], options[:type])
  92. ah.extra_vars['oo_host_group_exp'] = "groups['#{oo_env_host_type_tag}']"
  93. ah.extra_vars['oo_env'] = options[:env]
  94. host_type = options[:type]
  95. else
  96. abort 'Error: you need to specify either --name or (--type and --env)'
  97. end
  98. puts
  99. puts "Terminating #{options[:type]} instance(s) in GCE..."
  100. ah.ignore_bug_6407
  101. ah.run_playbook("playbooks/gce/#{host_type}/terminate.yml")
  102. end
  103. desc "list", "Lists instances."
  104. def list()
  105. hosts = GceHelper.list_hosts()
  106. data = {}
  107. hosts.each do |key,value|
  108. value.each { |h| (data[h] ||= []) << key }
  109. end
  110. puts
  111. puts "Instances"
  112. puts "---------"
  113. data.keys.sort.each { |k| puts " #{k}" }
  114. puts
  115. end
  116. option :file, :required => true, :type => :string,
  117. :desc => 'The name of the file to copy.'
  118. option :dest, :required => false, :type => :string,
  119. :desc => 'A relative path where files are written to.'
  120. desc "scp_from", "scp files from an instance"
  121. def scp_from(*ssh_ops, host)
  122. if host =~ /^([\w\d_.-]+)@([\w\d-_.]+)$/
  123. user = $1
  124. host = $2
  125. end
  126. path_to_file = options['file']
  127. dest = options['dest']
  128. details = GceHelper.get_host_details(host)
  129. abort "\nError: Instance [#{host}] is not RUNNING\n\n" unless details['gce_status'] == 'RUNNING'
  130. cmd = "scp #{ssh_ops.join(' ')}"
  131. if user.nil?
  132. cmd += " "
  133. else
  134. cmd += " #{user}@"
  135. end
  136. if dest.nil?
  137. download = File.join(Dir.pwd, 'download')
  138. FileUtils.mkdir_p(download) unless File.exists?(download)
  139. cmd += "#{details['gce_public_ip']}:#{path_to_file} download/"
  140. else
  141. cmd += "#{details['gce_public_ip']}:#{path_to_file} #{File.expand_path(dest)}"
  142. end
  143. exec(cmd)
  144. end
  145. desc "ssh", "Ssh to an instance"
  146. def ssh(*ssh_ops, host)
  147. puts host
  148. if host =~ /^([\w\d_.-]+)@([\w\d-_.]+)/
  149. user = $1
  150. host = $2
  151. end
  152. puts "user=#{user}"
  153. puts "host=#{host}"
  154. details = GceHelper.get_host_details(host)
  155. abort "\nError: Instance [#{host}] is not RUNNING\n\n" unless details['gce_status'] == 'RUNNING'
  156. cmd = "ssh #{ssh_ops.join(' ')}"
  157. if user.nil?
  158. cmd += " "
  159. else
  160. cmd += " #{user}@"
  161. end
  162. cmd += "#{details['gce_public_ip']}"
  163. exec(cmd)
  164. end
  165. option :name, :required => true, :aliases => '-n', :type => :string,
  166. :desc => 'The name of the instance.'
  167. desc 'details', 'Displays details about an instance.'
  168. def details()
  169. name = options[:name]
  170. details = GceHelper.get_host_details(name)
  171. key_size = details.keys.max_by { |k| k.size }.size
  172. header = "Details for #{name}"
  173. puts
  174. puts header
  175. header.size.times { print '-' }
  176. puts
  177. details.each { |k,v| printf("%#{key_size + 2}s: %s\n", k, v) }
  178. puts
  179. end
  180. desc 'types', 'Displays instance types'
  181. def types()
  182. puts
  183. puts "Available Host Types"
  184. puts "--------------------"
  185. LaunchHelper.get_gce_host_types.each { |t| puts " #{t}" }
  186. puts
  187. end
  188. end
  189. end
  190. end