diff --git a/README.md b/README.md index 2b83fa8e..07e684d2 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,12 @@ SecretNote SF 现在隐语实训平台提供云端版本,开箱即用,无需 使用上述配置的节点地址为 `127.0.0.1:8090` 和 `127.0.0.1:8092`。在代码中,节点间可通过 service 名相互访问;镜像使用 8888 作为 Notebook 服务端口,6379 作为 Ray 端口,8000 作为 SecretFlow 集群网络端口,8001 作为 SPU 端口 -- 如有需要,请查看更完整的具体[示例](docs/SECRETFLOW-INTRO.md) +- 典型的本地运行的两计算节点(2PC)架构示意图如下所示。如有需要,请查看更完整的具体[示例](docs/SECRETFLOW-INTRO.md) + +

+ sf-2pc-arch +

+ ### 本地启动 SecretNote SCQL diff --git a/docker/secretflow-secretnote/Dockerfile b/docker/secretflow-secretnote/Dockerfile index 56da71d3..2f3fc5ce 100644 --- a/docker/secretflow-secretnote/Dockerfile +++ b/docker/secretflow-secretnote/Dockerfile @@ -1,7 +1,7 @@ # This Dockerfile will build the secretflow/secretnote image for depolying a node # for SecretNote. -ARG SECRETFLOW_VERSION="1.10.0b0" +ARG SECRETFLOW_VERSION="1.11.0b1" # Get the repository and remove unncessary files FROM alpine:3.14 AS source-tree diff --git a/docker/secretflow-secretnote/root/scripts/start.sh b/docker/secretflow-secretnote/root/scripts/start.sh index 260f3454..c6f85d06 100755 --- a/docker/secretflow-secretnote/root/scripts/start.sh +++ b/docker/secretflow-secretnote/root/scripts/start.sh @@ -11,4 +11,7 @@ if [ -z "${PORT}" ]; then PORT=8888 fi -secretnote sf --config=/home/secretnote/.jupyter/jupyter_server_config.py --allow-root --no-browser --port $PORT +# `--_as-compute-node` is a private flag only used for SecretNote SF Docker image build +secretnote sf --_as-compute-node \ + --config=/home/secretnote/.jupyter/jupyter_server_config.py \ + --allow-root --no-browser --port $PORT diff --git a/docker/secretnote-sf-sim/docker-compose.yml b/docker/secretnote-sf-sim/docker-compose.yml index 9a4b8ca5..bc31d77e 100644 --- a/docker/secretnote-sf-sim/docker-compose.yml +++ b/docker/secretnote-sf-sim/docker-compose.yml @@ -1,6 +1,6 @@ services: alice: - image: secretflow/secretnote:1.10.0b0 + image: secretflow/secretnote:1.11.0b1 pull_policy: if_not_present platform: linux/amd64 environment: @@ -11,7 +11,7 @@ services: - ./alice:/home/secretnote/workspace bob: - image: secretflow/secretnote:1.10.0b0 + image: secretflow/secretnote:1.11.0b1 pull_policy: if_not_present platform: linux/amd64 environment: diff --git a/docs/images/sf-2pc-arch.jpg b/docs/images/sf-2pc-arch.jpg new file mode 100644 index 00000000..1b680b08 Binary files /dev/null and b/docs/images/sf-2pc-arch.jpg differ diff --git a/package.json b/package.json index 2b126cb6..87c2d84e 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,7 @@ "ci:check:javascript": "nx run-many -t format:prettier -t lint:eslint -t typecheck:tsc", "ci:check:python": "nx run-many -t format:black -t test:pytest -t typecheck:pyright", "ci:build": "nx run-many -t build:component -t build:site && nx run-many -t build:py:ci", - "docker:build": "docker buildx build --build-arg SECRETFLOW_VERSION=1.10.0b0 --platform linux/arm64 -t secretflow/secretnote:1.10.0b0 -f ./docker/secretflow-secretnote/Dockerfile .", + "docker:build": "docker buildx build --build-arg SECRETFLOW_VERSION=1.11.0b1 --platform linux/arm64 -t secretflow/secretnote:1.11.0b1 -f ./docker/secretflow-secretnote/Dockerfile .", "docker:up": "docker-compose -f ./docker/secretnote-sf-sim/docker-compose.yml up" }, "devDependencies": { diff --git a/packages/secretnote-sf/package.json b/packages/secretnote-sf/package.json index ac0f380f..f3d14a86 100644 --- a/packages/secretnote-sf/package.json +++ b/packages/secretnote-sf/package.json @@ -1,6 +1,6 @@ { "name": "@alipay/secretnote-sf", - "version": "0.0.51", + "version": "0.0.52", "license": "Apache-2.0", "author": "vectorse@126.com", "repository": "https://github.com/secretflow/secretnote/tree/main/packages/secretnote", diff --git a/packages/secretnote-sf/src/modules/preview/index.less b/packages/secretnote-sf/src/modules/preview/index.less index 45baa4ca..8e820b82 100644 --- a/packages/secretnote-sf/src/modules/preview/index.less +++ b/packages/secretnote-sf/src/modules/preview/index.less @@ -1,5 +1,13 @@ -.secretnote-split-panel-right { +.secretnote-preview-split-panel-right { .libro-view-content-left { padding-right: 0 !important; } + + > .mana-view-container { + > .libro-view { + > .libro-view-top { + display: none; + } + } + } } diff --git a/packages/secretnote-sf/src/modules/preview/layout.tsx b/packages/secretnote-sf/src/modules/preview/layout.tsx index aba0cb68..51f70b28 100644 --- a/packages/secretnote-sf/src/modules/preview/layout.tsx +++ b/packages/secretnote-sf/src/modules/preview/layout.tsx @@ -23,7 +23,7 @@ const PreviewSecreteNoteLayout: React.FC = () => { { minSize={400} flex={1} flexGrow={1} - className="secretnote-split-panel-right" + className="secretnote-preview-split-panel-right" > diff --git a/packages/secretnote-sf/src/pages/sf-preview/index.less b/packages/secretnote-sf/src/pages/sf-preview/index.less deleted file mode 100644 index 28efadff..00000000 --- a/packages/secretnote-sf/src/pages/sf-preview/index.less +++ /dev/null @@ -1,9 +0,0 @@ -.secretnote-sf-preview-container { - .mana-view-container { - > .libro-view { - > .libro-view-top { - display: none; - } - } - } -} diff --git a/packages/secretnote-sf/src/pages/sf-preview/index.tsx b/packages/secretnote-sf/src/pages/sf-preview/index.tsx index 49d2a2cc..20ba3542 100644 --- a/packages/secretnote-sf/src/pages/sf-preview/index.tsx +++ b/packages/secretnote-sf/src/pages/sf-preview/index.tsx @@ -16,7 +16,6 @@ import { useRunOnce } from '@/utils/hook'; import '@/lang'; import '../../override.less'; -import './index.less'; export interface ISecretNotePreviewProps { fileURL?: string; // file URL of the notebook to preview diff --git a/pyprojects/secretnote/package.json b/pyprojects/secretnote/package.json index 6bb4b89b..665a1377 100644 --- a/pyprojects/secretnote/package.json +++ b/pyprojects/secretnote/package.json @@ -1,7 +1,7 @@ { "name": "secretnote", "private": true, - "version": "0.0.51", + "version": "0.0.52", "type": "module", "scripts": { "dev:sf": "cd .. && NODE_ENV=development python -m secretnote sf --config=./secretnote/secretnote/sf/.jupyter/config_dev.py --no-browser", diff --git a/pyprojects/secretnote/secretnote/__init__.py b/pyprojects/secretnote/secretnote/__init__.py index a3ebe305..478240bb 100644 --- a/pyprojects/secretnote/secretnote/__init__.py +++ b/pyprojects/secretnote/secretnote/__init__.py @@ -1 +1 @@ -__version__ = "0.0.51" +__version__ = "0.0.52" diff --git a/pyprojects/secretnote/secretnote/__main__.py b/pyprojects/secretnote/secretnote/__main__.py index 10cdcd8e..135abff9 100644 --- a/pyprojects/secretnote/secretnote/__main__.py +++ b/pyprojects/secretnote/secretnote/__main__.py @@ -6,7 +6,7 @@ def main(): parser.add_argument( "_positionals", nargs=argparse.ZERO_OR_MORE, - help=f"? ?. in {MODE_CHOICES} (default: sf). (default: .).", + help=f"? ? [ in {MODE_CHOICES} (default: sf); (default: .)]", ) # [DEPRECATED] legacy --mode support _deprecationWarning = "[DEPRECATED] `--mode`. Use positional `mode` instead." @@ -17,6 +17,8 @@ def main(): required=False, help=_deprecationWarning, ) + # [PRIVATE] whether it's running as a compute node inside the Docker image + parser.add_argument("--_as-compute-node", action=argparse.BooleanOptionalAction) args, rest_args = parser.parse_known_args() # normalize positional arguments @@ -38,7 +40,9 @@ def main(): SecretNoteApp().launch([work_dir, *rest_args]) else: - from .sf.server.app import SecretNoteApp + from .sf.server.app import SecretNoteApp, set_as_compute_node + + set_as_compute_node(args._as_compute_node) SecretNoteApp().launch([work_dir, *rest_args]) diff --git a/pyprojects/secretnote/secretnote/sf/server/app.py b/pyprojects/secretnote/secretnote/sf/server/app.py index 1e78b445..04cb7b0c 100644 --- a/pyprojects/secretnote/secretnote/sf/server/app.py +++ b/pyprojects/secretnote/secretnote/sf/server/app.py @@ -4,12 +4,19 @@ import os from jupyter_server.extension.application import ExtensionApp, ExtensionAppJinjaMixin from .services.nodes_handlers import nodes_handlers -from .services.pages_handlers import pages_handlers +from .services.pages_handlers import pages_handlers, compute_node_pages_handlers from .services.misc_handlers import misc_handlers from .services.contents_handlers import contents_handlers __dirname__ = os.path.dirname(__file__) +_AS_COMPUTE_NODE = False + + +def set_as_compute_node(value: bool): + global _AS_COMPUTE_NODE + _AS_COMPUTE_NODE = value + class SecretNoteApp(ExtensionAppJinjaMixin, ExtensionApp): """The SecretNote application acted as an ExtensionApp of Jupyter Server.""" @@ -39,7 +46,7 @@ def initialize_handlers(self): *misc_handlers, *contents_handlers, *nodes_handlers, - *pages_handlers, + *(compute_node_pages_handlers if _AS_COMPUTE_NODE else pages_handlers), ] self.handlers.extend(handlers) diff --git a/pyprojects/secretnote/secretnote/sf/server/services/pages_handlers.py b/pyprojects/secretnote/secretnote/sf/server/services/pages_handlers.py index 5a83a63b..c5e5dcbf 100644 --- a/pyprojects/secretnote/secretnote/sf/server/services/pages_handlers.py +++ b/pyprojects/secretnote/secretnote/sf/server/services/pages_handlers.py @@ -32,6 +32,21 @@ async def get(self, path: str = "/"): self.write(self.render_template("index.html")) +class ThisIsComputeNodeHintPageHandler( + ExtensionHandlerMixin, + ExtensionHandlerJinjaMixin, + FileFindHandler, +): + @web.authenticated + async def get(self, *_): + """This handler is only activated when `--_as-compute-node` flag is set, + so as to hint the user is visiting the wrong SecretNote page holding + by the compute node instead of the SecretNote installed locally. + """ + self.clear() + self.write(self.render_template("this-is-compute-node.html")) + + pages_handlers: List[Tuple[str, Type[JupyterHandler], Dict]] = [ ( "/secretnote/(.*)", @@ -39,3 +54,11 @@ async def get(self, path: str = "/"): {"path": single_page_static_path}, ), ] + +compute_node_pages_handlers: List[Tuple[str, Type[JupyterHandler], Dict]] = [ + ( + "/secretnote/(.*)", + ThisIsComputeNodeHintPageHandler, + {}, + ), +] diff --git a/scripts/clean.js b/scripts/clean.js index 22e40666..d62efb8b 100644 --- a/scripts/clean.js +++ b/scripts/clean.js @@ -23,6 +23,11 @@ const candidates = [ // Python projects './pyprojects/secretnote/.ipynb_checkpoints', ...distAndDep('./pyprojects/secretnote'), + './pyprojects/secretnote/secretnote/__pycache__', + './pyprojects/secretnote/secretnote/sf/www', + './pyprojects/secretnote/secretnote/scql/www', + './pyprojects/secretnote/secretnote/sf/__pycache__', + './pyprojects/secretnote/secretnote/scql/__pycache__', ].map((v) => path.join(workDir, v)); candidates.forEach((dir) => { diff --git a/scripts/post-build-site.js b/scripts/post-build-site.js index 2dde1e9d..5ebe3194 100644 --- a/scripts/post-build-site.js +++ b/scripts/post-build-site.js @@ -24,3 +24,11 @@ fs.rmSync(dst, { fs.cpSync(src, dst, { recursive: true, }); +// copy the hint page for --_as-compute-node +if (siteName === 'sf') { + const filename = 'this-is-compute-node.html'; + fs.copyFileSync( + path.join(__dirname, `./${filename}`), + path.join(dst, `./${filename}`), + ); +} diff --git a/scripts/this-is-compute-node.html b/scripts/this-is-compute-node.html new file mode 100644 index 00000000..849c7e1a --- /dev/null +++ b/scripts/this-is-compute-node.html @@ -0,0 +1,53 @@ + + + + + + 这是 SecretNote SF 的计算节点 + + + +
+

👉 这是 SecretNote SF 的计算节点

+

+ 您正在直接访问计算节点上的 Jupyter + Server,这不符合预期。计算节点只用来承载计算任务,不用来编写程序。 +

+

+ 请使用本地的 SecretNote SF(通常在 + http://localhost:8888 + )在右上角添加计算节点(见 + 文档),随后即可正常使用相关功能。 +

+
+ +