foreman_docker 3.1.0 → 3.2.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 (35) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +10 -1
  3. data/app/assets/javascripts/foreman_docker/container_image_search.js +203 -0
  4. data/app/assets/javascripts/foreman_docker/create_registry.js +15 -0
  5. data/app/assets/stylesheets/foreman_docker/autocomplete.css.scss +4 -0
  6. data/app/controllers/concerns/foreman/controller/parameters/docker_registry.rb +1 -1
  7. data/app/controllers/image_search_controller.rb +6 -35
  8. data/app/helpers/container_steps_helper.rb +0 -1
  9. data/app/models/container.rb +1 -1
  10. data/app/models/docker_container_wizard_state.rb +1 -1
  11. data/app/models/docker_container_wizard_states/configuration.rb +1 -1
  12. data/app/models/docker_container_wizard_states/environment.rb +1 -1
  13. data/app/models/docker_container_wizard_states/image.rb +1 -1
  14. data/app/models/docker_container_wizard_states/preliminary.rb +1 -1
  15. data/app/models/docker_parameter.rb +1 -1
  16. data/app/models/docker_registry.rb +8 -4
  17. data/app/models/foreman_docker/docker.rb +10 -2
  18. data/app/models/service/registry_api.rb +10 -5
  19. data/app/views/containers/steps/_form_buttons.html.erb +5 -7
  20. data/app/views/containers/steps/_image_hub_tab.html.erb +16 -17
  21. data/app/views/containers/steps/image.html.erb +1 -3
  22. data/app/views/image_search/_repository_search_results.html.erb +1 -1
  23. data/app/views/registries/_form.html.erb +5 -3
  24. data/app/views/registries/index.html.erb +11 -10
  25. data/db/migrate/20170508130316_add_verify_ssl_option_to_docker_registries.rb +5 -0
  26. data/lib/foreman_docker/engine.rb +7 -6
  27. data/lib/foreman_docker/version.rb +1 -1
  28. data/test/functionals/image_search_controller_test.rb +120 -169
  29. data/test/integration/container_steps_test.rb +118 -18
  30. data/test/integration/registry_creation_test.rb +19 -0
  31. data/test/units/docker_container_wizard_states/image_test.rb +0 -1
  32. data/test/units/docker_registry_test.rb +0 -8
  33. data/test/units/registry_api_test.rb +13 -1
  34. metadata +10 -6
  35. data/app/assets/javascripts/foreman_docker/image_step.js +0 -175
@@ -1,24 +1,124 @@
1
1
  require 'integration_test_helper'
2
2
 
3
- class ContainerStepsTest < ActionDispatch::IntegrationTest
4
- test 'shows a link to a new compute resource if none is available' do
5
- visit new_container_path
6
- assert has_selector?("div.alert", :text => 'Please add a new one')
3
+ class ContainerStepsTest < IntegrationTestWithJavascript
4
+ let(:wizard_state) { DockerContainerWizardState.create! }
5
+ let(:compute_resource) { FactoryGirl.create(:docker_cr) }
6
+ let(:registry) { FactoryGirl.create(:docker_registry) }
7
+ let(:image_search_service) { ForemanDocker::ImageSearch.new }
8
+ let(:image_search_results) do
9
+ [{ 'name' => 'my_fake_repository_result',
10
+ 'star_count' => 300,
11
+ 'description' => 'fake repository' }]
7
12
  end
8
13
 
9
- test 'shows taxonomies tabs' do
10
- visit new_container_path
11
- assert has_selector?("a", :text => 'Locations') if SETTINGS[:locations_enabled]
12
- assert has_selector?("a", :text => 'Organizations') if SETTINGS[:organizations_enabled]
14
+ let(:preliminary) do
15
+ DockerContainerWizardStates::Preliminary.create!(
16
+ :wizard_state => wizard_state,
17
+ :compute_resource => compute_resource
18
+ )
19
+ end
20
+
21
+ setup do
22
+ stub_image_existance
23
+ stub_registry_api
24
+ ImageSearchController.any_instance.stubs(:image_search_service)
25
+ .returns(image_search_service)
26
+ end
27
+
28
+ describe 'on preliminary step' do
29
+ test 'it shows docker compute resources' do
30
+ compute_resource.save
31
+ visit wizard_state_step_path(:wizard_state_id => wizard_state, :id => :preliminary)
32
+ assert_text compute_resource.name
33
+ end
34
+
35
+ context 'when no compute resources are available' do
36
+ setup do
37
+ ForemanDocker::Docker.destroy_all
38
+ end
39
+
40
+ test 'shows a link to a new compute resource if none is available' do
41
+ visit wizard_state_step_path(:wizard_state_id => wizard_state, :id => :preliminary)
42
+ assert has_selector?("div.alert", :text => 'Please add a new one')
43
+ end
44
+ end
45
+
46
+ test 'shows taxonomies tabs' do
47
+ visit wizard_state_step_path(:wizard_state_id => wizard_state, :id => :preliminary)
48
+ assert has_selector?("a", :text => 'Locations') if SETTINGS[:locations_enabled]
49
+ assert has_selector?("a", :text => 'Organizations') if SETTINGS[:organizations_enabled]
50
+ end
51
+ end
52
+
53
+ describe 'on image step' do
54
+ ['hub', 'registry'].each do |tab|
55
+ describe "on #{tab} tab" do
56
+ let(:image_field_id) { "#{tab}_docker_container_wizard_states_image_repository_name" }
57
+ let(:tag_field_id) { "#{tab}_docker_container_wizard_states_image_tag" }
58
+
59
+ setup do
60
+ registry.save
61
+ wizard_state.preliminary = preliminary
62
+ visit wizard_state_step_path(:wizard_state_id => wizard_state, :id => :image)
63
+ find("##{tab}_tab").click
64
+
65
+ if tab == 'registry'
66
+ find("#docker_container_wizard_states_image_registry_id option:last-child", :visible => false)
67
+ .select_option
68
+ end
69
+ end
70
+
71
+ test 'clicking on search loads repositories' do
72
+ image_search_service.expects(:search).at_least(2)
73
+ .returns(image_search_results)
74
+ fill_in image_field_id, :with => "fake"
75
+ wait_for_ajax
76
+ find("#search_repository_button_#{tab}").click
77
+ wait_for_ajax
78
+ assert_text 'my_fake_repository_result'
79
+ end
80
+
81
+ describe 'autcomplete' do
82
+ describe 'for image name' do
83
+ test 'entering text triggers autocomplete' do
84
+ image_search_service.expects(:search)
85
+ .returns(image_search_results)
86
+ fill_in image_field_id, :with => 'fa'
87
+ wait_for_ajax
88
+ has_selector?('.ui-autocomplete a', :text => 'my_fake_repository_result')
89
+ end
90
+
91
+ if tab == 'registry'
92
+ context 'when no registry is selected' do
93
+ test 'it does not trigger a autocomplete' do
94
+ image_search_service.expects(:search).never
95
+ find("#docker_container_wizard_states_image_registry_id option:first-child", :visible => false).select_option
96
+ fill_in image_field_id, :with => 'fa'
97
+ wait_for_ajax
98
+ has_no_selector?('.ui-autocomplete a', :text => 'my_fake_repository_result')
99
+ end
100
+ end
101
+ end
102
+ end
103
+
104
+ describe 'for tag' do
105
+ let(:image_name) { 'fake' }
106
+ let(:tag_snippet) { 'lat' }
107
+
108
+ setup do
109
+ fill_in image_field_id, :with => 'fake'
110
+ end
111
+
112
+ test 'it searches for tags' do
113
+ image_search_service.expects(:search).at_least(2)
114
+ .returns(['latest'])
115
+ fill_in tag_field_id, :with => tag_snippet
116
+ wait_for_ajax
117
+ has_selector?('.ui-autocomplete a', :text => 'latest')
118
+ end
119
+ end
120
+ end
121
+ end
122
+ end
13
123
  end
14
- # test 'clicking on search loads repositories' do
15
- # Capybara.javascript_driver = :webkit
16
- # container = FactoryGirl.create(:container)
17
- # visit container_step_path(:container_id => container.id, :id => :repository)
18
- # ComputeResource.any_instance.expects(:search).returns([{'name' => 'my_fake_repository_result',
19
- # 'star_count' => 300,
20
- # 'description' => 'fake repository'}])
21
- # click_button 'search_repository'
22
- # assert has_link? 'my_fake_repository_result'
23
- # end
24
124
  end
@@ -0,0 +1,19 @@
1
+ require 'integration_test_helper'
2
+
3
+ class RegistryiCreationTest < IntegrationTestWithJavascript
4
+ let(:registry_values) { FactoryGirl.build(:docker_registry) }
5
+
6
+ setup do
7
+ DockerRegistry.any_instance.stubs(:attempt_login).returns(true)
8
+ visit new_registry_path
9
+ end
10
+
11
+ test 'can create a registy' do
12
+ assert_difference('DockerRegistry.count') do
13
+ fill_in 'docker_registry_name', with: registry_values.name
14
+ fill_in 'docker_registry_url', with: registry_values.url
15
+ page.find('#new_docker_registry .btn-primary').click
16
+ wait_for_ajax
17
+ end
18
+ end
19
+ end
@@ -32,7 +32,6 @@ module DockerContainerWizardStates
32
32
  Service::RegistryApi.stubs(:docker_hub).returns(docker_hub)
33
33
  end
34
34
 
35
-
36
35
  describe 'it validates that the image is available' do
37
36
  test 'validates via the image_search_service' do
38
37
  DockerContainerWizardStates::Image.any_instance
@@ -55,12 +55,4 @@ class DockerRegistryTest < ActiveSupport::TestCase
55
55
  assert_kind_of Service::RegistryApi, api
56
56
  end
57
57
  end
58
-
59
- describe '#api' do
60
- let(:api) { subject.api }
61
-
62
- test 'returns a RegistryApi instance' do
63
- assert_kind_of Service::RegistryApi, api
64
- end
65
- end
66
58
  end
@@ -30,6 +30,15 @@ class RegistryApiTest < ActiveSupport::TestCase
30
30
  assert_equal password, subject.connection.options[:password]
31
31
  end
32
32
  end
33
+
34
+ context 'verify ssl is set' do
35
+ let(:verify_ssl) { [true, false].sample }
36
+ subject { Service::RegistryApi.new(url: url, verify_ssl: verify_ssl) }
37
+
38
+ test 'it passes it as ssl_verify_peer' do
39
+ assert_equal verify_ssl, subject.connection.options[:ssl_verify_peer]
40
+ end
41
+ end
33
42
  end
34
43
 
35
44
  describe '#get' do
@@ -185,8 +194,11 @@ class RegistryApiTest < ActiveSupport::TestCase
185
194
 
186
195
  describe '#ok?' do
187
196
  test 'calls the API via #get with /v1/' do
197
+ params = subject.send(:default_connection_options)
198
+ .merge(subject.send(:credentials))
199
+ .merge(path: '/v1/')
188
200
  subject.connection.expects(:get)
189
- .with('/', nil, Service::RegistryApi::DEFAULTS[:connection].merge(path: '/v1/'))
201
+ .with('/', nil, params)
190
202
  .returns('Docker Registry API')
191
203
  assert subject.ok?
192
204
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: foreman_docker
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.1.0
4
+ version: 3.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel Lobato, Amos Benari
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-06-07 00:00:00.000000000 Z
11
+ date: 2017-06-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: docker-api
@@ -72,14 +72,14 @@ dependencies:
72
72
  requirements:
73
73
  - - '='
74
74
  - !ruby/object:Gem::Version
75
- version: 0.46.0
75
+ version: 0.49.1
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
80
  - - '='
81
81
  - !ruby/object:Gem::Version
82
- version: 0.46.0
82
+ version: 0.49.1
83
83
  description: Provision and manage Docker containers and images from Foreman.
84
84
  email:
85
85
  - dlobatog@redhat.com, abenari@redhat.com
@@ -91,7 +91,8 @@ files:
91
91
  - LICENSE
92
92
  - README.md
93
93
  - Rakefile
94
- - app/assets/javascripts/foreman_docker/image_step.js
94
+ - app/assets/javascripts/foreman_docker/container_image_search.js
95
+ - app/assets/javascripts/foreman_docker/create_registry.js
95
96
  - app/assets/stylesheets/foreman_docker/autocomplete.css.scss
96
97
  - app/assets/stylesheets/foreman_docker/terminal.css.scss
97
98
  - app/controllers/api/v2/containers_controller.rb
@@ -189,6 +190,7 @@ files:
189
190
  - db/migrate/20150814205620_change_container_column_type.rb
190
191
  - db/migrate/20160605133025_create_docker_parameters.rb
191
192
  - db/migrate/20160605134652_move_parameters_to_docker_parameters.rb
193
+ - db/migrate/20170508130316_add_verify_ssl_option_to_docker_registries.rb
192
194
  - lib/foreman_docker.rb
193
195
  - lib/foreman_docker/engine.rb
194
196
  - lib/foreman_docker/version.rb
@@ -226,6 +228,7 @@ files:
226
228
  - test/functionals/image_search_controller_test.rb
227
229
  - test/integration/container_steps_test.rb
228
230
  - test/integration/container_test.rb
231
+ - test/integration/registry_creation_test.rb
229
232
  - test/test_plugin_helper.rb
230
233
  - test/units/container_remover_test.rb
231
234
  - test/units/container_test.rb
@@ -272,15 +275,16 @@ test_files:
272
275
  - test/functionals/image_search_controller_test.rb
273
276
  - test/integration/container_test.rb
274
277
  - test/integration/container_steps_test.rb
278
+ - test/integration/registry_creation_test.rb
275
279
  - test/units/container_remover_test.rb
276
280
  - test/units/foreman_docker/compute_resource_extensions_test.rb
277
281
  - test/units/foreman_docker/docker_test.rb
278
282
  - test/units/utility_service_test.rb
279
283
  - test/units/container_test.rb
280
- - test/units/docker_registry_test.rb
281
284
  - test/units/image_search_service_test.rb
282
285
  - test/units/containers_service_test.rb
283
286
  - test/units/docker_container_wizard_states/image_test.rb
287
+ - test/units/docker_registry_test.rb
284
288
  - test/units/registry_api_test.rb
285
289
  - test/test_plugin_helper.rb
286
290
  - ".rubocop.yml"
@@ -1,175 +0,0 @@
1
- $(document).ready(function() {
2
- setupAutoComplete("hub");
3
- setupAutoComplete("registry");
4
- $('#hub_tab').click( function() {
5
- $('#docker_container_wizard_states_image_registry_id').val('');
6
- });
7
- });
8
-
9
- function setupAutoComplete(registryType) {
10
- var tag = getTag(registryType),
11
- repo = getRepo(registryType);
12
-
13
- tag.autocomplete({
14
- source: [],
15
- autoFocus: true,
16
- delay: 500,
17
- minLength: 0
18
- }).focus( function() {
19
- $(this).data("uiAutocomplete").search($(this).val());
20
- });
21
-
22
- repo.autocomplete({
23
- source: function( request, response ) { autoCompleteRepo(repo); },
24
- delay: 500,
25
- minLength: 1
26
- });
27
- }
28
-
29
- function paramsForSearch(registryType) {
30
- var image = getRepo(registryType),
31
- tag = getTag(registryType),
32
- registryId = $('#docker_container_wizard_states_image_registry_id').val(),
33
- params = {
34
- registry: registryType,
35
- search: image.val()
36
- }
37
-
38
- if (tag.val() != '') {
39
- params.search = image.val() + ':' + tag.val();
40
- };
41
-
42
- if (registryType == 'registry' && registryId != '') {
43
- params.registry_id = registryId;
44
- };
45
-
46
- return params;
47
- }
48
-
49
- function autoCompleteRepo(item) {
50
- var registryType = $(item).data('registry'),
51
- search_add_on = getImageConfirmation(registryType),
52
- tag = getTag(registryType),
53
- params = paramsForSearch(registryType);
54
-
55
- if (params.search == '' ||
56
- (registryType == 'registry' && typeof params.registry_id == 'undefined')) {
57
- return;
58
- }
59
-
60
- // Patternfly spinner uses 'float: left' and moves it to the left of the
61
- // search button. Instead, we use FontAwesome's spinner to keep it at
62
- // the right.
63
- search_add_on.attr('class', 'fa fa-spin fa-circle-o-notch');
64
-
65
- $.ajax({
66
- type:'get',
67
- url: $(item).attr('data-url'),
68
- data: params,
69
- success:function (result) {
70
- if(result == 'true'){
71
- search_add_on.attr('title', 'Image found in the compute resource');
72
- search_add_on.attr('class', 'pficon pficon-ok');
73
- setWaitingText('Image found: <strong>' + item.val() + '</strong>. Retrieving available tags, please wait...', registryType);
74
- setAutocompleteTags(registryType);
75
- } else {
76
- search_add_on.attr('title', 'Image NOT found in the compute resource');
77
- search_add_on.attr('class', 'pficon pficon-error-circle-o');
78
- tag.autocomplete('option', 'source', []);
79
- }
80
- },
81
- error: function(result) {
82
- $.jnotify(result.responseText, "error", true);
83
- }
84
- });
85
- }
86
-
87
- function setAutocompleteTags(registryType) {
88
- var registryType = registryType,
89
- tag = getTag(registryType),
90
- source = [];
91
-
92
- tag.addClass('spinner-label');
93
- tag.val('');
94
-
95
- $.getJSON( tag.data("url"),
96
- paramsForSearch(registryType),
97
- function(data) {
98
- getSearchSpinner(registryType).hide();
99
- tag.removeClass('spinner-label');
100
- $.each( data, function(index, value) {
101
- source.push({label: value.label, value: value.value});
102
- });
103
- tag.focus();
104
- })
105
- .error(function(result) {
106
- $.jnotify(result.responseText, "error", true);
107
- });
108
- tag.autocomplete('option', 'source', source);
109
- }
110
-
111
- function searchRepo(item) {
112
- var registryType = $(item).data('registry'),
113
- results = getRepositorySearchResults(registryType),
114
- search = getRepo(registryType),
115
- searching_spinner = getSearchSpinner(registryType);
116
- setWaitingText('<strong>Searching</strong> in the hub, this can be slow, please wait...', registryType);
117
- results.html('');
118
- results.show();
119
- $.ajax({
120
- type:'get',
121
- dataType:'text',
122
- url: $(item).attr('data-url'),
123
- data: paramsForSearch(registryType),
124
- success: function (result) {
125
- results.html(result);
126
- },
127
- error: function(result) {
128
- $.jnotify(result.responseText, "error", true);
129
- },
130
- complete: function (result) {
131
- searching_spinner.hide();
132
- }
133
- });
134
- }
135
-
136
- function repoSelected(item) {
137
- var registryType = "hub";
138
- if ($(item).data("hub") !== true) {
139
- registryType = "registry";
140
- }
141
-
142
- getRepositorySearchResults(registryType).hide();
143
- setWaitingText('Image selected: <strong>' + item.text + '</strong>. Retrieving available tags, please wait...', registryType);
144
- getRepo(registryType).val(item.text);
145
- setAutocompleteTags(registryType);
146
- }
147
-
148
- function setWaitingText(string, registryType) {
149
- getWaitText(registryType).html(string);
150
- getSearchSpinner(registryType).show();
151
- }
152
-
153
- function getTag(registryType) {
154
- return $('form[data-registry="' + registryType + '"] input[data-tag]:first');
155
- }
156
-
157
- function getRepo(registryType) {
158
- return $('form[data-registry="' + registryType + '"] input[data-search]:first');
159
- }
160
-
161
- function getSearchSpinner(registryType) {
162
- return $('form[data-registry="' + registryType + '"] [data-search-spinner]:first');
163
- }
164
-
165
- function getRepositorySearchResults(registryType) {
166
- return $('form[data-registry="' + registryType + '"] [data-repository-search-results]:first');
167
- }
168
-
169
- function getImageConfirmation(registryType) {
170
- return $('form[data-registry="' + registryType + '"] #image-confirmation');
171
- }
172
-
173
- function getWaitText(registryType) {
174
- return $('form[data-registry="' + registryType + '"] [data-wait-text]:first');
175
- }