iris-pex-embedded-python 4.0.0b7__tar.gz → 4.0.0b9__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.
- {iris_pex_embedded_python-4.0.0b7/src/iris_pex_embedded_python.egg-info → iris_pex_embedded_python-4.0.0b9}/PKG-INFO +1 -1
- {iris_pex_embedded_python-4.0.0b7 → iris_pex_embedded_python-4.0.0b9}/pyproject.toml +1 -1
- {iris_pex_embedded_python-4.0.0b7 → iris_pex_embedded_python-4.0.0b9}/src/iop/__init__.py +8 -0
- {iris_pex_embedded_python-4.0.0b7 → iris_pex_embedded_python-4.0.0b9}/src/iop/cli/main.py +137 -1
- {iris_pex_embedded_python-4.0.0b7 → iris_pex_embedded_python-4.0.0b9}/src/iop/cli/parser.py +32 -0
- {iris_pex_embedded_python-4.0.0b7 → iris_pex_embedded_python-4.0.0b9}/src/iop/cli/types.py +15 -0
- {iris_pex_embedded_python-4.0.0b7 → iris_pex_embedded_python-4.0.0b9}/src/iop/cls/IOP/Utils.cls +327 -0
- {iris_pex_embedded_python-4.0.0b7 → iris_pex_embedded_python-4.0.0b9}/src/iop/migration/utils.py +21 -0
- {iris_pex_embedded_python-4.0.0b7 → iris_pex_embedded_python-4.0.0b9}/src/iop/production/__init__.py +8 -0
- iris_pex_embedded_python-4.0.0b9/src/iop/production/actions.py +516 -0
- {iris_pex_embedded_python-4.0.0b7 → iris_pex_embedded_python-4.0.0b9}/src/iop/production/model.py +51 -2
- iris_pex_embedded_python-4.0.0b9/src/iop/production/planning.py +675 -0
- {iris_pex_embedded_python-4.0.0b7 → iris_pex_embedded_python-4.0.0b9}/src/iop/runtime/local.py +10 -0
- {iris_pex_embedded_python-4.0.0b7 → iris_pex_embedded_python-4.0.0b9}/src/iop/runtime/protocol.py +5 -0
- {iris_pex_embedded_python-4.0.0b7 → iris_pex_embedded_python-4.0.0b9}/src/iop/runtime/remote/director.py +10 -0
- {iris_pex_embedded_python-4.0.0b7 → iris_pex_embedded_python-4.0.0b9/src/iris_pex_embedded_python.egg-info}/PKG-INFO +1 -1
- {iris_pex_embedded_python-4.0.0b7 → iris_pex_embedded_python-4.0.0b9}/src/iris_pex_embedded_python.egg-info/SOURCES.txt +1 -0
- iris_pex_embedded_python-4.0.0b7/src/iop/production/actions.py +0 -228
- {iris_pex_embedded_python-4.0.0b7 → iris_pex_embedded_python-4.0.0b9}/LICENSE +0 -0
- {iris_pex_embedded_python-4.0.0b7 → iris_pex_embedded_python-4.0.0b9}/README.md +0 -0
- {iris_pex_embedded_python-4.0.0b7 → iris_pex_embedded_python-4.0.0b9}/setup.cfg +0 -0
- {iris_pex_embedded_python-4.0.0b7 → iris_pex_embedded_python-4.0.0b9}/src/iop/__main__.py +0 -0
- {iris_pex_embedded_python-4.0.0b7 → iris_pex_embedded_python-4.0.0b9}/src/iop/cli/__init__.py +0 -0
- {iris_pex_embedded_python-4.0.0b7 → iris_pex_embedded_python-4.0.0b9}/src/iop/cli/formatting.py +0 -0
- {iris_pex_embedded_python-4.0.0b7 → iris_pex_embedded_python-4.0.0b9}/src/iop/cls/IOP/BusinessOperation.cls +0 -0
- {iris_pex_embedded_python-4.0.0b7 → iris_pex_embedded_python-4.0.0b9}/src/iop/cls/IOP/BusinessProcess.cls +0 -0
- {iris_pex_embedded_python-4.0.0b7 → iris_pex_embedded_python-4.0.0b9}/src/iop/cls/IOP/BusinessService.cls +0 -0
- {iris_pex_embedded_python-4.0.0b7 → iris_pex_embedded_python-4.0.0b9}/src/iop/cls/IOP/Common.cls +0 -0
- {iris_pex_embedded_python-4.0.0b7 → iris_pex_embedded_python-4.0.0b9}/src/iop/cls/IOP/Director.cls +0 -0
- {iris_pex_embedded_python-4.0.0b7 → iris_pex_embedded_python-4.0.0b9}/src/iop/cls/IOP/Duplex/Operation.cls +0 -0
- {iris_pex_embedded_python-4.0.0b7 → iris_pex_embedded_python-4.0.0b9}/src/iop/cls/IOP/Duplex/Process.cls +0 -0
- {iris_pex_embedded_python-4.0.0b7 → iris_pex_embedded_python-4.0.0b9}/src/iop/cls/IOP/Duplex/Service.cls +0 -0
- {iris_pex_embedded_python-4.0.0b7 → iris_pex_embedded_python-4.0.0b9}/src/iop/cls/IOP/Generator/Message/Ack.cls +0 -0
- {iris_pex_embedded_python-4.0.0b7 → iris_pex_embedded_python-4.0.0b9}/src/iop/cls/IOP/Generator/Message/Poll.cls +0 -0
- {iris_pex_embedded_python-4.0.0b7 → iris_pex_embedded_python-4.0.0b9}/src/iop/cls/IOP/Generator/Message/Start.cls +0 -0
- {iris_pex_embedded_python-4.0.0b7 → iris_pex_embedded_python-4.0.0b9}/src/iop/cls/IOP/Generator/Message/StartPickle.cls +0 -0
- {iris_pex_embedded_python-4.0.0b7 → iris_pex_embedded_python-4.0.0b9}/src/iop/cls/IOP/Generator/Message/Stop.cls +0 -0
- {iris_pex_embedded_python-4.0.0b7 → iris_pex_embedded_python-4.0.0b9}/src/iop/cls/IOP/InboundAdapter.cls +0 -0
- {iris_pex_embedded_python-4.0.0b7 → iris_pex_embedded_python-4.0.0b9}/src/iop/cls/IOP/Message/JSONSchema.cls +0 -0
- {iris_pex_embedded_python-4.0.0b7 → iris_pex_embedded_python-4.0.0b9}/src/iop/cls/IOP/Message.cls +0 -0
- {iris_pex_embedded_python-4.0.0b7 → iris_pex_embedded_python-4.0.0b9}/src/iop/cls/IOP/OutboundAdapter.cls +0 -0
- {iris_pex_embedded_python-4.0.0b7 → iris_pex_embedded_python-4.0.0b9}/src/iop/cls/IOP/PickleMessage.cls +0 -0
- {iris_pex_embedded_python-4.0.0b7 → iris_pex_embedded_python-4.0.0b9}/src/iop/cls/IOP/PrivateSession/Duplex.cls +0 -0
- {iris_pex_embedded_python-4.0.0b7 → iris_pex_embedded_python-4.0.0b9}/src/iop/cls/IOP/PrivateSession/Message/Ack.cls +0 -0
- {iris_pex_embedded_python-4.0.0b7 → iris_pex_embedded_python-4.0.0b9}/src/iop/cls/IOP/PrivateSession/Message/Poll.cls +0 -0
- {iris_pex_embedded_python-4.0.0b7 → iris_pex_embedded_python-4.0.0b9}/src/iop/cls/IOP/PrivateSession/Message/Start.cls +0 -0
- {iris_pex_embedded_python-4.0.0b7 → iris_pex_embedded_python-4.0.0b9}/src/iop/cls/IOP/PrivateSession/Message/Stop.cls +0 -0
- {iris_pex_embedded_python-4.0.0b7 → iris_pex_embedded_python-4.0.0b9}/src/iop/cls/IOP/Projection.cls +0 -0
- {iris_pex_embedded_python-4.0.0b7 → iris_pex_embedded_python-4.0.0b9}/src/iop/cls/IOP/Service/Remote/Handler.cls +0 -0
- {iris_pex_embedded_python-4.0.0b7 → iris_pex_embedded_python-4.0.0b9}/src/iop/cls/IOP/Service/Remote/Rest/v1.cls +0 -0
- {iris_pex_embedded_python-4.0.0b7 → iris_pex_embedded_python-4.0.0b9}/src/iop/cls/IOP/Test.cls +0 -0
- {iris_pex_embedded_python-4.0.0b7 → iris_pex_embedded_python-4.0.0b9}/src/iop/cls/IOP/Wrapper.cls +0 -0
- {iris_pex_embedded_python-4.0.0b7 → iris_pex_embedded_python-4.0.0b9}/src/iop/components/__init__.py +0 -0
- {iris_pex_embedded_python-4.0.0b7 → iris_pex_embedded_python-4.0.0b9}/src/iop/components/async_request.py +0 -0
- {iris_pex_embedded_python-4.0.0b7 → iris_pex_embedded_python-4.0.0b9}/src/iop/components/business_host.py +0 -0
- {iris_pex_embedded_python-4.0.0b7 → iris_pex_embedded_python-4.0.0b9}/src/iop/components/business_operation.py +0 -0
- {iris_pex_embedded_python-4.0.0b7 → iris_pex_embedded_python-4.0.0b9}/src/iop/components/business_process.py +0 -0
- {iris_pex_embedded_python-4.0.0b7 → iris_pex_embedded_python-4.0.0b9}/src/iop/components/business_service.py +0 -0
- {iris_pex_embedded_python-4.0.0b7 → iris_pex_embedded_python-4.0.0b9}/src/iop/components/common.py +0 -0
- {iris_pex_embedded_python-4.0.0b7 → iris_pex_embedded_python-4.0.0b9}/src/iop/components/debugpy.py +0 -0
- {iris_pex_embedded_python-4.0.0b7 → iris_pex_embedded_python-4.0.0b9}/src/iop/components/generator_request.py +0 -0
- {iris_pex_embedded_python-4.0.0b7 → iris_pex_embedded_python-4.0.0b9}/src/iop/components/inbound_adapter.py +0 -0
- {iris_pex_embedded_python-4.0.0b7 → iris_pex_embedded_python-4.0.0b9}/src/iop/components/log_manager.py +0 -0
- {iris_pex_embedded_python-4.0.0b7 → iris_pex_embedded_python-4.0.0b9}/src/iop/components/outbound_adapter.py +0 -0
- {iris_pex_embedded_python-4.0.0b7 → iris_pex_embedded_python-4.0.0b9}/src/iop/components/polling_business_service.py +0 -0
- {iris_pex_embedded_python-4.0.0b7 → iris_pex_embedded_python-4.0.0b9}/src/iop/components/private_session_duplex.py +0 -0
- {iris_pex_embedded_python-4.0.0b7 → iris_pex_embedded_python-4.0.0b9}/src/iop/components/private_session_process.py +0 -0
- {iris_pex_embedded_python-4.0.0b7 → iris_pex_embedded_python-4.0.0b9}/src/iop/components/settings.py +0 -0
- {iris_pex_embedded_python-4.0.0b7 → iris_pex_embedded_python-4.0.0b9}/src/iop/messages/__init__.py +0 -0
- {iris_pex_embedded_python-4.0.0b7 → iris_pex_embedded_python-4.0.0b9}/src/iop/messages/base.py +0 -0
- {iris_pex_embedded_python-4.0.0b7 → iris_pex_embedded_python-4.0.0b9}/src/iop/messages/decorators.py +0 -0
- {iris_pex_embedded_python-4.0.0b7 → iris_pex_embedded_python-4.0.0b9}/src/iop/messages/dispatch.py +0 -0
- {iris_pex_embedded_python-4.0.0b7 → iris_pex_embedded_python-4.0.0b9}/src/iop/messages/persistent.py +0 -0
- {iris_pex_embedded_python-4.0.0b7 → iris_pex_embedded_python-4.0.0b9}/src/iop/messages/serialization.py +0 -0
- {iris_pex_embedded_python-4.0.0b7 → iris_pex_embedded_python-4.0.0b9}/src/iop/messages/validation.py +0 -0
- {iris_pex_embedded_python-4.0.0b7 → iris_pex_embedded_python-4.0.0b9}/src/iop/migration/__init__.py +0 -0
- {iris_pex_embedded_python-4.0.0b7 → iris_pex_embedded_python-4.0.0b9}/src/iop/migration/io.py +0 -0
- {iris_pex_embedded_python-4.0.0b7 → iris_pex_embedded_python-4.0.0b9}/src/iop/migration/manifest.py +0 -0
- {iris_pex_embedded_python-4.0.0b7 → iris_pex_embedded_python-4.0.0b9}/src/iop/migration/plans.py +0 -0
- {iris_pex_embedded_python-4.0.0b7 → iris_pex_embedded_python-4.0.0b9}/src/iop/production/common.py +0 -0
- {iris_pex_embedded_python-4.0.0b7 → iris_pex_embedded_python-4.0.0b9}/src/iop/production/component.py +0 -0
- {iris_pex_embedded_python-4.0.0b7 → iris_pex_embedded_python-4.0.0b9}/src/iop/production/declarations.py +0 -0
- {iris_pex_embedded_python-4.0.0b7 → iris_pex_embedded_python-4.0.0b9}/src/iop/production/declarative.py +0 -0
- {iris_pex_embedded_python-4.0.0b7 → iris_pex_embedded_python-4.0.0b9}/src/iop/production/diff.py +0 -0
- {iris_pex_embedded_python-4.0.0b7 → iris_pex_embedded_python-4.0.0b9}/src/iop/production/import_.py +0 -0
- {iris_pex_embedded_python-4.0.0b7 → iris_pex_embedded_python-4.0.0b9}/src/iop/production/inspection.py +0 -0
- {iris_pex_embedded_python-4.0.0b7 → iris_pex_embedded_python-4.0.0b9}/src/iop/production/reconstruction.py +0 -0
- {iris_pex_embedded_python-4.0.0b7 → iris_pex_embedded_python-4.0.0b9}/src/iop/production/rendering.py +0 -0
- {iris_pex_embedded_python-4.0.0b7 → iris_pex_embedded_python-4.0.0b9}/src/iop/production/runtime.py +0 -0
- {iris_pex_embedded_python-4.0.0b7 → iris_pex_embedded_python-4.0.0b9}/src/iop/production/types.py +0 -0
- {iris_pex_embedded_python-4.0.0b7 → iris_pex_embedded_python-4.0.0b9}/src/iop/production/validation.py +0 -0
- {iris_pex_embedded_python-4.0.0b7 → iris_pex_embedded_python-4.0.0b9}/src/iop/runtime/__init__.py +0 -0
- {iris_pex_embedded_python-4.0.0b7 → iris_pex_embedded_python-4.0.0b9}/src/iop/runtime/director.py +0 -0
- {iris_pex_embedded_python-4.0.0b7 → iris_pex_embedded_python-4.0.0b9}/src/iop/runtime/environment.py +0 -0
- {iris_pex_embedded_python-4.0.0b7 → iris_pex_embedded_python-4.0.0b9}/src/iop/runtime/iris.py +0 -0
- {iris_pex_embedded_python-4.0.0b7 → iris_pex_embedded_python-4.0.0b9}/src/iop/runtime/remote/__init__.py +0 -0
- {iris_pex_embedded_python-4.0.0b7 → iris_pex_embedded_python-4.0.0b9}/src/iop/runtime/remote/client.py +0 -0
- {iris_pex_embedded_python-4.0.0b7 → iris_pex_embedded_python-4.0.0b9}/src/iop/runtime/remote/migration.py +0 -0
- {iris_pex_embedded_python-4.0.0b7 → iris_pex_embedded_python-4.0.0b9}/src/iop/runtime/remote/settings.py +0 -0
- {iris_pex_embedded_python-4.0.0b7 → iris_pex_embedded_python-4.0.0b9}/src/iop/runtime/remote/setup.py +0 -0
- {iris_pex_embedded_python-4.0.0b7 → iris_pex_embedded_python-4.0.0b9}/src/iris_pex_embedded_python.egg-info/dependency_links.txt +0 -0
- {iris_pex_embedded_python-4.0.0b7 → iris_pex_embedded_python-4.0.0b9}/src/iris_pex_embedded_python.egg-info/entry_points.txt +0 -0
- {iris_pex_embedded_python-4.0.0b7 → iris_pex_embedded_python-4.0.0b9}/src/iris_pex_embedded_python.egg-info/requires.txt +0 -0
- {iris_pex_embedded_python-4.0.0b7 → iris_pex_embedded_python-4.0.0b9}/src/iris_pex_embedded_python.egg-info/top_level.txt +0 -0
|
@@ -32,9 +32,13 @@ from iop.production import OperationItem as OperationItem
|
|
|
32
32
|
from iop.production import Port as Port
|
|
33
33
|
from iop.production import ProcessItem as ProcessItem
|
|
34
34
|
from iop.production import Production as Production
|
|
35
|
+
from iop.production import ProductionApplyResult as ProductionApplyResult
|
|
36
|
+
from iop.production import ProductionChangePlan as ProductionChangePlan
|
|
35
37
|
from iop.production import ProductionDiff as ProductionDiff
|
|
36
38
|
from iop.production import ProductionDiffEntry as ProductionDiffEntry
|
|
37
39
|
from iop.production import ProductionGraph as ProductionGraph
|
|
40
|
+
from iop.production import ProductionPlanOperation as ProductionPlanOperation
|
|
41
|
+
from iop.production import ProductionVerifyResult as ProductionVerifyResult
|
|
38
42
|
from iop.production import ProductionValidationError as ProductionValidationError
|
|
39
43
|
from iop.production import ProductionValidationIssue as ProductionValidationIssue
|
|
40
44
|
from iop.production import ProductionValidationReport as ProductionValidationReport
|
|
@@ -70,9 +74,13 @@ __all__ = [
|
|
|
70
74
|
"Port",
|
|
71
75
|
"ProcessItem",
|
|
72
76
|
"Production",
|
|
77
|
+
"ProductionApplyResult",
|
|
78
|
+
"ProductionChangePlan",
|
|
73
79
|
"ProductionDiff",
|
|
74
80
|
"ProductionDiffEntry",
|
|
75
81
|
"ProductionGraph",
|
|
82
|
+
"ProductionPlanOperation",
|
|
83
|
+
"ProductionVerifyResult",
|
|
76
84
|
"ProductionValidationError",
|
|
77
85
|
"ProductionValidationIssue",
|
|
78
86
|
"ProductionValidationReport",
|
|
@@ -9,7 +9,7 @@ from importlib.metadata import version
|
|
|
9
9
|
import requests
|
|
10
10
|
|
|
11
11
|
from ..migration import utils as migration_utils
|
|
12
|
-
from ..production import Production
|
|
12
|
+
from ..production import Production, ProductionChangePlan
|
|
13
13
|
from ..runtime.local import _LocalDirector
|
|
14
14
|
from ..runtime.protocol import DirectorProtocol
|
|
15
15
|
from ..runtime.remote import _RemoteDirector, get_remote_settings
|
|
@@ -78,6 +78,11 @@ class Command:
|
|
|
78
78
|
self.args.bindings,
|
|
79
79
|
self.args.unbind is not None,
|
|
80
80
|
self.args.update,
|
|
81
|
+
self.args.plan,
|
|
82
|
+
self.args.review_plan,
|
|
83
|
+
self.args.apply_plan,
|
|
84
|
+
self.args.verify_plan,
|
|
85
|
+
self.args.rollback_backup,
|
|
81
86
|
]
|
|
82
87
|
)
|
|
83
88
|
|
|
@@ -109,6 +114,11 @@ class Command:
|
|
|
109
114
|
CommandType.UNBIND: self._handle_unbind,
|
|
110
115
|
CommandType.HELP: self._handle_help,
|
|
111
116
|
CommandType.UPDATE: self._handle_update,
|
|
117
|
+
CommandType.PLAN: self._handle_plan,
|
|
118
|
+
CommandType.REVIEW_PLAN: self._handle_review_plan,
|
|
119
|
+
CommandType.APPLY_PLAN: self._handle_apply_plan,
|
|
120
|
+
CommandType.VERIFY_PLAN: self._handle_verify_plan,
|
|
121
|
+
CommandType.ROLLBACK_BACKUP: self._handle_rollback_backup,
|
|
112
122
|
}
|
|
113
123
|
handler = command_handlers.get(command_type)
|
|
114
124
|
if handler:
|
|
@@ -149,6 +159,16 @@ class Command:
|
|
|
149
159
|
return CommandType.UNBIND
|
|
150
160
|
if self.args.update:
|
|
151
161
|
return CommandType.UPDATE
|
|
162
|
+
if self.args.plan:
|
|
163
|
+
return CommandType.PLAN
|
|
164
|
+
if self.args.review_plan:
|
|
165
|
+
return CommandType.REVIEW_PLAN
|
|
166
|
+
if self.args.apply_plan:
|
|
167
|
+
return CommandType.APPLY_PLAN
|
|
168
|
+
if self.args.verify_plan:
|
|
169
|
+
return CommandType.VERIFY_PLAN
|
|
170
|
+
if self.args.rollback_backup:
|
|
171
|
+
return CommandType.ROLLBACK_BACKUP
|
|
152
172
|
return CommandType.HELP
|
|
153
173
|
|
|
154
174
|
def _handle_default(self) -> None:
|
|
@@ -324,6 +344,55 @@ class Command:
|
|
|
324
344
|
self.director.unbind_component(self.args.unbind)
|
|
325
345
|
print(f"Removed binding {self.args.unbind}.")
|
|
326
346
|
|
|
347
|
+
def _handle_plan(self) -> None:
|
|
348
|
+
production = self._load_production_from_settings(
|
|
349
|
+
self.args.plan,
|
|
350
|
+
self.args.production,
|
|
351
|
+
)
|
|
352
|
+
plan = production.plan()
|
|
353
|
+
if self.args.out:
|
|
354
|
+
plan.save(self._absolute_path(self.args.out))
|
|
355
|
+
print(f"Production change plan written to {self.args.out}")
|
|
356
|
+
else:
|
|
357
|
+
print(plan)
|
|
358
|
+
|
|
359
|
+
def _handle_review_plan(self) -> None:
|
|
360
|
+
plan = ProductionChangePlan.load(self._absolute_path(self.args.review_plan))
|
|
361
|
+
print(plan)
|
|
362
|
+
|
|
363
|
+
def _handle_apply_plan(self) -> None:
|
|
364
|
+
if not self.args.settings:
|
|
365
|
+
raise ValueError("--apply-plan requires --settings.")
|
|
366
|
+
plan = ProductionChangePlan.load(self._absolute_path(self.args.apply_plan))
|
|
367
|
+
production = self._load_production_from_settings(
|
|
368
|
+
self.args.settings,
|
|
369
|
+
self.args.production or plan.production_name,
|
|
370
|
+
)
|
|
371
|
+
result = production.apply(
|
|
372
|
+
plan,
|
|
373
|
+
allow_destructive=self.args.allow_destructive,
|
|
374
|
+
backup_dir=self.args.backup_dir,
|
|
375
|
+
)
|
|
376
|
+
print(result)
|
|
377
|
+
|
|
378
|
+
def _handle_verify_plan(self) -> None:
|
|
379
|
+
plan = ProductionChangePlan.load(self._absolute_path(self.args.verify_plan))
|
|
380
|
+
production = Production(
|
|
381
|
+
self.args.production or plan.production_name,
|
|
382
|
+
namespace=self.director.namespace,
|
|
383
|
+
director=self.director,
|
|
384
|
+
)
|
|
385
|
+
print(production.verify(plan))
|
|
386
|
+
|
|
387
|
+
def _handle_rollback_backup(self) -> None:
|
|
388
|
+
result = Production.rollback_backup(
|
|
389
|
+
self._absolute_path(self.args.rollback_backup),
|
|
390
|
+
director=self.director,
|
|
391
|
+
namespace=self.director.namespace,
|
|
392
|
+
allow_destructive=self.args.allow_destructive,
|
|
393
|
+
)
|
|
394
|
+
print(result)
|
|
395
|
+
|
|
327
396
|
def _handle_help(self) -> None:
|
|
328
397
|
create_parser().print_help()
|
|
329
398
|
if self._is_remote:
|
|
@@ -334,6 +403,73 @@ class Command:
|
|
|
334
403
|
except Exception:
|
|
335
404
|
logging.warning("Could not retrieve default production.")
|
|
336
405
|
|
|
406
|
+
def _load_production_from_settings(
|
|
407
|
+
self,
|
|
408
|
+
settings_file: str | None,
|
|
409
|
+
production_name: str | None,
|
|
410
|
+
) -> Production:
|
|
411
|
+
if not settings_file:
|
|
412
|
+
raise ValueError("A settings.py file is required.")
|
|
413
|
+
settings_path = self._absolute_path(settings_file)
|
|
414
|
+
settings, path_added = migration_utils._load_settings(settings_path)
|
|
415
|
+
try:
|
|
416
|
+
production = _select_production(
|
|
417
|
+
getattr(settings, "PRODUCTIONS", None),
|
|
418
|
+
production_name,
|
|
419
|
+
director=self.director,
|
|
420
|
+
namespace=self.director.namespace,
|
|
421
|
+
)
|
|
422
|
+
production.with_director(self.director)
|
|
423
|
+
if not production.namespace:
|
|
424
|
+
production.in_namespace(self.director.namespace)
|
|
425
|
+
return production
|
|
426
|
+
finally:
|
|
427
|
+
migration_utils._cleanup_sys_path(path_added)
|
|
428
|
+
|
|
429
|
+
@staticmethod
|
|
430
|
+
def _absolute_path(path: str | None) -> str:
|
|
431
|
+
if not path:
|
|
432
|
+
raise ValueError("Path is required.")
|
|
433
|
+
if os.path.isabs(path):
|
|
434
|
+
return path
|
|
435
|
+
return os.path.join(os.getcwd(), path)
|
|
436
|
+
|
|
437
|
+
|
|
438
|
+
def _select_production(
|
|
439
|
+
productions,
|
|
440
|
+
production_name: str | None,
|
|
441
|
+
*,
|
|
442
|
+
director: DirectorProtocol,
|
|
443
|
+
namespace: str | None,
|
|
444
|
+
) -> Production:
|
|
445
|
+
if not isinstance(productions, list):
|
|
446
|
+
raise ValueError("settings.py must define PRODUCTIONS as a list.")
|
|
447
|
+
candidates: list[Production] = []
|
|
448
|
+
for entry in productions:
|
|
449
|
+
if isinstance(entry, Production):
|
|
450
|
+
candidate = entry
|
|
451
|
+
elif isinstance(entry, dict):
|
|
452
|
+
candidate = Production.from_dict(
|
|
453
|
+
entry,
|
|
454
|
+
director=director,
|
|
455
|
+
namespace=namespace,
|
|
456
|
+
)
|
|
457
|
+
else:
|
|
458
|
+
continue
|
|
459
|
+
candidates.append(candidate)
|
|
460
|
+
if production_name:
|
|
461
|
+
for candidate in candidates:
|
|
462
|
+
if candidate.name == production_name:
|
|
463
|
+
return candidate
|
|
464
|
+
raise ValueError(f"Production {production_name!r} not found in settings.")
|
|
465
|
+
if len(candidates) == 1:
|
|
466
|
+
return candidates[0]
|
|
467
|
+
names = ", ".join(candidate.name for candidate in candidates) or "none"
|
|
468
|
+
raise ValueError(
|
|
469
|
+
"Production name is required when settings.py contains multiple "
|
|
470
|
+
f"productions ({names})."
|
|
471
|
+
)
|
|
472
|
+
|
|
337
473
|
|
|
338
474
|
def main(argv=None) -> None:
|
|
339
475
|
parser = create_parser()
|
|
@@ -64,6 +64,17 @@ def create_parser() -> argparse.ArgumentParser:
|
|
|
64
64
|
"-t", "--test", help="test the iop module in iris", nargs="?", const="not_set"
|
|
65
65
|
)
|
|
66
66
|
parser.add_argument("-u", "--update", help="update a production", action="store_true")
|
|
67
|
+
parser.add_argument(
|
|
68
|
+
"--plan",
|
|
69
|
+
help="build a conservative production change plan from a Python settings file",
|
|
70
|
+
)
|
|
71
|
+
parser.add_argument("--review-plan", help="print a saved production change plan")
|
|
72
|
+
parser.add_argument("--apply-plan", help="apply a saved production change plan")
|
|
73
|
+
parser.add_argument("--verify-plan", help="verify a saved production change plan")
|
|
74
|
+
parser.add_argument(
|
|
75
|
+
"--rollback-backup",
|
|
76
|
+
help="restore a production from a plan/apply backup directory",
|
|
77
|
+
)
|
|
67
78
|
|
|
68
79
|
start = main_parser.add_argument_group("start arguments")
|
|
69
80
|
start.add_argument(
|
|
@@ -117,6 +128,27 @@ def create_parser() -> argparse.ArgumentParser:
|
|
|
117
128
|
action="store_true",
|
|
118
129
|
)
|
|
119
130
|
|
|
131
|
+
plan = main_parser.add_argument_group("production plan arguments")
|
|
132
|
+
plan.add_argument(
|
|
133
|
+
"--production",
|
|
134
|
+
help="target production name for --plan, or override the plan production",
|
|
135
|
+
)
|
|
136
|
+
plan.add_argument("--out", help="write --plan JSON to this path")
|
|
137
|
+
plan.add_argument(
|
|
138
|
+
"--settings",
|
|
139
|
+
help="settings.py file containing the desired Production for --apply-plan",
|
|
140
|
+
)
|
|
141
|
+
plan.add_argument(
|
|
142
|
+
"--backup-dir",
|
|
143
|
+
default=".iop/backups",
|
|
144
|
+
help="directory for apply backup artifacts",
|
|
145
|
+
)
|
|
146
|
+
plan.add_argument(
|
|
147
|
+
"--allow-destructive",
|
|
148
|
+
help="allow destructive plan operations or rollback",
|
|
149
|
+
action="store_true",
|
|
150
|
+
)
|
|
151
|
+
|
|
120
152
|
remote = main_parser.add_argument_group("remote arguments")
|
|
121
153
|
remote.add_argument(
|
|
122
154
|
"-R",
|
|
@@ -23,6 +23,11 @@ class CommandType(Enum):
|
|
|
23
23
|
UNBIND = auto()
|
|
24
24
|
HELP = auto()
|
|
25
25
|
UPDATE = auto()
|
|
26
|
+
PLAN = auto()
|
|
27
|
+
REVIEW_PLAN = auto()
|
|
28
|
+
APPLY_PLAN = auto()
|
|
29
|
+
VERIFY_PLAN = auto()
|
|
30
|
+
ROLLBACK_BACKUP = auto()
|
|
26
31
|
|
|
27
32
|
|
|
28
33
|
@dataclass
|
|
@@ -56,3 +61,13 @@ class CommandArgs:
|
|
|
56
61
|
update: bool = False
|
|
57
62
|
migration_plan: bool = False
|
|
58
63
|
strict_production_validation: bool = False
|
|
64
|
+
plan: str | None = None
|
|
65
|
+
production: str | None = None
|
|
66
|
+
out: str | None = None
|
|
67
|
+
review_plan: str | None = None
|
|
68
|
+
apply_plan: str | None = None
|
|
69
|
+
verify_plan: str | None = None
|
|
70
|
+
rollback_backup: str | None = None
|
|
71
|
+
settings: str | None = None
|
|
72
|
+
backup_dir: str = ".iop/backups"
|
|
73
|
+
allow_destructive: bool = False
|
{iris_pex_embedded_python-4.0.0b7 → iris_pex_embedded_python-4.0.0b9}/src/iop/cls/IOP/Utils.cls
RENAMED
|
@@ -878,6 +878,333 @@ ClassMethod ExportProductionQueueInfo(pProductionName As %String) As %String
|
|
|
878
878
|
Return result.%ToJSON()
|
|
879
879
|
}
|
|
880
880
|
|
|
881
|
+
/// Apply a conservative granular production change plan.
|
|
882
|
+
ClassMethod ApplyProductionPlan(
|
|
883
|
+
pProductionName As %String,
|
|
884
|
+
pPlan As %String,
|
|
885
|
+
pAllowDestructive As %Boolean = 0) As %String
|
|
886
|
+
{
|
|
887
|
+
Set result = {}
|
|
888
|
+
Set result.production = pProductionName
|
|
889
|
+
Set result.operations = []
|
|
890
|
+
Try {
|
|
891
|
+
Set plan = {}.%FromJSON(pPlan)
|
|
892
|
+
Set operations = plan.%Get("operations")
|
|
893
|
+
Set production = ##class(Ens.Config.Production).%OpenId(pProductionName)
|
|
894
|
+
If '$IsObject(production) {
|
|
895
|
+
Set loaded = ##class(Ens.Config.Production).LoadFromClass(pProductionName)
|
|
896
|
+
If $IsObject(loaded) {
|
|
897
|
+
Set production = loaded
|
|
898
|
+
} Else {
|
|
899
|
+
$$$ThrowStatus($$$ERROR($$$EnsErrGeneral,"Production could not be loaded: "_pProductionName))
|
|
900
|
+
}
|
|
901
|
+
}
|
|
902
|
+
If $IsObject(operations) {
|
|
903
|
+
For i=0:1:operations.%Size()-1 {
|
|
904
|
+
Set operation = operations.%Get(i)
|
|
905
|
+
Set opResult = {}
|
|
906
|
+
Set opResult.id = operation.%Get("id")
|
|
907
|
+
Set opResult."op_type" = operation.%Get("op_type")
|
|
908
|
+
Set opResult.path = operation.%Get("path")
|
|
909
|
+
Set risk = operation.%Get("risk")
|
|
910
|
+
If risk = "unsupported" {
|
|
911
|
+
Set opResult.status = "skipped"
|
|
912
|
+
Set opResult.message = $Select(operation.%Get("reason")'="":operation.%Get("reason"),1:"unsupported operation")
|
|
913
|
+
} ElseIf (risk = "destructive") && ('pAllowDestructive) {
|
|
914
|
+
Set opResult.status = "skipped"
|
|
915
|
+
Set opResult.message = "requires allow_destructive"
|
|
916
|
+
} Else {
|
|
917
|
+
Try {
|
|
918
|
+
$$$ThrowOnError(..ApplyProductionPlanOperation(production, operation))
|
|
919
|
+
Set opResult.status = "applied"
|
|
920
|
+
} Catch opEx {
|
|
921
|
+
Set opResult.status = "failed"
|
|
922
|
+
Set opResult.message = opEx.DisplayString()
|
|
923
|
+
}
|
|
924
|
+
}
|
|
925
|
+
Do result.operations.%Push(opResult)
|
|
926
|
+
}
|
|
927
|
+
}
|
|
928
|
+
$$$ThrowOnError(production.SaveToClass())
|
|
929
|
+
$$$ThrowOnError($System.OBJ.Compile(pProductionName,"k-d"))
|
|
930
|
+
} Catch ex {
|
|
931
|
+
Set result.error = ex.DisplayString()
|
|
932
|
+
}
|
|
933
|
+
Return result.%ToJSON()
|
|
934
|
+
}
|
|
935
|
+
|
|
936
|
+
ClassMethod ApplyProductionPlanOperation(
|
|
937
|
+
pProduction As Ens.Config.Production,
|
|
938
|
+
pOperation) As %Status [ Internal, Private ]
|
|
939
|
+
{
|
|
940
|
+
Set opType = pOperation.%Get("op_type")
|
|
941
|
+
If opType = "add_item" {
|
|
942
|
+
Return ..ApplyPlanAddItem(pProduction,pOperation)
|
|
943
|
+
}
|
|
944
|
+
If opType = "delete_item" {
|
|
945
|
+
Return ..ApplyPlanDeleteItem(pProduction,pOperation.%Get("item"))
|
|
946
|
+
}
|
|
947
|
+
If opType = "set_item_field" {
|
|
948
|
+
Return ..ApplyPlanSetItemField(pProduction,pOperation)
|
|
949
|
+
}
|
|
950
|
+
If opType = "replace_item_class" {
|
|
951
|
+
Return ..ApplyPlanSetItemField(pProduction,pOperation)
|
|
952
|
+
}
|
|
953
|
+
If opType = "set_production_field" {
|
|
954
|
+
Return ..ApplyPlanSetProductionField(pProduction,pOperation)
|
|
955
|
+
}
|
|
956
|
+
If opType = "set_setting" {
|
|
957
|
+
If pOperation.%Get("target") = "Other" {
|
|
958
|
+
Return ..ReplaceOtherSettings(..FindProductionItem(pProduction,pOperation.%Get("item")),pOperation.%Get("after"))
|
|
959
|
+
}
|
|
960
|
+
Return ..SetConfigSetting(..FindProductionItem(pProduction,pOperation.%Get("item")),pOperation.%Get("target"),pOperation.%Get("setting"),pOperation.%Get("after"))
|
|
961
|
+
}
|
|
962
|
+
If opType = "remove_setting" {
|
|
963
|
+
Return ..RemoveConfigSetting(..FindProductionItem(pProduction,pOperation.%Get("item")),pOperation.%Get("target"),pOperation.%Get("setting"))
|
|
964
|
+
}
|
|
965
|
+
If opType = "set_route_setting" {
|
|
966
|
+
Return ..SetConfigSetting(..FindProductionItem(pProduction,pOperation.%Get("source_item")),"Host",pOperation.%Get("source_port"),..DynamicArrayToCSV(pOperation.%Get("after")))
|
|
967
|
+
}
|
|
968
|
+
If opType = "remove_route" {
|
|
969
|
+
Return ..RemoveConfigSetting(..FindProductionItem(pProduction,pOperation.%Get("source_item")),"Host",pOperation.%Get("source_port"))
|
|
970
|
+
}
|
|
971
|
+
Quit $$$ERROR($$$EnsErrGeneral,"Unsupported production plan operation: "_opType)
|
|
972
|
+
}
|
|
973
|
+
|
|
974
|
+
ClassMethod ApplyPlanAddItem(
|
|
975
|
+
pProduction As Ens.Config.Production,
|
|
976
|
+
pOperation) As %Status [ Internal, Private ]
|
|
977
|
+
{
|
|
978
|
+
Set itemName = pOperation.%Get("item")
|
|
979
|
+
If itemName = "" {
|
|
980
|
+
Quit $$$ERROR($$$EnsErrGeneral,"Plan item name is required.")
|
|
981
|
+
}
|
|
982
|
+
If $IsObject(..FindProductionItem(pProduction,itemName,0)) {
|
|
983
|
+
Quit $$$ERROR($$$EnsErrGeneral,"Production item already exists: "_itemName)
|
|
984
|
+
}
|
|
985
|
+
Set data = pOperation.%Get("after")
|
|
986
|
+
Set item = ##class(Ens.Config.Item).%New()
|
|
987
|
+
Set item.Name = itemName
|
|
988
|
+
Set item.ClassName = data.%Get("class_name")
|
|
989
|
+
Set item.Category = data.%Get("category")
|
|
990
|
+
Set item.PoolSize = +data.%Get("pool_size")
|
|
991
|
+
Set item.Enabled = ..BooleanValue(data.%Get("enabled"))
|
|
992
|
+
Set item.Foreground = ..BooleanValue(data.%Get("foreground"))
|
|
993
|
+
Set item.Comment = data.%Get("comment")
|
|
994
|
+
Set item.LogTraceEvents = ..BooleanValue(data.%Get("log_trace_events"))
|
|
995
|
+
Set item.Schedule = data.%Get("schedule")
|
|
996
|
+
Set item.Production = pProduction
|
|
997
|
+
$$$ThrowOnError(..SetSettingsFromMap(item,"Host",data.%Get("host_settings")))
|
|
998
|
+
$$$ThrowOnError(..SetSettingsFromMap(item,"Adapter",data.%Get("adapter_settings")))
|
|
999
|
+
$$$ThrowOnError(..ReplaceOtherSettings(item,data.%Get("other_settings")))
|
|
1000
|
+
Do pProduction.Items.Insert(item)
|
|
1001
|
+
Quit $$$OK
|
|
1002
|
+
}
|
|
1003
|
+
|
|
1004
|
+
ClassMethod ApplyPlanDeleteItem(
|
|
1005
|
+
pProduction As Ens.Config.Production,
|
|
1006
|
+
pItemName As %String) As %Status [ Internal, Private ]
|
|
1007
|
+
{
|
|
1008
|
+
Set index = ..FindProductionItemIndex(pProduction,pItemName)
|
|
1009
|
+
If index < 1 {
|
|
1010
|
+
Quit $$$OK
|
|
1011
|
+
}
|
|
1012
|
+
Do pProduction.Items.RemoveAt(index)
|
|
1013
|
+
Quit $$$OK
|
|
1014
|
+
}
|
|
1015
|
+
|
|
1016
|
+
ClassMethod ApplyPlanSetItemField(
|
|
1017
|
+
pProduction As Ens.Config.Production,
|
|
1018
|
+
pOperation) As %Status [ Internal, Private ]
|
|
1019
|
+
{
|
|
1020
|
+
Set item = ..FindProductionItem(pProduction,pOperation.%Get("item"))
|
|
1021
|
+
Set field = pOperation.%Get("field")
|
|
1022
|
+
Set value = pOperation.%Get("after")
|
|
1023
|
+
If field = "class_name" {
|
|
1024
|
+
Set item.ClassName = value
|
|
1025
|
+
} ElseIf field = "category" {
|
|
1026
|
+
Set item.Category = value
|
|
1027
|
+
} ElseIf field = "pool_size" {
|
|
1028
|
+
Set item.PoolSize = +value
|
|
1029
|
+
} ElseIf field = "enabled" {
|
|
1030
|
+
Set item.Enabled = ..BooleanValue(value)
|
|
1031
|
+
} ElseIf field = "foreground" {
|
|
1032
|
+
Set item.Foreground = ..BooleanValue(value)
|
|
1033
|
+
} ElseIf field = "comment" {
|
|
1034
|
+
Set item.Comment = value
|
|
1035
|
+
} ElseIf field = "log_trace_events" {
|
|
1036
|
+
Set item.LogTraceEvents = ..BooleanValue(value)
|
|
1037
|
+
} ElseIf field = "schedule" {
|
|
1038
|
+
Set item.Schedule = value
|
|
1039
|
+
} Else {
|
|
1040
|
+
Quit $$$ERROR($$$EnsErrGeneral,"Unsupported item field: "_field)
|
|
1041
|
+
}
|
|
1042
|
+
Quit $$$OK
|
|
1043
|
+
}
|
|
1044
|
+
|
|
1045
|
+
ClassMethod ApplyPlanSetProductionField(
|
|
1046
|
+
pProduction As Ens.Config.Production,
|
|
1047
|
+
pOperation) As %Status [ Internal, Private ]
|
|
1048
|
+
{
|
|
1049
|
+
Set field = pOperation.%Get("field")
|
|
1050
|
+
Set value = pOperation.%Get("after")
|
|
1051
|
+
If field = "testing_enabled" {
|
|
1052
|
+
Set pProduction.TestingEnabled = ..BooleanValue(value)
|
|
1053
|
+
} ElseIf field = "log_general_trace_events" {
|
|
1054
|
+
Set pProduction.LogGeneralTraceEvents = ..BooleanValue(value)
|
|
1055
|
+
} ElseIf field = "actor_pool_size" {
|
|
1056
|
+
Set pProduction.ActorPoolSize = +value
|
|
1057
|
+
} ElseIf field = "description" {
|
|
1058
|
+
Set pProduction.Description = value
|
|
1059
|
+
} Else {
|
|
1060
|
+
Set settingName = ..ProductionSettingName(field)
|
|
1061
|
+
If settingName = "" {
|
|
1062
|
+
Quit $$$ERROR($$$EnsErrGeneral,"Unsupported production field: "_field)
|
|
1063
|
+
}
|
|
1064
|
+
$$$ThrowOnError(..SetConfigSetting(pProduction,"",settingName,value))
|
|
1065
|
+
}
|
|
1066
|
+
Quit $$$OK
|
|
1067
|
+
}
|
|
1068
|
+
|
|
1069
|
+
ClassMethod ProductionSettingName(pField As %String) As %String [ Internal, Private ]
|
|
1070
|
+
{
|
|
1071
|
+
Quit $Select(
|
|
1072
|
+
pField="shutdown_timeout":"ShutdownTimeout",
|
|
1073
|
+
pField="update_timeout":"UpdateTimeout",
|
|
1074
|
+
pField="alert_notification_manager":"AlertNotificationManager",
|
|
1075
|
+
pField="alert_notification_operation":"AlertNotificationOperation",
|
|
1076
|
+
pField="alert_notification_recipients":"AlertNotificationRecipients",
|
|
1077
|
+
pField="alert_action_window":"AlertActionWindow",
|
|
1078
|
+
1:"")
|
|
1079
|
+
}
|
|
1080
|
+
|
|
1081
|
+
ClassMethod FindProductionItem(
|
|
1082
|
+
pProduction As Ens.Config.Production,
|
|
1083
|
+
pItemName As %String,
|
|
1084
|
+
pThrow As %Boolean = 1) [ Internal, Private ]
|
|
1085
|
+
{
|
|
1086
|
+
Set index = ..FindProductionItemIndex(pProduction,pItemName)
|
|
1087
|
+
If index > 0 {
|
|
1088
|
+
Quit pProduction.Items.GetAt(index)
|
|
1089
|
+
}
|
|
1090
|
+
If pThrow {
|
|
1091
|
+
$$$ThrowStatus($$$ERROR($$$EnsErrGeneral,"Production item does not exist: "_pItemName))
|
|
1092
|
+
}
|
|
1093
|
+
Quit ""
|
|
1094
|
+
}
|
|
1095
|
+
|
|
1096
|
+
ClassMethod FindProductionItemIndex(
|
|
1097
|
+
pProduction As Ens.Config.Production,
|
|
1098
|
+
pItemName As %String) As %Integer [ Internal, Private ]
|
|
1099
|
+
{
|
|
1100
|
+
For i=1:1:pProduction.Items.Count() {
|
|
1101
|
+
Set item = pProduction.Items.GetAt(i)
|
|
1102
|
+
If $IsObject(item), item.Name = pItemName {
|
|
1103
|
+
Return i
|
|
1104
|
+
}
|
|
1105
|
+
}
|
|
1106
|
+
Quit 0
|
|
1107
|
+
}
|
|
1108
|
+
|
|
1109
|
+
ClassMethod SetSettingsFromMap(
|
|
1110
|
+
pOwner,
|
|
1111
|
+
pTarget As %String,
|
|
1112
|
+
pMap) As %Status [ Internal, Private ]
|
|
1113
|
+
{
|
|
1114
|
+
If '$IsObject(pMap) {
|
|
1115
|
+
Quit $$$OK
|
|
1116
|
+
}
|
|
1117
|
+
Set iterator = pMap.%GetIterator()
|
|
1118
|
+
While iterator.%GetNext(.key,.value) {
|
|
1119
|
+
$$$ThrowOnError(..SetConfigSetting(pOwner,pTarget,key,value))
|
|
1120
|
+
}
|
|
1121
|
+
Quit $$$OK
|
|
1122
|
+
}
|
|
1123
|
+
|
|
1124
|
+
ClassMethod SetConfigSetting(
|
|
1125
|
+
pOwner,
|
|
1126
|
+
pTarget As %String,
|
|
1127
|
+
pName As %String,
|
|
1128
|
+
pValue) As %Status [ Internal, Private ]
|
|
1129
|
+
{
|
|
1130
|
+
Set index = ..FindConfigSettingIndex(pOwner,pTarget,pName)
|
|
1131
|
+
If index > 0 {
|
|
1132
|
+
Set setting = pOwner.Settings.GetAt(index)
|
|
1133
|
+
} Else {
|
|
1134
|
+
Set setting = ##class(Ens.Config.Setting).%New()
|
|
1135
|
+
Set setting.Target = pTarget
|
|
1136
|
+
Set setting.Name = pName
|
|
1137
|
+
Do pOwner.Settings.Insert(setting)
|
|
1138
|
+
}
|
|
1139
|
+
Set setting.Value = pValue
|
|
1140
|
+
Quit $$$OK
|
|
1141
|
+
}
|
|
1142
|
+
|
|
1143
|
+
ClassMethod RemoveConfigSetting(
|
|
1144
|
+
pOwner,
|
|
1145
|
+
pTarget As %String,
|
|
1146
|
+
pName As %String) As %Status [ Internal, Private ]
|
|
1147
|
+
{
|
|
1148
|
+
Set index = ..FindConfigSettingIndex(pOwner,pTarget,pName)
|
|
1149
|
+
If index > 0 {
|
|
1150
|
+
Do pOwner.Settings.RemoveAt(index)
|
|
1151
|
+
}
|
|
1152
|
+
Quit $$$OK
|
|
1153
|
+
}
|
|
1154
|
+
|
|
1155
|
+
ClassMethod ReplaceOtherSettings(
|
|
1156
|
+
pOwner,
|
|
1157
|
+
pSettings) As %Status [ Internal, Private ]
|
|
1158
|
+
{
|
|
1159
|
+
For i=pOwner.Settings.Count():-1:1 {
|
|
1160
|
+
Set setting = pOwner.Settings.GetAt(i)
|
|
1161
|
+
If $IsObject(setting), setting.Target '= "Host", setting.Target '= "Adapter" {
|
|
1162
|
+
Do pOwner.Settings.RemoveAt(i)
|
|
1163
|
+
}
|
|
1164
|
+
}
|
|
1165
|
+
If '$IsObject(pSettings) {
|
|
1166
|
+
Quit $$$OK
|
|
1167
|
+
}
|
|
1168
|
+
For i=0:1:pSettings.%Size()-1 {
|
|
1169
|
+
Set data = pSettings.%Get(i)
|
|
1170
|
+
Set setting = ##class(Ens.Config.Setting).%New()
|
|
1171
|
+
Set setting.Target = ..DynamicGet(data,"@Target","")
|
|
1172
|
+
Set setting.Name = ..DynamicGet(data,"@Name","")
|
|
1173
|
+
Set setting.Value = ..DynamicGet(data,"#text","")
|
|
1174
|
+
Do pOwner.Settings.Insert(setting)
|
|
1175
|
+
}
|
|
1176
|
+
Quit $$$OK
|
|
1177
|
+
}
|
|
1178
|
+
|
|
1179
|
+
ClassMethod FindConfigSettingIndex(
|
|
1180
|
+
pOwner,
|
|
1181
|
+
pTarget As %String,
|
|
1182
|
+
pName As %String) As %Integer [ Internal, Private ]
|
|
1183
|
+
{
|
|
1184
|
+
For i=1:1:pOwner.Settings.Count() {
|
|
1185
|
+
Set setting = pOwner.Settings.GetAt(i)
|
|
1186
|
+
If $IsObject(setting), setting.Target = pTarget, setting.Name = pName {
|
|
1187
|
+
Return i
|
|
1188
|
+
}
|
|
1189
|
+
}
|
|
1190
|
+
Quit 0
|
|
1191
|
+
}
|
|
1192
|
+
|
|
1193
|
+
ClassMethod DynamicArrayToCSV(pArray) As %String [ Internal, Private ]
|
|
1194
|
+
{
|
|
1195
|
+
If '$IsObject(pArray) {
|
|
1196
|
+
Quit pArray
|
|
1197
|
+
}
|
|
1198
|
+
Set value = ""
|
|
1199
|
+
For i=0:1:pArray.%Size()-1 {
|
|
1200
|
+
If value '= "" {
|
|
1201
|
+
Set value = value_","
|
|
1202
|
+
}
|
|
1203
|
+
Set value = value_pArray.%Get(i)
|
|
1204
|
+
}
|
|
1205
|
+
Quit value
|
|
1206
|
+
}
|
|
1207
|
+
|
|
881
1208
|
ClassMethod dispatchTestComponent(
|
|
882
1209
|
pTargetName As %String,
|
|
883
1210
|
pInput As Ens.Request) As Ens.Response
|
{iris_pex_embedded_python-4.0.0b7 → iris_pex_embedded_python-4.0.0b9}/src/iop/migration/utils.py
RENAMED
|
@@ -1009,6 +1009,27 @@ def export_production_queue_info(production_name):
|
|
|
1009
1009
|
return json.loads(data)
|
|
1010
1010
|
|
|
1011
1011
|
|
|
1012
|
+
def apply_production_plan(plan: dict, allow_destructive: bool = False) -> dict:
|
|
1013
|
+
"""
|
|
1014
|
+
Apply a conservative granular production change plan locally in IRIS.
|
|
1015
|
+
"""
|
|
1016
|
+
production_name = plan.get("production") or plan.get("production_name")
|
|
1017
|
+
if not production_name:
|
|
1018
|
+
raise ValueError("Production plan is missing the production name.")
|
|
1019
|
+
data = (
|
|
1020
|
+
_iris.get_iris()
|
|
1021
|
+
.cls("IOP.Utils")
|
|
1022
|
+
.ApplyProductionPlan(
|
|
1023
|
+
production_name,
|
|
1024
|
+
json.dumps(plan),
|
|
1025
|
+
1 if allow_destructive else 0,
|
|
1026
|
+
)
|
|
1027
|
+
)
|
|
1028
|
+
if isinstance(data, dict):
|
|
1029
|
+
return data
|
|
1030
|
+
return json.loads(data)
|
|
1031
|
+
|
|
1032
|
+
|
|
1012
1033
|
def xml_to_json(xml_string: str) -> str:
|
|
1013
1034
|
return _xml_to_json(xml_string)
|
|
1014
1035
|
|
{iris_pex_embedded_python-4.0.0b7 → iris_pex_embedded_python-4.0.0b9}/src/iop/production/__init__.py
RENAMED
|
@@ -7,6 +7,10 @@ from .declarations import ProcessItem as ProcessItem
|
|
|
7
7
|
from .declarations import Route as Route
|
|
8
8
|
from .declarations import ServiceItem as ServiceItem
|
|
9
9
|
from .model import Production as Production
|
|
10
|
+
from .planning import ProductionApplyResult as ProductionApplyResult
|
|
11
|
+
from .planning import ProductionChangePlan as ProductionChangePlan
|
|
12
|
+
from .planning import ProductionPlanOperation as ProductionPlanOperation
|
|
13
|
+
from .planning import ProductionVerifyResult as ProductionVerifyResult
|
|
10
14
|
from .runtime import resolve_target as resolve_target
|
|
11
15
|
from .types import GraphEdge as GraphEdge
|
|
12
16
|
from .types import GraphNode as GraphNode
|
|
@@ -32,9 +36,13 @@ __all__ = [
|
|
|
32
36
|
"Port",
|
|
33
37
|
"ProcessItem",
|
|
34
38
|
"Production",
|
|
39
|
+
"ProductionApplyResult",
|
|
40
|
+
"ProductionChangePlan",
|
|
35
41
|
"ProductionDiff",
|
|
36
42
|
"ProductionDiffEntry",
|
|
37
43
|
"ProductionGraph",
|
|
44
|
+
"ProductionPlanOperation",
|
|
45
|
+
"ProductionVerifyResult",
|
|
38
46
|
"ProductionValidationError",
|
|
39
47
|
"ProductionValidationIssue",
|
|
40
48
|
"ProductionValidationReport",
|