1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.accumulo.core.util.shell.commands;
18
19 import java.io.IOException;
20 import java.util.ArrayList;
21 import java.util.List;
22 import java.util.Map;
23 import java.util.Map.Entry;
24 import java.util.Set;
25 import java.util.TreeMap;
26
27 import jline.ConsoleReader;
28
29 import org.apache.accumulo.core.client.AccumuloException;
30 import org.apache.accumulo.core.client.AccumuloSecurityException;
31 import org.apache.accumulo.core.client.TableNotFoundException;
32 import org.apache.accumulo.core.conf.AccumuloConfiguration;
33 import org.apache.accumulo.core.conf.Property;
34 import org.apache.accumulo.core.security.ColumnVisibility;
35 import org.apache.accumulo.core.util.BadArgumentException;
36 import org.apache.accumulo.core.util.shell.Shell;
37 import org.apache.accumulo.core.util.shell.Shell.Command;
38 import org.apache.accumulo.core.util.shell.Shell.PrintFile;
39 import org.apache.accumulo.core.util.shell.Token;
40 import org.apache.commons.cli.CommandLine;
41 import org.apache.commons.cli.Option;
42 import org.apache.commons.cli.OptionGroup;
43 import org.apache.commons.cli.Options;
44
45 public class ConfigCommand extends Command {
46 private Option tableOpt, deleteOpt, setOpt, filterOpt, disablePaginationOpt, outputFileOpt;
47
48 private int COL1 = 8, COL2 = 7;
49 private ConsoleReader reader;
50
51 @Override
52 public void registerCompletion(final Token root, final Map<Command.CompletionSet,Set<String>> completionSet) {
53 final Token cmd = new Token(getName());
54 final Token sub = new Token("-" + setOpt.getOpt());
55 for (Property p : Property.values()) {
56 if (!(p.getKey().endsWith(".")) && !p.isExperimental()) {
57 sub.addSubcommand(new Token(p.toString()));
58 }
59 }
60 cmd.addSubcommand(sub);
61 root.addSubcommand(cmd);
62 }
63
64 public int execute(final String fullCommand, final CommandLine cl, final Shell shellState) throws AccumuloException, AccumuloSecurityException,
65 TableNotFoundException, IOException, ClassNotFoundException {
66 reader = shellState.getReader();
67
68 final String tableName = cl.getOptionValue(tableOpt.getOpt());
69 if (tableName != null && !shellState.getConnector().tableOperations().exists(tableName)) {
70 throw new TableNotFoundException(null, tableName, null);
71 }
72 if (cl.hasOption(deleteOpt.getOpt())) {
73
74 String property = cl.getOptionValue(deleteOpt.getOpt());
75 if (property.contains("=")) {
76 throw new BadArgumentException("Invalid '=' operator in delete operation.", fullCommand, fullCommand.indexOf('='));
77 }
78 if (tableName != null) {
79 if (!Property.isValidTablePropertyKey(property)) {
80 Shell.log.warn("Invalid per-table property : " + property + ", still removing from zookeeper if it's there.");
81 }
82 shellState.getConnector().tableOperations().removeProperty(tableName, property);
83 Shell.log.debug("Successfully deleted table configuration option.");
84 } else {
85 if (!Property.isValidZooPropertyKey(property)) {
86 Shell.log.warn("Invalid per-table property : " + property + ", still removing from zookeeper if it's there.");
87 }
88 shellState.getConnector().instanceOperations().removeProperty(property);
89 Shell.log.debug("Successfully deleted system configuration option");
90 }
91 } else if (cl.hasOption(setOpt.getOpt())) {
92
93 String property = cl.getOptionValue(setOpt.getOpt()), value = null;
94 if (!property.contains("=")) {
95 throw new BadArgumentException("Missing '=' operator in set operation.", fullCommand, fullCommand.indexOf(property));
96 }
97 final String pair[] = property.split("=", 2);
98 property = pair[0];
99 value = pair[1];
100
101 if (tableName != null) {
102 if (!Property.isValidTablePropertyKey(property)) {
103 throw new BadArgumentException("Invalid per-table property.", fullCommand, fullCommand.indexOf(property));
104 }
105 if (property.equals(Property.TABLE_DEFAULT_SCANTIME_VISIBILITY.getKey())) {
106 new ColumnVisibility(value);
107 }
108 shellState.getConnector().tableOperations().setProperty(tableName, property, value);
109 Shell.log.debug("Successfully set table configuration option.");
110 } else {
111 if (!Property.isValidZooPropertyKey(property)) {
112 throw new BadArgumentException("Property cannot be modified in zookeeper", fullCommand, fullCommand.indexOf(property));
113 }
114 shellState.getConnector().instanceOperations().setProperty(property, value);
115 Shell.log.debug("Successfully set system configuration option");
116 }
117 } else {
118
119 final TreeMap<String,String> systemConfig = new TreeMap<String,String>();
120 systemConfig.putAll(shellState.getConnector().instanceOperations().getSystemConfiguration());
121
122 final String outputFile = cl.getOptionValue(outputFileOpt.getOpt());
123 final PrintFile printFile = outputFile == null ? null : new PrintFile(outputFile);
124
125 final TreeMap<String,String> siteConfig = new TreeMap<String,String>();
126 siteConfig.putAll(shellState.getConnector().instanceOperations().getSiteConfiguration());
127
128 final TreeMap<String,String> defaults = new TreeMap<String,String>();
129 for (Entry<String,String> defaultEntry : AccumuloConfiguration.getDefaultConfiguration()) {
130 defaults.put(defaultEntry.getKey(), defaultEntry.getValue());
131 }
132 Iterable<Entry<String,String>> acuconf = shellState.getConnector().instanceOperations().getSystemConfiguration().entrySet();
133 if (tableName != null) {
134 acuconf = shellState.getConnector().tableOperations().getProperties(tableName);
135 }
136 final TreeMap<String,String> sortedConf = new TreeMap<String,String>();
137 for (Entry<String,String> propEntry : acuconf) {
138 sortedConf.put(propEntry.getKey(), propEntry.getValue());
139 }
140
141 for (Entry<String,String> propEntry : acuconf) {
142 final String key = propEntry.getKey();
143
144
145 if (cl.hasOption(filterOpt.getOpt()) && !key.contains(cl.getOptionValue(filterOpt.getOpt()))) {
146 continue;
147 }
148 if (tableName != null && !Property.isValidTablePropertyKey(key)) {
149 continue;
150 }
151 COL2 = Math.max(COL2, propEntry.getKey().length() + 3);
152 }
153
154 final ArrayList<String> output = new ArrayList<String>();
155 printConfHeader(output);
156
157 for (Entry<String,String> propEntry : sortedConf.entrySet()) {
158 final String key = propEntry.getKey();
159
160
161
162 if (cl.hasOption(filterOpt.getOpt()) && !key.contains(cl.getOptionValue(filterOpt.getOpt()))) {
163 continue;
164 }
165 if (tableName != null && !Property.isValidTablePropertyKey(key)) {
166 continue;
167 }
168 String siteVal = siteConfig.get(key);
169 String sysVal = systemConfig.get(key);
170 String curVal = propEntry.getValue();
171 String dfault = defaults.get(key);
172 boolean printed = false;
173
174 if (dfault != null && key.toLowerCase().contains("password")) {
175 siteVal = sysVal = dfault = curVal = curVal.replaceAll(".", "*");
176 }
177 if (sysVal != null) {
178 if (defaults.containsKey(key)) {
179 printConfLine(output, "default", key, dfault);
180 printed = true;
181 }
182 if (!defaults.containsKey(key) || !defaults.get(key).equals(siteVal)) {
183 printConfLine(output, "site", printed ? " @override" : key, siteVal == null ? "" : siteVal);
184 printed = true;
185 }
186 if (!siteConfig.containsKey(key) || !siteVal.equals(sysVal)) {
187 printConfLine(output, "system", printed ? " @override" : key, sysVal == null ? "" : sysVal);
188 printed = true;
189 }
190 }
191
192
193 if (tableName != null && !curVal.equals(sysVal)) {
194 printConfLine(output, "table", printed ? " @override" : key, curVal);
195 }
196 }
197 printConfFooter(output);
198 shellState.printLines(output.iterator(), !cl.hasOption(disablePaginationOpt.getOpt()), printFile);
199 if (printFile != null) {
200 printFile.close();
201 }
202 }
203 return 0;
204 }
205
206 private void printConfHeader(List<String> output) {
207 printConfFooter(output);
208 output.add(String.format("%-" + COL1 + "s | %-" + COL2 + "s | %s", "SCOPE", "NAME", "VALUE"));
209 printConfFooter(output);
210 }
211
212 private void printConfLine(List<String> output, String s1, String s2, String s3) {
213 if (s2.length() < COL2) {
214 s2 += " " + Shell.repeat(".", COL2 - s2.length() - 1);
215 }
216 output.add(String.format("%-" + COL1 + "s | %-" + COL2 + "s | %s", s1, s2,
217 s3.replace("\n", "\n" + Shell.repeat(" ", COL1 + 1) + "|" + Shell.repeat(" ", COL2 + 2) + "|" + " ")));
218 }
219
220 private void printConfFooter(List<String> output) {
221 int col3 = Math.max(1, Math.min(Integer.MAX_VALUE, reader.getTermwidth() - COL1 - COL2 - 6));
222 output.add(String.format("%" + COL1 + "s-+-%" + COL2 + "s-+-%-" + col3 + "s", Shell.repeat("-", COL1), Shell.repeat("-", COL2), Shell.repeat("-", col3)));
223 }
224
225 @Override
226 public String description() {
227 return "prints system properties and table specific properties";
228 }
229
230 @Override
231 public Options getOptions() {
232 final Options o = new Options();
233 final OptionGroup og = new OptionGroup();
234
235 tableOpt = new Option(Shell.tableOption, "table", true, "table to display/set/delete properties for");
236 deleteOpt = new Option("d", "delete", true, "delete a per-table property");
237 setOpt = new Option("s", "set", true, "set a per-table property");
238 filterOpt = new Option("f", "filter", true, "show only properties that contain this string");
239 disablePaginationOpt = new Option("np", "no-pagination", false, "disables pagination of output");
240 outputFileOpt = new Option("o", "output", true, "local file to write the scan output to");
241
242 tableOpt.setArgName("table");
243 deleteOpt.setArgName("property");
244 setOpt.setArgName("property=value");
245 filterOpt.setArgName("string");
246 outputFileOpt.setArgName("file");
247
248 og.addOption(deleteOpt);
249 og.addOption(setOpt);
250 og.addOption(filterOpt);
251
252 o.addOption(tableOpt);
253 o.addOptionGroup(og);
254 o.addOption(disablePaginationOpt);
255 o.addOption(outputFileOpt);
256
257 return o;
258 }
259
260 @Override
261 public int numArgs() {
262 return 0;
263 }
264 }