Skip to content

Commit eb3462d

Browse files
committed
Fix remote migration settings key and improve error handling in migration methods
1 parent 88e9774 commit eb3462d

File tree

3 files changed

+67
-59
lines changed

3 files changed

+67
-59
lines changed

src/iop/_utils.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -264,9 +264,9 @@ def filename_to_module(filename) -> str:
264264
def migrate_remote(filename=None):
265265
"""
266266
Read a settings file from the filename
267-
If the settings.py file has a key 'REMOTE_SETTING' then it will use the value of that key
267+
If the settings.py file has a key 'REMOTE_SETTINGS' then it will use the value of that key
268268
as the remote host to connect to.
269-
the REMOTE_SETTING is a RemoteSettings dictionary with the following keys:
269+
the REMOTE_SETTINGS is a RemoteSettings dictionary with the following keys:
270270
* 'url': the host url to connect to (mandatory)
271271
* 'namespace': the namespace to use (optional, default is 'USER')
272272
* 'package': the package to use (optional, default is 'python')
@@ -285,15 +285,15 @@ def migrate_remote(filename=None):
285285
'body' will be constructed with all the files in the folder if the folder is not empty else use root folder of settings.py
286286
"""
287287
settings, path = _Utils._load_settings(filename)
288-
remote_settings: Optional[RemoteSettings] = getattr(settings, 'REMOTE_SETTING', None) if settings else None
288+
remote_settings: Optional[RemoteSettings] = getattr(settings, 'REMOTE_SETTINGS', None) if settings else None
289289

290290
if not remote_settings:
291291
_Utils.migrate(filename)
292292
return
293293

294294
# Validate required fields
295295
if 'url' not in remote_settings:
296-
raise ValueError("REMOTE_SETTING must contain 'url' field")
296+
raise ValueError("REMOTE_SETTINGS must contain 'url' field")
297297

298298
# prepare the payload with defaults
299299
payload = {
@@ -333,11 +333,9 @@ def migrate_remote(filename=None):
333333
timeout=10
334334
)
335335

336-
# check the response status
337-
if response.status_code != 200:
338-
raise RuntimeError(f"Failed to migrate: {response.status_code} - {response.text}")
339-
else:
340-
print(f"Migration successful: {response.status_code} - {response.text}")
336+
print(f"Response from remote migration: {response.text}")
337+
338+
response.raise_for_status() # Raise an error for bad responses
341339

342340
@staticmethod
343341
def migrate(filename=None):
@@ -360,6 +358,8 @@ def migrate(filename=None):
360358

361359
_Utils._cleanup_sys_path(path)
362360

361+
raise ValueError("Migration is not implemented yet. Please use the remote migration feature.")
362+
363363
@staticmethod
364364
def _load_settings(filename):
365365
"""Load settings module from file or default location.

src/iop/cls/IOP/Projection.cls

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ ClassMethod CreateProjection(
1818
set webName = "/api/iop"
1919
set webProperties("NameSpace") = tCurrentNamespace
2020
set webProperties("Enabled") = 1
21+
set webProperties("DispatchClass") = "IOP.Service.Remote.Handler"
2122
set webProperties("AutheEnabled") = 32
2223
set webProperties("ServeFiles")=2
2324
set webProperties("Recurse")=1

src/iop/cls/IOP/Service/Remote/Rest/v1.cls

Lines changed: 57 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -28,61 +28,68 @@ ClassMethod NamespaceCheck(pNamespace As %String) As %Boolean [ Internal, Privat
2828

2929
ClassMethod PutMigrate() As %DynamicObject
3030
{
31-
// Get the request body
32-
set dyna = {}.%FromJSON(%request.Content)
33-
set body = dyna.%Get("body")
34-
set namespace = dyna.%Get("namespace")
35-
set targetDirectory = dyna.%Get("remote_folder")
36-
set packageName = dyna.%Get("package")
37-
// check for namespace existence and user permissions against namespace
38-
If '..NamespaceCheck(namespace) {
39-
Return ""
40-
}
41-
New $NAMESPACE
42-
Set $NAMESPACE = namespace
31+
Try {
32+
// Get the request body
33+
set dyna = {}.%FromJSON(%request.Content)
34+
set body = dyna.%Get("body")
35+
set namespace = dyna.%Get("namespace")
36+
set targetDirectory = dyna.%Get("remote_folder")
37+
set packageName = dyna.%Get("package")
38+
// check for namespace existence and user permissions against namespace
39+
If '..NamespaceCheck(namespace) {
40+
Return ""
41+
}
42+
New $NAMESPACE
43+
Set $NAMESPACE = namespace
4344

44-
45-
//Create directory for custom packages
46-
If targetDirectory '= "" {
47-
If '##class(%Library.File).DirectoryExists(targetDirectory) {
48-
If '##class(%Library.File).CreateDirectory(targetDirectory) {
49-
$$$ThrowStatus($$$ERROR($$$DirectoryCannotCreate, targetDirectory))
50-
}
51-
}
52-
}
53-
Else {
54-
// Set targetDirectory to the CODE DATABASE directory
55-
do ##class(%SYS.Namespace).GetAllNSInfo("USER",.info)
56-
Set targetDirectory = info("RoutineDB","Directory")
57-
}
58-
59-
Set packagePath = ##class(%Library.File).NormalizeDirectory(packageName, targetDirectory)
60-
// If the package already exists then we must be meaning to re-load it. Delete files/directory/metadata and recreate fresh.
61-
If ##class(%Library.File).DirectoryExists(packagePath) {
62-
If '##class(%Library.File).RemoveDirectoryTree(packagePath) {
63-
$$$ThrowStatus($$$ERROR($$$DirectoryPermission , packagePath))
45+
46+
//Create directory for custom packages
47+
If targetDirectory '= "" {
48+
If '##class(%Library.File).DirectoryExists(targetDirectory) {
49+
If '##class(%Library.File).CreateDirectory(targetDirectory) {
50+
$$$ThrowStatus($$$ERROR($$$DirectoryCannotCreate, targetDirectory))
51+
}
52+
}
53+
}
54+
Else {
55+
// Set targetDirectory to the CODE DATABASE directory
56+
do ##class(%SYS.Namespace).GetAllNSInfo("USER",.info)
57+
Set targetDirectory = info("RoutineDB","Directory")
58+
}
59+
60+
Set packagePath = ##class(%Library.File).NormalizeDirectory(packageName, targetDirectory)
61+
// If the package already exists then we must be meaning to re-load it. Delete files/directory/metadata and recreate fresh.
62+
If ##class(%Library.File).DirectoryExists(packagePath) {
63+
If '##class(%Library.File).RemoveDirectoryTree(packagePath) {
64+
$$$ThrowStatus($$$ERROR($$$DirectoryPermission , packagePath))
65+
}
66+
}
67+
If '##class(%Library.File).CreateDirectory(packagePath) {
68+
$$$ThrowStatus($$$ERROR($$$DirectoryCannotCreate, packagePath))
69+
}
70+
71+
//Unpack JSON objects
72+
Set iterator = body.%GetIterator()
73+
While iterator.%GetNext(.key , .fileObject ) {
74+
// If fileObject.name has '/' then it is a path, we need to normalize it
75+
Set fileName = ##class(%Library.File).NormalizeFilename(fileObject.name,packagePath)
76+
do ##class(%Library.File).CreateDirectoryChain(##class(%Library.File).GetDirectory(fileName))
77+
Set fileStream = ##class(%Stream.FileCharacter).%New()
78+
Set fileStream.TranslateTable = "UTF8"
79+
$$$ThrowOnError(fileStream.LinkToFile(fileName))
80+
Do fileStream.Write(fileObject.data)
81+
$$$ThrowOnError(fileStream.%Save())
6482
}
65-
}
66-
If '##class(%Library.File).CreateDirectory(packagePath) {
67-
$$$ThrowStatus($$$ERROR($$$DirectoryCannotCreate, packagePath))
68-
}
6983

70-
//Unpack JSON objects
71-
Set iterator = body.%GetIterator()
72-
While iterator.%GetNext(.key , .fileObject ) {
73-
// If fileObject.name has '/' then it is a path, we need to normalize it
74-
Set fileName = ##class(%Library.File).NormalizeFilename(fileObject.name,packagePath)
75-
do ##class(%Library.File).CreateDirectoryChain(##class(%Library.File).GetDirectory(fileName))
76-
Set fileStream = ##class(%Stream.FileCharacter).%New()
77-
Set fileStream.TranslateTable = "UTF8"
78-
$$$ThrowOnError(fileStream.LinkToFile(fileName))
79-
Do fileStream.Write(fileObject.data)
80-
$$$ThrowOnError(fileStream.%Save())
84+
//Do the iop migration
85+
86+
set iopUtils = ##class(IOP.Wrapper).Import("iop._utils")
87+
do iopUtils."_Utils".migrate(##class(%Library.File).NormalizeFilename("settings.py", packagePath))
88+
}
89+
Catch ex {
90+
$$$ThrowOnError(ex.AsStatus())
8191
}
8292

83-
//Do the iop migration
84-
set iopUtils = ##class(IOP.Wrapper).Import("iop._utils")
85-
do iopUtils."_Utils".migrate(##class(%Library.File).NormalizeFilename("settings.py", packagePath))
8693

8794
return $$$OK
8895
}

0 commit comments

Comments
 (0)