Class: Cli

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

Direct Known Subclasses

Multissh

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeCli

Returns a new instance of Cli.



6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
# File 'lib/cli.rb', line 6

def initialize

  @options = {}
  opt_parse = OptionParser.new do |opt|
    opt.banner = 'Usage: multissh.rb --nodes "server1,server2" --command "echo \'hello\'"'
    opt.on('--nodes "NODES"', 'REQUIRED: "server1,server2,server3" OR "@nodes.txt"') { |o| @options[:nodes] = o }
    opt.on('--command "COMMAND"', 'REQUIRED: "echo \'hello\'" OR @command.txt') { |o| @options[:command] = o }
    opt.on('--username "USERNAME"', 'OPTIONAL: current user by default') { |o| @options[:username] = o }
    opt.on('--password "PASSWORD"', 'OPTIONAL: will prompt if needed') { |o| @options[:password] = o }
    opt.on('--pkey_password "PASSWORD"', 'OPTIONAL: will prompt if needed') { |o| @options[:pkey_password] = o }
    opt.on('--disable_sudo', 'OPTIONAL: disable_sudo requirement and run as current user') { @options[:disable_sudo] = true }
    opt.on('--block', 'OPTIONAL: block mode for command ouptut') { @options[:block] = true }
    opt.on('--match_width', 'OPTIONAL: matches hostname width for easier comparison of results') { @options[:match_width] = true }
    opt.on('--regenerate_config', 'OPTIONAL: regenerate configuration file') { @options[:regenerate_config] = true }
    opt.on('--debug', 'OPTIONAL: debug mode') { @options[:debug] = true }
  end
  opt_parse.parse!

  begin
    valid_options_set = false
    valid_options_set = true if @options[:nodes] && @options[:command]
    valid_options_set = true if @options[:regenerate_config]

    raise OptionParser::MissingArgument unless valid_options_set
  rescue
    abort(opt_parse.help)
  end

  @username       = @options[:username]
  @password       = @options[:password]
  @pkey_password  = @options[:pkey_password]

  @debug          = true if @options[:debug]
  @util           = Util.new(@debug)
  @regenerate     = true if @options[:regenerate_config]
  @disable_sudo   = true if @options[:disable_sudo]

  credential      = Credential.new(
                    username      = @username, 
                    password      = @password, 
                    pkey_password = @pkey_password, 
                    regenerate    = @regenerate, 
                    debug         = @debug
                  )
  @username       = credential.username
  @password       = credential.password
  @pkey_password  = if credential.pkey_password == "" then nil else credential.pkey_password end

  abort() if @options[:regenerate_config]

  @nodes          = parse_nodes(@options[:nodes])
  @command        = parse_command(@options[:command])
  @block          = true if @options[:block]

  @header_max_length = @options[:match_width] ? @nodes.max_by(&:length).length : nil

rescue Interrupt
  puts "\nCtrl+C Interrupt\n"
  exit 1

end

Instance Attribute Details

#blockObject

Returns the value of attribute block.



4
5
6
# File 'lib/cli.rb', line 4

def block
  @block
end

#commandObject

Returns the value of attribute command.



4
5
6
# File 'lib/cli.rb', line 4

def command
  @command
end

#credentialObject

Returns the value of attribute credential.



4
5
6
# File 'lib/cli.rb', line 4

def credential
  @credential
end

#debugObject

Returns the value of attribute debug.



4
5
6
# File 'lib/cli.rb', line 4

def debug
  @debug
end

#header_max_lengthObject

Returns the value of attribute header_max_length.



4
5
6
# File 'lib/cli.rb', line 4

def header_max_length
  @header_max_length
end

#key_passwordObject

Returns the value of attribute key_password.



4
5
6
# File 'lib/cli.rb', line 4

def key_password
  @key_password
end

#nodesObject

Returns the value of attribute nodes.



4
5
6
# File 'lib/cli.rb', line 4

def nodes
  @nodes
end

#passwordObject

Returns the value of attribute password.



4
5
6
# File 'lib/cli.rb', line 4

def password
  @password
end

#usernameObject

Returns the value of attribute username.



4
5
6
# File 'lib/cli.rb', line 4

def username
  @username
end

Instance Method Details

#format_command(command, disable_sudo = false) ⇒ Object



133
134
135
136
137
138
139
140
141
142
# File 'lib/cli.rb', line 133

def format_command(command, disable_sudo=false)
  pre_command = ". ~/.bash_profile; "\
                "export PATH=$PATH:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin; "
  unless command[0..3] == 'sudo'
    unless disable_sudo
      command = 'sudo ' + command
    end
  end
  pre_command + command + ' 2>&1'
end

#parse_command(command) ⇒ Object



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
# File 'lib/cli.rb', line 99

def parse_command(command)
  ##
  # If '@' is used, return a command string from a file
  # Otherwise return specified command
  #
  @util.dbg("input command: #{command}")
  if command.start_with?('@')
    command_list = []
    file_path = command[1..-1]
    expanded_file_path = File.expand_path(file_path)
    @util.dbg("command_file: #{expanded_file_path}")
    raise "File not found" unless File.exists?(expanded_file_path)

    command_file = File.open(expanded_file_path).read
    command_file.each_line do |line|
      @util.dbg("raw command: #{line}")
      line.chomp!.strip!
      unless line.start_with?('#') || line.empty?
        @util.dbg("valid command: #{line}")
        command_list << line
      end
    end

    command_list.map! do |command|
      command = format_command(command, @disable_sudo)
    end
    command = command_list.join('; ')
  else
    command = command.chomp
    command = format_command(command, @disable_sudo)
  end#if
end

#parse_nodes(nodes) ⇒ Object



69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/cli.rb', line 69

def parse_nodes(nodes)
  ##
  # If '@' is used, return a list of nodes from a file
  # Otherwise return a list of nodes parsed from comma-separated input from cli
  #
  @util.dbg("input nodes: #{nodes}")
  if nodes.start_with?('@')
    node_list = []
    file_path = nodes[1..-1]
    expanded_file_path = File.expand_path(file_path)
    @util.dbg("nodes_file: #{expanded_file_path}")
    raise "File not found" unless File.exists?(expanded_file_path)

    node_file = File.open(expanded_file_path).read
    node_file.each_line do |line|
      @util.dbg("raw node: #{line}")
      line.chomp!.strip!
      unless line.start_with?('#') || line.empty?
        @util.dbg("valid node: #{line}")
        node_list << line
      end
    end

    return node_list
  else
    return nodes.split(',').map(&:strip)
  end#if
end