pupistry 0.0.10 → 0.0.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/bin/pupistry +12 -94
- data/lib/pupistry/agent.rb +173 -0
- data/lib/pupistry/bootstrap.rb +2 -0
- data/lib/pupistry.rb +1 -0
- data/settings.example.yaml +13 -0
- metadata +16 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b516bef9aa8033e4871098cd224fe497ef82f1b6
|
4
|
+
data.tar.gz: 7b158bdc381764e80618a4236e6287d19ac6670e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8f2f7720b7b9ef5f8042282d49ba3093bfcc4c160bbc8288ba200410daaae4da4842d4b2bc21059879adb0ac4686a841413a58f4be2f90c9ba37a980a3ec5aed
|
7
|
+
data.tar.gz: 3466558b948d2e141fb73a1b7e86ac898dc4d88504133d8b450c14124b1013e6ec42a8f0d421eeacb80904e7e3960b79fd94ed1a31f2df6cb835fabecf898dd7
|
data/bin/pupistry
CHANGED
@@ -49,105 +49,18 @@ class CLI < Thor
|
|
49
49
|
$logger.warn "A daemon running in noop will do nothing except log what changes it could apply"
|
50
50
|
end
|
51
51
|
|
52
|
-
|
53
|
-
|
54
|
-
$logger.fatal "Daemon mode not implemented yet"
|
55
|
-
exit 0
|
56
|
-
end
|
57
|
-
|
58
|
-
|
59
|
-
# Fetch artifact versions
|
60
|
-
$logger.info "Checking version of artifact available..."
|
61
|
-
|
62
|
-
artifact = Pupistry::Artifact.new
|
63
|
-
artifact.checksum = artifact.fetch_latest
|
64
|
-
|
65
|
-
unless artifact.checksum
|
66
|
-
$logger.error "There is no current artifact available for download, no steps can be taken."
|
67
|
-
exit 0
|
68
|
-
end
|
69
|
-
|
70
|
-
artifact_installed = Pupistry::Artifact.new
|
71
|
-
artifact_installed.checksum = artifact_installed.fetch_installed
|
72
|
-
|
73
|
-
if artifact_installed.checksum
|
74
|
-
$logger.debug "Currently on #{artifact_installed.checksum}"
|
75
|
-
else
|
76
|
-
$logger.debug "No currently installed artifact - blank slate!"
|
77
|
-
end
|
78
|
-
|
79
|
-
# Download the new artifact if one has changed. If we already have this
|
80
|
-
# version, then we should skip downloading and go straight to running
|
81
|
-
# Puppet - unless the user runs with --force (eg to fix a corrupted
|
82
|
-
# artifact).
|
83
|
-
|
84
|
-
if artifact.checksum != artifact_installed.checksum or options[:force]
|
85
|
-
if options[:force]
|
86
|
-
$logger.warn "Forcing download of latest artifact regardless of current one."
|
87
|
-
end
|
88
|
-
|
89
|
-
# Install the artifact
|
90
|
-
$logger.info "Downloading latest artifact (#{artifact.checksum})..."
|
91
|
-
|
92
|
-
artifact.fetch_artifact
|
93
|
-
artifact.unpack
|
94
|
-
|
95
|
-
unless artifact.install
|
96
|
-
$logger.fatal "An unexpected error happened when installing the latest artifact, cancelling Puppet run"
|
97
|
-
exit 0
|
98
|
-
end
|
99
|
-
|
100
|
-
# Remove temporary unpacked files
|
101
|
-
artifact.clean_unpack
|
102
|
-
else
|
103
|
-
$logger.info "Already have latest artifact applied."
|
104
|
-
|
105
|
-
# By default we run Puppet even if we have the latest artifact. There's
|
106
|
-
# some grounds for debate about whether this is the right thing - in some
|
107
|
-
# ways it is often a waste of CPU, since if the artifact hasn't changed,
|
108
|
-
# then it's unlikley anything else has changed.
|
109
|
-
#
|
110
|
-
# But that's not always 100% true - Puppet will undo local changes or
|
111
|
-
# upgrade package versions (ensure => latest) if appropiate, so we should
|
112
|
-
# act like the standard command and attempt to apply whatever we can.
|
113
|
-
#
|
114
|
-
# To provide users with options, we provide the --lazy parameter to avoid
|
115
|
-
# running Puppet except when the artifact changes. By default, Puppet
|
116
|
-
# runs every thing to avoid surprise.
|
117
|
-
|
118
|
-
if options[:minimal]
|
119
|
-
$logger.info "Running with minimal effort mode enabled, not running Puppet since artifact version already applied"
|
120
|
-
exit 0
|
121
|
-
end
|
122
|
-
|
52
|
+
if options[:force] and options[:daemon]
|
53
|
+
$logger.warn "A daemon running with force will be very wasteful of system resources! NOT RECOMMENDED."
|
123
54
|
end
|
124
55
|
|
125
56
|
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
if options[:noop]
|
130
|
-
puppet_cmd += " --noop"
|
131
|
-
end
|
132
|
-
|
133
|
-
if options[:environment]
|
134
|
-
environment = options[:environment]
|
57
|
+
if options[:daemon]
|
58
|
+
# Run as a daemon service
|
59
|
+
Pupistry::Agent.daemon options
|
135
60
|
else
|
136
|
-
|
61
|
+
# Single-run Agent Execution
|
62
|
+
Pupistry::Agent.apply options
|
137
63
|
end
|
138
|
-
|
139
|
-
puppet_cmd += " --environment #{environment}"
|
140
|
-
puppet_cmd += " --modulepath #{$config["agent"]["puppetcode"]}/#{environment}/modules/"
|
141
|
-
puppet_cmd += " --hiera_config #{$config["agent"]["puppetcode"]}/#{environment}/hiera.yaml"
|
142
|
-
puppet_cmd += " #{$config["agent"]["puppetcode"]}/#{environment}/manifests/site.pp"
|
143
|
-
|
144
|
-
$logger.info "Executing Puppet..."
|
145
|
-
$logger.debug "With: #{puppet_cmd}"
|
146
|
-
|
147
|
-
unless system puppet_cmd
|
148
|
-
$logger.fatal "An unexpected issue occured when running puppet"
|
149
|
-
end
|
150
|
-
|
151
64
|
end
|
152
65
|
|
153
66
|
|
@@ -243,6 +156,11 @@ class CLI < Thor
|
|
243
156
|
#
|
244
157
|
# So given this, we might as well go native and just rely on the system
|
245
158
|
# diff command to do the job.
|
159
|
+
#
|
160
|
+
# TODO: We need smarts here to handle git branching, so a branch doens't
|
161
|
+
# produce a new mega diff, we want only the real changes to be
|
162
|
+
# easily visible, or the diff function loses value to people.
|
163
|
+
# Pull requests welcome :-) xoxo
|
246
164
|
|
247
165
|
Dir.chdir("#{$config["general"]["app_cache"]}/artifacts/") do
|
248
166
|
unless system "diff -Nuar unpacked.#{artifact_upstream.checksum} unpacked.#{artifact_current.checksum}"
|
@@ -0,0 +1,173 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'fileutils'
|
3
|
+
require 'rufus/scheduler'
|
4
|
+
|
5
|
+
module Pupistry
|
6
|
+
# Pupistry::Agent
|
7
|
+
|
8
|
+
class Agent
|
9
|
+
# Functions for running the Pupistry agent aka "apply mode" to actually
|
10
|
+
# download and run Puppet against the contents of the artifact.
|
11
|
+
|
12
|
+
|
13
|
+
def self.daemon options
|
14
|
+
## Run as a daemon
|
15
|
+
|
16
|
+
|
17
|
+
# Since options comes from Thor, it can't be modified, so we need to
|
18
|
+
# copy the options and then we can edit it.
|
19
|
+
|
20
|
+
options_new = options.inject({}) do |new, (name, value)|
|
21
|
+
new[name] = value;
|
22
|
+
new
|
23
|
+
end
|
24
|
+
|
25
|
+
# If the minimal mode has been enabled in config, respect.
|
26
|
+
if $config["agent"]["daemon_minimal"]
|
27
|
+
options_new[:minimal] = true
|
28
|
+
end
|
29
|
+
|
30
|
+
# If no frequency supplied, use 300 seconds safe default.
|
31
|
+
unless $config["agent"]["daemon_frequency"]
|
32
|
+
$config["agent"]["daemon_frequency"] = 300
|
33
|
+
end
|
34
|
+
|
35
|
+
|
36
|
+
# Use rufus-scheduler to run our apply job as a regularly scheduled job
|
37
|
+
# but with build in locking handling.
|
38
|
+
|
39
|
+
$logger.info "Launching daemon... frequency of #{$config["agent"]["daemon_frequency"]} seconds."
|
40
|
+
|
41
|
+
begin
|
42
|
+
|
43
|
+
scheduler = Rufus::Scheduler.new
|
44
|
+
|
45
|
+
scheduler.every "#{$config["agent"]["daemon_frequency"]}s", :overlap => false, :timeout => '1d', :first_at => Time.now + 1 do
|
46
|
+
$logger.info "Triggering another Pupistry run (#{$config["agent"]["daemon_frequency"]}s)"
|
47
|
+
apply options_new
|
48
|
+
end
|
49
|
+
|
50
|
+
scheduler.join
|
51
|
+
|
52
|
+
rescue Rufus::Scheduler::TimeoutError
|
53
|
+
$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"
|
54
|
+
|
55
|
+
rescue SignalException => e
|
56
|
+
# Clean shutdown signal (eg SIGTERM)
|
57
|
+
$logger.info "Clean shutdown of Pupistry daemon requests"
|
58
|
+
exit 0
|
59
|
+
|
60
|
+
rescue Exception => e
|
61
|
+
raise e
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
|
66
|
+
|
67
|
+
def self.apply options
|
68
|
+
## Download and apply the latest artifact (if any)
|
69
|
+
|
70
|
+
# Fetch artifact versions
|
71
|
+
$logger.info "Checking version of artifact available..."
|
72
|
+
|
73
|
+
artifact = Pupistry::Artifact.new
|
74
|
+
artifact.checksum = artifact.fetch_latest
|
75
|
+
|
76
|
+
unless artifact.checksum
|
77
|
+
$logger.error "There is no current artifact available for download, no steps can be taken."
|
78
|
+
return false
|
79
|
+
end
|
80
|
+
|
81
|
+
artifact_installed = Pupistry::Artifact.new
|
82
|
+
artifact_installed.checksum = artifact_installed.fetch_installed
|
83
|
+
|
84
|
+
if artifact_installed.checksum
|
85
|
+
$logger.debug "Currently on #{artifact_installed.checksum}"
|
86
|
+
else
|
87
|
+
$logger.debug "No currently installed artifact - blank slate!"
|
88
|
+
end
|
89
|
+
|
90
|
+
# Download the new artifact if one has changed. If we already have this
|
91
|
+
# version, then we should skip downloading and go straight to running
|
92
|
+
# Puppet - unless the user runs with --force (eg to fix a corrupted
|
93
|
+
# artifact).
|
94
|
+
|
95
|
+
if artifact.checksum != artifact_installed.checksum or options[:force]
|
96
|
+
if options[:force]
|
97
|
+
$logger.warn "Forcing download of latest artifact regardless of current one."
|
98
|
+
end
|
99
|
+
|
100
|
+
# Install the artifact
|
101
|
+
$logger.info "Downloading latest artifact (#{artifact.checksum})..."
|
102
|
+
|
103
|
+
artifact.fetch_artifact
|
104
|
+
artifact.unpack
|
105
|
+
|
106
|
+
unless artifact.install
|
107
|
+
$logger.fatal "An unexpected error happened when installing the latest artifact, cancelling Puppet run"
|
108
|
+
return false
|
109
|
+
end
|
110
|
+
|
111
|
+
# Remove temporary unpacked files
|
112
|
+
artifact.clean_unpack
|
113
|
+
else
|
114
|
+
$logger.info "Already have latest artifact applied."
|
115
|
+
|
116
|
+
# By default we run Puppet even if we have the latest artifact. There's
|
117
|
+
# some grounds for debate about whether this is the right thing - in some
|
118
|
+
# ways it is often a waste of CPU, since if the artifact hasn't changed,
|
119
|
+
# then it's unlikley anything else has changed.
|
120
|
+
#
|
121
|
+
# But that's not always 100% true - Puppet will undo local changes or
|
122
|
+
# upgrade package versions (ensure => latest) if appropiate, so we should
|
123
|
+
# act like the standard command and attempt to apply whatever we can.
|
124
|
+
#
|
125
|
+
# To provide users with options, we provide the --lazy parameter to avoid
|
126
|
+
# running Puppet except when the artifact changes. By default, Puppet
|
127
|
+
# runs every thing to avoid surprise.
|
128
|
+
|
129
|
+
if options[:minimal]
|
130
|
+
$logger.info "Running with minimal effort mode enabled, not running Puppet since artifact version already applied"
|
131
|
+
return false
|
132
|
+
end
|
133
|
+
|
134
|
+
end
|
135
|
+
|
136
|
+
# Check if the requested environment/branch actually exists
|
137
|
+
if options[:environment]
|
138
|
+
environment = options[:environment]
|
139
|
+
else
|
140
|
+
environment = 'master'
|
141
|
+
end
|
142
|
+
|
143
|
+
unless Dir.exists?("#{$config["agent"]["puppetcode"]}/#{environment}")
|
144
|
+
$logger.fatal "The requested branch/environment of #{environment} does not exist, unable to run Puppet"
|
145
|
+
return false
|
146
|
+
end
|
147
|
+
|
148
|
+
|
149
|
+
# Execute Puppet.
|
150
|
+
puppet_cmd = "puppet apply"
|
151
|
+
|
152
|
+
if options[:noop]
|
153
|
+
puppet_cmd += " --noop"
|
154
|
+
end
|
155
|
+
|
156
|
+
puppet_cmd += " --environment #{environment}"
|
157
|
+
puppet_cmd += " --modulepath #{$config["agent"]["puppetcode"]}/#{environment}/modules/"
|
158
|
+
puppet_cmd += " --hiera_config #{$config["agent"]["puppetcode"]}/#{environment}/hiera.yaml"
|
159
|
+
puppet_cmd += " #{$config["agent"]["puppetcode"]}/#{environment}/manifests/site.pp"
|
160
|
+
|
161
|
+
$logger.info "Executing Puppet..."
|
162
|
+
$logger.debug "With: #{puppet_cmd}"
|
163
|
+
|
164
|
+
unless system puppet_cmd
|
165
|
+
$logger.error "An unexpected issue occured when running puppet"
|
166
|
+
end
|
167
|
+
|
168
|
+
end
|
169
|
+
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
# vim:shiftwidth=2:tabstop=2:softtabstop=2:expandtab:smartindent
|
data/lib/pupistry/bootstrap.rb
CHANGED
@@ -72,6 +72,8 @@ module Pupistry
|
|
72
72
|
secret_access_key: $config["agent"]["secret_access_key"],
|
73
73
|
region: $config["agent"]["region"],
|
74
74
|
proxy_uri: $config["agent"]["proxy_uri"],
|
75
|
+
daemon_frequency: $config["agent"]["daemon_frequency"],
|
76
|
+
daemon_minimal: $config["agent"]["daemon_minimal"]
|
75
77
|
}
|
76
78
|
|
77
79
|
# Generate template using ERB
|
data/lib/pupistry.rb
CHANGED
data/settings.example.yaml
CHANGED
@@ -47,6 +47,19 @@ agent:
|
|
47
47
|
region: ap-southeast-2
|
48
48
|
proxy_uri:
|
49
49
|
|
50
|
+
# (If Daemonised)
|
51
|
+
# Default is to check for a new artifact every 60 seconds, but only to
|
52
|
+
# actually run Puppet if there has been a change to the artifact contents.
|
53
|
+
#
|
54
|
+
# At a polling rate of 60 seconds, the cost of S3 will be about $0.02 per
|
55
|
+
# month per system running Pupistry.
|
56
|
+
#
|
57
|
+
# If you want to force regular Puppet runs regardless whether or not a new
|
58
|
+
# artifact has been released, turn daemon_minimal off, but make sure the
|
59
|
+
# frequency isn't too low - 300 seconds+ recommended otherwise Puppet will
|
60
|
+
# be hammering your system resources.
|
61
|
+
daemon_frequency: 60
|
62
|
+
daemon_minimal: true
|
50
63
|
|
51
64
|
|
52
65
|
# The following settings are only needed on the build machines (people building
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pupistry
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.11
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jethro Carr
|
@@ -52,6 +52,20 @@ dependencies:
|
|
52
52
|
- - '>='
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rufus-scheduler
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ~>
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '3'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ~>
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '3'
|
55
69
|
- !ruby/object:Gem::Dependency
|
56
70
|
name: r10k
|
57
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -75,6 +89,7 @@ extra_rdoc_files: []
|
|
75
89
|
files:
|
76
90
|
- bin/pupistry
|
77
91
|
- lib/pupistry.rb
|
92
|
+
- lib/pupistry/agent.rb
|
78
93
|
- lib/pupistry/artifact.rb
|
79
94
|
- lib/pupistry/bootstrap.rb
|
80
95
|
- lib/pupistry/config.rb
|