diff --git a/CHANGELOG.md b/CHANGELOG.md index c34a5732e..b5ef2f540 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Various endpoint-related types have moved under the `ccf::endpoints` namespace. Apps will need to rename these types where they are not using `auto`, for instance to `ccf::endpoints::EndpointContext` and `ccf::endpoints::ForwardingRequired`. - Ledger entry frames are no longer serialised with `msgpack` (#2343). - In JavaScript apps, the field `caller.jwt.key_issuer` in the `Request` object has been renamed `caller.jwt.keyIssuer` (#2362). +- The proposals `set_module`, `remove_module` and `set_js_app` have been removed and `deploy_js_app` renamed to `set_js_app` (#2391). ## [0.19.3] diff --git a/doc/governance/proposals.rst b/doc/governance/proposals.rst index b01285c39..10bb9f347 100644 --- a/doc/governance/proposals.rst +++ b/doc/governance/proposals.rst @@ -23,7 +23,7 @@ Assuming the CCF Python package has been installed in the current Python environ python -m ccf.proposal_generator usage: proposal_generator.py [-h] [-po PROPOSAL_OUTPUT_FILE] [-vo VOTE_OUTPUT_FILE] [-pp] [-i] [-v] - {deploy_js_app,new_member,new_node_code,set_user,rekey_ledger,remove_ca_cert_bundle,remove_js_app,remove_jwt_issuer,remove_member,remove_module,remove_user,retire_node,retire_node_code,set_ca_cert_bundle,set_js_app,set_jwt_issuer,set_jwt_public_signing_keys,set_member_data,set_module,set_recovery_threshold,set_user_data,transition_service_to_open,trust_node,update_recovery_shares} + {new_member,new_node_code,set_user,rekey_ledger,remove_ca_cert_bundle,remove_js_app,remove_jwt_issuer,remove_member,remove_user,retire_node,retire_node_code,set_ca_cert_bundle,set_js_app,set_jwt_issuer,set_jwt_public_signing_keys,set_member_data,set_recovery_threshold,set_user_data,transition_service_to_open,trust_node,update_recovery_shares} Additional detail is available from the ``--help`` option. You can also find the script in a checkout of CCF: diff --git a/python/ccf/proposal_generator.py b/python/ccf/proposal_generator.py index 2a43e13f4..5407f6922 100644 --- a/python/ccf/proposal_generator.py +++ b/python/ccf/proposal_generator.py @@ -10,7 +10,6 @@ import os import sys import shutil import tempfile -from pathlib import PurePosixPath from typing import Union, Optional, Any, List, Dict from cryptography import x509 @@ -331,17 +330,7 @@ def set_user_data(user_id: str, user_data: Any, **kwargs): @cli_proposal -def set_js_app(app_script_path: str, **kwargs): - LOG.error( - "set_js_app proposal type is deprecated - update to use deploy_js_app instead" - ) - with open(app_script_path) as f: - app_script = f.read() - return build_proposal("set_js_app", app_script, **kwargs) - - -@cli_proposal -def deploy_js_app(bundle_path: str, **kwargs): +def set_js_app(bundle_path: str, **kwargs): # read modules if os.path.isfile(bundle_path): tmp_dir = tempfile.TemporaryDirectory(prefix="ccf") @@ -369,7 +358,7 @@ def deploy_js_app(bundle_path: str, **kwargs): "bundle": {"metadata": metadata, "modules": modules}, } - return build_proposal("deploy_js_app", proposal_args, **kwargs) + return build_proposal("set_js_app", proposal_args, **kwargs) @cli_proposal @@ -377,27 +366,6 @@ def remove_js_app(**kwargs): return build_proposal("remove_js_app", **kwargs) -@cli_proposal -def set_module(module_name: str, module_path: str, **kwargs): - module_name_ = PurePosixPath(module_name) - if not module_name_.is_absolute(): - raise ValueError("module name must be an absolute path") - if any(folder in [".", ".."] for folder in module_name_.parents): - raise ValueError("module name must not contain . or .. components") - if module_name_.suffix == ".js": - with open(module_path) as f: - js = f.read() - proposal_args = {"name": module_name, "module": js} - else: - raise ValueError("module name must end with .js") - return build_proposal("set_module", proposal_args, **kwargs) - - -@cli_proposal -def remove_module(module_name: str, **kwargs): - return build_proposal("remove_module", module_name, **kwargs) - - def read_modules(modules_path: str) -> List[dict]: modules = [] for path in glob.glob(f"{modules_path}/**/*.js", recursive=True): diff --git a/src/node/rpc/member_frontend.h b/src/node/rpc/member_frontend.h index ba337d5ad..a2c91937f 100644 --- a/src/node/rpc/member_frontend.h +++ b/src/node/rpc/member_frontend.h @@ -167,7 +167,7 @@ namespace ccf } } - bool deploy_js_app(kv::Tx& tx, const JsBundle& bundle) + bool set_js_app(kv::Tx& tx, const JsBundle& bundle) { std::string module_prefix = "/"; remove_modules(tx, module_prefix); @@ -334,36 +334,17 @@ namespace ccf std::string, std::function> hardcoded_funcs = { - // set the js application script + // deploy the js application bundle {"set_js_app", - [this](const ProposalId&, kv::Tx& tx, const nlohmann::json& args) { - const std::string app = args; - set_js_scripts(tx, lua::Interpreter().invoke(app)); - return true; - }}, - // deploy the js application bundle - {"deploy_js_app", [this](const ProposalId&, kv::Tx& tx, const nlohmann::json& args) { const auto parsed = args.get(); - return deploy_js_app(tx, parsed.bundle); + return set_js_app(tx, parsed.bundle); }}, // undeploy/remove the js application {"remove_js_app", [this](const ProposalId&, kv::Tx& tx, const nlohmann::json&) { return remove_js_app(tx); }}, - // add/update a module - {"set_module", - [this](const ProposalId&, kv::Tx& tx, const nlohmann::json& args) { - const auto parsed = args.get(); - return set_module(tx, parsed.name, parsed.module); - }}, - // remove a module - {"remove_module", - [this](const ProposalId&, kv::Tx& tx, const nlohmann::json& args) { - const auto name = args.get(); - return remove_module(tx, name); - }}, // add a new member {"new_member", [this](const ProposalId&, kv::Tx& tx, const nlohmann::json& args) { diff --git a/tests/infra/consortium.py b/tests/infra/consortium.py index 7fa2ba27f..a6ad78b1b 100644 --- a/tests/infra/consortium.py +++ b/tests/infra/consortium.py @@ -397,18 +397,8 @@ class Consortium: proposal = self.get_any_active_member().propose(remote_node, proposal) self.vote_using_majority(remote_node, proposal, careful_vote) - def set_js_app(self, remote_node, app_script_path): - LOG.error( - "set_js_app proposal type is deprecated - update to use deploy_js_app instead" - ) - proposal_body, careful_vote = self.make_proposal("set_js_app", app_script_path) - proposal = self.get_any_active_member().propose(remote_node, proposal_body) - return self.vote_using_majority(remote_node, proposal, careful_vote) - - def deploy_js_app(self, remote_node, app_bundle_path): - proposal_body, careful_vote = self.make_proposal( - "deploy_js_app", app_bundle_path - ) + def set_js_app(self, remote_node, app_bundle_path): + proposal_body, careful_vote = self.make_proposal("set_js_app", app_bundle_path) proposal = self.get_any_active_member().propose(remote_node, proposal_body) # Large apps take a long time to process - wait longer than normal for commit return self.vote_using_majority(remote_node, proposal, careful_vote, timeout=10) diff --git a/tests/infra/e2e_args.py b/tests/infra/e2e_args.py index a332eddc0..b6a0bb3ba 100644 --- a/tests/infra/e2e_args.py +++ b/tests/infra/e2e_args.py @@ -114,7 +114,6 @@ def cli_args(add=lambda x: None, parser=None, accept_unknown=False): action="append", default=[], ) - parser.add_argument("-j", "--js-app-script", help="Path to js app script") parser.add_argument("--js-app-bundle", help="Path to js app bundle") parser.add_argument( "--jwt-issuer", @@ -287,8 +286,7 @@ def cli_args(add=lambda x: None, parser=None, accept_unknown=False): else: args.library_dir = args.binary_dir - # js_app_script is deprecated - if not args.package and (args.js_app_script or args.js_app_bundle): + if not args.package and args.js_app_bundle: args.package = "libjs_generic" if accept_unknown: diff --git a/tests/infra/network.py b/tests/infra/network.py index 8d75794b7..0101033fe 100644 --- a/tests/infra/network.py +++ b/tests/infra/network.py @@ -397,19 +397,8 @@ class Network: self.consortium.activate(self.find_random_node()) - if args.js_app_script: - LOG.error( - "--js-app-script is deprecated - update to --js-app-bundle instead" - ) - infra.proc.ccall( - "cp", args.js_app_script, args.binary_dir - ).check_returncode() - self.consortium.set_js_app( - remote_node=self.find_random_node(), app_script_path=args.js_app_script - ) - if args.js_app_bundle: - self.consortium.deploy_js_app( + self.consortium.set_js_app( remote_node=self.find_random_node(), app_bundle_path=args.js_app_bundle ) diff --git a/tests/js-modules/modules.py b/tests/js-modules/modules.py index bd8343c6d..5627fe2fe 100644 --- a/tests/js-modules/modules.py +++ b/tests/js-modules/modules.py @@ -24,17 +24,6 @@ THIS_DIR = os.path.dirname(__file__) PARENT_DIR = os.path.normpath(os.path.join(THIS_DIR, os.path.pardir)) -def make_module_set_proposal(module_path, file_path, network): - primary, _ = network.find_nodes() - proposal_body, careful_vote = ccf.proposal_generator.set_module( - module_path, file_path - ) - proposal = network.consortium.get_any_active_member().propose( - primary, proposal_body - ) - network.consortium.vote_using_majority(primary, proposal, careful_vote) - - def validate_openapi(client): api_response = client.get("/app/api") assert api_response.status_code == http.HTTPStatus.OK, api_response.status_code @@ -49,42 +38,13 @@ def validate_openapi(client): raise e -@reqs.description("Test module set and remove") -def test_module_set_and_remove(network, args): - primary, _ = network.find_nodes() - - LOG.info("Member makes a module set proposal") - bundle_dir = os.path.join(THIS_DIR, "basic-module-import") - module_file_path = os.path.join(bundle_dir, "src", "foo.js") - module_path = "/anything/you/want/when/setting/manually/dot/js.js" - make_module_set_proposal(module_path, module_file_path, network) - module_content = open(module_file_path, "r").read() - - with primary.client(network.consortium.get_any_active_member().local_id) as c: - r = c.post("/gov/read", {"table": "public:gov.modules", "key": module_path}) - assert r.status_code == http.HTTPStatus.OK, r.status_code - assert r.body.json() == module_content, r.body - - LOG.info("Member makes a module remove proposal") - proposal_body, careful_vote = ccf.proposal_generator.remove_module(module_path) - proposal = network.consortium.get_any_active_member().propose( - primary, proposal_body - ) - network.consortium.vote_using_majority(primary, proposal, careful_vote) - - with primary.client(network.consortium.get_any_active_member().local_id) as c: - r = c.post("/gov/read", {"table": "public:gov.modules", "key": module_path}) - assert r.status_code == http.HTTPStatus.NOT_FOUND, r.status_code - return network - - @reqs.description("Test module import") def test_module_import(network, args): primary, _ = network.find_nodes() # Update JS app, deploying modules _and_ app script that imports module bundle_dir = os.path.join(THIS_DIR, "basic-module-import") - network.consortium.deploy_js_app(primary, bundle_dir) + network.consortium.set_js_app(primary, bundle_dir) with primary.client("user0") as c: r = c.post("/app/test_module", {}) @@ -106,7 +66,7 @@ def test_app_bundle(network, args): bundle_path = shutil.make_archive( os.path.join(tmp_dir, "bundle"), "zip", bundle_dir ) - network.consortium.deploy_js_app(primary, bundle_path) + network.consortium.set_js_app(primary, bundle_path) LOG.info("Verifying that modules and endpoints were added") with primary.client(network.consortium.get_any_active_member().local_id) as c: @@ -154,7 +114,7 @@ def test_dynamic_endpoints(network, args): bundle_dir = os.path.join(PARENT_DIR, "js-app-bundle") LOG.info("Deploying initial js app bundle archive") - network.consortium.deploy_js_app(primary, bundle_dir) + network.consortium.set_js_app(primary, bundle_dir) valid_body = {"op": "sub", "left": 82, "right": 40} expected_response = {"result": 42} @@ -195,7 +155,7 @@ def test_dynamic_endpoints(network, args): ] with open(metadata_path, "w") as f: json.dump(metadata, f, indent=2) - network.consortium.deploy_js_app(primary, modified_bundle_dir) + network.consortium.set_js_app(primary, modified_bundle_dir) LOG.info("Checking modified endpoint is accessible without auth") with primary.client() as c: @@ -232,7 +192,7 @@ def test_npm_app(network, args): LOG.info("Deploying npm app") bundle_dir = os.path.join(app_dir, "dist") - network.consortium.deploy_js_app(primary, bundle_dir) + network.consortium.set_js_app(primary, bundle_dir) LOG.info("Calling npm app endpoints") with primary.client("user0") as c: @@ -411,7 +371,6 @@ def run(args): args.nodes, args.binary_dir, args.debug_nodes, args.perf_nodes, pdb=args.pdb ) as network: network.start_and_join(args) - network = test_module_set_and_remove(network, args) network = test_module_import(network, args) network = test_app_bundle(network, args) network = test_dynamic_endpoints(network, args)