Skip to content

Commit 03a881f

Browse files
authored
Merge pull request #1213 from mshlyukarski/patch-distzip-container
[go-migration] Updated distZip container functionality.
2 parents 67a8514 + 45d77f5 commit 03a881f

2 files changed

Lines changed: 151 additions & 88 deletions

File tree

src/java/containers/dist_zip.go

Lines changed: 101 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -24,65 +24,97 @@ func NewDistZipContainer(ctx *common.Context) *DistZipContainer {
2424

2525
// Detect checks if this is a Dist ZIP application
2626
func (d *DistZipContainer) Detect() (string, error) {
27+
matches, err := d.findDistZipMatches()
28+
if err != nil {
29+
return "", err
30+
}
31+
32+
if len(matches) == 0 {
33+
return "", nil
34+
}
35+
36+
if len(matches) > 1 {
37+
d.context.Log.Debug("Rejecting Dist ZIP detection - multiple bin/lib structures detected")
38+
return "", nil
39+
}
40+
41+
d.startScript = matches[0]
42+
d.context.Log.Debug("Detected Dist ZIP application with start script: %s", d.startScript)
43+
return "Dist ZIP", nil
44+
}
45+
46+
func (d *DistZipContainer) findDistZipMatches() ([]string, error) {
2747
buildDir := d.context.Stager.BuildDir()
48+
type candidate struct {
49+
abs string
50+
rel string
51+
}
2852

29-
// Check for bin/ and lib/ directories at root (typical distZip structure)
30-
binDir := filepath.Join(buildDir, "bin")
31-
libDir := filepath.Join(buildDir, "lib")
53+
candidates := []candidate{{abs: buildDir}}
3254

33-
binStat, binErr := os.Stat(binDir)
34-
libStat, libErr := os.Stat(libDir)
55+
entries, err := os.ReadDir(buildDir)
56+
if err != nil {
57+
d.context.Log.Debug("Unable to list build dir for Dist ZIP detection: %s", err.Error())
58+
} else {
59+
for _, entry := range entries {
60+
if entry.IsDir() {
61+
candidates = append(candidates, candidate{
62+
abs: filepath.Join(buildDir, entry.Name()),
63+
rel: entry.Name(),
64+
})
65+
}
66+
}
67+
}
68+
69+
var matches []string
70+
for _, c := range candidates {
71+
binDir := filepath.Join(c.abs, "bin")
72+
libDir := filepath.Join(c.abs, "lib")
73+
74+
if !isDir(binDir) || !isDir(libDir) {
75+
continue
76+
}
3577

36-
if binErr == nil && libErr == nil && binStat.IsDir() && libStat.IsDir() {
37-
// Exclude Play Framework applications
3878
if d.isPlayFramework(libDir) {
39-
d.context.Log.Debug("Rejecting Dist ZIP detection - Play Framework JAR found")
40-
return "", nil
79+
d.context.Log.Debug("Rejecting Dist ZIP detection - Play Framework JAR found in %s", libDir)
80+
continue
4181
}
4282

43-
// Check for startup scripts in bin/
44-
entries, err := os.ReadDir(binDir)
45-
if err == nil && len(entries) > 0 {
46-
// Find a non-.bat script (Unix startup script)
47-
for _, entry := range entries {
48-
if !entry.IsDir() && filepath.Ext(entry.Name()) != ".bat" {
49-
d.startScript = entry.Name()
50-
d.context.Log.Debug("Detected Dist ZIP application with start script: %s", d.startScript)
51-
return "Dist ZIP", nil
52-
}
53-
}
83+
script := findUnixStartScript(binDir)
84+
if script == "" {
85+
continue
5486
}
87+
88+
relPath := filepath.Join(c.rel, "bin", script)
89+
relPath = strings.TrimPrefix(relPath, string(filepath.Separator))
90+
matches = append(matches, relPath)
5591
}
5692

57-
// Check for bin/ and lib/ directories in application-root (alternative structure)
58-
binDirApp := filepath.Join(buildDir, "application-root", "bin")
59-
libDirApp := filepath.Join(buildDir, "application-root", "lib")
93+
return matches, nil
94+
}
6095

61-
binStatApp, binErrApp := os.Stat(binDirApp)
62-
libStatApp, libErrApp := os.Stat(libDirApp)
96+
func isDir(path string) bool {
97+
info, err := os.Stat(path)
98+
if err != nil {
99+
return false
100+
}
101+
return info.IsDir()
102+
}
63103

64-
if binErrApp == nil && libErrApp == nil && binStatApp.IsDir() && libStatApp.IsDir() {
65-
// Exclude Play Framework applications
66-
if d.isPlayFramework(libDirApp) {
67-
d.context.Log.Debug("Rejecting Dist ZIP detection - Play Framework JAR found in application-root")
68-
return "", nil
69-
}
104+
func findUnixStartScript(binDir string) string {
105+
entries, err := os.ReadDir(binDir)
106+
if err != nil {
107+
return ""
108+
}
70109

71-
// Check for startup scripts in bin/
72-
entriesApp, errApp := os.ReadDir(binDirApp)
73-
if errApp == nil && len(entriesApp) > 0 {
74-
// Find a non-.bat script (Unix startup script)
75-
for _, entry := range entriesApp {
76-
if !entry.IsDir() && filepath.Ext(entry.Name()) != ".bat" {
77-
d.startScript = filepath.Join("application-root", "bin", entry.Name())
78-
d.context.Log.Debug("Detected Dist ZIP application (application-root) with start script: %s", d.startScript)
79-
return "Dist ZIP", nil
80-
}
81-
}
110+
for _, entry := range entries {
111+
if entry.IsDir() || filepath.Ext(entry.Name()) == ".bat" {
112+
continue
82113
}
114+
return entry.Name()
83115
}
84116

85-
return "", nil
117+
return ""
86118
}
87119

88120
// isPlayFramework checks if a lib directory contains Play Framework JARs
@@ -132,30 +164,30 @@ func (d *DistZipContainer) Supply() error {
132164
func (d *DistZipContainer) makeScriptsExecutable() error {
133165
buildDir := d.context.Stager.BuildDir()
134166

135-
// Try root bin/ directory
136-
binDir := filepath.Join(buildDir, "bin")
137-
entries, err := os.ReadDir(binDir)
138-
if err == nil {
139-
for _, entry := range entries {
140-
if !entry.IsDir() && filepath.Ext(entry.Name()) != ".bat" {
141-
scriptPath := filepath.Join(binDir, entry.Name())
142-
if err := os.Chmod(scriptPath, 0755); err != nil {
143-
d.context.Log.Warning("Could not make %s executable: %s", entry.Name(), err.Error())
144-
}
145-
}
167+
binDirs := map[string]struct{}{
168+
filepath.Join(buildDir, "bin"): {},
169+
filepath.Join(buildDir, "application-root", "bin"): {},
170+
}
171+
172+
if d.startScript != "" {
173+
scriptDir := filepath.Dir(d.startScript)
174+
if scriptDir != "" && scriptDir != "." {
175+
binDirs[filepath.Join(buildDir, scriptDir)] = struct{}{}
146176
}
147177
}
148178

149-
// Try application-root/bin/ directory
150-
binDirApp := filepath.Join(buildDir, "application-root", "bin")
151-
entriesApp, errApp := os.ReadDir(binDirApp)
152-
if errApp == nil {
153-
for _, entry := range entriesApp {
154-
if !entry.IsDir() && filepath.Ext(entry.Name()) != ".bat" {
155-
scriptPath := filepath.Join(binDirApp, entry.Name())
156-
if err := os.Chmod(scriptPath, 0755); err != nil {
157-
d.context.Log.Warning("Could not make %s executable: %s", entry.Name(), err.Error())
158-
}
179+
for dir := range binDirs {
180+
entries, err := os.ReadDir(dir)
181+
if err != nil {
182+
continue
183+
}
184+
for _, entry := range entries {
185+
if entry.IsDir() || filepath.Ext(entry.Name()) == ".bat" {
186+
continue
187+
}
188+
scriptPath := filepath.Join(dir, entry.Name())
189+
if err := os.Chmod(scriptPath, 0755); err != nil {
190+
d.context.Log.Warning("Could not make %s executable: %s", scriptPath, err.Error())
159191
}
160192
}
161193
}
@@ -168,15 +200,11 @@ func (d *DistZipContainer) Finalize() error {
168200
d.context.Log.BeginStep("Finalizing Dist ZIP")
169201
d.context.Log.Info("DistZip Finalize: Starting (startScript=%s)", d.startScript)
170202

171-
// Determine the script directory based on start script location
172-
var scriptDir string
173-
if strings.Contains(d.startScript, "/") {
174-
// application-root case: extract directory from script path
175-
scriptDir = filepath.Dir(d.startScript)
176-
} else {
177-
// root structure case: script in bin/
203+
scriptDir := filepath.Dir(d.startScript)
204+
if scriptDir == "" || scriptDir == "." {
178205
scriptDir = "bin"
179206
}
207+
scriptDir = filepath.ToSlash(scriptDir)
180208

181209
// Collect additional libraries (JVMKill agent, frameworks, etc.)
182210
additionalLibs := d.collectAdditionalLibraries()
@@ -323,23 +351,8 @@ func (d *DistZipContainer) Release() (string, error) {
323351
}
324352
}
325353

326-
// Determine the script directory based on start script location
327-
var scriptDir string
328-
if strings.Contains(d.startScript, "/") {
329-
// application-root case: extract directory from script path
330-
scriptDir = filepath.Dir(d.startScript)
331-
} else {
332-
// root structure case: script in bin/
333-
scriptDir = "bin"
334-
}
335-
336-
// Extract just the script name (remove any directory path)
337-
scriptName := filepath.Base(d.startScript)
338-
339-
// Use absolute path $HOME/<scriptDir>/<scriptName>
340-
// This eliminates dependency on profile.d script execution order
341-
// At runtime, CF makes the application available at $HOME
342-
cmd := fmt.Sprintf("$HOME/%s/%s", scriptDir, scriptName)
354+
scriptPath := filepath.ToSlash(d.startScript)
355+
cmd := fmt.Sprintf("$HOME/%s", scriptPath)
343356

344357
return cmd, nil
345358
}

src/java/containers/dist_zip_test.go

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,40 @@ var _ = Describe("Dist ZIP Container", func() {
9797
Expect(name).To(BeEmpty())
9898
})
9999
})
100+
101+
Context("with bin/ and lib/ inside an immediate subdirectory", func() {
102+
BeforeEach(func() {
103+
nested := filepath.Join(buildDir, "my-app-1.0")
104+
os.MkdirAll(filepath.Join(nested, "bin"), 0755)
105+
os.MkdirAll(filepath.Join(nested, "lib"), 0755)
106+
os.WriteFile(filepath.Join(nested, "bin", "launcher"), []byte("#!/bin/sh"), 0755)
107+
})
108+
109+
It("detects as Dist ZIP", func() {
110+
name, err := container.Detect()
111+
Expect(err).NotTo(HaveOccurred())
112+
Expect(name).To(Equal("Dist ZIP"))
113+
})
114+
})
115+
116+
Context("with multiple bin/lib structures", func() {
117+
BeforeEach(func() {
118+
os.MkdirAll(filepath.Join(buildDir, "bin"), 0755)
119+
os.MkdirAll(filepath.Join(buildDir, "lib"), 0755)
120+
os.WriteFile(filepath.Join(buildDir, "bin", "start"), []byte("#!/bin/sh"), 0755)
121+
122+
nested := filepath.Join(buildDir, "second")
123+
os.MkdirAll(filepath.Join(nested, "bin"), 0755)
124+
os.MkdirAll(filepath.Join(nested, "lib"), 0755)
125+
os.WriteFile(filepath.Join(nested, "bin", "launcher"), []byte("#!/bin/sh"), 0755)
126+
})
127+
128+
It("does not detect", func() {
129+
name, err := container.Detect()
130+
Expect(err).NotTo(HaveOccurred())
131+
Expect(name).To(BeEmpty())
132+
})
133+
})
100134
})
101135

102136
Describe("Release", func() {
@@ -130,6 +164,22 @@ var _ = Describe("Dist ZIP Container", func() {
130164
})
131165
})
132166

167+
Context("with start script in immediate subdirectory", func() {
168+
BeforeEach(func() {
169+
nested := filepath.Join(buildDir, "custom")
170+
os.MkdirAll(filepath.Join(nested, "bin"), 0755)
171+
os.MkdirAll(filepath.Join(nested, "lib"), 0755)
172+
os.WriteFile(filepath.Join(nested, "bin", "run"), []byte("#!/bin/sh"), 0755)
173+
container.Detect()
174+
})
175+
176+
It("uses absolute path with $HOME prefix", func() {
177+
cmd, err := container.Release()
178+
Expect(err).NotTo(HaveOccurred())
179+
Expect(cmd).To(Equal("$HOME/custom/bin/run"))
180+
})
181+
})
182+
133183
Context("with no start script detected", func() {
134184
It("returns error", func() {
135185
_, err := container.Release()

0 commit comments

Comments
 (0)