puppetdb_foreman 4.0.0 → 6.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +3 -23
  3. data/Rakefile +9 -6
  4. data/app/controllers/api/v2/puppetdb_nodes_controller.rb +8 -6
  5. data/app/controllers/puppetdb_foreman/nodes_controller.rb +32 -7
  6. data/app/helpers/concerns/puppetdb_foreman/hosts_helper_extensions.rb +28 -0
  7. data/app/models/concerns/orchestration/puppetdb.rb +13 -6
  8. data/app/models/puppetdb_foreman/host_extensions.rb +5 -4
  9. data/app/services/puppetdb.rb +8 -12
  10. data/app/services/puppetdb_client/base.rb +12 -6
  11. data/app/services/puppetdb_client/v4.rb +48 -1
  12. data/app/services/puppetdb_host.rb +5 -3
  13. data/app/views/api/v2/puppetdb_nodes/import.json.rabl +2 -0
  14. data/app/views/api/v2/puppetdb_nodes/index.json.rabl +2 -0
  15. data/app/views/api/v2/puppetdb_nodes/unknown.json.rabl +2 -0
  16. data/app/views/puppetdb_foreman/nodes/index.html.erb +1 -0
  17. data/app/views/puppetdb_foreman/nodes/show.html.erb +69 -0
  18. data/config/routes.rb +11 -11
  19. data/db/migrate/20170717140010_migrate_puppetdb_api_version_setting.rb +4 -2
  20. data/db/migrate/20181001113836_remove_puppetdb_dashboard_address_setting.puppetdb_foreman.rb +7 -0
  21. data/lib/puppetdb_foreman/engine.rb +58 -33
  22. data/lib/puppetdb_foreman/version.rb +3 -1
  23. data/lib/puppetdb_foreman.rb +2 -0
  24. data/lib/tasks/puppetdb_foreman_tasks.rake +4 -4
  25. data/test/controllers/api/v2/puppetdb_nodes_controller_test.rb +60 -55
  26. data/test/controllers/nodes_controller_test.rb +34 -9
  27. data/test/models/host_test.rb +5 -4
  28. data/test/static_fixtures/resources.json +41 -0
  29. data/test/test_plugin_helper.rb +2 -4
  30. data/test/unit/puppetdb_host_test.rb +5 -4
  31. data/test/unit/puppetdb_test.rb +34 -85
  32. metadata +20 -23
  33. data/app/controllers/puppetdb_foreman/puppetdb_controller.rb +0 -30
  34. data/app/models/setting/puppetdb.rb +0 -52
  35. data/app/services/puppetdb_client/v1.rb +0 -29
  36. data/app/services/puppetdb_client/v3.rb +0 -45
  37. data/app/views/puppetdb_foreman/puppetdb/error.html.erb +0 -6
  38. data/test/static_fixtures/query_nodes.json +0 -61
@@ -1,58 +1,83 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module PuppetdbForeman
2
4
  class Engine < ::Rails::Engine
3
5
  engine_name 'puppetdb_foreman'
4
6
 
5
- initializer 'puppetdb_foreman.load_default_settings', :before => :load_config_initializers do |_app|
6
- require_dependency File.expand_path('../../../app/models/setting/puppetdb.rb', __FILE__) if begin
7
- Setting.table_exists?
8
- rescue StandardError
9
- (false)
10
- end
11
- end
12
-
13
7
  initializer 'puppetdb_foreman.load_app_instance_data' do |app|
14
8
  PuppetdbForeman::Engine.paths['db/migrate'].existent.each do |path|
15
9
  app.config.paths['db/migrate'] << path
16
10
  end
17
11
  end
18
12
 
19
- initializer 'puppetdb_foreman.register_plugin', :before => :finisher_hook do |_app|
13
+ initializer 'puppetdb_foreman.register_plugin', before: :finisher_hook do |_app|
20
14
  Foreman::Plugin.register :puppetdb_foreman do
21
- requires_foreman '>= 1.17'
15
+ requires_foreman '>= 3.1'
22
16
 
23
17
  apipie_documented_controllers ["#{PuppetdbForeman::Engine.root}/app/controllers/api/v2/*.rb"]
24
18
 
19
+ settings do
20
+ category :puppetdb, N_('PuppetDB') do
21
+ setting :puppetdb_enabled,
22
+ type: :boolean,
23
+ default: false,
24
+ description: _("Integration with PuppetDB, enabled will deactivate a host in PuppetDB when it's deleted in Foreman") # rubocop:disable Layout/LineLength
25
+
26
+ setting :puppetdb_address,
27
+ type: :string,
28
+ default: 'https://puppetdb:8081/pdb/cmd/v1',
29
+ description: _('Foreman will send PuppetDB requests to this address')
30
+
31
+ setting :puppetdb_ssl_ca_file,
32
+ type: :string,
33
+ default: SETTINGS[:ssl_ca_file],
34
+ description: _('Foreman will send PuppetDB requests with this CA file')
35
+
36
+ setting :puppetdb_ssl_certificate,
37
+ type: :string,
38
+ default: SETTINGS[:ssl_certificate],
39
+ description: _('Foreman will send PuppetDB requests with this certificate file')
40
+
41
+ setting :puppetdb_ssl_private_key,
42
+ type: :string,
43
+ default: SETTINGS[:ssl_priv_key],
44
+ description: _('Foreman will send PuppetDB requests with this key file')
45
+
46
+ setting :puppetdb_api_version,
47
+ type: :integer,
48
+ default: 4,
49
+ full_name: N_('PuppetDB API Version'),
50
+ description: _('Foreman will use this PuppetDB API version'),
51
+ collection: proc { ::Puppetdb::API_VERSIONS }
52
+ end
53
+ end
54
+
25
55
  security_block :puppetdb_foreman do
26
- permission :view_puppetdb_dashboard, :'puppetdb_foreman/puppetdb' => [:index]
27
- permission :view_puppetdb_nodes, :'puppetdb_foreman/nodes' => [:index],
28
- :'api/v2/puppetdb_nodes' => [:index, :unknown]
29
- permission :destroy_puppetdb_nodes, :'puppetdb_foreman/nodes' => [:destroy],
30
- :'api/v2/puppetdb_nodes' => [:destroy]
31
- permission :import_puppetdb_nodes, :'puppetdb_foreman/nodes' => [:import],
32
- :'api/v2/puppetdb_nodes' => [:import]
56
+ permission :view_puppetdb_nodes, 'puppetdb_foreman/nodes': %i[index show],
57
+ 'api/v2/puppetdb_nodes': %i[index unknown]
58
+
59
+ permission :destroy_puppetdb_nodes, 'puppetdb_foreman/nodes': [:destroy],
60
+ 'api/v2/puppetdb_nodes': [:destroy]
61
+
62
+ permission :import_puppetdb_nodes, 'puppetdb_foreman/nodes': [:import],
63
+ 'api/v2/puppetdb_nodes': [:import]
33
64
  end
34
65
 
35
- role 'PuppetDB Dashboard', [:view_puppetdb_dashboard]
36
66
  role 'PuppetDB Node Viewer', [:view_puppetdb_nodes]
37
- role 'PuppetDB Node Manager', [:view_puppetdb_nodes, :destroy_puppetdb_nodes, :import_puppetdb_nodes]
38
-
39
- menu :top_menu, :puppetdb, :caption => N_('PuppetDB Dashboard'),
40
- :url_hash => { :controller => 'puppetdb_foreman/puppetdb', :action => 'index', :puppetdb => 'puppetdb' },
41
- :parent => :monitor_menu,
42
- :last => :true
43
- menu :top_menu, :nodes, :caption => N_('PuppetDB Nodes'),
44
- :url_hash => { :controller => 'puppetdb_foreman/nodes', :action => 'index' },
45
- :parent => :monitor_menu,
46
- :after => :puppetdb
67
+ role 'PuppetDB Node Manager', %i[view_puppetdb_nodes destroy_puppetdb_nodes import_puppetdb_nodes]
68
+
69
+ menu :top_menu, :nodes, caption: N_('PuppetDB Nodes'),
70
+ url_hash: { controller: 'puppetdb_foreman/nodes', action: 'index' },
71
+ parent: :monitor_menu,
72
+ after: :puppetdb
47
73
  end
48
74
  end
49
75
 
50
76
  config.to_prepare do
51
- begin
52
- Host::Managed.send :include, PuppetdbForeman::HostExtensions
53
- rescue StandardError => e
54
- Rails.logger.warn "PuppetdbForeman: skipping engine hook (#{e})"
55
- end
77
+ Host::Managed.include PuppetdbForeman::HostExtensions
78
+ HostsHelper.include PuppetdbForeman::HostsHelperExtensions
79
+ rescue StandardError => e
80
+ Rails.logger.warn "PuppetdbForeman: skipping engine hook (#{e})"
56
81
  end
57
82
  end
58
83
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module PuppetdbForeman
2
- VERSION = '4.0.0'.freeze
4
+ VERSION = '6.0.0'
3
5
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module PuppetdbForeman
2
4
  require 'puppetdb_foreman/engine'
3
5
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Tests
2
4
  namespace :test do
3
5
  desc 'Test PuppetdbForeman'
@@ -11,7 +13,7 @@ namespace :test do
11
13
  end
12
14
 
13
15
  namespace :puppetdb_foreman do
14
- task :rubocop do
16
+ task rubocop: :environment do
15
17
  begin
16
18
  require 'rubocop/rake_task'
17
19
  RuboCop::RakeTask.new(:rubocop_puppetdb_foreman) do |task|
@@ -30,6 +32,4 @@ end
30
32
  Rake::Task[:test].enhance ['test:puppetdb_foreman']
31
33
 
32
34
  load 'tasks/jenkins.rake'
33
- if Rake::Task.task_defined?(:'jenkins:unit')
34
- Rake::Task['jenkins:unit'].enhance ['test:puppetdb_foreman', 'puppetdb_foreman:rubocop']
35
- end
35
+ Rake::Task['jenkins:unit'].enhance ['test:puppetdb_foreman', 'puppetdb_foreman:rubocop'] if Rake::Task.task_defined?(:'jenkins:unit')
@@ -1,68 +1,73 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'test_plugin_helper'
2
4
 
3
- class Api::V2::PuppetdbNodesControllerTest < ActionController::TestCase
4
- setup do
5
- setup_settings
6
- User.current = users(:admin)
7
- @host = FactoryBot.create(:host, :managed)
8
- end
5
+ module Api
6
+ module V2
7
+ class PuppetdbNodesControllerTest < ActionController::TestCase
8
+ setup do
9
+ User.current = users(:admin)
10
+ @host = FactoryBot.create(:host, :managed)
11
+ end
9
12
 
10
- context '#index' do
11
- test 'lists puppetdb nodes unknown to foreman' do
12
- ::PuppetdbClient::V4.any_instance.stubs(:query_nodes).returns(['one.example.com', 'two.example.com'])
13
- get :index, session: set_session_user
14
- assert_response :success
15
- response = ActiveSupport::JSON.decode(@response.body)
16
- hosts = response['results']
17
- assert_includes hosts, 'name' => 'one.example.com'
18
- assert_includes hosts, 'name' => 'two.example.com'
19
- end
20
- end
13
+ context '#index' do
14
+ test 'lists puppetdb nodes unknown to foreman' do
15
+ ::PuppetdbClient::V4.any_instance.stubs(:query_nodes).returns(['one.example.com', 'two.example.com'])
16
+ get :index, session: set_session_user
17
+ assert_response :success
18
+ response = ActiveSupport::JSON.decode(@response.body)
19
+ hosts = response['results']
20
+ assert_includes hosts, 'name' => 'one.example.com'
21
+ assert_includes hosts, 'name' => 'two.example.com'
22
+ end
23
+ end
21
24
 
22
- context '#unknown' do
23
- test 'lists puppetdb nodes unknown to foreman' do
24
- host = FactoryBot.create(:host, :managed)
25
- ::PuppetdbClient::V4.any_instance.stubs(:query_nodes).returns([host.name, 'two.example.com'])
26
- get :unknown, session: set_session_user
27
- assert_response :success
28
- response = ActiveSupport::JSON.decode(@response.body)
29
- hosts = response['results']
30
- refute_includes hosts, 'name' => host.name
31
- assert_includes hosts, 'name' => 'two.example.com'
32
- end
33
- end
25
+ context '#unknown' do
26
+ test 'lists puppetdb nodes unknown to foreman' do
27
+ host = FactoryBot.create(:host, :managed)
28
+ ::PuppetdbClient::V4.any_instance.stubs(:query_nodes).returns([host.name, 'two.example.com'])
29
+ get :unknown, session: set_session_user
30
+ assert_response :success
31
+ response = ActiveSupport::JSON.decode(@response.body)
32
+ hosts = response['results']
33
+ assert_not_includes hosts, 'name' => host.name
34
+ assert_includes hosts, 'name' => 'two.example.com'
35
+ end
36
+ end
34
37
 
35
- context '#destroy' do
36
- let(:node) { 'test.example.com' }
37
- let(:uuid) { SecureRandom.uuid }
38
+ context '#destroy' do
39
+ let(:node) { 'test.example.com' }
40
+ let(:uuid) { SecureRandom.uuid }
38
41
 
39
- before do
40
- ::PuppetdbClient::V4.any_instance.expects(:deactivate_node).with(node).returns(uuid)
41
- end
42
+ before do
43
+ ::PuppetdbClient::V4.any_instance.expects(:deactivate_node).with(node).returns(uuid)
44
+ end
42
45
 
43
- test 'imports a host by puppetdb facts' do
44
- delete :destroy, params: { :id => node }, session: set_session_user
45
- assert_response :success
46
- response = ActiveSupport::JSON.decode(@response.body)
47
- expected = { 'job' => { 'uuid' => uuid } }
48
- assert_equal expected, response
49
- end
50
- end
46
+ test 'imports a host by puppetdb facts' do
47
+ delete :destroy, params: { id: node }, session: set_session_user
48
+ assert_response :success
49
+ response = ActiveSupport::JSON.decode(@response.body)
50
+ expected = { 'job' => { 'uuid' => uuid } }
51
+ assert_equal expected, response
52
+ end
53
+ end
51
54
 
52
- context '#import' do
53
- let(:node) { 'test.example.com' }
54
- let(:host) { FactoryBot.create(:host) }
55
+ context '#import' do
56
+ let(:node) { 'test.example.com' }
57
+ let(:host) { FactoryBot.create(:host) }
55
58
 
56
- before do
57
- ::PuppetdbClient::V4.any_instance.expects(:facts).with(node).returns({})
58
- PuppetdbHost.any_instance.expects(:to_host).returns(host)
59
- end
59
+ before do
60
+ ::PuppetdbClient::V4.any_instance.expects(:facts).with(node).returns({})
61
+ PuppetdbHost.any_instance.expects(:to_host).returns(host)
62
+ end
60
63
 
61
- test 'imports a host by puppetdb facts' do
62
- put :import, params: { :id => node }, session: set_session_user
63
- assert_response :success
64
- response = ActiveSupport::JSON.decode(@response.body)
65
- assert_equal host.id, response['id']
64
+ test 'imports a host by puppetdb facts' do
65
+ put :import, params: { id: node }, session: set_session_user
66
+ assert_response :success
67
+ response = ActiveSupport::JSON.decode(@response.body)
68
+ assert_equal host.id, response['id']
69
+ end
70
+ end
66
71
  end
67
72
  end
68
73
  end
@@ -1,10 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'test_plugin_helper'
2
4
 
3
5
  class NodesControllerTest < ActionController::TestCase
4
6
  tests ::PuppetdbForeman::NodesController
5
7
 
6
8
  setup do
7
- setup_settings
8
9
  User.current = users(:admin)
9
10
  @host = FactoryBot.create(:host, :managed)
10
11
  end
@@ -15,21 +16,45 @@ class NodesControllerTest < ActionController::TestCase
15
16
  ::PuppetdbClient::V4.any_instance.stubs(:query_nodes).returns([host.name, 'two.example.com'])
16
17
  get :index, session: set_session_user
17
18
  assert_response :success
18
- refute response.body =~ /#{host.name}/m
19
+ assert_not response.body =~ /#{host.name}/m
19
20
  assert response.body =~ /two.example.com/m
20
21
  end
21
22
  end
22
23
 
24
+ context '#show' do
25
+ let(:host) { FactoryBot.create(:host, :managed) }
26
+
27
+ before do
28
+ resources_resp = [
29
+ { 'type' => 'Class', 'title' => 'main' },
30
+ { 'type' => 'Class', 'title' => 'Settings' },
31
+ { 'type' => 'Stage', 'title' => 'main' },
32
+ ]
33
+
34
+ ::PuppetdbClient::V4.any_instance.stubs(:resources).returns(resources_resp)
35
+ end
36
+
37
+ test 'displays puppet classes information about a given node' do
38
+ get :show, params: { id: host.name }, session: set_session_user
39
+
40
+ assert_response :success
41
+ assert_includes response.body, '<tr><td>main</td></tr>'
42
+ assert_includes response.body, '<tr><td>Settings</td></tr>'
43
+ assert_includes response.body, '2</span> Classes'
44
+ assert_includes response.body, '2</span> Types'
45
+ end
46
+ end
47
+
23
48
  context '#destroy' do
24
49
  let(:node) { 'test.example.com' }
25
50
  test 'deactivating a node in puppetdb' do
26
51
  ::PuppetdbClient::V4.any_instance.expects(:deactivate_node).with(node).returns(true)
27
- delete :destroy, params: { :id => node }, session: set_session_user
52
+ delete :destroy, params: { id: node }, session: set_session_user
28
53
  assert_response :found
29
54
  assert_redirected_to puppetdb_foreman_nodes_path
30
55
  assert_nil flash[:error]
31
- assert_not_nil flash[:notice]
32
- assert_equal "Deactivated node #{node} in PuppetDB", flash[:notice]
56
+ assert_not_nil flash[:notice] || flash[:success]
57
+ assert_equal "Deactivated node #{node} in PuppetDB", flash[:notice] || flash[:success]
33
58
  end
34
59
  end
35
60
 
@@ -43,12 +68,12 @@ class NodesControllerTest < ActionController::TestCase
43
68
  end
44
69
 
45
70
  test 'imports a host from puppetdb facts' do
46
- put :import, params: { :id => node }, session: set_session_user
71
+ put :import, params: { id: node }, session: set_session_user
47
72
  assert_response :found
48
- assert_redirected_to host_path(:id => host)
73
+ assert_redirected_to host_path(id: host)
49
74
  assert_nil flash[:error]
50
- assert_not_nil flash[:notice]
51
- assert_equal "Imported host #{node} from PuppetDB", flash[:notice]
75
+ assert_not_nil flash[:notice] || flash[:success]
76
+ assert_equal "Imported host #{node} from PuppetDB", flash[:notice] || flash[:success]
52
77
  end
53
78
  end
54
79
  end
@@ -1,9 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'test_plugin_helper'
2
4
 
3
5
  class HostTest < ActiveSupport::TestCase
4
6
  setup do
5
7
  User.current = FactoryBot.build(:user, :admin)
6
- setup_settings
7
8
  disable_orchestration
8
9
  end
9
10
 
@@ -24,9 +25,9 @@ class HostTest < ActiveSupport::TestCase
24
25
  assert_equal 1, tasks.size
25
26
  end
26
27
 
27
- test '#delPuppetdb' do
28
+ test '#del_puppetdb' do
28
29
  ::PuppetdbClient::V4.any_instance.expects(:deactivate_node).with(host.name).returns(true)
29
- host.send(:delPuppetdb)
30
+ host.send(:del_puppetdb)
30
31
  end
31
32
  end
32
33
 
@@ -40,7 +41,7 @@ class HostTest < ActiveSupport::TestCase
40
41
  host.queue.clear
41
42
  host.send(:queue_puppetdb_destroy)
42
43
  tasks = host.queue.all.map(&:name)
43
- assert_equal [], tasks
44
+ assert_empty tasks
44
45
  end
45
46
  end
46
47
  end
@@ -0,0 +1,41 @@
1
+ [{
2
+ "tags": ["params", "class"],
3
+ "file": null,
4
+ "type": "Class",
5
+ "title": "Cron",
6
+ "line": null,
7
+ "resource": "f13ec266-2914-420c-8d71-13e3466c5856",
8
+ "certname": "host.example.com",
9
+ "parameters": {},
10
+ "exported": false
11
+ }, {
12
+ "tags": ["class"],
13
+ "file": null,
14
+ "type": "Anchor",
15
+ "title": "postgresql",
16
+ "line": null,
17
+ "resource": "9b007f50-87f3-48a1-a4c5-584f2f9d1740",
18
+ "certname": "host.example.com",
19
+ "parameters": {},
20
+ "exported": false
21
+ }, {
22
+ "tags": ["class"],
23
+ "file": null,
24
+ "type": "Class",
25
+ "title": "SomeClass",
26
+ "line": 21,
27
+ "resource": "4b68c39a-b1cc-45ab-96c2-690dbc045f76",
28
+ "certname": "host.example.com",
29
+ "parameters": {},
30
+ "exported": false
31
+ }, {
32
+ "tags": ["class", "params"],
33
+ "file": null,
34
+ "type": "Class",
35
+ "title": "AnotherClass::Params",
36
+ "line": null,
37
+ "resource": "69293889-3e16-48e1-943f-5602096f6c47",
38
+ "certname": "host.example.com",
39
+ "parameters": {},
40
+ "exported": false
41
+ }]
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # This calls the main test_helper in Foreman-core
2
4
  require 'test_helper'
3
5
  require 'database_cleaner'
@@ -6,10 +8,6 @@ require 'webmock/minitest'
6
8
  # Foreman's setup doesn't handle cleaning up for Minitest::Spec
7
9
  DatabaseCleaner.strategy = :transaction
8
10
 
9
- def setup_settings
10
- Setting::Puppetdb.load_defaults
11
- end
12
-
13
11
  def fixture(name)
14
12
  File.read(File.expand_path("../static_fixtures/#{name}", __FILE__))
15
13
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'test_plugin_helper'
2
4
 
3
5
  class PuppetdbHostTest < ActiveSupport::TestCase
@@ -7,7 +9,6 @@ class PuppetdbHostTest < ActiveSupport::TestCase
7
9
  setup do
8
10
  User.current = FactoryBot.create(:user, :admin)
9
11
  disable_orchestration
10
- setup_settings
11
12
  end
12
13
 
13
14
  let(:sample_facts) do
@@ -15,7 +16,7 @@ class PuppetdbHostTest < ActiveSupport::TestCase
15
16
  end
16
17
 
17
18
  let(:pdbhost) do
18
- PuppetdbHost.new(:facts => sample_facts)
19
+ PuppetdbHost.new(facts: sample_facts)
19
20
  end
20
21
 
21
22
  test 'parses facts' do
@@ -35,12 +36,12 @@ class PuppetdbHostTest < ActiveSupport::TestCase
35
36
 
36
37
  test 'updates an existing host by facts' do
37
38
  Setting[:update_subnets_from_facts] = true
38
- FactoryBot.create(:host, :managed, :hostname => 'host', :domain => FactoryBot.create(:domain, :name => 'example.com'))
39
+ FactoryBot.create(:host, :managed, hostname: 'host', domain: FactoryBot.create(:domain, name: 'example.com'))
39
40
  pdbhost.to_host
40
41
  host = Host.find_by(name: 'host.example.com')
41
42
  assert_equal 'host.example.com', host.name
42
43
  # foreman core does not delete old interfaces when importing interfaces from facts
43
- assert host.interfaces.where(:ip => '1.1.1.174').first
44
+ assert host.interfaces.where(ip: '1.1.1.174').first
44
45
  assert_equal Operatingsystem.find_by(title: 'RedHat 7.3'), host.operatingsystem
45
46
  end
46
47
  end