foreman_acd 0.0.4 → 0.4.0

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.
Files changed (121) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +79 -26
  3. data/app/controllers/foreman_acd/ansible_playbooks_controller.rb +122 -0
  4. data/app/controllers/foreman_acd/api/v2/ansible_playbooks_controller.rb +54 -0
  5. data/app/controllers/foreman_acd/api/v2/app_definitions_controller.rb +1 -2
  6. data/app/controllers/foreman_acd/api/v2/app_instances_controller.rb +54 -0
  7. data/app/controllers/foreman_acd/api/v2/app_playbooks_controller.rb +0 -0
  8. data/app/controllers/foreman_acd/app_definitions_controller.rb +36 -4
  9. data/app/controllers/foreman_acd/app_instances_controller.rb +24 -90
  10. data/app/controllers/foreman_acd/concerns/ansible_playbook_parameters.rb +23 -0
  11. data/app/controllers/foreman_acd/concerns/app_definition_parameters.rb +1 -1
  12. data/app/controllers/foreman_acd/concerns/app_instance_parameters.rb +1 -1
  13. data/app/controllers/foreman_acd/remote_execution_controller.rb +49 -0
  14. data/app/controllers/ui_acd_controller.rb +11 -4
  15. data/app/models/foreman_acd/ansible_playbook.rb +50 -0
  16. data/app/models/foreman_acd/app_definition.rb +2 -1
  17. data/app/models/foreman_acd/app_instance.rb +7 -0
  18. data/app/services/foreman_acd/app_configurator.rb +70 -0
  19. data/app/services/foreman_acd/app_deployer.rb +139 -0
  20. data/app/services/foreman_acd/inventory_creator.rb +67 -0
  21. data/app/views/foreman_acd/ansible_playbooks/_form.html.erb +21 -0
  22. data/app/views/foreman_acd/ansible_playbooks/edit.html.erb +3 -0
  23. data/app/views/foreman_acd/ansible_playbooks/index.html.erb +30 -0
  24. data/app/views/foreman_acd/ansible_playbooks/new.html.erb +3 -0
  25. data/app/views/foreman_acd/api/v2/ansible_playbooks/base.json.rabl +3 -0
  26. data/app/views/foreman_acd/api/v2/ansible_playbooks/index.json.rabl +3 -0
  27. data/app/views/foreman_acd/api/v2/ansible_playbooks/show.json.rabl +3 -0
  28. data/app/views/foreman_acd/api/v2/app_definitions/base.json.rabl +3 -0
  29. data/app/views/foreman_acd/api/v2/app_definitions/index.json.rabl +3 -0
  30. data/app/views/foreman_acd/api/v2/app_definitions/show.json.rabl +3 -0
  31. data/app/views/foreman_acd/api/v2/app_instances/base.json.rabl +3 -0
  32. data/app/views/foreman_acd/api/v2/app_instances/index.json.rabl +3 -0
  33. data/app/views/foreman_acd/api/v2/app_instances/show.json.rabl +3 -0
  34. data/app/views/foreman_acd/app_definitions/_form.html.erb +25 -19
  35. data/app/views/foreman_acd/app_definitions/edit.html.erb +5 -0
  36. data/app/views/foreman_acd/app_definitions/import.html.erb +18 -0
  37. data/app/views/foreman_acd/app_definitions/index.html.erb +9 -5
  38. data/app/views/foreman_acd/app_instances/_form.html.erb +10 -8
  39. data/app/views/foreman_acd/app_instances/deploy.html.erb +19 -0
  40. data/app/views/foreman_acd/app_instances/index.html.erb +10 -5
  41. data/app/views/foreman_acd/app_instances/report.html.erb +19 -0
  42. data/app/views/templates/job/run_acd_ansible_playbook.erb +49 -0
  43. data/app/views/ui_acd/ansible_data.json.rabl +6 -0
  44. data/app/views/ui_acd/app.json.rabl +6 -2
  45. data/app/views/ui_acd/app_definition.json.rabl +1 -1
  46. data/app/views/ui_acd/{fdata.json.rabl → foreman_data.json.rabl} +1 -1
  47. data/config/routes.rb +32 -1
  48. data/db/migrate/20190610202252_create_app_definitions.rb +1 -3
  49. data/db/migrate/20190625140305_create_app_instances.rb +1 -1
  50. data/db/migrate/20200916091018_create_ansible_playbooks.rb +20 -0
  51. data/db/migrate/20200917120220_add_ansible_playbook_id.rb +14 -0
  52. data/db/migrate/20201016002819_add_ansible_vars_all_to_app_definitions.rb +5 -0
  53. data/db/migrate/20201016104338_add_ansible_vars_all_to_app_instances.rb +5 -0
  54. data/db/seeds.d/75-job_templates.rb +8 -0
  55. data/lib/foreman_acd/engine.rb +3 -0
  56. data/lib/foreman_acd/plugin.rb +72 -4
  57. data/lib/foreman_acd/version.rb +1 -1
  58. data/package.json +1 -2
  59. data/webpack/components/ApplicationDefinition/ApplicationDefinition.js +376 -0
  60. data/webpack/components/ApplicationDefinition/ApplicationDefinition.scss +1 -0
  61. data/webpack/components/ApplicationDefinition/ApplicationDefinitionActions.js +295 -0
  62. data/webpack/components/ApplicationDefinition/ApplicationDefinitionConstants.js +14 -0
  63. data/webpack/components/ApplicationDefinition/ApplicationDefinitionHelper.js +26 -0
  64. data/webpack/components/ApplicationDefinition/ApplicationDefinitionReducer.js +243 -0
  65. data/webpack/components/ApplicationDefinition/ApplicationDefinitionSelectors.js +8 -0
  66. data/webpack/components/ApplicationDefinition/components/AnsiblePlaybookSelector.js +49 -0
  67. data/webpack/components/ApplicationDefinition/index.js +33 -0
  68. data/webpack/components/ApplicationInstance/ApplicationInstance.js +412 -0
  69. data/webpack/components/ApplicationInstance/ApplicationInstance.scss +11 -0
  70. data/webpack/components/ApplicationInstance/ApplicationInstanceActions.js +239 -0
  71. data/webpack/components/ApplicationInstance/ApplicationInstanceConstants.js +14 -0
  72. data/webpack/components/ApplicationInstance/ApplicationInstanceReducer.js +295 -0
  73. data/webpack/components/ApplicationInstance/ApplicationInstanceSelectors.js +9 -0
  74. data/webpack/components/ApplicationInstance/components/AppDefinitionSelector.js +49 -0
  75. data/webpack/components/ApplicationInstance/components/Service.js +30 -0
  76. data/webpack/components/ApplicationInstance/components/ServiceCounter.js +37 -0
  77. data/webpack/components/ApplicationInstance/index.js +35 -0
  78. data/webpack/components/ApplicationInstanceReport/ApplicationInstanceReport.js +155 -0
  79. data/webpack/components/ApplicationInstanceReport/ApplicationInstanceReport.scss +27 -0
  80. data/webpack/components/ApplicationInstanceReport/ApplicationInstanceReportActions.js +86 -0
  81. data/webpack/components/ApplicationInstanceReport/ApplicationInstanceReportConstants.js +4 -0
  82. data/webpack/components/ApplicationInstanceReport/ApplicationInstanceReportReducer.js +52 -0
  83. data/webpack/components/ApplicationInstanceReport/ApplicationInstanceReportSelectors.js +5 -0
  84. data/webpack/components/ApplicationInstanceReport/components/ReportViewer.js +26 -0
  85. data/webpack/components/ApplicationInstanceReport/index.js +27 -0
  86. data/webpack/components/ParameterSelection/ParameterSelection.js +96 -183
  87. data/webpack/components/ParameterSelection/ParameterSelection.scss +9 -2
  88. data/webpack/components/ParameterSelection/ParameterSelectionActions.js +72 -104
  89. data/webpack/components/ParameterSelection/ParameterSelectionConstants.js +14 -19
  90. data/webpack/components/ParameterSelection/ParameterSelectionHelper.js +3 -35
  91. data/webpack/components/ParameterSelection/ParameterSelectionReducer.js +100 -83
  92. data/webpack/components/ParameterSelection/ParameterSelectionSelectors.js +3 -7
  93. data/webpack/components/ParameterSelection/__fixtures__/parameterSelection.fixtures.js +12 -21
  94. data/webpack/components/ParameterSelection/__fixtures__/parameterSelectionData_1.fixtures.js +1 -1
  95. data/webpack/components/ParameterSelection/__fixtures__/parameterSelectionReducer.fixtures.js +3 -45
  96. data/webpack/components/ParameterSelection/__tests__/ParameterSelection.test.js +20 -0
  97. data/webpack/components/ParameterSelection/__tests__/ParameterSelectionReducer.test.js +22 -46
  98. data/webpack/components/ParameterSelection/__tests__/ParameterSelectionSelectors.test.js +6 -6
  99. data/webpack/components/ParameterSelection/__tests__/__snapshots__/ParameterSelection.test.js.snap +40 -265
  100. data/webpack/components/ParameterSelection/__tests__/__snapshots__/ParameterSelectionReducer.test.js.snap +11 -96
  101. data/webpack/components/ParameterSelection/__tests__/__snapshots__/ParameterSelectionSelectors.test.js.snap +3 -9
  102. data/webpack/components/ParameterSelection/index.js +6 -8
  103. data/webpack/components/common/AddTableEntry.js +30 -0
  104. data/webpack/components/common/DeleteTableEntry.js +39 -0
  105. data/webpack/components/common/EasyHeaderFormatter.js +18 -0
  106. data/webpack/components/common/ExtSelect.js +43 -0
  107. data/webpack/components/common/RailsData.js +27 -0
  108. data/webpack/components/common/__tests__/AddTableEntry.test.js +26 -0
  109. data/webpack/components/common/__tests__/DeleteTableEntry.test.js +29 -0
  110. data/webpack/components/common/__tests__/ExtSelect.test.js +38 -0
  111. data/webpack/components/common/__tests__/RailsData.test.js +16 -0
  112. data/webpack/components/common/__tests__/__snapshots__/AddParameter.test.js.snap +35 -0
  113. data/webpack/components/common/__tests__/__snapshots__/AddTableEntry.test.js.snap +35 -0
  114. data/webpack/components/common/__tests__/__snapshots__/DeleteParameter.test.js.snap +41 -0
  115. data/webpack/components/common/__tests__/__snapshots__/DeleteTableEntry.test.js.snap +41 -0
  116. data/webpack/components/common/__tests__/__snapshots__/ExtSelect.test.js.snap +18 -0
  117. data/webpack/components/common/__tests__/__snapshots__/RailsData.test.js.snap +10 -0
  118. data/webpack/helper.js +20 -0
  119. data/webpack/index.js +6 -0
  120. data/webpack/reducer.js +43 -3
  121. metadata +87 -39
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 52f1a7200ef20e354b5ca1225847b07f88dbc34eb143f4314bc21afa24067bd3
4
- data.tar.gz: 6fc5e9c82b0869d008ebaf10a44367294ac64c72fb4d05c370b2645ccbdf918e
3
+ metadata.gz: 433f2c68da81192db3c98fc013ed2149490f2471e84d372db8241522a33b6630
4
+ data.tar.gz: aa46c833de3feb1cce0802de82dec78f1610331984e6df8df649fdadfffa2b2a
5
5
  SHA512:
6
- metadata.gz: d50e3c9bf7ade7240f7c9482d9147b64727dcae514453c8f95c52205a00c8d46c5e3a21138ebdc9cc30b0b80ad2870fcc35a0ccf9cff5bfd32e0b38bbee64ff4
7
- data.tar.gz: 26bdb492ce794f3a7c5a3afb0597e9a65f1a7230efe9b7a60a530f6dc41c5e4a051f2a6a33280123867c1945c3f405f5d9bec29a40c9ea148c53f7edf36c39a6
6
+ metadata.gz: 0accbf314dd5776a5b012507d97619be98beff2c11e523da4d27f69e9fdb1bf1d284c134dba6549719312a66ede8cb80c8a06e3851f01a14951b1752ef2e29e8
7
+ data.tar.gz: d003bc7a5de1c180b2e33ade4e85b2912776db564d59ff9d8eca4f9ccc00c38591fd061649df07bb89e76ad0b0ac5efe1c64dd506132148aaf087b758a18c078
data/README.md CHANGED
@@ -4,67 +4,121 @@
4
4
 
5
5
  A plugin to bring an user self service portal and application centric deployment to Foreman.
6
6
 
7
+
7
8
  # Description
8
9
 
9
- The target of this plugin is, to deploy whole applications which include multiple hosts
10
- and an Ansible Playbook / saltstack state to configure the application.
10
+ The target of this plugin is, to deploy whole applications which include multiple hosts and
11
+ configure them using an Ansible Playbook / saltstack state.
11
12
 
12
13
  This plugin follows the idea of different user types working together.
13
- The administrative user creates application definitions including multiple servers and
14
+ The administrative user creates Application Definition including multiple servers and
14
15
  configuration management items (Ansible Playbook, saltstack state).
15
- The user can create and deploy new application instances with an easy to use self service portal.
16
+ The user can create and deploy new Application Instaces with an easy to use self service portal.
16
17
 
17
- *Example Application Definition:*
18
- To run a complex web application, a loadbalancer is required.
18
+ *Example Application Definition:* To run a complex web application, a loadbalancer is required.
19
19
  The loadbalancer routes the requests to 3 different web servers.
20
20
  The web servers are using a database which is in high availability mode on 2 hosts.
21
21
  => 6 hosts are required.
22
22
 
23
23
  This plugin aims to setup all 6 hosts and to deploy the application.
24
24
 
25
+
25
26
  # Current State
26
- In the current state the plugin can be used to provide an easy to use self service user portal
27
- to deploy new servers.
27
+
28
+ ## Application Definition
29
+
30
+ - Configure a ansible playbook
31
+ - Use the configured ansible playbook in a Application Definition
32
+ - Overwrite ansible playbook's group variables for the Application Definition
33
+ - Set foreman parameters in the Application Definition
34
+ - Setup various services like webservers, database-servers, etc.
35
+
36
+ ## Application Instance
37
+
38
+ - Use an Application Definition for your Application Instance
39
+ - Configure specific hosts which uses the Application Definitions services
40
+ - Deploy these hosts
41
+ - Configure the hosts using the configured ansible playbook
42
+
28
43
 
29
44
  # Road Map
30
- - Self service portal for single host deployments (current version)
31
- - Add application deployment with single host requirements
32
- - Add application deployment with multi host requirements
45
+ -
46
+ - Add Application deployment with single host requirements
47
+ - Add Application deployment with multi host requirements
33
48
 
34
49
  ## WARNING
35
50
 
36
51
  This plugin is in development.
37
- In the current state, a self service portal to deploy single servers can be created.
38
52
 
39
53
  ## Installation
40
54
 
41
- See [How_to_Install_a_Plugin](http://projects.theforeman.org/projects/foreman/wiki/How_to_Install_a_Plugin)
42
- for how to install Foreman plugins
55
+ See [How_to_Install_a_Plugin](https://theforeman.org/plugins/#2.Installation)
56
+ for how to install Foreman plugins.
57
+
58
+ ### TL;DR:
59
+
60
+ yum install tfm-rubygem-foreman_acd
61
+ foreman-maintain service restart --only foreman
62
+
63
+ In some cases you need to do manally
64
+
65
+ foreman-rake db:migrate
66
+ foreman-rake db:seed
67
+
68
+ ### Hints
43
69
 
44
- ATM, Katello plugin need to exist, too.
70
+ Katello plugin need to exist, too.
71
+
72
+ ### Configuration
73
+
74
+ To get ansible playbooks running, you need to:
75
+
76
+ cat /var/lib/foreman-proxy/ssh/id_rsa_foreman_proxy.pub >> /root/.ssh/authorized_keys
77
+
78
+ Make sure, that the job template 'Run ACD Ansible Playbook - SSH Default' is part of your organization / location.
45
79
 
46
80
  ## Usage
47
81
 
48
- Application Definition (Admin)
82
+ ### Ansible Playbook
83
+
84
+ * Copy (or checkout a git repository) to e.g. /opt/ansible-playbook
85
+ * Add a new Ansible Playbook via Configure -> Ansible Playbook
86
+ * Set the path to /opt/ansible-playbook and name the playbook file. (e.g. site.yml)
87
+ * Save it and press "Import group variables" for this newly created ansible playbook.
88
+
89
+ ### Application Definition (Admin)
90
+
49
91
  * Create an Application Definition (Configure -> Application Definition) first
50
- * Select the Hostgroup you want to use.
92
+ * Select the Ansible Playbook you want to use.
93
+ * Add new services and specifiy the host group you want to use.
51
94
  * Specifiy the values, a user could overwrite.
52
95
  (you can set a default value, if you want)
53
96
 
54
- Application Instance (User)
55
- * Create an Application Instance (Configure -> Application Instrane)
97
+ ### Application Instance (User)
98
+
99
+ * Create an Application Instance (Configure -> Application Instance)
56
100
  * Select the Application Definition which should be used
57
101
  * Set the values.
58
102
  Remember, all parameters need to have a value.
59
103
  * Save the Application Instance
60
- * To Deploy the host, select "Deploy" in the Action selection dropdown field
61
- on the Application Instance index site
104
+
105
+ ### Deploy & Configure the Application Instance (User)
106
+
107
+ * To Deploy the host, select "Deploy" in the action selection dropdown field
108
+ on the Application Instance index site.
109
+ * See if the hosts are deployed via action selection dropdown -> report.
110
+ * After all hosts are deployed, run the ansible playbook via
111
+ action selection dropdown -> Run ansible playbook
112
+
62
113
 
63
114
  ## TODO
64
115
 
65
- - Add ansible playbook / saltstack support to configure the application
66
- - Multi-host support
67
- - Add validation to the different parameter types
116
+ - Add saltstack support to configure the application
117
+ - "git" support for the ansible playbooks
118
+ - Automatically run the ansible playbook after all hosts are deployed
119
+ - More parameter / value validation
120
+ - Deliver ansible playbooks to the connected foreman smart proxies
121
+
68
122
 
69
123
  ## Contributing
70
124
 
@@ -72,7 +126,7 @@ Fork and send a Pull Request. Thanks!
72
126
 
73
127
  ## Copyright
74
128
 
75
- Copyright (c) 2019 ATIX AG
129
+ Copyright (c) 2020 ATIX AG
76
130
 
77
131
  This program is free software: you can redistribute it and/or modify
78
132
  it under the terms of the GNU General Public License as published by
@@ -86,4 +140,3 @@ GNU General Public License for more details.
86
140
 
87
141
  You should have received a copy of the GNU General Public License
88
142
  along with this program. If not, see <http://www.gnu.org/licenses/>.
89
-
@@ -0,0 +1,122 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ForemanAcd
4
+ # Ansible Playbook Controller
5
+ class AnsiblePlaybooksController < ::ForemanAcd::ApplicationController
6
+ include Foreman::Controller::AutoCompleteSearch
7
+ include ::ForemanAcd::Concerns::AnsiblePlaybookParameters
8
+
9
+ before_action :find_resource, :only => [:edit, :update, :destroy, :import_vars]
10
+
11
+ def index
12
+ @ansible_playbooks = resource_base.search_for(params[:search], :order => params[:order]).paginate(:page => params[:page])
13
+ end
14
+
15
+ def new
16
+ @ansible_playbook = AnsiblePlaybook.new
17
+ end
18
+
19
+ def create
20
+ @ansible_playbook = AnsiblePlaybook.new(ansible_playbook_params)
21
+ if @ansible_playbook.save
22
+ process_success
23
+ else
24
+ process_error
25
+ end
26
+ end
27
+
28
+ def edit
29
+ end
30
+
31
+ def update
32
+ if @ansible_playbook.update(ansible_playbook_params)
33
+ process_success
34
+ else
35
+ process_error
36
+ end
37
+ end
38
+
39
+ def destroy
40
+ if @ansible_playbook.destroy
41
+ process_success
42
+ else
43
+ process_error
44
+ end
45
+ end
46
+
47
+ def action_permission
48
+ case params[:action]
49
+ when 'import_vars'
50
+ :import_vars
51
+ else
52
+ super
53
+ end
54
+ end
55
+
56
+ # We need to move these to a smart_proxy_acd
57
+ def extract_variables(playbook_path)
58
+ errors = []
59
+ vars = {}
60
+
61
+ unless File.directory?(playbook_path) || File.directory?("#{playbook_path}/group_vars")
62
+ errors << "Playbook path '#{playbook_path}' or '#{playbook_path}/group_vars' doesn't exist"
63
+ return vars, errors
64
+ end
65
+
66
+ everything_empty = true
67
+
68
+ vars_files = Dir.glob("#{playbook_path}/group_vars/**/*")
69
+ vars_files.each do |vars_file|
70
+ loaded_yaml = {}
71
+ next if File.directory?(vars_file)
72
+
73
+ begin
74
+ loaded_yaml = YAML.load_file(vars_file)
75
+ rescue Psych::SyntaxError
76
+ err = "#{vars_file} is not YAML file"
77
+ logger.error(err)
78
+ errors << err
79
+ end
80
+ unless loaded_yaml.is_a? Hash
81
+ err = "Could not parse YAML file #{vars_file}"
82
+ logger.error(err)
83
+ errors << err
84
+ end
85
+ everything_empty = false unless loaded_yaml.empty?
86
+
87
+ # We need to support: group_vars/group_file and group_vars/group_dir/yaml_files
88
+ dir_and_file = File.split(vars_file)
89
+
90
+ if File.basename(dir_and_file[0]) == 'group_vars' # in case of group_vars/group_file
91
+ group_name = File.basename(dir_and_file[1], '.*')
92
+ else # in case of group_vars/group_dir/yaml_files
93
+ group_name = File.basename(dir_and_file[0])
94
+ end
95
+
96
+ logger.debug("Add ansible vars from file #{vars_file} to group #{group_name}")
97
+
98
+ if vars.has_key?(group_name)
99
+ vars[group_name].merge!(loaded_yaml)
100
+ else
101
+ vars[group_name] = loaded_yaml
102
+ end
103
+ end
104
+
105
+ errors << "No ansible group variable in #{playbook_path} defined." if everything_empty
106
+
107
+ return vars, errors
108
+ end
109
+
110
+ def import_vars
111
+ logger.debug("Load ansible group vars for #{@ansible_playbook} from #{@ansible_playbook.path}")
112
+ vars, errors = extract_variables(@ansible_playbook.path)
113
+ @ansible_playbook.vars = vars.to_json
114
+ @ansible_playbook.save
115
+ if errors.empty?
116
+ process_success :success_msg => _("Successfully loaded ansible group variables from %s") % @ansible_playbook.name, :redirect => ansible_playbooks_path
117
+ else
118
+ process_error :error_msg => _(errors.join(' ')), :redirect => ansible_playbooks_path
119
+ end
120
+ end
121
+ end
122
+ end
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ForemanAcd
4
+ module Api
5
+ module V2
6
+ # API controller for Ansible Playbooks
7
+ class AnsiblePlaybooksController < ::ForemanAcd::Api::V2::BaseController
8
+ include ::ForemanAcd::Concerns::AnsiblePlaybookParameters
9
+
10
+ before_action :find_resource, :except => [:index, :create]
11
+
12
+ api :GET, '/ansible_playbooks/:id', N_('Show ansible playbook')
13
+ param :id, :identifier, :required => true
14
+ def show; end
15
+
16
+ api :GET, '/ansible_playbooks', N_('List ansible playbooks')
17
+ param_group :search_and_pagination, ::Api::V2::BaseController
18
+ add_scoped_search_description_for(AnsiblePlaybook)
19
+ def index
20
+ @ansible_playbooks = resource_scope_for_index
21
+ end
22
+
23
+ def_param_group :ansible_playbook do
24
+ param :ansible_playbook, Hash, :required => true, :action_aware => true do
25
+ param :name, String, :required => true
26
+ param :description, String, :required => true
27
+ param :services, String, :required => true
28
+ end
29
+ end
30
+
31
+ api :POST, '/ansible_playbooks', N_('Create a ansible playbook')
32
+ param_group :ansible_playbook, :as => :create
33
+ def create
34
+ @ansible_playbook = AnsiblePlaybook.new(ansible_playbook_params)
35
+ process_response @ansible_playbook.save
36
+ end
37
+
38
+ api :DELETE, '/ansible_playbooks/:id', N_('Deletes ansible playbook')
39
+ param :id, :identifier, :required => true
40
+ def destroy
41
+ process_response @ansible_playbook.destroy
42
+ end
43
+
44
+ def controller_permission
45
+ 'ansible_playbooks'
46
+ end
47
+
48
+ def resource_class
49
+ ForemanAcd::AnsiblePlaybook
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
@@ -24,8 +24,7 @@ module ForemanAcd
24
24
  param :app_definition, Hash, :required => true, :action_aware => true do
25
25
  param :name, String, :required => true
26
26
  param :description, String, :required => true
27
- param :hostgroup_id, :number, :required => true
28
- param :parameters, String, :required => true
27
+ param :services, String, :required => true
29
28
  end
30
29
  end
31
30
 
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ForemanAcd
4
+ module Api
5
+ module V2
6
+ # API controller for App Instances
7
+ class AppInstancesController < ::ForemanAcd::Api::V2::BaseController
8
+ include ::ForemanAcd::Concerns::AppInstanceParameters
9
+
10
+ before_action :find_resource, :except => [:index, :create]
11
+
12
+ api :GET, '/app_instances/:id', N_('Show application instance')
13
+ param :id, :identifier, :required => true
14
+ def show; end
15
+
16
+ api :GET, '/app_instances', N_('List application instances')
17
+ param_group :search_and_pagination, ::Api::V2::BaseController
18
+ add_scoped_search_description_for(AppInstance)
19
+ def index
20
+ @app_instances = resource_scope_for_index
21
+ end
22
+
23
+ def_param_group :app_instance do
24
+ param :app_instance, Hash, :required => true, :action_aware => true do
25
+ param :name, String, :required => true
26
+ param :description, String, :required => true
27
+ param :services, String, :required => true
28
+ end
29
+ end
30
+
31
+ api :POST, '/app_instances', N_('Create a application instance')
32
+ param_group :app_instance, :as => :create
33
+ def create
34
+ @app_instance = AppInstance.new(app_instance_params)
35
+ process_response @app_instance.save
36
+ end
37
+
38
+ api :DELETE, '/app_instances/:id', N_('Deletes application instance')
39
+ param :id, :identifier, :required => true
40
+ def destroy
41
+ process_response @app_instance.destroy
42
+ end
43
+
44
+ def controller_permission
45
+ 'app_instances'
46
+ end
47
+
48
+ def resource_class
49
+ ForemanAcd::AppInstance
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
@@ -6,18 +6,25 @@ module ForemanAcd
6
6
  include Foreman::Controller::AutoCompleteSearch
7
7
  include ::ForemanAcd::Concerns::AppDefinitionParameters
8
8
 
9
- before_action :find_resource, :only => [:edit, :update, :destroy]
9
+ before_action :find_resource, :only => [:edit, :update, :destroy, :export]
10
+ before_action :read_hostgroups, :only => [:edit, :new, :import]
11
+ before_action :read_ansible_playbooks, :only => [:edit, :new]
12
+ before_action :handle_file_upload, :only => [:create]
10
13
 
11
14
  def index
12
15
  @app_definitions = resource_base.search_for(params[:search], :order => params[:order]).paginate(:page => params[:page])
13
16
  end
14
17
 
18
+ def read_ansible_playbooks
19
+ # Only use ansible playbooks for which the user pressed import group vars once.
20
+ @ansible_playbooks = AnsiblePlaybook.where.not(vars: nil).map { |elem| { elem.id => elem.name } }.reduce({}) { |h, v| h.merge v }
21
+ end
22
+
15
23
  def read_hostgroups
16
24
  @hostgroups = Hostgroup.all.map { |elem| { elem.id => elem.name } }.reduce({}) { |h, v| h.merge v }
17
25
  end
18
26
 
19
27
  def new
20
- read_hostgroups
21
28
  @app_definition = AppDefinition.new
22
29
  end
23
30
 
@@ -31,11 +38,10 @@ module ForemanAcd
31
38
  end
32
39
 
33
40
  def edit
34
- read_hostgroups
35
41
  end
36
42
 
37
43
  def update
38
- if @app_definition.update(app_definition_params)
44
+ if @app_definition.update_attributes(app_definition_params)
39
45
  process_success
40
46
  else
41
47
  process_error
@@ -49,5 +55,31 @@ module ForemanAcd
49
55
  process_error
50
56
  end
51
57
  end
58
+
59
+ def action_permission
60
+ case params[:action]
61
+ when 'export'
62
+ :export
63
+ else
64
+ super
65
+ end
66
+ end
67
+
68
+ def import
69
+ @app_definition = AppDefinition.new
70
+ end
71
+
72
+ def export
73
+ filename = "#{@app_definition.name}.yaml"
74
+ data = JSON.parse(@app_definition.services).to_yaml
75
+ send_data data, :type => 'text/yaml', :disposition => 'attachment', :filename => filename
76
+ end
77
+
78
+ private
79
+
80
+ def handle_file_upload
81
+ return unless params[:foreman_acd_app_definition] && raw_file = params[:foreman_acd_app_definition][:app_definition_file]
82
+ params[:foreman_acd_app_definition][:services] = YAML.load_file(raw_file.tempfile).to_json
83
+ end
52
84
  end
53
85
  end