puppet-masterless 0.1.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.
Files changed (3) hide show
  1. checksums.yaml +7 -0
  2. data/bin/puppet-masterless +180 -0
  3. metadata +46 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: f25c87151bb067f0180ff521e3d9321de1bde8c6
4
+ data.tar.gz: 27e83b426523ea8d6424f44826d9ce552ae20aa6
5
+ SHA512:
6
+ metadata.gz: 54f080712152dad70216e838c52664572e945e25fea3f15a4507a8208cece077cd087fbdc6c19a42b7e3c9f7b2db59e180b8bada031bb577dbe0ef8d7de2017c
7
+ data.tar.gz: bdab25968892f155f6fb37e0ebb462a975db8476c36978572b01463561a57ec82b2363ca851357dfb7954c8094d47509fcb39a75e768f4a1878d93e3c8e3c478
@@ -0,0 +1,180 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # Usage: puppet-masterless <subcommand> [<argument> ...] [-- puppet arguments ...]
4
+ #
5
+ # Applies a local puppet project to a remote host.
6
+ #
7
+ # Available subcommands:
8
+ #
9
+ # package
10
+ # apply
11
+ #
12
+ # Available arguments:
13
+ #
14
+ # confdir <directory>
15
+ # hiera_config <file>
16
+ # manifest <file>
17
+ # modulepath <directory>
18
+ # puppet <executable>
19
+ # to <hostname>
20
+ # as <username>
21
+ # file <file>
22
+ #
23
+ # At least <confdir> must be specified.
24
+ #
25
+
26
+ require 'shellwords'
27
+
28
+ module PuppetMasterless
29
+ ARCHIVE_NAME = 'puppet-masterless'
30
+ ARCHIVE_OPTIONS = '--ignore-failed-read --exclude-vcs'
31
+ DEFAULT_PUPPET = 'puppet'
32
+ REMOTE_USER = 'root'
33
+ REMOTE_WORKDIR = '/tmp'
34
+
35
+ class Main
36
+ def initialize
37
+ @files = []
38
+ @args = []
39
+ @path = ARCHIVE_NAME
40
+ @puppet = DEFAULT_PUPPET
41
+ @user = REMOTE_USER
42
+ @workdir = REMOTE_WORKDIR
43
+ @output = "#{ARCHIVE_NAME}.sh"
44
+ end
45
+
46
+ def banner
47
+ File.read(__FILE__).lines[1..23].map { |s| s.gsub(/^# ?/, '') }
48
+ end
49
+
50
+ def usage n = 1
51
+ STDERR.puts(banner)
52
+ exit(n)
53
+ end
54
+
55
+ def collect args
56
+ while word = args.shift
57
+ case word
58
+ when 'with', 'and'
59
+ when 'confdir' then @confdir = args.shift
60
+ when 'manifest' then @manifest = args.shift
61
+ when 'modulepath' then @modulepath = args.shift
62
+ when 'hiera_config' then @hiera_config = args.shift
63
+ when 'puppet' then @puppet = args.shift
64
+ when 'to' then @hostname = args.shift
65
+ when 'as' then @user = args.shift
66
+ when 'file' then @files << args.shift
67
+ when '--', nil then @args = args.slice!(0..-1)
68
+ else fail 'Invalid argument: ' << word
69
+ end
70
+ end
71
+ end
72
+
73
+ def validate
74
+ fail 'No confdir specified' unless @confdir
75
+ fail 'No puppet specified' unless @puppet
76
+
77
+ @manifest ||= File.join(@confdir, 'manifests')
78
+ @modulepath ||= File.join(@confdir, 'modules')
79
+ @hiera_config ||= File.join(@confdir, 'hiera.yaml')
80
+
81
+ fail 'No such confdir: ' << @confdir unless File.directory?(@confdir)
82
+ fail 'No such manifest: ' << @manifest unless File.exist?(@manifest)
83
+
84
+ @modulepath = nil unless File.directory?(@modulepath)
85
+ @hiera_config = nil unless File.file?(@hiera_config)
86
+ end
87
+
88
+ def package
89
+ create_distribution
90
+ end
91
+
92
+ def apply
93
+ if @hostname
94
+ create_distribution
95
+ apply_remote
96
+ else
97
+ apply_local
98
+ end
99
+ end
100
+
101
+ private
102
+
103
+ def archive_command
104
+ "tar -czf- #{ARCHIVE_OPTIONS} --transform 's|^|#{@path.gsub("'", "'\''")}/|' \
105
+ #{@files.shelljoin} \
106
+ #{@manifest.shellescape} \
107
+ #{@modulepath.shellescape if @modulepath} \
108
+ #{@hiera_config.shellescape if @hiera_config}"
109
+ end
110
+
111
+ def local_apply_command
112
+ command = "exec #{@puppet} apply #{@manifest.shellescape} --verbose --show_diff --color true --confdir #{@confdir.shellescape}"
113
+ command << ' --modulepath ' << @modulepath.shellescape if @modulepath
114
+ command << ' --hiera_config ' << @hiera_config.shellescape if @hiera_config
115
+ command << ' ' << @args.shelljoin
116
+ end
117
+
118
+ def remote_apply_command
119
+ "sudo -u #{@user.shellescape} #{@workdir.shellescape}/#{@output.shellescape}"
120
+ end
121
+
122
+ def remote_cleanup_command
123
+ "sudo -u #{@user.shellescape} rm -f #{@workdir.shellescape}/#{@output.shellescape} -r #{@workdir.shellescape}/#{@path.shellescape}"
124
+ end
125
+
126
+ def apply_local
127
+ STDERR.puts('Notice: Applying locally')
128
+ fail 'Apply command failed' unless system(local_apply_command)
129
+ end
130
+
131
+ def apply_remote
132
+ STDERR.puts('Notice: Copying to ' << @hostname)
133
+ fail 'Copy command failed' unless system("scp -q #{@output.shellescape} #{@hostname.shellescape}:#{@workdir.shellescape}")
134
+ STDERR.puts('Notice: Applying to ' << @hostname)
135
+ fail 'Apply command failed' unless system("ssh -q -t #{@hostname.shellescape} #{remote_apply_command.shellescape}")
136
+ ensure
137
+ system("ssh -q -t #{@hostname.shellescape} #{remote_cleanup_command.shellescape}")
138
+ end
139
+
140
+ def create_distribution
141
+ STDERR.puts("Notice: Creating distribution")
142
+
143
+ File.open(@output, 'w') do |o|
144
+ o.puts("#!/bin/sh -e")
145
+ o.puts("sed '0,/^# EOF$/d' \"$0\" | tar -xzf-")
146
+ o.puts("cd #{@path.shellescape}")
147
+ o.puts(local_apply_command)
148
+ o.puts("exit 1")
149
+ o.puts("# EOF")
150
+ o.chmod(0755)
151
+ end
152
+
153
+ unless system(archive_command << ' >> ' << @output.shellescape)
154
+ fail 'Archive command failed: ' << archive_command
155
+ end
156
+ end
157
+ end
158
+ end
159
+
160
+ main = PuppetMasterless::Main.new
161
+
162
+ begin
163
+ case ARGV.shift
164
+ when 'package'
165
+ main.collect(ARGV)
166
+ main.validate
167
+ main.package
168
+ when 'apply'
169
+ main.collect(ARGV)
170
+ main.validate
171
+ main.apply
172
+ when '-h', '--help', nil
173
+ main.usage(0)
174
+ else
175
+ main.usage(1)
176
+ end
177
+ rescue => e
178
+ STDERR.puts("Error: #{File.basename($0)}: #{e.message}")
179
+ exit(1)
180
+ end
metadata ADDED
@@ -0,0 +1,46 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: puppet-masterless
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Evan Hanson
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2018-01-05 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: Packages and optionally applies a multi-file Puppet project to a remote
14
+ host via SSH.
15
+ email: evanh@catalyst.net.nz
16
+ executables:
17
+ - puppet-masterless
18
+ extensions: []
19
+ extra_rdoc_files: []
20
+ files:
21
+ - bin/puppet-masterless
22
+ homepage: https://gitlab.wgtn.cat-it.co.nz/devtools/puppet-masterless
23
+ licenses:
24
+ - GPLv3
25
+ metadata: {}
26
+ post_install_message:
27
+ rdoc_options: []
28
+ require_paths:
29
+ - lib
30
+ required_ruby_version: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - ">="
33
+ - !ruby/object:Gem::Version
34
+ version: '0'
35
+ required_rubygems_version: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: '0'
40
+ requirements: []
41
+ rubyforge_project:
42
+ rubygems_version: 2.6.12
43
+ signing_key:
44
+ specification_version: 4
45
+ summary: Apply a local puppet project to a remote host
46
+ test_files: []