blob: 4cca68be8b786c8f16b80190ecc5cb3fff867902 [file] [log] [blame]
RafaƂ Szaleckide5cf842018-11-17 13:30:01 +01001/*
2 * Copyright 2018-present Open Networking Foundation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package org.onosproject.net.config.basics;
17
18import com.fasterxml.jackson.core.JsonProcessingException;
19import com.fasterxml.jackson.databind.JsonNode;
20import com.fasterxml.jackson.databind.ObjectMapper;
21import com.fasterxml.jackson.databind.node.ObjectNode;
22import org.onosproject.net.HostId;
23import org.onosproject.net.config.BaseConfig;
24import org.onosproject.net.config.InvalidFieldException;
25import org.slf4j.Logger;
26
27import java.util.HashMap;
28import java.util.Map;
29
30import static org.slf4j.LoggerFactory.getLogger;
31
32/**
33 * Configuration to add extra annotations to a host via netcfg subsystem.
34 */
35public class HostAnnotationConfig
36 extends BaseConfig<HostId> {
37
38 /**
39 * {@value #CONFIG_KEY} : a netcfg ConfigKey for {@link HostAnnotationConfig}.
40 */
41 public static final String CONFIG_KEY = "annotations";
42
43 /**
44 * JSON key for annotation entries.
45 * Value is a String.
46 */
47 private static final String ENTRIES = "entries";
48
49 private final Logger log = getLogger(getClass());
50
51 private static final int KEY_MAX_LENGTH = 1024;
52 private static final int VALUE_MAX_LENGTH = 1024;
53
54 @Override
55 public boolean isValid() {
56 JsonNode jsonNode = object.path(ENTRIES);
57 if (jsonNode.isObject()) {
58 jsonNode.fields().forEachRemaining(entry -> {
59 if (entry.getKey().length() > KEY_MAX_LENGTH) {
60 throw new InvalidFieldException(entry.getKey(),
61 entry.getKey() + " exceeds maximum length " + KEY_MAX_LENGTH);
62 }
63 if (entry.getValue().asText("").length() > VALUE_MAX_LENGTH) {
64 throw new InvalidFieldException(entry.getKey(),
65 entry.getKey() + " exceeds maximum length " + VALUE_MAX_LENGTH);
66 }
67 });
68 }
69 return hasField(ENTRIES) && object.get(ENTRIES).isObject();
70 }
71
72 /**
73 * Returns annotations to add to a Host.
74 *
75 * @return annotations as a map. null value represent key removal request
76 */
77 public Map<String, String> annotations() {
78 Map<String, String> map = new HashMap<>();
79
80 JsonNode jsonNode = object.path(ENTRIES);
81 if (!jsonNode.isObject()) {
82 return map;
83 }
84
85 jsonNode.fields().forEachRemaining(entry -> {
86 String key = entry.getKey();
87 JsonNode value = entry.getValue();
88 if (value.isTextual()) {
89 map.put(key, value.asText());
90 } else if (value.isNull()) {
91 map.put(key, null);
92 } else {
93 try {
94 map.put(key, mapper().writeValueAsString(value));
95 } catch (JsonProcessingException e) {
96 log.warn("Error processing JSON value for {}.", key, e);
97 }
98 }
99 });
100 return map;
101 }
102
103 /**
104 * Sets annotations to add to a Host.
105 *
106 * @param replace annotations to be added by this configuration.
107 * null value represent key removal request
108 * @return self
109 */
110 public HostAnnotationConfig annotations(Map<String, String> replace) {
111 ObjectNode anns = object.objectNode();
112 if (replace != null) {
113 replace.forEach(anns::put);
114 }
115 object.set(ENTRIES, anns);
116 return this;
117 }
118
119 /**
120 * Add configuration to set or remove annotation entry.
121 *
122 * @param key annotations key
123 * @param value annotations value. specifying null removes the entry.
124 * @return self
125 */
126 public HostAnnotationConfig annotation(String key, String value) {
127 JsonNode ent = object.path(ENTRIES);
128 ObjectNode obj = (ent.isObject()) ? (ObjectNode) ent : object.objectNode();
129
130 obj.put(key, value);
131
132 object.set(ENTRIES, obj);
133 return this;
134 }
135
136 /**
137 * Remove configuration about specified key.
138 *
139 * @param key annotations key
140 * @return self
141 */
142 public HostAnnotationConfig annotation(String key) {
143 JsonNode ent = object.path(ENTRIES);
144 ObjectNode obj = (ent.isObject()) ? (ObjectNode) ent : object.objectNode();
145
146 obj.remove(key);
147
148 object.set(ENTRIES, obj);
149 return this;
150 }
151
152 /**
153 * Create a detached {@link HostAnnotationConfig}.
154 * <p>
155 * Note: created instance needs to be initialized by #init(..) before using.
156 */
157 public HostAnnotationConfig() {
158 super();
159 }
160
161 /**
162 * Create a detached {@link HostAnnotationConfig} for specified host.
163 * <p>
164 * Note: created instance is not bound to NetworkConfigService,
165 * thus cannot use {@link #apply()}. Must be passed to the service
166 * using NetworkConfigService#applyConfig
167 *
168 * @param hostId Host id
169 */
170 public HostAnnotationConfig(HostId hostId) {
171 ObjectMapper mapper = new ObjectMapper();
172 init(hostId, CONFIG_KEY, mapper.createObjectNode(), mapper, null);
173 }
174}