foreman_acd 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.
- 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' %>
|