-
Notifications
You must be signed in to change notification settings - Fork 3
/
extract_config.groovy
189 lines (171 loc) · 5.99 KB
/
extract_config.groovy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
@Grapes([
@Grab(group='org.yaml', module='snakeyaml', version='1.15')
])
import groovy.json.JsonOutput
import groovy.json.JsonSlurper
import org.yaml.snakeyaml.Yaml
import java.util.regex.Matcher
def parseDefaults() {
def yaml = new Yaml()
def defaults
new File('storm/conf/defaults.yaml').withInputStream {
defaults = yaml.load(it)
}
return defaults
}
class Param {
String key
String type
Object default_
StringBuilder comment
String toString() {
return "${key}(${type}, ${default_}, ${comment})"
}
def toJson() {
assert key != null
assert type != null
assert comment != null
def result = [
name:'storm_' + key.replaceAll(/\./, '_'),
label:key,
description:comment.toString(),
configName:key,
]
switch(key) {
case 'storm.id': // topology-specific config makes no sense in storm.yaml
case ~/topology\..*/: // topology-specific config makes no sense in storm.yaml
case 'nimbus.host': // determined by service topology in CM
case 'storm.zookeeper.servers': // available in ZK_QUORUM environment variable
case 'storm.zookeeper.port': // available in ZK_QUORUM environment variable
case 'transactional.zookeeper.servers': // fall back to zookeeper.serversw
case 'transactional.zookeeper.port': // fall back to zookeeper.port
case 'storm.cluster.mode': // always run in distributed mode
case 'storm.local.mode.zmq': // ignored in distributed mode
case 'storm.local.hostname': // makes no sense to set this service-wide
case 'supervisor.enable': // only used by storm-core unit tests
case 'drpc.servers': // determined by service topology in CM (XXX not implemented)
case 'dev.zookeeper.path': // only used in development
return null
}
switch(type) {
case 'String.class':
case 'ConfigValidation.StringOrStringListValidator': // currently only worker.childopts
result['type'] = 'string'
break
case 'Boolean.class':
result['type'] = 'boolean'
break
case 'ConfigValidation.DoubleValidator':
result['type'] = 'double'
break
case 'ConfigValidation.IntegersValidator':
result['type'] = 'string_array'
result['separator'] = ' '
break
case 'ConfigValidation.StringsValidator':
result['type'] = 'string_array'
break
case 'ConfigValidation.IntegerValidator':
case 'ConfigValidation.PowerOf2Validator':
result['type'] = 'long'
break
case 'Map.class':
// XXX conversion from array of 'foo=bar' to yaml map not yet implemented
result['type'] = 'string_array'
result['separator'] = ','
break
default:
System.err.println "Ignoring unknown type for ${this}"
return null
}
switch(key) {
case ~/.*\.port/:
result['type'] = 'port'
result['required'] = true
result['configurableInWizard'] = true
break
case ~/.*\.secs/:
result['unit'] = 'seconds'
break
case ~/.*_ms/:
case ~/.*\.millis/:
case ~/.*\.timeout/: // must be tested *after* .secs since there are options named foo.timeout.secs
result['units'] = 'milliseconds'
break
case ~/\.*\.buffer\.size/:
case ~/\.*\.batch\.size/:
result['unit'] = 'bytes'
break
}
switch(key) {
case 'nimbus.thrift.port':
result['required'] = true // referenced by peerConfigGenerators, which cause a nasty NullPointerException in the Cloudera Manager server if the referenced parameter is not set
result['default'] = 6627
break
case 'ui.port': // default required because of externalLink in SDL file
result['default'] = 8080
break
case 'java.library.path':
result['type'] = 'path_array'
result['separator'] = ':'
result['pathType'] = 'serviceSpecific'
result['default'] = ['/opt/cloudera/parcels/CDH/lib/hadoop/lib/native']
break
case 'storm.local.dir':
result['type'] = 'path'
result['pathType'] = 'localDataDir'
result['mode'] = '0700'
result['required'] = true
result['default'] = '/var/lib/storm'
result['configurableInWizard'] = true
break
}
if (result.get('default') == null && default_ != null) {
result['default'] = default_
}
return result
}
}
def parseParams(def defaults) {
def result = []
def p
System.in.eachLine {
switch (it) {
case ~/.*?\/\*.*/:
p = new Param()
break
case ~/.*?\* (.*).*/:
if (p.comment == null)
p.comment = new StringBuilder()
else
p.comment << ' '
p.comment << Matcher.lastMatcher[0][1]
break
case ~/.*?public static final String [A-Z_]+\s*=\s*"([^"]+)".*/:
p.key = Matcher.lastMatcher[0][1]
p.default_ = defaults.get(p.key)
break
case ~/.*?public static final Object [A-Z_]+?_SCHEMA\s*=\s*([^;]+);.*/:
p.type = Matcher.lastMatcher[0][1]
result << p
p = null
break
}
}
return result
}
def knownParams = parseParams(parseDefaults())
def params = []
knownParams.each {
try {
def p = it.toJson()
if (p != null) params << p
} catch (Exception e) {
throw new RuntimeException("Bad parameter: ${it}", e)
}
}
def js = new JsonSlurper()
def sd = js.parse(new File('descriptor/service.sdl.in'))
sd['parameters'] += params
def jo = new JsonOutput()
System.out << JsonOutput.prettyPrint(jo.toJson(sd))