Class: Pupistry::Agent
- Inherits:
-
Object
- Object
- Pupistry::Agent
- Defined in:
- lib/pupistry/agent.rb
Overview
Functions for running the Pupistry agent aka “apply mode” to actually download and run Puppet against the contents of the artifact.
Class Method Summary collapse
- .apply(options) ⇒ Object
- .build_modulepath(environment) ⇒ Object
-
.daemon(options) ⇒ Object
Run as a daemon.
Class Method Details
.apply(options) ⇒ Object
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 |
# File 'lib/pupistry/agent.rb', line 56 def self.apply() ## Download and apply the latest artifact (if any) # Fetch artifact versions $logger.info 'Checking version of artifact available...' artifact = Pupistry::Artifact.new artifact.checksum = artifact.fetch_latest unless artifact.checksum $logger.error 'There is no current artifact available for download, no steps can be taken.' return false end artifact_installed = Pupistry::Artifact.new artifact_installed.checksum = artifact_installed.fetch_installed if artifact_installed.checksum $logger.debug "Currently on #{artifact_installed.checksum}" else $logger.debug 'No currently installed artifact - blank slate!' end # Download the new artifact if one has changed. If we already have this # version, then we should skip downloading and go straight to running # Puppet - unless the user runs with --force (eg to fix a corrupted # artifact). if artifact.checksum != artifact_installed.checksum || [:force] $logger.warn 'Forcing download of latest artifact regardless of current one.' if [:force] # Install the artifact $logger.info "Downloading latest artifact (#{artifact.checksum})..." artifact.fetch_artifact artifact.unpack artifact.hieracrypt_decrypt unless artifact.install $logger.fatal 'An unexpected error happened when installing the latest artifact, cancelling Puppet run' return false end # Remove temporary unpacked files artifact.clean_unpack else $logger.info 'Already have latest artifact applied.' # By default we run Puppet even if we have the latest artifact. There's # some grounds for debate about whether this is the right thing - in some # ways it is often a waste of CPU, since if the artifact hasn't changed, # then it's unlikley anything else has changed. # # But that's not always 100% true - Puppet will undo local changes or # upgrade package versions (ensure => latest) if appropiate, so we should # act like the standard command and attempt to apply whatever we can. # # To provide users with options, we provide the --lazy parameter to avoid # running Puppet except when the artifact changes. By default, Puppet # runs every thing to avoid surprise. if [:minimal] $logger.info 'Running with minimal effort mode enabled, not running Puppet since artifact version already applied' return false end end # If the environment has been specified, use it. environment = $config['agent']['environment'] || 'master' # override if environment is supplied on CLI environment = ["environment"] || environment unless Dir.exist?("#{$config['agent']['puppetcode']}/#{environment}") $logger.fatal "The requested branch/environment of #{environment} does not exist, unable to run Puppet" return false end # Execute Puppet. puppet_cmd = 'puppet apply' puppet_cmd += ' --noop' if [:noop] puppet_cmd += ' --show_diff' if [:verbose] puppet_cmd += " --environment #{environment}" puppet_cmd += " --confdir #{$config['agent']['puppetcode']}" puppet_cmd += " --environmentpath #{$config['agent']['puppetcode']}" puppet_cmd += " --modulepath #{build_modulepath(environment)}" puppet_cmd += " --hiera_config #{$config['agent']['puppetcode']}/#{environment}/hiera.yaml" puppet_cmd += " #{$config['agent']['puppetcode']}/#{environment}/manifests/site.pp" $logger.info 'Executing Puppet...' $logger.debug "With: #{puppet_cmd}" $logger.error 'An unexpected issue occured when running puppet' unless system puppet_cmd end |
.build_modulepath(environment) ⇒ Object
153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 |
# File 'lib/pupistry/agent.rb', line 153 def self.build_modulepath(environment) environment_path = "#{$config['agent']['puppetcode']}/#{environment}" environment_conf = "#{environment_path}/environment.conf" configured_paths = [] if File.exist?(environment_conf) $logger.debug "Adding modulepath config from '#{environment_path}'" File.open(environment_conf, 'r').readlines.each do |line| if line !~ /^\s*#/ && /^(.*)=(.*)/ =~ line key, val = $1.strip, $2.strip configured_paths = val.split(':') if key == 'modulepath' end end end modulepaths = configured_paths.map { |path| File.(path, environment_path) } # Ensure '<environment_path>/modules' in modulepath. ensure_path = File.('modules', environment_path) modulepaths.insert(0, ensure_path) unless modulepaths.include? ensure_path modulepaths.join(File::PATH_SEPARATOR) end |
.daemon(options) ⇒ Object
Run as a daemon
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
# File 'lib/pupistry/agent.rb', line 12 def self.daemon() # Since options comes from Thor, it can't be modified, so we need to # copy the options and then we can edit it. = .inject({}) do |new, (name, value)| new[name] = value new end # If the minimal mode has been enabled in config, respect. [:minimal] = true if $config['agent']['daemon_minimal'] # If no frequency supplied, use 300 seconds safe default. $config['agent']['daemon_frequency'] = 300 unless $config['agent']['daemon_frequency'] # Use rufus-scheduler to run our apply job as a regularly scheduled job # but with build in locking handling. $logger.info "Launching daemon... frequency of #{$config['agent']['daemon_frequency']} seconds." begin scheduler = Rufus::Scheduler.new scheduler.every "#{$config['agent']['daemon_frequency']}s", overlap: false, timeout: '1d', first_at: Time.now + 1 do $logger.info "Triggering another Pupistry run (#{$config['agent']['daemon_frequency']}s)" apply end scheduler.join rescue Rufus::Scheduler::TimeoutError $logger.error 'A run of Pupistry timed out after 1 day as a safety measure. There may be a bug or a Puppet action causing it to get stuck' rescue SignalException # Clean shutdown signal (eg SIGTERM) $logger.info 'Clean shutdown of Pupistry daemon requests' exit 0 rescue StandardError => e raise e end end |