foreman_chef 0.2.2 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|