foreman_acd 0.5.0 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (95) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +82 -86
  3. data/app/controllers/foreman_acd/ansible_playbooks_controller.rb +13 -11
  4. data/app/controllers/foreman_acd/api/v2/ansible_playbooks_controller.rb +4 -3
  5. data/app/controllers/foreman_acd/api/v2/app_definitions_controller.rb +1 -0
  6. data/app/controllers/foreman_acd/api/v2/app_instances_controller.rb +9 -1
  7. data/app/controllers/foreman_acd/app_definitions_controller.rb +14 -9
  8. data/app/controllers/foreman_acd/app_instances_controller.rb +97 -25
  9. data/app/controllers/foreman_acd/concerns/ansible_playbook_parameters.rb +1 -1
  10. data/app/controllers/foreman_acd/concerns/app_definition_parameters.rb +1 -1
  11. data/app/controllers/foreman_acd/concerns/app_instance_parameters.rb +1 -1
  12. data/app/controllers/foreman_acd/remote_execution_controller.rb +3 -6
  13. data/app/controllers/ui_acd_controller.rb +9 -0
  14. data/app/lib/actions/foreman_acd/deploy_all_hosts.rb +42 -0
  15. data/app/lib/actions/foreman_acd/run_configurator.rb +41 -0
  16. data/app/models/concerns/foreman_acd/host_managed_extensions.rb +51 -0
  17. data/app/models/foreman_acd/acd_provider.rb +3 -0
  18. data/app/models/foreman_acd/ansible_playbook.rb +30 -13
  19. data/app/models/foreman_acd/app_definition.rb +24 -1
  20. data/app/models/foreman_acd/app_instance.rb +40 -5
  21. data/app/models/foreman_acd/foreman_host.rb +23 -0
  22. data/app/models/foreman_acd/taxonomy_extensions.rb +17 -0
  23. data/app/services/foreman_acd/app_configurator.rb +7 -10
  24. data/app/services/foreman_acd/app_deployer.rb +59 -47
  25. data/app/services/foreman_acd/inventory_creator.rb +12 -25
  26. data/app/views/foreman_acd/ansible_playbooks/_form.html.erb +11 -2
  27. data/app/views/foreman_acd/ansible_playbooks/edit.html.erb +9 -1
  28. data/app/views/foreman_acd/ansible_playbooks/index.html.erb +3 -3
  29. data/app/views/foreman_acd/api/v2/ansible_playbooks/base.json.rabl +2 -0
  30. data/app/views/foreman_acd/api/v2/ansible_playbooks/index.json.rabl +2 -0
  31. data/app/views/foreman_acd/api/v2/ansible_playbooks/show.json.rabl +6 -0
  32. data/app/views/foreman_acd/api/v2/app_definitions/base.json.rabl +2 -0
  33. data/app/views/foreman_acd/api/v2/app_definitions/index.json.rabl +2 -0
  34. data/app/views/foreman_acd/api/v2/app_definitions/show.json.rabl +6 -0
  35. data/app/views/foreman_acd/api/v2/app_instances/base.json.rabl +3 -1
  36. data/app/views/foreman_acd/api/v2/app_instances/index.json.rabl +2 -0
  37. data/app/views/foreman_acd/api/v2/app_instances/show.json.rabl +2 -0
  38. data/app/views/foreman_acd/app_definitions/_form.html.erb +8 -0
  39. data/app/views/foreman_acd/app_definitions/edit.html.erb +10 -5
  40. data/app/views/foreman_acd/app_definitions/index.html.erb +4 -4
  41. data/app/views/foreman_acd/app_instances/_form.html.erb +3 -3
  42. data/app/views/foreman_acd/app_instances/edit.html.erb +10 -0
  43. data/app/views/foreman_acd/app_instances/index.html.erb +87 -14
  44. data/app/views/foreman_acd/app_instances/report.html.erb +5 -2
  45. data/app/views/templates/job/run_acd_ansible_playbook.erb +14 -1
  46. data/app/views/ui_acd/app_definition.json.rabl +1 -1
  47. data/config/routes.rb +1 -2
  48. data/db/migrate/20200917120220_add_ansible_playbook_id.rb +1 -1
  49. data/db/migrate/20201016002819_add_ansible_vars_all_to_app_definitions.rb +3 -0
  50. data/db/migrate/20201016104338_add_ansible_vars_all_to_app_instances.rb +3 -0
  51. data/db/migrate/20210112111548_add_organization_to_app_instance.rb +22 -0
  52. data/db/migrate/20210112113853_add_location_to_app_instance.rb +8 -0
  53. data/db/migrate/20210202141658_create_foreman_hosts.rb +24 -0
  54. data/db/migrate/20210204111306_remove_hosts_from_app_instances.rb +8 -0
  55. data/db/migrate/20210209091014_rename_acd_tables.rb +16 -0
  56. data/db/migrate/20210216083522_add_last_progress_report.rb +8 -0
  57. data/db/migrate/20210216091529_add_last_deploy_task.rb +8 -0
  58. data/db/seeds.d/62_acd_proxy_feature.rb +1 -3
  59. data/db/seeds.d/75-job_templates.rb +6 -1
  60. data/lib/foreman_acd/engine.rb +14 -3
  61. data/lib/foreman_acd/plugin.rb +49 -28
  62. data/lib/foreman_acd/version.rb +1 -1
  63. data/locale/en/foreman_acd.edit.po +326 -0
  64. data/locale/en/foreman_acd.po +232 -2
  65. data/{app/controllers/foreman_acd/api/v2/app_playbooks_controller.rb → locale/en/foreman_acd.po.time_stamp} +0 -0
  66. data/locale/foreman_acd.pot +343 -8
  67. data/test/controllers/ansible_playbooks_controller_test.rb +27 -0
  68. data/webpack/components/ApplicationDefinition/ApplicationDefinition.js +31 -18
  69. data/webpack/components/ApplicationDefinition/ApplicationDefinitionActions.js +8 -0
  70. data/webpack/components/ApplicationDefinition/ApplicationDefinitionConstants.js +1 -0
  71. data/webpack/components/ApplicationDefinition/ApplicationDefinitionReducer.js +26 -0
  72. data/webpack/components/ApplicationDefinition/ApplicationDefinitionSelectors.js +1 -0
  73. data/webpack/components/ApplicationDefinition/index.js +2 -0
  74. data/webpack/components/ApplicationInstance/ApplicationInstance.js +67 -30
  75. data/webpack/components/ApplicationInstance/ApplicationInstanceActions.js +8 -0
  76. data/webpack/components/ApplicationInstance/ApplicationInstanceConstants.js +1 -0
  77. data/webpack/components/ApplicationInstance/ApplicationInstanceReducer.js +16 -2
  78. data/webpack/components/ApplicationInstance/ApplicationInstanceSelectors.js +1 -0
  79. data/webpack/components/ApplicationInstance/components/Service.js +1 -1
  80. data/webpack/components/ApplicationInstance/index.js +2 -0
  81. data/webpack/components/ApplicationInstanceReport/ApplicationInstanceReport.js +53 -60
  82. data/webpack/components/ApplicationInstanceReport/ApplicationInstanceReport.scss +17 -0
  83. data/webpack/components/ApplicationInstanceReport/ApplicationInstanceReportActions.js +7 -51
  84. data/webpack/components/ApplicationInstanceReport/ApplicationInstanceReportConstants.js +2 -4
  85. data/webpack/components/ApplicationInstanceReport/ApplicationInstanceReportReducer.js +4 -18
  86. data/webpack/components/ApplicationInstanceReport/ApplicationInstanceReportSelectors.js +0 -1
  87. data/webpack/components/ApplicationInstanceReport/components/ReportViewer.js +1 -1
  88. data/webpack/components/ApplicationInstanceReport/index.js +0 -2
  89. data/webpack/components/ParameterSelection/ParameterSelection.js +10 -0
  90. data/webpack/components/ParameterSelection/ParameterSelectionActions.js +8 -7
  91. data/webpack/components/common/DeleteTableEntry.js +3 -2
  92. data/webpack/components/common/EditTableEntry.js +2 -1
  93. data/webpack/components/common/LockTableEntry.js +2 -1
  94. metadata +48 -6
  95. data/app/views/foreman_acd/app_instances/deploy.html.erb +0 -19
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0d211aae9186f8f78068084f48a57c33bcc12840c8c187345a195ce90b474b62
4
- data.tar.gz: ffdefcc21d390b4cd379cae7f5884a1660303408824206bcede99dfc00cac23b
3
+ metadata.gz: 809d34cc7063d66a26a1c0c913cd95287a6329cce55a75c1684046bb47b1afe1
4
+ data.tar.gz: d32aa387545b3fac503996354baae6704c30118a923d95706668895cad6440f5
5
5
  SHA512:
6
- metadata.gz: 596cce7e2dc9f22f8e53da0060d327e3649963a03df3b89bc60e454698c8318f96d2500dc266ef3a430da959437601154ee00682a416baeaaa0db119f2027d36
7
- data.tar.gz: 357f087227ff418cf2ed0cbcf18e0ec5487fdb55c985c35fe55dea387f93db7eb1ec4268a312e325f925621bdb2cf16fdad1d06b13e893bce672e8d1aa03d2c3
6
+ metadata.gz: 996b0c911e71e045b232b3d6b27776eaa9c7e6c52f23f78d29c911f899d4a60024990fa8866e2f401e2d91f1c2a0c06a7264f16ffc2e4bd0b97c0e794a0a7c63
7
+ data.tar.gz: 445dc99ec810e7fbbdf33d2c1e69b3a60942c58938212105033e472981bee85e626ce51d7e2f36359bbfb9148dca240fff134d183481d1d8312a3e9f933f4815
data/README.md CHANGED
@@ -2,143 +2,139 @@
2
2
 
3
3
  # Foreman Application Centric Deployment
4
4
 
5
- A plugin to bring an user self service portal and application centric deployment to Foreman.
5
+ A Foreman plugin providing application centric deployment and a self-service portal.
6
6
 
7
+ # Introduction
7
8
 
8
- # Description
9
-
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.
9
+ The target of this plugin is to deploy whole applications which include multiple hosts and configure them using an Ansible playbook.
12
10
 
13
11
  This plugin follows the idea of different user types working together.
14
- The administrative user creates Application Definition including multiple servers and
15
- configuration management items (Ansible Playbook, saltstack state).
16
- The user can create and deploy new Application Instaces with an easy to use self service portal.
17
-
18
- *Example Application Definition:* To run a complex web application, a loadbalancer is required.
19
- The loadbalancer routes the requests to 3 different web servers.
20
- The web servers are using a database which is in high availability mode on 2 hosts.
21
- => 6 hosts are required.
12
+ The _administrative user_ creates Application Definitions including multiple servers and configuration management items (Ansible Playbooks).
13
+ The _user_ can create and deploy new Application Instances with an easy to use self-service portal.
22
14
 
23
- This plugin aims to setup all 6 hosts and to deploy the application.
15
+ *Example Application Definition*
16
+ To run a complex web application, a load balancer is required.
17
+ The load balancer routes the requests to three different web servers.
18
+ The web servers are using a database which runs in high availability mode on two hosts.
19
+ Therefore, six hosts in total are required.
24
20
 
21
+ This plugin aims to setup all six hosts and to deploy the application.
25
22
 
26
- # Current State
23
+ # Architecture
27
24
 
28
- ## Application Definition
25
+ ## Ansible Playbooks
29
26
 
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.
27
+ * Specify the path on your Foreman server to the Ansible playbook and playfile
28
+ * Read groups configured in the Ansible playbook
35
29
 
36
- ## Application Instance
30
+ ## Application Definitions
37
31
 
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
32
+ * Use the configured Ansible playbook in an Application Definition
33
+ * Overwrite group variables of the Ansible playbook for the Application Definition
34
+ * Set Foreman parameters in the Application Definition
35
+ * Setup various services like web servers, database servers, etc.
42
36
 
43
- # How it works
37
+ ## Application Instances
44
38
 
45
- - Configure ansible playbook, application definition and create an instance.
46
- - If you deploy the application instance, all hosts are created.
47
- - When done, you can configure the hosts with the linked ansible-playbook.
48
- - To do so, the [Smart Proxy ACD](https://github.com/ATIX-AG/smart_proxy_acd) is used.
49
- - The job to configure the hosts will be send to the Smart Proxy ACD which will
50
- - download the ansible playbook from foreman (provided by an foreman_acd API)
51
- - extract the ansible playbook on the Smart Proxy
52
- - run the ansible-playbook on the Smart Proxy
53
- - On the Monitor -> Job page you see the output of the ansible-playbook run.
39
+ * Use an Application Definition for your Application Instance
40
+ * Configure specific hosts which use the Application Definition's services
41
+ * Deploy these hosts
42
+ * Configure the hosts using the configured Ansible playbook
54
43
 
44
+ # How It Works
55
45
 
56
- ## WARNING
46
+ * Configure an Ansible playbook, an Application Definition, and create an Application Instance.
47
+ * All hosts are created when deploying the Application Instance.
48
+ * After provisioning, the hosts are configured with the linked Ansible playbook.
49
+ * This uses the [Smart Proxy ACD](https://github.com/ATIX-AG/smart_proxy_acd) component.
50
+ * The job to configure the hosts will be send to the Smart Proxy ACD component which will
51
+ * download the Ansible playbook from your Foreman server (provided by an foreman_acd API);
52
+ * extract the Ansible playbook on the Smart Proxy;
53
+ * and run the Ansible playbook on the Smart Proxy.
54
+ * You can see the output of the Ansible playbook run on the *Monitor > Job* page.
57
55
 
58
- This plugin is in development.
56
+ :warning: This plugin is still in development.
59
57
 
60
58
  ## Installation
61
59
 
62
- See [How_to_Install_a_Plugin](https://theforeman.org/plugins/#2.Installation)
63
- for how to install Foreman plugins.
64
-
65
- You will need to install [Smart Proxy ACD](https://github.com/ATIX-AG/smart_proxy_acd), too.
60
+ See the [installation](https://theforeman.org/plugins/#2.Installation) chapter of the Foreman plugins documentation on how to install Foreman plugins.
66
61
 
67
62
  ### TL;DR:
68
63
 
69
- yum install tfm-rubygem-foreman_acd tfm-rubygem-smart_proxy_acd tfm-rubygem-smart_proxy_acd_core
64
+ yum install tfm-rubygem-foreman_acd
70
65
  foreman-maintain service restart
71
66
 
72
- In some cases you need to do manally
67
+ In some cases, you need to manually run
73
68
 
74
69
  foreman-rake db:migrate
75
70
  foreman-rake db:seed
76
71
 
77
- ### Hints
72
+ ### Smart Proxy Installation
73
+
74
+ You will need to install [Smart Proxy ACD](https://github.com/ATIX-AG/smart_proxy_acd), too.
75
+
76
+ yum install tfm-rubygem-smart_proxy_acd tfm-rubygem-smart_proxy_acd_core
77
+ foreman-maintain service restart
78
+
79
+ You need to refresh the smart proxy features in *Infrastructure > Smart Proxies > Your Smart-Proxy > Actions > Refresh* after the installation of the Smart Proxy ACD components.
78
80
 
79
- Katello plugin need to exist, too.
81
+ ### Tips
82
+
83
+ * Make sure you have the [Katello](https://theforeman.org/plugins/katello/) plugin installed.
84
+ * Make sure the Job Template `Run ACD Ansible Playbook - ACD Default` is part of your organization/location context.
80
85
 
81
86
  ## Usage
82
87
 
83
88
  ### Ansible Playbook
84
89
 
85
- * Copy (or checkout a git repository) to e.g. /opt/ansible-playbook
86
- * Add a new Ansible Playbook via Configure -> Ansible Playbook
87
- * Set the path to /opt/ansible-playbook and name the playbook file. (e.g. site.yml)
88
- * Save it and press "Import group variables" for this newly created ansible playbook.
90
+ * Copy (or checkout a git repository) an Ansible playbook.
91
+ Store it in `/etc/foreman/plugins/foreman_acd/ansible-playbooks/` so that SELinux is able to read it.
92
+ * Add a new Ansible Playbook via *Applications > Ansible Playbooks*.
93
+ * Specify the path to the Ansible playbook and name of the playbook file. (e.g. `site.yml`).
94
+ * Save it and press *Import group variables* for this newly created Ansible playbook.
89
95
 
90
- ### Application Definition (Admin)
96
+ ### Application Definition (for Admins)
91
97
 
92
- * Create an Application Definition (Configure -> Application Definition) first
98
+ * Create an Application Definition via *Applications > Application Definitions*.
93
99
  * Select the Ansible Playbook you want to use.
94
- * Add new services and specifiy the host group you want to use.
95
- * Specifiy the values, a user could overwrite.
96
- (you can set a default value, if you want)
97
-
98
- ### Application Instance (User)
100
+ * Add new services and specify the host group you want to use.
101
+ * Specify any values a user will be allowed to overwrite.
102
+ You may also set a default value.
99
103
 
100
- * Create an Application Instance (Configure -> Application Instance)
101
- * Select the Application Definition which should be used
102
- * Set the values.
103
- Remember, all parameters need to have a value.
104
- * Save the Application Instance
104
+ ### Application Instance (for Users)
105
105
 
106
- ### Deploy & Configure the Application Instance (User)
106
+ * Create an Application Instance via *Applications > Application Instances*.
107
+ * Select the Application Definition you want to use.
108
+ * Overwrite desired values.
109
+ All Foreman parameters require a value.
110
+ * Save the Application Instance.
107
111
 
108
- * To Deploy the host, select "Deploy" in the action selection dropdown field
109
- on the Application Instance index site.
110
- * See if the hosts are deployed via action selection dropdown -> report.
111
- * After all hosts are deployed, run the ansible playbook via
112
- action selection dropdown -> Run ansible playbook
112
+ ### Deploy and Configure the Application Instance (for Users)
113
113
 
114
+ * Select *Deploy* in the action drop down menu via *Applications > Application Instance* to deploy a host.
115
+ * Verify if the hosts are deployed via the *Report* button from the action drop down menu.
116
+ * Run the Ansible playbook via *Run Ansible playbook* from the action drop down menu after all hosts are deployed.
114
117
 
115
118
  ## TODO
116
119
 
117
- - "git" support for the ansible playbooks
118
- - Provide application templates which contains application definition and
119
- the required ansible-playbook.
120
- - Add saltstack support to configure the application
121
- - Automatically run the ansible playbook after all hosts are deployed
122
- - More parameter / value validation
123
-
120
+ * Add `git` support for the Ansible playbooks.
121
+ * Provide application templates which contains application definition and the required Ansible-playbook.
122
+ * Add Saltstack support to configure the application.
123
+ * Extend the Foreman parameter and value validation.
124
124
 
125
125
  ## Contributing
126
126
 
127
- Fork and send a Pull Request. Thanks!
127
+ Fork and send a Pull Request.
128
+ Thanks!
128
129
 
129
130
  ## Copyright
130
131
 
131
132
  Copyright (c) 2021 ATIX AG
132
133
 
133
- This program is free software: you can redistribute it and/or modify
134
- it under the terms of the GNU General Public License as published by
135
- the Free Software Foundation, either version 3 of the License, or
136
- (at your option) any later version.
134
+ This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
137
135
 
138
- This program is distributed in the hope that it will be useful,
139
- but WITHOUT ANY WARRANTY; without even the implied warranty of
140
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
141
- GNU General Public License for more details.
136
+ This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
137
+ See the GNU General Public License for more details.
142
138
 
143
- You should have received a copy of the GNU General Public License
144
- along with this program. If not, see <http://www.gnu.org/licenses/>.
139
+ You should have received a copy of the GNU General Public License along with this program.
140
+ If not, see <http://www.gnu.org/licenses/>.
@@ -19,14 +19,14 @@ module ForemanAcd
19
19
  def create
20
20
  @ansible_playbook = AnsiblePlaybook.new(ansible_playbook_params)
21
21
  if @ansible_playbook.save
22
- process_success
22
+ process_success :success_msg => _("Successfully created %s. You need to press the \"Import groups\" button
23
+ before this ansible playbook can be used in App Definitions!") % @ansible_playbook
23
24
  else
24
25
  process_error
25
26
  end
26
27
  end
27
28
 
28
- def edit
29
- end
29
+ def edit; end
30
30
 
31
31
  def update
32
32
  if @ansible_playbook.update(ansible_playbook_params)
@@ -48,6 +48,8 @@ module ForemanAcd
48
48
  case params[:action]
49
49
  when 'import_vars'
50
50
  :import_vars
51
+ when 'grab'
52
+ :grab
51
53
  else
52
54
  super
53
55
  end
@@ -87,15 +89,15 @@ module ForemanAcd
87
89
  # We need to support: group_vars/group_file and group_vars/group_dir/yaml_files
88
90
  dir_and_file = File.split(vars_file)
89
91
 
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
92
+ group_name = if File.basename(dir_and_file[0]) == 'group_vars' # in case of group_vars/group_file
93
+ File.basename(dir_and_file[1], '.*')
94
+ else # in case of group_vars/group_dir/yaml_files
95
+ File.basename(dir_and_file[0])
96
+ end
95
97
 
96
98
  logger.debug("Add ansible vars from file #{vars_file} to group #{group_name}")
97
99
 
98
- if vars.has_key?(group_name)
100
+ if vars.key?(group_name)
99
101
  vars[group_name].merge!(loaded_yaml)
100
102
  else
101
103
  vars[group_name] = loaded_yaml
@@ -104,7 +106,7 @@ module ForemanAcd
104
106
 
105
107
  errors << "No ansible group variable in #{playbook_path} defined." if everything_empty
106
108
 
107
- return vars, errors
109
+ [vars, errors]
108
110
  end
109
111
 
110
112
  def import_vars
@@ -113,7 +115,7 @@ module ForemanAcd
113
115
  @ansible_playbook.vars = vars.to_json
114
116
  @ansible_playbook.save
115
117
  if errors.empty?
116
- process_success :success_msg => _("Successfully loaded ansible group variables from %s") % @ansible_playbook.name, :redirect => ansible_playbooks_path
118
+ process_success :success_msg => _('Successfully loaded ansible group variables from %s') % @ansible_playbook.name, :redirect => ansible_playbooks_path
117
119
  else
118
120
  process_error :error_msg => _(errors.join(' ')), :redirect => ansible_playbooks_path
119
121
  end
@@ -26,6 +26,7 @@ module ForemanAcd
26
26
  def_param_group :ansible_playbook do
27
27
  param :ansible_playbook, Hash, :required => true, :action_aware => true do
28
28
  param :name, String, :required => true
29
+ param_group :taxonomies, ::Api::V2::BaseController
29
30
  param :description, String, :required => true
30
31
  param :services, String, :required => true
31
32
  end
@@ -49,8 +50,8 @@ module ForemanAcd
49
50
  def grab
50
51
  ap = resource_class.find(params['id'])
51
52
  command = "tar cz -C #{ap.path} --exclude \".git\" . 2>/dev/null | base64"
52
- result = %x<#{command}>
53
- send_data result, type: "text/plain", disposition: 'inline'
53
+ result = `#{command}`
54
+ send_data result, :type => 'text/plain', :disposition => 'inline'
54
55
  end
55
56
 
56
57
  def action_permission
@@ -58,7 +59,7 @@ module ForemanAcd
58
59
  when 'grab'
59
60
  'grab'
60
61
  else
61
- super
62
+ super
62
63
  end
63
64
  end
64
65
 
@@ -23,6 +23,7 @@ module ForemanAcd
23
23
  def_param_group :app_definition do
24
24
  param :app_definition, Hash, :required => true, :action_aware => true do
25
25
  param :name, String, :required => true
26
+ param_group :taxonomies, ::Api::V2::BaseController
26
27
  param :description, String, :required => true
27
28
  param :services, String, :required => true
28
29
  end
@@ -11,18 +11,26 @@ module ForemanAcd
11
11
 
12
12
  api :GET, '/app_instances/:id', N_('Show application instance')
13
13
  param :id, :identifier, :required => true
14
+ param :organization_id, :identifier, :required => true
15
+ param :location_id, :identifier, :required => true
14
16
  def show; end
15
17
 
16
18
  api :GET, '/app_instances', N_('List application instances')
19
+ param :organization_id, :identifier, :required => true
20
+ param :location_id, :identifier, :required => true
17
21
  param_group :search_and_pagination, ::Api::V2::BaseController
18
22
  add_scoped_search_description_for(AppInstance)
19
23
  def index
20
- @app_instances = resource_scope_for_index
24
+ scope = resource_scope_for_index.where(:organization => params[:organization_id]) if params[:organization_id].present?
25
+ scope = scope.where(:location => params[:location_id]) if params[:location_id].present?
26
+ @app_instances = scope
21
27
  end
22
28
 
23
29
  def_param_group :app_instance do
24
30
  param :app_instance, Hash, :required => true, :action_aware => true do
25
31
  param :name, String, :required => true
32
+ param :organization_id, :identifier, :required => true
33
+ param :location_id, :identifier, :required => true
26
34
  param :description, String, :required => true
27
35
  param :services, String, :required => true
28
36
  end
@@ -17,7 +17,7 @@ module ForemanAcd
17
17
 
18
18
  def read_ansible_playbooks
19
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 }
20
+ @ansible_playbooks = AnsiblePlaybook.where.not(:vars => nil).map { |elem| { elem.id => elem.name } }.reduce({}) { |h, v| h.merge v }
21
21
  end
22
22
 
23
23
  def read_hostgroups
@@ -30,18 +30,21 @@ module ForemanAcd
30
30
 
31
31
  def create
32
32
  @app_definition = AppDefinition.new(app_definition_params)
33
- if @app_definition.save
34
- process_success
35
- else
36
- process_error
33
+ begin
34
+ if @app_definition.save!
35
+ process_success
36
+ else
37
+ process_error
38
+ end
39
+ rescue StandardError, ValidationError => e
40
+ redirect_to new_app_definition_path, :flash => { :error => _(e.message) }
37
41
  end
38
42
  end
39
43
 
40
- def edit
41
- end
44
+ def edit; end
42
45
 
43
46
  def update
44
- if @app_definition.update_attributes(app_definition_params)
47
+ if @app_definition.update(app_definition_params)
45
48
  process_success
46
49
  else
47
50
  process_error
@@ -60,6 +63,8 @@ module ForemanAcd
60
63
  case params[:action]
61
64
  when 'export'
62
65
  :export
66
+ when 'import'
67
+ :import
63
68
  else
64
69
  super
65
70
  end
@@ -78,7 +83,7 @@ module ForemanAcd
78
83
  private
79
84
 
80
85
  def handle_file_upload
81
- return unless params[:foreman_acd_app_definition] && raw_file = params[:foreman_acd_app_definition][:app_definition_file]
86
+ return unless params[:foreman_acd_app_definition] && (raw_file = params[:foreman_acd_app_definition][:app_definition_file])
82
87
  params[:foreman_acd_app_definition][:services] = YAML.load_file(raw_file.tempfile).to_json
83
88
  end
84
89
  end
@@ -6,40 +6,53 @@ module ForemanAcd
6
6
  include Foreman::Controller::AutoCompleteSearch
7
7
  include ::ForemanAcd::Concerns::AppInstanceParameters
8
8
 
9
- before_action :find_resource, :only => [:edit, :update, :destroy, :deploy, :report]
9
+ before_action :find_resource, :only => [:edit, :update, :destroy_with_hosts, :deploy, :report]
10
10
  before_action :read_applications, :only => [:new, :edit]
11
+ before_action :find_taxonomy
12
+ helper_method :collect_hosts_data
11
13
 
12
14
  def index
13
- @app_instances = resource_base.search_for(params[:search], :order => params[:order]).paginate(:page => params[:page])
15
+ @app_instances = resource_base.where(:organization => @organization).
16
+ where(:location => @location).
17
+ search_for(params[:search], :order => params[:order]).paginate(:page => params[:page])
14
18
  end
15
19
 
16
20
  def new
17
21
  @app_instance = AppInstance.new
22
+ @app_instance.organization = @organization
23
+ @app_instance.location = @location
18
24
  end
19
25
 
20
26
  def create
21
27
  @app_instance = AppInstance.new(app_instance_params)
22
- if @app_instance.save
23
- process_success
24
- else
25
- process_error
28
+ begin
29
+ if @app_instance.save!
30
+ app_instance_has_foreman_hosts
31
+ process_success
32
+ else
33
+ process_error
34
+ end
35
+ rescue StandardError, ValidationError => e
36
+ redirect_to new_app_instance_path, :flash => { :error => _(e.message) }
26
37
  end
27
38
  end
28
39
 
29
- def edit
30
- end
40
+ def edit; end
31
41
 
32
42
  def update
33
43
  if @app_instance.update(app_instance_params)
44
+ app_instance_has_foreman_hosts
34
45
  process_success
35
46
  else
36
47
  process_error
37
48
  end
38
49
  end
39
50
 
40
- def destroy
51
+ def destroy_with_hosts
52
+ @app_instance = AppInstance.find(params[:id])
53
+ @app_instance.clean_hosts_by_id(params[:foreman_host_ids]) if params[:foreman_host_ids]
41
54
  if @app_instance.destroy
42
- process_success
55
+ redirect_to app_instances_path, :flash => { :success => _('Successfully deleted %s') % @app_instance }
43
56
  else
44
57
  process_error
45
58
  end
@@ -51,40 +64,99 @@ module ForemanAcd
51
64
  :deploy
52
65
  when 'report'
53
66
  :report
67
+ when 'destroy_with_hosts'
68
+ :destroy
54
69
  else
55
70
  super
56
71
  end
57
72
  end
58
73
 
59
74
  def deploy
60
- app_deployer = ForemanAcd::AppDeployer.new(@app_instance)
61
- app_hosts = app_deployer.deploy
62
-
63
- # save any change to the app_hosts json
64
- @app_instance.hosts = app_hosts.to_json
65
- @app_instance.save
66
-
67
- @deploy_hosts = collect_host_report_data(app_hosts)
75
+ @app_instance.clean_all_hosts if params[:delete_hosts]
76
+
77
+ logger.info('Run async foreman task to deploy hosts')
78
+ async_task = ForemanTasks.async_task(::Actions::ForemanAcd::DeployAllHosts, @app_instance)
79
+ @app_instance.update!(:last_deploy_task => async_task)
80
+ process_success(:success_msg => _('Started task to deploy hosts for %s') % @app_instance)
81
+ rescue StandardError => e
82
+ error_msg = "Error happend while deploying hosts of #{@app_instance}: #{e.message}"
83
+ logger.error("#{error_msg} - #{e.class}\n#{e.backtrace.join($INPUT_RECORD_SEPARATOR)}")
84
+ process_error :error_msg => error_msg
68
85
  end
69
86
 
70
87
  def report
71
- app_hosts = JSON.parse(@app_instance.hosts)
72
- @report_hosts = collect_host_report_data(app_hosts)
88
+ @report_hosts = collect_host_report_data
89
+ logger.debug("app instance host details: #{@report_hosts.inspect}")
90
+ end
73
91
 
74
- logger.debug("deploy report hosts are: #{@report_hosts.inspect}")
92
+ def app_instance_has_foreman_hosts
93
+ hosts = JSON.parse(@app_instance.hosts)
94
+ hosts.each do |h|
95
+ if @app_instance.foreman_hosts.where(:hostname => h['hostname']).exists?
96
+ @app_instance.foreman_hosts.where(:hostname => h['hostname']).
97
+ update(:service => h['service'], :description => h['description'],
98
+ :foremanParameters => JSON.dump(h['foremanParameters']), :ansibleParameters => JSON.dump(h['ansibleParameters']))
99
+ else
100
+ @app_instance.foreman_hosts.create(:hostname => h['hostname'], :service => h['service'], :description => h['description'],
101
+ :foremanParameters => JSON.dump(h['foremanParameters']), :ansibleParameters => JSON.dump(h['ansibleParameters']))
102
+ end
103
+ end
104
+
105
+ # Delete record if json hosts are deleted
106
+ deleted_json_hosts = @app_instance.foreman_hosts.pluck('hostname') - hosts.pluck('hostname')
107
+ @app_instance.foreman_hosts.where(:hostname => deleted_json_hosts).destroy_all if deleted_json_hosts
108
+ end
109
+
110
+ def collect_hosts_data
111
+ hosts_data = []
112
+ @app_instance.foreman_hosts.each do |h|
113
+ hosts_data << {
114
+ :id => h.id,
115
+ :hostname => h.hostname,
116
+ :service => h.service,
117
+ :description => h.description,
118
+ :foremanParameters => JSON.parse(h.foremanParameters),
119
+ :ansibleParameters => JSON.parse(h.ansibleParameters)
120
+ }
121
+ end
122
+ hosts_data
75
123
  end
76
124
 
77
125
  private
78
126
 
127
+ def find_taxonomy
128
+ @organization = Organization.current
129
+ redirect_to '/select_organization?toState=' + request.path and return unless @organization
130
+
131
+ @location = Location.current
132
+ redirect_to root_path, :error => 'Select a location to show App Instances' and return unless @location
133
+ end
134
+
79
135
  def read_applications
80
136
  @applications = AppDefinition.all.map { |elem| { elem.id => elem.name } }.reduce({}) { |h, v| h.merge v }
81
137
  end
82
138
 
83
- def collect_host_report_data(app_hosts)
139
+ def collect_host_report_data
84
140
  report_data = []
85
- app_hosts.each do |host_data|
86
- host = Host.find(host_data['foreman_host_id'])
87
- report_data << { id: host.id, name: host_data['hostname'], hostname: host.hostname, hostUrl: host_path(host), progress_report_id: host.progress_report_id}
141
+
142
+ @app_instance.foreman_hosts.each do |foreman_host|
143
+ a_host = {
144
+ :id => nil,
145
+ :name => foreman_host.hostname,
146
+ :build => nil,
147
+ :hostUrl => nil,
148
+ :progress_report => foreman_host.last_progress_report.empty? ? [] : JSON.parse(foreman_host.last_progress_report)
149
+ }
150
+
151
+ if foreman_host.host.present?
152
+ a_host.update({
153
+ :id => foreman_host.host.id,
154
+ :build => foreman_host.host.build,
155
+ :hostUrl => host_path(foreman_host.host),
156
+ :powerStatusUrl => power_api_host_path(foreman_host.host)
157
+ })
158
+ end
159
+ report_data << a_host
88
160
  end
89
161
  report_data
90
162
  end