2019-05-31 06:35:44 +00:00
import millify from 'millify'
import got from '../libs/got'
2020-10-28 02:41:13 +00:00
import { getDockerAuthToken , getManifestList , getImageManifest , getImageConfig } from '../libs/docker'
2019-11-18 15:52:07 +00:00
import { createBadgenHandler , PathArgs } from '../libs/create-badgen-handler'
2019-05-31 06:35:44 +00:00
2020-10-28 02:41:13 +00:00
const help = ` ## Usage
- \ ` /docker/stars/:scope/:name \` _stars_
- \ ` /docker/pulls/:scope/:name \` _pulls_
- \ ` /docker/size/:scope/:name/:tag?/:architecture?/:variant? \` _size (scoped/tag/architecture/variant)_
- \ ` /docker/layers/:scope/:name/:tag?/:architecture?/:variant? \` _layers (scoped/tag/architecture/variant)_
- \ ` /docker/metadata/:type/:scope/:name/:tag?/:architecture?/:variant? \` _metadata (type/scoped/tag/architecture/variant)_
# # # Querying [ Label - Schema ] ( http : //label-schema.org/) Metadata
Metadata associated with an image in the [ label - schema ] ( http : //label-schema.org/) format can be queried using the metadata handler. For example, a label of \`org.label-schema.build-date=2020-10-26T14:25:14Z\` on the image \`lucashalbert/curl\` can be queried using the badgen URL of [/docker/metadata/build-date/lucashalbert/curl/](/docker/metadata/build-date/lucashalbert/curl/).
`
2019-11-18 15:52:07 +00:00
export default createBadgenHandler ( {
2020-10-28 02:41:13 +00:00
help ,
2019-05-31 06:35:44 +00:00
title : 'Docker' ,
examples : {
'/docker/pulls/library/ubuntu' : 'pulls (library)' ,
'/docker/stars/library/ubuntu' : 'stars (library)' ,
2019-12-12 06:01:22 +00:00
'/docker/size/library/ubuntu' : 'size (library)' ,
2019-05-31 06:35:44 +00:00
'/docker/pulls/amio/node-chrome' : 'pulls (scoped)' ,
'/docker/stars/library/mongo?icon=docker&label=stars' : 'stars (icon & label)' ,
2019-12-12 06:01:22 +00:00
'/docker/size/lukechilds/bitcoind/latest/amd64' : 'size (scoped/tag/architecture)' ,
2020-10-19 04:32:18 +00:00
'/docker/size/lucashalbert/curl/latest/arm/v6' : 'size (scoped/tag/architecture/variant)' ,
2020-10-28 02:41:13 +00:00
'/docker/layers/lucashalbert/curl/latest/arm/v7' : 'layers (size)' ,
'/docker/layers/lucashalbert/curl/latest/arm/v7?icon=docker&label=layers' : 'layers (icon & label)' ,
'/docker/layers/lucashalbert/curl/latest/arm/v7?label=docker%20layers' : 'layers (label)' ,
'/docker/metadata/version/lucashalbert/curl/latest/arm64/v8' : 'metadata (version)' ,
'/docker/metadata/architecture/lucashalbert/curl/latest/arm64/v8' : 'metadata (architecture)' ,
'/docker/metadata/build-date/lucashalbert/curl/latest/arm64/v8' : 'metadata (build-date)' ,
'/docker/metadata/maintainer/lucashalbert/curl/latest/arm64/v8' : 'metadata (maintainer)' ,
2019-11-18 15:52:07 +00:00
} ,
handlers : {
2019-12-12 06:01:22 +00:00
'/docker/:topic<stars|pulls>/:scope/:name' : starPullHandler ,
2020-10-28 02:41:13 +00:00
'/docker/size/:scope/:name/:tag?/:architecture?/:variant?' : sizeHandler ,
'/docker/layers/:scope/:name/:tag?/:architecture?/:variant?' : layersHandler ,
'/docker/metadata/:type/:scope/:name/:tag?/:architecture?/:variant?' : metadataHandler ,
2019-05-31 06:35:44 +00:00
}
2019-11-18 15:52:07 +00:00
} )
2019-05-31 06:35:44 +00:00
2019-12-12 06:01:22 +00:00
async function starPullHandler ( { topic , scope , name } : PathArgs ) {
2019-05-31 06:35:44 +00:00
if ( ! [ 'stars' , 'pulls' ] . includes ( topic ) ) {
return {
subject : 'docker' ,
status : 'unknown topic' ,
color : 'grey'
}
}
/* eslint-disable camelcase */
const endpoint = ` https://hub.docker.com/v2/repositories/ ${ scope } / ${ name } `
2020-01-26 07:43:40 +00:00
const { pull_count , star_count } = await got ( endpoint ) . json < any > ( )
2019-05-31 06:35:44 +00:00
switch ( topic ) {
case 'stars' :
return {
subject : 'docker stars' ,
status : millify ( star_count ) ,
color : 'blue'
}
case 'pulls' :
return {
subject : 'docker pulls' ,
status : millify ( pull_count ) ,
color : 'blue'
}
}
}
2019-12-12 06:01:22 +00:00
2020-10-19 04:32:18 +00:00
async function sizeHandler ( { scope , name , tag , architecture , variant } : PathArgs ) {
2019-12-12 06:01:22 +00:00
tag = tag ? tag : 'latest'
architecture = architecture ? architecture : 'amd64'
2020-10-19 04:32:18 +00:00
variant = variant ? variant : ''
2019-12-12 06:01:22 +00:00
/* eslint-disable camelcase */
const endpoint = ` https://hub.docker.com/v2/repositories/ ${ scope } / ${ name } /tags `
2020-01-26 07:43:40 +00:00
let body = await got ( endpoint ) . json < any > ( )
2019-12-12 06:01:22 +00:00
let results = [ . . . body . results ]
while ( body . next ) {
2020-01-26 07:43:40 +00:00
body = await got ( body . next ) . json < any > ( )
2019-12-12 06:01:22 +00:00
results = [ . . . results , . . . body . results ]
}
const tagData = results . find ( tagData = > tagData . name === tag )
if ( ! tagData ) {
return {
subject : 'docker' ,
status : 'unknown tag' ,
color : 'grey'
}
}
2020-10-19 04:32:18 +00:00
let imageData = tagData . images . find ( image = > image . architecture === architecture )
2019-12-12 06:01:22 +00:00
if ( ! imageData ) {
return {
subject : 'docker' ,
status : 'unknown architecture' ,
color : 'grey'
}
}
2020-10-19 04:32:18 +00:00
if ( variant ) {
imageData = tagData . images . filter ( image = > image . architecture === architecture ) . find ( image = > image . variant === variant )
if ( ! imageData ) {
return {
subject : 'docker' ,
status : 'unknown variant' ,
color : 'grey'
}
}
}
2019-12-12 06:01:22 +00:00
const sizeInMegabytes = ( imageData . size / 1024 / 1024 ) . toFixed ( 2 )
return {
2020-10-28 02:41:13 +00:00
subject : 'docker size' ,
2019-12-12 06:01:22 +00:00
status : ` ${ sizeInMegabytes } MB ` ,
color : 'blue'
}
}
2020-10-28 02:41:13 +00:00
async function layersHandler ( { scope , name , tag , architecture , variant } : PathArgs ) {
tag = tag ? tag : 'latest'
architecture = architecture ? architecture : 'amd64'
variant = variant ? variant : ''
2020-11-08 02:39:19 +00:00
2020-10-28 02:41:13 +00:00
const token = ( await getDockerAuthToken ( scope , name ) ) . token
const manifest_list = await getManifestList ( scope , name , tag , architecture , variant , token )
const image_manifest = await getImageManifest ( scope , name , manifest_list . digest , token )
const image_config = await getImageConfig ( scope , name , image_manifest . config . digest , token )
const layers = image_config . history
if ( ! layers ) {
return {
subject : 'docker layers' ,
status : 'error getting layers' ,
color : 'grey'
}
}
return {
subject : 'docker layers' ,
status : ` ${ layers . length } ` ,
color : 'blue'
}
}
async function metadataHandler ( { type , scope , name , tag , architecture , variant } : PathArgs ) {
tag = tag ? tag : 'latest'
architecture = architecture ? architecture : 'amd64'
variant = variant ? variant : ''
2020-11-08 02:39:19 +00:00
2020-10-28 02:41:13 +00:00
const token = ( await getDockerAuthToken ( scope , name ) ) . token
const manifest_list = await getManifestList ( scope , name , tag , architecture , variant , token )
const image_manifest = await getImageManifest ( scope , name , manifest_list . digest , token )
const image_config = await getImageConfig ( scope , name , image_manifest . config . digest , token )
const metadata = image_config . container_config . Labels [ ` org.label-schema. ${ type } ` ]
if ( ! metadata ) {
return {
subject : 'docker metadata' ,
status : ` error getting ${ type } ` ,
color : 'grey'
}
}
return {
subject : ` ${ type } ` ,
status : ` ${ metadata } ` ,
color : 'blue'
}
}