Class: Do::CLI

Inherits:
Thor
  • Object
show all
Defined in:
lib/do/cli.rb

Overview

Thor-based CLI. Every command follows the Unix-friendly style:

do run backup
do list
do status backup

Configuration is loaded lazily per command so that short commands like do version don't need a valid config file.

Constant Summary collapse

BUILTINS =

Commands that are taken literally rather than treated as task names by the shorthand do <task> form.

%w[
  run list status logs enable disable remove validate reload
  schedule unschedule doctor version help config
].freeze

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.dispatch(meth, given_args, given_opts, config) ⇒ Object



76
77
78
79
80
81
# File 'lib/do/cli.rb', line 76

def dispatch(meth, given_args, given_opts, config)
  super
rescue Do::Error => e
  warn "Error: #{e.message}"
  exit 1
end

.exit_on_failure?Boolean

Returns:

  • (Boolean)


59
60
61
# File 'lib/do/cli.rb', line 59

def self.exit_on_failure?
  true
end

.is_thor_reserved_word?(_word, _type) ⇒ Boolean

run is a Thor reserved word; we want it as a real command.

Returns:

  • (Boolean)


64
65
66
# File 'lib/do/cli.rb', line 64

def self.is_thor_reserved_word?(_word, _type)
  false
end

Instance Method Details

#disable(task = nil) ⇒ Object



128
129
130
# File 'lib/do/cli.rb', line 128

def disable(task = nil)
  change_enabled(task, false)
end

#doctorObject



194
195
196
# File 'lib/do/cli.rb', line 194

def doctor
  run_doctor
end

#enable(task = nil) ⇒ Object



123
124
125
# File 'lib/do/cli.rb', line 123

def enable(task = nil)
  change_enabled(task, true)
end

#listObject



94
95
96
97
98
99
100
101
# File 'lib/do/cli.rb', line 94

def list
  config = load_config!(validate: false)
  say header = 'TASK        STATUS     SCHEDULE            NEXT'
  say '-' * header.length
  config.tasks.each do |task|
    say format_list_row(task, systemd)
  end
end

#logs(task = nil) ⇒ Object

Raises:



112
113
114
115
116
117
118
119
120
# File 'lib/do/cli.rb', line 112

def logs(task = nil)
  task = require_task!(task)
  units = units_for(task)
  raise Do::Error, "task '#{task.name}' has no generated service unit." if units[:service].nil?

  say "Journal for #{units[:service]} (#{task.name}):" if $stdout.tty?
  ok = systemd.logs(units[:service], follow: options[:follow], tail: options[:tail])
  exit(1) unless ok
end

#reloadObject



166
167
168
169
170
# File 'lib/do/cli.rb', line 166

def reload
  config = load_config!(validate: true)
  Manager.new(systemd: systemd, config: config).reload
  say "Reloaded units for #{config.tasks.size} task(s)."
end

#remove(task = nil) ⇒ Object



135
136
137
138
139
140
141
142
143
144
145
146
147
148
# File 'lib/do/cli.rb', line 135

def remove(task = nil)
  config = load_config!(validate: false)
  task = require_task!(task, config)
  manager = Manager.new(systemd: systemd, config: config)

  confirm!("Remove generated units for task '#{task.name}'?") unless options[:yes]
  manager.remove_units_for(task)
  if options[:'keep-config']
    say "Removed generated units for '#{task.name}' (kept configuration)."
  else
    config.remove_task(task.name)
    say "Removed task '#{task.name}' from configuration and removed its units."
  end
end

#run(task = nil) ⇒ Object



85
86
87
88
89
90
91
# File 'lib/do/cli.rb', line 85

def run(task = nil)
  task = require_task!(task)
  say "> do run #{task.name}: #{task.command}"
  code = Executor.new.run(task)
  say "  finished (exit #{code})"
  exit(code) if code != 0
end

#schedule(task = nil) ⇒ Object



173
174
175
176
177
178
179
180
181
182
183
# File 'lib/do/cli.rb', line 173

def schedule(task = nil)
  config = load_config!(validate: true)
  task = require_task!(task, config)
  unless task.scheduled?
    raise Do::Error,
          "task '#{task.name}' has no schedule in the configuration."
  end

  Manager.new(systemd: systemd, config: config).reload
  say "Scheduled task '#{task.name}' (#{task.schedule})."
end

#status(task = nil) ⇒ Object



104
105
106
107
# File 'lib/do/cli.rb', line 104

def status(task = nil)
  task = require_task!(task)
  show_task_status(task)
end

#unschedule(task = nil) ⇒ Object



186
187
188
189
190
191
# File 'lib/do/cli.rb', line 186

def unschedule(task = nil)
  config = load_config!(validate: false)
  task = require_task!(task, config)
  Manager.new(systemd: systemd, config: config).unschedule(task)
  say "Unscheduled task '#{task.name}'."
end

#validateObject

Raises:



151
152
153
154
155
156
157
158
159
160
161
162
163
# File 'lib/do/cli.rb', line 151

def validate
  path = config_path
  raise Do::Error, "Configuration file does not exist: #{path}" unless File.exist?(path)

  config = Config.load(path)
  errors = Validator.validate(config)
  if errors.empty?
    say "OK: configuration is valid (#{config.tasks.size} task(s))."
  else
    errors.each { |e| say "Error: #{e}", :red }
    exit(1)
  end
end

#versionObject



202
203
204
# File 'lib/do/cli.rb', line 202

def version
  say Do::VERSION
end