import { workspace } from "vscode" ; import { Response } from "request" ; import * as request from 'request-promise-native' ; import { Errorable } from '../utils/errorable' ; const urljoin = require ( 'url-join' ) ; const MAX_TAGS_RESULTS = 12 ; interface IResponse < T > extends Response { body : T ; } export async function registryRequest < T > ( method , url , customOptions ? ) { let httpSettings = workspace . getConfiguration ( 'http' ) ; let strictSSL = httpSettings . get < boolean > ( 'proxyStrictSSL' , true ) ; const options = { method , json : true , resolveWithFullResponse : true , strictSSL : strictSSL , ... customOptions } ; return < IResponse < T > > await request ( url , options ) ; } interface ITags { next ? : string ; results : ITag [ ] ; } export interface ITagImage { architecture : string ; } export interface ITag { name : string ; tag_status : string ; last_updated : string ; images : ITagImage [ ] ; } function ITagCompare ( a , b ) { return new Date ( a . last_updated ) . getTime ( ) - new Date ( b . last_updated ) . getTime ( ) ; } export async function registryTagsForImage ( registry , namespace , repoName , regex ? , arch ? , limit = MAX_TAGS_RESULTS ) { if ( ! registry . startsWith ( "http" ) ) { registry = `https://${ registry }` ; } let res = [ ] ; let url = urljoin ( registry , "v2" , "repositories" , namespace , repoName , "tags" ) . toString ( ) ; while ( true ) { let response = await registryRequest < ITags > ( 'GET' , url . toString ( ) ) ; if ( response . statusCode !== 200 ) { return { succeeded : false , error : [ response . statusMessage ] } ; } res = res . concat ( response . body . results . filter ( ( i ) => i . tag_status === "active" ) . filter ( ( image ) => regex ? regex . test ( image . name ) : true ) . filter ( ( image ) => arch ? image . images . some ( ( x ) => x . architecture === getVariantForArch ( arch ) ) : true ) ) ; if ( response . body . next && response . body . next !== url && res . length < limit ) { url = response . body . next ; } else { return { succeeded : true , result : res . sort ( ITagCompare ) . slice ( 0 , limit ) } ; } } } function getVariantForArch ( arch ) { switch ( arch ) { case "x86_64" : return "amd64" ; case "arm64" : return "arm64" ; default : return "amd64" ; } }