foreman_chef 0.2.2 → 0.3.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/app/assets/javascripts/chef_proxy_environment_refresh.js +26 -0
- data/app/controllers/foreman_chef/application_controller.rb +7 -0
- data/app/controllers/foreman_chef/environments_controller.rb +90 -0
- data/app/helpers/foreman_chef/chef_proxy_form.rb +22 -8
- data/app/lib/proxy_api/foreman_chef/chef_proxy.rb +13 -0
- data/app/models/foreman_chef/concerns/host_action_subject.rb +1 -2
- data/app/models/foreman_chef/concerns/host_and_hostgroup_extensions.rb +18 -0
- data/app/models/foreman_chef/concerns/host_extensions.rb +17 -0
- data/app/models/foreman_chef/concerns/hostgroup_extensions.rb +32 -0
- data/app/models/foreman_chef/concerns/smart_proxy_extensions.rb +44 -0
- data/app/models/foreman_chef/environment.rb +33 -0
- data/app/models/foreman_chef/fact_importer.rb +1 -1
- data/app/models/foreman_chef/fact_name.rb +1 -0
- data/app/overrides/add_chef_proxy.rb +1 -0
- data/app/services/foreman_chef/chef_server_importer.rb +100 -0
- data/app/views/foreman/unattended/snippets/_chef_client_bootstrap.erb +2 -1
- data/app/views/foreman_chef/environments/_form.html.erb +11 -0
- data/app/views/foreman_chef/environments/edit.html.erb +3 -0
- data/app/views/foreman_chef/environments/environments_for_chef_proxy.html.erb +3 -0
- data/app/views/foreman_chef/environments/import.html.erb +58 -0
- data/app/views/foreman_chef/environments/index.html.erb +35 -0
- data/app/views/foreman_chef/environments/new.html.erb +3 -0
- data/config/routes.rb +14 -0
- data/db/migrate/20150916141657_create_chef_environment.rb +20 -0
- data/lib/foreman_chef/engine.rb +46 -6
- data/lib/foreman_chef/version.rb +1 -1
- metadata +19 -6
- data/app/models/foreman_chef/chef_proxy_association.rb +0 -10
- data/app/models/foreman_chef/host_extensions.rb +0 -16
- data/app/models/foreman_chef/hostgroup_extensions.rb +0 -18
- data/app/models/foreman_chef/smart_proxy_extensions.rb +0 -38
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7da1a055be91131a483a56eb8769bf6fafe304b9
|
4
|
+
data.tar.gz: 2375b6891121651e6824fff3e73e8ec38261a437
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f6e44141df5a607f79c380b3ca81ded67314e4eb6553e6e7b262b666915b0bee84442003e44cdaf8a20f34a230eba1230dc0948dab4157012ba1660e69e26dc4
|
7
|
+
data.tar.gz: efd17ea55ffb24fb2ae0067f023d9fa4f029aca65a85008ddd57e427710b57f78c3481f3d72cf8ec18608864a26f5b2961af3041cbe7d0bf0e8e98020638928a
|
@@ -0,0 +1,26 @@
|
|
1
|
+
$(function () {
|
2
|
+
$("#host_chef_proxy_id, #hostgroup_chef_proxy_id").change(function () {
|
3
|
+
var element = $(this);
|
4
|
+
var attrs = attribute_hash(['chef_proxy_id']);
|
5
|
+
var url = element.attr('data-url');
|
6
|
+
if (element.attr('id') == 'host_chef_proxy_id') {
|
7
|
+
attrs['type'] = 'host'
|
8
|
+
} else {
|
9
|
+
attrs['type'] = 'hostgroup'
|
10
|
+
}
|
11
|
+
|
12
|
+
foreman.tools.showSpinner();
|
13
|
+
$.ajax({
|
14
|
+
data: attrs,
|
15
|
+
type: 'get',
|
16
|
+
url: url,
|
17
|
+
complete: function () {
|
18
|
+
reloadOnAjaxComplete(element);
|
19
|
+
},
|
20
|
+
success: function (request) {
|
21
|
+
$('#host_chef_environment_id, #hostgroup_chef_environment_id').parent().parent().replaceWith(request);
|
22
|
+
}
|
23
|
+
});
|
24
|
+
});
|
25
|
+
});
|
26
|
+
|
@@ -0,0 +1,90 @@
|
|
1
|
+
module ForemanChef
|
2
|
+
class EnvironmentsController < ::ForemanChef::ApplicationController
|
3
|
+
include Foreman::Controller::AutoCompleteSearch
|
4
|
+
before_filter :find_resource, :only => [:edit, :update, :destroy]
|
5
|
+
|
6
|
+
def import
|
7
|
+
proxy = SmartProxy.authorized(:view_smart_proxies).find(params[:proxy])
|
8
|
+
opts = params[:proxy].blank? ? {} : { :url => proxy.url, :chef_proxy => proxy }
|
9
|
+
opts[:env] = params[:env] unless params[:env].blank?
|
10
|
+
@importer = ChefServerImporter.new(opts)
|
11
|
+
@changed = @importer.changes
|
12
|
+
if @changed.values.all?(&:empty?)
|
13
|
+
notice _("Nothing to synchronize")
|
14
|
+
redirect_to foreman_chef_environments_path
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def synchronize
|
19
|
+
proxy = SmartProxy.authorized(:view_smart_proxies).find(params[:proxy])
|
20
|
+
if (errors = ChefServerImporter.new(:chef_proxy => proxy).obsolete_and_new(params[:changed])).empty?
|
21
|
+
notice _("Successfully updated environments")
|
22
|
+
else
|
23
|
+
error _("Failed to update environments: %s") % errors.to_sentence
|
24
|
+
end
|
25
|
+
redirect_to foreman_chef_environments_path
|
26
|
+
end
|
27
|
+
|
28
|
+
def index
|
29
|
+
@environments = resource_base.includes(:chef_proxy).search_for(params[:search], :order => params[:order]).paginate(:page => params[:page])
|
30
|
+
end
|
31
|
+
|
32
|
+
def new
|
33
|
+
@environment = ForemanChef::Environment.new
|
34
|
+
end
|
35
|
+
|
36
|
+
def create
|
37
|
+
@environment = ForemanChef::Environment.new(params[:foreman_chef_environment])
|
38
|
+
if @environment.save
|
39
|
+
process_success
|
40
|
+
else
|
41
|
+
process_error
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def edit
|
46
|
+
end
|
47
|
+
|
48
|
+
def update
|
49
|
+
if @environment.update_attributes(params[:foreman_chef_environment])
|
50
|
+
process_success
|
51
|
+
else
|
52
|
+
process_error
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def destroy
|
57
|
+
if @environment.destroy
|
58
|
+
process_success
|
59
|
+
else
|
60
|
+
process_error
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def auto_complete_controller_name
|
65
|
+
'foreman_chef_environments'
|
66
|
+
end
|
67
|
+
|
68
|
+
def environments_for_chef_proxy
|
69
|
+
@chef_proxy = SmartProxy.authorized(:view_smart_proxies).with_features('Chef').find_by_id(params[:chef_proxy_id])
|
70
|
+
@environments = @chef_proxy.present? ? @chef_proxy.chef_environments : []
|
71
|
+
@type = params[:type]
|
72
|
+
render :layout => false
|
73
|
+
end
|
74
|
+
|
75
|
+
protected
|
76
|
+
|
77
|
+
def controller_permission
|
78
|
+
'chef_environments'
|
79
|
+
end
|
80
|
+
|
81
|
+
def action_permission
|
82
|
+
case params[:action]
|
83
|
+
when 'import', 'synchronize'
|
84
|
+
'import'
|
85
|
+
else
|
86
|
+
super
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
@@ -1,14 +1,28 @@
|
|
1
1
|
module ForemanChef
|
2
2
|
module ChefProxyForm
|
3
3
|
def chef_proxy_form(f)
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
4
|
+
# Don't show this if we have no Chef proxies, otherwise always include blank
|
5
|
+
# so the user can choose not to use puppet on this host
|
6
|
+
proxies = SmartProxy.with_taxonomy_scope_override(@location,@organization).with_features('Chef')
|
7
|
+
return if proxies.count == 0
|
8
|
+
javascript('chef_proxy_environment_refresh')
|
9
|
+
|
10
|
+
chef_proxy_form_chef_proxy_select(f, proxies) +
|
11
|
+
chef_proxy_form_chef_environment_select(f, f.object.available_chef_environments)
|
12
|
+
end
|
13
|
+
|
14
|
+
def chef_proxy_form_chef_environment_select(f, environments)
|
15
|
+
select_f(f, :chef_environment_id, environments, :id, :name,
|
16
|
+
{:include_blank => blank_or_inherit_f(f, :chef_environment_id)},
|
17
|
+
{:label => _("Chef environment")})
|
18
|
+
end
|
19
|
+
|
20
|
+
def chef_proxy_form_chef_proxy_select(f, proxies)
|
21
|
+
select_f(f, :chef_proxy_id, proxies, :id, :name,
|
22
|
+
{ :include_blank => blank_or_inherit_f(f, :chef_proxy) },
|
23
|
+
{ :label => _("Chef proxy"),
|
24
|
+
:help_inline => _("Use this foreman proxy as an entry point to your Chef, node will be managed via this proxy"),
|
25
|
+
:data => { :url => environments_for_chef_proxy_foreman_chef_environments_path } })
|
12
26
|
end
|
13
27
|
end
|
14
28
|
end
|
@@ -17,6 +17,13 @@ module ProxyAPI
|
|
17
17
|
end
|
18
18
|
end
|
19
19
|
|
20
|
+
class Environment < ProxyAPI::Resource
|
21
|
+
def initialize(args)
|
22
|
+
@url = "#{args[:url]}/#{PREFIX}/environments"
|
23
|
+
super args
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
20
27
|
def initialize(args)
|
21
28
|
@args = args
|
22
29
|
end
|
@@ -48,6 +55,12 @@ module ProxyAPI
|
|
48
55
|
def delete_client(key)
|
49
56
|
Client.new(@args).send(:delete, key)
|
50
57
|
end
|
58
|
+
|
59
|
+
# List all Chef environments
|
60
|
+
# Returns : Hash representation of environments on chef server
|
61
|
+
def list_environments
|
62
|
+
Environment.new(@args).send(:get)
|
63
|
+
end
|
51
64
|
end
|
52
65
|
end
|
53
66
|
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module ForemanChef
|
2
|
+
module Concerns
|
3
|
+
module HostAndHostgroupExtensions
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
included do
|
7
|
+
belongs_to :chef_proxy, :class_name => "SmartProxy"
|
8
|
+
belongs_to :chef_environment, :class_name => "ForemanChef::Environment"
|
9
|
+
|
10
|
+
attr_accessible :chef_proxy_id, :chef_environment_id
|
11
|
+
end
|
12
|
+
|
13
|
+
def available_chef_environments
|
14
|
+
self.chef_proxy.present? ? self.chef_proxy.chef_environments : []
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module ForemanChef
|
2
|
+
module Concerns
|
3
|
+
module HostExtensions
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
included do
|
7
|
+
alias_method_chain :set_hostgroup_defaults, :chef_attributes
|
8
|
+
end
|
9
|
+
|
10
|
+
def set_hostgroup_defaults_with_chef_attributes
|
11
|
+
set_hostgroup_defaults_without_chef_attributes
|
12
|
+
return unless hostgroup
|
13
|
+
assign_hostgroup_attributes(['chef_proxy_id', 'chef_environment_id'])
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module ForemanChef
|
2
|
+
module Concerns
|
3
|
+
module HostgroupExtensions
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
def inherited_chef_proxy_id
|
7
|
+
read_attribute(:chef_proxy_id) || nested(:chef_proxy_id)
|
8
|
+
end
|
9
|
+
|
10
|
+
def inherited_chef_environment_id
|
11
|
+
read_attribute(:chef_environment_id) || nested(:chef_environment_id)
|
12
|
+
end
|
13
|
+
|
14
|
+
def chef_proxy
|
15
|
+
if ancestry.present?
|
16
|
+
SmartProxy.with_features('Chef').find_by_id(inherited_chef_proxy_id)
|
17
|
+
else
|
18
|
+
super
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def chef_environment
|
23
|
+
if ancestry.present?
|
24
|
+
::ForemanChef::Environment.find_by_id(inherited_chef_environment_id)
|
25
|
+
else
|
26
|
+
super
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module ForemanChef
|
2
|
+
module Concerns
|
3
|
+
module SmartProxyExtensions
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
included do
|
7
|
+
has_many :chef_environments, :class_name => "::ForemanChef::Environment", :foreign_key => 'chef_proxy_id'
|
8
|
+
end
|
9
|
+
|
10
|
+
# create or overwrite instance methods...
|
11
|
+
def show_node(fqdn)
|
12
|
+
reply = ProxyAPI::ForemanChef::ChefProxy.new(:url => url).show_node(fqdn)
|
13
|
+
JSON.parse(reply)
|
14
|
+
rescue RestClient::ResourceNotFound
|
15
|
+
Foreman::Logging.logger('foreman_chef').debug "Node '#{fqdn}' not found"
|
16
|
+
return false
|
17
|
+
end
|
18
|
+
|
19
|
+
def delete_node(fqdn)
|
20
|
+
begin
|
21
|
+
reply = ProxyAPI::ForemanChef::ChefProxy.new(:url => url).delete_node(fqdn)
|
22
|
+
JSON.parse(reply)
|
23
|
+
#rescue RestClient::
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def show_client(fqdn)
|
28
|
+
reply = ProxyAPI::ForemanChef::ChefProxy.new(:url => url).show_client(fqdn)
|
29
|
+
JSON.parse(reply)
|
30
|
+
rescue RestClient::ResourceNotFound
|
31
|
+
Foreman::Logging.logger('foreman_chef').debug "Client '#{fqdn}' not found"
|
32
|
+
return false
|
33
|
+
end
|
34
|
+
|
35
|
+
def delete_client(fqdn)
|
36
|
+
begin
|
37
|
+
reply = ProxyAPI::ForemanChef::ChefProxy.new(:url => url).delete_client(fqdn)
|
38
|
+
JSON.parse(reply)
|
39
|
+
#rescue RestClient::
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module ForemanChef
|
2
|
+
class Environment < ActiveRecord::Base
|
3
|
+
include Authorizable
|
4
|
+
extend FriendlyId
|
5
|
+
friendly_id :name
|
6
|
+
include Parameterizable::ByName
|
7
|
+
|
8
|
+
has_many :hosts, :class_name => '::Host::Managed'
|
9
|
+
has_many :hostgroups, :class_name => '::Hostgroup'
|
10
|
+
belongs_to :chef_proxy, :class_name => '::SmartProxy'
|
11
|
+
|
12
|
+
attr_accessible :name, :description, :chef_proxy_id
|
13
|
+
|
14
|
+
validates :name, :uniqueness => true, :presence => true, :format => { :with => /\A[\w\d\.]+\z/, :message => N_('is alphanumeric and cannot contain spaces') }
|
15
|
+
|
16
|
+
scoped_search :on => :name, :complete_value => true
|
17
|
+
scoped_search :in => :hostgroups, :on => :name, :complete_value => true, :rename => :hostgroup
|
18
|
+
scoped_search :in => :hosts, :on => :name, :complete_value => true, :rename => :host
|
19
|
+
scoped_search :in => :chef_proxy, :on => :name, :complete_value => true, :rename => 'chef_proxy.name'
|
20
|
+
|
21
|
+
class Jail < Safemode::Jail
|
22
|
+
allow :name
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.humanize_class_name(_name = nil)
|
26
|
+
_('Chef environment')
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.permission_name(action)
|
30
|
+
"#{action}_chef_environments"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -75,7 +75,7 @@ module ForemanChef
|
|
75
75
|
end
|
76
76
|
|
77
77
|
def fact_names
|
78
|
-
@fact_names ||= fact_name_class.maximum(:id
|
78
|
+
@fact_names ||= fact_name_class.group(:name).maximum(:id)
|
79
79
|
end
|
80
80
|
|
81
81
|
# if the host does not exists yet, we don't have an host_id to use the fact_values table.
|
@@ -0,0 +1,100 @@
|
|
1
|
+
module ForemanChef
|
2
|
+
class ChefServerImporter
|
3
|
+
def initialize(args = {})
|
4
|
+
@chef_proxy = args[:chef_proxy]
|
5
|
+
@environment = args[:env]
|
6
|
+
@proxy = args[:proxy]
|
7
|
+
@url_arg = args[:url]
|
8
|
+
end
|
9
|
+
|
10
|
+
def proxy
|
11
|
+
if @proxy
|
12
|
+
@proxy
|
13
|
+
elsif @url_arg
|
14
|
+
@proxy = ProxyAPI::ForemanChef::ChefProxy.new(:url => @url_arg)
|
15
|
+
else
|
16
|
+
url = SmartProxy.with_features('Chef').first.try(:url)
|
17
|
+
raise "Can't find a valid Proxy with a Chef feature" if url.blank?
|
18
|
+
@proxy = ProxyAPI::ForemanChef::ChefProxy.new(:url => url)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
attr_writer :proxy
|
22
|
+
|
23
|
+
# return changes hash, currently exists to keep compatibility with importer html
|
24
|
+
def changes
|
25
|
+
changes = {'new' => {}, 'obsolete' => {}, 'updated' => {}}
|
26
|
+
|
27
|
+
if @environment.nil?
|
28
|
+
new_environments.each do |env|
|
29
|
+
changes['new'][env] = {}
|
30
|
+
end
|
31
|
+
|
32
|
+
old_environments.each do |env|
|
33
|
+
changes['obsolete'][env] = {}
|
34
|
+
end
|
35
|
+
else
|
36
|
+
env = @environment
|
37
|
+
changes['new'][env] = {} if new_environments.include?(@environment)
|
38
|
+
changes['obsolete'][env] = {} if old_environments.include?(@environment)
|
39
|
+
end
|
40
|
+
changes
|
41
|
+
end
|
42
|
+
|
43
|
+
# Update the environments based upon the user's selection
|
44
|
+
# +changes+ : Hash with two keys: :new and :obsolete.
|
45
|
+
# changed[:/new|obsolete/] is and Array of Strings
|
46
|
+
# Returns : Array of Strings containing all record errors
|
47
|
+
def obsolete_and_new(changes = { })
|
48
|
+
return if changes.empty?
|
49
|
+
if changes['new'].present?
|
50
|
+
changes['new'].each { |name, _| ForemanChef::Environment.create(:name => name, :chef_proxy_id => @chef_proxy.id) }
|
51
|
+
end
|
52
|
+
if changes['obsolete'].present?
|
53
|
+
changes['obsolete'].each { |name, _| ForemanChef::Environment.where(:chef_proxy_id => @chef_proxy.id).find_by_name(name).destroy }
|
54
|
+
end
|
55
|
+
[]
|
56
|
+
end
|
57
|
+
|
58
|
+
def db_environments
|
59
|
+
@db_environments ||= (ForemanChef::Environment.where(:chef_proxy_id => @chef_proxy.id).pluck('name') - ignored_environments)
|
60
|
+
end
|
61
|
+
|
62
|
+
def actual_environments
|
63
|
+
@actual_environments ||= (fetch_environments_from_proxy.map { |e| e['name'] } - ignored_environments)
|
64
|
+
end
|
65
|
+
|
66
|
+
def new_environments
|
67
|
+
actual_environments - db_environments
|
68
|
+
end
|
69
|
+
|
70
|
+
def old_environments
|
71
|
+
db_environments - actual_environments
|
72
|
+
end
|
73
|
+
|
74
|
+
private
|
75
|
+
|
76
|
+
def fetch_environments_from_proxy
|
77
|
+
JSON.parse(proxy.list_environments)
|
78
|
+
rescue => e
|
79
|
+
Foreman::Logging.exception 'Failed to get environments from proxy', e
|
80
|
+
return []
|
81
|
+
end
|
82
|
+
|
83
|
+
def ignored_environments
|
84
|
+
ignored_file[:ignored] || []
|
85
|
+
end
|
86
|
+
|
87
|
+
def ignored_file
|
88
|
+
return @ignored_file if @ignored_file
|
89
|
+
file = File.join(Rails.root.to_s, "config", "ignored_environments.yml")
|
90
|
+
@ignored_file = File.exist?(file) ? YAML.load_file(file) : {}
|
91
|
+
rescue => e
|
92
|
+
logger.warn "Failed to parse environment ignore file: #{e}"
|
93
|
+
@ignored_file = {}
|
94
|
+
end
|
95
|
+
|
96
|
+
def logger
|
97
|
+
@logger ||= Foreman::Logging.logger('foreman_chef')
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
@@ -43,7 +43,8 @@ EOF
|
|
43
43
|
|
44
44
|
#first run of chef-client
|
45
45
|
echo "First run of chef-client"
|
46
|
-
|
46
|
+
<% chef_args = "-j /tmp/base.json -E #{@host.chef_environment.nil? ? '_default' : @host.chef_environment.name }" -%>
|
47
|
+
/usr/local/bin/chef-client <%= chef_args %> || /usr/bin/chef-client <%= chef_args %>
|
47
48
|
|
48
49
|
echo "Finished, cleaning"
|
49
50
|
rm -f /tmp/base.json
|
@@ -0,0 +1,11 @@
|
|
1
|
+
<%= form_for @environment, :url => (@environment.new_record? ? foreman_chef_environments_path : foreman_chef_environment_path(:id => @environment)) do |f| %>
|
2
|
+
<%= base_errors_for @environment %>
|
3
|
+
|
4
|
+
<%= text_f f, :name %>
|
5
|
+
<%= select_f f, :chef_proxy_id, SmartProxy.with_features('Chef'), :id, :name,
|
6
|
+
{},
|
7
|
+
{ :label => _('Chef proxy'), :help_inline => popover('Chef proxy association', _('When you select this proxy in host or host group form,<br>all associated environments will be loaded into environment select box')) } %>
|
8
|
+
<%= textarea_f f, :description, :rows => 3 %>
|
9
|
+
|
10
|
+
<%= submit_or_cancel f, false, :cancel_path => foreman_chef_environments_path %>
|
11
|
+
<% end %>
|
@@ -0,0 +1,58 @@
|
|
1
|
+
<% title _("Changed environments") %>
|
2
|
+
<%= form_tag synchronize_foreman_chef_environments_path do %>
|
3
|
+
<%= hidden_field_tag :proxy, params[:proxy] %>
|
4
|
+
<h4><%= _("Select the changes you want to realize in Foreman") %></h4>
|
5
|
+
<h6>
|
6
|
+
<%= _("Toggle") %>:
|
7
|
+
<%= link_to_function(icon_text("check", _("New")),
|
8
|
+
"toggleCheckboxesBySelector('.env_select_boxes_new')",
|
9
|
+
:title => _("Check/Uncheck new")) %> |
|
10
|
+
<%= link_to_function(icon_text("check", _("Updated")),
|
11
|
+
"toggleCheckboxesBySelector('.env_select_boxes_updated')",
|
12
|
+
:title => _("Check/Uncheck updated")) %> |
|
13
|
+
<%= link_to_function(icon_text("check", _("Obsolete")),
|
14
|
+
"toggleCheckboxesBySelector('.env_select_boxes_obsolete')",
|
15
|
+
:title => _("Check/Uncheck obsolete")) %>
|
16
|
+
</h6>
|
17
|
+
<table class="table table-striped table-bordered">
|
18
|
+
<thead>
|
19
|
+
<tr>
|
20
|
+
<th class="ca">
|
21
|
+
<%= link_to_function(icon_text("check"),
|
22
|
+
"toggleCheckboxesBySelector('.env_select_boxes')",
|
23
|
+
:title => _("Check/Uncheck all")) %>
|
24
|
+
</th>
|
25
|
+
<th><%= _("Environment") %></th>
|
26
|
+
<th><%= _("Operation") %></th>
|
27
|
+
<th><%= _("Additional data") %></th>
|
28
|
+
</tr>
|
29
|
+
</thead>
|
30
|
+
<tbody>
|
31
|
+
<% for kind in ["new", "obsolete", "updated"] %>
|
32
|
+
<% unless (envs = @changed[kind]).empty? %>
|
33
|
+
<% for env in envs.keys.sort %>
|
34
|
+
<tr>
|
35
|
+
<td>
|
36
|
+
<%= check_box_tag "changed[#{kind}][#{env}]", @changed[kind][env].to_json, false, :class => "env_select_boxes env_select_boxes_#{kind} env_select_boxes_env_#{env}" %>
|
37
|
+
</td>
|
38
|
+
<td>
|
39
|
+
<%= link_to_function("#{env}", "toggleCheckboxesBySelector('.env_select_boxes_env_#{env}')", :title => _("Check/Uncheck all %s changes") % env) %>
|
40
|
+
</td>
|
41
|
+
<td>
|
42
|
+
<%= {"new" => _("Add:"), "obsolete" => _("Remove:"), "updated" => _("Update:")}[kind] %>
|
43
|
+
</td>
|
44
|
+
<td>
|
45
|
+
<% pcs = @changed[kind][env] %>
|
46
|
+
<%= class_update_text pcs, env %>
|
47
|
+
</td>
|
48
|
+
</tr>
|
49
|
+
<% end %>
|
50
|
+
<% end %>
|
51
|
+
<% end %>
|
52
|
+
</tbody>
|
53
|
+
</table>
|
54
|
+
<div>
|
55
|
+
<%= link_to _("Cancel"), send("foreman_chef_environments_path"), :class => "btn btn-default" %>
|
56
|
+
<%= submit_tag _("Update"), :class => "btn btn-primary" %>
|
57
|
+
</div>
|
58
|
+
<% end %>
|
@@ -0,0 +1,35 @@
|
|
1
|
+
<% title _('Chef Environments') %>
|
2
|
+
|
3
|
+
<% title_actions(
|
4
|
+
select_action_button(_('Import'), {}, SmartProxy.with_features('Chef').map do |proxy|
|
5
|
+
display_link_if_authorized(_("Import from %s chef server") % proxy.name,
|
6
|
+
hash_for_import_foreman_chef_environments_path(:proxy => proxy),
|
7
|
+
{:class => 'btn btn-default', :"data-no-turbolink" => true})
|
8
|
+
end.flatten)
|
9
|
+
) %>
|
10
|
+
<% title_actions button_group(display_link_if_authorized(_('New Chef Environment'), hash_for_new_foreman_chef_environment_path)) %>
|
11
|
+
|
12
|
+
<table class="table table-bordered table-striped">
|
13
|
+
<tr>
|
14
|
+
<th><%= sort :name, :as => s_('Environment|Name') %></th>
|
15
|
+
<th><%= sort :host, :as => _('Hosts'), :default => 'DESC' %></th>
|
16
|
+
<th><%= sort :hostgroup, :as => _('Host groups'), :default => 'DESC' %></th>
|
17
|
+
<th><%= sort 'chef_proxy.name', :as => _('Chef proxy'), :default => 'DESC' %></th>
|
18
|
+
<th></th>
|
19
|
+
</tr>
|
20
|
+
<% for chef_environment in @environments %>
|
21
|
+
<tr>
|
22
|
+
<td><%= link_to_if_authorized h(chef_environment.name), hash_for_edit_foreman_chef_environment_path(:id => chef_environment).merge(:auth_object => chef_environment, :authorizer => authorizer) %></td>
|
23
|
+
<td><%= link_to_if_authorized(chef_environment.hosts.count, hash_for_hosts_path(:search => "chef_environment = #{chef_environment}")) %></td>
|
24
|
+
<td><%= link_to_if_authorized(chef_environment.hostgroups.count, hash_for_hostgroups_path(:search => "chef_environment = #{chef_environment}")) %></td>
|
25
|
+
<td><%= link_to_if_authorized(chef_environment.chef_proxy.name, hash_for_smart_proxy_path(chef_environment.chef_proxy)) %></td>
|
26
|
+
<td>
|
27
|
+
<%= action_buttons(display_delete_if_authorized(hash_for_foreman_chef_environment_path(:id => chef_environment).merge(:auth_object => chef_environment, :authorizer => authorizer),
|
28
|
+
:confirm => _('Delete %s?') % chef_environment.name)) %>
|
29
|
+
</td>
|
30
|
+
</tr>
|
31
|
+
<% end %>
|
32
|
+
</table>
|
33
|
+
|
34
|
+
<%= page_entries_info @environments %>
|
35
|
+
<%= will_paginate @environments %>
|
data/config/routes.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
class CreateChefEnvironment < ActiveRecord::Migration
|
2
|
+
def up
|
3
|
+
create_table :foreman_chef_environments do |t|
|
4
|
+
t.string :name, :default => '', :null => false
|
5
|
+
t.text :description, :default => ''
|
6
|
+
t.integer :chef_proxy_id, :null => false
|
7
|
+
t.timestamps
|
8
|
+
end
|
9
|
+
|
10
|
+
add_column :hosts, :chef_environment_id, :integer
|
11
|
+
add_column :hostgroups, :chef_environment_id, :integer
|
12
|
+
end
|
13
|
+
|
14
|
+
def down
|
15
|
+
remove_column :hostgroups, :chef_environment_id
|
16
|
+
remove_column :hosts, :chef_environment_id
|
17
|
+
|
18
|
+
drop_table :foreman_chef_environments
|
19
|
+
end
|
20
|
+
end
|
data/lib/foreman_chef/engine.rb
CHANGED
@@ -12,6 +12,24 @@ module ForemanChef
|
|
12
12
|
end
|
13
13
|
end
|
14
14
|
|
15
|
+
config.autoload_paths += Dir["#{config.root}/app/helpers/concerns"]
|
16
|
+
|
17
|
+
# Precompile any JS or CSS files under app/assets/
|
18
|
+
# If requiring files from each other, list them explicitly here to avoid precompiling the same
|
19
|
+
# content twice.
|
20
|
+
assets_to_precompile =
|
21
|
+
Dir.chdir(root) do
|
22
|
+
Dir['app/assets/javascripts/**/*', 'app/assets/stylesheets/**/*'].map do |f|
|
23
|
+
f.split(File::SEPARATOR, 4).last.gsub(/\.scss\Z/, '')
|
24
|
+
end
|
25
|
+
end
|
26
|
+
initializer 'foreman_chef.assets.precompile' do |app|
|
27
|
+
app.config.assets.precompile += assets_to_precompile
|
28
|
+
end
|
29
|
+
initializer 'foreman_chef.configure_assets', group: :assets do
|
30
|
+
SETTINGS[:foreman_chef] = { assets: { precompile: assets_to_precompile } }
|
31
|
+
end
|
32
|
+
|
15
33
|
initializer 'foreman_chef.load_default_settings', :before => :load_config_initializers do
|
16
34
|
require_dependency File.expand_path('../../../app/models/setting/foreman_chef.rb', __FILE__) if (Setting.table_exists? rescue(false))
|
17
35
|
end
|
@@ -28,8 +46,20 @@ module ForemanChef
|
|
28
46
|
|
29
47
|
initializer 'foreman_chef.register_plugin', :after => :finisher_hook do |app|
|
30
48
|
Foreman::Plugin.register :foreman_chef do
|
31
|
-
requires_foreman '>= 1.
|
49
|
+
requires_foreman '>= 1.11'
|
32
50
|
allowed_template_helpers :chef_bootstrap
|
51
|
+
|
52
|
+
permission :import_chef_environments, { :environments => [:import, :synchronize] }, :resource_type => 'ForemanChef::Environment'
|
53
|
+
permission :view_chef_environments, { :environments => [:index, :environments_for_chef_proxy] }, :resource_type => 'ForemanChef::Environment'
|
54
|
+
permission :edit_chef_environments, { :environments => [:edit, :update] }, :resource_type => 'ForemanChef::Environment'
|
55
|
+
permission :destroy_chef_environments, { :environments => [:destroy] }, :resource_type => 'ForemanChef::Environment'
|
56
|
+
|
57
|
+
divider :top_menu, :caption => N_('Chef'), :last => true, :parent => :configure_menu
|
58
|
+
menu :top_menu, :chef_environments,
|
59
|
+
url_hash: { controller: 'foreman_chef/environments', action: :index },
|
60
|
+
caption: N_('Environments'),
|
61
|
+
parent: :configure_menu,
|
62
|
+
last: true
|
33
63
|
end
|
34
64
|
end
|
35
65
|
|
@@ -44,13 +74,15 @@ module ForemanChef
|
|
44
74
|
|
45
75
|
#Include extensions to models in this config.to_prepare block
|
46
76
|
config.to_prepare do
|
47
|
-
::Host::Managed.send :include, ForemanChef::HostExtensions
|
48
|
-
::Hostgroup.send :include, ForemanChef::HostgroupExtensions
|
49
|
-
::Host::Managed.send :include, ChefProxyAssociation
|
50
|
-
::Hostgroup.send :include, ChefProxyAssociation
|
51
|
-
::SmartProxy.send :include, SmartProxyExtensions
|
52
77
|
::FactImporter.register_fact_importer(:foreman_chef, ForemanChef::FactImporter)
|
53
78
|
::FactParser.register_fact_parser(:foreman_chef, ForemanChef::FactParser)
|
79
|
+
::ConfigReportImporter.register_smart_proxy_feature('Chef')
|
80
|
+
|
81
|
+
::Host::Managed.send :include, ForemanChef::Concerns::HostAndHostgroupExtensions
|
82
|
+
::Hostgroup.send :include, ForemanChef::Concerns::HostAndHostgroupExtensions
|
83
|
+
::Host::Managed.send :include, ForemanChef::Concerns::HostExtensions
|
84
|
+
::Hostgroup.send :include, ForemanChef::Concerns::HostgroupExtensions
|
85
|
+
::SmartProxy.send :include, ForemanChef::Concerns::SmartProxyExtensions
|
54
86
|
::Host::Base.send :include, ForemanChef::Concerns::HostActionSubject
|
55
87
|
::HostsController.send :include, ForemanChef::Concerns::HostsControllerRescuer
|
56
88
|
# Renderer Concern needs to be injected to controllers, ForemanRenderer was already included
|
@@ -63,4 +95,12 @@ module ForemanChef
|
|
63
95
|
::Foreman::Renderer.send :include, ForemanChef::Concerns::Renderer
|
64
96
|
end
|
65
97
|
end
|
98
|
+
|
99
|
+
def self.table_name_prefix
|
100
|
+
"foreman_chef_"
|
101
|
+
end
|
102
|
+
|
103
|
+
def use_relative_model_naming
|
104
|
+
true
|
105
|
+
end
|
66
106
|
end
|
data/lib/foreman_chef/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: foreman_chef
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Marek Hulan
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-03-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: deface
|
@@ -68,28 +68,41 @@ files:
|
|
68
68
|
- LICENSE
|
69
69
|
- README.md
|
70
70
|
- Rakefile
|
71
|
+
- app/assets/javascripts/chef_proxy_environment_refresh.js
|
72
|
+
- app/controllers/foreman_chef/application_controller.rb
|
71
73
|
- app/controllers/foreman_chef/concerns/hosts_controller_rescuer.rb
|
74
|
+
- app/controllers/foreman_chef/environments_controller.rb
|
72
75
|
- app/helpers/foreman_chef/chef_proxy_form.rb
|
73
76
|
- app/lib/actions/foreman_chef/client/destroy.rb
|
74
77
|
- app/lib/actions/foreman_chef/host/destroy.rb
|
75
78
|
- app/lib/proxy_api/foreman_chef/chef_proxy.rb
|
76
|
-
- app/models/foreman_chef/chef_proxy_association.rb
|
77
79
|
- app/models/foreman_chef/concerns/host_action_subject.rb
|
80
|
+
- app/models/foreman_chef/concerns/host_and_hostgroup_extensions.rb
|
81
|
+
- app/models/foreman_chef/concerns/host_extensions.rb
|
82
|
+
- app/models/foreman_chef/concerns/hostgroup_extensions.rb
|
78
83
|
- app/models/foreman_chef/concerns/renderer.rb
|
84
|
+
- app/models/foreman_chef/concerns/smart_proxy_extensions.rb
|
85
|
+
- app/models/foreman_chef/environment.rb
|
79
86
|
- app/models/foreman_chef/fact_importer.rb
|
80
87
|
- app/models/foreman_chef/fact_name.rb
|
81
88
|
- app/models/foreman_chef/fact_parser.rb
|
82
|
-
- app/models/foreman_chef/host_extensions.rb
|
83
|
-
- app/models/foreman_chef/hostgroup_extensions.rb
|
84
|
-
- app/models/foreman_chef/smart_proxy_extensions.rb
|
85
89
|
- app/models/setting/foreman_chef.rb
|
86
90
|
- app/overrides/add_chef_proxy.rb
|
91
|
+
- app/services/foreman_chef/chef_server_importer.rb
|
87
92
|
- app/services/foreman_chef/proxy_exception.rb
|
88
93
|
- app/views/foreman/unattended/snippets/_chef_client_bootstrap.erb
|
89
94
|
- app/views/foreman/unattended/snippets/_chef_client_gem_bootstrap.erb
|
90
95
|
- app/views/foreman/unattended/snippets/_chef_client_omnibus_bootstrap.erb
|
96
|
+
- app/views/foreman_chef/environments/_form.html.erb
|
97
|
+
- app/views/foreman_chef/environments/edit.html.erb
|
98
|
+
- app/views/foreman_chef/environments/environments_for_chef_proxy.html.erb
|
99
|
+
- app/views/foreman_chef/environments/import.html.erb
|
100
|
+
- app/views/foreman_chef/environments/index.html.erb
|
101
|
+
- app/views/foreman_chef/environments/new.html.erb
|
102
|
+
- config/routes.rb
|
91
103
|
- db/migrate/20140220145827_add_chef_proxy_id_to_host.rb
|
92
104
|
- db/migrate/20140513144804_add_chef_proxy_id_to_hostgroup.rb
|
105
|
+
- db/migrate/20150916141657_create_chef_environment.rb
|
93
106
|
- db/seeds.rb
|
94
107
|
- lib/foreman_chef.rb
|
95
108
|
- lib/foreman_chef/engine.rb
|
@@ -1,16 +0,0 @@
|
|
1
|
-
module ForemanChef
|
2
|
-
module HostExtensions
|
3
|
-
extend ActiveSupport::Concern
|
4
|
-
|
5
|
-
included do
|
6
|
-
alias_method_chain :set_hostgroup_defaults, :chef_proxy
|
7
|
-
end
|
8
|
-
|
9
|
-
def set_hostgroup_defaults_with_chef_proxy
|
10
|
-
set_hostgroup_defaults_without_chef_proxy
|
11
|
-
return unless hostgroup
|
12
|
-
assign_hostgroup_attributes(['chef_proxy_id'])
|
13
|
-
end
|
14
|
-
|
15
|
-
end
|
16
|
-
end
|
@@ -1,18 +0,0 @@
|
|
1
|
-
module ForemanChef
|
2
|
-
module HostgroupExtensions
|
3
|
-
extend ActiveSupport::Concern
|
4
|
-
|
5
|
-
def inherited_chef_proxy_id
|
6
|
-
read_attribute(:chef_proxy_id) || nested(:chef_proxy_id)
|
7
|
-
end
|
8
|
-
|
9
|
-
def chef_proxy
|
10
|
-
if ancestry.present?
|
11
|
-
SmartProxy.with_features('Chef').find_by_id(inherited_chef_proxy_id)
|
12
|
-
else
|
13
|
-
super
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
end
|
18
|
-
end
|
@@ -1,38 +0,0 @@
|
|
1
|
-
module ForemanChef
|
2
|
-
module SmartProxyExtensions
|
3
|
-
extend ActiveSupport::Concern
|
4
|
-
|
5
|
-
# create or overwrite instance methods...
|
6
|
-
def show_node(fqdn)
|
7
|
-
reply = ProxyAPI::ForemanChef::ChefProxy.new(:url => url).show_node(fqdn)
|
8
|
-
JSON.parse(reply)
|
9
|
-
rescue RestClient::ResourceNotFound
|
10
|
-
Foreman::Logging.logger('foreman_chef').debug "Node '#{fqdn}' not found"
|
11
|
-
return false
|
12
|
-
end
|
13
|
-
|
14
|
-
def delete_node(fqdn)
|
15
|
-
begin
|
16
|
-
reply = ProxyAPI::ForemanChef::ChefProxy.new(:url => url).delete_node(fqdn)
|
17
|
-
JSON.parse(reply)
|
18
|
-
#rescue RestClient::
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
def show_client(fqdn)
|
23
|
-
reply = ProxyAPI::ForemanChef::ChefProxy.new(:url => url).show_client(fqdn)
|
24
|
-
JSON.parse(reply)
|
25
|
-
rescue RestClient::ResourceNotFound
|
26
|
-
Foreman::Logging.logger('foreman_chef').debug "Client '#{fqdn}' not found"
|
27
|
-
return false
|
28
|
-
end
|
29
|
-
|
30
|
-
def delete_client(fqdn)
|
31
|
-
begin
|
32
|
-
reply = ProxyAPI::ForemanChef::ChefProxy.new(:url => url).delete_client(fqdn)
|
33
|
-
JSON.parse(reply)
|
34
|
-
#rescue RestClient::
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|