pupistry 1.1.0 → 1.2.0

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: 8e3280a3e4dd9385278ae57d3ce8ac72ada37c0f
4
- data.tar.gz: 1625107171f0d871a16b35008fac3c5e4ba3db63
3
+ metadata.gz: 19803e351862b0c1f835d5a9091f94cd980adb1e
4
+ data.tar.gz: bd052ce0fe5a40568c75fa53ab157653f70afaa8
5
5
  SHA512:
6
- metadata.gz: 388aeb48985189832a1acd9f3e469cf07ec3a3eb784dee51fea8be3fae325dac439802727d8e7efcf124304e035ed9b53450051c0a2df3cdb4e35b7db5378b60
7
- data.tar.gz: c8c90250e40b22b82c9192a96dc3f1d572d84b6b4f01c7303be889ffaadee86ea266fa76c800f521338696ad7537875c83c6ab49a8a75a196e2c6db9d6de455d
6
+ metadata.gz: 4ca14cd1082df16d9b2ade7d5e6d839abbd681195d8fe118ef5fe601540900ef067fabd7582dd436fc951031a4e1674debc10299c7e751c42caddb593a112fb4
7
+ data.tar.gz: b25c20084c6243a78eefcdd5163db87aa47ecc8a5116405177a39d68d5d14001005e8a496b810c05e068af621360329f944f88d3d2df26e08746308c4693ebe2
data/README.md CHANGED
@@ -376,13 +376,44 @@ The bootstrap script goal is to get you from stock OS to running Pupistry and
376
376
  doing your first Puppet run. After that - it's up to you and your Puppet
377
377
  skills to make your node actually do something useful. :-)
378
378
 
379
+
380
+ ## 5. (optional) Baking an image with Packer
381
+
379
382
  Note that the node initialisation process is still susceptable to weaknesses
380
383
  such as a bug in a new version of Puppet or Pupistry, or changes to the OS
381
384
  packages. If this is a concern/issue for you and you want complete reliability,
382
385
  then use the user data to build a host pre-loaded with Puppet and Pupistry and
383
- then create an image of it using a tool like Packer. Doing this, you can make
384
- it possible to build all the way to Puppet execution with no dependencies on any
385
- third parties other than your VM provider and AWS S3.
386
+ then create an image of it using a tool like [Packer](www.packer.io). Doing
387
+ this, you can make it possible to build all the way to Puppet execution with no
388
+ dependencies on any third parties other than your VM provider and AWS S3.
389
+
390
+ Pupistry includes support for generating some Packer examples that you can
391
+ either use as-is or built upon to meet your own needs. You can list all the
392
+ available Packer templates with:
393
+
394
+ pupistry packer
395
+
396
+ You can select a template and generate a Packer file by specifying the template
397
+ and the output file on the command line:
398
+
399
+ pupistry packer --template aws_amazon-any --file packer.json
400
+
401
+ Once the file has been generated, you can build your packer environment with
402
+ the `packer build` command. Note that some templates will require additional
403
+ variables to be passed to them at run time, for example the AWS template
404
+ requires a VPC ID and subnet ID specific to your account.
405
+
406
+ packer build \
407
+ -var 'aws_vpc_id=vpc-example' \
408
+ -var 'aws_subnet_id=subnet-example' \
409
+ output.json
410
+
411
+ By default any Packer machines are built with the hostname of "packer" which
412
+ allows you to specifically target them with your manifests. If you don't do any
413
+ targetting, the default manifests will be applied.
414
+
415
+ Templates tend to have other customisable variables, check the available
416
+ options and their defaults with `packer inspect output.json`.
386
417
 
387
418
 
388
419
  # Tutorials
data/exe/pupistry CHANGED
@@ -215,6 +215,44 @@ class CLI < Thor
215
215
  end
216
216
  end
217
217
 
218
+ desc 'packer', 'Generate a packer template for a particular provider with OS bootstrap script included'
219
+ method_option :template, type: :string, desc: 'The template you want to generate'
220
+ method_option :file, type: :string, desc: 'File to write the generated packer template into'
221
+ def packer
222
+ # Thor seems to force class options to be defined repeatedly? :-/
223
+ if options[:verbose]
224
+ $logger.level = Logger::DEBUG
225
+ else
226
+ $logger.level = Logger::INFO
227
+ end
228
+
229
+ if options[:config]
230
+ Pupistry::Config.load(options[:config])
231
+ else
232
+ Pupistry::Config.find_and_load
233
+ end
234
+
235
+ if options[:template]
236
+ $logger.info "Generating packer template #{options[:template]}"
237
+
238
+ templates = Pupistry::Packer.new
239
+ templates.build options[:template]
240
+
241
+ if options[:file]
242
+ templates.output_file options[:file]
243
+ else
244
+ templates.output_plain
245
+ end
246
+ else
247
+ templates = Pupistry::Packer.new
248
+ templates.list
249
+
250
+ puts '--'
251
+ puts 'Tip: Run `pupistry packer --template example` to generate a specific template'
252
+ end
253
+ end
254
+
255
+
218
256
  ## Other Commands
219
257
 
220
258
  desc 'setup', 'Write a template configuration file'
@@ -82,6 +82,12 @@ module Pupistry
82
82
  end
83
83
  end
84
84
 
85
+ def output_array
86
+ # Return the output as an array of lines. Useful by other internal
87
+ # methods such as Packer templates.
88
+ @contents.split(/\n/)
89
+ end
90
+
85
91
  def output_plain
86
92
  # Do nothing clever, just output the template data.
87
93
  puts '-- Bootstrap Start --'
@@ -0,0 +1,116 @@
1
+ # rubocop:disable Style/Documentation, Style/GlobalVars
2
+ require 'rubygems'
3
+ require 'erubis'
4
+
5
+ module Pupistry
6
+ # Pupistry::Packer
7
+
8
+ class Packer
9
+ attr_accessor :template_dir
10
+ attr_accessor :contents
11
+
12
+ def initialize
13
+ # We need to find where the templates are located - either it should be
14
+ # in the current working directory, or if we are an installed gem, we
15
+ # can try the gem's installed path.
16
+
17
+ if Dir.exist?('resources/packer/')
18
+ # Use local PWD version first if possible
19
+ @template_dir = Dir.pwd
20
+ else
21
+ # Check for GEM installed location
22
+ begin
23
+ @template_dir = Gem::Specification.find_by_name('pupistry').gem_dir
24
+ rescue Gem::LoadError
25
+ $logger.error "Unable to find packer templates directory, doesn't appear we are running from project dir nor as a Gem"
26
+ return false
27
+ end
28
+ end
29
+
30
+ @template_dir = @template_dir.chomp('/') + '/resources/packer/'
31
+
32
+ if Dir.exist?(@template_dir)
33
+ $logger.debug "Using directory #{@template_dir} for packer templates"
34
+ else
35
+ $logger.error "Unable to find packer templates dir at #{@template_dir}, unable to proceed."
36
+ return false
37
+ end
38
+ end
39
+
40
+ def list
41
+ # Simply glob the templates directory and list their names.
42
+ $logger.debug 'Finding all available templates'
43
+
44
+ Dir.glob("#{@template_dir}/*.erb").each do |file|
45
+ puts "- #{File.basename(file, '.json.erb')}"
46
+ end
47
+ end
48
+
49
+ def build(template)
50
+ # Build a template with the configured parameters already to go and save
51
+ # into the object, so it can be outputted in the desired format.
52
+
53
+ $logger.debug "Generating a packer template using #{template}"
54
+
55
+ unless File.exist?("#{@template_dir}/#{template}.json.erb")
56
+ $logger.error 'The requested template does not exist, unable to build'
57
+ return 0
58
+ end
59
+
60
+ # Extract the OS bootstrap name from the template filename, we can then
61
+ # generate the bootstrap commands to be inserted inline into the packer
62
+ # configuration.
63
+
64
+ matches = template.match(/^\S*_(\S*)$/)
65
+
66
+ if matches[1]
67
+ $logger.debug "Fetching bootstrap data for #{matches[1]}..."
68
+ else
69
+ $logger.error 'Unable to parse the packer filename properly'
70
+ return 0
71
+ end
72
+
73
+ bootstrap = Pupistry::Bootstrap.new
74
+ unless bootstrap.build matches[1]
75
+ $logger.error 'An unexpected error occured when building the bootstrap data to go inside Packer'
76
+ end
77
+
78
+ # Pass the values we care about to the template
79
+ template_values = {
80
+ bootstrap_commands: bootstrap.output_array
81
+ }
82
+
83
+ # Generate template using ERB
84
+ begin
85
+ @contents = Erubis::Eruby.new(File.read("#{@template_dir}/#{template}.json.erb")).result(template_values)
86
+ rescue StandardError => e
87
+ $logger.error 'An unexpected error occured when trying to generate the packer template'
88
+ raise e
89
+ end
90
+ end
91
+
92
+ def output_plain
93
+ # Do nothing clever, just output the template data.
94
+ puts '-- Packer Start --'
95
+ puts @contents
96
+ puts '-- Packer End --'
97
+ puts 'Tip: add --file output.json to write out the packer file directly and then run with `packer build output.json`'
98
+ end
99
+
100
+ def output_file(filename)
101
+ # Write the template to the specified file
102
+ begin
103
+ File.open(filename, 'w') do |f|
104
+ f.puts @contents
105
+ end
106
+ rescue StandardError => e
107
+ $logger.error "An unexpected erorr occured when attempting to write the template to #{filename}"
108
+ raise e
109
+ else
110
+ $logger.info "Wrote template into file #{filename} successfully."
111
+ end
112
+ end
113
+ end
114
+ end
115
+
116
+ # vim:shiftwidth=2:tabstop=2:softtabstop=2:expandtab:smartindent
@@ -1,3 +1,3 @@
1
1
  module Pupistry
2
- VERSION = '1.1.0'
2
+ VERSION = '1.2.0'
3
3
  end
data/lib/pupistry.rb CHANGED
@@ -4,6 +4,7 @@ require 'pupistry/artifact'
4
4
  require 'pupistry/bootstrap'
5
5
  require 'pupistry/config'
6
6
  require 'pupistry/gpg'
7
+ require 'pupistry/packer'
7
8
  require 'pupistry/storage_aws'
8
9
 
9
10
  # vim:shiftwidth=2:tabstop=2:softtabstop=2:expandtab:smartindent
@@ -12,6 +12,8 @@
12
12
  # * We can't rely on Bash, since it's not available in FreeBSD by default.
13
13
  #
14
14
 
15
+ setenv PATH /sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin
16
+
15
17
  env ASSUME_ALWAYS_YES=YES pkg bootstrap
16
18
  env ASSUME_ALWAYS_YES=YES pkg upgrade --yes
17
19
  env ASSUME_ALWAYS_YES=YES pkg install --yes ruby devel/ruby-gems puppet gnupg
@@ -37,5 +39,5 @@ agent:
37
39
  EOF
38
40
  chmod 700 /usr/local/etc/pupistry
39
41
  chmod 700 /usr/local/etc/puppetlabs/code/environments
40
- pupistry apply --verbose
42
+ /usr/local/bin/pupistry apply --verbose
41
43
 
@@ -0,0 +1,49 @@
1
+ # Packer Templates
2
+
3
+ This directory contains templates for use with Packer (https://www.packer.io/).
4
+
5
+ It can be very useful to use Packer with Pupistry, since it allows you to
6
+ create your own image with Puppet, Pupistry and updates already loaded which
7
+ is very useful when doing autoscaling and you need fast, consistent startup
8
+ times.
9
+
10
+ The packer templates provided will build an image which has Pupistry installed
11
+ and will apply any manifests that match hostname of "packer". This should give
12
+ you a good general purpose image, but if you want to autoscale a particular app
13
+ you may wish to build packer images using specific hostnames to match your
14
+ Puppet manifests
15
+
16
+ Additional packer templates for major platforms are always welcome. Please
17
+ submit a pull request for review and if acceptable, will be merged.
18
+
19
+
20
+ # Usage
21
+
22
+ Refer to the main application README.md file for usage information.
23
+
24
+
25
+ # Development Notes
26
+
27
+ The filenames of the templates must be in the format of
28
+ PLATFORM_OPERATINGSYSTEM.json.erb, this is intentional since OPERATINGSYSTEM
29
+ then matches one of the OSes in the bootstrap directory and we can
30
+ automatically populate the inline shell commands.
31
+
32
+ When debugging broken packer template runs, add -debug to the build command
33
+ to have control over stepping through the build process. This will give you
34
+ the ability to log into the instance before it gets terminated to do any
35
+ debugging on the system if needed.
36
+
37
+
38
+ # Examples
39
+
40
+ See the "aws_amazon-any.json.erb" template for an example on how the templates
41
+ should be written for AWS.
42
+
43
+
44
+ # Life Span
45
+
46
+ Any distribution that is EOL and no longer supported by either the distribution
47
+ or by Puppetlabs will be subject to removal to keep the bootstrap selection
48
+ modern and clean. Pull requests to clean up cruft are accepted.
49
+
@@ -0,0 +1,38 @@
1
+ {
2
+ "variables": {
3
+ "aws_access_key": "",
4
+ "aws_secret_key": "",
5
+ "aws_ami": "ami-fd9cecc7",
6
+ "aws_region": "ap-southeast-2",
7
+ "aws_ami_name": "pupistry aws_amazon-any {{isotime \"2006-01-02\"}}",
8
+ "aws_vpc_id": null,
9
+ "aws_subnet_id": null,
10
+ "hostname": "packer"
11
+ },
12
+ "builders": [{
13
+ "type": "amazon-ebs",
14
+ "access_key": "{{user `aws_access_key`}}",
15
+ "secret_key": "{{user `aws_secret_key`}}",
16
+ "region": "{{user `aws_region`}}",
17
+ "source_ami": "{{user `aws_ami`}}",
18
+ "instance_type": "t2.micro",
19
+ "ssh_username": "ec2-user",
20
+ "vpc_id": "{{user `aws_vpc_id`}}",
21
+ "subnet_id": "{{user `aws_subnet_id`}}",
22
+ "ami_name": "{{user `aws_ami_name`}}"
23
+ }],
24
+ "provisioners": [{
25
+ "type": "shell",
26
+ "inline": ["sudo hostname {{user `hostname`}}"]
27
+ },
28
+ {
29
+ "type": "shell",
30
+ "inline_shebang": "/bin/bash -x",
31
+ "execute_command": "chmod +x {{ .Path }}; {{ .Vars }} sudo '{{ .Path }}'",
32
+ "inline": <%= bootstrap_commands %>
33
+ },
34
+ {
35
+ "type": "shell",
36
+ "inline": ["sudo rm -rf /tmp/*"]
37
+ }]
38
+ }
@@ -0,0 +1,39 @@
1
+ {
2
+ "variables": {
3
+ "aws_access_key": "",
4
+ "aws_secret_key": "",
5
+ "aws_ami": "ami-193f5123",
6
+ "aws_region": "ap-southeast-2",
7
+ "aws_ami_name": "pupistry aws_freebsd-10 {{isotime \"2006-01-02\"}}",
8
+ "aws_vpc_id": null,
9
+ "aws_subnet_id": null,
10
+ "hostname": "packer"
11
+ },
12
+ "builders": [{
13
+ "type": "amazon-ebs",
14
+ "access_key": "{{user `aws_access_key`}}",
15
+ "secret_key": "{{user `aws_secret_key`}}",
16
+ "region": "{{user `aws_region`}}",
17
+ "source_ami": "{{user `aws_ami`}}",
18
+ "instance_type": "t2.micro",
19
+ "ssh_username": "ec2-user",
20
+ "ssh_timeout": "15m",
21
+ "vpc_id": "{{user `aws_vpc_id`}}",
22
+ "subnet_id": "{{user `aws_subnet_id`}}",
23
+ "ami_name": "{{user `aws_ami_name`}}"
24
+ }],
25
+ "provisioners": [{
26
+ "type": "shell",
27
+ "inline": ["su -m root -c 'hostname {{user `hostname`}}'"]
28
+ },
29
+ {
30
+ "type": "shell",
31
+ "inline_shebang": "/bin/tcsh",
32
+ "execute_command": "chmod +x {{ .Path }}; {{ .Vars }} su -m root -c '/bin/tcsh {{ .Path }}'",
33
+ "inline": <%= bootstrap_commands %>
34
+ },
35
+ {
36
+ "type": "shell",
37
+ "inline": ["su -m root -c 'rm -rf /tmp/*'"]
38
+ }]
39
+ }
@@ -0,0 +1,38 @@
1
+ {
2
+ "variables": {
3
+ "aws_access_key": "",
4
+ "aws_secret_key": "",
5
+ "aws_ami": "ami-19c8b123",
6
+ "aws_region": "ap-southeast-2",
7
+ "aws_ami_name": "pupistry aws_ubuntu-14.04 {{isotime \"2006-01-02\"}}",
8
+ "aws_vpc_id": null,
9
+ "aws_subnet_id": null,
10
+ "hostname": "packer"
11
+ },
12
+ "builders": [{
13
+ "type": "amazon-ebs",
14
+ "access_key": "{{user `aws_access_key`}}",
15
+ "secret_key": "{{user `aws_secret_key`}}",
16
+ "region": "{{user `aws_region`}}",
17
+ "source_ami": "{{user `aws_ami`}}",
18
+ "instance_type": "t2.micro",
19
+ "ssh_username": "ubuntu",
20
+ "vpc_id": "{{user `aws_vpc_id`}}",
21
+ "subnet_id": "{{user `aws_subnet_id`}}",
22
+ "ami_name": "{{user `aws_ami_name`}}"
23
+ }],
24
+ "provisioners": [{
25
+ "type": "shell",
26
+ "inline": ["sudo hostname {{user `hostname`}}"]
27
+ },
28
+ {
29
+ "type": "shell",
30
+ "inline_shebang": "/bin/bash -x",
31
+ "execute_command": "chmod +x {{ .Path }}; {{ .Vars }} sudo '{{ .Path }}'",
32
+ "inline": <%= bootstrap_commands %>
33
+ },
34
+ {
35
+ "type": "shell",
36
+ "inline": ["sudo rm -rf /tmp/*"]
37
+ }]
38
+ }
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: 1.1.0
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jethro Carr
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2015-05-31 00:00:00.000000000 Z
11
+ date: 2015-06-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -177,6 +177,7 @@ files:
177
177
  - lib/pupistry/bootstrap.rb
178
178
  - lib/pupistry/config.rb
179
179
  - lib/pupistry/gpg.rb
180
+ - lib/pupistry/packer.rb
180
181
  - lib/pupistry/storage_aws.rb
181
182
  - lib/pupistry/version.rb
182
183
  - lib/pupistry.rb
@@ -190,8 +191,10 @@ files:
190
191
  - resources/bootstrap/fedora-any.erb
191
192
  - resources/bootstrap/freebsd-10.erb
192
193
  - resources/bootstrap/ubuntu-14.04.erb
193
- - resources/packer/amazon_linux.json
194
- - resources/packer/test_user_data.txt
194
+ - resources/packer/aws_amazon-any.json.erb
195
+ - resources/packer/aws_freebsd-10.json.erb
196
+ - resources/packer/aws_ubuntu-14.04.json.erb
197
+ - resources/packer/PACKER_NOTES.md
195
198
  - README.md
196
199
  - settings.example.yaml
197
200
  homepage: https://github.com/jethrocarr/pupistry
@@ -1,17 +0,0 @@
1
- {
2
- "variables": {
3
- "aws_access_key": "",
4
- "aws_secret_key": ""
5
- },
6
- "builders": [{
7
- "type": "amazon-ebs",
8
- "access_key": "{{user `aws_access_key`}}",
9
- "secret_key": "{{user `aws_secret_key`}}",
10
- "region": "ap-southeast-2",
11
- "source_ami": "ami-fd9cecc7",
12
- "instance_type": "m3.medium",
13
- "ssh_username": "ec2-user",
14
- "ami_name": "pupistry default {{timestamp}}",
15
- "user_data": "test_user_data.txt"
16
- }]
17
- }
@@ -1,33 +0,0 @@
1
- -- Bootstrap Start --
2
- IyEvYmluL2Jhc2ggLXgKIyBUaGlzIGJvb3RzdHJhcCBpcyBzcGVjaWZjaWFs
3
- bHkgZm9yIEFtYXpvbidzIExpbnV4IEFNSXMsIGlmIHlvdSBhcmUgdXNpbmcK
4
- IyBvdGhlciBkaXN0cmlidXRpb25zIGxpa2UgVWJ1bnR1IG9yIENlbnRPUyBv
5
- biBBV1MsIHVzZSB0aG9zZSBib290c3RyYXAKIyB0ZW1wbGF0ZXMuCiMKIyBB
6
- bWF6b24gTGludXggaXMgYmFzZWQgb24gUkhFTCwgYnV0IGhhcyBhIGxvdCBt
7
- b3JlIHZhcmlhdGlvbnMgdGhhdCBvdGhlcgojIGNsb25lcyBsaWtlIENlbnRP
8
- Uywgc3VjaCBhcyBzaGlwcGluZyB3aXRoIG11bHRpcGxlIHZlcnNpb25zIG9m
9
- IFB1cHBldAojIGFuZCBSdWJ5IC0gd2hpY2ggaXMgdXNlZnVsLCBidXQgY2Fu
10
- IGFsc28gbWFrZSBsaWZlLi4uLiBpbnRlcmVzdGluZy4KKApleGVjIDE+ID4o
11
- bG9nZ2VyIC1zIC10IHVzZXItZGF0YSkgMj4mMQoKZXhwb3J0IFBBVEg9JFBB
12
- VEg6L3Vzci9sb2NhbC9iaW4KCnl1bSB1cGRhdGUgLS1hc3N1bWV5ZXMKeXVt
13
- IGluc3RhbGwgLS1hc3N1bWV5ZXMgcHVwcGV0MyBydWJ5LWRldmVsIHJ1Ynln
14
- ZW1zIGdjYyB6bGliLWRldmVsIGxpYnhtbDItZGV2ZWwgcGF0Y2ggZ251cGcy
15
- CgojIE5vdCBzdXJlIHdoeSB0aGlzIGRvZXNuJ3QgZ2V0IHB1bGxlZCBkb3du
16
- IHByb3Blcmx5LCBtYXliZSBpdCdzIGNvcmUgYW5kCiMgQW1hem9uIGRpZG4n
17
- dCBwYWNrYWdlIGl0IHByb3Blcmx5PyBOZWVkIGl0IGZvciBUaG9yIHdoaWNo
18
- IGlzIHVzZWQgYnkgUHVwaXN0cnkKZ2VtIGluc3RhbGwgaW8tY29uc29sZQoK
19
- Z2VtIGluc3RhbGwgcHVwaXN0cnkKbWtkaXIgLXAgL2V0Yy9wdXBpc3RyeQpt
20
- a2RpciAtcCAvZXRjL3B1cHBldGxhYnMvY29kZS9lbnZpcm9ubWVudHMKY2F0
21
- ID4gL2V0Yy9wdXBpc3RyeS9zZXR0aW5ncy55YW1sIDw8ICJFT0YiCmdlbmVy
22
- YWw6CiAgYXBwX2NhY2hlOiB+Ly5wdXBpc3RyeS9jYWNoZQogIHMzX2J1Y2tl
23
- dDogcHVwaXN0cnktcmVzb3VyY2VzCiAgczNfcHJlZml4OiAKICBncGdfZGlz
24
- YWJsZTogZmFsc2UKICBncGdfc2lnbmluZ19rZXk6IEE4MEFDQTZGCmFnZW50
25
- OgogIHB1cHBldGNvZGU6IC9ldGMvcHVwcGV0bGFicy9jb2RlL2Vudmlyb25t
26
- ZW50cwogIGFjY2Vzc19rZXlfaWQ6IEFLSUFKMlhKQ01TNFJBUDNCVFpBCiAg
27
- c2VjcmV0X2FjY2Vzc19rZXk6IHdoQWlFaCtZV1hzaUw4Y0NONitLSFovT1Zs
28
- M1VCK3ZZb0FHZEd4eDkKICByZWdpb246IGFwLXNvdXRoZWFzdC0yCiAgcHJv
29
- eHlfdXJpOiAKICBkYWVtb25fZnJlcXVlbmN5OiA2MAogIGRhZW1vbl9taW5p
30
- bWFsOiB0cnVlCkVPRgpjaG1vZCA3MDAgL2V0Yy9wdXBpc3RyeS9zZXR0aW5n
31
- cy55YW1sCmNobW9kIDcwMCAvZXRjL3B1cHBldGxhYnMvY29kZS9lbnZpcm9u
32
- bWVudHMKcHVwaXN0cnkgYXBwbHkgLS12ZXJib3NlCgopCg==
33
- -- Bootstrap End --