lita-puppet 2.0.0 → 2.1.0

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: 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