Skip to content

Commit b70d75b

Browse files
authored
Web Applications will default to current namespace instead of %SYS (#936)
* Web Applications will default to current namespace instead of %SYS * Fix update tests by opening tarball * Fix CHANGELOG
1 parent 7c3f797 commit b70d75b

File tree

7 files changed

+137
-49
lines changed

7 files changed

+137
-49
lines changed

CHANGELOG.md

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1111
- #874: Modules can now specify required Python version in `<SystemRequirements>` in `module.xml`
1212
- #909: IPM now warns when Python 3.13 or higher is installed (IRIS incompatibility)
1313
- #850: Re-added `<SystemSetting> Resource Processor for backwards compatibility
14+
- #550: Add a new "update" command and framework to support in-place module updates. install/load of a module to newer version than currently installed will be blocked by default if module has UpdatePackage defined.
1415

1516
### Fixed
1617
- #899: Fixed CLI parser parses modifiers incorrectly
@@ -21,9 +22,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2122
- #908: Fix case where `uninstall -all` would fail because of incomplete dependency information
2223
- #892: Fixed load behavior (no longer sets Developer Mode unless -dev flag is set)
2324
- #903: Fixed install behavior which succeeded even when trying to reinstall a module without -dev or -force modifiers (breaking change)
24-
25-
### Added
26-
- #550: Add a new "update" command and framework to support in-place module updates. install/load of a module to newer version than currently installed will be blocked by default if module has UpdatePackage defined.
2725
- #363: `help load` and `help install` will now mention that setting the `dev` flag will not roll back transactions on failure
2826
- #884: Fix missing module version in error message when dependency resolution fails to find suitable version
2927
- #838: Improve error messages when installation fails
@@ -38,6 +36,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
3836
- #374: A new System Expression `${ipmdir}` points to the module's default installation location: `$System.Util.DataDirectory()/ipm/<packagename>/<version>/`
3937
- #563: The `verify` phase will uninstall all modules after every integration test
4038
- #611, #686: If a path is supplied for `package`, it will now create a temporary subdirectory in that path to export the module into to avoid clashes with any existing files. This subdirectory will be deleted afterwards, leaving just the .tgz file.
39+
- #844: If the "NameSpace" attribute isn't specified for a Web Application, it will be created in the current namespace instead of %SYS
4140

4241
## [0.10.3] - 2025-09-17
4342

src/cls/IPM/ResourceProcessor/WebApplication.cls

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,11 @@ Method CopyAttributes() [ Private ]
2828
* attribute as the attribute list is just all non-private/transient properties
2929
* in Security.Applications.
3030
*/
31+
32+
// If NameSpace isn't specified, default to current namespace
33+
if ..ResourceReference.Attributes.GetAt("NameSpace") = "" {
34+
$$$ThrowOnError(..ResourceReference.Attributes.SetAt($namespace, "NameSpace"))
35+
}
3136
set key = ""
3237
while 1 {
3338
set value = ..ResourceReference.Attributes.GetNext(.key)

tests/integration_tests/Test/PM/Integration/InstallApplication.cls

Lines changed: 63 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,14 @@ Class Test.PM.Integration.InstallApplication Extends Test.PM.Integration.Base
33

44
Method TestSimpleApp()
55
{
6-
Set tSC = $$$OK
7-
Try {
8-
Set tTestRoot = ##class(%File).NormalizeDirectory($Get(^UnitTestRoot))
9-
6+
set tSC = $$$OK
7+
try {
8+
set tTestRoot = ##class(%File).NormalizeDirectory($get(^UnitTestRoot))
9+
1010
set tModuleDir = ##class(%File).NormalizeDirectory(##class(%File).GetDirectory(tTestRoot)_"/_data/simple-app/")
11-
Set tSC = ##class(%IPM.Main).Shell("load " _ tModuleDir)
12-
Do $$$AssertStatusOK(tSC,"Loaded SimpleApp module successfully. " _ tModuleDir)
13-
11+
set tSC = ##class(%IPM.Main).Shell("load " _ tModuleDir)
12+
do $$$AssertStatusOK(tSC,"Loaded SimpleApp module successfully. " _ tModuleDir)
13+
1414
#; Set tInstallInfo = ##class(%IPM.PackageManager.Core.InstallationInfo).%New()
1515
#; Set tInstallInfo.Namespace = "INTTEST"
1616
#; #; Set tInstallInfo.ModuleReference = tQualRef //tResults.GetAt(1)
@@ -20,50 +20,79 @@ Method TestSimpleApp()
2020
#; } Else {
2121
#; Do $$$LogMessage("Successfully cleaned up existing namespace with application installed.")
2222
#; }
23-
23+
2424
#; // Finally: Given a qualified module reference, install it.
2525
#; Set tSC = ##class(%IPM.Repo.Utils).InstallApplication(tInstallInfo)
26-
Quit:'$$$AssertStatusOK(tSC,"Successfully installed SimpleApp application.")
27-
} Catch e {
28-
Do $$$AssertStatusOK(e.AsStatus(),"An exception occurred.")
26+
quit:'$$$AssertStatusOK(tSC,"Successfully installed SimpleApp application.")
27+
} catch e {
28+
do $$$AssertStatusOK(e.AsStatus(),"An exception occurred.")
2929
}
3030
}
3131

3232
Method TestWSGIApp()
3333
{
34-
Set tSC = $$$OK
35-
Try {
36-
Set tVersion = $Piece($ZVersion," ",9)
37-
If $Piece(tVersion, ".", 1) < 2024 {
38-
Do $$$AssertSkipped("WSGI applications are only supported in 2024+. Current version: "_tVersion)
39-
Return
34+
set tSC = $$$OK
35+
try {
36+
set tVersion = $piece($zversion," ",9)
37+
if $piece(tVersion, ".", 1) < 2024 {
38+
do $$$AssertSkipped("WSGI applications are only supported in 2024+. Current version: "_tVersion)
39+
return
4040
}
41-
Set tTestRoot = ##class(%File).NormalizeDirectory($Get(^UnitTestRoot))
41+
set tTestRoot = ##class(%File).NormalizeDirectory($get(^UnitTestRoot))
4242
set tModuleDir = ##class(%File).NormalizeDirectory(##class(%File).GetDirectory(tTestRoot)_"/_data/wsgi-app/")
43-
Set tSC = ##class(%IPM.Main).Shell("load -verbose " _ tModuleDir)
44-
Do $$$AssertStatusOK(tSC,"Loaded WSGI Application successfully. " _ tModuleDir)
45-
Do $$$AssertStatusOK(..HttpGet("my/flask/demo/"))
46-
} Catch e {
47-
Do $$$AssertStatusOK(e.AsStatus(),"An exception occurred.")
43+
set tSC = ##class(%IPM.Main).Shell("load -verbose " _ tModuleDir)
44+
do $$$AssertStatusOK(tSC,"Loaded WSGI Application successfully. " _ tModuleDir)
45+
do $$$AssertStatusOK(..HttpGet("my/flask/demo/"))
46+
} catch e {
47+
do $$$AssertStatusOK(e.AsStatus(),"An exception occurred.")
4848
}
4949
}
5050

5151
Method TestRestApp()
5252
{
53-
Set tSC = $$$OK
54-
Try {
55-
Set tTestRoot = ##class(%File).NormalizeDirectory($Get(^UnitTestRoot))
53+
set tSC = $$$OK
54+
try {
55+
set tTestRoot = ##class(%File).NormalizeDirectory($get(^UnitTestRoot))
56+
57+
set tModuleDir1 = ##class(%File).NormalizeDirectory(##class(%File).GetDirectory(tTestRoot)_"/_data/rest-app/")
58+
set tSC = ##class(%IPM.Main).Shell("load -verbose " _ tModuleDir1)
59+
do $$$AssertStatusOK(tSC,"Loaded REST Application ""restdemo/"" successfully. " _ tModuleDir1)
60+
do $$$AssertStatusOK(..HttpGet("restdemo/"))
61+
62+
// Delete the 1st REST application
63+
set tSC = ##class(%IPM.Main).Shell("uninstall -verbose rest-demo")
64+
do $$$AssertStatusOK(tSC,"Deleted REST Application ""restdemo/"" successfully. " _ tModuleDir1)
65+
} catch e {
66+
do $$$AssertStatusOK(e.AsStatus(),"An exception occurred.")
67+
}
68+
}
69+
70+
Method TestRestAppNamespace()
71+
{
72+
set tSC = $$$OK
73+
try {
74+
set tTestRoot = ##class(%File).NormalizeDirectory($get(^UnitTestRoot))
75+
76+
set tModuleDir1 = ##class(%File).NormalizeDirectory(##class(%File).GetDirectory(tTestRoot)_"/_data/rest-app-ns/")
77+
set tSC = ##class(%IPM.Main).Shell("load -verbose " _ tModuleDir1)
78+
do $$$AssertStatusOK(tSC,"Loaded REST Application ""restdemons/"" successfully. " _ tModuleDir1)
79+
do $$$AssertStatusOK(..HttpGet("restdemons/"))
80+
81+
// verify the web application was created in the correct namespace
82+
set expectedNS = $namespace
83+
new $namespace
84+
set $namespace = "%SYS"
5685

57-
Set tModuleDir1 = ##class(%File).NormalizeDirectory(##class(%File).GetDirectory(tTestRoot)_"/_data/rest-app/")
58-
Set tSC = ##class(%IPM.Main).Shell("load -verbose " _ tModuleDir1)
59-
Do $$$AssertStatusOK(tSC,"Loaded REST Application ""restdemo/"" successfully. " _ tModuleDir1)
60-
Do $$$AssertStatusOK(..HttpGet("restdemo/"))
86+
$$$ThrowOnError(##class(Security.Applications).Get("/restdemons", .properties))
87+
set actualNS = $get(properties("NameSpace"))
88+
do $$$AssertEquals(expectedNS, actualNS, "Web application was created in the wrong namespace. Expected: "_expectedNS_" Actual: "_actualNS)
89+
set $namespace = expectedNS
6190

6291
// Delete the 1st REST application
63-
Set tSC = ##class(%IPM.Main).Shell("uninstall -verbose rest-demo")
64-
Do $$$AssertStatusOK(tSC,"Deleted REST Application ""restdemo/"" successfully. " _ tModuleDir1)
65-
} Catch e {
66-
Do $$$AssertStatusOK(e.AsStatus(),"An exception occurred.")
92+
set tSC = ##class(%IPM.Main).Shell("uninstall -verbose rest-demo-ns")
93+
do $$$AssertStatusOK(tSC,"Deleted REST Application ""restdemons/"" successfully. " _ tModuleDir1)
94+
} catch e {
95+
do $$$AssertStatusOK(e.AsStatus(),"An exception occurred.")
6796
}
6897
}
6998

tests/integration_tests/Test/PM/Integration/Update.cls

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -514,16 +514,21 @@ Method AssertModulePackagedCorrectly(
514514
version As %String,
515515
packageDir As %String)
516516
{
517-
// Initial install of module (necessary to be able to package)
518-
set sc = ##class(%IPM.Main).Shell("install "_moduleName_" "_version)
519-
do $$$AssertStatusOK(sc,"Installed "_moduleName_" version = "_version_" successfully for packaging.")
517+
// Initial install of module (necessary to be able to package)
518+
set sc = ##class(%IPM.Main).Shell("install "_moduleName_" "_version)
519+
do $$$AssertStatusOK(sc,"Installed "_moduleName_" version = "_version_" successfully for packaging.")
520520

521-
// Package module
522-
set sc = ##class(%IPM.Main).Shell(moduleName_" package -only -v -DPath="_packageDir)
523-
do $$$AssertStatusOK(sc, "Successfully packaged module "_moduleName_" to "_packageDir)
521+
// Package module
522+
set sc = ##class(%IPM.Main).Shell(moduleName_" package -only -v -DPath="_packageDir)
523+
do $$$AssertStatusOK(sc, "Successfully packaged module "_moduleName_" to "_packageDir)
524524

525-
// Uninstall module
526-
do ..CleanUp()
525+
// Unpack the tarball
526+
set tgzFile = $zstrip(packageDir,">","/\")_".tgz"
527+
set tSC = ##class(%IPM.General.Archive).Extract(tgzFile,packageDir,.tOutput)
528+
do $$$AssertStatusOK(tSC, "Unpackaged " _ tgzFile _ " to "_ packageDir)
529+
530+
// Uninstall module
531+
do ..CleanUp()
527532
}
528533

529534
ClassMethod InterruptedUpdateJobWrapper(
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<Export generator="Cache" version="25">
3+
<Document name="rest-demo-ns.ZPM">
4+
<Module>
5+
<Name>rest-demo-ns</Name>
6+
<Version>1.0.0</Version>
7+
<Description>This is a demo of a rest application</Description>
8+
<Keywords>rest</Keywords>
9+
<Author>
10+
<Person>Shuheng Liu</Person>
11+
<Organization>InterSystems</Organization>
12+
<CopyrightDate>2024</CopyrightDate>
13+
<License>MIT</License>
14+
<Notes>notes</Notes>
15+
</Author>
16+
<Packaging>module</Packaging>
17+
<SourcesRoot>src</SourcesRoot>
18+
19+
<Resource Name="Test.Rest.Demo.CLS"/>
20+
<WebApplication
21+
Name="/restdemons"
22+
Path="/src"
23+
Recurse="1"
24+
MatchRoles=":${dbrole}:%SQL:%All:%Developer,%Manager:%All"
25+
AutheEnabled="#{$$$AutheCache + $$$AutheUnauthenticated}"
26+
DispatchClass="Test.Rest.Demo"
27+
ServeFiles="1"
28+
CookiePath="/restdemons"
29+
UseCookies="2"
30+
/>
31+
<AfterInstallMessage>Module installed successfully!</AfterInstallMessage>
32+
</Module>
33+
</Document>
34+
</Export>
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
Class Test.Rest.Demo Extends %CSP.REST
2+
{
3+
4+
XData UrlMap [ XMLNamespace = "http://www.intersystems.com/urlmap" ]
5+
{
6+
<Routes>
7+
<Route Url="/" Method="GET" Call="GetInfo" Cors="true"/>
8+
</Routes>
9+
}
10+
11+
ClassMethod GetInfo() As %Status
12+
{
13+
Write "Hello, World!"
14+
Quit $$$OK
15+
}
16+
17+
}

tests/integration_tests/Test/PM/Integration/_data/rest-app/module.xml

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,20 +17,19 @@
1717
<SourcesRoot>src</SourcesRoot>
1818

1919
<Resource Name="Test.Rest.Demo.CLS"/>
20-
<WebApplication
20+
<WebApplication
2121
Name="/restdemo"
2222
NameSpace="{$namespace}"
2323
Path="/src"
2424
Recurse="1"
25-
Directory="{$cspdir}/restdemo"
2625
MatchRoles=":${dbrole}:%SQL:%All:%Developer,%Manager:%All"
2726
AutheEnabled="#{$$$AutheCache + $$$AutheUnauthenticated}"
2827
DispatchClass="Test.Rest.Demo"
2928
ServeFiles="1"
3029
CookiePath="/restdemo"
3130
UseCookies="2"
3231
/>
33-
<AfterInstallMessage>Module installed successfully!</AfterInstallMessage>
34-
</Module>
32+
<AfterInstallMessage>Module installed successfully!</AfterInstallMessage>
33+
</Module>
3534
</Document>
3635
</Export>

0 commit comments

Comments
 (0)