engines/registry/app/services/registry_catalog_service.rb

Summary

Maintainability
A
0 mins
Test Coverage
require 'json'
require 'net/http'

CATALOG_API_URL = 'http://127.0.0.1:5000/v2/_catalog'.freeze
AUTH_URL = 'api/registry/authorize'.freeze
CATALOG_SCOPE = 'registry:catalog:*'.freeze
SERVICE = 'SUSE Linux OCI Registry'.freeze

class RegistryCatalogService
  attr_accessor :catalog_api_url

  # We overwrite the public request /v2/_catalog with our endpoint
  # RMT still needs to be able to get the unfiltered _catalog from the registry
  # So we query CATALOG_API_URL (registry catalog) and return the fetched repositories
  # n > 1000 crashes the request to CATALOG_API_URL

  def initialize(url = CATALOG_API_URL)
    @catalog_api_url = url
  end

  # be aware that this takes about 20-25 seconds to be finished if not in cache
  def repos(reload: false, system: nil, origin_url: nil)
    Rails.cache.fetch(@catalog_api_url, expires_in: 1.hour, force: reload) do
      fetch_registry_repos(system, origin_url)
    end
  end

  private

  def fetch_registry_repos(system, origin_url)
    Rails.logger.info('Fetch registry repos')
    response = catalog_token(system, origin_url)
    catalog_auth_token = JSON.parse(response.body).fetch('token', '')
    response = all_repos(catalog_auth_token)
    JSON.parse(response.body).fetch('repositories', [])
  end

  def catalog_token(system, origin_url)
    uri = URI.parse(URI.join(origin_url, AUTH_URL).to_s)
    catalog_token_params = {
      service: SERVICE,
      account: system.login,
      scope: CATALOG_SCOPE
    }
    uri.query = URI.encode_www_form(catalog_token_params)
    http = Net::HTTP.new(uri.host, uri.port)
    http.use_ssl = true
    registry_request = Net::HTTP::Get.new(uri.to_s)
    http.request(registry_request)
  end

  def all_repos(auth_token)
    uri = URI.parse(@catalog_api_url)
    # n > 1000 crashes the request to CATALOG_API_URL
    uri.query = URI.encode_www_form({ n: 1000 })
    http = Net::HTTP.new(uri.host, uri.port)
    http.use_ssl = false
    registry_request = Net::HTTP::Get.new(uri.to_s)
    registry_request['Authorization'] = format("Bearer #{auth_token}")
    response = nil
    time = Benchmark.realtime do
      response = http.request(registry_request)
    end
    Rails.logger.info("… took #{time}")
    response
  end
end