-
Notifications
You must be signed in to change notification settings - Fork 103
/
process.go
128 lines (109 loc) · 3.84 KB
/
process.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
package launch
import (
"fmt"
"github.com/pkg/errors"
"github.com/buildpacks/lifecycle/api"
)
// ProcessFor creates a process from container cmd
//
// If the Platform API if 0.4 or greater and DefaultProcess is set:
// * The default process is returned with `cmd` appended to the process args
// If the Platform API is less than 0.4
// * If there is exactly one argument and it matches a process type, it returns that process.
// * If cmd is empty, it returns the default process
// Else
// * it constructs a new process from cmd
// * If the first element in cmd is `cmd` the process shall be direct
func (l *Launcher) ProcessFor(cmd []string) (Process, error) {
if l.DefaultProcessType == "" {
process, err := l.userProvidedProcess(cmd)
if err != nil {
return Process{}, err
}
return process, nil
}
process, ok := l.findProcessType(l.DefaultProcessType)
if !ok {
return Process{}, fmt.Errorf("process type %s was not found", l.DefaultProcessType)
}
if l.PlatformAPI.LessThan("0.10") {
return l.handleUserArgsPlatformLessThan010(process, cmd)
}
return l.handleUserArgs(process, cmd)
}
func (l *Launcher) handleUserArgsPlatformLessThan010(process Process, userArgs []string) (Process, error) {
process.Args = append(process.Args, userArgs...)
return process, nil
}
func (l *Launcher) handleUserArgs(process Process, userArgs []string) (Process, error) {
switch {
case len(process.Command.Entries) > 1: // definitely newer buildpack
overridableArgs := process.Args
process.Args = process.Command.Entries[1:] // set always-provided args
process.Command.Entries = []string{process.Command.Entries[0]} // when exec'ing the process we always expect Command to have just one entry
if len(userArgs) > 0 {
process.Args = append(process.Args, userArgs...)
} else {
process.Args = append(process.Args, overridableArgs...)
}
case len(userArgs) == 0:
// nothing to do, we just provide whatever the original process args were
default:
// we have user-provided args, and we need to check the buildpack API to know how to handle them
bp, err := l.buildpackForProcess(process)
if err != nil {
return Process{}, err
}
if api.MustParse(bp.API).LessThan("0.9") {
process.Args = append(process.Args, userArgs...) // user-provided args are appended to process args
} else {
process.Args = userArgs // user-provided args replace process args
}
}
return process, nil
}
func (l *Launcher) buildpackForProcess(process Process) (Buildpack, error) {
for _, bp := range l.Buildpacks {
if bp.ID == process.BuildpackID {
return bp, nil
}
}
return Buildpack{}, fmt.Errorf("failed to find buildpack for process %s with buildpack ID %s", process.Type, process.BuildpackID)
}
func (l *Launcher) processForLegacy(cmd []string) (Process, error) {
if len(cmd) == 0 {
if process, ok := l.findProcessType(l.DefaultProcessType); ok {
return process, nil
}
return Process{}, fmt.Errorf("process type %s was not found", l.DefaultProcessType)
}
if len(cmd) == 1 {
if process, ok := l.findProcessType(cmd[0]); ok {
return process, nil
}
}
return l.userProvidedProcess(cmd)
}
func (l *Launcher) findProcessType(pType string) (Process, bool) {
for _, p := range l.Processes {
if p.Type == pType {
return p, true
}
}
return Process{}, false
}
func (l *Launcher) userProvidedProcess(cmd []string) (Process, error) {
if len(cmd) == 0 {
return Process{}, errors.New("when there is no default process a command is required")
}
if len(cmd) > 1 && cmd[0] == "--" {
return Process{Command: RawCommand{Entries: []string{cmd[1]}}, Args: cmd[2:], Direct: true}, nil
}
return Process{Command: RawCommand{Entries: []string{cmd[0]}}, Args: cmd[1:]}, nil
}
func getProcessWorkingDirectory(process Process, appDir string) string {
if process.WorkingDirectory == "" {
return appDir
}
return process.WorkingDirectory
}