orchestrator-core 4.0.0rc4__py3-none-any.whl → 4.0.1__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.
orchestrator/__init__.py CHANGED
@@ -13,7 +13,7 @@
13
13
 
14
14
  """This is the orchestrator workflow engine."""
15
15
 
16
- __version__ = "4.0.0rc4"
16
+ __version__ = "4.0.1"
17
17
 
18
18
  from orchestrator.app import OrchestratorCore
19
19
  from orchestrator.settings import app_settings
@@ -163,6 +163,7 @@ def subscriptions_search(
163
163
  @router.get(
164
164
  "/workflows/{subscription_id}",
165
165
  response_model=SubscriptionWorkflowListsSchema,
166
+ response_model_by_alias=True,
166
167
  response_model_exclude_none=True,
167
168
  deprecated=True,
168
169
  description="This endpoint is deprecated and will be removed in a future release. Please use the GraphQL query",
@@ -24,6 +24,19 @@ from pydantic_forms.types import UUIDstr
24
24
  logger = structlog.get_logger(__name__)
25
25
 
26
26
 
27
+ def has_table_column(table_name: str, column_name: str, conn: sa.engine.Connection) -> bool:
28
+ """Checks if the specified column exists in a given table.
29
+
30
+ :param table_name: Name of the database table
31
+ :param column_name: Name of the column to check
32
+ :param conn: SQLAlchemy database Connection
33
+ :return: True if column exists, False otherwise
34
+ """
35
+ inspector = sa.inspect(conn.engine)
36
+ columns = inspector.get_columns(table_name)
37
+ return any(col["name"] == column_name for col in columns)
38
+
39
+
27
40
  def get_resource_type_id_by_name(conn: sa.engine.Connection, name: str) -> UUID:
28
41
  result = conn.execute(
29
42
  sa.text("SELECT resource_type_id FROM resource_types WHERE resource_types.resource_type=:name"), {"name": name}
@@ -79,8 +92,9 @@ def insert_resource_type(conn: sa.engine.Connection, resource_type: str, descrip
79
92
  """Create a new resource types."""
80
93
  conn.execute(
81
94
  sa.text(
82
- """INSERT INTO resource_types (resource_type, description) VALUES
83
- (:resource_type, :description) ON CONFLICT DO NOTHING;"""
95
+ """INSERT INTO resource_types (resource_type, description)
96
+ VALUES (:resource_type, :description)
97
+ ON CONFLICT DO NOTHING;"""
84
98
  ),
85
99
  {
86
100
  "resource_type": resource_type,
@@ -144,27 +158,41 @@ def create_workflow(conn: sa.engine.Connection, workflow: dict) -> None:
144
158
  if not workflow.get("is_task", False):
145
159
  workflow["is_task"] = False
146
160
 
147
- conn.execute(
148
- sa.text(
149
- """
161
+ if has_table_column(table_name="workflows", column_name="is_task", conn=conn):
162
+ query = """
150
163
  WITH new_workflow AS (
151
- INSERT INTO workflows(name, target, is_task, description)
152
- VALUES (:name, :target, :is_task, :description)
153
- ON CONFLICT DO NOTHING
154
- RETURNING workflow_id)
164
+ INSERT INTO workflows (name, target, is_task, description)
165
+ VALUES (:name, :target, :is_task, :description)
166
+ ON CONFLICT DO NOTHING
167
+ RETURNING workflow_id)
155
168
  INSERT
156
169
  INTO products_workflows (product_id, workflow_id)
157
- SELECT
158
- p.product_id,
159
- nw.workflow_id
170
+ SELECT p.product_id,
171
+ nw.workflow_id
160
172
  FROM products AS p
161
- CROSS JOIN new_workflow AS nw
162
- WHERE p.product_type = :product_type
163
- ON CONFLICT DO NOTHING
164
- """
165
- ),
166
- workflow,
167
- )
173
+ CROSS JOIN new_workflow AS nw
174
+ WHERE p.product_type = :product_type
175
+ ON CONFLICT DO NOTHING \
176
+ """
177
+ else:
178
+ # Remove is_task from workflow dict and insert SQL
179
+ workflow = {k: v for k, v in workflow.items() if k != "is_task"}
180
+ query = """
181
+ WITH new_workflow AS (
182
+ INSERT INTO workflows (name, target, description)
183
+ VALUES (:name, :target, :description)
184
+ ON CONFLICT DO NOTHING
185
+ RETURNING workflow_id)
186
+ INSERT
187
+ INTO products_workflows (product_id, workflow_id)
188
+ SELECT p.product_id, nw.workflow_id
189
+ FROM products AS p
190
+ CROSS JOIN new_workflow AS nw
191
+ WHERE p.product_type = :product_type
192
+ ON CONFLICT DO NOTHING \
193
+ """
194
+
195
+ conn.execute(sa.text(query), workflow)
168
196
 
169
197
 
170
198
  def create_task(conn: sa.engine.Connection, task: dict) -> None:
@@ -183,18 +211,22 @@ def create_task(conn: sa.engine.Connection, task: dict) -> None:
183
211
  }
184
212
  >>> create_workflow(conn, task)
185
213
  """
186
-
187
- conn.execute(
188
- sa.text(
189
- """
214
+ if has_table_column(table_name="workflows", column_name="is_task", conn=conn):
215
+ query = """
190
216
  INSERT INTO workflows(name, target, is_task, description)
191
- VALUES (:name, 'SYSTEM', TRUE, :description)
192
- ON CONFLICT DO NOTHING
193
- RETURNING workflow_id
194
- """
195
- ),
196
- task,
197
- )
217
+ VALUES (:name, 'SYSTEM', TRUE, :description)
218
+ ON CONFLICT DO NOTHING
219
+ RETURNING workflow_id \
220
+ """
221
+ else:
222
+ query = """
223
+ INSERT INTO workflows(name, target, description)
224
+ VALUES (:name, 'SYSTEM', :description)
225
+ ON CONFLICT DO NOTHING
226
+ RETURNING workflow_id
227
+ """
228
+
229
+ conn.execute(sa.text(query), task)
198
230
 
199
231
 
200
232
  def create_workflows(conn: sa.engine.Connection, new: dict) -> None:
@@ -222,26 +254,40 @@ def create_workflows(conn: sa.engine.Connection, new: dict) -> None:
222
254
  if not workflow.get("is_task", False):
223
255
  workflow["is_task"] = False
224
256
 
225
- conn.execute(
226
- sa.text(
227
- """
228
- WITH new_workflow AS (
229
- INSERT INTO workflows(workflow_id, name, target, is_task, description)
230
- VALUES (:workflow_id, :name, :target, :is_task, :description)
231
- RETURNING workflow_id)
232
- INSERT
233
- INTO products_workflows (product_id, workflow_id)
234
- SELECT
235
- p.product_id,
236
- nw.workflow_id
237
- FROM products AS p
238
- CROSS JOIN new_workflow AS nw
239
- WHERE p.tag = :tag
240
- AND p.name LIKE :search_phrase
241
- """
242
- ),
243
- workflow,
244
- )
257
+ if has_table_column(table_name="workflows", column_name="is_task", conn=conn):
258
+ query = """
259
+ WITH new_workflow AS (
260
+ INSERT INTO workflows (workflow_id, name, target, is_task, description)
261
+ VALUES (:workflow_id, :name, :target, :is_task, :description)
262
+ RETURNING workflow_id)
263
+ INSERT
264
+ INTO products_workflows (product_id, workflow_id)
265
+ SELECT p.product_id,
266
+ nw.workflow_id
267
+ FROM products AS p
268
+ CROSS JOIN new_workflow AS nw
269
+ WHERE p.tag = :tag
270
+ AND p.name LIKE :search_phrase
271
+ """
272
+ else:
273
+ # Remove is_task from workflow dict and insert SQL
274
+ workflow = {k: v for k, v in workflow.items() if k != "is_task"}
275
+ query = """
276
+ WITH new_workflow AS (
277
+ INSERT INTO workflows (workflow_id, name, target, description)
278
+ VALUES (:workflow_id, :name, :target, :description)
279
+ RETURNING workflow_id)
280
+ INSERT
281
+ INTO products_workflows (product_id, workflow_id)
282
+ SELECT p.product_id,
283
+ nw.workflow_id
284
+ FROM products AS p
285
+ CROSS JOIN new_workflow AS nw
286
+ WHERE p.tag = :tag
287
+ AND p.name LIKE :search_phrase
288
+ """
289
+
290
+ conn.execute(sa.text(query), workflow)
245
291
 
246
292
 
247
293
  def create_fixed_inputs(conn: sa.engine.Connection, product_id: UUID | UUIDstr, new: dict) -> dict[str, str]:
@@ -272,13 +318,13 @@ def create_fixed_inputs(conn: sa.engine.Connection, product_id: UUID | UUIDstr,
272
318
  """
273
319
  insert_fixed_input_with_id = sa.text(
274
320
  """INSERT INTO fixed_inputs (fixed_input_id, name, value, created_at, product_id)
275
- VALUES (:fixed_input_id, :key, :value, now(), :product_id)
276
- ON CONFLICT DO NOTHING;"""
321
+ VALUES (:fixed_input_id, :key, :value, now(), :product_id)
322
+ ON CONFLICT DO NOTHING;"""
277
323
  )
278
324
  insert_fixed_input_without_id = sa.text(
279
325
  """INSERT INTO fixed_inputs (name, value, created_at, product_id)
280
- VALUES (:key, :value, now(), :product_id)
281
- ON CONFLICT DO NOTHING;"""
326
+ VALUES (:key, :value, now(), :product_id)
327
+ ON CONFLICT DO NOTHING;"""
282
328
  )
283
329
 
284
330
  uuids = {}
@@ -339,7 +385,7 @@ def create_products(conn: sa.engine.Connection, new: dict) -> dict[str, UUIDstr]
339
385
  INSERT INTO products (product_id, name, description, product_type, tag, status, created_at)
340
386
  VALUES (:product_id, :name, :description, :product_type, :tag, :status, now())
341
387
  ON CONFLICT DO NOTHING;
342
- """
388
+ """
343
389
  ),
344
390
  product,
345
391
  )
@@ -390,7 +436,7 @@ def create_product_blocks(conn: sa.engine.Connection, new: dict) -> dict[str, UU
390
436
  INSERT INTO product_blocks (product_block_id, name, description, tag, status, created_at)
391
437
  VALUES (:product_block_id, :name, :description, :tag, :status, now())
392
438
  ON CONFLICT DO NOTHING;
393
- """
439
+ """
394
440
  ),
395
441
  product_block,
396
442
  )
@@ -455,13 +501,13 @@ def create_resource_types_for_product_blocks(conn: sa.engine.Connection, new: di
455
501
  """
456
502
  insert_resource_type_with_id = sa.text(
457
503
  """INSERT INTO resource_types (resource_type_id, resource_type, description)
458
- VALUES (:resource_type_id, :resource_type, :description)
459
- ON CONFLICT DO NOTHING;"""
504
+ VALUES (:resource_type_id, :resource_type, :description)
505
+ ON CONFLICT DO NOTHING;"""
460
506
  )
461
507
  insert_resource_type_without_id = sa.text(
462
508
  """INSERT INTO resource_types (resource_type, description)
463
- VALUES (:resource_type, :description)
464
- ON CONFLICT DO NOTHING;"""
509
+ VALUES (:resource_type, :description)
510
+ ON CONFLICT DO NOTHING;"""
465
511
  )
466
512
 
467
513
  resource_type_ids = []
@@ -485,25 +531,20 @@ def create_resource_types_for_product_blocks(conn: sa.engine.Connection, new: di
485
531
  conn.execute(
486
532
  sa.text(
487
533
  """
488
- WITH resource_type_ids AS (
489
- SELECT resource_types.resource_type_id
490
- FROM resource_types
491
- WHERE resource_types.resource_type = ANY(:new_resource_types)
492
- ), service_attach_point AS (
493
- SELECT product_blocks.product_block_id
494
- FROM product_blocks
495
- WHERE product_blocks.name = :product_block_name
496
- )
534
+ WITH resource_type_ids AS (SELECT resource_types.resource_type_id
535
+ FROM resource_types
536
+ WHERE resource_types.resource_type = ANY (:new_resource_types)),
537
+ service_attach_point AS (SELECT product_blocks.product_block_id
538
+ FROM product_blocks
539
+ WHERE product_blocks.name = :product_block_name)
497
540
 
498
- INSERT INTO
499
- product_block_resource_types (product_block_id, resource_type_id)
500
- SELECT
501
- service_attach_point.product_block_id,
502
- resource_type_ids.resource_type_id
503
- FROM
504
- service_attach_point
505
- CROSS JOIN
506
- resource_type_ids
541
+ INSERT
542
+ INTO product_block_resource_types (product_block_id, resource_type_id)
543
+ SELECT service_attach_point.product_block_id,
544
+ resource_type_ids.resource_type_id
545
+ FROM service_attach_point
546
+ CROSS JOIN
547
+ resource_type_ids
507
548
  """
508
549
  ),
509
550
  {
@@ -666,16 +707,17 @@ def add_products_to_workflow_by_product_tag(
666
707
  conn.execute(
667
708
  sa.text(
668
709
  """
669
- WITH workflow AS (
670
- SELECT workflow_id FROM workflows WHERE name=:workflow_name
671
- )
672
- INSERT INTO products_workflows (product_id, workflow_id)
673
- SELECT
674
- p.product_id,
675
- nw.workflow_id
676
- FROM products AS p
677
- CROSS JOIN workflow AS nw
678
- WHERE p.tag=:product_tag AND name LIKE :product_name_like
710
+ WITH workflow AS (SELECT workflow_id
711
+ FROM workflows
712
+ WHERE name = :workflow_name)
713
+ INSERT
714
+ INTO products_workflows (product_id, workflow_id)
715
+ SELECT p.product_id,
716
+ nw.workflow_id
717
+ FROM products AS p
718
+ CROSS JOIN workflow AS nw
719
+ WHERE p.tag = :product_tag
720
+ AND name LIKE :product_name_like
679
721
  """
680
722
  ),
681
723
  {
@@ -708,13 +750,15 @@ def remove_products_from_workflow_by_product_tag(
708
750
  conn.execute(
709
751
  sa.text(
710
752
  """
711
- DELETE FROM products_workflows
712
- WHERE workflow_id = (
713
- SELECT workflow_id FROM workflows where name=:workflow_name
714
- ) AND product_id IN (
715
- SELECT product_id FROM products
716
- WHERE tag=:product_tag AND name LIKE :product_name_like
717
- )
753
+ DELETE
754
+ FROM products_workflows
755
+ WHERE workflow_id = (SELECT workflow_id
756
+ FROM workflows
757
+ where name = :workflow_name)
758
+ AND product_id IN (SELECT product_id
759
+ FROM products
760
+ WHERE tag = :product_tag
761
+ AND name LIKE :product_name_like)
718
762
  """
719
763
  ),
720
764
  {
@@ -746,8 +790,8 @@ def add_product_block_relation_between_products_by_id(
746
790
  conn.execute(
747
791
  sa.text(
748
792
  """
749
- INSERT INTO product_block_relations (in_use_by_id, depends_on_id)
750
- VALUES (:in_use_by_id, :depends_on_id)
793
+ INSERT INTO product_block_relations (in_use_by_id, depends_on_id)
794
+ VALUES (:in_use_by_id, :depends_on_id)
751
795
  """
752
796
  ),
753
797
  {
@@ -778,8 +822,10 @@ def remove_product_block_relation_between_products_by_id(
778
822
  conn.execute(
779
823
  sa.text(
780
824
  """
781
- DELETE FROM product_block_relations
782
- WHERE in_use_by_id=:in_use_by_id AND depends_on_id=:depends_on_id
825
+ DELETE
826
+ FROM product_block_relations
827
+ WHERE in_use_by_id = :in_use_by_id
828
+ AND depends_on_id = :depends_on_id
783
829
  """
784
830
  ),
785
831
  {
@@ -829,11 +875,13 @@ def delete_resource_types_from_product_blocks(conn: sa.engine.Connection, delete
829
875
  for product_block_name, resource_types in delete.items():
830
876
  conn.execute(
831
877
  sa.text(
832
- """DELETE FROM product_block_resource_types
833
- USING resource_types
834
- WHERE product_block_id = (SELECT product_block_id FROM product_blocks WHERE name=:product_block_name) AND
835
- resource_types.resource_type_id = product_block_resource_types.resource_type_id AND
836
- resource_types.resource_type = ANY(:obsolete_resource_types)"""
878
+ """DELETE
879
+ FROM product_block_resource_types
880
+ USING resource_types
881
+ WHERE
882
+ product_block_id = (SELECT product_block_id FROM product_blocks WHERE name = :product_block_name)
883
+ AND resource_types.resource_type_id = product_block_resource_types.resource_type_id
884
+ AND resource_types.resource_type = ANY (:obsolete_resource_types)"""
837
885
  ),
838
886
  {
839
887
  "product_block_name": product_block_name,
@@ -855,10 +903,11 @@ def delete_resource_types(conn: sa.engine.Connection, delete: Iterable) -> None:
855
903
  """
856
904
  conn.execute(
857
905
  sa.text(
858
- """DELETE FROM product_block_resource_types
859
- USING resource_types
906
+ """DELETE
907
+ FROM product_block_resource_types
908
+ USING resource_types
860
909
  WHERE resource_types.resource_type_id = product_block_resource_types.resource_type_id
861
- AND resource_types.resource_type = ANY(:obsolete)"""
910
+ AND resource_types.resource_type = ANY (:obsolete)"""
862
911
  ),
863
912
  {"obsolete": tuple(delete)},
864
913
  )
@@ -866,7 +915,14 @@ def delete_resource_types(conn: sa.engine.Connection, delete: Iterable) -> None:
866
915
 
867
916
 
868
917
  def delete_products_by_tag(conn: sa.engine.Connection, name: str) -> None:
869
- conn.execute(sa.text("""DELETE FROM products p WHERE p.name=:name"""), {"name": name})
918
+ conn.execute(
919
+ sa.text(
920
+ """DELETE
921
+ FROM products p
922
+ WHERE p.name = :name"""
923
+ ),
924
+ {"name": name},
925
+ )
870
926
 
871
927
 
872
928
  def delete_product(conn: sa.engine.Connection, name: str) -> None:
@@ -884,16 +940,14 @@ def delete_product(conn: sa.engine.Connection, name: str) -> None:
884
940
  sa.text(
885
941
  """
886
942
  WITH deleted_p AS (
887
- DELETE FROM products WHERE name=:name
888
- RETURNING product_id
889
- ),
890
- deleted_p_pb AS (
891
- DELETE FROM product_product_blocks WHERE product_id IN (SELECT product_id FROM deleted_p)
892
- ),
893
- deleted_pb_rt AS (
894
- DELETE FROM products_workflows WHERE product_id IN (SELECT product_id FROM deleted_p)
895
- )
896
- SELECT * from deleted_p;
943
+ DELETE FROM products WHERE name = :name
944
+ RETURNING product_id),
945
+ deleted_p_pb AS (
946
+ DELETE FROM product_product_blocks WHERE product_id IN (SELECT product_id FROM deleted_p)),
947
+ deleted_pb_rt AS (
948
+ DELETE FROM products_workflows WHERE product_id IN (SELECT product_id FROM deleted_p))
949
+ SELECT *
950
+ from deleted_p;
897
951
  """
898
952
  ),
899
953
  {"name": name},
@@ -915,16 +969,14 @@ def delete_product_block(conn: sa.engine.Connection, name: str) -> None:
915
969
  sa.text(
916
970
  """
917
971
  WITH deleted_pb AS (
918
- DELETE FROM product_blocks WHERE name=:name
919
- RETURNING product_block_id
920
- ),
921
- deleted_p_pb AS (
922
- DELETE FROM product_product_blocks WHERE product_block_id IN (SELECT product_block_id FROM deleted_pb)
923
- ),
924
- deleted_pb_rt AS (
925
- DELETE FROM product_block_resource_types WHERE product_block_id IN (SELECT product_block_id FROM deleted_pb)
926
- )
927
- SELECT * from deleted_pb;
972
+ DELETE FROM product_blocks WHERE name = :name
973
+ RETURNING product_block_id),
974
+ deleted_p_pb AS (
975
+ DELETE FROM product_product_blocks WHERE product_block_id IN (SELECT product_block_id FROM deleted_pb)),
976
+ deleted_pb_rt AS (
977
+ DELETE FROM product_block_resource_types WHERE product_block_id IN (SELECT product_block_id FROM deleted_pb))
978
+ SELECT *
979
+ from deleted_pb;
928
980
  """
929
981
  ),
930
982
  {"name": name},
@@ -948,9 +1000,9 @@ def delete_workflow(conn: sa.engine.Connection, name: str) -> None:
948
1000
  conn.execute(
949
1001
  sa.text(
950
1002
  """
951
- DELETE
952
- FROM workflows
953
- WHERE name = :name;
1003
+ DELETE
1004
+ FROM workflows
1005
+ WHERE name = :name;
954
1006
  """
955
1007
  ),
956
1008
  {"name": name},
@@ -972,13 +1024,12 @@ def delete_resource_type(conn: sa.engine.Connection, resource_type: str) -> None
972
1024
  sa.text(
973
1025
  """
974
1026
  WITH deleted_pb AS (
975
- DELETE FROM resource_types WHERE resource_type=:resource_type
976
- RETURNING resource_type_id
977
- ),
978
- deleted_pb_rt AS (
979
- DELETE FROM product_block_resource_types WHERE resource_type_id IN (SELECT resource_type_id FROM deleted_pb)
980
- )
981
- SELECT * from deleted_pb;
1027
+ DELETE FROM resource_types WHERE resource_type = :resource_type
1028
+ RETURNING resource_type_id),
1029
+ deleted_pb_rt AS (
1030
+ DELETE FROM product_block_resource_types WHERE resource_type_id IN (SELECT resource_type_id FROM deleted_pb))
1031
+ SELECT *
1032
+ from deleted_pb;
982
1033
  """
983
1034
  ),
984
1035
  {"resource_type": resource_type},
@@ -1058,19 +1109,20 @@ def convert_resource_type_relations_to_instance_relations(
1058
1109
  sa.text(
1059
1110
  """
1060
1111
  INSERT INTO subscription_instance_relations (in_use_by_id, depends_on_id, order_id, domain_model_attr)
1061
- WITH dependencies AS (
1062
- SELECT siv.value AS subscription_id, siv.subscription_instance_id AS in_use_by_instance_id, si.product_block_id
1063
- FROM subscription_instance_values AS siv
1064
- LEFT JOIN subscription_instances AS si on siv.subscription_instance_id = si.subscription_instance_id
1065
- WHERE siv.resource_type_id=:resource_type_id
1066
- )
1067
- SELECT
1068
- in_use_by_instance_id AS in_use_by_id,
1069
- sii.subscription_instance_id AS depends_on_id,
1070
- (row_number() OVER (PARTITION BY in_use_by_instance_id) - 1) AS order_id,
1071
- :domain_model_attr AS domain_model_attr
1112
+ WITH dependencies AS (SELECT siv.value AS subscription_id,
1113
+ siv.subscription_instance_id AS in_use_by_instance_id,
1114
+ si.product_block_id
1115
+ FROM subscription_instance_values AS siv
1116
+ LEFT JOIN subscription_instances AS si
1117
+ on siv.subscription_instance_id = si.subscription_instance_id
1118
+ WHERE siv.resource_type_id = :resource_type_id)
1119
+ SELECT in_use_by_instance_id AS in_use_by_id,
1120
+ sii.subscription_instance_id AS depends_on_id,
1121
+ (row_number() OVER (PARTITION BY in_use_by_instance_id) - 1) AS order_id,
1122
+ :domain_model_attr AS domain_model_attr
1072
1123
  FROM subscription_instances AS sii
1073
- INNER JOIN dependencies AS dep ON sii.subscription_id=uuid(dep.subscription_id) ON CONFLICT DO NOTHING
1124
+ INNER JOIN dependencies AS dep ON sii.subscription_id = uuid(dep.subscription_id)
1125
+ ON CONFLICT DO NOTHING
1074
1126
  """
1075
1127
  ),
1076
1128
  {
@@ -1083,8 +1135,9 @@ def convert_resource_type_relations_to_instance_relations(
1083
1135
  conn.execute(
1084
1136
  sa.text(
1085
1137
  """
1086
- DELETE FROM subscription_instance_values
1087
- WHERE resource_type_id=:resource_type_id
1138
+ DELETE
1139
+ FROM subscription_instance_values
1140
+ WHERE resource_type_id = :resource_type_id
1088
1141
  """
1089
1142
  ),
1090
1143
  {"resource_type_id": resource_type_id},
@@ -1114,14 +1167,15 @@ def convert_instance_relations_to_resource_type_relations_by_domain_model_attr(
1114
1167
  conn.execute(
1115
1168
  sa.text(
1116
1169
  """
1117
- INSERT INTO subscription_instance_values (subscription_instance_id, resource_type_id, value)
1118
- WITH instance_relations AS (
1119
- SELECT in_use_by_id, depends_on_id FROM subscription_instance_relations
1120
- WHERE domain_model_attr=:domain_model_attr
1121
- )
1122
- SELECT ir.in_use_by_id AS subscription_instance_id, :resource_type_id AS resource_type_id, si.subscription_id AS value
1123
- from subscription_instances as si
1124
- inner join instance_relations as ir on si.subscription_instance_id=ir.depends_on_id
1170
+ INSERT INTO subscription_instance_values (subscription_instance_id, resource_type_id, value)
1171
+ WITH instance_relations AS (SELECT in_use_by_id, depends_on_id
1172
+ FROM subscription_instance_relations
1173
+ WHERE domain_model_attr = :domain_model_attr)
1174
+ SELECT ir.in_use_by_id AS subscription_instance_id,
1175
+ :resource_type_id AS resource_type_id,
1176
+ si.subscription_id AS value
1177
+ from subscription_instances as si
1178
+ inner join instance_relations as ir on si.subscription_instance_id = ir.depends_on_id
1125
1179
  """
1126
1180
  ),
1127
1181
  {
@@ -1144,10 +1198,12 @@ def backfill_resource_type_with_default(
1144
1198
  sa.text(
1145
1199
  """
1146
1200
  INSERT INTO subscription_instance_values (subscription_instance_id, resource_type_id, value)
1147
- SELECT si.subscription_instance_id AS subscription_instance_id, :resource_type_id AS resource_type_id, :value AS value
1201
+ SELECT si.subscription_instance_id AS subscription_instance_id,
1202
+ :resource_type_id AS resource_type_id,
1203
+ :value AS value
1148
1204
  FROM subscription_instances AS si
1149
- JOIN product_blocks pb on si.product_block_id = pb.product_block_id
1150
- WHERE pb.name = :product_block_name;
1205
+ JOIN product_blocks pb on si.product_block_id = pb.product_block_id
1206
+ WHERE pb.name = :product_block_name;
1151
1207
  """
1152
1208
  ),
1153
1209
  {
@@ -1162,6 +1218,10 @@ def remove_resource_type_from_subscription_instance(conn: sa.engine.Connection,
1162
1218
  resource_type_id = get_resource_type_id_by_name(conn, resource_type_name)
1163
1219
 
1164
1220
  conn.execute(
1165
- sa.text("""DELETE FROM subscription_instance_values WHERE resource_type_id=:resource_type_id"""),
1221
+ sa.text(
1222
+ """DELETE
1223
+ FROM subscription_instance_values
1224
+ WHERE resource_type_id = :resource_type_id"""
1225
+ ),
1166
1226
  {"resource_type_id": resource_type_id},
1167
1227
  )
@@ -6,8 +6,7 @@ file_template = %%(year)d-%%(month).2d-%%(day).2d_%%(rev)s_%%(slug)s
6
6
 
7
7
  # set to 'true' to run the environment during
8
8
  # the 'revision' command, regardless of autogenerate
9
- # revision_environment = false
10
- script_location = {{ migrations_dir }}
9
+ script_location = %(here)s/{{ migrations_dir }}
11
10
  version_locations = %(here)s/{{ migrations_dir }}/versions/schema
12
11
  # Logging configuration
13
12
  [loggers]
@@ -1,9 +1,7 @@
1
- import logging
2
- import os
1
+ import structlog
3
2
  from alembic import context
4
3
  from sqlalchemy import engine_from_config, pool
5
4
 
6
- import orchestrator
7
5
  from orchestrator.db.database import BaseModel
8
6
  from orchestrator.settings import app_settings
9
7
 
@@ -11,11 +9,10 @@ from orchestrator.settings import app_settings
11
9
  # access to the values within the .ini file in use.
12
10
  config = context.config
13
11
 
14
- # Interpret the config file for Python logging.
15
- # This line sets up loggers basically.
16
- logger = logging.getLogger("alembic.env")
12
+ # Setup logging
13
+ logger = structlog.get_logger()
17
14
 
18
- config.set_main_option("sqlalchemy.url", app_settings.DATABASE_URI)
15
+ config.set_main_option("sqlalchemy.url", str(app_settings.DATABASE_URI))
19
16
 
20
17
  # add your model's MetaData object here
21
18
  # for 'autogenerate' support
@@ -15,7 +15,7 @@ from datetime import datetime
15
15
  from typing import Any
16
16
  from uuid import UUID
17
17
 
18
- from pydantic import ConfigDict
18
+ from pydantic import ConfigDict, Field
19
19
 
20
20
  from orchestrator.schemas.base import OrchestratorBaseModel
21
21
  from orchestrator.targets import Target
@@ -60,6 +60,7 @@ class SubscriptionWorkflowListsSchema(OrchestratorBaseModel):
60
60
  modify: list[WorkflowListItemSchema]
61
61
  terminate: list[WorkflowListItemSchema]
62
62
  system: list[WorkflowListItemSchema]
63
+ validate_: list[WorkflowListItemSchema] = Field(default_factory=list, alias="validate")
63
64
 
64
65
 
65
66
  class WorkflowPatchSchema(OrchestratorBaseModel):
@@ -72,8 +72,8 @@ def _celery_start_process(
72
72
  def _celery_resume_process(
73
73
  process: ProcessTable,
74
74
  *,
75
- user_inputs: list[State] | None,
76
- user: str | None,
75
+ user_inputs: list[State] | None = None,
76
+ user: str | None = None,
77
77
  **kwargs: Any,
78
78
  ) -> UUID:
79
79
  """Client side call of Celery."""
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: orchestrator-core
3
- Version: 4.0.0rc4
3
+ Version: 4.0.1
4
4
  Summary: This is the orchestrator workflow engine.
5
5
  Requires-Python: >=3.11,<3.14
6
6
  Classifier: Intended Audience :: Information Technology
@@ -49,17 +49,17 @@ Requires-Dist: pytz==2025.2
49
49
  Requires-Dist: redis==5.1.1
50
50
  Requires-Dist: schedule==1.1.0
51
51
  Requires-Dist: semver==3.0.4
52
- Requires-Dist: sentry-sdk[fastapi]~=2.27.0
53
- Requires-Dist: SQLAlchemy==2.0.40
52
+ Requires-Dist: sentry-sdk[fastapi]~=2.28.0
53
+ Requires-Dist: SQLAlchemy==2.0.41
54
54
  Requires-Dist: SQLAlchemy-Utils==0.41.2
55
55
  Requires-Dist: structlog
56
- Requires-Dist: typer==0.15.3
56
+ Requires-Dist: typer==0.15.4
57
57
  Requires-Dist: uvicorn[standard]~=0.34.0
58
58
  Requires-Dist: nwa-stdlib~=1.9.0
59
59
  Requires-Dist: oauth2-lib~=2.4.0
60
60
  Requires-Dist: tabulate==0.9.0
61
61
  Requires-Dist: strawberry-graphql>=0.246.2
62
- Requires-Dist: pydantic-forms>=1.4.0, <=2.0.0
62
+ Requires-Dist: pydantic-forms>=1.4.0, <=2.1.0
63
63
  Requires-Dist: celery~=5.5.1 ; extra == "celery"
64
64
  Requires-Dist: toml ; extra == "dev"
65
65
  Requires-Dist: bumpversion ; extra == "dev"
@@ -1,4 +1,4 @@
1
- orchestrator/__init__.py,sha256=4DxV-lt8lBVBK_FUrtqliQAVswqjM5XsXcx8oy7Yj0c,1066
1
+ orchestrator/__init__.py,sha256=amioWXwUtHG21kSVqsajhHV08ntganqtFHTU9Kukg48,1063
2
2
  orchestrator/app.py,sha256=7UrXKjBKNSEaSSXAd5ww_RdMFhFqE4yvfj8faS2MzAA,12089
3
3
  orchestrator/exception_handlers.py,sha256=UsW3dw8q0QQlNLcV359bIotah8DYjMsj2Ts1LfX4ClY,1268
4
4
  orchestrator/log_config.py,sha256=1tPRX5q65e57a6a_zEii_PFK8SzWT0mnA5w2sKg4hh8,1853
@@ -23,7 +23,7 @@ orchestrator/api/api_v1/endpoints/products.py,sha256=BfFtwu9dZXEQbtKxYj9icc73GKG
23
23
  orchestrator/api/api_v1/endpoints/resource_types.py,sha256=gGyuaDyOD0TAVoeFGaGmjDGnQ8eQQArOxKrrk4MaDzA,2145
24
24
  orchestrator/api/api_v1/endpoints/settings.py,sha256=orcwFqGiQ3Ala3mLm_27ChXPkUFoGUeGNaDZnEIk2Ak,5848
25
25
  orchestrator/api/api_v1/endpoints/subscription_customer_descriptions.py,sha256=1_6LtgQleoq3M6z_W-Qz__Bj3OFUweoPrUqHMwSH6AM,3288
26
- orchestrator/api/api_v1/endpoints/subscriptions.py,sha256=EwkWBztI9xSMPkol49SM5csECthyu7HC38AhuW7pWUE,8724
26
+ orchestrator/api/api_v1/endpoints/subscriptions.py,sha256=V-ebvjtFEKlALx8SKX42SiNPM-GAgSMWbuaimyktUQQ,8758
27
27
  orchestrator/api/api_v1/endpoints/translations.py,sha256=dIWh_fCnZZUxJoGiNeJ49DK_xpf75IpR_0EIMSvzIvY,963
28
28
  orchestrator/api/api_v1/endpoints/user.py,sha256=RyI32EXVu6I-IxWjz0XB5zQWzzLL60zKXLgLqLH02xU,1827
29
29
  orchestrator/api/api_v1/endpoints/workflows.py,sha256=_0vhGiQeu3-z16Zi0WmuDWBs8gmed6BzRNwYH_sF6AY,1977
@@ -210,10 +210,10 @@ orchestrator/metrics/subscriptions.py,sha256=vC1O8VmTq5oJxNrn5CU99Rf8cxzdyhc7tXb
210
210
  orchestrator/migrations/README,sha256=heMzebYwlGhnE8_4CWJ4LS74WoEZjBy-S-mIJRxAEKI,39
211
211
  orchestrator/migrations/alembic.ini,sha256=kMoADqhGeubU8xanILNaqm4oixLy9m4ngYtdGpZcc7I,873
212
212
  orchestrator/migrations/env.py,sha256=M_cPoAL2axuuup5fvMy8I_WTPHEw0RbPEHkhZ3QEGoE,3740
213
- orchestrator/migrations/helpers.py,sha256=xwi1Z-0MMZJ1Bk-HXkb6f_RU7BmO3ajK5a4qqO94elc,44068
213
+ orchestrator/migrations/helpers.py,sha256=OcdwDbox9P-Gx7eeSKgPI_qZco1QGCXgJQAbfwa3Nm8,47515
214
214
  orchestrator/migrations/script.py.mako,sha256=607Zrgp-Z-m9WGLt4wewN1QDOmHeifxcePUdADkSZyM,510
215
- orchestrator/migrations/templates/alembic.ini.j2,sha256=jA-QykVparwWSNt5XDP0Zk7epLOhK7D87Af-i2shJV4,905
216
- orchestrator/migrations/templates/env.py.j2,sha256=RfLAQItZ56Jlzwi6LJfBo92m1-th_bdfkFKD1mwTZIE,2821
215
+ orchestrator/migrations/templates/alembic.ini.j2,sha256=8v7UbKvOiWEbEKQa-Au3uONKUuYx6aflulYanZX6r2I,883
216
+ orchestrator/migrations/templates/env.py.j2,sha256=LIt0ildZTZvNEx3imhy4GNzfFi_rPZg-8H7rGgrBOP8,2717
217
217
  orchestrator/migrations/templates/helpers.py.j2,sha256=3MWNMICGrcQFObyBQefL-FPjoVKUgP0QIlbk4TdMZds,98
218
218
  orchestrator/migrations/versions/schema/2020-10-19_3323bcb934e7_fix_tsv_triggers.py,sha256=ufe6OFUELNpx6N2663bvdwgB4lP-v71fuMuJtx9CmJc,2698
219
219
  orchestrator/migrations/versions/schema/2020-10-19_a76b9185b334_add_generic_workflows_to_core.py,sha256=EHj87IXucruyB8KuxEWcc7JK1NIizZ5Jzmj-bzY0t1Y,1265
@@ -258,9 +258,9 @@ orchestrator/schemas/product_block.py,sha256=kCqvm6qadHpegMr9aWI_fYX-T7mS-5S-ldP
258
258
  orchestrator/schemas/resource_type.py,sha256=VDju4XywcDDLxdpbWU62RTvR9QF8x_GRrpTlN_NE8uI,1064
259
259
  orchestrator/schemas/subscription.py,sha256=-jXyHZIed9Xlia18ksSDyenblNN6Q2yM2FlGELyJ458,3423
260
260
  orchestrator/schemas/subscription_descriptions.py,sha256=Ft_jw1U0bf9Z0U8O4OWfLlcl0mXCVT_qYVagBP3GbIQ,1262
261
- orchestrator/schemas/workflow.py,sha256=gBpLXttgU3cSkVyEqr5ji4yBskl-n7QNmEerUr9UXt0,2003
261
+ orchestrator/schemas/workflow.py,sha256=VqQ9XfV4fVd6MjY0LRRQzWBJHmlPsAamWfTwDx1cZkg,2102
262
262
  orchestrator/services/__init__.py,sha256=GyHNfEFCGKQwRiN6rQmvSRH2iYX7npjMZn97n8XzmLU,571
263
- orchestrator/services/celery.py,sha256=ezw7IxkIZbmaRJt-9_Iwvn86TJV3Y3DTHI7Qjh0-r9s,5075
263
+ orchestrator/services/celery.py,sha256=SmAUsN755yE7cZ3og92qTvPPeRIpdEKlbaLih7o38h8,5089
264
264
  orchestrator/services/fixed_inputs.py,sha256=kyz7s2HLzyDulvcq-ZqefTw1om86COvyvTjz0_5CmgI,876
265
265
  orchestrator/services/input_state.py,sha256=HF7wl9fWdaAW8pdCCqbuYoKyNj8dY0g8Ff8vXis8z5A,2211
266
266
  orchestrator/services/process_broadcast_thread.py,sha256=D44YbjF8mRqGuznkRUV4SoRn1J0lfy_x1H508GnSVlU,4649
@@ -307,7 +307,7 @@ orchestrator/workflows/tasks/resume_workflows.py,sha256=MzJqlSXUvKStkT7NGzxZyRlf
307
307
  orchestrator/workflows/tasks/validate_product_type.py,sha256=paG-NAY1bdde3Adt8zItkcBKf5Pxw6f5ngGW6an6dYU,3192
308
308
  orchestrator/workflows/tasks/validate_products.py,sha256=GZJBoFF-WMphS7ghMs2-gqvV2iL1F0POhk0uSNt93n0,8510
309
309
  orchestrator/workflows/translations/en-GB.json,sha256=ST53HxkphFLTMjFHonykDBOZ7-P_KxksktZU3GbxLt0,846
310
- orchestrator_core-4.0.0rc4.dist-info/licenses/LICENSE,sha256=b-aA5OZQuuBATmLKo_mln8CQrDPPhg3ghLzjPjLn4Tg,11409
311
- orchestrator_core-4.0.0rc4.dist-info/WHEEL,sha256=G2gURzTEtmeR8nrdXUJfNiB3VYVxigPQ-bEQujpNiNs,82
312
- orchestrator_core-4.0.0rc4.dist-info/METADATA,sha256=I90LCMRMfzx83Wy3CsS1TkfSoxn6PMryPcjFj6WNaok,5073
313
- orchestrator_core-4.0.0rc4.dist-info/RECORD,,
310
+ orchestrator_core-4.0.1.dist-info/licenses/LICENSE,sha256=b-aA5OZQuuBATmLKo_mln8CQrDPPhg3ghLzjPjLn4Tg,11409
311
+ orchestrator_core-4.0.1.dist-info/WHEEL,sha256=G2gURzTEtmeR8nrdXUJfNiB3VYVxigPQ-bEQujpNiNs,82
312
+ orchestrator_core-4.0.1.dist-info/METADATA,sha256=hZAgEHN9fviU95h0Let76rdZJz9JRlpMZ_xhg9l8q0s,5070
313
+ orchestrator_core-4.0.1.dist-info/RECORD,,