Class: Superhosting::Cli::Base

Inherits:
Object
  • Object
show all
Includes:
Mixlib::CLI
Defined in:
lib/superhosting/cli/base.rb

Constant Summary collapse

COMMANDS_MODULE =
Cmd
CONTROLLERS_MODULE =
Superhosting::Controller
CONTROLLER_BASE_OPTIONS =
[:config_path, :lib_path, :docker_socket]

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(argv, node) ⇒ Base

Returns a new instance of Base.



35
36
37
38
39
40
41
42
43
44
45
46
47
# File 'lib/superhosting/cli/base.rb', line 35

def initialize(argv, node)
  self.class.options.merge!(Base::options)
  super()

  @pos_args = parse_options(argv)
  @node = node

  @logger = Logger.new(STDOUT)
  @logger.level = config[:debug] ? Logger::DEBUG : Logger::INFO
  @logger.formatter = proc {|severity, datetime, progname, msg| sprintf("%s\n", msg.to_s.strip) }

  self.help if config[:help] or self.class == Base
end

Class Method Details

.get_cmd_and_node(args) ⇒ Object



192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
# File 'lib/superhosting/cli/base.rb', line 192

def get_cmd_and_node(args)
  def positional_arguments(args)
    args.select { |arg| arg =~ /^([[:alnum:]\_\-]+)$/ }
  end

  args = positional_arguments(args)
  node = @@commands_hierarchy
  path = []
  key = ''
  cmd = nil
  while arg = args.shift and cmd.nil?
    res = node.keys.select { |k| k.start_with? arg }

    case res.count
      when 1
        key = res.first
        cmd = node[key] if node[key].is_a? Class
      when 0
        break
      else
        raise Error::AmbiguousCommand.new(path: path, commands: res)
    end

    path << key
    node = node[key]
  end

  cmd ||= self
  node = { key => node }

  [cmd, node]
end

.get_split_class_nameObject



184
185
186
# File 'lib/superhosting/cli/base.rb', line 184

def get_split_class_name
  self.split_toggle_case_name(self.name.split('::').last)
end

.has_required_param?Boolean

Returns:

  • (Boolean)


165
166
167
# File 'lib/superhosting/cli/base.rb', line 165

def has_required_param?
  false
end

.prependObject



148
149
150
151
# File 'lib/superhosting/cli/base.rb', line 148

def prepend
  set_commands_hierarchy
  set_banners
end

.set_banners(node = @@commands_hierarchy, path = []) ⇒ Object



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

def set_banners(node=@@commands_hierarchy, path=[])
  node.each do |k,v|
    path_ = path.dup
    path_ << k
    if v.is_a? Hash
      set_banners(v, path_)
    else
      v.banner("sx #{path_.join(' ')}#{" <#{path.last}>" if v.has_required_param?}#{' (options)' unless v.options.empty?}")
    end
  end
end

.set_commands_hierarchyObject



169
170
171
172
173
174
175
176
177
178
179
180
181
182
# File 'lib/superhosting/cli/base.rb', line 169

def set_commands_hierarchy
  def get_commands
    COMMANDS_MODULE.constants.select {|c| Class === COMMANDS_MODULE.const_get(c) }.sort
  end

  @@commands_hierarchy = get_commands.inject({}) do |h,k|
    node = h
    parts = split_toggle_case_name(k)
    parts.each do |cmd|
      node = (node[cmd] ||= (cmd == parts.last) ? COMMANDS_MODULE.const_get(k) : {})
    end
    h
  end
end

.split_toggle_case_name(klass) ⇒ Object



188
189
190
# File 'lib/superhosting/cli/base.rb', line 188

def split_toggle_case_name(klass)
  klass.to_s.gsub(/([[:lower:]])([[:upper:]])/, '\1 \2').split(' ').map(&:downcase)
end

.start(args) ⇒ Object



136
137
138
139
140
141
142
143
144
145
146
# File 'lib/superhosting/cli/base.rb', line 136

def start(args)
  def clear_args(args, cmd)
    split_toggle_case_name(cmd).length.times{ args.shift }
    args
  end

  prepend
  cmd, node = get_cmd_and_node(args)
  args = clear_args(args, cmd)
  cmd.new(args, node).run
end

Instance Method Details

#actionObject



82
83
84
85
86
87
88
89
90
91
92
93
94
95
# File 'lib/superhosting/cli/base.rb', line 82

def action
  method = get_controller
  opts = {}
  method.parameters.each do |req, name|
    if req.to_s.start_with? 'key'
      opt = config[name]
      self.help unless opt = @pos_args.shift if name == :name
      opts.merge!(name => opt)
    end
  end
  self.help unless @pos_args.empty? # only one position argument

  method.parameters.empty? ? method.call : method.call(**opts)
end

#clear_args(args, cmd) ⇒ Object



137
138
139
140
# File 'lib/superhosting/cli/base.rb', line 137

def clear_args(args, cmd)
  split_toggle_case_name(cmd).length.times{ args.shift }
  args
end

#get_childs_banners(node) ⇒ Object



50
51
52
53
54
55
56
57
58
59
60
61
62
# File 'lib/superhosting/cli/base.rb', line 50

def get_childs_banners(node)
  if node.is_a? Hash
    node.map do |k,v|
      if v.is_a? Hash
        get_childs_banners(node[k])
      else
        v.banner
      end
    end.join("\n")
  else
    node.banner
  end
end

#get_commandsObject



170
171
172
# File 'lib/superhosting/cli/base.rb', line 170

def get_commands
  COMMANDS_MODULE.constants.select {|c| Class === COMMANDS_MODULE.const_get(c) }.sort
end

#get_controllerObject

Raises:



97
98
99
100
101
102
103
104
105
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
# File 'lib/superhosting/cli/base.rb', line 97

def get_controller
  def get_subcontroller_option
    key = :"#{self.class.get_split_class_name.first}_name"
    config[key] unless config[key].nil?
  end

  node = CONTROLLERS_MODULE
  names = self.class.get_split_class_name

  names.each do |n|
    c_name = n.capitalize.to_sym
    m_name = n.to_sym

    if node.respond_to? :constants and node.constants.include? c_name
      node = node.const_get(c_name)
    elsif node.respond_to? :instance_methods and node.instance_methods(false).include? m_name
      params = node.instance_method(:initialize).parameters

      opts = {}
      params.each do |req, name|
        if req.to_s.start_with? 'key'
          if name == :name
            opt = get_subcontroller_option
          elsif config.key? name
            opt = config[name]
          end
          opts.merge!(name => opt) unless opt.nil?
        end
      end

      CONTROLLER_BASE_OPTIONS.each {|opt| opts.merge!(opt => config[opt]) unless config[opt].nil? }
      opts.merge!(logger: @logger)
      return node.new(**opts).method(m_name)
    end
  end
  raise Error::Base.new('Method doesn\'t found')
end

#get_subcontroller_optionObject



98
99
100
101
# File 'lib/superhosting/cli/base.rb', line 98

def get_subcontroller_option
  key = :"#{self.class.get_split_class_name.first}_name"
  config[key] unless config[key].nil?
end

#helpObject



49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/superhosting/cli/base.rb', line 49

def help
  def get_childs_banners(node)
    if node.is_a? Hash
      node.map do |k,v|
        if v.is_a? Hash
          get_childs_banners(node[k])
        else
          v.banner
        end
      end.join("\n")
    else
      node.banner
    end
  end

  @logger.info("#{opt_parser.to_s}\n#{get_childs_banners(@node) if self.class == Base}")

  exit 1
end

#positional_arguments(args) ⇒ Object



193
194
195
# File 'lib/superhosting/cli/base.rb', line 193

def positional_arguments(args)
  args.select { |arg| arg =~ /^([[:alnum:]\_\-]+)$/ }
end

#runObject



69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/superhosting/cli/base.rb', line 69

def run
  begin
    net_status = action
    net_status ||= {}

    raise Error::Controller, net_status unless net_status[:error].nil?
    @logger.info(net_status[:data]) unless net_status[:data].nil?
    @logger.debug('Done!')
  rescue NetStatus::Exception => e
    raise Error::Controller, e.net_status
  end
end