Class: Sunshine::ListCommand

Inherits:
DefaultCommand show all
Defined in:
lib/commands/list.rb

Overview

List and perform simple state actions on lists of sunshine apps.

Usage: sunshine list [options] app_name [more names…]

Arguments:

app_name      Name of an application to list.

Options:

-s, --status             Check if an app is running.
-d, --details            Get details about the deployed apps.
-f, --format FORMAT      Set the output format (txt, yml, json)
-u, --user USER          User to use for remote login. Use with -r
-r, --remote svr1,svr2   Run on one or more remote servers.
-S, --sudo               Run remote commands using sudo or sudo -u USER
-v, --verbose            Run in verbose mode.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from DefaultCommand

copy_middleware, copy_rakefile, opt_parser, parse_remote_args

Constructor Details

#initialize(shell) ⇒ ListCommand

Returns a new instance of ListCommand.



130
131
132
133
# File 'lib/commands/list.rb', line 130

def initialize shell
  @shell    = shell
  @app_list = self.class.load_list @shell
end

Instance Attribute Details

#app_listObject

Returns the value of attribute app_list.



128
129
130
# File 'lib/commands/list.rb', line 128

def app_list
  @app_list
end

#shellObject

Returns the value of attribute shell.



128
129
130
# File 'lib/commands/list.rb', line 128

def shell
  @shell
end

Class Method Details

.build_response(success, data = nil) ⇒ Object

Builds a standard response entry:

{:success => true, :data => "somedata"}


251
252
253
# File 'lib/commands/list.rb', line 251

def self.build_response success, data=nil
  {:success => success, :data => data}
end

.exec(names, config) ⇒ Object

Takes an array and a hash, runs the command and returns:

true: success
false: failed
exitcode:
  code == 0: success
  code != 0: failed

and optionally an accompanying message.



31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/commands/list.rb', line 31

def self.exec names, config
  action = config['return'] || :exist?

  args = config[action.to_s] || []
  args = [args, names].flatten

  output = exec_each_server config do |shell|
    new(shell).send(action, *args)
  end

  return output
end

.exec_each_server(config) ⇒ Object

Executes common list functionality for each deploy server.



48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/commands/list.rb', line 48

def self.exec_each_server config
  shells = config['servers']
  format = config['format']

  responses = {}
  success   = true

  shells.each do |shell|
    shell.with_session do

      begin
        state, response = yield(shell)

      rescue => e
        state = false
        response = "#{e.class}: #{e.message}\n#{e.backtrace.join("\n")}"
      end

      host            = shell.host
      success         = state if success
      responses[host] = build_response state, response
    end
  end

  output = format ? self.send(format, responses) : responses
  return success, output
end

.json_format(res_hash) ⇒ Object

Formats response as json:



122
123
124
# File 'lib/commands/list.rb', line 122

def self.json_format res_hash
  res_hash.to_json
end

.load_list(server) ⇒ Object

Load the app list yaml file from the server.



259
260
261
262
263
264
265
# File 'lib/commands/list.rb', line 259

def self.load_list server
  yml_list = server.call "cat #{Sunshine::APP_LIST_PATH} || echo"

  list = YAML.load yml_list
  list = {} unless Hash === list
  list
end

.parse_args(argv) ⇒ Object

Parses the argv passed to the command



280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
# File 'lib/commands/list.rb', line 280

def self.parse_args argv
  parse_remote_args(argv) do |opt, options|
    opt.banner = <<-EOF

Usage: #{opt.program_name} list [options] app_name [more names...]

Arguments:
app_name      Name of an application to list.
    EOF

    opt.on('-s', '--status',
           'Check if an app is running.') do
      options['return'] = :status
    end

    opt.on('-d', '--details',
           'Get details about the deployed apps.') do
      options['return'] = :details
    end

  end
end

.save_list(list, server) ⇒ Object

Write the app list hash to the remote server.



271
272
273
274
# File 'lib/commands/list.rb', line 271

def self.save_list list, server
  path = server.expand_path Sunshine::APP_LIST_PATH
  server.make_file path, list.to_yaml
end

.txt_format(res_hash) ⇒ Object

Formats response as text output:

------------------
subdomain.host.com
------------------
app_name: running


84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
# File 'lib/commands/list.rb', line 84

def self.txt_format res_hash
  str_out = ""

  res_hash.each do |host, response|
    separator = "-" * host.length

    host_status = if Hash === response[:data]
      apps_status = response[:data].map do |app_name, status|
        "#{app_name}: #{status[:data]}\n"
      end
      apps_status.join("\n")

    else
      response[:data]
    end

    str_out << "\n"
    str_out << [separator, host, separator].join("\n")
    str_out << "\n"
    str_out << host_status
    str_out << "\n"
  end

  str_out
end

.yml_format(res_hash) ⇒ Object

Formats response as yaml:



114
115
116
# File 'lib/commands/list.rb', line 114

def self.yml_format res_hash
  res_hash.to_yaml
end

Instance Method Details

#details(*app_names) ⇒ Object

Reads and returns the specified apps’ info file. Returns a response hash (see ListCommand#each_app).



140
141
142
143
144
# File 'lib/commands/list.rb', line 140

def details(*app_names)
  each_app(*app_names) do |server_app|
    "\n#{server_app.deploy_details.to_yaml}"
  end
end

#each_app(*app_names) ⇒ Object

Do something with each server app and build a response hash:

each_app do |server_app|
  ...
end

Restrict it to a set of apps if they are present on the server:

each_app('app1', 'app2') do |server_app|
  ...
end

Returns a response hash:

{"app_name" => {:success => true, :data => "somedata"} ...}


206
207
208
209
210
211
212
213
214
215
216
217
218
# File 'lib/commands/list.rb', line 206

def each_app(*app_names)
  app_names = @app_list.keys if app_names.empty?

  response_for_each(*app_names) do |name|
    path = @app_list[name]

    raise "Application not found." unless path

    server_app = ServerApp.new name, @shell, :root_path => path

    yield(server_app) if block_given?
  end
end

#exist?(*app_names) ⇒ Boolean

Returns the path of specified apps. Returns a response hash (see ListCommand#each_app).

Returns:

  • (Boolean)


151
152
153
154
155
# File 'lib/commands/list.rb', line 151

def exist?(*app_names)
  each_app(*app_names) do |server_app|
    server_app.root_path
  end
end

#response_for_each(*items) ⇒ Object

Builds a response object for each item passed and returns the result of the passed block as its data value.



225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
# File 'lib/commands/list.rb', line 225

def response_for_each(*items)
  response  = {}
  success   = true

  items.each do |item|

    begin
      data = yield(item) if block_given?

      response[item] = self.class.build_response true, data

    rescue => e
      success = false
      response[item] = self.class.build_response false, e.message
    end

  end

  [success, response]
end

#status(*app_names) ⇒ Object

Checks if the apps’ pids are present. Returns a response hash (see ListCommand#each_app).



162
163
164
165
166
167
168
169
170
# File 'lib/commands/list.rb', line 162

def status(*app_names)
  each_app(*app_names) do |server_app|
    begin
      server_app.status
    rescue => e
      e.message
    end
  end
end

#status_after_command(cmd, app_names, options = nil) ⇒ Object

Runs a command and returns the status for each app_name:

status_after_command 'restart', ['app1', 'app2']


177
178
179
180
181
182
183
184
185
186
187
188
189
190
# File 'lib/commands/list.rb', line 177

def status_after_command cmd, app_names, options=nil
  each_app(*app_names) do |server_app|

    yield(server_app) if block_given?

    begin
      server_app.run_script! cmd, options
      server_app.status.to_s

    rescue CmdError => e
      raise "Failed running #{cmd}: #{server_app.status rescue :not_found}"
    end
  end
end