mirror of https://github.com/nucypher/nucypher.git
Respond to RFCs in PR #861
parent
13024ed048
commit
9abd4e27fb
|
@ -11,15 +11,22 @@ from nucypher.config.constants import DEFAULT_CONFIG_ROOT, USER_LOG_DIR
|
|||
from nucypher.network.middleware import RestMiddleware
|
||||
|
||||
DESTRUCTION = '''
|
||||
*Permanently and irreversibly delete all* nucypher files including
|
||||
*Permanently and irreversibly delete all* nucypher files including:
|
||||
- Private and Public Keys
|
||||
- Known Nodes
|
||||
- TLS certificates
|
||||
- Node Configurations
|
||||
- Log Files
|
||||
|
||||
Delete {}?'''
|
||||
|
||||
CHARACTER_DESTRUCTION = '''
|
||||
Delete all {name} character files including:
|
||||
- Private and Public Keys
|
||||
- Known Nodes
|
||||
- Node Configuration File
|
||||
|
||||
Delete {root}?'''
|
||||
|
||||
|
||||
LOG = Logger('cli.actions')
|
||||
|
||||
|
@ -46,13 +53,12 @@ def load_seednodes(min_stake: int,
|
|||
|
||||
|
||||
def destroy_configuration_root(config_root=None, force=False, logs: bool = False) -> str:
|
||||
"""CAUTION: This will destroy *all* nucypher configuration files from the filesystem"""
|
||||
"""CAUTION: This will destroy *all* nucypher configuration files from the configuration root"""
|
||||
|
||||
config_root = config_root or DEFAULT_CONFIG_ROOT
|
||||
|
||||
if not force:
|
||||
message = f"Destroy top-level configuration directory: {config_root}?"
|
||||
click.confirm(message, abort=True) # ABORT
|
||||
click.confirm(DESTRUCTION.format(config_root), abort=True) # ABORT
|
||||
|
||||
if os.path.isdir(config_root):
|
||||
shutil.rmtree(config_root, ignore_errors=force) # config
|
||||
|
@ -68,7 +74,8 @@ def destroy_configuration_root(config_root=None, force=False, logs: bool = False
|
|||
def destroy_configuration(character_config, force: bool = False) -> None:
|
||||
|
||||
if not force:
|
||||
click.confirm(DESTRUCTION.format(character_config.config_root), abort=True)
|
||||
click.confirm(CHARACTER_DESTRUCTION.format(name=character_config._NAME,
|
||||
root=character_config.config_root), abort=True)
|
||||
|
||||
try:
|
||||
character_config.destroy()
|
||||
|
@ -117,3 +124,12 @@ performing accurate re-encryption work orders will result in rewards
|
|||
paid out in ETH retro-actively, on-demand.
|
||||
|
||||
Accept node operator obligation?""", abort=True)
|
||||
|
||||
|
||||
def handle_missing_configuration_file(character_config_class, config_file: str = None):
|
||||
config_file_location = config_file or character_config_class.DEFAULT_CONFIG_FILE_LOCATION
|
||||
message = f'No {character_config_class._NAME.capitalize()} configuration file found.\n' \
|
||||
f'To create a new persistent {character_config_class._NAME.capitalize()} run: ' \
|
||||
f'\'nucypher {character_config_class._NAME} init\''
|
||||
|
||||
raise click.FileError(filename=config_file_location, hint=message)
|
||||
|
|
|
@ -105,13 +105,17 @@ def alice(click_config,
|
|||
federated_only=True)
|
||||
|
||||
else:
|
||||
alice_config = AliceConfiguration.from_configuration_file(
|
||||
filepath=config_file,
|
||||
domains={network or GLOBAL_DOMAIN},
|
||||
network_middleware=click_config.middleware,
|
||||
rest_port=discovery_port,
|
||||
checksum_public_address=checksum_address,
|
||||
provider_uri=provider_uri)
|
||||
try:
|
||||
alice_config = AliceConfiguration.from_configuration_file(
|
||||
filepath=config_file,
|
||||
domains={network or GLOBAL_DOMAIN},
|
||||
network_middleware=click_config.middleware,
|
||||
rest_port=discovery_port,
|
||||
checksum_public_address=checksum_address,
|
||||
provider_uri=provider_uri)
|
||||
except FileNotFoundError:
|
||||
return actions.handle_missing_configuration_file(character_config_class=AliceConfiguration,
|
||||
config_file=config_file)
|
||||
|
||||
if not dev:
|
||||
click_config.unlock_keyring(character_configuration=alice_config)
|
||||
|
|
|
@ -62,10 +62,7 @@ def bob(click_config,
|
|||
"""Create a brand-new persistent Bob"""
|
||||
|
||||
if dev:
|
||||
actions.handle_control_output(message="WARNING: Using temporary storage area",
|
||||
quiet=quiet,
|
||||
color='yellow',
|
||||
json=click_config.json)
|
||||
click_config.emit(message="WARNING: Using temporary storage area", color='yellow')
|
||||
|
||||
if not config_root: # Flag
|
||||
config_root = click_config.config_file # Envvar
|
||||
|
@ -82,22 +79,6 @@ def bob(click_config,
|
|||
return painting.paint_new_installation_help(new_configuration=new_bob_config,
|
||||
config_file=config_file)
|
||||
|
||||
elif action == "destroy":
|
||||
"""Delete all configuration files from the disk"""
|
||||
|
||||
if dev:
|
||||
message = "'nucypher ursula destroy' cannot be used in --dev mode"
|
||||
raise click.BadOptionUsage(option_name='--dev', message=message)
|
||||
|
||||
destroyed_path = actions.destroy_configuration_root(config_class=BobConfiguration,
|
||||
config_file=config_file,
|
||||
network=network,
|
||||
config_root=config_root,
|
||||
force=force)
|
||||
|
||||
return click_config.emitter(message=f"Destroyed {destroyed_path}")
|
||||
|
||||
|
||||
#
|
||||
# Get Bob Configuration
|
||||
#
|
||||
|
@ -109,12 +90,17 @@ def bob(click_config,
|
|||
federated_only=True,
|
||||
network_middleware=click_config.middleware)
|
||||
else:
|
||||
bob_config = BobConfiguration.from_configuration_file(
|
||||
filepath=config_file,
|
||||
domains={network or GLOBAL_DOMAIN},
|
||||
rest_port=discovery_port,
|
||||
provider_uri=provider_uri,
|
||||
network_middleware=click_config.middleware)
|
||||
|
||||
try:
|
||||
bob_config = BobConfiguration.from_configuration_file(
|
||||
filepath=config_file,
|
||||
domains={network or GLOBAL_DOMAIN},
|
||||
rest_port=discovery_port,
|
||||
provider_uri=provider_uri,
|
||||
network_middleware=click_config.middleware)
|
||||
except FileNotFoundError:
|
||||
return actions.handle_missing_configuration_file(character_config_class=BobConfiguration,
|
||||
config_file=config_file)
|
||||
|
||||
# Teacher Ursula
|
||||
teacher_uris = [teacher_uri] if teacher_uri else list()
|
||||
|
@ -167,5 +153,12 @@ def bob(click_config,
|
|||
response = BOB.controller.retrieve(request=bob_request_data)
|
||||
return response
|
||||
|
||||
elif action == "destroy":
|
||||
"""Delete Bob's character configuration files from the disk"""
|
||||
if dev:
|
||||
message = "'nucypher ursula destroy' cannot be used in --dev mode"
|
||||
raise click.BadOptionUsage(option_name='--dev', message=message)
|
||||
return actions.destroy_configuration(character_config=bob_config)
|
||||
|
||||
else:
|
||||
raise click.BadArgumentUsage(f"No such argument {action}")
|
||||
|
|
|
@ -36,7 +36,6 @@ from nucypher.cli.types import (
|
|||
STAKE_VALUE
|
||||
)
|
||||
from nucypher.config.characters import UrsulaConfiguration
|
||||
from nucypher.config.keyring import NucypherKeyring
|
||||
from nucypher.utilities.sandbox.constants import (
|
||||
TEMPORARY_DOMAIN,
|
||||
)
|
||||
|
@ -197,18 +196,22 @@ def ursula(click_config,
|
|||
else:
|
||||
|
||||
# Domains -> bytes | or default
|
||||
domains = [bytes(network, encoding='utf-8')] if network else None
|
||||
domains = set(bytes(network, encoding='utf-8')) if network else None
|
||||
|
||||
# Load Ursula from Configuration File
|
||||
ursula_config = UrsulaConfiguration.from_configuration_file(filepath=config_file,
|
||||
domains=domains,
|
||||
registry_filepath=registry_filepath,
|
||||
provider_uri=provider_uri,
|
||||
rest_host=rest_host,
|
||||
rest_port=rest_port,
|
||||
db_filepath=db_filepath,
|
||||
poa=poa,
|
||||
federated_only=federated_only)
|
||||
try:
|
||||
ursula_config = UrsulaConfiguration.from_configuration_file(filepath=config_file,
|
||||
domains=domains,
|
||||
registry_filepath=registry_filepath,
|
||||
provider_uri=provider_uri,
|
||||
rest_host=rest_host,
|
||||
rest_port=rest_port,
|
||||
db_filepath=db_filepath,
|
||||
poa=poa,
|
||||
federated_only=federated_only)
|
||||
except FileNotFoundError:
|
||||
return actions.handle_missing_configuration_file(character_config_class=UrsulaConfiguration,
|
||||
config_file=config_file)
|
||||
|
||||
click_config.unlock_keyring(character_configuration=ursula_config)
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@ You should have received a copy of the GNU Affero General Public License
|
|||
along with nucypher. If not, see <https://www.gnu.org/licenses/>.
|
||||
"""
|
||||
import base64
|
||||
import contextlib
|
||||
import json
|
||||
import os
|
||||
import shutil
|
||||
|
@ -666,8 +667,8 @@ class NucypherKeyring:
|
|||
keypaths = self._generate_key_filepaths(account=self.checksum_address,
|
||||
public_key_dir=public_key_dir,
|
||||
private_key_dir=private_key_dir)
|
||||
|
||||
# Remove the parsed paths from the disk, weather they exist or not.
|
||||
for filepath in keypaths.values():
|
||||
try:
|
||||
with contextlib.suppress(FileNotFoundError):
|
||||
os.remove(filepath)
|
||||
except FileNotFoundError:
|
||||
pass
|
|
@ -81,7 +81,7 @@ def test_coexisting_configurations(click_runner,
|
|||
assert os.path.isfile(felix_file_location)
|
||||
assert len(os.listdir(public_keys_dir)) == 3
|
||||
|
||||
# Use a custom local filepath to init an persistent Alice
|
||||
# Use a custom local filepath to init a persistent Alice
|
||||
alice_init_args = ('alice', 'init',
|
||||
'--network', TEMPORARY_DOMAIN,
|
||||
'--provider-uri', TEST_PROVIDER_URI,
|
||||
|
@ -94,7 +94,7 @@ def test_coexisting_configurations(click_runner,
|
|||
assert os.path.isfile(alice_file_location)
|
||||
assert len(os.listdir(public_keys_dir)) == 5
|
||||
|
||||
# Use the same local filepath to init an persistent Ursula
|
||||
# Use the same local filepath to init a persistent Ursula
|
||||
init_args = ('ursula', 'init',
|
||||
'--network', TEMPORARY_DOMAIN,
|
||||
'--provider-uri', TEST_PROVIDER_URI,
|
||||
|
@ -128,15 +128,16 @@ def test_coexisting_configurations(click_runner,
|
|||
# Run
|
||||
#
|
||||
|
||||
# Now start running your Ursula!
|
||||
# Run an Ursula amidst the other configuration files
|
||||
run_args = ('ursula', 'run', '--dry-run',
|
||||
'--config-file', another_ursula_configuration_file_location)
|
||||
|
||||
user_input = f'{INSECURE_DEVELOPMENT_PASSWORD}'
|
||||
result = click_runner.invoke(nucypher_cli, run_args, input=user_input, catch_exceptions=False)
|
||||
assert result.exit_code == 0
|
||||
assert another_ursula in result.output
|
||||
|
||||
# Check that the proper Ursula console is attached
|
||||
assert another_ursula in result.output
|
||||
|
||||
#
|
||||
# Destroy
|
||||
|
|
|
@ -220,7 +220,7 @@ def test_ursula_destroy_configuration(custom_filepath, click_runner):
|
|||
|
||||
# Ensure the files are deleted from the filesystem
|
||||
assert not os.path.isfile(custom_config_filepath), 'Files still exist' # ... shes's gone...
|
||||
assert os.path.isdir(custom_filepath), 'Nucypher files no longer still exist' # ... but not NuCypher ...
|
||||
assert os.path.isdir(custom_filepath), 'Nucypher files no longer exist' # ... but not NuCypher ...
|
||||
|
||||
# If this test started off with a live configuration, ensure it still exists
|
||||
if preexisting_live_configuration:
|
||||
|
|
Loading…
Reference in New Issue