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 app_name [more names…] [options]

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.
-h, --health [STATUS]    Set or get the healthcheck status.
                         (enable, disable, remove)
-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.
-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.



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

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.



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

def app_list
  @app_list
end

#shellObject

Returns the value of attribute shell.



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

def shell
  @shell
end

Class Method Details

.build_response(success, data = nil) ⇒ Object

Builds a standard response entry:

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


262
263
264
# File 'lib/commands/list.rb', line 262

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.



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

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.



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
75
# File 'lib/commands/list.rb', line 49

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

  responses = {}
  success   = true

  shells.each do |shell|
    shell.connect

    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

    shell.disconnect
  end

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

.json_format(res_hash) ⇒ Object

Formats response as json:



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

def self.json_format res_hash
  res_hash.to_json
end

.load_list(server) ⇒ Object

Load the app list yaml file from the server.



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

def self.load_list server
  list = YAML.load(server.call(Sunshine::READ_LIST_CMD))
  list = {} unless Hash === list
  list
end

.parse_args(argv) ⇒ Object

Parses the argv passed to the command



289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
# File 'lib/commands/list.rb', line 289

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

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

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


    vals = [:enable, :disable, :remove]
    desc = "Set or get the healthcheck status. (#{vals.join(", ")})"

    opt.on('-h', '--health [STATUS]', vals, desc) do |status|
      options['health'] = status.to_sym if status
      options['return'] = :health
    end
  end
end

.save_list(list, server) ⇒ Object

Write the app list hash to the remote server.



280
281
282
283
# File 'lib/commands/list.rb', line 280

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


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

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:



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

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).



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

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"} ...}


217
218
219
220
221
222
223
224
225
226
227
228
229
# File 'lib/commands/list.rb', line 217

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)


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

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

#health(*app_names) ⇒ Object

Get or set the healthcheck state. Returns a response hash (see ListCommand#each_app).



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

def health(*app_names)
  action = app_names.delete_at(0) if Symbol === app_names.first

  each_app(*app_names) do |server_app|
    server_app.health.send action if action
    server_app.health.status
  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.



236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
# File 'lib/commands/list.rb', line 236

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).



177
178
179
180
181
# File 'lib/commands/list.rb', line 177

def status(*app_names)
  each_app(*app_names) do |server_app|
    server_app.status
  end
end

#status_after_command(cmd, app_names) ⇒ Object

Runs a command and returns the status for each app_name:

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


188
189
190
191
192
193
194
195
196
197
198
199
200
201
# File 'lib/commands/list.rb', line 188

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

    yield(server_app) if block_given?

    begin
      server_app.send cmd.to_sym
      server_app.running? ? 'running' : 'down'

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