foreman_remote_execution 1.2.2 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +11 -0
  3. data/app/assets/javascripts/template_invocation.js +6 -11
  4. data/app/controllers/api/v2/job_templates_controller.rb +1 -0
  5. data/app/controllers/concerns/foreman/controller/parameters/remote_execution_feature.rb +1 -1
  6. data/app/controllers/job_invocations_controller.rb +6 -2
  7. data/app/controllers/job_templates_controller.rb +0 -5
  8. data/app/helpers/concerns/foreman_remote_execution/hosts_helper_extensions.rb +18 -2
  9. data/app/helpers/concerns/foreman_remote_execution/job_templates_extensions.rb +1 -2
  10. data/app/helpers/remote_execution_helper.rb +42 -41
  11. data/app/lib/actions/remote_execution/run_host_job.rb +2 -15
  12. data/app/lib/actions/remote_execution/run_hosts_job.rb +17 -3
  13. data/app/models/concerns/foreman_remote_execution/host_extensions.rb +7 -6
  14. data/app/models/input_template_renderer.rb +1 -1
  15. data/app/models/job_invocation.rb +23 -5
  16. data/app/models/remote_execution_feature.rb +16 -3
  17. data/app/models/setting/remote_execution.rb +4 -1
  18. data/app/models/ssh_execution_provider.rb +33 -2
  19. data/app/models/targeting.rb +7 -3
  20. data/app/views/api/v2/remote_execution_features/base.json.rabl +1 -1
  21. data/app/views/job_invocations/_form.html.erb +1 -4
  22. data/app/views/job_invocations/_host_name_td.html.erb +2 -1
  23. data/app/views/job_invocations/index.html.erb +1 -1
  24. data/app/views/job_invocations/show.html.erb +1 -1
  25. data/app/views/job_templates/_custom_tabs.html.erb +1 -4
  26. data/app/views/overrides/nics/_execution_interface.html.erb +2 -3
  27. data/app/views/remote_execution_features/index.html.erb +1 -1
  28. data/db/migrate/20170110145641_add_host_action_button_to_remote_execution_feature.rb +5 -0
  29. data/foreman_remote_execution.gemspec +1 -1
  30. data/lib/foreman_remote_execution/engine.rb +3 -1
  31. data/lib/foreman_remote_execution/version.rb +1 -1
  32. data/locale/action_names.rb +2 -5
  33. data/locale/de/LC_MESSAGES/foreman_remote_execution.mo +0 -0
  34. data/locale/de/foreman_remote_execution.po +13 -23
  35. data/locale/en/foreman_remote_execution.po +12 -22
  36. data/locale/en_GB/LC_MESSAGES/foreman_remote_execution.mo +0 -0
  37. data/locale/en_GB/foreman_remote_execution.po +12 -22
  38. data/locale/es/LC_MESSAGES/foreman_remote_execution.mo +0 -0
  39. data/locale/es/foreman_remote_execution.po +13 -23
  40. data/locale/foreman_remote_execution.pot +71 -80
  41. data/locale/fr/LC_MESSAGES/foreman_remote_execution.mo +0 -0
  42. data/locale/fr/foreman_remote_execution.po +13 -23
  43. data/locale/ja/LC_MESSAGES/foreman_remote_execution.mo +0 -0
  44. data/locale/ja/foreman_remote_execution.po +13 -23
  45. data/locale/ko/LC_MESSAGES/foreman_remote_execution.mo +0 -0
  46. data/locale/ko/foreman_remote_execution.po +13 -23
  47. data/locale/pt_BR/LC_MESSAGES/foreman_remote_execution.mo +0 -0
  48. data/locale/pt_BR/foreman_remote_execution.po +13 -23
  49. data/locale/ru/LC_MESSAGES/foreman_remote_execution.mo +0 -0
  50. data/locale/ru/foreman_remote_execution.po +13 -23
  51. data/locale/zh_CN/LC_MESSAGES/foreman_remote_execution.mo +0 -0
  52. data/locale/zh_CN/foreman_remote_execution.po +13 -23
  53. data/locale/zh_TW/LC_MESSAGES/foreman_remote_execution.mo +0 -0
  54. data/locale/zh_TW/foreman_remote_execution.po +13 -23
  55. data/test/benchmark/run_hosts_job_benchmark.rb +70 -0
  56. data/test/benchmark/targeting_benchmark.rb +31 -0
  57. data/test/factories/foreman_remote_execution_factories.rb +3 -0
  58. data/test/functional/api/v2/job_templates_controller_test.rb +1 -1
  59. data/test/unit/actions/run_hosts_job_test.rb +1 -0
  60. data/test/unit/concerns/host_extensions_test.rb +1 -4
  61. data/test/unit/job_invocation_test.rb +28 -1
  62. data/test/unit/remote_execution_feature_test.rb +40 -0
  63. data/test/unit/remote_execution_provider_test.rb +55 -1
  64. metadata +10 -7
  65. data/test/unit/actions/run_host_job_test.rb +0 -50
@@ -97,8 +97,8 @@ msgstr "并发等级"
97
97
  msgid "Control concurrency level and distribution over time"
98
98
  msgstr "控制并行等级及分配时间"
99
99
 
100
- msgid "Could not use any proxy. Consider configuring %{global_proxy} or %{fallback_proxy} in settings"
101
- msgstr "无法使用任何代理服务器。可考虑在设置中配置 %{global_proxy} 或者 %{fallback_proxy}。"
100
+ msgid "Could not use any proxy. Consider configuring %{global_proxy}, %{fallback_proxy} or %{no_proxy} in settings"
101
+ msgstr ""
102
102
 
103
103
  msgid "Could not use any template used in the job invocation"
104
104
  msgstr "无法使用在任务调用中使用的任意模板"
@@ -118,9 +118,6 @@ msgstr "创建重复任务"
118
118
  msgid "Create a template input"
119
119
  msgstr "创建模板输入"
120
120
 
121
- msgid "Create architecture"
122
- msgstr "生成架构"
123
-
124
121
  msgid "Default user to use for SSH. You may override per host by setting a parameter called remote_execution_ssh_user."
125
122
  msgstr "SSH 默认使用的用户。可设置 remote_execution_ssh_user 调用的参数替换每台主机设置。"
126
123
 
@@ -136,9 +133,6 @@ msgstr "删除任务模板"
136
133
  msgid "Delete a template input"
137
134
  msgstr "删除模板输入"
138
135
 
139
- msgid "Delete architecture"
140
- msgstr "删除架构"
141
-
142
136
  msgid "Description"
143
137
  msgstr "描述"
144
138
 
@@ -211,9 +205,6 @@ msgstr "已失败"
211
205
  msgid "Failed rendering template: %s"
212
206
  msgstr "修改模板失败:%s"
213
207
 
214
- msgid "Failed to initialize command"
215
- msgstr "初始化命令失败"
216
-
217
208
  msgid "Feature input %{input_name} not defined in template %{template_name}"
218
209
  msgstr "模板 %{template_name} 的功能输入 %{input_name} "
219
210
 
@@ -262,9 +253,6 @@ msgstr ""
262
253
  msgid "Indicates that the action should be cancelled if it cannot be started before this time."
263
254
  msgstr "表示如果在这个时间之前无法启动该操作,则应将其取消。"
264
255
 
265
- msgid "Initialization error: %s"
266
- msgstr "初始化出错:%s"
267
-
268
256
  msgid "Input"
269
257
  msgstr "输入"
270
258
 
@@ -391,9 +379,6 @@ msgstr "尚未完成任何执行"
391
379
  msgid "No hosts found."
392
380
  msgstr "未找到任何主机。"
393
381
 
394
- msgid "No output"
395
- msgstr "无输出结果"
396
-
397
382
  msgid "No template mapped to feature %{feature_name}"
398
383
  msgstr "没有与功能 %{feature_name} 映射的模板"
399
384
 
@@ -418,6 +403,12 @@ msgstr "等待处理"
418
403
  msgid "Perform no more executions after this time"
419
404
  msgstr "这个时间后不再执行任何操作"
420
405
 
406
+ msgid "Playbook execution failed"
407
+ msgstr ""
408
+
409
+ msgid "Port to use for SSH communication. Default port 22. You may override per host by setting a parameter called remote_execution_ssh_port."
410
+ msgstr ""
411
+
421
412
  msgid "Preview"
422
413
  msgstr "预览"
423
414
 
@@ -511,9 +502,6 @@ msgstr "将该任务调度为在将来的某个时间开始"
511
502
  msgid "Schedule the job to start at a later time"
512
503
  msgstr "将该任务调度为于稍后开始"
513
504
 
514
- msgid "Script execution failed"
515
- msgstr "脚本执行失败"
516
-
517
505
  msgid "Scroll to bottom"
518
506
  msgstr "滚动到底部"
519
507
 
@@ -699,9 +687,6 @@ msgstr "更新任务模板"
699
687
  msgid "Update a template input"
700
688
  msgstr "更新模板输入"
701
689
 
702
- msgid "Update architecture"
703
- msgstr "更新架构"
704
-
705
690
  msgid "Use default description template"
706
691
  msgstr "使用默认描述模板"
707
692
 
@@ -735,6 +720,11 @@ msgstr "应由什么用户运行此脚本(使用类似 sudo 的机制)。"
735
720
  msgid "What user should be used to run the script (using sudo-like mechanisms). Defaults to a template parameter or global setting."
736
721
  msgstr "应由什么用户运行此脚本(使用类似 sudo 的机制)。默认为模板参数或全局设置。"
737
722
 
723
+ msgid ""
724
+ "When enabled, the remote execution will try to run the commands directly, when no\n"
725
+ " proxy with remote execution feature is configured for the host."
726
+ msgstr ""
727
+
738
728
  msgid "Whether it should be allowed to override the effective user from the invocation form."
739
729
  msgstr "是否应允许使用调用形式替代有效用户。"
740
730
 
@@ -97,8 +97,8 @@ msgstr "同步等級"
97
97
  msgid "Control concurrency level and distribution over time"
98
98
  msgstr "隨時間控制週期等級並散佈"
99
99
 
100
- msgid "Could not use any proxy. Consider configuring %{global_proxy} or %{fallback_proxy} in settings"
101
- msgstr "無法使用任何代理伺服器。請考慮配置設定中的 %{global_proxy} 或 %{fallback_proxy}"
100
+ msgid "Could not use any proxy. Consider configuring %{global_proxy}, %{fallback_proxy} or %{no_proxy} in settings"
101
+ msgstr ""
102
102
 
103
103
  msgid "Could not use any template used in the job invocation"
104
104
  msgstr "無法使用任何用於這工作祈願的範本"
@@ -118,9 +118,6 @@ msgstr "建立週期性工作"
118
118
  msgid "Create a template input"
119
119
  msgstr "建立範本輸入"
120
120
 
121
- msgid "Create architecture"
122
- msgstr "建立架構"
123
-
124
121
  msgid "Default user to use for SSH. You may override per host by setting a parameter called remote_execution_ssh_user."
125
122
  msgstr "使用 SSH 的預設使用者。您可以透過設定參數呼叫 remote_execution_ssh_user 來覆寫每台主機的設定。"
126
123
 
@@ -136,9 +133,6 @@ msgstr "刪除工作範本"
136
133
  msgid "Delete a template input"
137
134
  msgstr "刪除範本輸入"
138
135
 
139
- msgid "Delete architecture"
140
- msgstr "刪除架構"
141
-
142
136
  msgid "Description"
143
137
  msgstr "說明"
144
138
 
@@ -211,9 +205,6 @@ msgstr "已失敗"
211
205
  msgid "Failed rendering template: %s"
212
206
  msgstr "無法生成範本:%s"
213
207
 
214
- msgid "Failed to initialize command"
215
- msgstr "無法初始化指令"
216
-
217
208
  msgid "Feature input %{input_name} not defined in template %{template_name}"
218
209
  msgstr "未知的輸入 %{input_name} 未定義於範本 %{template_name}"
219
210
 
@@ -262,9 +253,6 @@ msgstr ""
262
253
  msgid "Indicates that the action should be cancelled if it cannot be started before this time."
263
254
  msgstr "這表示如果不能在這時間之前開始,就應該取消動作。"
264
255
 
265
- msgid "Initialization error: %s"
266
- msgstr "初始化錯誤:%s"
267
-
268
256
  msgid "Input"
269
257
  msgstr "輸入"
270
258
 
@@ -391,9 +379,6 @@ msgstr "尚無執行完成"
391
379
  msgid "No hosts found."
392
380
  msgstr "找不到主機。"
393
381
 
394
- msgid "No output"
395
- msgstr "沒有輸出"
396
-
397
382
  msgid "No template mapped to feature %{feature_name}"
398
383
  msgstr "沒有範本定義至功能 %{feature_name}"
399
384
 
@@ -418,6 +403,12 @@ msgstr "等待處理中"
418
403
  msgid "Perform no more executions after this time"
419
404
  msgstr "此時間之後不再進行任何執行"
420
405
 
406
+ msgid "Playbook execution failed"
407
+ msgstr ""
408
+
409
+ msgid "Port to use for SSH communication. Default port 22. You may override per host by setting a parameter called remote_execution_ssh_port."
410
+ msgstr ""
411
+
421
412
  msgid "Preview"
422
413
  msgstr "預覽"
423
414
 
@@ -511,9 +502,6 @@ msgstr "排程工作至未來時間"
511
502
  msgid "Schedule the job to start at a later time"
512
503
  msgstr "排程工作至晚一點的時間"
513
504
 
514
- msgid "Script execution failed"
515
- msgstr "執行 script 失敗"
516
-
517
505
  msgid "Scroll to bottom"
518
506
  msgstr "捲動至底端"
519
507
 
@@ -699,9 +687,6 @@ msgstr "更新工作範本"
699
687
  msgid "Update a template input"
700
688
  msgstr "更新範本輸入"
701
689
 
702
- msgid "Update architecture"
703
- msgstr "更新架構"
704
-
705
690
  msgid "Use default description template"
706
691
  msgstr "使用預設的描述範本"
707
692
 
@@ -735,6 +720,11 @@ msgstr "哪位使用者該用來執行此 script(使用類似 sudo 機制)"
735
720
  msgid "What user should be used to run the script (using sudo-like mechanisms). Defaults to a template parameter or global setting."
736
721
  msgstr "哪位使用者該用來執行此 script(使用類似 sudo 機制)。預設值設為範本參數或全域設定。"
737
722
 
723
+ msgid ""
724
+ "When enabled, the remote execution will try to run the commands directly, when no\n"
725
+ " proxy with remote execution feature is configured for the host."
726
+ msgstr ""
727
+
738
728
  msgid "Whether it should be allowed to override the effective user from the invocation form."
739
729
  msgstr "是否允許從祈願清單覆寫有效使用者。"
740
730
 
@@ -0,0 +1,70 @@
1
+ require "benchmark/benchmark_helper"
2
+ require 'dynflow/testing'
3
+
4
+ # Add plugin to FactoryGirl's paths
5
+ FactoryGirl.definition_file_paths << File.expand_path('../../factories', __FILE__)
6
+ FactoryGirl.definition_file_paths << "#{ForemanTasks::Engine.root}/test/factories"
7
+ FactoryGirl.reload
8
+
9
+ module Actions
10
+ module RemoteExecution
11
+ class RunHostsJob < Actions::ActionWithSubPlans
12
+ # stub function that calls other actions.
13
+ def trigger(*args)
14
+ nil
15
+ end
16
+ end
17
+ end
18
+ end
19
+
20
+ module Support
21
+ class DummyDynflowAction < Dynflow::Action
22
+ end
23
+ end
24
+
25
+ def generate_hosts(total)
26
+ FactoryGirl.create_list(:host, total, :comment => "benchmark-#{Foreman.uuid}")
27
+ end
28
+
29
+ Rails.logger.level = Logger::ERROR
30
+
31
+ class ActionTester
32
+ include Dynflow::Testing::Factories
33
+
34
+ def initialize(task)
35
+ @task = task
36
+ end
37
+
38
+ def run_action(*args)
39
+ action = create_action(Actions::RemoteExecution::RunHostsJob)
40
+ @task.update_attributes(:external_id => action.execution_plan_id)
41
+ plan_action(action, *args)
42
+ end
43
+ end
44
+
45
+ puts 'generating admin user'
46
+ admin = FactoryGirl.build(:user, :admin)
47
+ admin.save(:validate => false)
48
+ User.current = admin
49
+ targeting = FactoryGirl.create(:targeting, :search_query => "comment = benchmark-#{Foreman.uuid}", :user => User.current)
50
+ template_invocation = FactoryGirl.build(:template_invocation, :job_invocation => nil)
51
+ job_invocation = FactoryGirl.build(:job_invocation, :targeting => targeting, :pattern_template_invocations => [template_invocation]).tap do |invocation|
52
+ invocation.targeting = targeting
53
+ invocation.save
54
+ end
55
+
56
+ task = FactoryGirl.create(:dynflow_task, :external_id => '1')
57
+ tester = ActionTester.new(task)
58
+
59
+ puts 'generating hosts'
60
+ generate_hosts(1000)
61
+ puts 'starting benchmarking'
62
+ foreman_benchmark do
63
+ Benchmark.ips do |x|
64
+ x.config(:time => 10, :warmup => 0)
65
+
66
+ x.report("rex-run-hosts-job") do
67
+ tester.run_action(job_invocation)
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,31 @@
1
+ require "benchmark/benchmark_helper"
2
+ require 'dynflow/testing'
3
+
4
+ # Add plugin to FactoryGirl's paths
5
+ FactoryGirl.definition_file_paths << File.expand_path('../../factories', __FILE__)
6
+ FactoryGirl.reload
7
+
8
+ def generate_hosts(total)
9
+ FactoryGirl.create_list(:host, total, :comment => "benchmark-#{Foreman.uuid}")
10
+ end
11
+
12
+ Rails.logger.level = Logger::ERROR
13
+
14
+ puts 'generating hosts'
15
+ generate_hosts(1000)
16
+ puts 'generating admin user'
17
+ admin = FactoryGirl.build(:user, :admin)
18
+ admin.save(:validate => false)
19
+ User.current = admin
20
+
21
+ puts 'starting benchmarking'
22
+ foreman_benchmark do
23
+ Benchmark.ips do |x|
24
+ x.config(:time => 10, :warmup => 0)
25
+
26
+ x.report("rex-targeting-resolve-hosts") do
27
+ targeting = FactoryGirl.create(:targeting, :search_query => "comment = benchmark-#{Foreman.uuid}", :user => User.current)
28
+ targeting.resolve_hosts!
29
+ end
30
+ end
31
+ end
@@ -5,6 +5,9 @@ FactoryGirl.define do
5
5
  sequence(:job_category) { |n| "job name #{n}" }
6
6
  f.template 'id'
7
7
  f.provider_type 'SSH'
8
+ organizations { [Organization.find_by_name('Organization 1')] } if SETTINGS[:organizations_enabled]
9
+ locations { [Location.find_by_name('Location 1')] } if SETTINGS[:locations_enabled]
10
+
8
11
 
9
12
  trait :with_input do
10
13
  after(:build) do |template, evaluator|
@@ -91,7 +91,7 @@ module Api
91
91
  erb_data = @template.to_erb
92
92
  post :import, :template => erb_data
93
93
  assert_response :success
94
- assert JobTemplate.find_by_name(new_name)
94
+ assert JobTemplate.unscoped.find_by_name(new_name)
95
95
  end
96
96
  end
97
97
 
@@ -43,6 +43,7 @@ module ForemanRemoteExecution
43
43
  end
44
44
 
45
45
  it 'triggers the RunHostJob actions on the resolved hosts in run phase' do
46
+ planned.expects(:output).returns(:planned_count => 0)
46
47
  planned.expects(:trigger).with() { |*args| args[0] == Actions::RemoteExecution::RunHostJob }
47
48
  planned.create_sub_plans
48
49
  end
@@ -40,10 +40,7 @@ describe ForemanRemoteExecution::HostExtensions do
40
40
 
41
41
  it 'has ssh keys in the parameters even when no user specified' do
42
42
  # this is a case, when using the helper in provisioning templates
43
- FactoryGirl.create(:smart_proxy, :ssh) do |proxy|
44
- proxy.organizations << host.organization
45
- proxy.locations << host.location
46
- end
43
+ FactoryGirl.create(:smart_proxy, :ssh)
47
44
  host.interfaces.first.subnet.remote_execution_proxies.clear
48
45
  User.current = nil
49
46
  host.remote_execution_ssh_keys.must_include sshkey
@@ -45,6 +45,10 @@ describe JobInvocation do
45
45
 
46
46
  before do
47
47
  input = job_invocation.pattern_template_invocations.first.template.template_inputs.create!(:name => 'foo', :required => true, :input_type => 'user')
48
+ input2 = job_invocation.pattern_template_invocations.first.template.template_inputs.create!(:name => 'bar', :required => true, :input_type => 'user')
49
+ FactoryGirl.create(:template_invocation_input_value,
50
+ :template_invocation => job_invocation.pattern_template_invocations.first,
51
+ :template_input => input2)
48
52
  @input_value = FactoryGirl.create(:template_invocation_input_value,
49
53
  :template_invocation => job_invocation.pattern_template_invocations.first,
50
54
  :template_input => input)
@@ -101,6 +105,18 @@ describe JobInvocation do
101
105
 
102
106
  context 'with task' do
103
107
  let(:task) { ForemanTasks::Task.new }
108
+ let(:progress_report_without_sub_tasks) do
109
+ {
110
+ :error => 0,
111
+ :warning => 0,
112
+ :total => 0,
113
+ :success => 0,
114
+ :cancelled => 0,
115
+ :failed => 0,
116
+ :pending => 0,
117
+ :progress => 0
118
+ }
119
+ end
104
120
  before { job_invocation.task = task }
105
121
 
106
122
  context 'which is scheduled' do
@@ -109,6 +125,7 @@ describe JobInvocation do
109
125
  specify { job_invocation.status.must_equal HostStatus::ExecutionStatus::QUEUED }
110
126
  specify { job_invocation.queued?.must_equal true }
111
127
  specify { job_invocation.progress.must_equal 0 }
128
+ specify { job_invocation.progress_report.must_equal progress_report_without_sub_tasks }
112
129
  end
113
130
 
114
131
  context 'with succeeded task' do
@@ -119,7 +136,17 @@ describe JobInvocation do
119
136
 
120
137
  specify { job_invocation.status.must_equal HostStatus::ExecutionStatus::OK }
121
138
  specify { job_invocation.queued?.must_equal false }
122
- specify { job_invocation.progress.must_equal 100 }
139
+
140
+ it 'calculates the progress correctly' do
141
+ sub_tasks = [ForemanTasks::Task.new]
142
+ job_invocation.targeting.expects(:resolved?).returns(true)
143
+ job_invocation.targeting.expects(:hosts).returns([1])
144
+ sub_tasks.expects(:where).with(:result => %w(success warning error)).returns(sub_tasks)
145
+ job_invocation.stubs(:sub_tasks).returns(sub_tasks)
146
+
147
+ job_invocation.progress.must_equal 100
148
+ end
123
149
  end
124
150
  end
151
+
125
152
  end
@@ -42,5 +42,45 @@ describe RemoteExecutionFeature do
42
42
 
43
43
  composer.targeting.search_query.must_equal "name = #{host.name}"
44
44
  end
45
+
46
+ it "updates the feature when attributes change" do
47
+ updated_feature = RemoteExecutionFeature.register(install_feature.label, N_('Katello: Install package'),
48
+ :description => 'New description',
49
+ :provided_inputs => ['package', 'force'])
50
+ updated_feature.reload
51
+ updated_feature.id.must_equal(install_feature.id)
52
+ updated_feature.description.must_equal 'New description'
53
+ updated_feature.provided_input_names.must_equal ['package', 'force']
54
+ end
55
+ end
56
+
57
+ describe '.register' do
58
+ it "creates a feature if it's missing" do
59
+ feature = RemoteExecutionFeature.register('new_feature_that_does_not_exist', 'name')
60
+ feature.must_be :persisted?
61
+ feature.label.must_equal 'new_feature_that_does_not_exist'
62
+ feature.name.must_equal 'name'
63
+ refute feature.host_action_button
64
+ end
65
+
66
+ it "creates a feature with host action flag" do
67
+ feature = RemoteExecutionFeature.register('new_feature_that_does_not_exist_button', 'name', :host_action_button => true)
68
+ feature.must_be :persisted?
69
+ assert feature.host_action_button
70
+ end
71
+
72
+ it "created feature with host action flag can be found using named scope" do
73
+ feature = RemoteExecutionFeature.register('new_feature_that_does_not_exist_button', 'name', :host_action_button => true)
74
+ assert_includes RemoteExecutionFeature.with_host_action_button, feature
75
+ end
76
+
77
+
78
+ it "updates a feature if it exists" do
79
+ existing = FactoryGirl.create(:remote_execution_feature, :name => 'existing_feature_withou_action_button')
80
+ feature = RemoteExecutionFeature.register(existing.label, existing.name, :host_action_button => true)
81
+ feature.must_be :persisted?
82
+ existing.reload
83
+ assert existing.host_action_button
84
+ end
45
85
  end
46
86
  end