pupistry 0.0.10 → 0.0.11

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e5f9601622da2e9d834ecb81aec0b908ef5ad12e
4
- data.tar.gz: 2fdd67a6cb8433ee0556e24b3c17ee0836657849
3
+ metadata.gz: b516bef9aa8033e4871098cd224fe497ef82f1b6
4
+ data.tar.gz: 7b158bdc381764e80618a4236e6287d19ac6670e
5
5
  SHA512:
6
- metadata.gz: f13aeefb955e9784a5c1b34d861ef6ff2f6d7c94e89ac0f1c0d0bcb7f28409bc2b3e76a62786da160773d872bc229b5b52715c08fbecae8dea7f3b713254664b
7
- data.tar.gz: 044fd9496533f320be7f0a0e17963b8713a5ca00f70408ae0858587005a41e4ea1c74b71b3bec8d2eaf7132afdf821499fd1d806a145abb1f70de706981b5217
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
- # Muppet dev check
53
- if options[:daemon]
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
- # Execute Puppet.
127
- puppet_cmd = "puppet apply"
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
- environment = 'master'
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
@@ -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
@@ -1,3 +1,4 @@
1
+ require 'pupistry/agent'
1
2
  require 'pupistry/artifact'
2
3
  require 'pupistry/bootstrap'
3
4
  require 'pupistry/config'
@@ -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.10
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