Class: OctocatalogDiff::Cli
- Inherits:
-
Object
- Object
- OctocatalogDiff::Cli
- Defined in:
- lib/octocatalog-diff/cli.rb,
lib/octocatalog-diff/cli/diffs.rb,
lib/octocatalog-diff/cli/options.rb,
lib/octocatalog-diff/cli/printer.rb
Overview
This is the CLI for catalog-diff. It’s responsible for parsing the command line arguments and then handing off to appropriate methods to perform the catalog-diff.
Defined Under Namespace
Classes: Diffs, Options, Printer
Constant Summary collapse
- VERSION =
Version number
OctocatalogDiff::Version::VERSION
- EXITCODE_SUCCESS_NO_DIFFS =
Exit codes
0
- EXITCODE_FAILURE =
1
- EXITCODE_SUCCESS_WITH_DIFFS =
2
- DEFAULT_IGNORES =
The default type+title+attribute to ignore in catalog-diff.
[ { type: 'Class' } # Don't care about classes themselves, only what they actually do! ].freeze
- DEFAULT_OPTIONS =
The default options.
{ from_env: 'origin/master', to_env: '.', colors: true, debug: false, quiet: false, format: :color_text, display_source_file_line: false, compare_file_text: true, display_datatype_changes: true, parallel: true, storeconfigs_backend: 'puppetdb', suppress_absent_file_details: true, hiera_path: 'hieradata', use_lcs: true }.freeze
Class Method Summary collapse
-
.bootstrap_then_exit(logger, catalogs_obj) ⇒ Object
–bootstrap-then-exit command.
-
.catalog_only(logger, options) ⇒ Object
Compile the catalog only.
-
.cli(argv = ARGV, logger = Logger.new(STDERR), opts = {}) ⇒ Integer
This method is the one to call externally.
-
.parse_opts(argv) ⇒ Hash
Parse command line options with ‘optparse’.
-
.run_octocatalog_diff(node, options, logger) ⇒ Object
Run the octocatalog-diff process for a given node.
-
.setup_enc_overrides(options) ⇒ Object
ENC parameter overrides come in here.
-
.setup_fact_overrides(options) ⇒ Object
Fact overrides come in here.
-
.setup_logger(logger, options, argv_save) ⇒ Object
Helper method: Configure and setup logger.
-
.setup_overrides(key, options) ⇒ Object
Generic overrides.
Class Method Details
.bootstrap_then_exit(logger, catalogs_obj) ⇒ Object
–bootstrap-then-exit command
227 228 229 230 231 232 233 |
# File 'lib/octocatalog-diff/cli.rb', line 227 def self.bootstrap_then_exit(logger, catalogs_obj) catalogs_obj.bootstrap_then_exit return EXITCODE_SUCCESS_NO_DIFFS rescue OctocatalogDiff::Errors::BootstrapError => exc logger.fatal("--bootstrap-then-exit error: bootstrap failed (#{exc})") return EXITCODE_FAILURE end |
.catalog_only(logger, options) ⇒ Object
Compile the catalog only
208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 |
# File 'lib/octocatalog-diff/cli.rb', line 208 def self.catalog_only(logger, ) opts = .merge(logger: logger) to_catalog = OctocatalogDiff::API::V1.catalog(opts) # If the catalog compilation failed, an exception would have been thrown. So if # we get here, the catalog succeeded. Dump the catalog to the appropriate place # and exit successfully. if [:output_file] File.open([:output_file], 'w') { |f| f.write(to_catalog.to_json) } logger.info "Wrote catalog to #{[:output_file]}" else puts to_catalog.to_json end return { exitcode: EXITCODE_SUCCESS_NO_DIFFS, to: to_catalog } if [:INTEGRATION] # For integration testing EXITCODE_SUCCESS_NO_DIFFS end |
.cli(argv = ARGV, logger = Logger.new(STDERR), opts = {}) ⇒ Integer
This method is the one to call externally. It is possible to specify alternate command line arguments, for testing.
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 |
# File 'lib/octocatalog-diff/cli.rb', line 58 def self.cli(argv = ARGV, logger = Logger.new(STDERR), opts = {}) # Save a copy of argv to print out later in debugging argv_save = OctocatalogDiff::Util::Util.deep_dup(argv) # Are there additional ARGV to munge, e.g. that have been supplied in the options from a # configuration file? if opts.key?(:additional_argv) raise ArgumentError, ':additional_argv must be array!' unless opts[:additional_argv].is_a?(Array) argv.concat opts[:additional_argv] end # Parse command line = parse_opts(argv) # Additional options from hard-coded specified options. These are only processed if # there are not already values defined from command line options. # Note: do NOT use 'options[k] ||= v' here because if the value of options[k] is boolean(false) # it will then be overridden. Whereas the intent is to define values only for those keys that don't exist. opts.each { |k, v| [k] = v unless .key?(k) } = %w(enc header include_tags) .each { |x| .delete(x.to_sym) if ["no_#{x}".to_sym] } if [:no_hiera_config] vetoes = %w[hiera_config to_hiera_config from_hiera_config] vetoes.each do |key| .delete(key.to_sym) end end [:ignore].concat opts.fetch(:additional_ignores, []) # Incorporate default options where needed. # Note: do NOT use 'options[k] ||= v' here because if the value of options[k] is boolean(false) # it will then be overridden. Whereas the intent is to define values only for those keys that don't exist. DEFAULT_OPTIONS.each { |k, v| [k] = v unless .key?(k) } = %w(hiera_path hiera_path_strip) .each { |x| .delete(x.to_sym) if [x.to_sym] == :none } # Fact and ENC overrides come in here - 'options' is modified setup_fact_overrides() setup_enc_overrides() # Configure the logger and logger.debug initial information # 'logger' is modified and used setup_logger(logger, , argv_save) # --catalog-only is a special case that compiles the catalog for the "to" branch # and then exits, without doing any 'diff' whatsoever. Support that option. return catalog_only(logger, ) if [:catalog_only] # Set up the cached master directory - maintain it, adjust options if needed. However, if we # are getting the 'from' catalog from PuppetDB, then don't do this. unless [:cached_master_dir].nil? || [:from_puppetdb] OctocatalogDiff::CatalogUtil::CachedMasterDirectory.run(, logger) end # bootstrap_then_exit is a special case that only prepares directories and does not # depend on facts. This happens within the 'catalogs' object, since bootstrapping and # preparing catalogs are tightly coupled operations. However this does not actually # build catalogs. if [:bootstrap_then_exit] catalogs_obj = OctocatalogDiff::Util::Catalogs.new(, logger) return bootstrap_then_exit(logger, catalogs_obj) end # Compile catalogs and do catalog-diff node_set = .delete(:node) node_set = [node_set] unless node_set.is_a?(Array) # run multiple node diffs in parallel catalog_diffs = if node_set.size == 1 [run_octocatalog_diff(node_set.first, , logger)] else ::Parallel.map(node_set, in_threads: 4) { |node| run_octocatalog_diff(node, , logger) } end # Return the resulting diff object if requested (generally for testing) # or otherwise return exit code return catalog_diffs.first if opts[:INTEGRATION] all_diffs = catalog_diffs.map(&:diffs) all_diffs.each do |diff| next unless diff.any? return EXITCODE_SUCCESS_WITH_DIFFS end EXITCODE_SUCCESS_NO_DIFFS end |
.parse_opts(argv) ⇒ Hash
Parse command line options with ‘optparse’. Returns a hash with the parsed arguments.
167 168 169 170 |
# File 'lib/octocatalog-diff/cli.rb', line 167 def self.parse_opts(argv) = { ignore: OctocatalogDiff::Util::Util.deep_dup(DEFAULT_IGNORES) } Options.(argv, ) end |
.run_octocatalog_diff(node, options, logger) ⇒ Object
Run the octocatalog-diff process for a given node. Return the diffs for a contribution to the final exit status. node - String with the node options - All of the currently defined options logger - Logger object
151 152 153 154 155 156 157 158 159 160 161 162 |
# File 'lib/octocatalog-diff/cli.rb', line 151 def self.run_octocatalog_diff(node, , logger) = .merge(node: node) catalog_diff = OctocatalogDiff::API::V1.catalog_diff(.merge(logger: logger)) diffs = catalog_diff.diffs # Display diffs printer_obj = OctocatalogDiff::Cli::Printer.new(, logger) printer_obj.printer(diffs, catalog_diff.from.compilation_dir, catalog_diff.to.compilation_dir) # Return catalog-diff object. catalog_diff end |
.setup_enc_overrides(options) ⇒ Object
ENC parameter overrides come in here
188 189 190 191 |
# File 'lib/octocatalog-diff/cli.rb', line 188 def self.setup_enc_overrides() setup_overrides(:from_enc_override, ) setup_overrides(:to_enc_override, ) end |
.setup_fact_overrides(options) ⇒ Object
Fact overrides come in here
182 183 184 185 |
# File 'lib/octocatalog-diff/cli.rb', line 182 def self.setup_fact_overrides() setup_overrides(:from_fact_override, ) setup_overrides(:to_fact_override, ) end |
.setup_logger(logger, options, argv_save) ⇒ Object
Helper method: Configure and setup logger
194 195 196 197 198 199 200 201 202 203 204 205 |
# File 'lib/octocatalog-diff/cli.rb', line 194 def self.setup_logger(logger, , argv_save) # Configure the logger logger.level = Logger::INFO logger.level = Logger::DEBUG if [:debug] logger.level = Logger::ERROR if [:quiet] # Some debugging information up front version_display = ENV['OCTOCATALOG_DIFF_CUSTOM_VERSION'] || VERSION logger.debug "Running octocatalog-diff #{version_display} with ruby #{RUBY_VERSION}" logger.debug "Command line arguments: #{argv_save.inspect}" logger.debug "Running on host #{Socket.gethostname} (#{RUBY_PLATFORM})" end |
.setup_overrides(key, options) ⇒ Object
Generic overrides
173 174 175 176 177 178 179 |
# File 'lib/octocatalog-diff/cli.rb', line 173 def self.setup_overrides(key, ) o = ["#{key}_in".to_sym] return unless o.is_a?(Array) return unless o.any? [key] ||= [] [key].concat o.map { |x| OctocatalogDiff::API::V1::Override.create_from_input(x) } end |