Class: WavefrontCliController

Inherits:
Object
  • Object
show all
Includes:
WavefrontCli::Constants
Defined in:
lib/wavefront-cli/controller.rb

Overview

Dynamically generate a CLI interface from files which describe each subcomand.

Constant Summary

Constants included from WavefrontCli::Constants

WavefrontCli::Constants::ALL_PAGE_SIZE, WavefrontCli::Constants::DEFAULT_CONFIG, WavefrontCli::Constants::DEFAULT_OPTS, WavefrontCli::Constants::HUMAN_TIME_FORMAT, WavefrontCli::Constants::HUMAN_TIME_FORMAT_MS

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(args) ⇒ WavefrontCliController

Returns a new instance of WavefrontCliController.



31
32
33
34
35
36
37
38
39
40
# File 'lib/wavefront-cli/controller.rb', line 31

def initialize(args)
  @args = args
  @cmds = load_commands
  @usage = docopt_hash
  cmd, opts = parse_args
  @opts = parse_opts(opts)
  pp @opts if @opts[:debug]
  cli_class_obj = load_cli_class(cmd, @opts)
  run_command(cli_class_obj)
end

Instance Attribute Details

#argsObject (readonly)

Returns the value of attribute args.



27
28
29
# File 'lib/wavefront-cli/controller.rb', line 27

def args
  @args
end

#cmdsObject (readonly)

Returns the value of attribute cmds.



27
28
29
# File 'lib/wavefront-cli/controller.rb', line 27

def cmds
  @cmds
end

#optsObject (readonly)

Returns the value of attribute opts.



27
28
29
# File 'lib/wavefront-cli/controller.rb', line 27

def opts
  @opts
end

#twObject (readonly)

Returns the value of attribute tw.



27
28
29
# File 'lib/wavefront-cli/controller.rb', line 27

def tw
  @tw
end

#usageObject (readonly)

Returns the value of attribute usage.



27
28
29
# File 'lib/wavefront-cli/controller.rb', line 27

def usage
  @usage
end

Instance Method Details

#default_helpString

What you see when you do ‘wf –help’

Returns:



45
46
47
48
49
50
51
# File 'lib/wavefront-cli/controller.rb', line 45

def default_help
  s = "Wavefront CLI\n\nUsage:\n  #{CMD} command [options]\n" \
      "  #{CMD} --version\n  #{CMD} --help\n\nCommands:\n"

  cmds.sort.each { |k, v| s.<< format("  %-18s %s\n", k, v.description) }
  s.<< "\nUse '#{CMD} <command> --help' for further information.\n"
end

#docopt_hashHash

Returns command descriptions for docopt.

Returns:

  • (Hash)

    command descriptions for docopt.



55
56
57
58
59
# File 'lib/wavefront-cli/controller.rb', line 55

def docopt_hash
  cmds.each_with_object(default: default_help) do |(k, v), ret|
    ret[k.to_sym] = v.docopt
  end
end

#handle_missing_credentials(error) ⇒ Object



153
154
155
156
157
158
159
160
161
162
163
# File 'lib/wavefront-cli/controller.rb', line 153

def handle_missing_credentials(error)
  if DEFAULT_CONFIG.exist? && DEFAULT_CONFIG.file?
    abort "Credential error. #{error.message}"
  else
    puts 'No credentials supplied on the command line or via ' \
         'environment variables, and no configuration file found. ' \
         "Please run 'wf config setup' to create configuration."
      .fold(TW, 0)
    exit 1
  end
end

#import_command(path) ⇒ Object

Load a command description from a file. Each is in its own class

return [Class] new class object defining command.

Parameters:

  • f (Pathname)

    path of file to load



181
182
183
184
185
186
# File 'lib/wavefront-cli/controller.rb', line 181

def import_command(path)
  return if path.extname != '.rb' || path.basename.to_s == 'base.rb'
  k_name = path.basename.to_s[0..-4]
  require(CMD_DIR + k_name)
  Object.const_get("WavefrontCommand#{k_name.capitalize}").new
end

#load_cli_class(cmd, opts) ⇒ Object

Get the CLI class we need to run the command we’ve been given.

rubocop:disable Metrics/AbcSize

Parameters:

Returns:

  • WavefrontCli::cmd



92
93
94
95
96
97
98
99
100
101
# File 'lib/wavefront-cli/controller.rb', line 92

def load_cli_class(cmd, opts)
  require_relative File.join('.', cmds[cmd].sdk_file)
  Object.const_get('WavefrontCli').const_get(cmds[cmd].sdk_class).new(opts)
rescue WavefrontCli::Exception::UnhandledCommand
  abort 'Fatal error. Unsupported command. Please open a Github issue.'
rescue WavefrontCli::Exception::InvalidInput => e
  abort "Invalid input. #{e.message}"
rescue RuntimeError => e
  abort "Unable to run command. #{e.message}."
end

#load_commandsHash

Each command is defined in its own file. Dynamically load all those commands.

Returns:

  • (Hash)

    :command => CommandClass



169
170
171
172
173
174
# File 'lib/wavefront-cli/controller.rb', line 169

def load_commands
  CMD_DIR.children.each_with_object({}) do |f, ret|
    k = import_command(f)
    ret[k.word.to_sym] = k if k
  end
end

#parse_argsObject

Parse the input. The first Docopt.docopt handles the default options, the second works on the command.

rubocop:disable Metrics/AbcSize



65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/wavefront-cli/controller.rb', line 65

def parse_args
  Docopt.docopt(usage[:default], version: WF_CLI_VERSION, argv: args)
rescue Docopt::Exit => e
  cmd = args.empty? ? nil : args.first.to_sym

  abort e.message unless usage.key?(cmd)

  begin
    [cmd, sanitize_keys(Docopt.docopt(usage[cmd], argv: args))]
  rescue Docopt::DocoptLanguageError => e
    abort "Mangled command description:\n#{e.message}"
  rescue Docopt::Exit => e
    abort e.message
  end
end

#parse_opts(options) ⇒ Object

rubocop:enable Metrics/AbcSize



82
83
84
# File 'lib/wavefront-cli/controller.rb', line 82

def parse_opts(options)
  WavefrontCli::OptHandler.new(options).opts
end

#run_command(cli_class_obj) ⇒ Object

rubocop:disable Metrics/AbcSize rubocop:disable Metrics/MethodLength



106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
# File 'lib/wavefront-cli/controller.rb', line 106

def run_command(cli_class_obj)
  cli_class_obj.validate_opts
  cli_class_obj.run
rescue Interrupt
  abort "\nOperation aborted at user request."
rescue WavefrontCli::Exception::ConfigFileNotFound => e
  abort "Configuration file #{e}' not found."
rescue WavefrontCli::Exception::CredentialError => e
  handle_missing_credentials(e)
rescue WavefrontCli::Exception::MandatoryValue
  abort 'A value must be supplied.'
rescue WavefrontCli::Exception::InvalidValue => e
  abort "Invalid value for #{e}."
rescue WavefrontCli::Exception::ProfileExists => e
  abort "Profile '#{e}' already exists."
rescue WavefrontCli::Exception::ProfileNotFound => e
  abort "Profile '#{e}' not found."
rescue WavefrontCli::Exception::FileNotFound
  abort 'File not found.'
rescue WavefrontCli::Exception::InsufficientData => e
  abort "Insufficient data. #{e.message}"
rescue WavefrontCli::Exception::SystemError => e
  abort "Host system error. #{e.message}"
rescue WavefrontCli::Exception::UnparseableInput => e
  abort "Cannot parse input. #{e.message}"
rescue WavefrontCli::Exception::UnsupportedFileFormat
  abort 'Unsupported file format.'
rescue WavefrontCli::Exception::UnsupportedOperation => e
  abort "Unsupported operation.\n#{e.message}"
rescue WavefrontCli::Exception::UnsupportedOutput => e
  abort e.message
rescue WavefrontCli::Exception::UnsupportedNoop
  abort 'Multiple API call operations cannot be performed as no-ops.'
rescue WavefrontCli::Exception::UserGroupNotFound => e
  abort "Cannot find user group '#{e.message}'."
rescue Wavefront::Exception::UnsupportedWriter => e
  abort "Unsupported writer '#{e.message}'."
rescue StandardError => e
  warn "general error: #{e}"
  warn "Backtrace:\n\t#{e.backtrace.join("\n\t")}"
  abort
end

#sanitize_keys(options) ⇒ Object

Symbolize, and remove dashes from option keys

return [Hash] h with modified keys

Parameters:

  • h (Hash)

    options hash



193
194
195
196
197
# File 'lib/wavefront-cli/controller.rb', line 193

def sanitize_keys(options)
  options.each_with_object({}) do |(k, v), r|
    r[k.to_s.delete('-').to_sym] = v
  end
end