Started implementing design for docker api requests.

Display page for image details.
This commit is contained in:
Josh Stark 2019-12-14 15:27:25 +00:00
parent 0fb61d05ef
commit e0c9317225
21 changed files with 111 additions and 34 deletions

View File

@ -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;

View File

@ -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.*;

View File

@ -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<RepositoryKey, Repository> {
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())) {

View File

@ -15,7 +15,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package io.linuxserver.fleet.rest;
package io.linuxserver.fleet.v2.client.rest;
public class HttpException extends RuntimeException {

View File

@ -15,11 +15,11 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
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);

View File

@ -15,9 +15,9 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
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<T> {

View File

@ -15,7 +15,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
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;

View File

@ -1,4 +1,4 @@
package io.linuxserver.fleet.rest.marshalling;
package io.linuxserver.fleet.v2.client.rest.marshalling;
import java.io.IOException;

View File

@ -15,10 +15,10 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
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;

View File

@ -15,7 +15,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package io.linuxserver.fleet.rest.proxy;
package io.linuxserver.fleet.v2.client.rest.proxy;
public interface PayloadProxy<T> {

View File

@ -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(?)}";

View File

@ -17,7 +17,7 @@
package io.linuxserver.fleet.v2.key;
public class AbstractLookupKey implements Key {
public abstract class AbstractLookupKey<TYPE extends HasKey<?>> 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);
}

View File

@ -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);
}
}

View File

@ -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<Image> {
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);
}
}

View File

@ -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);
}

View File

@ -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<ImageKey, Image> {
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<ImageKey, Image> {
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<TagBranch> getTagBranches() {
return new ArrayList<>(tagBranches);
}

View File

@ -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;
}
}

View File

@ -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";

View File

@ -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()));
});
}

View File

@ -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%;
}

View File

@ -30,8 +30,10 @@
<div class="media-content">
<div class="content">
<h4 class="title is-5">
<span class="has-text-weight-light">${image.repositoryKey.name}/</span><span class="has-text-weight-500">${image.name}</span>
<h4 class="title is-6">
<a class="has-text-grey-dark" href="/image?name=${image.fullName}">
<span class="has-text-weight-light">${image.repositoryKey.name}/</span><span class="has-text-weight-500">${image.name}</span>
</a>
</h4>
${image.description!""}