smart_proxy_container_gateway 2.0.0 → 3.0.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/README.md +2 -3
- data/lib/smart_proxy_container_gateway/container_gateway.rb +10 -6
- data/lib/smart_proxy_container_gateway/container_gateway_api.rb +36 -8
- data/lib/smart_proxy_container_gateway/container_gateway_main.rb +19 -14
- data/lib/smart_proxy_container_gateway/database.rb +7 -14
- data/lib/smart_proxy_container_gateway/version.rb +1 -1
- data/settings.d/container_gateway.yml.example +13 -7
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bb4e40d814ff330008ad5f1bf4bf667ba9e91415bc997ea4d66a2beb7fb0a00e
|
4
|
+
data.tar.gz: 84360d1228198e91460a2b841985b12c5c9f5d5d062d191862a2e9cc5bef10e9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 37997d8de598e480912ecc0785fc755138aa90163dcb20981210eff4a935ae85a49a157b8c51189a6a13a6a29a1ff391429e477257d466b0b9d0d19d04d33fcd
|
7
|
+
data.tar.gz: 5a81a246030ed8d9fcd7b847c30fb241c2974e203ae09b256a017432cffa549073430a203e5d6231f55527db005237477a4903482c88ddad47e4c2ca894f8def
|
data/README.md
CHANGED
@@ -38,9 +38,8 @@ The Container Gateway plugin requires a Pulp 3 instance to connect to. Related
|
|
38
38
|
SQLite and PostgreSQL are supported, with SQLite being the default for development and testing.
|
39
39
|
Use PostgreSQL in production for improved performance by adding the following settings:
|
40
40
|
```
|
41
|
-
# Example PostgreSQL connection settings
|
42
|
-
:
|
43
|
-
:postgresql_connection_string: postgres://foreman-proxy:changeme@localhost:5432/container_gateway
|
41
|
+
# Example PostgreSQL connection settings, using UNIX socket and ident auth
|
42
|
+
:db_connection_string: postgres:///container_gateway
|
44
43
|
```
|
45
44
|
|
46
45
|
When switching from SQLite to PostgreSQL, if the PostgreSQL database is empty, the SQLite database will be automatically migrated to PostgreSQL.
|
@@ -7,8 +7,6 @@ module Proxy
|
|
7
7
|
|
8
8
|
default_settings :pulp_endpoint => "https://#{`hostname`.strip}",
|
9
9
|
:katello_registry_path => '/v2/',
|
10
|
-
:database_backend => 'sqlite',
|
11
|
-
:sqlite_db_path => '/var/lib/foreman-proxy/smart_proxy_container_gateway.db',
|
12
10
|
:sqlite_timeout => 30_000
|
13
11
|
|
14
12
|
# Load defaults that copy values from SETTINGS. This is done as
|
@@ -29,10 +27,16 @@ module Proxy
|
|
29
27
|
|
30
28
|
load_dependency_injection_wirings do |container_instance, settings|
|
31
29
|
container_instance.singleton_dependency :database_impl, (lambda do
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
30
|
+
connection_string = settings.fetch(:db_connection_string) do
|
31
|
+
unless settings[:sqlite_db_path]
|
32
|
+
raise ValueError, 'Missing db_connection_string or sqlite_db_path option'
|
33
|
+
end
|
34
|
+
|
35
|
+
# Legacy setup
|
36
|
+
"sqlite://#{settings[:sqlite_db_path]}?timeout=#{settings[:sqlite_timeout]}"
|
37
|
+
end
|
38
|
+
|
39
|
+
Proxy::ContainerGateway::Database.new(connection_string, settings[:sqlite_db_path])
|
36
40
|
end)
|
37
41
|
container_instance.singleton_dependency :container_gateway_main_impl, (lambda do
|
38
42
|
Proxy::ContainerGateway::ContainerGatewayMain.new(
|
@@ -19,13 +19,17 @@ module Proxy
|
|
19
19
|
inject_attr :container_gateway_main_impl, :container_gateway_main
|
20
20
|
|
21
21
|
get '/v1/_ping/?' do
|
22
|
-
container_gateway_main.ping
|
22
|
+
pulp_response = container_gateway_main.ping(translated_headers_for_proxy)
|
23
|
+
status pulp_response.code.to_i
|
24
|
+
body pulp_response.body
|
23
25
|
end
|
24
26
|
|
25
27
|
get '/v2/?' do
|
26
28
|
if auth_header.present? && (auth_header.unauthorized_token? || auth_header.valid_user_token?)
|
27
29
|
response.headers['Docker-Distribution-API-Version'] = 'registry/2.0'
|
28
|
-
container_gateway_main.ping
|
30
|
+
pulp_response = container_gateway_main.ping(translated_headers_for_proxy)
|
31
|
+
status pulp_response.code.to_i
|
32
|
+
body pulp_response.body
|
29
33
|
else
|
30
34
|
redirect_authorization_headers
|
31
35
|
halt 401, "unauthorized"
|
@@ -36,22 +40,34 @@ module Proxy
|
|
36
40
|
repository = params[:splat][0]
|
37
41
|
tag = params[:splat][1]
|
38
42
|
handle_repo_auth(repository, auth_header, request)
|
39
|
-
|
40
|
-
|
43
|
+
pulp_response = container_gateway_main.manifests(repository, tag, translated_headers_for_proxy)
|
44
|
+
if pulp_response.code.to_i >= 400
|
45
|
+
status pulp_response.code.to_i
|
46
|
+
body pulp_response.body
|
47
|
+
else
|
48
|
+
redirection_location = pulp_response['location']
|
49
|
+
redirect to(redirection_location)
|
50
|
+
end
|
41
51
|
end
|
42
52
|
|
43
53
|
get '/v2/*/blobs/*/?' do
|
44
54
|
repository = params[:splat][0]
|
45
55
|
digest = params[:splat][1]
|
46
56
|
handle_repo_auth(repository, auth_header, request)
|
47
|
-
|
48
|
-
|
57
|
+
pulp_response = container_gateway_main.blobs(repository, digest, translated_headers_for_proxy)
|
58
|
+
if pulp_response.code.to_i >= 400
|
59
|
+
status pulp_response.code.to_i
|
60
|
+
body pulp_response.body
|
61
|
+
else
|
62
|
+
redirection_location = pulp_response['location']
|
63
|
+
redirect to(redirection_location)
|
64
|
+
end
|
49
65
|
end
|
50
66
|
|
51
67
|
get '/v2/*/tags/list/?' do
|
52
68
|
repository = params[:splat][0]
|
53
69
|
handle_repo_auth(repository, auth_header, request)
|
54
|
-
pulp_response = container_gateway_main.tags(repository, params)
|
70
|
+
pulp_response = container_gateway_main.tags(repository, translated_headers_for_proxy, params)
|
55
71
|
# "link"=>["<http://pulpcore-api/v2/container-image-name/tags/list?n=100&last=last-tag-name>; rel=\"next\""],
|
56
72
|
# https://docs.docker.com/registry/spec/api/#pagination-1
|
57
73
|
if pulp_response['link'].nil?
|
@@ -59,7 +75,8 @@ module Proxy
|
|
59
75
|
else
|
60
76
|
headers['link'] = pulp_response['link']
|
61
77
|
end
|
62
|
-
pulp_response.
|
78
|
+
status pulp_response.code.to_i
|
79
|
+
body pulp_response.body
|
63
80
|
end
|
64
81
|
|
65
82
|
get '/v1/search/?' do
|
@@ -181,6 +198,17 @@ module Proxy
|
|
181
198
|
|
182
199
|
private
|
183
200
|
|
201
|
+
def translated_headers_for_proxy
|
202
|
+
current_headers = {}
|
203
|
+
env = request.env.select do |key, _value|
|
204
|
+
key.match("^HTTP_.*")
|
205
|
+
end
|
206
|
+
env.each do |header|
|
207
|
+
current_headers[header[0].split('_')[1..].join('-')] = header[1]
|
208
|
+
end
|
209
|
+
current_headers
|
210
|
+
end
|
211
|
+
|
184
212
|
def handle_repo_auth(repository, auth_header, request)
|
185
213
|
user_token_is_valid = false
|
186
214
|
if auth_header.present? && auth_header.valid_user_token?
|
@@ -21,7 +21,7 @@ module Proxy
|
|
21
21
|
)
|
22
22
|
end
|
23
23
|
|
24
|
-
def pulp_registry_request(uri)
|
24
|
+
def pulp_registry_request(uri, headers)
|
25
25
|
http_client = Net::HTTP.new(uri.host, uri.port)
|
26
26
|
http_client.ca_file = @pulp_client_ssl_ca
|
27
27
|
http_client.cert = @pulp_client_ssl_cert
|
@@ -30,30 +30,33 @@ module Proxy
|
|
30
30
|
|
31
31
|
http_client.start do |http|
|
32
32
|
request = Net::HTTP::Get.new uri
|
33
|
+
headers.each do |key, value|
|
34
|
+
request[key] = value
|
35
|
+
end
|
33
36
|
http.request request
|
34
37
|
end
|
35
38
|
end
|
36
39
|
|
37
|
-
def ping
|
40
|
+
def ping(headers)
|
38
41
|
uri = URI.parse("#{@pulp_endpoint}/pulpcore_registry/v2/")
|
39
|
-
pulp_registry_request(uri)
|
42
|
+
pulp_registry_request(uri, headers)
|
40
43
|
end
|
41
44
|
|
42
|
-
def manifests(repository, tag)
|
45
|
+
def manifests(repository, tag, headers)
|
43
46
|
uri = URI.parse(
|
44
47
|
"#{@pulp_endpoint}/pulpcore_registry/v2/#{repository}/manifests/#{tag}"
|
45
48
|
)
|
46
|
-
pulp_registry_request(uri)
|
49
|
+
pulp_registry_request(uri, headers)
|
47
50
|
end
|
48
51
|
|
49
|
-
def blobs(repository, digest)
|
52
|
+
def blobs(repository, digest, headers)
|
50
53
|
uri = URI.parse(
|
51
54
|
"#{@pulp_endpoint}/pulpcore_registry/v2/#{repository}/blobs/#{digest}"
|
52
55
|
)
|
53
|
-
pulp_registry_request(uri)
|
56
|
+
pulp_registry_request(uri, headers)
|
54
57
|
end
|
55
58
|
|
56
|
-
def tags(repository, params = {})
|
59
|
+
def tags(repository, headers, params = {})
|
57
60
|
query = "?"
|
58
61
|
unless params[:n].nil? || params[:n] == ""
|
59
62
|
query = "#{query}n=#{params[:n]}"
|
@@ -64,7 +67,7 @@ module Proxy
|
|
64
67
|
uri = URI.parse(
|
65
68
|
"#{@pulp_endpoint}/pulpcore_registry/v2/#{repository}/tags/list#{query}"
|
66
69
|
)
|
67
|
-
pulp_registry_request(uri)
|
70
|
+
pulp_registry_request(uri, headers)
|
68
71
|
end
|
69
72
|
|
70
73
|
def v1_search(params = {})
|
@@ -192,12 +195,14 @@ module Proxy
|
|
192
195
|
checksum = Digest::SHA256.hexdigest(token)
|
193
196
|
user = Sequel::Model(database.connection[:users]).find_or_create(name: username)
|
194
197
|
|
195
|
-
database.connection
|
196
|
-
|
197
|
-
|
198
|
-
|
198
|
+
database.connection.transaction(isolation: :serializable, retry_on: [Sequel::SerializationFailure]) do
|
199
|
+
database.connection[:authentication_tokens].where(:token_checksum => checksum).delete
|
200
|
+
Sequel::Model(database.connection[:authentication_tokens]).
|
201
|
+
create(token_checksum: checksum, expire_at: expire_at_string.to_s, user_id: user.id)
|
202
|
+
return unless clear_expired_tokens
|
199
203
|
|
200
|
-
|
204
|
+
database.connection[:authentication_tokens].where { expire_at < Sequel::CURRENT_TIMESTAMP }.delete
|
205
|
+
end
|
201
206
|
end
|
202
207
|
|
203
208
|
private
|
@@ -4,22 +4,15 @@ module Proxy
|
|
4
4
|
class Database
|
5
5
|
attr_reader :connection
|
6
6
|
|
7
|
-
def initialize(
|
8
|
-
|
9
|
-
|
7
|
+
def initialize(connection_string, prior_sqlite_db_path = nil)
|
8
|
+
@connection = Sequel.connect(connection_string)
|
9
|
+
if connection_string.start_with?('sqlite://')
|
10
10
|
@connection.run("PRAGMA foreign_keys = ON;")
|
11
11
|
@connection.run("PRAGMA journal_mode = wal;")
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
@connection = Sequel.connect(options[:postgresql_connection_string])
|
18
|
-
if File.exist?(options[:sqlite_db_path]) &&
|
19
|
-
(!@connection.table_exists?(:repositories) || @connection[:repositories].count.zero?)
|
20
|
-
migrate_to_postgres(Sequel.sqlite(options[:sqlite_db_path]), @connection)
|
21
|
-
File.delete(options[:sqlite_db_path])
|
22
|
-
end
|
12
|
+
elsif prior_sqlite_db_path && File.exist?(prior_sqlite_db_path) &&
|
13
|
+
(!@connection.table_exists?(:repositories) || @connection[:repositories].count.zero?)
|
14
|
+
migrate_to_postgres(Sequel.sqlite(prior_sqlite_db_path), @connection)
|
15
|
+
File.delete(prior_sqlite_db_path)
|
23
16
|
end
|
24
17
|
migrate
|
25
18
|
end
|
@@ -1,10 +1,16 @@
|
|
1
1
|
---
|
2
2
|
:enabled: true
|
3
|
-
|
4
|
-
:
|
5
|
-
:
|
6
|
-
:
|
7
|
-
:
|
8
|
-
|
3
|
+
|
4
|
+
#:pulp_endpoint: 'https://pulp3.example.com'
|
5
|
+
#:pulp_client_ssl_ca: '/path/to/ca.pem'
|
6
|
+
#:pulp_client_ssl_cert: '/path/to/cert.pem'
|
7
|
+
#:pulp_client_ssl_key: '/path/to/key.pem'
|
8
|
+
|
9
|
+
#:katello_registry_path: '/v2/'
|
10
|
+
|
11
|
+
#:db_connection_string: postgresql:///container_gateway
|
12
|
+
|
13
|
+
# Legacy options
|
14
|
+
#:sqlite_db_path: '/var/lib/foreman-proxy/smart_proxy_container_gateway.db'
|
9
15
|
# Database busy timeout in milliseconds
|
10
|
-
|
16
|
+
#:sqlite_timeout: 30000
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: smart_proxy_container_gateway
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 3.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ian Ballou
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-05-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|