19
19
# under the License.
20
20
21
21
''' main.py '''
22
- import argparse
22
+ import logging
23
23
import os
24
24
import signal
25
25
import sys
29
29
from tornado .options import define
30
30
from tornado .httpclient import AsyncHTTPClient
31
31
32
- import heron .tools .common .src .python .utils . config as common_config
33
- import heron .common .src .python .utils . log as log
32
+ from heron .tools .common .src .python .utils import config as common_config
33
+ from heron .common .src .python .utils import log
34
34
from heron .tools .tracker .src .python import constants
35
35
from heron .tools .tracker .src .python import handlers
36
36
from heron .tools .tracker .src .python import utils
37
37
from heron .tools .tracker .src .python .config import Config , STATEMGRS_KEY
38
38
from heron .tools .tracker .src .python .tracker import Tracker
39
39
40
+ import click
41
+
40
42
Log = log .Log
41
43
42
44
class Application (tornado .web .Application ):
@@ -93,173 +95,110 @@ def __init__(self, config):
93
95
def stop (self ):
94
96
self .tracker .stop_sync ()
95
97
96
- # pylint: disable=protected-access
97
- class _HelpAction (argparse ._HelpAction ):
98
- """ HelpAction """
99
- def __call__ (self , parser , namespace , values , option_string = None ):
100
- parser .print_help ()
101
-
102
- # retrieve subparsers from parser
103
- subparsers_actions = [
104
- action for action in parser ._actions
105
- if isinstance (action , argparse ._SubParsersAction )]
106
-
107
- # there will probably only be one subparser_action,
108
- # but better save than sorry
109
- for subparsers_action in subparsers_actions :
110
- # get all subparsers and print help
111
- for choice , subparser in list (subparsers_action .choices .items ()):
112
- print ("Subparser '{}'" .format (choice ))
113
- print (subparser .format_help ())
114
-
115
- parser .exit ()
116
-
117
- # pylint: disable=bad-super-call
118
- class SubcommandHelpFormatter (argparse .RawDescriptionHelpFormatter ):
119
- """ Subcommand help formatter """
120
- def _format_action (self , action ):
121
- parts = super (argparse .RawDescriptionHelpFormatter , self )._format_action (action )
122
- if action .nargs == argparse .PARSER :
123
- parts = "\n " .join (parts .split ("\n " )[1 :])
124
- return parts
125
-
126
-
127
- def add_titles (parser ):
128
- """ add titles """
129
- parser ._positionals .title = "Required arguments"
130
- parser ._optionals .title = "Optional arguments"
131
- return parser
132
-
133
-
134
- def add_arguments (parser ):
135
- """ add arguments """
136
- default_config_file = os .path .join (
137
- utils .get_heron_tracker_conf_dir (), constants .DEFAULT_CONFIG_FILE )
138
-
139
- parser .add_argument (
140
- '--config-file' ,
141
- metavar = '(a string; path to config file; default: "' + default_config_file + '")' ,
142
- default = default_config_file )
143
-
144
- parser .add_argument (
145
- '--type' ,
146
- metavar = '(an string; type of state manager (zookeeper or file, etc.); example: ' \
147
- + str (constants .DEFAULT_STATE_MANAGER_TYPE ) + ')' ,
148
- choices = ["file" , "zookeeper" ])
149
-
150
- parser .add_argument (
151
- '--name' ,
152
- metavar = '(an string; name to be used for the state manager; example: ' \
153
- + str (constants .DEFAULT_STATE_MANAGER_NAME ) + ')' )
154
-
155
- parser .add_argument (
156
- '--rootpath' ,
157
- metavar = '(an string; where all the states are stored; example: ' \
158
- + str (constants .DEFAULT_STATE_MANAGER_ROOTPATH ) + ')' )
159
-
160
- parser .add_argument (
161
- '--tunnelhost' ,
162
- metavar = '(an string; if ssh tunneling needs to be established to connect to it; example: ' \
163
- + str (constants .DEFAULT_STATE_MANAGER_TUNNELHOST ) + ')' )
164
-
165
- parser .add_argument (
166
- '--hostport' ,
167
- metavar = '(an string; only used to connect to zk, must be of the form \' host:port\' ;' \
168
- ' example: ' + str (constants .DEFAULT_STATE_MANAGER_HOSTPORT ) + ')' )
169
-
170
- parser .add_argument (
171
- '--port' ,
172
- metavar = '(an integer; port to listen; default: ' + str (constants .DEFAULT_PORT ) + ')' ,
173
- type = int ,
174
- default = constants .DEFAULT_PORT )
175
98
176
- parser .add_argument (
177
- '--verbose' ,
178
- action = 'store_true' )
179
-
180
- return parser
181
-
182
- def create_parsers ():
183
- """ create argument parser """
184
- parser = argparse .ArgumentParser (
185
- epilog = 'For detailed documentation, go to http://github.com/apache/incubator-heron' ,
186
- usage = "%(prog)s [options] [help]" ,
187
- add_help = False )
188
-
189
- parser = add_titles (parser )
190
- parser = add_arguments (parser )
191
-
192
- ya_parser = argparse .ArgumentParser (
193
- parents = [parser ],
194
- formatter_class = SubcommandHelpFormatter ,
195
- add_help = False )
196
-
197
- subparsers = ya_parser .add_subparsers (
198
- title = "Available commands" )
199
-
200
- help_parser = subparsers .add_parser (
201
- 'help' ,
202
- help = 'Prints help' ,
203
- add_help = False )
204
-
205
- help_parser .set_defaults (help = True )
206
-
207
- subparsers .add_parser (
208
- 'version' ,
209
- help = 'Prints version' ,
210
- add_help = True )
211
-
212
- return parser , ya_parser
213
-
214
- def define_options (port , config_file ):
99
+ def define_options (port : int , config_file : str ) -> None :
215
100
""" define Tornado global variables """
216
101
define ("port" , default = port )
217
102
define ("config_file" , default = config_file )
218
103
219
- def create_tracker_config (namespace ):
104
+
105
+ def create_tracker_config (config_file : str , stmgr_override : dict ) -> dict :
220
106
# try to parse the config file if we find one
221
- config_file = namespace ["config_file" ]
222
107
config = utils .parse_config_file (config_file )
223
108
if config is None :
224
- Log .debug ("Config file does not exists: %s" % config_file )
109
+ Log .debug (f "Config file does not exists: { config_file } " )
225
110
config = {STATEMGRS_KEY :[{}]}
226
111
227
- # update the config if we have any flags
228
- config_flags = ["type" , "name" , "rootpath" , "tunnelhost" , "hostport" ]
229
- config_to_update = config [STATEMGRS_KEY ][0 ]
230
- for flag in config_flags :
231
- value = namespace .get (flag , None )
232
- if value is not None :
233
- config_to_update [flag ] = value
234
-
112
+ # update non-null options
113
+ config [STATEMGRS_KEY ][0 ].update (
114
+ (k , v )
115
+ for k , v in stmgr_override .items ()
116
+ if v is not None
117
+ )
235
118
return config
236
119
237
- def main ():
238
- """ main """
239
- # create the parser and parse the arguments
240
- (parser , _ ) = create_parsers ()
241
- (args , remaining ) = parser .parse_known_args ()
242
120
243
- if remaining == ['help' ]:
244
- parser .print_help ()
245
- parser .exit ()
246
-
247
- elif remaining == ['version' ]:
121
+ def show_version (_ , __ , value ):
122
+ if value :
248
123
common_config .print_build_info ()
249
- parser .exit ()
250
-
251
- elif remaining != []:
252
- Log .error ('Invalid subcommand' )
253
- sys .exit (1 )
254
-
255
- namespace = vars (args )
256
-
257
- log .set_logging_level (namespace )
124
+ sys .exit (0 )
125
+
126
+
127
+ @click .command ()
128
+ @click .option (
129
+ "--version" ,
130
+ is_flag = True ,
131
+ is_eager = True ,
132
+ expose_value = False ,
133
+ callback = show_version ,
134
+ )
135
+ @click .option ('--verbose' , is_flag = True )
136
+ @click .option (
137
+ '--config-file' ,
138
+ help = "path to a tracker config file" ,
139
+ default = os .path .join (utils .get_heron_tracker_conf_dir (), constants .DEFAULT_CONFIG_FILE ),
140
+ show_default = True ,
141
+ )
142
+ @click .option (
143
+ '--port' ,
144
+ type = int ,
145
+ default = constants .DEFAULT_PORT ,
146
+ show_default = True ,
147
+ help = "local port to serve on" ,
148
+ )
149
+ @click .option (
150
+ '--type' ,
151
+ "stmgr_type" ,
152
+ help = f"statemanager type e.g. { constants .DEFAULT_STATE_MANAGER_TYPE } " ,
153
+ type = click .Choice (choices = ["file" , "zookeeper" ]),
154
+ )
155
+ @click .option (
156
+ '--name' ,
157
+ help = f"statemanager name e.g. { constants .DEFAULT_STATE_MANAGER_NAME } " ,
158
+ )
159
+ @click .option (
160
+ '--rootpath' ,
161
+ help = f"statemanager rootpath e.g. { constants .DEFAULT_STATE_MANAGER_ROOTPATH } " ,
162
+ )
163
+ @click .option (
164
+ '--tunnelhost' ,
165
+ help = f"statemanager tunnelhost e.g. { constants .DEFAULT_STATE_MANAGER_TUNNELHOST } " ,
166
+ )
167
+ @click .option (
168
+ '--hostport' ,
169
+ help = f"statemanager hostport e.g. { constants .DEFAULT_STATE_MANAGER_HOSTPORT } " ,
170
+ )
171
+ def cli (
172
+ config_file : str ,
173
+ stmgr_type : str ,
174
+ name : str ,
175
+ rootpath : str ,
176
+ tunnelhost : str ,
177
+ hostport : str ,
178
+ port : int ,
179
+ verbose : bool ,
180
+ ) -> None :
181
+ """
182
+ A HTTP service for serving data about clusters.
183
+
184
+ The statemanager's config from the given config file can be overrided using
185
+ options on this executable.
186
+
187
+ """
188
+
189
+ log .configure (logging .DEBUG if verbose else logging .INFO )
258
190
259
191
# set Tornado global option
260
- define_options (namespace [ ' port' ], namespace [ ' config_file' ] )
192
+ define_options (port , config_file )
261
193
262
- config = Config (create_tracker_config (namespace ))
194
+ stmgr_override = {
195
+ "type" : stmgr_type ,
196
+ "name" : name ,
197
+ "rootpath" : rootpath ,
198
+ "tunnelhost" : tunnelhost ,
199
+ "hostport" : hostport ,
200
+ }
201
+ config = Config (create_tracker_config (config_file , stmgr_override ))
263
202
264
203
# create Tornado application
265
204
application = Application (config )
@@ -278,15 +217,15 @@ def signal_handler(signum, frame):
278
217
signal .signal (signal .SIGINT , signal_handler )
279
218
signal .signal (signal .SIGTERM , signal_handler )
280
219
281
- Log .info ("Running on port: %d" , namespace [ ' port' ] )
282
- if namespace [ " config_file" ] :
283
- Log .info ("Using config file: %s" , namespace [ ' config_file' ] )
284
- Log .info ("Using state manager:\n " + str ( config ) )
220
+ Log .info ("Running on port: %d" , port )
221
+ if config_file :
222
+ Log .info ("Using config file: %s" , config_file )
223
+ Log .info (f "Using state manager:\n { config } " )
285
224
286
225
http_server = tornado .httpserver .HTTPServer (application )
287
- http_server .listen (namespace [ ' port' ] )
226
+ http_server .listen (port )
288
227
289
228
tornado .ioloop .IOLoop .instance ().start ()
290
229
291
230
if __name__ == "__main__" :
292
- main ()
231
+ cli () # pylint: disable=no-value-for-parameter
0 commit comments