shellfoundry 1.2.25__py3-none-any.whl
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.
- shellfoundry/__init__.py +8 -0
- shellfoundry/__main__.py +7 -0
- shellfoundry/bootstrap.py +169 -0
- shellfoundry/commands/__init__.py +0 -0
- shellfoundry/commands/config_command.py +87 -0
- shellfoundry/commands/delete_command.py +24 -0
- shellfoundry/commands/dist_command.py +34 -0
- shellfoundry/commands/extend_command.py +182 -0
- shellfoundry/commands/generate_command.py +44 -0
- shellfoundry/commands/get_templates_command.py +151 -0
- shellfoundry/commands/install_command.py +81 -0
- shellfoundry/commands/list_command.py +110 -0
- shellfoundry/commands/new_command.py +393 -0
- shellfoundry/commands/pack_command.py +45 -0
- shellfoundry/commands/show_command.py +55 -0
- shellfoundry/data/standards.json +44 -0
- shellfoundry/data/templates.yml +117 -0
- shellfoundry/decorators/__init__.py +1 -0
- shellfoundry/decorators/standards.py +20 -0
- shellfoundry/decorators/version_check.py +52 -0
- shellfoundry/exceptions.py +52 -0
- shellfoundry/models/__init__.py +0 -0
- shellfoundry/models/install_config.py +82 -0
- shellfoundry/models/shell_template.py +22 -0
- shellfoundry/models/shellfoundry_settings.py +13 -0
- shellfoundry/utilities/__init__.py +114 -0
- shellfoundry/utilities/archive_creator.py +35 -0
- shellfoundry/utilities/cloudshell_api/__init__.py +1 -0
- shellfoundry/utilities/cloudshell_api/client_wrapper.py +71 -0
- shellfoundry/utilities/config/__init__.py +0 -0
- shellfoundry/utilities/config/config_context.py +44 -0
- shellfoundry/utilities/config/config_file_creation.py +32 -0
- shellfoundry/utilities/config/config_providers.py +50 -0
- shellfoundry/utilities/config/config_record.py +24 -0
- shellfoundry/utilities/config_reader.py +154 -0
- shellfoundry/utilities/constants.py +37 -0
- shellfoundry/utilities/cookiecutter_integration.py +67 -0
- shellfoundry/utilities/driver_generator.py +121 -0
- shellfoundry/utilities/filters.py +45 -0
- shellfoundry/utilities/installer.py +44 -0
- shellfoundry/utilities/modifiers/__init__.py +0 -0
- shellfoundry/utilities/modifiers/configuration/__init__.py +0 -0
- shellfoundry/utilities/modifiers/configuration/aggregated_modifiers.py +26 -0
- shellfoundry/utilities/modifiers/configuration/password_modification.py +48 -0
- shellfoundry/utilities/modifiers/definition/__init__.py +0 -0
- shellfoundry/utilities/modifiers/definition/definition_modification.py +205 -0
- shellfoundry/utilities/package_builder.py +152 -0
- shellfoundry/utilities/python_dependencies_packager.py +53 -0
- shellfoundry/utilities/repository_downloader.py +76 -0
- shellfoundry/utilities/shell_config_reader.py +59 -0
- shellfoundry/utilities/shell_datamodel_merger.py +44 -0
- shellfoundry/utilities/shell_package.py +59 -0
- shellfoundry/utilities/shell_package_builder.py +149 -0
- shellfoundry/utilities/shell_package_installer.py +231 -0
- shellfoundry/utilities/standards/__init__.py +3 -0
- shellfoundry/utilities/standards/consts.py +2 -0
- shellfoundry/utilities/standards/standards_retriever.py +32 -0
- shellfoundry/utilities/standards/standards_versions.py +34 -0
- shellfoundry/utilities/temp_dir_context.py +17 -0
- shellfoundry/utilities/template_retriever.py +309 -0
- shellfoundry/utilities/template_url.py +38 -0
- shellfoundry/utilities/template_versions.py +47 -0
- shellfoundry/utilities/validations/__init__.py +2 -0
- shellfoundry/utilities/validations/shell_generation_validation.py +29 -0
- shellfoundry/utilities/validations/shell_name_validations.py +10 -0
- shellfoundry/utilities/version_utilities.py +19 -0
- shellfoundry-1.2.25.dist-info/LICENSE +201 -0
- shellfoundry-1.2.25.dist-info/METADATA +417 -0
- shellfoundry-1.2.25.dist-info/RECORD +72 -0
- shellfoundry-1.2.25.dist-info/WHEEL +5 -0
- shellfoundry-1.2.25.dist-info/entry_points.txt +2 -0
- shellfoundry-1.2.25.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
#!/usr/bin/python
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
|
|
4
|
+
import os
|
|
5
|
+
import shutil
|
|
6
|
+
from threading import Thread, currentThread
|
|
7
|
+
|
|
8
|
+
import click
|
|
9
|
+
import yaml
|
|
10
|
+
from requests.exceptions import SSLError
|
|
11
|
+
|
|
12
|
+
from shellfoundry.exceptions import VersionRequestException
|
|
13
|
+
from shellfoundry.utilities.config_reader import CloudShellConfigReader, Configuration
|
|
14
|
+
from shellfoundry.utilities.repository_downloader import RepositoryDownloader
|
|
15
|
+
from shellfoundry.utilities.temp_dir_context import TempDirContext
|
|
16
|
+
from shellfoundry.utilities.template_retriever import TemplateRetriever
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class GetTemplatesCommandExecutor(object):
|
|
20
|
+
def __init__(self, repository_downloader=None, template_retriever=None):
|
|
21
|
+
"""Download all templates relevant to provided CloudShell Version.
|
|
22
|
+
|
|
23
|
+
:param TemplateRetriever template_retriever:
|
|
24
|
+
:param RepositoryDownloader repository_downloader:
|
|
25
|
+
"""
|
|
26
|
+
self.cloudshell_config_reader = Configuration(CloudShellConfigReader())
|
|
27
|
+
self.template_retriever = template_retriever or TemplateRetriever()
|
|
28
|
+
self.repository_downloader = repository_downloader or RepositoryDownloader()
|
|
29
|
+
|
|
30
|
+
def get_templates(self, cs_version, output_dir=None):
|
|
31
|
+
"""Download all templates relevant to provided CloudShell Version.
|
|
32
|
+
|
|
33
|
+
:param str cs_version: The desired version of the CloudShell
|
|
34
|
+
:param str output_dir: Output directory to download templates
|
|
35
|
+
"""
|
|
36
|
+
shellfoundry_config = self.cloudshell_config_reader.read()
|
|
37
|
+
online_mode = shellfoundry_config.online_mode.lower() == "true"
|
|
38
|
+
if online_mode:
|
|
39
|
+
try:
|
|
40
|
+
response = self.template_retriever._get_templates_from_github()
|
|
41
|
+
config = yaml.safe_load(response)
|
|
42
|
+
repos = {template["repository"] for template in config["templates"]}
|
|
43
|
+
|
|
44
|
+
if not output_dir:
|
|
45
|
+
output_dir = os.path.abspath(os.path.curdir)
|
|
46
|
+
|
|
47
|
+
archive_name = "shellfoundry_templates_{}".format(cs_version)
|
|
48
|
+
|
|
49
|
+
archive_path = os.path.join(output_dir, "{}.zip".format(archive_name))
|
|
50
|
+
if os.path.exists(archive_path):
|
|
51
|
+
click.confirm(
|
|
52
|
+
text="Templates archive for CloudShell Version {cs_version} already exists in path {path}." # noqa: E501
|
|
53
|
+
"\nDo you wish to overwrite it?".format(
|
|
54
|
+
cs_version=cs_version, path=archive_path
|
|
55
|
+
),
|
|
56
|
+
abort=True,
|
|
57
|
+
)
|
|
58
|
+
os.remove(archive_path)
|
|
59
|
+
|
|
60
|
+
with TempDirContext(archive_name) as temp_dir:
|
|
61
|
+
templates_path = temp_dir
|
|
62
|
+
threads = []
|
|
63
|
+
errors = []
|
|
64
|
+
for i, repo in enumerate(repos):
|
|
65
|
+
template_thread = Thread(
|
|
66
|
+
name=str(i),
|
|
67
|
+
target=self.download_template,
|
|
68
|
+
args=(
|
|
69
|
+
repo,
|
|
70
|
+
cs_version,
|
|
71
|
+
templates_path,
|
|
72
|
+
shellfoundry_config.github_login,
|
|
73
|
+
shellfoundry_config.github_password,
|
|
74
|
+
errors,
|
|
75
|
+
),
|
|
76
|
+
)
|
|
77
|
+
threads.append(template_thread)
|
|
78
|
+
|
|
79
|
+
for thread in threads:
|
|
80
|
+
thread.start()
|
|
81
|
+
for thread in threads:
|
|
82
|
+
thread.join()
|
|
83
|
+
|
|
84
|
+
if errors:
|
|
85
|
+
raise click.ClickException(errors[0])
|
|
86
|
+
|
|
87
|
+
os.chdir(output_dir)
|
|
88
|
+
shutil.make_archive(archive_name, "zip", templates_path)
|
|
89
|
+
|
|
90
|
+
click.echo(
|
|
91
|
+
"Downloaded templates for CloudShell {cs_version} to {templates}".format( # noqa: E501
|
|
92
|
+
cs_version=cs_version, templates=os.path.abspath(archive_path)
|
|
93
|
+
)
|
|
94
|
+
)
|
|
95
|
+
except SSLError:
|
|
96
|
+
raise click.UsageError(
|
|
97
|
+
"Could not retrieve the templates list to download. Are you offline?" # noqa: E501
|
|
98
|
+
)
|
|
99
|
+
else:
|
|
100
|
+
click.echo(
|
|
101
|
+
"Please, move shellfoundry to online mode. See, shellfoundry config command" # noqa: E501
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
def download_template(
|
|
105
|
+
self,
|
|
106
|
+
repository,
|
|
107
|
+
cs_version,
|
|
108
|
+
templates_path,
|
|
109
|
+
github_login,
|
|
110
|
+
github_password,
|
|
111
|
+
errors,
|
|
112
|
+
):
|
|
113
|
+
try:
|
|
114
|
+
result_branch = self.template_retriever.get_latest_template(
|
|
115
|
+
repository, cs_version, github_login, github_password
|
|
116
|
+
)
|
|
117
|
+
|
|
118
|
+
if result_branch:
|
|
119
|
+
try:
|
|
120
|
+
template_path = os.path.join(
|
|
121
|
+
templates_path, currentThread().getName()
|
|
122
|
+
)
|
|
123
|
+
os.mkdir(template_path)
|
|
124
|
+
res = self.repository_downloader.download_template(
|
|
125
|
+
target_dir=template_path,
|
|
126
|
+
repo_address=repository,
|
|
127
|
+
branch=result_branch,
|
|
128
|
+
is_need_construct=True,
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
shutil.copytree(
|
|
132
|
+
res, os.path.join(templates_path, repository.split("/")[-1])
|
|
133
|
+
)
|
|
134
|
+
shutil.rmtree(path=template_path, ignore_errors=True)
|
|
135
|
+
except VersionRequestException:
|
|
136
|
+
errors.append(
|
|
137
|
+
"Failed to download template from repository {} version {}".format( # noqa: E501
|
|
138
|
+
repository, result_branch
|
|
139
|
+
)
|
|
140
|
+
)
|
|
141
|
+
except shutil.Error:
|
|
142
|
+
errors.append(
|
|
143
|
+
"Failed to build correct template '{}' structure".format(
|
|
144
|
+
repository
|
|
145
|
+
)
|
|
146
|
+
)
|
|
147
|
+
finally:
|
|
148
|
+
pass
|
|
149
|
+
|
|
150
|
+
except click.ClickException as err:
|
|
151
|
+
errors.append(str(err))
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# !/usr/bin/python
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
|
|
4
|
+
import os
|
|
5
|
+
|
|
6
|
+
import click
|
|
7
|
+
|
|
8
|
+
try:
|
|
9
|
+
# Python 2.x version
|
|
10
|
+
from urllib2 import HTTPError, URLError
|
|
11
|
+
except ImportError:
|
|
12
|
+
# Python 3.x version
|
|
13
|
+
from urllib.error import HTTPError, URLError
|
|
14
|
+
|
|
15
|
+
from shellfoundry.exceptions import FatalError
|
|
16
|
+
from shellfoundry.utilities.config_reader import CloudShellConfigReader, Configuration
|
|
17
|
+
from shellfoundry.utilities.installer import ShellInstaller
|
|
18
|
+
from shellfoundry.utilities.shell_config_reader import ShellConfigReader
|
|
19
|
+
from shellfoundry.utilities.shell_package import ShellPackage
|
|
20
|
+
from shellfoundry.utilities.shell_package_installer import ShellPackageInstaller
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class InstallCommandExecutor(object):
|
|
24
|
+
def __init__(
|
|
25
|
+
self,
|
|
26
|
+
cloudshell_config_reader=None,
|
|
27
|
+
installer=None,
|
|
28
|
+
shell_config_reader=None,
|
|
29
|
+
shell_package_installer=None,
|
|
30
|
+
):
|
|
31
|
+
self.cloudshell_config_reader = cloudshell_config_reader or Configuration(
|
|
32
|
+
CloudShellConfigReader()
|
|
33
|
+
)
|
|
34
|
+
self.installer = installer or ShellInstaller()
|
|
35
|
+
self.shell_config_reader = shell_config_reader or ShellConfigReader()
|
|
36
|
+
self.shell_package_installer = (
|
|
37
|
+
shell_package_installer or ShellPackageInstaller()
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
def install(self):
|
|
41
|
+
current_path = os.getcwd()
|
|
42
|
+
shell_package = ShellPackage(current_path)
|
|
43
|
+
if shell_package.is_layer_one():
|
|
44
|
+
click.secho(
|
|
45
|
+
"Installing a L1 shell directly via shellfoundry is not supported. "
|
|
46
|
+
"Please follow the L1 shell import procedure described in help.quali.com.", # noqa: E501
|
|
47
|
+
fg="yellow",
|
|
48
|
+
)
|
|
49
|
+
else:
|
|
50
|
+
if shell_package.is_tosca():
|
|
51
|
+
self.shell_package_installer.install(current_path)
|
|
52
|
+
else:
|
|
53
|
+
self._install_old_school_shell()
|
|
54
|
+
click.secho("Successfully installed shell", fg="green")
|
|
55
|
+
|
|
56
|
+
def _install_old_school_shell(self):
|
|
57
|
+
error = None
|
|
58
|
+
try:
|
|
59
|
+
cloudshell_config = self.cloudshell_config_reader.read()
|
|
60
|
+
shell_config = self.shell_config_reader.read()
|
|
61
|
+
self.installer.install(shell_config.name, cloudshell_config)
|
|
62
|
+
except HTTPError as e:
|
|
63
|
+
if e.code == 401:
|
|
64
|
+
raise FatalError(
|
|
65
|
+
"Login to CloudShell failed. "
|
|
66
|
+
"Please verify the credentials in the config"
|
|
67
|
+
)
|
|
68
|
+
error = str(e)
|
|
69
|
+
except URLError:
|
|
70
|
+
raise FatalError(
|
|
71
|
+
"Connection to CloudShell Server failed. "
|
|
72
|
+
"Please make sure it is up and running properly."
|
|
73
|
+
)
|
|
74
|
+
except Exception as e:
|
|
75
|
+
error = str(e)
|
|
76
|
+
|
|
77
|
+
if error:
|
|
78
|
+
raise FatalError(
|
|
79
|
+
"Failed to install shell. "
|
|
80
|
+
"CloudShell responded with: '{}'".format(error)
|
|
81
|
+
)
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
#!/usr/bin/python
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
|
|
4
|
+
from os import linesep
|
|
5
|
+
from textwrap import wrap
|
|
6
|
+
|
|
7
|
+
import click
|
|
8
|
+
from cloudshell.rest.exceptions import FeatureUnavailable
|
|
9
|
+
from requests.exceptions import SSLError
|
|
10
|
+
from terminaltables import AsciiTable
|
|
11
|
+
|
|
12
|
+
from ..exceptions import FatalError
|
|
13
|
+
|
|
14
|
+
from shellfoundry import ALTERNATIVE_TEMPLATES_PATH
|
|
15
|
+
from shellfoundry.utilities.config_reader import (
|
|
16
|
+
CloudShellConfigReader,
|
|
17
|
+
Configuration,
|
|
18
|
+
ShellFoundryConfig,
|
|
19
|
+
)
|
|
20
|
+
from shellfoundry.utilities.standards import Standards
|
|
21
|
+
from shellfoundry.utilities.template_retriever import (
|
|
22
|
+
FilteredTemplateRetriever,
|
|
23
|
+
TemplateRetriever,
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class ListCommandExecutor(object):
|
|
28
|
+
def __init__(self, default_view=None, template_retriever=None, standards=None):
|
|
29
|
+
dv = default_view or Configuration(ShellFoundryConfig()).read().defaultview
|
|
30
|
+
self.template_retriever = template_retriever or FilteredTemplateRetriever(
|
|
31
|
+
dv, TemplateRetriever()
|
|
32
|
+
)
|
|
33
|
+
self.show_info_msg = default_view is None
|
|
34
|
+
self.standards = standards or Standards()
|
|
35
|
+
self.cloudshell_config_reader = Configuration(CloudShellConfigReader())
|
|
36
|
+
|
|
37
|
+
def list(self): # noqa: A003
|
|
38
|
+
online_mode = self.cloudshell_config_reader.read().online_mode.lower() == "true"
|
|
39
|
+
template_location = self.cloudshell_config_reader.read().template_location
|
|
40
|
+
|
|
41
|
+
try:
|
|
42
|
+
standards = self.standards.fetch()
|
|
43
|
+
if online_mode:
|
|
44
|
+
try:
|
|
45
|
+
templates = self.template_retriever.get_templates(
|
|
46
|
+
standards=standards
|
|
47
|
+
)
|
|
48
|
+
except SSLError:
|
|
49
|
+
raise click.UsageError(
|
|
50
|
+
"Could not retrieve the templates list. Are you offline?"
|
|
51
|
+
)
|
|
52
|
+
else:
|
|
53
|
+
templates = self.template_retriever.get_templates(
|
|
54
|
+
template_location=template_location, standards=standards
|
|
55
|
+
)
|
|
56
|
+
except FatalError as err:
|
|
57
|
+
raise click.UsageError(str(err))
|
|
58
|
+
except FeatureUnavailable:
|
|
59
|
+
if online_mode:
|
|
60
|
+
templates = self.template_retriever.get_templates(
|
|
61
|
+
alternative=ALTERNATIVE_TEMPLATES_PATH
|
|
62
|
+
)
|
|
63
|
+
else:
|
|
64
|
+
templates = self.template_retriever.get_templates(
|
|
65
|
+
template_location=template_location
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
if not templates:
|
|
69
|
+
raise click.ClickException(
|
|
70
|
+
"No templates matched the view criteria(gen1/gen2) or "
|
|
71
|
+
"available templates and standards are not compatible"
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
template_rows = [["Template Name", "CloudShell Ver.", "Description"]]
|
|
75
|
+
for template in list(templates.values()):
|
|
76
|
+
template = template[0]
|
|
77
|
+
cs_ver_txt = str(template.min_cs_ver) + " and up"
|
|
78
|
+
template_rows.append(
|
|
79
|
+
[template.name, cs_ver_txt, template.description]
|
|
80
|
+
) # description is later wrapped based on the size of the console
|
|
81
|
+
|
|
82
|
+
table = AsciiTable(template_rows)
|
|
83
|
+
table.outer_border = False
|
|
84
|
+
table.inner_column_border = False
|
|
85
|
+
max_width = table.column_max_width(2)
|
|
86
|
+
|
|
87
|
+
if max_width <= 0: # verify that the console window is not too small,
|
|
88
|
+
# and if so skip the wrapping logic
|
|
89
|
+
click.echo(table.table)
|
|
90
|
+
return
|
|
91
|
+
|
|
92
|
+
row = 1
|
|
93
|
+
for template in list(templates.values()):
|
|
94
|
+
template = template[0]
|
|
95
|
+
wrapped_string = linesep.join(wrap(template.description, max_width))
|
|
96
|
+
table.table_data[row][2] = wrapped_string
|
|
97
|
+
row += 1
|
|
98
|
+
|
|
99
|
+
output = table.table
|
|
100
|
+
click.echo(output)
|
|
101
|
+
|
|
102
|
+
if self.show_info_msg:
|
|
103
|
+
click.echo(
|
|
104
|
+
"""
|
|
105
|
+
As of CloudShell 8.0, CloudShell uses 2nd generation shells,
|
|
106
|
+
to view the list of 1st generation shells use: shellfoundry list --gen1.
|
|
107
|
+
For more information, please visit our devguide:
|
|
108
|
+
https://qualisystems.github.io/devguide/
|
|
109
|
+
"""
|
|
110
|
+
)
|