semaphoreui-client 0.1.0__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.
@@ -0,0 +1 @@
1
+ __version__ = "0.1.0"
@@ -0,0 +1 @@
1
+ __version__ = "0.1.0"
@@ -0,0 +1 @@
1
+ from .client import SemaphoreUIClient as Client # NOQA
@@ -0,0 +1,799 @@
1
+ from dataclasses import dataclass
2
+ import typing
3
+
4
+ from dataclasses_json import dataclass_json
5
+ import requests
6
+
7
+
8
+ class SemaphoreUIClient:
9
+
10
+ def __init__(self, host, path="/api"):
11
+ self.http = requests.Session()
12
+ self.api_endpoint = f"{host}{path}"
13
+
14
+ def login(self, user, password):
15
+ response = self.http.post(
16
+ f"{self.api_endpoint}/auth/login", json={"auth": user, "password": password}
17
+ )
18
+ if response.status_code != 204:
19
+ raise ValueError(
20
+ f"Username and/or password incorrect. Response from POST /auth/login was {response.status_code}"
21
+ )
22
+
23
+ def whoami(self):
24
+ response = self.http.get(f"{self.api_endpoint}/auth/login")
25
+ assert (
26
+ response.status_code == 200
27
+ ), f"GET /auth/login return response {response.status_code}"
28
+
29
+ def logout(self):
30
+ response = self.http.post(f"{self.api_endpoint}/auth/logout")
31
+ assert response.status_code == 204
32
+
33
+ def tokens(self) -> typing.List["Token"]:
34
+ response = self.http.get(f"{self.api_endpoint}/user/tokens")
35
+ assert response.status_code == 200
36
+ return [Token(**token_data, client=self) for token_data in response.json()]
37
+
38
+ def create_token(self) -> "Token":
39
+ response = self.http.post(f"{self.api_endpoint}/user/tokens")
40
+ assert response.status_code == 201
41
+ return Token(**response.json(), client=self)
42
+
43
+ def delete_token(self, id):
44
+ response = self.http.post(f"{self.api_endpoint}/user/tokens/{id}")
45
+ assert response.status_code in (204, 404) # 404 if token was already expired
46
+
47
+ def projects(self) -> typing.List["Project"]:
48
+ response = self.http.get(f"{self.api_endpoint}/projects")
49
+ assert response.status_code == 200
50
+ return [Project(**data, client=self) for data in response.json()]
51
+
52
+ def get_project(self, id: int) -> "Project":
53
+ response = self.http.get(f"{self.api_endpoint}/project/{id}")
54
+ assert response.status_code == 200
55
+ return Project(**response.json(), client=self)
56
+
57
+ def create_project(
58
+ self,
59
+ name: str,
60
+ alert: bool,
61
+ alert_chat: str,
62
+ max_parallel_tasks: int,
63
+ type: typing.Optional[str] = None,
64
+ demo: typing.Optional[bool] = False,
65
+ ) -> "Project":
66
+ response = self.http.post(
67
+ f"{self.api_endpoint}/projects",
68
+ json={
69
+ "name": name,
70
+ "alert": alert,
71
+ "alert_chat": alert_chat,
72
+ "max_parallel_tasks": max_parallel_tasks,
73
+ "type": type,
74
+ "demo": demo,
75
+ },
76
+ )
77
+ assert response.status_code == 201
78
+ return Project(**response.json(), client=self)
79
+
80
+ def delete_project(self, id: int):
81
+ response = self.http.delete(f"{self.api_endpoint}/project/{id}")
82
+ assert response.status_code == 204
83
+
84
+ def update_project(
85
+ self,
86
+ id: int,
87
+ name: str,
88
+ alert: bool,
89
+ alert_chat: str,
90
+ max_parallel_tasks: int,
91
+ type: str,
92
+ ):
93
+ response = self.http.put(
94
+ f"{self.api_endpoint}/project/{id}",
95
+ json={
96
+ "name": name,
97
+ "alert": alert,
98
+ },
99
+ )
100
+ assert response.status_code == 204
101
+
102
+ def backup_project(self, id: int) -> "ProjectBackup":
103
+ response = self.http.get(f"{self.api_endpoint}/project/{id}/backup")
104
+ assert response.status_code == 200
105
+ return ProjectBackup(**response.json())
106
+
107
+ def get_project_role(self, id: int) -> "Permissions":
108
+ response = self.http.get(f"{self.api_endpoint}/project/{id}/role")
109
+ assert response.status_code == 200
110
+ return Permissions(**response.json())
111
+
112
+ def get_project_events(self, id: int) -> typing.List["Event"]:
113
+ response = self.http.get(f"{self.api_endpoint}/project/{id}/events")
114
+ assert response.status_code == 200
115
+ return [Event(**data) for data in response.json()]
116
+
117
+ def get_project_users(self, id: int, sort: str, order: str) -> typing.List["User"]:
118
+ response = self.http.get(f"{self.api_endpoint}/project/{id}/")
119
+ assert response.status_code == 200
120
+ return [User(**data) for data in response.json()]
121
+
122
+ def add_project_user(self, id: int, user: "User"):
123
+ response = self.http.post(
124
+ f"{self.api_endpoint}/project/{id}/users", json=user.to_json() # type: ignore
125
+ )
126
+ assert response.status_code == 204
127
+
128
+ def update_project_user(self, id: int, user: "User"):
129
+ response = self.http.put(
130
+ f"{self.api_endpoint}/project/{id}/users/{user.id}", json=user.to_json() # type: ignore
131
+ )
132
+ assert response.status_code == 204
133
+
134
+ def remove_project_user(self, id: int, user_id: int):
135
+ response = self.http.delete(f"{self.api_endpoint}/project/{id}/users/{user_id}")
136
+ assert response.status_code == 204
137
+
138
+ def get_project_integrations(self, id: int) -> typing.List["Integration"]:
139
+ response = self.http.get(f"{self.api_endpoint}/project/{id}/integrations")
140
+ assert response.status_code == 200
141
+ return [Integration(**data, client=self) for data in response.json()]
142
+
143
+ def create_project_integrations(
144
+ self, project_id: int, name: str, template_id: int
145
+ ) -> "Integration":
146
+ response = self.http.post(
147
+ f"{self.api_endpoint}/project/{id}integrations",
148
+ json={"project_id": project_id, "name": name, "template_id": template_id},
149
+ )
150
+ assert response.status_code == 200
151
+ return Integration(**response.json(), client=self)
152
+
153
+ def update_project_integration(
154
+ self, project_id: int, id: int, name: str, template_id: int
155
+ ):
156
+ response = self.http.put(
157
+ f"{self.api_endpoint}/project/{project_id}/integrations/{id}",
158
+ json={"project_id": project_id, "name": name, "template_id": template_id},
159
+ )
160
+ assert response.status_code == 204
161
+
162
+ def delete_project_integration(self, project_id: int, id: int):
163
+ response = self.http.delete(
164
+ f"{self.api_endpoint}/project/{project_id}/integrations/{id}"
165
+ )
166
+ assert response.status_code == 204
167
+
168
+ def get_project_keys(
169
+ self,
170
+ project_id: int,
171
+ key_type: typing.Optional[str] = None,
172
+ sort: typing.Optional[str] = None,
173
+ order: typing.Optional[str] = None,
174
+ ) -> typing.List["Key"]:
175
+ response = self.http.get(f"{self.api_endpoint}/project/{project_id}/keys")
176
+ assert response.status_code == 200
177
+ return [Key(**data, client=self) for data in response.json()]
178
+
179
+ def create_project_key(
180
+ self,
181
+ project_id: int,
182
+ name: str,
183
+ key_type: str,
184
+ override_secret: bool,
185
+ login_password: typing.Optional[typing.Tuple[str, str]],
186
+ ssh: typing.Optional[typing.Tuple[str, str, str]],
187
+ ) -> "Key":
188
+ if key_type not in ("ssh", "login_password"):
189
+ raise ValueError(f"Invalid key_type: {key_type}. Acceptable values are: ssh, login_password")
190
+ if key_type == "ssh" and ssh is None:
191
+ raise ValueError("ssh parameter must be set on key_type: ssh")
192
+ elif key_type == "login_password" and login_password is None:
193
+ raise ValueError("login_password parameter must be set on key_type: login_password")
194
+ response = self.http.post(
195
+ f"{self.api_endpoint}/project/{project_id}/keys",
196
+ json={
197
+ "id": 0,
198
+ "project_id": project_id,
199
+ "name": name,
200
+ "type": key_type,
201
+ "override_secret": override_secret,
202
+ "login_password": {
203
+ "login": login_password[0],
204
+ "password": login_password[1],
205
+ },
206
+ "ssh": {
207
+ "login": ssh[0],
208
+ "passphrase": ssh[1],
209
+ "private_key": ssh[2],
210
+ },
211
+ },
212
+ )
213
+ assert response.status_code == 204
214
+
215
+ try:
216
+ return Key(**response.json(), client=self)
217
+ except ValueError:
218
+ # Sporadically, the response is an empty string. Get the actual key from the API
219
+ return [
220
+ key for key in self.get_project_keys(project_id) if key.name == name
221
+ ][0]
222
+
223
+ def delete_project_key(self, project_id: int, id: int):
224
+ response = self.http.delete(
225
+ f"{self.api_endpoint}/project/{project_id}/keys/{id}"
226
+ )
227
+ assert response.status_code == 204
228
+
229
+ def get_project_repositories(self, project_id: int) -> typing.List["Repository"]:
230
+ response = self.http.get(
231
+ f"{self.api_endpoint}/project/{project_id}/repositories"
232
+ )
233
+ assert response.status_code == 200
234
+ return [Repository(**data, client=self) for data in response.json()]
235
+
236
+ def create_project_repository(
237
+ self, project_id: int, name: str, git_url: str, git_branch: str, ssh_key_id: int
238
+ ) -> "Repository":
239
+ response = self.http.post(
240
+ f"{self.api_endpoint}/project/{project_id}/repositories",
241
+ json={
242
+ "name": name,
243
+ "project_id": project_id,
244
+ "git_url": git_url,
245
+ "git_branch": git_branch,
246
+ "ssh_key_id": ssh_key_id,
247
+ },
248
+ )
249
+ assert response.status_code == 204
250
+ try:
251
+ return Repository(**response.json(), client=self)
252
+ except ValueError:
253
+ return [
254
+ repo
255
+ for repo in self.get_project_repositories(project_id)
256
+ if repo.name == name
257
+ ][0]
258
+
259
+ def delete_project_repository(self, project_id: int, id: int):
260
+ response = self.http.delete(
261
+ f"{self.api_endpoint}/project/{project_id}/repositories/{id}"
262
+ )
263
+ assert response.status_code == 204
264
+
265
+ def get_project_environments(self, project_id: int) -> typing.List["Environment"]:
266
+ response = self.http.get(
267
+ f"{self.api_endpoint}/project/{project_id}/environment"
268
+ )
269
+ assert response.status_code == 200
270
+ return [Environment(**data, client=self) for data in response.json()]
271
+
272
+ def create_project_environment(
273
+ self,
274
+ project_id: int,
275
+ name: str,
276
+ password: str,
277
+ json: str,
278
+ env: str,
279
+ secrets: typing.List[typing.Dict[typing.Any, typing.Any]],
280
+ ) -> "Environment":
281
+ response = self.http.post(
282
+ f"{self.api_endpoint}/project/{project_id}/environment",
283
+ json={
284
+ "name": name,
285
+ "project_id": project_id,
286
+ "password": None,
287
+ "json": json,
288
+ "env": env,
289
+ "secrets": secrets,
290
+ },
291
+ )
292
+ assert response.status_code == 204
293
+ try:
294
+ return Environment(**response.json(), client=self)
295
+ except ValueError:
296
+ return [
297
+ env
298
+ for env in self.get_project_environments(project_id)
299
+ if env.name == name
300
+ ][0]
301
+
302
+ def delete_project_environment(self, project_id: int, id: int):
303
+ response = self.http.delete(
304
+ f"{self.api_endpoint}/project/{project_id}/environment/{id}"
305
+ )
306
+ assert response.status_code == 204
307
+
308
+ def get_project_views(self, project_id: int) -> typing.List["View"]:
309
+ response = self.http.get(f"{self.api_endpoint}/project/{project_id}/views")
310
+ assert response.status_code == 200
311
+ return [View(**data, client=self) for data in response.json()]
312
+
313
+ def create_project_view(self, project_id: int, title: str, position: int) -> "View":
314
+ response = self.http.post(
315
+ f"{self.api_endpoint}/project/{project_id}/views",
316
+ json={"position": position, "title": title, "project_id": project_id},
317
+ )
318
+ assert response.status_code == 201
319
+ return View(**response.json(), client=self)
320
+
321
+ def delete_project_view(self, project_id: int, id: int):
322
+ response = self.http.delete(
323
+ f"{self.api_endpoint}/project/{project_id}/views/{id}"
324
+ )
325
+ assert response.status_code == 204
326
+
327
+ def get_project_inventories(self, project_id: int) -> typing.List["Inventory"]:
328
+ response = self.http.get(f"{self.api_endpoint}/project/{project_id}/inventory")
329
+ assert response.status_code == 200
330
+ return [Inventory(**data, client=self) for data in response.json()]
331
+
332
+ def create_project_inventory(
333
+ self,
334
+ project_id: int,
335
+ name: str,
336
+ inventory: str,
337
+ ssh_key_id: int,
338
+ become_key_id: int,
339
+ type: str,
340
+ repostory_id: int,
341
+ ) -> "Inventory":
342
+ response = self.http.post(
343
+ f"{self.api_endpoint}/project/{project_id}/inventory",
344
+ json={
345
+ "id": 0,
346
+ "name": name,
347
+ "project_id": project_id,
348
+ "inventory": inventory,
349
+ "ssh_key_id": ssh_key_id,
350
+ "become_key_id": become_key_id,
351
+ "type": type,
352
+ "repository_id": repostory_id,
353
+ },
354
+ )
355
+ assert response.status_code == 201
356
+ return Inventory(**response.json(), client=self)
357
+
358
+ def delete_project_inventory(self, project_id: int, id: int):
359
+ response = self.http.delete(
360
+ f"{self.api_endpoint}/project/{project_id}/inventory/{id}"
361
+ )
362
+ assert response.status_code == 204
363
+
364
+ def get_project_templates(self, project_id: int) -> typing.List["Template"]:
365
+ response = self.http.get(f"{self.api_endpoint}/project/{project_id}/templates")
366
+ assert response.status_code == 200
367
+ return [Template(**data, client=self) for data in response.json()]
368
+
369
+ def create_project_template(
370
+ self,
371
+ project_id: int,
372
+ name: str,
373
+ repository_id: int,
374
+ inventory_id: int,
375
+ environment_id: int,
376
+ view_id: int,
377
+ vaults: typing.List[typing.Dict[str, typing.Any]],
378
+ playbook: str,
379
+ arguments: str,
380
+ description: str,
381
+ allow_override_args_in_task: bool,
382
+ limit: int,
383
+ suppress_success_alerts: bool,
384
+ app: str,
385
+ git_branch: str,
386
+ survey_vars: typing.List[typing.Dict[str, typing.Any]],
387
+ type: str,
388
+ start_version: str,
389
+ autorun: bool,
390
+ build_template_id: typing.Optional[int]=None,
391
+ ) -> "Template":
392
+ response = self.http.post(
393
+ f"{self.api_endpoint}/project/{project_id}/templates",
394
+ json={
395
+ "id": 1,
396
+ "project_id": project_id,
397
+ "inventory_id": inventory_id,
398
+ "repository_id": repository_id,
399
+ "environment_id": environment_id,
400
+ "view_id": view_id,
401
+ "vaults": vaults,
402
+ "name": name,
403
+ "playbook": playbook,
404
+ "arguments": arguments,
405
+ "description": description,
406
+ "allow_override_args_in_task": allow_override_args_in_task,
407
+ "limit": limit,
408
+ "suppress_success_alerts": suppress_success_alerts,
409
+ "app": app,
410
+ "git_branch": git_branch,
411
+ "survey_vars": survey_vars,
412
+ "type": type,
413
+ "start_version": start_version,
414
+ "build_template_id": build_template_id,
415
+ "autorun": autorun,
416
+ },
417
+ )
418
+ assert (
419
+ response.status_code == 201
420
+ ), f"Expected response code 201, got {response.status_code}"
421
+ return Template(**response.json(), client=self)
422
+
423
+ def delete_project_template(self, project_id: int, id: int):
424
+ response = self.http.delete(
425
+ f"{self.api_endpoint}/project/{project_id}/templates/{id}"
426
+ )
427
+ assert response.status_code == 204
428
+
429
+
430
+ @dataclass
431
+ class Integration:
432
+ """A project integration"""
433
+
434
+ id: int
435
+ name: str
436
+ project_id: int
437
+ template_id: int
438
+
439
+ client: SemaphoreUIClient
440
+
441
+ def save(self):
442
+ self.client.update_project_integration(
443
+ self.project_id, self.id, self.name, self.template_id
444
+ )
445
+
446
+ def delete(self):
447
+ self.client.delete_project_integration(self.project_id, self.id)
448
+
449
+
450
+ @dataclass
451
+ class Token:
452
+ """An authorization token."""
453
+
454
+ id: str
455
+ created: str
456
+ expired: bool
457
+ user_id: int
458
+
459
+ client: SemaphoreUIClient
460
+
461
+ def delete(self):
462
+ self.client.delete_token(self.id)
463
+
464
+
465
+ @dataclass
466
+ class Project:
467
+ """A Semaphore UI project."""
468
+
469
+ id: int
470
+ name: str
471
+ created: str
472
+ alert: bool
473
+ alert_chat: str
474
+ max_parallel_tasks: int
475
+ type: str # This might be an enum?
476
+
477
+ client: SemaphoreUIClient
478
+
479
+ def delete(self):
480
+ self.client.delete_project(self.id)
481
+
482
+ def save(self):
483
+ self.client.update_project(
484
+ self.id,
485
+ self.name,
486
+ self.alert,
487
+ self.alert_chat,
488
+ self.max_parallel_tasks,
489
+ self.type,
490
+ )
491
+
492
+ def backup(self):
493
+ return self.client.backup_project(self.id)
494
+
495
+ def role(self):
496
+ return self.client.get_project_role(self.id)
497
+
498
+ def events(self):
499
+ return self.client.get_project_events(self.id)
500
+
501
+ def users(self, sort: str, order: str):
502
+ return self.client.get_project_users(self.id, sort, order)
503
+
504
+ def add_user(self, user: "User"):
505
+ return self.client.add_project_user(self.id, user)
506
+
507
+ def remove_user(self, user_id: int):
508
+ return self.client.remove_project_user(self.id, user_id)
509
+
510
+ def update_user(self, user: "User"):
511
+ return self.client.update_project_user(self.id, user)
512
+
513
+ def keys(self) -> typing.List["Key"]:
514
+ return self.client.get_project_keys(self.id)
515
+
516
+ def create_key(
517
+ self,
518
+ name: str,
519
+ key_type: str,
520
+ override_secret: bool,
521
+ string: str,
522
+ login_password: typing.Optional[typing.Tuple[str, str]],
523
+ ssh: typing.Optional[typing.Tuple[str, str, str]],
524
+ ):
525
+ return self.client.create_project_key(
526
+ self.id, name, key_type, override_secret, login_password, ssh
527
+ )
528
+
529
+ def repositories(self) -> typing.List["Repository"]:
530
+ return self.client.get_project_repositories(self.id)
531
+
532
+ def create_repository(
533
+ self, name: str, git_url: str, git_branch: str, ssh_key_id: int
534
+ ) -> "Repository":
535
+ return self.client.create_project_repository(
536
+ self.id, name, git_url, git_branch, ssh_key_id
537
+ )
538
+
539
+ def environments(self) -> typing.List["Environment"]:
540
+ return self.client.get_project_environments(self.id)
541
+
542
+ def create_environment(
543
+ self,
544
+ name: str,
545
+ password: str,
546
+ json: str,
547
+ env: str,
548
+ secrets: typing.List[typing.Dict[typing.Any, typing.Any]],
549
+ ) -> "Environment":
550
+ return self.client.create_project_environment(
551
+ self.id, name, password, json, env, secrets
552
+ )
553
+
554
+ def views(self) -> typing.List["View"]:
555
+ return self.client.get_project_views(self.id)
556
+
557
+ def create_view(self, title: str, position: int) -> "View":
558
+ return self.client.create_project_view(self.id, title, position)
559
+
560
+ def inventories(self) -> typing.List["Inventory"]:
561
+ return self.client.get_project_inventories(self.id)
562
+
563
+ def create_inventory(
564
+ self,
565
+ name: str,
566
+ inventory: str,
567
+ ssh_key_id: int,
568
+ become_key_id: int,
569
+ type: str,
570
+ repository_id: int,
571
+ ) -> "Inventory":
572
+ return self.client.create_project_inventory(
573
+ self.id, name, inventory, ssh_key_id, become_key_id, type, repository_id
574
+ )
575
+
576
+ def templates(self) -> typing.List["Template"]:
577
+ return self.client.get_project_templates(self.id)
578
+
579
+ def create_template(
580
+ self,
581
+ name: str,
582
+ repository_id: int,
583
+ inventory_id: int,
584
+ environment_id: int,
585
+ view_id: int,
586
+ vaults: typing.List[typing.Dict[str, typing.Any]],
587
+ playbook: str,
588
+ arguments: str,
589
+ description: str,
590
+ allow_override_args_in_task: bool,
591
+ limit: int,
592
+ suppress_success_alerts: bool,
593
+ app: str,
594
+ git_branch: str,
595
+ survey_vars: typing.List[typing.Dict[str, typing.Any]],
596
+ type: str,
597
+ start_version: str,
598
+ autorun: bool,
599
+ build_template_id: typing.Optional[int]=None,
600
+ ) -> "Template":
601
+ return self.client.create_project_template(
602
+ self.id,
603
+ name,
604
+ repository_id,
605
+ inventory_id,
606
+ environment_id,
607
+ view_id,
608
+ vaults,
609
+ playbook,
610
+ arguments,
611
+ description,
612
+ allow_override_args_in_task,
613
+ limit,
614
+ suppress_success_alerts,
615
+ app,
616
+ git_branch,
617
+ survey_vars,
618
+ type,
619
+ start_version,
620
+ autorun,
621
+ build_template_id,
622
+ )
623
+
624
+
625
+ @dataclass
626
+ class Permissions:
627
+ role: str
628
+ permissions: int
629
+
630
+
631
+ @dataclass
632
+ class ProjectBackup: ...
633
+
634
+
635
+ @dataclass
636
+ class Event:
637
+ project_id: int
638
+ user_id: int
639
+ object_id: str
640
+ object_type: str
641
+ description: str
642
+
643
+
644
+ @dataclass_json
645
+ @dataclass
646
+ class User:
647
+ user_id: int
648
+ role: str
649
+
650
+ @property
651
+ def id(self) -> int:
652
+ return self.user_id
653
+
654
+
655
+ @dataclass
656
+ class KeySsh:
657
+ login: str
658
+ passphrase: str
659
+ private_key: str
660
+
661
+
662
+ @dataclass
663
+ class KeyLoginPassword:
664
+ login: str
665
+ password: str
666
+
667
+
668
+ @dataclass
669
+ class Key:
670
+ id: int
671
+ name: str
672
+ type: str
673
+ project_id: int
674
+
675
+ string: str
676
+ override_secret: bool
677
+ login_password: KeyLoginPassword
678
+ ssh: KeySsh
679
+
680
+ client: SemaphoreUIClient
681
+
682
+ @classmethod
683
+ def from_dict(cls, **keys) -> "Key":
684
+ ssh = KeySsh(
685
+ login=keys["ssh"]["login"],
686
+ passphrase=keys["ssh"]["passphrase"],
687
+ private_key=keys["ssh"]["private_key"],
688
+ )
689
+ login_password = KeyLoginPassword(
690
+ login=keys["login_password"]["login"],
691
+ password=keys["login_password"]["password"],
692
+ )
693
+ del keys["ssh"]
694
+ del keys["login_password"]
695
+ return cls(**keys, ssh=ssh, login_password=login_password)
696
+
697
+ def delete(self):
698
+ self.client.delete_project_key(self.project_id, self.id)
699
+
700
+
701
+ @dataclass
702
+ class Repository:
703
+ id: int
704
+ name: str
705
+ project_id: int
706
+ git_url: str
707
+ git_branch: str
708
+ ssh_key_id: int
709
+
710
+ client: SemaphoreUIClient
711
+
712
+ def delete(self):
713
+ self.client.delete_project_repository(self.project_id, self.id)
714
+
715
+
716
+ @dataclass
717
+ class Secret:
718
+ id: int
719
+ name: str
720
+ type: str
721
+
722
+
723
+ @dataclass
724
+ class Environment:
725
+ id: int
726
+ name: str
727
+ project_id: int
728
+ password: str
729
+ json: str
730
+ env: str
731
+ secrets: typing.List["Secret"]
732
+
733
+ client: SemaphoreUIClient
734
+
735
+ def delete(self):
736
+ self.client.delete_project_environment(self.project_id, self.id)
737
+
738
+
739
+ @dataclass
740
+ class View:
741
+ id: int
742
+ title: str
743
+ position: int
744
+ project_id: int
745
+
746
+ client: SemaphoreUIClient
747
+
748
+ def delete(self):
749
+ self.client.delete_project_view(self.project_id, self.id)
750
+
751
+
752
+ @dataclass
753
+ class Inventory:
754
+ id: int
755
+ name: str
756
+ project_id: int
757
+ inventory: str
758
+ ssh_key_id: int
759
+ become_key_id: int
760
+ type: str
761
+
762
+ holder_id: int
763
+ repository_id: int
764
+
765
+ client: SemaphoreUIClient
766
+
767
+ def delete(self):
768
+ self.client.delete_project_inventory(self.project_id, self.id)
769
+
770
+
771
+ @dataclass
772
+ class Template:
773
+ id: int
774
+ project_id: int
775
+ repository_id: int
776
+ inventory_id: int
777
+ environment_id: int
778
+ view_id: int
779
+ name: str
780
+ playbook: str
781
+ arguments: str
782
+ description: str
783
+ allow_override_args_in_task: bool
784
+ suppress_success_alerts: bool
785
+ app: str
786
+ survey_vars: typing.List[typing.Dict[str, typing.Any]]
787
+ type: str
788
+ start_version: str
789
+ build_template_id: int
790
+ autorun: bool
791
+ vault_key_id: int
792
+ last_task: int
793
+ tasks: int
794
+
795
+
796
+ client: SemaphoreUIClient
797
+
798
+ def delete(self):
799
+ self.client.delete_project_template(self.project_id, self.id)
@@ -0,0 +1,20 @@
1
+ Metadata-Version: 2.4
2
+ Name: semaphoreui-client
3
+ Version: 0.1.0
4
+ Summary: An api client for interacting with Semaphore UI
5
+ Project-URL: Documentation, https://github.com/Paul Hummer/semaphoreui-client#readme
6
+ Project-URL: Issues, https://github.com/Paul Hummer/semaphoreui-client/issues
7
+ Project-URL: Source, https://github.com/Paul Hummer/semaphoreui-client
8
+ Author-email: Paul Hummer <paul@eventuallyanyway.com>
9
+ License-Expression: MIT
10
+ Classifier: Development Status :: 4 - Beta
11
+ Classifier: Programming Language :: Python
12
+ Classifier: Programming Language :: Python :: 3.9
13
+ Classifier: Programming Language :: Python :: 3.10
14
+ Classifier: Programming Language :: Python :: 3.11
15
+ Classifier: Programming Language :: Python :: 3.12
16
+ Classifier: Programming Language :: Python :: Implementation :: CPython
17
+ Classifier: Programming Language :: Python :: Implementation :: PyPy
18
+ Requires-Python: >=3.9
19
+ Requires-Dist: dataclasses-json>=0.6.7
20
+ Requires-Dist: requests>=2.32.3
@@ -0,0 +1,7 @@
1
+ semaphoreui_client/__about__.py,sha256=Pru0BlFBASFCFo7McHdohtKkUtgMPDwbGfyUZlE2_Vw,21
2
+ semaphoreui_client/__about__.py.backup,sha256=Pru0BlFBASFCFo7McHdohtKkUtgMPDwbGfyUZlE2_Vw,21
3
+ semaphoreui_client/__init__.py,sha256=r2j1tTgwFzp3AKAktr8izDIXllRf-Y0SdHAjInYDTP0,55
4
+ semaphoreui_client/client.py,sha256=dTR1ExrXwGOtPXTqmQZx5iia7uZ8zlDAkFZC_5t-3Bo,24280
5
+ semaphoreui_client-0.1.0.dist-info/METADATA,sha256=HgH0R8iNzgUhehXqm3xX3cLanj_ZHypl5J34IEq4TBE,955
6
+ semaphoreui_client-0.1.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
7
+ semaphoreui_client-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.27.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any