Hook up CLI with JSON Character control; Extract CLI actions module for shared config setup and tear down logic.

pull/802/head
Kieran R. Prasch 2019-02-21 22:37:17 -07:00 committed by Kieran Prasch
parent 89c5f15ec0
commit f1cd291df2
No known key found for this signature in database
GPG Key ID: 199AB839D4125A62
9 changed files with 202 additions and 252 deletions

View File

@ -1,8 +1,12 @@
import shutil
from typing import List
import click
from nacl.exceptions import CryptoError
from twisted.logger import Logger
from nucypher.blockchain.eth.registry import EthereumContractRegistry
from nucypher.characters.lawful import Ursula
from nucypher.config.constants import DEFAULT_CONFIG_ROOT
@ -20,6 +24,19 @@ Delete {}?'''
LOG = Logger('cli.actions')
def load_seednodes(min_stake: int, federated_only: bool, teacher_uris: list = None) -> List[Ursula]:
teacher_nodes = list()
if teacher_uris is None:
# Default teacher nodes can be placed here
return teacher_nodes
for uri in teacher_uris:
teacher_node = Ursula.from_teacher_uri(teacher_uri=uri,
min_stake=min_stake,
federated_only=federated_only)
teacher_nodes.append(teacher_node)
return teacher_nodes
def destroy_system_configuration(config_class,
config_file=None,
network=None,
@ -56,3 +73,29 @@ def destroy_system_configuration(config_class,
message = "Deleted configuration files at {}".format(character_config.config_root)
click.secho(message, fg='green')
log.debug(message)
def unlock_keyring(configuration, password):
try:
click.secho("Decrypting keyring...", fg='blue')
configuration.keyring.unlock(password=password)
except CryptoError:
raise configuration.keyring.AuthenticationFailed
def connect_to_blockchain(configuration, recompile_contracts: bool = False):
try:
configuration.connect_to_blockchain(recompile_contracts=recompile_contracts)
configuration.connect_to_contracts()
except EthereumContractRegistry.NoRegistry:
message = "Cannot configure blockchain character: No contract registry found; " \
"Did you mean to pass --federated-only?"
raise EthereumContractRegistry.NoRegistry(message)
def forget(configuration):
"""Forget all known nodes via storages"""
click.confirm("Permanently delete all known node data?", abort=True)
configuration.forget_nodes()
message = "Removed all stored node node metadata and certificates"
click.secho(message=message, fg='red')

View File

@ -1,14 +1,11 @@
import datetime
import os
from base64 import b64encode
import click
import maya
from nacl.exceptions import CryptoError
from nucypher.characters.banners import ALICE_BANNER
from nucypher.characters.lawful import Ursula
from nucypher.cli.actions import destroy_system_configuration
from nucypher.cli import actions, painting
from nucypher.cli.config import nucypher_click_config
from nucypher.cli.painting import paint_configuration
from nucypher.cli.types import NETWORK_PORT, EXISTING_READABLE_FILE
@ -79,44 +76,35 @@ def alice(click_config,
if not config_root: # Flag
config_root = click_config.config_file # Envvar
alice_config = AliceConfiguration.generate(password=click_config.get_password(confirm=True),
config_root=config_root,
rest_host="localhost",
domains={network} if network else None,
federated_only=federated_only,
no_registry=True, # Yes we have no registry,
registry_filepath=registry_filepath,
provider_uri=provider_uri,
)
new_alice_config = AliceConfiguration.generate(password=click_config.get_password(confirm=True),
config_root=config_root,
rest_host="localhost",
domains={network} if network else None,
federated_only=federated_only,
no_registry=True, # Yes we have no registry,
registry_filepath=registry_filepath,
provider_uri=provider_uri)
if not quiet:
click.secho("Generated keyring {}".format(alice_config.keyring_dir), fg='green')
click.secho("Saved configuration file {}".format(alice_config.config_file_location), fg='green')
# Give the use a suggestion as to what to do next...
how_to_run_message = "\nTo run an Alice node from the default configuration filepath run: \n\n'{}'\n"
suggested_command = 'nucypher alice run'
if config_root is not None:
config_file_location = os.path.join(config_root, config_file or AliceConfiguration.CONFIG_FILENAME)
suggested_command += ' --config-file {}'.format(config_file_location)
click.secho(how_to_run_message.format(suggested_command), fg='green')
return # FIN
painting.paint_new_installation_help(new_configuration=new_alice_config,
config_root=config_root,
config_file=config_file)
return
else:
click.secho("OK")
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)
destroy_system_configuration(config_class=AliceConfiguration,
config_file=config_file,
network=network,
config_root=config_root,
force=force)
actions.destroy_system_configuration(config_class=AliceConfiguration,
config_file=config_file,
network=network,
config_root=config_root,
force=force)
if not quiet:
click.secho("Destroyed {}".format(config_root))
return
@ -129,8 +117,8 @@ def alice(click_config,
alice_config = AliceConfiguration(dev_mode=True,
domains={network},
provider_uri=provider_uri,
federated_only=True,
)
federated_only=True)
else:
alice_config = AliceConfiguration.from_configuration_file(
filepath=config_file,
@ -138,34 +126,26 @@ def alice(click_config,
rest_port=discovery_port,
provider_uri=provider_uri)
# Teacher
teacher_nodes = list()
if teacher_uri:
teacher_node = Ursula.from_teacher_uri(teacher_uri=teacher_uri,
min_stake=min_stake,
federated_only=alice_config.federated_only)
teacher_nodes.append(teacher_node)
if not dev:
# Keyring
try:
click.secho("Decrypting keyring...", fg='blue')
alice_config.keyring.unlock(password=click_config.get_password())
except CryptoError:
raise alice_config.keyring.AuthenticationFailed
finally:
click_config.alice_config = alice_config
actions.unlock_keyring(password=click_config.get_password(), configuration=alice_config)
# Teacher Ursula
teacher_uris = [teacher_uri] if teacher_uri else list()
teacher_nodes = actions.load_seednodes(teacher_uris=teacher_uris,
min_stake=min_stake,
federated_only=federated_only)
# Produce
ALICE = alice_config(known_nodes=teacher_nodes)
if action == "run":
return ALICE.control.run(http_port=http_port, dry_run=dry_run)
click.secho(f"Alice Verifying Key {bytes(ALICE.stamp).hex()}", fg="green", bold=True)
return ALICE.control.start_wsgi_controller(http_port=http_port, dry_run=dry_run)
elif action == "view":
"""Paint an existing configuration to the console"""
paint_configuration(config_filepath=config_file or alice_config.config_file_location)
return
json_config = AliceConfiguration._read_configuration_file(filepath=config_file or alice_config.config_file_location)
paint_configuration(json_config=json_config)
return json_config
elif action == "create-policy":
if not all((bob_verifying_key, bob_encrypting_key, label)):
@ -187,7 +167,6 @@ def alice(click_config,
elif action == "derive-policy":
response = ALICE.control.derive_policy(label=label)
click.secho(response)
# click.secho(f"Created new Policy with label {label} | {policy_encrypting_key}", fg='green')
return response
elif action == "grant":

View File

@ -1,22 +1,14 @@
import json
import os
from base64 import b64encode
import click
import requests
from nacl.exceptions import CryptoError
from hendrix.deploy.base import HendrixDeploy
from nucypher.characters.banners import BOB_BANNER
from nucypher.characters.lawful import Ursula
from nucypher.cli.actions import destroy_system_configuration
from nucypher.cli import actions, painting
from nucypher.cli.config import nucypher_click_config
from nucypher.cli.painting import paint_configuration
from nucypher.cli.types import NETWORK_PORT, EXISTING_READABLE_FILE
from nucypher.config.characters import BobConfiguration
from nucypher.config.constants import GLOBAL_DOMAIN
from nucypher.crypto.kits import UmbralMessageKit
from nucypher.crypto.powers import DecryptingPower
@ -75,27 +67,18 @@ def bob(click_config,
if not config_root: # Flag
config_root = click_config.config_file # Envvar
bob_config = BobConfiguration.generate(password=click_config.get_password(confirm=True),
config_root=config_root,
rest_host="localhost",
domains={network} if network else None,
federated_only=federated_only,
no_registry=True, # Yes we have no registry,
registry_filepath=registry_filepath,
provider_uri=provider_uri,
)
new_bob_config = BobConfiguration.generate(password=click_config.get_password(confirm=True),
config_root=config_root,
rest_host="localhost",
domains={network} if network else None,
federated_only=federated_only,
no_registry=True, # Yes we have no registry,
registry_filepath=registry_filepath,
provider_uri=provider_uri,
)
if not quiet:
click.secho("Generated keyring {}".format(bob_config.keyring_dir), fg='green')
click.secho("Saved configuration file {}".format(bob_config.config_file_location), fg='green')
# Give the use a suggestion as to what to do next...
how_to_run_message = "\nTo run an Bob node from the default configuration filepath run: \n\n'{}'\n"
suggested_command = 'nucypher bob run'
if config_root is not None:
config_file_location = os.path.join(config_root, config_file or BobConfiguration.CONFIG_FILENAME)
suggested_command += ' --config-file {}'.format(config_file_location)
click.secho(how_to_run_message.format(suggested_command), fg='green')
painting.paint_new_installation_help(new_configuration=new_bob_config)
return # FIN
else:
@ -108,11 +91,11 @@ def bob(click_config,
message = "'nucypher ursula destroy' cannot be used in --dev mode"
raise click.BadOptionUsage(option_name='--dev', message=message)
destroy_system_configuration(config_class=BobConfiguration,
config_file=config_file,
network=network,
config_root=config_root,
force=force)
actions.destroy_system_configuration(config_class=BobConfiguration,
config_file=config_file,
network=network,
config_root=config_root,
force=force)
if not quiet:
click.secho("Destroyed {}".format(config_root))
return
@ -134,13 +117,11 @@ def bob(click_config,
rest_port=discovery_port,
provider_uri=provider_uri)
# Teacher
teacher_nodes = list()
if teacher_uri:
teacher_node = Ursula.from_teacher_uri(teacher_uri=teacher_uri,
min_stake=min_stake,
federated_only=bob_config.federated_only)
teacher_nodes.append(teacher_node)
# Teacher Ursula
teacher_uris = [teacher_uri] if teacher_uri else list()
teacher_nodes = actions.load_seednodes(teacher_uris=teacher_uris,
min_stake=min_stake,
federated_only=federated_only)
# Produce
BOB = bob_config(known_nodes=teacher_nodes)
@ -148,47 +129,30 @@ def bob(click_config,
if action == "run":
if not dev:
# Keyring
try:
click.secho("Decrypting keyring...", fg='blue')
bob_config.keyring.unlock(password=click_config.get_password())
except CryptoError:
raise bob_config.keyring.AuthenticationFailed
finally:
click_config.bob_config = bob_config
# Bob Control
bob_control = BOB.make_wsgi_app()
click.secho("Starting Bob Character Control...")
actions.unlock_keyring(configuration=bob_config, password=click_config.get_password())
click.secho(f"Bob Verifying Key {bytes(BOB.stamp).hex()}", fg="green", bold=True)
click.secho(f"Bob Encrypting Key {bytes(BOB.public_keys(DecryptingPower)).hex()}", fg="blue", bold=True)
# Run
if dry_run:
return
hx_deployer = HendrixDeploy(action="start", options={"wsgi": bob_control, "http_port": http_port})
hx_deployer.run() # <--- Blocking Call to Reactor
BOB.control.start_wsgi_control(dry_run=dry_run, http_port=http_port)
elif action == "view":
"""Paint an existing configuration to the console"""
paint_configuration(config_filepath=config_file or bob_config.config_file_location)
return
json_config = BobConfiguration._read_configuration_file(filepath=config_file or bob_config.config_file_location)
paint_configuration(json_config=json_config)
return json_config
elif action == "retrieve":
# bob_request_data = {
# 'label': b64encode(label).decode(),
# 'policy_encrypting_key': policy_encrypting_key,
# 'alice_signing_pubkey': alice_encrypting_key,
# # 'message_kit': b64encode(bob_message_kit.to_bytes()).decode(), # TODO
# }
stdin_text = click.get_text_stream('stdin')
message_kit = UmbralMessageKit.from_bytes(bytes(stdin_text))
result = BOB.retrieve(label=label, alice_verifying_key=alice_encrypting_key, message_kit=message_kit)
click.secho(result)
return
bob_request_data = {
'label': b64encode(label).decode(),
'policy_encrypting_pubkey': policy_encrypting_key,
'alice_signing_pubkey': alice_encrypting_key,
# 'message_kit': b64encode(bob_message_kit.to_bytes()).decode(), # TODO
}
response = BOB.control.retrieve(request=bob_request_data)
click.secho(response)
return response
else:
raise click.BadArgumentUsage(f"No such argument {action}")

View File

@ -1,9 +1,8 @@
import click
from umbral.keys import UmbralPublicKey
from hendrix.deploy.base import HendrixDeploy
from nucypher.characters.lawful import Enrico
from nucypher.cli.types import NETWORK_PORT
from umbral.keys import UmbralPublicKey
ENRICO_BANNER = r"""
___
@ -19,7 +18,7 @@ the Encryptor.
@click.command()
@click.argument('action')
@click.option('--dry-run', '-x', help="Execute normally without actually starting the node", is_flag=True)
@click.option('--http-port', help="The host port to run Moe HTTP services on", type=NETWORK_PORT, default=5151) # TODO
@click.option('--http-port', help="The host port to run Moe HTTP services on", type=NETWORK_PORT, default=5151) # TODO: default ports
@click.option('--policy-encrypting-key', help="Encrypting Public Key for Policy as hexidecimal string", type=click.STRING)
def enrico(action, policy_encrypting_key, dry_run, http_port):
"""
@ -31,19 +30,7 @@ def enrico(action, policy_encrypting_key, dry_run, http_port):
if action == 'run': # Forest
policy_encrypting_key = UmbralPublicKey.from_bytes(bytes.fromhex(policy_encrypting_key))
ENRICO = Enrico(policy_encrypting_key=policy_encrypting_key)
# Enrico Control
enrico_control = ENRICO.make_wsgi_app()
click.secho("Starting Enrico Character Control...")
click.secho(f"Enrico Verifying Key {bytes(ENRICO.stamp).hex()}", fg="green", bold=True)
# Run
if dry_run:
return
hx_deployer = HendrixDeploy(action="start", options={"wsgi": enrico_control, "http_port": http_port})
hx_deployer.run() # <--- Blocking Call to Reactor
ENRICO.control.start_wsgi_conrol(http_port=http_port, dry_run=dry_run)
else:
raise click.BadArgumentUsage

View File

@ -30,6 +30,7 @@ from twisted.logger import globalLogPublisher
from nucypher.blockchain.eth.constants import MIN_LOCKED_PERIODS, MAX_MINTING_PERIODS
from nucypher.blockchain.eth.registry import EthereumContractRegistry
from nucypher.characters.lawful import Ursula
from nucypher.cli import actions
from nucypher.cli.actions import destroy_system_configuration
from nucypher.cli.config import nucypher_click_config
from nucypher.cli.painting import paint_configuration
@ -88,6 +89,7 @@ the Untrusted Re-Encryption Proxy.
@click.option('--config-file', help="Path to configuration file", type=EXISTING_READABLE_FILE)
@click.option('--metadata-dir', help="Custom known metadata directory", type=EXISTING_WRITABLE_DIRECTORY)
@click.option('--provider-uri', help="Blockchain provider's URI", type=click.STRING)
@click.option('--recompile-solidity', help="Compile solidity from source when making a web3 connection", is_flag=True)
@click.option('--no-registry', help="Skip importing the default contract registry", is_flag=True)
@click.option('--registry-filepath', help="Custom contract registry filepath", type=EXISTING_READABLE_FILE)
@nucypher_click_config
@ -112,6 +114,7 @@ def ursula(click_config,
config_file,
metadata_dir, # TODO: Start nodes from an additional existing metadata dir
provider_uri,
recompile_solidity,
no_registry,
registry_filepath
) -> None:
@ -260,21 +263,11 @@ def ursula(click_config,
# federated_only=federated_only,
)
try: # Unlock Keyring
if not quiet:
click.secho('Decrypting keyring...', fg='blue')
ursula_config.keyring.unlock(password=click_config.get_password()) # Takes ~3 seconds, ~1GB Ram
except CryptoError:
raise ursula_config.keyring.AuthenticationFailed
actions.unlock_keyring(configuration=ursula_config,
password=click_config.get_password())
if not ursula_config.federated_only:
try:
ursula_config.connect_to_blockchain(recompile_contracts=False)
ursula_config.connect_to_contracts()
except EthereumContractRegistry.NoRegistry:
message = "Cannot configure blockchain character: No contract registry found; " \
"Did you mean to pass --federated-only?"
raise EthereumContractRegistry.NoRegistry(message)
actions.connect_to_blockchain(configuration=ursula_config, recompile_contracts=recompile_solidity)
click_config.ursula_config = ursula_config # Pass Ursula's config onto staking sub-command
@ -295,17 +288,16 @@ def ursula(click_config,
#
# Seed - Step 1
#
teacher_nodes = list()
if teacher_uri:
node = Ursula.from_teacher_uri(teacher_uri=teacher_uri,
min_stake=min_stake,
federated_only=ursula_config.federated_only)
teacher_nodes.append(node)
teacher_uris = [teacher_uri] if teacher_uri else list()
teacher_nodes = actions.load_seednodes(teacher_uris=teacher_uris,
min_stake=min_stake,
federated_only=federated_only)
#
# Produce - Step 2
#
ursula = ursula_config(known_nodes=teacher_nodes, lonely=lonely)
URSULA = ursula_config(known_nodes=teacher_nodes, lonely=lonely)
# GO!
try:
@ -314,15 +306,15 @@ def ursula(click_config,
# Run - Step 3
#
click.secho("Connecting to {}".format(','.join(str(d) for d in ursula_config.domains)), fg='blue', bold=True)
click.secho("Running Ursula {} on {}".format(ursula, ursula.rest_interface), fg='green', bold=True)
click.secho("Running Ursula {} on {}".format(URSULA, URSULA.rest_interface), fg='green', bold=True)
if not debug:
stdio.StandardIO(UrsulaCommandProtocol(ursula=ursula))
stdio.StandardIO(UrsulaCommandProtocol(ursula=URSULA))
if dry_run:
# That's all folks!
return
ursula.get_deployer().run() # <--- Blocking Call (Reactor)
URSULA.get_deployer().run() # <--- Blocking Call (Reactor)
except Exception as e:
ursula_config.log.critical(str(e))
@ -341,23 +333,20 @@ def ursula(click_config,
elif action == "save-metadata":
"""Manually save a node self-metadata file"""
ursula = ursula_config.produce(ursula_config=ursula_config)
metadata_path = ursula.write_node_metadata(node=ursula)
URSULA = ursula_config.produce(ursula_config=ursula_config)
metadata_path = ursula.write_node_metadata(node=URSULA)
if not quiet:
click.secho("Successfully saved node metadata to {}.".format(metadata_path), fg='green')
return
elif action == "view":
"""Paint an existing configuration to the console"""
paint_configuration(config_filepath=config_file or ursula_config.config_file_location)
return
json_config = UrsulaConfiguration._read_configuration_file(filepath=config_file or ursula_config.config_file_location)
paint_configuration(json_config=json_config)
return json_config
elif action == "forget":
"""Forget all known nodes via storages"""
click.confirm("Permanently delete all known node data?", abort=True)
ursula_config.forget_nodes()
message = "Removed all stored node node metadata and certificates"
click.secho(message=message, fg='red')
actions.forget(configuration=ursula_config)
return
else:
@ -413,7 +402,7 @@ def stake(click_config,
click.echo(row)
click.echo("Select ethereum address")
account_selection = click.prompt("Enter 0-{}".format(len(ur.accounts)), type=click.INT)
account_selection = click.prompt("Enter 0-{}".format(len(ursula_config.accounts)), type=click.INT)
address = click_config.accounts[account_selection]
if action == 'list':

View File

@ -15,7 +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 collections
import os
import click
@ -23,7 +23,6 @@ from constant_sorrow.constants import NO_PASSWORD
from twisted.logger import Logger
from twisted.logger import globalLogPublisher
from nucypher.characters.banners import BANNER
from nucypher.config.constants import NUCYPHER_SENTRY_ENDPOINT
from nucypher.utilities.logging import (
logToSentry,
@ -67,12 +66,39 @@ class NucypherClickConfig:
return self.__keyring_password
# Register the above click configuration class as a decorator
class NucypherDeployerClickConfig(NucypherClickConfig):
# Deploy Environment Variables
miner_escrow_deployment_secret = os.environ.get("NUCYPHER_MINER_ESCROW_SECRET", None)
policy_manager_deployment_secret = os.environ.get("NUCYPHER_POLICY_MANAGER_SECRET", None)
user_escrow_proxy_deployment_secret = os.environ.get("NUCYPHER_USER_ESCROW_PROXY_SECRET", None)
Secrets = collections.namedtuple('Secrets', ('miner_secret', 'policy_secret', 'escrow_proxy_secret'))
def collect_deployment_secrets(self) -> Secrets:
miner_secret = self.miner_escrow_deployment_secret
if not miner_secret:
miner_secret = click.prompt('Enter MinerEscrow Deployment Secret', hide_input=True,
confirmation_prompt=True)
policy_secret = self.policy_manager_deployment_secret
if not policy_secret:
policy_secret = click.prompt('Enter PolicyManager Deployment Secret', hide_input=True,
confirmation_prompt=True)
escrow_proxy_secret = self.user_escrow_proxy_deployment_secret
if not escrow_proxy_secret:
escrow_proxy_secret = click.prompt('Enter UserEscrowProxy Deployment Secret', hide_input=True,
confirmation_prompt=True)
secrets = self.Secrets(miner_secret=miner_secret, # type: str
policy_secret=policy_secret, # type: str
escrow_proxy_secret=escrow_proxy_secret # type: str
)
return secrets
# Register the above click configuration classes as a decorators
nucypher_click_config = click.make_pass_decorator(NucypherClickConfig, ensure=True)
def echo_version(ctx, param, value):
if not value or ctx.resilient_parsing:
return
click.secho(BANNER, bold=True)
ctx.exit()
nucypher_deployer_config = click.make_pass_decorator(NucypherDeployerClickConfig, ensure=True)

View File

@ -15,76 +15,17 @@ 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 collections
import json
import os
import click
from twisted.logger import Logger
from twisted.logger import globalLogPublisher
from nucypher.blockchain.eth.actors import Deployer
from nucypher.blockchain.eth.chains import Blockchain
from nucypher.blockchain.eth.interfaces import BlockchainInterface
from nucypher.characters.banners import BANNER
from nucypher.cli.config import nucypher_deployer_config
from nucypher.cli.types import EIP55_CHECKSUM_ADDRESS, EXISTING_READABLE_FILE
from nucypher.config.constants import DEFAULT_CONFIG_ROOT
from nucypher.utilities.logging import getTextFileObserver
#
# Click Eager Functions
#
def echo_version(ctx, param, value):
if not value or ctx.resilient_parsing:
return
click.secho(BANNER, bold=True)
ctx.exit()
class NucypherDeployerClickConfig:
# Environment Variables
log_to_file = os.environ.get("NUCYPHER_FILE_LOGS", True)
miner_escrow_deployment_secret = os.environ.get("NUCYPHER_MINER_ESCROW_SECRET", None)
policy_manager_deployment_secret = os.environ.get("NUCYPHER_POLICY_MANAGER_SECRET", None)
user_escrow_proxy_deployment_secret = os.environ.get("NUCYPHER_USER_ESCROW_PROXY_SECRET", None)
Secrets = collections.namedtuple('Secrets', ('miner_secret', 'policy_secret', 'escrow_proxy_secret'))
def __init__(self):
if self.log_to_file:
globalLogPublisher.addObserver(getTextFileObserver())
self.log = Logger(self.__class__.__name__)
def collect_deployment_secrets(self) -> Secrets:
miner_secret = self.miner_escrow_deployment_secret
if not miner_secret:
miner_secret = click.prompt('Enter MinerEscrow Deployment Secret', hide_input=True,
confirmation_prompt=True)
policy_secret = self.policy_manager_deployment_secret
if not policy_secret:
policy_secret = click.prompt('Enter PolicyManager Deployment Secret', hide_input=True,
confirmation_prompt=True)
escrow_proxy_secret = self.user_escrow_proxy_deployment_secret
if not escrow_proxy_secret:
escrow_proxy_secret = click.prompt('Enter UserEscrowProxy Deployment Secret', hide_input=True,
confirmation_prompt=True)
secrets = self.Secrets(miner_secret=miner_secret, # type: str
policy_secret=policy_secret, # type: str
escrow_proxy_secret=escrow_proxy_secret # type: str
)
return secrets
# Register the above class as a decorator
nucypher_deployer_config = click.make_pass_decorator(NucypherDeployerClickConfig, ensure=True)
@click.command()

View File

@ -20,9 +20,9 @@ along with nucypher. If not, see <https://www.gnu.org/licenses/>.
import click
from nucypher.characters.banners import BANNER
from nucypher.cli import status
from nucypher.cli.characters import moe, bob, ursula, alice, enrico
from nucypher.cli.config import echo_version, nucypher_click_config
from nucypher.cli import moe, ursula, status, alice, bob, enrico
from nucypher.cli.config import nucypher_click_config
from nucypher.cli.painting import BANNER, echo_version
from nucypher.utilities.logging import GlobalConsoleLogger
GlobalConsoleLogger.start_if_not_started()

View File

@ -14,14 +14,13 @@ GNU Affero General Public License for more details.
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 os
import click
import maya
from constant_sorrow.constants import NO_KNOWN_NODES
import nucypher
from constant_sorrow.constants import NO_KNOWN_NODES
from nucypher.config.characters import UrsulaConfiguration
from nucypher.config.constants import SEEDNODES
@ -29,6 +28,29 @@ from nucypher.config.constants import SEEDNODES
# Paint
#
def echo_version(ctx, param, value):
if not value or ctx.resilient_parsing:
return
click.secho(BANNER, bold=True)
ctx.exit()
def paint_new_installation_help(new_configuration, config_root=None, config_file=None):
character_config_class = new_configuration.__class__
character_name = character_config_class._CHARACTER_CLASS.__name__.lower()
click.secho("Generated keyring {}".format(new_configuration.keyring_dir), fg='green')
click.secho("Saved configuration file {}".format(new_configuration.config_file_location), fg='green')
# Give the use a suggestion as to what to do next...
suggested_command = f'nucypher {character_name} run'
how_to_run_message = f"\nTo run an {character_name.capitalize()} node from the default configuration filepath run: \n\n'{suggested_command}'\n"
if config_root is not None:
config_file_location = os.path.join(config_root, config_file or character_config_class.CONFIG_FILENAME)
suggested_command += ' --config-file {}'.format(config_file_location)
click.secho(how_to_run_message.format(suggested_command), fg='green')
def build_fleet_state_status(ursula) -> str:
# Build FleetState status line
if ursula.known_nodes.checksum is not NO_KNOWN_NODES:
@ -46,9 +68,8 @@ def build_fleet_state_status(ursula) -> str:
return fleet_state
def paint_configuration(config_filepath: str) -> None:
json_config = UrsulaConfiguration._read_configuration_file(filepath=config_filepath)
click.secho("\n======== Ursula Configuration ======== \n", bold=True)
def paint_configuration(json_config: dict) -> None:
click.secho("\n======== Character Configuration ======== \n", bold=True)
for key, value in json_config.items():
click.secho("{} = {}".format(key, value))