Module: ManageIQ::ApplianceConsole::Prompts

Included in:
DatabaseAdmin, DatabaseReplication, MessageConfiguration
Defined in:
lib/manageiq/appliance_console/prompts.rb

Constant Summary collapse

CLEAR_CODE =
`clear`
IPV4_REGEXP =
Resolv::IPv4::Regex
IPV6_REGEXP =
Resolv::IPv6::Regex
IP_REGEXP =
Regexp.union(Resolv::IPv4::Regex, Resolv::IPv6::Regex).freeze
DOMAIN_REGEXP =
/^[a-z0-9]+([\-\.]{1}[a-z0-9]+)*(\.[a-z]{2,13})?$/
INT_REGEXP =
/^[0-9]+$/
NONE_REGEXP =
/^('?NONE'?)?$/i.freeze
HOSTNAME_REGEXP =
/^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])$/.freeze
MESSAGING_HOSTNAME_REGEXP =
/^(?!.*localhost)(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])$/.freeze
MESSAGING_PASSWORD_REGEXP =
/\A[a-zA-Z0-9_\-\.\$\*]+\z/.freeze

Instance Method Summary collapse

Instance Method Details

#are_you_sure?(clarifier = nil) ⇒ Boolean

Returns:

  • (Boolean)


50
51
52
53
# File 'lib/manageiq/appliance_console/prompts.rb', line 50

def are_you_sure?(clarifier = nil)
  clarifier = " you want to #{clarifier}" if clarifier && !clarifier.include?("want")
  agree("Are you sure#{clarifier}? (Y/N): ")
end

#ask_for_disk(disk_name, verify = true, silent = false) ⇒ Object



161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
# File 'lib/manageiq/appliance_console/prompts.rb', line 161

def ask_for_disk(disk_name, verify = true, silent = false)
  require "linux_admin"
  disks = LinuxAdmin::Disk.local.select { |d| d.partitions.empty? }

  if disks.empty?
    say("No partition found for #{disk_name}. You probably want to add an unpartitioned disk and try again.") unless silent
  else
    default_choice = disks.size == 1 ? "1" : nil
    disk = ask_with_menu(
      disk_name,
      disks.collect { |d| [("#{d.path}: #{d.size.to_i / 1.megabyte} MB"), d] },
      default_choice
    ) do |q|
      q.choice("Don't partition the disk") { nil }
    end
  end
  if verify && disk.nil?
    say("")
    raise MiqSignalError unless are_you_sure?(" you don't want to partition the #{disk_name}")
  end
  disk
end

#ask_for_domain(prompt, default = nil, validate = DOMAIN_REGEXP, error_text = "a valid Domain.", &block) ⇒ Object



64
65
66
# File 'lib/manageiq/appliance_console/prompts.rb', line 64

def ask_for_domain(prompt, default = nil, validate = DOMAIN_REGEXP, error_text = "a valid Domain.", &block)
  just_ask(prompt, default, validate, error_text, &block)
end

#ask_for_hostname(prompt, default = nil, validate = HOSTNAME_REGEXP, error_text = "a valid Hostname.", &block) ⇒ Object



72
73
74
# File 'lib/manageiq/appliance_console/prompts.rb', line 72

def ask_for_hostname(prompt, default = nil, validate = HOSTNAME_REGEXP, error_text = "a valid Hostname.", &block)
  just_ask(prompt, default, validate, error_text, &block)
end

#ask_for_hour_number(prompt) ⇒ Object



96
97
98
# File 'lib/manageiq/appliance_console/prompts.rb', line 96

def ask_for_hour_number(prompt)
  ask_for_integer(prompt, (0..23))
end

#ask_for_integer(prompt, range = nil, default = nil) ⇒ Object



157
158
159
# File 'lib/manageiq/appliance_console/prompts.rb', line 157

def ask_for_integer(prompt, range = nil, default = nil)
  just_ask(prompt, default, INT_REGEXP, "an integer", Integer) { |q| q.in = range if range }
end

#ask_for_ip(prompt, default, validate = IP_REGEXP, error_text = "a valid IP Address.", &block) ⇒ Object



68
69
70
# File 'lib/manageiq/appliance_console/prompts.rb', line 68

def ask_for_ip(prompt, default, validate = IP_REGEXP, error_text = "a valid IP Address.", &block)
  just_ask(prompt, default, validate, error_text, &block)
end

#ask_for_ip_or_hostname(prompt, default = nil) ⇒ Object



81
82
83
84
# File 'lib/manageiq/appliance_console/prompts.rb', line 81

def ask_for_ip_or_hostname(prompt, default = nil)
  validation = ->(h) { (h =~ HOSTNAME_REGEXP || h =~ IP_REGEXP) && h.length > 0 }
  ask_for_ip(prompt, default, validation, "a valid Hostname or IP Address.")
end

#ask_for_ip_or_hostname_or_none(prompt, default = nil) ⇒ Object



86
87
88
89
# File 'lib/manageiq/appliance_console/prompts.rb', line 86

def ask_for_ip_or_hostname_or_none(prompt, default = nil)
  validation = Regexp.union(NONE_REGEXP, HOSTNAME_REGEXP, IP_REGEXP)
  ask_for_ip(prompt, default, validation, "a valid Hostname or IP Address.").gsub(NONE_REGEXP, "")
end

#ask_for_many(prompt, collective = nil, default = nil, max_length = 255, max_count = 6) ⇒ Object



108
109
110
111
112
113
# File 'lib/manageiq/appliance_console/prompts.rb', line 108

def ask_for_many(prompt, collective = nil, default = nil, max_length = 255, max_count = 6)
  collective ||= "#{prompt}s"
  validate = ->(p) { (p.length < max_length) && (p.split(/[\s,;]+/).length <= max_count) }
  error_message = "up to #{max_count} #{prompt}s separated by a space and up to #{max_length} characters"
  just_ask(collective, default, validate, error_message).split(/[\s,;]+/).collect(&:strip)
end

#ask_for_messaging_hostname(prompt, default = nil, error_text = "a valid Messaging Hostname (not an IP or localhost)", &block) ⇒ Object



76
77
78
79
# File 'lib/manageiq/appliance_console/prompts.rb', line 76

def ask_for_messaging_hostname(prompt, default = nil, error_text = "a valid Messaging Hostname (not an IP or localhost)", &block)
  validation = ->(h) { h =~ MESSAGING_HOSTNAME_REGEXP && h !~ IP_REGEXP }
  just_ask(prompt, default, validation, error_text, &block)
end

#ask_for_messaging_password(prompt) ⇒ Object



149
150
151
# File 'lib/manageiq/appliance_console/prompts.rb', line 149

def ask_for_messaging_password(prompt)
  ask_for_new_password(prompt, :validation => MESSAGING_PASSWORD_REGEXP, :validation_err => "allowed characters are a-z, A-Z, 0-9, -, _, ., $, and *")
end

#ask_for_month_day_number(prompt) ⇒ Object



104
105
106
# File 'lib/manageiq/appliance_console/prompts.rb', line 104

def ask_for_month_day_number(prompt)
  ask_for_integer(prompt, (1..31))
end

#ask_for_new_password(prompt, default: nil, allow_empty: false, retry_limit: 1, confirm_password: true, validation: nil, validation_err: nil) ⇒ Object



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/manageiq/appliance_console/prompts.rb', line 123

def ask_for_new_password(prompt, default: nil, allow_empty: false, retry_limit: 1, confirm_password: true, validation: nil, validation_err: nil)
  count = 0
  loop do
    password1 = ask_for_password(prompt, default)
    if password1.strip.empty? && !allow_empty
      say("\nPassword can not be empty, please try again")
      next
    end

    if validation && password1 !~ validation
      say("\nPassword is invalid: #{validation_err}, please try again")
      next
    end

    return password1 if password1 == default || !confirm_password

    password2 = ask_for_password(prompt)
    return password1 if password1 == password2

    raise "passwords did not match" if count >= retry_limit

    count += 1
    say("\nThe passwords did not match, please try again")
  end
end

#ask_for_password(prompt, default = nil) ⇒ Object



115
116
117
118
119
120
121
# File 'lib/manageiq/appliance_console/prompts.rb', line 115

def ask_for_password(prompt, default = nil)
  pass = just_ask(prompt, default.present? ? "********" : nil) do |q|
    q.echo = '*'
    yield q if block_given?
  end
  pass == "********" ? (default || "") : pass
end

#ask_for_schedule_frequency(prompt, default = nil) ⇒ Object



91
92
93
94
# File 'lib/manageiq/appliance_console/prompts.rb', line 91

def ask_for_schedule_frequency(prompt, default = nil)
  validation = ->(h) { %w(hourly daily weekly monthly).include?(h) }
  just_ask(prompt, default, validation, "hourly, daily, weekly or monthly")
end

#ask_for_string(prompt, default = nil) ⇒ Object



153
154
155
# File 'lib/manageiq/appliance_console/prompts.rb', line 153

def ask_for_string(prompt, default = nil)
  just_ask(prompt, default)
end

#ask_for_uri(prompt, expected_scheme, opts = {}) ⇒ Object



20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# File 'lib/manageiq/appliance_console/prompts.rb', line 20

def ask_for_uri(prompt, expected_scheme, opts = {})
  require 'uri'
  just_ask(prompt, nil, nil, 'a valid URI') do |q|
    q.validate = lambda do |a|
      # Convert all backslashes in the URI to forward slashes and strip whitespace
      a.tr!('\\', '/')
      a.strip!
      u = URI(a)
      # validate it has a hostname/ip and a share
      u.scheme == expected_scheme &&
        (u.host =~ HOSTNAME_REGEXP || u.hostname =~ IP_REGEXP) &&
        (opts[:optional_path] || !u.path.empty?)
    end
    yield q if block_given?
  end
end

#ask_for_week_day_number(prompt) ⇒ Object



100
101
102
# File 'lib/manageiq/appliance_console/prompts.rb', line 100

def ask_for_week_day_number(prompt)
  ask_for_integer(prompt, (0..6))
end

#ask_with_menu(prompt, options, default = nil, clear_screen_after = true) ⇒ Object



196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
# File 'lib/manageiq/appliance_console/prompts.rb', line 196

def ask_with_menu(prompt, options, default = nil, clear_screen_after = true)
  say("#{prompt}\n\n")

  default = default_to_index(default, options)
  selection = nil
  choose do |menu|
    menu.default      = default
    menu.index        = :number
    menu.index_suffix = ") "
    menu.prompt       = "\nChoose the #{prompt.downcase}:#{" |#{default}|" if default} "
    options.each { |o, v| menu.choice(o) { |c| selection = v || c } }
    yield menu if block_given?
  end
  clear_screen if clear_screen_after
  selection
end

#ask_yn?(prompt, default = nil) ⇒ Boolean

Returns:

  • (Boolean)


55
56
57
58
59
60
61
62
# File 'lib/manageiq/appliance_console/prompts.rb', line 55

def ask_yn?(prompt, default = nil)
  ask("#{prompt}? (Y/N): ") do |q|
    q.default = default if default
    q.validate = ->(p) { (p.blank? && default) || %w(y n).include?(p.downcase[0]) }
    q.responses[:not_valid] = "Please provide yes or no."
    yield q if block_given?
  end.downcase[0] == 'y'
end

#clear_screenObject



46
47
48
# File 'lib/manageiq/appliance_console/prompts.rb', line 46

def clear_screen
  print CLEAR_CODE
end

#default_to_index(default, options) ⇒ Object

use the integer index for menu prompts ensure default is a string



186
187
188
189
190
191
192
193
194
# File 'lib/manageiq/appliance_console/prompts.rb', line 186

def default_to_index(default, options)
  return unless default
  default_index = if options.kind_of?(Hash)
                    options.values.index(default) || options.keys.index(default)
                  else
                    options.index(default)
                  end
  default_index ? (default_index.to_i + 1).to_s : default.to_s
end

#just_ask(prompt, default = nil, validate = nil, error_text = nil, klass = nil) ⇒ Object



213
214
215
216
217
218
219
220
221
# File 'lib/manageiq/appliance_console/prompts.rb', line 213

def just_ask(prompt, default = nil, validate = nil, error_text = nil, klass = nil)
  ask("Enter the #{prompt}: ", klass) do |q|
    q.readline = true
    q.default = default.to_s if default
    q.validate = validate if validate
    q.responses[:not_valid] = error_text ? "Please provide #{error_text}" : "Please provide in the specified format"
    yield q if block_given?
  end
end

#press_any_keyObject



37
38
39
40
41
42
43
44
# File 'lib/manageiq/appliance_console/prompts.rb', line 37

def press_any_key
  say("\nPress any key to continue.")
  HighLine.default_instance.tap do |highline|
    highline.terminal.raw_no_echo_mode_exec do
      highline.terminal.get_character
    end
  end
end