cloudshell-cli 4.0.5__zip → 4.1.1__zip
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {cloudshell-cli-4.0.5/cloudshell_cli.egg-info → cloudshell-cli-4.1.1}/PKG-INFO +2 -5
- {cloudshell-cli-4.0.5 → cloudshell-cli-4.1.1}/cloudshell/cli/configurator.py +37 -38
- {cloudshell-cli-4.0.5 → cloudshell-cli-4.1.1}/cloudshell/cli/examples/cli_demo/connect_to_switch/SwitchClihandler.py +0 -1
- {cloudshell-cli-4.0.5 → cloudshell-cli-4.1.1}/cloudshell/cli/examples/cli_demo/connect_to_switch/runner.py +2 -2
- {cloudshell-cli-4.0.5 → cloudshell-cli-4.1.1}/cloudshell/cli/examples/cli_demo/connect_to_ubuntu/runnur.py +1 -2
- cloudshell-cli-4.1.1/cloudshell/cli/factory/session_factory.py +96 -0
- {cloudshell-cli-4.0.5 → cloudshell-cli-4.1.1}/cloudshell/cli/service/cli_service_impl.py +2 -1
- {cloudshell-cli-4.0.5 → cloudshell-cli-4.1.1}/cloudshell/cli/service/command_mode_helper.py +2 -2
- {cloudshell-cli-4.0.5 → cloudshell-cli-4.1.1}/cloudshell/cli/session/expect_session.py +46 -1
- {cloudshell-cli-4.0.5 → cloudshell-cli-4.1.1}/cloudshell/cli/session/scpi_session.py +0 -1
- {cloudshell-cli-4.0.5 → cloudshell-cli-4.1.1}/cloudshell/cli/session/ssh_session.py +24 -25
- {cloudshell-cli-4.0.5 → cloudshell-cli-4.1.1}/cloudshell/cli/session/tcp_session.py +5 -16
- {cloudshell-cli-4.0.5 → cloudshell-cli-4.1.1}/cloudshell/cli/session/telnet_session.py +4 -19
- cloudshell-cli-4.1.1/cloudshell/cli/session_pool_context_manager.py +0 -0
- {cloudshell-cli-4.0.5 → cloudshell-cli-4.1.1/cloudshell_cli.egg-info}/PKG-INFO +2 -5
- {cloudshell-cli-4.0.5 → cloudshell-cli-4.1.1}/cloudshell_cli.egg-info/SOURCES.txt +4 -0
- {cloudshell-cli-4.0.5 → cloudshell-cli-4.1.1}/cloudshell_cli.egg-info/requires.txt +1 -0
- cloudshell-cli-4.1.1/dev_requirements.txt +4 -0
- {cloudshell-cli-4.0.5 → cloudshell-cli-4.1.1}/requirements.txt +1 -0
- {cloudshell-cli-4.0.5 → cloudshell-cli-4.1.1}/setup.py +1 -0
- {cloudshell-cli-4.0.5 → cloudshell-cli-4.1.1}/tests/cli/session/test_expect_session.py +8 -5
- cloudshell-cli-4.1.1/tests/cli/session/test_expect_session_py3.py +13 -0
- {cloudshell-cli-4.0.5 → cloudshell-cli-4.1.1}/tests/cli/session/test_ssh_session.py +11 -16
- cloudshell-cli-4.1.1/tests/conftest.py +15 -0
- {cloudshell-cli-4.0.5 → cloudshell-cli-4.1.1}/tox.ini +1 -1
- cloudshell-cli-4.1.1/version.txt +1 -0
- cloudshell-cli-4.0.5/dev_requirements.txt +0 -5
- cloudshell-cli-4.0.5/version.txt +0 -1
- {cloudshell-cli-4.0.5 → cloudshell-cli-4.1.1}/LICENSE +0 -0
- {cloudshell-cli-4.0.5 → cloudshell-cli-4.1.1}/MANIFEST.in +0 -0
- {cloudshell-cli-4.0.5 → cloudshell-cli-4.1.1}/README.txt +0 -0
- {cloudshell-cli-4.0.5 → cloudshell-cli-4.1.1}/cloudshell/__init__.py +0 -0
- {cloudshell-cli-4.0.5 → cloudshell-cli-4.1.1}/cloudshell/cli/__init__.py +0 -0
- {cloudshell-cli-4.0.5 → cloudshell-cli-4.1.1}/cloudshell/cli/cli.py +0 -0
- {cloudshell-cli-4.0.5 → cloudshell-cli-4.1.1}/cloudshell/cli/command_template/__init__.py +0 -0
- {cloudshell-cli-4.0.5 → cloudshell-cli-4.1.1}/cloudshell/cli/command_template/command_template.py +0 -0
- {cloudshell-cli-4.0.5 → cloudshell-cli-4.1.1}/cloudshell/cli/command_template/command_template_executor.py +0 -0
- {cloudshell-cli-4.0.5 → cloudshell-cli-4.1.1}/cloudshell/cli/examples/__init__.py +0 -0
- {cloudshell-cli-4.0.5 → cloudshell-cli-4.1.1}/cloudshell/cli/examples/cli_demo/__init__.py +0 -0
- {cloudshell-cli-4.0.5 → cloudshell-cli-4.1.1}/cloudshell/cli/examples/cli_demo/connect_to_AWS/__init__.py +0 -0
- {cloudshell-cli-4.0.5 → cloudshell-cli-4.1.1}/cloudshell/cli/examples/cli_demo/connect_to_AWS/runnur.py +0 -0
- {cloudshell-cli-4.0.5 → cloudshell-cli-4.1.1}/cloudshell/cli/examples/cli_demo/connect_to_switch/__init__.py +0 -0
- {cloudshell-cli-4.0.5 → cloudshell-cli-4.1.1}/cloudshell/cli/examples/cli_demo/connect_to_ubuntu/__init__.py +0 -0
- {cloudshell-cli-4.0.5 → cloudshell-cli-4.1.1}/cloudshell/cli/examples/cli_demo/connect_to_ubuntu/readfrom.txt +0 -0
- {cloudshell-cli-4.0.5/cloudshell/cli/service → cloudshell-cli-4.1.1/cloudshell/cli/factory}/__init__.py +0 -0
- /cloudshell-cli-4.0.5/cloudshell/cli/session_pool_context_manager.py → /cloudshell-cli-4.1.1/cloudshell/cli/service/__init__.py +0 -0
- {cloudshell-cli-4.0.5 → cloudshell-cli-4.1.1}/cloudshell/cli/service/cli.py +0 -0
- {cloudshell-cli-4.0.5 → cloudshell-cli-4.1.1}/cloudshell/cli/service/cli_exception.py +0 -0
- {cloudshell-cli-4.0.5 → cloudshell-cli-4.1.1}/cloudshell/cli/service/cli_service.py +0 -0
- {cloudshell-cli-4.0.5 → cloudshell-cli-4.1.1}/cloudshell/cli/service/command_mode.py +0 -0
- {cloudshell-cli-4.0.5 → cloudshell-cli-4.1.1}/cloudshell/cli/service/node.py +0 -0
- {cloudshell-cli-4.0.5 → cloudshell-cli-4.1.1}/cloudshell/cli/service/session_manager.py +0 -0
- {cloudshell-cli-4.0.5 → cloudshell-cli-4.1.1}/cloudshell/cli/service/session_manager_impl.py +0 -0
- {cloudshell-cli-4.0.5 → cloudshell-cli-4.1.1}/cloudshell/cli/service/session_pool.py +0 -0
- {cloudshell-cli-4.0.5 → cloudshell-cli-4.1.1}/cloudshell/cli/service/session_pool_context_manager.py +0 -0
- {cloudshell-cli-4.0.5 → cloudshell-cli-4.1.1}/cloudshell/cli/service/session_pool_manager.py +0 -0
- {cloudshell-cli-4.0.5 → cloudshell-cli-4.1.1}/cloudshell/cli/session/__init__.py +0 -0
- {cloudshell-cli-4.0.5 → cloudshell-cli-4.1.1}/cloudshell/cli/session/connection_params.py +0 -0
- {cloudshell-cli-4.0.5 → cloudshell-cli-4.1.1}/cloudshell/cli/session/helper/__init__.py +0 -0
- {cloudshell-cli-4.0.5 → cloudshell-cli-4.1.1}/cloudshell/cli/session/helper/normalize_buffer.py +0 -0
- {cloudshell-cli-4.0.5 → cloudshell-cli-4.1.1}/cloudshell/cli/session/session.py +0 -0
- {cloudshell-cli-4.0.5 → cloudshell-cli-4.1.1}/cloudshell/cli/session/session_exceptions.py +0 -0
- {cloudshell-cli-4.0.5 → cloudshell-cli-4.1.1}/cloudshell/cli/session/tl1_session.py +0 -0
- {cloudshell-cli-4.0.5 → cloudshell-cli-4.1.1}/cloudshell_cli.egg-info/dependency_links.txt +0 -0
- {cloudshell-cli-4.0.5 → cloudshell-cli-4.1.1}/cloudshell_cli.egg-info/top_level.txt +0 -0
- {cloudshell-cli-4.0.5 → cloudshell-cli-4.1.1}/setup.cfg +0 -0
- {cloudshell-cli-4.0.5 → cloudshell-cli-4.1.1}/test_requirements.txt +0 -0
- {cloudshell-cli-4.0.5 → cloudshell-cli-4.1.1}/tests/__init__.py +0 -0
- {cloudshell-cli-4.0.5 → cloudshell-cli-4.1.1}/tests/cli/__init__.py +0 -0
- {cloudshell-cli-4.0.5 → cloudshell-cli-4.1.1}/tests/cli/command_template/__init__.py +0 -0
- {cloudshell-cli-4.0.5 → cloudshell-cli-4.1.1}/tests/cli/command_template/test_command_template.py +0 -0
- {cloudshell-cli-4.0.5 → cloudshell-cli-4.1.1}/tests/cli/session/__init__.py +0 -0
- {cloudshell-cli-4.0.5 → cloudshell-cli-4.1.1}/tests/cli/session/test_connection_params.py +0 -0
- {cloudshell-cli-4.0.5 → cloudshell-cli-4.1.1}/tests/cli/session/test_telnet_session.py +0 -0
- {cloudshell-cli-4.0.5 → cloudshell-cli-4.1.1}/tests/cli/test_cli.py +0 -0
- {cloudshell-cli-4.0.5 → cloudshell-cli-4.1.1}/tests/cli/test_cli_service_impl.py +0 -0
- {cloudshell-cli-4.0.5 → cloudshell-cli-4.1.1}/tests/cli/test_command_mode.py +0 -0
- {cloudshell-cli-4.0.5 → cloudshell-cli-4.1.1}/tests/cli/test_command_mode_helper.py +0 -0
- {cloudshell-cli-4.0.5 → cloudshell-cli-4.1.1}/tests/cli/test_node.py +0 -0
- {cloudshell-cli-4.0.5 → cloudshell-cli-4.1.1}/tests/cli/test_session_manager.py +0 -0
- {cloudshell-cli-4.0.5 → cloudshell-cli-4.1.1}/tests/cli/test_session_pool_context_manager.py +0 -0
- {cloudshell-cli-4.0.5 → cloudshell-cli-4.1.1}/tests/cli/test_session_pool_manager.py +0 -0
|
@@ -1,14 +1,11 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: cloudshell-cli
|
|
3
|
-
Version: 4.
|
|
3
|
+
Version: 4.1.1
|
|
4
4
|
Summary: QualiSystems CloudShell CLI support package
|
|
5
5
|
Home-page: http://www.qualisystems.com/
|
|
6
6
|
Author: QualiSystems
|
|
7
7
|
Author-email: info@qualisystems.com
|
|
8
|
-
License: UNKNOWN
|
|
9
|
-
Platform: UNKNOWN
|
|
10
8
|
Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, !=3.6.*, <4
|
|
11
9
|
License-File: LICENSE
|
|
12
10
|
|
|
13
|
-
|
|
14
|
-
|
|
11
|
+
QualiSystems CloudShell CLI support package
|
|
@@ -2,7 +2,13 @@
|
|
|
2
2
|
# -*- coding: utf-8 -*-
|
|
3
3
|
import sys
|
|
4
4
|
from abc import ABCMeta, abstractmethod
|
|
5
|
+
from collections import defaultdict
|
|
5
6
|
|
|
7
|
+
from cloudshell.cli.factory.session_factory import (
|
|
8
|
+
CloudInfoAccessKeySessionFactory,
|
|
9
|
+
GenericSessionFactory,
|
|
10
|
+
SessionFactory,
|
|
11
|
+
)
|
|
6
12
|
from cloudshell.cli.service.cli import CLI
|
|
7
13
|
from cloudshell.cli.session.ssh_session import SSHSession
|
|
8
14
|
from cloudshell.cli.session.telnet_session import TelnetSession
|
|
@@ -16,39 +22,33 @@ else:
|
|
|
16
22
|
|
|
17
23
|
|
|
18
24
|
class CLIServiceConfigurator(object):
|
|
19
|
-
REGISTERED_SESSIONS = (SSHSession, TelnetSession)
|
|
20
|
-
|
|
21
|
-
|
|
25
|
+
REGISTERED_SESSIONS = (CloudInfoAccessKeySessionFactory(SSHSession), TelnetSession)
|
|
26
|
+
"""Using factories instead of """
|
|
27
|
+
|
|
28
|
+
def __init__(
|
|
29
|
+
self,
|
|
30
|
+
resource_config,
|
|
31
|
+
logger,
|
|
32
|
+
cli=None,
|
|
33
|
+
registered_sessions=None,
|
|
34
|
+
access_key=None,
|
|
35
|
+
access_key_passphrase=None,
|
|
36
|
+
):
|
|
22
37
|
"""Initialize CLI service configurator.
|
|
23
38
|
|
|
24
39
|
:param cloudshell.shell.standards.resource_config_generic_models.GenericCLIConfig resource_config: # noqa: E501
|
|
25
40
|
:param logging.Logger logger:
|
|
26
41
|
:param cloudshell.cli.service.cli.CLI cli:
|
|
27
42
|
:param registered_sessions: Session types and order
|
|
43
|
+
:param access_key: access key for the resource
|
|
44
|
+
:param access_key_passphrase: access key passphrase for the resource
|
|
28
45
|
"""
|
|
29
46
|
self._cli = cli or CLI()
|
|
30
47
|
self._resource_config = resource_config
|
|
31
48
|
self._logger = logger
|
|
32
49
|
self._registered_sessions = registered_sessions or self.REGISTERED_SESSIONS
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
def _username(self):
|
|
36
|
-
return self._resource_config.user
|
|
37
|
-
|
|
38
|
-
@property
|
|
39
|
-
@lru_cache()
|
|
40
|
-
def _password(self):
|
|
41
|
-
return self._resource_config.password
|
|
42
|
-
|
|
43
|
-
@property
|
|
44
|
-
def _resource_address(self):
|
|
45
|
-
"""Resource IP."""
|
|
46
|
-
return self._resource_config.address
|
|
47
|
-
|
|
48
|
-
@property
|
|
49
|
-
def _port(self):
|
|
50
|
-
"""Connection port property, to open socket on."""
|
|
51
|
-
return self._resource_config.cli_tcp_port
|
|
50
|
+
self._access_key = access_key
|
|
51
|
+
self._access_key_passphrase = access_key_passphrase
|
|
52
52
|
|
|
53
53
|
@property
|
|
54
54
|
def _cli_type(self):
|
|
@@ -58,29 +58,28 @@ class CLIServiceConfigurator(object):
|
|
|
58
58
|
@property
|
|
59
59
|
@lru_cache()
|
|
60
60
|
def _session_dict(self):
|
|
61
|
-
|
|
61
|
+
session_dict = defaultdict(list)
|
|
62
|
+
for sess in self._registered_sessions:
|
|
63
|
+
session_dict[sess.SESSION_TYPE.lower()].append(sess)
|
|
64
|
+
return session_dict
|
|
62
65
|
|
|
63
66
|
def _on_session_start(self, session, logger):
|
|
64
|
-
"""Perform some default commands when session just opened.
|
|
65
|
-
|
|
66
|
-
Like 'no logging console'
|
|
67
|
-
"""
|
|
68
67
|
pass
|
|
69
68
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
return
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
69
|
+
def initialize_session(self, session):
|
|
70
|
+
if not isinstance(session, SessionFactory):
|
|
71
|
+
session = GenericSessionFactory(session)
|
|
72
|
+
return session.init_session(
|
|
73
|
+
self._resource_config,
|
|
74
|
+
self._logger,
|
|
75
|
+
on_session_start=self._on_session_start,
|
|
76
|
+
access_key=self._access_key,
|
|
77
|
+
access_key_passphrase=self._access_key_passphrase,
|
|
78
|
+
)
|
|
80
79
|
|
|
81
80
|
def _defined_sessions(self):
|
|
82
81
|
return [
|
|
83
|
-
|
|
82
|
+
self.initialize_session(sess)
|
|
84
83
|
for sess in self._session_dict.get(
|
|
85
84
|
self._cli_type.lower(), self._registered_sessions
|
|
86
85
|
)
|
|
@@ -96,7 +96,6 @@ class SwitchCliHandler(CliHandlerImpl):
|
|
|
96
96
|
session.hardware_expect("exit", EnableCommandMode.PROMPT, logger)
|
|
97
97
|
|
|
98
98
|
def enter_enable_mode(self, session, logger):
|
|
99
|
-
|
|
100
99
|
enable_password = get_attribute_by_name(
|
|
101
100
|
attribute_name="Enable Password", context=self._context
|
|
102
101
|
)
|
|
@@ -40,6 +40,6 @@ if __name__ == "__main__":
|
|
|
40
40
|
out = session.send_command("echo checking switch")
|
|
41
41
|
with session.enter_mode(cli_handler.config_mode) as config_session:
|
|
42
42
|
out = config_session.send_command("echo checking switch")
|
|
43
|
-
print(out) # noqa:
|
|
43
|
+
print(out) # noqa: T201
|
|
44
44
|
out = config_session.send_command("echo checking switch")
|
|
45
|
-
print(out) # noqa:
|
|
45
|
+
print(out) # noqa: T201
|
|
@@ -13,7 +13,6 @@ class CliCommandMode(CommandMode):
|
|
|
13
13
|
EXIT_COMMAND = "exit"
|
|
14
14
|
|
|
15
15
|
def __init__(self, context):
|
|
16
|
-
|
|
17
16
|
CommandMode.__init__(
|
|
18
17
|
self,
|
|
19
18
|
CliCommandMode.PROMPT,
|
|
@@ -45,6 +44,6 @@ if __name__ == "__main__":
|
|
|
45
44
|
|
|
46
45
|
with cli.get_session(session, default_mode) as default_session:
|
|
47
46
|
out = default_session.send_command("echo Cli Demo connected to Ubuntu Machine")
|
|
48
|
-
print(out) # noqa:
|
|
47
|
+
print(out) # noqa: T201
|
|
49
48
|
fd = open("<src_file_path>")
|
|
50
49
|
default_session.session.upload_scp(fd, "<dst_file_path>", "<file_size>", "0666")
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
#!/usr/bin/python
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
from abc import ABCMeta, abstractmethod
|
|
4
|
+
|
|
5
|
+
ABC = ABCMeta("ABC", (object,), {"__slots__": ()})
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class SessionFactory(ABC):
|
|
9
|
+
"""Session factory.
|
|
10
|
+
|
|
11
|
+
Help to initialize session for specified session class.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
def __init__(self, session_class):
|
|
15
|
+
""":param session_class: Session class."""
|
|
16
|
+
self.session_class = session_class
|
|
17
|
+
|
|
18
|
+
@abstractmethod
|
|
19
|
+
def init_session(
|
|
20
|
+
self,
|
|
21
|
+
resource_config,
|
|
22
|
+
logger,
|
|
23
|
+
on_session_start=None,
|
|
24
|
+
access_key=None,
|
|
25
|
+
access_key_passphrase=None,
|
|
26
|
+
):
|
|
27
|
+
"""Initialize session instance.
|
|
28
|
+
|
|
29
|
+
Encapsulate the logic of the session instance creation.
|
|
30
|
+
:param resource_config:
|
|
31
|
+
:param logging.Logger logger:
|
|
32
|
+
:param on_session_start: function that will be called on session start
|
|
33
|
+
:param access_key: access key for the resource
|
|
34
|
+
:param access_key_passphrase: access key passphrase for the resource
|
|
35
|
+
"""
|
|
36
|
+
raise NotImplementedError
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class GenericSessionFactory(SessionFactory):
|
|
40
|
+
def init_session(
|
|
41
|
+
self,
|
|
42
|
+
resource_config,
|
|
43
|
+
logger,
|
|
44
|
+
on_session_start=None,
|
|
45
|
+
access_key=None,
|
|
46
|
+
access_key_passphrase=None,
|
|
47
|
+
):
|
|
48
|
+
return self.session_class(
|
|
49
|
+
**self._session_kwargs(
|
|
50
|
+
resource_config,
|
|
51
|
+
logger,
|
|
52
|
+
on_session_start,
|
|
53
|
+
access_key,
|
|
54
|
+
access_key_passphrase,
|
|
55
|
+
)
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
@property
|
|
59
|
+
def SESSION_TYPE(self):
|
|
60
|
+
return self.session_class.SESSION_TYPE
|
|
61
|
+
|
|
62
|
+
def _session_kwargs(
|
|
63
|
+
self,
|
|
64
|
+
resource_config,
|
|
65
|
+
logger,
|
|
66
|
+
on_session_start,
|
|
67
|
+
access_key,
|
|
68
|
+
access_key_passphrase,
|
|
69
|
+
):
|
|
70
|
+
return {
|
|
71
|
+
"host": resource_config.address,
|
|
72
|
+
"username": resource_config.user,
|
|
73
|
+
"password": resource_config.password,
|
|
74
|
+
"port": resource_config.cli_tcp_port,
|
|
75
|
+
"on_session_start": on_session_start,
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
class CloudInfoAccessKeySessionFactory(GenericSessionFactory):
|
|
80
|
+
def _session_kwargs(
|
|
81
|
+
self,
|
|
82
|
+
resource_config,
|
|
83
|
+
logger,
|
|
84
|
+
on_session_start,
|
|
85
|
+
access_key,
|
|
86
|
+
access_key_passphrase,
|
|
87
|
+
):
|
|
88
|
+
return {
|
|
89
|
+
"host": resource_config.address,
|
|
90
|
+
"username": resource_config.user,
|
|
91
|
+
"password": resource_config.password,
|
|
92
|
+
"port": resource_config.cli_tcp_port,
|
|
93
|
+
"pkey": access_key,
|
|
94
|
+
"pkey_passphrase": access_key_passphrase,
|
|
95
|
+
"on_session_start": on_session_start,
|
|
96
|
+
}
|
|
@@ -158,7 +158,8 @@ class CliServiceImpl(CliService):
|
|
|
158
158
|
steps = CommandModeHelper.calculate_route_steps(
|
|
159
159
|
self.command_mode, requested_command_mode
|
|
160
160
|
)
|
|
161
|
-
|
|
161
|
+
for s in steps:
|
|
162
|
+
s(self, self._logger)
|
|
162
163
|
|
|
163
164
|
def reconnect(self, timeout=None):
|
|
164
165
|
"""Reconnect session, keep current command mode.
|
|
@@ -35,7 +35,7 @@ class CommandModeHelper(NodeOperations):
|
|
|
35
35
|
|
|
36
36
|
:rtype: OrderedDict
|
|
37
37
|
"""
|
|
38
|
-
|
|
38
|
+
|
|
39
39
|
def _get_child_nodes(command_node):
|
|
40
40
|
return reduce(
|
|
41
41
|
lambda x, y: x + _get_child_nodes(y),
|
|
@@ -60,7 +60,7 @@ class CommandModeHelper(NodeOperations):
|
|
|
60
60
|
|
|
61
61
|
:rtype: dict
|
|
62
62
|
"""
|
|
63
|
-
|
|
63
|
+
|
|
64
64
|
def _create_child_modes(instance, child_dict):
|
|
65
65
|
instance_dict = {}
|
|
66
66
|
for mode_type in child_dict:
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import re
|
|
2
|
+
import socket
|
|
2
3
|
import time
|
|
3
4
|
from abc import ABCMeta, abstractmethod
|
|
4
5
|
from collections import OrderedDict
|
|
@@ -158,6 +159,51 @@ class ExpectSession(Session, ABC):
|
|
|
158
159
|
self.__class__.__name__, "Socket closed by timeout"
|
|
159
160
|
)
|
|
160
161
|
|
|
162
|
+
def _receive(self, timeout, logger):
|
|
163
|
+
"""Read session's buffer.
|
|
164
|
+
|
|
165
|
+
:type timeout: float
|
|
166
|
+
:type logger: logging.Logger
|
|
167
|
+
:rtype: str
|
|
168
|
+
"""
|
|
169
|
+
timeout = timeout or self._timeout
|
|
170
|
+
self._set_timeout(timeout)
|
|
171
|
+
try:
|
|
172
|
+
data = self._read_str_data()
|
|
173
|
+
except socket.timeout:
|
|
174
|
+
raise SessionReadTimeout
|
|
175
|
+
if not data:
|
|
176
|
+
raise SessionReadEmptyData
|
|
177
|
+
return data
|
|
178
|
+
|
|
179
|
+
@abstractmethod
|
|
180
|
+
def _set_timeout(self, timeout):
|
|
181
|
+
pass
|
|
182
|
+
|
|
183
|
+
def _read_str_data(self):
|
|
184
|
+
byte_data = b""
|
|
185
|
+
for _ in range(5):
|
|
186
|
+
new_data = self._read_byte_data()
|
|
187
|
+
|
|
188
|
+
if not new_data:
|
|
189
|
+
str_data = byte_data.decode()
|
|
190
|
+
break
|
|
191
|
+
|
|
192
|
+
byte_data += new_data
|
|
193
|
+
try:
|
|
194
|
+
str_data = byte_data.decode()
|
|
195
|
+
except UnicodeDecodeError:
|
|
196
|
+
continue # byte data can end with a wrong utf8 symbol, read more
|
|
197
|
+
else:
|
|
198
|
+
break
|
|
199
|
+
else:
|
|
200
|
+
str_data = byte_data.decode()
|
|
201
|
+
return str_data
|
|
202
|
+
|
|
203
|
+
@abstractmethod
|
|
204
|
+
def _read_byte_data(self):
|
|
205
|
+
pass
|
|
206
|
+
|
|
161
207
|
def _generate_command_pattern(self, command):
|
|
162
208
|
"""Generate command_pattern.
|
|
163
209
|
|
|
@@ -262,7 +308,6 @@ class ExpectSession(Session, ABC):
|
|
|
262
308
|
self._loop_detector_max_combination_length,
|
|
263
309
|
)
|
|
264
310
|
while retries == 0 or retries_count < retries:
|
|
265
|
-
|
|
266
311
|
read_buffer = self._receive_all(timeout, logger)
|
|
267
312
|
|
|
268
313
|
if read_buffer:
|
|
@@ -1,15 +1,11 @@
|
|
|
1
|
-
import
|
|
1
|
+
from io import StringIO
|
|
2
2
|
|
|
3
3
|
import paramiko
|
|
4
4
|
from scp import SCPClient
|
|
5
5
|
|
|
6
6
|
from cloudshell.cli.session.connection_params import ConnectionParams
|
|
7
7
|
from cloudshell.cli.session.expect_session import ExpectSession
|
|
8
|
-
from cloudshell.cli.session.session_exceptions import
|
|
9
|
-
SessionException,
|
|
10
|
-
SessionReadEmptyData,
|
|
11
|
-
SessionReadTimeout,
|
|
12
|
-
)
|
|
8
|
+
from cloudshell.cli.session.session_exceptions import SessionException
|
|
13
9
|
|
|
14
10
|
|
|
15
11
|
class SSHSessionException(SessionException):
|
|
@@ -28,6 +24,7 @@ class SSHSession(ExpectSession, ConnectionParams):
|
|
|
28
24
|
port=None,
|
|
29
25
|
on_session_start=None,
|
|
30
26
|
pkey=None,
|
|
27
|
+
pkey_passphrase=None,
|
|
31
28
|
*args,
|
|
32
29
|
**kwargs
|
|
33
30
|
):
|
|
@@ -42,6 +39,7 @@ class SSHSession(ExpectSession, ConnectionParams):
|
|
|
42
39
|
self.username = username
|
|
43
40
|
self.password = password
|
|
44
41
|
self.pkey = pkey
|
|
42
|
+
self.pkey_passphrase = pkey_passphrase
|
|
45
43
|
|
|
46
44
|
self._handler = None
|
|
47
45
|
self._current_channel = None
|
|
@@ -58,6 +56,7 @@ class SSHSession(ExpectSession, ConnectionParams):
|
|
|
58
56
|
self.username == other.username,
|
|
59
57
|
self.password == other.password,
|
|
60
58
|
self.pkey == other.pkey,
|
|
59
|
+
self.pkey_passphrase == other.pkey_passphrase,
|
|
61
60
|
]
|
|
62
61
|
)
|
|
63
62
|
|
|
@@ -86,7 +85,7 @@ class SSHSession(ExpectSession, ConnectionParams):
|
|
|
86
85
|
banner_timeout=30,
|
|
87
86
|
allow_agent=False,
|
|
88
87
|
look_for_keys=False,
|
|
89
|
-
pkey=self.pkey,
|
|
88
|
+
pkey=self._get_pkey_object(self.pkey, self.pkey_passphrase, logger),
|
|
90
89
|
)
|
|
91
90
|
except Exception as e:
|
|
92
91
|
logger.exception("Failed to initialize session:")
|
|
@@ -122,26 +121,11 @@ class SSHSession(ExpectSession, ConnectionParams):
|
|
|
122
121
|
"""
|
|
123
122
|
self._current_channel.send(command)
|
|
124
123
|
|
|
125
|
-
def
|
|
126
|
-
"""Read session buffer.
|
|
127
|
-
|
|
128
|
-
:param int timeout: time between retries
|
|
129
|
-
:param logging.Logger logger:
|
|
130
|
-
"""
|
|
131
|
-
# Set the channel timeout
|
|
132
|
-
timeout = timeout if timeout else self._timeout
|
|
124
|
+
def _set_timeout(self, timeout):
|
|
133
125
|
self._current_channel.settimeout(timeout)
|
|
134
126
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
data = byte_data.decode()
|
|
138
|
-
except socket.timeout:
|
|
139
|
-
raise SessionReadTimeout()
|
|
140
|
-
|
|
141
|
-
if not data:
|
|
142
|
-
raise SessionReadEmptyData()
|
|
143
|
-
|
|
144
|
-
return data
|
|
127
|
+
def _read_byte_data(self):
|
|
128
|
+
return self._current_channel.recv(self._buffer_size)
|
|
145
129
|
|
|
146
130
|
def upload_scp(
|
|
147
131
|
self, file_stream, dest_pathname, file_size=None, dest_permissions="0601"
|
|
@@ -182,3 +166,18 @@ class SSHSession(ExpectSession, ConnectionParams):
|
|
|
182
166
|
sftp.putfo(file_stream, dest_pathname)
|
|
183
167
|
sftp.chmod(dest_pathname, int(dest_permissions, base=8))
|
|
184
168
|
sftp.close()
|
|
169
|
+
|
|
170
|
+
@staticmethod
|
|
171
|
+
def _get_pkey_object(key_material, passphrase, logger):
|
|
172
|
+
"""Try to detect private key type and return paramiko.PKey object."""
|
|
173
|
+
if not key_material:
|
|
174
|
+
return None
|
|
175
|
+
|
|
176
|
+
for cls in [paramiko.RSAKey, paramiko.DSSKey, paramiko.ECDSAKey]:
|
|
177
|
+
try:
|
|
178
|
+
key = cls.from_private_key(StringIO(key_material), password=passphrase)
|
|
179
|
+
except paramiko.ssh_exception.SSHException as e:
|
|
180
|
+
# Invalid key, try other key type
|
|
181
|
+
logger.warning(e)
|
|
182
|
+
else:
|
|
183
|
+
return key
|
|
@@ -2,14 +2,9 @@ import socket
|
|
|
2
2
|
|
|
3
3
|
from cloudshell.cli.session.connection_params import ConnectionParams
|
|
4
4
|
from cloudshell.cli.session.expect_session import ExpectSession
|
|
5
|
-
from cloudshell.cli.session.session_exceptions import (
|
|
6
|
-
SessionReadEmptyData,
|
|
7
|
-
SessionReadTimeout,
|
|
8
|
-
)
|
|
9
5
|
|
|
10
6
|
|
|
11
7
|
class TCPSession(ExpectSession, ConnectionParams):
|
|
12
|
-
|
|
13
8
|
SESSION_TYPE = "TCP"
|
|
14
9
|
BUFFER_SIZE = 1024
|
|
15
10
|
|
|
@@ -49,17 +44,11 @@ class TCPSession(ExpectSession, ConnectionParams):
|
|
|
49
44
|
"""
|
|
50
45
|
self._handler.sendall(command)
|
|
51
46
|
|
|
52
|
-
def
|
|
53
|
-
"""Read session buffer."""
|
|
54
|
-
timeout = timeout if timeout else self._timeout
|
|
47
|
+
def _set_timeout(self, timeout):
|
|
55
48
|
self._handler.settimeout(timeout)
|
|
56
49
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
except socket.timeout:
|
|
60
|
-
raise SessionReadTimeout()
|
|
61
|
-
|
|
62
|
-
if not data:
|
|
63
|
-
raise SessionReadEmptyData()
|
|
50
|
+
def _read_byte_data(self):
|
|
51
|
+
pass
|
|
64
52
|
|
|
65
|
-
|
|
53
|
+
def _read_str_data(self):
|
|
54
|
+
return self._handler.recv(self._buffer_size)
|
|
@@ -1,14 +1,9 @@
|
|
|
1
|
-
import socket
|
|
2
1
|
import telnetlib
|
|
3
2
|
from collections import OrderedDict
|
|
4
3
|
|
|
5
4
|
from cloudshell.cli.session.connection_params import ConnectionParams
|
|
6
5
|
from cloudshell.cli.session.expect_session import ExpectSession
|
|
7
|
-
from cloudshell.cli.session.session_exceptions import
|
|
8
|
-
SessionException,
|
|
9
|
-
SessionReadEmptyData,
|
|
10
|
-
SessionReadTimeout,
|
|
11
|
-
)
|
|
6
|
+
from cloudshell.cli.session.session_exceptions import SessionException
|
|
12
7
|
|
|
13
8
|
|
|
14
9
|
class TelnetSessionException(SessionException):
|
|
@@ -100,18 +95,8 @@ class TelnetSession(ExpectSession, ConnectionParams):
|
|
|
100
95
|
byte_command = command.encode()
|
|
101
96
|
self._handler.write(byte_command)
|
|
102
97
|
|
|
103
|
-
def
|
|
104
|
-
"""Read session buffer."""
|
|
105
|
-
timeout = timeout if timeout else self._timeout
|
|
98
|
+
def _set_timeout(self, timeout):
|
|
106
99
|
self._handler.get_socket().settimeout(timeout)
|
|
107
100
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
except socket.timeout:
|
|
111
|
-
raise SessionReadTimeout()
|
|
112
|
-
|
|
113
|
-
if not byte_data:
|
|
114
|
-
raise SessionReadEmptyData()
|
|
115
|
-
|
|
116
|
-
data = byte_data.decode()
|
|
117
|
-
return data
|
|
101
|
+
def _read_byte_data(self):
|
|
102
|
+
self._handler.read_some()
|
|
File without changes
|
|
@@ -1,14 +1,11 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: cloudshell-cli
|
|
3
|
-
Version: 4.
|
|
3
|
+
Version: 4.1.1
|
|
4
4
|
Summary: QualiSystems CloudShell CLI support package
|
|
5
5
|
Home-page: http://www.qualisystems.com/
|
|
6
6
|
Author: QualiSystems
|
|
7
7
|
Author-email: info@qualisystems.com
|
|
8
|
-
License: UNKNOWN
|
|
9
|
-
Platform: UNKNOWN
|
|
10
8
|
Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, !=3.6.*, <4
|
|
11
9
|
License-File: LICENSE
|
|
12
10
|
|
|
13
|
-
|
|
14
|
-
|
|
11
|
+
QualiSystems CloudShell CLI support package
|
|
@@ -26,6 +26,8 @@ cloudshell/cli/examples/cli_demo/connect_to_switch/runner.py
|
|
|
26
26
|
cloudshell/cli/examples/cli_demo/connect_to_ubuntu/__init__.py
|
|
27
27
|
cloudshell/cli/examples/cli_demo/connect_to_ubuntu/readfrom.txt
|
|
28
28
|
cloudshell/cli/examples/cli_demo/connect_to_ubuntu/runnur.py
|
|
29
|
+
cloudshell/cli/factory/__init__.py
|
|
30
|
+
cloudshell/cli/factory/session_factory.py
|
|
29
31
|
cloudshell/cli/service/__init__.py
|
|
30
32
|
cloudshell/cli/service/cli.py
|
|
31
33
|
cloudshell/cli/service/cli_exception.py
|
|
@@ -57,6 +59,7 @@ cloudshell_cli.egg-info/dependency_links.txt
|
|
|
57
59
|
cloudshell_cli.egg-info/requires.txt
|
|
58
60
|
cloudshell_cli.egg-info/top_level.txt
|
|
59
61
|
tests/__init__.py
|
|
62
|
+
tests/conftest.py
|
|
60
63
|
tests/cli/__init__.py
|
|
61
64
|
tests/cli/test_cli.py
|
|
62
65
|
tests/cli/test_cli_service_impl.py
|
|
@@ -71,5 +74,6 @@ tests/cli/command_template/test_command_template.py
|
|
|
71
74
|
tests/cli/session/__init__.py
|
|
72
75
|
tests/cli/session/test_connection_params.py
|
|
73
76
|
tests/cli/session/test_expect_session.py
|
|
77
|
+
tests/cli/session/test_expect_session_py3.py
|
|
74
78
|
tests/cli/session/test_ssh_session.py
|
|
75
79
|
tests/cli/session/test_telnet_session.py
|
|
@@ -15,7 +15,7 @@ except ImportError:
|
|
|
15
15
|
from mock import MagicMock, Mock, call, patch
|
|
16
16
|
|
|
17
17
|
|
|
18
|
-
class
|
|
18
|
+
class ExpectSessionException(Exception):
|
|
19
19
|
pass
|
|
20
20
|
|
|
21
21
|
|
|
@@ -32,10 +32,13 @@ class ExpectSessionImpl(ExpectSession):
|
|
|
32
32
|
def disconnect(self):
|
|
33
33
|
pass
|
|
34
34
|
|
|
35
|
-
def
|
|
35
|
+
def _send(self, command, logger):
|
|
36
36
|
pass
|
|
37
37
|
|
|
38
|
-
def
|
|
38
|
+
def _read_byte_data(self):
|
|
39
|
+
pass
|
|
40
|
+
|
|
41
|
+
def _set_timeout(self, timeout):
|
|
39
42
|
pass
|
|
40
43
|
|
|
41
44
|
|
|
@@ -98,7 +101,7 @@ class TestExpectSession(TestCase):
|
|
|
98
101
|
self._instance._clear_buffer(timeout, self._logger)
|
|
99
102
|
|
|
100
103
|
def test_clear_buffer_exit_with_no_data(self, normalize_buffer, loops_detected):
|
|
101
|
-
self._receive.side_effect = ["",
|
|
104
|
+
self._receive.side_effect = ["", ExpectSessionException("Breaking loop")]
|
|
102
105
|
timeout = Mock()
|
|
103
106
|
self._instance._clear_buffer(timeout, self._logger)
|
|
104
107
|
self.assertTrue(True)
|
|
@@ -109,7 +112,7 @@ class TestExpectSession(TestCase):
|
|
|
109
112
|
self._receive.side_effect = [
|
|
110
113
|
"test",
|
|
111
114
|
"",
|
|
112
|
-
|
|
115
|
+
ExpectSessionException("Breaking loop"),
|
|
113
116
|
]
|
|
114
117
|
timeout = Mock()
|
|
115
118
|
self._instance._clear_buffer(timeout, self._logger)
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
from tests.cli.session.test_expect_session import ExpectSessionImpl
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def test_expect_session_read_wrong_utf8_symbol(logger):
|
|
5
|
+
class TestSession(ExpectSessionImpl):
|
|
6
|
+
data = [b"\xe2\x80\x99hi\xe2", b"\x80\x99"] # ’hi’
|
|
7
|
+
|
|
8
|
+
def _read_byte_data(self):
|
|
9
|
+
return self.data.pop(0)
|
|
10
|
+
|
|
11
|
+
session = TestSession()
|
|
12
|
+
|
|
13
|
+
assert session._receive(1, logger) == "’hi’"
|
|
@@ -46,7 +46,7 @@ y9/ziFJPPMN703N1dJ0e1oRWpfSFUzlGn1OgF1EY9qQTwQK4PL9bhyJi1/MswZHB
|
|
|
46
46
|
/XmDlKr7An89Iy+B/Q9ncja2FfK49AP23AMYKhdWBrEq+enXwjkr5Uz8ffD3eagD
|
|
47
47
|
VZxBlCGUp4bmlS5s7sttMZRvJq0CXfxy+q8Qe0sz/CyOAN/J8iZu8AJyp04DQk4d
|
|
48
48
|
-----END RSA PRIVATE KEY-----
|
|
49
|
-
"""
|
|
49
|
+
""" # noqa
|
|
50
50
|
KEY_PASSPHRASE = "quali1234"
|
|
51
51
|
|
|
52
52
|
|
|
@@ -443,9 +443,6 @@ class TestSshSession(TestCase):
|
|
|
443
443
|
)
|
|
444
444
|
)
|
|
445
445
|
|
|
446
|
-
pkey = paramiko.RSAKey.from_private_key(
|
|
447
|
-
StringIO(KEY_WITH_PASSPHRASE), password=KEY_PASSPHRASE
|
|
448
|
-
)
|
|
449
446
|
self.assertFalse(
|
|
450
447
|
self._instance.__eq__(
|
|
451
448
|
SSHSession(
|
|
@@ -454,23 +451,22 @@ class TestSshSession(TestCase):
|
|
|
454
451
|
"",
|
|
455
452
|
port=self._port,
|
|
456
453
|
on_session_start=self._on_session_start,
|
|
457
|
-
pkey=
|
|
454
|
+
pkey=KEY_WITH_PASSPHRASE,
|
|
455
|
+
pkey_passphrase=KEY_PASSPHRASE,
|
|
458
456
|
)
|
|
459
457
|
)
|
|
460
458
|
)
|
|
461
459
|
|
|
462
460
|
@patch("cloudshell.cli.session.ssh_session.ExpectSession")
|
|
463
461
|
def test_eq_rsa(self, expect_session):
|
|
464
|
-
pkey = paramiko.RSAKey.from_private_key(
|
|
465
|
-
StringIO(KEY_WITH_PASSPHRASE), password=KEY_PASSPHRASE
|
|
466
|
-
)
|
|
467
462
|
self._instance = SSHSession(
|
|
468
463
|
self._hostname,
|
|
469
464
|
self._username,
|
|
470
465
|
self._password,
|
|
471
466
|
port=self._port,
|
|
472
467
|
on_session_start=self._on_session_start,
|
|
473
|
-
pkey=
|
|
468
|
+
pkey=KEY_WITH_PASSPHRASE,
|
|
469
|
+
pkey_passphrase=KEY_PASSPHRASE,
|
|
474
470
|
)
|
|
475
471
|
|
|
476
472
|
self.assertTrue(
|
|
@@ -481,7 +477,8 @@ class TestSshSession(TestCase):
|
|
|
481
477
|
self._password,
|
|
482
478
|
port=self._port,
|
|
483
479
|
on_session_start=self._on_session_start,
|
|
484
|
-
pkey=
|
|
480
|
+
pkey=KEY_WITH_PASSPHRASE,
|
|
481
|
+
pkey_passphrase=KEY_PASSPHRASE,
|
|
485
482
|
)
|
|
486
483
|
)
|
|
487
484
|
)
|
|
@@ -640,16 +637,13 @@ class TestSshSession(TestCase):
|
|
|
640
637
|
"",
|
|
641
638
|
port=server.port,
|
|
642
639
|
on_session_start=self._on_session_start,
|
|
643
|
-
pkey=
|
|
640
|
+
pkey=KEY_WITH_PASSPHRASE,
|
|
641
|
+
pkey_passphrase=KEY_PASSPHRASE,
|
|
644
642
|
)
|
|
645
643
|
self._instance.connect(">", logger=Mock())
|
|
646
644
|
self._instance.hardware_expect("dummy command", ">", Mock())
|
|
647
645
|
|
|
648
646
|
def test_rsa_failure(self):
|
|
649
|
-
pkey = paramiko.RSAKey.from_private_key(
|
|
650
|
-
StringIO(KEY_WITH_PASSPHRASE), password=KEY_PASSPHRASE
|
|
651
|
-
)
|
|
652
|
-
|
|
653
647
|
server = SSHServer(user2key={})
|
|
654
648
|
|
|
655
649
|
with self.assertRaises(SSHSessionException):
|
|
@@ -659,7 +653,8 @@ class TestSshSession(TestCase):
|
|
|
659
653
|
"",
|
|
660
654
|
port=server.port,
|
|
661
655
|
on_session_start=self._on_session_start,
|
|
662
|
-
pkey=
|
|
656
|
+
pkey=KEY_WITH_PASSPHRASE,
|
|
657
|
+
pkey_passphrase=KEY_PASSPHRASE,
|
|
663
658
|
)
|
|
664
659
|
self._instance.connect(">", logger=Mock())
|
|
665
660
|
self._instance.hardware_expect("dummy command", ">", Mock())
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
import sys
|
|
3
|
+
|
|
4
|
+
import pytest
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
@pytest.fixture()
|
|
8
|
+
def logger():
|
|
9
|
+
return logging.getLogger(__file__)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def pytest_ignore_collect(path):
|
|
13
|
+
if sys.version_info.major == 2:
|
|
14
|
+
if str(path).endswith("_py3.py"):
|
|
15
|
+
return True
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
4.1.1
|
cloudshell-cli-4.0.5/version.txt
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
4.0.5
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cloudshell-cli-4.0.5 → cloudshell-cli-4.1.1}/cloudshell/cli/command_template/command_template.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cloudshell-cli-4.0.5 → cloudshell-cli-4.1.1}/cloudshell/cli/service/session_manager_impl.py
RENAMED
|
File without changes
|
|
File without changes
|
{cloudshell-cli-4.0.5 → cloudshell-cli-4.1.1}/cloudshell/cli/service/session_pool_context_manager.py
RENAMED
|
File without changes
|
{cloudshell-cli-4.0.5 → cloudshell-cli-4.1.1}/cloudshell/cli/service/session_pool_manager.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cloudshell-cli-4.0.5 → cloudshell-cli-4.1.1}/cloudshell/cli/session/helper/normalize_buffer.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cloudshell-cli-4.0.5 → cloudshell-cli-4.1.1}/tests/cli/command_template/test_command_template.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cloudshell-cli-4.0.5 → cloudshell-cli-4.1.1}/tests/cli/test_session_pool_context_manager.py
RENAMED
|
File without changes
|
|
File without changes
|