foreman_orchestration 0.0.1
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.
- data/LICENSE +619 -0
- data/README.md +38 -0
- data/Rakefile +47 -0
- data/app/assets/javascripts/foreman_orchestration/stacks.js +129 -0
- data/app/assets/stylesheets/foreman_orchestration/stacks.css.scss +3 -0
- data/app/assets/stylesheets/foreman_orchestration/templates.css.scss +4 -0
- data/app/controllers/concerns/foreman_orchestration/compute_resources_controller_extensions.rb +17 -0
- data/app/controllers/foreman_orchestration/stack_templates_controller.rb +57 -0
- data/app/controllers/foreman_orchestration/stacks_controller.rb +75 -0
- data/app/controllers/foreman_orchestration/tenants_controller.rb +26 -0
- data/app/helpers/concerns/foreman_orchestration/layout_helper_extensions.rb +22 -0
- data/app/models/concerns/foreman_orchestration/openstack_extensions.rb +51 -0
- data/app/models/foreman_orchestration/orchestration_client.rb +51 -0
- data/app/models/foreman_orchestration/stack.rb +91 -0
- data/app/models/foreman_orchestration/stack_template.rb +31 -0
- data/app/views/dashboard/_foreman_orchestration_widget.html.erb +2 -0
- data/app/views/foreman_orchestration/stack_templates/_form.html.erb +8 -0
- data/app/views/foreman_orchestration/stack_templates/_with_params.html.erb +31 -0
- data/app/views/foreman_orchestration/stack_templates/edit.html.erb +3 -0
- data/app/views/foreman_orchestration/stack_templates/index.html.erb +27 -0
- data/app/views/foreman_orchestration/stack_templates/new.html.erb +3 -0
- data/app/views/foreman_orchestration/stacks/_form.html.erb +40 -0
- data/app/views/foreman_orchestration/stacks/all.html.erb +40 -0
- data/app/views/foreman_orchestration/stacks/index.html.erb +49 -0
- data/app/views/foreman_orchestration/stacks/new.html.erb +6 -0
- data/app/views/foreman_orchestration/tenants/_for_select.html.erb +21 -0
- data/config/routes.rb +30 -0
- data/db/migrate/20151112145323_create_stack_templates.rb +10 -0
- data/lib/foreman_orchestration.rb +4 -0
- data/lib/foreman_orchestration/engine.rb +71 -0
- data/lib/foreman_orchestration/version.rb +3 -0
- data/lib/tasks/foreman_orchestration_tasks.rake +39 -0
- data/locale/Makefile +62 -0
- data/locale/en/foreman_orchestration.po +19 -0
- data/locale/foreman_orchestration.pot +19 -0
- data/locale/gemspec.rb +2 -0
- data/test/factories/foreman_orchestration_factories.rb +5 -0
- data/test/test_plugin_helper.rb +6 -0
- data/test/unit/foreman_orchestration_test.rb +11 -0
- metadata +137 -0
data/README.md
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
# ForemanOrchestration
|
2
|
+
|
3
|
+
*Introdction here*
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
See [How_to_Install_a_Plugin](http://projects.theforeman.org/projects/foreman/wiki/How_to_Install_a_Plugin)
|
8
|
+
for how to install Foreman plugins
|
9
|
+
|
10
|
+
## Usage
|
11
|
+
|
12
|
+
*Usage here*
|
13
|
+
|
14
|
+
## TODO
|
15
|
+
|
16
|
+
*Todo list here*
|
17
|
+
|
18
|
+
## Contributing
|
19
|
+
|
20
|
+
Fork and send a Pull Request. Thanks!
|
21
|
+
|
22
|
+
## Copyright
|
23
|
+
|
24
|
+
Copyright (c) *year* *your name*
|
25
|
+
|
26
|
+
This program is free software: you can redistribute it and/or modify
|
27
|
+
it under the terms of the GNU General Public License as published by
|
28
|
+
the Free Software Foundation, either version 3 of the License, or
|
29
|
+
(at your option) any later version.
|
30
|
+
|
31
|
+
This program is distributed in the hope that it will be useful,
|
32
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
33
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
34
|
+
GNU General Public License for more details.
|
35
|
+
|
36
|
+
You should have received a copy of the GNU General Public License
|
37
|
+
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
38
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
#!/usr/bin/env rake
|
2
|
+
begin
|
3
|
+
require 'bundler/setup'
|
4
|
+
rescue LoadError
|
5
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
6
|
+
end
|
7
|
+
begin
|
8
|
+
require 'rdoc/task'
|
9
|
+
rescue LoadError
|
10
|
+
require 'rdoc/rdoc'
|
11
|
+
require 'rake/rdoctask'
|
12
|
+
RDoc::Task = Rake::RDocTask
|
13
|
+
end
|
14
|
+
|
15
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
16
|
+
rdoc.rdoc_dir = 'rdoc'
|
17
|
+
rdoc.title = 'ForemanOrchestration'
|
18
|
+
rdoc.options << '--line-numbers'
|
19
|
+
rdoc.rdoc_files.include('README.rdoc')
|
20
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
21
|
+
end
|
22
|
+
|
23
|
+
APP_RAKEFILE = File.expand_path('../test/dummy/Rakefile', __FILE__)
|
24
|
+
|
25
|
+
Bundler::GemHelper.install_tasks
|
26
|
+
|
27
|
+
require 'rake/testtask'
|
28
|
+
|
29
|
+
Rake::TestTask.new(:test) do |t|
|
30
|
+
t.libs << 'lib'
|
31
|
+
t.libs << 'test'
|
32
|
+
t.pattern = 'test/**/*_test.rb'
|
33
|
+
t.verbose = false
|
34
|
+
end
|
35
|
+
|
36
|
+
task default: :test
|
37
|
+
|
38
|
+
begin
|
39
|
+
require 'rubocop/rake_task'
|
40
|
+
RuboCop::RakeTask.new
|
41
|
+
rescue => _
|
42
|
+
puts 'Rubocop not loaded.'
|
43
|
+
end
|
44
|
+
|
45
|
+
task :default do
|
46
|
+
Rake::Task['rubocop'].execute
|
47
|
+
end
|
@@ -0,0 +1,129 @@
|
|
1
|
+
function updateDefaultEntityButton(selector, defaultValue, currentValue) {
|
2
|
+
var $button = $(selector);
|
3
|
+
if (currentValue == defaultValue || currentValue == '') {
|
4
|
+
$button.prop('disabled', true);
|
5
|
+
} else {
|
6
|
+
$button.prop('disabled', false);
|
7
|
+
}
|
8
|
+
}
|
9
|
+
|
10
|
+
function stacksComputeResourceSelected(item) {
|
11
|
+
var $item = $(item);
|
12
|
+
var computeResource = $item.val();
|
13
|
+
if (computeResource === '') {
|
14
|
+
return false;
|
15
|
+
} else {
|
16
|
+
$item.indicator_show();
|
17
|
+
var url = $item.data('url').replace(':id', computeResource);
|
18
|
+
var defaultValue = $item.data('default-value');
|
19
|
+
var $tenants = $('#tenants-list');
|
20
|
+
$('#stacks-list').empty();
|
21
|
+
$tenants.empty();
|
22
|
+
$tenants.load(url, function () {
|
23
|
+
$tenants.find('select').select2({allowClear: true});
|
24
|
+
$item.indicator_hide();
|
25
|
+
updateDefaultEntityButton('#set-default-compute-resource', defaultValue, computeResource);
|
26
|
+
});
|
27
|
+
}
|
28
|
+
}
|
29
|
+
|
30
|
+
function stacksNewComputeResourceSelected(item) {
|
31
|
+
var $item = $(item);
|
32
|
+
var computeResource = $item.val();
|
33
|
+
if (computeResource === '') {
|
34
|
+
return false;
|
35
|
+
} else {
|
36
|
+
$item.indicator_show();
|
37
|
+
var url = $item.data('url');
|
38
|
+
var params = $.param({compute_resource_id: computeResource});
|
39
|
+
var $main = $('#main-stack-parameters');
|
40
|
+
$main.hide();
|
41
|
+
var $container = $('#tenants-list-container');
|
42
|
+
$container.empty();
|
43
|
+
$container.load(url + ' #tenants-list', params, function () {
|
44
|
+
$container.find('select').select2({allowClear: true});
|
45
|
+
$main.show();
|
46
|
+
$item.indicator_hide();
|
47
|
+
});
|
48
|
+
}
|
49
|
+
}
|
50
|
+
|
51
|
+
function stacksTenantSelected(item) {
|
52
|
+
var $item = $(item);
|
53
|
+
var tenant = $item.val();
|
54
|
+
if (tenant === '') {
|
55
|
+
return false;
|
56
|
+
} else {
|
57
|
+
$item.indicator_show();
|
58
|
+
var url = $item.data('url').replace(':id', tenant);
|
59
|
+
var defaultValue = $item.data('default-value');
|
60
|
+
var $stacks = $('#stacks-list');
|
61
|
+
$stacks.empty();
|
62
|
+
$stacks.load(url, function () {
|
63
|
+
$item.indicator_hide();
|
64
|
+
updateDefaultEntityButton('#set-default-tenant', defaultValue, tenant);
|
65
|
+
});
|
66
|
+
}
|
67
|
+
}
|
68
|
+
|
69
|
+
function stacksLoadTemplateWithParams(item) {
|
70
|
+
var $item = $(item);
|
71
|
+
var templateId = $item.val();
|
72
|
+
if (templateId === '') {
|
73
|
+
return false;
|
74
|
+
} else {
|
75
|
+
$item.indicator_show();
|
76
|
+
var url = $item.data('url').replace(':template_id', templateId);
|
77
|
+
var params = $.param({template_id: templateId});
|
78
|
+
var $container = $('#template-with-params');
|
79
|
+
$container.hide();
|
80
|
+
$container.load(url, params, function () {
|
81
|
+
$container.show();
|
82
|
+
$item.indicator_hide();
|
83
|
+
});
|
84
|
+
}
|
85
|
+
}
|
86
|
+
|
87
|
+
function setDefaultComputeResource(button) {
|
88
|
+
var $button = $(button);
|
89
|
+
var $select = $('#compute_resource');
|
90
|
+
var computeResourceId = $select.val();
|
91
|
+
if (!$button.data('processing') && computeResourceId !== '') {
|
92
|
+
$button.data('processing', true);
|
93
|
+
var url = $button.data('url').replace(':id', computeResourceId);
|
94
|
+
var oldText = $button.text();
|
95
|
+
$button.text($button.data('disable-with'));
|
96
|
+
$.post(url).done(function () {
|
97
|
+
$button.prop('disabled', true);
|
98
|
+
$select.data('default-value', Number(computeResourceId));
|
99
|
+
}).fail(function () {
|
100
|
+
alert('Something went wrong');
|
101
|
+
}).always(function () {
|
102
|
+
$button.text(oldText);
|
103
|
+
$button.data('processing', false);
|
104
|
+
});
|
105
|
+
}
|
106
|
+
return false;
|
107
|
+
}
|
108
|
+
|
109
|
+
function setDefaultTenant(button) {
|
110
|
+
var $button = $(button);
|
111
|
+
var $select = $('#tenant');
|
112
|
+
var tenantId = $select.val();
|
113
|
+
if (!$button.data('processing') && tenantId !== '') {
|
114
|
+
$button.data('processing', true);
|
115
|
+
var url = $button.data('url').replace(':id', tenantId);
|
116
|
+
var oldText = $button.text();
|
117
|
+
$button.text($button.data('disable-with'));
|
118
|
+
$.post(url).done(function () {
|
119
|
+
$button.prop('disabled', true);
|
120
|
+
$select.data('default-value', tenantId);
|
121
|
+
}).fail(function () {
|
122
|
+
alert('Something went wrong');
|
123
|
+
}).always(function () {
|
124
|
+
$button.text(oldText);
|
125
|
+
$button.data('processing', false);
|
126
|
+
});
|
127
|
+
}
|
128
|
+
return false;
|
129
|
+
}
|
data/app/controllers/concerns/foreman_orchestration/compute_resources_controller_extensions.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
module ForemanOrchestration
|
2
|
+
module ComputeResourcesControllerExtensions
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
included do
|
6
|
+
before_filter :ajax_request, only: [:default]
|
7
|
+
end
|
8
|
+
|
9
|
+
def default
|
10
|
+
Foreman::Model::Openstack.find(params[:id])
|
11
|
+
.mark_as_default
|
12
|
+
respond_to do |format|
|
13
|
+
format.json { render :json => {}, :status => :ok }
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
module ForemanOrchestration
|
2
|
+
class StackTemplatesController < ::ApplicationController
|
3
|
+
before_filter :find_resource, only: [:edit, :update, :destroy, :with_params]
|
4
|
+
|
5
|
+
def index
|
6
|
+
@templates = StackTemplate.order(:name).all
|
7
|
+
end
|
8
|
+
|
9
|
+
def new
|
10
|
+
@template = StackTemplate.new
|
11
|
+
end
|
12
|
+
|
13
|
+
# TODO: there is an API for template validation:
|
14
|
+
# http://developer.openstack.org/api-ref-orchestration-v1.html#template_validate
|
15
|
+
# Maybe we can use it here?
|
16
|
+
def create
|
17
|
+
@template = StackTemplate.new(template_params)
|
18
|
+
if @template.save
|
19
|
+
process_success object: @template
|
20
|
+
else
|
21
|
+
process_error object: @template
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def update
|
26
|
+
if @template.update_attributes(template_params)
|
27
|
+
process_success object: @template
|
28
|
+
else
|
29
|
+
process_error object: @template
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def destroy
|
34
|
+
if @template.destroy
|
35
|
+
process_success object: @template
|
36
|
+
else
|
37
|
+
process_error object: @template
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# ajax methods
|
42
|
+
def with_params
|
43
|
+
render partial: 'with_params', locals: {template: @template, parameters: {}}
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
def template_params
|
49
|
+
params.fetch(:foreman_orchestration_stack_template)
|
50
|
+
.slice(:name, :template)
|
51
|
+
end
|
52
|
+
|
53
|
+
def find_resource
|
54
|
+
@template = StackTemplate.find(params[:id])
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
module ForemanOrchestration
|
2
|
+
class StacksController < ::ApplicationController
|
3
|
+
before_filter :load_compute_resources, only: [:all, :new]
|
4
|
+
|
5
|
+
def all
|
6
|
+
@compute_resource = find_default_compute_resource
|
7
|
+
if @compute_resource
|
8
|
+
@tenants = @compute_resource.orchestration_clients
|
9
|
+
@tenant = @compute_resource.default_tenant
|
10
|
+
@stacks = @tenant.stacks if @tenant
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def index
|
15
|
+
@compute_resource = find_compute_resource
|
16
|
+
@tenant = @compute_resource.orchestration_client_for(params[:tenant_id])
|
17
|
+
@stacks = @tenant.stacks
|
18
|
+
render layout: !ajax?
|
19
|
+
end
|
20
|
+
|
21
|
+
def new
|
22
|
+
@stack = Stack.new(new_stack_params)
|
23
|
+
end
|
24
|
+
|
25
|
+
def create
|
26
|
+
@stack = Stack.new(create_stack_params)
|
27
|
+
if @stack.save
|
28
|
+
flash[:notice] = "Stack '#{@stack.name}' is being created now"
|
29
|
+
redirect_to all_stacks_path
|
30
|
+
else
|
31
|
+
load_compute_resources
|
32
|
+
process_error object: @stack
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def destroy
|
37
|
+
@stack = Stack.new(compute_resource_id: params[:compute_resource_id],
|
38
|
+
tenant_id: params[:tenant_id],
|
39
|
+
id: params[:id])
|
40
|
+
@stack.destroy
|
41
|
+
redirect_to all_stacks_path, notice: 'Stack is being deleted now'
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
def new_stack_params
|
47
|
+
if params[:compute_resource_id] && params[:tenant_id]
|
48
|
+
params.slice(:compute_resource_id, :tenant_id)
|
49
|
+
else
|
50
|
+
compute_resource = find_default_compute_resource
|
51
|
+
{
|
52
|
+
compute_resource: compute_resource,
|
53
|
+
tenant: compute_resource.default_tenant
|
54
|
+
}
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def create_stack_params
|
59
|
+
params.fetch(:foreman_orchestration_stack)
|
60
|
+
.slice(:compute_resource_id, :tenant_id, :name, :template_id, :parameters)
|
61
|
+
end
|
62
|
+
|
63
|
+
def load_compute_resources
|
64
|
+
@compute_resources = ::Foreman::Model::Openstack.all
|
65
|
+
end
|
66
|
+
|
67
|
+
def find_default_compute_resource
|
68
|
+
@compute_resources.find(&:is_default) || @compute_resources.first
|
69
|
+
end
|
70
|
+
|
71
|
+
def find_compute_resource
|
72
|
+
Foreman::Model::Openstack.find(params[:compute_resource_id])
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module ForemanOrchestration
|
2
|
+
class TenantsController < ::ApplicationController
|
3
|
+
before_filter :ajax_request, only: [:default]
|
4
|
+
before_filter :find_compute_resource, only: [:for_select, :default]
|
5
|
+
|
6
|
+
def for_select
|
7
|
+
@tenants = @compute_resource.tenants
|
8
|
+
render partial: 'for_select'
|
9
|
+
end
|
10
|
+
|
11
|
+
def default
|
12
|
+
tenant = @compute_resource.orchestration_client_for(params[:id])
|
13
|
+
@compute_resource.default_tenant_id = tenant.id
|
14
|
+
@compute_resource.save!
|
15
|
+
respond_to do |format|
|
16
|
+
format.json { render :json => {}, :status => :ok }
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def find_compute_resource
|
23
|
+
@compute_resource = ::Foreman::Model::Openstack.find(params[:compute_resource_id])
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module ForemanOrchestration
|
2
|
+
module LayoutHelperExtensions
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
def selectable_tag(name, options_tags = nil, options = {})
|
6
|
+
content_tag(:div, :class => 'clearfix') do
|
7
|
+
content_tag(:div, :class => 'form-group') do
|
8
|
+
label = label_tag(name, options.delete(:label), :class => 'col-md-3 control-label')
|
9
|
+
help = help_inline(:indicator, '')
|
10
|
+
add_help_to_label('col-md-4', label, help) do
|
11
|
+
addClass options, 'form-control'
|
12
|
+
select_tag name, options_tags, options
|
13
|
+
end + if block_given?
|
14
|
+
content_tag(:div, :class => 'col-md-2') do
|
15
|
+
yield
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module ForemanOrchestration
|
2
|
+
module OpenstackExtensions
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
def orchestration_clients
|
6
|
+
# TODO: select only enabled: true tenants?
|
7
|
+
@orchestration_clients ||= tenants.map do |t|
|
8
|
+
create_orchestration_client(t)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def orchestration_client_for(tenant_id)
|
13
|
+
orchestration_clients.find { |client| client.id == tenant_id }
|
14
|
+
end
|
15
|
+
|
16
|
+
def create_orchestration_client(tenant)
|
17
|
+
ForemanOrchestration::OrchestrationClient.new(tenant, fog_credentials)
|
18
|
+
end
|
19
|
+
|
20
|
+
def is_default
|
21
|
+
attrs[:is_default]
|
22
|
+
end
|
23
|
+
|
24
|
+
def mark_as_default
|
25
|
+
ActiveRecord::Base.transaction do
|
26
|
+
self.class.all.each do |record|
|
27
|
+
record.attrs[:is_default] = false
|
28
|
+
record.save!
|
29
|
+
end
|
30
|
+
attrs[:is_default] = true
|
31
|
+
save!
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def default_tenant_id
|
36
|
+
attrs[:default_tenant_id]
|
37
|
+
end
|
38
|
+
|
39
|
+
def default_tenant_id=(tenant_id)
|
40
|
+
attrs[:default_tenant_id] = tenant_id
|
41
|
+
end
|
42
|
+
|
43
|
+
def default_tenant
|
44
|
+
if default_tenant_id
|
45
|
+
orchestration_client_for(default_tenant_id)
|
46
|
+
else
|
47
|
+
orchestration_clients.first
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|