puppet-masterless 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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: []