lita-puppet 0.6.1 → 0.6.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 24922d792c78cac0dbc47d19319680e6d4aa8e65
4
- data.tar.gz: af23e3bb3dce2e5a053356a8ae03128b5d18b426
3
+ metadata.gz: 9d628affc13749d488e0425795d1c186529d6aa1
4
+ data.tar.gz: 9d6b10693e3ecccab9e6250b5a6dda87fc7abc25
5
5
  SHA512:
6
- metadata.gz: 3fa73002df79c370f7d4717d99a5b8784ab3a1fd4435e7ebf7e9d36f91e52aea1d2220dd50869ca3ad6d3d2089256f96b0525a2f3560f5a63dce0d0d398e3bee
7
- data.tar.gz: 969b0634bc6f682a5118b16a7c08c904deff71f2d640632964ae079c2ca61fccb5c2335baf599942a885a8d1c1df37276d6cc0dd22db83b38afb04e46b7bc7a7
6
+ metadata.gz: 33df42ee1cb7799138a0b829423cbe5d6316da8eff92f0c856695bf5143e8f4214f5ebab06291d9297e2524628ef6a09ae021a77fece2cd25b3696cbe29b2709
7
+ data.tar.gz: a7e34d69a70957729c495f40bef7d835d140a99a722bbdf57e16d192758f741d9a49a0a887b7727e458a4352b65f5e577f41a8860fe3195f3564dbf7a2b9b026
data/.rubocop.yml ADDED
@@ -0,0 +1,19 @@
1
+ Documentation:
2
+ Exclude:
3
+ - lib/lita/handlers/puppet.rb
4
+
5
+ FileName:
6
+ Exclude:
7
+ - lib/lita-puppet.rb
8
+
9
+ Metrics/LineLength:
10
+ Max: 100
11
+
12
+ Metrics/AbcSize:
13
+ Max: 22
14
+
15
+ Metrics/MethodLength:
16
+ Max: 20
17
+
18
+ Metrics/ClassLength:
19
+ Max: 150
data/.travis.yml ADDED
@@ -0,0 +1,7 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.2.5
4
+ - 2.3.1
5
+ services:
6
+ - redis-server
7
+ cache: bundler
data/Gemfile CHANGED
@@ -1,3 +1,3 @@
1
- source "https://rubygems.org"
1
+ source 'https://rubygems.org'
2
2
 
3
3
  gemspec
data/README.md CHANGED
@@ -1,5 +1,10 @@
1
1
  # lita-puppet
2
2
 
3
+ [![Build Status](https://img.shields.io/travis/knuedge/lita-puppet/master.svg)](https://travis-ci.org/knuedge/lita-puppet)
4
+ [![MIT License](https://img.shields.io/badge/license-MIT-brightgreen.svg)](https://tldrlegal.com/license/mit-license)
5
+ [![RubyGems :: RMuh Gem Version](http://img.shields.io/gem/v/lita-puppet.svg)](https://rubygems.org/gems/lita-puppet)
6
+ [![Code Climate](https://img.shields.io/codeclimate/github/knuedge/lita-puppet.svg)](https://codeclimate.com/github/knuedge/lita-puppet)
7
+
3
8
  A [Lita](https://www.lita.io/) handler plugin for some basic [Puppet](https://puppet.com/) operations.
4
9
 
5
10
  ## Installation
data/Rakefile CHANGED
@@ -1,6 +1,8 @@
1
- require "bundler/gem_tasks"
2
- require "rspec/core/rake_task"
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
+ require 'rubocop/rake_task'
3
4
 
4
5
  RSpec::Core::RakeTask.new(:spec)
6
+ RuboCop::RakeTask.new(:rubocop)
5
7
 
6
- task default: :spec
8
+ task default: [:spec, :rubocop]
data/lib/lita-puppet.rb CHANGED
@@ -1,18 +1,18 @@
1
- require "lita"
1
+ require 'lita'
2
2
  require 'rye'
3
3
  require 'timeout'
4
4
  require 'puppetdb'
5
5
 
6
6
  Lita.load_locales Dir[File.expand_path(
7
- File.join("..", "..", "locales", "*.yml"), __FILE__
7
+ File.join('..', '..', 'locales', '*.yml'), __FILE__
8
8
  )]
9
9
 
10
- require 'utils/puppetdb'
11
- require 'utils/ssh'
12
- require 'utils/text'
13
- require "lita/handlers/puppet"
10
+ require 'utils/lita_puppet/puppetdb'
11
+ require 'utils/lita_puppet/ssh'
12
+ require 'utils/lita_puppet/text'
13
+ require 'lita/handlers/puppet'
14
14
 
15
15
  Lita::Handlers::Puppet.template_root File.expand_path(
16
- File.join("..", "..", "templates"),
17
- __FILE__
16
+ File.join('..', '..', 'templates'),
17
+ __FILE__
18
18
  )
@@ -3,225 +3,185 @@ module Lita
3
3
  class Puppet < Handler
4
4
  namespace 'Puppet'
5
5
  config :master_hostname, required: true, type: String
6
- config :ssh_user, required: false, type: String
7
- config :control_repo_path, required: false, type: String
6
+ config :ssh_user, required: false, type: String, default: 'lita'
7
+ config :control_repo_path, required: false, type: String, default: '/opt/puppet/control'
8
8
  config :puppetdb_url, required: false, type: String
9
9
 
10
10
  route(
11
11
  /(puppet|pp)(\s+agent)?\s+(run)(\s+on)?\s+(\S+)/i,
12
12
  :puppet_agent_run,
13
13
  command: true,
14
- help: {
15
- "puppet agent run on <host>" => "Run the puppet agent on <host>."
16
- }
14
+ help: { t('help.puppet_agent_run.syntax') => t('help.puppet_agent_run.desc') }
17
15
  )
18
16
 
19
17
  route(
20
18
  /(puppet|pp)\s+(cert)\s+(clean)\s+(\S+)/i,
21
19
  :cert_clean,
22
20
  command: true,
23
- help: {
24
- "puppet cert clean <host>" => "Remove all traces of the SSL cert for <host> on the Puppet Master."
25
- }
21
+ help: { t('help.cert_clean.syntax') => t('help.cert_clean.desc') }
26
22
  )
27
23
 
28
24
  route(
29
25
  /(puppet|pp)\s+(catalog|node)\s+(\S+)\s+(profiles)/i,
30
26
  :node_profiles,
31
27
  command: true,
32
- help: {
33
- "puppet catalog <host> profiles" => "Query PuppetDB to get a list of all roles and profiles applied to <host>."
34
- }
28
+ help: { t('help.node_profiles.syntax') => t('help.node_profiles.desc') }
35
29
  )
36
30
 
37
31
  route(
38
32
  /(puppet|pp)\s+(class)\s+(nodes)\s+(\S+)/i,
39
33
  :nodes_with_class,
40
34
  command: true,
41
- help: {
42
- "puppet class nodes <class>" => "Query PuppetDB to get a list of all nodes containing a class."
43
- }
35
+ help: { t('help.nodes_with_class.syntax') => t('help.nodes_with_class.desc') }
44
36
  )
45
37
 
46
38
  route(
47
39
  /(puppet|pp)\s+(r10k|deploy)(\s+(\S+)(\s+(\S+))?)?/i,
48
40
  :r10k_deploy,
49
41
  command: true,
50
- help: {
51
- "puppet r10k [env [module]]" => "Deploy the latest puppet code on the puppet master via r10k, optionally specifying an environment, and possibly a module."
52
- }
42
+ help: { t('help.r10k_deploy.syntax') => t('help.r10k_deploy.desc') }
53
43
  )
54
44
 
55
- include ::Utils::PuppetDB
56
- include ::Utils::SSH
57
- include ::Utils::Text
45
+ include ::Utils::LitaPuppet::PuppetDB
46
+ include ::Utils::LitaPuppet::SSH
47
+ include ::Utils::LitaPuppet::Text
58
48
 
59
49
  def cert_clean(response)
60
50
  cert = response.matches[0][3]
61
- user = config.ssh_user || 'lita'
62
- username = friendly_name(response.user.name)
63
51
 
64
- response.reply("#{username}, working on that `puppet cert clean`. I'll get right back to you.")
52
+ response.reply_with_mention(t('replies.cert_clean.working'))
65
53
 
66
- result = over_ssh(host: config.master_hostname, user: user, timeout: 120) do |server|
67
- server.cd '/tmp'
68
- # Need to use sudo
69
- server.enable_sudo
70
- # scary...
71
- server.disable_safe_mode
72
-
73
- server.execute "puppet cert clean #{cert} 2>&1"
74
- end
54
+ result = cert_clean_result(config.master_hostname, config.ssh_user, cert)
75
55
 
76
56
  if result[:exception]
77
- response.reply "#{username}, your `puppet cert clean` didn't seem to work... ;-("
78
- response.reply as_code(result[:exception].message)
79
- return false
57
+ fail_message t('replies.cert_clean.failure'), result[:exception].message
58
+ else
59
+ success_message(
60
+ t('replies.cert_clean.success'),
61
+ (result[:stdout] + result[:stderr]).join("\n")
62
+ )
80
63
  end
81
-
82
- # build a reply
83
- response.reply("#{username}, your `puppet cert clean` is all done!")
84
- reply_content = [result[:stdout].join("\n"), result[:stderr].join("\n")].join("\n")
85
- response.reply as_code(reply_content)
86
64
  end
87
65
 
88
66
  def puppet_agent_run(response)
89
67
  host = response.matches[0][4]
90
- user = config.ssh_user || 'lita'
91
- username = friendly_name(response.user.name)
92
68
 
93
- response.reply("#{username}, I'll run puppet right away. Give me a sec and I'll let you know how it goes.")
69
+ response.reply_with_mention(t('replies.puppet_agent_run.working'))
94
70
 
95
- result = over_ssh(host: host, user: user) do |server|
96
- server.cd '/tmp'
97
-
98
- # Need to use sudo from here on
99
- server.enable_sudo
100
-
101
- # scary...
102
- server.disable_safe_mode
103
-
104
- # build up the command
105
- command = 'puppet agent'
106
- command << ' --onetime --verbose --no-daemonize'
107
- command << ' --no-usecacheonfailure'
108
- command << ' --no-splay --show_diff 2>&1'
109
-
110
- server.execute command
111
- end
71
+ result = simple_ssh_command(host, config.ssh_user, agent_command)
112
72
 
113
73
  # build a reply
114
- if !result[:exception]
115
- response.reply "#{username}, that puppet run is complete! It exited with status #{result[:exit_status]}."
116
- # Send the standard out, but strip off the bash color code stuff...
117
- response.reply as_code(result[:stdout].join("\n"))
74
+ if result[:exception]
75
+ fail_message t('replies.puppet_agent_run.failure'), result[:exception].message
118
76
  else
119
- response.reply "#{username}, your puppet run is done, but didn't seem to work... I think it may have timed out."
120
- response.reply as_code(result[:exception].message)
77
+ success_message(
78
+ t('replies.puppet_agent_run.success', status: result[:exit_status]),
79
+ result[:stdout].join("\n")
80
+ )
121
81
  end
122
82
  end
123
83
 
124
84
  def node_profiles(response)
125
85
  host = response.matches[0][2]
126
86
  url = config.puppetdb_url
127
- username = friendly_name(response.user.name)
128
87
 
129
88
  unless url
130
- cant_reply = "#{username}, I would do that, but I don't know how to connect to PuppetDB."
131
- cant_reply << "Edit my config and add `config.handlers.puppet.puppetdb_url`."
132
- response.reply(cant_reply)
89
+ response.reply(t('replies.node_profiles.notconf'))
133
90
  return false
134
91
  end
135
92
 
136
- response.reply("#{username}, let me see what I can find in PuppetDB for you.")
93
+ response.reply_with_mention(t('replies.node_profiles.working'))
137
94
 
138
95
  profiles = node_roles_and_profiles(url, host)
96
+
139
97
  if profiles.is_a? String
140
- response.reply("Hmmm, that didn't work. Here's what PuppetDB responded with: '#{profiles}'")
141
- return false
98
+ fail_message t('replies.node_profiles.failure', error: profiles)
142
99
  else
143
- response.reply("Here are the profiles and roles for #{host}:")
144
- response.reply as_code(profiles.join("\n"))
100
+ success_message t('replies.node_profiles.success', host: host), profiles.join("\n")
145
101
  end
146
102
  end
147
103
 
148
104
  def nodes_with_class(response)
149
105
  puppet_class = response.matches[0][3]
150
106
  url = config.puppetdb_url
151
- username = friendly_name(response.user.name)
152
107
 
153
108
  unless url
154
- cant_reply = "#{username}, I would do that, but I don't know how to connect to PuppetDB."
155
- cant_reply << "Edit my config and add `config.handlers.puppet.puppetdb_url`."
156
- response.reply(cant_reply)
109
+ response.reply(t('replies.nodes_with_class.notconf'))
157
110
  return false
158
111
  end
159
112
 
160
- response.reply("#{username}, let me see what I can find in PuppetDB for you.")
161
-
162
- search = class_camel(puppet_class)
163
- puppet_classes = class_nodes(url, search)
113
+ response.reply_with_mention(t('replies.nodes_with_class.working'))
114
+
115
+ puppet_classes = class_nodes(url, class_camel(puppet_class))
164
116
  if puppet_classes.empty?
165
- response.reply("There are no nodes with #{puppet_class} class, are you sure its a valid class?")
166
- return false
117
+ fail_message t('replies.nodes_with_class.failure', pclass: puppet_class)
167
118
  else
168
- response.reply("Here are all the nodes with class #{puppet_class}:")
169
- response.reply as_code(puppet_classes.join("\n"))
119
+ success_message(
120
+ t('replies.nodes_with_class.success', pclass: puppet_class),
121
+ puppet_classes.join("\n")
122
+ )
170
123
  end
171
124
  end
172
125
 
173
-
126
+ # rubocop:disable Metrics/AbcSize
174
127
  def r10k_deploy(response)
175
128
  environment = response.matches[0][3]
176
129
  mod = response.matches[0][5]
177
- control_repo = config.control_repo_path || '/opt/puppet/control'
178
- user = config.ssh_user || 'lita'
179
- username = friendly_name(response.user.name)
130
+ user = config.ssh_user
180
131
 
181
- response.reply("#{username}, I'll get right on that. Give me a moment and I'll let you know how it went.")
132
+ response.reply_with_mention(t('replies.r10k_deploy.working'))
182
133
 
183
- result1 = over_ssh(host: config.master_hostname, user: user, timeout: 120) do |server|
184
- # Need to use sudo
185
- server.enable_sudo
186
- server[control_repo].git :pull
187
- end
134
+ result1 = r10k_git_result(config.master_hostname, user, config.control_repo_path)
188
135
 
189
136
  if result1[:exception]
190
- response.reply "#{username}, your r10k run didn't seem to work. Looks like there was a problem with Git:"
191
- response.reply as_code(result1[:exception].message)
137
+ fail_message t('replies.r10k_deploy.gitfail'), result1[:exception].message
192
138
  return false
193
139
  end
194
140
 
195
- result2 = over_ssh(host: config.master_hostname, user: user) do |server|
141
+ result2 = simple_ssh_command(config.master_hostname, user, r10k_command(environment, mod))
142
+
143
+ if result2[:exception]
144
+ fail_message t('replies.r10k_deploy.pupfail'), result2[:exception].message
145
+ else
146
+ success_message(
147
+ t('replies.r10k_deploy.success'),
148
+ [result1[:stdout].join("\n"), result2[:stderr].join("\n")].join("\n")
149
+ )
150
+ end
151
+ end
152
+
153
+ private
154
+
155
+ def fail_message(message, data = nil)
156
+ response.reply_with_mention(message)
157
+ response.reply(as_code(data)) if data
158
+ end
159
+
160
+ alias success_message fail_message
161
+
162
+ def simple_ssh_command(host, user, command, timeout = 300)
163
+ over_ssh(host: host, user: user, timeout: timeout) do |server|
164
+ server.cd '/tmp'
196
165
  # Need to use sudo
197
166
  server.enable_sudo
198
167
  # scary...
199
168
  server.disable_safe_mode
200
169
 
201
- command = "r10k deploy"
202
- if environment && mod
203
- command << ' module'
204
- command << " -e #{environment}"
205
- command << " #{mod}"
206
- command << " -v"
207
- else
208
- command << " environment"
209
- command << " #{environment}" if environment
210
- command << ' -pv'
211
- end
212
170
  server.execute command
213
171
  end
172
+ end
214
173
 
215
- if result2[:exception]
216
- response.reply "#{username}, your r10k run didn't seem to work... Maybe it timed out?"
217
- response.reply as_code(result2[:exception].message)
218
- return false
219
- end
174
+ def cert_clean_result(host, user, cert)
175
+ cmd = "puppet cert clean #{cert} 2>&1"
176
+ simple_ssh_command(host, user, cmd, 120)
177
+ end
220
178
 
221
- # build a reply
222
- response.reply("#{username}, your r10k deployment is done!")
223
- reply_content = [result1[:stdout].join("\n"), result2[:stderr].join("\n")].join("\n")
224
- response.reply as_code(reply_content)
179
+ def r10k_git_result(host, user, repo_location)
180
+ over_ssh(host: host, user: user, timeout: 120) do |server|
181
+ # Need to use sudo
182
+ server.enable_sudo
183
+ server[repo_location].git :pull
184
+ end
225
185
  end
226
186
 
227
187
  Lita.register_handler(self)
@@ -0,0 +1,39 @@
1
+ module Utils
2
+ module LitaPuppet
3
+ # Utility methods for working with PuppetDB
4
+ module PuppetDB
5
+ def dbquery(url, q)
6
+ # TODO: validate incoming query structure
7
+ client = ::PuppetDB::Client.new(server: url)
8
+ client.request(*q)
9
+ end
10
+
11
+ def node_roles_and_profiles(url, nodename)
12
+ # TODO: validate url and nodename
13
+ ::PuppetDB::Client.new(server: url) # this is weird but required
14
+ d = ::PuppetDB::Client.get("/catalogs/#{nodename}")
15
+ return d['error'] if d['error']
16
+
17
+ tags = []
18
+ d['data']['resources'].each { |r| tags.concat(r['tags']) }
19
+
20
+ # return all the tags related to profile:: or role::
21
+ tags.sort.uniq.select { |t| t.match(/^(profile|role)::/) }
22
+ end
23
+
24
+ def class_nodes(url, classname)
25
+ client = ::PuppetDB::Client.new(server: url)
26
+ q = client.request(
27
+ 'resources',
28
+ [
29
+ :and,
30
+ [:'=', 'type', 'Class'],
31
+ [:'=', 'title', classname.to_s]
32
+ ]
33
+ )
34
+
35
+ q.data.map { |node| node['certname'] }
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,47 @@
1
+ module Utils
2
+ module LitaPuppet
3
+ # Utility methods for doing things over SSH
4
+ module SSH
5
+ # Intelligently do some things over SSH
6
+ def over_ssh(opts = {})
7
+ raise 'MissingSSHHost' unless opts[:host]
8
+ raise 'MissingSSHUser' unless opts[:user]
9
+ opts[:timeout] ||= 300 # default to a 5 minute timeout
10
+
11
+ remote = Rye::Box.new(
12
+ opts[:host],
13
+ user: opts[:user],
14
+ auth_methods: ['publickey'],
15
+ password_prompt: false,
16
+ error: STDOUT # send STDERR to STDOUT for things that actually print
17
+ )
18
+
19
+ exception = nil
20
+
21
+ # Getting serious about not crashing Lita...
22
+ output = begin
23
+ # pass our host back to the user to work with
24
+ Timeout.timeout(opts[:timeout]) { yield remote }
25
+ rescue Rye::Err, StandardError => e
26
+ exception = e
27
+ ensure
28
+ remote.disconnect
29
+ end
30
+
31
+ calculate_result(output, exception)
32
+ end
33
+
34
+ def calculate_result(output, exception)
35
+ result = {}
36
+ if exception
37
+ result[:exception] = exception
38
+ else
39
+ result[:exit_status] = output.exit_status
40
+ result[:stdout] = output.stdout
41
+ result[:stderr] = output.stderr
42
+ end
43
+ result
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,42 @@
1
+ module Utils
2
+ module LitaPuppet
3
+ # Utility methods for manipulating text
4
+ module Text
5
+ # Strip off bad characters
6
+ def sanitze_for_chat(text)
7
+ # Remove bash colorings
8
+ text.gsub(/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[mGK]/, '')
9
+ end
10
+
11
+ # camel case puppet classes
12
+ def class_camel(text)
13
+ text.split('::').map(&:capitalize).join('::')
14
+ end
15
+
16
+ # Format some text as code
17
+ # Note that this is HipChat specific for the moment
18
+ # TODO: Make this *not* HipChat specific
19
+ def as_code(text)
20
+ '/code ' + sanitze_for_chat(text)
21
+ end
22
+
23
+ def r10k_command(environment, mod)
24
+ command = 'r10k deploy'
25
+ if environment && mod
26
+ command << " module -e #{environment} #{mod} -v"
27
+ else
28
+ command << ' environment'
29
+ command << " #{environment}" if environment
30
+ command << ' -pv'
31
+ end
32
+ end
33
+
34
+ def agent_command
35
+ command = 'puppet agent'
36
+ command << ' --onetime --verbose --no-daemonize'
37
+ command << ' --no-usecacheonfailure'
38
+ command << ' --no-splay --show_diff 2>&1'
39
+ end
40
+ end
41
+ end
42
+ end
data/lita-puppet.gemspec CHANGED
@@ -1,26 +1,29 @@
1
1
  Gem::Specification.new do |spec|
2
- spec.name = "lita-puppet"
3
- spec.version = "0.6.1"
4
- spec.authors = ["Daniel Schaaff", "Jonathan Gnagy"].sort
5
- spec.email = ["jgnagy@knuedge.com"]
6
- spec.description = "Some basic Puppet interactions for Lita"
7
- spec.summary = "Allow the Lita bot to handle requests for puppet tasks"
8
- spec.homepage = "https://github.com/knuedge/lita-puppet"
2
+ spec.name = 'lita-puppet'
3
+ spec.version = '0.6.2'
4
+ spec.authors = ['Daniel Schaaff', 'Jonathan Gnagy'].sort
5
+ spec.email = ['jgnagy@knuedge.com']
6
+ spec.description = 'Some basic Puppet interactions for Lita'
7
+ spec.summary = 'Allow the Lita bot to handle requests for puppet tasks'
8
+ spec.homepage = 'https://github.com/knuedge/lita-puppet'
9
9
  spec.license = 'MIT'
10
- spec.metadata = { "lita_plugin_type" => "handler" }
10
+ spec.metadata = { 'lita_plugin_type' => 'handler' }
11
11
 
12
- spec.files = `git ls-files`.split($/)
12
+ spec.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR)
13
13
  spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
14
14
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
15
- spec.require_paths = ["lib"]
15
+ spec.require_paths = ['lib']
16
16
 
17
- spec.add_runtime_dependency "lita", "~> 4.7"
18
- spec.add_runtime_dependency "rye"
19
- spec.add_runtime_dependency "puppetdb-ruby"
17
+ spec.add_runtime_dependency 'lita', '~> 4.7'
18
+ spec.add_runtime_dependency 'rye'
19
+ spec.add_runtime_dependency 'puppetdb-ruby'
20
20
 
21
- spec.add_development_dependency "bundler", "~> 1.3"
22
- spec.add_development_dependency "pry-byebug"
23
- spec.add_development_dependency "rake"
24
- spec.add_development_dependency "rack-test"
25
- spec.add_development_dependency "rspec", "~> 3.0"
21
+ spec.add_development_dependency 'bundler', '~> 1.3'
22
+ spec.add_development_dependency 'pry-byebug'
23
+ spec.add_development_dependency 'rake'
24
+ spec.add_development_dependency 'rack-test'
25
+ spec.add_development_dependency 'rspec', '~> 3.0'
26
+ spec.add_development_dependency 'simplecov'
27
+ spec.add_development_dependency 'coveralls'
28
+ spec.add_development_dependency 'rubocop'
26
29
  end
data/locales/en.yml CHANGED
@@ -2,3 +2,43 @@ en:
2
2
  lita:
3
3
  handlers:
4
4
  puppet:
5
+ help:
6
+ puppet_agent_run:
7
+ syntax: puppet agent run on <host>
8
+ desc: Run the puppet agent on <host>.
9
+ cert_clean:
10
+ syntax: puppet cert clean <host>
11
+ desc: Remove all traces of the SSL cert for <host> on the Puppet Master.
12
+ node_profiles:
13
+ syntax: puppet catalog <host> profiles
14
+ desc: Query PuppetDB to get a list of all roles and profiles applied to <host>.
15
+ nodes_with_class:
16
+ syntax: puppet class nodes <class>
17
+ desc: Query PuppetDB to get a list of all nodes containing a class.
18
+ r10k_deploy:
19
+ syntax: puppet r10k [env [module]]
20
+ desc: Deploy the latest puppet code on the puppet master via r10k, optionally specifying an environment, and possibly a module.
21
+ replies:
22
+ cert_clean:
23
+ working: "working on that `puppet cert clean`. I'll get right back to you."
24
+ failure: "your `puppet cert clean` didn't seem to work... ;-("
25
+ success: "your `puppet cert clean` is all done!"
26
+ puppet_agent_run:
27
+ working: "I'll run puppet right away. Give me a sec and I'll let you know how it goes."
28
+ failure: "your puppet run is done, but didn't seem to work... I think it may have timed out."
29
+ success: "that puppet run is complete! It exited with status %{status}."
30
+ node_profiles:
31
+ notconf: "I would do that, but I don't know how to connect to PuppetDB. Edit my config and add `config.handlers.puppet.puppetdb_url`."
32
+ working: "let me see what I can find in PuppetDB for you."
33
+ failure: "Hmmm, that didn't work. Here's what PuppetDB responded with: '%{error}'"
34
+ success: "Here are the profiles and roles for %{host}:"
35
+ nodes_with_class:
36
+ notconf: "I would do that, but I don't know how to connect to PuppetDB. Edit my config and add `config.handlers.puppet.puppetdb_url`."
37
+ working: "let me see what I can find in PuppetDB for you."
38
+ failure: "There are no nodes with %{pclass} class, are you sure it's a valid class?"
39
+ success: "Here are all the nodes with class %{pclass}:"
40
+ r10k_deploy:
41
+ working: "I'll get right on that. Give me a moment and I'll let you know how it went."
42
+ gitfail: "your r10k run didn't seem to work. Looks like there was a problem with Git:"
43
+ pupfail: "your r10k run didn't seem to work. Here's what went wrong:"
44
+ success: "your r10k deployment is done!"
@@ -1,4 +1,23 @@
1
- require "spec_helper"
1
+ require 'spec_helper'
2
2
 
3
3
  describe Lita::Handlers::Puppet, lita_handler: true do
4
+ it 'routes agent run commands properly' do
5
+ is_expected.to route_command('puppet agent run on foo').to(:puppet_agent_run)
6
+ end
7
+
8
+ it 'routes cert clean commands properly' do
9
+ is_expected.to route_command('puppet cert clean foo').to(:cert_clean)
10
+ end
11
+
12
+ it 'routes catalog profiles commands properly' do
13
+ is_expected.to route_command('puppet catalog foo profiles').to(:node_profiles)
14
+ end
15
+
16
+ it 'routes class nodes commands properly' do
17
+ is_expected.to route_command('puppet class nodes foo').to(:nodes_with_class)
18
+ end
19
+
20
+ it 'routes r10k commands properly' do
21
+ is_expected.to route_command('puppet r10k').to(:r10k_deploy)
22
+ end
4
23
  end
data/spec/spec_helper.rb CHANGED
@@ -1,5 +1,12 @@
1
- require "lita-puppet"
2
- require "lita/rspec"
1
+ require 'simplecov'
2
+ # require 'coveralls'
3
+ SimpleCov.formatters = [
4
+ SimpleCov::Formatter::HTMLFormatter
5
+ ]
6
+ SimpleCov.start { add_filter '/spec/' }
7
+
8
+ require 'lita-puppet'
9
+ require 'lita/rspec'
3
10
 
4
11
  # A compatibility mode is provided for older plugins upgrading from Lita 3. Since this plugin
5
12
  # was generated with Lita 4, the compatibility mode should be left disabled.
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lita-puppet
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.1
4
+ version: 0.6.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel Schaaff
@@ -123,6 +123,48 @@ dependencies:
123
123
  - - "~>"
124
124
  - !ruby/object:Gem::Version
125
125
  version: '3.0'
126
+ - !ruby/object:Gem::Dependency
127
+ name: simplecov
128
+ requirement: !ruby/object:Gem::Requirement
129
+ requirements:
130
+ - - ">="
131
+ - !ruby/object:Gem::Version
132
+ version: '0'
133
+ type: :development
134
+ prerelease: false
135
+ version_requirements: !ruby/object:Gem::Requirement
136
+ requirements:
137
+ - - ">="
138
+ - !ruby/object:Gem::Version
139
+ version: '0'
140
+ - !ruby/object:Gem::Dependency
141
+ name: coveralls
142
+ requirement: !ruby/object:Gem::Requirement
143
+ requirements:
144
+ - - ">="
145
+ - !ruby/object:Gem::Version
146
+ version: '0'
147
+ type: :development
148
+ prerelease: false
149
+ version_requirements: !ruby/object:Gem::Requirement
150
+ requirements:
151
+ - - ">="
152
+ - !ruby/object:Gem::Version
153
+ version: '0'
154
+ - !ruby/object:Gem::Dependency
155
+ name: rubocop
156
+ requirement: !ruby/object:Gem::Requirement
157
+ requirements:
158
+ - - ">="
159
+ - !ruby/object:Gem::Version
160
+ version: '0'
161
+ type: :development
162
+ prerelease: false
163
+ version_requirements: !ruby/object:Gem::Requirement
164
+ requirements:
165
+ - - ">="
166
+ - !ruby/object:Gem::Version
167
+ version: '0'
126
168
  description: Some basic Puppet interactions for Lita
127
169
  email:
128
170
  - jgnagy@knuedge.com
@@ -131,6 +173,8 @@ extensions: []
131
173
  extra_rdoc_files: []
132
174
  files:
133
175
  - ".gitignore"
176
+ - ".rubocop.yml"
177
+ - ".travis.yml"
134
178
  - CONTRIBUTING.md
135
179
  - Gemfile
136
180
  - LICENSE
@@ -138,9 +182,9 @@ files:
138
182
  - Rakefile
139
183
  - lib/lita-puppet.rb
140
184
  - lib/lita/handlers/puppet.rb
141
- - lib/utils/puppetdb.rb
142
- - lib/utils/ssh.rb
143
- - lib/utils/text.rb
185
+ - lib/utils/lita_puppet/puppetdb.rb
186
+ - lib/utils/lita_puppet/ssh.rb
187
+ - lib/utils/lita_puppet/text.rb
144
188
  - lita-puppet.gemspec
145
189
  - locales/en.yml
146
190
  - spec/lita/handlers/puppet_spec.rb
@@ -1,31 +0,0 @@
1
- module Utils
2
- # Utility methods for working with PuppetDB
3
- module PuppetDB
4
- def dbquery(url, q)
5
- # TODO: validate incoming query structure
6
- client = ::PuppetDB::Client.new(server: url)
7
- client.request *q
8
- end
9
-
10
- def node_roles_and_profiles(url, nodename)
11
- # TODO: validate url and nodename
12
- ::PuppetDB::Client.new(server: url) # this is weird but required
13
- d = ::PuppetDB::Client.get("/catalogs/#{nodename}")
14
- return d["error"] if d['error']
15
-
16
- tags = []
17
- d["data"]["resources"].each {|r| tags.concat(r['tags'])}
18
-
19
- # return all the tags related to profile:: or role::
20
- tags.sort.uniq.select {|t| t.match /^(profile|role)::/ }
21
- end
22
-
23
- def class_nodes(url, classname)
24
- client = ::PuppetDB::Client.new(server: url)
25
- q = client.request('resources',[:and,[:'=','type', 'Class'],[:'=','title',"#{classname}"]])
26
-
27
- q.data.map { |node| node['certname'] }
28
- end
29
-
30
- end
31
- end
data/lib/utils/ssh.rb DELETED
@@ -1,46 +0,0 @@
1
- module Utils
2
- # Utility methods for doing things over SSH
3
- module SSH
4
- # Intelligently do some things over SSH
5
- def over_ssh(opts = {})
6
- result = {}
7
- fail "MissingSSHHost" unless opts[:host]
8
- fail "MissingSSHUser" unless opts[:user]
9
- opts[:timeout] ||= 300 # default to a 5 minute timeout
10
-
11
- remote = Rye::Box.new(
12
- opts[:host],
13
- user: opts[:user],
14
- auth_methods: ['publickey'],
15
- password_prompt: false,
16
- error: STDOUT # send STDERR to STDOUT for things that actually print
17
- )
18
-
19
- exception = nil
20
-
21
- # Getting serious about not crashing Lita...
22
- output = begin
23
- Timeout::timeout(opts[:timeout]) do
24
- yield remote # pass our host back to the user to work with
25
- end
26
- rescue Rye::Err => e
27
- exception = e
28
- rescue StandardError => e
29
- exception = e
30
- rescue Exception => e
31
- exception = e
32
- ensure
33
- remote.disconnect
34
- end
35
-
36
- if exception
37
- result[:exception] = exception
38
- else
39
- result[:exit_status] = output.exit_status
40
- result[:stdout] = output.stdout
41
- result[:stderr] = output.stderr
42
- end
43
- return result
44
- end
45
- end
46
- end
data/lib/utils/text.rb DELETED
@@ -1,28 +0,0 @@
1
- module Utils
2
- # Utility methods for manipulating text
3
- module Text
4
- # Try to make names more friendly
5
- def friendly_name(long_name)
6
- long_name.split(/\s/).first
7
- end
8
-
9
- # Strip off bad characters
10
- def sanitze_for_chat(text)
11
- # Remove bash colorings
12
- text.gsub(/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[mGK]/, '')
13
- end
14
-
15
- # camel case puppet classes
16
- def class_camel(text)
17
- text.split('::').map(&:capitalize).join('::')
18
- end
19
-
20
- # Format some text as code
21
- # Note that this is HipChat specific for the moment
22
- # TODO: Make this *not* HipChat specific
23
- def as_code(text)
24
- "/code " + sanitze_for_chat(text)
25
- end
26
- end
27
-
28
- end