Quick refactor to introduce abstract base class for docker registry clients

This commit is contained in:
Josh Stark 2020-11-01 11:29:03 +00:00
parent f407b15c92
commit 7150b2c3a9
11 changed files with 287 additions and 81 deletions

View File

@ -0,0 +1,60 @@
/*
* Copyright (c) 2020 LinuxServer.io
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package io.linuxserver.fleet.v2.client.docker;
import io.linuxserver.fleet.v2.client.docker.converter.DockerResponseConverter;
import io.linuxserver.fleet.v2.types.docker.DockerImage;
import io.linuxserver.fleet.v2.types.docker.DockerTag;
import java.util.List;
import java.util.stream.Collectors;
public abstract class AbstractDockerApiClient<D, T, IC extends DockerResponseConverter<D, DockerImage>, TC extends DockerResponseConverter<T, DockerTag>> implements DockerApiClient {
private final IC imageConverter;
private final TC tagConverter;
public AbstractDockerApiClient(final IC imageConverter, final TC tagConverter) {
this.imageConverter = imageConverter;
this.tagConverter = tagConverter;
}
@Override
public final DockerImage fetchImage(String imageName) {
final D dockerModel = fetchImageFromApi(imageName);
if (null == dockerModel) {
return null;
}
return imageConverter.convert(dockerModel);
}
@Override
public final List<DockerImage> fetchAllImages(String repositoryName) {
return fetchAllImagesFromApi(repositoryName).stream().map(imageConverter::convert).collect(Collectors.toList());
}
@Override
public final List<DockerTag> fetchImageTags(String imageName) {
return fetchTagsFromApi(imageName).stream().map(tagConverter::convert).collect(Collectors.toList());
}
protected abstract D fetchImageFromApi(final String imageName);
protected abstract List<D> fetchAllImagesFromApi(final String repositoryName);
protected abstract List<T> fetchTagsFromApi(final String imageName);
}

View File

@ -15,28 +15,27 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package io.linuxserver.fleet.v2.client.docker.dockerhub;
package io.linuxserver.fleet.v2.client.docker.converter;
import io.linuxserver.fleet.v2.client.docker.converter.DockerResponseConverter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.time.LocalDateTime;
import java.time.format.DateTimeParseException;
public abstract class AbstractDockerHubConverter<DOCKER_HUB, INTERNAL> implements DockerResponseConverter<DOCKER_HUB, INTERNAL> {
public abstract class AbstractDockerResponseConverter<D, I> implements DockerResponseConverter<D, I> {
private final Logger LOGGER = LoggerFactory.getLogger(getClass());
@Override
public final INTERNAL convert(final DOCKER_HUB dockerHubV2Image) {
public final I convert(final D dockerModel) {
try {
if (null == dockerHubV2Image) {
if (null == dockerModel) {
LOGGER.warn("Attempted to convert null image");
} else {
return doPlainConvert(dockerHubV2Image);
return doPlainConvert(dockerModel);
}
} catch (Exception e) {
@ -46,7 +45,7 @@ public abstract class AbstractDockerHubConverter<DOCKER_HUB, INTERNAL> implement
return null;
}
protected abstract INTERNAL doPlainConvert(final DOCKER_HUB dockerHubV2Image);
protected abstract I doPlainConvert(final D dockerApiImage);
protected final LocalDateTime parseDockerHubDate(String date) {

View File

@ -20,38 +20,62 @@ package io.linuxserver.fleet.v2.client.docker.dockerhub;
import io.linuxserver.fleet.dockerhub.DockerHubException;
import io.linuxserver.fleet.dockerhub.model.DockerHubV2Image;
import io.linuxserver.fleet.dockerhub.model.DockerHubV2ImageListResult;
import io.linuxserver.fleet.dockerhub.model.DockerHubV2Tag;
import io.linuxserver.fleet.dockerhub.model.DockerHubV2TagListResult;
import io.linuxserver.fleet.v2.client.docker.DockerApiClient;
import io.linuxserver.fleet.v2.client.docker.AbstractDockerApiClient;
import io.linuxserver.fleet.v2.client.rest.HttpException;
import io.linuxserver.fleet.v2.client.rest.RestClient;
import io.linuxserver.fleet.v2.client.rest.RestResponse;
import io.linuxserver.fleet.v2.types.docker.DockerImage;
import io.linuxserver.fleet.v2.types.docker.DockerTag;
import java.util.ArrayList;
import java.util.List;
public class DockerHubApiClient implements DockerApiClient {
public class DockerHubApiClient extends AbstractDockerApiClient<DockerHubV2Image, DockerHubV2Tag, DockerHubImageConverter, DockerHubTagConverter> {
private static final String DockerHubApiUrl = "https://hub.docker.com/v2";
private static final int DefaultPageSize = 1000;
private final RestClient restClient;
private final DockerHubImageConverter imageConverter;
private final DockerHubTagConverter tagConverter;
public DockerHubApiClient() {
super(new DockerHubImageConverter(), new DockerHubTagConverter());
restClient = new RestClient();
imageConverter = new DockerHubImageConverter();
tagConverter = new DockerHubTagConverter();
}
@Override
public List<DockerImage> fetchAllImages(String repositoryName) {
public final boolean isRepositoryValid(String repositoryName) {
final List<DockerImage> images = new ArrayList<>();
try {
return !fetchAllImages(repositoryName).isEmpty();
} catch (HttpException e) {
throw new DockerHubException("Unable to verify repository " + repositoryName, e);
}
}
@Override
protected final DockerHubV2Image fetchImageFromApi(String imageName) {
try {
final String absoluteUrl = DockerHubApiUrl + "/repositories/" + imageName + "/";
final RestResponse<DockerHubV2Image> restResponse = doCall(absoluteUrl, DockerHubV2Image.class);
if (isResponseOK(restResponse)) {
return restResponse.getPayload();
}
return null;
} catch (HttpException e) {
throw new DockerHubException("Unable to get images for " + imageName, e);
}
}
@Override
protected final List<DockerHubV2Image> fetchAllImagesFromApi(String repositoryName) {
final List<DockerHubV2Image> images = new ArrayList<>();
try {
@ -63,13 +87,7 @@ public class DockerHubApiClient implements DockerApiClient {
if (isResponseOK(response)) {
DockerHubV2ImageListResult payload = response.getPayload();
payload.getResults().forEach(i -> {
final DockerImage converted = imageConverter.convert(i);
if (null != converted) {
images.add(converted);
}
});
images.addAll(payload.getResults());
url = payload.getNext();
}
@ -83,41 +101,11 @@ public class DockerHubApiClient implements DockerApiClient {
}
@Override
public boolean isRepositoryValid(String repositoryName) {
try {
return !fetchAllImages(repositoryName).isEmpty();
} catch (HttpException e) {
throw new DockerHubException("Unable to verify repository " + repositoryName, e);
}
}
@Override
public DockerImage fetchImage(String imageName) {
protected final List<DockerHubV2Tag> fetchTagsFromApi(String imageName) {
try {
final String absoluteUrl = DockerHubApiUrl + "/repositories/" + imageName + "/";
final RestResponse<DockerHubV2Image> restResponse = doCall(absoluteUrl, DockerHubV2Image.class);
if (isResponseOK(restResponse)) {
return imageConverter.convert(restResponse.getPayload());
}
return null;
} catch (HttpException e) {
throw new DockerHubException("Unable to get images for " + imageName, e);
}
}
@Override
public List<DockerTag> fetchImageTags(String imageName) {
try {
List<DockerTag> tags = new ArrayList<>();
List<DockerHubV2Tag> tags = new ArrayList<>();
String absoluteUrl = DockerHubApiUrl + "/repositories/" + imageName + "/tags/?page_size=" + DefaultPageSize;
while (absoluteUrl != null) {
@ -127,13 +115,7 @@ public class DockerHubApiClient implements DockerApiClient {
if (isResponseOK(response)) {
final DockerHubV2TagListResult payload = response.getPayload();
payload.getResults().forEach(t -> {
final DockerTag converted = tagConverter.convert(t);
if (null != converted) {
tags.add(converted);
}
});
tags.addAll(payload.getResults());
absoluteUrl = payload.getNext();
}

View File

@ -18,19 +18,20 @@
package io.linuxserver.fleet.v2.client.docker.dockerhub;
import io.linuxserver.fleet.dockerhub.model.DockerHubV2Image;
import io.linuxserver.fleet.v2.client.docker.converter.AbstractDockerResponseConverter;
import io.linuxserver.fleet.v2.types.docker.DockerImage;
public class DockerHubImageConverter extends AbstractDockerHubConverter<DockerHubV2Image, DockerImage> {
public class DockerHubImageConverter extends AbstractDockerResponseConverter<DockerHubV2Image, DockerImage> {
@Override
protected final DockerImage doPlainConvert(final DockerHubV2Image dockerHubV2Image) {
protected final DockerImage doPlainConvert(final DockerHubV2Image dockerApiImage) {
return new DockerImage(dockerHubV2Image.getName(),
dockerHubV2Image.getNamespace(),
dockerHubV2Image.getDescription(),
dockerHubV2Image.getStarCount(),
dockerHubV2Image.getPullCount(),
parseDockerHubDate(dockerHubV2Image.getLastUpdated()));
return new DockerImage(dockerApiImage.getName(),
dockerApiImage.getNamespace(),
dockerApiImage.getDescription(),
dockerApiImage.getStarCount(),
dockerApiImage.getPullCount(),
parseDockerHubDate(dockerApiImage.getLastUpdated()));
}
@Override

View File

@ -19,19 +19,20 @@ package io.linuxserver.fleet.v2.client.docker.dockerhub;
import io.linuxserver.fleet.dockerhub.model.DockerHubV2Tag;
import io.linuxserver.fleet.dockerhub.model.DockerHubV2TagDigest;
import io.linuxserver.fleet.v2.client.docker.converter.AbstractDockerResponseConverter;
import io.linuxserver.fleet.v2.types.docker.DockerTag;
import io.linuxserver.fleet.v2.types.docker.DockerTagManifestDigest;
public class DockerHubTagConverter extends AbstractDockerHubConverter<DockerHubV2Tag, DockerTag> {
public class DockerHubTagConverter extends AbstractDockerResponseConverter<DockerHubV2Tag, DockerTag> {
@Override
protected final DockerTag doPlainConvert(final DockerHubV2Tag dockerHubV2Tag) {
protected final DockerTag doPlainConvert(final DockerHubV2Tag dockerApiImage) {
final DockerTag dockerTag = new DockerTag(dockerHubV2Tag.getName(),
dockerHubV2Tag.getFullSize(),
parseDockerHubDate(dockerHubV2Tag.getLastUpdated()));
final DockerTag dockerTag = new DockerTag(dockerApiImage.getName(),
dockerApiImage.getFullSize(),
parseDockerHubDate(dockerApiImage.getLastUpdated()));
for (DockerHubV2TagDigest tagImageDigest : dockerHubV2Tag.getImages()) {
for (DockerHubV2TagDigest tagImageDigest : dockerApiImage.getImages()) {
dockerTag.addDigest(new DockerTagManifestDigest(tagImageDigest.getSize(),
tagImageDigest.getDigest(),

View File

@ -0,0 +1,51 @@
/*
* Copyright (c) 2020 LinuxServer.io
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package io.linuxserver.fleet.v2.client.docker.github;
import io.linuxserver.fleet.v2.client.docker.AbstractDockerApiClient;
import io.linuxserver.fleet.v2.client.docker.github.model.GitHubImage;
import io.linuxserver.fleet.v2.client.docker.github.model.GitHubTag;
import java.util.List;
public class GitHubContainerRegistryClient extends AbstractDockerApiClient<GitHubImage, GitHubTag, GitHubImageConverter, GitHubTagConverter> {
public GitHubContainerRegistryClient() {
super(new GitHubImageConverter(), new GitHubTagConverter());
}
@Override
protected final GitHubImage fetchImageFromApi(String imageName) {
return null;
}
@Override
protected final List<GitHubImage> fetchAllImagesFromApi(String repositoryName) {
return null;
}
@Override
protected final List<GitHubTag> fetchTagsFromApi(String imageName) {
return null;
}
@Override
public final boolean isRepositoryValid(String repositoryName) {
return false;
}
}

View File

@ -0,0 +1,35 @@
/*
* Copyright (c) 2020 LinuxServer.io
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package io.linuxserver.fleet.v2.client.docker.github;
import io.linuxserver.fleet.v2.client.docker.converter.AbstractDockerResponseConverter;
import io.linuxserver.fleet.v2.client.docker.github.model.GitHubImage;
import io.linuxserver.fleet.v2.types.docker.DockerImage;
public class GitHubImageConverter extends AbstractDockerResponseConverter<GitHubImage, DockerImage> {
@Override
protected final DockerImage doPlainConvert(final GitHubImage dockerApiImage) {
return null;
}
@Override
public final Class<GitHubImage> getConverterClass() {
return GitHubImage.class;
}
}

View File

@ -0,0 +1,35 @@
/*
* Copyright (c) 2020 LinuxServer.io
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package io.linuxserver.fleet.v2.client.docker.github;
import io.linuxserver.fleet.v2.client.docker.converter.AbstractDockerResponseConverter;
import io.linuxserver.fleet.v2.client.docker.github.model.GitHubTag;
import io.linuxserver.fleet.v2.types.docker.DockerTag;
public class GitHubTagConverter extends AbstractDockerResponseConverter<GitHubTag, DockerTag> {
@Override
protected final DockerTag doPlainConvert(final GitHubTag dockerApiImage) {
return null;
}
@Override
public final Class<GitHubTag> getConverterClass() {
return GitHubTag.class;
}
}

View File

@ -0,0 +1,21 @@
/*
* Copyright (c) 2020 LinuxServer.io
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package io.linuxserver.fleet.v2.client.docker.github.model;
public class GitHubImage {
}

View File

@ -0,0 +1,21 @@
/*
* Copyright (c) 2020 LinuxServer.io
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package io.linuxserver.fleet.v2.client.docker.github.model;
public class GitHubTag {
}

View File

@ -1,5 +1,5 @@
#Fri Aug 21 17:45:10 BST 2020
app.build.date=2020-08-21T17\:45\:10
#Sun Nov 01 11:27:50 GMT 2020
app.build.date=2020-11-01T11\:27\:50
app.build.os=Linux
app.build.user=josh
app.version=2.1.1