Skip to content

Commit 4af5689

Browse files
authored
add initial version of command-line tool gsctl. (#2868)
<!-- copilot:summary --> ### <samp>🤖 Generated by Copilot at f6e1599</samp> This pull request introduces a new command-line utility for GraphScope, `gsutil.py`, which can perform various tasks such as installing dependencies, building components, making docker images, and triggering tests. It also adds the `click` package as a dependency in `requirements.txt` to support the utility. to issue #2825
1 parent 7a3e06b commit 4af5689

File tree

5 files changed

+255
-1
lines changed

5 files changed

+255
-1
lines changed

docs/utilities/gs.md

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,33 @@
1-
# Command-line Utility `gs`
1+
# Command-line Utility `gsctl`
22

3+
`gsctl` is a command-line utility for GraphScope. It is shipped with `graphscope-client` and provides a set of functionalities to make it easy to use GraphScope. These functionalities include building and testing binaries, managing sessions and resources, and more.
4+
5+
## Install/Update `gsctl`
6+
7+
Since it is shipped with python package `graphscope-client`, the `gsctl` command will be available in your terminal after installing GraphScope:
8+
```bash
9+
pip install graphscope-client
10+
```
11+
12+
In some cases, such as development on `gsctl`, you may want to build it from source.
13+
To do this, navigate to the directory where the source code is located and run the following command:
14+
15+
```bash
16+
cd REPO_HOME/python
17+
# If you want to develop gsctl,
18+
# please note the entry point is located on:
19+
# /python/graphscope/gsctl/gsctl.py
20+
pip install --editable .
21+
```
22+
This will install `gsctl` in an editable mode, which means that any changes you make to the source code will be reflected in the installed version of `gsctl`.
23+
24+
## Commands
25+
26+
With `gsctl`, you can do the following things. Always remember to
27+
use `--help` on a command to get more information.
28+
29+
- `gsctl install-deps`, install dependencies for building GraphScope.
30+
- `gsctl make`, build GraphScope executable binaries and artifacts.
31+
- `gsctl make-image`, build GraphScope docker images.
32+
- `gsctl test`, trigger test suites.
333

python/graphscope/gsctl/gsctl.py

Lines changed: 218 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,218 @@
1+
#!/usr/bin/env python3
2+
# -*- coding: utf-8 -*-
3+
#
4+
# Copyright 2023 Alibaba Group Holding Limited. All Rights Reserved.
5+
#
6+
# Licensed under the Apache License, Version 2.0 (the "License");
7+
# you may not use this file except in compliance with the License.
8+
# You may obtain a copy of the License at
9+
#
10+
# http://www.apache.org/licenses/LICENSE-2.0
11+
#
12+
# Unless required by applicable law or agreed to in writing, software
13+
# distributed under the License is distributed on an "AS IS" BASIS,
14+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
# See the License for the specific language governing permissions and
16+
# limitations under the License.
17+
#
18+
19+
import io
20+
import os
21+
import subprocess
22+
23+
import click
24+
25+
26+
def run_shell_cmd(cmd, workingdir):
27+
"""wrapper function to run a shell command/scripts."""
28+
click.echo(f"run a shell command on cwd={workingdir}. \ncmd=\"{' '.join(cmd)}\"")
29+
proc = subprocess.Popen(cmd, cwd=workingdir, stdout=subprocess.PIPE)
30+
for line in io.TextIOWrapper(proc.stdout, encoding="utf-8"):
31+
print(line.rstrip())
32+
33+
34+
class GSCtl(object):
35+
"""GraphScope command-line utility
36+
37+
This is a context for the utility.
38+
"""
39+
40+
def __init__(self, repo_home=None, debug=False):
41+
self.home = os.path.abspath("../")
42+
self.debug = debug
43+
44+
45+
@click.group()
46+
@click.option(
47+
"--repo-home",
48+
envvar="REPO_HOME",
49+
type=click.Path(),
50+
help="GraphScope code repo location.",
51+
)
52+
@click.pass_context
53+
def cli(ctx, repo_home):
54+
ctx.obj = GSCtl(repo_home)
55+
56+
57+
@click.command()
58+
@click.pass_obj
59+
def install_deps():
60+
"""Install dependencies for building GraphScope."""
61+
click.echo("install_deps")
62+
63+
64+
@click.command()
65+
@click.argument(
66+
"component",
67+
type=click.Choice(
68+
["interactive", "analytical", "learning", "coordinator", "client"],
69+
case_sensitive=False,
70+
),
71+
required=False,
72+
)
73+
@click.option(
74+
"--clean",
75+
is_flag=True,
76+
default=False,
77+
help="Flag indicating whether clean previous build.",
78+
)
79+
@click.option(
80+
"--install",
81+
is_flag=True,
82+
default=False,
83+
help="Flag indicating whether install after built binaries.",
84+
)
85+
@click.option(
86+
"--install-prefix",
87+
type=click.Path(),
88+
default="/opt/graphscope",
89+
show_default=True,
90+
help="Install built binaries to customized location.",
91+
)
92+
@click.option(
93+
"--with-java",
94+
is_flag=True,
95+
default=False,
96+
help="Whether build analytical engine with Java support.",
97+
)
98+
@click.option(
99+
"--storage-type",
100+
type=click.Choice(["experimental", "vineyard"], case_sensitive=False),
101+
help="Make gie with specified storage type.",
102+
)
103+
@click.pass_obj
104+
def make(repo, component, clean, install, install_prefix, storage_type, with_java):
105+
"""Build executive binaries of COMPONENT. If not given a specific component, build all.
106+
107+
\f
108+
TODO: maybe without make?
109+
"""
110+
if clean:
111+
click.secho("Cleaning previous build.", fg="green")
112+
cmd = ["make", "clean"]
113+
run_shell_cmd(cmd, repo.home)
114+
return
115+
click.secho(
116+
"Before making artifacts, please manually source ENVs from ~/.graphscope_env.",
117+
fg="yellow",
118+
)
119+
click.secho(
120+
f"Begin the make command, to build components [{component}] of GraphScope, with repo = {repo.home}",
121+
fg="green",
122+
)
123+
cmd = []
124+
workingdir = repo.home
125+
if component == "interactive":
126+
click.secho("Building interactive engine.", fg="green")
127+
if storage_type == "experimental":
128+
cmd = ["make", "build", 'QUIET_OPT=""']
129+
workingdir = os.path.join(repo.home, "interactive_engine", "compiler")
130+
if storage_type == "vineyard":
131+
cmd = [
132+
"mvn",
133+
"install",
134+
"-DskipTests",
135+
"-Drust.compile.mode=release",
136+
"-P",
137+
"graphscope,graphscope-assembly",
138+
]
139+
workingdir = os.path.join(repo.home, "interactive_engine")
140+
run_shell_cmd(cmd, workingdir)
141+
cmd = ["tar", "xvzf", "graphscope.tar.gz"]
142+
workingdir = os.path.join(
143+
repo.home, "interactive_engine", "assembly", "target"
144+
)
145+
click.secho(f"Begin to extract, from {workingdir}.", fg="green")
146+
run_shell_cmd(cmd, workingdir)
147+
click.secho("GraphScope interactive engine has been built.", fg="green")
148+
if install is True:
149+
cmd = [
150+
"make",
151+
"interactive-install",
152+
"INSTALL_PREFIX={}".format(install_prefix),
153+
]
154+
run_shell_cmd(cmd, repo.home)
155+
click.secho(
156+
f"GraphScope interactive engine has been installed to {install_prefix}.",
157+
fg="green",
158+
)
159+
160+
if component == "analytical":
161+
cmd = ["make", "analytical"]
162+
if with_java:
163+
cmd = ["make", "analytical-java"]
164+
run_shell_cmd(cmd, repo.home)
165+
click.secho("GraphScope analytical engine has been built.", fg="green")
166+
if install is True:
167+
cmd = [
168+
"make",
169+
"analytical-install",
170+
"INSTALL_PREFIX={}".format(install_prefix),
171+
]
172+
run_shell_cmd(cmd, repo.home)
173+
click.secho(
174+
f"GraphScope analytical engine has been installed to {install_prefix}.",
175+
fg="green",
176+
)
177+
178+
if component == "client":
179+
cmd = ["make", "client"]
180+
run_shell_cmd(cmd, repo.home)
181+
182+
if component == "coordinator":
183+
cmd = ["make", "coordinator"]
184+
run_shell_cmd(cmd, repo.home)
185+
186+
if component is None:
187+
click.secho("Building all components.", fg="green")
188+
cmd = ["make", "all"]
189+
if install is True:
190+
cmd = ["make", "install", "INSTALL_PREFIX={}".format(install_prefix)]
191+
run_shell_cmd(cmd, repo.home)
192+
193+
194+
@click.command()
195+
def make_image():
196+
"""Make docker images from source code for deployment.
197+
198+
\f
199+
TODO: fulfill this.
200+
"""
201+
click.echo("make_image")
202+
203+
204+
@click.command()
205+
@click.pass_obj
206+
def test(repo):
207+
"""Trigger tests on built artifacts.
208+
209+
\f
210+
TODO: fulfill this."""
211+
click.secho(f"repo.home = {repo.home}", fg="green")
212+
click.echo("test")
213+
214+
215+
cli.add_command(install_deps)
216+
cli.add_command(make)
217+
cli.add_command(make_image)
218+
cli.add_command(test)

python/graphscope/gsctl/scripts/__init__.py

Whitespace-only changes.

python/requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ ujson;python_version>="3.11"
2020
PyYAML
2121
rich
2222
tqdm
23+
click
2324
vineyard>=0.15.0;sys_platform!="win32"
2425
vineyard-io>=0.15.0;sys_platform!="win32"
2526

python/setup.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,11 @@ def parse_version(root, **kwargs):
326326
"Source": "https://github.com/alibaba/GraphScope",
327327
"Tracker": "https://github.com/alibaba/GraphScope/issues",
328328
},
329+
entry_points={
330+
"console_scripts": [
331+
"gsctl = graphscope.gsctl.gsctl:cli",
332+
],
333+
},
329334
)
330335

331336
if os.name == "nt":

0 commit comments

Comments
 (0)