Class: ChefApply::Startup
- Inherits:
-
Object
- Object
- ChefApply::Startup
- Defined in:
- lib/chef_apply/startup.rb
Defined Under Namespace
Classes: ConfigPathInvalid, ConfigPathNotProvided, UnsupportedInstallation
Constant Summary collapse
Instance Attribute Summary collapse
-
#argv ⇒ Object
readonly
Returns the value of attribute argv.
Instance Method Summary collapse
- #create_default_config ⇒ Object
-
#custom_config_path ⇒ Object
Look for a user-supplied config path by manually parsing the option.
- #first_run_tasks ⇒ Object
- #init_terminal ⇒ Object
-
#initialize(argv) ⇒ Startup
constructor
A new instance of Startup.
- #load_config ⇒ Object
- #run(enforce_license: false) ⇒ Object
- #setup_error_handling ⇒ Object
- #setup_logging ⇒ Object
- #setup_telemetry ⇒ Object
- #setup_workstation_user_directories ⇒ Object
- #start_chef_apply(enforce_license: false) ⇒ Object
- #start_telemeter_upload ⇒ Object
-
#verify_not_in_chefdk ⇒ Object
Verify that chef-run gem is not executing out of ChefDK by checking the runtime path of this file.
Constructor Details
#initialize(argv) ⇒ Startup
Returns a new instance of Startup.
28 29 30 31 32 33 34 |
# File 'lib/chef_apply/startup.rb', line 28 def initialize(argv) @term_init = false @argv = argv.clone # Enable CLI output via Terminal. This comes first because other startup steps may # need to output to the terminal. init_terminal end |
Instance Attribute Details
#argv ⇒ Object (readonly)
Returns the value of attribute argv.
25 26 27 |
# File 'lib/chef_apply/startup.rb', line 25 def argv @argv end |
Instance Method Details
#create_default_config ⇒ Object
114 115 116 117 118 119 |
# File 'lib/chef_apply/startup.rb', line 114 def create_default_config UI::Terminal.output T.creating_config(Config.default_location) UI::Terminal.output "" FileUtils.mkdir_p(Config::WS_BASE_PATH) FileUtils.touch(Config.default_location) end |
#custom_config_path ⇒ Object
Look for a user-supplied config path by manually parsing the option. Note that we can’t use Mixlib::CLI for this. To ensure that ChefApply::CLI initializes with correct option defaults, we need to have configuration loaded before initializing it.
172 173 174 175 176 177 178 179 180 181 182 183 |
# File 'lib/chef_apply/startup.rb', line 172 def custom_config_path argv.each_with_index do |arg, index| if arg == "--config-path" || arg == "-c" next_arg = argv[index + 1] raise ConfigPathNotProvided.new if next_arg.nil? raise ConfigPathInvalid.new(next_arg) unless File.file?(next_arg) && File.readable?(next_arg) return next_arg end end nil end |
#first_run_tasks ⇒ Object
107 108 109 110 111 112 |
# File 'lib/chef_apply/startup.rb', line 107 def first_run_tasks return if Dir.exist?(Config::WS_BASE_PATH) create_default_config setup_telemetry end |
#init_terminal ⇒ Object
94 95 96 |
# File 'lib/chef_apply/startup.rb', line 94 def init_terminal UI::Terminal.init($stdout) end |
#load_config ⇒ Object
162 163 164 165 166 |
# File 'lib/chef_apply/startup.rb', line 162 def load_config path = custom_config_path Config.custom_location(path) unless path.nil? Config.load end |
#run(enforce_license: false) ⇒ Object
36 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 |
# File 'lib/chef_apply/startup.rb', line 36 def run(enforce_license: false) # This component is not supported in ChefDK; an exception will be raised # if running in that context. verify_not_in_chefdk # Some tasks we do only once in an installation: first_run_tasks # Call this every time, so that if we add or change ~/.chef-workstation # directory structure, we can be sure that it exists. Even with a # custom configuration, the .chef-workstation directory and sub-dirs # are required. setup_workstation_user_directories # Customize behavior of Ruby and any gems around error handling setup_error_handling # Startup tasks that may change behavior based on configuration value # must be run after load_config load_config # Init logging using log level out of config setup_logging # Begin upload of previous session telemetry. (If telemetry is not enabled, # in config the uploader will clean up previous session(s) without sending) start_telemeter_upload # Launch the actual Chef Apply behavior start_chef_apply(enforce_license: enforce_license) # NOTE: Because these exceptions occur outside of the # CLI handling, they won't be tracked in telemetry. # We can revisit this once the pending error handling rework # is underway. rescue ConfigPathInvalid => e UI::Terminal.output(T.error.bad_config_file(e.path)) rescue ConfigPathNotProvided UI::Terminal.output(T.error.missing_config_path) rescue UnsupportedInstallation UI::Terminal.output(T.error.unsupported_installation) rescue Mixlib::Config::UnknownConfigOptionError => e # Ideally we'd update the exception in mixlib to include # a field with the faulty value, line number, and nested context - # it's less fragile than depending on text parsing, which # is what we'll do for now. if e. =~ /.*unsupported config value (.*)[.]+$/ # TODO - levenshteinian distance to figure out # what they may have meant instead. UI::Terminal.output(T.error.invalid_config_key($1, Config.location)) else # Safety net in case the error text changes from under us. UI::Terminal.output(T.error.unknown_config_error(e., Config.location)) end rescue Tomlrb::ParseError => e UI::Terminal.output(T.error.unknown_config_error(e., Config.location)) end |
#setup_error_handling ⇒ Object
151 152 153 154 155 156 157 158 159 160 |
# File 'lib/chef_apply/startup.rb', line 151 def setup_error_handling # In Ruby 2.5+ threads print out to stdout when they raise an exception. This is an aggressive # attempt to ensure debugging information is not lost, but in our case it is not necessary # because we handle all the errors ourself. So we disable this to keep output clean. # See https://ruby-doc.org/core-2.5.0/Thread.html#method-c-report_on_exception # # We set this globally so that it applies to all threads we create - we never want any non-UI thread # to render error output to the terminal. Thread.report_on_exception = false end |
#setup_logging ⇒ Object
185 186 187 188 189 190 191 192 193 194 195 |
# File 'lib/chef_apply/startup.rb', line 185 def setup_logging ChefApply::Log.setup(Config.log.location, Config.log.level.to_sym) ChefApply::Log.info("Initialized logger") ChefConfig.logger = ChefApply::Log # Setting the config isn't enough, we need to ensure the logger is # initialized with our existing stream or automatic initialization # will still go to stdout instead of the log file we opened. Chef::Log.init(ChefApply::Log.stream) Chef::Log.level = ChefApply::Log.level end |
#setup_telemetry ⇒ Object
121 122 123 124 125 126 127 128 129 130 |
# File 'lib/chef_apply/startup.rb', line 121 def setup_telemetry require "securerandom" unless defined?(SecureRandom) installation_id = SecureRandom.uuid File.write(Config.telemetry_installation_identifier_file, installation_id) # Tell the user we're anonymously tracking, give brief opt-out # and a link to detailed information. UI::Terminal.output T.telemetry_enabled(Config.location) UI::Terminal.output "" end |
#setup_workstation_user_directories ⇒ Object
143 144 145 146 147 148 149 |
# File 'lib/chef_apply/startup.rb', line 143 def setup_workstation_user_directories # Note that none of these paths are customizable in config, so # it's safe to do before we load config. FileUtils.mkdir_p(Config::WS_BASE_PATH) FileUtils.mkdir_p(Config.base_log_directory) FileUtils.mkdir_p(Config.telemetry_path) end |
#start_chef_apply(enforce_license: false) ⇒ Object
197 198 199 200 |
# File 'lib/chef_apply/startup.rb', line 197 def start_chef_apply(enforce_license: false) require_relative "cli" ChefApply::CLI.new(@argv).run(enforce_license: enforce_license) end |
#start_telemeter_upload ⇒ Object
132 133 134 135 136 137 138 139 140 141 |
# File 'lib/chef_apply/startup.rb', line 132 def start_telemeter_upload cfg = { enabled: Config.telemetry[:enabled], dev_mode: Config.telemetry[:dev_mode], payload_dir: Config.telemetry_path, installation_identifier_file: Config.telemetry_installation_identifier_file, session_file: Config.telemetry_session_file, } Chef::Telemeter.setup(cfg) end |
#verify_not_in_chefdk ⇒ Object
Verify that chef-run gem is not executing out of ChefDK by checking the runtime path of this file.
NOTE: This is imperfect - someone could theoretically install chefdk to a path other than the default.
103 104 105 |
# File 'lib/chef_apply/startup.rb', line 103 def verify_not_in_chefdk raise UnsupportedInstallation.new if script_path =~ /chefdk/ end |