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
Showing
8 changed files
with
196 additions
and
27 deletions
... | @@ -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 | ... | ... |
-
Please register or login to post a comment