Skip to content

Commit 01d1bf7

Browse files
committed
Ray config files over ibm-gen2 VPC
1 parent b0eb7ca commit 01d1bf7

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

57 files changed

+227
-2159
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
*.pyc
22
__pycache__
3+
*.egg-info

README.md

Lines changed: 18 additions & 113 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,28 @@
11
# Tool to generate Lithops configuration file
22

3-
Lithopscloud is a CLI tool that greatly simplifies user experience by generating Lithops and Ray configuration files.
3+
ibm-ray-config is a CLI tool that greatly simplifies user experience by generating Ray configuration files for IBM services.
44

55
## Setup
66

7-
The tool been mostly tested with Ubuntu 18.04/20.04, but should work with most Linux systems
7+
The tool been mostly tested with Ubuntu 18.04/20.04 and Fedora 35, but should work with most Linux systems
88
Requirements: `ssh-keygen` utility installed:
99
```
1010
sudo apt install openssh-client
1111
```
1212

13-
Install `lithopscloud` from pip repository
13+
Install `ibm-ray-config` from pip repository
1414

1515
```
16-
pip install lithopscloud
16+
pip install ibm-ray-config
1717
```
1818

1919
## Usage
2020
Use the configuration tool as follows
2121

2222
```
23-
lithopscloud [--iam-api-key IAM_API_KEY] [-i INPUT_FILE] [-o OUTPUT_PATH] [--verify_config CONFIG_FILE_PATH] [--version] [--backend backend] [--defaults]
23+
ibm-ray-config [--iam-api-key IAM_API_KEY] [-i INPUT_FILE] [-o OUTPUT_PATH] [--version] [--defaults]
2424
```
25-
Get a short description of the available flags via ```lithopscloud --help```
25+
Get a short description of the available flags via ```ibm-ray-config --help```
2626

2727
<br/>
2828

@@ -34,135 +34,40 @@ Get a short description of the available flags via ```lithopscloud --help```
3434
| iam-api-key | |yes|IBM Cloud API key. To generate a new API Key, adhere to the following [guide](https://www.ibm.com/docs/en/spectrumvirtualizecl/8.1.3?topic=installing-creating-api-key)
3535
| input-file |<compute_backend>/defaults.py| no | Existing config file to be used as a template in the configuration process |
3636
| output-path |A randomly generated path to a randomly named yaml file | no |A custom location the config file will be written to |
37-
| verify-config <img width=125/>| | no |Verifies the integrity of an existing config file and outputs a usable config file based on it. Currently doesn't support gen2 backends.
38-
| version | | no |Returns lithopscloud's package version|
37+
| version | | no |Returns ibm-ray-config's package version|
38+
3939

40-
<br/>
4140

42-
#### Verify Additional ways of configuration
43-
Using the ```verify-config``` option enables verification of additional valid ways of configuration, that otherwise
44-
left unchecked. This mode scans for any possible subset of valid parameters and extract them to output a new
45-
lithops config file (e.g., verify cos configured by HMAC credentials).
46-
To utilize simply run ```lithopscloud --verify-config CONFIG_FILE_PATH -o OUTPUT_FILE_PATH```
47-
<br/> Please note that this feature doesn't currently support the verification of gen2 backends.
48-
49-
## Supported backends:
50-
<table>
51-
<tr>
52-
<th align="center">
53-
<p>
54-
<span style="color:orange">Standalone Compute Backends</span>
55-
</p>
56-
</th>
57-
<th align="center">
58-
59-
<p>
60-
<span style="color:orange">Serverless Compute Backends</span>
61-
</p>
62-
</th>
63-
<th align="center">
64-
<p>
65-
<span style="color:orange">Storage Backends</span>
66-
</p>
67-
</th>
68-
</tr>
69-
<tr>
70-
<td>
71-
72-
- Gen2/Lithops
73-
- Gen2/Ray
74-
- Local Host
75-
76-
</td>
77-
<td>
78-
79-
- IBM Cloud Functions
80-
- IBM Code Engine
81-
</td>
82-
<td>
83-
84-
- IBM Cloud Object Storage
85-
86-
</td>
87-
</tr>
88-
</table>
89-
90-
### Using lithopscloud to generate config file without user interaction
91-
In order to let lithopscloud generate config file based on some defaults and create vpc and all its peripherial assets automatically, please run:
41+
### Using ibm-ray-config to generate config file without user interaction
42+
In order to let ibm-ray-config generate config file based on some defaults and create vpc and all its peripheral assets automatically, please run:
9243

9344
```
94-
lithopscloud -a <API_KEY> -b <BACKEND> --defaults
45+
ibm-ray-config -a <API_KEY> --defaults
9546
```
9647

97-
* currently, lithops `gen2` is the only supported backend
98-
99-
### Using lithopscloud config tool programmatically
48+
### Using ibm-ray-config config tool programmatically
10049
Notice, not all fields are mandatory. Unspecified resources will be created automatically on the backend.
10150

10251
E.g.
103-
If existing vpc id not provided - vpc will be created automatically with all required peripherial resources like security groups, gateway.. etc following minimal default requierments
52+
If existing vpc id not provided - vpc will be created automatically with all required peripheral resources like security groups, gateway.. etc following minimal default requirements
10453
If ssh key details not provided - new ssh key pair will be generated and registered in ibm cloud
10554

106-
107-
##### Lithops Gen2
108-
```
109-
from lithopscloud import generate_config
110-
from lithopscloud import LITHOPS_GEN2, LITHOPS_CF, LITHOPS_CE, RAY_GEN2, LOCAL_HOST
111-
112-
api_key = '<IAM_API_KEY>'
113-
region = 'eu-de'
114-
generate_config(LITHOPS_GEN2, api_key, region, cos_bucket_name='kpavel-bucket', image_id='r010-5a674db7-95aa-45c5-a2f1-a6aa9d7e93ad', key_id='r010-fe6cb103-60e6-46bc-9cb5-14e415990849', ssh_key_filename='/home/kpavel/.ssh/id_rsa', profile_name='bx2-2x8', vpc_id='r010-af1adda4-e4e5-4060-9aa2-7a0c981aff8e')
115-
116-
```
117-
118-
Mandatory fields are: backend_type (LITHOPS_GEN2), api_key, region and cos_bucket.
119-
Minimal example:
120-
121-
```
122-
from lithopscloud import generate_config
123-
from lithopscloud import LITHOPS_GEN2, RAY_GEN2
124-
125-
api_key = <IAM_API_KEY>
126-
region = 'ca-tor'
127-
cos_bucket_name='kpavel-bucket'
128-
config_file = generate_config(LITHOPS_GEN2, api_key, region, cos_bucket_name=cos_bucket_name)
129-
```
130-
13155
###### Ray Gen2
13256
```
133-
from lithopscloud import generate_config
134-
from lithopscloud import RAY_GEN2
57+
from ibm_ray_config import generate_config
13558
13659
api_key = '<IAM_API_KEY>'
13760
region = 'eu-de'
138-
generate_config(RAY_GEN2, api_key, region, image_id='r010-5a674db7-95aa-45c5-a2f1-a6aa9d7e93ad', key_id='r010-fe6cb103-60e6-46bc-9cb5-14e415990849', ssh_key_filename='/home/kpavel/.ssh/id_rsa', profile_name='bx2-2x8', vpc_id='r010-af1adda4-e4e5-4060-9aa2-7a0c981aff8e', min_workers=1, max_workers=1)
61+
generate_config(iam_api_key=api_key, region=region, image_id='r010-5a674db7-95aa-45c5-a2f1-a6aa9d7e93ad', key_id='r010-fe6cb103-60e6-46bc-9cb5-14e415990849', ssh_key_filename='/home/kpavel/.ssh/id_rsa', profile_name='bx2-2x8', vpc_id='r010-af1adda4-e4e5-4060-9aa2-7a0c981aff8e', min_workers=1, max_workers=1)
13962
```
14063

141-
Mandatory fields are: backend_type (LITHOPS_GEN2), api_key, region and cos_bucket.
64+
Mandatory fields are: api_key, region.
14265
Minimal example:
14366

14467
```
145-
from lithopscloud import generate_config
146-
from lithopscloud import RAY_GEN2
68+
from ibm_ray_config import generate_config
14769
14870
api_key = <IAM_API_KEY>
14971
region = 'eu-de'
150-
config_file = generate_config(RAY_GEN2, api_key, region)
72+
config_file = generate_config(iam_api_key=api_key, region=region)
15173
```
152-
153-
## For Contributors
154-
155-
### Add new unsupported sections to config file
156-
157-
#### If the new configuration is provider specific
158-
159-
1. implement [__config_builder.py__](src/lithopscloud/modules/config_builder.py) interface
160-
2. add your implementation under __provider__ package
161-
3. add reference to your implementation in the list of exported modules, e.g. [lithops modules](src/lithopscloud/modules/lithops/__init__.py__)
162-
163-
164-
#### If the new configuration is common for multiple providers
165-
166-
1. implement [__config_builder.py__](src/lithopscloud/modules/config_builder.py) interface to hold common logic
167-
2. add your implementation to __modules__ package
168-
3. extend your common implementation under each provider package, e.g. [lithops image.py](src/lithopscloud/modules/lithops/image.py) and [ray image.py](src/lithopscloud/modules/ray/image.py) to have config file specific logic

bin/lithopscloud renamed to bin/ibm-ray-config

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
# -*- coding: utf-8 -*-
33
import re
44
import sys
5-
from lithopscloud.main import builder
5+
from ibm_ray_config.main import builder
66

77
if __name__ == '__main__':
88
sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])

setup.cfg

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
[metadata]
2-
name = lithopscloud
3-
version = 1.0.0b96
4-
author = kpavel
5-
author_email = kpavel@il.ibm.com
6-
description = Interactive tool for generation of lithops configuration
2+
name = ibm-ray-config
3+
version = 1.0.0b1
4+
author = Omer J Cohen
5+
author_email = omer.cohen.ibm.com
6+
description = Interactive tool generating ray configuration for IBM platforms
77
long_description = file: README.md
88
long_description_content_type = text/markdown
9-
url = https://github.com/lithops-cloud/lithopscloud
9+
url = https://github.com/<INSERT_HERE>/ibm-ray-config
1010
classifiers =
1111
Programming Language :: Python :: 3
1212

@@ -16,18 +16,15 @@ package_dir =
1616
packages = find:
1717
python_requires = >=3.6
1818
scripts =
19-
bin/lithopscloud
19+
bin/ibm-ray-config
2020
install_requires =
2121
click >=8.0.1
2222
inquirer >=2.7.0
2323
ibm-cloud-sdk-core
2424
ibm-platform-services
25-
ibm-cos-sdk
2625
PyYAML >=5.4.1
27-
ibm-code-engine-sdk
2826
ibm_watson
2927
docker >=5.0.3
30-
lithops>=2.5.4
3128
ibm-vpc
3229

3330
[options.packages.find]

src/ibm_ray_config/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
from ibm_ray_config.main import generate_config, delete_config

src/ibm_ray_config/main.py

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
import importlib
2+
import pkg_resources
3+
import os
4+
import click
5+
import yaml
6+
7+
from ibm_ray_config.modules.utils import color_msg, Color, verify_paths
8+
9+
# currently supporting configuration for ray above IBM Gen2 VPC.
10+
IBM_GEN2 = 'IBM Gen2'
11+
backends =[{'name': IBM_GEN2, 'path': 'gen2.ray'}]
12+
13+
def select_backend(input_file, default_config_suffix=''):
14+
"""returns a base config file for the backend and its package """
15+
backend = backends[0] # currently supporting a single backend
16+
17+
base_config = {}
18+
19+
if input_file:
20+
with open(input_file) as f:
21+
base_config = yaml.safe_load(f)
22+
else:
23+
base_config = load_base_config(backend, default_config_suffix)
24+
25+
# find the right modules
26+
backend_pkg = importlib.import_module(f"ibm_ray_config.modules.{backend['path']}")
27+
28+
return base_config, backend_pkg
29+
30+
def load_base_config(backend, default_config_suffix=''):
31+
"""returns a default base configuration dict for the chosen backend """
32+
backend_path = backend['path'].replace('.', '/')
33+
dir_path = os.path.dirname(os.path.realpath(__file__))
34+
input_file = f"{dir_path}/modules/{backend_path}/defaults{default_config_suffix}.yaml"
35+
36+
base_config = None
37+
with open(input_file) as f:
38+
base_config = yaml.safe_load(f)
39+
40+
return base_config
41+
42+
def validate_api_keys(base_config, modules, iam_api_key, compute_iam_endpoint):
43+
"""validates the api key specified.
44+
returns a base config dict, updated with the api-key field populated and the post api-key module removal modules list """
45+
# The API_KEY module is invoked and popped from the list.
46+
api_key_module = modules[0]
47+
base_config = api_key_module(base_config).run(api_key=iam_api_key,
48+
compute_iam_endpoint=compute_iam_endpoint)
49+
50+
modules = modules[1:]
51+
return base_config, modules
52+
53+
@click.command()
54+
@click.option('--output-file', '-o', help='Output filename to save configurations')
55+
@click.option('--input-file', '-i', help=f'Template for the new configuration')
56+
@click.option('--iam-api-key', '-a', help='IAM_API_KEY')
57+
@click.option('--version', '-v', help=f'Get package version', is_flag=True)
58+
@click.option('--compute-iam-endpoint', help='IAM endpoint url used for compute instead of default https://iam.cloud.ibm.com')
59+
@click.option('--endpoint', help='IBM Cloud API endpoint')
60+
@click.option('--defaults', help=f'Create defaults if not exist and generate default config', is_flag=True)
61+
@click.option('--pr', '-g', help=f'Temporary workaround for ray gen2 only. If specified, use provider setup from PR github', is_flag=True, default=False)
62+
def builder(iam_api_key, output_file, input_file, version, compute_iam_endpoint, endpoint, defaults, pr):
63+
64+
if version:
65+
print(f"{pkg_resources.get_distribution('ibm-ray-config').project_name} "
66+
f"{pkg_resources.get_distribution('ibm-ray-config').version}")
67+
exit(0)
68+
69+
print(color_msg("\nWelcome to ibm_ray_config export helper\n", color=Color.YELLOW))
70+
71+
input_file, output_file = verify_paths(input_file, output_file)
72+
73+
default_config_suffix = ''
74+
if pr:
75+
default_config_suffix = '_pr'
76+
77+
base_config, backend_pkg = select_backend(input_file, default_config_suffix)
78+
79+
modules = backend_pkg.MODULES
80+
base_config['create_defaults'] = defaults
81+
base_config, modules = validate_api_keys(base_config, modules, iam_api_key, compute_iam_endpoint)
82+
83+
if endpoint and 'ibm_vpc' in base_config:
84+
base_config['ibm_vpc']['endpoint'] = endpoint
85+
elif endpoint and 'provider' in base_config:
86+
base_config['provider']['endpoint'] = endpoint
87+
88+
for module in modules:
89+
next_module = module(base_config)
90+
91+
if defaults:
92+
base_config = next_module.create_default()
93+
else:
94+
base_config = next_module.run()
95+
96+
with open(output_file, 'w') as outfile:
97+
del base_config['create_defaults']
98+
yaml.dump(base_config, outfile, default_flow_style=False)
99+
100+
if hasattr(backend_pkg, 'finish_message'):
101+
print(backend_pkg.finish_message(output_file))
102+
else:
103+
print("\n\n=================================================")
104+
print(color_msg(f"Cluster config file: {output_file}", color=Color.LIGHTGREEN))
105+
print("=================================================")
106+
107+
def error(msg):
108+
print(msg)
109+
raise Exception(msg)
110+
111+
def generate_config(*args, **kwargs):
112+
"""A programmatic way to create configuration files, to be used externally by user."""
113+
backend = backends[0] # currently supporting a single backend
114+
_, output_file = verify_paths(None, None)
115+
116+
# now update base config with backend specific params
117+
base_config = importlib.import_module(f"ibm_ray_config.modules.{backend['path']}").load_config(backend, *args, **kwargs)
118+
119+
# now find the right modules
120+
modules = importlib.import_module(f"ibm_ray_config.modules.{backend['path']}").MODULES
121+
122+
for module in modules:
123+
base_config = module(base_config).verify(base_config)
124+
125+
with open(output_file, 'w') as outfile:
126+
yaml.dump(base_config, outfile, default_flow_style=False)
127+
128+
print("\n\n=================================================")
129+
print(color_msg(f"Cluster config file: {output_file}", color=Color.LIGHTGREEN))
130+
print("=================================================")
131+
132+
return output_file
133+
134+
def delete_config(config_file_path):
135+
config = None
136+
with open(config_file_path) as f:
137+
config = yaml.safe_load(f)
138+
139+
from ibm_ray_config.modules.gen2 import delete_config
140+
delete_config(config)
141+
142+
if __name__ == '__main__':
143+
try:
144+
builder()
145+
except KeyboardInterrupt:
146+
# User interrupt the program
147+
exit()

0 commit comments

Comments
 (0)