Module: MCollective::Util
- Defined in:
- lib/mcollective/util.rb,
lib/mcollective/util/choria.rb,
lib/mcollective/util/playbook.rb,
lib/mcollective/util/natswrapper.rb,
lib/mcollective/util/bolt_support.rb,
lib/mcollective/util/playbook/uses.rb,
lib/mcollective/util/tasks_support.rb,
lib/mcollective/util/playbook/nodes.rb,
lib/mcollective/util/playbook/tasks.rb,
lib/mcollective/util/playbook/inputs.rb,
lib/mcollective/util/playbook/report.rb,
lib/mcollective/util/indifferent_hash.rb,
lib/mcollective/util/tasks_support/cli.rb,
lib/mcollective/util/playbook/tasks/base.rb,
lib/mcollective/util/playbook/data_stores.rb,
lib/mcollective/util/playbook/task_result.rb,
lib/mcollective/util/playbook/puppet_logger.rb,
lib/mcollective/util/playbook/template_util.rb,
lib/mcollective/util/bolt_support/plan_runner.rb,
lib/mcollective/util/bolt_support/task_result.rb,
lib/mcollective/util/playbook/nodes/pql_nodes.rb,
lib/mcollective/util/playbook/playbook_logger.rb,
lib/mcollective/util/bolt_support/task_results.rb,
lib/mcollective/util/playbook/data_stores/base.rb,
lib/mcollective/util/playbook/nodes/yaml_nodes.rb,
lib/mcollective/util/playbook/tasks/shell_task.rb,
lib/mcollective/util/playbook/tasks/slack_task.rb,
lib/mcollective/util/playbook/nodes/shell_nodes.rb,
lib/mcollective/util/playbook/tasks/webhook_task.rb,
lib/mcollective/util/tasks_support/json_formatter.rb,
lib/mcollective/util/playbook/nodes/terraform_nodes.rb,
lib/mcollective/util/playbook/tasks/mcollective_task.rb,
lib/mcollective/util/tasks_support/default_formatter.rb,
lib/mcollective/util/playbook/nodes/mcollective_nodes.rb,
lib/mcollective/util/playbook/tasks/graphite_event_task.rb,
lib/mcollective/util/playbook/data_stores/etcd_data_store.rb,
lib/mcollective/util/playbook/data_stores/file_data_store.rb,
lib/mcollective/util/playbook/data_stores/shell_data_store.rb,
lib/mcollective/util/playbook/data_stores/consul_data_store.rb,
lib/mcollective/util/playbook/data_stores/environment_data_store.rb
Overview
Some basic utility helper methods useful to clients, agents, runner etc.
Defined Under Namespace
Classes: BoltSupport, Choria, IndifferentHash, NatsWrapper, Playbook, TasksSupport
Class Method Summary collapse
-
.absolute_path?(path, separator = File::SEPARATOR, alt_separator = File::ALT_SEPARATOR) ⇒ Boolean
we should really use Pathname#absolute? but it’s not in all the ruby versions we support and it comes down to roughly this.
-
.align_text(text, console_cols = nil, preamble = 5) ⇒ Object
Returns an aligned_string of text relative to the size of the terminal window.
- .choria_windows_prefix ⇒ Object
-
.color(code) ⇒ Object
Return color codes, if the config color= option is false just return a empty string.
-
.colorize(code, msg) ⇒ Object
Helper to return a string in specific color.
-
.command_in_path?(command) ⇒ Boolean
Checks in PATH returns true if the command is found.
-
.config_file_for_user ⇒ Object
Picks the default user config file, priorities are first Choria ones then old MCollective ones.
- .config_paths_for_user ⇒ Object
-
.default_options ⇒ Object
Creates a standard options hash.
-
.empty_filter ⇒ Object
Creates an empty filter.
-
.empty_filter?(filter) ⇒ Boolean
Checks if the passed in filter is an empty one.
-
.field_number(field_size, max_size = 90) ⇒ Object
Calculate number of fields for printing.
-
.field_size(elements, min_size = 40) ⇒ Object
Get field size for printing.
-
.get_fact(fact) ⇒ Object
Gets the value of a specific fact, mostly just a duplicate of MCollective::Facts.get_fact but it kind of goes with the other classes here.
- .get_hidden_input(message = "Please enter data: ") ⇒ Object
-
.get_hidden_input_on_unix ⇒ Object
rubocop:disable Naming/AccessorMethodName.
-
.get_hidden_input_on_windows ⇒ Object
rubocop:disable Naming/AccessorMethodName.
-
.has_agent?(agent) ⇒ Boolean
Finds out if this MCollective has an agent by the name passed.
-
.has_cf_class?(klass) ⇒ Boolean
Checks if this node has a configuration management class by parsing the a text file with just a list of classes, recipes, roles etc.
-
.has_fact?(fact, value, operator) ⇒ Boolean
Compares fact == value,.
-
.has_identity?(identity) ⇒ Boolean
Checks if the configured identity matches the one supplied.
-
.loadclass(klass) ⇒ Object
Wrapper around PluginManager.loadclass.
- .make_subscriptions(agent, type, collective = nil) ⇒ Object
- .mcollective_version ⇒ Object
-
.parse_fact_string(fact) ⇒ Object
Parse a fact filter string like foo=bar into the tuple hash thats needed.
-
.ruby_version ⇒ Object
Returns the current ruby version as per RUBY_VERSION, mostly doing this here to aid testing.
-
.setup_windows_sleeper ⇒ Object
On windows ^c can’t interrupt the VM if its blocking on IO, so this sets up a dummy thread that sleeps and this will have the end result of being interruptable at least once a second.
-
.shellescape(str) ⇒ Object
Escapes a string so it’s safe to use in system() or backticks.
-
.str_to_bool(val) ⇒ Object
Converts a string into a boolean value Strings matching 1,y,yes,true or t will return TrueClass Any other value will return FalseClass.
-
.subscribe(targets) ⇒ Object
Helper to subscribe to a topic on multiple collectives or just one.
-
.subscribe_to_direct_addressing_queue ⇒ Object
subscribe to the direct addressing queue.
-
.templatepath(template_file) ⇒ Object
Looks up the template directory and returns its full path.
-
.terminal_dimensions(stdout = $stdout, environment = ENV) ⇒ Object
Figures out the columns and lines of the current tty.
-
.unsubscribe(targets) ⇒ Object
Helper to unsubscribe to a topic on multiple collectives or just one.
-
.versioncmp(version_a, version_b) ⇒ Object
compare two software versions as commonly found in package versions.
- .windows? ⇒ Boolean
-
.windows_prefix ⇒ Object
Returns the PuppetLabs mcollective path for windows.
Class Method Details
.absolute_path?(path, separator = File::SEPARATOR, alt_separator = File::ALT_SEPARATOR) ⇒ Boolean
we should really use Pathname#absolute? but it’s not in all the ruby versions we support and it comes down to roughly this
497 498 499 500 501 502 503 504 505 |
# File 'lib/mcollective/util.rb', line 497 def self.absolute_path?(path, separator=File::SEPARATOR, alt_separator=File::ALT_SEPARATOR) if alt_separator path_matcher = /^([a-zA-Z]:){0,1}[#{Regexp.quote alt_separator}#{Regexp.quote separator}]/ else path_matcher = /^#{Regexp.quote separator}/ end !!path.match(path_matcher) end |
.align_text(text, console_cols = nil, preamble = 5) ⇒ Object
Returns an aligned_string of text relative to the size of the terminal window. If a line in the string exceeds the width of the terminal window the line will be chopped off at the whitespace chacter closest to the end of the line and prepended to the next line, keeping all indentation.
The terminal size is detected by default, but custom line widths can passed. All strings will also be left aligned with 5 whitespace characters by default.
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 416 417 418 419 420 421 422 423 424 |
# File 'lib/mcollective/util.rb', line 352 def self.align_text(text, console_cols=nil, preamble=5) unless console_cols console_cols = terminal_dimensions[0] # if unknown size we default to the typical unix default console_cols = 80 if console_cols == 0 end console_cols -= preamble # Return unaligned text if console window is too small return text if console_cols <= 0 # If console is 0 this implies unknown so we assume the common # minimal unix configuration of 80 characters console_cols = 80 if console_cols <= 0 text = text.split("\n") piece = "" whitespace = 0 text.each_with_index do |line, i| whitespace = 0 whitespace += 1 while whitespace < line.length && line[whitespace].chr == " " # If the current line is empty, indent it so that a snippet # from the previous line is aligned correctly. line = (" " * whitespace) if line == "" # If text was snipped from the previous line, prepend it to the # current line after any current indentation. if piece != "" # Reset whitespaces to 0 if there are more whitespaces than there are # console columns whitespace = 0 if whitespace >= console_cols # If the current line is empty and being prepended to, create a new # empty line in the text so that formatting is preserved. text.insert(i + 1, "") if text[i + 1] && line == (" " * whitespace) # Add the snipped text to the current line line.insert(whitespace, "#{piece} ") end piece = "" # Compare the line length to the allowed line length. # If it exceeds it, snip the offending text from the line # and store it so that it can be prepended to the next line. if line.length > (console_cols + preamble) reverse = console_cols reverse -= 1 while line[reverse].chr != " " piece = line.slice!(reverse, (line.length - 1)).lstrip end # If a snippet exists when all the columns in the text have been # updated, create a new line and append the snippet to it, using # the same left alignment as the last line in the text. if piece != "" && text[i + 1].nil? text[i + 1] = "#{' ' * whitespace}#{piece}" piece = "" end # Add the preamble to the line and add it to the text line = ((" " * preamble) + line) text[i] = line end text.join("\n") end |
.choria_windows_prefix ⇒ Object
153 154 155 |
# File 'lib/mcollective/util.rb', line 153 def self.choria_windows_prefix File.join(ENV["ALLUSERSPROFILE"], "choria") end |
.color(code) ⇒ Object
Return color codes, if the config color= option is false just return a empty string
310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 |
# File 'lib/mcollective/util.rb', line 310 def self.color(code) colorize = Config.instance.color colors = { :red => "[31m", :green => "[32m", :yellow => "[33m", :cyan => "[36m", :bold => "[1m", :reset => "[0m" } if colorize colors[code] || "" else "" end end |
.colorize(code, msg) ⇒ Object
Helper to return a string in specific color
330 331 332 |
# File 'lib/mcollective/util.rb', line 330 def self.colorize(code, msg) "%s%s%s" % [color(code), msg, color(:reset)] end |
.command_in_path?(command) ⇒ Boolean
Checks in PATH returns true if the command is found
451 452 453 454 455 456 457 |
# File 'lib/mcollective/util.rb', line 451 def self.command_in_path?(command) found = ENV["PATH"].split(File::PATH_SEPARATOR).map do |p| File.exist?(File.join(p, command)) end found.include?(true) end |
.config_file_for_user ⇒ Object
Picks the default user config file, priorities are first Choria ones then old MCollective ones
In roughly this order, first to exist is used:
-
~/.choriarc
-
~/.mcollective
On Unix:
-
/etc/choria/client.conf
-
/usr/local/etc/choria/client.conf
-
/etc/puppetlabs/mcollective/client.cfg
-
/etc/mcollective/client.cfg
-
/usr/local/etc/mcollective/client.cfg
On Windows:
-
APPData/ChoriaIO/choria/etc/client.conf on windows
-
APPData/PuppetLabs/mcollective/etc/client.cfg on windows
201 202 203 204 205 206 207 |
# File 'lib/mcollective/util.rb', line 201 def self.config_file_for_user config_paths = config_paths_for_user found = config_paths.find_index { |file| File.readable?(file) } || 0 config_paths[found] end |
.config_paths_for_user ⇒ Object
157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 |
# File 'lib/mcollective/util.rb', line 157 def self.config_paths_for_user config_paths = [] ["~/.choriarc", "~/.mcollective"].each do |f| begin # File.expand_path will raise if HOME isn't set, catch it config_paths << File.(f) rescue ArgumentError # rubocop:disable Lint/SuppressedException end end if windows? config_paths << File.join(choria_windows_prefix, "etc", "client.conf") config_paths << File.join(windows_prefix, "etc", "client.cfg") else config_paths << "/etc/choria/client.conf" config_paths << "/usr/local/etc/choria/client.conf" config_paths << "/etc/puppetlabs/mcollective/client.cfg" config_paths << "/etc/mcollective/client.cfg" config_paths << "/usr/local/etc/mcollective/client.cfg" end config_paths end |
.default_options ⇒ Object
Creates a standard options hash
210 211 212 213 214 215 216 217 218 219 220 221 222 |
# File 'lib/mcollective/util.rb', line 210 def self. { :verbose => false, :disctimeout => nil, :timeout => 5, :config => config_file_for_user, :collective => nil, :discovery_method => nil, :discovery_options => Config.instance., :filter => empty_filter, :federations => Config.instance.federations } end |
.empty_filter ⇒ Object
Creates an empty filter
138 139 140 141 142 143 144 145 146 |
# File 'lib/mcollective/util.rb', line 138 def self.empty_filter { "fact" => [], "cf_class" => [], "agent" => [], "identity" => [], "compound" => [] } end |
.empty_filter?(filter) ⇒ Boolean
Checks if the passed in filter is an empty one
133 134 135 |
# File 'lib/mcollective/util.rb', line 133 def self.empty_filter?(filter) filter == empty_filter || filter == {} end |
.field_number(field_size, max_size = 90) ⇒ Object
Calculate number of fields for printing
543 544 545 546 |
# File 'lib/mcollective/util.rb', line 543 def self.field_number(field_size, max_size=90) number = (max_size / field_size).to_i number == 0 ? 1 : number end |
.field_size(elements, min_size = 40) ⇒ Object
Get field size for printing
537 538 539 540 |
# File 'lib/mcollective/util.rb', line 537 def self.field_size(elements, min_size=40) max_length = elements.max_by(&:length).length max_length > min_size ? max_length : min_size end |
.get_fact(fact) ⇒ Object
Gets the value of a specific fact, mostly just a duplicate of MCollective::Facts.get_fact but it kind of goes with the other classes here
60 61 62 |
# File 'lib/mcollective/util.rb', line 60 def self.get_fact(fact) Facts.get_fact(fact) end |
.get_hidden_input(message = "Please enter data: ") ⇒ Object
581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 |
# File 'lib/mcollective/util.rb', line 581 def self.get_hidden_input(="Please enter data: ") print unless .nil? if versioncmp(ruby_version, "1.9.3") >= 0 require "io/console" input = $stdin.noecho(&:gets) elsif windows? # Use hacks to get hidden input on Ruby <1.9.3 input = get_hidden_input_on_windows else input = get_hidden_input_on_unix end input.chomp! if input input end |
.get_hidden_input_on_unix ⇒ Object
rubocop:disable Naming/AccessorMethodName
570 571 572 573 574 575 576 577 578 579 |
# File 'lib/mcollective/util.rb', line 570 def self.get_hidden_input_on_unix # rubocop:disable Naming/AccessorMethodName raise "Could not hook to stdin to hide input. If using SSH, try using -t flag while connecting to server." unless $stdin.tty? raise "Could not hide input using stty command." unless system "stty -echo -icanon" input = $stdin.gets ensure raise "Could not enable echoing of input. Try executing `stty echo icanon` to debug." unless system "stty echo icanon" input end |
.get_hidden_input_on_windows ⇒ Object
rubocop:disable Naming/AccessorMethodName
548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 |
# File 'lib/mcollective/util.rb', line 548 def self.get_hidden_input_on_windows # rubocop:disable Naming/AccessorMethodName require "Win32API" # Hook into getch from crtdll. Keep reading all keys till return # or newline is hit. # If key is backspace or delete, then delete the character and update # the buffer. input = "" while char = Win32API.new("crtdll", "_getch", [], "I").Call break if [10, 13].include?(char) # return or newline if [127, 8].include?(char) # backspace and delete input.slice!(-1, 1) unless input.empty? else input << char.chr end end input end |
.has_agent?(agent) ⇒ Boolean
Finds out if this MCollective has an agent by the name passed
If the passed name starts with a / it’s assumed to be regex and will use regex to match
8 9 10 11 12 13 14 15 16 17 18 19 20 |
# File 'lib/mcollective/util.rb', line 8 def self.has_agent?(agent) agent = Regexp.new(agent.gsub("\/", "")) if agent.start_with?("/") if agent.is_a?(Regexp) if !Agents.agentlist.grep(agent).empty? true else false end else Agents.agentlist.include?(agent) end end |
.has_cf_class?(klass) ⇒ Boolean
Checks if this node has a configuration management class by parsing the a text file with just a list of classes, recipes, roles etc. This is ala the classes.txt from puppet.
If the passed name starts with a / it’s assumed to be regex and will use regex to match
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
# File 'lib/mcollective/util.rb', line 36 def self.has_cf_class?(klass) klass = Regexp.new(klass.gsub("\/", "")) if klass.start_with?("/") cfile = Config.instance.classesfile Log.debug("Looking for configuration management classes in #{cfile}") begin File.readlines(cfile).each do |k| case klass when Regexp return true if k.chomp.match(klass) when k.chomp return true end end rescue Exception => e # rubocop:disable Lint/RescueException Log.warn("Parsing classes file '#{cfile}' failed: #{e.class}: #{e}") end false end |
.has_fact?(fact, value, operator) ⇒ Boolean
Compares fact == value,
If the passed value starts with a / it’s assumed to be regex and will use regex to match
68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 |
# File 'lib/mcollective/util.rb', line 68 def self.has_fact?(fact, value, operator) Log.debug("Comparing #{fact} #{operator} #{value}") Log.debug("where :fact = '#{fact}', :operator = '#{operator}', :value = '#{value}'") fact = Facts[fact] return false if fact.nil? fact = fact.clone case fact when Array fact.any? { |element| test_fact_value(element, value, operator)} when Hash fact.keys.any? { |element| test_fact_value(element, value, operator)} else test_fact_value(fact, value, operator) end end |
.has_identity?(identity) ⇒ Boolean
Checks if the configured identity matches the one supplied
If the passed name starts with a / it’s assumed to be regex and will use regex to match
119 120 121 122 123 124 125 126 127 128 129 130 |
# File 'lib/mcollective/util.rb', line 119 def self.has_identity?(identity) identity = Regexp.new(identity.gsub("\/", "")) if identity.start_with?("/") case identity when Regexp return Config.instance.identity.match(identity) when Config.instance.identity return true end false end |
.loadclass(klass) ⇒ Object
Wrapper around PluginManager.loadclass
263 264 265 |
# File 'lib/mcollective/util.rb', line 263 def self.loadclass(klass) PluginManager.loadclass(klass) end |
.make_subscriptions(agent, type, collective = nil) ⇒ Object
224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 |
# File 'lib/mcollective/util.rb', line 224 def self.make_subscriptions(agent, type, collective=nil) config = Config.instance raise("Unknown target type #{type}") unless [:broadcast, :directed, :reply].include?(type) if collective.nil? config.collectives.map do |c| {:agent => agent, :type => type, :collective => c} end else raise("Unknown collective '#{collective}' known collectives are '#{config.collectives.join ', '}'") unless config.collectives.include?(collective) [{:agent => agent, :type => type, :collective => collective}] end end |
.mcollective_version ⇒ Object
340 341 342 |
# File 'lib/mcollective/util.rb', line 340 def self.mcollective_version MCollective::VERSION end |
.parse_fact_string(fact) ⇒ Object
Parse a fact filter string like foo=bar into the tuple hash thats needed
268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 |
# File 'lib/mcollective/util.rb', line 268 def self.parse_fact_string(fact) case fact when /^([^ ]+?) *=> *(.+)/ {:fact => $1, :value => $2, :operator => ">="} when /^([^ ]+?) *=< *(.+)/ {:fact => $1, :value => $2, :operator => "<="} when /^([^ ]+?) *(<=|>=|<|>|!=|==|=~) *(.+)/ {:fact => $1, :value => $3, :operator => $2} when /^(.+?) *= *\/(.+)\/$/ {:fact => $1, :value => "/#{$2}/", :operator => "=~"} when /^([^= ]+?) *= *(.+)/ {:fact => $1, :value => $2, :operator => "=="} else raise "Could not parse fact #{fact} it does not appear to be in a valid format" end end |
.ruby_version ⇒ Object
Returns the current ruby version as per RUBY_VERSION, mostly doing this here to aid testing
336 337 338 |
# File 'lib/mcollective/util.rb', line 336 def self.ruby_version RUBY_VERSION end |
.setup_windows_sleeper ⇒ Object
On windows ^c can’t interrupt the VM if its blocking on IO, so this sets up a dummy thread that sleeps and this will have the end result of being interruptable at least once a second. This is a common pattern found in Rails etc
26 27 28 |
# File 'lib/mcollective/util.rb', line 26 def self.setup_windows_sleeper Thread.new { loop { sleep 1 } } if Util.windows? end |
.shellescape(str) ⇒ Object
Escapes a string so it’s safe to use in system() or backticks
Taken from Shellwords#shellescape since it’s only in a few ruby versions
288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 |
# File 'lib/mcollective/util.rb', line 288 def self.shellescape(str) return "''" if str.empty? str = str.dup # Process as a single byte sequence because not all shell # implementations are multibyte aware. str.gsub!(/([^A-Za-z0-9_\-.,:\/@\n])/n, "\\\\\\1") # A LF cannot be escaped with a backslash because a backslash + LF # combo is regarded as line continuation and simply ignored. str.gsub!(/\n/, "'\n'") str end |
.str_to_bool(val) ⇒ Object
Converts a string into a boolean value Strings matching 1,y,yes,true or t will return TrueClass Any other value will return FalseClass
510 511 512 513 514 515 516 517 518 519 520 |
# File 'lib/mcollective/util.rb', line 510 def self.str_to_bool(val) clean_val = val.to_s.strip case clean_val when /^(1|yes|true|y|t)$/i true when /^(0|no|false|n|f)$/i false else raise("Cannot convert string value '#{clean_val}' into a boolean.") end end |
.subscribe(targets) ⇒ Object
Helper to subscribe to a topic on multiple collectives or just one
241 242 243 244 245 246 247 248 249 |
# File 'lib/mcollective/util.rb', line 241 def self.subscribe(targets) connection = PluginManager["connector_plugin"] targets = [targets].flatten targets.each do |target| connection.subscribe(target[:agent], target[:type], target[:collective]) end end |
.subscribe_to_direct_addressing_queue ⇒ Object
subscribe to the direct addressing queue
532 533 534 |
# File 'lib/mcollective/util.rb', line 532 def self.subscribe_to_direct_addressing_queue subscribe(make_subscriptions("mcollective", :directed)) end |
.templatepath(template_file) ⇒ Object
Looks up the template directory and returns its full path
523 524 525 526 527 528 529 |
# File 'lib/mcollective/util.rb', line 523 def self.templatepath(template_file) config_dir = File.dirname(Config.instance.configfile) template_path = File.join(config_dir, template_file) return template_path if File.exist?(template_path) File.join("/etc/mcollective", template_file) end |
.terminal_dimensions(stdout = $stdout, environment = ENV) ⇒ Object
Figures out the columns and lines of the current tty
Returns [0, 0] if it can’t figure it out or if you’re not running on a tty
430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 |
# File 'lib/mcollective/util.rb', line 430 def self.terminal_dimensions(stdout=$stdout, environment=ENV) return [0, 0] unless stdout.tty? return [80, 40] if Util.windows? if environment["COLUMNS"] && environment["LINES"] [environment["COLUMNS"].to_i, environment["LINES"].to_i] elsif environment["TERM"] && command_in_path?("tput") [`tput cols`.to_i, `tput lines`.to_i] elsif command_in_path?("stty") `stty size`.scan(/\d+/).map(&:to_i) else [0, 0] end rescue [0, 0] end |
.unsubscribe(targets) ⇒ Object
Helper to unsubscribe to a topic on multiple collectives or just one
252 253 254 255 256 257 258 259 260 |
# File 'lib/mcollective/util.rb', line 252 def self.unsubscribe(targets) connection = PluginManager["connector_plugin"] targets = [targets].flatten targets.each do |target| connection.unsubscribe(target[:agent], target[:type], target[:collective]) end end |
.versioncmp(version_a, version_b) ⇒ Object
compare two software versions as commonly found in package versions.
returns 0 if a == b returns -1 if a < b returns 1 if a > b
Code originally from Puppet
467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 |
# File 'lib/mcollective/util.rb', line 467 def self.versioncmp(version_a, version_b) vre = /[-.]|\d+|[^-.\d]+/ ax = version_a.scan(vre) bx = version_b.scan(vre) while !ax.empty? && !bx.empty? a = ax.shift b = bx.shift if a == b then next elsif a == "-" && b == "-" then next elsif a == "-" then return -1 elsif b == "-" then return 1 elsif a == "." && b == "." then next elsif a == "." then return -1 elsif b == "." then return 1 elsif a =~ /^\d+$/ && b =~ /^\d+$/ return a.to_s.upcase <=> b.to_s.upcase if a =~ /^0/ || b =~ /^0/ return a.to_i <=> b.to_i else return a.upcase <=> b.upcase end end version_a <=> version_b end |
.windows? ⇒ Boolean
304 305 306 |
# File 'lib/mcollective/util.rb', line 304 def self.windows? !!(RbConfig::CONFIG["host_os"] =~ /mswin|win32|dos|mingw|cygwin/i) end |
.windows_prefix ⇒ Object
Returns the PuppetLabs mcollective path for windows
149 150 151 |
# File 'lib/mcollective/util.rb', line 149 def self.windows_prefix File.join(ENV["ALLUSERSPROFILE"], "PuppetLabs", "choria") end |