Skip to content

Commit f659310

Browse files
committed
fix(tomcat): propagate os.Stat errors and always remove ROOT.xml on non-root context_path
- os.Stat unexpected errors (non-IsNotExist) now returned as failures instead of silently treating the context XML as already existing - ROOT.xml removal now happens regardless of whether context XML was generated or already existed from external config, so non-root context_path always removes a stale ROOT.xml - Unit test added (TDD) for external-config + non-root ROOT.xml removal
1 parent 02f0fe1 commit f659310

2 files changed

Lines changed: 44 additions & 16 deletions

File tree

src/java/containers/tomcat.go

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -593,7 +593,11 @@ func (t *TomcatContainer) Finalize() error {
593593
return fmt.Errorf("failed to create context directory: %w", err)
594594
}
595595

596-
if _, statErr := os.Stat(contextXMLPath); os.IsNotExist(statErr) {
596+
_, statErr := os.Stat(contextXMLPath)
597+
if statErr != nil && !os.IsNotExist(statErr) {
598+
return fmt.Errorf("failed to check context XML %s: %w", contextXMLName, statErr)
599+
}
600+
if os.IsNotExist(statErr) {
597601
appContextXML := filepath.Join(buildDir, "META-INF", "context.xml")
598602
var contextContent string
599603

@@ -616,16 +620,15 @@ func (t *TomcatContainer) Finalize() error {
616620
if err := os.WriteFile(contextXMLPath, []byte(contextContent), 0644); err != nil {
617621
return fmt.Errorf("failed to write %s: %w", contextXMLName, err)
618622
}
619-
620-
if contextXMLName != "ROOT.xml" {
621-
rootXMLPath := filepath.Join(t.tomcatDir(), "conf", "Catalina", "localhost", "ROOT.xml")
622-
if err := os.Remove(rootXMLPath); err != nil && !os.IsNotExist(err) {
623-
return fmt.Errorf("failed to remove ROOT.xml: %w", err)
624-
}
625-
}
626623
} else {
627624
t.context.Log.Info("Context XML %s already exists (e.g. from external config), skipping generation", contextXMLName)
628625
}
626+
if contextXMLName != "ROOT.xml" {
627+
rootXMLPath := filepath.Join(t.tomcatDir(), "conf", "Catalina", "localhost", "ROOT.xml")
628+
if err := os.Remove(rootXMLPath); err != nil && !os.IsNotExist(err) {
629+
return fmt.Errorf("failed to remove ROOT.xml: %w", err)
630+
}
631+
}
629632
} else {
630633
warMatches, err := filepath.Glob(filepath.Join(buildDir, "*.war"))
631634
if err == nil && len(warMatches) == 1 {
@@ -637,21 +640,24 @@ func (t *TomcatContainer) Finalize() error {
637640
return fmt.Errorf("failed to create context directory: %w", err)
638641
}
639642

640-
if _, statErr := os.Stat(contextXMLPath); os.IsNotExist(statErr) {
643+
_, statErr := os.Stat(contextXMLPath)
644+
if statErr != nil && !os.IsNotExist(statErr) {
645+
return fmt.Errorf("failed to check context XML %s: %w", contextXMLName, statErr)
646+
}
647+
if os.IsNotExist(statErr) {
641648
if err := os.WriteFile(contextXMLPath, []byte(contextContent), 0644); err != nil {
642649
return fmt.Errorf("failed to write %s: %w", contextXMLName, err)
643650
}
644-
645-
if contextXMLName != "ROOT.xml" {
646-
rootXMLPath := filepath.Join(t.tomcatDir(), "conf", "Catalina", "localhost", "ROOT.xml")
647-
if err := os.Remove(rootXMLPath); err != nil && !os.IsNotExist(err) {
648-
return fmt.Errorf("failed to remove ROOT.xml: %w", err)
649-
}
650-
}
651651
t.context.Log.Info("Created %s with docBase pointing to %s", contextXMLName, warFilename)
652652
} else {
653653
t.context.Log.Info("Context XML %s already exists (e.g. from external config), skipping generation", contextXMLName)
654654
}
655+
if contextXMLName != "ROOT.xml" {
656+
rootXMLPath := filepath.Join(t.tomcatDir(), "conf", "Catalina", "localhost", "ROOT.xml")
657+
if err := os.Remove(rootXMLPath); err != nil && !os.IsNotExist(err) {
658+
return fmt.Errorf("failed to remove ROOT.xml: %w", err)
659+
}
660+
}
655661
} else if len(warMatches) > 1 {
656662
t.context.Log.Warning("Multiple WAR files found in build directory; context_path not applied")
657663
}

src/java/containers/tomcat_test.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,28 @@ var _ = Describe("Tomcat Container", func() {
279279
Expect(string(content)).To(Equal(preExistingContent))
280280
})
281281

282+
It("removes ROOT.xml even when non-root context XML already exists (external config)", func() {
283+
os.Setenv("JBP_CONFIG_TOMCAT", `{tomcat: {context_path: /my/path}}`)
284+
defer os.Unsetenv("JBP_CONFIG_TOMCAT")
285+
286+
tomcatDir := filepath.Join(depsDir, "0", "tomcat")
287+
contextDir := filepath.Join(tomcatDir, "conf", "Catalina", "localhost")
288+
Expect(os.MkdirAll(contextDir, 0755)).To(Succeed())
289+
externalContent := "<Context docBase=\"/external/path\"/>"
290+
contextXML := filepath.Join(contextDir, "my#path.xml")
291+
Expect(os.WriteFile(contextXML, []byte(externalContent), 0644)).To(Succeed())
292+
rootXML := filepath.Join(contextDir, "ROOT.xml")
293+
Expect(os.WriteFile(rootXML, []byte("<Context/>"), 0644)).To(Succeed())
294+
295+
err := container.Finalize()
296+
Expect(err).NotTo(HaveOccurred())
297+
298+
content, readErr := os.ReadFile(contextXML)
299+
Expect(readErr).NotTo(HaveOccurred())
300+
Expect(string(content)).To(Equal(externalContent))
301+
Expect(rootXML).NotTo(BeAnExistingFile())
302+
})
303+
282304
Context("with packaged WAR (no WEB-INF)", func() {
283305
BeforeEach(func() {
284306
Expect(os.RemoveAll(filepath.Join(buildDir, "WEB-INF"))).To(Succeed())

0 commit comments

Comments
 (0)