From e0c93172259814ed8bfbc176f34eb975e25857fe Mon Sep 17 00:00:00 2001 From: Josh Stark Date: Sat, 14 Dec 2019 15:27:25 +0000 Subject: [PATCH] Started implementing design for docker api requests. Display page for image details. --- .../dockerhub/DockerHubAuthenticator.java | 4 +-- .../fleet/dockerhub/DockerHubV2Client.java | 6 ++-- .../fleet/v2/cache/RepositoryCache.java | 14 +++++++++ .../{ => v2/client}/rest/HttpException.java | 2 +- .../{ => v2/client}/rest/RestClient.java | 12 ++++---- .../{ => v2/client}/rest/RestResponse.java | 4 +-- .../JacksonMarshallingStrategy.java | 2 +- .../rest/marshalling/MarshallingStrategy.java | 2 +- .../rest/proxy/LazyLoadPayloadProxy.java | 6 ++-- .../client}/rest/proxy/PayloadProxy.java | 2 +- .../fleet/v2/db/DefaultImageDAO.java | 2 +- .../fleet/v2/key/AbstractLookupKey.java | 9 +++++- .../io/linuxserver/fleet/v2/key/ImageKey.java | 5 ++++ .../fleet/v2/key/ImageLookupKey.java | 29 ++++++++++++++++++- .../fleet/v2/service/RepositoryManager.java | 5 ++++ .../io/linuxserver/fleet/v2/types/Image.java | 11 +++++++ .../fleet/v2/types/docker/DockerImage.java | 12 ++++---- .../linuxserver/fleet/v2/web/Locations.java | 2 +- .../fleet/v2/web/WebRouteController.java | 2 ++ src/main/resources/static/assets/css/app.css | 8 +++-- .../views/prebuilt/image-list-item.ftl | 6 ++-- 21 files changed, 111 insertions(+), 34 deletions(-) rename src/main/java/io/linuxserver/fleet/{ => v2/client}/rest/HttpException.java (95%) rename src/main/java/io/linuxserver/fleet/{ => v2/client}/rest/RestClient.java (93%) rename src/main/java/io/linuxserver/fleet/{ => v2/client}/rest/RestResponse.java (91%) rename src/main/java/io/linuxserver/fleet/{ => v2/client}/rest/marshalling/JacksonMarshallingStrategy.java (96%) rename src/main/java/io/linuxserver/fleet/{ => v2/client}/rest/marshalling/MarshallingStrategy.java (93%) rename src/main/java/io/linuxserver/fleet/{ => v2/client}/rest/proxy/LazyLoadPayloadProxy.java (88%) rename src/main/java/io/linuxserver/fleet/{ => v2/client}/rest/proxy/PayloadProxy.java (93%) diff --git a/src/main/java/io/linuxserver/fleet/dockerhub/DockerHubAuthenticator.java b/src/main/java/io/linuxserver/fleet/dockerhub/DockerHubAuthenticator.java index 1111174..27cce86 100644 --- a/src/main/java/io/linuxserver/fleet/dockerhub/DockerHubAuthenticator.java +++ b/src/main/java/io/linuxserver/fleet/dockerhub/DockerHubAuthenticator.java @@ -17,8 +17,8 @@ package io.linuxserver.fleet.dockerhub; -import io.linuxserver.fleet.rest.RestClient; -import io.linuxserver.fleet.rest.RestResponse; +import io.linuxserver.fleet.v2.client.rest.RestClient; +import io.linuxserver.fleet.v2.client.rest.RestResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/src/main/java/io/linuxserver/fleet/dockerhub/DockerHubV2Client.java b/src/main/java/io/linuxserver/fleet/dockerhub/DockerHubV2Client.java index 1b1f243..59812b7 100644 --- a/src/main/java/io/linuxserver/fleet/dockerhub/DockerHubV2Client.java +++ b/src/main/java/io/linuxserver/fleet/dockerhub/DockerHubV2Client.java @@ -18,9 +18,9 @@ package io.linuxserver.fleet.dockerhub; import io.linuxserver.fleet.dockerhub.model.*; -import io.linuxserver.fleet.rest.HttpException; -import io.linuxserver.fleet.rest.RestClient; -import io.linuxserver.fleet.rest.RestResponse; +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 java.util.*; diff --git a/src/main/java/io/linuxserver/fleet/v2/cache/RepositoryCache.java b/src/main/java/io/linuxserver/fleet/v2/cache/RepositoryCache.java index b9a0a6e..2204796 100644 --- a/src/main/java/io/linuxserver/fleet/v2/cache/RepositoryCache.java +++ b/src/main/java/io/linuxserver/fleet/v2/cache/RepositoryCache.java @@ -18,12 +18,26 @@ package io.linuxserver.fleet.v2.cache; import io.linuxserver.fleet.v2.key.ImageKey; +import io.linuxserver.fleet.v2.key.ImageLookupKey; import io.linuxserver.fleet.v2.key.RepositoryKey; import io.linuxserver.fleet.v2.types.Image; import io.linuxserver.fleet.v2.types.Repository; public class RepositoryCache extends AbstractItemCache { + public final Image lookupImage(final ImageLookupKey lookupKey) { + + for (Repository repository : getAllItems()) { + for (Image image : repository.getImages()) { + if (lookupKey.isLookupKeyFor(image)) { + return image; + } + } + } + + return null; + } + public final Image findImage(final ImageKey imageKey) { if (isItemCached(imageKey.getRepositoryKey())) { diff --git a/src/main/java/io/linuxserver/fleet/rest/HttpException.java b/src/main/java/io/linuxserver/fleet/v2/client/rest/HttpException.java similarity index 95% rename from src/main/java/io/linuxserver/fleet/rest/HttpException.java rename to src/main/java/io/linuxserver/fleet/v2/client/rest/HttpException.java index b8081be..f30e5c8 100644 --- a/src/main/java/io/linuxserver/fleet/rest/HttpException.java +++ b/src/main/java/io/linuxserver/fleet/v2/client/rest/HttpException.java @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package io.linuxserver.fleet.rest; +package io.linuxserver.fleet.v2.client.rest; public class HttpException extends RuntimeException { diff --git a/src/main/java/io/linuxserver/fleet/rest/RestClient.java b/src/main/java/io/linuxserver/fleet/v2/client/rest/RestClient.java similarity index 93% rename from src/main/java/io/linuxserver/fleet/rest/RestClient.java rename to src/main/java/io/linuxserver/fleet/v2/client/rest/RestClient.java index ef82ae9..ea244ac 100644 --- a/src/main/java/io/linuxserver/fleet/rest/RestClient.java +++ b/src/main/java/io/linuxserver/fleet/v2/client/rest/RestClient.java @@ -15,11 +15,11 @@ * along with this program. If not, see . */ -package io.linuxserver.fleet.rest; +package io.linuxserver.fleet.v2.client.rest; -import io.linuxserver.fleet.rest.marshalling.JacksonMarshallingStrategy; -import io.linuxserver.fleet.rest.marshalling.MarshallingStrategy; -import io.linuxserver.fleet.rest.proxy.LazyLoadPayloadProxy; +import io.linuxserver.fleet.v2.client.rest.marshalling.JacksonMarshallingStrategy; +import io.linuxserver.fleet.v2.client.rest.marshalling.MarshallingStrategy; +import io.linuxserver.fleet.v2.client.rest.proxy.LazyLoadPayloadProxy; import org.apache.http.HttpEntity; import org.apache.http.StatusLine; import org.apache.http.client.methods.CloseableHttpResponse; @@ -36,7 +36,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.IOException; -import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; import java.util.Map; /** @@ -85,7 +85,7 @@ public class RestClient { try { HttpPost post = new HttpPost(url + parseQueryParameters(queryParameters)); - post.setEntity(new StringEntity(marshallingStrategy.marshall(payload), Charset.forName("UTF-8"))); + post.setEntity(new StringEntity(marshallingStrategy.marshall(payload), StandardCharsets.UTF_8)); post.setHeader("Content-Type", marshallingStrategy.getContentType()); return executeBaseRequest(responseType, headers, post); diff --git a/src/main/java/io/linuxserver/fleet/rest/RestResponse.java b/src/main/java/io/linuxserver/fleet/v2/client/rest/RestResponse.java similarity index 91% rename from src/main/java/io/linuxserver/fleet/rest/RestResponse.java rename to src/main/java/io/linuxserver/fleet/v2/client/rest/RestResponse.java index a3a8119..cbe8ae9 100644 --- a/src/main/java/io/linuxserver/fleet/rest/RestResponse.java +++ b/src/main/java/io/linuxserver/fleet/v2/client/rest/RestResponse.java @@ -15,9 +15,9 @@ * along with this program. If not, see . */ -package io.linuxserver.fleet.rest; +package io.linuxserver.fleet.v2.client.rest; -import io.linuxserver.fleet.rest.proxy.PayloadProxy; +import io.linuxserver.fleet.v2.client.rest.proxy.PayloadProxy; public class RestResponse { diff --git a/src/main/java/io/linuxserver/fleet/rest/marshalling/JacksonMarshallingStrategy.java b/src/main/java/io/linuxserver/fleet/v2/client/rest/marshalling/JacksonMarshallingStrategy.java similarity index 96% rename from src/main/java/io/linuxserver/fleet/rest/marshalling/JacksonMarshallingStrategy.java rename to src/main/java/io/linuxserver/fleet/v2/client/rest/marshalling/JacksonMarshallingStrategy.java index 0870b1b..6697d18 100644 --- a/src/main/java/io/linuxserver/fleet/rest/marshalling/JacksonMarshallingStrategy.java +++ b/src/main/java/io/linuxserver/fleet/v2/client/rest/marshalling/JacksonMarshallingStrategy.java @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package io.linuxserver.fleet.rest.marshalling; +package io.linuxserver.fleet.v2.client.rest.marshalling; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.DeserializationFeature; diff --git a/src/main/java/io/linuxserver/fleet/rest/marshalling/MarshallingStrategy.java b/src/main/java/io/linuxserver/fleet/v2/client/rest/marshalling/MarshallingStrategy.java similarity index 93% rename from src/main/java/io/linuxserver/fleet/rest/marshalling/MarshallingStrategy.java rename to src/main/java/io/linuxserver/fleet/v2/client/rest/marshalling/MarshallingStrategy.java index df0da76..e492064 100644 --- a/src/main/java/io/linuxserver/fleet/rest/marshalling/MarshallingStrategy.java +++ b/src/main/java/io/linuxserver/fleet/v2/client/rest/marshalling/MarshallingStrategy.java @@ -1,4 +1,4 @@ -package io.linuxserver.fleet.rest.marshalling; +package io.linuxserver.fleet.v2.client.rest.marshalling; import java.io.IOException; diff --git a/src/main/java/io/linuxserver/fleet/rest/proxy/LazyLoadPayloadProxy.java b/src/main/java/io/linuxserver/fleet/v2/client/rest/proxy/LazyLoadPayloadProxy.java similarity index 88% rename from src/main/java/io/linuxserver/fleet/rest/proxy/LazyLoadPayloadProxy.java rename to src/main/java/io/linuxserver/fleet/v2/client/rest/proxy/LazyLoadPayloadProxy.java index f5ed2d4..36223d9 100644 --- a/src/main/java/io/linuxserver/fleet/rest/proxy/LazyLoadPayloadProxy.java +++ b/src/main/java/io/linuxserver/fleet/v2/client/rest/proxy/LazyLoadPayloadProxy.java @@ -15,10 +15,10 @@ * along with this program. If not, see . */ -package io.linuxserver.fleet.rest.proxy; +package io.linuxserver.fleet.v2.client.rest.proxy; -import io.linuxserver.fleet.rest.HttpException; -import io.linuxserver.fleet.rest.marshalling.MarshallingStrategy; +import io.linuxserver.fleet.v2.client.rest.HttpException; +import io.linuxserver.fleet.v2.client.rest.marshalling.MarshallingStrategy; import java.io.IOException; diff --git a/src/main/java/io/linuxserver/fleet/rest/proxy/PayloadProxy.java b/src/main/java/io/linuxserver/fleet/v2/client/rest/proxy/PayloadProxy.java similarity index 93% rename from src/main/java/io/linuxserver/fleet/rest/proxy/PayloadProxy.java rename to src/main/java/io/linuxserver/fleet/v2/client/rest/proxy/PayloadProxy.java index 6f6a60a..42b12ef 100644 --- a/src/main/java/io/linuxserver/fleet/rest/proxy/PayloadProxy.java +++ b/src/main/java/io/linuxserver/fleet/v2/client/rest/proxy/PayloadProxy.java @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package io.linuxserver.fleet.rest.proxy; +package io.linuxserver.fleet.v2.client.rest.proxy; public interface PayloadProxy { diff --git a/src/main/java/io/linuxserver/fleet/v2/db/DefaultImageDAO.java b/src/main/java/io/linuxserver/fleet/v2/db/DefaultImageDAO.java index 9c5ca17..cd51a99 100644 --- a/src/main/java/io/linuxserver/fleet/v2/db/DefaultImageDAO.java +++ b/src/main/java/io/linuxserver/fleet/v2/db/DefaultImageDAO.java @@ -44,7 +44,7 @@ public class DefaultImageDAO extends AbstractDAO implements ImageDAO { private static final String CreateTagBranchOutline = "{CALL Image_CreateTagBranchOutline(?,?)}"; private static final String StoreTagDigest = "{CALL Image_StoreTagDigest(?,?,?,?,?)}"; private static final String GetTagBranches = "{CALL Image_GetTagBranches(?)}"; - public static final String GetTagDigests = "{CALL Image_GetTagDigests(?)}"; + private static final String GetTagDigests = "{CALL Image_GetTagDigests(?)}"; private static final String CreateImageOutline = "{CALL Image_CreateOutline(?,?,?,?)}"; private static final String GetImage = "{CALL Image_Get(?)}"; private static final String DeleteImage = "{CALL Image_Delete(?)}"; diff --git a/src/main/java/io/linuxserver/fleet/v2/key/AbstractLookupKey.java b/src/main/java/io/linuxserver/fleet/v2/key/AbstractLookupKey.java index 3050b06..67f86f4 100644 --- a/src/main/java/io/linuxserver/fleet/v2/key/AbstractLookupKey.java +++ b/src/main/java/io/linuxserver/fleet/v2/key/AbstractLookupKey.java @@ -17,7 +17,7 @@ package io.linuxserver.fleet.v2.key; -public class AbstractLookupKey implements Key { +public abstract class AbstractLookupKey> implements Key { private final String query; @@ -33,4 +33,11 @@ public class AbstractLookupKey implements Key { public final Integer getId() { return null; } + + @Override + public String toString() { + return query; + } + + public abstract boolean isLookupKeyFor(final TYPE type); } diff --git a/src/main/java/io/linuxserver/fleet/v2/key/ImageKey.java b/src/main/java/io/linuxserver/fleet/v2/key/ImageKey.java index c29a3a3..07ecc4c 100644 --- a/src/main/java/io/linuxserver/fleet/v2/key/ImageKey.java +++ b/src/main/java/io/linuxserver/fleet/v2/key/ImageKey.java @@ -74,4 +74,9 @@ public class ImageKey extends AbstractDatabaseKey { public String toString() { return repositoryKey.getId() + ":" + super.toString() + ":" + repositoryKey.getName() + "/" + name; } + + @Override + public boolean equals(Object o) { + return super.equals(o) && ((ImageKey) o).name.equals(name); + } } diff --git a/src/main/java/io/linuxserver/fleet/v2/key/ImageLookupKey.java b/src/main/java/io/linuxserver/fleet/v2/key/ImageLookupKey.java index a3b33dd..22bcc08 100644 --- a/src/main/java/io/linuxserver/fleet/v2/key/ImageLookupKey.java +++ b/src/main/java/io/linuxserver/fleet/v2/key/ImageLookupKey.java @@ -17,9 +17,36 @@ package io.linuxserver.fleet.v2.key; -public class ImageLookupKey extends AbstractLookupKey { +import io.linuxserver.fleet.v2.types.Image; + +public class ImageLookupKey extends AbstractLookupKey { + + private static final String KeyPattern = "^[^/]+/[^/]+$"; + + private final String lookupRepositoryName; + private final String lookupImageName; public ImageLookupKey(final String query) { super(query); + + if (query.matches(KeyPattern)) { + + final String[] names = query.split("/"); + lookupRepositoryName = names[0]; + lookupImageName = names[1]; + + } else { + throw new IllegalArgumentException("Malformed lookup query for ImageLookupKey"); + } + } + + @Override + public final boolean isLookupKeyFor(final Image image) { + + if (null == image) { + return false; + } + + return image.getRepositoryName().equals(lookupRepositoryName) && image.getName().equals(lookupImageName); } } diff --git a/src/main/java/io/linuxserver/fleet/v2/service/RepositoryManager.java b/src/main/java/io/linuxserver/fleet/v2/service/RepositoryManager.java index aefd763..15a940b 100644 --- a/src/main/java/io/linuxserver/fleet/v2/service/RepositoryManager.java +++ b/src/main/java/io/linuxserver/fleet/v2/service/RepositoryManager.java @@ -21,6 +21,7 @@ import io.linuxserver.fleet.db.query.InsertUpdateResult; import io.linuxserver.fleet.v2.cache.RepositoryCache; import io.linuxserver.fleet.v2.db.ImageDAO; import io.linuxserver.fleet.v2.key.ImageKey; +import io.linuxserver.fleet.v2.key.ImageLookupKey; import io.linuxserver.fleet.v2.key.RepositoryKey; import io.linuxserver.fleet.v2.types.Image; import io.linuxserver.fleet.v2.types.Repository; @@ -86,6 +87,10 @@ public class RepositoryManager { return repositoryCache.findImage(imageKey); } + public final Image lookupImage(final ImageLookupKey imageLookupKey) { + return repositoryCache.lookupImage(imageLookupKey); + } + public final Repository getRepository(final RepositoryKey repositoryKey) { return repositoryCache.findItem(repositoryKey); } diff --git a/src/main/java/io/linuxserver/fleet/v2/types/Image.java b/src/main/java/io/linuxserver/fleet/v2/types/Image.java index 4b646e9..598a3f4 100644 --- a/src/main/java/io/linuxserver/fleet/v2/types/Image.java +++ b/src/main/java/io/linuxserver/fleet/v2/types/Image.java @@ -23,6 +23,7 @@ import io.linuxserver.fleet.v2.key.RepositoryKey; import io.linuxserver.fleet.v2.types.meta.ItemSyncSpec; import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.List; import java.util.Set; @@ -74,6 +75,10 @@ public class Image extends AbstractSyncItem { return cloned; } + public final String getFullName() { + return getRepositoryName() + "/" + getName(); + } + public final RepositoryKey getRepositoryKey() { return getKey().getRepositoryKey(); } @@ -94,6 +99,12 @@ public class Image extends AbstractSyncItem { return parseDateTime(lastUpdated); } + public final String getLastUpdatedAsString() { + + final LocalDateTime lastUpdated = parseDateTime(this.lastUpdated); + return null == lastUpdated ? null : DateTimeFormatter.ISO_DATE_TIME.format(lastUpdated); + } + public final List getTagBranches() { return new ArrayList<>(tagBranches); } diff --git a/src/main/java/io/linuxserver/fleet/v2/types/docker/DockerImage.java b/src/main/java/io/linuxserver/fleet/v2/types/docker/DockerImage.java index ee34289..5ed4d21 100644 --- a/src/main/java/io/linuxserver/fleet/v2/types/docker/DockerImage.java +++ b/src/main/java/io/linuxserver/fleet/v2/types/docker/DockerImage.java @@ -44,27 +44,27 @@ public class DockerImage { this.buildDate = buildDate; } - public String getName() { + public final String getName() { return name; } - public String getRepository() { + public final String getRepository() { return repository; } - public String getDescription() { + public final String getDescription() { return description; } - public int getStarCount() { + public final int getStarCount() { return starCount; } - public long getPullCount() { + public final long getPullCount() { return pullCount; } - public LocalDateTime getBuildDate() { + public final LocalDateTime getBuildDate() { return buildDate; } } diff --git a/src/main/java/io/linuxserver/fleet/v2/web/Locations.java b/src/main/java/io/linuxserver/fleet/v2/web/Locations.java index c5b414d..cbe3e22 100644 --- a/src/main/java/io/linuxserver/fleet/v2/web/Locations.java +++ b/src/main/java/io/linuxserver/fleet/v2/web/Locations.java @@ -34,7 +34,7 @@ public interface Locations { // All pages String Home = "/"; String Login = "/login"; - String Image = "/image/:imageKey"; + String Image = "/image"; // Api endpoints String ApiImages = "/api/v1/images"; diff --git a/src/main/java/io/linuxserver/fleet/v2/web/WebRouteController.java b/src/main/java/io/linuxserver/fleet/v2/web/WebRouteController.java index 8889914..f1c82ab 100644 --- a/src/main/java/io/linuxserver/fleet/v2/web/WebRouteController.java +++ b/src/main/java/io/linuxserver/fleet/v2/web/WebRouteController.java @@ -22,6 +22,7 @@ import io.linuxserver.fleet.core.FleetAppController; import io.linuxserver.fleet.core.config.WebConfiguration; import io.linuxserver.fleet.v2.web.routes.DefaultAccessManager; import io.linuxserver.fleet.v2.web.routes.HomeController; +import io.linuxserver.fleet.v2.web.routes.ImageController; import io.linuxserver.fleet.v2.web.routes.LoginController; public class WebRouteController { @@ -46,6 +47,7 @@ public class WebRouteController { webInstance.get(Locations.Login, new LoginController()); webInstance.get(Locations.Home, new HomeController(app.getRepositoryManager())); + webInstance.get(Locations.Image, new ImageController(app.getRepositoryManager())); }); } diff --git a/src/main/resources/static/assets/css/app.css b/src/main/resources/static/assets/css/app.css index df5537e..1bdb5aa 100644 --- a/src/main/resources/static/assets/css/app.css +++ b/src/main/resources/static/assets/css/app.css @@ -1,5 +1,5 @@ -body.has-context-home { - background-color: #eaeaea; +body { + font-size: 0.8rem; } .card { @@ -154,4 +154,8 @@ input:checked + .slider:before { .slider.round:before { border-radius: 50%; +} + +table tbody th.is-half { + width: 50%; } \ No newline at end of file diff --git a/src/main/resources/views/prebuilt/image-list-item.ftl b/src/main/resources/views/prebuilt/image-list-item.ftl index 5b10283..57c0cd4 100644 --- a/src/main/resources/views/prebuilt/image-list-item.ftl +++ b/src/main/resources/views/prebuilt/image-list-item.ftl @@ -30,8 +30,10 @@
-

- ${image.repositoryKey.name}/${image.name} +

+ + ${image.repositoryKey.name}/${image.name} +

${image.description!""}