lita-puppet 2.0.0 → 2.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 21c2bf71dcadd164239ace4a8810aa2a7ef3ac78
4
- data.tar.gz: 769464679133edea58a9d1e7791af3b5a39efea9
3
+ metadata.gz: b1b3f7b216de57ce1507c62606049abe09c4a6d7
4
+ data.tar.gz: bf814b1efdb2b666499d4df0149fe28bbbeff81d
5
5
  SHA512:
6
- metadata.gz: 5b5d3cc7423f4b833e0658cb23a3aa3c473def0f9576ff1f7c803d3b486af75bf4be55a8211eb2dc64fbaeb92e5a5a9120cf2bba5dd024bc7b573c23c3561fc6
7
- data.tar.gz: fd0bbf3801dc0e55b8b6ea8ab93cf5fd19795b6303f75e3f99db94413f55d10009656864f560039950fcf9f5d0c8b9dbac3b17bd5d38cb7e04658de2b9157998
6
+ metadata.gz: 0b01deb2674c47f115759323cae6093828d2aa9d5c727068c3f97edd1e83b69957d4c029682cf07ddaf6a3dc2b6ca8399d9c592a9ca1b64cb2cadc631ff28ed3
7
+ data.tar.gz: 40617d283ae66ef75a502f68ebcced9c35e126b5227e3057b96f62f92f972b2d557569463729199a5b7fe8d5f4f2b6f37a50dcc407e2d6581c9da6768396ace8
@@ -16,7 +16,7 @@ Metrics/MethodLength:
16
16
  Max: 20
17
17
 
18
18
  Metrics/ClassLength:
19
- Max: 150
19
+ Max: 165
20
20
 
21
21
  Metrics/BlockLength:
22
22
  Max: 30
data/README.md CHANGED
@@ -94,3 +94,19 @@ This is also available as:
94
94
  pp class nodes <class>
95
95
 
96
96
  Where `<class>` is a class name as it shows up in the catalog. Usually something like Role::Foo_bar
97
+
98
+ #### Query PuppetDB for the fact value of a given node
99
+ `puppet fact <certname> <fact>`
100
+
101
+ This is also available as:
102
+
103
+ `pp fact <certname> <fact>`
104
+
105
+ #### Query PuppetDB for some basic info about a node
106
+ `puppet <certname> info`
107
+
108
+ This is also available as:
109
+
110
+ `pp <certname> info`
111
+
112
+ This queries the [PuppetDB nodes endpoint](https://docs.puppet.com/puppetdb/4.4/api/query/v4/nodes.html)
data/Rakefile CHANGED
@@ -5,4 +5,4 @@ require 'rubocop/rake_task'
5
5
  RSpec::Core::RakeTask.new(:spec)
6
6
  RuboCop::RakeTask.new(:rubocop)
7
7
 
8
- task default: [:spec, :rubocop]
8
+ task default: %i[spec rubocop]
@@ -40,6 +40,20 @@ module Lita
40
40
  help: { t('help.nodes_with_class.syntax') => t('help.nodes_with_class.desc') }
41
41
  )
42
42
 
43
+ route(
44
+ /(puppet|pp)\s+(fact)\s+(\S+)\s+(\S+)/i,
45
+ :node_facts,
46
+ command: true,
47
+ help: { t('help.node_facts.syntax') => t('help.node_facts.desc') }
48
+ )
49
+
50
+ route(
51
+ /(puppet|pp)\s+(\S+)\s+(info)/i,
52
+ :nodes_info,
53
+ command: true,
54
+ help: { t('help.nodes_info.syntax') => t('help.nodes_info.desc') }
55
+ )
56
+
43
57
  route(
44
58
  /(puppet|pp)\s+(r10k|deploy)(\s+(\S+)(\s+(\S+))?)?/i,
45
59
  :r10k_deploy,
@@ -92,16 +106,10 @@ module Lita
92
106
  def node_profiles(response)
93
107
  host = response.matches[0][2]
94
108
  what = response.matches[0][1]
95
- url = config.puppetdb_url
96
-
97
- unless url
98
- response.reply(t('replies.node_profiles.notconf'))
99
- return false
100
- end
101
109
 
102
110
  response.reply_with_mention(t('replies.node_profiles.working'))
103
111
 
104
- profiles = node_roles_and_profiles(url, what, host)
112
+ profiles = node_roles_and_profiles(what, host)
105
113
 
106
114
  if profiles.is_a? String
107
115
  fail_message response, t('replies.node_profiles.failure', error: profiles)
@@ -116,16 +124,10 @@ module Lita
116
124
 
117
125
  def nodes_with_class(response)
118
126
  puppet_class = response.matches[0][3]
119
- url = config.puppetdb_url
120
-
121
- unless url
122
- response.reply(t('replies.nodes_with_class.notconf'))
123
- return false
124
- end
125
127
 
126
128
  response.reply_with_mention(t('replies.nodes_with_class.working'))
127
129
 
128
- puppet_classes = class_nodes(url, class_camel(puppet_class))
130
+ puppet_classes = class_nodes(class_camel(puppet_class))
129
131
  if puppet_classes.empty?
130
132
  fail_message response, t('replies.nodes_with_class.failure', pclass: puppet_class)
131
133
  else
@@ -137,6 +139,31 @@ module Lita
137
139
  end
138
140
  end
139
141
 
142
+ def node_facts(response)
143
+ host = response.matches[0][2]
144
+ fact = response.matches[0][3]
145
+ result = query_fact(host, fact)
146
+ if result.nil?
147
+ response.reply_with_mention(
148
+ t('replies.node_facts.error', host: host)
149
+ )
150
+ else
151
+ response.reply result
152
+ end
153
+ end
154
+
155
+ def nodes_info(response)
156
+ host = response.matches[0][1]
157
+ result = node_info(host)
158
+ if result.nil?
159
+ response.reply_with_mention(
160
+ t('replies.nodes_info.error', host: host)
161
+ )
162
+ else
163
+ response.reply result
164
+ end
165
+ end
166
+
140
167
  # rubocop:disable Metrics/AbcSize
141
168
  def r10k_deploy(response)
142
169
  environment = response.matches[0][3]
@@ -2,16 +2,19 @@ module Utils
2
2
  module LitaPuppet
3
3
  # Utility methods for working with PuppetDB
4
4
  module PuppetDB
5
- def class_nodes(url, classname)
6
- client = ::PuppetDB::Client.new({
7
- server: url,
8
- pem: {
9
- 'key' => config.puppetdb_key,
10
- 'cert' => config.puppetdb_cert,
11
- 'ca_file' => config.puppetdb_ca_cert
12
- }
13
- }, config.puppetdb_api_vers)
14
- q = client.request(
5
+ def db_connect
6
+ ::PuppetDB::Client.new({
7
+ server: config.puppetdb_url,
8
+ pem: {
9
+ 'key' => config.puppetdb_key,
10
+ 'cert' => config.puppetdb_cert,
11
+ 'ca_file' => config.puppetdb_ca_cert
12
+ }
13
+ }, config.puppetdb_api_vers)
14
+ end
15
+
16
+ def class_nodes(classname)
17
+ q = db_connect.request(
15
18
  'resources',
16
19
  [
17
20
  :and,
@@ -23,11 +26,37 @@ module Utils
23
26
  q.data.map { |node| node['certname'] }
24
27
  end
25
28
 
29
+ def query_fact(node, fact)
30
+ q = db_connect.request(
31
+ "facts/#{fact}",
32
+ [:'=', 'certname', node]
33
+ )
34
+ begin
35
+ raise 'invalid query' if q.data.empty?
36
+ q.data.last['value']
37
+ rescue
38
+ nil
39
+ end
40
+ end
41
+
42
+ def node_info(node)
43
+ q = db_connect.request(
44
+ 'nodes',
45
+ [:'=', 'certname', node]
46
+ )
47
+ begin
48
+ raise 'invalid node' if q.data.empty?
49
+ q.data.last.to_yaml
50
+ rescue
51
+ nil
52
+ end
53
+ end
54
+
26
55
  # rubocop:disable AbcSize
27
- def node_roles_and_profiles(url, what, nodename)
56
+ def node_roles_and_profiles(what, nodename)
28
57
  # TODO: validate url and nodename
29
58
  ::PuppetDB::Client.new({
30
- server: url,
59
+ server: config.puppetdb_url,
31
60
  pem: {
32
61
  'key' => config.puppetdb_key,
33
62
  'cert' => config.puppetdb_cert,
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |spec|
2
2
  spec.name = 'lita-puppet'
3
- spec.version = '2.0.0'
3
+ spec.version = '2.1.0'
4
4
  spec.authors = ['Daniel Schaaff', 'Jonathan Gnagy'].sort
5
5
  spec.email = ['jgnagy@knuedge.com']
6
6
  spec.description = 'Some basic Puppet interactions for Lita'
@@ -15,6 +15,12 @@ en:
15
15
  nodes_with_class:
16
16
  syntax: puppet class nodes <class>
17
17
  desc: Query PuppetDB to get a list of all nodes containing a class.
18
+ node_facts:
19
+ syntax: puppet fact <certname> <factname>
20
+ desc: Query PuppetDB for facts of a given node
21
+ nodes_info:
22
+ syntax: puppet <certname> info
23
+ desc: returns basic info about a node from puppetdb
18
24
  r10k_deploy:
19
25
  syntax: puppet r10k [env [module]]
20
26
  desc: Deploy the latest puppet code on the puppet master via r10k, optionally specifying an environment, and possibly a module.
@@ -37,6 +43,10 @@ en:
37
43
  working: "let me see what I can find in PuppetDB for you."
38
44
  failure: "There are no nodes with %{pclass} class, are you sure it's a valid class?"
39
45
  success: "Here are all the nodes with class %{pclass}:"
46
+ node_facts:
47
+ error: "that didn't work, are you sure %{host} is a valid certname?"
48
+ nodes_info:
49
+ error: "that didn't work, are you sure %{host} is a valid certname?"
40
50
  r10k_deploy:
41
51
  working: "I'll get right on that. Give me a moment and I'll let you know how it went."
42
52
  failure: "your r10k run didn't seem to work. Here's what went wrong:"
@@ -16,6 +16,18 @@ describe Lita::Handlers::Puppet, lita_handler: true do
16
16
  instance_double('::PuppetDB::Client', request: puppetdb_nodes)
17
17
  end
18
18
 
19
+ let(:fact_request) do
20
+ instance_double('::PuppetDB::Client', request: puppetdb_fact_result)
21
+ end
22
+
23
+ let(:info_request) do
24
+ instance_double('::PuppetDB::Client', request: puppetdb_host_info)
25
+ end
26
+
27
+ let(:bad_request) do
28
+ instance_double('::PuppetDB::Client', request: puppetdb_nil_data)
29
+ end
30
+
19
31
  let(:puppetdb_nodes) do
20
32
  double(
21
33
  data: [
@@ -25,6 +37,35 @@ describe Lita::Handlers::Puppet, lita_handler: true do
25
37
  )
26
38
  end
27
39
 
40
+ let(:puppetdb_nil_data) do
41
+ double(
42
+ data: [
43
+ ]
44
+ )
45
+ end
46
+ let(:puppetdb_host_info) do
47
+ double(
48
+ data: [
49
+ { 'deactivated' => nil,
50
+ 'latest_report_hash' => '693feed',
51
+ 'facts_environment' => 'production' }
52
+ ]
53
+ )
54
+ end
55
+
56
+ let(:puppetdb_fact_result) do
57
+ double(
58
+ data: [
59
+ {
60
+ 'certname' => 'foo.example.com',
61
+ 'name' => 'operatingsystem',
62
+ 'value' => 'Darwin',
63
+ 'environment' => 'production'
64
+ }
65
+ ]
66
+ )
67
+ end
68
+
28
69
  let(:rye_box) do
29
70
  box = instance_double(
30
71
  'Rye::Box',
@@ -48,6 +89,8 @@ describe Lita::Handlers::Puppet, lita_handler: true do
48
89
  is_expected.to route_command('puppet class nodes foo').to(:nodes_with_class)
49
90
  is_expected.to route_command('puppet r10k')
50
91
  .with_authorization_for(:puppet_admins).to(:r10k_deploy)
92
+ is_expected.to route_command('puppet fact node foo').to(:node_facts)
93
+ is_expected.to route_command('puppet node info').to(:nodes_info)
51
94
  end
52
95
 
53
96
  describe('#cert_clean') do
@@ -95,6 +138,35 @@ describe Lita::Handlers::Puppet, lita_handler: true do
95
138
  end
96
139
  end
97
140
 
141
+ describe('#node_facts') do
142
+ it 'should return error msg for invalid certname' do
143
+ allow(::PuppetDB::Client).to receive(:new).and_return(bad_request)
144
+ send_command('puppet fact foo.example.com operatingsystem')
145
+ expect(replies.last)
146
+ .to eq("that didn't work, are you sure foo.example.com is a valid certname?")
147
+ end
148
+ it 'should return error msg for invalid certname' do
149
+ allow(::PuppetDB::Client).to receive(:new).and_return(fact_request)
150
+ send_command('puppet fact foo.example.com operatingsystem')
151
+ expect(replies.last).to eq('Darwin')
152
+ end
153
+ end
154
+
155
+ describe('#nodes_info') do
156
+ it 'should return error msg for invalid certname' do
157
+ allow(::PuppetDB::Client).to receive(:new).and_return(bad_request)
158
+ send_command('puppet foo.example.com info')
159
+ expect(replies.last)
160
+ .to eq("that didn't work, are you sure foo.example.com is a valid certname?")
161
+ end
162
+ it 'should return the node info' do
163
+ allow(::PuppetDB::Client).to receive(:new).and_return(info_request)
164
+ send_command('puppet foo.example.com info')
165
+ expect(replies.last)
166
+ .to eq("---\ndeactivated: \nlatest_report_hash: 693feed\nfacts_environment: production\n")
167
+ end
168
+ end
169
+
98
170
  describe('#r10k_deploy') do
99
171
  before do
100
172
  robot.auth.add_user_to_group!(lita_user, :puppet_admins)
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: 2.0.0
4
+ version: 2.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel Schaaff
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2017-03-22 00:00:00.000000000 Z
12
+ date: 2017-04-10 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: lita
@@ -225,7 +225,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
225
225
  version: '0'
226
226
  requirements: []
227
227
  rubyforge_project:
228
- rubygems_version: 2.4.8
228
+ rubygems_version: 2.4.5
229
229
  signing_key:
230
230
  specification_version: 4
231
231
  summary: Allow the Lita bot to handle requests for puppet tasks