Module: D3::Admin::Interactive
Overview
This module contains methods for interacting with the user in the terminal prompting for data related to administering d3 packages.
These methods all return a string of user input, possibly an empty string.
Constant Summary collapse
- UNSET =
'n'.freeze
- DFT_EDITOR =
'/usr/bin/nano -L'.freeze
Class Method Summary collapse
-
.get_auto_groups(default = nil) ⇒ String
Prompt the admin for one or more auto-groups for this installer.
-
.get_basename(default = nil) ⇒ Object
get a basename from the user.
-
.get_category(default = 'n') ⇒ String
Get a JSS Category from the user.
-
.get_computer(default = nil) ⇒ String
What computer are we generating a receipt report for?.
-
.get_config_target(default = 'all') ⇒ String
Get the config target.
-
.get_cpu_type(default = 'x86') ⇒ Symbol?
Get a the CPU-type limitation for this package.
-
.get_description(current_desc = '') ⇒ String
Get a multiline description from the user using the editor of their choice: nano, vi, emacs, or ENV.
-
.get_editor(default = '/usr/bin/nano') ⇒ String
get the shell command for editing package descriptions.
-
.get_excluded_groups(default = nil) ⇒ Object
Prompt the admin for one or more auto-groups for this installer.
-
.get_existing_package(default = nil) ⇒ String?
Ask the user for an edition or basename of an existing package.
-
.get_expiration(default = 0) ⇒ Integer
Get an expiration period (# of days) from the user.
-
.get_expiration_paths(default = 'n') ⇒ Array<Pathname>
Get the path to the executable(s) to monitor for expiration.
-
.get_filename(default = nil) ⇒ Object
get a package name from user.
-
.get_groups(desc, opt, default = nil) ⇒ String?
Prompt the admin for one or more groups.
-
.get_jss_package_for_import(default = nil) ⇒ String
Ask the user for an id or name of an existing JSS package to import into d3.
-
.get_keep_in_jss(default = 'n') ⇒ String
when deleting a pkg, should it be kept in the JSS?.
-
.get_keep_scripts(default = 'n') ⇒ String
when deleting a pkg, should its pre- and post- scripts be kept?.
-
.get_menu_choice(header, items) ⇒ Integer, String
Display a menu of numbered choices, and return the user’s choice, or ‘x’ if the user is done choosing.
-
.get_oses(default = []) ⇒ String?
Get a list of allowed OSes for this pkg.
-
.get_package_build_type(default = D3::Admin::DFT_PKG_TYPE) ⇒ Symbol
If we’re builting a pkg, should we build a .pkg, or a .dmg?.
-
.get_package_name(default = nil) ⇒ Object
get a package name from user.
-
.get_pkg_identifier(default = nil) ⇒ String
Get the pkg identifier for building .pkgs.
-
.get_pkg_identifier_prefix(default = D3::Admin::DFT_PKG_ID_PREFIX) ⇒ String
Get the pkg identifier prefex for building .pkgs When building .pkgs, this string is prefixed to the basename to create the Apple Pkg identifier.
-
.get_pkg_preserve_owners(default = 'n') ⇒ String
Ask if the pkg should preserve source ownership, or apply OS defaults.
-
.get_post_install_script(default = nil) ⇒ Pathname, ...
Get a post-install script, either local file, JSS id, or JSS name.
-
.get_post_remove_script(default = nil) ⇒ Pathname, ...
Get a post-remove script, either local file, JSS id, or JSS name.
-
.get_pre_install_script(default = nil) ⇒ Pathname, ...
Get a pre-install script, either local file, JSS id, or JSS name.
-
.get_pre_remove_script(default = nil) ⇒ Pathname, ...
Get a pre-remove script, either local file, JSS id, or JSS name.
-
.get_prohibiting_processes(default = 'n') ⇒ Regexp?
Get a pattern to match for the prohibiting processes If this matches a line of output from ‘/bin/ps -A -c -o comm` at install time, then graceful quit will be attempted.
-
.get_reboot(default = 'n') ⇒ String
Ask if this package needs a reboot.
-
.get_removable(default = 'y') ⇒ String
Ask if this package is uninstallable.
-
.get_remove_first(default = 'y') ⇒ String
Ask if we should ininstall older versions of this basename before installing this one.
-
.get_revision(default = nil) ⇒ String
Get a revision from the user.
-
.get_script(heading, opt, default = nil) ⇒ Pathname, ...
Get a script, either local file, JSS id, or JSS name.
-
.get_search_target(default = false) ⇒ String
Prompt the admin for text to search for package searchs.
-
.get_show_type(default = D3::Admin::Report::DFT_SHOW_TYPE) ⇒ String
what kind of package list are we showing?.
-
.get_signing_identity(default = ) ⇒ String
Get the optional Apple Developer signing ID .pkgs can be codesigned with a certificate from Apple The Developer ID Installer certificate must be in the login.keychain of the user operating d3admin unless otherwise specified in signing_options.
-
.get_signing_options(default = ) ⇒ String
Get any arguments and options to pass to pkgbuild A signing identity must be defined for these options to be used.
-
.get_source_path(default = false) ⇒ Pathname
Get the local path to the package being added to d3 Also sets @build_installer, and @build_installer_type if the source is a root-folder rather than a .pkg or .dmg.
-
.get_status_for_filter(with_frozen = false) ⇒ Object
get auto.
-
.get_value(option_or_get_method, default = nil, validate_method = nil) ⇒ Object
Call one of the get_ methods and do the matching validity check, if desired, repeatedly until a valid value is supplied.
-
.get_version(default = nil) ⇒ String
Get a version from the user.
-
.get_workspace(default = ) ⇒ Pathname
Get the desired local workspace for building pkgs Defaults to ENV.
-
.prompt_for_data(desc: nil, prompt: nil, opt: nil, default: :no_default, required: true) ⇒ String
Prompt for user input for an option and return the response.
Instance Method Summary collapse
-
#get_auto_groups(default = nil) ⇒ String
Prompt the admin for one or more auto-groups for this installer.
-
#get_basename(default = nil) ⇒ Object
get a basename from the user.
-
#get_category(default = 'n') ⇒ String
Get a JSS Category from the user.
-
#get_computer(default = nil) ⇒ String
What computer are we generating a receipt report for?.
-
#get_config_target(default = 'all') ⇒ String
Get the config target.
-
#get_cpu_type(default = 'x86') ⇒ Symbol?
Get a the CPU-type limitation for this package.
-
#get_description(current_desc = '') ⇒ String
Get a multiline description from the user using the editor of their choice: nano, vi, emacs, or ENV.
-
#get_editor(default = '/usr/bin/nano') ⇒ String
get the shell command for editing package descriptions.
-
#get_excluded_groups(default = nil) ⇒ Object
Prompt the admin for one or more auto-groups for this installer.
-
#get_existing_package(default = nil) ⇒ String?
Ask the user for an edition or basename of an existing package.
-
#get_expiration(default = 0) ⇒ Integer
Get an expiration period (# of days) from the user.
-
#get_expiration_paths(default = 'n') ⇒ Array<Pathname>
Get the path to the executable(s) to monitor for expiration.
-
#get_filename(default = nil) ⇒ Object
get a package name from user.
-
#get_groups(desc, opt, default = nil) ⇒ String?
Prompt the admin for one or more groups.
-
#get_jss_package_for_import(default = nil) ⇒ String
Ask the user for an id or name of an existing JSS package to import into d3.
-
#get_keep_in_jss(default = 'n') ⇒ String
when deleting a pkg, should it be kept in the JSS?.
-
#get_keep_scripts(default = 'n') ⇒ String
when deleting a pkg, should its pre- and post- scripts be kept?.
-
#get_menu_choice(header, items) ⇒ Integer, String
Display a menu of numbered choices, and return the user’s choice, or ‘x’ if the user is done choosing.
-
#get_oses(default = []) ⇒ String?
Get a list of allowed OSes for this pkg.
-
#get_package_build_type(default = D3::Admin::DFT_PKG_TYPE) ⇒ Symbol
If we’re builting a pkg, should we build a .pkg, or a .dmg?.
-
#get_package_name(default = nil) ⇒ Object
get a package name from user.
-
#get_pkg_identifier(default = nil) ⇒ String
Get the pkg identifier for building .pkgs.
-
#get_pkg_identifier_prefix(default = D3::Admin::DFT_PKG_ID_PREFIX) ⇒ String
Get the pkg identifier prefex for building .pkgs When building .pkgs, this string is prefixed to the basename to create the Apple Pkg identifier.
-
#get_pkg_preserve_owners(default = 'n') ⇒ String
Ask if the pkg should preserve source ownership, or apply OS defaults.
-
#get_post_install_script(default = nil) ⇒ Pathname, ...
Get a post-install script, either local file, JSS id, or JSS name.
-
#get_post_remove_script(default = nil) ⇒ Pathname, ...
Get a post-remove script, either local file, JSS id, or JSS name.
-
#get_pre_install_script(default = nil) ⇒ Pathname, ...
Get a pre-install script, either local file, JSS id, or JSS name.
-
#get_pre_remove_script(default = nil) ⇒ Pathname, ...
Get a pre-remove script, either local file, JSS id, or JSS name.
-
#get_prohibiting_processes(default = 'n') ⇒ Regexp?
Get a pattern to match for the prohibiting processes If this matches a line of output from ‘/bin/ps -A -c -o comm` at install time, then graceful quit will be attempted.
-
#get_reboot(default = 'n') ⇒ String
Ask if this package needs a reboot.
-
#get_removable(default = 'y') ⇒ String
Ask if this package is uninstallable.
-
#get_remove_first(default = 'y') ⇒ String
Ask if we should ininstall older versions of this basename before installing this one.
-
#get_revision(default = nil) ⇒ String
Get a revision from the user.
-
#get_script(heading, opt, default = nil) ⇒ Pathname, ...
Get a script, either local file, JSS id, or JSS name.
-
#get_search_target(default = false) ⇒ String
Prompt the admin for text to search for package searchs.
-
#get_show_type(default = D3::Admin::Report::DFT_SHOW_TYPE) ⇒ String
what kind of package list are we showing?.
-
#get_signing_identity(default = ) ⇒ String
Get the optional Apple Developer signing ID .pkgs can be codesigned with a certificate from Apple The Developer ID Installer certificate must be in the login.keychain of the user operating d3admin unless otherwise specified in signing_options.
-
#get_signing_options(default = ) ⇒ String
Get any arguments and options to pass to pkgbuild A signing identity must be defined for these options to be used.
-
#get_source_path(default = false) ⇒ Pathname
Get the local path to the package being added to d3 Also sets @build_installer, and @build_installer_type if the source is a root-folder rather than a .pkg or .dmg.
-
#get_status_for_filter(with_frozen = false) ⇒ Object
get auto.
-
#get_value(option_or_get_method, default = nil, validate_method = nil) ⇒ Object
Call one of the get_ methods and do the matching validity check, if desired, repeatedly until a valid value is supplied.
-
#get_version(default = nil) ⇒ String
Get a version from the user.
-
#get_workspace(default = ) ⇒ Pathname
Get the desired local workspace for building pkgs Defaults to ENV.
-
#prompt_for_data(desc: nil, prompt: nil, opt: nil, default: :no_default, required: true) ⇒ String
Prompt for user input for an option and return the response.
Class Method Details
.get_auto_groups(default = nil) ⇒ String
Prompt the admin for one or more auto-groups for this installer
637 638 639 640 641 642 643 644 645 646 |
# File 'lib/d3/admin/interactive.rb', line 637 def get_auto_groups(default = nil) desc = "AUTO-INSTALL GROUPS\nEnter a comma-separated list of JSS Computer Group names whose members should\nhave this package installed automatically when it is made live.\nEnter 'v' to view a list of computer groups.\nEnter '\#{D3::STANDARD_AUTO_GROUP}' to install on all machines.\n END_DESC\n get_groups desc, :auto_groups, default\nend\n" |
.get_basename(default = nil) ⇒ Object
get a basename from the user
265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 |
# File 'lib/d3/admin/interactive.rb', line 265 def get_basename(default = nil) desc = "BASENAME\nEnter a basename.\nEnter 'v' to view a list of all basenames in d3 and\nthe newest edition for each.\n END_DESC\n\n input = 'v'\n while input == 'v'\n input = prompt_for_data(desc: desc, prompt: 'Basename', required: true)\n D3::Admin::Report.show_all_basenames_and_editions if input == 'v'\n end\n input\nend\n" |
.get_category(default = 'n') ⇒ String
Get a JSS Category from the user
748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 |
# File 'lib/d3/admin/interactive.rb', line 748 def get_category(default = 'n') desc = "CATEGORY\nEnter the JSS category name for this package.\nEnter:\n - 'v' to view all JSS categories\n - 'n' for no category\n END_DESC\n\n result = 'v'\n while result == 'v'\n result = prompt_for_data(desc: desc, prompt: 'Category', default: default, required: true)\n D3.less_text JSS::Category.all_names.sort_by(&:downcase).join(\"\\n\") if result == 'v'\n end\n return nil if result == 'n'\n result\nend\n" |
.get_computer(default = nil) ⇒ String
What computer are we generating a receipt report for?
945 946 947 948 949 950 951 952 953 954 955 956 957 |
# File 'lib/d3/admin/interactive.rb', line 945 def get_computer(default = nil) desc = "COMPUTER NAME\nEnter the name of a computer Jamf Pro.\nEnter 'v' to view a list available computer names.\n" input = 'v' while input == 'v' input = prompt_for_data(desc: desc, prompt: 'Computer name', default: nil, required: true) D3::Admin::Report.show_available_computers_for_reports if input == 'v' end input end |
.get_config_target(default = 'all') ⇒ String
Get the config target
965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 |
# File 'lib/d3/admin/interactive.rb', line 965 def get_config_target(default = 'all') desc = "CONFIGURATION\nWhich setting would you like to configure?\n jss - the JSS and credentials (stored in your keychain)\n db - the MySQL server and credentials (stored in your keychain)\n dist - the master distribution point RW password (stored in your keychain)\n workspace - the folder in which to build .pkgs and .dmgs\n editor - the shell command for editing package descriptions\n pkg-id-prefix - the prefix for the .pkg identifier when building .pkgs\n signing-identity - optional Developer ID Installer certificate issued by Apple\n signing-options - optional string of signing options to pass to pkgbuild.\n all - all of the above\n display - show current configuration\n\n END_DESC\n prompt_for_data(opt: :pkg_identifier_prefix, desc: desc, default: default, required: true)\nend\n" |
.get_cpu_type(default = 'x86') ⇒ Symbol?
Get a the CPU-type limitation for this package
733 734 735 736 737 738 739 740 |
# File 'lib/d3/admin/interactive.rb', line 733 def get_cpu_type(default = 'x86') desc = "LIMIT TO CPU TYPE\nShould this packge be limited to certain CPU types?\nEnter 'ppc' or 'x86' or 'none' for neither.\n END_DESC\n prompt_for_data(desc: desc, opt: :cpu_type, default: default, required: true)\nend\n" |
.get_description(current_desc = '') ⇒ String
Get a multiline description from the user using the editor of their choice: nano, vi, emacs, or ENV
352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 |
# File 'lib/d3/admin/interactive.rb', line 352 def get_description(current_desc = '') # do we have a current desc to display and possibly keep? current_desc_review = '' unless current_desc.to_s.empty? current_desc_review = "\n----- Current Description -----\n#{current_desc}\n-------------------------------\n\n" end if prefd_editor = D3::Admin::Prefs.prefs[:editor] prefd_editor_choice = "\n - 'e' to edit using '#{prefd_editor}' " else prefd_editor_choice = '' end # the blurb to show the user input_desc = "DESCRIPTION\nCreate a multi-line description of this package:\n - what does the installed thing do?\n - where did it come from, where to get updates?\n - who maintains it in your environment?\n - any other info useful to d3 and Jamf Pro admins.\n(don't just say \"installs foo\" when \"foo\" is the basename)\n \#{current_desc_review}Enter:\#{prefd_editor_choice}\n - 'n' to edit using 'nano'\n - 'v' to edit using 'vi' or 'vim'\n - 'm' to edit using 'emacs'\n - 'b' to have a blank description\nAnything else will edit with the EDITOR for your environment\nor '\#{DFT_EDITOR}' if none is set.\n END_DESC\n\n # show it, get response\n puts input_desc\n choice = Readline.readline('Your choice (hit return to keep current desc.): ', false)\n\n # keep or empty?\n return current_desc if choice.empty?\n\n return '' if choice.casecmp('b').zero?\n\n # make a tem file, save current into it\n desc_tmp_file = Pathname.new Tempfile.new('d3_description_')\n desc_tmp_file.jss_save current_desc\n\n # which editor?\n if choice.casecmp('e').zero?\n cmd = prefd_editor\n elsif choice.casecmp('v').zero?\n cmd = '/usr/bin/vim'\n elsif choice.casecmp('m').zero?\n cmd = '/usr/bin/emacs'\n elsif choice.casecmp('n').zero?\n cmd = '/usr/bin/nano -L'\n else\n cmd = ENV['EDITOR']\n end\n cmd ||= DFT_EDITOR\n\n system \"\#{cmd} '\#{desc_tmp_file}'\"\n\n result = desc_tmp_file.read.chomp\n desc_tmp_file.delete\n result.chomp\nend\n" |
.get_editor(default = '/usr/bin/nano') ⇒ String
get the shell command for editing package descriptions
990 991 992 993 994 995 996 997 998 999 1000 1001 1002 |
# File 'lib/d3/admin/interactive.rb', line 990 def get_editor(default = '/usr/bin/nano') desc = "EDITOR\nEnter the shell command to use during --walkthru\nfor editing package descriptions\ne.g. /usr/bin/vim, /usr/bin/emacs\n\nNote: if the command launches a GUI editor, make sure the\nshell command stays running until the document is closed.\nMost such editors have an option for that.\n" prompt_for_data(desc: desc, default: default, prompt: 'Command', required: true) end |
.get_excluded_groups(default = nil) ⇒ Object
Prompt the admin for one or more auto-groups for this installer
651 652 653 654 655 656 657 658 659 |
# File 'lib/d3/admin/interactive.rb', line 651 def get_excluded_groups(default = nil) desc = "EXCLUDED GROUPS\nEnter a comma-separated list of JSS Computer Group names\nwhose members should not get this installed without force.\nEnter 'v' to view list of computer groups.\n END_PROMPT\n get_groups desc, :excluded_groups, default\nend\n" |
.get_existing_package(default = nil) ⇒ String?
Ask the user for an edition or basename of an existing package.
225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 |
# File 'lib/d3/admin/interactive.rb', line 225 def get_existing_package(default = nil) desc = "EXISTING PACKAGE\nEnter a package edition or basename for an existing d3 package.\nIf a basename, the currently live package for that basename will be used.\nEnter:\n - 'v' to view a list of all packages with the basenames and editions in d3.\n END_DESC\n\n input = 'v'\n while input == 'v'\n input = prompt_for_data(desc: desc, prompt: 'Edition or Basename', default: default, required: true)\n D3::Admin::Report.show_all_basenames_and_editions if input == 'v'\n end\n input\nend\n" |
.get_expiration(default = 0) ⇒ Integer
Get an expiration period (# of days) from the user
852 853 854 855 856 857 858 859 860 861 862 |
# File 'lib/d3/admin/interactive.rb', line 852 def get_expiration(default = 0) desc = "EXPIRATION\nOn machines that allow package expiration,\nshould this package be removed after some\nnumber of days without being used?\nEnter the number of days, or 0 for no expiration.\n END_DESC\n\n prompt_for_data(desc: desc, prompt: 'Expiration days', default: default, required: true)\nend\n" |
.get_expiration_paths(default = 'n') ⇒ Array<Pathname>
Get the path to the executable(s) to monitor for expiration
870 871 872 873 874 875 876 877 878 879 880 |
# File 'lib/d3/admin/interactive.rb', line 870 def get_expiration_paths(default = 'n') desc = "EXPIRATION PATH(S)\nEnter the path(s) to the executable(s) that must be used\nto prevent expiration. Multiple paths should be separated by commas, spaces\nshould not be escaped. E.g.\n/Applications/Google Chrome.app/Contents/MacOS/Google Chrome, /Applications/Firefox.app/Contents/MacOS/firefox\nEnter 'n' for none\n END_DESC\n prompt_for_data(desc: desc, prompt: 'Expiration Path(s)', default: default, required: true)\nend\n" |
.get_filename(default = nil) ⇒ Object
get a package name from user
297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 |
# File 'lib/d3/admin/interactive.rb', line 297 def get_filename(default = nil) desc = "INSTALLER FILENAME\nEnter a unique name for this package's installer file\non the master distribution point. The file will be\nrenamed to this name on the distribution point.\nEnter 'v' to see a list of existing pkg filenames in the JSS\n END_DESC\n input = 'v'\n while input == 'v'\n input = prompt_for_data(opt: :filename, desc: desc, default: default, required: true)\n D3::Admin::Report.show_existing_package_ids if input == 'v'\n end\n input\nend\n" |
.get_groups(desc, opt, default = nil) ⇒ String?
Prompt the admin for one or more groups
701 702 703 704 705 706 707 708 |
# File 'lib/d3/admin/interactive.rb', line 701 def get_groups(desc, opt, default = nil) result = 'v' while result == 'v' result = prompt_for_data(opt: opt, desc: desc, default: default, required: true) D3.less_text JSS::ComputerGroup.all_names.sort_by(&:downcase).join("\n") if result == 'v' end result end |
.get_jss_package_for_import(default = nil) ⇒ String
Ask the user for an id or name of an existing JSS package to import into d3
247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 |
# File 'lib/d3/admin/interactive.rb', line 247 def get_jss_package_for_import(default = nil) desc = "IMPORT JSS PACKAGE\nEnter a package id or display-name for\nan existing JSS package to import into d3.\nEnter:\n - 'v' to view a list of all JSS package names not in d3.\n END_DESC\n\n input = 'v'\n while input == 'v'\n input = prompt_for_data(desc: desc, prompt: 'JSS id or display name', default: default, required: true)\n D3::Admin::Report.show_pkgs_available_for_import if input == 'v'\n end\n input\nend\n" |
.get_keep_in_jss(default = 'n') ⇒ String
when deleting a pkg, should it be kept in the JSS?
907 908 909 910 911 912 913 914 915 |
# File 'lib/d3/admin/interactive.rb', line 907 def get_keep_in_jss(default = 'n') desc = "KEEP THE PACKAGE IN JAMF PRO?\nWhen deleting a package, should it be kept as a Jamf Pro package\nand only deleted from d3?\nEnter 'y' or 'n'\n END_DESC\n prompt_for_data(desc: desc, prompt: 'Keep in JSS? (y/n)', default: default, required: true)\nend\n" |
.get_keep_scripts(default = 'n') ⇒ String
when deleting a pkg, should its pre- and post- scripts be kept?
888 889 890 891 892 893 894 895 896 897 898 899 |
# File 'lib/d3/admin/interactive.rb', line 888 def get_keep_scripts(default = 'n') desc = "KEEP ASSOCIATED SCRIPTS IN JAMF PRO?\nWhen deleting a package, should any associated scripts\n(pre-install, post-install, pre-remove, post-remove) be kept in Jamf Pro?\n\nNOTE: If any other d3 packages or policies are using the scripts\nthey won't be deleted. The other users of the scripts will be reported.\nEnter 'y' or 'n'\n END_DESC\n prompt_for_data(desc: desc, prompt: 'Delete Scripts? (y/n)', default: default, required: true)\nend\n" |
.get_menu_choice(header, items) ⇒ Integer, String
Display a menu of numbered choices, and return the user’s choice, or ‘x’ if the user is done choosing.
64 65 66 67 68 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 97 98 |
# File 'lib/d3/admin/interactive.rb', line 64 def (header, items) # add a 1-based number and ) to the start of each line, like 1), and 2)... items.each_index { |i| items[i] = "#{i + 1}) #{items[i]}" } = items.count = "(1-#{menu_count}, x=done, ^c=cancel)" = "#{header}\n#{items.join("\n")}" # clear the screen between displays of the menu, so its always at the top. system 'clear' or system 'cls' puts choice = '' while choice == '' choice = Readline.readline("Which to change? #{menu_count_display}: ", false) break if choice == 'x' # they chose a number.. if choice =~ /^\d+$/ # map it to one of the editing options choice = choice.to_i - 1 # but they might have chosen a higher number than allowws choice = '' unless (0..( - 1)).cover? choice else choice = '' end # tell them they made a bad choice if choice == '' puts "\n******* Sorry, invalid choice.\n" next end end # while choice == "" choice end |
.get_oses(default = []) ⇒ String?
Get a list of allowed OSes for this pkg
717 718 719 720 721 722 723 724 725 |
# File 'lib/d3/admin/interactive.rb', line 717 def get_oses(default = []) desc = "LIMIT TO OS's\nEnter a comma-separated list of OS's allowed to\ninstall this package, e.g. '10.8.5, 10.9.5, 10.10.x'\nUse '>=' to set a minimum OS, e.g. '>=10.8.5'\n END_DESC\n prompt_for_data(desc: desc, opt: :oses, default: default, required: true)\nend\n" |
.get_package_build_type(default = D3::Admin::DFT_PKG_TYPE) ⇒ Symbol
If we’re builting a pkg, should we build a .pkg, or a .dmg?
438 439 440 441 442 443 444 445 |
# File 'lib/d3/admin/interactive.rb', line 438 def get_package_build_type(default = D3::Admin::DFT_PKG_TYPE) desc = "PACKAGE BUILD TYPE\nLooks like we need to build the installer from a package-root.\nShould we build a .pkg or .dmg? ( p = pkg, d = dmg )\n END_DESC\n prompt_for_data(opt: :package_build_type, desc: desc, default: default, required: true)\nend\n" |
.get_package_name(default = nil) ⇒ Object
get a package name from user
282 283 284 285 286 287 288 289 290 291 292 293 294 |
# File 'lib/d3/admin/interactive.rb', line 282 def get_package_name(default = nil) desc = "JSS PACKAGE NAME\nEnter a unique name for this package in d3 and Jamf Pro.\nEnter 'v' to view a list of package names currently in d3.\n END_DESC\n input = 'v'\n while input == 'v'\n input = prompt_for_data(opt: :package_name, desc: desc, default: default, required: true)\n D3::Admin::Report.show_existing_package_ids if input == 'v'\n end\n input\nend\n" |
.get_pkg_identifier(default = nil) ⇒ String
Get the pkg identifier for building .pkgs
453 454 455 456 457 458 459 460 |
# File 'lib/d3/admin/interactive.rb', line 453 def get_pkg_identifier(default = nil) desc = "PKG IDENTIFIER\nEnter the Apple .pkg indentifier for building a .pkg.\nE.g. com.mycompany.myapp\n END_DESC\n prompt_for_data(opt: :pkg_identifier_prefix, desc: desc, default: default, required: true)\nend\n" |
.get_pkg_identifier_prefix(default = D3::Admin::DFT_PKG_ID_PREFIX) ⇒ String
Get the pkg identifier prefex for building .pkgs When building .pkgs, this string is prefixed to the basename to create the Apple Pkg identifier. For example if the value is com.pixar.d3, then when building a pkg with the basename “foo” the identifier will be com.pixar.d3.foo
This value is saved in the admin prefs for future use.
475 476 477 478 479 480 481 482 483 |
# File 'lib/d3/admin/interactive.rb', line 475 def get_pkg_identifier_prefix(default = D3::Admin::DFT_PKG_ID_PREFIX) desc = "PKG IDENTIFIER PREFIX\nEnter the prefix to prepend to a basename to create an Apple .pkg indentifier.\nE.g. If you enter 'com.mycompany', then when you build a .pkg with basename 'foo'\nthe default .pkg identifier will be 'com.mycompany.foo'\n END_DESC\n prompt_for_data(opt: :pkg_identifier_prefix, desc: desc, default: default, required: true)\nend\n" |
.get_pkg_preserve_owners(default = 'n') ⇒ String
Ask if the pkg should preserve source ownership, or apply OS defaults
548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 |
# File 'lib/d3/admin/interactive.rb', line 548 def get_pkg_preserve_owners(default = 'n') desc = "PRESERVE SOURCE OWNERSHIP\nWhen building a .pkg, the OS generally sets the ownership and permissions\nof the payload to match OS standards, e.g. Apps owned by 'root' with group\n'admin' or 'wheel'\n\nIf desired you can preserve the current ownership and permissions of the source\nfolder contents when the payload is installed. This is generally not recomended.\n\nShould we override the OS and preserve the ownership on\nthe source folder when the item is installed on the client?\nEnter 'y' or 'n'\n END_DESC\n prompt_for_data(desc: desc, prompt: 'Preserve ownership (y/n)', default: default, required: true)\nend\n" |
.get_post_install_script(default = nil) ⇒ Pathname, ...
Get a post-install script, either local file, JSS id, or JSS name
583 584 585 |
# File 'lib/d3/admin/interactive.rb', line 583 def get_post_install_script(default = nil) get_script 'POST-INSTALL SCRIPT', :post_install, default end |
.get_post_remove_script(default = nil) ⇒ Pathname, ...
Get a post-remove script, either local file, JSS id, or JSS name
605 606 607 |
# File 'lib/d3/admin/interactive.rb', line 605 def get_post_remove_script(default = nil) get_script 'POST-REMOVE SCRIPT', :post_remove, default end |
.get_pre_install_script(default = nil) ⇒ Pathname, ...
Get a pre-install script, either local file, JSS id, or JSS name
572 573 574 |
# File 'lib/d3/admin/interactive.rb', line 572 def get_pre_install_script(default = nil) get_script 'PRE-INSTALL SCRIPT', :pre_install, default end |
.get_pre_remove_script(default = nil) ⇒ Pathname, ...
Get a pre-remove script, either local file, JSS id, or JSS name
594 595 596 |
# File 'lib/d3/admin/interactive.rb', line 594 def get_pre_remove_script(default = nil) get_script 'PRE-REMOVE SCRIPT', :pre_remove, default end |
.get_prohibiting_processes(default = 'n') ⇒ Regexp?
Get a pattern to match for the prohibiting processes If this matches a line of output from ‘/bin/ps -A -c -o comm` at install time, then graceful quit will be attempted. Strings must match a whole line, Regexps will work with any match.
776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 |
# File 'lib/d3/admin/interactive.rb', line 776 def get_prohibiting_processes(default = 'n') desc = "PROHIBITING PROCESSES\nEnter a comma separated string of process name(s) as they appear in the\nof the output of `/bin/ps -A -c -o comm`.\n\nExample: Safari, Google Chrome, cfprefsd\n\nIf a process is running at install time, the installer will\nquit any background processes automatically, and may prompt the user\nto quit GUI applications gracefully. Matching is case sensitive.\n\nEnter 'n' for none.\n END_DESC\n\n result = prompt_for_data(desc: desc, prompt: 'Prohibiting Processes', opt: :prohibiting_processes, default: default, required: true)\n return nil if result == 'n'\n result\nend\n" |
.get_reboot(default = 'n') ⇒ String
Ask if this package needs a reboot
834 835 836 837 838 839 840 841 842 843 844 |
# File 'lib/d3/admin/interactive.rb', line 834 def get_reboot(default = 'n') desc = "REBOOT REQUIRED (PUPPIES!)\nDoes this package require a reboot after installation?\nIf so, it will be added to the Puppy Queue when installed\nwith 'd3 install', and the user will be notified to log\nout as soon as possible.\nEnter 'y' or 'n'\n END_DESC\n prompt_for_data(desc: desc, prompt: 'Requires reboot? (y/n)', default: default, required: true)\nend\n" |
.get_removable(default = 'y') ⇒ String
Ask if this package is uninstallable
802 803 804 805 806 807 808 809 |
# File 'lib/d3/admin/interactive.rb', line 802 def get_removable(default = 'y') desc = "REMOVABLE\nCan this package be uninstalled?\nEnter 'y' or 'n'\n END_DESC\n prompt_for_data(desc: desc, prompt: 'Removable? (y/n)', default: default, required: true)\nend\n" |
.get_remove_first(default = 'y') ⇒ String
Ask if we should ininstall older versions of this basename before installing this one
818 819 820 821 822 823 824 825 826 |
# File 'lib/d3/admin/interactive.rb', line 818 def get_remove_first(default = 'y') desc = "UNINSTALL OLDER VERSIONS\nShould older versions of this basename be uninstalled\n(if they are removable) before attempting to install this package?\nEnter 'y' or 'n'\n END_DESC\n prompt_for_data(desc: desc, prompt: 'Remove older installs first? (y/n)', default: default, required: true)\nend\n" |
.get_revision(default = nil) ⇒ String
Get a revision from the user
334 335 336 337 338 339 340 341 342 343 |
# File 'lib/d3/admin/interactive.rb', line 334 def get_revision(default = nil) desc = "REVISION\nEnter a Package revision for this package.\nThis is an integer representing a new packaging of\nan existing version of a given basename.\n END_DESC\n\n prompt_for_data(opt: :revision, desc: desc, default: default, required: true)\nend\n" |
.get_script(heading, opt, default = nil) ⇒ Pathname, ...
Get a script, either local file, JSS id, or JSS name
616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 |
# File 'lib/d3/admin/interactive.rb', line 616 def get_script(heading, opt, default = nil) desc = "\#{heading}\nEnter a path to a local file containing the script\nor the name or id of an existing script in the JSS.\nEnter 'v' to view a list of scripts in the JSS.\n END_DESC\n\n result = 'v'\n while result == 'v'\n result = prompt_for_data(opt: opt, desc: desc, default: default, required: true)\n D3.less_text JSS::Script.all_names.sort_by(&:downcase).join(\"\\n\") if result == 'v'\n end\n result\nend\n" |
.get_search_target(default = false) ⇒ String
Prompt the admin for text to search for package searchs
665 666 667 668 669 670 671 672 673 674 675 |
# File 'lib/d3/admin/interactive.rb', line 665 def get_search_target(default = false) desc = "SEARCH TEXT\nEnter text to use in matching basenames or computer group names.\nMatching a basename will list all packages with the basename.\nMatching a group name will list all packages auto-installed or\nexcluded for the group. (RegExp's OK)\nEnter 'all' to list all packages in d3.\n END_PROMPT\n prompt_for_data(desc: desc, prompt: \"Text to match or 'all'\").chomp\nend\n" |
.get_show_type(default = D3::Admin::Report::DFT_SHOW_TYPE) ⇒ String
what kind of package list are we showing?
923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 |
# File 'lib/d3/admin/interactive.rb', line 923 def get_show_type(default = D3::Admin::Report::DFT_SHOW_TYPE) desc = "SERVER PACKAGE LIST\nEnter the type of list you'd like to generate about packages in d3.\n\nOne of:\n all - all packages in d3\n pilot - packages newer than live\n live - live packages\n deprecated - old packages that used to be live\n skipped - old packages that were never made live\n missing - packages in d3, but not Jamf Pro\n auto - packages auto-installed for a given computer group\n excluded - packages not available to a given computer group\n" prompt_for_data(desc: desc, prompt: 'Show packages', default: default, required: true) end |
.get_signing_identity(default = ) ⇒ String
Get the optional Apple Developer signing ID .pkgs can be codesigned with a certificate from Apple The Developer ID Installer certificate must be in the login.keychain of the user operating d3admin unless otherwise specified in signing_options
This value is saved in the admin prefs for future use.
497 498 499 500 501 502 503 504 505 |
# File 'lib/d3/admin/interactive.rb', line 497 def get_signing_identity(default = D3::Admin::Prefs.prefs[:signing_identity]) desc = "SIGNING IDENTITY\nEnter the common name of your Apple Developer signing ID to create signed Apple .pkgs.\nE.g. If you enter 'Developer ID Installer: My Company (A12BC34DE56)', then that string will be passed\nas the option for pkgbuild --sign. D3 will not attempt to sign unless this option is set.'\n END_DESC\n prompt_for_data(opt: :signing_identity, desc: desc, default: default, required: false)\nend\n" |
.get_signing_options(default = ) ⇒ String
Get any arguments and options to pass to pkgbuild A signing identity must be defined for these options to be used.
This value is saved in the admin prefs for future use.
516 517 518 519 520 521 522 523 |
# File 'lib/d3/admin/interactive.rb', line 516 def (default = D3::Admin::Prefs.prefs[:signing_options]) desc = "SIGNING OPTIONS\nEnter optional arguments and options to pass to pkgbuild. These options are ignored unless a signing identity is defined.\nE.g. --keychain '/Users/d3/Library/Keychain' --cert 'My Awesome Authority' --timestamp\n END_DESC\n prompt_for_data(opt: :signing_options, desc: desc, default: default, required: false)\nend\n" |
.get_source_path(default = false) ⇒ Pathname
Get the local path to the package being added to d3 Also sets @build_installer, and @build_installer_type if the source is a root-folder rather than a .pkg or .dmg
422 423 424 425 426 427 428 429 430 431 432 |
# File 'lib/d3/admin/interactive.rb', line 422 def get_source_path(default = false) desc = "SOURCE\nEnter the path to a .pkg or .dmg installer\nor a 'root' folder from which to build one.\n" # dragging in items from the finder will esacpe spaces in the path with \'s # in the shell this is good, but ruby is interpreting the \'s, so lets remove them. prompt_for_data(opt: :source_path, desc: desc, default: default, required: true).strip.gsub(/\\ /, ' ') end |
.get_status_for_filter(with_frozen = false) ⇒ Object
get auto
677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 |
# File 'lib/d3/admin/interactive.rb', line 677 def get_status_for_filter(with_frozen = false) if with_frozen frozen_line = "\nUse 'frozen' to limit to frozen receipts" frozen_title = 'OR FROZEN' else frozen_line = '' frozen_title = '' end desc = "LIMIT TO STATUS\#{frozen_title}\nEnter a comma-separate list of statuses for limiting the list.\nValid Statuses are: \#{D3::Basename::STATUSES_FOR_FILTERS.join(', ')}\#{frozen_line}\nEnter 'all' to show all statuses\n END_PROMPT\n prompt_for_data(desc: desc, prompt: 'Statuses', default: 'all').chomp\nend\n" |
.get_value(option_or_get_method, default = nil, validate_method = nil) ⇒ Object
Call one of the get_ methods and do the matching validity check, if desired, repeatedly until a valid value is supplied.
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 |
# File 'lib/d3/admin/interactive.rb', line 115 def get_value(option_or_get_method, default = nil, validate_method = nil) # if the option_or_get_method is one of the keys in OPTIONS, then use OPTIONS[get_method][:get] if it exists if D3::Admin::OPTIONS.keys.include?(option_or_get_method) get_method = D3::Admin::OPTIONS[option_or_get_method][:get] # if we weren't giving a validate method, get it from the OPTIONS validate_method ||= D3::Admin::OPTIONS[option_or_get_method][:validate] end # otherwise we should have been given a symbolic method name. get_method ||= option_or_get_method valid = :start validated = nil until valid === true # Keep the ===, trust me. Don't listen to rubocop. puts "\nSorry: #{validated}, Try again.\n" unless valid === :start value_input = self.send get_method, default # no check method? just return the value return value_input if validate_method.nil? (valid, validated) = D3::Admin::Validate.validate(value_input, validate_method) end # until valid === true validated end |
.get_version(default = nil) ⇒ String
Get a version from the user
318 319 320 321 322 323 324 325 326 |
# File 'lib/d3/admin/interactive.rb', line 318 def get_version(default = nil) desc = "VERSION\nEnter a version for this package.\nAll spaces will be converted to underscores.\n END_DESC\n\n prompt_for_data(opt: :version, desc: desc, default: default, required: true)\nend\n" |
.get_workspace(default = ) ⇒ Pathname
Get the desired local workspace for building pkgs Defaults to ENV
532 533 534 535 536 537 538 539 |
# File 'lib/d3/admin/interactive.rb', line 532 def get_workspace(default = ENV['HOME']) desc = "PACKAGE BUILD WORKSPACE\nEnter the path to a folder where we can build packages.\nThis will be stored between uses of d3admin.\n END_DESC\n Pathname.new prompt_for_data(opt: :workspace, desc: desc, default: default, required: true)\nend\n" |
.prompt_for_data(desc: nil, prompt: nil, opt: nil, default: :no_default, required: true) ⇒ String
Prompt for user input for an option and return the response.
A Description of the option is displayed, followed by a prompt. If a default value is provided, the prompt includes the text
(Hit return for #{default_value})
If the option is defined in D3::Admin::OPTIONS, the data for the option is used, if not provided in the args.
If the option is defined as unsettable, a line “Enter ‘n’ for none.” is also displayed before the prompt and a value of ‘n’ will cause the method to return nil.
If no prompt is given in the args, the :label is used from D3::Admin::OPTIONS
If no default value is given in the args, the one from D3::Admin::OPTIONS is used. If required is true, the input can’t be an empty string.
Note: watch out for nil vs false in default values
179 180 181 182 183 184 185 186 187 188 189 190 191 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 |
# File 'lib/d3/admin/interactive.rb', line 179 def prompt_for_data(desc: nil, prompt: nil, opt: nil, default: :no_default, required: true) unset_line = nil default_display = default # look up some info about this option, if needed if opt opt_def = D3::Admin::OPTIONS[opt] if opt_def prompt ||= opt_def[:label] unset_line = "Enter '#{UNSET}' for none." if opt_def[:unsetable] default = opt_def[:default] if opt_def[:default] and default == :no_default default_display = opt_def[:display_conversion].call(default) if opt_def[:display_conversion] end end # if args[:opt] # some values are special for displaying default_display = case default_display when :no_default then '' when D3::Admin::DFT_REQUIRED then '' # the '---Required---' should only be visible in the menu, not the prompt when D3::Admin::DFT_NONE then UNSET else default_display.to_s end data_entered = '' puts "\n#{desc}" if desc prompt ||= 'Please enter a value' hit_return = default_display.empty? ? '' : " (Hit return for '#{default_display}' )" prompt_line = "#{prompt}#{hit_return}: " while true do data_entered = Readline.readline(prompt_line, false) data_entered = default_display if data_entered == '' break unless required && data_entered.empty? end # if 'n' was typed for an unsettable option, return nil return nil if opt_def && opt_def[:unsetable] && data_entered == UNSET data_entered.strip end |
Instance Method Details
#get_auto_groups(default = nil) ⇒ String
Prompt the admin for one or more auto-groups for this installer
637 638 639 640 641 642 643 644 645 646 |
# File 'lib/d3/admin/interactive.rb', line 637 def get_auto_groups(default = nil) desc = "AUTO-INSTALL GROUPS\nEnter a comma-separated list of JSS Computer Group names whose members should\nhave this package installed automatically when it is made live.\nEnter 'v' to view a list of computer groups.\nEnter '\#{D3::STANDARD_AUTO_GROUP}' to install on all machines.\n END_DESC\n get_groups desc, :auto_groups, default\nend\n" |
#get_basename(default = nil) ⇒ Object
get a basename from the user
265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 |
# File 'lib/d3/admin/interactive.rb', line 265 def get_basename(default = nil) desc = "BASENAME\nEnter a basename.\nEnter 'v' to view a list of all basenames in d3 and\nthe newest edition for each.\n END_DESC\n\n input = 'v'\n while input == 'v'\n input = prompt_for_data(desc: desc, prompt: 'Basename', required: true)\n D3::Admin::Report.show_all_basenames_and_editions if input == 'v'\n end\n input\nend\n" |
#get_category(default = 'n') ⇒ String
Get a JSS Category from the user
748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 |
# File 'lib/d3/admin/interactive.rb', line 748 def get_category(default = 'n') desc = "CATEGORY\nEnter the JSS category name for this package.\nEnter:\n - 'v' to view all JSS categories\n - 'n' for no category\n END_DESC\n\n result = 'v'\n while result == 'v'\n result = prompt_for_data(desc: desc, prompt: 'Category', default: default, required: true)\n D3.less_text JSS::Category.all_names.sort_by(&:downcase).join(\"\\n\") if result == 'v'\n end\n return nil if result == 'n'\n result\nend\n" |
#get_computer(default = nil) ⇒ String
What computer are we generating a receipt report for?
945 946 947 948 949 950 951 952 953 954 955 956 957 |
# File 'lib/d3/admin/interactive.rb', line 945 def get_computer(default = nil) desc = "COMPUTER NAME\nEnter the name of a computer Jamf Pro.\nEnter 'v' to view a list available computer names.\n" input = 'v' while input == 'v' input = prompt_for_data(desc: desc, prompt: 'Computer name', default: nil, required: true) D3::Admin::Report.show_available_computers_for_reports if input == 'v' end input end |
#get_config_target(default = 'all') ⇒ String
Get the config target
965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 |
# File 'lib/d3/admin/interactive.rb', line 965 def get_config_target(default = 'all') desc = "CONFIGURATION\nWhich setting would you like to configure?\n jss - the JSS and credentials (stored in your keychain)\n db - the MySQL server and credentials (stored in your keychain)\n dist - the master distribution point RW password (stored in your keychain)\n workspace - the folder in which to build .pkgs and .dmgs\n editor - the shell command for editing package descriptions\n pkg-id-prefix - the prefix for the .pkg identifier when building .pkgs\n signing-identity - optional Developer ID Installer certificate issued by Apple\n signing-options - optional string of signing options to pass to pkgbuild.\n all - all of the above\n display - show current configuration\n\n END_DESC\n prompt_for_data(opt: :pkg_identifier_prefix, desc: desc, default: default, required: true)\nend\n" |
#get_cpu_type(default = 'x86') ⇒ Symbol?
Get a the CPU-type limitation for this package
733 734 735 736 737 738 739 740 |
# File 'lib/d3/admin/interactive.rb', line 733 def get_cpu_type(default = 'x86') desc = "LIMIT TO CPU TYPE\nShould this packge be limited to certain CPU types?\nEnter 'ppc' or 'x86' or 'none' for neither.\n END_DESC\n prompt_for_data(desc: desc, opt: :cpu_type, default: default, required: true)\nend\n" |
#get_description(current_desc = '') ⇒ String
Get a multiline description from the user using the editor of their choice: nano, vi, emacs, or ENV
352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 |
# File 'lib/d3/admin/interactive.rb', line 352 def get_description(current_desc = '') # do we have a current desc to display and possibly keep? current_desc_review = '' unless current_desc.to_s.empty? current_desc_review = "\n----- Current Description -----\n#{current_desc}\n-------------------------------\n\n" end if prefd_editor = D3::Admin::Prefs.prefs[:editor] prefd_editor_choice = "\n - 'e' to edit using '#{prefd_editor}' " else prefd_editor_choice = '' end # the blurb to show the user input_desc = "DESCRIPTION\nCreate a multi-line description of this package:\n - what does the installed thing do?\n - where did it come from, where to get updates?\n - who maintains it in your environment?\n - any other info useful to d3 and Jamf Pro admins.\n(don't just say \"installs foo\" when \"foo\" is the basename)\n \#{current_desc_review}Enter:\#{prefd_editor_choice}\n - 'n' to edit using 'nano'\n - 'v' to edit using 'vi' or 'vim'\n - 'm' to edit using 'emacs'\n - 'b' to have a blank description\nAnything else will edit with the EDITOR for your environment\nor '\#{DFT_EDITOR}' if none is set.\n END_DESC\n\n # show it, get response\n puts input_desc\n choice = Readline.readline('Your choice (hit return to keep current desc.): ', false)\n\n # keep or empty?\n return current_desc if choice.empty?\n\n return '' if choice.casecmp('b').zero?\n\n # make a tem file, save current into it\n desc_tmp_file = Pathname.new Tempfile.new('d3_description_')\n desc_tmp_file.jss_save current_desc\n\n # which editor?\n if choice.casecmp('e').zero?\n cmd = prefd_editor\n elsif choice.casecmp('v').zero?\n cmd = '/usr/bin/vim'\n elsif choice.casecmp('m').zero?\n cmd = '/usr/bin/emacs'\n elsif choice.casecmp('n').zero?\n cmd = '/usr/bin/nano -L'\n else\n cmd = ENV['EDITOR']\n end\n cmd ||= DFT_EDITOR\n\n system \"\#{cmd} '\#{desc_tmp_file}'\"\n\n result = desc_tmp_file.read.chomp\n desc_tmp_file.delete\n result.chomp\nend\n" |
#get_editor(default = '/usr/bin/nano') ⇒ String
get the shell command for editing package descriptions
990 991 992 993 994 995 996 997 998 999 1000 1001 1002 |
# File 'lib/d3/admin/interactive.rb', line 990 def get_editor(default = '/usr/bin/nano') desc = "EDITOR\nEnter the shell command to use during --walkthru\nfor editing package descriptions\ne.g. /usr/bin/vim, /usr/bin/emacs\n\nNote: if the command launches a GUI editor, make sure the\nshell command stays running until the document is closed.\nMost such editors have an option for that.\n" prompt_for_data(desc: desc, default: default, prompt: 'Command', required: true) end |
#get_excluded_groups(default = nil) ⇒ Object
Prompt the admin for one or more auto-groups for this installer
651 652 653 654 655 656 657 658 659 |
# File 'lib/d3/admin/interactive.rb', line 651 def get_excluded_groups(default = nil) desc = "EXCLUDED GROUPS\nEnter a comma-separated list of JSS Computer Group names\nwhose members should not get this installed without force.\nEnter 'v' to view list of computer groups.\n END_PROMPT\n get_groups desc, :excluded_groups, default\nend\n" |
#get_existing_package(default = nil) ⇒ String?
Ask the user for an edition or basename of an existing package.
225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 |
# File 'lib/d3/admin/interactive.rb', line 225 def get_existing_package(default = nil) desc = "EXISTING PACKAGE\nEnter a package edition or basename for an existing d3 package.\nIf a basename, the currently live package for that basename will be used.\nEnter:\n - 'v' to view a list of all packages with the basenames and editions in d3.\n END_DESC\n\n input = 'v'\n while input == 'v'\n input = prompt_for_data(desc: desc, prompt: 'Edition or Basename', default: default, required: true)\n D3::Admin::Report.show_all_basenames_and_editions if input == 'v'\n end\n input\nend\n" |
#get_expiration(default = 0) ⇒ Integer
Get an expiration period (# of days) from the user
852 853 854 855 856 857 858 859 860 861 862 |
# File 'lib/d3/admin/interactive.rb', line 852 def get_expiration(default = 0) desc = "EXPIRATION\nOn machines that allow package expiration,\nshould this package be removed after some\nnumber of days without being used?\nEnter the number of days, or 0 for no expiration.\n END_DESC\n\n prompt_for_data(desc: desc, prompt: 'Expiration days', default: default, required: true)\nend\n" |
#get_expiration_paths(default = 'n') ⇒ Array<Pathname>
Get the path to the executable(s) to monitor for expiration
870 871 872 873 874 875 876 877 878 879 880 |
# File 'lib/d3/admin/interactive.rb', line 870 def get_expiration_paths(default = 'n') desc = "EXPIRATION PATH(S)\nEnter the path(s) to the executable(s) that must be used\nto prevent expiration. Multiple paths should be separated by commas, spaces\nshould not be escaped. E.g.\n/Applications/Google Chrome.app/Contents/MacOS/Google Chrome, /Applications/Firefox.app/Contents/MacOS/firefox\nEnter 'n' for none\n END_DESC\n prompt_for_data(desc: desc, prompt: 'Expiration Path(s)', default: default, required: true)\nend\n" |
#get_filename(default = nil) ⇒ Object
get a package name from user
297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 |
# File 'lib/d3/admin/interactive.rb', line 297 def get_filename(default = nil) desc = "INSTALLER FILENAME\nEnter a unique name for this package's installer file\non the master distribution point. The file will be\nrenamed to this name on the distribution point.\nEnter 'v' to see a list of existing pkg filenames in the JSS\n END_DESC\n input = 'v'\n while input == 'v'\n input = prompt_for_data(opt: :filename, desc: desc, default: default, required: true)\n D3::Admin::Report.show_existing_package_ids if input == 'v'\n end\n input\nend\n" |
#get_groups(desc, opt, default = nil) ⇒ String?
Prompt the admin for one or more groups
701 702 703 704 705 706 707 708 |
# File 'lib/d3/admin/interactive.rb', line 701 def get_groups(desc, opt, default = nil) result = 'v' while result == 'v' result = prompt_for_data(opt: opt, desc: desc, default: default, required: true) D3.less_text JSS::ComputerGroup.all_names.sort_by(&:downcase).join("\n") if result == 'v' end result end |
#get_jss_package_for_import(default = nil) ⇒ String
Ask the user for an id or name of an existing JSS package to import into d3
247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 |
# File 'lib/d3/admin/interactive.rb', line 247 def get_jss_package_for_import(default = nil) desc = "IMPORT JSS PACKAGE\nEnter a package id or display-name for\nan existing JSS package to import into d3.\nEnter:\n - 'v' to view a list of all JSS package names not in d3.\n END_DESC\n\n input = 'v'\n while input == 'v'\n input = prompt_for_data(desc: desc, prompt: 'JSS id or display name', default: default, required: true)\n D3::Admin::Report.show_pkgs_available_for_import if input == 'v'\n end\n input\nend\n" |
#get_keep_in_jss(default = 'n') ⇒ String
when deleting a pkg, should it be kept in the JSS?
907 908 909 910 911 912 913 914 915 |
# File 'lib/d3/admin/interactive.rb', line 907 def get_keep_in_jss(default = 'n') desc = "KEEP THE PACKAGE IN JAMF PRO?\nWhen deleting a package, should it be kept as a Jamf Pro package\nand only deleted from d3?\nEnter 'y' or 'n'\n END_DESC\n prompt_for_data(desc: desc, prompt: 'Keep in JSS? (y/n)', default: default, required: true)\nend\n" |
#get_keep_scripts(default = 'n') ⇒ String
when deleting a pkg, should its pre- and post- scripts be kept?
888 889 890 891 892 893 894 895 896 897 898 899 |
# File 'lib/d3/admin/interactive.rb', line 888 def get_keep_scripts(default = 'n') desc = "KEEP ASSOCIATED SCRIPTS IN JAMF PRO?\nWhen deleting a package, should any associated scripts\n(pre-install, post-install, pre-remove, post-remove) be kept in Jamf Pro?\n\nNOTE: If any other d3 packages or policies are using the scripts\nthey won't be deleted. The other users of the scripts will be reported.\nEnter 'y' or 'n'\n END_DESC\n prompt_for_data(desc: desc, prompt: 'Delete Scripts? (y/n)', default: default, required: true)\nend\n" |
#get_menu_choice(header, items) ⇒ Integer, String
Display a menu of numbered choices, and return the user’s choice, or ‘x’ if the user is done choosing.
64 65 66 67 68 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 97 98 |
# File 'lib/d3/admin/interactive.rb', line 64 def (header, items) # add a 1-based number and ) to the start of each line, like 1), and 2)... items.each_index { |i| items[i] = "#{i + 1}) #{items[i]}" } = items.count = "(1-#{menu_count}, x=done, ^c=cancel)" = "#{header}\n#{items.join("\n")}" # clear the screen between displays of the menu, so its always at the top. system 'clear' or system 'cls' puts choice = '' while choice == '' choice = Readline.readline("Which to change? #{menu_count_display}: ", false) break if choice == 'x' # they chose a number.. if choice =~ /^\d+$/ # map it to one of the editing options choice = choice.to_i - 1 # but they might have chosen a higher number than allowws choice = '' unless (0..( - 1)).cover? choice else choice = '' end # tell them they made a bad choice if choice == '' puts "\n******* Sorry, invalid choice.\n" next end end # while choice == "" choice end |
#get_oses(default = []) ⇒ String?
Get a list of allowed OSes for this pkg
717 718 719 720 721 722 723 724 725 |
# File 'lib/d3/admin/interactive.rb', line 717 def get_oses(default = []) desc = "LIMIT TO OS's\nEnter a comma-separated list of OS's allowed to\ninstall this package, e.g. '10.8.5, 10.9.5, 10.10.x'\nUse '>=' to set a minimum OS, e.g. '>=10.8.5'\n END_DESC\n prompt_for_data(desc: desc, opt: :oses, default: default, required: true)\nend\n" |
#get_package_build_type(default = D3::Admin::DFT_PKG_TYPE) ⇒ Symbol
If we’re builting a pkg, should we build a .pkg, or a .dmg?
438 439 440 441 442 443 444 445 |
# File 'lib/d3/admin/interactive.rb', line 438 def get_package_build_type(default = D3::Admin::DFT_PKG_TYPE) desc = "PACKAGE BUILD TYPE\nLooks like we need to build the installer from a package-root.\nShould we build a .pkg or .dmg? ( p = pkg, d = dmg )\n END_DESC\n prompt_for_data(opt: :package_build_type, desc: desc, default: default, required: true)\nend\n" |
#get_package_name(default = nil) ⇒ Object
get a package name from user
282 283 284 285 286 287 288 289 290 291 292 293 294 |
# File 'lib/d3/admin/interactive.rb', line 282 def get_package_name(default = nil) desc = "JSS PACKAGE NAME\nEnter a unique name for this package in d3 and Jamf Pro.\nEnter 'v' to view a list of package names currently in d3.\n END_DESC\n input = 'v'\n while input == 'v'\n input = prompt_for_data(opt: :package_name, desc: desc, default: default, required: true)\n D3::Admin::Report.show_existing_package_ids if input == 'v'\n end\n input\nend\n" |
#get_pkg_identifier(default = nil) ⇒ String
Get the pkg identifier for building .pkgs
453 454 455 456 457 458 459 460 |
# File 'lib/d3/admin/interactive.rb', line 453 def get_pkg_identifier(default = nil) desc = "PKG IDENTIFIER\nEnter the Apple .pkg indentifier for building a .pkg.\nE.g. com.mycompany.myapp\n END_DESC\n prompt_for_data(opt: :pkg_identifier_prefix, desc: desc, default: default, required: true)\nend\n" |
#get_pkg_identifier_prefix(default = D3::Admin::DFT_PKG_ID_PREFIX) ⇒ String
Get the pkg identifier prefex for building .pkgs When building .pkgs, this string is prefixed to the basename to create the Apple Pkg identifier. For example if the value is com.pixar.d3, then when building a pkg with the basename “foo” the identifier will be com.pixar.d3.foo
This value is saved in the admin prefs for future use.
475 476 477 478 479 480 481 482 483 |
# File 'lib/d3/admin/interactive.rb', line 475 def get_pkg_identifier_prefix(default = D3::Admin::DFT_PKG_ID_PREFIX) desc = "PKG IDENTIFIER PREFIX\nEnter the prefix to prepend to a basename to create an Apple .pkg indentifier.\nE.g. If you enter 'com.mycompany', then when you build a .pkg with basename 'foo'\nthe default .pkg identifier will be 'com.mycompany.foo'\n END_DESC\n prompt_for_data(opt: :pkg_identifier_prefix, desc: desc, default: default, required: true)\nend\n" |
#get_pkg_preserve_owners(default = 'n') ⇒ String
Ask if the pkg should preserve source ownership, or apply OS defaults
548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 |
# File 'lib/d3/admin/interactive.rb', line 548 def get_pkg_preserve_owners(default = 'n') desc = "PRESERVE SOURCE OWNERSHIP\nWhen building a .pkg, the OS generally sets the ownership and permissions\nof the payload to match OS standards, e.g. Apps owned by 'root' with group\n'admin' or 'wheel'\n\nIf desired you can preserve the current ownership and permissions of the source\nfolder contents when the payload is installed. This is generally not recomended.\n\nShould we override the OS and preserve the ownership on\nthe source folder when the item is installed on the client?\nEnter 'y' or 'n'\n END_DESC\n prompt_for_data(desc: desc, prompt: 'Preserve ownership (y/n)', default: default, required: true)\nend\n" |
#get_post_install_script(default = nil) ⇒ Pathname, ...
Get a post-install script, either local file, JSS id, or JSS name
583 584 585 |
# File 'lib/d3/admin/interactive.rb', line 583 def get_post_install_script(default = nil) get_script 'POST-INSTALL SCRIPT', :post_install, default end |
#get_post_remove_script(default = nil) ⇒ Pathname, ...
Get a post-remove script, either local file, JSS id, or JSS name
605 606 607 |
# File 'lib/d3/admin/interactive.rb', line 605 def get_post_remove_script(default = nil) get_script 'POST-REMOVE SCRIPT', :post_remove, default end |
#get_pre_install_script(default = nil) ⇒ Pathname, ...
Get a pre-install script, either local file, JSS id, or JSS name
572 573 574 |
# File 'lib/d3/admin/interactive.rb', line 572 def get_pre_install_script(default = nil) get_script 'PRE-INSTALL SCRIPT', :pre_install, default end |
#get_pre_remove_script(default = nil) ⇒ Pathname, ...
Get a pre-remove script, either local file, JSS id, or JSS name
594 595 596 |
# File 'lib/d3/admin/interactive.rb', line 594 def get_pre_remove_script(default = nil) get_script 'PRE-REMOVE SCRIPT', :pre_remove, default end |
#get_prohibiting_processes(default = 'n') ⇒ Regexp?
Get a pattern to match for the prohibiting processes If this matches a line of output from ‘/bin/ps -A -c -o comm` at install time, then graceful quit will be attempted. Strings must match a whole line, Regexps will work with any match.
776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 |
# File 'lib/d3/admin/interactive.rb', line 776 def get_prohibiting_processes(default = 'n') desc = "PROHIBITING PROCESSES\nEnter a comma separated string of process name(s) as they appear in the\nof the output of `/bin/ps -A -c -o comm`.\n\nExample: Safari, Google Chrome, cfprefsd\n\nIf a process is running at install time, the installer will\nquit any background processes automatically, and may prompt the user\nto quit GUI applications gracefully. Matching is case sensitive.\n\nEnter 'n' for none.\n END_DESC\n\n result = prompt_for_data(desc: desc, prompt: 'Prohibiting Processes', opt: :prohibiting_processes, default: default, required: true)\n return nil if result == 'n'\n result\nend\n" |
#get_reboot(default = 'n') ⇒ String
Ask if this package needs a reboot
834 835 836 837 838 839 840 841 842 843 844 |
# File 'lib/d3/admin/interactive.rb', line 834 def get_reboot(default = 'n') desc = "REBOOT REQUIRED (PUPPIES!)\nDoes this package require a reboot after installation?\nIf so, it will be added to the Puppy Queue when installed\nwith 'd3 install', and the user will be notified to log\nout as soon as possible.\nEnter 'y' or 'n'\n END_DESC\n prompt_for_data(desc: desc, prompt: 'Requires reboot? (y/n)', default: default, required: true)\nend\n" |
#get_removable(default = 'y') ⇒ String
Ask if this package is uninstallable
802 803 804 805 806 807 808 809 |
# File 'lib/d3/admin/interactive.rb', line 802 def get_removable(default = 'y') desc = "REMOVABLE\nCan this package be uninstalled?\nEnter 'y' or 'n'\n END_DESC\n prompt_for_data(desc: desc, prompt: 'Removable? (y/n)', default: default, required: true)\nend\n" |
#get_remove_first(default = 'y') ⇒ String
Ask if we should ininstall older versions of this basename before installing this one
818 819 820 821 822 823 824 825 826 |
# File 'lib/d3/admin/interactive.rb', line 818 def get_remove_first(default = 'y') desc = "UNINSTALL OLDER VERSIONS\nShould older versions of this basename be uninstalled\n(if they are removable) before attempting to install this package?\nEnter 'y' or 'n'\n END_DESC\n prompt_for_data(desc: desc, prompt: 'Remove older installs first? (y/n)', default: default, required: true)\nend\n" |
#get_revision(default = nil) ⇒ String
Get a revision from the user
334 335 336 337 338 339 340 341 342 343 |
# File 'lib/d3/admin/interactive.rb', line 334 def get_revision(default = nil) desc = "REVISION\nEnter a Package revision for this package.\nThis is an integer representing a new packaging of\nan existing version of a given basename.\n END_DESC\n\n prompt_for_data(opt: :revision, desc: desc, default: default, required: true)\nend\n" |
#get_script(heading, opt, default = nil) ⇒ Pathname, ...
Get a script, either local file, JSS id, or JSS name
616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 |
# File 'lib/d3/admin/interactive.rb', line 616 def get_script(heading, opt, default = nil) desc = "\#{heading}\nEnter a path to a local file containing the script\nor the name or id of an existing script in the JSS.\nEnter 'v' to view a list of scripts in the JSS.\n END_DESC\n\n result = 'v'\n while result == 'v'\n result = prompt_for_data(opt: opt, desc: desc, default: default, required: true)\n D3.less_text JSS::Script.all_names.sort_by(&:downcase).join(\"\\n\") if result == 'v'\n end\n result\nend\n" |
#get_search_target(default = false) ⇒ String
Prompt the admin for text to search for package searchs
665 666 667 668 669 670 671 672 673 674 675 |
# File 'lib/d3/admin/interactive.rb', line 665 def get_search_target(default = false) desc = "SEARCH TEXT\nEnter text to use in matching basenames or computer group names.\nMatching a basename will list all packages with the basename.\nMatching a group name will list all packages auto-installed or\nexcluded for the group. (RegExp's OK)\nEnter 'all' to list all packages in d3.\n END_PROMPT\n prompt_for_data(desc: desc, prompt: \"Text to match or 'all'\").chomp\nend\n" |
#get_show_type(default = D3::Admin::Report::DFT_SHOW_TYPE) ⇒ String
what kind of package list are we showing?
923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 |
# File 'lib/d3/admin/interactive.rb', line 923 def get_show_type(default = D3::Admin::Report::DFT_SHOW_TYPE) desc = "SERVER PACKAGE LIST\nEnter the type of list you'd like to generate about packages in d3.\n\nOne of:\n all - all packages in d3\n pilot - packages newer than live\n live - live packages\n deprecated - old packages that used to be live\n skipped - old packages that were never made live\n missing - packages in d3, but not Jamf Pro\n auto - packages auto-installed for a given computer group\n excluded - packages not available to a given computer group\n" prompt_for_data(desc: desc, prompt: 'Show packages', default: default, required: true) end |
#get_signing_identity(default = ) ⇒ String
Get the optional Apple Developer signing ID .pkgs can be codesigned with a certificate from Apple The Developer ID Installer certificate must be in the login.keychain of the user operating d3admin unless otherwise specified in signing_options
This value is saved in the admin prefs for future use.
497 498 499 500 501 502 503 504 505 |
# File 'lib/d3/admin/interactive.rb', line 497 def get_signing_identity(default = D3::Admin::Prefs.prefs[:signing_identity]) desc = "SIGNING IDENTITY\nEnter the common name of your Apple Developer signing ID to create signed Apple .pkgs.\nE.g. If you enter 'Developer ID Installer: My Company (A12BC34DE56)', then that string will be passed\nas the option for pkgbuild --sign. D3 will not attempt to sign unless this option is set.'\n END_DESC\n prompt_for_data(opt: :signing_identity, desc: desc, default: default, required: false)\nend\n" |
#get_signing_options(default = ) ⇒ String
Get any arguments and options to pass to pkgbuild A signing identity must be defined for these options to be used.
This value is saved in the admin prefs for future use.
516 517 518 519 520 521 522 523 |
# File 'lib/d3/admin/interactive.rb', line 516 def (default = D3::Admin::Prefs.prefs[:signing_options]) desc = "SIGNING OPTIONS\nEnter optional arguments and options to pass to pkgbuild. These options are ignored unless a signing identity is defined.\nE.g. --keychain '/Users/d3/Library/Keychain' --cert 'My Awesome Authority' --timestamp\n END_DESC\n prompt_for_data(opt: :signing_options, desc: desc, default: default, required: false)\nend\n" |
#get_source_path(default = false) ⇒ Pathname
Get the local path to the package being added to d3 Also sets @build_installer, and @build_installer_type if the source is a root-folder rather than a .pkg or .dmg
422 423 424 425 426 427 428 429 430 431 432 |
# File 'lib/d3/admin/interactive.rb', line 422 def get_source_path(default = false) desc = "SOURCE\nEnter the path to a .pkg or .dmg installer\nor a 'root' folder from which to build one.\n" # dragging in items from the finder will esacpe spaces in the path with \'s # in the shell this is good, but ruby is interpreting the \'s, so lets remove them. prompt_for_data(opt: :source_path, desc: desc, default: default, required: true).strip.gsub(/\\ /, ' ') end |
#get_status_for_filter(with_frozen = false) ⇒ Object
get auto
677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 |
# File 'lib/d3/admin/interactive.rb', line 677 def get_status_for_filter(with_frozen = false) if with_frozen frozen_line = "\nUse 'frozen' to limit to frozen receipts" frozen_title = 'OR FROZEN' else frozen_line = '' frozen_title = '' end desc = "LIMIT TO STATUS\#{frozen_title}\nEnter a comma-separate list of statuses for limiting the list.\nValid Statuses are: \#{D3::Basename::STATUSES_FOR_FILTERS.join(', ')}\#{frozen_line}\nEnter 'all' to show all statuses\n END_PROMPT\n prompt_for_data(desc: desc, prompt: 'Statuses', default: 'all').chomp\nend\n" |
#get_value(option_or_get_method, default = nil, validate_method = nil) ⇒ Object
Call one of the get_ methods and do the matching validity check, if desired, repeatedly until a valid value is supplied.
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 |
# File 'lib/d3/admin/interactive.rb', line 115 def get_value(option_or_get_method, default = nil, validate_method = nil) # if the option_or_get_method is one of the keys in OPTIONS, then use OPTIONS[get_method][:get] if it exists if D3::Admin::OPTIONS.keys.include?(option_or_get_method) get_method = D3::Admin::OPTIONS[option_or_get_method][:get] # if we weren't giving a validate method, get it from the OPTIONS validate_method ||= D3::Admin::OPTIONS[option_or_get_method][:validate] end # otherwise we should have been given a symbolic method name. get_method ||= option_or_get_method valid = :start validated = nil until valid === true # Keep the ===, trust me. Don't listen to rubocop. puts "\nSorry: #{validated}, Try again.\n" unless valid === :start value_input = self.send get_method, default # no check method? just return the value return value_input if validate_method.nil? (valid, validated) = D3::Admin::Validate.validate(value_input, validate_method) end # until valid === true validated end |
#get_version(default = nil) ⇒ String
Get a version from the user
318 319 320 321 322 323 324 325 326 |
# File 'lib/d3/admin/interactive.rb', line 318 def get_version(default = nil) desc = "VERSION\nEnter a version for this package.\nAll spaces will be converted to underscores.\n END_DESC\n\n prompt_for_data(opt: :version, desc: desc, default: default, required: true)\nend\n" |
#get_workspace(default = ) ⇒ Pathname
Get the desired local workspace for building pkgs Defaults to ENV
532 533 534 535 536 537 538 539 |
# File 'lib/d3/admin/interactive.rb', line 532 def get_workspace(default = ENV['HOME']) desc = "PACKAGE BUILD WORKSPACE\nEnter the path to a folder where we can build packages.\nThis will be stored between uses of d3admin.\n END_DESC\n Pathname.new prompt_for_data(opt: :workspace, desc: desc, default: default, required: true)\nend\n" |
#prompt_for_data(desc: nil, prompt: nil, opt: nil, default: :no_default, required: true) ⇒ String
Prompt for user input for an option and return the response.
A Description of the option is displayed, followed by a prompt. If a default value is provided, the prompt includes the text
(Hit return for #{default_value})
If the option is defined in D3::Admin::OPTIONS, the data for the option is used, if not provided in the args.
If the option is defined as unsettable, a line “Enter ‘n’ for none.” is also displayed before the prompt and a value of ‘n’ will cause the method to return nil.
If no prompt is given in the args, the :label is used from D3::Admin::OPTIONS
If no default value is given in the args, the one from D3::Admin::OPTIONS is used. If required is true, the input can’t be an empty string.
Note: watch out for nil vs false in default values
179 180 181 182 183 184 185 186 187 188 189 190 191 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 |
# File 'lib/d3/admin/interactive.rb', line 179 def prompt_for_data(desc: nil, prompt: nil, opt: nil, default: :no_default, required: true) unset_line = nil default_display = default # look up some info about this option, if needed if opt opt_def = D3::Admin::OPTIONS[opt] if opt_def prompt ||= opt_def[:label] unset_line = "Enter '#{UNSET}' for none." if opt_def[:unsetable] default = opt_def[:default] if opt_def[:default] and default == :no_default default_display = opt_def[:display_conversion].call(default) if opt_def[:display_conversion] end end # if args[:opt] # some values are special for displaying default_display = case default_display when :no_default then '' when D3::Admin::DFT_REQUIRED then '' # the '---Required---' should only be visible in the menu, not the prompt when D3::Admin::DFT_NONE then UNSET else default_display.to_s end data_entered = '' puts "\n#{desc}" if desc prompt ||= 'Please enter a value' hit_return = default_display.empty? ? '' : " (Hit return for '#{default_display}' )" prompt_line = "#{prompt}#{hit_return}: " while true do data_entered = Readline.readline(prompt_line, false) data_entered = default_display if data_entered == '' break unless required && data_entered.empty? end # if 'n' was typed for an unsettable option, return nil return nil if opt_def && opt_def[:unsetable] && data_entered == UNSET data_entered.strip end |