class Proxy::ContainerGateway::ContainerGatewayMain
Attributes
client_endpoint[R]
database[R]
Public Class Methods
new(database:, pulp_endpoint:, pulp_client_ssl_ca:, pulp_client_ssl_cert:, pulp_client_ssl_key:, client_endpoint: nil)
click to toggle source
rubocop:disable Metrics/ParameterLists, Layout/LineLength
# File lib/smart_proxy_container_gateway/container_gateway_main.rb, line 16 def initialize(database:, pulp_endpoint:, pulp_client_ssl_ca:, pulp_client_ssl_cert:, pulp_client_ssl_key:, client_endpoint: nil) @database = database @pulp_endpoint = pulp_endpoint @client_endpoint = client_endpoint || pulp_endpoint @pulp_client_ssl_ca = pulp_client_ssl_ca @pulp_client_ssl_cert = OpenSSL::X509::Certificate.new(File.read(pulp_client_ssl_cert)) @pulp_client_ssl_key = OpenSSL::PKey::RSA.new( File.read(pulp_client_ssl_key) ) end
Public Instance Methods
blobs(repository, digest, headers)
click to toggle source
# File lib/smart_proxy_container_gateway/container_gateway_main.rb, line 64 def blobs(repository, digest, headers) uri = URI.parse( "#{@pulp_endpoint}/pulpcore_registry/v2/#{repository}/blobs/#{digest}" ) pulp_registry_request(uri, headers) end
build_host_entries(hosts, repositories, host_uuid, repos)
click to toggle source
# File lib/smart_proxy_container_gateway/container_gateway_main.rb, line 216 def build_host_entries(hosts, repositories, host_uuid, repos) return if host_uuid.nil? || host_uuid.to_s.strip.empty? host = hosts[{ uuid: host_uuid }] return unless host return if repos.nil? || repos.empty? repo_names = extract_auth_required_repo_names(repos) repositories .where(name: repo_names, auth_required: true) .select(:id) .map { |repo| [repo[:id], host[:id]] } end
build_host_repository_mapping(host_repo_maps)
click to toggle source
# File lib/smart_proxy_container_gateway/container_gateway_main.rb, line 202 def build_host_repository_mapping(host_repo_maps) return [] if host_repo_maps['hosts'].nil? hosts = database.connection[:hosts] repositories = database.connection[:repositories] entries = host_repo_maps['hosts'].flat_map do |host_map| host_map.filter_map do |host_uuid, repos| build_host_entries(hosts, repositories, host_uuid, repos) end end entries&.flatten(1)&.compact end
catalog(user = nil)
click to toggle source
# File lib/smart_proxy_container_gateway/container_gateway_main.rb, line 102 def catalog(user = nil) if user.nil? unauthenticated_repos else database.connection[:repositories]. left_join(:repositories_users, repository_id: :id). left_join(:users, ::Sequel[:users][:id] => :user_id).where(user_id: user[:id]). or(Sequel[:repositories][:auth_required] => false).order(::Sequel[:repositories][:name]) end end
extract_auth_required_repo_names(repos)
click to toggle source
# File lib/smart_proxy_container_gateway/container_gateway_main.rb, line 230 def extract_auth_required_repo_names(repos) repos .select { |repo| repo['auth_required'].to_s.downcase == "true" } .map { |repo| repo['repository'] } end
find_or_create_host(uuid)
click to toggle source
# File lib/smart_proxy_container_gateway/container_gateway_main.rb, line 258 def find_or_create_host(uuid) database.connection[:hosts].insert_conflict(target: :uuid, action: :ignore).insert(uuid: uuid) database.connection[:hosts][{ uuid: uuid }] end
flatpak_static_index(headers, params = {})
click to toggle source
# File lib/smart_proxy_container_gateway/container_gateway_main.rb, line 44 def flatpak_static_index(headers, params = {}) uri = URI.parse("#{@pulp_endpoint}/pulpcore_registry/index/static") unless params.empty? uri.query = params.map { |k, v| "#{ERB::Util.url_encode(k.to_s)}=#{ERB::Util.url_encode(v.to_s)}" }.join('&') end pulp_registry_request(uri, headers) end
host_catalog(host_uuid = nil)
click to toggle source
# File lib/smart_proxy_container_gateway/container_gateway_main.rb, line 113 def host_catalog(host_uuid = nil) if host_uuid.nil? unauthenticated_repos else database.connection[:repositories]. left_join(:hosts_repositories, repository_id: :id). left_join(:hosts, ::Sequel[:hosts][:id] => :host_id).where(uuid: host_uuid). or(Sequel[:repositories][:auth_required] => false).order(::Sequel[:repositories][:name]) end end
insert_token(username, token, expire_at_string, clear_expired_tokens: true)
click to toggle source
# File lib/smart_proxy_container_gateway/container_gateway_main.rb, line 311 def insert_token(username, token, expire_at_string, clear_expired_tokens: true) checksum = Digest::SHA256.hexdigest(token) user = Sequel::Model(database.connection[:users]).find_or_create(name: username) database.connection.transaction(isolation: :serializable, retry_on: [Sequel::SerializationFailure]) do database.connection[:authentication_tokens].where(:token_checksum => checksum).delete Sequel::Model(database.connection[:authentication_tokens]). create(token_checksum: checksum, expire_at: expire_at_string.to_s, user_id: user.id) return unless clear_expired_tokens database.connection[:authentication_tokens].where { expire_at < Sequel::CURRENT_TIMESTAMP }.delete end end
manifests(repository, tag, headers)
click to toggle source
# File lib/smart_proxy_container_gateway/container_gateway_main.rb, line 57 def manifests(repository, tag, headers) uri = URI.parse( "#{@pulp_endpoint}/pulpcore_registry/v2/#{repository}/manifests/#{tag}" ) pulp_registry_request(uri, headers) end
ping(headers)
click to toggle source
# File lib/smart_proxy_container_gateway/container_gateway_main.rb, line 52 def ping(headers) uri = URI.parse("#{@pulp_endpoint}/pulpcore_registry/v2/") pulp_registry_request(uri, headers) end
pulp_registry_request(uri, headers)
click to toggle source
rubocop:enable Metrics/ParameterLists, Layout/LineLength
# File lib/smart_proxy_container_gateway/container_gateway_main.rb, line 28 def pulp_registry_request(uri, headers) http_client = Net::HTTP.new(uri.host, uri.port) http_client.ca_file = @pulp_client_ssl_ca http_client.cert = @pulp_client_ssl_cert http_client.key = @pulp_client_ssl_key http_client.use_ssl = true http_client.start do |http| request = Net::HTTP::Get.new uri headers.each do |key, value| request[key] = value end http.request request end end
token_user(token)
click to toggle source
# File lib/smart_proxy_container_gateway/container_gateway_main.rb, line 299 def token_user(token) database.connection[:users][{ id: database.connection[:authentication_tokens].where(token_checksum: checksum(token)).select(:user_id) }] end
unauthenticated_repos()
click to toggle source
# File lib/smart_proxy_container_gateway/container_gateway_main.rb, line 124 def unauthenticated_repos database.connection[:repositories].where(auth_required: false).order(:name) end
update_host_repo_mapping(host_repo_maps)
click to toggle source
Replaces the entire host-repo mapping for all hosts. Assumes host is present in the DB.
# File lib/smart_proxy_container_gateway/container_gateway_main.rb, line 188 def update_host_repo_mapping(host_repo_maps) # Get DB tables hosts_repositories = database.connection[:hosts_repositories] # Build list of [repository_id, host_id] pairs entries = build_host_repository_mapping(host_repo_maps) # Insert all in a single transaction database.connection.transaction(isolation: :serializable, retry_on: [Sequel::SerializationFailure]) do hosts_repositories.delete hosts_repositories.import(%i[repository_id host_id], entries) unless entries.nil? || entries.empty? end end
update_host_repositories(uuid, repositories)
click to toggle source
# File lib/smart_proxy_container_gateway/container_gateway_main.rb, line 236 def update_host_repositories(uuid, repositories) return if uuid.nil? || uuid.to_s.strip.empty? host = find_or_create_host(uuid) return unless host hosts_repositories = database.connection[:hosts_repositories] database.connection.transaction(isolation: :serializable, retry_on: [Sequel::SerializationFailure], num_retries: 10) do hosts_repositories.where(host_id: host[:id]).delete return if repositories.nil? || repositories.empty? hosts_repositories.import( %i[repository_id host_id], database.connection[:repositories].where(name: repositories, auth_required: true).select(:id).map do |repo| [repo[:id], host[:id]] end ) end end
update_repository_list(repo_list)
click to toggle source
Replaces the entire list of repositories
# File lib/smart_proxy_container_gateway/container_gateway_main.rb, line 129 def update_repository_list(repo_list) # repositories_users cascades on deleting repositories (or users) database.connection.transaction(isolation: :serializable, retry_on: [Sequel::SerializationFailure]) do repository = database.connection[:repositories] repository.delete repository.import( %i[name auth_required], repo_list.map { |repo| [repo['repository'], repo['auth_required'].to_s.downcase == "true"] } ) end end
update_user_repo_mapping(user_repo_maps)
click to toggle source
Replaces the entire user-repo mapping for all logged-in users
# File lib/smart_proxy_container_gateway/container_gateway_main.rb, line 143 def update_user_repo_mapping(user_repo_maps) # Get hash map of all users and their repositories # Ex: {"users"=> [{"admin"=>[{"repository"=>"repo", "auth_required"=>"true"}]}]} # Go through list of repositories and add them to the DB repositories = database.connection[:repositories] entries = user_repo_maps['users'].flat_map do |user_repo_map| user_repo_map.filter_map do |username, repos| user_repo_names = repos.filter { |repo| repo['auth_required'].to_s.downcase == "true" }.map do |repo| repo['repository'] end user = database.connection[:users][{ name: username }] repositories.where(name: user_repo_names, auth_required: true).select(:id).map { |repo| [repo[:id], user[:id]] } end end entries.flatten!(1) repositories_users = database.connection[:repositories_users] database.connection.transaction(isolation: :serializable, retry_on: [Sequel::SerializationFailure]) do repositories_users.delete repositories_users.import(%i[repository_id user_id], entries) end end
update_user_repositories(username, repositories)
click to toggle source
Replaces the user-repo mapping for a single user
# File lib/smart_proxy_container_gateway/container_gateway_main.rb, line 168 def update_user_repositories(username, repositories) user = database.connection[:users][{ name: username }] user_repositories = database.connection[:repositories_users] database.connection.transaction(isolation: :serializable, retry_on: [Sequel::SerializationFailure], num_retries: 10) do user_repositories.where(user_id: user[:id]).delete user_repositories.import( %i[repository_id user_id], database.connection[:repositories].where(name: repositories, auth_required: true).select(:id).map do |repo| [repo[:id], user[:id]] end ) end end
v1_search(params = {})
click to toggle source
# File lib/smart_proxy_container_gateway/container_gateway_main.rb, line 85 def v1_search(params = {}) if params[:n].nil? || params[:n] == "" limit = 25 else limit = params[:n].to_i end return [] unless limit.positive? query = params[:q] query = nil if query == '' user = params[:user].nil? ? nil : database.connection[:users][{ name: params[:user] }] repositories = query ? catalog(user).grep(:name, "%#{query}%") : catalog(user) repositories.limit(limit).select_map(::Sequel[:repositories][:name]) end
valid_token?(token)
click to toggle source
# File lib/smart_proxy_container_gateway/container_gateway_main.rb, line 305 def valid_token?(token) !database.connection[:authentication_tokens].where(token_checksum: checksum(token)).where do expire_at > Sequel::CURRENT_TIMESTAMP end.empty? end
Private Instance Methods
checksum(token)
click to toggle source
# File lib/smart_proxy_container_gateway/container_gateway_main.rb, line 327 def checksum(token) Digest::SHA256.hexdigest(token) end