Class: Cult::Commander
- Inherits:
-
Object
- Object
- Cult::Commander
- Defined in:
- lib/cult/commander.rb
Instance Attribute Summary collapse
-
#node ⇒ Object
readonly
Returns the value of attribute node.
-
#project ⇒ Object
readonly
Returns the value of attribute project.
Instance Method Summary collapse
- #bootstrap! ⇒ Object
- #connect(user: nil, &block) ⇒ Object
- #create_build_tar(role) ⇒ Object
- #create_sync_tar(pass:, roles: nil) ⇒ Object
- #esc(s) ⇒ Object
- #exec_remote!(ssh:, role:, task:) ⇒ Object
- #find_sync_tasks(pass:, roles: nil) ⇒ Object
-
#initialize(project:, node:) ⇒ Commander
constructor
A new instance of Commander.
- #install!(role) ⇒ Object
- #ping ⇒ Object
- #send_tar(io, ssh) ⇒ Object
- #sync!(pass:, roles: nil) ⇒ Object
Constructor Details
#initialize(project:, node:) ⇒ Commander
Returns a new instance of Commander.
12 13 14 15 |
# File 'lib/cult/commander.rb', line 12 def initialize(project:, node:) @project = project @node = node end |
Instance Attribute Details
#node ⇒ Object (readonly)
Returns the value of attribute node.
10 11 12 |
# File 'lib/cult/commander.rb', line 10 def node @node end |
#project ⇒ Object (readonly)
Returns the value of attribute project.
9 10 11 |
# File 'lib/cult/commander.rb', line 9 def project @project end |
Instance Method Details
#bootstrap! ⇒ Object
128 129 130 131 |
# File 'lib/cult/commander.rb', line 128 def bootstrap! bootstrap_role = CLI.fetch_item('bootstrap', from: Role) install!(bootstrap_role) end |
#connect(user: nil, &block) ⇒ Object
141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 |
# File 'lib/cult/commander.rb', line 141 def connect(user: nil, &block) 5.times do |attempt| begin user ||= node.user puts "Connecting with user=#{user}, host=#{node.host}, " + "key=#{node.ssh_private_key_file}" Net::SSH.start(node.host, user, port: node.ssh_port, user_known_hosts_file: node.ssh_known_hosts_file, timeout: 5, auth_methods: ['publickey'], keys_only: true, keys: [node.ssh_private_key_file]) do |ssh| return (yield ssh) end rescue Errno::ECONNREFUSED, Net::SSH::ConnectionTimeout puts "Connection refused. Retrying" sleep attempt * 3 end end end |
#create_build_tar(role) ⇒ Object
31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
# File 'lib/cult/commander.rb', line 31 def create_build_tar(role) io = StringIO.new Bundle.new(io) do |bundle| puts "Building bundle..." role.build_order.each do |r| (r.artifacts + r.build_tasks).each do |transferable| bundle.add_file(project, r, node, transferable) end end end io.rewind io end |
#create_sync_tar(pass:, roles: nil) ⇒ Object
102 103 104 105 106 107 108 109 110 111 112 |
# File 'lib/cult/commander.rb', line 102 def create_sync_tar(pass:, roles: nil) io = StringIO.new Bundle.new(io) do |bundle| find_sync_tasks(pass: pass, roles: roles).each do |task| bundle.add_file(project, task.role, node, task) end end io.rewind io end |
#esc(s) ⇒ Object
17 18 19 |
# File 'lib/cult/commander.rb', line 17 def esc(s) Shellwords.escape(s) end |
#exec_remote!(ssh:, role:, task:) ⇒ Object
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
# File 'lib/cult/commander.rb', line 47 def exec_remote!(ssh:, role:, task:) token = SecureRandom.hex task_bin = role.relative_path(task.path) puts "Executing: #{task.remote_path} on #{node.name}" res = ssh.exec! <<~BASH cd #{esc(role.remote_path)}; \ ./#{esc(task_bin)} && \ echo #{esc(token)} BASH if res.chomp.end_with?(token) res = res.gsub(token, '') puts Rainbow(res.gsub(/^/, ' ')).darkgray.italic true else puts Rainbow(res).red puts "Failed" false end end |
#find_sync_tasks(pass:, roles: nil) ⇒ Object
85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 |
# File 'lib/cult/commander.rb', line 85 def find_sync_tasks(pass:, roles: nil) selected_roles = node.build_order if roles selected_roles.select! { |r| roles.include?(r) } end r = [] selected_roles.each do |role| r += role.event_tasks.select do |t| t.event == :sync && t.pass == pass end end r end |
#install!(role) ⇒ Object
70 71 72 73 74 75 76 77 78 79 80 81 82 |
# File 'lib/cult/commander.rb', line 70 def install!(role) connect(user: role.user) do |ssh| io = create_build_tar(role) send_tar(io, ssh) role.build_order.each do |r| puts "Installing role: #{Rainbow(r.name).blue}" r.build_tasks.each do |task| exec_remote!(ssh: ssh, role: r, task: task) end end end end |
#ping ⇒ Object
133 134 135 136 137 138 139 |
# File 'lib/cult/commander.rb', line 133 def ping connect do |ssh| ssh.exec!("uptime").chomp end rescue nil end |
#send_tar(io, ssh) ⇒ Object
22 23 24 25 26 27 28 |
# File 'lib/cult/commander.rb', line 22 def send_tar(io, ssh) filename = SecureRandom.hex + ".tar" puts "Uploading bundle: #{filename}" scp = Net::SCP.new(ssh) scp.upload!(io, filename) ssh.exec! "tar -xf #{esc(filename)} && rm #{esc(filename)}" end |
#sync!(pass:, roles: nil) ⇒ Object
115 116 117 118 119 120 121 122 123 124 125 |
# File 'lib/cult/commander.rb', line 115 def sync!(pass:, roles: nil) io = create_sync_tar(pass: pass, roles: roles) return if io.eof? connect do |ssh| send_tar(io, ssh) find_sync_tasks(pass: pass, roles: roles).each do |task| exec_remote!(ssh: ssh, role: task.role, task: task) end end end |