feat: support OCI index images (such as produced by buildkit cache exports) (#227)

fixes #227
This commit is contained in:
Joxit 2022-03-19 22:35:41 +01:00
parent 7c0874694a
commit 05cbb51125
No known key found for this signature in database
GPG Key ID: F526592B8E012263
5 changed files with 53 additions and 26 deletions

View File

@ -69,7 +69,7 @@
oReq.open('GET', `${registryUrl}/v2/${name}/manifests/${tag}`);
oReq.setRequestHeader(
'Accept',
'application/vnd.docker.distribution.manifest.v2+json, application/vnd.oci.image.manifest.v1+json, application/vnd.docker.distribution.manifest.list.v2+json'
'application/vnd.docker.distribution.manifest.v2+json, application/vnd.oci.image.manifest.v1+json, application/vnd.docker.distribution.manifest.list.v2+json, application/vnd.oci.image.index.v1+json'
);
oReq.send();
},

View File

@ -15,27 +15,27 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<image-date>
<div title="Creation date { getLocalDate(props.image) }">{ getDate(props.image) } ago</div>
<div title="Creation date { getLocalDate(props.image) }">{ getDate(props.image) }</div>
<script>
import {
dateFormat,
} from '../../scripts/utils';
import { dateFormat } from '../../scripts/utils';
export default {
onMounted(props) {
props.image.one('creation-date', (date) => {
this.update({
date: date,
localDate: date.toLocaleString()
localDate: date && date.toLocaleString(),
});
});
props.image.trigger('get-date');
},
getDate(image) {
return dateFormat(image.creationDate)
return !image.ociImage ? `${dateFormat(image.creationDate)} ago` : 'Not Available';
},
getLocalDate(image) {
return (image.creationDate && image.creationDate.toLocaleString()) || 'unknown'
}
}
return !image.ociImage
? (image.creationDate && image.creationDate.toLocaleString()) || 'unknown'
: 'unavailable on OCI index/Buildkit export cache';
},
};
</script>
</image-date>
</image-date>

View File

@ -21,11 +21,11 @@
onMounted(props) {
props.image.on('sha256', (sha256) => {
this.update({
sha256: sha256.substring(0, 19)
sha256: sha256 && sha256.substring(0, 19),
});
});
props.image.trigger('get-sha256');
}
}
},
};
</script>
</image-tag>
</image-tag>

View File

@ -15,16 +15,34 @@ You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<tag-history-button>
<material-button title="This will show the history of given tag" waves-center="true" rounded="true" waves-color="#ddd"
onClick="{ routeToHistory }">
<material-button
title="{ buttonTittle() }"
waves-center="true"
rounded="true"
waves-color="#ddd"
onClick="{ routeToHistory }"
disabled="{ props.image.ociImage }"
>
<i class="material-icons">history</i>
</material-button>
<script>
import router from '../../scripts/router';
export default {
onMounted(props) {
props.image.one('oci-image', () => {
this.update();
});
},
buttonTittle() {
return !this.props.image.ociImage
? 'This will show the history of given tag'
: 'History is unavailable on OCI index/Buildkit export cache';
},
routeToHistory() {
router.history(this.props.image.name, this.props.image.tag)
}
}
if (!this.props.image.ociImage) {
router.history(this.props.image.name, this.props.image.tag);
}
},
};
</script>
</tag-history-button>
</tag-history-button>

View File

@ -56,6 +56,7 @@ export class DockerImage {
onNotify,
onAuthentication,
};
this.ociImage = false;
observable(this);
this.on('get-size', function () {
if (this.size !== undefined) {
@ -107,11 +108,12 @@ export class DockerImage {
self.variants = [image];
return;
}
self.size = response.layers.reduce(function (acc, e) {
self.ociImage = response.mediaType === 'application/vnd.oci.image.index.v1+json';
self.layers = self.ociImage ? response.manifests : response.layers;
self.size = self.layers.reduce(function (acc, e) {
return acc + e.size;
}, 0);
self.sha256 = response.config.digest;
self.layers = response.layers;
self.sha256 = response.config && response.config.digest;
self.trigger('size', self.size);
self.trigger('sha256', self.sha256);
oReq.getContentDigest(function (digest) {
@ -121,7 +123,14 @@ export class DockerImage {
self.opts.onNotify(ERROR_CAN_NOT_READ_CONTENT_DIGEST);
}
});
self.getBlobs(response.config.digest);
if (!self.ociImage) {
self.getBlobs(self.sha256);
} else {
// Force updates
self.trigger('creation-date');
self.trigger('blobs');
self.trigger('oci-image');
}
} else if (this.status == 404) {
self.opts.onNotify(`Manifest for ${self.name}:${self.tag} not found`, true);
} else {
@ -131,7 +140,7 @@ export class DockerImage {
oReq.open('GET', `${this.opts.registryUrl}/v2/${self.name}/manifests/${self.tag}`);
oReq.setRequestHeader(
'Accept',
'application/vnd.docker.distribution.manifest.v2+json, application/vnd.oci.image.manifest.v1+json' +
'application/vnd.docker.distribution.manifest.v2+json, application/vnd.oci.image.manifest.v1+json, application/vnd.oci.image.index.v1+json' +
(self.opts.list ? ', application/vnd.docker.distribution.manifest.list.v2+json' : '')
);
oReq.send();