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.
- checksums.yaml +4 -4
- data/.rubocop.yml +22 -22
- data/app/assets/javascripts/foreman_docker/image_step.js +36 -6
- data/app/controllers/api/v2/containers_controller.rb +13 -11
- data/app/controllers/containers/steps_controller.rb +8 -2
- data/app/controllers/containers_controller.rb +4 -3
- data/app/controllers/image_search_controller.rb +36 -79
- data/app/helpers/container_steps_helper.rb +21 -0
- data/app/models/concerns/foreman_docker/parameter_validators.rb +27 -4
- data/app/models/container.rb +9 -10
- data/app/models/docker_container_wizard_state.rb +2 -0
- data/app/models/docker_container_wizard_states/dns.rb +2 -8
- data/app/models/docker_container_wizard_states/environment.rb +4 -14
- data/app/models/docker_container_wizard_states/environment_variable.rb +2 -2
- data/app/models/docker_container_wizard_states/exposed_port.rb +2 -8
- data/app/models/docker_container_wizard_states/image.rb +30 -0
- data/app/models/docker_container_wizard_states/preliminary.rb +1 -1
- data/app/models/docker_parameter.rb +20 -0
- data/app/models/docker_registry.rb +6 -4
- data/app/models/environment_variable.rb +3 -3
- data/app/models/exposed_port.rb +4 -10
- data/app/models/foreman_docker/compute_resource_extensions.rb +11 -0
- data/app/models/foreman_docker/dns.rb +3 -9
- data/app/models/foreman_docker/docker.rb +1 -5
- data/app/models/service/containers.rb +15 -11
- data/app/models/service/registry_api.rb +87 -15
- data/app/services/foreman_docker/image_search.rb +92 -0
- data/app/views/containers/index.html.erb +1 -3
- data/app/views/containers/show.html.erb +1 -1
- data/app/views/containers/steps/_image_hub_tab.html.erb +39 -29
- data/app/views/containers/steps/_title.html.erb +1 -1
- data/app/views/containers/steps/preliminary.html.erb +1 -1
- data/app/views/foreman_docker/common_parameters/_dns_entry.html.erb +1 -1
- data/app/views/foreman_docker/common_parameters/_environment_variable.html.erb +1 -1
- data/app/views/foreman_docker/common_parameters/_exposed_port.html.erb +1 -1
- data/app/views/image_search/_repository_search_results.html.erb +1 -1
- data/app/views/registries/index.html.erb +1 -3
- data/app/views/registries/new.html.erb +1 -1
- data/db/migrate/20160605133025_create_docker_parameters.rb +13 -0
- data/db/migrate/20160605134652_move_parameters_to_docker_parameters.rb +27 -0
- data/lib/foreman_docker/engine.rb +6 -7
- data/lib/foreman_docker/version.rb +1 -1
- data/lib/tasks/test.rake +35 -0
- data/test/functionals/api/v2/containers_controller_test.rb +21 -0
- data/test/functionals/api/v2/registries_controller_test.rb +4 -3
- data/test/functionals/containers_controller_test.rb +5 -0
- data/test/functionals/containers_steps_controller_test.rb +74 -36
- data/test/functionals/image_search_controller_test.rb +166 -12
- data/test/integration/container_test.rb +1 -1
- data/test/test_plugin_helper.rb +10 -0
- data/test/units/container_test.rb +1 -1
- data/test/units/containers_service_test.rb +31 -9
- data/test/units/docker_container_wizard_states/image_test.rb +84 -0
- data/test/units/docker_registry_test.rb +27 -10
- data/test/units/foreman_docker/compute_resource_extensions_test.rb +10 -0
- data/test/units/image_search_service_test.rb +188 -0
- data/test/units/registry_api_test.rb +206 -12
- metadata +55 -36
- data/lib/foreman_docker/tasks/test.rake +0 -45
- data/locale/de/foreman_docker.edit.po +0 -631
- data/locale/de/foreman_docker.po.time_stamp +0 -0
- data/locale/es/foreman_docker.edit.po +0 -631
- data/locale/es/foreman_docker.po.time_stamp +0 -0
- data/locale/fr/foreman_docker.edit.po +0 -632
- data/locale/fr/foreman_docker.po.time_stamp +0 -0
- data/locale/it/foreman_docker.edit.po +0 -630
- data/locale/it/foreman_docker.po.time_stamp +0 -0
- data/locale/ja/foreman_docker.edit.po +0 -634
- data/locale/ja/foreman_docker.po.time_stamp +0 -0
- data/locale/ko/foreman_docker.edit.po +0 -629
- data/locale/ko/foreman_docker.po.time_stamp +0 -0
- data/locale/pt_BR/foreman_docker.edit.po +0 -631
- data/locale/pt_BR/foreman_docker.po.time_stamp +0 -0
- data/locale/ru/foreman_docker.edit.po +0 -630
- data/locale/ru/foreman_docker.po.time_stamp +0 -0
- data/locale/zh_CN/foreman_docker.edit.po +0 -628
- data/locale/zh_CN/foreman_docker.po.time_stamp +0 -0
- data/locale/zh_TW/foreman_docker.edit.po +0 -628
- 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:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ebb80b781a7f84fa7654be95ec8d3404a4164931
|
4
|
+
data.tar.gz: 27d789e92be3bd4b2e10078808f8769aece0874c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5a9d5ffaf42b7a30a2a67f41ee5250dba09da5f18ba7e92e02ffe120791de1c5558b7b1b458c2f9e50a48e778dc0efd4e5d6972225345787ea3e8a88c2afb553
|
7
|
+
data.tar.gz: bd2b7877e5fd9e3c2c95a8991b0c9f189b67cc8d82def3d2e43442f0afb47ffd443664a6a991fa35a3b5fec3fc2cc58ac1a6bfad8272dfd4c7877c9f04342f52
|
data/.rubocop.yml
CHANGED
@@ -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
|
-
|
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
|
-
#
|
19
|
+
# Support both ruby19 and hash_rockets
|
9
20
|
Style/HashSyntax:
|
10
|
-
|
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
|
-
|
20
|
-
|
23
|
+
Style/StringLiterals:
|
24
|
+
Enabled: false
|
21
25
|
|
22
|
-
|
26
|
+
Style/FrozenStringLiteralComment:
|
23
27
|
Enabled: false
|
24
28
|
|
25
29
|
Metrics/ClassLength:
|
26
|
-
|
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
|
-
|
35
|
-
|
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:
|
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
|
88
|
+
var registryType = registryType,
|
89
|
+
tag = getTag(registryType),
|
90
|
+
source = [];
|
91
|
+
|
63
92
|
tag.addClass('spinner-label');
|
64
93
|
tag.val('');
|
65
|
-
|
66
|
-
$.getJSON( tag.data("url"),
|
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:
|
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
|
-
|
21
|
-
|
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,
|
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
|
-
|
173
|
-
|
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 =>
|
54
|
-
:
|
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
|
-
|
103
|
-
|
104
|
-
|
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
|
-
|
12
|
-
|
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
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
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
|
-
|
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 =
|
40
|
-
|
41
|
-
|
42
|
-
|
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
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
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
|
-
|
7
|
-
|
8
|
-
|
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
|