Prechádzať zdrojové kódy

Rewrite token handling to simplify the "registry" interface (especially now that we need to expand that interface with more requests)

Tianon Gravi 9 rokov pred
rodič
commit
a558264f9c
1 zmenil súbory, kde vykonal 52 pridanie a 32 odobranie
  1. 52 32
      .template-helpers/generate-tag-details.pl

+ 52 - 32
.template-helpers/generate-tag-details.pl

@@ -19,7 +19,7 @@ sub ua_req {
 	do {
 		--$tries;
 		$tx = $ua->$method(@_);
-		return $tx if $tx->success;
+		return $tx if $tx->success or $tx->res->code == 401 or $tx->res->code == 404;
 	} while ($tries > 0);
 	return $tx;
 }
@@ -43,45 +43,67 @@ sub split_image_name {
 	die "unrecognized image name format in: $image";
 }
 
-sub get_token {
+sub registry_req {
+	my $method = shift;
 	my $repo = shift;
+	my $url = shift;
+	my %extHeaders = @_;
+
 	state %tokens;
-	return $tokens{$repo} if $tokens{$repo};
-	my $realmTx = $ua->get("https://registry-1.docker.io/v2/$repo/tags/list");
-	my $auth = $realmTx->res->headers->www_authenticate;
-	die "unexpected WWW-Authenticate header: $auth" unless $auth =~ m{ ^ Bearer \s+ (\S.*) $ }x;
-	my $realm = $1;
-	my $url = Mojo::URL->new;
-	while ($realm =~ m{
-		# key="val",
-		([^=]+)
-		=
-		"([^"]+)"
-		,?
-	}xg) {
-		my ($key, $val) = ($1, $2);
-		if ($key eq 'realm') {
-			$url->base(Mojo::URL->new($val));
-		} else {
-			$url->query->append($key => $val);
+
+	$url = "https://registry-1.docker.io/v2/$repo/$url";
+
+	for (;;) {
+		my %headers = (
+			%extHeaders,
+		);
+
+		if (my $token = $tokens{$repo}) {
+			$headers{Authorization} = "Bearer $token";
+		}
+
+		my $tx = ua_req($method => $url => \%headers);
+
+		if ($tx->res->code == 401) {
+			my $auth = $tx->res->headers->www_authenticate;
+			die "unexpected WWW-Authenticate header: $auth" unless $auth =~ m{ ^ Bearer \s+ (\S.*) $ }x;
+			my $realm = $1;
+			my $authUrl = Mojo::URL->new;
+			while ($realm =~ m{
+				# key="val",
+				([^=]+)
+				=
+				"([^"]+)"
+				,?
+			}xg) {
+				my ($key, $val) = ($1, $2);
+				if ($key eq 'realm') {
+					$authUrl->base(Mojo::URL->new($val));
+				} else {
+					$authUrl->query->append($key => $val);
+				}
+			}
+			$authUrl = $authUrl->to_abs;
+			my $tokenTx = ua_req(get => $authUrl);
+			die "failed to fetch token for $repo" unless $tokenTx->success;
+			$tokens{$repo} = $tokenTx->res->json->{token};
+			next;
 		}
+
+		return $tx;
 	}
-	$url = $url->to_abs;
-	my $tokenTx = ua_req(get => $url);
-	die "failed to fetch token for $repo" unless $tokenTx->success;
-	return $tokens{$repo} = $tokenTx->res->json->{token};
 }
 
 sub get_manifest {
 	my ($repo, $tag) = @_;
+
 	my $image = "$repo:$tag";
 	state %manifests;
 	return $manifests{$image} if $manifests{$image};
 
-	my $token = get_token($repo);
-	my $authorizationHeader = { Authorization => "Bearer $token" };
-
-	my $manifestTx = ua_req(get => "https://registry-1.docker.io/v2/$repo/manifests/$tag" => $authorizationHeader);
+	my $manifestTx = registry_req(get => $repo => "manifests/$tag" => (
+			#Accept => 'application/vnd.docker.distribution.manifest.v2+json',
+		));
 	return () if $manifestTx->res->code == 404; # tag doesn't exist
 	die "failed to get manifest for $image" unless $manifestTx->success;
 	return (
@@ -92,14 +114,12 @@ sub get_manifest {
 
 sub get_blob_headers {
 	my ($repo, $blob) = @_;
+
 	my $key = $repo . '@' . $blob;
 	state %headers;
 	return $headers{$key} if $headers{$key};
 
-	my $token = get_token($repo);
-	my $authorizationHeader = { Authorization => "Bearer $token" };
-
-	my $headersTx = ua_req(head => "https://registry-1.docker.io/v2/$repo/blobs/$blob" => $authorizationHeader);
+	my $headersTx = registry_req(head => $repo => "blobs/$blob" => ());
 	die "failed to get headers for $key" unless $headersTx->success;
 	return $headers{$key} = $headersTx->res->headers;
 }