3
3
~~~~~~~~~~~~~~~~~~~~~~~~~
4
4
Abstracts everything related to the user's environment when running the CLI
6
:copyright: (c) 2013, SoftLayer Technologies, Inc. All rights reserved.
7
6
:license: MIT, see LICENSE for more details.
16
15
from SoftLayer.CLI.modules import get_module_list
16
from SoftLayer.utils import console_input
17
17
from SoftLayer import SoftLayerError
19
# pylint: disable=R0201
20
22
class InvalidCommand(SoftLayerError):
21
23
" Raised when trying to use a command that does not exist "
37
39
class Environment(object):
38
# {'module_name': {'action': 'actionClass'}}
40
""" Provides access to the current CLI environment """
42
# {'module_name': {'action': 'actionClass'}}
55
self.stdout = sys.stdout
56
self.stderr = sys.stderr
51
58
def get_command(self, module_name, command_name):
59
""" Based on the loaded modules, return a command """
52
60
actions = self.plugins.get(module_name) or {}
53
61
if command_name in actions:
54
62
return actions[command_name]
57
65
raise InvalidCommand(module_name, command_name)
59
67
def get_module_name(self, module_name):
68
""" Returns the actual module name. Uses the alias mapping """
60
69
if module_name in self.aliases:
61
70
return self.aliases[module_name]
64
73
def load_module(self, module_name): # pragma: no cover
74
""" Loads module by name """
66
76
module = import_module('SoftLayer.CLI.modules.%s' % module_name)
67
77
for _, obj in inspect.getmembers(module):
72
82
raise InvalidModule(module_name)
74
84
def add_plugin(self, cls):
85
""" Add a CLIRunnable as a plugin to the environment """
75
86
command = cls.__module__.split('.')[-1]
76
87
if command not in self.plugins:
77
88
self.plugins[command] = {}
78
89
self.plugins[command][cls.action] = cls
80
91
def plugin_list(self):
92
""" Returns the list of modules in SoftLayer.CLI.modules """
81
93
return get_module_list()
83
def out(self, s, nl=True):
95
def out(self, output, newline=True):
96
""" Outputs a string to the console (stdout) """
97
self.stdout.write(output)
86
99
self.stdout.write(os.linesep)
88
def err(self, s, nl=True):
101
def err(self, output, newline=True):
102
""" Outputs an error string to the console (stderr) """
103
self.stderr.write(output)
91
105
self.stderr.write(os.linesep)
93
107
def input(self, prompt):
94
return raw_input(prompt)
108
""" Provide a command prompt """
109
return console_input(prompt)
96
111
def getpass(self, prompt):
112
""" Provide a password prompt """
97
113
return getpass.getpass(prompt)
99
115
def exit(self, code=0):
103
120
class CLIRunnable(object):
121
""" CLIRunnable is intended to be subclassed. It represents a descrete
122
command or action in the CLI. """
104
123
options = [] # set by subclass
105
action = None # set by subclass
124
action = 'not set' # set by subclass
107
126
def __init__(self, client=None, env=None):
108
127
self.client = client
111
130
def execute(self, args):
131
""" Execute the command. This is intended to be overridden in a