foreman_acd 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE +619 -0
- data/README.md +87 -0
- data/Rakefile +49 -0
- data/app/assets/javascripts/foreman_acd/acd_dummy.js +3 -0
- data/app/controllers/foreman_acd/api/v2/app_definitions_controller.rb +55 -0
- data/app/controllers/foreman_acd/api/v2/base_controller.rb +16 -0
- data/app/controllers/foreman_acd/app_definitions_controller.rb +53 -0
- data/app/controllers/foreman_acd/app_instances_controller.rb +158 -0
- data/app/controllers/foreman_acd/application_controller.rb +10 -0
- data/app/controllers/foreman_acd/concerns/app_definition_parameters.rb +23 -0
- data/app/controllers/foreman_acd/concerns/app_instance_parameters.rb +23 -0
- data/app/controllers/ui_acd_controller.rb +30 -0
- data/app/models/foreman_acd/app_definition.rb +23 -0
- data/app/models/foreman_acd/app_instance.rb +21 -0
- data/app/views/foreman_acd/app_definitions/_form.html.erb +40 -0
- data/app/views/foreman_acd/app_definitions/edit.html.erb +11 -0
- data/app/views/foreman_acd/app_definitions/index.html.erb +27 -0
- data/app/views/foreman_acd/app_definitions/new.html.erb +10 -0
- data/app/views/foreman_acd/app_instances/_form.html.erb +46 -0
- data/app/views/foreman_acd/app_instances/edit.html.erb +11 -0
- data/app/views/foreman_acd/app_instances/index.html.erb +30 -0
- data/app/views/foreman_acd/app_instances/new.html.erb +11 -0
- data/app/views/ui_acd/app.json.rabl +9 -0
- data/app/views/ui_acd/app_definition.json.rabl +5 -0
- data/app/views/ui_acd/computeprofile.json.rabl +4 -0
- data/app/views/ui_acd/domain.json.rabl +4 -0
- data/app/views/ui_acd/environment.json.rabl +4 -0
- data/app/views/ui_acd/fdata.json.rabl +24 -0
- data/app/views/ui_acd/lifecycle_environment.json.rabl +4 -0
- data/app/views/ui_acd/ptable.json.rabl +4 -0
- data/config/routes.rb +24 -0
- data/db/migrate/20190610202252_create_app_definitions.rb +19 -0
- data/db/migrate/20190625140305_create_app_instances.rb +19 -0
- data/lib/foreman_acd/engine.rb +43 -0
- data/lib/foreman_acd/plugin.rb +80 -0
- data/lib/foreman_acd/version.rb +5 -0
- data/lib/foreman_acd.rb +7 -0
- data/lib/tasks/foreman_acd_tasks.rake +47 -0
- data/locale/Makefile +60 -0
- data/locale/en/foreman_acd.po +19 -0
- data/locale/foreman_acd.pot +19 -0
- data/locale/gemspec.rb +2 -0
- data/package.json +121 -0
- data/test/controllers/app_definitions_controller_test.rb +24 -0
- data/test/controllers/app_instances_controller_test.rb +24 -0
- data/test/controllers/ui_acd_controller_test.rb +26 -0
- data/test/factories/foreman_acd_factories.rb +17 -0
- data/test/models/app_definition_test.rb +11 -0
- data/test/models/app_instance_test.rb +8 -0
- data/test/test_plugin_helper.rb +8 -0
- data/webpack/__mocks__/foremanReact/components/common/forms/Select.js +2 -0
- data/webpack/components/ParameterSelection/ParameterSelection.js +468 -0
- data/webpack/components/ParameterSelection/ParameterSelection.scss +3 -0
- data/webpack/components/ParameterSelection/ParameterSelectionActions.js +294 -0
- data/webpack/components/ParameterSelection/ParameterSelectionConstants.js +31 -0
- data/webpack/components/ParameterSelection/ParameterSelectionHelper.js +52 -0
- data/webpack/components/ParameterSelection/ParameterSelectionReducer.js +175 -0
- data/webpack/components/ParameterSelection/ParameterSelectionSelectors.js +15 -0
- data/webpack/components/ParameterSelection/__fixtures__/parameterSelection.fixtures.js +162 -0
- data/webpack/components/ParameterSelection/__fixtures__/parameterSelectionData_1.fixtures.js +194 -0
- data/webpack/components/ParameterSelection/__fixtures__/parameterSelectionReducer.fixtures.js +127 -0
- data/webpack/components/ParameterSelection/__tests__/ParameterSelection.test.js +48 -0
- data/webpack/components/ParameterSelection/__tests__/ParameterSelectionReducer.test.js +150 -0
- data/webpack/components/ParameterSelection/__tests__/ParameterSelectionSelectors.test.js +47 -0
- data/webpack/components/ParameterSelection/__tests__/__snapshots__/ParameterSelection.test.js.snap +454 -0
- data/webpack/components/ParameterSelection/__tests__/__snapshots__/ParameterSelectionReducer.test.js.snap +2265 -0
- data/webpack/components/ParameterSelection/__tests__/__snapshots__/ParameterSelectionSelectors.test.js.snap +209 -0
- data/webpack/components/ParameterSelection/index.js +39 -0
- data/webpack/index.js +8 -0
- data/webpack/reducer.js +7 -0
- data/webpack/test_setup.js +11 -0
- metadata +206 -0
data/README.md
ADDED
@@ -0,0 +1,87 @@
|
|
1
|
+
# Foreman Application Centric Deployment
|
2
|
+
|
3
|
+
A plugin to bring an user self service portal and application centric deployment to Foreman.
|
4
|
+
|
5
|
+
# Description
|
6
|
+
|
7
|
+
The target of this plugin is, to deploy whole applications which include multiple hosts
|
8
|
+
and an Ansible Playbook / saltstack state to configure the application.
|
9
|
+
|
10
|
+
This plugin follows the idea of different user types working together.
|
11
|
+
The administrative user creates application definitions including multiple servers and
|
12
|
+
configuration management items (Ansible Playbook, saltstack state).
|
13
|
+
The user can create and deploy new application instances with an easy to use self service portal.
|
14
|
+
|
15
|
+
*Example Application Definition:*
|
16
|
+
To run a complex web application, a loadbalancer is required.
|
17
|
+
The loadbalancer routes the requests to 3 different web servers.
|
18
|
+
The web servers are using a database which is in high availability mode on 2 hosts.
|
19
|
+
=> 6 hosts are required.
|
20
|
+
|
21
|
+
This plugin aims to setup all 6 hosts and to deploy the application.
|
22
|
+
|
23
|
+
# Current State
|
24
|
+
In the current state the plugin can be used to provide an easy to use self service user portal
|
25
|
+
to deploy new servers.
|
26
|
+
|
27
|
+
# Road Map
|
28
|
+
- Self service portal for single host deployments (current version)
|
29
|
+
- Add application deployment with single host requirements
|
30
|
+
- Add application deployment with multi host requirements
|
31
|
+
|
32
|
+
## WARNING
|
33
|
+
|
34
|
+
This plugin is in development.
|
35
|
+
In the current state, a self service portal to deploy single servers can be created.
|
36
|
+
|
37
|
+
## Installation
|
38
|
+
|
39
|
+
See [How_to_Install_a_Plugin](http://projects.theforeman.org/projects/foreman/wiki/How_to_Install_a_Plugin)
|
40
|
+
for how to install Foreman plugins
|
41
|
+
|
42
|
+
ATM, Katello plugin need to exist, too.
|
43
|
+
|
44
|
+
## Usage
|
45
|
+
|
46
|
+
Application Definition (Admin)
|
47
|
+
* Create an Application Definition (Configure -> Application Definition) first
|
48
|
+
* Select the Hostgroup you want to use.
|
49
|
+
* Specifiy the values, a user could overwrite.
|
50
|
+
(you can set a default value, if you want)
|
51
|
+
|
52
|
+
Application Instance (User)
|
53
|
+
* Create an Application Instance (Configure -> Application Instrane)
|
54
|
+
* Select the Application Definition which should be used
|
55
|
+
* Set the values.
|
56
|
+
Remember, all parameters need to have a value.
|
57
|
+
* Save the Application Instance
|
58
|
+
* To Deploy the host, select "Deploy" in the Action selection dropdown field
|
59
|
+
on the Application Instance index site
|
60
|
+
|
61
|
+
## TODO
|
62
|
+
|
63
|
+
- Add ansible playbook / saltstack support to configure the application
|
64
|
+
- Multi-host support
|
65
|
+
- Add validation to the different parameter types
|
66
|
+
|
67
|
+
## Contributing
|
68
|
+
|
69
|
+
Fork and send a Pull Request. Thanks!
|
70
|
+
|
71
|
+
## Copyright
|
72
|
+
|
73
|
+
Copyright (c) 2019 ATIX AG
|
74
|
+
|
75
|
+
This program is free software: you can redistribute it and/or modify
|
76
|
+
it under the terms of the GNU General Public License as published by
|
77
|
+
the Free Software Foundation, either version 3 of the License, or
|
78
|
+
(at your option) any later version.
|
79
|
+
|
80
|
+
This program is distributed in the hope that it will be useful,
|
81
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
82
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
83
|
+
GNU General Public License for more details.
|
84
|
+
|
85
|
+
You should have received a copy of the GNU General Public License
|
86
|
+
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
87
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
#!/usr/bin/env rake
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'bundler/setup'
|
6
|
+
rescue LoadError
|
7
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
8
|
+
end
|
9
|
+
begin
|
10
|
+
require 'rdoc/task'
|
11
|
+
rescue LoadError
|
12
|
+
require 'rdoc/rdoc'
|
13
|
+
require 'rake/rdoctask'
|
14
|
+
RDoc::Task = Rake::RDocTask
|
15
|
+
end
|
16
|
+
|
17
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
18
|
+
rdoc.rdoc_dir = 'rdoc'
|
19
|
+
rdoc.title = 'ForemanAppcendep'
|
20
|
+
rdoc.options << '--line-numbers'
|
21
|
+
rdoc.rdoc_files.include('README.rdoc')
|
22
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
23
|
+
end
|
24
|
+
|
25
|
+
APP_RAKEFILE = File.expand_path('test/dummy/Rakefile', __dir__)
|
26
|
+
|
27
|
+
Bundler::GemHelper.install_tasks
|
28
|
+
|
29
|
+
require 'rake/testtask'
|
30
|
+
|
31
|
+
Rake::TestTask.new(:test) do |t|
|
32
|
+
t.libs << 'lib'
|
33
|
+
t.libs << 'test'
|
34
|
+
t.pattern = 'test/**/*_test.rb'
|
35
|
+
t.verbose = false
|
36
|
+
end
|
37
|
+
|
38
|
+
task :default => :test
|
39
|
+
|
40
|
+
begin
|
41
|
+
require 'rubocop/rake_task'
|
42
|
+
RuboCop::RakeTask.new
|
43
|
+
rescue StandardError => _e
|
44
|
+
puts 'Rubocop not loaded.'
|
45
|
+
end
|
46
|
+
|
47
|
+
task :default do
|
48
|
+
Rake::Task['rubocop'].execute
|
49
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ForemanAcd
|
4
|
+
module Api
|
5
|
+
module V2
|
6
|
+
# API controller for App Definitions
|
7
|
+
class AppDefinitionsController < ::ForemanAcd::Api::V2::BaseController
|
8
|
+
include ::ForemanAcd::Concerns::AppDefinitionParameters
|
9
|
+
|
10
|
+
before_action :find_resource, :except => [:index, :create]
|
11
|
+
|
12
|
+
api :GET, '/app_definitions/:id', N_('Show application definition')
|
13
|
+
param :id, :identifier, :required => true
|
14
|
+
def show; end
|
15
|
+
|
16
|
+
api :GET, '/app_definitions', N_('List application definitions')
|
17
|
+
param_group :search_and_pagination, ::Api::V2::BaseController
|
18
|
+
add_scoped_search_description_for(AppDefinition)
|
19
|
+
def index
|
20
|
+
@app_definitions = resource_scope_for_index
|
21
|
+
end
|
22
|
+
|
23
|
+
def_param_group :app_definition do
|
24
|
+
param :app_definition, Hash, :required => true, :action_aware => true do
|
25
|
+
param :name, String, :required => true
|
26
|
+
param :description, String, :required => true
|
27
|
+
param :hostgroup_id, :number, :required => true
|
28
|
+
param :parameters, String, :required => true
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
api :POST, '/app_definitions', N_('Create a application definition')
|
33
|
+
param_group :app_definition, :as => :create
|
34
|
+
def create
|
35
|
+
@app_definition = AppDefinition.new(app_definition_params)
|
36
|
+
process_response @app_definition.save
|
37
|
+
end
|
38
|
+
|
39
|
+
api :DELETE, '/app_definitions/:id', N_('Deletes application definition')
|
40
|
+
param :id, :identifier, :required => true
|
41
|
+
def destroy
|
42
|
+
process_response @app_definition.destroy
|
43
|
+
end
|
44
|
+
|
45
|
+
def controller_permission
|
46
|
+
'app_definitions'
|
47
|
+
end
|
48
|
+
|
49
|
+
def resource_class
|
50
|
+
ForemanAcd::AppDefinition
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ForemanAcd
|
4
|
+
module Api
|
5
|
+
module V2
|
6
|
+
# Base Controller for all Acd API controllers
|
7
|
+
class BaseController < ::Api::V2::BaseController
|
8
|
+
resource_description do
|
9
|
+
resource_id 'foreman_acd'
|
10
|
+
api_version 'v2'
|
11
|
+
api_base_url '/acd/api'
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ForemanAcd
|
4
|
+
# Application Definition Controller
|
5
|
+
class AppDefinitionsController < ::ForemanAcd::ApplicationController
|
6
|
+
include Foreman::Controller::AutoCompleteSearch
|
7
|
+
include ::ForemanAcd::Concerns::AppDefinitionParameters
|
8
|
+
|
9
|
+
before_action :find_resource, :only => [:edit, :update, :destroy]
|
10
|
+
|
11
|
+
def index
|
12
|
+
@app_definitions = resource_base.search_for(params[:search], :order => params[:order]).paginate(:page => params[:page])
|
13
|
+
end
|
14
|
+
|
15
|
+
def read_hostgroups
|
16
|
+
@hostgroups = Hostgroup.all.map { |elem| { elem.id => elem.name } }.reduce({}) { |h, v| h.merge v }
|
17
|
+
end
|
18
|
+
|
19
|
+
def new
|
20
|
+
read_hostgroups
|
21
|
+
@app_definition = AppDefinition.new
|
22
|
+
end
|
23
|
+
|
24
|
+
def create
|
25
|
+
@app_definition = AppDefinition.new(app_definition_params)
|
26
|
+
if @app_definition.save
|
27
|
+
process_success
|
28
|
+
else
|
29
|
+
process_error
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def edit
|
34
|
+
read_hostgroups
|
35
|
+
end
|
36
|
+
|
37
|
+
def update
|
38
|
+
if @app_definition.update(app_definition_params)
|
39
|
+
process_success
|
40
|
+
else
|
41
|
+
process_error
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def destroy
|
46
|
+
if @app_definition.destroy
|
47
|
+
process_success
|
48
|
+
else
|
49
|
+
process_error
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,158 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ForemanAcd
|
4
|
+
# Application Instance Controller
|
5
|
+
class AppInstancesController < ::ForemanAcd::ApplicationController
|
6
|
+
include Foreman::Controller::AutoCompleteSearch
|
7
|
+
include ::ForemanAcd::Concerns::AppInstanceParameters
|
8
|
+
|
9
|
+
before_action :find_resource, :only => [:edit, :update, :destroy, :deploy]
|
10
|
+
|
11
|
+
def index
|
12
|
+
@app_instances = resource_base.search_for(params[:search], :order => params[:order]).paginate(:page => params[:page])
|
13
|
+
end
|
14
|
+
|
15
|
+
def read_applications
|
16
|
+
@applications = ForemanAcd::AppDefinition.all.map { |elem| { elem.id => elem.name } }.reduce({}) { |h, v| h.merge v }
|
17
|
+
end
|
18
|
+
|
19
|
+
def new
|
20
|
+
@app_instance = AppInstance.new
|
21
|
+
read_applications
|
22
|
+
end
|
23
|
+
|
24
|
+
def create
|
25
|
+
@app_instance = AppInstance.new(app_instance_params)
|
26
|
+
if @app_instance.save
|
27
|
+
process_success
|
28
|
+
else
|
29
|
+
process_error
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def edit
|
34
|
+
read_applications
|
35
|
+
end
|
36
|
+
|
37
|
+
def update
|
38
|
+
if @app_instance.update(app_instance_params)
|
39
|
+
process_success
|
40
|
+
else
|
41
|
+
process_error
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def destroy
|
46
|
+
if @app_instance.destroy
|
47
|
+
process_success
|
48
|
+
else
|
49
|
+
process_error
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def action_permission
|
54
|
+
case params[:action]
|
55
|
+
when 'deploy'
|
56
|
+
:deploy
|
57
|
+
else
|
58
|
+
super
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def deploy
|
63
|
+
params = host_attributes(set_host_params)
|
64
|
+
|
65
|
+
# Print to log for debugging purposes
|
66
|
+
logger.info("Host creation parameters:\n#{params}\n")
|
67
|
+
|
68
|
+
@host = Host.new(params)
|
69
|
+
apply_compute_profile(@host)
|
70
|
+
@host.suggest_default_pxe_loader
|
71
|
+
@host.save
|
72
|
+
success _('Successfully initiated host creation')
|
73
|
+
rescue StandardError => e
|
74
|
+
logger.error("Failed to initiate host creation: #{e.backtrace.join($INPUT_RECORD_SEPARATOR)}")
|
75
|
+
ensure
|
76
|
+
redirect_to app_instances_path
|
77
|
+
end
|
78
|
+
|
79
|
+
private
|
80
|
+
|
81
|
+
# Copied from foreman/app/controllers/api/v2/hosts_controller.rb
|
82
|
+
def apply_compute_profile(host)
|
83
|
+
host.apply_compute_profile(InterfaceMerge.new(:merge_compute_attributes => true))
|
84
|
+
host.apply_compute_profile(ComputeAttributeMerge.new)
|
85
|
+
end
|
86
|
+
|
87
|
+
# Copied from foreman/app/controllers/api/v2/hosts_controller.rb
|
88
|
+
def host_attributes(params, host = nil)
|
89
|
+
return {} if params.nil?
|
90
|
+
|
91
|
+
params = params.deep_clone
|
92
|
+
if params[:interfaces_attributes]
|
93
|
+
# handle both hash and array styles of nested attributes
|
94
|
+
params[:interfaces_attributes] = params[:interfaces_attributes].values if params[:interfaces_attributes].is_a?(Hash) || params[:interfaces_attributes].is_a?(ActionController::Parameters)
|
95
|
+
# map interface types
|
96
|
+
params[:interfaces_attributes] = params[:interfaces_attributes].map do |nic_attr|
|
97
|
+
interface_attributes(nic_attr, :allow_nil_type => host.nil?)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
params = host.apply_inherited_attributes(params) if host
|
101
|
+
params
|
102
|
+
end
|
103
|
+
|
104
|
+
# Copied from foreman/app/controllers/api/v2/hosts_controller.rb
|
105
|
+
def interface_attributes(params, allow_nil_type: false)
|
106
|
+
params[:type] = InterfaceTypeMapper.map(params[:type]) if params.key?(:type) || allow_nil_type
|
107
|
+
params
|
108
|
+
end
|
109
|
+
|
110
|
+
def hardcoded_params
|
111
|
+
result = {}
|
112
|
+
result['managed'] = true
|
113
|
+
result['enabled'] = true
|
114
|
+
result['build'] = true
|
115
|
+
result['compute_attributes'] = { 'start' => '1' }
|
116
|
+
result['host_parameters_attributes'] = []
|
117
|
+
result
|
118
|
+
end
|
119
|
+
|
120
|
+
def set_host_params
|
121
|
+
result = hardcoded_params
|
122
|
+
result['hostgroup_id'] = @app_instance.app_definition.hostgroup_id
|
123
|
+
JSON.parse(@app_instance.parameters).each do |param|
|
124
|
+
case param['type']
|
125
|
+
|
126
|
+
when 'computeprofile'
|
127
|
+
result['compute_profile_id'] = param['value']
|
128
|
+
|
129
|
+
when 'domain'
|
130
|
+
result['domain_id'] = param['value']
|
131
|
+
|
132
|
+
when 'hostname'
|
133
|
+
result['name'] = param['value']
|
134
|
+
|
135
|
+
when 'hostparam'
|
136
|
+
result['host_parameters_attributes'].push(:name => param['name'], :value => param['value'])
|
137
|
+
|
138
|
+
when 'ip'
|
139
|
+
result['ip'] = param['value']
|
140
|
+
|
141
|
+
when 'lifecycleenv'
|
142
|
+
result['content_facet_attributes'] = { 'lifecycle_environment_id' => param['value'] }
|
143
|
+
|
144
|
+
when 'ptable'
|
145
|
+
result['ptable_id'] = param['value']
|
146
|
+
|
147
|
+
when 'puppetenv'
|
148
|
+
result['environment_id'] = param['value']
|
149
|
+
|
150
|
+
when 'password'
|
151
|
+
result['root_pass'] = param['value']
|
152
|
+
|
153
|
+
end
|
154
|
+
end
|
155
|
+
result
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ForemanAcd
|
4
|
+
module Concerns
|
5
|
+
# Parameters for AppDefinitions
|
6
|
+
module AppDefinitionParameters
|
7
|
+
extend ActiveSupport::Concern
|
8
|
+
|
9
|
+
class_methods do
|
10
|
+
def app_definition_params_filter
|
11
|
+
Foreman::ParameterFilter.new(::ForemanAcd::AppDefinition).tap do |filter|
|
12
|
+
filter.permit(:name, :description, :hostgroup_id, :parameters)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def app_definition_params
|
18
|
+
param_name = parameter_filter_context.api? ? 'app_definition' : 'foreman_acd_app_definition'
|
19
|
+
self.class.app_definition_params_filter.filter_params(params, parameter_filter_context, param_name)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ForemanAcd
|
4
|
+
module Concerns
|
5
|
+
# Parameters for AppInstances
|
6
|
+
module AppInstanceParameters
|
7
|
+
extend ActiveSupport::Concern
|
8
|
+
|
9
|
+
class_methods do
|
10
|
+
def app_instance_params_filter
|
11
|
+
Foreman::ParameterFilter.new(::ForemanAcd::AppInstance).tap do |filter|
|
12
|
+
filter.permit(:name, :app_definition_id, :description, :parameters)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def app_instance_params
|
18
|
+
param_name = parameter_filter_context.api? ? 'app_instance' : 'foreman_acd_app_instance'
|
19
|
+
self.class.app_instance_params_filter.filter_params(params, parameter_filter_context, param_name)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Controller to create JSON data to be used in react app
|
4
|
+
class UiAcdController < ::Api::V2::BaseController
|
5
|
+
def app
|
6
|
+
@app_data = {}
|
7
|
+
app_definition = ForemanAcd::AppDefinition.find(params[:id])
|
8
|
+
@app_data['app_definition'] = app_definition
|
9
|
+
@app_data['fdata'] = collect_fdata(app_definition.hostgroup_id)
|
10
|
+
end
|
11
|
+
|
12
|
+
def fdata
|
13
|
+
@fdata = collect_fdata(params['id'])
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def collect_fdata(hostgroup_id)
|
19
|
+
hg = Hostgroup.find(hostgroup_id)
|
20
|
+
fdata = OpenStruct.new(
|
21
|
+
:environments => Environment.all,
|
22
|
+
:lifecycle_environments => Katello::KTEnvironment.all,
|
23
|
+
:domains => Domain.all,
|
24
|
+
:computeprofiles => ComputeProfile.all,
|
25
|
+
:hostgroup_id => hg.id,
|
26
|
+
:ptables => hg&.operatingsystem.ptables
|
27
|
+
)
|
28
|
+
fdata
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ForemanAcd
|
4
|
+
# Application Definition
|
5
|
+
class AppDefinition < ApplicationRecord
|
6
|
+
include Authorizable
|
7
|
+
extend FriendlyId
|
8
|
+
friendly_id :name
|
9
|
+
|
10
|
+
validates :name, :presence => true, :uniqueness => true
|
11
|
+
belongs_to :hostgroup, :class_name => '::Hostgroup'
|
12
|
+
has_many :app_instances, :inverse_of => :app_definition, :dependent => :destroy
|
13
|
+
scoped_search :on => :name
|
14
|
+
|
15
|
+
def self.humanize_class_name(_name = nil)
|
16
|
+
_('App Definition')
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.permission_name
|
20
|
+
'app_definitions'
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ForemanAcd
|
4
|
+
# Application Instance
|
5
|
+
class AppInstance < ApplicationRecord
|
6
|
+
include Authorizable
|
7
|
+
extend FriendlyId
|
8
|
+
friendly_id :name
|
9
|
+
validates :name, :presence => true, :uniqueness => true
|
10
|
+
belongs_to :app_definition, :inverse_of => :app_instances
|
11
|
+
scoped_search :on => :name
|
12
|
+
|
13
|
+
def self.humanize_class_name(_name = nil)
|
14
|
+
_('App Instance')
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.permission_name
|
18
|
+
'app_instances'
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
<%
|
2
|
+
json = {
|
3
|
+
"organization": current_organization,
|
4
|
+
"location": current_location,
|
5
|
+
"hostgroups": @hostgroups,
|
6
|
+
"loadForemanDataUrl": ui_acd_fdata_path("__id__")
|
7
|
+
}
|
8
|
+
|
9
|
+
if @app_definition.name.empty?
|
10
|
+
json["mode"] = "newDefinition"
|
11
|
+
else
|
12
|
+
json["mode"] = "editDefinition"
|
13
|
+
json["appDefinition"] = {
|
14
|
+
"id": @app_definition.id,
|
15
|
+
"name": @app_definition.name,
|
16
|
+
"hostgroup_id": @app_definition.hostgroup_id,
|
17
|
+
}
|
18
|
+
json["parameters"] = JSON.parse(@app_definition.parameters)
|
19
|
+
end
|
20
|
+
|
21
|
+
%>
|
22
|
+
|
23
|
+
<%= form_for @app_definition, :url => (@app_definition.new_record? ? app_definitions_path : app_definition_path(:id => @app_definition.id)) do |f| %>
|
24
|
+
<%= base_errors_for @app_definition %>
|
25
|
+
<ul class="nav nav-tabs" data-tabs="tabs">
|
26
|
+
<li class="active"><a href="#primary" data-toggle="tab"><%= _('Application Definitions') %></a></li>
|
27
|
+
</ul>
|
28
|
+
|
29
|
+
<div class="tab-content">
|
30
|
+
<div class="tab-pane active" id="primary">
|
31
|
+
<%= text_f f, :name %>
|
32
|
+
<%= text_f f, :description %>
|
33
|
+
|
34
|
+
<div id='param-selection'></div>
|
35
|
+
<%= mount_react_component('ParameterSelection', "#param-selection", json.to_json) %>
|
36
|
+
</div>
|
37
|
+
</div>
|
38
|
+
|
39
|
+
<%= submit_or_cancel f %>
|
40
|
+
<% end %>
|
@@ -0,0 +1,11 @@
|
|
1
|
+
<% title(_('Edit Application Definition %s') % @app_definition) %>
|
2
|
+
|
3
|
+
<% content_for(:javascripts) do %>
|
4
|
+
<%= webpacked_plugins_js_for :foreman_acd %>
|
5
|
+
<% end %>
|
6
|
+
<% content_for(:stylesheets) do %>
|
7
|
+
<%= webpacked_plugins_css_for :foreman_acd %>
|
8
|
+
<% end %>
|
9
|
+
|
10
|
+
<%= render :partial => 'form' %>
|
11
|
+
|
@@ -0,0 +1,27 @@
|
|
1
|
+
<% title _('Application Definitions') %>
|
2
|
+
|
3
|
+
<% title_actions button_group(new_link(_('New Application Definition'))) %>
|
4
|
+
|
5
|
+
<table class="table table-bordered table-striped">
|
6
|
+
<tr>
|
7
|
+
<th><%= sort :name, :as => s_('AppDefinition|Name') %></th>
|
8
|
+
<th><%= _('Description') %></th>
|
9
|
+
<th><%= sort :hostgroup, :as => _('Host groups'), :default => 'DESC' %></th>
|
10
|
+
<th></th>
|
11
|
+
</tr>
|
12
|
+
<% for app_definition in @app_definitions %>
|
13
|
+
<tr>
|
14
|
+
<td><%=link_to_if_authorized h(app_definition.name), hash_for_edit_app_definition_path(:id => app_definition).merge(:auth_object => app_definition, :authorizer => authorizer) %></td>
|
15
|
+
<td><%= app_definition.description %></td>
|
16
|
+
<td><%= app_definition.hostgroup %></td>
|
17
|
+
<td>
|
18
|
+
<%= action_buttons(display_delete_if_authorized(hash_for_app_definition_path(:id => app_definition).merge(:auth_object => app_definition, :authorizer => authorizer),
|
19
|
+
:data => { 'confirm': _('Delete %s?') % app_definition.name })) %>
|
20
|
+
</td>
|
21
|
+
</tr>
|
22
|
+
<% end %>
|
23
|
+
</table>
|
24
|
+
|
25
|
+
<%= page_entries_info @app_definitions %>
|
26
|
+
<%= will_paginate @app_definitions %>
|
27
|
+
|
@@ -0,0 +1,10 @@
|
|
1
|
+
<% title _('New Application Definition') %>
|
2
|
+
|
3
|
+
<% content_for(:javascripts) do %>
|
4
|
+
<%= webpacked_plugins_js_for :foreman_acd %>
|
5
|
+
<% end %>
|
6
|
+
<% content_for(:stylesheets) do %>
|
7
|
+
<%= webpacked_plugins_css_for :foreman_acd %>
|
8
|
+
<% end %>
|
9
|
+
|
10
|
+
<%= render :partial => 'form' %>
|