smart_proxy_container_gateway 2.0.0 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fee65676d4362e1328671832a7bf3308b193ab1265ea5626eb52d5300ab7d35a
4
- data.tar.gz: fe57f17f732079b2ac27ce70cc7c04ef3ed141283cba58db75676a36dfb4b678
3
+ metadata.gz: bb4e40d814ff330008ad5f1bf4bf667ba9e91415bc997ea4d66a2beb7fb0a00e
4
+ data.tar.gz: 84360d1228198e91460a2b841985b12c5c9f5d5d062d191862a2e9cc5bef10e9
5
5
  SHA512:
6
- metadata.gz: b6f0716504c021e799a8a7d31390c9d203c248530073211cf24d7659439b1220647306033c4e60bf98b9425d427b822a8f98b6962f3dab788883bc17b3f5e9a8
7
- data.tar.gz: cfe03eaf3ce5e9ffa23dd355849e81abf249cede80a0f98ac12cf056fc7ec20de81195794e820c44adc9eea9000f176c837b70756670244334b1bbca4690dc54
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 (default port is 5432)
42
- :database_backend: postgresql
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
- Proxy::ContainerGateway::Database.new(
33
- database_backend: settings[:database_backend], sqlite_db_path: settings[:sqlite_db_path],
34
- sqlite_timeout: settings[:sqlite_timeout], postgresql_connection_string: settings[:postgresql_connection_string]
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
- redirection_location = container_gateway_main.manifests(repository, tag)
40
- redirect to(redirection_location)
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
- redirection_location = container_gateway_main.blobs(repository, digest)
48
- redirect to(redirection_location)
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.body
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).body
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)['location']
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)['location']
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[:authentication_tokens].where(:token_checksum => checksum).delete
196
- Sequel::Model(database.connection[:authentication_tokens]).
197
- create(token_checksum: checksum, expire_at: expire_at_string.to_s, user_id: user.id)
198
- return unless clear_expired_tokens
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
- database.connection[:authentication_tokens].where { expire_at < Sequel::CURRENT_TIMESTAMP }.delete
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(options = {})
8
- if options[:database_backend] == 'sqlite'
9
- @connection = Sequel.connect("sqlite://#{options[:sqlite_db_path]}", timeout: options[:sqlite_timeout])
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
- else
13
- unless options[:postgresql_connection_string]
14
- raise ArgumentError, 'PostgreSQL connection string is required'
15
- end
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,5 +1,5 @@
1
1
  module Proxy
2
2
  module ContainerGateway
3
- VERSION = '2.0.0'.freeze
3
+ VERSION = '3.0.0'.freeze
4
4
  end
5
5
  end
@@ -1,10 +1,16 @@
1
1
  ---
2
2
  :enabled: true
3
- :pulp_endpoint: 'https://your_pulp_3_server_here.com'
4
- :pulp_client_ssl_ca: 'CA Cert for authenticating with Pulp'
5
- :pulp_client_ssl_cert: 'X509 certificate for authenticating with Pulp'
6
- :pulp_client_ssl_key: 'RSA private key for the Pulp certificate'
7
- :katello_registry_path: 'Katello container registry suffix, e.g., /v2/'
8
- :sqlite_db_path: '/var/lib/foreman-proxy/smart_proxy_container_gateway.db'
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
- :sqlite_timeout: 30000
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: 2.0.0
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-04-15 00:00:00.000000000 Z
11
+ date: 2024-05-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport