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.
Files changed (72) hide show
  1. shellfoundry/__init__.py +8 -0
  2. shellfoundry/__main__.py +7 -0
  3. shellfoundry/bootstrap.py +169 -0
  4. shellfoundry/commands/__init__.py +0 -0
  5. shellfoundry/commands/config_command.py +87 -0
  6. shellfoundry/commands/delete_command.py +24 -0
  7. shellfoundry/commands/dist_command.py +34 -0
  8. shellfoundry/commands/extend_command.py +182 -0
  9. shellfoundry/commands/generate_command.py +44 -0
  10. shellfoundry/commands/get_templates_command.py +151 -0
  11. shellfoundry/commands/install_command.py +81 -0
  12. shellfoundry/commands/list_command.py +110 -0
  13. shellfoundry/commands/new_command.py +393 -0
  14. shellfoundry/commands/pack_command.py +45 -0
  15. shellfoundry/commands/show_command.py +55 -0
  16. shellfoundry/data/standards.json +44 -0
  17. shellfoundry/data/templates.yml +117 -0
  18. shellfoundry/decorators/__init__.py +1 -0
  19. shellfoundry/decorators/standards.py +20 -0
  20. shellfoundry/decorators/version_check.py +52 -0
  21. shellfoundry/exceptions.py +52 -0
  22. shellfoundry/models/__init__.py +0 -0
  23. shellfoundry/models/install_config.py +82 -0
  24. shellfoundry/models/shell_template.py +22 -0
  25. shellfoundry/models/shellfoundry_settings.py +13 -0
  26. shellfoundry/utilities/__init__.py +114 -0
  27. shellfoundry/utilities/archive_creator.py +35 -0
  28. shellfoundry/utilities/cloudshell_api/__init__.py +1 -0
  29. shellfoundry/utilities/cloudshell_api/client_wrapper.py +71 -0
  30. shellfoundry/utilities/config/__init__.py +0 -0
  31. shellfoundry/utilities/config/config_context.py +44 -0
  32. shellfoundry/utilities/config/config_file_creation.py +32 -0
  33. shellfoundry/utilities/config/config_providers.py +50 -0
  34. shellfoundry/utilities/config/config_record.py +24 -0
  35. shellfoundry/utilities/config_reader.py +154 -0
  36. shellfoundry/utilities/constants.py +37 -0
  37. shellfoundry/utilities/cookiecutter_integration.py +67 -0
  38. shellfoundry/utilities/driver_generator.py +121 -0
  39. shellfoundry/utilities/filters.py +45 -0
  40. shellfoundry/utilities/installer.py +44 -0
  41. shellfoundry/utilities/modifiers/__init__.py +0 -0
  42. shellfoundry/utilities/modifiers/configuration/__init__.py +0 -0
  43. shellfoundry/utilities/modifiers/configuration/aggregated_modifiers.py +26 -0
  44. shellfoundry/utilities/modifiers/configuration/password_modification.py +48 -0
  45. shellfoundry/utilities/modifiers/definition/__init__.py +0 -0
  46. shellfoundry/utilities/modifiers/definition/definition_modification.py +205 -0
  47. shellfoundry/utilities/package_builder.py +152 -0
  48. shellfoundry/utilities/python_dependencies_packager.py +53 -0
  49. shellfoundry/utilities/repository_downloader.py +76 -0
  50. shellfoundry/utilities/shell_config_reader.py +59 -0
  51. shellfoundry/utilities/shell_datamodel_merger.py +44 -0
  52. shellfoundry/utilities/shell_package.py +59 -0
  53. shellfoundry/utilities/shell_package_builder.py +149 -0
  54. shellfoundry/utilities/shell_package_installer.py +231 -0
  55. shellfoundry/utilities/standards/__init__.py +3 -0
  56. shellfoundry/utilities/standards/consts.py +2 -0
  57. shellfoundry/utilities/standards/standards_retriever.py +32 -0
  58. shellfoundry/utilities/standards/standards_versions.py +34 -0
  59. shellfoundry/utilities/temp_dir_context.py +17 -0
  60. shellfoundry/utilities/template_retriever.py +309 -0
  61. shellfoundry/utilities/template_url.py +38 -0
  62. shellfoundry/utilities/template_versions.py +47 -0
  63. shellfoundry/utilities/validations/__init__.py +2 -0
  64. shellfoundry/utilities/validations/shell_generation_validation.py +29 -0
  65. shellfoundry/utilities/validations/shell_name_validations.py +10 -0
  66. shellfoundry/utilities/version_utilities.py +19 -0
  67. shellfoundry-1.2.25.dist-info/LICENSE +201 -0
  68. shellfoundry-1.2.25.dist-info/METADATA +417 -0
  69. shellfoundry-1.2.25.dist-info/RECORD +72 -0
  70. shellfoundry-1.2.25.dist-info/WHEEL +5 -0
  71. shellfoundry-1.2.25.dist-info/entry_points.txt +2 -0
  72. 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
+ )