foreman_docker 3.0.0 → 3.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (79) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +22 -22
  3. data/app/assets/javascripts/foreman_docker/image_step.js +36 -6
  4. data/app/controllers/api/v2/containers_controller.rb +13 -11
  5. data/app/controllers/containers/steps_controller.rb +8 -2
  6. data/app/controllers/containers_controller.rb +4 -3
  7. data/app/controllers/image_search_controller.rb +36 -79
  8. data/app/helpers/container_steps_helper.rb +21 -0
  9. data/app/models/concerns/foreman_docker/parameter_validators.rb +27 -4
  10. data/app/models/container.rb +9 -10
  11. data/app/models/docker_container_wizard_state.rb +2 -0
  12. data/app/models/docker_container_wizard_states/dns.rb +2 -8
  13. data/app/models/docker_container_wizard_states/environment.rb +4 -14
  14. data/app/models/docker_container_wizard_states/environment_variable.rb +2 -2
  15. data/app/models/docker_container_wizard_states/exposed_port.rb +2 -8
  16. data/app/models/docker_container_wizard_states/image.rb +30 -0
  17. data/app/models/docker_container_wizard_states/preliminary.rb +1 -1
  18. data/app/models/docker_parameter.rb +20 -0
  19. data/app/models/docker_registry.rb +6 -4
  20. data/app/models/environment_variable.rb +3 -3
  21. data/app/models/exposed_port.rb +4 -10
  22. data/app/models/foreman_docker/compute_resource_extensions.rb +11 -0
  23. data/app/models/foreman_docker/dns.rb +3 -9
  24. data/app/models/foreman_docker/docker.rb +1 -5
  25. data/app/models/service/containers.rb +15 -11
  26. data/app/models/service/registry_api.rb +87 -15
  27. data/app/services/foreman_docker/image_search.rb +92 -0
  28. data/app/views/containers/index.html.erb +1 -3
  29. data/app/views/containers/show.html.erb +1 -1
  30. data/app/views/containers/steps/_image_hub_tab.html.erb +39 -29
  31. data/app/views/containers/steps/_title.html.erb +1 -1
  32. data/app/views/containers/steps/preliminary.html.erb +1 -1
  33. data/app/views/foreman_docker/common_parameters/_dns_entry.html.erb +1 -1
  34. data/app/views/foreman_docker/common_parameters/_environment_variable.html.erb +1 -1
  35. data/app/views/foreman_docker/common_parameters/_exposed_port.html.erb +1 -1
  36. data/app/views/image_search/_repository_search_results.html.erb +1 -1
  37. data/app/views/registries/index.html.erb +1 -3
  38. data/app/views/registries/new.html.erb +1 -1
  39. data/db/migrate/20160605133025_create_docker_parameters.rb +13 -0
  40. data/db/migrate/20160605134652_move_parameters_to_docker_parameters.rb +27 -0
  41. data/lib/foreman_docker/engine.rb +6 -7
  42. data/lib/foreman_docker/version.rb +1 -1
  43. data/lib/tasks/test.rake +35 -0
  44. data/test/functionals/api/v2/containers_controller_test.rb +21 -0
  45. data/test/functionals/api/v2/registries_controller_test.rb +4 -3
  46. data/test/functionals/containers_controller_test.rb +5 -0
  47. data/test/functionals/containers_steps_controller_test.rb +74 -36
  48. data/test/functionals/image_search_controller_test.rb +166 -12
  49. data/test/integration/container_test.rb +1 -1
  50. data/test/test_plugin_helper.rb +10 -0
  51. data/test/units/container_test.rb +1 -1
  52. data/test/units/containers_service_test.rb +31 -9
  53. data/test/units/docker_container_wizard_states/image_test.rb +84 -0
  54. data/test/units/docker_registry_test.rb +27 -10
  55. data/test/units/foreman_docker/compute_resource_extensions_test.rb +10 -0
  56. data/test/units/image_search_service_test.rb +188 -0
  57. data/test/units/registry_api_test.rb +206 -12
  58. metadata +55 -36
  59. data/lib/foreman_docker/tasks/test.rake +0 -45
  60. data/locale/de/foreman_docker.edit.po +0 -631
  61. data/locale/de/foreman_docker.po.time_stamp +0 -0
  62. data/locale/es/foreman_docker.edit.po +0 -631
  63. data/locale/es/foreman_docker.po.time_stamp +0 -0
  64. data/locale/fr/foreman_docker.edit.po +0 -632
  65. data/locale/fr/foreman_docker.po.time_stamp +0 -0
  66. data/locale/it/foreman_docker.edit.po +0 -630
  67. data/locale/it/foreman_docker.po.time_stamp +0 -0
  68. data/locale/ja/foreman_docker.edit.po +0 -634
  69. data/locale/ja/foreman_docker.po.time_stamp +0 -0
  70. data/locale/ko/foreman_docker.edit.po +0 -629
  71. data/locale/ko/foreman_docker.po.time_stamp +0 -0
  72. data/locale/pt_BR/foreman_docker.edit.po +0 -631
  73. data/locale/pt_BR/foreman_docker.po.time_stamp +0 -0
  74. data/locale/ru/foreman_docker.edit.po +0 -630
  75. data/locale/ru/foreman_docker.po.time_stamp +0 -0
  76. data/locale/zh_CN/foreman_docker.edit.po +0 -628
  77. data/locale/zh_CN/foreman_docker.po.time_stamp +0 -0
  78. data/locale/zh_TW/foreman_docker.edit.po +0 -628
  79. data/locale/zh_TW/foreman_docker.po.time_stamp +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 26d60710f8feff575f0ad158fe70dcd4ca943a4b
4
- data.tar.gz: c2cb12599647a844761982076c1b8b176d5c378e
3
+ metadata.gz: ebb80b781a7f84fa7654be95ec8d3404a4164931
4
+ data.tar.gz: 27d789e92be3bd4b2e10078808f8769aece0874c
5
5
  SHA512:
6
- metadata.gz: 96ad25c6bd9fa70731aaa122c26d4515e6094162bd0b998b88b0d64d5f5cd1bc420b21f932ea624c65b5fb9410030a232d5e6dc0c587321b0e4952717f4abd18
7
- data.tar.gz: 1e1853fbe2f9f8ce9ecf4f3b8811d7cd0a2a2fbf0afa43298662607559f0cbf7e0d143de93e4c384ce7e16a393aaf157bca069d408c5b931364205aa468860e2
6
+ metadata.gz: 5a9d5ffaf42b7a30a2a67f41ee5250dba09da5f18ba7e92e02ffe120791de1c5558b7b1b458c2f9e50a48e778dc0efd4e5d6972225345787ea3e8a88c2afb553
7
+ data.tar.gz: bd2b7877e5fd9e3c2c95a8991b0c9f189b67cc8d82def3d2e43442f0afb47ffd443664a6a991fa35a3b5fec3fc2cc58ac1a6bfad8272dfd4c7877c9f04342f52
@@ -1,38 +1,38 @@
1
+ # TODO: remove this file by either moving cops here or fixing code
2
+ inherit_from:
3
+ - .rubocop_todo.yml
4
+
1
5
  AllCops:
2
- RunRailsCops: true # always run the rails cops
6
+ TargetRubyVersion: 2.0
7
+
8
+ Rails: # always run the rails cops
9
+ Enabled: true
10
+
11
+ # Don't is_a? over kind_of?
12
+ Style/ClassCheck:
13
+ Enabled: false
3
14
 
4
15
  # Don't enforce documentation
5
16
  Style/Documentation:
6
17
  Enabled: false
7
18
 
8
- # Need to support ruby 1.8
19
+ # Support both ruby19 and hash_rockets
9
20
  Style/HashSyntax:
10
- EnforcedStyle: hash_rockets
11
-
12
- # Force before_filter until upgrade to Rails 4
13
- Rails/ActionFilter:
14
- EnforcedStyle: filter
15
-
16
- Metrics/LineLength:
17
- Max: 100
21
+ Enabled: false
18
22
 
19
- Metrics/MethodLength:
20
- Max: 20
23
+ Style/StringLiterals:
24
+ Enabled: false
21
25
 
22
- StringLiterals:
26
+ Style/FrozenStringLiteralComment:
23
27
  Enabled: false
24
28
 
25
29
  Metrics/ClassLength:
26
- Max: 200
27
-
28
- Metrics/AbcSize:
29
- Enabled: false # should we turn this on?
30
-
31
- Style/MethodCalledOnDoEndBlock:
32
- Enabled: true
30
+ Exclude:
31
+ - 'test/**/*'
33
32
 
34
- Style/DotPosition:
35
- EnforcedStyle: 'leading'
33
+ Performance/FixedSize:
34
+ Exclude:
35
+ - 'test/**/*'
36
36
 
37
37
  Rails/Date:
38
38
  Exclude:
@@ -26,10 +26,36 @@ function setupAutoComplete(registryType) {
26
26
  });
27
27
  }
28
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
+
29
49
  function autoCompleteRepo(item) {
30
50
  var registryType = $(item).data('registry'),
31
51
  search_add_on = getImageConfirmation(registryType),
32
- tag = getTag(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
+ }
33
59
 
34
60
  // Patternfly spinner uses 'float: left' and moves it to the left of the
35
61
  // search button. Instead, we use FontAwesome's spinner to keep it at
@@ -39,7 +65,7 @@ function autoCompleteRepo(item) {
39
65
  $.ajax({
40
66
  type:'get',
41
67
  url: $(item).attr('data-url'),
42
- data: { search: item.val(), registry_id: $('#docker_container_wizard_states_image_registry_id').val() },
68
+ data: params,
43
69
  success:function (result) {
44
70
  if(result == 'true'){
45
71
  search_add_on.attr('title', 'Image found in the compute resource');
@@ -59,11 +85,15 @@ function autoCompleteRepo(item) {
59
85
  }
60
86
 
61
87
  function setAutocompleteTags(registryType) {
62
- var tag = getTag(registryType);
88
+ var registryType = registryType,
89
+ tag = getTag(registryType),
90
+ source = [];
91
+
63
92
  tag.addClass('spinner-label');
64
93
  tag.val('');
65
- var source = [];
66
- $.getJSON( tag.data("url"), { search: getRepo(registryType).val(), registry_id: $('#docker_container_wizard_states_image_registry_id').val() },
94
+
95
+ $.getJSON( tag.data("url"),
96
+ paramsForSearch(registryType),
67
97
  function(data) {
68
98
  getSearchSpinner(registryType).hide();
69
99
  tag.removeClass('spinner-label');
@@ -90,7 +120,7 @@ function searchRepo(item) {
90
120
  type:'get',
91
121
  dataType:'text',
92
122
  url: $(item).attr('data-url'),
93
- data: { search: search.val(), registry_id: $('#docker_container_wizard_states_image_registry_id').val() },
123
+ data: paramsForSearch(registryType),
94
124
  success: function (result) {
95
125
  results.html(result);
96
126
  },
@@ -17,11 +17,10 @@ module Api
17
17
  param_group :search_and_pagination, ::Api::V2::BaseController
18
18
 
19
19
  def index
20
- if params[:compute_resource_id].present?
21
- scoped = Container.where(:compute_resource_id => params[:compute_resource_id])
22
- else
23
- scoped = Container.where(nil)
20
+ compute_resource_id = params[:compute_resource_id].tap do |id|
21
+ id.present? ? { :compute_resource_id => id } : nil
24
22
  end
23
+ scoped = Container.where(compute_resource_id)
25
24
  @containers = scoped.search_for(params[:search], :order => params[:order])
26
25
  .paginate(:page => params[:page])
27
26
  end
@@ -53,7 +52,7 @@ module Api
53
52
  param :memory, String
54
53
  param :cpu_shares, :number
55
54
  param :cpu_set, String
56
- param :environment_variables, Hash
55
+ param :environment_variables, Array, :desc => N_("Optional array of environment variables hashes. e.g. 'environment_variables': [{'name' => 'example', 'value' => '123'}]")
57
56
  param :attach_stdout, :bool
58
57
  param :attach_stdin, :bool
59
58
  param :attach_stderr, :bool
@@ -73,16 +72,13 @@ module Api
73
72
  @container = service.start_container!(set_wizard_state)
74
73
  if service.errors.any?
75
74
  render :json => { :errors => service.errors,
76
- :full_messages => service.full_messages
75
+ :full_messages => service.full_messages.join(', ')
77
76
  },
78
77
  :status => :unprocessable_entity
79
78
  else
80
79
  set_container_taxonomies
81
80
  process_response @container.save
82
81
  end
83
- rescue ActiveModel::MassAssignmentSecurity::Error => e
84
- render :json => { :error => _("Wrong attributes: %s") % e.message },
85
- :status => :unprocessable_entity
86
82
  end
87
83
 
88
84
  api :DELETE, '/containers/:id/', N_('Delete a container')
@@ -169,8 +165,14 @@ module Api
169
165
  end
170
166
 
171
167
  if params[:container][:environment_variables].present?
172
- wizard_state.environment.environment_variables =
173
- params[:container][:environment_variables]
168
+ environment_variables = []
169
+ params[:container][:environment_variables].each do |env_var|
170
+ environment_variable = DockerContainerWizardStates::EnvironmentVariable.new
171
+ environment_variable.key = env_var[:key]
172
+ environment_variable.value = env_var[:value]
173
+ environment_variables << environment_variable
174
+ end
175
+ wizard_state.environment.environment_variables = environment_variables
174
176
  end
175
177
  wizard_state.tap(&:save)
176
178
  end
@@ -39,6 +39,10 @@ module Containers
39
39
  instance_variable_set("@docker_container_wizard_states_#{step}", s)
40
40
  end
41
41
 
42
+ def docker_parameters_permited_params
43
+ [:key, :reference_id, :value, :_destroy, :id]
44
+ end
45
+
42
46
  def state_params
43
47
  attrs = case step
44
48
  when :preliminary
@@ -50,8 +54,9 @@ module Containers
50
54
  when :environment
51
55
  [:tty, :docker_container_wizard_state_id,
52
56
  :attach_stdin, :attach_stdout, :attach_stderr,
53
- :exposed_ports_attributes => [], :environment_variables_attributes => [],
54
- :dns_attributes => []
57
+ :exposed_ports_attributes => docker_parameters_permited_params,
58
+ :environment_variables_attributes => docker_parameters_permited_params,
59
+ :dns_attributes => docker_parameters_permited_params
55
60
  ]
56
61
  end
57
62
 
@@ -72,6 +77,7 @@ module Containers
72
77
  else
73
78
  service.create_container!(@state)
74
79
  end
80
+
75
81
  if container.present?
76
82
  process_success(:object => container, :success_redirect => container_path(container))
77
83
  else
@@ -99,9 +99,10 @@ class ContainersController < ::ApplicationController
99
99
  end
100
100
 
101
101
  def container_deletion
102
- if params[:compute_resource_id].present?
103
- compute_resource_id = params[:compute_resource_id]
104
- container_uuid = params[:id]
102
+ # TODO: Refactor to recognize params[:compute_resource_id] as well.
103
+ compute_resource_id = params[:compute_resource_id].tap { |id| id.present? ? id : nil }
104
+ if compute_resource_id
105
+ container_uuid = params[:id]
105
106
  @container ||= Container.authorized("#{action_permission}_#{controller_name}".to_sym).find_by_uuid(container_uuid)
106
107
  else
107
108
  find_container
@@ -1,34 +1,21 @@
1
1
  class ImageSearchController < ::ApplicationController
2
- before_filter :find_resource
3
-
4
- # this is incredibly odd. for some reason, rails sees the
5
- # requests ImageSearchControllerTest makes as requests from another host
6
- # thus, violating CSRF.
7
- protect_from_forgery :only => :nothing if Rails.env.test?
8
-
9
2
  def auto_complete_repository_name
10
3
  catch_network_errors do
11
- text = if use_hub?
12
- hub_image_exists?(params[:search])
13
- else
14
- registry_image_exists?(params[:search])
15
- end
16
- render :text => text.to_s
4
+ available = image_search_service.available?(params[:search])
5
+ render :text => available.to_s
17
6
  end
18
7
  end
19
8
 
20
9
  def auto_complete_image_tag
21
10
  catch_network_errors do
22
- # This is the format jQuery UI autocomplete expects
23
- tags = if use_hub?
24
- hub_auto_complete_image_tags(params[:search])
25
- else
26
- registry_auto_complete_image_tags(params[:search])
27
- end
11
+ tags = image_search_service.search({
12
+ term: params[:search],
13
+ tags: 'true'
14
+ })
15
+
28
16
  respond_to do |format|
29
17
  format.js do
30
- tags.map! { |tag| { :label => CGI.escapeHTML(tag), :value => CGI.escapeHTML(tag) } }
31
- render :json => tags
18
+ render :json => prepare_for_autocomplete(tags)
32
19
  end
33
20
  end
34
21
  end
@@ -36,11 +23,10 @@ class ImageSearchController < ::ApplicationController
36
23
 
37
24
  def search_repository
38
25
  catch_network_errors do
39
- repositories = if use_hub?
40
- hub_search_image(params[:search])
41
- else
42
- registry_search_image(params[:search])
43
- end
26
+ repositories = image_search_service.search({
27
+ term: params[:search].split(':').first,
28
+ tags: 'false'
29
+ })
44
30
 
45
31
  respond_to do |format|
46
32
  format.js do
@@ -52,6 +38,8 @@ class ImageSearchController < ::ApplicationController
52
38
  end
53
39
  end
54
40
 
41
+ private
42
+
55
43
  def catch_network_errors
56
44
  yield
57
45
  rescue Docker::Error::NotFoundError => e
@@ -67,52 +55,6 @@ class ImageSearchController < ::ApplicationController
67
55
  @registry.nil?
68
56
  end
69
57
 
70
- def hub_image_exists?(terms)
71
- @compute_resource.exist?(terms)
72
- end
73
-
74
- def hub_auto_complete_image_tags(terms)
75
- @compute_resource.tags(terms)
76
- end
77
-
78
- def hub_search_image(terms)
79
- @compute_resource.search(terms).map do |item|
80
- # el7 returns -> "name" => "docker.io: docker.io/centos",
81
- # while f20 returns -> "name" => "centos"
82
- # we need repo name to be => "docker.io/centos" for el7 and "centos" for fedora
83
- # to ensure proper search with respect to the tags, image creation etc.
84
- new_item = item.clone
85
- new_item["name"] = item["name"].split.last
86
- new_item
87
- end
88
- end
89
-
90
- def registry_image_exists?(term)
91
- result = ::Service::RegistryApi.new(:url => @registry.url,
92
- :user => @registry.username,
93
- :password => @registry.password).search(term)
94
- registry_name = if term.split('/').size > 1
95
- term
96
- else
97
- "library/#{term}"
98
- end
99
-
100
- result['results'].any? { |r| r['name'] == registry_name }
101
- end
102
-
103
- def registry_auto_complete_image_tags(terms)
104
- ::Service::RegistryApi.new(:url => @registry.url,
105
- :user => @registry.username,
106
- :password => @registry.password).list_repository_tags(terms).keys
107
- end
108
-
109
- def registry_search_image(terms)
110
- r = ::Service::RegistryApi.new(:url => @registry.url,
111
- :user => @registry.username,
112
- :password => @registry.password).search(terms)
113
- r['results']
114
- end
115
-
116
58
  def action_permission
117
59
  case params[:action]
118
60
  when 'auto_complete_repository_name', 'auto_complete_image_tag', 'search_repository'
@@ -122,13 +64,28 @@ class ImageSearchController < ::ApplicationController
122
64
  end
123
65
  end
124
66
 
125
- def find_resource
126
- if params[:registry_id].present?
127
- @registry = DockerRegistry.authorized(:view_registries).find(params[:registry_id])
128
- else
129
- @compute_resource = ComputeResource.authorized(:view_compute_resources).find(params[:id])
67
+ # This is the format jQuery UI autocomplete expects
68
+ def prepare_for_autocomplete(tags)
69
+ tags.map do |tag|
70
+ tag = tag.is_a?(Hash) ? tag.fetch('name', tag) : tag
71
+ tag = CGI.escapeHTML(tag)
72
+ { :label => tag, :value => tag }
73
+ end
74
+ end
75
+
76
+ def image_search_service
77
+ @image_search_service ||= ForemanDocker::ImageSearch.new(*sources)
78
+ end
79
+
80
+ def sources
81
+ if params[:registry] == 'hub'
82
+ @registry ||= Service::RegistryApi.docker_hub
83
+ @compute_resource ||= ComputeResource.authorized(:view_compute_resources).find(params[:id])
84
+ [@registry, @compute_resource]
85
+ elsif params[:registry] == 'registry' && params[:registry_id].present?
86
+ @registry ||= DockerRegistry.authorized(:view_registries)
87
+ .find(params[:registry_id]).api
88
+ [@registry]
130
89
  end
131
- rescue ActiveRecord::RecordNotFound
132
- not_found
133
90
  end
134
91
  end
@@ -34,6 +34,15 @@ module ContainerStepsHelper
34
34
  active_tab.to_s == tab_name.to_s ? "active" : ""
35
35
  end
36
36
 
37
+ # el7 returns -> "name" => "docker.io: docker.io/centos",
38
+ # while f20 returns -> "name" => "centos"
39
+ # we need repo name to be => "docker.io/centos" for el7 and "centos" for fedora
40
+ # to ensure proper search with respect to the tags, image creation etc.
41
+ def cleanup_image_name(name)
42
+ name.split.last
43
+ end
44
+
45
+
37
46
  def model_for(registry_type)
38
47
  if active_tab.to_s == registry_type.to_s
39
48
  @docker_container_wizard_states_image
@@ -42,6 +51,18 @@ module ContainerStepsHelper
42
51
  end
43
52
  end
44
53
 
54
+ def image_search_wrapper_class(model)
55
+ if model.errors.messages[:image]
56
+ 'form-group has-error'
57
+ else
58
+ 'form-group'
59
+ end
60
+ end
61
+
62
+ def tab_active?(registry)
63
+ active_tab == registry.to_sym
64
+ end
65
+
45
66
  def active_tab
46
67
  if @docker_container_wizard_states_image.katello?
47
68
  :katello
@@ -1,11 +1,34 @@
1
1
  module ForemanDocker
2
2
  module ParameterValidators
3
3
  extend ActiveSupport::Concern
4
- include ::ParameterValidators
5
4
 
6
- def parameters_symbol
7
- return :environment_variables if is_a? Container
8
- super
5
+ included do
6
+ validate :validate_unique_parameter_keys
7
+ end
8
+
9
+ def validate_unique_parameter_keys
10
+ parameters_symbol = [:environment_variables, :exposed_ports, :dns]
11
+ parameters_symbol.each do |param_symbol|
12
+ keys = []
13
+ errors = false
14
+
15
+ self.public_send(param_symbol).each do |param|
16
+ errors = duplicate_key?(keys, param)
17
+ end
18
+
19
+ self.errors[param_symbol] = _('Please ensure the following parameters are unique') if errors
20
+ end
21
+ end
22
+
23
+ def duplicate_key?(keys, param)
24
+ if keys.include?(param.key)
25
+ param.errors[:key] = _('has already been taken')
26
+ return true
27
+ else
28
+ keys << param.key
29
+ end
30
+
31
+ false
9
32
  end
10
33
  end
11
34
  end