Thomas Vachuska
Committed by Gerrit Code Review

ONOS-3725 Adding ability to retain pending configs.

This allows up-load of configurations before their backing classes are registered by apps/subsystems.

 Validation and delegation of network config change events is deferred until the class registration.

Change-Id: Ifc9c97fbc86e764cb03cecb1f73f7191de3e7754
...@@ -135,6 +135,28 @@ public interface NetworkConfigService ...@@ -135,6 +135,28 @@ public interface NetworkConfigService
135 JsonNode json); 135 JsonNode json);
136 136
137 /** 137 /**
138 + * Applies configuration for the specified subject and configuration
139 + * key using the raw JSON object. If configuration already exists, it
140 + * will be updated. If the specified configuration key does not yet have
141 + * a registered class associated with it, the configuration will be pending
142 + * and null value will be returned. Once the backing configuration class is
143 + * registered, the configuration will be validated and accepted.
144 + *
145 + * @param subjectClassKey subject class key
146 + * @param subject configuration subject
147 + * @param configKey configuration class key
148 + * @param json raw JSON node containing the configuration data
149 + * @param <S> type of subject
150 + * @param <C> type of configuration
151 + * @return configuration object or null if configuration key does not have
152 + * a registered class yet
153 + * @throws IllegalArgumentException if the supplied JSON node contains
154 + * invalid data
155 + */
156 + <S, C extends Config<S>> C applyConfig(String subjectClassKey, S subject,
157 + String configKey, JsonNode json);
158 +
159 + /**
138 * Clears any configuration for the specified subject and configuration 160 * Clears any configuration for the specified subject and configuration
139 * class. If one does not exist, this call has no effect. 161 * class. If one does not exist, this call has no effect.
140 * 162 *
...@@ -145,4 +167,13 @@ public interface NetworkConfigService ...@@ -145,4 +167,13 @@ public interface NetworkConfigService
145 */ 167 */
146 <S, C extends Config<S>> void removeConfig(S subject, Class<C> configClass); 168 <S, C extends Config<S>> void removeConfig(S subject, Class<C> configClass);
147 169
170 + /**
171 + * Clears any configuration for the specified subject and configuration
172 + * key. If one does not exist, this call has no effect.
173 + *
174 + * @param subject configuration subject
175 + * @param configKey configuration key
176 + * @param <S> type of subject
177 + */
178 + <S> void removeConfig(String subjectClassKey, S subject, String configKey);
148 } 179 }
......
...@@ -129,4 +129,26 @@ public interface NetworkConfigStore extends Store<NetworkConfigEvent, NetworkCon ...@@ -129,4 +129,26 @@ public interface NetworkConfigStore extends Store<NetworkConfigEvent, NetworkCon
129 */ 129 */
130 <S, C extends Config<S>> void clearConfig(S subject, Class<C> configClass); 130 <S, C extends Config<S>> void clearConfig(S subject, Class<C> configClass);
131 131
132 + /**
133 + * Queues pending configuration for the specified subject and configuration
134 + * class using the raw JSON object.
135 + *
136 + * @param subject configuration subject
137 + * @param configKey configuration key
138 + * @param json raw JSON node containing the configuration data
139 + * @param <S> type of subject
140 + * @throws IllegalArgumentException if the supplied JSON node contains
141 + * invalid data
142 + */
143 + <S> void queueConfig(S subject, String configKey, JsonNode json);
144 +
145 + /**
146 + * Clears the configuration of the given class for the specified subject.
147 + *
148 + * @param subject configuration subject
149 + * @param configKey configuration key
150 + * @param <S> type of subject
151 + */
152 + <S> void clearQueuedConfig(S subject, String configKey);
153 +
132 } 154 }
......
...@@ -74,17 +74,24 @@ public class NetworkConfigServiceAdapter implements NetworkConfigService { ...@@ -74,17 +74,24 @@ public class NetworkConfigServiceAdapter implements NetworkConfigService {
74 } 74 }
75 75
76 @Override 76 @Override
77 + public <S, C extends Config<S>> C applyConfig(String subjectClassKey, S subject, String configKey, JsonNode json) {
78 + return null;
79 + }
80 +
81 + @Override
77 public <S, C extends Config<S>> void removeConfig(S subject, Class<C> configClass) { 82 public <S, C extends Config<S>> void removeConfig(S subject, Class<C> configClass) {
78 83
79 } 84 }
80 85
81 @Override 86 @Override
82 - public void addListener(NetworkConfigListener listener) { 87 + public <S> void removeConfig(String subjectClassKey, S subject, String configKey) {
88 + }
83 89
90 + @Override
91 + public void addListener(NetworkConfigListener listener) {
84 } 92 }
85 93
86 @Override 94 @Override
87 public void removeListener(NetworkConfigListener listener) { 95 public void removeListener(NetworkConfigListener listener) {
88 -
89 } 96 }
90 } 97 }
......
...@@ -56,8 +56,11 @@ public class NetworkConfigManager ...@@ -56,8 +56,11 @@ public class NetworkConfigManager
56 56
57 private static final String NULL_FACTORY_MSG = "Factory cannot be null"; 57 private static final String NULL_FACTORY_MSG = "Factory cannot be null";
58 private static final String NULL_SCLASS_MSG = "Subject class cannot be null"; 58 private static final String NULL_SCLASS_MSG = "Subject class cannot be null";
59 + private static final String NULL_SKEY_MSG = "Subject key cannot be null";
59 private static final String NULL_CCLASS_MSG = "Config class cannot be null"; 60 private static final String NULL_CCLASS_MSG = "Config class cannot be null";
61 + private static final String NULL_CKEY_MSG = "Config key cannot be null";
60 private static final String NULL_SUBJECT_MSG = "Subject cannot be null"; 62 private static final String NULL_SUBJECT_MSG = "Subject cannot be null";
63 + private static final String NULL_JSON_MSG = "JSON cannot be null";
61 64
62 // Inventory of configuration factories 65 // Inventory of configuration factories
63 private final Map<ConfigKey, ConfigFactory> factories = Maps.newConcurrentMap(); 66 private final Map<ConfigKey, ConfigFactory> factories = Maps.newConcurrentMap();
...@@ -156,6 +159,8 @@ public class NetworkConfigManager ...@@ -156,6 +159,8 @@ public class NetworkConfigManager
156 159
157 @Override 160 @Override
158 public Class<? extends Config> getConfigClass(String subjectClassKey, String configKey) { 161 public Class<? extends Config> getConfigClass(String subjectClassKey, String configKey) {
162 + checkNotNull(subjectClassKey, NULL_SKEY_MSG);
163 + checkNotNull(configKey, NULL_CKEY_MSG);
159 return configClasses.get(new ConfigIdentifier(subjectClassKey, configKey)); 164 return configClasses.get(new ConfigIdentifier(subjectClassKey, configKey));
160 } 165 }
161 166
...@@ -182,7 +187,7 @@ public class NetworkConfigManager ...@@ -182,7 +187,7 @@ public class NetworkConfigManager
182 } 187 }
183 188
184 @Override 189 @Override
185 - public <S, T extends Config<S>> T getConfig(S subject, Class<T> configClass) { 190 + public <S, C extends Config<S>> C getConfig(S subject, Class<C> configClass) {
186 checkNotNull(subject, NULL_SUBJECT_MSG); 191 checkNotNull(subject, NULL_SUBJECT_MSG);
187 checkNotNull(configClass, NULL_CCLASS_MSG); 192 checkNotNull(configClass, NULL_CCLASS_MSG);
188 return store.getConfig(subject, configClass); 193 return store.getConfig(subject, configClass);
...@@ -200,16 +205,47 @@ public class NetworkConfigManager ...@@ -200,16 +205,47 @@ public class NetworkConfigManager
200 public <S, C extends Config<S>> C applyConfig(S subject, Class<C> configClass, JsonNode json) { 205 public <S, C extends Config<S>> C applyConfig(S subject, Class<C> configClass, JsonNode json) {
201 checkNotNull(subject, NULL_SUBJECT_MSG); 206 checkNotNull(subject, NULL_SUBJECT_MSG);
202 checkNotNull(configClass, NULL_CCLASS_MSG); 207 checkNotNull(configClass, NULL_CCLASS_MSG);
208 + checkNotNull(subject, NULL_JSON_MSG);
203 return store.applyConfig(subject, configClass, json); 209 return store.applyConfig(subject, configClass, json);
204 } 210 }
205 211
206 @Override 212 @Override
213 + @SuppressWarnings("unchecked")
214 + public <S, C extends Config<S>> C applyConfig(String subjectClassKey, S subject,
215 + String configKey, JsonNode json) {
216 + checkNotNull(subjectClassKey, NULL_SKEY_MSG);
217 + checkNotNull(subject, NULL_SUBJECT_MSG);
218 + checkNotNull(configKey, NULL_CKEY_MSG);
219 + checkNotNull(subject, NULL_JSON_MSG);
220 + Class<? extends Config> configClass = configClasses.get(new ConfigIdentifier(subjectClassKey, configKey));
221 + if (configClass != null) {
222 + return store.applyConfig(subject, (Class<C>) configClass, json);
223 + } else {
224 + store.queueConfig(subject, configKey, json);
225 + return null;
226 + }
227 + }
228 +
229 + @Override
207 public <S, C extends Config<S>> void removeConfig(S subject, Class<C> configClass) { 230 public <S, C extends Config<S>> void removeConfig(S subject, Class<C> configClass) {
208 checkNotNull(subject, NULL_SUBJECT_MSG); 231 checkNotNull(subject, NULL_SUBJECT_MSG);
209 checkNotNull(configClass, NULL_CCLASS_MSG); 232 checkNotNull(configClass, NULL_CCLASS_MSG);
210 store.clearConfig(subject, configClass); 233 store.clearConfig(subject, configClass);
211 } 234 }
212 235
236 + @Override
237 + public <S> void removeConfig(String subjectClassKey, S subject, String configKey) {
238 + checkNotNull(subjectClassKey, NULL_SKEY_MSG);
239 + checkNotNull(subject, NULL_SUBJECT_MSG);
240 + checkNotNull(configKey, NULL_CCLASS_MSG);
241 + Class<? extends Config> configClass = configClasses.get(new ConfigIdentifier(subjectClassKey, configKey));
242 + if (configClass != null) {
243 + store.clearConfig(subject, configClass);
244 + } else {
245 + store.clearQueuedConfig(subject, configKey);
246 + }
247 + }
248 +
213 // Auxiliary store delegate to receive notification about changes in 249 // Auxiliary store delegate to receive notification about changes in
214 // the network configuration store state - by the store itself. 250 // the network configuration store state - by the store itself.
215 private class InternalStoreDelegate implements NetworkConfigStoreDelegate { 251 private class InternalStoreDelegate implements NetworkConfigStoreDelegate {
...@@ -259,17 +295,17 @@ public class NetworkConfigManager ...@@ -259,17 +295,17 @@ public class NetworkConfigManager
259 } 295 }
260 296
261 static final class ConfigIdentifier { 297 static final class ConfigIdentifier {
262 - final String subjectKey; 298 + final String subjectClassKey;
263 final String configKey; 299 final String configKey;
264 300
265 - protected ConfigIdentifier(String subjectKey, String configKey) { 301 + protected ConfigIdentifier(String subjectClassKey, String configKey) {
266 - this.subjectKey = subjectKey; 302 + this.subjectClassKey = subjectClassKey;
267 this.configKey = configKey; 303 this.configKey = configKey;
268 } 304 }
269 305
270 @Override 306 @Override
271 public int hashCode() { 307 public int hashCode() {
272 - return Objects.hash(subjectKey, configKey); 308 + return Objects.hash(subjectClassKey, configKey);
273 } 309 }
274 310
275 @Override 311 @Override
...@@ -279,10 +315,11 @@ public class NetworkConfigManager ...@@ -279,10 +315,11 @@ public class NetworkConfigManager
279 } 315 }
280 if (obj instanceof ConfigIdentifier) { 316 if (obj instanceof ConfigIdentifier) {
281 final ConfigIdentifier other = (ConfigIdentifier) obj; 317 final ConfigIdentifier other = (ConfigIdentifier) obj;
282 - return Objects.equals(this.subjectKey, other.subjectKey) 318 + return Objects.equals(this.subjectClassKey, other.subjectClassKey)
283 && Objects.equals(this.configKey, other.configKey); 319 && Objects.equals(this.configKey, other.configKey);
284 } 320 }
285 return false; 321 return false;
286 } 322 }
287 } 323 }
324 +
288 } 325 }
......
...@@ -29,7 +29,7 @@ import com.fasterxml.jackson.databind.node.ShortNode; ...@@ -29,7 +29,7 @@ import com.fasterxml.jackson.databind.node.ShortNode;
29 import com.fasterxml.jackson.databind.node.TextNode; 29 import com.fasterxml.jackson.databind.node.TextNode;
30 import com.google.common.collect.ImmutableSet; 30 import com.google.common.collect.ImmutableSet;
31 import com.google.common.collect.Maps; 31 import com.google.common.collect.Maps;
32 - 32 +import com.google.common.collect.Sets;
33 import org.apache.felix.scr.annotations.Activate; 33 import org.apache.felix.scr.annotations.Activate;
34 import org.apache.felix.scr.annotations.Component; 34 import org.apache.felix.scr.annotations.Component;
35 import org.apache.felix.scr.annotations.Deactivate; 35 import org.apache.felix.scr.annotations.Deactivate;
...@@ -117,10 +117,35 @@ public class DistributedNetworkConfigStore ...@@ -117,10 +117,35 @@ public class DistributedNetworkConfigStore
117 @Override 117 @Override
118 public void addConfigFactory(ConfigFactory configFactory) { 118 public void addConfigFactory(ConfigFactory configFactory) {
119 factoriesByConfig.put(configFactory.configClass().getName(), configFactory); 119 factoriesByConfig.put(configFactory.configClass().getName(), configFactory);
120 + processPendingConfigs(configFactory);
120 notifyDelegate(new NetworkConfigEvent(CONFIG_REGISTERED, configFactory.configKey(), 121 notifyDelegate(new NetworkConfigEvent(CONFIG_REGISTERED, configFactory.configKey(),
121 configFactory.configClass())); 122 configFactory.configClass()));
122 } 123 }
123 124
125 + // Sweep through any pending configurations, validate them and then prune them.
126 + private void processPendingConfigs(ConfigFactory configFactory) {
127 + Set<ConfigKey> toBePruned = Sets.newHashSet();
128 + configs.keySet().forEach(k -> {
129 + if (Objects.equals(k.configKey, configFactory.configKey())) {
130 + validateConfig(k, configFactory, configs.get(k).value());
131 + toBePruned.add(k); // Prune whether valid or not
132 + }
133 + });
134 + toBePruned.forEach(configs::remove);
135 + }
136 +
137 + @SuppressWarnings("unchecked")
138 + private void validateConfig(ConfigKey key, ConfigFactory configFactory, JsonNode json) {
139 + Config config = createConfig(key.subject, configFactory.configClass(), json);
140 + try {
141 + checkArgument(config.isValid(), INVALID_CONFIG_JSON);
142 + configs.putAndGet(key(key.subject, configFactory.configClass()), json);
143 + } catch (Exception e) {
144 + log.warn("Failed to validate pending {} configuration for {}: {}",
145 + key.configKey, configFactory.subjectFactory().subjectKey(key.subject), json);
146 + }
147 + }
148 +
124 @Override 149 @Override
125 public void removeConfigFactory(ConfigFactory configFactory) { 150 public void removeConfigFactory(ConfigFactory configFactory) {
126 factoriesByConfig.remove(configFactory.configClass().getName()); 151 factoriesByConfig.remove(configFactory.configClass().getName());
...@@ -152,7 +177,7 @@ public class DistributedNetworkConfigStore ...@@ -152,7 +177,7 @@ public class DistributedNetworkConfigStore
152 ImmutableSet.Builder<S> builder = ImmutableSet.builder(); 177 ImmutableSet.Builder<S> builder = ImmutableSet.builder();
153 String cName = configClass.getName(); 178 String cName = configClass.getName();
154 configs.keySet().forEach(k -> { 179 configs.keySet().forEach(k -> {
155 - if (subjectClass.isInstance(k.subject) && cName.equals(k.configClass)) { 180 + if (subjectClass.isInstance(k.subject) && Objects.equals(cName, k.configClass)) {
156 builder.add((S) k.subject); 181 builder.add((S) k.subject);
157 } 182 }
158 }); 183 });
...@@ -164,7 +189,7 @@ public class DistributedNetworkConfigStore ...@@ -164,7 +189,7 @@ public class DistributedNetworkConfigStore
164 public <S> Set<Class<? extends Config<S>>> getConfigClasses(S subject) { 189 public <S> Set<Class<? extends Config<S>>> getConfigClasses(S subject) {
165 ImmutableSet.Builder<Class<? extends Config<S>>> builder = ImmutableSet.builder(); 190 ImmutableSet.Builder<Class<? extends Config<S>>> builder = ImmutableSet.builder();
166 configs.keySet().forEach(k -> { 191 configs.keySet().forEach(k -> {
167 - if (Objects.equals(subject, k.subject) && delegate != null) { 192 + if (Objects.equals(subject, k.subject) && k.configClass != null && delegate != null) {
168 builder.add(factoriesByConfig.get(k.configClass).configClass()); 193 builder.add(factoriesByConfig.get(k.configClass).configClass());
169 } 194 }
170 }); 195 });
...@@ -201,8 +226,12 @@ public class DistributedNetworkConfigStore ...@@ -201,8 +226,12 @@ public class DistributedNetworkConfigStore
201 226
202 // Re-create the config if for some reason what we attempted to put 227 // Re-create the config if for some reason what we attempted to put
203 // was supplanted by someone else already. 228 // was supplanted by someone else already.
204 - return versioned.value() == json ? config : 229 + return versioned.value() == json ? config : createConfig(subject, configClass, versioned.value());
205 - createConfig(subject, configClass, versioned.value()); 230 + }
231 +
232 + @Override
233 + public <S> void queueConfig(S subject, String configKey, JsonNode json) {
234 + configs.put(key(subject, configKey), json);
206 } 235 }
207 236
208 @Override 237 @Override
...@@ -210,6 +239,11 @@ public class DistributedNetworkConfigStore ...@@ -210,6 +239,11 @@ public class DistributedNetworkConfigStore
210 configs.remove(key(subject, configClass)); 239 configs.remove(key(subject, configClass));
211 } 240 }
212 241
242 + @Override
243 + public <S> void clearQueuedConfig(S subject, String configKey) {
244 + configs.remove(key(subject, configKey));
245 + }
246 +
213 /** 247 /**
214 * Produces a config from the specified subject, config class and raw JSON. 248 * Produces a config from the specified subject, config class and raw JSON.
215 * 249 *
...@@ -248,19 +282,35 @@ public class DistributedNetworkConfigStore ...@@ -248,19 +282,35 @@ public class DistributedNetworkConfigStore
248 return new ConfigKey(subject, configClass); 282 return new ConfigKey(subject, configClass);
249 } 283 }
250 284
285 + // Produces a key for uniquely tracking a subject config.
286 + private static ConfigKey key(Object subject, String configKey) {
287 + return new ConfigKey(subject, configKey);
288 + }
289 +
251 // Auxiliary key to track subject configurations. 290 // Auxiliary key to track subject configurations.
291 + // Keys with non-null configKey are pending configurations.
252 private static final class ConfigKey { 292 private static final class ConfigKey {
253 final Object subject; 293 final Object subject;
294 + final String configKey;
254 final String configClass; 295 final String configClass;
255 296
297 + // Create a key for pending configuration class
298 + private ConfigKey(Object subject, String configKey) {
299 + this.subject = subject;
300 + this.configKey = configKey;
301 + this.configClass = null;
302 + }
303 +
304 + // Create a key for registered class configuration
256 private ConfigKey(Object subject, Class<?> configClass) { 305 private ConfigKey(Object subject, Class<?> configClass) {
257 this.subject = subject; 306 this.subject = subject;
307 + this.configKey = null;
258 this.configClass = configClass.getName(); 308 this.configClass = configClass.getName();
259 } 309 }
260 310
261 @Override 311 @Override
262 public int hashCode() { 312 public int hashCode() {
263 - return Objects.hash(subject, configClass); 313 + return Objects.hash(subject, configKey, configClass);
264 } 314 }
265 315
266 @Override 316 @Override
...@@ -271,6 +321,7 @@ public class DistributedNetworkConfigStore ...@@ -271,6 +321,7 @@ public class DistributedNetworkConfigStore
271 if (obj instanceof ConfigKey) { 321 if (obj instanceof ConfigKey) {
272 final ConfigKey other = (ConfigKey) obj; 322 final ConfigKey other = (ConfigKey) obj;
273 return Objects.equals(this.subject, other.subject) 323 return Objects.equals(this.subject, other.subject)
324 + && Objects.equals(this.configKey, other.configKey)
274 && Objects.equals(this.configClass, other.configClass); 325 && Objects.equals(this.configClass, other.configClass);
275 } 326 }
276 return false; 327 return false;
...@@ -280,6 +331,11 @@ public class DistributedNetworkConfigStore ...@@ -280,6 +331,11 @@ public class DistributedNetworkConfigStore
280 private class InternalMapListener implements MapEventListener<ConfigKey, JsonNode> { 331 private class InternalMapListener implements MapEventListener<ConfigKey, JsonNode> {
281 @Override 332 @Override
282 public void event(MapEvent<ConfigKey, JsonNode> event) { 333 public void event(MapEvent<ConfigKey, JsonNode> event) {
334 + // Do not delegate pending configs.
335 + if (event.key().configClass == null) {
336 + return;
337 + }
338 +
283 NetworkConfigEvent.Type type; 339 NetworkConfigEvent.Type type;
284 switch (event.type()) { 340 switch (event.type()) {
285 case INSERT: 341 case INSERT:
......
...@@ -62,9 +62,8 @@ public class DistributedNetworkConfigStoreTest { ...@@ -62,9 +62,8 @@ public class DistributedNetworkConfigStoreTest {
62 * Config factory class for testing. 62 * Config factory class for testing.
63 */ 63 */
64 public class MockConfigFactory extends ConfigFactory<String, BasicConfig> { 64 public class MockConfigFactory extends ConfigFactory<String, BasicConfig> {
65 - protected MockConfigFactory(SubjectFactory<String> subjectFactory, 65 + protected MockConfigFactory(Class<BasicConfig> configClass, String configKey) {
66 - Class<BasicConfig> configClass, String configKey) { 66 + super(new MockSubjectFactory("strings"), configClass, configKey);
67 - super(subjectFactory, configClass, configKey);
68 } 67 }
69 @Override 68 @Override
70 public BasicConfig createConfig() { 69 public BasicConfig createConfig() {
...@@ -73,11 +72,25 @@ public class DistributedNetworkConfigStoreTest { ...@@ -73,11 +72,25 @@ public class DistributedNetworkConfigStoreTest {
73 } 72 }
74 73
75 /** 74 /**
75 + * Subject factory class for testing.
76 + */
77 + public class MockSubjectFactory extends SubjectFactory<String> {
78 + protected MockSubjectFactory(String subjectClassKey) {
79 + super(String.class, subjectClassKey);
80 + }
81 +
82 + @Override
83 + public String createSubject(String subjectKey) {
84 + return subjectKey;
85 + }
86 + }
87 +
88 + /**
76 * Tests creation, query and removal of a config. 89 * Tests creation, query and removal of a config.
77 */ 90 */
78 @Test 91 @Test
79 public void testCreateConfig() { 92 public void testCreateConfig() {
80 - configStore.addConfigFactory(new MockConfigFactory(null, BasicConfig.class, "config1")); 93 + configStore.addConfigFactory(new MockConfigFactory(BasicConfig.class, "config1"));
81 94
82 configStore.createConfig("config1", BasicConfig.class); 95 configStore.createConfig("config1", BasicConfig.class);
83 assertThat(configStore.getConfigClasses("config1"), hasSize(1)); 96 assertThat(configStore.getConfigClasses("config1"), hasSize(1));
...@@ -101,7 +114,7 @@ public class DistributedNetworkConfigStoreTest { ...@@ -101,7 +114,7 @@ public class DistributedNetworkConfigStoreTest {
101 */ 114 */
102 @Test 115 @Test
103 public void testCreateFactory() { 116 public void testCreateFactory() {
104 - MockConfigFactory mockFactory = new MockConfigFactory(null, BasicConfig.class, "config1"); 117 + MockConfigFactory mockFactory = new MockConfigFactory(BasicConfig.class, "config1");
105 118
106 assertThat(configStore.getConfigFactory(BasicConfig.class), nullValue()); 119 assertThat(configStore.getConfigFactory(BasicConfig.class), nullValue());
107 120
...@@ -117,7 +130,7 @@ public class DistributedNetworkConfigStoreTest { ...@@ -117,7 +130,7 @@ public class DistributedNetworkConfigStoreTest {
117 */ 130 */
118 @Test 131 @Test
119 public void testApplyConfig() { 132 public void testApplyConfig() {
120 - configStore.addConfigFactory(new MockConfigFactory(null, BasicConfig.class, "config1")); 133 + configStore.addConfigFactory(new MockConfigFactory(BasicConfig.class, "config1"));
121 134
122 configStore.applyConfig("config1", BasicConfig.class, new ObjectMapper().createObjectNode()); 135 configStore.applyConfig("config1", BasicConfig.class, new ObjectMapper().createObjectNode());
123 assertThat(configStore.getConfigClasses("config1"), hasSize(1)); 136 assertThat(configStore.getConfigClasses("config1"), hasSize(1));
......
...@@ -264,8 +264,9 @@ public class NetworkConfigWebResource extends AbstractWebResource { ...@@ -264,8 +264,9 @@ public class NetworkConfigWebResource extends AbstractWebResource {
264 InputStream request) throws IOException { 264 InputStream request) throws IOException {
265 NetworkConfigService service = get(NetworkConfigService.class); 265 NetworkConfigService service = get(NetworkConfigService.class);
266 ObjectNode root = (ObjectNode) mapper().readTree(request); 266 ObjectNode root = (ObjectNode) mapper().readTree(request);
267 - service.applyConfig(service.getSubjectFactory(subjectClassKey).createSubject(subjectKey), 267 + service.applyConfig(subjectClassKey,
268 - service.getConfigClass(subjectClassKey, configKey), root); 268 + service.getSubjectFactory(subjectClassKey).createSubject(subjectKey),
269 + configKey, root);
269 return Response.ok().build(); 270 return Response.ok().build();
270 } 271 }
271 272
...@@ -279,13 +280,14 @@ public class NetworkConfigWebResource extends AbstractWebResource { ...@@ -279,13 +280,14 @@ public class NetworkConfigWebResource extends AbstractWebResource {
279 280
280 private void consumeSubjectJson(NetworkConfigService service, 281 private void consumeSubjectJson(NetworkConfigService service,
281 ObjectNode subjectNode, Object subject, 282 ObjectNode subjectNode, Object subject,
282 - String subjectKey) { 283 + String subjectClassKey) {
283 - subjectNode.fieldNames().forEachRemaining(c -> 284 + subjectNode.fieldNames().forEachRemaining(configKey ->
284 - service.applyConfig(subject, service.getConfigClass(subjectKey, c), 285 + service.applyConfig(subjectClassKey, subject, configKey, subjectNode.path(configKey)));
285 - subjectNode.path(c)));
286 } 286 }
287 287
288 288
289 + // FIXME: Refactor to allow queued configs to be removed
290 +
289 /** 291 /**
290 * Clear entire network configuration base. 292 * Clear entire network configuration base.
291 * 293 *
......
...@@ -56,6 +56,7 @@ import static org.junit.Assert.fail; ...@@ -56,6 +56,7 @@ import static org.junit.Assert.fail;
56 */ 56 */
57 public class NetworkConfigWebResourceTest extends ResourceTest { 57 public class NetworkConfigWebResourceTest extends ResourceTest {
58 58
59 +
59 MockNetworkConfigService mockNetworkConfigService; 60 MockNetworkConfigService mockNetworkConfigService;
60 61
61 public class MockDeviceConfig extends Config<Device> { 62 public class MockDeviceConfig extends Config<Device> {
...@@ -201,7 +202,7 @@ public class NetworkConfigWebResourceTest extends ResourceTest { ...@@ -201,7 +202,7 @@ public class NetworkConfigWebResourceTest extends ResourceTest {
201 mockNetworkConfigService = new MockNetworkConfigService(); 202 mockNetworkConfigService = new MockNetworkConfigService();
202 ServiceDirectory testDirectory = 203 ServiceDirectory testDirectory =
203 new TestServiceDirectory() 204 new TestServiceDirectory()
204 - .add(NetworkConfigService.class, mockNetworkConfigService); 205 + .add(NetworkConfigService.class, mockNetworkConfigService);
205 BaseResource.setServiceDirectory(testDirectory); 206 BaseResource.setServiceDirectory(testDirectory);
206 } 207 }
207 208
......