pupistry 0.0.3 → 0.0.4

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 040c9a706127947909dc602972b7e9cbd28ebe42
4
- data.tar.gz: 864c4368a6ae0d3103b4ca50d9cc987e135b077c
3
+ metadata.gz: 5ff9e16fb23fac8d09a0bf86e4bd88c452f52b29
4
+ data.tar.gz: f944f6ea67120033772613d9e88186ca9cacdbf8
5
5
  SHA512:
6
- metadata.gz: 82f9c81beee09687e742c95fd49107b1e13edb75752f24546770a72d05f944b35f4ee3513c27b6e91f9f0bd017169ce874a52cb41866c6fe6f3dbf0bb0b10135
7
- data.tar.gz: af932b06e1cef3f9f64dec3dc074e5276eb8aab4897854d8013b693c8e92aa463452b384f6041d06821e8c6fa3ba20dcb0cafcb7812fcb84124c4f46139d598b
6
+ metadata.gz: beb20b7264be3c5a105dc6cb5e405944b51126d0a9880f998ec226c058e1869bb05037fa829e962fd487d2281292d355d2bcefbe5bbb2ac2039e8bd016cad278
7
+ data.tar.gz: 0bc78b2c6f99795c877b75da67068844c89c7fc091b1c371109986d0fce1cc03d32c7ccd2b320ec412d3fe8cd02ad12d97e0719bb714d52f90cea00fb250d10a
data/README.md CHANGED
@@ -109,16 +109,56 @@ off if you have it disabled. :-)
109
109
 
110
110
  ## Bootstrapping nodes
111
111
 
112
- You need to bootstrap your masterless nodes, which involves installing Pupistry
113
- and setting up Puppet configuration accordingly.
114
-
115
- pupistry bootstrap
112
+ New machines need to be bootstrapped in order to install Pupistry, configure it
113
+ and be able to download configuration. Generally this is a step done differently
114
+ site-by-site (and you can still do it that way if you want), but if you want a
115
+ nice easy life, Pupistry can generate you a bootstrap script for your platform.
116
+
117
+ $ pupistry bootstrap
118
+ - rhel-7
119
+ - ubuntu-14.04
120
+
121
+ $ pupistry boostrap --template rhel-7
122
+ # Bootstrap for Red Hat Enterprise Linux Platform
123
+ # Compatible with RHEL 7, CentOS 7 and maybe other variations.
124
+
125
+ rpm -ivh http://yum.puppetlabs.com/puppetlabs-release-el-7.noarch.rpm
126
+ rpm -ivh http://download.fedoraproject.org/pub/epel/7/x86_64/e/epel-release-7-5.noarch.rpm
127
+
128
+ yum update --assumeyes
129
+ yum install --assumeyes puppet ruby-devel rubygems
130
+ yum install --assumeyes gcc zlib-devel libxml2-devel patch
131
+
132
+ gem install pupistry
133
+ mkdir /etc/pupistry
134
+ cat > /etc/pupistry/settings.yaml << "EOF"
135
+ general:
136
+ app_cache: ~/.pupistry/cache
137
+ s3_bucket: example
138
+ s3_prefix:
139
+ gpg_disable: true
140
+ gpg_signing_key: XYZXYZ
141
+ agent:
142
+ puppetcode: /etc/puppet/environents/
143
+ access_key_id:
144
+ secret_access_key:
145
+ region: ap-southeast-2
146
+ proxy_uri:
147
+ EOF
148
+ pupistry apply --verbose
116
149
 
117
- pupistry boostrap --template rhel7
150
+ You generally can run this on a new non-Puppetised machine, or paste into the
151
+ user data field of most cloud providers like AWS or Digital Ocean. If using CFN
152
+ with AWS, you can make it part of the stack itself.
118
153
 
154
+ These bootstraps aren't mandatory, if you prefer a different approach you can
155
+ use these as an example and write your own - generally the essential bit is to
156
+ get puppet installed, get pupistry (and deps to build it's gems) installed and
157
+ write the config before finally executing your first Pupistry/Puppet run.
119
158
 
120
- You generally can run this on a new non-Puppetised machine, or into the user
121
- data field of most cloud providers like AWS or Digital Ocean.
159
+ If using AWS and IAM Roles feature, it is acceptable for access_key_id and
160
+ secret_access_key to be blank, if not you will need to have these set to an
161
+ account with read-only access to the configured S3 bucket!
122
162
 
123
163
 
124
164
  ## Running Puppet on target nodes
@@ -230,7 +270,7 @@ Pupistry will default to applying the "master" branch if one is not listed, if
230
270
  you are doing branch-based environments, you can specifiy when bootstrapping
231
271
  and override on a per-execution basis.
232
272
 
233
- You'll notice pretty quickly if something is broken when doing `puppet apply`
273
+ You'll notice pretty quickly if something is broken when doing `pupistry apply`
234
274
 
235
275
  Confused? No worried, check out the sample repo that shows a very simple setup.
236
276
  You can copy this and start your own Puppet adventure, just add in your modules
@@ -258,11 +298,15 @@ You can fetch the module from:
258
298
  https://github.com/jethrocarr/puppet-pupistry
259
299
 
260
300
  If you're doing r10k and Puppet masterless from scratch, this is probably
261
- something you want to make life easy.
301
+ something you want to make life easy. With r10k, just add the following to your
302
+ Puppetfile:
262
303
 
304
+ # Install the Pupistry companion module
305
+ mod 'jethrocarr/pupistry'
263
306
 
264
307
 
265
- ## 4. Bootstrapping Nodes
308
+
309
+ ## 4. Building you first node (Bootstrapping)
266
310
 
267
311
  No need for manual configuration of your servers/nodes, you just need to build
268
312
  your first artifact with Pupistry (`pupistry build && pupistry push`) and then
@@ -274,41 +318,12 @@ The bootstrap script will:
274
318
  2. Download the latest artifact
275
319
  3. Trigger a Puppet run to build your server.
276
320
 
277
- Once done, it's up to your Puppet manifests to build your machine how you want
278
- it - enjoy!
279
-
280
- TODO: Currently being worked on, for now the following is a rough example of
281
- what you can do to bootstrap a RHEL/CentOS7 box:
282
-
283
- rpm -ivh http://yum.puppetlabs.com/puppetlabs-release-el-7.noarch.rpm
284
- rpm -ivh http://download.fedoraproject.org/pub/epel/7/x86_64/e/epel-release-7-5.noarch.rpm
285
-
286
- yum update --assumeyes
287
- yum install --assumeyes puppet ruby-devel rubygems
288
- yum install --assumeyes gcc zlib-devel libxml2-devel patch
289
-
290
- gem install pupistry
291
- mkdir /etc/pupistry
292
- cat > /etc/pupistry/settings.yaml << "EOF"
293
- general:
294
- app_cache: ~/.pupistry/cache
295
- s3_bucket: example
296
- s3_prefix:
297
- gpg_disable: true
298
- gpg_signing_key: XXXXX
299
- agent:
300
- puppetcode: /etc/puppet/environments
301
- access_key_id:
302
- secret_access_key:
303
- region: ap-southeast-2
304
- proxy_uri:
305
- EOF
306
- pupistry apply --verbose
307
-
308
- It will setup the Puppet repo for RHEL 7, install updates (remember that security
309
- thing?) and then install the gem (and deps to build it). Then we generate the
310
- minimal configuration file needed, and kick off a Puppet run!
321
+ These bootstrap scripts can be generated for you. Refer to "Bootstrapping" under
322
+ "Usage" instructions above for details.
311
323
 
324
+ The bootstrap script goal is to get you from stock OS to running Pupistry and
325
+ doing your first Puppet run. After that - it's up to you and your Puppet
326
+ skills to make your node actually do something useful. :-)
312
327
 
313
328
 
314
329
  # Tutorials
data/bin/pupistry CHANGED
@@ -23,9 +23,11 @@ class CLI < Thor
23
23
  ## Agent Commands
24
24
 
25
25
  desc "apply", "Apply the latest Puppet artifact"
26
- method_option :noop, :type => :boolean
27
- method_option :daemon, :type => :boolean
28
- method_option :environment, :type => :string
26
+ method_option :noop, :type => :boolean, :desc => "No changes mode (note: does change checked out artifact, but no Puppet changes)"
27
+ method_option :force, :type => :boolean, :desc => "Ignore existing versions, re-apply every time"
28
+ method_option :minimal, :type => :boolean, :desc => "Don't run Puppet unless the artifact has changed"
29
+ method_option :daemon, :type => :boolean, :desc => "Run as a system daemon"
30
+ method_option :environment, :type => :string, :desc => "Specifiy which environment to deploy (default: master)"
29
31
  def apply
30
32
 
31
33
  # Thor seems to force class options to be defined repeatedly? :-/
@@ -52,24 +54,66 @@ class CLI < Thor
52
54
  exit 0
53
55
  end
54
56
 
55
- # Install the artifact
56
- # TODO: Check if we've already installed it or not... :-)
57
- $logger.info "Pulling latest artifact...."
57
+
58
+ # Fetch artifact versions
59
+ $logger.info "Checking version of artifact available..."
58
60
 
59
61
  artifact = Pupistry::Artifact.new
60
62
  artifact.checksum = artifact.fetch_latest
61
- artifact.fetch_artifact
62
- artifact.unpack
63
- unless artifact.install
64
- $logger.fatal "An unexpected error happened when installing the latest artifact, cancelling Puppet run"
65
- exit 0
66
- end
67
63
 
68
- # Remove temporary unpacked files
69
- artifact.clean_unpack
64
+ artifact_installed = Pupistry::Artifact.new
65
+ artifact_installed.checksum = artifact_installed.fetch_installed
70
66
 
71
67
 
72
- # Execute Puppet. At this point
68
+ # Download the new artifact if one has changed. If we already have this
69
+ # version, then we should skip downloading and go straight to running
70
+ # Puppet - unless the user runs with --force (eg to fix a corrupted
71
+ # artifact).
72
+ $logger.debug "Currently on #{artifact_installed.checksum}"
73
+
74
+ if artifact.checksum != artifact_installed.checksum or options[:force]
75
+ if options[:force]
76
+ $logger.warn "Forcing download of latest artifact regardless of current one."
77
+ end
78
+
79
+ # Install the artifact
80
+ $logger.info "Downloading latest artifact (#{artifact.checksum})..."
81
+
82
+ artifact.fetch_artifact
83
+ artifact.unpack
84
+
85
+ unless artifact.install
86
+ $logger.fatal "An unexpected error happened when installing the latest artifact, cancelling Puppet run"
87
+ exit 0
88
+ end
89
+
90
+ # Remove temporary unpacked files
91
+ artifact.clean_unpack
92
+ else
93
+ $logger.info "Already have latest artifact applied."
94
+
95
+ # By default we run Puppet even if we have the latest artifact. There's
96
+ # some grounds for debate about whether this is the right thing - in some
97
+ # ways it is often a waste of CPU, since if the artifact hasn't changed,
98
+ # then it's unlikley anything else has changed.
99
+ #
100
+ # But that's not always 100% true - Puppet will undo local changes or
101
+ # upgrade package versions (ensure => latest) if appropiate, so we should
102
+ # act like the standard command and attempt to apply whatever we can.
103
+ #
104
+ # To provide users with options, we provide the --lazy parameter to avoid
105
+ # running Puppet except when the artifact changes. By default, Puppet
106
+ # runs every thing to avoid surprise.
107
+
108
+ if options[:minimal]
109
+ $logger.info "Running with minimal effort mode enabled, not running Puppet since artifact version already applied"
110
+ exit 0
111
+ end
112
+
113
+ end
114
+
115
+
116
+ # Execute Puppet.
73
117
  puppet_cmd = "puppet apply"
74
118
 
75
119
  if options[:noop]
@@ -242,11 +286,15 @@ class CLI < Thor
242
286
 
243
287
  if options[:template]
244
288
  $logger.info "Generating bootstrap template #{options[:template]}"
245
- else
246
- puts "Listing all avaible templates"
247
- Pupistry::Bootstrap.templates_list
248
289
 
249
-
290
+ templates = Pupistry::Bootstrap.new
291
+ templates.build options[:template]
292
+ else
293
+ templates = Pupistry::Bootstrap.new
294
+ templates.list
295
+
296
+ puts "--"
297
+ puts "Tip: Run `pupistry bootstrap --template example` to generate a specific template"
250
298
  end
251
299
 
252
300
  end
@@ -111,6 +111,27 @@ module Pupistry
111
111
  end
112
112
 
113
113
 
114
+ def fetch_installed
115
+ # Fetch the current version that is installed.
116
+
117
+ # Make sure the Puppetcode install directory exists
118
+ unless Dir.exists?($config["agent"]["puppetcode"])
119
+ $logger.warn "The destination path of #{$config["agent"]["puppetcode"]} does not appear to exist or is not readable"
120
+ return 0
121
+ end
122
+
123
+ # Look for a manifest file in the directory and read the version from it.
124
+ if File.exists?($config["agent"]["puppetcode"] + "/manifest.pupistry.yaml")
125
+ manifest = YAML::load(File.open($config["agent"]["puppetcode"] + "/manifest.pupistry.yaml"))
126
+
127
+ return manifest['version']
128
+ else
129
+ $logger.warn "No current version installed"
130
+ return 0
131
+ end
132
+ end
133
+
134
+
114
135
  def fetch_artifact
115
136
 
116
137
  # Figure out which version to fetch (if not explicitly defined)
@@ -387,6 +408,7 @@ module Pupistry
387
408
  # Clone unpacked contents to the installation directory
388
409
  begin
389
410
  FileUtils.cp_r $config["general"]["app_cache"] + "/artifacts/unpacked.#{@checksum}/puppetcode/.", $config["agent"]["puppetcode"]
411
+ FileUtils.cp $config["general"]["app_cache"] + "/artifacts/manifest.#{@checksum}.yaml", $config["agent"]["puppetcode"] + "/manifest.pupistry.yaml"
390
412
  return true
391
413
  rescue
392
414
  $logger.fatal "An unexpected error occured when copying the unpacked artifact to #{$config["agent"]["puppetcode"]}"
@@ -395,7 +417,6 @@ module Pupistry
395
417
 
396
418
  end
397
419
 
398
-
399
420
  def clean_install
400
421
  # Cleanup the destination installation directory before we unpack the artifact
401
422
  # into it, otherwise long term we will end up with old deprecated files hanging
@@ -1,4 +1,5 @@
1
1
  require 'rubygems'
2
+ require 'erubis'
2
3
 
3
4
  module Pupistry
4
5
  # Pupistry::Bootstrap
@@ -6,16 +7,82 @@ module Pupistry
6
7
  class Bootstrap
7
8
  attr_accessor :template_dir
8
9
 
9
- def initalize
10
- template_dir = "dir"
10
+ def initialize
11
+
12
+ # We need to find where the templates are located - either it should be
13
+ # in the current working directory, or if we are an installed gem, we
14
+ # can try the gem's installed path.
15
+
16
+ if Dir.exists?("resources/bootstrap/")
17
+ # Use local PWD version first if possible
18
+ @template_dir = Dir.pwd
19
+ else
20
+ # Check for GEM installed location
21
+ begin
22
+ @template_dir = Gem::Specification.find_by_name("pupistry").gem_dir
23
+ rescue Gem::LoadError
24
+ $logger.error "Unable to find templates/ directory, doesn't appear we are running from project dir nor as a Gem"
25
+ return false
26
+ end
27
+ end
28
+
29
+ @template_dir = @template_dir.chomp("/") + "/resources/bootstrap/"
30
+
31
+ unless Dir.exists?(@template_dir)
32
+ $logger.error "Unable to find templates dir at #{@template_dir}, unable to proceed."
33
+ return false
34
+ else
35
+ $logger.debug "Using directory #{@template_dir} for bootstrap templates"
36
+ end
37
+
11
38
  end
12
39
 
13
- def self.templates_list
14
- # glob all the templates
15
- puts "Template"
40
+
41
+ def list
42
+ # Simply glob the templates directory and list their names.
43
+ $logger.debug "Finding all available templates"
44
+
45
+ Dir.glob("#{@template_dir}/*.erb").each do |file|
46
+ puts "- #{File.basename(file, ".erb")}"
47
+ end
16
48
  end
17
49
 
18
50
 
51
+ def build template
52
+ # Build a template with the configured parameters already to go
53
+ $logger.debug "Generating a bootstrap script for #{template}"
54
+
55
+ unless File.exists?("#{@template_dir}/#{template}.erb")
56
+ $logger.error "The requested template does not exist, unable to build"
57
+ return 0
58
+ end
59
+
60
+ # Assume values we care about
61
+ template_values = {
62
+ s3_bucket: $config["general"]["s3_bucket"],
63
+ s3_prefix: $config["general"]["s3_prefix"],
64
+ gpg_disable: $config["general"]["gpg_disable"],
65
+ gpg_signing_key: $config["general"]["gpg_signing_key"],
66
+ puppetcode: $config["agent"]["puppetcode"],
67
+ access_key_id: $config["agent"]["access_key_id"],
68
+ secret_access_key: $config["agent"]["secret_access_key"],
69
+ region: $config["agent"]["region"],
70
+ proxy_uri: $config["agent"]["proxy_uri"],
71
+ }
72
+
73
+ # Generate template using ERB
74
+ begin
75
+ template_contents = Erubis::Eruby.new(File.read("#{@template_dir}/#{template}.erb")).result(template_values)
76
+ rescue Exception => e
77
+ $logger.error "An unexpected error occured when trying to generate the bootstrap template"
78
+ raise e
79
+ end
80
+
81
+ # Output template
82
+ puts "-- Bootstrap Start --"
83
+ puts template_contents
84
+ puts "-- Bootstrap End --"
85
+ end
19
86
  end
20
87
  end
21
88
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pupistry
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jethro Carr
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-04-10 00:00:00.000000000 Z
11
+ date: 2015-04-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: aws-sdk-v1
@@ -38,6 +38,20 @@ dependencies:
38
38
  - - '>='
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: erubis
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
41
55
  - !ruby/object:Gem::Dependency
42
56
  name: r10k
43
57
  requirement: !ruby/object:Gem::Requirement