foreman_docker 3.1.0 → 3.2.0

Sign up to get free protection for your applications and to get access to all the features.
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
- }