foreman_acd 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (73) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +619 -0
  3. data/README.md +87 -0
  4. data/Rakefile +49 -0
  5. data/app/assets/javascripts/foreman_acd/acd_dummy.js +3 -0
  6. data/app/controllers/foreman_acd/api/v2/app_definitions_controller.rb +55 -0
  7. data/app/controllers/foreman_acd/api/v2/base_controller.rb +16 -0
  8. data/app/controllers/foreman_acd/app_definitions_controller.rb +53 -0
  9. data/app/controllers/foreman_acd/app_instances_controller.rb +158 -0
  10. data/app/controllers/foreman_acd/application_controller.rb +10 -0
  11. data/app/controllers/foreman_acd/concerns/app_definition_parameters.rb +23 -0
  12. data/app/controllers/foreman_acd/concerns/app_instance_parameters.rb +23 -0
  13. data/app/controllers/ui_acd_controller.rb +30 -0
  14. data/app/models/foreman_acd/app_definition.rb +23 -0
  15. data/app/models/foreman_acd/app_instance.rb +21 -0
  16. data/app/views/foreman_acd/app_definitions/_form.html.erb +40 -0
  17. data/app/views/foreman_acd/app_definitions/edit.html.erb +11 -0
  18. data/app/views/foreman_acd/app_definitions/index.html.erb +27 -0
  19. data/app/views/foreman_acd/app_definitions/new.html.erb +10 -0
  20. data/app/views/foreman_acd/app_instances/_form.html.erb +46 -0
  21. data/app/views/foreman_acd/app_instances/edit.html.erb +11 -0
  22. data/app/views/foreman_acd/app_instances/index.html.erb +30 -0
  23. data/app/views/foreman_acd/app_instances/new.html.erb +11 -0
  24. data/app/views/ui_acd/app.json.rabl +9 -0
  25. data/app/views/ui_acd/app_definition.json.rabl +5 -0
  26. data/app/views/ui_acd/computeprofile.json.rabl +4 -0
  27. data/app/views/ui_acd/domain.json.rabl +4 -0
  28. data/app/views/ui_acd/environment.json.rabl +4 -0
  29. data/app/views/ui_acd/fdata.json.rabl +24 -0
  30. data/app/views/ui_acd/lifecycle_environment.json.rabl +4 -0
  31. data/app/views/ui_acd/ptable.json.rabl +4 -0
  32. data/config/routes.rb +24 -0
  33. data/db/migrate/20190610202252_create_app_definitions.rb +19 -0
  34. data/db/migrate/20190625140305_create_app_instances.rb +19 -0
  35. data/lib/foreman_acd/engine.rb +43 -0
  36. data/lib/foreman_acd/plugin.rb +80 -0
  37. data/lib/foreman_acd/version.rb +5 -0
  38. data/lib/foreman_acd.rb +7 -0
  39. data/lib/tasks/foreman_acd_tasks.rake +47 -0
  40. data/locale/Makefile +60 -0
  41. data/locale/en/foreman_acd.po +19 -0
  42. data/locale/foreman_acd.pot +19 -0
  43. data/locale/gemspec.rb +2 -0
  44. data/package.json +121 -0
  45. data/test/controllers/app_definitions_controller_test.rb +24 -0
  46. data/test/controllers/app_instances_controller_test.rb +24 -0
  47. data/test/controllers/ui_acd_controller_test.rb +26 -0
  48. data/test/factories/foreman_acd_factories.rb +17 -0
  49. data/test/models/app_definition_test.rb +11 -0
  50. data/test/models/app_instance_test.rb +8 -0
  51. data/test/test_plugin_helper.rb +8 -0
  52. data/webpack/__mocks__/foremanReact/components/common/forms/Select.js +2 -0
  53. data/webpack/components/ParameterSelection/ParameterSelection.js +468 -0
  54. data/webpack/components/ParameterSelection/ParameterSelection.scss +3 -0
  55. data/webpack/components/ParameterSelection/ParameterSelectionActions.js +294 -0
  56. data/webpack/components/ParameterSelection/ParameterSelectionConstants.js +31 -0
  57. data/webpack/components/ParameterSelection/ParameterSelectionHelper.js +52 -0
  58. data/webpack/components/ParameterSelection/ParameterSelectionReducer.js +175 -0
  59. data/webpack/components/ParameterSelection/ParameterSelectionSelectors.js +15 -0
  60. data/webpack/components/ParameterSelection/__fixtures__/parameterSelection.fixtures.js +162 -0
  61. data/webpack/components/ParameterSelection/__fixtures__/parameterSelectionData_1.fixtures.js +194 -0
  62. data/webpack/components/ParameterSelection/__fixtures__/parameterSelectionReducer.fixtures.js +127 -0
  63. data/webpack/components/ParameterSelection/__tests__/ParameterSelection.test.js +48 -0
  64. data/webpack/components/ParameterSelection/__tests__/ParameterSelectionReducer.test.js +150 -0
  65. data/webpack/components/ParameterSelection/__tests__/ParameterSelectionSelectors.test.js +47 -0
  66. data/webpack/components/ParameterSelection/__tests__/__snapshots__/ParameterSelection.test.js.snap +454 -0
  67. data/webpack/components/ParameterSelection/__tests__/__snapshots__/ParameterSelectionReducer.test.js.snap +2265 -0
  68. data/webpack/components/ParameterSelection/__tests__/__snapshots__/ParameterSelectionSelectors.test.js.snap +209 -0
  69. data/webpack/components/ParameterSelection/index.js +39 -0
  70. data/webpack/index.js +8 -0
  71. data/webpack/reducer.js +7 -0
  72. data/webpack/test_setup.js +11 -0
  73. 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,3 @@
1
+ function acd_dummy_method() {
2
+ console.log("This file / function / method exists so that %foreman_precompile_plugin -s works during RPM build stage...");
3
+ }
@@ -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,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ForemanAcd
4
+ # Base controller for all controllers
5
+ class ApplicationController < ::ApplicationController
6
+ def resource_class
7
+ "ForemanAcd::#{controller_name.singularize.classify}".constantize
8
+ end
9
+ end
10
+ 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' %>