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.
- 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
|