foreman_docker 3.0.0 → 3.1.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 (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