lib/docker/remote/client.rb in docker-remote-0.6.0 vs lib/docker/remote/client.rb in docker-remote-0.7.0
- old
+ new
@@ -10,21 +10,20 @@
class UnexpectedResponseCodeError < DockerRemoteError; end
class Client
include Utils
- attr_reader :registry_url, :repo, :username, :password
+ attr_reader :registry_url, :repo, :creds
PORTMAP = { 'ghcr.io' => 443 }.freeze
DEFAULT_PORT = 443
STANDARD_PORTS = [DEFAULT_PORT, 80].freeze
def initialize(registry_url, repo, username = nil, password = nil)
@registry_url = registry_url
@repo = repo
- @username = username
- @password = password
+ @creds = Credentials.new(username, password)
end
def tags
response = get("/v2/#{repo}/tags/list")
potentially_raise_error!(response)
@@ -45,18 +44,18 @@
private
def auth
@auth ||= begin
- response = get('/v2/', use_auth: nil)
+ response = get('/v2/', use_auth: NoAuth.instance)
- case response.code
- when '200'
+ case response
+ when Net::HTTPSuccess
NoAuth.instance
- when '401'
- www_auth(response)
- when '404'
+ when Net::HTTPUnauthorized
+ www_auth(response).strategy
+ when Net::HTTPNotFound
raise UnsupportedVersionError,
"the registry at #{registry_url} doesn't support v2 "\
'of the Docker registry API'
else
raise UnexpectedResponseCodeError,
@@ -65,53 +64,42 @@
end
end
end
def www_auth(response)
- auth = response['www-authenticate']
-
- idx = auth.index(' ')
- auth_type = auth[0..idx].strip
-
- params = auth[idx..-1].split(',').each_with_object({}) do |param, ret|
- key, value = param.split('=')
- ret[key.strip] = value.strip[1..-2] # remove quotes
- end
-
- case auth_type.downcase
- when 'bearer'
- BearerAuth.new(params, repo, username, password)
- when 'basic'
- BasicAuth.new(username, password)
- else
- raise UnsupportedAuthTypeError,
- "unsupported Docker auth type '#{auth_type}'"
- end
+ AuthInfo.from_header(response['www-authenticate'], creds)
end
def get(path, http: registry_http, use_auth: auth, limit: 5)
if limit == 0
raise DockerRemoteError, 'too many redirects'
end
- request = if use_auth
- use_auth.make_get(path)
- else
- Net::HTTP::Get.new(path)
- end
-
+ request = use_auth.make_get(path)
response = http.request(request)
case response
+ when Net::HTTPUnauthorized
+ auth_info = www_auth(response)
+
+ if auth_info.params['error'] == 'insufficient_scope'
+ if auth_info.params.include?('scope')
+ return get(
+ path,
+ http: http,
+ use_auth: auth_info.strategy,
+ limit: limit - 1
+ )
+ end
+ end
when Net::HTTPRedirection
redirect_uri = URI.parse(response['location'])
redirect_http = make_http(redirect_uri)
return get(
- redirect_uri.path, {
- http: redirect_http,
- use_auth: use_auth,
- limit: limit - 1
- }
+ redirect_uri.path,
+ http: redirect_http,
+ use_auth: use_auth,
+ limit: limit - 1
)
end
response
end