Skip to content

Commit

Permalink
Merge branch 'main' into dependabot/go_modules/github.com/paketo-buil…
Browse files Browse the repository at this point in the history
…dpacks/libpak-1.50.1
  • Loading branch information
ekcasey authored Jan 21, 2021
2 parents f6c364c + 42b2c4e commit 8adc50b
Show file tree
Hide file tree
Showing 2 changed files with 238 additions and 204 deletions.
146 changes: 79 additions & 67 deletions native/native_image.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ type NativeImage struct {
ApplicationPath string
Arguments []string
Executor effect.Executor
LayerContributor libpak.LayerContributor
Logger bard.Logger
Manifest *properties.Properties
StackID string
Expand All @@ -49,89 +48,59 @@ type NativeImage struct {
func NewNativeImage(applicationPath string, arguments string, manifest *properties.Properties, stackID string) (NativeImage, error) {
var err error

expected := map[string]interface{}{}

expected["arguments"], err = shellwords.Parse(arguments)
args, err := shellwords.Parse(arguments)
if err != nil {
return NativeImage{}, fmt.Errorf("unable to parse arguments from %s\n%w", arguments, err)
}

expected["files"], err = sherpa.NewFileListing(applicationPath)
if err != nil {
return NativeImage{}, fmt.Errorf("unable to create file listing for %s\n%w", applicationPath, err)
}

n := NativeImage{
return NativeImage{
ApplicationPath: applicationPath,
Arguments: expected["arguments"].([]string),
Arguments: args,
Executor: effect.NewExecutor(),
LayerContributor: libpak.NewLayerContributor("Native Image", expected),
Manifest: manifest,
StackID: stackID,
}

return n, nil
}, nil
}

func (n NativeImage) Contribute(layer libcnb.Layer) (libcnb.Layer, error) {
n.LayerContributor.Logger = n.Logger

startClass, ok := n.Manifest.Get("Start-Class")
if !ok {
return libcnb.Layer{}, fmt.Errorf("manifest does not contain Start-Class")
}

layer, err := n.LayerContributor.Contribute(layer, func() (libcnb.Layer, error) {
cp := []string{n.ApplicationPath}

s, ok := n.Manifest.Get("Spring-Boot-Classes")
if !ok {
return libcnb.Layer{}, fmt.Errorf("manifest does not contain Spring-Boot-Classes")
}
cp = append(cp, filepath.Join(n.ApplicationPath, s))

s, ok = n.Manifest.Get("Spring-Boot-Classpath-Index")
if !ok {
return libcnb.Layer{}, fmt.Errorf("manifest does not contain Spring-Boot-Classpath-Index")
}

file := filepath.Join(n.ApplicationPath, s)
in, err := os.Open(file)
if err != nil {
return libcnb.Layer{}, fmt.Errorf("unable to open %s\n%w", file, err)
}
defer in.Close()

var libs []string
if err := yaml.NewDecoder(in).Decode(&libs); err != nil {
return libcnb.Layer{}, fmt.Errorf("unable to decode %s\n%w", file, err)
}
cp, err := n.classpath()
if err != nil {
return libcnb.Layer{}, fmt.Errorf("failed to compute classpath\n%w", err)
}

s, ok = n.Manifest.Get("Spring-Boot-Lib")
if !ok {
return libcnb.Layer{}, fmt.Errorf("manifest does not contain Spring-Boot-Lib")
}
if !n.hasSpringNative(cp) {
return libcnb.Layer{}, errors.New("application is missing required 'spring-native' dependency")
}

for _, l := range libs {
cp = append(cp, filepath.Join(n.ApplicationPath, s, l))
}
arguments := n.Arguments

if !n.hasSpringNative(libs) {
return libcnb.Layer{}, errors.New("application is missing required 'spring-native' dependency")
}
if n.StackID == libpak.TinyStackID {
arguments = append(arguments, "-H:+StaticExecutableWithDynamicLibC")
}

arguments := n.Arguments
arguments = append(arguments,
fmt.Sprintf("-H:Name=%s", filepath.Join(layer.Path, startClass)),
"-cp", strings.Join(cp, ":"),
startClass,
)

if n.StackID == libpak.TinyStackID {
arguments = append(arguments, "-H:+StaticExecutableWithDynamicLibC")
}
files, err := sherpa.NewFileListing(n.ApplicationPath)
if err != nil {
return libcnb.Layer{}, fmt.Errorf("unable to create file listing for %s\n%w", n.ApplicationPath, err)
}

arguments = append(arguments,
fmt.Sprintf("-H:Name=%s", filepath.Join(layer.Path, startClass)),
"-cp", strings.Join(cp, ":"),
startClass,
)
contributor := libpak.NewLayerContributor("Native Image", map[string]interface{}{
"files": files,
"arguments": arguments,
})
contributor.Logger = n.Logger

layer, err = contributor.Contribute(layer, func() (libcnb.Layer, error) {
if err := n.Executor.Execute(effect.Execution{
Command: "native-image",
Args: []string{"--version"},
Expand Down Expand Up @@ -171,17 +140,17 @@ func (n NativeImage) Contribute(layer libcnb.Layer) (libcnb.Layer, error) {
}
}

file := filepath.Join(layer.Path, startClass)
in, err := os.Open(file)
src := filepath.Join(layer.Path, startClass)
in, err := os.Open(src)
if err != nil {
return libcnb.Layer{}, fmt.Errorf("unable to open %s\n%w", file, err)
return libcnb.Layer{}, fmt.Errorf("unable to open %s\n%w", filepath.Join(layer.Path, startClass), err)
}
defer in.Close()

file = filepath.Join(n.ApplicationPath, startClass)
out, err := os.OpenFile(file, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0755)
dst := filepath.Join(n.ApplicationPath, startClass)
out, err := os.OpenFile(dst, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0755)
if err != nil {
return libcnb.Layer{}, fmt.Errorf("unable to open %s\n%w", file, err)
return libcnb.Layer{}, fmt.Errorf("unable to open %s\n%w", dst, err)
}
defer out.Close()

Expand All @@ -192,6 +161,49 @@ func (n NativeImage) Contribute(layer libcnb.Layer) (libcnb.Layer, error) {
return layer, nil
}

func (n NativeImage) classpath() ([]string, error) {
cp := []string{n.ApplicationPath}

classesDir, ok := n.Manifest.Get("Spring-Boot-Classes")
if !ok {
return nil, fmt.Errorf("manifest does not contain Spring-Boot-Classes")
}
cp = append(cp, filepath.Join(n.ApplicationPath, classesDir))

classpathIdx, ok := n.Manifest.Get("Spring-Boot-Classpath-Index")
if !ok {
return nil, fmt.Errorf("manifest does not contain Spring-Boot-Classpath-Index")
}

file := filepath.Join(n.ApplicationPath, classpathIdx)
in, err := os.Open(filepath.Join(n.ApplicationPath, classpathIdx))
if err != nil {
return nil, fmt.Errorf("unable to open %s\n%w", file, err)
}
defer in.Close()

var libs []string
if err := yaml.NewDecoder(in).Decode(&libs); err != nil {
return nil, fmt.Errorf("unable to decode %s\n%w", file, err)
}

libDir, ok := n.Manifest.Get("Spring-Boot-Lib")
if !ok {
return nil, fmt.Errorf("manifest does not contain Spring-Boot-Lib")
}

for _, l := range libs {
if dir, _ := filepath.Split(l); dir == "" {
// In Spring Boot version 2.3.0.M4 -> 2.4.2 classpath.idx contains a list of jars
cp = append(cp, filepath.Join(n.ApplicationPath, libDir, l))
} else {
// In Spring Boot version <= 2.3.0.M3 or >= 2.4.2 classpath.idx contains a list of relative paths to jars
cp = append(cp, filepath.Join(n.ApplicationPath, l))
}
}
return cp, nil
}

func (NativeImage) Name() string {
return "native-image"
}
Expand Down
Loading

0 comments on commit 8adc50b

Please sign in to comment.