puppet_webhook 0.1.0 → 1.0.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 +4 -4
- data/CHANGELOG.md +29 -2
- data/README.md +107 -57
- data/bin/puppet_webhook +95 -27
- data/config/app.yml +10 -9
- data/lib/helpers/data_parsers.rb +4 -0
- data/lib/helpers/deployments.rb +4 -4
- data/lib/helpers/tasks.rb +16 -25
- data/lib/parsers/webhook_json_parser.rb +7 -19
- data/lib/puppet_webhook.rb +30 -130
- data/lib/routes/default.rb +18 -0
- data/lib/routes/module.rb +28 -0
- data/lib/routes/payload.rb +70 -0
- metadata +21 -5
- data/config/server.yml +0 -13
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 4a2bedbab06ccd3b043abda7e4e3c4711f90bae1fcc6cc102c283c63c517f783
|
|
4
|
+
data.tar.gz: b609d99c486ef605836756939f1ff33ae40056b38641d13c2665b33ecbd56093
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 4cd5c13d66c1fef5b8eda9c5768e5ecc216cb24617cdd04ec07e0655213b543561074aec522790b394879e3906cd8835896d8bdf7abaffb265ade893cb2496ff
|
|
7
|
+
data.tar.gz: d3870a2daffca879005cac928fa0fbe46a4c65c7d3594fb12a8333d9394afc2fb5e181027e45a57dfea6505ceb92e1369587aefe4dc4abe49a3025a4fd9d988f
|
data/CHANGELOG.md
CHANGED
|
@@ -1,7 +1,33 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Changelog
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
Each new release typically also includes the latest modulesync defaults.
|
|
5
|
+
These should not affect the functionality of the module.
|
|
4
6
|
|
|
7
|
+
## [v1.0.0](https://github.com/voxpupuli/puppet_webhook/tree/v1.0.0) (2017-12-21)
|
|
8
|
+
[Full Changelog](https://github.com/voxpupuli/puppet_webhook/compare/v0.1.0...v1.0.0)
|
|
9
|
+
|
|
10
|
+
**Implemented enhancements:**
|
|
11
|
+
|
|
12
|
+
- \(\#puppethack\) Add cli binary [\#40](https://github.com/voxpupuli/puppet_webhook/pull/40) ([dhollinger](https://github.com/dhollinger))
|
|
13
|
+
|
|
14
|
+
**Closed issues:**
|
|
15
|
+
|
|
16
|
+
- Move all routes into a routes/ directory [\#26](https://github.com/voxpupuli/puppet_webhook/issues/26)
|
|
17
|
+
|
|
18
|
+
**Merged pull requests:**
|
|
19
|
+
|
|
20
|
+
- Update config options and docs [\#41](https://github.com/voxpupuli/puppet_webhook/pull/41) ([dhollinger](https://github.com/dhollinger))
|
|
21
|
+
- Fix payload gentypes [\#39](https://github.com/voxpupuli/puppet_webhook/pull/39) ([dhollinger](https://github.com/dhollinger))
|
|
22
|
+
- Add simple config.ru file [\#38](https://github.com/voxpupuli/puppet_webhook/pull/38) ([dhollinger](https://github.com/dhollinger))
|
|
23
|
+
- Switch to using rack-bodyparser [\#36](https://github.com/voxpupuli/puppet_webhook/pull/36) ([alexjfisher](https://github.com/alexjfisher))
|
|
24
|
+
- Move routes into a routes directory [\#35](https://github.com/voxpupuli/puppet_webhook/pull/35) ([dhollinger](https://github.com/dhollinger))
|
|
25
|
+
- Fix generate\_types typo [\#34](https://github.com/voxpupuli/puppet_webhook/pull/34) ([alexjfisher](https://github.com/alexjfisher))
|
|
26
|
+
- Fix Code Climate badges [\#33](https://github.com/voxpupuli/puppet_webhook/pull/33) ([alexjfisher](https://github.com/alexjfisher))
|
|
27
|
+
- Add reporting to CodeClimate and associated badges [\#32](https://github.com/voxpupuli/puppet_webhook/pull/32) ([alexjfisher](https://github.com/alexjfisher))
|
|
28
|
+
- Report coverage to Codacy and add badge [\#31](https://github.com/voxpupuli/puppet_webhook/pull/31) ([alexjfisher](https://github.com/alexjfisher))
|
|
29
|
+
|
|
30
|
+
## [v0.1.0](https://github.com/voxpupuli/puppet_webhook/tree/v0.1.0) (2017-11-17)
|
|
5
31
|
**Implemented enhancements:**
|
|
6
32
|
|
|
7
33
|
- Cleanup config loader [\#2](https://github.com/voxpupuli/puppet_webhook/issues/2)
|
|
@@ -13,6 +39,7 @@
|
|
|
13
39
|
|
|
14
40
|
**Merged pull requests:**
|
|
15
41
|
|
|
42
|
+
- Development release 0.1.0 [\#24](https://github.com/voxpupuli/puppet_webhook/pull/24) ([dhollinger](https://github.com/dhollinger))
|
|
16
43
|
- Add rubygems deploy to travis [\#23](https://github.com/voxpupuli/puppet_webhook/pull/23) ([dhollinger](https://github.com/dhollinger))
|
|
17
44
|
- Fix TFS checks and add more fixtures/tests [\#22](https://github.com/voxpupuli/puppet_webhook/pull/22) ([dhollinger](https://github.com/dhollinger))
|
|
18
45
|
- Fix README badges after project rename [\#21](https://github.com/voxpupuli/puppet_webhook/pull/21) ([dhollinger](https://github.com/dhollinger))
|
data/README.md
CHANGED
|
@@ -4,6 +4,9 @@
|
|
|
4
4
|
[](https://travis-ci.org/voxpupuli/puppet_webhook)
|
|
5
5
|
[](https://rubygems.org/gems/puppet_webhook)
|
|
6
6
|
[](https://rubygems.org/gems/puppet_webhook)
|
|
7
|
+
[](https://codeclimate.com/github/voxpupuli/puppet_webhook/maintainability)
|
|
8
|
+
[](https://codeclimate.com/github/voxpupuli/puppet_webhook/test_coverage)
|
|
9
|
+
[](https://www.codacy.com/app/VoxPupuli/puppet_webhook?utm_source=github.com&utm_medium=referral&utm_content=voxpupuli/puppet_webhook&utm_campaign=Badge_Grade)
|
|
7
10
|
[](https://coveralls.io/github/voxpupuli/puppet_webhook?branch=master)
|
|
8
11
|
[](https://gemnasium.com/github.com/voxpupuli/puppet_webhook)
|
|
9
12
|
|
|
@@ -12,11 +15,6 @@
|
|
|
12
15
|
puppet_webhook is a Sinatra-based application receiving REST-based calls to trigger Puppet and r10k-related tasks such as:
|
|
13
16
|
|
|
14
17
|
* Webhooks from Source Code systems to trigger r10k environment and module deploys
|
|
15
|
-
* REST calls from systems to trigger Puppet Decommissions such as:
|
|
16
|
-
* `puppet node clean`
|
|
17
|
-
* `puppet cert clean`
|
|
18
|
-
* `puppet cert revoke`
|
|
19
|
-
* etc.
|
|
20
18
|
* Send notifications via Slack
|
|
21
19
|
|
|
22
20
|
## Prerequisites
|
|
@@ -39,12 +37,24 @@ NOTE: RPM, DEB, and Arch packages are planned for future releases.
|
|
|
39
37
|
|
|
40
38
|
### Running puppet_webhook
|
|
41
39
|
|
|
42
|
-
|
|
40
|
+
#### Quick Start
|
|
43
41
|
|
|
44
|
-
|
|
45
|
-
You can also set the `server_type` option in `/etc/puppet_webhook/server.yml` to `daemon` to run the application in the background. By default the application will log to `/var/log/puppet_webhook/access.log`.
|
|
42
|
+
Simply run `# puppet_webhook` after installation to start puppet_webhook in non-daemon mode on your system. This is great for testing the server out.
|
|
46
43
|
|
|
47
|
-
|
|
44
|
+
#### CLI Tool
|
|
45
|
+
|
|
46
|
+
The `puppet_webhook` CLI command has several options you can pass it as well.
|
|
47
|
+
|
|
48
|
+
To see these options run `# puppet_webook -h` in your terminal to see all the options.
|
|
49
|
+
|
|
50
|
+
#### Start using Rack-based server software
|
|
51
|
+
|
|
52
|
+
A `config.ru` file is also packaged with the application to provide users with the ability to start the app using their own rack-based server such as
|
|
53
|
+
unicorn or puma. It will use the defaults passed to it by said server.
|
|
54
|
+
|
|
55
|
+
#### Service Start
|
|
56
|
+
|
|
57
|
+
Once the native packages are built, they will include default systemd and/or sysvinit service files that you can use to start puppet_webhook as well.
|
|
48
58
|
|
|
49
59
|
### Configuring puppet_webhook
|
|
50
60
|
|
|
@@ -56,154 +66,194 @@ Any configuration option is placed in `/etc/puppet_webhook/server.yml` or `/etc/
|
|
|
56
66
|
|
|
57
67
|
#### Configuration options
|
|
58
68
|
|
|
59
|
-
####
|
|
69
|
+
#### Command-Line Options
|
|
70
|
+
|
|
71
|
+
* `-h, --help`: Display the default help output.
|
|
72
|
+
* `-d, --debug`: Set logging to debug mode.
|
|
73
|
+
* `-l [LOGFILE], --logfile [LOGFILE]`: Define a logfile to log to.
|
|
74
|
+
* `-p PORT, --port PORT`: Define port to listen on. Default: `8088`
|
|
75
|
+
* `-D, --daemon`: Run WEBrick in Daemon mode.
|
|
76
|
+
* `--pidfile FILE`: Define the PID File for the application's process. Default: `/var/run/puppet_webhook/webhook.pid`
|
|
77
|
+
* `--ssl`: Enable SSL Support.
|
|
78
|
+
* `--ssl-cert FILE`: Specify the SSL cert to use. Pair with `--ssl-key`. Requires `--ssl` option or `ssl_enable: true` in config file.
|
|
79
|
+
* `--ssl-key FILE`: Specify the SSL Private key to use. Pair with `--ssl-cert`. Requires `--ssl` or `ssl_enable: true` in config file.
|
|
80
|
+
* `-c FILE, --configfile FILE`: Specifies a config file to use. Must be a `.yml` file in YAML format.
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
#### Server Configuration File
|
|
84
|
+
|
|
85
|
+
The Server configuration file is a YAML formatted file with file extension `.yml` and defined with the `-c` or `--configfile`
|
|
86
|
+
command line option. These settings are exclusively for setting server configs and currently will override any command line settings
|
|
87
|
+
passed.
|
|
88
|
+
|
|
89
|
+
When using the default SystemD unit file or SysVInit service file, the server configuration file will default to `/etc/puppet_webhook/server.yml` (Not implemented yet).
|
|
90
|
+
|
|
91
|
+
##### Options
|
|
60
92
|
|
|
61
93
|
#####`server_type`
|
|
94
|
+
|
|
62
95
|
Determines if the Webrick server should run in Simple or Daemon mode.
|
|
63
96
|
* Valid options: [ `simple`, `daemon` ].
|
|
64
97
|
* Default: `simple`
|
|
65
98
|
|
|
66
99
|
##### `logfile`
|
|
100
|
+
|
|
67
101
|
Location to write the log file to.
|
|
68
|
-
* Default: `/var/log/puppet_webhook
|
|
102
|
+
* Default: `/var/log/puppet_webhook`
|
|
69
103
|
|
|
70
|
-
##### `
|
|
71
|
-
Location of the application's PID file
|
|
72
|
-
* Default: `/var/run/puppet_webhook/webhook.pid`
|
|
104
|
+
##### `loglevel`
|
|
73
105
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
* Default: `/var/run/puppet_webhook/webhook.lock`
|
|
106
|
+
Define the logging level.
|
|
107
|
+
* Default: `WARN`
|
|
77
108
|
|
|
78
|
-
##### `
|
|
79
|
-
Location of the Root of the application's directory
|
|
80
|
-
* Default: `./`
|
|
81
|
-
NOTE: Currently unused
|
|
109
|
+
##### `pidfile`
|
|
82
110
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
* MUST BE VALID IPv4 ADDRESS.
|
|
86
|
-
* Default: `0.0.0.0`
|
|
111
|
+
Location of the application's PID file
|
|
112
|
+
* Default: `/var/run/puppet_webhook/webhook.pid`
|
|
87
113
|
|
|
88
114
|
##### `port`
|
|
115
|
+
|
|
89
116
|
Port number to bind to.
|
|
90
117
|
* Valid options: Integer between `1024` and `65535`
|
|
91
118
|
* Default: `8088`
|
|
92
119
|
|
|
93
120
|
##### `enable_ssl`
|
|
121
|
+
|
|
94
122
|
Whether or not to enable SSL communication.
|
|
95
123
|
* Valid options: [ `true`, `false` ]
|
|
96
124
|
* Default: `false`
|
|
97
125
|
|
|
98
|
-
##### `
|
|
126
|
+
##### `ssl_verify`
|
|
127
|
+
|
|
99
128
|
Whether or not to verify the SSL CA/Peer on the certifcate. Set to false if using a self-signed certificate and the CA is not installed locally.
|
|
100
129
|
* Valid options: [ `true`, `false` ]
|
|
101
130
|
* Default: `false`
|
|
102
131
|
|
|
103
|
-
##### `
|
|
132
|
+
##### `ssl_cert`
|
|
133
|
+
|
|
104
134
|
Path to the public SSL certificate for puppet_webhook. REQUIRED IF `ssl_enable` IS SET TO `true`
|
|
105
|
-
* Default: ''
|
|
106
135
|
|
|
107
|
-
##### `
|
|
136
|
+
##### `ssl_key`
|
|
137
|
+
|
|
108
138
|
Path to the SSL Private Key for puppet_webhook. REQUIRED IF `ssl_enable` IS SET TO `true`
|
|
109
|
-
* Default: ''
|
|
110
139
|
|
|
111
|
-
|
|
112
|
-
Command to prefix the r10k and puppet commands with when executed.
|
|
113
|
-
* Default: 'umask 0022;'
|
|
140
|
+
#### Application Configuration File
|
|
114
141
|
|
|
115
|
-
|
|
142
|
+
This file stores the configuration for the Application itself. A default configuration file is included in the `APP_ROOT/config/app.yml`.
|
|
116
143
|
|
|
117
|
-
|
|
118
|
-
|
|
144
|
+
The SystemD unit and SysVInit service files will use `/etc/puppet_webhook/app.yml` by default (Not implemented yet).
|
|
145
|
+
|
|
146
|
+
Currently, the above two locations are the only valid locations for the app.yml file. Like the Server Config, it must be a .yml file in YAML format.
|
|
147
|
+
|
|
148
|
+
##### Options
|
|
149
|
+
|
|
150
|
+
##### `protected`
|
|
151
|
+
|
|
152
|
+
Whether or not to require authentication when sending to puppet_webhook.
|
|
119
153
|
* Valid options: [ `true`, `false` ]
|
|
120
154
|
* Default: `false`
|
|
121
155
|
|
|
122
156
|
##### `user`
|
|
123
|
-
|
|
124
|
-
|
|
157
|
+
|
|
158
|
+
User for which the sending application must authenticate with. Required if `protected` is true.
|
|
125
159
|
|
|
126
160
|
##### `pass`
|
|
127
|
-
Password for which the sending application must authenticate with.
|
|
128
|
-
* Default: `puppet`
|
|
129
161
|
|
|
130
|
-
|
|
131
|
-
Whether or not to require authentication when sending to puppet_webhook.
|
|
132
|
-
* Valid options: [ `true`, `false` ]
|
|
133
|
-
* Default: `true`
|
|
162
|
+
Password for which the sending application must authenticate with. Require if `protected` is true.
|
|
134
163
|
|
|
135
164
|
##### client_cfg
|
|
165
|
+
|
|
136
166
|
Mcollective client configuration file.
|
|
137
167
|
* Default: `/var/lib/peadmin/.mcollective`
|
|
138
168
|
|
|
139
169
|
##### client_timeout
|
|
170
|
+
|
|
140
171
|
Mcollective client timeout in seconds.
|
|
141
172
|
* MUST BE A STRING
|
|
142
173
|
* Default: `"120"`
|
|
143
174
|
|
|
144
175
|
##### use_mco_ruby
|
|
176
|
+
|
|
145
177
|
Whether or not to execute MCollective via Ruby Client Library or not. REQUIRES MCOLLECTIVE AND MCOLLECTIVE R10K!
|
|
146
178
|
* Valid options: [ `true`, `false` ]
|
|
147
179
|
* Default: `false`
|
|
148
180
|
|
|
149
|
-
##### discovery_timeout
|
|
150
|
-
MCollective Ruby discovery timeout. REQUIRES `use_mco_ruby` TO BE `true`.
|
|
151
|
-
* Default: `'10'`
|
|
152
|
-
|
|
153
181
|
##### use_mcollective
|
|
182
|
+
|
|
154
183
|
Whether or not to use MCollective CLI command. REQUIRES MCOLLECTIVE AND MCOLLECTIVE R10K.
|
|
155
184
|
* Valid options: [ `true`, `false` ]
|
|
156
185
|
* Default: `false`
|
|
157
186
|
|
|
187
|
+
##### discovery_timeout
|
|
188
|
+
|
|
189
|
+
MCollective Ruby discovery timeout. REQUIRES `use_mco_ruby` TO BE `true`.
|
|
190
|
+
* Default: `'10'`
|
|
191
|
+
|
|
158
192
|
##### slack_webhook
|
|
193
|
+
|
|
159
194
|
Whether or not to use Slack Notifications.
|
|
160
195
|
* Valid options: [ `true`, `false` ]
|
|
161
196
|
* Default: `false`
|
|
162
197
|
|
|
163
|
-
##### slack_channel
|
|
164
|
-
Slack channel to notify.
|
|
165
|
-
* Default: `'#default'`
|
|
166
|
-
|
|
167
|
-
##### slack_user
|
|
168
|
-
Slack user to notify as.
|
|
169
|
-
* Default: `'r10k'`
|
|
170
|
-
|
|
171
198
|
##### slack_proxy_url
|
|
199
|
+
|
|
172
200
|
The proxy URL for Slack if used.
|
|
173
201
|
* MUST BE A VALID URL.
|
|
174
202
|
* Default: `nil`
|
|
175
203
|
|
|
176
204
|
##### default_branch
|
|
205
|
+
|
|
177
206
|
The default git branch to use with the r10k Control Repo.
|
|
178
207
|
* Default: `production`
|
|
179
208
|
|
|
180
209
|
##### ignore_environment
|
|
210
|
+
|
|
181
211
|
An Array of environments for r10k to ignore during deployment.
|
|
182
212
|
* Default: []
|
|
183
213
|
|
|
184
214
|
##### prefix
|
|
215
|
+
|
|
185
216
|
r10k Environment Prefix to use. When set to `repo`, `user`, or `command`, the prefix will be generated from the repo_name, repo_user, or `prefix_command`. Otherwise it will set the prefix to the passed string. `false` disables prefix.
|
|
186
217
|
* Valid Options: [ `repo`, `user`, `command`, `<String_value>`, `false` ]
|
|
187
|
-
* Default: `
|
|
218
|
+
* Default: `nil`
|
|
188
219
|
|
|
189
220
|
##### prefix_command
|
|
221
|
+
|
|
190
222
|
Command to execute that will generate an r10k environment prefix.
|
|
191
223
|
* Default: ''
|
|
192
224
|
|
|
193
225
|
##### r10k_deploy_arguments
|
|
226
|
+
|
|
194
227
|
r10k command arguments to pass to the `r10k deploy environment` command.
|
|
195
228
|
* Default: `"-pv"`
|
|
196
229
|
|
|
197
230
|
##### allow_uppercase
|
|
231
|
+
|
|
198
232
|
Whether or not to allow uppercase letters in environment names. If false, then puppet_webhook assumes environment names are downcase. If `true`, then puppet_webhook will normalize the environment name.
|
|
199
233
|
* Valid options: [ `true`, `false` ]
|
|
200
234
|
* Default: `true`
|
|
201
235
|
|
|
202
236
|
##### github_secret
|
|
237
|
+
|
|
203
238
|
Used to verify the signature on a repo. Currently only supported for Github repos.
|
|
204
239
|
* MUST BE A VALID OPENSSL `sha1` HASH.
|
|
205
240
|
* Default: `nil`
|
|
206
241
|
|
|
207
242
|
##### repository_events
|
|
243
|
+
|
|
208
244
|
Array of webhook events to ignore.
|
|
209
245
|
* Default: `nil`
|
|
246
|
+
|
|
247
|
+
## Getting Help
|
|
248
|
+
|
|
249
|
+
* IRC: Vox Pupuli has a dedicated channel, `#voxpupuli`, on Freenode where `puppet_webhook` questions can be directed.
|
|
250
|
+
* Mailing Lists: [voxpupuli](https://groups.io/g/voxpupuli)
|
|
251
|
+
* Slack: Vox Pupuli has a dedicated Slack Channel, `#voxpupuli`, on the [Puppet Community](https://slack.puppet.com/) Slack.
|
|
252
|
+
|
|
253
|
+
## Contributors
|
|
254
|
+
|
|
255
|
+
A big thank you to all our [Contributor](https://github.com/voxpupuli/puppet_webhook/graphs/contributors)
|
|
256
|
+
|
|
257
|
+
## License
|
|
258
|
+
|
|
259
|
+
See LICENSE
|
data/bin/puppet_webhook
CHANGED
|
@@ -1,43 +1,111 @@
|
|
|
1
1
|
#!/usr/bin/env ruby
|
|
2
2
|
require 'openssl'
|
|
3
|
-
require '
|
|
4
|
-
require 'sinatra/config_file'
|
|
3
|
+
require 'optparse'
|
|
5
4
|
require 'webrick'
|
|
6
5
|
require 'webrick/https'
|
|
7
6
|
require 'puppet_webhook'
|
|
8
7
|
|
|
9
|
-
|
|
8
|
+
approot = File.expand_path(File.join(File.dirname(__FILE__), '..'))
|
|
9
|
+
options = {
|
|
10
|
+
host: '0.0.0.0',
|
|
11
|
+
port: '8088',
|
|
12
|
+
logfile: $stderr,
|
|
13
|
+
loglevel: WEBrick::Log::WARN,
|
|
14
|
+
server_type: WEBrick::SimpleServer
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
ssl_opts = { ssl_verify: false }
|
|
18
|
+
|
|
19
|
+
optparse = OptionParser.new do |opts| # rubocop:disable Metrics/BlockLength
|
|
20
|
+
opts.banner = 'Usage: puppet_webhook [-p <port>] [-l <logfile>] [-d]
|
|
21
|
+
-- Starts the Puppet Webhook API service.
|
|
22
|
+
|
|
23
|
+
'
|
|
24
|
+
|
|
25
|
+
opts.on('-d', '--debug', 'Display or log messages.') do
|
|
26
|
+
options[:loglevel] = WEBrick::Log::DEBUG
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
opts.on('-l [LOGFILE]', '--logfile [LOGFILE]',
|
|
30
|
+
'Path to logfile. Defaults to no logging, or /var/log/puppet_webhook if no filename is passed.') do |arg|
|
|
31
|
+
options[:logfile] = arg || '/var/log/puppet_webhook'
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
opts.on('-p PORT', '--port PORT', 'Port to listen on. Defaults to 8088.') do |arg|
|
|
35
|
+
options[:port] = arg
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
opts.on('-D', '--daemon', 'Run the server in daemon mode. Defaults to simple if not passed') do
|
|
39
|
+
options[:server_type] = WEBrick::Daemon
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
opts.on('--pidfile FILE', 'Specify the PID file to use.') do |arg|
|
|
43
|
+
options[:pidfile] = arg || '/var/run/puppet_webhook/webhook.pid'
|
|
44
|
+
end
|
|
10
45
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
COMMAND_PREFIX = settings.command_prefix
|
|
15
|
-
LOGGER = WEBrick::Log.new(settings.logfile, WEBrick::Log::DEBUG)
|
|
46
|
+
opts.on('--ssl', 'Enable SSL Support.') do
|
|
47
|
+
ssl_opts[:enable_ssl] = true
|
|
48
|
+
end
|
|
16
49
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
50
|
+
opts.on('--ssl-cert FILE', 'Specify the SSL cert to use. Pair with --ssl-key.') do |arg|
|
|
51
|
+
ssl_opts[:ssl_cert] = OpenSSL::X509::Certificate.new(File.open(arg).read)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
opts.on('--ssl-key FILE', 'Specify the SSL key to use. Pair with --ssl-cert.') do |arg|
|
|
55
|
+
ssl_opts[:ssl_key] = OpenSSL::PKey::RSA.new(File.open(arg))
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
opts.on('-c FILE', '--configfile FILE', 'Specifies a configuration file to use.') do |arg|
|
|
59
|
+
@server_config = arg
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
opts.separator('')
|
|
63
|
+
|
|
64
|
+
opts.on('-h', '--help') do
|
|
65
|
+
puts
|
|
66
|
+
puts opts
|
|
67
|
+
puts
|
|
68
|
+
exit
|
|
69
|
+
end
|
|
22
70
|
end
|
|
23
71
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
72
|
+
optparse.parse!
|
|
73
|
+
|
|
74
|
+
if @server_config
|
|
75
|
+
config_file(@server_config)
|
|
76
|
+
if settings.respond_to? :server_type=
|
|
77
|
+
options[:server_type] = WEBrick::Daemon if settings.server_type == 'daemon'
|
|
78
|
+
end
|
|
79
|
+
options[:host] = settings.host if settings.respond_to? :host=
|
|
80
|
+
options[:port] = settings.port if settings.respond_to? :port=
|
|
81
|
+
options[:pidfile] = settings.pidfile if settings.respond_to? :pidfile=
|
|
82
|
+
options[:logfile] = settings.logfile if settings.respond_to? :logfile=
|
|
83
|
+
options[:loglevel] = settings.loglevel if settings.respond_to? :loglevel=
|
|
84
|
+
ssl_opts[:enable_ssl] = settings.enable_ssl if settings.respond_to? :enable_ssl=
|
|
85
|
+
ssl_opts[:ssl_verify] = settings.ssl_verify if settings.respond_to? :ssl_verify=
|
|
86
|
+
ssl_opts[:ssl_cert] = settings.ssl_cert if settings.respond_to? :ssl_cert=
|
|
87
|
+
ssl_opts[:ssl_key] = settings.enable_ssl if settings.respond_to? :ssl_key=
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
LOGGER = WEBrick::Log.new(options[:logfile], options[:loglevel])
|
|
91
|
+
|
|
92
|
+
webrick_opts = {
|
|
93
|
+
Host: options[:host],
|
|
94
|
+
Port: options[:port],
|
|
95
|
+
DocumentRoot: approot,
|
|
96
|
+
ServerType: options[:server_type],
|
|
97
|
+
ServerSoftware: PuppetWebhook,
|
|
98
|
+
StartCallBack: proc { File.open(options[:pidfile], 'w') { |f| f.write Process.pid } }
|
|
32
99
|
}
|
|
33
100
|
|
|
34
|
-
if
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
101
|
+
if ssl_opts[:enable_ssl]
|
|
102
|
+
webrick_opts[:SSLEnable] = ssl_opts[:enable_ssl]
|
|
103
|
+
webrick_opts[:SSLVerifyClient] = ssl_opts[:ssl_verify]
|
|
104
|
+
webrick_opts[:SSLCertificate] = ssl_opts[:ssl_cert]
|
|
105
|
+
webrick_opts[:SSLPrivateKey] = ssl_opts[:ssl_key]
|
|
106
|
+
webrick_opts[:SSLCertName] = [['CN', WEBrick::Utils.getservername]]
|
|
39
107
|
end
|
|
40
108
|
|
|
41
|
-
Rack::Handler::WEBrick.run(PuppetWebhook,
|
|
109
|
+
Rack::Handler::WEBrick.run(PuppetWebhook, webrick_opts) do |server|
|
|
42
110
|
%i[INT TERM].each { |sig| trap(sig) { server.stop } }
|
|
43
111
|
end
|
data/config/app.yml
CHANGED
|
@@ -1,21 +1,22 @@
|
|
|
1
|
-
|
|
1
|
+
# Authentication
|
|
2
|
+
protected: true
|
|
2
3
|
user: puppet
|
|
3
4
|
pass: puppet
|
|
4
|
-
|
|
5
|
+
|
|
6
|
+
# Mcollective
|
|
5
7
|
client_cfg: "/var/lib/peadmin/.mcollective"
|
|
6
8
|
client_timeout: "120"
|
|
7
9
|
use_mco_ruby: false
|
|
8
10
|
use_mcollective: false
|
|
11
|
+
discovery_timeout: '10'
|
|
12
|
+
|
|
13
|
+
# Slack Notifications
|
|
9
14
|
slack_webhook: false
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
slack_proxy_url: ~
|
|
15
|
+
|
|
16
|
+
# R10k
|
|
13
17
|
default_branch: production
|
|
14
|
-
discovery_timeout: '10'
|
|
15
18
|
ignore_environments: []
|
|
16
|
-
prefix: ~
|
|
17
19
|
prefix_command: ''
|
|
18
20
|
r10k_deploy_arguments: "-pv"
|
|
19
21
|
allow_uppercase: true
|
|
20
|
-
|
|
21
|
-
repository_events: ~
|
|
22
|
+
command_prefix: 'umask 0022;'
|
data/lib/helpers/data_parsers.rb
CHANGED
|
@@ -15,4 +15,8 @@ module DataParsers # rubocop:disable Style/Documentation
|
|
|
15
15
|
signature = 'sha1=' + OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha1'), settings.github_secret, payload_body)
|
|
16
16
|
throw(:halt, [500, "Signatures didn't match!\n"]) unless Rack::Utils.secure_compare(signature, request.env['HTTP_X_HUB_SIGNATURE'])
|
|
17
17
|
end
|
|
18
|
+
|
|
19
|
+
def payload
|
|
20
|
+
env['parsed_body']
|
|
21
|
+
end
|
|
18
22
|
end
|
data/lib/helpers/deployments.rb
CHANGED
|
@@ -7,10 +7,10 @@ module Deployments # rubocop:disable Style/Documentation
|
|
|
7
7
|
message = result.results[:statusmsg]
|
|
8
8
|
else
|
|
9
9
|
command = if settings.use_mcollective
|
|
10
|
-
"#{
|
|
10
|
+
"#{settings.command_prefix} mco r10k deploy #{branch} #{settings.mco_arguments}"
|
|
11
11
|
else
|
|
12
12
|
# If you don't use mcollective then this hook needs to be running as r10k's user i.e. root
|
|
13
|
-
"#{
|
|
13
|
+
"#{settings.command_prefix} r10k deploy environment #{branch} #{settings.r10k_deploy_arguments}"
|
|
14
14
|
end
|
|
15
15
|
message = run_command(command)
|
|
16
16
|
end
|
|
@@ -31,9 +31,9 @@ module Deployments # rubocop:disable Style/Documentation
|
|
|
31
31
|
|
|
32
32
|
def deploy_module(module_name)
|
|
33
33
|
command = if settings.use_mcollective
|
|
34
|
-
"#{
|
|
34
|
+
"#{settings.command_prefix} mco r10k deploy_module #{module_name} #{settings.mco_arguments}"
|
|
35
35
|
else
|
|
36
|
-
"#{
|
|
36
|
+
"#{settings.command_prefix} r10k deploy module #{module_name}"
|
|
37
37
|
end
|
|
38
38
|
message = run_command(command)
|
|
39
39
|
LOGGER.info("message: #{message} module_name: #{module_name}")
|
data/lib/helpers/tasks.rb
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
require 'open3'
|
|
2
2
|
require 'slack-notifier'
|
|
3
3
|
require 'mcollective'
|
|
4
|
-
include MCollective::RPC
|
|
5
4
|
|
|
6
5
|
module Tasks # rubocop:disable Style/Documentation
|
|
6
|
+
include MCollective::RPC
|
|
7
|
+
|
|
7
8
|
def ignore_env?(env)
|
|
8
9
|
list = settings.ignore_environments
|
|
9
10
|
return false if list.nil? || list.empty?
|
|
@@ -46,28 +47,20 @@ module Tasks # rubocop:disable Style/Documentation
|
|
|
46
47
|
end
|
|
47
48
|
|
|
48
49
|
def run_command(command)
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
if Open3.respond_to?('capture3')
|
|
57
|
-
stdout, stderr, exit_status = Open3.capture3(command)
|
|
58
|
-
message = "triggered: #{command}\n#{stdout}\n#{stderr}"
|
|
59
|
-
else
|
|
60
|
-
message = "forked: #{command}"
|
|
61
|
-
Process.detach(fork { exec "#{command} &" })
|
|
62
|
-
exit_status = 0
|
|
63
|
-
end
|
|
64
|
-
raise "#{stdout}\n#{stderr}" if exit_status != 0
|
|
50
|
+
if Open3.respond_to?('capture3')
|
|
51
|
+
stdout, stderr, exit_status = Open3.capture3(command)
|
|
52
|
+
message = "triggered: #{command}\n#{stdout}\n#{stderr}"
|
|
53
|
+
else
|
|
54
|
+
message = "forked: #{command}"
|
|
55
|
+
Process.detach(fork { exec "#{command} &" })
|
|
56
|
+
exit_status = 0
|
|
65
57
|
end
|
|
58
|
+
raise "#{stdout}\n#{stderr}" if exit_status != 0
|
|
66
59
|
message
|
|
67
60
|
end
|
|
68
61
|
|
|
69
62
|
def generate_types(environment)
|
|
70
|
-
command = "#{
|
|
63
|
+
command = "#{settings.command_prefix} /opt/puppetlabs/puppet/bin generate types --environment #{environment}"
|
|
71
64
|
|
|
72
65
|
message = run_command(command)
|
|
73
66
|
LOGGER.info("message: #{message} environment: #{environment}")
|
|
@@ -82,9 +75,6 @@ module Tasks # rubocop:disable Style/Documentation
|
|
|
82
75
|
def notify_slack(status_message)
|
|
83
76
|
return unless settings.slack_webhook
|
|
84
77
|
|
|
85
|
-
slack_channel = settings.slack_channel || '#default'
|
|
86
|
-
slack_user = settings.slack_username || 'r10k'
|
|
87
|
-
|
|
88
78
|
if settings.slack_proxy_url
|
|
89
79
|
uri = URI(settings.slack_proxy_url)
|
|
90
80
|
http_options = {
|
|
@@ -97,8 +87,8 @@ module Tasks # rubocop:disable Style/Documentation
|
|
|
97
87
|
end
|
|
98
88
|
|
|
99
89
|
notifier = Slack::Notifier.new settings.slack_webhook do
|
|
100
|
-
defaults channel:
|
|
101
|
-
username:
|
|
90
|
+
defaults channel: '#general',
|
|
91
|
+
username: 'puppet_webhook',
|
|
102
92
|
icon_emoji: ':ocean:',
|
|
103
93
|
http_options: http_options
|
|
104
94
|
end
|
|
@@ -138,8 +128,9 @@ module Tasks # rubocop:disable Style/Documentation
|
|
|
138
128
|
end
|
|
139
129
|
|
|
140
130
|
def types?
|
|
141
|
-
return false
|
|
142
|
-
settings.
|
|
131
|
+
return false unless settings.respond_to?(:generate_types=)
|
|
132
|
+
return false if settings.generate_types.nil?
|
|
133
|
+
settings.generate_types
|
|
143
134
|
end
|
|
144
135
|
|
|
145
136
|
def authorized?
|
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
require 'rack/
|
|
1
|
+
require 'rack/bodyparser'
|
|
2
2
|
require 'json'
|
|
3
3
|
|
|
4
4
|
module Sinatra
|
|
5
5
|
module Parsers
|
|
6
6
|
class WebhookJsonParser # rubocop:disable Style/Documentation
|
|
7
|
+
attr_accessor :env, :data
|
|
8
|
+
|
|
7
9
|
def call(body)
|
|
8
10
|
@data = JSON.parse(body, quirks_mode: true)
|
|
9
11
|
@vcs = detect_vcs
|
|
@@ -27,35 +29,23 @@ module Sinatra
|
|
|
27
29
|
|
|
28
30
|
def github_webhook?
|
|
29
31
|
# https://developer.github.com/v3/activity/events/types/#pushevent
|
|
30
|
-
|
|
31
|
-
return false unless @data.key? 'repository'
|
|
32
|
-
return false unless @data['repository'].key? 'id'
|
|
33
|
-
return false unless @data['repository'].key? 'html_url'
|
|
34
|
-
return false unless @data['repository']['html_url'] =~ %r{github\.com}
|
|
35
|
-
true
|
|
32
|
+
env.key?('HTTP_X_GITHUB_EVENT')
|
|
36
33
|
end
|
|
37
34
|
|
|
38
35
|
def gitlab_webhook?
|
|
39
36
|
# https://docs.gitlab.com/ce/user/project/integrations/webhooks.html
|
|
40
|
-
|
|
41
|
-
return false unless @data.key? 'object_kind'
|
|
42
|
-
return false unless @data.key? 'ref'
|
|
43
|
-
true
|
|
37
|
+
env.key?('HTTP_X_GITLAB_EVENT')
|
|
44
38
|
end
|
|
45
39
|
|
|
46
40
|
# stash/bitbucket server
|
|
47
41
|
def stash_webhook?
|
|
48
42
|
# https://confluence.atlassian.com/bitbucketserver/post-service-webhook-for-bitbucket-server-776640367.html
|
|
49
|
-
|
|
50
|
-
true
|
|
43
|
+
env.key?('HTTP_X_ATLASSIAN_TOKEN')
|
|
51
44
|
end
|
|
52
45
|
|
|
53
46
|
def bitbucket_webhook?
|
|
54
47
|
# https://confluence.atlassian.com/bitbucket/event-payloads-740262817.html
|
|
55
|
-
|
|
56
|
-
return false unless @data.key? 'repository'
|
|
57
|
-
return false unless @data.key? 'push'
|
|
58
|
-
true
|
|
48
|
+
env.key?('HTTP_X_EVENT_KEY')
|
|
59
49
|
end
|
|
60
50
|
|
|
61
51
|
def tfs_webhook?
|
|
@@ -97,8 +87,6 @@ module Sinatra
|
|
|
97
87
|
@data['push']['changes'][0]['closed']
|
|
98
88
|
when 'tfs'
|
|
99
89
|
@data['resource']['refUpdates'][0]['newObjectId'] == '0000000000000000000000000000000000000000'
|
|
100
|
-
else
|
|
101
|
-
false
|
|
102
90
|
end
|
|
103
91
|
end
|
|
104
92
|
|
data/lib/puppet_webhook.rb
CHANGED
|
@@ -4,148 +4,48 @@ require 'json'
|
|
|
4
4
|
require 'cgi'
|
|
5
5
|
require 'parsers/webhook_json_parser'
|
|
6
6
|
|
|
7
|
+
# Routes
|
|
8
|
+
require_relative 'routes/default'
|
|
9
|
+
require_relative 'routes/module'
|
|
10
|
+
require_relative 'routes/payload'
|
|
11
|
+
|
|
7
12
|
class PuppetWebhook < Sinatra::Base # rubocop:disable Style/Documentation
|
|
8
13
|
set :root, File.dirname(__FILE__)
|
|
9
|
-
use Rack::
|
|
14
|
+
use Rack::BodyParser,
|
|
10
15
|
parsers: { 'application/json' => Sinatra::Parsers::WebhookJsonParser.new },
|
|
11
16
|
handlers: { 'application/json' => proc { |e, type| [400, { 'Content-Type' => type }, [{ error: e.to_s }.to_json]] } }
|
|
12
17
|
register Sinatra::ConfigFile
|
|
13
18
|
|
|
14
19
|
config_file(File.join(__dir__, '..', 'config', 'app.yml'), '/etc/puppet_webhook/app.yml')
|
|
15
20
|
|
|
21
|
+
# Sinatra settings
|
|
16
22
|
set :static, false
|
|
17
|
-
set :lock, true
|
|
23
|
+
set :lock, true
|
|
24
|
+
|
|
25
|
+
# Custom Settings
|
|
26
|
+
set :protected, false unless settings.respond_to? :protected=
|
|
27
|
+
set :client_cfg, '/var/lib/peadmin/.mcollective' unless settings.respond_to? :client_cfg=
|
|
28
|
+
set :client_timeout, '120' unless settings.respond_to? :client_timeout=
|
|
29
|
+
set :use_mco_ruby, false unless settings.respond_to? :use_mco_ruby=
|
|
30
|
+
set :use_mcollective, false unless settings.respond_to? :use_mcollective=
|
|
31
|
+
set :discovery_timeout, false unless settings.respond_to? :discovery_timeout=
|
|
32
|
+
set :slack_webhook, false unless settings.respond_to? :slack_webhook=
|
|
33
|
+
set :slack_proxy_url, nil unless settings.respond_to? :slack_proxy_url=
|
|
34
|
+
set :default_branch, 'production' unless settings.respond_to? :default_branch=
|
|
35
|
+
set :ignore_environments, [] unless settings.respond_to? :ignore_environments=
|
|
36
|
+
set :prefix, nil unless settings.respond_to? :prefix=
|
|
37
|
+
set :prefix_command, '' unless settings.respond_to? :prefix_command=
|
|
38
|
+
set :r10k_deploy_arguments, '-pv' unless settings.respond_to? :r10k_deploy_arguments=
|
|
39
|
+
set :allow_uppercase, true unless settings.respond_to? :allow_uppercase=
|
|
40
|
+
set :command_prefix, 'umask 0022;' unless settings.respond_to? :command_prefix=
|
|
41
|
+
set :github_secret, nil unless settings.respond_to? :github_secret=
|
|
42
|
+
set :repository_events, nil unless settings.respond_to? :respository_events=
|
|
18
43
|
|
|
19
44
|
require 'helpers/init'
|
|
20
45
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
get '/heartbeat' do
|
|
26
|
-
return 200, { status: :success, message: 'running' }.to_json
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
# TODO: Move examples into the README.md
|
|
30
|
-
# Simulate a github post:
|
|
31
|
-
# curl -X POST \
|
|
32
|
-
# -H "Content-Type: application/json" \
|
|
33
|
-
# -d '{ \
|
|
34
|
-
# "repository": { \
|
|
35
|
-
# "id": 12345, \
|
|
36
|
-
# "name": "puppetlabs-stdlib", \
|
|
37
|
-
# "html_url": "http://github.com", \
|
|
38
|
-
# "owner": {\
|
|
39
|
-
# "login": "foo"
|
|
40
|
-
# } \
|
|
41
|
-
# } \
|
|
42
|
-
# }' \
|
|
43
|
-
# 'https://puppet:puppet@localhost:8088/module' -k -q
|
|
44
|
-
#
|
|
45
|
-
# Simulate a BitBucket post:
|
|
46
|
-
# curl -X POST \
|
|
47
|
-
# -H "Content-Type: application/json" \
|
|
48
|
-
# -d '{ \
|
|
49
|
-
# "repository": { \
|
|
50
|
-
# "full_name": "puppetlabs/puppetlabs-stdlib", \
|
|
51
|
-
# "name": "PuppetLabs : StdLib"
|
|
52
|
-
# } }' \
|
|
53
|
-
# 'https://puppet:puppet@localhost:8088/module' -k -q
|
|
54
|
-
#
|
|
55
|
-
# This example shows that, unlike github, BitBucket allows special characters
|
|
56
|
-
# in repository names but translates it to generate a full_name which
|
|
57
|
-
# is used in the repository URL and is most useful for this webhook handler.
|
|
58
|
-
post '/module' do
|
|
59
|
-
protected! if settings.protected
|
|
60
|
-
request.body.rewind # in case someone has already read it
|
|
61
|
-
|
|
62
|
-
# Short circuit if we're ignoring this event
|
|
63
|
-
return 200 if ignore_event?
|
|
64
|
-
|
|
65
|
-
# TODO: Move these two lines of code into the parser
|
|
66
|
-
decoded = request.body.read
|
|
67
|
-
verify_signature(decoded) if verify_signature?
|
|
68
|
-
|
|
69
|
-
module_name = params['module_name']
|
|
70
|
-
|
|
71
|
-
module_name = sanitize_input(module_name)
|
|
72
|
-
LOGGER.info("Deploying module #{module_name}")
|
|
73
|
-
deploy_module(module_name)
|
|
74
|
-
end
|
|
75
|
-
|
|
76
|
-
# Simulate a github post:
|
|
77
|
-
# curl -d '{ "ref": "refs/heads/production" }' -H "Accept: application/json" 'https://puppet:puppet@localhost:8088/payload' -k -q
|
|
78
|
-
#
|
|
79
|
-
# If using stash look at the stash_mco.rb script included here.
|
|
80
|
-
# It will filter the stash post and make it look like a github post.
|
|
81
|
-
#
|
|
82
|
-
# Simulate a Gitorious post:
|
|
83
|
-
# curl -X POST -d '%7b%22ref%22%3a%22master%22%7d' 'http://puppet:puppet@localhost:8088/payload' -q
|
|
84
|
-
# Yes, Gitorious does not support https...
|
|
85
|
-
#
|
|
86
|
-
# Simulate a BitBucket post:
|
|
87
|
-
# curl -X POST -d '{ "push": { "changes": [ { "new": { "name": "production" } } ] } }' \
|
|
88
|
-
# 'https://puppet:puppet@localhost:8088/payload' -k -q
|
|
89
|
-
|
|
90
|
-
post '/payload' do # rubocop:disable Metrics/BlockLength
|
|
91
|
-
LOGGER.info "params = #{params}"
|
|
92
|
-
protected! if settings.protected
|
|
93
|
-
request.body.rewind # in case someone already read it
|
|
94
|
-
|
|
95
|
-
# Short circuit if we're ignoring this event
|
|
96
|
-
return 200 if ignore_event?
|
|
97
|
-
|
|
98
|
-
# Check if content type is x-www-form-urlencoded
|
|
99
|
-
decoded = if request.content_type.to_s.casecmp('application/x-www-form-urlencoded').zero?
|
|
100
|
-
CGI.unescape(request.body.read).gsub(%r{^payload\=}, '')
|
|
101
|
-
else
|
|
102
|
-
request.body.read
|
|
103
|
-
end
|
|
104
|
-
verify_signature(decoded) if verify_signature?
|
|
105
|
-
data = JSON.parse(decoded, quirks_mode: true)
|
|
106
|
-
|
|
107
|
-
# Iterate the data structure to determine what's should be deployed
|
|
108
|
-
branch = params['branch']
|
|
109
|
-
|
|
110
|
-
# If prefix is enabled in our config file, determine what the prefix should be
|
|
111
|
-
prefix = case settings.prefix
|
|
112
|
-
when :repo
|
|
113
|
-
params['repo_name']
|
|
114
|
-
when :user
|
|
115
|
-
params['repo_user']
|
|
116
|
-
when :command, TrueClass
|
|
117
|
-
run_prefix_command(data.to_json)
|
|
118
|
-
when String
|
|
119
|
-
settings.prefix
|
|
120
|
-
end
|
|
121
|
-
|
|
122
|
-
# When a branch is being deleted, a deploy against it will result in a failure, as it no longer exists.
|
|
123
|
-
# Instead, deploy the default branch, which will purge deleted branches per the user's configuration
|
|
124
|
-
deleted = params['deleted']
|
|
125
|
-
|
|
126
|
-
branch = if deleted
|
|
127
|
-
settings.default_branch
|
|
128
|
-
else
|
|
129
|
-
sanitize_input(branch)
|
|
130
|
-
end
|
|
131
|
-
|
|
132
|
-
# r10k doesn't yet know how to deploy all branches from a single source.
|
|
133
|
-
# The best we can do is just deploy all environments by passing nil to
|
|
134
|
-
# deploy() if we don't know the correct branch.
|
|
135
|
-
env = if prefix.nil? || prefix.empty? || branch.nil? || branch.empty?
|
|
136
|
-
normalize(branch)
|
|
137
|
-
else
|
|
138
|
-
normalize("#{prefix}_#{branch}")
|
|
139
|
-
end
|
|
140
|
-
|
|
141
|
-
if ignore_env?(env)
|
|
142
|
-
LOGGER.info("Skipping deployment of environment #{env} according to ignore_environments configuration parameter")
|
|
143
|
-
return 200
|
|
144
|
-
else
|
|
145
|
-
LOGGER.info("Deploying environment #{env}")
|
|
146
|
-
deploy(env, deleted)
|
|
147
|
-
end
|
|
148
|
-
end
|
|
46
|
+
register Sinatra::PuppetWebhookRoutes::Default
|
|
47
|
+
register Sinatra::PuppetWebhookRoutes::Module
|
|
48
|
+
register Sinatra::PuppetWebhookRoutes::Payload
|
|
149
49
|
|
|
150
50
|
not_found do
|
|
151
51
|
halt 404, "You shall not pass! (page not found)\n"
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
require 'sinatra'
|
|
2
|
+
|
|
3
|
+
module Sinatra
|
|
4
|
+
module PuppetWebhookRoutes
|
|
5
|
+
# Registers the default GET routes for PuppetWebhook
|
|
6
|
+
module Default
|
|
7
|
+
def self.registered(puppet_webhook)
|
|
8
|
+
puppet_webhook.get '/' do
|
|
9
|
+
raise Sinatra::NotFound
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
puppet_webhook.get '/heartbeat' do
|
|
13
|
+
return 200, { status: :success, message: 'running' }.to_json
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
require 'sinatra'
|
|
2
|
+
|
|
3
|
+
module Sinatra
|
|
4
|
+
module PuppetWebhookRoutes
|
|
5
|
+
# Registers a POST endpoint for the PuppetWebhook App
|
|
6
|
+
module Module
|
|
7
|
+
def self.registered(puppet_webhook)
|
|
8
|
+
puppet_webhook.post '/module' do
|
|
9
|
+
protected! if settings.protected
|
|
10
|
+
request.body.rewind # in case someone has already read it
|
|
11
|
+
|
|
12
|
+
# Short circuit if we're ignoring this event
|
|
13
|
+
return 200 if ignore_event?
|
|
14
|
+
|
|
15
|
+
# TODO: Move these two lines of code into the parser
|
|
16
|
+
decoded = request.body.read
|
|
17
|
+
verify_signature(decoded) if verify_signature?
|
|
18
|
+
|
|
19
|
+
module_name = payload[:module_name]
|
|
20
|
+
|
|
21
|
+
module_name = sanitize_input(module_name)
|
|
22
|
+
LOGGER.info("Deploying module #{module_name}")
|
|
23
|
+
deploy_module(module_name)
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
require 'sinatra'
|
|
2
|
+
|
|
3
|
+
module Sinatra
|
|
4
|
+
module PuppetWebhookRoutes
|
|
5
|
+
# Registers a POST route for the Payload endpoint on PuppetWebhook
|
|
6
|
+
module Payload
|
|
7
|
+
def self.registered(puppet_webhook)
|
|
8
|
+
puppet_webhook.post '/payload' do # rubocop:disable Metrics/BlockLength
|
|
9
|
+
LOGGER.info "parsed payload contained: #{payload}"
|
|
10
|
+
protected! if settings.protected
|
|
11
|
+
request.body.rewind # in case someone already read it
|
|
12
|
+
|
|
13
|
+
# Short circuit if we're ignoring this event
|
|
14
|
+
return 200 if ignore_event?
|
|
15
|
+
|
|
16
|
+
# Check if content type is x-www-form-urlencoded
|
|
17
|
+
decoded = if request.content_type.to_s.casecmp('application/x-www-form-urlencoded').zero?
|
|
18
|
+
CGI.unescape(request.body.read).gsub(%r{^payload\=}, '')
|
|
19
|
+
else
|
|
20
|
+
request.body.read
|
|
21
|
+
end
|
|
22
|
+
verify_signature(decoded) if verify_signature?
|
|
23
|
+
data = JSON.parse(decoded, quirks_mode: true)
|
|
24
|
+
|
|
25
|
+
# Iterate the data structure to determine what's should be deployed
|
|
26
|
+
branch = payload[:branch]
|
|
27
|
+
|
|
28
|
+
# If prefix is enabled in our config file, determine what the prefix should be
|
|
29
|
+
prefix = case settings.prefix
|
|
30
|
+
when :repo
|
|
31
|
+
payload[:repo_name]
|
|
32
|
+
when :user
|
|
33
|
+
payload[:repo_user]
|
|
34
|
+
when :command, TrueClass
|
|
35
|
+
run_prefix_command(data.to_json)
|
|
36
|
+
when String
|
|
37
|
+
settings.prefix
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# When a branch is being deleted, a deploy against it will result in a failure, as it no longer exists.
|
|
41
|
+
# Instead, deploy the default branch, which will purge deleted branches per the user's configuration
|
|
42
|
+
deleted = payload[:deleted]
|
|
43
|
+
|
|
44
|
+
branch = if deleted
|
|
45
|
+
settings.default_branch
|
|
46
|
+
else
|
|
47
|
+
sanitize_input(branch)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# r10k doesn't yet know how to deploy all branches from a single source.
|
|
51
|
+
# The best we can do is just deploy all environments by passing nil to
|
|
52
|
+
# deploy() if we don't know the correct branch.
|
|
53
|
+
env = if prefix.nil? || prefix.empty? || branch.nil? || branch.empty?
|
|
54
|
+
normalize(branch)
|
|
55
|
+
else
|
|
56
|
+
normalize("#{prefix}_#{branch}")
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
if ignore_env?(env)
|
|
60
|
+
LOGGER.info("Skipping deployment of environment #{env} according to ignore_environments configuration parameter")
|
|
61
|
+
return 200
|
|
62
|
+
else
|
|
63
|
+
LOGGER.info("Deploying environment #{env}")
|
|
64
|
+
deploy(env, deleted)
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: puppet_webhook
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version:
|
|
4
|
+
version: 1.0.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Vox Pupuli
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2017-
|
|
11
|
+
date: 2017-12-21 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: json
|
|
@@ -39,7 +39,7 @@ dependencies:
|
|
|
39
39
|
- !ruby/object:Gem::Version
|
|
40
40
|
version: '0'
|
|
41
41
|
- !ruby/object:Gem::Dependency
|
|
42
|
-
name: rack-
|
|
42
|
+
name: rack-bodyparser
|
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
|
44
44
|
requirements:
|
|
45
45
|
- - ">="
|
|
@@ -108,6 +108,20 @@ dependencies:
|
|
|
108
108
|
- - ">="
|
|
109
109
|
- !ruby/object:Gem::Version
|
|
110
110
|
version: '0'
|
|
111
|
+
- !ruby/object:Gem::Dependency
|
|
112
|
+
name: codacy-coverage
|
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
|
114
|
+
requirements:
|
|
115
|
+
- - ">="
|
|
116
|
+
- !ruby/object:Gem::Version
|
|
117
|
+
version: '0'
|
|
118
|
+
type: :development
|
|
119
|
+
prerelease: false
|
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
121
|
+
requirements:
|
|
122
|
+
- - ">="
|
|
123
|
+
- !ruby/object:Gem::Version
|
|
124
|
+
version: '0'
|
|
111
125
|
- !ruby/object:Gem::Dependency
|
|
112
126
|
name: coveralls
|
|
113
127
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -218,13 +232,15 @@ files:
|
|
|
218
232
|
- README.md
|
|
219
233
|
- bin/puppet_webhook
|
|
220
234
|
- config/app.yml
|
|
221
|
-
- config/server.yml
|
|
222
235
|
- lib/helpers/data_parsers.rb
|
|
223
236
|
- lib/helpers/deployments.rb
|
|
224
237
|
- lib/helpers/init.rb
|
|
225
238
|
- lib/helpers/tasks.rb
|
|
226
239
|
- lib/parsers/webhook_json_parser.rb
|
|
227
240
|
- lib/puppet_webhook.rb
|
|
241
|
+
- lib/routes/default.rb
|
|
242
|
+
- lib/routes/module.rb
|
|
243
|
+
- lib/routes/payload.rb
|
|
228
244
|
homepage: https://github.com/voxpupuli/puppet_webhook
|
|
229
245
|
licenses:
|
|
230
246
|
- apache
|
|
@@ -246,7 +262,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
246
262
|
version: '0'
|
|
247
263
|
requirements: []
|
|
248
264
|
rubyforge_project:
|
|
249
|
-
rubygems_version: 2.7.
|
|
265
|
+
rubygems_version: 2.7.3
|
|
250
266
|
signing_key:
|
|
251
267
|
specification_version: 4
|
|
252
268
|
summary: Sinatra Webhook Server for Puppet/R10K
|
data/config/server.yml
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
server_type: simple
|
|
2
|
-
logfile: /var/log/puppet_webhook/access.log
|
|
3
|
-
pidfile: /var/run/puppet_webhook/webhook.pid
|
|
4
|
-
lockfile: /var/run/puppet_webhook/webhook.lock
|
|
5
|
-
approot: './'
|
|
6
|
-
server_software: PuppetWebhook
|
|
7
|
-
bind_address: 0.0.0.0
|
|
8
|
-
port: 8088
|
|
9
|
-
enable_ssl: false
|
|
10
|
-
verify_ssl: false
|
|
11
|
-
public_key_path: ''
|
|
12
|
-
private_key_path: ''
|
|
13
|
-
command_prefix: 'umask 0022;'
|