Skip to content

Commit

Permalink
feat: support OCI index images (such as produced by buildkit cache ex…
Browse files Browse the repository at this point in the history
…ports) (#227)

fixes #227
  • Loading branch information
Joxit committed Mar 19, 2022
1 parent 7c08746 commit 05cbb51
Show file tree
Hide file tree
Showing 5 changed files with 53 additions and 26 deletions.
2 changes: 1 addition & 1 deletion src/components/dialogs/confirm-delete-image.riot
Original file line number Diff line number Diff line change
Expand Up @@ -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();
},
Expand Down
20 changes: 10 additions & 10 deletions src/components/tag-list/image-date.riot
Original file line number Diff line number Diff line change
Expand Up @@ -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>
8 changes: 4 additions & 4 deletions src/components/tag-list/image-tag.riot
Original file line number Diff line number Diff line change
Expand Up @@ -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>
30 changes: 24 additions & 6 deletions src/components/tag-list/tag-history-button.riot
Original file line number Diff line number Diff line change
Expand Up @@ -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>
19 changes: 14 additions & 5 deletions src/scripts/docker-image.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ export class DockerImage {
onNotify,
onAuthentication,
};
this.ociImage = false;
observable(this);
this.on('get-size', function () {
if (this.size !== undefined) {
Expand Down Expand Up @@ -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) {
Expand All @@ -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 {
Expand All @@ -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();
Expand Down

0 comments on commit 05cbb51

Please sign in to comment.