primitive 0.2.10__py3-none-any.whl → 0.2.11__py3-none-any.whl
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.
- primitive/__about__.py +1 -1
- primitive/agent/actions.py +20 -18
- primitive/agent/runner.py +30 -33
- primitive/cli.py +2 -0
- primitive/client.py +41 -16
- primitive/daemons/actions.py +48 -62
- primitive/daemons/commands.py +68 -22
- primitive/daemons/launch_agents.py +205 -122
- primitive/daemons/launch_service.py +224 -164
- primitive/daemons/ui.py +41 -0
- primitive/db/base.py +5 -0
- primitive/db/models.py +78 -0
- primitive/db/sqlite.py +27 -0
- primitive/exec/actions.py +0 -1
- primitive/files/actions.py +0 -1
- primitive/hardware/actions.py +4 -8
- primitive/hardware/commands.py +1 -68
- primitive/hardware/ui.py +67 -0
- primitive/monitor/actions.py +102 -0
- primitive/monitor/commands.py +13 -0
- primitive/reservations/actions.py +0 -2
- primitive/utils/auth.py +0 -2
- primitive/utils/daemons.py +54 -0
- {primitive-0.2.10.dist-info → primitive-0.2.11.dist-info}/METADATA +3 -1
- {primitive-0.2.10.dist-info → primitive-0.2.11.dist-info}/RECORD +28 -20
- {primitive-0.2.10.dist-info → primitive-0.2.11.dist-info}/WHEEL +0 -0
- {primitive-0.2.10.dist-info → primitive-0.2.11.dist-info}/entry_points.txt +0 -0
- {primitive-0.2.10.dist-info → primitive-0.2.11.dist-info}/licenses/LICENSE.txt +0 -0
primitive/hardware/commands.py
CHANGED
@@ -3,13 +3,11 @@ import typing
|
|
3
3
|
import click
|
4
4
|
|
5
5
|
from ..utils.printer import print_result
|
6
|
+
from .ui import render_hardware_table
|
6
7
|
|
7
8
|
if typing.TYPE_CHECKING:
|
8
9
|
from ..client import Primitive
|
9
10
|
|
10
|
-
from rich.console import Console
|
11
|
-
from rich.table import Table
|
12
|
-
|
13
11
|
|
14
12
|
@click.group()
|
15
13
|
@click.pass_context
|
@@ -71,71 +69,6 @@ def checkin_command(context):
|
|
71
69
|
print_result(message=message, context=context, fg="green")
|
72
70
|
|
73
71
|
|
74
|
-
def hardware_status_string(hardware):
|
75
|
-
if activeReservation := hardware.get("activeReservation"):
|
76
|
-
if activeReservation.get("status", None) == "in_progress":
|
77
|
-
return "Reserved"
|
78
|
-
if hardware.get("isQuarantined"):
|
79
|
-
return "Quarantined"
|
80
|
-
if not hardware.get("isOnline"):
|
81
|
-
return "Offline"
|
82
|
-
if not hardware.get("isHealthy"):
|
83
|
-
return "Not healthy"
|
84
|
-
if not hardware.get("isAvailable"):
|
85
|
-
return "Not available"
|
86
|
-
else:
|
87
|
-
return "Available"
|
88
|
-
|
89
|
-
|
90
|
-
def render_hardware_table(hardware_list):
|
91
|
-
console = Console()
|
92
|
-
|
93
|
-
table = Table(show_header=True, header_style="bold magenta")
|
94
|
-
table.add_column("Organization")
|
95
|
-
table.add_column("Name | Slug")
|
96
|
-
table.add_column("Status")
|
97
|
-
table.add_column("Reservation")
|
98
|
-
|
99
|
-
for hardware in hardware_list:
|
100
|
-
name = hardware.get("name")
|
101
|
-
slug = hardware.get("slug")
|
102
|
-
print_name = name
|
103
|
-
if name != slug:
|
104
|
-
print_name = f"{name} | {slug}"
|
105
|
-
child_table = Table(show_header=False, header_style="bold magenta")
|
106
|
-
child_table.add_column("Organization")
|
107
|
-
child_table.add_column("Name | Slug")
|
108
|
-
child_table.add_column("Status")
|
109
|
-
child_table.add_column("Reservation", justify="right")
|
110
|
-
|
111
|
-
table.add_row(
|
112
|
-
hardware.get("organization").get("name"),
|
113
|
-
print_name,
|
114
|
-
hardware_status_string(hardware),
|
115
|
-
f"{hardware.get('activeReservation').get('createdBy').get('username')} | {hardware.get('activeReservation').get('status')}"
|
116
|
-
if hardware.get("activeReservation", None)
|
117
|
-
else "",
|
118
|
-
)
|
119
|
-
|
120
|
-
if len(hardware.get("children", [])) > 0:
|
121
|
-
for child in hardware.get("children"):
|
122
|
-
name = child.get("name")
|
123
|
-
slug = child.get("slug")
|
124
|
-
print_name = name
|
125
|
-
if name != slug:
|
126
|
-
print_name = f"└── {name} | {slug}"
|
127
|
-
table.add_row(
|
128
|
-
hardware.get("organization").get("name"),
|
129
|
-
print_name,
|
130
|
-
hardware_status_string(hardware),
|
131
|
-
f"{hardware.get('activeReservation').get('createdBy').get('username')} | {hardware.get('activeReservation').get('status')}"
|
132
|
-
if hardware.get("activeReservation", None)
|
133
|
-
else "",
|
134
|
-
)
|
135
|
-
|
136
|
-
console.print(table)
|
137
|
-
|
138
|
-
|
139
72
|
@cli.command("list")
|
140
73
|
@click.pass_context
|
141
74
|
def list_command(context):
|
primitive/hardware/ui.py
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
from rich.console import Console
|
2
|
+
from rich.table import Table
|
3
|
+
|
4
|
+
|
5
|
+
def render_hardware_table(hardware_list) -> None:
|
6
|
+
console = Console()
|
7
|
+
|
8
|
+
table = Table(show_header=True, header_style="bold #FFA800")
|
9
|
+
table.add_column("Organization")
|
10
|
+
table.add_column("Name | Slug")
|
11
|
+
table.add_column("Status")
|
12
|
+
table.add_column("Reservation")
|
13
|
+
|
14
|
+
for hardware in hardware_list:
|
15
|
+
name = hardware.get("name")
|
16
|
+
slug = hardware.get("slug")
|
17
|
+
print_name = name
|
18
|
+
if name != slug:
|
19
|
+
print_name = f"{name} | {slug}"
|
20
|
+
child_table = Table(show_header=False, header_style="bold #FFA800")
|
21
|
+
child_table.add_column("Organization")
|
22
|
+
child_table.add_column("Name | Slug")
|
23
|
+
child_table.add_column("Status")
|
24
|
+
child_table.add_column("Reservation", justify="right")
|
25
|
+
|
26
|
+
table.add_row(
|
27
|
+
hardware.get("organization").get("name"),
|
28
|
+
print_name,
|
29
|
+
hardware_status_string(hardware),
|
30
|
+
f"{hardware.get('activeReservation').get('createdBy').get('username')} | {hardware.get('activeReservation').get('status')}"
|
31
|
+
if hardware.get("activeReservation", None)
|
32
|
+
else "",
|
33
|
+
)
|
34
|
+
|
35
|
+
if len(hardware.get("children", [])) > 0:
|
36
|
+
for child in hardware.get("children"):
|
37
|
+
name = child.get("name")
|
38
|
+
slug = child.get("slug")
|
39
|
+
print_name = name
|
40
|
+
if name != slug:
|
41
|
+
print_name = f"└── {name} | {slug}"
|
42
|
+
table.add_row(
|
43
|
+
hardware.get("organization").get("name"),
|
44
|
+
print_name,
|
45
|
+
hardware_status_string(hardware),
|
46
|
+
f"{hardware.get('activeReservation').get('createdBy').get('username')} | {hardware.get('activeReservation').get('status')}"
|
47
|
+
if hardware.get("activeReservation", None)
|
48
|
+
else "",
|
49
|
+
)
|
50
|
+
|
51
|
+
console.print(table)
|
52
|
+
|
53
|
+
|
54
|
+
def hardware_status_string(hardware) -> str:
|
55
|
+
if activeReservation := hardware.get("activeReservation"):
|
56
|
+
if activeReservation.get("status", None) == "in_progress":
|
57
|
+
return "Reserved"
|
58
|
+
if hardware.get("isQuarantined"):
|
59
|
+
return "Quarantined"
|
60
|
+
if not hardware.get("isOnline"):
|
61
|
+
return "Offline"
|
62
|
+
if not hardware.get("isHealthy"):
|
63
|
+
return "Not healthy"
|
64
|
+
if not hardware.get("isAvailable"):
|
65
|
+
return "Not available"
|
66
|
+
else:
|
67
|
+
return "Available"
|
@@ -0,0 +1,102 @@
|
|
1
|
+
from primitive.utils.actions import BaseAction
|
2
|
+
from loguru import logger
|
3
|
+
from primitive.__about__ import __version__
|
4
|
+
from ..utils.exceptions import P_CLI_100
|
5
|
+
import sys
|
6
|
+
import psutil
|
7
|
+
from ..db import sqlite
|
8
|
+
from ..db.models import JobRun
|
9
|
+
from time import sleep
|
10
|
+
|
11
|
+
|
12
|
+
class Monitor(BaseAction):
|
13
|
+
def start(self):
|
14
|
+
logger.remove()
|
15
|
+
logger.add(
|
16
|
+
sink=sys.stderr,
|
17
|
+
format="<green>{time:YYYY-MM-DD HH:mm:ss.SSS}</green> | <level>{level: <8}</level> | <level>{message}</level>",
|
18
|
+
backtrace=True,
|
19
|
+
diagnose=True,
|
20
|
+
level="DEBUG" if self.primitive.DEBUG else "INFO",
|
21
|
+
)
|
22
|
+
logger.info("[*] primitive monitor")
|
23
|
+
logger.info(f"[*] Version: {__version__}")
|
24
|
+
|
25
|
+
# Initialize the database
|
26
|
+
sqlite.init()
|
27
|
+
|
28
|
+
try:
|
29
|
+
# hey stupid:
|
30
|
+
# do not set is_available to True here, it will mess up the reservation logic
|
31
|
+
# only set is_available after we've checked that no active reservation is present
|
32
|
+
# setting is_available of the parent also effects the children,
|
33
|
+
# which may have active reservations as well
|
34
|
+
self.primitive.hardware.check_in_http(is_online=True)
|
35
|
+
except Exception as exception:
|
36
|
+
logger.exception(f"Error checking in hardware: {exception}")
|
37
|
+
sys.exit(1)
|
38
|
+
|
39
|
+
try:
|
40
|
+
while True:
|
41
|
+
logger.debug("Syncing children...")
|
42
|
+
self.primitive.hardware._sync_children()
|
43
|
+
|
44
|
+
# Look for entries in the database
|
45
|
+
procs = JobRun.objects.all()
|
46
|
+
|
47
|
+
# No procs in the database => nothing to monitor
|
48
|
+
if len(procs) == 0:
|
49
|
+
sleep_amount = 5
|
50
|
+
logger.debug(
|
51
|
+
f"No active processes found... [sleeping {sleep_amount} seconds]"
|
52
|
+
)
|
53
|
+
sleep(sleep_amount)
|
54
|
+
continue
|
55
|
+
|
56
|
+
# If there is a process in the database, take over check in from agent
|
57
|
+
try:
|
58
|
+
self.primitive.hardware.check_in_http(is_online=True)
|
59
|
+
except Exception as exception:
|
60
|
+
logger.exception(f"Error checking in hardware: {exception}")
|
61
|
+
|
62
|
+
# For each process, check status and kill if cancelled
|
63
|
+
for proc in procs:
|
64
|
+
logger.debug(f"Checking process {proc.pid}...")
|
65
|
+
|
66
|
+
status = self.primitive.jobs.get_job_status(proc.job_run_id)
|
67
|
+
status_value = status.data["jobRun"]["status"]
|
68
|
+
conclusion_value = status.data["jobRun"]["conclusion"]
|
69
|
+
|
70
|
+
logger.debug(f"- Status: {status_value}")
|
71
|
+
logger.debug(f"- Conclusion: {conclusion_value}")
|
72
|
+
|
73
|
+
try:
|
74
|
+
parent = psutil.Process(proc.pid)
|
75
|
+
except psutil.NoSuchProcess:
|
76
|
+
logger.debug("Process not found")
|
77
|
+
continue
|
78
|
+
|
79
|
+
children = parent.children(recursive=True)
|
80
|
+
|
81
|
+
if status_value == "completed" and conclusion_value == "cancelled":
|
82
|
+
logger.warning("Job cancelled by user")
|
83
|
+
for child in children:
|
84
|
+
logger.debug(f"Killing child process {child.pid}...")
|
85
|
+
child.kill()
|
86
|
+
|
87
|
+
logger.debug(f"Killing parent process {parent.pid}...")
|
88
|
+
parent.kill()
|
89
|
+
|
90
|
+
sleep(5)
|
91
|
+
|
92
|
+
except KeyboardInterrupt:
|
93
|
+
logger.info("[*] Stopping primitive monitor...")
|
94
|
+
try:
|
95
|
+
self.primitive.hardware.check_in_http(
|
96
|
+
is_available=False, is_online=False, stopping_agent=True
|
97
|
+
)
|
98
|
+
|
99
|
+
except P_CLI_100 as exception:
|
100
|
+
logger.error("[*] Error stopping primitive monitor.")
|
101
|
+
logger.error(str(exception))
|
102
|
+
sys.exit()
|
@@ -0,0 +1,13 @@
|
|
1
|
+
import click
|
2
|
+
import typing
|
3
|
+
|
4
|
+
if typing.TYPE_CHECKING:
|
5
|
+
from ..client import Primitive
|
6
|
+
|
7
|
+
|
8
|
+
@click.command("monitor")
|
9
|
+
@click.pass_context
|
10
|
+
def cli(context):
|
11
|
+
"""monitor"""
|
12
|
+
primitive: Primitive = context.obj.get("PRIMITIVE")
|
13
|
+
primitive.monitor.start()
|
@@ -89,7 +89,6 @@ class Reservations(BaseAction):
|
|
89
89
|
)
|
90
90
|
if messages := result.data.get("reservationCreate").get("messages"):
|
91
91
|
for message in messages:
|
92
|
-
logger.enable("primitive")
|
93
92
|
if message.get("kind") == "ERROR":
|
94
93
|
logger.error(message.get("message"))
|
95
94
|
else:
|
@@ -141,7 +140,6 @@ class Reservations(BaseAction):
|
|
141
140
|
reservation = reservation_result.data["reservation"]
|
142
141
|
current_status = reservation["status"]
|
143
142
|
|
144
|
-
logger.enable("primitive")
|
145
143
|
logger.debug(
|
146
144
|
f"Waiting {total_sleep_time}s for reservation {reservation_id} to be in_progress."
|
147
145
|
)
|
primitive/utils/auth.py
CHANGED
@@ -11,7 +11,6 @@ MAX_TIME_FOR_BACKOFF = 60 * 15 # 15 minutes
|
|
11
11
|
|
12
12
|
|
13
13
|
def connection_backoff_handler(details):
|
14
|
-
logger.enable("primitive")
|
15
14
|
logger.error(
|
16
15
|
"Cannot connect to API. Waiting {wait:0.1f} seconds after {tries} tries.".format(
|
17
16
|
**details
|
@@ -25,7 +24,6 @@ def create_new_session(primitive):
|
|
25
24
|
fingerprint = primitive.host_config.get("fingerprint")
|
26
25
|
|
27
26
|
if not token or not transport:
|
28
|
-
logger.enable("primitive")
|
29
27
|
logger.error(
|
30
28
|
"CLI is not configured. Run `primitive config` to add an auth token."
|
31
29
|
)
|
@@ -0,0 +1,54 @@
|
|
1
|
+
from pathlib import Path
|
2
|
+
from abc import ABC, abstractmethod
|
3
|
+
|
4
|
+
|
5
|
+
class Daemon(ABC):
|
6
|
+
name: str
|
7
|
+
label: str
|
8
|
+
|
9
|
+
@property
|
10
|
+
@abstractmethod
|
11
|
+
def logs(self) -> Path:
|
12
|
+
"""Path to to agent or service logs"""
|
13
|
+
pass
|
14
|
+
|
15
|
+
@property
|
16
|
+
@abstractmethod
|
17
|
+
def file_path(self) -> Path:
|
18
|
+
"""Path to agent or service definition file"""
|
19
|
+
pass
|
20
|
+
|
21
|
+
@abstractmethod
|
22
|
+
def install(self) -> bool:
|
23
|
+
"""Install the daemon"""
|
24
|
+
pass
|
25
|
+
|
26
|
+
@abstractmethod
|
27
|
+
def uninstall(self) -> bool:
|
28
|
+
"""Uninstall the daemon"""
|
29
|
+
pass
|
30
|
+
|
31
|
+
@abstractmethod
|
32
|
+
def start(self) -> bool:
|
33
|
+
"""Start the daemon"""
|
34
|
+
pass
|
35
|
+
|
36
|
+
@abstractmethod
|
37
|
+
def stop(self) -> bool:
|
38
|
+
"""Stop the daemon"""
|
39
|
+
pass
|
40
|
+
|
41
|
+
@abstractmethod
|
42
|
+
def is_installed(self) -> bool:
|
43
|
+
"""Check if the daemon is installed"""
|
44
|
+
pass
|
45
|
+
|
46
|
+
@abstractmethod
|
47
|
+
def is_active(self) -> bool:
|
48
|
+
"""Check if the daemon is active"""
|
49
|
+
pass
|
50
|
+
|
51
|
+
@abstractmethod
|
52
|
+
def view_logs(self) -> None:
|
53
|
+
"""View the daemon logs"""
|
54
|
+
pass
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: primitive
|
3
|
-
Version: 0.2.
|
3
|
+
Version: 0.2.11
|
4
4
|
Project-URL: Documentation, https://github.com//primitivecorp/primitive-cli#readme
|
5
5
|
Project-URL: Issues, https://github.com//primitivecorp/primitive-cli/issues
|
6
6
|
Project-URL: Source, https://github.com//primitivecorp/primitive-cli
|
@@ -23,9 +23,11 @@ Requires-Dist: gql[all]
|
|
23
23
|
Requires-Dist: loguru
|
24
24
|
Requires-Dist: paramiko[invoke]
|
25
25
|
Requires-Dist: primitive-pal==0.1.4
|
26
|
+
Requires-Dist: psutil>=7.0.0
|
26
27
|
Requires-Dist: pyyaml
|
27
28
|
Requires-Dist: rich>=13.9.4
|
28
29
|
Requires-Dist: speedtest-cli
|
30
|
+
Requires-Dist: sqlalchemy>=2.0.40
|
29
31
|
Description-Content-Type: text/markdown
|
30
32
|
|
31
33
|
# primitive
|
@@ -1,11 +1,11 @@
|
|
1
|
-
primitive/__about__.py,sha256=
|
1
|
+
primitive/__about__.py,sha256=51uVt8anKtwpofvSe0Zwd_GncrkYXPbI0DjswyDbXRs,130
|
2
2
|
primitive/__init__.py,sha256=bwKdgggKNVssJFVPfKSxqFMz4IxSr54WWbmiZqTMPNI,106
|
3
|
-
primitive/cli.py,sha256=
|
4
|
-
primitive/client.py,sha256=
|
3
|
+
primitive/cli.py,sha256=g7EtHI9MATAB0qQu5w-WzbXtxz_8zu8z5E7sETmMkKU,2509
|
4
|
+
primitive/client.py,sha256=h8WZVnQylVe0vbpuyC8YZHl2JyITSPC-1HbUcmrE5pc,3623
|
5
5
|
primitive/agent/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
6
|
-
primitive/agent/actions.py,sha256=
|
6
|
+
primitive/agent/actions.py,sha256=mmMwc9D8zo1w9aLlaYPBArncQ_qqnG6L9TWadcxvO-g,7018
|
7
7
|
primitive/agent/commands.py,sha256=-dVDilELfkGfbZB7qfEPs77Dm1oT62qJj4tsIk4KoxI,254
|
8
|
-
primitive/agent/runner.py,sha256=
|
8
|
+
primitive/agent/runner.py,sha256=IuY-UMZ1WupYBXuPr-Ne0dcWeLFeV2_O-6F0SiG3VOs,13942
|
9
9
|
primitive/agent/uploader.py,sha256=6pjUyb1LyUCpHBE6p13pRpXxy6iDxu14qJGvE3R6cVo,3155
|
10
10
|
primitive/auth/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
11
11
|
primitive/auth/actions.py,sha256=MPsG9LcKcOPwA7gZ9Ewk0PZJhTQvIrGfODdz4GxSzgA,999
|
@@ -13,16 +13,20 @@ primitive/auth/commands.py,sha256=2z5u5xX64n0yILucx9emtWh3uQXLvs2QQQQIldZGr94,23
|
|
13
13
|
primitive/auth/graphql/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
14
14
|
primitive/auth/graphql/queries.py,sha256=jhrr_VFzHIn8vcVprMIzUx7V4kkWYdR6CKMKPoVFv60,180
|
15
15
|
primitive/daemons/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
16
|
-
primitive/daemons/actions.py,sha256=
|
17
|
-
primitive/daemons/commands.py,sha256
|
18
|
-
primitive/daemons/launch_agents.py,sha256=
|
19
|
-
primitive/daemons/launch_service.py,sha256=
|
16
|
+
primitive/daemons/actions.py,sha256=V4BUCLS8UoQOZoS2vwEkYQpWAUNdZnMPBhQR19RvQXs,2023
|
17
|
+
primitive/daemons/commands.py,sha256=Xt4qFymNrDLdHJhRnEH_4Re-2xX6w1OT-chV9k7dFCs,2670
|
18
|
+
primitive/daemons/launch_agents.py,sha256=KD7cqQZDtfDmMyNiYrswTRWEktvS9A1QsqQF1jhMDjw,7940
|
19
|
+
primitive/daemons/launch_service.py,sha256=IhvKZqU5juA3hKsvUB2275BP8lNBl5XWkVoqVgdwy-o,8013
|
20
|
+
primitive/daemons/ui.py,sha256=Af3OJWJ0jdGlb1nfA5yaGYdhBEqqpM8zP2U2vUQdCbw,1236
|
21
|
+
primitive/db/base.py,sha256=mH7f2d_jiyxJSSx9Gk53QBXRa3LiKBsBjkFgvmtH1WA,83
|
22
|
+
primitive/db/models.py,sha256=UnbRVhYoIG3rjfcjAQaGaJfSi_c7iJVQWfnpKU9TOp4,2543
|
23
|
+
primitive/db/sqlite.py,sha256=t942Yrj7Z1wyRla3ZtLdk5Z7rmKDuGUY3fNKc39UbRQ,735
|
20
24
|
primitive/exec/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
21
|
-
primitive/exec/actions.py,sha256=
|
25
|
+
primitive/exec/actions.py,sha256=4d_TCjNDcVFoZ9Zw7ZuBa6hKMv2Xzm7_UX_8wcX1aSk,4124
|
22
26
|
primitive/exec/commands.py,sha256=66LO2kkJC-ynNZQpUCXv4Ol15QoacdSZAHblePDcmLo,510
|
23
27
|
primitive/exec/interactive.py,sha256=TscY6s2ZysijidKPheq6y-fCErUVLS0zcdTW8XyFWGI,2435
|
24
28
|
primitive/files/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
25
|
-
primitive/files/actions.py,sha256=
|
29
|
+
primitive/files/actions.py,sha256=jvsBivYBmPeqb6Ge7gECm_x20AFUL7UYPGJJFmoCeOM,12409
|
26
30
|
primitive/files/commands.py,sha256=ZNW4y8JZF1li7P5ej1r-Xcqu0iGpRRlMYvthuZOLLbQ,1163
|
27
31
|
primitive/files/graphql/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
28
32
|
primitive/files/graphql/fragments.py,sha256=II6WHZjzSqX4IELwdiWokqHTKvDq6mMHF5gp3rLnj3U,231
|
@@ -38,9 +42,10 @@ primitive/graphql/relay.py,sha256=bmij2AjdpURQ6GGVCxwWhauF-r_SxuAU2oJ4sDbLxpI,72
|
|
38
42
|
primitive/graphql/sdk.py,sha256=KhVWDZms_eMBgt6ftSJitRALguagy-nmrj4IC2taeXY,1535
|
39
43
|
primitive/graphql/utility_fragments.py,sha256=uIjwILC4QtWNyO5vu77VjQf_p0jvP3A9q_6zRq91zqs,303
|
40
44
|
primitive/hardware/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
41
|
-
primitive/hardware/actions.py,sha256=
|
45
|
+
primitive/hardware/actions.py,sha256=8irVoDN4uzMMp58sgA9VOB1aO2NwBBVnJfg_k7i5tmA,25912
|
42
46
|
primitive/hardware/android.py,sha256=tu7pBPxWFrIwb_mm5CEdFFf1_veNDOKjOCQg13i_Lh4,2758
|
43
|
-
primitive/hardware/commands.py,sha256=
|
47
|
+
primitive/hardware/commands.py,sha256=ixMPhDOpsU-eONxmimqKVynus-Eaq2XPKEK017WM_rM,3229
|
48
|
+
primitive/hardware/ui.py,sha256=12rucuZ2s-w5R4bKyxON5dEbrdDnVf5sbj3K_nbdo44,2473
|
44
49
|
primitive/hardware/graphql/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
45
50
|
primitive/hardware/graphql/fragments.py,sha256=kI6qnTNjaEaUr-C6eD55COphtueVYbYOWZwN5EW_3qw,350
|
46
51
|
primitive/hardware/graphql/mutations.py,sha256=_4Hkbfik9Ron4T-meulu6T-9FR_BZjyPNwn745MPksU,1484
|
@@ -52,6 +57,8 @@ primitive/jobs/graphql/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3
|
|
52
57
|
primitive/jobs/graphql/fragments.py,sha256=1_ZttT7dx36KDC3DClJz9M8LMpsPwXySBygHSiUEcGg,619
|
53
58
|
primitive/jobs/graphql/mutations.py,sha256=8ASvCmwQh7cMeeiykOdYaYVryG8FRIuVF6v_J8JJZuw,219
|
54
59
|
primitive/jobs/graphql/queries.py,sha256=BrU_GnLjK0bTAmWsLSmGEUea7EM8MqTKxN1Qp6sSjwc,1597
|
60
|
+
primitive/monitor/actions.py,sha256=AHPtZRXdvlZNfzpBJd4PkXF5QxTYj0BYwq-qB8PLZZY,3990
|
61
|
+
primitive/monitor/commands.py,sha256=dZsD8WKGU4OYO_AlKawfeRNVTMN0xJ-DFRkmKTS464s,258
|
55
62
|
primitive/organizations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
56
63
|
primitive/organizations/actions.py,sha256=Tgp_rox0jcvfhQ-LmcWc9vkPdeJu5Bk6U1rNuT9oDnw,1088
|
57
64
|
primitive/organizations/commands.py,sha256=_dwgVEJCqMa5VgB_7P1wLPFc0AuT1p9dtyR9JRr4kpw,487
|
@@ -71,7 +78,7 @@ primitive/provisioning/actions.py,sha256=IYZYAbtomtZtlkqDaBxx4e7PFKGkRNqek_tABH6
|
|
71
78
|
primitive/provisioning/graphql/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
72
79
|
primitive/provisioning/graphql/queries.py,sha256=cBtuKa6shoatYZfKSnQoPJP6B8g8y3QhFqJ_pkvMcG0,134
|
73
80
|
primitive/reservations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
74
|
-
primitive/reservations/actions.py,sha256=
|
81
|
+
primitive/reservations/actions.py,sha256=FiodRTVUgGgFfoksnN9W0XNdGTd2AxPJTfUrZbmQ0_g,6179
|
75
82
|
primitive/reservations/commands.py,sha256=LFRoV59QGgWIjBdrGjJdffHugg8TLe0Fwlcyu_JaTkk,2369
|
76
83
|
primitive/reservations/graphql/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
77
84
|
primitive/reservations/graphql/fragments.py,sha256=o5JXkhrFrftYZbsmOQRj105bNw4WwO6U34yN0X-pbCg,411
|
@@ -79,17 +86,18 @@ primitive/reservations/graphql/mutations.py,sha256=IqzwQL7OclN7RpIcidrTQo9cGYofY
|
|
79
86
|
primitive/reservations/graphql/queries.py,sha256=x31wTRelskX2fc0fx2qrY7XT1q74nvzLv_Xef3o9weg,746
|
80
87
|
primitive/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
81
88
|
primitive/utils/actions.py,sha256=HOFrmM3-0A_A3NS84MqrZ6JmQEiiPSoDqEeuu6b_qfQ,196
|
82
|
-
primitive/utils/auth.py,sha256=
|
89
|
+
primitive/utils/auth.py,sha256=uBIZNPF2CpbaPV2UMi6eWVUKghV6WIm-pG3-UM29bNs,1465
|
83
90
|
primitive/utils/cache.py,sha256=FHGmVWYLJFQOazpXXcEwI0YJEZbdkgG39nOLdOv6VNk,1575
|
84
91
|
primitive/utils/chunk_size.py,sha256=PAuVuirUTA9oRXyjo1c6MWxo31WVBRkWMuWw-AS58Bw,2914
|
85
92
|
primitive/utils/config.py,sha256=DlFM5Nglo22WPtbpZSVtH7NX-PTMaKYlcrUE7GPRG4c,1058
|
93
|
+
primitive/utils/daemons.py,sha256=YkG-OcrTxMhGedbNJMKLq_e7CdTy30Ba2oCVUY-09Co,1086
|
86
94
|
primitive/utils/exceptions.py,sha256=DrYHTcCAJGC7cCUwOx_FmdlVLWRdpzvDvpLb82heppE,311
|
87
95
|
primitive/utils/memory_size.py,sha256=4xfha21kW82nFvOTtDFx9Jk2ZQoEhkfXii-PGNTpIUk,3058
|
88
96
|
primitive/utils/printer.py,sha256=f1XUpqi5dkTL3GWvYRUGlSwtj2IxU1q745T4Fxo7Tn4,370
|
89
97
|
primitive/utils/shell.py,sha256=jWzb7ky7p987dJas6ZvarK3IJNZ5cwBXcryRWb9Uh6U,2072
|
90
98
|
primitive/utils/text.py,sha256=XiESMnlhjQ534xE2hMNf08WehE1SKaYFRNih0MmnK0k,829
|
91
|
-
primitive-0.2.
|
92
|
-
primitive-0.2.
|
93
|
-
primitive-0.2.
|
94
|
-
primitive-0.2.
|
95
|
-
primitive-0.2.
|
99
|
+
primitive-0.2.11.dist-info/METADATA,sha256=MR8wugqoR7n8zbscUyXhhgynbMQnmeXAXMnD2fk4gPs,3733
|
100
|
+
primitive-0.2.11.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
101
|
+
primitive-0.2.11.dist-info/entry_points.txt,sha256=p1K8DMCWka5FqLlqP1sPek5Uovy9jq8u51gUsP-z334,48
|
102
|
+
primitive-0.2.11.dist-info/licenses/LICENSE.txt,sha256=B8kmQMJ2sxYygjCLBk770uacaMci4mPSoJJ8WoDBY_c,1098
|
103
|
+
primitive-0.2.11.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|