apigeecli 0.53.8__tar.gz → 0.53.9__tar.gz
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.
- {apigeecli-0.53.8/apigeecli.egg-info → apigeecli-0.53.9}/PKG-INFO +1 -1
- {apigeecli-0.53.8 → apigeecli-0.53.9}/apigee/__init__.py +4 -2
- apigeecli-0.53.9/apigee/plugins/commands.py +275 -0
- {apigeecli-0.53.8 → apigeecli-0.53.9/apigeecli.egg-info}/PKG-INFO +1 -1
- apigeecli-0.53.8/apigee/plugins/commands.py +0 -240
- {apigeecli-0.53.8 → apigeecli-0.53.9}/LICENSE +0 -0
- {apigeecli-0.53.8 → apigeecli-0.53.9}/NOTICE +0 -0
- {apigeecli-0.53.8 → apigeecli-0.53.9}/README.rst +0 -0
- {apigeecli-0.53.8 → apigeecli-0.53.9}/apigee/__main__.py +0 -0
- {apigeecli-0.53.8 → apigeecli-0.53.9}/apigee/apiproducts/__init__.py +0 -0
- {apigeecli-0.53.8 → apigeecli-0.53.9}/apigee/apiproducts/apiproducts.py +0 -0
- {apigeecli-0.53.8 → apigeecli-0.53.9}/apigee/apiproducts/commands.py +0 -0
- {apigeecli-0.53.8 → apigeecli-0.53.9}/apigee/apiproducts/serializer.py +0 -0
- {apigeecli-0.53.8 → apigeecli-0.53.9}/apigee/apis/__init__.py +0 -0
- {apigeecli-0.53.8 → apigeecli-0.53.9}/apigee/apis/api_puller_with_dependency_extraction.py +0 -0
- {apigeecli-0.53.8 → apigeecli-0.53.9}/apigee/apis/apis.py +0 -0
- {apigeecli-0.53.8 → apigeecli-0.53.9}/apigee/apis/commands.py +0 -0
- {apigeecli-0.53.8 → apigeecli-0.53.9}/apigee/apis/deploy.py +0 -0
- {apigeecli-0.53.8 → apigeecli-0.53.9}/apigee/apis/serializer.py +0 -0
- {apigeecli-0.53.8 → apigeecli-0.53.9}/apigee/apps/__init__.py +0 -0
- {apigeecli-0.53.8 → apigeecli-0.53.9}/apigee/apps/apps.py +0 -0
- {apigeecli-0.53.8 → apigeecli-0.53.9}/apigee/apps/commands.py +0 -0
- {apigeecli-0.53.8 → apigeecli-0.53.9}/apigee/apps/serializer.py +0 -0
- {apigeecli-0.53.8 → apigeecli-0.53.9}/apigee/auth.py +0 -0
- {apigeecli-0.53.8 → apigeecli-0.53.9}/apigee/backups/__init__.py +0 -0
- {apigeecli-0.53.8 → apigeecli-0.53.9}/apigee/backups/backups.py +0 -0
- {apigeecli-0.53.8 → apigeecli-0.53.9}/apigee/backups/commands.py +0 -0
- {apigeecli-0.53.8 → apigeecli-0.53.9}/apigee/caches/__init__.py +0 -0
- {apigeecli-0.53.8 → apigeecli-0.53.9}/apigee/caches/caches.py +0 -0
- {apigeecli-0.53.8 → apigeecli-0.53.9}/apigee/caches/commands.py +0 -0
- {apigeecli-0.53.8 → apigeecli-0.53.9}/apigee/caches/serializer.py +0 -0
- {apigeecli-0.53.8 → apigeecli-0.53.9}/apigee/cls.py +0 -0
- {apigeecli-0.53.8 → apigeecli-0.53.9}/apigee/configure/__init__.py +0 -0
- {apigeecli-0.53.8 → apigeecli-0.53.9}/apigee/configure/commands.py +0 -0
- {apigeecli-0.53.8 → apigeecli-0.53.9}/apigee/console.py +0 -0
- {apigeecli-0.53.8 → apigeecli-0.53.9}/apigee/crypto.py +0 -0
- {apigeecli-0.53.8 → apigeecli-0.53.9}/apigee/deployments/__init__.py +0 -0
- {apigeecli-0.53.8 → apigeecli-0.53.9}/apigee/deployments/commands.py +0 -0
- {apigeecli-0.53.8 → apigeecli-0.53.9}/apigee/deployments/deployments.py +0 -0
- {apigeecli-0.53.8 → apigeecli-0.53.9}/apigee/deployments/serializer.py +0 -0
- {apigeecli-0.53.8 → apigeecli-0.53.9}/apigee/developers/__init__.py +0 -0
- {apigeecli-0.53.8 → apigeecli-0.53.9}/apigee/developers/commands.py +0 -0
- {apigeecli-0.53.8 → apigeecli-0.53.9}/apigee/developers/developers.py +0 -0
- {apigeecli-0.53.8 → apigeecli-0.53.9}/apigee/developers/serializer.py +0 -0
- {apigeecli-0.53.8 → apigeecli-0.53.9}/apigee/encryption_utils.py +0 -0
- {apigeecli-0.53.8 → apigeecli-0.53.9}/apigee/exceptions.py +0 -0
- {apigeecli-0.53.8 → apigeecli-0.53.9}/apigee/keystores/__init__.py +0 -0
- {apigeecli-0.53.8 → apigeecli-0.53.9}/apigee/keystores/commands.py +0 -0
- {apigeecli-0.53.8 → apigeecli-0.53.9}/apigee/keystores/keystores.py +0 -0
- {apigeecli-0.53.8 → apigeecli-0.53.9}/apigee/keystores/serializer.py +0 -0
- {apigeecli-0.53.8 → apigeecli-0.53.9}/apigee/keyvaluemaps/__init__.py +0 -0
- {apigeecli-0.53.8 → apigeecli-0.53.9}/apigee/keyvaluemaps/commands.py +0 -0
- {apigeecli-0.53.8 → apigeecli-0.53.9}/apigee/keyvaluemaps/keyvaluemaps.py +0 -0
- {apigeecli-0.53.8 → apigeecli-0.53.9}/apigee/keyvaluemaps/serializer.py +0 -0
- {apigeecli-0.53.8 → apigeecli-0.53.9}/apigee/maskconfigs/__init__.py +0 -0
- {apigeecli-0.53.8 → apigeecli-0.53.9}/apigee/maskconfigs/commands.py +0 -0
- {apigeecli-0.53.8 → apigeecli-0.53.9}/apigee/maskconfigs/maskconfigs.py +0 -0
- {apigeecli-0.53.8 → apigeecli-0.53.9}/apigee/maskconfigs/serializer.py +0 -0
- {apigeecli-0.53.8 → apigeecli-0.53.9}/apigee/permissions/__init__.py +0 -0
- {apigeecli-0.53.8 → apigeecli-0.53.9}/apigee/permissions/commands.py +0 -0
- {apigeecli-0.53.8 → apigeecli-0.53.9}/apigee/permissions/permissions.py +0 -0
- {apigeecli-0.53.8 → apigeecli-0.53.9}/apigee/permissions/serializer.py +0 -0
- {apigeecli-0.53.8 → apigeecli-0.53.9}/apigee/plugins/__init__.py +0 -0
- {apigeecli-0.53.8 → apigeecli-0.53.9}/apigee/prefix.py +0 -0
- {apigeecli-0.53.8 → apigeecli-0.53.9}/apigee/references/__init__.py +0 -0
- {apigeecli-0.53.8 → apigeecli-0.53.9}/apigee/references/commands.py +0 -0
- {apigeecli-0.53.8 → apigeecli-0.53.9}/apigee/references/references.py +0 -0
- {apigeecli-0.53.8 → apigeecli-0.53.9}/apigee/references/serializer.py +0 -0
- {apigeecli-0.53.8 → apigeecli-0.53.9}/apigee/sharedflows/__init__.py +0 -0
- {apigeecli-0.53.8 → apigeecli-0.53.9}/apigee/sharedflows/commands.py +0 -0
- {apigeecli-0.53.8 → apigeecli-0.53.9}/apigee/sharedflows/serializer.py +0 -0
- {apigeecli-0.53.8 → apigeecli-0.53.9}/apigee/sharedflows/sharedflows.py +0 -0
- {apigeecli-0.53.8 → apigeecli-0.53.9}/apigee/silent.py +0 -0
- {apigeecli-0.53.8 → apigeecli-0.53.9}/apigee/targetservers/__init__.py +0 -0
- {apigeecli-0.53.8 → apigeecli-0.53.9}/apigee/targetservers/commands.py +0 -0
- {apigeecli-0.53.8 → apigeecli-0.53.9}/apigee/targetservers/serializer.py +0 -0
- {apigeecli-0.53.8 → apigeecli-0.53.9}/apigee/targetservers/targetservers.py +0 -0
- {apigeecli-0.53.8 → apigeecli-0.53.9}/apigee/types.py +0 -0
- {apigeecli-0.53.8 → apigeecli-0.53.9}/apigee/userroles/__init__.py +0 -0
- {apigeecli-0.53.8 → apigeecli-0.53.9}/apigee/userroles/commands.py +0 -0
- {apigeecli-0.53.8 → apigeecli-0.53.9}/apigee/userroles/userroles.py +0 -0
- {apigeecli-0.53.8 → apigeecli-0.53.9}/apigee/utils.py +0 -0
- {apigeecli-0.53.8 → apigeecli-0.53.9}/apigee/utils_init.py +0 -0
- {apigeecli-0.53.8 → apigeecli-0.53.9}/apigee/verbose.py +0 -0
- {apigeecli-0.53.8 → apigeecli-0.53.9}/apigee/virtualhosts/__init__.py +0 -0
- {apigeecli-0.53.8 → apigeecli-0.53.9}/apigee/virtualhosts/commands.py +0 -0
- {apigeecli-0.53.8 → apigeecli-0.53.9}/apigee/virtualhosts/serializer.py +0 -0
- {apigeecli-0.53.8 → apigeecli-0.53.9}/apigee/virtualhosts/virtualhosts.py +0 -0
- {apigeecli-0.53.8 → apigeecli-0.53.9}/apigeecli.egg-info/SOURCES.txt +0 -0
- {apigeecli-0.53.8 → apigeecli-0.53.9}/apigeecli.egg-info/dependency_links.txt +0 -0
- {apigeecli-0.53.8 → apigeecli-0.53.9}/apigeecli.egg-info/entry_points.txt +0 -0
- {apigeecli-0.53.8 → apigeecli-0.53.9}/apigeecli.egg-info/requires.txt +0 -0
- {apigeecli-0.53.8 → apigeecli-0.53.9}/apigeecli.egg-info/top_level.txt +0 -0
- {apigeecli-0.53.8 → apigeecli-0.53.9}/setup.cfg +0 -0
- {apigeecli-0.53.8 → apigeecli-0.53.9}/setup.py +0 -0
- {apigeecli-0.53.8 → apigeecli-0.53.9}/tests/__init__.py +0 -0
- {apigeecli-0.53.8 → apigeecli-0.53.9}/tests/test_auth.py +0 -0
- {apigeecli-0.53.8 → apigeecli-0.53.9}/tests/test_echo.py +0 -0
- {apigeecli-0.53.8 → apigeecli-0.53.9}/tests/test_encryption_utils.py +0 -0
|
@@ -6,7 +6,7 @@ from apigee import utils_init
|
|
|
6
6
|
|
|
7
7
|
APP = "apigeecli"
|
|
8
8
|
CMD = "apigee"
|
|
9
|
-
__version__ = "0.53.
|
|
9
|
+
__version__ = "0.53.9"
|
|
10
10
|
description = "(DEPRECATED) apigeecli simplifies and automates Apigee Edge API usage."
|
|
11
11
|
long_description = """The Apigee Edge command-line interface is an unofficial Python command-line tool built to simplify and automate Apigee Edge API usage, with support for SSO, MFA, and basic authentication."""
|
|
12
12
|
|
|
@@ -26,6 +26,8 @@ APIGEE_CLI_EXCEPTIONS_LOG_FILE = utils_init.join_path_components(
|
|
|
26
26
|
APIGEE_CLI_DIRECTORY, "exceptions.log")
|
|
27
27
|
APIGEE_CLI_IS_MACHINE_USER = utils_init.is_truthy_envvar(
|
|
28
28
|
getenv("APIGEE_CLI_IS_MACHINE_USER"))
|
|
29
|
+
APIGEE_CLI_PLUGIN_INFO_FILE = "apigee-cli-info.json"
|
|
30
|
+
APIGEE_CLI_PLUGIN_INFO_FILE_LEGACY = "apigee-cli.info"
|
|
29
31
|
APIGEE_CLI_PLUGINS_CONFIG_FILE = utils_init.join_path_components(
|
|
30
32
|
APIGEE_CLI_PLUGINS_DIRECTORY, "config")
|
|
31
33
|
APIGEE_CLI_PLUGINS_PATH = utils_init.join_path_components(
|
|
@@ -45,4 +47,4 @@ APIGEE_ZONENAME = getenv("APIGEE_ZONENAME")
|
|
|
45
47
|
APIGEE_ZONENAME_OAUTH_URL = "https://{zonename}.login.apigee.com/oauth/token"
|
|
46
48
|
|
|
47
49
|
builtins.APIGEE_CLI_TOGGLE_SILENT = APIGEE_CLI_TOGGLE_SILENT
|
|
48
|
-
builtins.APIGEE_CLI_TOGGLE_VERBOSE = APIGEE_CLI_TOGGLE_VERBOSE
|
|
50
|
+
builtins.APIGEE_CLI_TOGGLE_VERBOSE = APIGEE_CLI_TOGGLE_VERBOSE
|
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
import configparser
|
|
2
|
+
import os
|
|
3
|
+
import shutil
|
|
4
|
+
import stat
|
|
5
|
+
import sys
|
|
6
|
+
from os import path
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
|
|
9
|
+
import click
|
|
10
|
+
from click_option_group import MutuallyExclusiveOptionGroup, optgroup
|
|
11
|
+
|
|
12
|
+
from apigee import (APIGEE_CLI_PLUGIN_INFO_FILE,
|
|
13
|
+
APIGEE_CLI_PLUGIN_INFO_FILE_LEGACY,
|
|
14
|
+
APIGEE_CLI_PLUGINS_CONFIG_FILE,
|
|
15
|
+
APIGEE_CLI_PLUGINS_DIRECTORY, APIGEE_CLI_PLUGINS_PATH,
|
|
16
|
+
console)
|
|
17
|
+
from apigee.silent import common_silent_options
|
|
18
|
+
from apigee.utils import (create_directory, create_empty_file,
|
|
19
|
+
execute_function_on_directory_files, is_directory,
|
|
20
|
+
is_regular_file, read_file_content)
|
|
21
|
+
from apigee.verbose import common_verbose_options
|
|
22
|
+
|
|
23
|
+
# ---- Global Variables ----
|
|
24
|
+
IS_GIT_INSTALLED = False
|
|
25
|
+
PLUGINS_COMMAND_HELP = (
|
|
26
|
+
"Originally meant to help Darumatic clients automate Apigee and API-related "
|
|
27
|
+
"tasks, but available for anyone to use. Refer to "
|
|
28
|
+
"https://github.com/mdelotavo/apigee-cli-plugins to learn how.")
|
|
29
|
+
|
|
30
|
+
try:
|
|
31
|
+
from git import Repo
|
|
32
|
+
IS_GIT_INSTALLED = True
|
|
33
|
+
except ImportError:
|
|
34
|
+
PLUGINS_COMMAND_HELP = (
|
|
35
|
+
"Simple plugins manager for distributing commands. "
|
|
36
|
+
"[Warning: Git must be installed to use plugin commands]")
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
# ---- Helper Classes ----
|
|
40
|
+
class FileUtils:
|
|
41
|
+
"""Internal helper class for file/directory operations."""
|
|
42
|
+
|
|
43
|
+
@staticmethod
|
|
44
|
+
def chmod_directory(directory, mode):
|
|
45
|
+
"""Recursively change permissions of a directory and its contents."""
|
|
46
|
+
for root, dirs, files in os.walk(directory):
|
|
47
|
+
for d in dirs:
|
|
48
|
+
os.chmod(path.join(root, d), mode)
|
|
49
|
+
for f in files:
|
|
50
|
+
os.chmod(path.join(root, f), mode)
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
class GitUtils:
|
|
54
|
+
"""Internal helper class for Git operations."""
|
|
55
|
+
|
|
56
|
+
@staticmethod
|
|
57
|
+
def exit_if_not_installed():
|
|
58
|
+
if not IS_GIT_INSTALLED:
|
|
59
|
+
sys.exit(0)
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
class PluginManager:
|
|
63
|
+
"""Internal helper class for Apigee CLI plugin management."""
|
|
64
|
+
|
|
65
|
+
@staticmethod
|
|
66
|
+
def initialize_plugins():
|
|
67
|
+
create_directory(APIGEE_CLI_PLUGINS_DIRECTORY)
|
|
68
|
+
create_empty_file(APIGEE_CLI_PLUGINS_PATH)
|
|
69
|
+
create_empty_file(APIGEE_CLI_PLUGINS_CONFIG_FILE)
|
|
70
|
+
|
|
71
|
+
@staticmethod
|
|
72
|
+
def load_config(config_file=APIGEE_CLI_PLUGINS_CONFIG_FILE):
|
|
73
|
+
config = configparser.ConfigParser(allow_no_value=True)
|
|
74
|
+
config.read(config_file)
|
|
75
|
+
return config
|
|
76
|
+
|
|
77
|
+
@staticmethod
|
|
78
|
+
def clone_repositories(section="sources"):
|
|
79
|
+
PluginManager.initialize_plugins()
|
|
80
|
+
config = PluginManager.load_config()
|
|
81
|
+
if not config._sections:
|
|
82
|
+
return
|
|
83
|
+
sources = dict(config._sections[section])
|
|
84
|
+
for name, uri in sources.items():
|
|
85
|
+
dest = Path(APIGEE_CLI_PLUGINS_DIRECTORY) / name
|
|
86
|
+
if is_directory(dest):
|
|
87
|
+
continue
|
|
88
|
+
try:
|
|
89
|
+
console.echo(f"Installing {name}... ",
|
|
90
|
+
line_ending="",
|
|
91
|
+
should_flush=True)
|
|
92
|
+
Repo.clone_from(uri, dest)
|
|
93
|
+
console.echo("Done")
|
|
94
|
+
except Exception as e:
|
|
95
|
+
console.echo(e)
|
|
96
|
+
|
|
97
|
+
@staticmethod
|
|
98
|
+
def prune_unused_directories(section="sources"):
|
|
99
|
+
PluginManager.initialize_plugins()
|
|
100
|
+
config = PluginManager.load_config()
|
|
101
|
+
if not config._sections:
|
|
102
|
+
return
|
|
103
|
+
sources = dict(config._sections[section])
|
|
104
|
+
|
|
105
|
+
def _func(path_):
|
|
106
|
+
if not is_directory(path_):
|
|
107
|
+
return
|
|
108
|
+
name = Path(path_).stem
|
|
109
|
+
if name in sources:
|
|
110
|
+
return
|
|
111
|
+
console.echo(f"Removing {name}... ",
|
|
112
|
+
line_ending="",
|
|
113
|
+
should_flush=True)
|
|
114
|
+
plugin_directory = Path(APIGEE_CLI_PLUGINS_DIRECTORY) / name
|
|
115
|
+
try:
|
|
116
|
+
FileUtils.chmod_directory(str(Path(plugin_directory) / ".git"),
|
|
117
|
+
stat.S_IRWXU)
|
|
118
|
+
shutil.rmtree(plugin_directory)
|
|
119
|
+
console.echo("Done")
|
|
120
|
+
except Exception as e:
|
|
121
|
+
console.echo(e)
|
|
122
|
+
|
|
123
|
+
return execute_function_on_directory_files(
|
|
124
|
+
APIGEE_CLI_PLUGINS_DIRECTORY, _func, glob="[!.][!__]*")
|
|
125
|
+
|
|
126
|
+
@staticmethod
|
|
127
|
+
def update_repositories():
|
|
128
|
+
|
|
129
|
+
def _func(path_):
|
|
130
|
+
if not is_directory(path_):
|
|
131
|
+
return
|
|
132
|
+
console.echo(f"Updating {Path(path_).stem}... ",
|
|
133
|
+
line_ending="",
|
|
134
|
+
should_flush=True)
|
|
135
|
+
repo = Repo(path_)
|
|
136
|
+
if repo.bare:
|
|
137
|
+
return
|
|
138
|
+
try:
|
|
139
|
+
repo.remotes["origin"].pull()
|
|
140
|
+
console.echo("Done")
|
|
141
|
+
except Exception as e:
|
|
142
|
+
console.echo(e)
|
|
143
|
+
|
|
144
|
+
return execute_function_on_directory_files(
|
|
145
|
+
APIGEE_CLI_PLUGINS_DIRECTORY, _func, glob="[!.][!__]*")
|
|
146
|
+
|
|
147
|
+
@staticmethod
|
|
148
|
+
def list_sources(section="sources"):
|
|
149
|
+
"""Return a dictionary of plugin sources from config."""
|
|
150
|
+
config = PluginManager.load_config()
|
|
151
|
+
return dict(config._sections.get(section, {}))
|
|
152
|
+
|
|
153
|
+
@staticmethod
|
|
154
|
+
def get_plugin_info(name):
|
|
155
|
+
"""Return the parsed plugin info JSON or None if file missing."""
|
|
156
|
+
plugin_directory = Path(APIGEE_CLI_PLUGINS_DIRECTORY) / name
|
|
157
|
+
info_json = plugin_directory / APIGEE_CLI_PLUGIN_INFO_FILE
|
|
158
|
+
info_legacy = plugin_directory / APIGEE_CLI_PLUGIN_INFO_FILE_LEGACY
|
|
159
|
+
info_file = info_json if info_json.exists() else info_legacy
|
|
160
|
+
if not is_regular_file(info_file):
|
|
161
|
+
return None
|
|
162
|
+
return read_file_content(info_file, type="json")
|
|
163
|
+
|
|
164
|
+
@staticmethod
|
|
165
|
+
def print_latest_commit(name):
|
|
166
|
+
"""Print the latest Git commit of a plugin repository."""
|
|
167
|
+
GitUtils.exit_if_not_installed()
|
|
168
|
+
repo = Repo(Path(APIGEE_CLI_PLUGINS_DIRECTORY) / name)
|
|
169
|
+
console.echo(
|
|
170
|
+
repo.git.log(
|
|
171
|
+
"--pretty=format:%Cred%h%Creset -%C(yellow)%d%Creset %s "
|
|
172
|
+
"%Cgreen(%cr) %C(bold blue)<%an>%Creset", "-1"))
|
|
173
|
+
|
|
174
|
+
@staticmethod
|
|
175
|
+
def print_dependencies(plugins_info):
|
|
176
|
+
"""Print the 'Requires' field from plugin info, if any."""
|
|
177
|
+
requires = plugins_info.get("Requires")
|
|
178
|
+
if requires:
|
|
179
|
+
console.echo(requires)
|
|
180
|
+
|
|
181
|
+
@staticmethod
|
|
182
|
+
def print_full_info(plugins_info):
|
|
183
|
+
"""Print all key/value pairs from plugin info."""
|
|
184
|
+
for key, value in plugins_info.items():
|
|
185
|
+
console.echo(f"{key}: {value}")
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
# ---- CLI Commands ----
|
|
189
|
+
@click.group(help=PLUGINS_COMMAND_HELP)
|
|
190
|
+
def plugins():
|
|
191
|
+
pass
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
@plugins.command(help="Edit config file manually.")
|
|
195
|
+
@common_silent_options
|
|
196
|
+
@common_verbose_options
|
|
197
|
+
@click.option(
|
|
198
|
+
"-a/-A",
|
|
199
|
+
"--apply-changes/--no-apply-changes",
|
|
200
|
+
default=False,
|
|
201
|
+
help="Install plugins from new sources after exiting the editor.",
|
|
202
|
+
show_default=True,
|
|
203
|
+
)
|
|
204
|
+
def configure(silent, verbose, apply_changes):
|
|
205
|
+
GitUtils.exit_if_not_installed()
|
|
206
|
+
PluginManager.initialize_plugins()
|
|
207
|
+
click.edit(filename=APIGEE_CLI_PLUGINS_CONFIG_FILE)
|
|
208
|
+
if apply_changes:
|
|
209
|
+
PluginManager.clone_repositories()
|
|
210
|
+
PluginManager.prune_unused_directories()
|
|
211
|
+
else:
|
|
212
|
+
console.echo("\n Run `apigee plugins update` to apply any changes, "
|
|
213
|
+
"or rerun `apigee plugins configure` with `-a` "
|
|
214
|
+
"to apply changes automatically.\n")
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
@plugins.command(help="Update or install plugins.")
|
|
218
|
+
@common_silent_options
|
|
219
|
+
@common_verbose_options
|
|
220
|
+
def update(silent, verbose, section="sources"):
|
|
221
|
+
GitUtils.exit_if_not_installed()
|
|
222
|
+
PluginManager.clone_repositories()
|
|
223
|
+
PluginManager.update_repositories()
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
@plugins.command(help="Show plugins information.")
|
|
227
|
+
@common_silent_options
|
|
228
|
+
@common_verbose_options
|
|
229
|
+
@click.option("-n", "--name", help="Name of the plugins package")
|
|
230
|
+
@optgroup.group("Filter options",
|
|
231
|
+
cls=MutuallyExclusiveOptionGroup,
|
|
232
|
+
help="The filter options")
|
|
233
|
+
@optgroup.option(
|
|
234
|
+
"--show-commit-only/--no-show-commit-only",
|
|
235
|
+
default=False,
|
|
236
|
+
help="Only print latest Git commit log",
|
|
237
|
+
)
|
|
238
|
+
@optgroup.option(
|
|
239
|
+
"--show-dependencies-only/--no-show-dependencies-only",
|
|
240
|
+
default=False,
|
|
241
|
+
help="Only print list of required packages",
|
|
242
|
+
)
|
|
243
|
+
def show(silent,
|
|
244
|
+
verbose,
|
|
245
|
+
name,
|
|
246
|
+
section="sources",
|
|
247
|
+
show_commit_only=False,
|
|
248
|
+
show_dependencies_only=False):
|
|
249
|
+
"""Show plugins sources, info, commits, or dependencies based on options."""
|
|
250
|
+
|
|
251
|
+
if not name:
|
|
252
|
+
# List all plugin sources
|
|
253
|
+
sources = PluginManager.list_sources(section)
|
|
254
|
+
for plugin_name, uri in sources.items():
|
|
255
|
+
console.echo(f"{plugin_name}: {uri}")
|
|
256
|
+
return
|
|
257
|
+
|
|
258
|
+
plugins_info = PluginManager.get_plugin_info(name)
|
|
259
|
+
if not plugins_info:
|
|
260
|
+
return
|
|
261
|
+
|
|
262
|
+
if show_commit_only:
|
|
263
|
+
PluginManager.print_latest_commit(name)
|
|
264
|
+
elif show_dependencies_only:
|
|
265
|
+
PluginManager.print_dependencies(plugins_info)
|
|
266
|
+
else:
|
|
267
|
+
PluginManager.print_full_info(plugins_info)
|
|
268
|
+
|
|
269
|
+
|
|
270
|
+
@plugins.command(help="Prune plugins with removed sources.")
|
|
271
|
+
@common_silent_options
|
|
272
|
+
@common_verbose_options
|
|
273
|
+
def prune(silent, verbose, section="sources"):
|
|
274
|
+
GitUtils.exit_if_not_installed()
|
|
275
|
+
PluginManager.prune_unused_directories()
|
|
@@ -1,240 +0,0 @@
|
|
|
1
|
-
import configparser
|
|
2
|
-
import os
|
|
3
|
-
import shutil
|
|
4
|
-
import stat
|
|
5
|
-
import sys
|
|
6
|
-
from os import path
|
|
7
|
-
from pathlib import Path
|
|
8
|
-
|
|
9
|
-
import click
|
|
10
|
-
from click_option_group import MutuallyExclusiveOptionGroup, optgroup
|
|
11
|
-
|
|
12
|
-
from apigee import (APIGEE_CLI_PLUGINS_CONFIG_FILE,
|
|
13
|
-
APIGEE_CLI_PLUGINS_DIRECTORY, APIGEE_CLI_PLUGINS_PATH,
|
|
14
|
-
console)
|
|
15
|
-
from apigee.silent import common_silent_options
|
|
16
|
-
from apigee.utils import (create_directory, create_empty_file,
|
|
17
|
-
execute_function_on_directory_files, is_directory,
|
|
18
|
-
is_regular_file, read_file_content)
|
|
19
|
-
from apigee.verbose import common_verbose_options
|
|
20
|
-
|
|
21
|
-
is_git_installed = False
|
|
22
|
-
plugins_command_help = (
|
|
23
|
-
"[Experimental] Simple plugins manager for distributing commands.")
|
|
24
|
-
|
|
25
|
-
try:
|
|
26
|
-
from git import Repo
|
|
27
|
-
|
|
28
|
-
is_git_installed = True
|
|
29
|
-
except ImportError:
|
|
30
|
-
plugins_command_help = "[Unavailable - Git not found] Simple plugins manager for distributing commands."
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
def chmod_directory(directory, mode):
|
|
34
|
-
"""
|
|
35
|
-
Recursively changes the permissions of a directory and its contents.
|
|
36
|
-
|
|
37
|
-
Reference: https://stackoverflow.com/a/58878271
|
|
38
|
-
|
|
39
|
-
Args:
|
|
40
|
-
directory (str): Path to the directory.
|
|
41
|
-
mode (int): Permissions to be set (e.g., 0o0700).
|
|
42
|
-
|
|
43
|
-
"""
|
|
44
|
-
for root, dirs, files in os.walk(directory):
|
|
45
|
-
for dir in dirs:
|
|
46
|
-
os.chmod(path.join(root, dir), mode)
|
|
47
|
-
for file in files:
|
|
48
|
-
os.chmod(path.join(root, file), mode)
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
def clone_plugin_repositories(section="sources"):
|
|
52
|
-
initialize_apigee_cli_plugins()
|
|
53
|
-
config = load_plugin_config()
|
|
54
|
-
if not config._sections:
|
|
55
|
-
return
|
|
56
|
-
sources = dict(config._sections[section])
|
|
57
|
-
for name, uri in sources.items():
|
|
58
|
-
dest = Path(APIGEE_CLI_PLUGINS_DIRECTORY) / name
|
|
59
|
-
if is_directory(dest):
|
|
60
|
-
continue
|
|
61
|
-
try:
|
|
62
|
-
console.echo(f"Installing {name}... ",
|
|
63
|
-
line_ending="",
|
|
64
|
-
should_flush=True)
|
|
65
|
-
Repo.clone_from(uri, dest)
|
|
66
|
-
console.echo("Done")
|
|
67
|
-
except Exception as e:
|
|
68
|
-
console.echo(e)
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
def exit_quietly_if_git_not_installed():
|
|
72
|
-
if not is_git_installed:
|
|
73
|
-
sys.exit(0)
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
def initialize_and_save_plugin_config():
|
|
77
|
-
initialize_apigee_cli_plugins()
|
|
78
|
-
config = load_plugin_config()
|
|
79
|
-
if not config._sections:
|
|
80
|
-
return
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
def initialize_apigee_cli_plugins():
|
|
84
|
-
create_directory(APIGEE_CLI_PLUGINS_DIRECTORY)
|
|
85
|
-
create_empty_file(APIGEE_CLI_PLUGINS_PATH)
|
|
86
|
-
create_empty_file(APIGEE_CLI_PLUGINS_CONFIG_FILE)
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
def load_plugin_config(config_file=APIGEE_CLI_PLUGINS_CONFIG_FILE):
|
|
90
|
-
config = configparser.ConfigParser(allow_no_value=True)
|
|
91
|
-
config.read(config_file)
|
|
92
|
-
return config
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
def prune_unused_plugin_directories(section="sources"):
|
|
96
|
-
initialize_apigee_cli_plugins()
|
|
97
|
-
config = load_plugin_config()
|
|
98
|
-
if not config._sections:
|
|
99
|
-
return
|
|
100
|
-
sources = dict(config._sections[section])
|
|
101
|
-
|
|
102
|
-
def _func(path):
|
|
103
|
-
if not is_directory(path):
|
|
104
|
-
return
|
|
105
|
-
name = Path(path).stem
|
|
106
|
-
if name in sources:
|
|
107
|
-
return
|
|
108
|
-
console.echo(f"Removing {name}... ", line_ending="", should_flush=True)
|
|
109
|
-
plugin_directory = Path(APIGEE_CLI_PLUGINS_DIRECTORY) / name
|
|
110
|
-
try:
|
|
111
|
-
chmod_directory(str(Path(plugin_directory) / ".git"), stat.S_IRWXU)
|
|
112
|
-
shutil.rmtree(plugin_directory)
|
|
113
|
-
console.echo("Done")
|
|
114
|
-
except Exception as e:
|
|
115
|
-
console.echo(e)
|
|
116
|
-
|
|
117
|
-
return execute_function_on_directory_files(APIGEE_CLI_PLUGINS_DIRECTORY,
|
|
118
|
-
_func,
|
|
119
|
-
glob="[!.][!__]*")
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
def update_plugin_repositories():
|
|
123
|
-
|
|
124
|
-
def _func(path):
|
|
125
|
-
if not is_directory(path):
|
|
126
|
-
return
|
|
127
|
-
console.echo(f"Updating {Path(path).stem}... ",
|
|
128
|
-
line_ending="",
|
|
129
|
-
should_flush=True)
|
|
130
|
-
repo = Repo(path)
|
|
131
|
-
if repo.bare:
|
|
132
|
-
return
|
|
133
|
-
try:
|
|
134
|
-
repo.remotes["origin"].pull()
|
|
135
|
-
console.echo("Done")
|
|
136
|
-
except Exception as e:
|
|
137
|
-
console.echo(e)
|
|
138
|
-
|
|
139
|
-
return execute_function_on_directory_files(APIGEE_CLI_PLUGINS_DIRECTORY,
|
|
140
|
-
_func,
|
|
141
|
-
glob="[!.][!__]*")
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
@click.group(help=plugins_command_help)
|
|
145
|
-
def plugins():
|
|
146
|
-
pass
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
@plugins.command(help="Edit config file manually.")
|
|
150
|
-
@common_silent_options
|
|
151
|
-
@common_verbose_options
|
|
152
|
-
@click.option(
|
|
153
|
-
"-a/-A",
|
|
154
|
-
"--apply-changes/--no-apply-changes",
|
|
155
|
-
default=False,
|
|
156
|
-
help="Install plugins from new sources after exiting the editor.",
|
|
157
|
-
show_default=True,
|
|
158
|
-
)
|
|
159
|
-
def configure(silent, verbose, apply_changes):
|
|
160
|
-
exit_quietly_if_git_not_installed()
|
|
161
|
-
initialize_apigee_cli_plugins()
|
|
162
|
-
click.edit(filename=APIGEE_CLI_PLUGINS_CONFIG_FILE)
|
|
163
|
-
if apply_changes:
|
|
164
|
-
clone_plugin_repositories()
|
|
165
|
-
prune_unused_plugin_directories()
|
|
166
|
-
else:
|
|
167
|
-
console.echo("\n Run `apigee plugins update` to apply any changes,")
|
|
168
|
-
console.echo(" or rerun `apigee plugins configure` with `-a`")
|
|
169
|
-
console.echo(" to apply changes automatically.\n")
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
@plugins.command(help="Update or install plugins.")
|
|
173
|
-
@common_silent_options
|
|
174
|
-
@common_verbose_options
|
|
175
|
-
def update(silent, verbose, section="sources"):
|
|
176
|
-
exit_quietly_if_git_not_installed()
|
|
177
|
-
clone_plugin_repositories()
|
|
178
|
-
update_plugin_repositories()
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
@plugins.command(help="Show plugins information.")
|
|
182
|
-
@common_silent_options
|
|
183
|
-
@common_verbose_options
|
|
184
|
-
@click.option("-n", "--name", help="name of the plugins package")
|
|
185
|
-
@optgroup.group("Filter options",
|
|
186
|
-
cls=MutuallyExclusiveOptionGroup,
|
|
187
|
-
help="The filter options")
|
|
188
|
-
@optgroup.option(
|
|
189
|
-
"--show-commit-only/--no-show-commit-only",
|
|
190
|
-
default=False,
|
|
191
|
-
help="only print latest Git commit log",
|
|
192
|
-
)
|
|
193
|
-
@optgroup.option(
|
|
194
|
-
"--show-dependencies-only/--no-show-dependencies-only",
|
|
195
|
-
default=False,
|
|
196
|
-
help="only print list of required packages",
|
|
197
|
-
)
|
|
198
|
-
def show(
|
|
199
|
-
silent,
|
|
200
|
-
verbose,
|
|
201
|
-
name,
|
|
202
|
-
section="sources",
|
|
203
|
-
show_commit_only=False,
|
|
204
|
-
show_dependencies_only=False,
|
|
205
|
-
):
|
|
206
|
-
if not name:
|
|
207
|
-
config = load_plugin_config()
|
|
208
|
-
if not config._sections:
|
|
209
|
-
return
|
|
210
|
-
sources = dict(config._sections[section])
|
|
211
|
-
for name, uri in sources.items():
|
|
212
|
-
console.echo(f"{name}: {uri}")
|
|
213
|
-
return
|
|
214
|
-
plugins_info_file = Path(
|
|
215
|
-
APIGEE_CLI_PLUGINS_DIRECTORY) / name / "apigee-cli.info"
|
|
216
|
-
if not is_regular_file(plugins_info_file):
|
|
217
|
-
return
|
|
218
|
-
plugins_info = read_file_content(plugins_info_file, type="json")
|
|
219
|
-
if show_commit_only:
|
|
220
|
-
exit_quietly_if_git_not_installed()
|
|
221
|
-
console.echo(
|
|
222
|
-
Repo(Path(APIGEE_CLI_PLUGINS_DIRECTORY) / name).git.log(
|
|
223
|
-
"--pretty=format:%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset",
|
|
224
|
-
"-1",
|
|
225
|
-
))
|
|
226
|
-
return
|
|
227
|
-
if show_dependencies_only:
|
|
228
|
-
if plugins_info.get("Requires"):
|
|
229
|
-
console.echo(plugins_info.get("Requires"))
|
|
230
|
-
return
|
|
231
|
-
for k, v in plugins_info.items():
|
|
232
|
-
console.echo(f"{k}: {v}")
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
@plugins.command(help="Prune plugins with removed sources.")
|
|
236
|
-
@common_silent_options
|
|
237
|
-
@common_verbose_options
|
|
238
|
-
def prune(silent, verbose, section="sources"):
|
|
239
|
-
exit_quietly_if_git_not_installed()
|
|
240
|
-
prune_unused_plugin_directories()
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|