Skip to content

Commit 24eb493

Browse files
committed
move nfsupport use case to separate repo
1 parent 2c0944e commit 24eb493

File tree

4 files changed

+40
-148
lines changed

4 files changed

+40
-148
lines changed

netfoundry/ctl.py

Lines changed: 6 additions & 132 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@
3030

3131
# importing this causes the 'config' subcommand to be available
3232
from jwt.exceptions import PyJWTError
33-
from milc import set_metadata # this function needed to set metadata immediately below
3433
from platformdirs import user_cache_path
3534
from pygments import highlight
3635
from pygments.formatters import Terminal256Formatter
@@ -48,6 +47,7 @@
4847
from .organization import Organization
4948
from .utility import DC_PROVIDERS, MUTABLE_NETWORK_RESOURCES, MUTABLE_RESOURCE_ABBREVIATIONS, RESOURCE_ABBREVIATIONS, RESOURCE_STATUS_SYMBOLS, RESOURCES, is_jwt, normalize_caseless, plural, singular
5049

50+
from milc import set_metadata # this function needed to set metadata immediately below
5151
set_metadata(version=f"v{netfoundry_version}", author="NetFoundry", name="nfctl") # must precend import milc.cli
5252
from milc import cli, questions # this uses metadata set above
5353
from milc.subcommand import config # this creates the config subcommand
@@ -196,135 +196,6 @@ def login(cli):
196196
cli.echo(token_env)
197197

198198

199-
@cli.argument('-u', '--user', help="alternative proxy user, default is logged in username")
200-
@cli.argument('-s', '--ssh', help="alternative ssh executable, default is 'ssh'")
201-
@cli.argument('ziti_args', help=argparse.SUPPRESS, arg_only=True, nargs='*')
202-
@cli.argument('ziti_subcmd', help=argparse.SUPPRESS, arg_only=True)
203-
@cli.subcommand('run ziti CLI', hidden=True)
204-
def ziti(cli):
205-
"""Run read-only Ziti CLI commands remotely on controller host."""
206-
if not cli.config.general.network:
207-
cli.log.error("need --network=ACMENet")
208-
sysexit(1)
209-
210-
# set up the ziti config cache
211-
network_name_safe = '_'.join(cli.config.general.network.casefold().split())
212-
cache_dir_path = user_cache_path(appname=cli.prog_name)
213-
try:
214-
# create and correct mode to 0o700
215-
cache_dir_path.mkdir(mode=S_IRUSR | S_IWUSR | S_IXUSR, parents=True, exist_ok=True)
216-
cache_dir_path.chmod(mode=S_IRUSR | S_IWUSR | S_IXUSR)
217-
except Exception as e:
218-
raise RuntimeError(f"failed to create cache dir '{str(cache_dir_path.resolve())}', got {e}")
219-
else:
220-
cache_dir_stats = stat(cache_dir_path)
221-
logging.debug(f"ziti config cache dir {str(cache_dir_path.resolve())} has mode {filemode(cache_dir_stats.st_mode)}")
222-
ssh_config_file = Path(cache_dir_path / network_name_safe)
223-
logging.debug(f"ziti config file path is computed '{str(ssh_config_file.resolve())}'")
224-
225-
# verify we can run OpenSSH client `ssh`, optionally an alternative `ssh` executable
226-
if cli.config.login.ssh:
227-
ssh_bin = cli.config.login.ssh
228-
else:
229-
if platform.system() == 'Windows':
230-
ssh_bin = 'ssh.exe'
231-
else:
232-
ssh_bin = 'ssh'
233-
which_ssh = which(ssh_bin)
234-
if which_ssh:
235-
cli.log.debug(f"found ssh executable in {which_ssh}")
236-
else:
237-
cli.log.error(f"missing executable '{ssh_bin}' in PATH: {environ['PATH']}")
238-
sysexit(1)
239-
exec = cli.run([which_ssh, '-V'])
240-
if exec.returncode == 0:
241-
cli.log.debug(f"found '{which_ssh}' version '{exec.stdout}'")
242-
else:
243-
cli.log.error(f"failed to get {which_ssh} version: {exec.stderr}")
244-
sysexit(exec.returncode)
245-
246-
if cli.config.ziti.user:
247-
proxy_user = cli.config.ziti.user
248-
else:
249-
try:
250-
proxy_user = getuser()
251-
assert proxy_user, f"failed to get logged in username, got {proxy_user}"
252-
except AssertionError:
253-
raise
254-
255-
ziti_cmd = " /opt/netfoundry/ziti/ziti "
256-
257-
# if command is 'edge' and verb is 'login' then get a token and cache to ziti ssh config file, ignoring extra args
258-
if cli.args.ziti_subcmd == 'edge' and cli.args.ziti_args[0] == 'login':
259-
if len(cli.args.ziti_args[1:]) > 0:
260-
cli.log.warning(f"ignoring extra args: {' '.join(cli.args.ziti_args[1:])}")
261-
spinner = get_spinner("Logging in to Ziti Controller Edge Management API")
262-
with spinner:
263-
organization, networks = use_organization(spinner=spinner)
264-
network, network_group = use_network(
265-
organization=organization,
266-
group=cli.config.general.network_group,
267-
network_name=cli.config.general.network,
268-
spinner=spinner)
269-
network_controller = network.get_resource_by_id(type="network-controller", id=network.network_controller['id'])
270-
controller_host = network.get_resource_by_id(type="host", id=network_controller['hostId'])
271-
if network_controller.get('domainName') and network_controller['domainName']:
272-
ziti_ctrl_ip = network_controller['domainName']
273-
else:
274-
ziti_ctrl_ip = controller_host['ipAddress']
275-
try:
276-
session = network.get_controller_session(network.network_controller['id'])
277-
except:
278-
spinner.fail("experimental ziti login failed")
279-
sysexit(1)
280-
else:
281-
ziti_token = session['sessionToken']
282-
ssh_config = f"""
283-
Host {ziti_ctrl_ip}
284-
User {controller_host['username']}
285-
ProxyJump {proxy_user}@bastion.{organization.environment}.netfoundry.io
286-
PubKeyAuthentication yes
287-
PasswordAuthentication no
288-
GSSAPIAuthentication no
289-
ControlMaster auto
290-
ControlPersist 9m
291-
ControlPath {str(cache_dir_path.resolve()) + r'/ssh-%u-%C'}
292-
"""
293-
# UserKnownHostsFile /dev/null
294-
try:
295-
with open(ssh_config_file, 'w') as f:
296-
f.write(ssh_config)
297-
except Exception as e:
298-
raise RuntimeError(f"problem writing ssh_config in {str(ssh_config_file.resolve())}, got {e}")
299-
else:
300-
cli.log.debug(f"wrote ssh_config in {str(ssh_config_file.resolve())}")
301-
proxy_jump_cmd = f" {which_ssh} -F '{str(ssh_config_file.resolve())}' {ziti_ctrl_ip} "
302-
ziti_login_cmd = f" edge login 127.0.0.1:{controller_host['port']}/edge/management/v1/ --token {ziti_token} --cert /opt/netfoundry/ziti/ziti-controller/certs/ca.external/certs/intermediate-chain.pem --read-only "
303-
try:
304-
exec = cli.run(shplit(proxy_jump_cmd + ziti_cmd + ziti_login_cmd), capture_output=False)
305-
except Exception as e:
306-
raise RuntimeError(f"problem running ssh command: {proxy_jump_cmd + ziti_cmd + ziti_login_cmd}, got {e}")
307-
else:
308-
if exec.returncode == 0: # if succeeded
309-
spinner.succeed("Login succeeded")
310-
else:
311-
spinner.fail("Login failed")
312-
sysexit(exec.returncode)
313-
314-
elif ssh_config_file.exists():
315-
# compute and check network unique signature
316-
# pass-through ziti commands to remote
317-
with open(ssh_config_file, 'r') as f:
318-
for line in f:
319-
if len(line.split()) == 2 and line.split()[0] == "Host":
320-
ziti_ctrl_ip = line.split()[1]
321-
proxy_jump_cmd = f" {which_ssh} -F '{str(ssh_config_file.resolve())}' {ziti_ctrl_ip} "
322-
cli.run(shplit(proxy_jump_cmd + ziti_cmd + cli.args.ziti_subcmd) + cli.args.ziti_args, capture_output=False)
323-
else:
324-
cli.log.error("need login:\n\t nfctl --network=ACMENet ziti edge login")
325-
sysexit(1)
326-
327-
328199
@cli.subcommand('logout current profile from an organization')
329200
def logout(cli):
330201
"""Logout by deleting the cached token."""
@@ -664,9 +535,12 @@ def get(cli, echo: bool = True, embed='all', spinner: object = None):
664535
@cli.argument('-a', '--as', dest='accept', arg_only=True, choices=['create'], help="request the as=create alternative form of the resources")
665536
@cli.argument('resource_type', arg_only=True, help='type of resource', metavar="RESOURCE_TYPE", choices=[choice for group in [[type, RESOURCES[type].abbreviation] for type in RESOURCES.keys()] for choice in group])
666537
@cli.subcommand(description='find resources as lists')
667-
def list(cli):
538+
def list(cli, spinner: object = None):
668539
"""Find resources as lists."""
669-
spinner = get_spinner("working")
540+
if not spinner:
541+
spinner = get_spinner("working")
542+
else:
543+
cli.log.debug("got spinner as function param")
670544
if RESOURCE_ABBREVIATIONS.get(cli.args.resource_type):
671545
cli.args.resource_type = RESOURCE_ABBREVIATIONS[cli.args.resource_type].name
672546
if cli.args.accept and not MUTABLE_NETWORK_RESOURCES.get(cli.args.resource_type): # mutable excludes data-centers

netfoundry/demo.py

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,35 @@
44
Usage:
55
$ python3 -m netfoundry.demo --network BibbidiBobbidiBoo
66
"""
7-
from subprocess import run
8-
from sys import argv
7+
import re
8+
import sys
99

10-
def main():
11-
"""Run the built-in demo."""
12-
raw_args = ['nfctl', 'demo']
13-
if len(argv) > 1:
14-
raw_args.extend(argv[1:])
15-
run(raw_args)
10+
try:
11+
from importlib.metadata import distribution
12+
except ImportError:
13+
try:
14+
from importlib_metadata import distribution
15+
except ImportError:
16+
from pkg_resources import load_entry_point
17+
18+
19+
def importlib_load_entry_point(spec, group, name):
20+
dist_name, _, _ = spec.partition('==')
21+
matches = (
22+
entry_point
23+
for entry_point in distribution(dist_name).entry_points
24+
if entry_point.group == group and entry_point.name == name
25+
)
26+
return next(matches).load()
1627

1728

29+
globals().setdefault('load_entry_point', importlib_load_entry_point)
30+
31+
def main():
32+
sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
33+
_args = [sys.argv[0], 'demo'] + sys.argv[1:]
34+
sys.argv = _args
35+
sys.exit(load_entry_point('netfoundry', 'console_scripts', 'nfctl')())
36+
1837
if __name__ == '__main__':
1938
main()

setup.cfg

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,3 @@
1-
[options.entry_points]
2-
console_scripts =
3-
nfdemo = netfoundry.demo:main
4-
nfctl = netfoundry.ctl:cli
5-
61
[versioneer]
72
VCS = git
83
style = pep440-pre

setup.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,12 @@
3232
'platformdirs >= 2.4',
3333
'tabulate >= 0.8',
3434
'packaging >= 20.9',
35-
'nanoid >= 2.0',
3635
'pygments >= 2.11'
37-
]
36+
],
37+
entry_points={
38+
'console_scripts': [
39+
'nfdemo = netfoundry.demo:main',
40+
'nfctl = netfoundry.ctl:cli',
41+
]
42+
}
3843
)
39-

0 commit comments

Comments
 (0)