foreman_acd 0.6.0 → 0.9.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (197) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +5 -5
  3. data/app/controllers/foreman_acd/ansible_playbooks_controller.rb +90 -0
  4. data/app/controllers/foreman_acd/app_definitions_controller.rb +104 -7
  5. data/app/controllers/foreman_acd/app_instances_controller.rb +34 -32
  6. data/app/controllers/foreman_acd/concerns/ansible_playbook_parameters.rb +1 -1
  7. data/app/controllers/foreman_acd/concerns/app_instance_mixins.rb +36 -0
  8. data/app/controllers/foreman_acd/remote_execution_controller.rb +37 -21
  9. data/app/controllers/ui_acd_controller.rb +42 -3
  10. data/app/lib/actions/foreman_acd/deploy_all_hosts.rb +12 -7
  11. data/app/lib/actions/foreman_acd/run_configurator.rb +11 -7
  12. data/app/models/concerns/foreman_acd/host_managed_extensions.rb +41 -28
  13. data/app/models/foreman_acd/acd_provider.rb +7 -1
  14. data/app/models/foreman_acd/ansible_playbook.rb +2 -1
  15. data/app/models/foreman_acd/app_instance.rb +48 -3
  16. data/app/models/foreman_acd/foreman_host.rb +8 -0
  17. data/app/services/foreman_acd/acd_proxy_proxy_selector.rb +17 -0
  18. data/app/services/foreman_acd/app_configurator.rb +59 -15
  19. data/app/services/foreman_acd/app_deployer.rb +27 -4
  20. data/app/services/foreman_acd/inventory_creator.rb +25 -1
  21. data/app/views/foreman_acd/ansible_playbooks/_form.html.erb +41 -7
  22. data/app/views/foreman_acd/app_definitions/_form.html.erb +5 -1
  23. data/app/views/foreman_acd/app_definitions/import.html.erb +20 -1
  24. data/app/views/foreman_acd/app_definitions/index.html.erb +3 -6
  25. data/app/views/foreman_acd/app_instances/_form.html.erb +5 -1
  26. data/app/views/foreman_acd/app_instances/index.html.erb +18 -12
  27. data/app/views/foreman_acd/app_instances/report.html.erb +8 -3
  28. data/app/views/templates/job/run_acd_ansible_playbook.erb +1 -1
  29. data/app/views/ui_acd/host_report.json.rabl +4 -0
  30. data/app/views/ui_acd/report_data.json.rabl +10 -0
  31. data/app/views/ui_acd/validate_hostname.json.rabl +6 -0
  32. data/config/routes.rb +6 -0
  33. data/db/migrate/20210316151145_add_git_commit_to_ansible_playbooks.rb +8 -0
  34. data/db/migrate/20210503122809_add_git_url_to_ansible_playbooks.rb +8 -0
  35. data/db/migrate/20210818125913_add_is_existing_host_to_foreman_host.rb +8 -0
  36. data/db/migrate/20210902110645_add_initial_configure_task.rb +8 -0
  37. data/db/seeds.d/75-job_templates.rb +1 -1
  38. data/lib/foreman_acd/engine.rb +26 -4
  39. data/lib/foreman_acd/plugin.rb +9 -18
  40. data/lib/foreman_acd/version.rb +1 -1
  41. data/lib/foreman_acd.rb +30 -0
  42. data/lib/tasks/foreman_acd_tasks.rake +0 -12
  43. data/package.json +8 -22
  44. data/test/controllers/ansible_playbooks_controller_test.rb +1 -1
  45. data/test/controllers/app_instances_controller_test.rb +8 -3
  46. data/test/controllers/ui_acd_controller_test.rb +25 -6
  47. data/test/factories/foreman_acd_factories.rb +18 -4
  48. data/test/models/acd_provider_test.rb +37 -0
  49. data/test/models/ansible_playbook_test.rb +11 -0
  50. data/test/models/app_definition_test.rb +1 -1
  51. data/test/models/app_instance_test.rb +2 -0
  52. data/test/models/concerns/host_extensions_test.rb +26 -0
  53. data/test/models/foreman_host_test.rb +12 -0
  54. data/webpack/__mocks__/foremanReact/API.js +2 -0
  55. data/webpack/__mocks__/foremanReact/common/I18n.js +3 -0
  56. data/webpack/__mocks__/foremanReact/common/helpers.js +2 -0
  57. data/webpack/__mocks__/foremanReact/components/ForemanModal/ForemanModalActions.js +2 -0
  58. data/webpack/__mocks__/foremanReact/components/ForemanModal.js +7 -0
  59. data/webpack/__mocks__/foremanReact/components/common/forms/CommonForm.js +2 -0
  60. data/webpack/__mocks__/foremanReact/components/common/forms/TextInput.js +2 -0
  61. data/webpack/__mocks__/foremanReact/components/hosts/powerStatus.js +1 -0
  62. data/webpack/__snapshots__/helper.test.js.snap +14 -0
  63. data/webpack/components/ApplicationDefinition/ApplicationDefinition.js +35 -11
  64. data/webpack/components/ApplicationDefinition/ApplicationDefinitionActions.js +12 -0
  65. data/webpack/components/ApplicationDefinition/ApplicationDefinitionConstants.js +1 -0
  66. data/webpack/components/ApplicationDefinition/ApplicationDefinitionReducer.js +30 -9
  67. data/webpack/components/ApplicationDefinition/ApplicationDefinitionSelectors.js +4 -0
  68. data/webpack/components/ApplicationDefinition/__fixtures__/applicationDefinitionConfData_1.fixtures.js +288 -0
  69. data/webpack/components/ApplicationDefinition/__fixtures__/applicationDefinitionReducer.fixtures.js +79 -0
  70. data/webpack/components/ApplicationDefinition/__tests__/ApplicationDefinition.test.js +26 -0
  71. data/webpack/components/ApplicationDefinition/__tests__/ApplicationDefinitionReducer.test.js +119 -0
  72. data/webpack/components/ApplicationDefinition/__tests__/ApplicationDefinitionSelectors.test.js +53 -0
  73. data/webpack/components/ApplicationDefinition/__tests__/__snapshots__/ApplicationDefinition.test.js.snap +226 -0
  74. data/webpack/components/ApplicationDefinition/__tests__/__snapshots__/ApplicationDefinitionReducer.test.js.snap +3033 -0
  75. data/webpack/components/ApplicationDefinition/__tests__/__snapshots__/ApplicationDefinitionSelectors.test.js.snap +307 -0
  76. data/webpack/components/ApplicationDefinition/components/AnsiblePlaybookSelector.js +2 -1
  77. data/webpack/components/ApplicationDefinition/components/__tests__/AnsiblePlaybookSelector.test.js +41 -0
  78. data/webpack/components/ApplicationDefinition/components/__tests__/__snapshots__/AnsiblePlaybookSelector.test.js.snap +121 -0
  79. data/webpack/components/ApplicationDefinition/index.js +8 -0
  80. data/webpack/components/ApplicationDefinitionImport/ApplicationDefinitionImport.js +214 -0
  81. data/webpack/components/ApplicationDefinitionImport/ApplicationDefinitionImport.scss +1 -0
  82. data/webpack/components/ApplicationDefinitionImport/ApplicationDefinitionImportActions.js +161 -0
  83. data/webpack/components/ApplicationDefinitionImport/ApplicationDefinitionImportConstants.js +6 -0
  84. data/webpack/components/ApplicationDefinitionImport/ApplicationDefinitionImportReducer.js +79 -0
  85. data/webpack/components/ApplicationDefinitionImport/ApplicationDefinitionImportSelectors.js +8 -0
  86. data/webpack/components/ApplicationDefinitionImport/__fixtures__/applicationDefinitionImportConfData_1.fixtures.js +129 -0
  87. data/webpack/components/ApplicationDefinitionImport/__fixtures__/applicationDefinitionImportReducer.fixtures.js +29 -0
  88. data/webpack/components/ApplicationDefinitionImport/__tests__/ApplicationDefinitionImport.test.js +20 -0
  89. data/webpack/components/ApplicationDefinitionImport/__tests__/ApplicationDefinitionImportReducer.test.js +43 -0
  90. data/webpack/components/ApplicationDefinitionImport/__tests__/ApplicationDefinitionImportSelectors.test.js +29 -0
  91. data/webpack/components/ApplicationDefinitionImport/__tests__/__snapshots__/ApplicationDefinitionImport.test.js.snap +62 -0
  92. data/webpack/components/ApplicationDefinitionImport/__tests__/__snapshots__/ApplicationDefinitionImportReducer.test.js.snap +362 -0
  93. data/webpack/components/ApplicationDefinitionImport/__tests__/__snapshots__/ApplicationDefinitionImportSelectors.test.js.snap +130 -0
  94. data/webpack/components/ApplicationDefinitionImport/index.js +32 -0
  95. data/webpack/components/ApplicationInstance/ApplicationInstance.js +105 -31
  96. data/webpack/components/ApplicationInstance/ApplicationInstanceActions.js +118 -6
  97. data/webpack/components/ApplicationInstance/ApplicationInstanceConstants.js +4 -0
  98. data/webpack/components/ApplicationInstance/ApplicationInstanceHelper.js +15 -0
  99. data/webpack/components/ApplicationInstance/ApplicationInstanceReducer.js +71 -30
  100. data/webpack/components/ApplicationInstance/ApplicationInstanceSelectors.js +4 -0
  101. data/webpack/components/ApplicationInstance/__fixtures__/applicationInstanceConfData_1.fixtures.js +263 -0
  102. data/webpack/components/ApplicationInstance/__fixtures__/applicationInstanceReducer.fixtures.js +80 -0
  103. data/webpack/components/ApplicationInstance/__tests__/ApplicationInstance.test.js +24 -0
  104. data/webpack/components/ApplicationInstance/__tests__/ApplicationInstanceReducer.test.js +131 -0
  105. data/webpack/components/ApplicationInstance/__tests__/ApplicationInstanceSelectors.test.js +56 -0
  106. data/webpack/components/ApplicationInstance/__tests__/__snapshots__/ApplicationInstance.test.js.snap +300 -0
  107. data/webpack/components/ApplicationInstance/__tests__/__snapshots__/ApplicationInstanceReducer.test.js.snap +2990 -0
  108. data/webpack/components/ApplicationInstance/__tests__/__snapshots__/ApplicationInstanceSelectors.test.js.snap +284 -0
  109. data/webpack/components/ApplicationInstance/components/AppDefinitionSelector.js +1 -0
  110. data/webpack/components/ApplicationInstance/components/ServiceCounter.js +1 -1
  111. data/webpack/components/ApplicationInstance/helper.js +0 -0
  112. data/webpack/components/ApplicationInstance/index.js +8 -0
  113. data/webpack/components/ApplicationInstanceReport/ApplicationInstanceReport.js +81 -6
  114. data/webpack/components/ApplicationInstanceReport/ApplicationInstanceReportActions.js +35 -1
  115. data/webpack/components/ApplicationInstanceReport/ApplicationInstanceReportConstants.js +3 -0
  116. data/webpack/components/ApplicationInstanceReport/ApplicationInstanceReportReducer.js +19 -0
  117. data/webpack/components/ApplicationInstanceReport/ApplicationInstanceReportSelectors.js +4 -0
  118. data/webpack/components/ApplicationInstanceReport/__fixtures__/applicationInstanceReportData_1.fixtures.js +349 -0
  119. data/webpack/components/ApplicationInstanceReport/__fixtures__/applicationInstanceReportReducer.fixtures.js +20 -0
  120. data/webpack/components/ApplicationInstanceReport/__tests__/ApplicationInstanceReport.test.js +47 -0
  121. data/webpack/components/ApplicationInstanceReport/__tests__/ApplicationInstanceReportReducer.test.js +41 -0
  122. data/webpack/components/ApplicationInstanceReport/__tests__/ApplicationInstanceReportSelectors.test.js +26 -0
  123. data/webpack/components/ApplicationInstanceReport/__tests__/__snapshots__/ApplicationInstanceReport.test.js.snap +7 -0
  124. data/webpack/components/ApplicationInstanceReport/__tests__/__snapshots__/ApplicationInstanceReportReducer.test.js.snap +718 -0
  125. data/webpack/components/ApplicationInstanceReport/__tests__/__snapshots__/ApplicationInstanceReportSelectors.test.js.snap +347 -0
  126. data/webpack/components/ApplicationInstanceReport/components/__tests__/ReportViewer.test.js +24 -0
  127. data/webpack/components/ApplicationInstanceReport/components/__tests__/__snapshots__/ReportViewer.test.js.snap +24 -0
  128. data/webpack/components/ApplicationInstanceReport/index.js +8 -1
  129. data/webpack/components/ExistingHostSelection/ExistingHostSelection.js +104 -0
  130. data/webpack/components/ExistingHostSelection/ExistingHostSelection.scss +15 -0
  131. data/webpack/components/ExistingHostSelection/ExistingHostSelectionActions.js +71 -0
  132. data/webpack/components/ExistingHostSelection/ExistingHostSelectionConstants.js +4 -0
  133. data/webpack/components/ExistingHostSelection/ExistingHostSelectionHelper.js +0 -0
  134. data/webpack/components/ExistingHostSelection/ExistingHostSelectionReducer.js +90 -0
  135. data/webpack/components/ExistingHostSelection/ExistingHostSelectionSelectors.js +8 -0
  136. data/webpack/components/ExistingHostSelection/__fixtures__/existingHostSelectionConfData_1.fixtures.js +191 -0
  137. data/webpack/components/ExistingHostSelection/__fixtures__/existingHostSelectionReducer.fixtures.js +203 -0
  138. data/webpack/components/ExistingHostSelection/__tests__/ExistingHostSelection.test.js +19 -0
  139. data/webpack/components/ExistingHostSelection/__tests__/ExistingHostSelectionReducer.test.js +59 -0
  140. data/webpack/components/ExistingHostSelection/__tests__/ExistingHostSelectionSelectors.test.js +36 -0
  141. data/webpack/components/ExistingHostSelection/__tests__/__snapshots__/ExistingHostSelection.test.js.snap +35 -0
  142. data/webpack/components/ExistingHostSelection/__tests__/__snapshots__/ExistingHostSelectionReducer.test.js.snap +614 -0
  143. data/webpack/components/ExistingHostSelection/__tests__/__snapshots__/ExistingHostSelectionSelectors.test.js.snap +27 -0
  144. data/webpack/components/ExistingHostSelection/components/ServiceSelector.js +48 -0
  145. data/webpack/components/ExistingHostSelection/components/__tests__/ServiceSelector.test.js +35 -0
  146. data/webpack/components/ExistingHostSelection/components/__tests__/__snapshots__/ServiceSelector.test.js.snap +77 -0
  147. data/webpack/components/ExistingHostSelection/index.js +26 -0
  148. data/webpack/components/ParameterSelection/ParameterSelection.js +103 -1
  149. data/webpack/components/ParameterSelection/ParameterSelection.scss +7 -0
  150. data/webpack/components/ParameterSelection/ParameterSelectionActions.js +46 -4
  151. data/webpack/components/ParameterSelection/ParameterSelectionConstants.js +2 -0
  152. data/webpack/components/ParameterSelection/ParameterSelectionHelper.js +5 -1
  153. data/webpack/components/ParameterSelection/ParameterSelectionReducer.js +51 -29
  154. data/webpack/components/ParameterSelection/ParameterSelectionSelectors.js +2 -0
  155. data/webpack/components/ParameterSelection/__fixtures__/parameterSelectionData_1.fixtures.js +124 -84
  156. data/webpack/components/ParameterSelection/__fixtures__/parameterSelectionReducer.fixtures.js +10 -4
  157. data/webpack/components/ParameterSelection/__tests__/ParameterSelection.test.js +36 -46
  158. data/webpack/components/ParameterSelection/__tests__/ParameterSelectionReducer.test.js +33 -25
  159. data/webpack/components/ParameterSelection/__tests__/ParameterSelectionSelectors.test.js +12 -6
  160. data/webpack/components/ParameterSelection/__tests__/__snapshots__/ParameterSelection.test.js.snap +84 -112
  161. data/webpack/components/ParameterSelection/__tests__/__snapshots__/ParameterSelectionReducer.test.js.snap +1589 -878
  162. data/webpack/components/ParameterSelection/__tests__/__snapshots__/ParameterSelectionSelectors.test.js.snap +130 -79
  163. data/webpack/components/ParameterSelection/index.js +4 -1
  164. data/webpack/components/SyncGitRepo/SyncGitRepo.js +202 -0
  165. data/webpack/components/SyncGitRepo/SyncGitRepo.scss +1 -0
  166. data/webpack/components/SyncGitRepo/SyncGitRepoActions.js +123 -0
  167. data/webpack/components/SyncGitRepo/SyncGitRepoConstants.js +8 -0
  168. data/webpack/components/SyncGitRepo/SyncGitRepoReducer.js +80 -0
  169. data/webpack/components/SyncGitRepo/SyncGitRepoSelectors.js +6 -0
  170. data/webpack/components/SyncGitRepo/__fixtures__/syncGitRepoConfData_1.fixtures.js +7 -0
  171. data/webpack/components/SyncGitRepo/__fixtures__/syncGitRepoReducer.fixtures.js +44 -0
  172. data/webpack/components/SyncGitRepo/__tests__/SyncGitRepo.test.js +27 -0
  173. data/webpack/components/SyncGitRepo/__tests__/SyncGitRepoReducer.test.js +95 -0
  174. data/webpack/components/SyncGitRepo/__tests__/SyncGitRepoSelectors.test.js +32 -0
  175. data/webpack/components/SyncGitRepo/__tests__/__snapshots__/SyncGitRepo.test.js.snap +31 -0
  176. data/webpack/components/SyncGitRepo/__tests__/__snapshots__/SyncGitRepoReducer.test.js.snap +137 -0
  177. data/webpack/components/SyncGitRepo/__tests__/__snapshots__/SyncGitRepoSelectors.test.js.snap +13 -0
  178. data/webpack/components/SyncGitRepo/components/FormTextInput.js +42 -0
  179. data/webpack/components/SyncGitRepo/components/ScmTypeSelector.js +47 -0
  180. data/webpack/components/SyncGitRepo/index.js +28 -0
  181. data/webpack/components/common/DeleteTableEntry.js +16 -2
  182. data/webpack/components/common/ExtTextInput.js +43 -0
  183. data/webpack/components/common/__tests__/EditTableEntry.test.js +53 -0
  184. data/webpack/components/common/__tests__/LockTableEntry.test.js +35 -0
  185. data/webpack/components/common/__tests__/__snapshots__/DeleteTableEntry.test.js.snap +40 -2
  186. data/webpack/components/common/__tests__/__snapshots__/EditTableEntry.test.js.snap +81 -0
  187. data/webpack/components/common/__tests__/__snapshots__/LockTableEntry.test.js.snap +60 -0
  188. data/webpack/helper.js +35 -1
  189. data/webpack/helper.test.js +56 -0
  190. data/webpack/index.js +7 -0
  191. data/webpack/js-yaml.js +3874 -0
  192. data/webpack/reducer.js +16 -1
  193. data/webpack/test_setup.js +0 -2
  194. metadata +136 -11
  195. data/webpack/components/common/EasyHeaderFormatter.js +0 -18
  196. data/webpack/components/common/__tests__/__snapshots__/AddParameter.test.js.snap +0 -35
  197. data/webpack/components/common/__tests__/__snapshots__/DeleteParameter.test.js.snap +0 -41
@@ -53,21 +53,25 @@
53
53
  <div class="modal-content">
54
54
  <div class="modal-header">
55
55
  <button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">&times;</span><span class="sr-only">Close</span></button>
56
- <h4 class="modal-title"><%= _('Confirmation Box')%></h4>
56
+ <h4 class="modal-title"><%= _('Confirmation')%></h4>
57
57
  </div>
58
58
  <div class="modal-body">
59
- <p> <%= _("Confirm to delete ") %> <%= app_instance %></p>
59
+ <p> <%= _("Confirm to delete application instance: ") %> <%= app_instance %></p>
60
60
  <%= form_tag destroy_with_hosts_app_instance_path(:id => app_instance.id), :method => :delete do %>
61
- <% if app_instance.foreman_hosts.where.not(:host_id => [nil, false]).any? %>
62
- <p><%= _("Select the hosts to delete along with ") %> <%= app_instance %>: </p>
63
- <% end %>
64
- <% app_instance.foreman_hosts.each do |foreman_host|%>
61
+ <% showSelectHostsNote = true %>
62
+ <% app_instance.foreman_hosts.select(&:fresh_host?).each do |foreman_host|%>
65
63
  <% if foreman_host.host_id? %>
66
- <%= check_box_tag 'foreman_host_ids[]', foreman_host.host_id -%>
67
- <%= h foreman_host.host.name -%>
68
- </br>
64
+ <% if showSelectHostsNote %>
65
+ <p><%= _("Select the hosts to delete along with ") %> <%= app_instance %>: </p>
66
+ <% showSelectHostsNote = false %>
67
+ <% end %>
68
+ <%= check_box_tag 'foreman_host_ids[]', foreman_host.host_id, false, class: 'acd_host' -%> <%= h foreman_host.host.name -%>
69
+ </br>
69
70
  <% end %>
70
71
  <% end %>
72
+ <hr width="90%">
73
+ <p> <%= check_box_tag "check_all", "", false, { :onchange => "toggleCheckboxesBySelector('.acd_host')" } %> Select / unselect all hosts</p>
74
+ <br /><p><%= _("Note: Hosts which already existed and were added to the application instance are not shown in this dialog!") %></p>
71
75
  </div>
72
76
  <div class="modal-footer">
73
77
  <button type="button" class="btn btn-primary" data-dismiss="modal"><%= _('Cancel') %></button>
@@ -89,10 +93,12 @@
89
93
  <div class="modal-body">
90
94
  <p><%= _('Confirm to deploy ') %><%= app_instance%></p>
91
95
  <%= form_tag deploy_app_instance_path(:id => app_instance.id), :method => :post do %>
92
- <!-- TODO: Add safe-deploy method with delete all hosts option
93
96
  <% if app_instance.foreman_hosts.where.not(:host_id => [nil, false]).any? %>
94
- <%= check_box_tag 'delete_hosts'-%><%= _('Delete all hosts before deploying ') %><%= app_instance%>
95
- <% end %> -->
97
+ <ul>
98
+ <li><%= check_box_tag 'delete_hosts'-%> <%= _('Delete all hosts before deploying ') %><%= app_instance%></li>
99
+ <li><%= check_box_tag 'safe_deploy' -%> <%= _('Deploy only new and changed hosts for ') %><%= app_instance%></li>
100
+ </ul>
101
+ <% end %>
96
102
  </div>
97
103
  <div class="modal-footer">
98
104
  <button type="button" class="btn btn-danger" data-dismiss="modal"><%= _('Cancel') %></button>
@@ -9,14 +9,19 @@
9
9
 
10
10
  <%
11
11
  json = {
12
- "mode": 'lastReport',
12
+ "deploymentState": @app_instance.deployment_state.to_s,
13
+ "initialConfigureState": @app_instance.initial_configure_state.to_s,
13
14
  "appInstanceName": @app_instance.name,
14
15
  "hosts": @report_hosts,
15
16
  "deployTaskUrl": foreman_tasks_task_path(@app_instance.last_deploy_task),
16
- "configureJobUrl": job_invocations_path(search: "description ~ \"ACD application #{@app_instance.name}\"")
17
+ "configureJobUrl": job_invocations_path(search: "description ~ \"ACD application #{@app_instance.name}\""),
18
+ "reportDataUrl": ui_acd_report_data_path("__id__"),
19
+ "appInstanceId": @app_instance.id,
17
20
  }
21
+
22
+ json["initialConfigureJobUrl"] = job_invocation_path(@app_instance.initial_configure_job) unless @app_instance.initial_configure_job.nil?
18
23
  %>
19
24
 
20
25
  <div id='report'></div>
21
- <%= mount_react_component('ApplicationInstanceReport', "#report", json.to_json) %>
26
+ <%= react_component('ApplicationInstanceReport', :data => json) %>
22
27
  </div
@@ -3,7 +3,7 @@ kind: job_template
3
3
  name: Run ACD Ansible Playbook - ACD Default
4
4
  model: JobTemplate
5
5
  job_category: Application Centric Deployment
6
- description_format: "Run Ansible playbook %{playbook_name} for ACD application %{application_name}"
6
+ description_format: "Run Ansible playbook to configure ACD application %{application_name}"
7
7
  feature: run_acd_ansible_playbook
8
8
  provider_type: ACD
9
9
  template_inputs:
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ collection @hosts
4
+ attributes :id, :name, :build, :hostUrl, :isExistingHost, :progress_report, :powerStatusUrl
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ object @report_data
4
+ attribute :deploymentState
5
+ attribute :initialConfigureState
6
+ attribute :initialConfigureJobUrl
7
+
8
+ child :hosts => :hosts do
9
+ extends 'ui_acd/host_report'
10
+ end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ object @host_validation
4
+ attribute :hostname
5
+ attribute :fqdn
6
+ attribute :result
data/config/routes.rb CHANGED
@@ -5,9 +5,12 @@ Rails.application.routes.draw do
5
5
  resources :ansible_playbooks, :controller => 'foreman_acd/ansible_playbooks' do
6
6
  collection do
7
7
  get 'auto_complete_search'
8
+ put 'sync_git_repo'
9
+ post 'sync_git_repo'
8
10
  end
9
11
 
10
12
  member do
13
+ post 'sync_git_repo'
11
14
  get 'import_vars'
12
15
  end
13
16
  end
@@ -15,6 +18,7 @@ Rails.application.routes.draw do
15
18
  collection do
16
19
  get 'auto_complete_search'
17
20
  get 'import'
21
+ post 'handle_file_upload'
18
22
  end
19
23
 
20
24
  member do
@@ -39,6 +43,8 @@ Rails.application.routes.draw do
39
43
  get 'ui_acd_app/:id', :to => 'ui_acd#app', :constraints => { :id => /[\w\.-]+/ }, :as => :ui_acd_app
40
44
  get 'ui_acd_foreman_data/:id', :to => 'ui_acd#foreman_data', :constraints => { :id => /[\w\.-]+/ }, :as => :ui_acd_foreman_data
41
45
  get 'ui_acd_ansible_data/:id', :to => 'ui_acd#ansible_data', :constraints => { :id => /[\w\.-]+/ }, :as => :ui_acd_ansible_data
46
+ get 'ui_acd_report_data/:id', :to => 'ui_acd#report_data', :constraints => { :id => /[\w\.-]+/ }, :as => :ui_acd_report_data
47
+ get 'ui_acd_validate_hostname', :to => 'ui_acd#validate_hostname', :as => :ui_acd_validate_hostname
42
48
 
43
49
  scope :api, :path => '/api', :defaults => { :format => 'json' } do
44
50
  scope '(:apiv)', :defaults => { :apiv => 'v2' },
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Add git_commit column to ansible_playbook
4
+ class AddGitCommitToAnsiblePlaybooks < ActiveRecord::Migration[6.0]
5
+ def change
6
+ add_column :acd_ansible_playbooks, :git_commit, :string
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Add git_url column to ansible_playbook
4
+ class AddGitUrlToAnsiblePlaybooks < ActiveRecord::Migration[6.0]
5
+ def change
6
+ add_column :acd_ansible_playbooks, :git_url, :string
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Add is_existing_host to app instance
4
+ class AddIsExistingHostToForemanHost < ActiveRecord::Migration[6.0]
5
+ def change
6
+ add_column :acd_foreman_hosts, :is_existing_host, :boolean, :default => false, :null => false
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Add AddInitialConfigureTask
4
+ class AddInitialConfigureTask < ActiveRecord::Migration[5.2]
5
+ def change
6
+ add_column :acd_app_instances, :initial_configure_task_id, :uuid, :null => true
7
+ end
8
+ end
@@ -4,7 +4,7 @@ User.as_anonymous_admin do
4
4
  JobTemplate.without_auditing do
5
5
  Dir[File.join("#{ForemanAcd::Engine.root}/app/views/templates/**/*.erb")].each do |template|
6
6
  sync = !Rails.env.test? && Setting[:remote_execution_sync_templates]
7
- template = JobTemplate.import_raw!(File.read(template), :default => true, :locked => true, :update => sync)
7
+ template = JobTemplate.import_raw!(File.read(template), :default => true, :lock => true, :update => sync)
8
8
 
9
9
  template.organizations << Organization.unscoped.all if template&.organizations&.empty?
10
10
  template.locations << Location.unscoped.all if template&.locations&.empty?
@@ -1,7 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'foreman_remote_execution'
4
+ require 'git'
4
5
 
6
+ # The ForemanAcd module
5
7
  module ForemanAcd
6
8
  # This engine connects ForemanAcd with Foreman core
7
9
  class Engine < ::Rails::Engine
@@ -49,13 +51,33 @@ module ForemanAcd
49
51
  end
50
52
 
51
53
  config.to_prepare do
52
- RemoteExecutionProvider.register(:ACD, AcdProvider)
53
54
  ::Taxonomy.include ForemanAcd::TaxonomyExtensions
54
55
  ::Host::Managed.prepend ForemanAcd::HostManagedExtensions
55
- end
56
56
 
57
- def self.with_katello?
58
- defined?(::Katello)
57
+ RemoteExecutionProvider.register(:ACD, AcdProvider)
58
+ ForemanAcd.register_rex_feature
59
59
  end
60
60
  end
61
+
62
+ def self.with_katello?
63
+ defined?(::Katello)
64
+ end
65
+
66
+ def self.with_remote_execution?
67
+ RemoteExecutionFeature
68
+ rescue StandardError
69
+ false
70
+ end
71
+
72
+ def self.register_rex_feature
73
+ return unless ForemanAcd.with_remote_execution?
74
+ RemoteExecutionFeature.register(
75
+ :run_acd_ansible_playbook,
76
+ N_('Run playbook for ACD'),
77
+ {
78
+ :description => N_('Run an Ansible playbook to configure ACD application'),
79
+ :provided_inputs => %w[application_name playbook_name playbook_path inventory_path]
80
+ }
81
+ )
82
+ end
61
83
  end
@@ -33,7 +33,7 @@ Foreman::Plugin.register :foreman_acd do
33
33
  :resource_type => 'ForemanAcd::AnsiblePlaybook'
34
34
 
35
35
  permission :edit_ansible_playbooks,
36
- { :'foreman_acd/ansible_playbooks' => [:update, :edit],
36
+ { :'foreman_acd/ansible_playbooks' => [:update, :edit, :sync_git_repo],
37
37
  :'foreman_acd/api/v2/ansible_playbooks' => [:update] },
38
38
  :resource_type => 'ForemanAcd::AnsiblePlaybook'
39
39
 
@@ -72,7 +72,7 @@ Foreman::Plugin.register :foreman_acd do
72
72
  :resource_type => 'ForemanAcd::AppDefinition'
73
73
 
74
74
  permission :export_app_definitions,
75
- { :'foreman_acd/app_definitions' => [:export],
75
+ { :'foreman_acd/app_definitions' => [:export, :handle_file_upload],
76
76
  :'foreman_acd/api/v2/app_definitions' => [:export] },
77
77
  :resource_type => 'ForemanAcd::AppDefinition'
78
78
 
@@ -111,16 +111,16 @@ Foreman::Plugin.register :foreman_acd do
111
111
  :'foreman_acd/api/v2/app_instances' => [:report] },
112
112
  :resource_type => 'ForemanAcd::AppInstance'
113
113
 
114
- permission :new_remote_execution,
114
+ permission :new_acd_configure_job,
115
115
  { :'foreman_acd/remote_execution' => [:new] },
116
- :resource_type => 'ForemanAcd::RemoteExecution'
116
+ :resource_type => 'ForemanAcd::AppInstance'
117
117
 
118
- permission :create_remote_execution,
118
+ permission :create_acd_configure_job,
119
119
  { :'foreman_acd/remote_execution' => [:create] },
120
- :resource_type => 'ForemanAcd::RemoteExecution'
120
+ :resource_type => 'ForemanAcd::AppInstance'
121
121
 
122
122
  permission :view_ui_acd,
123
- { :ui_acd => [:app, :foreman_data, :ansible_data] }
123
+ { :ui_acd => [:app, :foreman_data, :ansible_data, :validate_hostname, :report_data] }
124
124
 
125
125
  permission :acd_foreman_hosts,
126
126
  { :'foreman_acd/app_instances' => [:create, :edit, :update, :deploy, :destroy_with_hosts, :destroy] },
@@ -137,7 +137,7 @@ Foreman::Plugin.register :foreman_acd do
137
137
  :create_app_instances, :view_app_instances, :edit_app_instances,
138
138
  :destroy_app_instances,
139
139
  :deploy_app_instances,
140
- :new_remote_execution, :create_remote_execution,
140
+ :new_acd_configure_job, :create_acd_configure_job,
141
141
  :report_app_instances,
142
142
  :view_ui_acd,
143
143
  :view_hosts, :build_hosts, :power_hosts, :create_hosts, :edit_hosts, :destroy_hosts, :console_hosts,
@@ -150,7 +150,7 @@ Foreman::Plugin.register :foreman_acd do
150
150
  role 'Application Centric Deployment User', [:create_app_instances, :view_app_instances, :edit_app_instances,
151
151
  :destroy_app_instances,
152
152
  :deploy_app_instances,
153
- :new_remote_execution, :create_remote_execution,
153
+ :new_acd_configure_job, :create_acd_configure_job,
154
154
  :report_app_instances,
155
155
  :view_ui_acd,
156
156
  :view_hosts, :build_hosts, :power_hosts, :create_hosts, :edit_hosts, :destroy_hosts, :console_hosts,
@@ -160,13 +160,4 @@ Foreman::Plugin.register :foreman_acd do
160
160
  :acd_foreman_hosts, :view_smart_proxies]
161
161
 
162
162
  add_all_permissions_to_default_roles
163
-
164
- RemoteExecutionFeature.register(
165
- :run_acd_ansible_playbook,
166
- N_('Run playbook for ACD'),
167
- {
168
- :description => N_('Run an Ansible playbook to configure ACD application'),
169
- :provided_inputs => %w[application_name playbook_name playbook_path inventory_path]
170
- }
171
- )
172
163
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ForemanAcd
4
- VERSION = '0.6.0'
4
+ VERSION = '0.9.1'
5
5
  end
data/lib/foreman_acd.rb CHANGED
@@ -4,4 +4,34 @@ require 'foreman_acd/engine'
4
4
 
5
5
  # Module required to start the Foreman Rails engine
6
6
  module ForemanAcd
7
+ RUN_CONFIGURATOR_DELAY = 240
8
+
9
+ class << self
10
+ def acd_base_path
11
+ '/var/lib/foreman/foreman_acd/'
12
+ end
13
+
14
+ def ansible_playbook_path
15
+ File.join(acd_base_path, 'ansible-playbooks')
16
+ end
17
+
18
+ def proxy_setting
19
+ HttpProxy.default_global_content_proxy&.full_url ||
20
+ Setting[:http_proxy]
21
+ end
22
+
23
+ def initiate_acd_app_configurator(app_instance)
24
+ return unless app_instance.hosts_deployment_finished?
25
+
26
+ ::Foreman::Logging.logger('foreman_acd').info("All hosts of app (#{app_instance.name}) were built. Schedule app configurator...")
27
+ start_acd_app_configurator(app_instance)
28
+ end
29
+
30
+ def start_acd_app_configurator(app_instance)
31
+ task = ForemanTasks.delay(::Actions::ForemanAcd::RunConfigurator,
32
+ { :start_at => Time.zone.now + RUN_CONFIGURATOR_DELAY },
33
+ app_instance)
34
+ app_instance.update(:initial_configure_task_id => task.id)
35
+ end
36
+ end
7
37
  end
@@ -1,17 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'rake/testtask'
4
-
5
- # Tasks
6
- namespace :foreman_acd do
7
- namespace :example do
8
- desc 'Example Task'
9
- task :task => :environment do
10
- # Task goes here
11
- end
12
- end
13
- end
14
-
15
3
  # Tests
16
4
  namespace :test do
17
5
  desc 'Test ForemanAcd'
data/package.json CHANGED
@@ -1,42 +1,28 @@
1
1
  {
2
2
  "name": "foreman_acd",
3
- "version": "0.3.0",
3
+ "version": "0.9.0",
4
4
  "description": "foreman application centric deployment",
5
5
  "main": "index.js",
6
6
  "directories": {
7
7
  "test": "test"
8
8
  },
9
9
  "dependencies": {
10
- "@theforeman/vendor": "^1.7.0",
10
+ "@theforeman/vendor": "^4.14.0",
11
11
  "react-intl": "^2.8.0"
12
12
  },
13
13
  "devDependencies": {
14
- "@theforeman/vendor-dev": "^1.7.0",
15
- "babel-eslint": "^8.2.1",
16
- "babel-jest": "^23.6.0",
17
- "babel-plugin-dynamic-import-node": "^2.0.0",
14
+ "@theforeman/builder": "^4.14.0",
15
+ "@theforeman/vendor-dev": "^4.14.0",
18
16
  "babel-plugin-transform-class-properties": "^6.24.1",
19
- "babel-plugin-transform-object-assign": "^6.22.0",
20
- "babel-plugin-transform-object-rest-spread": "^6.26.0",
21
- "babel-plugin-syntax-dynamic-import": "^6.18.0",
22
17
  "babel-preset-env": "^1.6.0",
23
18
  "babel-preset-react": "^6.24.1",
24
- "enzyme": "^3.7.0",
25
- "enzyme-adapter-react-16": "^1.7.0",
26
- "enzyme-to-json": "^3.3.5",
27
- "eslint": "^4.18.1",
28
- "eslint-plugin-import": "^2.8.0",
29
- "eslint-plugin-jest": "^21.2.0",
30
- "eslint-plugin-patternfly-react": "^0.2.1",
31
- "eslint-plugin-react": "^7.4.0",
19
+ "enzyme": "^3.11.0",
20
+ "enzyme-adapter-react-16": "^1.15.6",
21
+ "enzyme-to-json": "^3.6.1",
32
22
  "identity-obj-proxy": "^3.0.0",
33
- "lodash": "^4.17.11",
34
23
  "jest": "^23.6.0",
35
- "jest-cli": "^23.6.0",
36
24
  "jest-prop-type-error": "^1.1.0",
37
- "react-redux-test-utils": "^0.1.1",
38
- "sortabular": "~1.5.1",
39
- "table-resolver": "~3.2.0"
25
+ "react-redux-test-utils": "^0.1.1"
40
26
  },
41
27
  "scripts": {
42
28
  "test": "node node_modules/.bin/jest --no-cache"
@@ -11,7 +11,7 @@ module ForemanAcd
11
11
  @model = ForemanAcd::AnsiblePlaybook.first
12
12
  end
13
13
 
14
- basic_index_test('ansible_playbook')
14
+ basic_index_test('ansible_playbooks')
15
15
  basic_new_test
16
16
  basic_edit_test('ansible_playbook')
17
17
 
@@ -11,17 +11,22 @@ module ForemanAcd
11
11
  @model = ForemanAcd::AppInstance.first
12
12
  end
13
13
 
14
+ def set_session_user
15
+ org_a = Organization.find_by(:name => 'Organization 1')
16
+ loc_a = Location.find_by(:name => 'Location 1')
17
+ super.merge(:location_id => loc_a.id, :organization_id => org_a.id)
18
+ end
19
+
14
20
  basic_index_test('app_instances')
15
21
  basic_new_test
16
- basic_edit_test('app_instance')
22
+ # basic_edit_test('app_instance')
17
23
 
18
24
  test 'should destroy app instance' do
19
25
  assert_difference('AppInstance.count', -1) do
20
- delete :destroy,
26
+ delete :destroy_with_hosts,
21
27
  :params => { :id => @model.id },
22
28
  :session => set_session_user
23
29
  end
24
- assert_redirected_to app_instances_url
25
30
  end
26
31
  end
27
32
  end
@@ -19,20 +19,39 @@ class UiAcdControllerTest < ActionController::TestCase
19
19
  get :app, :params => { :id => app_def.id }, :session => set_session_user
20
20
  assert_response :success
21
21
 
22
+ json_app_services = JSON.parse(app_def.services)
23
+ json_app_all = JSON.parse(app_def.ansible_vars_all)
24
+ parsed_services_response = JSON.parse(json_response['app_definition']['services'])
25
+ parsed_all_response = JSON.parse(json_response['app_definition']['ansible_vars_all'])
26
+
22
27
  assert_equal app_def.name, json_response['app_definition']['name']
23
- assert_equal app_def.hostgroup_id, json_response['fdata']['hostgroup_id']
24
- assert_equal app_def.hostgroup.domain.name, json_response['fdata']['domains'][0]['name']
25
- assert_equal app_def.hostgroup.environment.name, json_response['fdata']['environments'][0]['name']
26
- assert_equal app_def.hostgroup.ptable.name, json_response['fdata']['ptables'][0]['name']
28
+ assert_equal json_app_services.first['name'], parsed_services_response.first['name']
29
+ assert_equal json_app_services.first['ansibleGroup'], parsed_services_response.first['ansibleGroup']
30
+ assert_equal json_app_all.first['name'], parsed_all_response.first['name']
27
31
  end
28
32
 
29
- test 'get fdata json' do
33
+ test 'get foreman data json foreman <3' do
34
+ # TODO: Get rid of the puppet dependency at all!
35
+ skip 'Puppet env was removed with foreman >= 3.x' unless defined?(ForemanPuppet)
36
+
30
37
  hostgroup = FactoryBot.create(:hostgroup, :with_domain, :with_os, :with_environment)
31
- get :fdata, :params => { :id => hostgroup.id }, :session => set_session_user
38
+ get :foreman_data, :params => { :id => hostgroup.id }, :session => set_session_user
32
39
  assert_response :success
33
40
 
41
+ assert_equal hostgroup.id, json_response['hostgroup_id']
34
42
  assert_equal hostgroup.environment.name, json_response['environments'][0]['name']
35
43
  assert_equal hostgroup.domain.name, json_response['domains'][0]['name']
36
44
  assert_equal hostgroup.ptable.name, json_response['ptables'][0]['name']
37
45
  end
46
+
47
+ test 'get ansible data json' do
48
+ ansible_playbook = FactoryBot.create(:ansible_playbook)
49
+ get :ansible_data, :params => { :id => ansible_playbook.id }, :session => set_session_user
50
+ assert_response :success
51
+
52
+ json_playbook = JSON.parse(ansible_playbook.vars)
53
+ assert_equal ansible_playbook.name, json_response['name']
54
+ assert_equal json_playbook['dbservers']['mysqlservice'], json_response['groups']['dbservers']['mysqlservice']
55
+ assert_equal json_playbook['all']['repository'], json_response['groups']['all']['repository']
56
+ end
38
57
  end
@@ -1,17 +1,31 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  FactoryBot.define do
4
+ factory :ansible_playbook, :class => 'ForemanAcd::AnsiblePlaybook' do
5
+ sequence(:name) { |n| "ansible_playbook#{n}" }
6
+ sequence(:description) { |n| "description#{n}" }
7
+ scm_type { 'directory' }
8
+ path { '/home/vagrant/acd_examples/ansible-playbook' }
9
+ playfile { 'site.yml' }
10
+ vars { '{"dbservers":{"mysqlservice":"mysqld","mysql_port":3306,"dbuser":"webapp","dbname":"ANSAP01","upassword":"Bond@007","masterpassword":"MySQL@007"},"all":{"repository":"https://github.com/bennojoy/mywebapp.git"},"webservers":{"dummy_var":0}}' }
11
+ end
12
+
4
13
  factory :app_definition, :class => 'ForemanAcd::AppDefinition' do
5
14
  sequence(:name) { |n| "app_definition#{n}" }
6
15
  sequence(:description) { |n| "description#{n}" }
7
- hostgroup { FactoryBot.create(:hostgroup, :with_domain, :with_os, :with_environment) }
8
- parameters { '[{"id":0,"name":"Hostname","description":"","type":"hostname","value":"mysqllinux"},{"id":1,"name":"RootPW","description":"","type":"password","value":"sesam12345"},{"id":2,"name":"ansible_root","description":"","type":"hostparam","value":"/root/ansible"}]' }
16
+ ansible_playbook
17
+ services do
18
+ '[{"id":1,"name":"DB","description":"","hostgroup":"1","ansibleGroup":"dbservers","minCount":"","maxCount":"","foremanParameters":[],"ansibleParameters":[{"id":0,"name":"mysqlservice","value":"mysqld"},{"id":1,"name":"mysql_port","value":"3306"},{"id":2,"name":"dbuser","value":"webapp"},{"id":3,"name":"dbname","value":"ANSAP01"},{"id":4,"name":"upassword","value":"Bond@007"},{"id":5,"name":"masterpassword","value":"MySQL@007"}]},{"id":2,"name":"Web","description":"","hostgroup":"1","ansibleGroup":"webservers","minCount":"","maxCount":"","foremanParameters":[],"ansibleParameters":[{"id":0,"name":"dummy_var","value":"0"}]}]'
19
+ end
20
+ ansible_vars_all { '[{"id":0,"name":"repository","value":"https://github.com/bennojoy/mywebapp.git"}]' }
9
21
  end
10
22
 
11
23
  factory :app_instance, :class => 'ForemanAcd::AppInstance' do
12
24
  sequence(:name) { |n| "app_instance#{n}" }
13
- app_definition { FactoryBot.create(:app_definition) }
14
25
  sequence(:description) { |n| "description#{n}" }
15
- parameters { '[{"id":0,"name":"Hostname","description":"","type":"hostname","value":"mysqllinux"},{"id":1,"name":"RootPW","description":"","type":"password","value":"sesam12345"},{"id":2,"name":"ansible_root","description":"","type":"hostparam","value":"/root/ansible"}]' }
26
+ app_definition
27
+ location { Location.find_by(:name => 'Location 1') }
28
+ organization { Organization.find_by(:name => 'Organization 1') }
29
+ ansible_vars_all { '[{"id":0,"name":"repository","value":"https://github.com/bennojoy/mywebapp.git"}]' }
16
30
  end
17
31
  end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'test_plugin_helper'
4
+
5
+ module ForemanAcd
6
+ # ACD Provider Test
7
+ class AcdProviderTest < ActiveSupport::TestCase
8
+ describe '.provider_names' do
9
+ let(:provider_names) { AcdProvider.provider_names }
10
+
11
+ it 'returns only strings' do
12
+ provider_names.each do |name|
13
+ _(name).must_be_kind_of String
14
+ end
15
+ end
16
+
17
+ context 'provider is registetered under :custom symbol' do
18
+ before { AcdProvider.register(:ACD, String) }
19
+ it { _(provider_names).must_include 'ACD' }
20
+ end
21
+ end
22
+
23
+ describe AcdProvider do
24
+ before { User.current = FactoryBot.build(:user, :admin) }
25
+ after { User.current = nil }
26
+
27
+ before do
28
+ Setting::RemoteExecution.load_defaults
29
+ end
30
+
31
+ let(:job_invocation) { FactoryBot.create(:job_invocation, :with_template) }
32
+ let(:template_invocation) { job_invocation.pattern_template_invocations.first }
33
+ let(:host) { FactoryBot.create(:host) }
34
+ let(:proxy_options) { AcdProvider.proxy_command_options(template_invocation, host) }
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'test_plugin_helper'
4
+
5
+ module ForemanAcd
6
+ # Ansible Playbook Model tests
7
+ class AnsiblePlaybookTest < ActiveSupport::TestCase
8
+ should validate_presence_of(:name)
9
+ should validate_uniqueness_of(:name)
10
+ end
11
+ end
@@ -7,7 +7,7 @@ module ForemanAcd
7
7
  class AppDefinitionTest < ActiveSupport::TestCase
8
8
  should validate_presence_of(:name)
9
9
  should validate_uniqueness_of(:name)
10
- should belong_to(:hostgroup)
10
+ should belong_to(:ansible_playbook)
11
11
  should have_many(:app_instances).dependent(:destroy)
12
12
  end
13
13
  end
@@ -7,5 +7,7 @@ module ForemanAcd
7
7
  class AppInstanceTest < ActiveSupport::TestCase
8
8
  should validate_presence_of(:name)
9
9
  should belong_to(:app_definition)
10
+ should belong_to(:location)
11
+ should belong_to(:organization)
10
12
  end
11
13
  end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'test_plugin_helper'
4
+
5
+ module ForemanAcd
6
+ # Host Extensions Test
7
+ class HostExtensionsTest < ActiveSupport::TestCase
8
+ setup do
9
+ User.current = users :admin
10
+ end
11
+
12
+ test 'host was deployed via acd?' do
13
+ host = FactoryBot.create :host
14
+ app = FactoryBot.create :app_instance
15
+
16
+ foreman_host = app.foreman_hosts.create(:hostname => host.name,
17
+ :service => 'DB',
18
+ :description => 'Description',
19
+ :foremanParameters => nil,
20
+ :ansibleParameters => nil)
21
+ foreman_host.host = host
22
+ foreman_host.save
23
+ assert host.deployed_via_acd?
24
+ end
25
+ end
26
+ end