Class: QB::Role
- Inherits:
-
Object
- Object
- QB::Role
- Includes:
- SemanticLogger::Loggable
- Defined in:
- lib/qb/role.rb,
lib/qb/role/name.rb,
lib/qb/role/errors.rb,
lib/qb/role/matches.rb,
lib/qb/role/default_dir.rb,
lib/qb/role/search_path.rb
Overview
Definitions
Defined Under Namespace
Classes: MetadataError, MultipleMatchesError, NoMatchesError
Constant Summary collapse
- BUILTIN_PATH =
"Factory defaults" that PATH is initialized to, and what it gets reset to when reset_path! is called.
Read the PATH docs for details on how QB role paths work.
This value is deeply frozen, and you should not attempt to change it - mess with PATH instead.
[ # Development Paths # ================= # # These come first because: # # 1. They are working dir-local. # # 2. They should only be present in local development, and should be # capable of overriding roles in other local directories to allow # custom development behavior (the same way `./dev/bin` is put in # front or `./bin`). # # Role paths declared in ./dev/ansible.cfg, if it exists. File.join('.', 'dev', 'ansible.cfg'), # Roles in ./dev/roles File.join('.', 'dev', 'roles'), # Working Directory Paths # ======================= # # Next up, `ansible.cfg` and `roles` directory in the working dir. # Makes sense, right? # # ./ansible.cfg File.join('.', 'ansible.cfg'), # ./roles File.join('.', 'roles'), # Working Directory-Local Ansible Directory # ========================================= # # `ansible.cfg` and `roles` in a `./ansible` directory, making a common # place to put Ansible stuff in an project accessible when running from # the project root. # # ./ansible/ansible.cfg File.join('.', 'ansible', 'ansible.cfg'), # ./ansible/roles File.join('.', 'ansible', 'roles'), # TODO Git repo root relative? # Some sort of flag file for a find-up? # System Ansible locations? # QB Gem Role Directories # ======================= # # Last, but far from least, paths provided by the QB Gem to the user's # QB role install location and the roles that come built-in to the gem. QB::USER_ROLES_DIR, QB::GEM_ROLES_DIR, ].freeze
- PATH =
Array of string paths to directories to search for roles or paths to
ansible.cfg
files to look for an extract role paths from.Value is a duplicate of the frozen BUILTIN_PATH. You can reset to those values at any time via reset_path!.
For the moment at least you can just mutate this value like you would
$LOAD_PATH
:QB::Role::PATH.unshift '~/where/some/roles/be' QB::Role::PATH.unshift '~/my/ansible.cfg'
The paths are searched from first to last.
WARNING
Search is deep - don't point this at large directory trees and expect any sort of reasonable performance (any directory that contains
node_modules
is usually a terrible idea for instance). BUILTIN_PATH.dup
Instance Attribute Summary collapse
-
#display_path ⇒ Object
readonly
the path to the role that we display.
-
#meta_path ⇒ Object
readonly
Returns the value of attribute meta_path.
-
#name ⇒ Object
readonly
Returns the value of attribute name.
-
#path ⇒ Object
readonly
Returns the value of attribute path.
Class Method Summary collapse
-
.available ⇒ Array<QB::Role>
All Role found in search path.
-
.default_name_for(path) ⇒ String
Do our best to figure out a role name from a path (that might not exist).
-
.get_include_path(role, option_meta, current_include_path) ⇒ Array<string>
Get the include path for an included role based on the option metadata that defines the include and the current include path.
-
.matches(input) ⇒ Array<QB::Role>
Get an array of Role that match an input string.
- .namespace_for(name) ⇒ Object
- .namespaceless_for(name) ⇒ Object
-
.require(input) ⇒ QB::Role
Find exactly one matching role for the input string or raise.
-
.reset_path! ⇒ Array<String>
Reset PATH to the original built-in values in BUILTIN_PATH.
-
.role_dir?(pathname) ⇒ Boolean
true if pathname is a QB role directory.
-
.search_path ⇒ Array<Pathname>
Gets the array of paths to search for QB roles based on PATH and the working directory at the time it's called.
-
.to_display_path(path) ⇒ Pathname
The path we display in the CLI, see #display_path.
Instance Method Summary collapse
- #==(other) ⇒ Object (also: #eql?)
-
#ask_vault_pass? ⇒ Boolean
should qb ask for an ansible vault password?.
-
#banner ⇒ Object
get the CLI banner for the role.
-
#check_requirements ⇒ nil
Check the role's requirements.
-
#default_ansible_options ⇒ Hash<String, *>
Default
ansible-playbook
CLI options from role qb metadata. -
#default_dir(cwd, options) ⇒ Pathname
Gets the default
qb_dir
value, raising an error if the role doesn't define how to get one or there is a problem getting it. -
#defaults ⇒ Object
gets the role variable defaults from defaults/main.yml, or {}.
-
#description ⇒ String
The
description
value from the role's QB metadata, or '' if it doesn't have one. -
#display_name ⇒ Object
Just a string version of #display_path.
- #examples ⇒ Object
-
#format_examples ⇒ String
format the
meta.examples
hash into a string suitable for cli output. -
#has_dir_arg? ⇒ Boolean
Test if the Role uses a directory argument (that gets assigned to the
qb_dir
variable in Ansible). -
#hash ⇒ Object
Language Inter-Op -----------------------------------------------------------------------.
-
#initialize(path, search_dir: nil) ⇒ Role
constructor
Instantiate a Role.
-
#load_defaults(cache = true) ⇒ Object
loads the defaults from vars/main.yml and defaults/main.yml, caching by default.
-
#load_meta(cache = true) ⇒ Object
load qb metadata from meta/qb.yml or from executing meta/qb and parsing the YAML written to stdout.
-
#meta ⇒ Hash{String => Object}
The QB metadata for the role.
-
#mkdir ⇒ Object
if the exe should auto-make the directory.
-
#namespace ⇒ Object
Instance Methods ============================================================================.
- #namespaceless ⇒ Object
-
#option_metas ⇒ Object
get the options from the metadata, defaulting to [] if none defined.
-
#options(include_path = []) ⇒ Array<QB::Options::Option> an array of Option for the role, including any included roles.
ArrayQB::Options::Option an array of Option for the role, including any included roles.
- #options_key ⇒ Object
-
#puts_examples ⇒ Object
examples text.
-
#requirements ⇒ Hash
Parsed tree structure of version requirements of the role from the
requirements
value in the QB meta data. - #save_options ⇒ Object
-
#summary ⇒ String
Short summary pulled from the role description - first line if it's multi-line, or first sentence if it's a single line.
- #to_s ⇒ String
-
#usage ⇒ String
Usage information formatted as plain text for the CLI.
-
#var_prefix ⇒ Object
gets the variable prefix that will be appended to cli options before passing them to the role.
Constructor Details
#initialize(path, search_dir: nil) ⇒ Role
Instantiate a Role.
216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 |
# File 'lib/qb/role.rb', line 216 def initialize path, search_dir: nil @path = if path.is_a?(Pathname) then path else Pathname.new(path) end # check it... unless @path.exist? raise Errno::ENOENT.new @path.to_s end unless @path.directory? raise Errno::ENOTDIR.new @path.to_s end @display_path = self.class.to_display_path @path @meta_path = if (@path + 'meta' + 'qb').exist? @path + 'meta' + 'qb' elsif (@path + 'meta' + 'qb.yml').exist? @path + 'meta' + 'qb.yml' else raise Errno::ENOENT.new "#{ @path.join('meta').to_s }/[qb|qb.yml]" end if search_dir.nil? @name = @path.to_s.split(File::SEPARATOR).last else @name = @path.relative_path_from(search_dir).to_s end end |
Instance Attribute Details
#display_path ⇒ Object (readonly)
the path to the role that we display. we only show the directory name
for QB roles, and use Util.compact_path to show .
and ~
for
paths relative to the current directory and home directory, respectively.
@return [Pathname]
193 194 195 |
# File 'lib/qb/role.rb', line 193 def display_path @display_path end |
#meta_path ⇒ Object (readonly)
Returns the value of attribute meta_path.
200 201 202 |
# File 'lib/qb/role.rb', line 200 def @meta_path end |
#name ⇒ Object (readonly)
Returns the value of attribute name.
183 184 185 |
# File 'lib/qb/role.rb', line 183 def name @name end |
#path ⇒ Object (readonly)
Returns the value of attribute path.
177 178 179 |
# File 'lib/qb/role.rb', line 177 def path @path end |
Class Method Details
.available ⇒ Array<QB::Role>
All QB::Role found in search path.
Does it's best to remove duplicates that end up being reached though multiple search paths (happens most in development).
60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 |
# File 'lib/qb/role.rb', line 60 def self.available self.search_path. select {|search_dir| # make sure it's there (and a directory) search_dir.directory? }. map {|search_dir| ['', '.yml', '.yaml'].flat_map { |ext| Pathname.glob(search_dir.join '**', 'meta', "qb#{ ext }"). map {|| [.dirname.dirname, search_dir: search_dir] } } }. flatten( 1 ). map { |args| QB::Role.new *args }. uniq end |
.default_name_for(path) ⇒ String
Do our best to figure out a role name from a path (that might not exist).
We needs this when we're creating a role.
61 62 63 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 99 100 101 |
# File 'lib/qb/role/name.rb', line 61 def self.default_name_for path resolved_path = QB::Util.resolve path # Find the first directory in the search path that contains the path, # if any do. # # It *could* be in more than one in funky situations like overlapping # search paths or link silliness, but that doesn't matter - we consider # the first place we find it to be the relevant once, since the search # path is most-important-first. # search_dir = search_path.find { |pathname| resolved_path.fnmatch? ( pathname / '**' ).to_s } if search_dir.nil? # It's not in any of the search directories # # If it has 'roles' as a segment than use what's after the last occurrence # of that (unless there isn't anything). # segments = resolved_path.to_s.split File::SEPARATOR if index = segments.rindex( 'roles' ) name_segs = segments[( index + 1 )..( -1 )] unless name_segs.empty? return File.join name_segs end end # Ok, that didn't work... just return the basename I guess... return File.basename resolved_path end # it's in the search path, return the relative path from the containing # search dir to the resolved path (string version of it). resolved_path.relative_path_from( search_dir ).to_s end |
.get_include_path(role, option_meta, current_include_path) ⇒ Array<string>
Get the include path for an included role based on the option metadata that defines the include and the current include path.
136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 |
# File 'lib/qb/role.rb', line 136 def self.get_include_path role, , current_include_path new_include_path = if .key? 'as' case ['as'] when nil, false # include it in with the parent role's options current_include_path when String current_include_path + [['as']] else raise QB::Role::MetadataError.new, "bad 'as' value: #{ .inspect }" end else current_include_path + [role.namespaceless] end end |
.matches(input) ⇒ Array<QB::Role>
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 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 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 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 |
# File 'lib/qb/role/matches.rb', line 37 def self.matches input # keep this here to we don't re-gen every loop available = self.available # first off, see if input matches any relative paths exactly available.each {|role| return [role] if role.display_path.to_s == input } # create an array of "separator" variations to try *exact* matching # against. in order of preference: # # 1. exact input # - this means if you ended up with roles that actually *are* # differentiated by '_/-' differences (which, IMHO, is a # horrible fucking idea), you can get exactly what you ask for # as a first priority # 2. input with '-' changed to '_' # - prioritized because convention is to underscore-separate # role names. # 3. input with '_' changed to '-' # - really just for convenience's sake so you don't really have to # remember what separator is used. # separator_variations = [ input, input.gsub('-', '_'), input.gsub('_', '-'), ] # {QB::Role} method names to check against, from highest to lowest # precedence method_names = [ # 1. The path we display to the user. This comes first because typing # in exactly what they see should always work. :display_name, # 2. The role's full name (with namespace) as it is likely to be used # in Ansible :name, # 3. The part of the role after the namespace, which is far less # specific, but nice short-hand if it's unique :namespaceless ] # 1. Exact matches (allowing `-`/`_` substitution) # # Highest precedence, guaranteeing that exact verbatim matches will # always work (or that's the intent). # method_names.each { |method_name| separator_variations.each { |variation| matches = available.select { |role| role.public_send( method_name ) == variation } return matches unless matches.empty? } } # 2. Prefix matches # # Do any of {#display_path}, {#name} or {#namespaceless} or start with # the input pattern? # method_names.each { |method_name| separator_variations.each { |variation| matches = available.select { |role| role.public_send( method_name ).start_with? variation } return matches unless matches.empty? } } # 3. Word slice full matches # # Split the {#display_name} and input first by `/` and `.` segments, # then {String#downcase} each segments and split it into words (using # {NRSER.words}). # # Then see if the input appears in the role name. # # We test only {#display_name} because it should always contain # {#name} and {#namesaceless}, so it's pointless to test the other # two after it). # word_parse = ->( string ) { string.split( /[\/\.]/ ).map { |seg| seg.downcase.words } } input_parse = word_parse.call input exact_word_slice_matches = available.select { |role| word_parse.call( role.display_name ).slice? input_parse } return exact_word_slice_matches unless exact_word_slice_matches.empty? # 4. Word slice prefix matches # # Same thing as (3), but do a prefix match instead of the entire # words. # name_word_matches = available.select { |role| word_parse.call( role.display_name ). slice?( input_parse ) { |role_words, input_words| # Use a custom match block to implement prefix matching # # We want to match if each input word is the start of the # corresponding role name word # if role_words.length >= input_words.length input_words.each_with_index.all? { |input_word, index| role_words[index].start_with? input_word } else false end } QB::Util.words_start_with? role.display_path.to_s, input } return name_word_matches unless name_word_matches.empty? # nada [] end |
.namespace_for(name) ⇒ Object
107 108 109 110 111 112 113 114 115 116 117 |
# File 'lib/qb/role/name.rb', line 107 def self.namespace_for name *namespace_segments, last = name.split File::Separator namespace_segments << last.split('.').first if last.include?('.') if namespace_segments.empty? nil else File.join *namespace_segments end end |
.namespaceless_for(name) ⇒ Object
120 121 122 |
# File 'lib/qb/role/name.rb', line 120 def self.namespaceless_for name File.basename( name ).split('.', 2).last end |
.require(input) ⇒ QB::Role
Find exactly one matching role for the input string or raise.
Where we look is determined by PATH via search_path.
96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 |
# File 'lib/qb/role.rb', line 96 def self.require input as_pathname = Pathname.new(input) # allow a path to a role dir if role_dir? as_pathname return QB::Role.new as_pathname end matches = self.matches input role = case matches.length when 0 raise QB::Role::NoMatchesError.new input when 1 matches[0] else raise QB::Role::MultipleMatchesError.new input, matches end QB.debug "role match" => role role end |
.reset_path! ⇒ Array<String>
Reset PATH to the original built-in values in BUILTIN_PATH.
Created for testing but might be useful elsewhere as well.
139 140 141 142 143 |
# File 'lib/qb/role/search_path.rb', line 139 def self.reset_path! PATH.clear BUILTIN_PATH.each { |path| PATH << path } PATH end |
.role_dir?(pathname) ⇒ Boolean
true if pathname is a QB role directory.
45 46 47 48 49 50 |
# File 'lib/qb/role.rb', line 45 def self.role_dir? pathname # must be a directory pathname.directory? && # and must have meta/qb.yml or meta/qb file ['qb.yml', 'qb'].any? {|filename| pathname.join('meta', filename).file?} end |
.search_path ⇒ Array<Pathname>
Gets the array of paths to search for QB roles based on PATH and the working directory at the time it's called.
QB then uses the returned value to figure out what roles are available.
The process:
Resolve relative paths against the working directory.
Load up any
ansible.cfg
files on the path and add anyroles_path
they define where theansible.cfg
entry was in PATH.
161 162 163 164 165 166 167 168 169 170 171 172 173 174 |
# File 'lib/qb/role/search_path.rb', line 161 def self.search_path QB::Role::PATH. map { |path| if QB::Ansible::ConfigFile.end_with_config_file?(path) if File.file?(path) QB::Ansible::ConfigFile.new(path).defaults.roles_path end else QB::Util.resolve path end }. flatten. reject(&:nil?) end |
.to_display_path(path) ⇒ Pathname
The path we display in the CLI, see #display_path.
162 163 164 165 166 167 168 |
# File 'lib/qb/role.rb', line 162 def self.to_display_path path if path.realpath.start_with? QB::GEM_ROLES_DIR path.realpath.sub (QB::GEM_ROLES_DIR.to_s + '/'), '' else QB::Util.contract_path path end end |
Instance Method Details
#==(other) ⇒ Object Also known as: eql?
585 586 587 |
# File 'lib/qb/role.rb', line 585 def == other other.is_a?(self.class) && other.path.realpath == path.realpath end |
#ask_vault_pass? ⇒ Boolean
should qb ask for an ansible vault password?
479 480 481 |
# File 'lib/qb/role.rb', line 479 def ask_vault_pass? !!@meta['ask_vault_pass'] end |
#banner ⇒ Object
get the CLI banner for the role
411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 |
# File 'lib/qb/role.rb', line 411 def lines = [] name_line = "#{ name } role" lines << name_line lines << "=" * name_line.length lines << '' if ['description'] lines << ['description'] lines << '' end lines << 'Usage:' lines << '' lines << " #{ usage }" lines << '' lines << '' lines.join("\n") end |
#check_requirements ⇒ nil
Check the role's requirements.
528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 |
# File 'lib/qb/role.rb', line 528 def check_requirements if ansible_req = requirements['ansible'] unless ansible_req.satisfied_by? QB.ansible_version raise QB::AnsibleVersionError.squished <<-END QB #{ QB::VERSION } requires Ansible #{ ansible_req }, found version #{ QB.ansible_version } at #{ `which ansible` } END end end if qb_req = requirements.dig( 'gems', 'qb' ) unless qb_req.satisfied_by? QB.gem_version raise QB::QBVersionError.squished <<-END Role #{ self } requires QB #{ qb_req }, using QB #{ QB.gem_version } from #{ QB::ROOT }. END end end nil end |
#default_ansible_options ⇒ Hash<String, *>
Returns default ansible-playbook
CLI options from role qb metadata.
Hash of option name to value.
497 498 499 |
# File 'lib/qb/role.rb', line 497 def 'ansible_options', {} end |
#default_dir(cwd, options) ⇒ Pathname
Gets the default qb_dir
value, raising an error if the role doesn't
define how to get one or there is a problem getting it.
It uses a "strategy" value found at the 'default_dir' key in the role's
QB metadata (in <role_path>/meta/qb.yml
or returned by a
<role_path>/meta/qb
executable).
See the default_dir documentation for details on the accepted strategy values.
71 72 73 74 75 76 77 78 79 80 81 82 83 84 |
# File 'lib/qb/role/default_dir.rb', line 71 def default_dir cwd, logger.debug "CALLING default_dir", role: self.instance_variables.assoc_to { |key| self.instance_variable_get key }, cwd: cwd, options: default_dir_for( strategy: self.['default_dir'], cwd: cwd, options: ).to_pn end |
#defaults ⇒ Object
gets the role variable defaults from defaults/main.yml, or {}
362 363 364 |
# File 'lib/qb/role.rb', line 362 def defaults @defaults || load_defaults end |
#description ⇒ String
Returns The description
value from the role's QB metadata, or '' if it doesn't
have one.
554 555 556 |
# File 'lib/qb/role.rb', line 554 def description ['description'].to_s end |
#display_name ⇒ Object
Just a string version of #display_path
252 253 254 |
# File 'lib/qb/role.rb', line 252 def display_name display_path.to_s end |
#examples ⇒ Object
432 433 434 |
# File 'lib/qb/role.rb', line 432 def examples @meta['examples'] end |
#format_examples ⇒ String
format the meta.examples
hash into a string suitable for cli
output.
442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 |
# File 'lib/qb/role.rb', line 442 def format_examples examples. map {|title, body| [ "#{ title }:", body.lines.map {|l| # only indent non-empty lines # makes compacting newline sequences easier (see below) if l.match(/^\s*$/) l else ' ' + l end }, '' ] }. flatten. join("\n"). # compact newline sequences gsub(/\n\n+/, "\n\n") end |
#has_dir_arg? ⇒ Boolean
Test if the QB::Role uses a directory argument (that gets assigned to
the qb_dir
variable in Ansible).
489 490 491 |
# File 'lib/qb/role.rb', line 489 def has_dir_arg? ['default_dir'] != false end |
#hash ⇒ Object
Language Inter-Op
580 581 582 |
# File 'lib/qb/role.rb', line 580 def hash path.realpath.hash end |
#load_defaults(cache = true) ⇒ Object
loads the defaults from vars/main.yml and defaults/main.yml, caching by default. vars override defaults values.
337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 |
# File 'lib/qb/role.rb', line 337 def load_defaults cache = true defaults_path = @path + 'defaults' + 'main.yml' defaults = if defaults_path.file? YAML.load(defaults_path.read) || {} else {} end vars_path = @path + 'vars' + 'main.yml' vars = if vars_path.file? YAML.load(vars_path.read) || {} else {} end defaults = defaults.merge! vars if cache @defaults = defaults end defaults end |
#load_meta(cache = true) ⇒ Object
load qb metadata from meta/qb.yml or from executing meta/qb and parsing the YAML written to stdout.
if cache
is true caches it as @meta
266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 |
# File 'lib/qb/role.rb', line 266 def cache = true = if @meta_path.extname == '.yml' contents = begin @meta_path.read rescue Exception => error raise QB::Role::MetadataError, "Failed to read metadata file at #{ @meta_path.to_s }, " + "error: #{ error.inspect }" end begin YAML.load(contents) || {} rescue Exception => error raise QB::Role::MetadataError, "Failed to load metadata YAML from #{ @meta_path.to_s }, " + "error: #{ error.inspect }" end else YAML.load(Cmds.out!(@meta_path.realpath.to_s)) || {} end if cache @meta = end end |
#meta ⇒ Hash{String => Object}
Returns the QB metadata for the role.
297 298 299 |
# File 'lib/qb/role.rb', line 297 def @meta || end |
#mkdir ⇒ Object
if the exe should auto-make the directory. this is nice for most roles but some need it to be missing
372 373 374 |
# File 'lib/qb/role.rb', line 372 def mkdir !!('mkdir', true) end |
#namespace ⇒ Object
Instance Methods
128 129 130 |
# File 'lib/qb/role/name.rb', line 128 def namespace self.class.namespace_for @name end |
#namespaceless ⇒ Object
133 134 135 |
# File 'lib/qb/role/name.rb', line 133 def namespaceless self.class.namespaceless_for @name end |
#option_metas ⇒ Object
get the options from the metadata, defaulting to [] if none defined
314 315 316 |
# File 'lib/qb/role.rb', line 314 def ['options', 'opts', 'vars'], [] end |
#options(include_path = []) ⇒ Array<QB::Options::Option> an array of Option for the role, including any included roles.
Returns ArrayQB::Options::Option an array of Option for the role, including any included roles.
322 323 324 325 326 327 328 329 330 331 332 |
# File 'lib/qb/role.rb', line 322 def include_path = [] .map {|| if .key? 'include' role_name = ['include'] role = QB::Role.require role_name role. QB::Role.get_include_path(role, , include_path) else QB::Options::Option.new self, , include_path end }.flatten end |
#options_key ⇒ Object
257 258 259 |
# File 'lib/qb/role.rb', line 257 def display_name end |
#puts_examples ⇒ Object
examples text
466 467 468 469 470 |
# File 'lib/qb/role.rb', line 466 def puts_examples return unless examples puts "\n" + format_examples + "\n" end |
#requirements ⇒ Hash
Parsed tree structure of version requirements of the role from the
requirements
value in the QB meta data.
508 509 510 511 512 513 514 |
# File 'lib/qb/role.rb', line 508 def requirements @requirements ||= NRSER.map_leaves( 'requirements', {'gems' => {}} ) { |key_path, req_str| Gem::Requirement.new req_str } end |
#save_options ⇒ Object
366 367 368 |
# File 'lib/qb/role.rb', line 366 def !!('save_options', true) end |
#summary ⇒ String
Short summary pulled from the role description - first line if it's multi-line, or first sentence if it's a single line.
Will be an empty string if the role doesn't have a description.
566 567 568 569 570 571 572 573 574 |
# File 'lib/qb/role.rb', line 566 def summary description.lines.first.thru { |line| if line line.split( '. ', 2 ).first else '' end } end |
#to_s ⇒ String
Returns #display_path.
595 596 597 |
# File 'lib/qb/role.rb', line 595 def to_s @display_path.to_s end |
#usage ⇒ String
Returns usage information formatted as plain text for the CLI.
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 |
# File 'lib/qb/role.rb', line 379 def usage # Split up options by required and optional. = [] = [] .each { |option| if option.required? << option else << option end } parts = ['qb [run]', name] .each { |option| parts << option.usage } unless .empty? parts << '[OPTIONS]' end if has_dir_arg? parts << 'DIRECTORY' end parts.join ' ' end |
#var_prefix ⇒ Object
gets the variable prefix that will be appended to cli options before
passing them to the role. defaults to #namespaceless
unless specified
in meta.
305 306 307 308 309 310 |
# File 'lib/qb/role.rb', line 305 def var_prefix # ugh, i was generating meta/qb.yml files that set 'var_prefix' to # `null`, but it would be nice to # 'var_prefix', namespaceless end |