Full Fix to getRegisteredApps

Change-Id: I63efb375af941cebcbd858b9b8f03524a72f0562
This commit is contained in:
Arnav Jain 2019-07-09 14:24:10 -07:00
parent fb9926708e
commit efb57e5f99
7 changed files with 182 additions and 43 deletions

View File

@ -62,16 +62,23 @@ public class ApplicationsListCommand extends AbstractShellCommand {
private boolean sortByName = false; private boolean sortByName = false;
@Option(name = "-r", aliases = "--regapps", description = "Get Registered Apps for Runtime Version")
private boolean getRegisteredApps = false;
@Override @Override
protected void doExecute() { protected void doExecute() {
ApplicationService service = get(ApplicationService.class); ApplicationService service = get(ApplicationService.class);
List<Application> apps = newArrayList(service.getApplications()); List<Application> apps;
if (getRegisteredApps) {
apps = newArrayList(service.getRegisteredApplications());
} else {
apps = newArrayList(service.getApplications());
}
if (sortByName) { if (sortByName) {
apps.sort(Comparator.comparing(app -> app.id().name())); apps.sort(Comparator.comparing(app -> app.id().name()));
} else { } else {
Collections.sort(apps, Comparators.APP_COMPARATOR); Collections.sort(apps, Comparators.APP_COMPARATOR);
} }
if (outputJson()) { if (outputJson()) {
print("%s", json(service, apps)); print("%s", json(service, apps));
} else { } else {

View File

@ -21,6 +21,7 @@ import java.net.URI;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.Set; import java.util.Set;
import java.net.URL;
/** /**
* Abstraction of a network control/management application. * Abstraction of a network control/management application.
@ -132,4 +133,11 @@ public interface Application {
* @return list of application names * @return list of application names
*/ */
List<String> requiredApps(); List<String> requiredApps();
}
/**
* Returns binary image URL.
*
* @return URL of binary image
*/
URL imageUrl();
}

View File

@ -26,6 +26,7 @@ import java.util.Set;
import java.util.Optional; import java.util.Optional;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
import java.net.URL;
import static com.google.common.base.MoreObjects.toStringHelper; import static com.google.common.base.MoreObjects.toStringHelper;
import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkArgument;
@ -50,7 +51,7 @@ public final class DefaultApplication implements Application {
private final Optional<URI> featuresRepo; private final Optional<URI> featuresRepo;
private final List<String> features; private final List<String> features;
private final List<String> requiredApps; private final List<String> requiredApps;
private final URL imageUrl;
/** /**
* Default constructor is hidden to prevent calls to new. * Default constructor is hidden to prevent calls to new.
*/ */
@ -69,6 +70,7 @@ public final class DefaultApplication implements Application {
featuresRepo = Optional.empty(); featuresRepo = Optional.empty();
features = ImmutableList.of(); features = ImmutableList.of();
requiredApps = ImmutableList.of(); requiredApps = ImmutableList.of();
imageUrl = null;
} }
/** /**
@ -88,13 +90,14 @@ public final class DefaultApplication implements Application {
* @param featuresRepo optional features repo URI * @param featuresRepo optional features repo URI
* @param features application features * @param features application features
* @param requiredApps list of required application names * @param requiredApps list of required application names
* @param imageUrl url of oar file
*/ */
private DefaultApplication(ApplicationId appId, Version version, String title, public DefaultApplication(ApplicationId appId, Version version, String title,
String description, String origin, String category, String description, String origin, String category,
String url, String readme, byte[] icon, String url, String readme, byte[] icon,
ApplicationRole role, Set<Permission> permissions, ApplicationRole role, Set<Permission> permissions,
Optional<URI> featuresRepo, List<String> features, Optional<URI> featuresRepo, List<String> features,
List<String> requiredApps) { List<String> requiredApps, URL imageUrl) {
this.appId = appId; this.appId = appId;
this.version = version; this.version = version;
this.title = title; this.title = title;
@ -109,8 +112,8 @@ public final class DefaultApplication implements Application {
this.featuresRepo = featuresRepo; this.featuresRepo = featuresRepo;
this.features = ImmutableList.copyOf(features); this.features = ImmutableList.copyOf(features);
this.requiredApps = ImmutableList.copyOf(requiredApps); this.requiredApps = ImmutableList.copyOf(requiredApps);
this.imageUrl = imageUrl;
} }
@Override @Override
public ApplicationId id() { public ApplicationId id() {
return appId; return appId;
@ -181,6 +184,11 @@ public final class DefaultApplication implements Application {
return requiredApps; return requiredApps;
} }
@Override
public URL imageUrl() {
return imageUrl;
}
@Override @Override
public int hashCode() { public int hashCode() {
return Objects.hash(appId, version, title, description, origin, category, url, return Objects.hash(appId, version, title, description, origin, category, url,
@ -230,6 +238,7 @@ public final class DefaultApplication implements Application {
.add("featuresRepo", featuresRepo) .add("featuresRepo", featuresRepo)
.add("features", features) .add("features", features)
.add("requiredApps", requiredApps) .add("requiredApps", requiredApps)
.add("imageURL", imageUrl)
.toString(); .toString();
} }
@ -277,7 +286,6 @@ public final class DefaultApplication implements Application {
* Default application builder. * Default application builder.
*/ */
public static final class Builder { public static final class Builder {
private ApplicationId appId; private ApplicationId appId;
private Version version; private Version version;
private String title; private String title;
@ -285,13 +293,14 @@ public final class DefaultApplication implements Application {
private String category; private String category;
private String url; private String url;
private String readme; private String readme;
private byte[] icon; private byte[] icon = new byte[0];
private String origin; private String origin;
private ApplicationRole role; private ApplicationRole role = ApplicationRole.ADMIN;
private Set<Permission> permissions; private Set<Permission> permissions = ImmutableSet.of();
private Optional<URI> featuresRepo; private Optional<URI> featuresRepo = Optional.empty();
private List<String> features; private List<String> features = ImmutableList.of();
private List<String> requiredApps; private List<String> requiredApps = ImmutableList.of();
private URL imageUrl;
/** /**
* Default constructor for the builder. * Default constructor for the builder.
@ -517,6 +526,17 @@ public final class DefaultApplication implements Application {
return this; return this;
} }
/**
* Adds a Binary Image URL.
*
* @param imageUrl url of oar file
* @return builder
*/
public Builder withImageUrl(URL imageUrl) {
this.imageUrl = imageUrl;
return this;
}
/** /**
* Builds a default application object from the gathered parameters. * Builds a default application object from the gathered parameters.
* *
@ -542,7 +562,7 @@ public final class DefaultApplication implements Application {
url, readme, icon, url, readme, icon,
role, permissions, role, permissions,
featuresRepo, features, featuresRepo, features,
requiredApps); requiredApps, imageUrl);
} }
} }
} }

View File

@ -49,20 +49,20 @@ public class DefaultApplicationTest {
public static final ApplicationId APP_ID = new DefaultApplicationId(2, APP_NAME); public static final ApplicationId APP_ID = new DefaultApplicationId(2, APP_NAME);
private Builder baseBuilder = DefaultApplication.builder() private Builder baseBuilder = DefaultApplication.builder()
.withAppId(APP_ID) .withAppId(APP_ID)
.withVersion(VER) .withVersion(VER)
.withTitle(TITLE) .withTitle(TITLE)
.withDescription(DESC) .withDescription(DESC)
.withOrigin(ORIGIN) .withOrigin(ORIGIN)
.withCategory(CATEGORY) .withCategory(CATEGORY)
.withUrl(URL) .withUrl(URL)
.withReadme(README) .withReadme(README)
.withIcon(ICON) .withIcon(ICON)
.withRole(ROLE) .withRole(ROLE)
.withPermissions(PERMS) .withPermissions(PERMS)
.withFeaturesRepo(Optional.of(FURL)) .withFeaturesRepo(Optional.of(FURL))
.withFeatures(FEATURES) .withFeatures(FEATURES)
.withRequiredApps(APPS); .withRequiredApps(APPS);
@Test @Test
public void basics() { public void basics() {
@ -77,8 +77,8 @@ public class DefaultApplicationTest {
assertEquals("incorrect URL", URL, app.url()); assertEquals("incorrect URL", URL, app.url());
assertEquals("incorrect readme", README, app.readme()); assertEquals("incorrect readme", README, app.readme());
assertArrayEquals("incorrect icon", ICON, app.icon()); assertArrayEquals("incorrect icon", ICON, app.icon());
assertEquals("incorrect role", ROLE, app.role());
assertEquals("incorrect permissions", PERMS, app.permissions()); assertEquals("incorrect permissions", PERMS, app.permissions());
assertEquals("incorrect role", ROLE, app.role());
assertEquals("incorrect features repo", FURL, app.featuresRepo().get()); assertEquals("incorrect features repo", FURL, app.featuresRepo().get());
assertEquals("incorrect features", FEATURES, app.features()); assertEquals("incorrect features", FEATURES, app.features());
assertEquals("incorrect apps", APPS, app.requiredApps()); assertEquals("incorrect apps", APPS, app.requiredApps());
@ -88,7 +88,7 @@ public class DefaultApplicationTest {
@Test @Test
public void testEquality() { public void testEquality() {
Application a1 = baseBuilder.build(); Application a1 = baseBuilder.build();
Application a2 = DefaultApplication.builder(a1) Application a2 = DefaultApplication.builder(a1)
.build(); .build();
Application a3 = DefaultApplication.builder(baseBuilder) Application a3 = DefaultApplication.builder(baseBuilder)
.withFeaturesRepo(Optional.empty()) .withFeaturesRepo(Optional.empty())
@ -227,4 +227,4 @@ public class DefaultApplicationTest {
assertNotNull("null icon", icon); assertNotNull("null icon", icon);
assertEquals("unexpected size", 0, icon.length); assertEquals("unexpected size", 0, icon.length);
} }
} }

View File

@ -15,9 +15,15 @@
*/ */
package org.onosproject.app.impl; package org.onosproject.app.impl;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.common.cache.Cache; import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheBuilder;
import com.google.common.collect.HashMultimap; import com.google.common.collect.HashMultimap;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Multimap; import com.google.common.collect.Multimap;
import com.google.common.util.concurrent.Uninterruptibles; import com.google.common.util.concurrent.Uninterruptibles;
import org.apache.karaf.features.Feature; import org.apache.karaf.features.Feature;
@ -31,6 +37,10 @@ import org.onosproject.app.ApplicationStore;
import org.onosproject.app.ApplicationStoreDelegate; import org.onosproject.app.ApplicationStoreDelegate;
import org.onosproject.core.Application; import org.onosproject.core.Application;
import org.onosproject.core.ApplicationId; import org.onosproject.core.ApplicationId;
import org.onosproject.core.DefaultApplication;
import org.onosproject.core.DefaultApplicationId;
import org.onosproject.core.Version;
import org.onosproject.core.VersionService;
import org.onosproject.event.AbstractListenerManager; import org.onosproject.event.AbstractListenerManager;
import org.onosproject.security.Permission; import org.onosproject.security.Permission;
import org.onosproject.security.SecurityUtil; import org.onosproject.security.SecurityUtil;
@ -41,17 +51,19 @@ import org.osgi.service.component.annotations.Reference;
import org.osgi.service.component.annotations.ReferenceCardinality; import org.osgi.service.component.annotations.ReferenceCardinality;
import org.slf4j.Logger; import org.slf4j.Logger;
import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Iterator;
import java.util.Set; import java.util.Set;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.function.Consumer; import java.util.function.Consumer;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import static org.onosproject.app.ApplicationEvent.Type.APP_ACTIVATED; import static org.onosproject.app.ApplicationEvent.Type.*;
import static org.onosproject.app.ApplicationEvent.Type.APP_DEACTIVATED;
import static org.onosproject.app.ApplicationEvent.Type.APP_INSTALLED;
import static org.onosproject.app.ApplicationEvent.Type.APP_UNINSTALLED;
import static org.onosproject.security.AppGuard.checkPermission; import static org.onosproject.security.AppGuard.checkPermission;
import static org.onosproject.security.AppPermission.Type.APP_READ; import static org.onosproject.security.AppPermission.Type.APP_READ;
import static org.slf4j.LoggerFactory.getLogger; import static org.slf4j.LoggerFactory.getLogger;
@ -66,9 +78,10 @@ public class ApplicationManager
private final Logger log = getLogger(getClass()); private final Logger log = getLogger(getClass());
private static final String APP_REGISTRY_URL = "http://api.onosproject.org:8080/api/applications";
private static final String APP_ID_NULL = "Application ID cannot be null"; private static final String APP_ID_NULL = "Application ID cannot be null";
private static final long DEFAULT_OPERATION_TIMEOUT_MILLIS = 2000; private static final long DEFAULT_OPERATION_TIMEOUT_MILLIS = 2000;
private final ApplicationStoreDelegate delegate = new InternalStoreDelegate(); private final ApplicationStoreDelegate delegate = new InternalStoreDelegate();
@Reference(cardinality = ReferenceCardinality.MANDATORY) @Reference(cardinality = ReferenceCardinality.MANDATORY)
@ -77,12 +90,15 @@ public class ApplicationManager
@Reference(cardinality = ReferenceCardinality.MANDATORY) @Reference(cardinality = ReferenceCardinality.MANDATORY)
protected FeaturesService featuresService; protected FeaturesService featuresService;
@Reference(cardinality = ReferenceCardinality.MANDATORY)
protected VersionService versionService;
// Application supplied hooks for pre-activation processing. // Application supplied hooks for pre-activation processing.
private final Multimap<String, Runnable> deactivateHooks = HashMultimap.create(); private final Multimap<String, Runnable> deactivateHooks = HashMultimap.create();
private final Cache<ApplicationId, CountDownLatch> pendingOperations = private final Cache<ApplicationId, CountDownLatch> pendingOperations =
CacheBuilder.newBuilder() CacheBuilder.newBuilder()
.expireAfterWrite(DEFAULT_OPERATION_TIMEOUT_MILLIS * 2, TimeUnit.MILLISECONDS) .expireAfterWrite(DEFAULT_OPERATION_TIMEOUT_MILLIS * 2, TimeUnit.MILLISECONDS)
.build(); .build();
@Activate @Activate
public void activate() { public void activate() {
@ -303,7 +319,8 @@ public class ApplicationManager
} }
// Invokes the specified function, if not null. // Invokes the specified function, if not null.
@java.lang.SuppressWarnings("squid:S1217") // We really do mean to call run() @java.lang.SuppressWarnings("squid:S1217")
// We really do mean to call run()
private void invokeHook(Runnable hook, ApplicationId appId) { private void invokeHook(Runnable hook, ApplicationId appId) {
if (hook != null) { if (hook != null) {
try { try {
@ -315,4 +332,68 @@ public class ApplicationManager
} }
} }
} @Override
public Set<Application> getRegisteredApplications() {
ImmutableSet.Builder<Application> builder = ImmutableSet.builder();
ObjectMapper mapper = new ObjectMapper();
// Get input stream from the URL
try {
URL githubUrl = new URL(APP_REGISTRY_URL + "?onosVersion=" + versionService.version().toString());
HttpURLConnection githubHttp = (HttpURLConnection) githubUrl.openConnection();
InputStream githubStream = githubHttp.getInputStream();
// Read input stream into an ArrayNode
ArrayNode rootTree = (ArrayNode) mapper.readTree(githubStream);
// Iterate over the array node for each object add each version as application object to the set
rootTree.forEach(n -> {
mapObject(builder, (ObjectNode) n);
});
//Iterate through Builder to remove unnecessary apps
Set<Application> apps = builder.build();
return apps;
} catch (MalformedURLException e) {
throw new IllegalStateException("Bad URL " + APP_REGISTRY_URL, e);
} catch (IOException e) {
throw new IllegalStateException("Unable to fetch URL " + APP_REGISTRY_URL, e);
}
}
private void mapObject(ImmutableSet.Builder<Application> apps, ObjectNode node) {
String appIDs = node.get("id").asText();
ApplicationId appID = new DefaultApplicationId(1, appIDs);
String title = node.get("title").asText();
String readme = node.get("readme").asText();
String category = node.get("category").asText();
String url = node.get("url").asText();
String origin = node.get("maintainer").asText();
JsonNode it = node.get("versions");
Iterator iterate = it.iterator();
while (iterate.hasNext()) {
DefaultApplication.Builder app = new DefaultApplication.Builder();
JsonNode jsonNode = (JsonNode) iterate.next();
URL imageUrl = null;
try {
imageUrl = new URL(jsonNode.get("oarURL").asText());
} catch (MalformedURLException e) {
e.printStackTrace();
}
Version version1 = Version.version(jsonNode.get("onosVersion").asText());
app.withImageUrl(imageUrl)
.withAppId(new DefaultApplicationId(1, node.get("id").asText()))
.withVersion(version1)
.withAppId(appID)
.withReadme(readme)
.withDescription(readme)
.withTitle(title)
.withFeatures(ImmutableList.of("none"))
.withCategory(category)
.withUrl(url)
.withOrigin(origin);
apps.add(app.build());
}
}
}

View File

@ -29,6 +29,8 @@ import org.onosproject.core.Application;
import org.onosproject.core.ApplicationId; import org.onosproject.core.ApplicationId;
import org.onosproject.core.DefaultApplication; import org.onosproject.core.DefaultApplication;
import org.onosproject.core.DefaultApplicationId; import org.onosproject.core.DefaultApplicationId;
import org.onosproject.core.Version;
import org.onosproject.core.VersionServiceAdapter;
import java.io.InputStream; import java.io.InputStream;
import java.net.URI; import java.net.URI;
@ -49,10 +51,13 @@ import static org.onosproject.net.NetTestTools.injectEventDispatcher;
public class ApplicationManagerTest { public class ApplicationManagerTest {
public static final DefaultApplicationId APP_ID = new DefaultApplicationId(1, APP_NAME); public static final DefaultApplicationId APP_ID = new DefaultApplicationId(1, APP_NAME);
private static final Version CORE_VERSION = Version.version(2, 1, "0", "");
private ApplicationManager mgr = new ApplicationManager(); private ApplicationManager mgr = new ApplicationManager();
private ApplicationListener listener = new TestListener(); private ApplicationListener listener = new TestListener();
private boolean deactivated = false; private boolean deactivated = false;
@Before @Before
@ -80,6 +85,22 @@ public class ApplicationManagerTest {
assertEquals("incorrect features", FEATURES, app.features()); assertEquals("incorrect features", FEATURES, app.features());
} }
@Test
public void testGetRegisteredApps() {
mgr.versionService = new TestVersionService();
Set<Application> apps = mgr.getRegisteredApplications();
System.out.println(apps);
assertFalse("SET contains less Apps than it should", apps.size() < 158);
}
private static class TestVersionService extends VersionServiceAdapter {
@Override
public Version version() {
return CORE_VERSION;
}
}
@Test @Test
public void install() { public void install() {
InputStream stream = ApplicationArchive.class.getResourceAsStream("app.zip"); InputStream stream = ApplicationArchive.class.getResourceAsStream("app.zip");
@ -223,4 +244,4 @@ public class ApplicationManagerTest {
} }
} }
} }

View File

@ -294,6 +294,7 @@ import org.onosproject.upgrade.Upgrade;
import java.lang.invoke.SerializedLambda; import java.lang.invoke.SerializedLambda;
import java.net.URI; import java.net.URI;
import java.net.URL;
import java.time.Duration; import java.time.Duration;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
@ -433,6 +434,7 @@ public final class KryoNamespaces {
.register(MISC) .register(MISC)
.nextId(KryoNamespace.INITIAL_ID + BASIC_MAX_SIZE + MISC_MAX_SIZE) .nextId(KryoNamespace.INITIAL_ID + BASIC_MAX_SIZE + MISC_MAX_SIZE)
.register( .register(
URL.class,
Instructions.MeterInstruction.class, Instructions.MeterInstruction.class,
Instructions.StatTriggerInstruction.class, Instructions.StatTriggerInstruction.class,
StatTriggerFlag.class, StatTriggerFlag.class,