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
data/app/models/container.rb
CHANGED
@@ -6,20 +6,19 @@ class Container < ActiveRecord::Base
|
|
6
6
|
belongs_to :registry, :class_name => "DockerRegistry", :foreign_key => :registry_id
|
7
7
|
has_many :environment_variables, :dependent => :destroy, :foreign_key => :reference_id,
|
8
8
|
:inverse_of => :container,
|
9
|
-
:class_name => 'EnvironmentVariable'
|
10
|
-
|
9
|
+
:class_name => 'EnvironmentVariable'
|
10
|
+
|
11
11
|
accepts_nested_attributes_for :environment_variables, :allow_destroy => true
|
12
|
-
include ForemanDocker::ParameterValidators
|
13
12
|
|
14
13
|
has_many :exposed_ports, :dependent => :destroy, :foreign_key => :reference_id,
|
15
14
|
:inverse_of => :container,
|
16
|
-
:class_name => 'ExposedPort'
|
17
|
-
:validate => true
|
15
|
+
:class_name => 'ExposedPort'
|
18
16
|
|
19
17
|
has_many :dns, :dependent => :destroy, :foreign_key => :reference_id,
|
20
18
|
:inverse_of => :container,
|
21
|
-
:class_name => 'ForemanDocker::Dns'
|
22
|
-
|
19
|
+
:class_name => 'ForemanDocker::Dns'
|
20
|
+
|
21
|
+
include ForemanDocker::ParameterValidators
|
23
22
|
|
24
23
|
accepts_nested_attributes_for :exposed_ports, :allow_destroy => true
|
25
24
|
scoped_search :on => :name
|
@@ -41,10 +40,10 @@ class Container < ActiveRecord::Base
|
|
41
40
|
'AttachStdout' => attach_stdout, 'AttachStdin' => attach_stdin,
|
42
41
|
'AttachStderr' => attach_stderr, 'CpuShares' => cpu_shares,
|
43
42
|
'Cpuset' => cpu_set,
|
44
|
-
'Env' => environment_variables.map { |env| "#{env.
|
45
|
-
'ExposedPorts' => Hash[*exposed_ports.map { |v| [v.
|
43
|
+
'Env' => environment_variables.map { |env| "#{env.key}=#{env.value}" },
|
44
|
+
'ExposedPorts' => Hash[*exposed_ports.map { |v| [v.key + "/" + v.value, {}] }.flatten],
|
46
45
|
'HostConfig' => {
|
47
|
-
'Dns' => dns.map { |env| "#{env.
|
46
|
+
'Dns' => dns.map { |env| "#{env.key}" }
|
48
47
|
} }
|
49
48
|
end
|
50
49
|
|
@@ -9,6 +9,8 @@ class DockerContainerWizardState < ActiveRecord::Base
|
|
9
9
|
:dependent => :destroy, :validate => true, :autosave => true
|
10
10
|
|
11
11
|
delegate :compute_resource_id, :to => :preliminary
|
12
|
+
delegate :compute_resource, :to => :preliminary
|
13
|
+
|
12
14
|
delegate :environment_variables, :to => :environment
|
13
15
|
delegate :exposed_ports, :to => :environment
|
14
16
|
delegate :dns, :to => :environment
|
@@ -1,17 +1,11 @@
|
|
1
1
|
require 'resolv'
|
2
2
|
|
3
3
|
module DockerContainerWizardStates
|
4
|
-
class Dns <
|
5
|
-
# The Parameter class from which this Dns class inherits,validates for the
|
6
|
-
# presence of an associated domain, operating system, host or host group.
|
7
|
-
# We will have to reset those validations for the Dns class as they do not
|
8
|
-
# make any sense for the context in which this class is being used here.
|
9
|
-
Dns.reset_callbacks(:validate)
|
10
|
-
|
4
|
+
class Dns < DockerParameter
|
11
5
|
belongs_to :environment, :foreign_key => :reference_id,
|
12
6
|
:inverse_of => :dns,
|
13
7
|
:class_name => 'DockerContainerWizardStates::Environment'
|
14
|
-
validates :
|
8
|
+
validates :key, :uniqueness => { :scope => :reference_id },
|
15
9
|
:format => {
|
16
10
|
:with => Regexp.union(Resolv::IPv4::Regex,
|
17
11
|
Resolv::IPv6::Regex,
|
@@ -3,32 +3,22 @@ module DockerContainerWizardStates
|
|
3
3
|
self.table_name_prefix = 'docker_container_wizard_states_'
|
4
4
|
belongs_to :wizard_state, :class_name => DockerContainerWizardState
|
5
5
|
|
6
|
-
# Fix me:
|
7
|
-
# Validations are off on this association as there's a bug in ::Parameter
|
8
|
-
# that forces validation of reference_id. This will fail on new records as
|
9
|
-
# validations are executed before parent and children records have been persisted.
|
10
6
|
has_many :environment_variables, :dependent => :destroy, :foreign_key => :reference_id,
|
11
7
|
:inverse_of => :environment,
|
12
8
|
:class_name =>
|
13
|
-
'DockerContainerWizardStates::EnvironmentVariable'
|
14
|
-
:validate => false
|
15
|
-
include ::ParameterValidators
|
9
|
+
'DockerContainerWizardStates::EnvironmentVariable'
|
16
10
|
|
17
11
|
has_many :exposed_ports, :dependent => :destroy, :foreign_key => :reference_id,
|
18
12
|
:inverse_of => :environment,
|
19
|
-
:class_name => 'DockerContainerWizardStates::ExposedPort'
|
20
|
-
:validate => true
|
13
|
+
:class_name => 'DockerContainerWizardStates::ExposedPort'
|
21
14
|
has_many :dns, :dependent => :destroy, :foreign_key => :reference_id,
|
22
15
|
:inverse_of => :environment,
|
23
|
-
:class_name => 'DockerContainerWizardStates::Dns'
|
24
|
-
:validate => true
|
16
|
+
:class_name => 'DockerContainerWizardStates::Dns'
|
25
17
|
|
18
|
+
include ForemanDocker::ParameterValidators
|
26
19
|
accepts_nested_attributes_for :environment_variables, :allow_destroy => true
|
27
20
|
accepts_nested_attributes_for :exposed_ports, :allow_destroy => true
|
28
21
|
accepts_nested_attributes_for :dns, :allow_destroy => true
|
29
22
|
|
30
|
-
def parameters_symbol
|
31
|
-
:environment_variables
|
32
|
-
end
|
33
23
|
end
|
34
24
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module DockerContainerWizardStates
|
2
|
-
class EnvironmentVariable <
|
2
|
+
class EnvironmentVariable < DockerParameter
|
3
3
|
belongs_to :environment, :foreign_key => :reference_id, :inverse_of => :environment_variables,
|
4
4
|
:class_name => 'DockerContainerWizardStates::Environment'
|
5
|
-
validates :
|
5
|
+
validates :key, :uniqueness => { :scope => :reference_id }
|
6
6
|
end
|
7
7
|
end
|
@@ -1,14 +1,8 @@
|
|
1
1
|
module DockerContainerWizardStates
|
2
|
-
class ExposedPort <
|
3
|
-
# The Parameter class from which ExposedPort class inherits,validates for the
|
4
|
-
# presence of an associated domain, operating system, host or host group. We
|
5
|
-
# will have to reset those validations for the ExposedPort class as they do
|
6
|
-
# not make any sense for the context in which this class is being used here.
|
7
|
-
ExposedPort.reset_callbacks(:validate)
|
8
|
-
|
2
|
+
class ExposedPort < DockerParameter
|
9
3
|
belongs_to :environment, :foreign_key => :reference_id, :inverse_of => :exposed_ports,
|
10
4
|
:class_name => 'DockerContainerWizardStates::Environment'
|
11
|
-
validates :
|
5
|
+
validates :key, :uniqueness => { :scope => :reference_id },
|
12
6
|
:numericality => { :only_integer => true,
|
13
7
|
:greater_than => 0,
|
14
8
|
:less_than_or_equal_to => 655_35 }
|
@@ -4,8 +4,38 @@ module DockerContainerWizardStates
|
|
4
4
|
belongs_to :wizard_state, :class_name => DockerContainerWizardState,
|
5
5
|
:foreign_key => :docker_container_wizard_state_id
|
6
6
|
delegate :compute_resource_id, :to => :wizard_state
|
7
|
+
delegate :compute_resource, :to => :wizard_state
|
7
8
|
|
8
9
|
validates :tag, :presence => true
|
9
10
|
validates :repository_name, :presence => true
|
11
|
+
validate :image_exists
|
12
|
+
|
13
|
+
def name
|
14
|
+
"#{repository_name}:#{tag}"
|
15
|
+
end
|
16
|
+
|
17
|
+
def registry_api
|
18
|
+
if registry_id
|
19
|
+
DockerRegistry.find(registry_id).api
|
20
|
+
else
|
21
|
+
Service::RegistryApi.docker_hub
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def sources
|
26
|
+
[compute_resource, registry_api]
|
27
|
+
end
|
28
|
+
|
29
|
+
def image_search_service
|
30
|
+
ForemanDocker::ImageSearch.new(*sources)
|
31
|
+
end
|
32
|
+
|
33
|
+
def image_exists
|
34
|
+
return true if image_search_service.available?(name)
|
35
|
+
error_msg = _("Container image %{image_name} is not available.") % {
|
36
|
+
image_name: "#{name}",
|
37
|
+
}
|
38
|
+
errors.add(:image, error_msg)
|
39
|
+
end
|
10
40
|
end
|
11
41
|
end
|
@@ -6,7 +6,7 @@ module DockerContainerWizardStates
|
|
6
6
|
belongs_to :wizard_state, :class_name => DockerContainerWizardState,
|
7
7
|
:foreign_key => :docker_container_wizard_state_id
|
8
8
|
|
9
|
-
|
9
|
+
belongs_to :compute_resource, :required => true
|
10
10
|
|
11
11
|
def used_location_ids
|
12
12
|
Location.joins(:taxable_taxonomies).where(
|
@@ -0,0 +1,20 @@
|
|
1
|
+
class DockerParameter < ActiveRecord::Base
|
2
|
+
extend FriendlyId
|
3
|
+
friendly_id :key
|
4
|
+
include Parameterizable::ByIdName
|
5
|
+
|
6
|
+
validates_lengths_from_database
|
7
|
+
|
8
|
+
include Authorizable
|
9
|
+
validates :key, :presence => true, :no_whitespace => true
|
10
|
+
|
11
|
+
scoped_search :on => :key, :complete_value => true
|
12
|
+
|
13
|
+
default_scope -> { order("docker_parameters.key") }
|
14
|
+
|
15
|
+
before_validation :strip_whitespaces
|
16
|
+
|
17
|
+
def strip_whitespaces
|
18
|
+
self.value.strip! unless value.blank?
|
19
|
+
end
|
20
|
+
end
|
@@ -42,13 +42,15 @@ class DockerRegistry < ActiveRecord::Base
|
|
42
42
|
_("Docker/Registry")
|
43
43
|
end
|
44
44
|
|
45
|
+
def api
|
46
|
+
@api ||= Service::RegistryApi.new(url: url, user: username,
|
47
|
+
password: password)
|
48
|
+
end
|
49
|
+
|
45
50
|
private
|
46
51
|
|
47
52
|
def attempt_login
|
48
|
-
|
49
|
-
:user => username,
|
50
|
-
:password => password)
|
51
|
-
login_endpoint.get == "\"OK\""
|
53
|
+
api.ok?
|
52
54
|
rescue => e
|
53
55
|
errors.add(:base, _('Unable to log in to this Docker Registry - %s') % e)
|
54
56
|
end
|
@@ -1,5 +1,5 @@
|
|
1
|
-
class EnvironmentVariable <
|
1
|
+
class EnvironmentVariable < DockerParameter
|
2
2
|
belongs_to :container, :foreign_key => :reference_id, :inverse_of => :environment_variables
|
3
|
-
audited :
|
4
|
-
validates :
|
3
|
+
audited :associated_with => :container, :allow_mass_assignment => true
|
4
|
+
validates :key, :uniqueness => { :scope => :reference_id }
|
5
5
|
end
|
data/app/models/exposed_port.rb
CHANGED
@@ -1,14 +1,8 @@
|
|
1
|
-
class ExposedPort <
|
2
|
-
# The Parameter class from which ExposedPort class inherits,validates for the
|
3
|
-
# presence of an associated domain, operating system, host or host group. We
|
4
|
-
# will have to reset those validations for the ExposedPort class as they do
|
5
|
-
# not make any sense for the context in which this class is being used here.
|
6
|
-
ExposedPort.reset_callbacks(:validate)
|
7
|
-
|
1
|
+
class ExposedPort < DockerParameter
|
8
2
|
belongs_to :container, :foreign_key => :reference_id, :inverse_of => :exposed_ports
|
9
|
-
audited :
|
10
|
-
validates :
|
11
|
-
validates :
|
3
|
+
audited :associated_with => :container, :allow_mass_assignment => true
|
4
|
+
validates :key, :uniqueness => { :scope => :reference_id }
|
5
|
+
validates :key, :numericality => { :only_integer => true,
|
12
6
|
:greater_than => 0,
|
13
7
|
:less_than_or_equal_to => 655_35,
|
14
8
|
:message => "%{value} is not a valid port number" }
|
@@ -1,19 +1,13 @@
|
|
1
1
|
require 'resolv'
|
2
2
|
|
3
3
|
module ForemanDocker
|
4
|
-
class Dns <
|
5
|
-
# The Parameter class from which this Dns class inherits,validates for the
|
6
|
-
# presence of an associated domain, operating system, host or host group.
|
7
|
-
# We will have to reset those validations for the Dns class as they do not
|
8
|
-
# make any sense for the context in which this class is being used here.
|
9
|
-
ForemanDocker::Dns.reset_callbacks(:validate)
|
10
|
-
|
4
|
+
class Dns < DockerParameter
|
11
5
|
belongs_to :container, :foreign_key => :reference_id,
|
12
6
|
:inverse_of => :dns,
|
13
7
|
:class_name => "Container"
|
14
8
|
|
15
|
-
audited :
|
16
|
-
validates :
|
9
|
+
audited :associated_with => :container, :allow_mass_assignment => true
|
10
|
+
validates :key, :uniqueness => { :scope => :reference_id },
|
17
11
|
:format => {
|
18
12
|
:with => Regexp.union(Resolv::IPv4::Regex,
|
19
13
|
Resolv::IPv6::Regex,
|
@@ -61,11 +61,7 @@ module ForemanDocker
|
|
61
61
|
if exist?(image_name)
|
62
62
|
tags_for_local_image(image(image_name))
|
63
63
|
else
|
64
|
-
|
65
|
-
hub_api_url = "https://index.docker.io/v1/repositories/#{image_name}/tags"
|
66
|
-
JSON.parse(URI.parse(hub_api_url).read).map do |tag|
|
67
|
-
tag['name']
|
68
|
-
end
|
64
|
+
Service::RegistryApi.docker_hub.tags(image_name).map { |tag| tag['name'] }
|
69
65
|
end
|
70
66
|
end
|
71
67
|
|
@@ -41,9 +41,14 @@ module Service
|
|
41
41
|
|
42
42
|
pull_image(container)
|
43
43
|
start_container(container)
|
44
|
-
|
44
|
+
unless container.valid?
|
45
|
+
@errors = errors + container.errors.full_messages
|
46
|
+
end
|
45
47
|
|
46
|
-
|
48
|
+
if @errors.present?
|
49
|
+
@errors = @errors.flatten.uniq
|
50
|
+
fail ActiveRecord::Rollback
|
51
|
+
end
|
47
52
|
|
48
53
|
container.name = container.in_fog.name[1..-1] unless container.name.present?
|
49
54
|
|
@@ -53,7 +58,8 @@ module Service
|
|
53
58
|
def pull_image(container)
|
54
59
|
success = container.compute_resource.
|
55
60
|
create_image(:fromImage => container.repository_pull_url)
|
56
|
-
|
61
|
+
return true if success
|
62
|
+
@errors = errors + container.compute_resource.errors.full_messages
|
57
63
|
end
|
58
64
|
|
59
65
|
def start_container(container)
|
@@ -61,7 +67,7 @@ module Service
|
|
61
67
|
if started
|
62
68
|
container.uuid = started.id
|
63
69
|
else
|
64
|
-
errors
|
70
|
+
@errors = errors + container.compute_resource.errors.full_messages
|
65
71
|
end
|
66
72
|
started
|
67
73
|
end
|
@@ -74,31 +80,29 @@ module Service
|
|
74
80
|
def load_environment_variables(state, r)
|
75
81
|
state.environment_variables.each do |environment_variable|
|
76
82
|
var = r.environment_variables.build
|
77
|
-
var.
|
83
|
+
var.key = environment_variable.key
|
78
84
|
var.value = environment_variable.value
|
79
|
-
var.priority = environment_variable.priority
|
80
85
|
end
|
81
86
|
end
|
82
87
|
|
83
88
|
def load_exposed_ports(state, r)
|
84
89
|
state.exposed_ports.each do |e|
|
85
90
|
port = r.exposed_ports.build
|
86
|
-
port.
|
91
|
+
port.key = e.key
|
87
92
|
port.value = e.value
|
88
|
-
port.priority = e.priority
|
89
93
|
end
|
90
94
|
end
|
91
95
|
|
92
96
|
def load_dns(state, r)
|
93
97
|
state.dns.each do |e|
|
94
98
|
dns = r.dns.build
|
95
|
-
dns.
|
96
|
-
dns.priority = e.priority
|
99
|
+
dns.key = e.key
|
97
100
|
end
|
98
101
|
end
|
99
102
|
|
100
103
|
def full_messages
|
101
|
-
errors.respond_to?(:full_messages)
|
104
|
+
return errors.full_messages if errors.respond_to?(:full_messages)
|
105
|
+
@errors
|
102
106
|
end
|
103
107
|
|
104
108
|
def run_container(container)
|
@@ -1,26 +1,98 @@
|
|
1
1
|
module Service
|
2
2
|
class RegistryApi
|
3
|
-
|
4
|
-
|
3
|
+
DOCKER_HUB = 'https://registry.hub.docker.com/'.freeze
|
4
|
+
DEFAULTS = {
|
5
|
+
url: 'http://localhost:5000'.freeze,
|
6
|
+
connection: { omit_default_port: true }
|
7
|
+
}
|
8
|
+
|
9
|
+
attr_accessor :config, :url
|
10
|
+
delegate :logger, :to => Rails
|
5
11
|
|
6
12
|
def initialize(params = {})
|
7
|
-
config = DEFAULTS.merge(params)
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
13
|
+
self.config = DEFAULTS.merge(params)
|
14
|
+
self.url = config[:url]
|
15
|
+
@user = config[:user] unless config[:user].blank?
|
16
|
+
@password = config[:password] unless config[:password].blank?
|
17
|
+
|
18
|
+
Docker.logger = logger if Rails.env.development? || Rails.env.test?
|
19
|
+
end
|
20
|
+
|
21
|
+
def connection
|
22
|
+
@connection ||= ::Docker::Connection.new(url, credentials)
|
23
|
+
end
|
24
|
+
|
25
|
+
def get(path, params = nil)
|
26
|
+
response = connection.get('/'.freeze, params,
|
27
|
+
DEFAULTS[:connection].merge({ path: "#{path}" }))
|
28
|
+
response = parse_json(response)
|
29
|
+
response
|
30
|
+
end
|
31
|
+
|
32
|
+
# Since the Registry API v2 does not support a search the v1 endpoint is used
|
33
|
+
# Newer registries will fail, the v2 catalog endpoint is used
|
34
|
+
def search(query)
|
35
|
+
get('/v1/search'.freeze, { q: query })
|
36
|
+
rescue => e
|
37
|
+
logger.warn "API v1 - Search failed #{e.backtrace}"
|
38
|
+
{ 'results' => catalog(query) }
|
39
|
+
end
|
40
|
+
|
41
|
+
# Some Registries might have this endpoint not implemented/enabled
|
42
|
+
def catalog(query)
|
43
|
+
get('/v2/_catalog'.freeze)['repositories'].select do |image|
|
44
|
+
image =~ /^#{query}/
|
45
|
+
end.map { |image_name| { 'name' => image_name } }
|
46
|
+
end
|
47
|
+
|
48
|
+
def tags(image_name, query = nil)
|
49
|
+
result = get_tags(image_name)
|
50
|
+
result = result.keys.map { |t| {'name' => t.to_s } } if result.is_a? Hash
|
51
|
+
result = filter_tags(result, query) if query
|
52
|
+
result
|
53
|
+
end
|
54
|
+
|
55
|
+
def ok?
|
56
|
+
get('/v1/'.freeze).match("Docker Registry API")
|
57
|
+
rescue => e
|
58
|
+
logger.warn "API v1 - Ping failed #{e.backtrace}"
|
59
|
+
get('/v2/'.freeze).is_a? Hash
|
60
|
+
end
|
61
|
+
|
62
|
+
def self.docker_hub
|
63
|
+
@@docker_hub ||= new(url: DOCKER_HUB)
|
64
|
+
end
|
65
|
+
|
66
|
+
private
|
67
|
+
|
68
|
+
def parse_json(string)
|
69
|
+
JSON.parse(string)
|
70
|
+
rescue => e
|
71
|
+
logger.warn "JSON parsing failed: #{e.backtrace}"
|
72
|
+
string
|
73
|
+
end
|
74
|
+
|
75
|
+
def get_tags(image_name)
|
76
|
+
get("/v1/repositories/#{image_name}/tags")
|
77
|
+
rescue => e
|
78
|
+
logger.warn "API v1 - Repository images request failed #{e.backtrace}"
|
79
|
+
tags_v2(image_name)
|
80
|
+
end
|
81
|
+
|
82
|
+
def tags_v2(image_name)
|
83
|
+
get("/v2/#{image_name}/tags/list")['tags'].map { |tag| { 'name' => tag } }
|
84
|
+
rescue Docker::Error::NotFoundError
|
85
|
+
[]
|
12
86
|
end
|
13
87
|
|
14
|
-
def
|
15
|
-
|
16
|
-
:params => { :q => aquery }, :accept => :json)
|
17
|
-
JSON.parse(response.body)
|
88
|
+
def credentials
|
89
|
+
{ user: @user, password: @password }
|
18
90
|
end
|
19
91
|
|
20
|
-
def
|
21
|
-
|
22
|
-
|
23
|
-
|
92
|
+
def filter_tags(result, query)
|
93
|
+
result.select do |tag_name|
|
94
|
+
tag_name['name'] =~ /^#{query}/
|
95
|
+
end
|
24
96
|
end
|
25
97
|
end
|
26
98
|
end
|