foreman_ansible 10.0.1 → 10.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. data/app/helpers/foreman_ansible/smart_proxies_helper.rb +38 -0
  3. data/app/views/foreman/smart_proxies/_update_smart_proxy.html.erb +1 -0
  4. data/app/views/foreman_ansible/job_templates/capsule_upgrade_-_ansible_default.erb +39 -3
  5. data/db/migrate/20221031114720_rename_capsule_upgrade_playbook.rb +21 -0
  6. data/lib/foreman_ansible/register.rb +13 -0
  7. data/lib/foreman_ansible/version.rb +1 -1
  8. data/test/graphql/queries/host_ansible_roles_query_test.rb +11 -8
  9. data/test/unit/ansible_provider_test.rb +3 -6
  10. data/test/unit/concerns/host_managed_extensions_test.rb +6 -6
  11. data/test/unit/concerns/hostgroup_extensions_test.rb +8 -8
  12. data/webpack/components/AnsibleHostDetail/components/JobsTab/NewRecurringJobHelper.js +4 -4
  13. data/webpack/components/AnsibleHostDetail/components/JobsTab/NewRecurringJobModal.js +30 -4
  14. data/webpack/components/AnsibleHostDetail/components/JobsTab/NewRecurringJobModal.scss +9 -2
  15. data/webpack/components/AnsibleHostDetail/components/RolesTab/AllRolesModal/index.js +1 -1
  16. data/webpack/components/AnsibleHostDetail/components/RolesTab/EditRolesModal/index.js +1 -1
  17. metadata +24 -62
  18. data/locale/ca/foreman_ansible.edit.po +0 -1162
  19. data/locale/ca/foreman_ansible.po.time_stamp +0 -0
  20. data/locale/cs_CZ/foreman_ansible.edit.po +0 -1207
  21. data/locale/cs_CZ/foreman_ansible.po.time_stamp +0 -0
  22. data/locale/de/foreman_ansible.edit.po +0 -1148
  23. data/locale/de/foreman_ansible.po.time_stamp +0 -0
  24. data/locale/en/foreman_ansible.edit.po +0 -1146
  25. data/locale/en/foreman_ansible.po.time_stamp +0 -0
  26. data/locale/en_GB/foreman_ansible.edit.po +0 -1155
  27. data/locale/en_GB/foreman_ansible.po.time_stamp +0 -0
  28. data/locale/es/foreman_ansible.edit.po +0 -1148
  29. data/locale/es/foreman_ansible.po.time_stamp +0 -0
  30. data/locale/fr/foreman_ansible.edit.po +0 -1148
  31. data/locale/fr/foreman_ansible.po.time_stamp +0 -0
  32. data/locale/gl/foreman_ansible.edit.po +0 -1156
  33. data/locale/gl/foreman_ansible.po.time_stamp +0 -0
  34. data/locale/it/foreman_ansible.edit.po +0 -1148
  35. data/locale/it/foreman_ansible.po.time_stamp +0 -0
  36. data/locale/ja/foreman_ansible.edit.po +0 -1148
  37. data/locale/ja/foreman_ansible.po.time_stamp +0 -0
  38. data/locale/ko/foreman_ansible.edit.po +0 -1148
  39. data/locale/ko/foreman_ansible.po.time_stamp +0 -0
  40. data/locale/nl_NL/foreman_ansible.edit.po +0 -1168
  41. data/locale/nl_NL/foreman_ansible.po.time_stamp +0 -0
  42. data/locale/pl/foreman_ansible.edit.po +0 -1180
  43. data/locale/pl/foreman_ansible.po.time_stamp +0 -0
  44. data/locale/pt_BR/foreman_ansible.edit.po +0 -1148
  45. data/locale/pt_BR/foreman_ansible.po.time_stamp +0 -0
  46. data/locale/ru/foreman_ansible.edit.po +0 -1149
  47. data/locale/ru/foreman_ansible.po.time_stamp +0 -0
  48. data/locale/sv_SE/foreman_ansible.edit.po +0 -1180
  49. data/locale/sv_SE/foreman_ansible.po.time_stamp +0 -0
  50. data/locale/zh_CN/foreman_ansible.edit.po +0 -1148
  51. data/locale/zh_CN/foreman_ansible.po.time_stamp +0 -0
  52. data/locale/zh_TW/foreman_ansible.edit.po +0 -1148
  53. data/locale/zh_TW/foreman_ansible.po.time_stamp +0 -0
  54. data/test/unit/actions/run_ansible_job_test.rb +0 -0
  55. data/test/unit/actions/run_proxy_ansible_command_test.rb +0 -0
  56. data/webpack/components/AnsibleHostDetail/components/JobsTab/PreviousJobsTable.js.orig +0 -151
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 98a2c9aa6bcc8e2feb5b8eee62d111926d0dab191561f808399587d7462debbc
4
- data.tar.gz: 2fc48fc5f59725cd8000229bdf08e68f5e8e53a1158271ce2d6db3766ab5826b
3
+ metadata.gz: f66c95bc367d1265d1be106e25a63a8fcfae2b95fd8d209f683c260c8d0d3647
4
+ data.tar.gz: cfad57982a9e2cf39324caf14f656df50148cd451dba92e963cbd54dd22a8875
5
5
  SHA512:
6
- metadata.gz: a8be9228e0b1532cdbef43e88b0f7ba84f9bd8edc5a9d9e21e1ee6d601f63bbccf16eff5e146f33d18ea06d7cdd5adc528d310d7ddb723ff3a6b91ce3a6774c6
7
- data.tar.gz: 35b55ca402a155fae45abd89c6fecde949d133e50b855473a25dba13df9452a13a5b9342b93e49fefd553902909a565dd59f9d57afb07d4f8efec6f0311057a9
6
+ metadata.gz: 340ab3cb55ecc5c54eb76f483e5e6b24e677831488dad250fd4c4b58ac33f37c7cdd27445246a95594d5f17db091e2df3445f3266c97dbd26dba34ecc88879ab
7
+ data.tar.gz: f50cb95108f5809cc30b8fdb6627b041d3261949c98fe15e149cef799e5e98ddea3955b39d642de6f1625817ce5e2e1e7e3314b3e59c6e6cb7788e8c59ad0fe3
@@ -0,0 +1,38 @@
1
+ module ForemanAnsible
2
+ module SmartProxiesHelper
3
+ def can_update_proxy?(proxy)
4
+ hosts = proxy.smart_proxy_hosts
5
+
6
+ return if !can_schedule_jobs? ||
7
+ hosts.empty? ||
8
+ !hosts.all? { |host| can_execute_on_host?(host) }
9
+
10
+ begin
11
+ version = proxy.statuses[:version].version
12
+ rescue Foreman::Exception
13
+ return false
14
+ end
15
+
16
+ foreman_version = Foreman::Version.new
17
+ proxy_version = Foreman::Version.new(version['version'])
18
+
19
+ foreman_major = foreman_version.major.to_i
20
+ foreman_minor = foreman_version.minor.to_i
21
+
22
+ proxy_major = proxy_version.major.to_i
23
+ proxy_minor = proxy_version.minor.to_i
24
+
25
+ foreman_major > proxy_major ||
26
+ (foreman_major == proxy_major && foreman_minor > proxy_minor)
27
+ end
28
+
29
+ def proxy_update_button(proxy)
30
+ feature = RemoteExecutionFeature.feature(:ansible_run_capsule_upgrade)
31
+ return if feature.nil?
32
+
33
+ path = new_job_invocation_path(:host_ids => proxy.infrastructure_host_facets.pluck(:host_id),
34
+ :feature => feature.label)
35
+ link_to(_('Upgrade'), path)
36
+ end
37
+ end
38
+ end
@@ -0,0 +1 @@
1
+ <%= proxy_update_button(subject) %>
@@ -1,9 +1,9 @@
1
1
  <%#
2
- name: Capsule Upgrade Playbook
2
+ name: Smart Proxy Upgrade Playbook
3
3
  snippet: false
4
4
  template_inputs:
5
5
  - name: target_version
6
- required: true
6
+ required: false
7
7
  input_type: user
8
8
  advanced: false
9
9
  value_type: plain
@@ -24,6 +24,9 @@ feature: ansible_run_capsule_upgrade
24
24
 
25
25
  ---
26
26
  - hosts: all
27
+ vars:
28
+ target_version: "<%= input('target_version').present? ? input('target_version') : product_short_version %>"
29
+ <% if plugin_present?('foreman_theme_satellite') -%>
27
30
  tasks:
28
31
  - name: Gather the rpm package facts
29
32
  package_facts:
@@ -44,7 +47,7 @@ feature: ansible_run_capsule_upgrade
44
47
  "--whitelist=#{input('whitelist_options')}"
45
48
  end -%>
46
49
  - name: Upgrade Capsule server using satellite-maintain
47
- shell: satellite-maintain upgrade run --assumeyes --target-version=<%= input('target_version') %> <%= whitelist_option %>
50
+ shell: satellite-maintain upgrade run --assumeyes --target-version={{ target_version }} <%= whitelist_option %>
48
51
  register: result
49
52
 
50
53
  - name: Re-Gather the rpm package facts after the upgrade
@@ -71,3 +74,36 @@ feature: ansible_run_capsule_upgrade
71
74
  - name: satellite-maintain upgrade return code is non-zero
72
75
  fail:
73
76
  msg: "Failed! Capsule server upgrade failed. See /var/log/foreman-installer/capsule.log in the Capsule server for more information"
77
+ <% else -%>
78
+ tasks:
79
+ - name: Gather the rpm package facts
80
+ package_facts:
81
+ manager: auto
82
+
83
+ - name: Fail if the target server is a Foreman server
84
+ fail:
85
+ msg: "This playbook cannot be executed on a Foreman server. Use only on a Smart Proxy server."
86
+ when: "'foreman' in ansible_facts.packages"
87
+
88
+ - name: Install foreman release gpg key
89
+ rpm_key:
90
+ state: present
91
+ key: http://yum.theforeman.org/releases/{{ target_version }}/RPM-GPG-KEY-foreman
92
+ when: target_version != "nightly"
93
+
94
+ - name: Update foreman repositories
95
+ package:
96
+ name: https://yum.theforeman.org/releases/{{ target_version }}/el{{ ansible_distribution_major_version }}/{{ ansible_architecture }}/foreman-release.rpm
97
+ state: installed
98
+
99
+ - name: Clean yum metadata
100
+ command: yum clean all
101
+
102
+ - name: Update all packages
103
+ package:
104
+ name: '*'
105
+ state: latest
106
+
107
+ - name: Run the installer
108
+ shell: foreman-installer
109
+ <% end -%>
@@ -0,0 +1,21 @@
1
+ class RenameCapsuleUpgradePlaybook < ActiveRecord::Migration[6.0]
2
+ MAPPING = {
3
+ 'Capsule Upgrade Playbook' => 'Smart Proxy Upgrade Playbook'
4
+ }.freeze
5
+
6
+ def up
7
+ rename(MAPPING)
8
+ end
9
+
10
+ def down
11
+ rename(MAPPING.invert)
12
+ end
13
+
14
+ private
15
+
16
+ def rename(mapping)
17
+ mapping.each do |old, new|
18
+ Template.where(name: old).update_all(name: new)
19
+ end
20
+ end
21
+ end
@@ -244,4 +244,17 @@ Foreman::Plugin.register :foreman_ansible do
244
244
  describe_hostgroup do
245
245
  hostgroup_actions_provider :ansible_hostgroups_actions
246
246
  end
247
+
248
+ extend_page('smart_proxies/show') do |context|
249
+ context.add_pagelet :smart_proxy_title_actions,
250
+ :name => _('Update Smart Proxy'),
251
+ :partial => 'foreman/smart_proxies/update_smart_proxy',
252
+ :onlyif => ->(proxy, view) { view.can_update_proxy?(proxy) }
253
+ end
254
+ extend_page('smart_proxies/index') do |context|
255
+ context.add_pagelet :smart_proxy_title_actions,
256
+ :name => _('Update Smart Proxy'),
257
+ :partial => 'foreman/smart_proxies/update_smart_proxy',
258
+ :onlyif => ->(proxy, view) { view.can_update_proxy?(proxy) }
259
+ end
247
260
  end
@@ -4,5 +4,5 @@
4
4
  # This way other parts of Foreman can just call ForemanAnsible::VERSION
5
5
  # and detect what version the plugin is running.
6
6
  module ForemanAnsible
7
- VERSION = '10.0.1'
7
+ VERSION = '10.1.0'
8
8
  end
@@ -37,13 +37,15 @@ module Queries
37
37
  let(:data) { result['data']['host']['allAnsibleRoles'] }
38
38
 
39
39
  it 'allows to fetch inherited roles' do
40
- value(data['totalCount']).must_equal(2)
40
+ assert_equal 2, data['totalCount']
41
+
41
42
  r1_data = data['nodes'].first
42
43
  r2_data = data['nodes'].second
43
- value(r1_data['name']).must_equal(role1.name)
44
- value(r1_data['inherited']).must_equal(true)
45
- value(r2_data['name']).must_equal(role2.name)
46
- value(r2_data['inherited']).must_equal(false)
44
+
45
+ assert_equal role1.name, r1_data['name']
46
+ assert r1_data['inherited']
47
+ assert_equal role2.name, r2_data['name']
48
+ assert_not r2_data['inherited']
47
49
  end
48
50
 
49
51
  it 'allow fetching variables' do
@@ -52,9 +54,10 @@ module Queries
52
54
  FactoryBot.create(:ansible_variable, ansible_role: role2, override: true)
53
55
  r1_vars = data['nodes'].first['ansibleVariables']
54
56
  r2_vars = data['nodes'].second['ansibleVariables']
55
- value(r1_vars['totalCount']).must_equal(2)
56
- value(r2_vars['totalCount']).must_equal(1)
57
- value(r1_vars['nodes'].first['key']).must_equal(var1.key)
57
+
58
+ assert_equal 2, r1_vars['totalCount']
59
+ assert_equal 1, r2_vars['totalCount']
60
+ assert_equal var1.key, r1_vars['nodes'].first['key']
58
61
  end
59
62
  end
60
63
  end
@@ -19,11 +19,8 @@ class AnsibleProviderTest < ActiveSupport::TestCase
19
19
  end
20
20
 
21
21
  context 'when it is using the ansible_run_host feature' do
22
- let(:rex_feature) do
23
- RemoteExecutionFeature.where(:label => 'ansible_run_host').first
24
- end
25
-
26
22
  it 'has remote_execution_command false' do
23
+ rex_feature = RemoteExecutionFeature.where(:label => 'ansible_run_host', :name => 'Run Ansible roles').first_or_create
27
24
  template_invocation.template.remote_execution_features << rex_feature
28
25
  assert_not command_options[:remote_execution_command]
29
26
  end
@@ -51,12 +48,12 @@ class AnsibleProviderTest < ActiveSupport::TestCase
51
48
  describe '#proxy_batch_size' do
52
49
  it 'returns integer if setting is string' do
53
50
  Setting.expects(:[]).with('foreman_ansible_proxy_batch_size').returns('10')
54
- _(ForemanAnsible::AnsibleProvider.proxy_batch_size).must_equal(10)
51
+ assert_equal 10, ForemanAnsible::AnsibleProvider.proxy_batch_size
55
52
  end
56
53
 
57
54
  it 'returns nil if setting is empty' do
58
55
  Setting.expects(:[]).with('foreman_ansible_proxy_batch_size').returns('')
59
- _(ForemanAnsible::AnsibleProvider.proxy_batch_size).must_equal(nil)
56
+ assert_nil ForemanAnsible::AnsibleProvider.proxy_batch_size
60
57
  end
61
58
  end
62
59
  end
@@ -18,23 +18,23 @@ class HostManagedExtensionsTest < ActiveSupport::TestCase
18
18
 
19
19
  describe '#all_ansible_roles' do
20
20
  test 'returns assigned roles for host without a hostgroup' do
21
- @host.all_ansible_roles.must_equal [@role1]
21
+ assert_equal [@role1], @host.all_ansible_roles
22
22
  end
23
23
 
24
24
  test 'returns assigned and inherited roles for host with a hostgroup' do
25
25
  @host.hostgroup = @hostgroup
26
- @host.all_ansible_roles.must_equal [@role2, @role1]
26
+ assert_equal [@role2, @role1], @host.all_ansible_roles
27
27
  end
28
28
  end
29
29
 
30
30
  describe '#inherited_ansible_roles' do
31
31
  test 'returns empty array for host without hostgroup' do
32
- @host.inherited_ansible_roles.must_equal []
32
+ assert_equal [], @host.inherited_ansible_roles
33
33
  end
34
34
 
35
35
  test 'returns roles inherited from a hostgroup' do
36
36
  @host.hostgroup = @hostgroup
37
- @host.inherited_ansible_roles.must_equal [@role2]
37
+ assert_equal [@role2], @host.inherited_ansible_roles
38
38
  end
39
39
  end
40
40
 
@@ -54,13 +54,13 @@ class HostManagedExtensionsTest < ActiveSupport::TestCase
54
54
  FactoryBot.create(:host_ansible_role, :ansible_role_id => @role1.id, :position => 1, :host_id => host.id)
55
55
  FactoryBot.create(:host_ansible_role, :ansible_role_id => @role2.id, :position => 2, :host_id => host.id)
56
56
  FactoryBot.create(:host_ansible_role, :ansible_role_id => @role3.id, :position => 0, :host_id => host.id)
57
- host.ansible_roles.must_equal [@role3, @role1, @role2]
57
+ assert_equal [@role3, @role1, @role2], host.ansible_roles
58
58
  end
59
59
 
60
60
  test 'should order hostgroup roles before host roles' do
61
61
  host = FactoryBot.create(:host, :hostgroup => @hostgroup)
62
62
  FactoryBot.create(:host_ansible_role, :ansible_role_id => @role1.id, :position => 0, :host_id => host.id)
63
- host.all_ansible_roles.must_equal [@role2, @role1]
63
+ assert_equal [@role2, @role1], host.all_ansible_roles
64
64
  end
65
65
 
66
66
  test 'should find hosts with role2' do
@@ -20,45 +20,45 @@ class HostgroupExtensionsTest < ActiveSupport::TestCase
20
20
  describe '#all_ansible_roles' do
21
21
  test 'returns assigned roles without any parent hostgroup' do
22
22
  @hostgroup.host_ansible_roles
23
- @hostgroup.all_ansible_roles.must_equal [@role1, @role3]
23
+ assert_equal [@role1, @role3], @hostgroup.all_ansible_roles
24
24
  end
25
25
 
26
26
  test 'returns assigned and inherited roles with from parent hostgroup' do
27
27
  @hostgroup.parent = @hostgroup_parent
28
- @hostgroup.all_ansible_roles.must_equal [@role2, @role1, @role3]
28
+ assert_equal [@role2, @role1, @role3], @hostgroup.all_ansible_roles
29
29
  end
30
30
  end
31
31
 
32
32
  describe '#inherited_ansible_roles' do
33
33
  test 'returns empty array for hostgroup without any parent' do
34
- @hostgroup.inherited_ansible_roles.must_equal []
34
+ assert_equal [], @hostgroup.inherited_ansible_roles
35
35
  end
36
36
 
37
37
  test 'returns roles inherited from a chain of parents' do
38
38
  @hostgroup.parent = @hostgroup_parent
39
- @hostgroup.inherited_ansible_roles.must_equal [@role2]
39
+ assert_equal [@role2], @hostgroup.inherited_ansible_roles
40
40
  end
41
41
  end
42
42
 
43
43
  describe '#inherited_and_own_ansible_roles' do
44
44
  test 'returns only hostgroup roles' do
45
- @hostgroup_parent.inherited_and_own_ansible_roles.must_equal [@role2]
45
+ assert_equal [@role2], @hostgroup_parent.inherited_and_own_ansible_roles
46
46
  end
47
47
 
48
48
  test 'returns only hostgroup roles including inheritance' do
49
49
  @hostgroup.parent = @hostgroup_parent
50
- @hostgroup.inherited_and_own_ansible_roles.must_equal [@role2, @role1]
50
+ assert_equal [@role2, @role1], @hostgroup.inherited_and_own_ansible_roles
51
51
  end
52
52
  end
53
53
 
54
54
  test 'should return ordered roles for hostgroup' do
55
55
  @hostgroup.parent = @hostgroup_parent
56
- @hostgroup.inherited_and_own_ansible_roles.must_equal [@role2, @role1]
56
+ assert_equal [@role2, @role1], @hostgroup.inherited_and_own_ansible_roles
57
57
  end
58
58
 
59
59
  describe '#cloned_ansibe_roles' do
60
60
  test 'clone ansible roles from hostgroup parent' do
61
- @hostgroup_parent.clone.all_ansible_roles.must_equal @hostgroup_parent.all_ansible_roles
61
+ assert_equal @hostgroup_parent.all_ansible_roles, @hostgroup_parent.clone.all_ansible_roles
62
62
  end
63
63
  end
64
64
 
@@ -19,12 +19,12 @@ export const rangeValidator = date => {
19
19
  };
20
20
 
21
21
  export const createValidationSchema = () => {
22
- const cantBeBlank = __("can't be blank");
22
+ const required = __('Required field');
23
23
 
24
24
  return Yup.object().shape({
25
- repeat: Yup.string().required(cantBeBlank),
26
- startTime: Yup.string().required(cantBeBlank),
27
- startDate: Yup.string().required(cantBeBlank),
25
+ repeat: Yup.string().required(required),
26
+ startTime: Yup.string().required(required),
27
+ startDate: Yup.string().required(required),
28
28
  });
29
29
  };
30
30
 
@@ -1,5 +1,7 @@
1
1
  import React from 'react';
2
2
  import PropTypes from 'prop-types';
3
+ import { useDispatch } from 'react-redux';
4
+ import { push } from 'connected-react-router';
3
5
  import { Formik, Field as FormikField } from 'formik';
4
6
  import { useMutation } from '@apollo/client';
5
7
  import { translate as __ } from 'foremanReact/common/I18n';
@@ -33,6 +35,7 @@ import jobsQuery from '../../../../graphql/queries/recurringJobs.gql';
33
35
 
34
36
  const NewRecurringJobModal = props => {
35
37
  const { onClose, resourceId, resourceName } = props;
38
+ const dispatch = useDispatch();
36
39
 
37
40
  const [callMutation] = useMutation(createJobInvocation, {
38
41
  refetchQueries: [
@@ -81,10 +84,31 @@ const NewRecurringJobModal = props => {
81
84
  actions.push(<Spinner key="spinner" size="lg" />);
82
85
  }
83
86
 
87
+ const modalDescription = (
88
+ <>
89
+ {__('This job will run all the assigned Ansible roles.')}
90
+ <br />
91
+ {__('For more advanced scheduling options')}{' '}
92
+ <Button
93
+ variant="link"
94
+ isInline
95
+ onClick={() =>
96
+ dispatch(
97
+ push(`/job_invocations/new?host_ids%5B%5D=${resourceId}`)
98
+ )
99
+ }
100
+ key="schedule-job-action"
101
+ >
102
+ {__('view remote execution page.')}
103
+ </Button>
104
+ </>
105
+ );
106
+
84
107
  return (
85
108
  <Modal
86
- variant={ModalVariant.large}
87
- title="Create New Recurring Ansible Run"
109
+ variant={ModalVariant.small}
110
+ title={__('Schedule recurring Ansible roles job')}
111
+ description={modalDescription}
88
112
  ouiaId="modal-recurring-ansible-run"
89
113
  isOpen={props.isOpen}
90
114
  className="foreman-modal modal-high"
@@ -103,14 +127,16 @@ const NewRecurringJobModal = props => {
103
127
  <FormikField
104
128
  name="startTime"
105
129
  component={TimePickerField}
106
- label="Start Time"
130
+ label="Start time"
107
131
  isRequired
108
132
  is24Hour
133
+ width="250px"
134
+ menuAppendTo={() => document.body}
109
135
  />
110
136
  <FormikField
111
137
  name="startDate"
112
138
  component={DatePickerField}
113
- label="Start Date"
139
+ label="Start date"
114
140
  isRequired
115
141
  validators={[rangeValidator]}
116
142
  />
@@ -2,6 +2,13 @@
2
2
  z-index: 1040;
3
3
  }
4
4
 
5
- .modal-high {
6
- height: 70%;
5
+ .foreman-modal.modal-high {
6
+ height: 50vh;
7
+ @media only screen and (max-height: 960px) {
8
+ height: 70vh;
9
+ }
10
+
11
+ .pf-c-form-control, .pf-c-date-picker, .pf-c-date-picker__input {
12
+ width: 250px
13
+ }
7
14
  }
@@ -24,7 +24,7 @@ const AllRolesModal = ({ hostGlobalId, onClose, history }) => {
24
24
  title: __('All assigned Ansible roles'),
25
25
  disableFocusTrap: true,
26
26
  description: __(
27
- 'This list consists of host assigned roles and group assigned roles. Group assigned roles will always be executed prior to host assigned roles'
27
+ 'This list consists of host assigned roles and group assigned roles. Group assigned roles will always be executed prior to host assigned roles.'
28
28
  ),
29
29
  };
30
30
 
@@ -28,7 +28,7 @@ const EditRolesModal = ({
28
28
  title: __('Edit Ansible Roles'),
29
29
  disableFocusTrap: true,
30
30
  description: __(
31
- 'Add, remove or reorder host assigned Ansible roles. This host has also group assigned roles that are not displayed here and will always be executed prior to host assigned roles'
31
+ 'Add, remove or reorder host assigned Ansible roles. This host has also group assigned roles that are not displayed here and will always be executed prior to host assigned roles.'
32
32
  ),
33
33
  };
34
34