integrate-ai 9.16.0__tar.gz → 10.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of integrate-ai might be problematic. Click here for more details.
- {integrate-ai-9.16.0 → integrate_ai-10.1.0}/PKG-INFO +8 -2
- integrate_ai-10.1.0/integrate_ai/onprem_node.py +254 -0
- {integrate-ai-9.16.0 → integrate_ai-10.1.0}/integrate_ai/sdk.py +5 -3
- {integrate-ai-9.16.0 → integrate_ai-10.1.0}/integrate_ai/utils/rest_client.py +18 -2
- {integrate-ai-9.16.0 → integrate_ai-10.1.0}/integrate_ai.egg-info/PKG-INFO +8 -2
- {integrate-ai-9.16.0 → integrate_ai-10.1.0}/integrate_ai.egg-info/requires.txt +1 -0
- {integrate-ai-9.16.0 → integrate_ai-10.1.0}/setup.py +3 -2
- integrate-ai-9.16.0/integrate_ai/onprem_node.py +0 -154
- {integrate-ai-9.16.0 → integrate_ai-10.1.0}/MANIFEST.in +0 -0
- {integrate-ai-9.16.0 → integrate_ai-10.1.0}/backend_shim.py +0 -0
- {integrate-ai-9.16.0 → integrate_ai-10.1.0}/integrate_ai/__init__.py +0 -0
- {integrate-ai-9.16.0 → integrate_ai-10.1.0}/integrate_ai/cli.py +0 -0
- {integrate-ai-9.16.0 → integrate_ai-10.1.0}/integrate_ai/client.py +0 -0
- {integrate-ai-9.16.0 → integrate_ai-10.1.0}/integrate_ai/main.py +0 -0
- {integrate-ai-9.16.0 → integrate_ai-10.1.0}/integrate_ai/server.py +0 -0
- {integrate-ai-9.16.0 → integrate_ai-10.1.0}/integrate_ai/utils/__init__.py +0 -0
- {integrate-ai-9.16.0 → integrate_ai-10.1.0}/integrate_ai/utils/docker_client.py +0 -0
- {integrate-ai-9.16.0 → integrate_ai-10.1.0}/integrate_ai/utils/error_handling.py +0 -0
- {integrate-ai-9.16.0 → integrate_ai-10.1.0}/integrate_ai/utils/logger.py +0 -0
- {integrate-ai-9.16.0 → integrate_ai-10.1.0}/integrate_ai/utils/path_utils.py +0 -0
- {integrate-ai-9.16.0 → integrate_ai-10.1.0}/integrate_ai/utils/typer_utils.py +0 -0
- {integrate-ai-9.16.0 → integrate_ai-10.1.0}/integrate_ai.egg-info/SOURCES.txt +0 -0
- {integrate-ai-9.16.0 → integrate_ai-10.1.0}/integrate_ai.egg-info/dependency_links.txt +0 -0
- {integrate-ai-9.16.0 → integrate_ai-10.1.0}/integrate_ai.egg-info/entry_points.txt +0 -0
- {integrate-ai-9.16.0 → integrate_ai-10.1.0}/integrate_ai.egg-info/namespace_packages.txt +0 -0
- {integrate-ai-9.16.0 → integrate_ai-10.1.0}/integrate_ai.egg-info/top_level.txt +0 -0
- {integrate-ai-9.16.0 → integrate_ai-10.1.0}/setup.cfg +0 -0
|
@@ -1,12 +1,18 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
|
-
Name:
|
|
3
|
-
Version:
|
|
2
|
+
Name: integrate_ai
|
|
3
|
+
Version: 10.1.0
|
|
4
4
|
Summary: integrate.ai
|
|
5
5
|
Author: integrate.ai
|
|
6
6
|
License: Copyright (C) 2022 integrate.ai, Inc. All rights reserved.
|
|
7
7
|
Classifier: Programming Language :: Python :: 3
|
|
8
8
|
Requires-Python: >=3.7.5
|
|
9
9
|
Description-Content-Type: text/markdown
|
|
10
|
+
Requires-Dist: click==8.1.8
|
|
11
|
+
Requires-Dist: docker==7.1.0
|
|
12
|
+
Requires-Dist: pyjwt>=2.4.0
|
|
13
|
+
Requires-Dist: requests<3.0.0,>=2.32.2
|
|
14
|
+
Requires-Dist: rich<14.0.0,>=13.3.4
|
|
15
|
+
Requires-Dist: typer<0.8.0,>=0.7.0
|
|
10
16
|
|
|
11
17
|
# integrate.ai Command Line Interface
|
|
12
18
|
|
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
|
|
2
|
+
# Copyright (C) Integrate.ai, Inc. All rights reserved.
|
|
3
|
+
|
|
4
|
+
import subprocess
|
|
5
|
+
import sys
|
|
6
|
+
from integrate_ai.utils.rest_client import RestClient
|
|
7
|
+
import typer
|
|
8
|
+
import os
|
|
9
|
+
import rich
|
|
10
|
+
from integrate_ai.utils.typer_utils import (
|
|
11
|
+
TogglePromptOption,
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
app = typer.Typer(no_args_is_help=True)
|
|
15
|
+
# Default white list for AWS addr to query EC2 metadata
|
|
16
|
+
no_proxy_addr = "169.254.169.254,169.254.170.2,/var/run/docker.sock"
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
@app.command()
|
|
20
|
+
def install(
|
|
21
|
+
token: str = TogglePromptOption(
|
|
22
|
+
...,
|
|
23
|
+
help="Your generated IAI token.",
|
|
24
|
+
prompt="Please provide your IAI token",
|
|
25
|
+
envvar="IAI_TOKEN",
|
|
26
|
+
),
|
|
27
|
+
taskrunner_name: str = TogglePromptOption(
|
|
28
|
+
...,
|
|
29
|
+
help="The taskrunner name to register.",
|
|
30
|
+
prompt="Please provide the taskrunner name",
|
|
31
|
+
envvar="IAI_TASKRUNNER_NAME",
|
|
32
|
+
),
|
|
33
|
+
):
|
|
34
|
+
"""
|
|
35
|
+
This command register this node and save the regiter information to ecsanywhere_output.txt
|
|
36
|
+
"""
|
|
37
|
+
if os.geteuid() != 0:
|
|
38
|
+
rich.print("This command must be run as root.")
|
|
39
|
+
sys.exit(1)
|
|
40
|
+
try:
|
|
41
|
+
# clean up rm /tmp/ecs-anywhere-install.sh if there is any
|
|
42
|
+
if os.path.exists("/tmp/ecs-anywhere-install.sh"):
|
|
43
|
+
subprocess.run("rm /tmp/ecs-anywhere-install.sh", shell=True, check=True, text=True, capture_output=True)
|
|
44
|
+
|
|
45
|
+
# register taskrunner id
|
|
46
|
+
client = RestClient(token=token)
|
|
47
|
+
response = client.register_on_prem_taskrunner(taskrunner_name)
|
|
48
|
+
|
|
49
|
+
# install ecs anywhere
|
|
50
|
+
rich.print("Installing ECS Agent..")
|
|
51
|
+
install_ecs_agent(response)
|
|
52
|
+
rich.print("---ECS Agent Installed---")
|
|
53
|
+
taskrunners = client.get_taskrunner_info(taskrunner_name=taskrunner_name)
|
|
54
|
+
prov_info = taskrunners[0].get("provisioning_info", {})
|
|
55
|
+
runner_config = taskrunners[0].get("runner_config", {})
|
|
56
|
+
runtime_info = prov_info.get("runtime_info")
|
|
57
|
+
if runtime_info:
|
|
58
|
+
proxy_addr = runtime_info.get("iai_forward_proxy_http_url")
|
|
59
|
+
# configure proxy
|
|
60
|
+
if proxy_addr and runner_config.get("use_global_proxy"):
|
|
61
|
+
rich.print(f"Configuring ECS proxy: {proxy_addr}")
|
|
62
|
+
configure_proxy(proxy_addr=proxy_addr)
|
|
63
|
+
rich.print("OnPrem node installed successfully!")
|
|
64
|
+
except Exception as e:
|
|
65
|
+
rich.print(
|
|
66
|
+
f"On-Prem register command failed with error: {e}, Logs can be found in ecsanywhere_output.txt and proxy_config.txt"
|
|
67
|
+
)
|
|
68
|
+
raise e
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def install_ecs_agent(response):
|
|
72
|
+
# install ecs anywhere
|
|
73
|
+
cmd = 'sudo curl --proto "https" -o "/tmp/ecs-anywhere-install.sh" "https://amazon-ecs-agent.s3.amazonaws.com/ecs-anywhere-install-latest.sh"'
|
|
74
|
+
cmd += " && sudo bash /tmp/ecs-anywhere-install.sh"
|
|
75
|
+
cmd += f' --region "{response["region"]}"'
|
|
76
|
+
cmd += f' --cluster "{response["cluster_name"]}"'
|
|
77
|
+
cmd += f' --activation-id "{response["activation_id"]}"'
|
|
78
|
+
cmd += f' --activation-code "{response["activation_code"]}"'
|
|
79
|
+
cmd += "> ecsanywhere_output.txt"
|
|
80
|
+
try:
|
|
81
|
+
rich.print("Registering...")
|
|
82
|
+
subprocess.run(cmd, shell=True, check=True, timeout=1200)
|
|
83
|
+
rich.print("Agent registered successfully.")
|
|
84
|
+
rich.print("Output is saved in ecsanywhere_output.txt. The file contains instance id, please do not delete.")
|
|
85
|
+
except subprocess.CalledProcessError as e:
|
|
86
|
+
message = f"ECS Installation command failed with error: {e.stderr}, Logs can be found in ecsanywhere_output.txt"
|
|
87
|
+
rich.print(message)
|
|
88
|
+
raise Exception(message) from e
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
# Add proxy addresses to the ecs config so traffic can go through the proxy by default
|
|
92
|
+
# See : https://docs.aws.amazon.com/AmazonECS/latest/developerguide/http_proxy_config.html
|
|
93
|
+
def configure_proxy(proxy_addr: str):
|
|
94
|
+
rich.print("Configuring Proxy config in the host")
|
|
95
|
+
# proxy ssm agent
|
|
96
|
+
ssm_config_cmd = "sudo mkdir -p /etc/systemd/system/amazon-ssm-agent.service.d"
|
|
97
|
+
ssm_config_cmd += "&& { cat > /etc/systemd/system/amazon-ssm-agent.service.d/http-proxy.conf <<-EOF \n"
|
|
98
|
+
ssm_config_cmd += "[Service] \n"
|
|
99
|
+
ssm_config_cmd += f"Environment=HTTPS_PROXY={proxy_addr} \n"
|
|
100
|
+
ssm_config_cmd += f"Environment=NO_PROXY={no_proxy_addr} \n"
|
|
101
|
+
ssm_config_cmd += "EOF\n"
|
|
102
|
+
ssm_config_cmd += "}"
|
|
103
|
+
|
|
104
|
+
# proxy docker service
|
|
105
|
+
docker_svc_cmd = "sudo mkdir -p /etc/systemd/system/docker.service.d"
|
|
106
|
+
docker_svc_cmd += "&& { cat > /etc/systemd/system/docker.service.d/http-proxy.conf <<-EOF \n"
|
|
107
|
+
docker_svc_cmd += "[Service] \n"
|
|
108
|
+
docker_svc_cmd += f"Environment=HTTPS_PROXY={proxy_addr} \n"
|
|
109
|
+
docker_svc_cmd += f"Environment=NO_PROXY={no_proxy_addr} \n"
|
|
110
|
+
docker_svc_cmd += "EOF\n"
|
|
111
|
+
docker_svc_cmd += "}"
|
|
112
|
+
|
|
113
|
+
# proxy ecs-init
|
|
114
|
+
ecs_init_config_cmd = "sudo mkdir -p /etc/systemd/system/ecs.service.d"
|
|
115
|
+
ecs_init_config_cmd += "&& { cat > /etc/systemd/system/ecs.service.d/http-proxy.conf <<-EOF \n"
|
|
116
|
+
ecs_init_config_cmd += "[Service] \n"
|
|
117
|
+
ecs_init_config_cmd += f"Environment=HTTPS_PROXY={proxy_addr} \n"
|
|
118
|
+
ecs_init_config_cmd += f"Environment=NO_PROXY={no_proxy_addr} \n"
|
|
119
|
+
ecs_init_config_cmd += "EOF\n"
|
|
120
|
+
ecs_init_config_cmd += "}"
|
|
121
|
+
|
|
122
|
+
# proxy ecs
|
|
123
|
+
ecs_config_cmd = "echo patching ecs config"
|
|
124
|
+
ecs_config_cmd += "&& { cat >> /etc/ecs/ecs.config <<-EOF \n"
|
|
125
|
+
ecs_config_cmd += "[Service] \n"
|
|
126
|
+
ecs_config_cmd += f"HTTPS_PROXY={proxy_addr} \n"
|
|
127
|
+
ecs_config_cmd += f"NO_PROXY={no_proxy_addr} \n"
|
|
128
|
+
ecs_config_cmd += "EOF\n"
|
|
129
|
+
ecs_config_cmd += "}"
|
|
130
|
+
|
|
131
|
+
# restart all affected services
|
|
132
|
+
restart_cmd = (
|
|
133
|
+
"sudo systemctl daemon-reload && sudo systemctl restart docker.service && sudo systemctl restart "
|
|
134
|
+
"amazon-ssm-agent && sudo systemctl restart ecs"
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
# completion_command
|
|
138
|
+
completion_command = "echo proxy config successfully updated"
|
|
139
|
+
|
|
140
|
+
command_to_execute = f"{ssm_config_cmd} && {docker_svc_cmd} && {ecs_init_config_cmd} && {ecs_config_cmd} && {restart_cmd} && {completion_command}"
|
|
141
|
+
try:
|
|
142
|
+
# rich.print(f"Configuring Proxy command : {command_to_execute}")
|
|
143
|
+
subprocess.run(command_to_execute, shell=True, check=True, timeout=1200)
|
|
144
|
+
rich.print("Proxy configured successfully")
|
|
145
|
+
except subprocess.CalledProcessError as e:
|
|
146
|
+
message = f"Proxy configuration failed with error: {e.stderr}"
|
|
147
|
+
rich.print(message)
|
|
148
|
+
raise Exception(message) from e
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
@app.command()
|
|
152
|
+
def uninstall(
|
|
153
|
+
token: str = TogglePromptOption(
|
|
154
|
+
...,
|
|
155
|
+
help="Your generated IAI token.",
|
|
156
|
+
prompt="Please provide your IAI token",
|
|
157
|
+
envvar="IAI_TOKEN",
|
|
158
|
+
),
|
|
159
|
+
taskrunner_name: str = TogglePromptOption(
|
|
160
|
+
...,
|
|
161
|
+
help="The taskrunner id to register.",
|
|
162
|
+
prompt="Please provide the taskrunner id",
|
|
163
|
+
envvar="IAI_TASKRUNNER_NAME",
|
|
164
|
+
),
|
|
165
|
+
):
|
|
166
|
+
"""
|
|
167
|
+
This command deregister this node and clean up the directory.
|
|
168
|
+
"""
|
|
169
|
+
if os.geteuid() != 0:
|
|
170
|
+
rich.print("This command must be run as root.")
|
|
171
|
+
sys.exit(1)
|
|
172
|
+
# register taskrunner id
|
|
173
|
+
client = RestClient(token=token)
|
|
174
|
+
instance_id = get_instance_id()
|
|
175
|
+
# Deregister only if an instance state file is found
|
|
176
|
+
if instance_id:
|
|
177
|
+
response = client.deregister_on_prem_taskrunner(taskrunner_name=taskrunner_name, instance_id=instance_id)
|
|
178
|
+
rich.print("Deregister instance ", response["containerInstance"]["ec2InstanceId"])
|
|
179
|
+
|
|
180
|
+
# uninstall ecs anywhere
|
|
181
|
+
stop_ecs = "sudo systemctl stop ecs amazon-ssm-agent"
|
|
182
|
+
|
|
183
|
+
try:
|
|
184
|
+
stop_ecs_out = subprocess.run(stop_ecs, shell=True, check=True, text=True, capture_output=True)
|
|
185
|
+
rich.print(stop_ecs_out.stdout)
|
|
186
|
+
|
|
187
|
+
# Check OS and remove packages
|
|
188
|
+
os_type = None
|
|
189
|
+
try:
|
|
190
|
+
with open("/etc/os-release", "r") as f:
|
|
191
|
+
for line in f:
|
|
192
|
+
if line.startswith("ID="):
|
|
193
|
+
os_type = line.strip().split("=")[1].replace('"', "").lower()
|
|
194
|
+
break
|
|
195
|
+
except FileNotFoundError:
|
|
196
|
+
raise Exception("Unable to detect OS. /etc/os-release not found.")
|
|
197
|
+
|
|
198
|
+
if "centos" in os_type or "rhel" in os_type:
|
|
199
|
+
uninstall_packages_cmd = "sudo yum remove -y amazon-ecs-init amazon-ssm-agent"
|
|
200
|
+
elif "debian" in os_type or "ubuntu" in os_type:
|
|
201
|
+
uninstall_packages_cmd = "sudo apt remove -y amazon-ecs-init amazon-ssm-agent"
|
|
202
|
+
else:
|
|
203
|
+
raise Exception("Unsupported OS for package removal")
|
|
204
|
+
|
|
205
|
+
uninstall_out = subprocess.run(uninstall_packages_cmd, shell=True, check=True, text=True, capture_output=True)
|
|
206
|
+
rich.print(uninstall_out.stdout)
|
|
207
|
+
|
|
208
|
+
# Remove leftover directories
|
|
209
|
+
remove_directories_cmd = (
|
|
210
|
+
"sudo rm -rf /var/lib/ecs /etc/ecs /var/lib/amazon/ssm /var/log/ecs /var/log/amazon/ssm"
|
|
211
|
+
)
|
|
212
|
+
remove_directories_cmd += " && sudo rm -rf /var/lib/amazon/ssm/Vault/Store/RegistrationKey"
|
|
213
|
+
remove_directories_cmd += " && sudo rm -rf /etc/ecs"
|
|
214
|
+
remove_directories_cmd += " && sudo rm -rf /var/lib/ecs"
|
|
215
|
+
remove_directories_cmd += " && sudo rm -rf /var/log/ecs"
|
|
216
|
+
remove_directories_cmd += " && sudo rm /etc/systemd/system/ecs.service"
|
|
217
|
+
remove_directories_cmd += " && sudo systemctl daemon-reexec"
|
|
218
|
+
remove_directories_cmd += " && sudo rm -rf /etc/systemd/system/amazon-ssm-agent.service.d/http-proxy.conf"
|
|
219
|
+
remove_directories_cmd += " && sudo rm -rf /etc/systemd/system/docker.service.d/http-proxy.conf"
|
|
220
|
+
remove_directories_cmd += " && sudo rm -rf /etc/systemd/system/ecs.service.d/http-proxy.conf"
|
|
221
|
+
remove_directories_cmd += " && sudo rm -rf /etc/ecs/ecs.config"
|
|
222
|
+
|
|
223
|
+
subprocess.run(remove_directories_cmd, shell=True, check=True, text=True)
|
|
224
|
+
rich.print("Leftover directories removed")
|
|
225
|
+
|
|
226
|
+
# Remove instance id file
|
|
227
|
+
remove_output_cmd = "sudo rm -f ecsanywhere_output.txt"
|
|
228
|
+
subprocess.run(remove_output_cmd, shell=True, check=True, text=True)
|
|
229
|
+
rich.print("ecsanywhere_output.txt removed")
|
|
230
|
+
rich.print("proxy entries removed")
|
|
231
|
+
|
|
232
|
+
except subprocess.CalledProcessError as e:
|
|
233
|
+
rich.print(f"Command failed with error: {e.stderr}")
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
def get_instance_id():
|
|
237
|
+
result = subprocess.check_output(
|
|
238
|
+
"grep 'Container instance arn:' ecsanywhere_output.txt | sed 's#.*/##'", shell=True
|
|
239
|
+
)
|
|
240
|
+
instance_id = result.decode("utf-8").strip().strip('"')
|
|
241
|
+
if not instance_id:
|
|
242
|
+
rich.print(
|
|
243
|
+
"[red]Error: Could not parse instance ID from ecsanywhere_output.txt. Please verify the file's contents."
|
|
244
|
+
)
|
|
245
|
+
rich.print("Instance ID not found.")
|
|
246
|
+
rich.print("Deregister instance with instance_id ", instance_id)
|
|
247
|
+
return instance_id
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
@app.callback()
|
|
251
|
+
def main():
|
|
252
|
+
"""
|
|
253
|
+
Sub command for managing on-prem taskrunners related operations.
|
|
254
|
+
"""
|
|
@@ -8,6 +8,7 @@ from rich import print as rprint
|
|
|
8
8
|
from integrate_ai.utils.rest_client import RestClient
|
|
9
9
|
import subprocess
|
|
10
10
|
from integrate_ai.utils.error_handling import IntegrateAIException
|
|
11
|
+
import shutil
|
|
11
12
|
|
|
12
13
|
from integrate_ai.utils.typer_utils import TogglePromptOption, show_package_version
|
|
13
14
|
|
|
@@ -26,7 +27,7 @@ def install(
|
|
|
26
27
|
version: str = typer.Option("", "--version", "-v", help="The version of the sdk to download."),
|
|
27
28
|
):
|
|
28
29
|
"""
|
|
29
|
-
Install the integrate_ai sdk package. Defaults to
|
|
30
|
+
Install the integrate_ai sdk package. Defaults to pinned version
|
|
30
31
|
Installing a new sdk will override the existing one.
|
|
31
32
|
Will automatically read from the IAI_TOKEN environment variable if set.
|
|
32
33
|
"""
|
|
@@ -34,10 +35,11 @@ def install(
|
|
|
34
35
|
pip_install_command = rest_client.get_pip_install_command(version=version, package=package)["pipInstallCommand"]
|
|
35
36
|
if f"pip install {package}" not in pip_install_command:
|
|
36
37
|
raise IntegrateAIException(f" Not installing the right package {pip_install_command}")
|
|
37
|
-
|
|
38
|
+
if shutil.which("uv"):
|
|
39
|
+
pip_install_command = f"uv {pip_install_command}"
|
|
38
40
|
# pip will output the version number and give an error if the version is not found
|
|
39
41
|
if version == "":
|
|
40
|
-
rprint(f"Trying to install
|
|
42
|
+
rprint(f"Trying to install the pinned version of {package}.")
|
|
41
43
|
else:
|
|
42
44
|
rprint(f"Trying to install {package}=={version}.")
|
|
43
45
|
subprocess.run(pip_install_command, check=True, shell=True)
|
|
@@ -8,9 +8,9 @@ This contains a `RestClient` class that will be used to interface with the IAI R
|
|
|
8
8
|
"""
|
|
9
9
|
|
|
10
10
|
import jwt
|
|
11
|
+
import requests
|
|
11
12
|
from typing import Any, Dict
|
|
12
13
|
from integrate_ai.utils.error_handling import check_for_IntegrateAIException
|
|
13
|
-
import requests
|
|
14
14
|
import os
|
|
15
15
|
|
|
16
16
|
|
|
@@ -116,7 +116,7 @@ class RestClient:
|
|
|
116
116
|
def get_pip_install_command(self, version="", package="") -> Dict[str, str]:
|
|
117
117
|
"""Get pip install command to install sdk.
|
|
118
118
|
Args:
|
|
119
|
-
version (str): Version of sdk to install
|
|
119
|
+
version (str): Version of sdk to install
|
|
120
120
|
package (str): Package name to install.
|
|
121
121
|
Returns:
|
|
122
122
|
A Dict of the form
|
|
@@ -174,6 +174,21 @@ class RestClient:
|
|
|
174
174
|
|
|
175
175
|
return response.json()
|
|
176
176
|
|
|
177
|
+
def get_taskrunner_info(self, taskrunner_name) -> Dict[str, Any]:
|
|
178
|
+
"""Get taskrunner info.
|
|
179
|
+
Args:
|
|
180
|
+
taskrunner_name (str): Name of the taskrunner
|
|
181
|
+
Returns:
|
|
182
|
+
List of Taskrunner info
|
|
183
|
+
Raises:
|
|
184
|
+
IntegrateAIException: Customized IntegrateAI exception for the HTTP Exception.
|
|
185
|
+
"""
|
|
186
|
+
url = f"{self.api_url}/taskrunners"
|
|
187
|
+
params = {"name": taskrunner_name}
|
|
188
|
+
response = requests.get(url, headers=self._headers(), params=params)
|
|
189
|
+
check_for_IntegrateAIException(response=response)
|
|
190
|
+
return response.json()
|
|
191
|
+
|
|
177
192
|
def register_on_prem_taskrunner(self, taskrunner_name) -> Dict[str, Any]:
|
|
178
193
|
"""Get package versions.
|
|
179
194
|
Args:
|
|
@@ -182,6 +197,7 @@ class RestClient:
|
|
|
182
197
|
A Dict of the form
|
|
183
198
|
```
|
|
184
199
|
{
|
|
200
|
+
"proxy_info" : {"iai_forward_proxy_http_url" : "http://iai-proxy-ca-central-1-prod.integrateai.net:8888"}
|
|
185
201
|
"activation_id": <activation_id>,
|
|
186
202
|
"activation_code": <activation_code>,
|
|
187
203
|
"region": <region>,
|
|
@@ -1,12 +1,18 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
|
-
Name:
|
|
3
|
-
Version:
|
|
2
|
+
Name: integrate_ai
|
|
3
|
+
Version: 10.1.0
|
|
4
4
|
Summary: integrate.ai
|
|
5
5
|
Author: integrate.ai
|
|
6
6
|
License: Copyright (C) 2022 integrate.ai, Inc. All rights reserved.
|
|
7
7
|
Classifier: Programming Language :: Python :: 3
|
|
8
8
|
Requires-Python: >=3.7.5
|
|
9
9
|
Description-Content-Type: text/markdown
|
|
10
|
+
Requires-Dist: click==8.1.8
|
|
11
|
+
Requires-Dist: docker==7.1.0
|
|
12
|
+
Requires-Dist: pyjwt>=2.4.0
|
|
13
|
+
Requires-Dist: requests<3.0.0,>=2.32.2
|
|
14
|
+
Requires-Dist: rich<14.0.0,>=13.3.4
|
|
15
|
+
Requires-Dist: typer<0.8.0,>=0.7.0
|
|
10
16
|
|
|
11
17
|
# integrate.ai Command Line Interface
|
|
12
18
|
|
|
@@ -16,6 +16,7 @@ setup(**{
|
|
|
16
16
|
],
|
|
17
17
|
},
|
|
18
18
|
'install_requires': (
|
|
19
|
+
'click==8.1.8',
|
|
19
20
|
'docker==7.1.0',
|
|
20
21
|
'pyjwt>=2.4.0',
|
|
21
22
|
'requests<3.0.0,>=2.32.2',
|
|
@@ -60,7 +61,7 @@ iai client train --token <IAI_TOKEN> --session <SESSION_ID> --train_path <PATH_T
|
|
|
60
61
|
```
|
|
61
62
|
""",
|
|
62
63
|
'long_description_content_type': 'text/markdown',
|
|
63
|
-
'name': '
|
|
64
|
+
'name': 'integrate_ai',
|
|
64
65
|
'namespace_packages': (
|
|
65
66
|
),
|
|
66
67
|
'package_data': {
|
|
@@ -70,5 +71,5 @@ iai client train --token <IAI_TOKEN> --session <SESSION_ID> --train_path <PATH_T
|
|
|
70
71
|
'integrate_ai.utils',
|
|
71
72
|
),
|
|
72
73
|
'python_requires': '>=3.7.5',
|
|
73
|
-
'version': '
|
|
74
|
+
'version': '10.1.0',
|
|
74
75
|
})
|
|
@@ -1,154 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
# Copyright (C) Integrate.ai, Inc. All rights reserved.
|
|
3
|
-
|
|
4
|
-
import subprocess
|
|
5
|
-
import sys
|
|
6
|
-
from integrate_ai.utils.rest_client import RestClient
|
|
7
|
-
import typer
|
|
8
|
-
import os
|
|
9
|
-
import rich
|
|
10
|
-
from integrate_ai.utils.typer_utils import (
|
|
11
|
-
TogglePromptOption,
|
|
12
|
-
)
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
app = typer.Typer(no_args_is_help=True)
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
@app.command()
|
|
19
|
-
def install(
|
|
20
|
-
token: str = TogglePromptOption(
|
|
21
|
-
...,
|
|
22
|
-
help="Your generated IAI token.",
|
|
23
|
-
prompt="Please provide your IAI token",
|
|
24
|
-
envvar="IAI_TOKEN",
|
|
25
|
-
),
|
|
26
|
-
taskrunner_name: str = TogglePromptOption(
|
|
27
|
-
...,
|
|
28
|
-
help="The taskrunner name to register.",
|
|
29
|
-
prompt="Please provide the taskrunner name",
|
|
30
|
-
envvar="IAI_TASKRUNNER_NAME",
|
|
31
|
-
),
|
|
32
|
-
):
|
|
33
|
-
"""
|
|
34
|
-
This command register this node and save the regiter information to ecsanywhere_output.txt
|
|
35
|
-
"""
|
|
36
|
-
if os.geteuid() != 0:
|
|
37
|
-
rich.print("This command must be run as root.")
|
|
38
|
-
sys.exit(1)
|
|
39
|
-
|
|
40
|
-
# clean up rm /tmp/ecs-anywhere-install.sh if there is any
|
|
41
|
-
if os.path.exists("/tmp/ecs-anywhere-install.sh"):
|
|
42
|
-
subprocess.run("rm /tmp/ecs-anywhere-install.sh", shell=True, check=True, text=True, capture_output=True)
|
|
43
|
-
|
|
44
|
-
# register taskrunner id
|
|
45
|
-
client = RestClient(token=token)
|
|
46
|
-
response = client.register_on_prem_taskrunner(taskrunner_name)
|
|
47
|
-
|
|
48
|
-
# install ecs anywhere
|
|
49
|
-
cmd = 'sudo curl --proto "https" -o "/tmp/ecs-anywhere-install.sh" "https://amazon-ecs-agent.s3.amazonaws.com/ecs-anywhere-install-latest.sh"'
|
|
50
|
-
cmd += " && sudo bash /tmp/ecs-anywhere-install.sh"
|
|
51
|
-
cmd += f' --region "{response["region"]}"'
|
|
52
|
-
cmd += f' --cluster "{response["cluster_name"]}"'
|
|
53
|
-
cmd += f' --activation-id "{response["activation_id"]}"'
|
|
54
|
-
cmd += f' --activation-code "{response["activation_code"]}"'
|
|
55
|
-
cmd += "> ecsanywhere_output.txt"
|
|
56
|
-
|
|
57
|
-
try:
|
|
58
|
-
rich.print("Registering...")
|
|
59
|
-
subprocess.run(cmd, shell=True, check=True)
|
|
60
|
-
rich.print("Agent registered successfully.")
|
|
61
|
-
rich.print("Output is saved in ecsanywhere_output.txt. The file contains instance id, please do not delete.")
|
|
62
|
-
except subprocess.CalledProcessError as e:
|
|
63
|
-
rich.print(f"Command failed with error: {e.stderr}, Logs can be found in ecsanywhere_output.txt.")
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
@app.command()
|
|
67
|
-
def uninstall(
|
|
68
|
-
token: str = TogglePromptOption(
|
|
69
|
-
...,
|
|
70
|
-
help="Your generated IAI token.",
|
|
71
|
-
prompt="Please provide your IAI token",
|
|
72
|
-
envvar="IAI_TOKEN",
|
|
73
|
-
),
|
|
74
|
-
taskrunner_name: str = TogglePromptOption(
|
|
75
|
-
...,
|
|
76
|
-
help="The taskrunner id to register.",
|
|
77
|
-
prompt="Please provide the taskrunner id",
|
|
78
|
-
envvar="IAI_TASKRUNNER_NAME",
|
|
79
|
-
),
|
|
80
|
-
):
|
|
81
|
-
"""
|
|
82
|
-
This command deregister this node and clean up the directory.
|
|
83
|
-
"""
|
|
84
|
-
if os.geteuid() != 0:
|
|
85
|
-
rich.print("This command must be run as root.")
|
|
86
|
-
sys.exit(1)
|
|
87
|
-
# register taskrunner id
|
|
88
|
-
client = RestClient(token=token)
|
|
89
|
-
response = client.deregister_on_prem_taskrunner(taskrunner_name=taskrunner_name, instance_id=get_instance_id())
|
|
90
|
-
rich.print("Deregister instance ", response["containerInstance"]["ec2InstanceId"])
|
|
91
|
-
|
|
92
|
-
# uninstall ecs anywhere
|
|
93
|
-
stop_ecs = "sudo systemctl stop ecs amazon-ssm-agent"
|
|
94
|
-
|
|
95
|
-
try:
|
|
96
|
-
stop_ecs_out = subprocess.run(stop_ecs, shell=True, check=True, text=True, capture_output=True)
|
|
97
|
-
rich.print(stop_ecs_out.stdout)
|
|
98
|
-
|
|
99
|
-
# Check OS and remove packages
|
|
100
|
-
os_type = None
|
|
101
|
-
try:
|
|
102
|
-
with open("/etc/os-release", "r") as f:
|
|
103
|
-
for line in f:
|
|
104
|
-
if line.startswith("ID="):
|
|
105
|
-
os_type = line.strip().split("=")[1].replace('"', "").lower()
|
|
106
|
-
break
|
|
107
|
-
except FileNotFoundError:
|
|
108
|
-
raise Exception("Unable to detect OS. /etc/os-release not found.")
|
|
109
|
-
|
|
110
|
-
if "centos" in os_type or "rhel" in os_type:
|
|
111
|
-
uninstall_packages_cmd = "sudo yum remove -y amazon-ecs-init amazon-ssm-agent"
|
|
112
|
-
elif "debian" in os_type or "ubuntu" in os_type:
|
|
113
|
-
uninstall_packages_cmd = "sudo apt remove -y amazon-ecs-init amazon-ssm-agent"
|
|
114
|
-
else:
|
|
115
|
-
raise Exception("Unsupported OS for package removal")
|
|
116
|
-
|
|
117
|
-
uninstall_out = subprocess.run(uninstall_packages_cmd, shell=True, check=True, text=True, capture_output=True)
|
|
118
|
-
rich.print(uninstall_out.stdout)
|
|
119
|
-
|
|
120
|
-
# Remove leftover directories
|
|
121
|
-
remove_directories_cmd = (
|
|
122
|
-
"sudo rm -rf /var/lib/ecs /etc/ecs /var/lib/amazon/ssm /var/log/ecs /var/log/amazon/ssm"
|
|
123
|
-
)
|
|
124
|
-
subprocess.run(remove_directories_cmd, shell=True, check=True, text=True)
|
|
125
|
-
rich.print("Leftover directories removed")
|
|
126
|
-
|
|
127
|
-
# Remove instance id file
|
|
128
|
-
remove_output_cmd = "sudo rm ecsanywhere_output.txt"
|
|
129
|
-
subprocess.run(remove_output_cmd, shell=True, check=True, text=True)
|
|
130
|
-
rich.print("ecsanywhere_output.txt removed")
|
|
131
|
-
|
|
132
|
-
except subprocess.CalledProcessError as e:
|
|
133
|
-
rich.print(f"Command failed with error: {e.stderr}")
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
def get_instance_id():
|
|
137
|
-
result = subprocess.check_output(
|
|
138
|
-
"grep 'Container instance arn:' ecsanywhere_output.txt | sed 's#.*/##'", shell=True
|
|
139
|
-
)
|
|
140
|
-
instance_id = result.decode("utf-8").strip().strip('"')
|
|
141
|
-
if not instance_id:
|
|
142
|
-
rich.print(
|
|
143
|
-
"[red]Error: Could not parse instance ID from ecsanywhere_output.txt. Please verify the file's contents."
|
|
144
|
-
)
|
|
145
|
-
raise Exception("Instance ID not found.")
|
|
146
|
-
rich.print("Deregister instance with instance_id ", instance_id)
|
|
147
|
-
return instance_id
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
@app.callback()
|
|
151
|
-
def main():
|
|
152
|
-
"""
|
|
153
|
-
Sub command for managing on-prem taskrunners related operations.
|
|
154
|
-
"""
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|