Skip to content

Commit

Permalink
Split version detection from build
Browse files Browse the repository at this point in the history
  • Loading branch information
modulo11 committed Dec 20, 2021
1 parent 4425a66 commit eb10f2b
Show file tree
Hide file tree
Showing 5 changed files with 209 additions and 100 deletions.
46 changes: 2 additions & 44 deletions build.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@ func (b Build) Build(context libcnb.BuildContext) (libcnb.BuildResult, error) {
cl := NewCertificateLoader()
cl.Logger = b.Logger.BodyWriter()

v, err := b.getJVMVersion(context.Application.Path, cr)
jvmVersion := JVMVersion{Logger: b.Logger}
v, err := jvmVersion.GetJVMVersion(context.Application.Path, cr)
if err != nil {
return libcnb.BuildResult{}, fmt.Errorf("unable to determine jvm version\n%w", err)
}
Expand Down Expand Up @@ -174,46 +175,3 @@ func (b Build) warnIfJreNotUsed(jreAvailable, jreSkipped bool) {

b.Logger.Header(color.New(color.FgYellow, color.Bold).Sprint(msg))
}

func (b Build) getJVMVersion(appPath string, cr libpak.ConfigurationResolver) (string, error) {
version, explicit := cr.Resolve("BP_JVM_VERSION")

if !explicit {
manifest, err := NewManifest(appPath)
if err != nil {
return version, err
}

javaVersion := ""

buildJdkSpecVersion, ok := manifest.Get("Build-Jdk-Spec")
if ok {
javaVersion = buildJdkSpecVersion
}

buildJdkVersion, ok := manifest.Get("Build-Jdk")
if ok {
javaVersion = buildJdkVersion
}

if len(javaVersion) > 0 {
javaVersionFromMaven := extractMajorVersion(javaVersion)
f := color.New(color.Faint)
b.Logger.Header(f.Sprint("Context specific overrides:"))
b.Logger.Body(f.Sprintf("$BP_JVM_VERSION \t\t%s\t\tthe Java version, extracted from main class", javaVersionFromMaven))
return javaVersionFromMaven, nil
}
}

return version, nil
}

func extractMajorVersion(version string) string {
versionParts := strings.Split(version, ".")

if versionParts[0] == "1" {
return versionParts[1]
}

return versionParts[0]
}
56 changes: 0 additions & 56 deletions build_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,7 @@
package libjvm_test

import (
"bytes"
"encoding/binary"
"io/ioutil"
"os"
"path/filepath"
"testing"

"github.com/buildpacks/libcnb"
Expand Down Expand Up @@ -93,58 +89,6 @@ func testBuild(t *testing.T, context spec.G, it spec.S) {
Expect(result.BOM.Entries[1].Launch).To(BeTrue())
})

it("contributes JRE read from JAR", func() {
ctx.Plan.Entries = append(ctx.Plan.Entries, libcnb.BuildpackPlanEntry{Name: "jre", Metadata: LaunchContribution})
ctx.Buildpack.API = "0.6"
ctx.Buildpack.Metadata = map[string]interface{}{
"dependencies": []map[string]interface{}{
{
"id": "jre",
"version": "11",
"stacks": []interface{}{"test-stack-id"},
},
},
}
ctx.StackID = "test-stack-id"
temp, err := ioutil.TempDir("", "jre-application")
ctx.Application.Path = temp
Expect(err).NotTo(HaveOccurred())

defer os.RemoveAll(temp)

err = os.Mkdir(filepath.Join(temp, "META-INF"), 0744)
Expect(err).NotTo(HaveOccurred())
manifest := filepath.Join(temp, "META-INF", "MANIFEST.MF")
manifestContent := []byte("Main-Class: main")
err = ioutil.WriteFile(manifest, manifestContent, 0644)
Expect(err).NotTo(HaveOccurred())

classFile := filepath.Join(temp, "main.class")
classFileContent := bytes.NewBuffer(nil)
binary.Write(classFileContent, binary.BigEndian, uint8(0xCA))
binary.Write(classFileContent, binary.BigEndian, uint8(0xFE))
binary.Write(classFileContent, binary.BigEndian, uint8(0xBA))
binary.Write(classFileContent, binary.BigEndian, uint8(0xBE))
binary.Write(classFileContent, binary.BigEndian, uint16(0))
binary.Write(classFileContent, binary.BigEndian, uint16(55))
err = ioutil.WriteFile(classFile, classFileContent.Bytes(), 0666)
Expect(err).NotTo(HaveOccurred())

result, err := libjvm.Build{}.Build(ctx)
Expect(err).NotTo(HaveOccurred())

Expect(result.Layers).To(HaveLen(3))
Expect(result.Layers[0].Name()).To(Equal("jre"))
Expect(result.Layers[1].Name()).To(Equal("helper"))
Expect(result.Layers[2].Name()).To(Equal("java-security-properties"))

Expect(result.BOM.Entries).To(HaveLen(2))
Expect(result.BOM.Entries[0].Name).To(Equal("jre"))
Expect(result.BOM.Entries[0].Launch).To(BeTrue())
Expect(result.BOM.Entries[1].Name).To(Equal("helper"))
Expect(result.BOM.Entries[1].Launch).To(BeTrue())
})

it("contributes security-providers-classpath-8 before Java 9", func() {
ctx.Plan.Entries = append(ctx.Plan.Entries, libcnb.BuildpackPlanEntry{Name: "jre", Metadata: LaunchContribution})
ctx.Buildpack.Metadata = map[string]interface{}{
Expand Down
1 change: 1 addition & 0 deletions init_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,5 +41,6 @@ func TestUnit(t *testing.T) {
suite("Manifest", testManifest)
suite("MavenJARListing", testMavenJARListing)
suite("Versions", testVersions)
suite("JVMVersions", testJVMVersion)
suite.Run(t)
}
56 changes: 56 additions & 0 deletions jvm_version.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package libjvm

import (
"strings"

"github.com/heroku/color"
"github.com/paketo-buildpacks/libpak"
"github.com/paketo-buildpacks/libpak/bard"
)

type JVMVersion struct {
Logger bard.Logger
}

func (jvmVersion JVMVersion) GetJVMVersion(appPath string, cr libpak.ConfigurationResolver) (string, error) {
version, explicit := cr.Resolve("BP_JVM_VERSION")

if !explicit {
manifest, err := NewManifest(appPath)
if err != nil {
return version, err
}

javaVersion := ""

buildJdkSpecVersion, ok := manifest.Get("Build-Jdk-Spec")
if ok {
javaVersion = buildJdkSpecVersion
}

buildJdkVersion, ok := manifest.Get("Build-Jdk")
if ok {
javaVersion = buildJdkVersion
}

if len(javaVersion) > 0 {
javaVersionFromMaven := extractMajorVersion(javaVersion)
f := color.New(color.Faint)
jvmVersion.Logger.Header(f.Sprint("Context specific overrides:"))
jvmVersion.Logger.Body(f.Sprintf("$BP_JVM_VERSION \t\t %s \t\tthe Java version, extracted from main class", javaVersionFromMaven))
return javaVersionFromMaven, nil
}
}

return version, nil
}

func extractMajorVersion(version string) string {
versionParts := strings.Split(version, ".")

if versionParts[0] == "1" {
return versionParts[1]
}

return versionParts[0]
}
150 changes: 150 additions & 0 deletions jvm_version_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
/*
* Copyright 2018-2020 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package libjvm_test

import (
"github.com/paketo-buildpacks/libpak"
"github.com/paketo-buildpacks/libpak/bard"
"io/ioutil"
"os"
"path/filepath"
"testing"

"github.com/buildpacks/libcnb"
. "github.com/onsi/gomega"
"github.com/sclevine/spec"

"github.com/paketo-buildpacks/libjvm"
)

func testJVMVersion(t *testing.T, context spec.G, it spec.S) {
var (
Expect = NewWithT(t).Expect
appPath string
logger bard.Logger
buildpack libcnb.Buildpack
)

it.Before(func() {
buildpack = libcnb.Buildpack{
Metadata: map[string]interface{}{
"configurations": []map[string]interface{}{
{
"name": "BP_JVM_VERSION",
"default": "1.1.1",
},
},
},
}
logger = bard.NewLogger(ioutil.Discard)
})

it("detecting JVM version from default", func() {
jvmVersion := libjvm.JVMVersion{Logger: logger}

cr, err := libpak.NewConfigurationResolver(buildpack, &logger)
Expect(err).ToNot(HaveOccurred())
version, err := jvmVersion.GetJVMVersion(appPath, cr)
Expect(err).ToNot(HaveOccurred())
Expect(version).To(Equal("1.1.1"))
})

context("detecting JVM version", func() {
it.Before(func() {
Expect(os.Setenv("BP_JVM_VERSION", "17")).To(Succeed())
})

it.After(func() {
Expect(os.Unsetenv("BP_JVM_VERSION")).To(Succeed())
})

it("from environment variable", func() {
jvmVersion := libjvm.JVMVersion{Logger: logger}

cr, err := libpak.NewConfigurationResolver(buildpack, &logger)
Expect(err).ToNot(HaveOccurred())
version, err := jvmVersion.GetJVMVersion(appPath, cr)
Expect(err).ToNot(HaveOccurred())
Expect(version).To(Equal("17"))
})
})

context("detecting JVM version", func() {
it.Before(func() {
temp, err := prepareAppWithEntry("Build-Jdk: 1.8")
Expect(err).ToNot(HaveOccurred())
appPath = temp
})

it.After(func() {
os.RemoveAll(appPath)
})

it("from manifest via Build-Jdk-Spec", func() {
jvmVersion := libjvm.JVMVersion{Logger: logger}

cr, err := libpak.NewConfigurationResolver(buildpack, &logger)
Expect(err).ToNot(HaveOccurred())
version, err := jvmVersion.GetJVMVersion(appPath, cr)
Expect(err).ToNot(HaveOccurred())
Expect(version).To(Equal("8"))
})
})

context("detecting JVM version", func() {
it.Before(func() {
Expect(os.Setenv("BP_JVM_VERSION", "17")).To(Succeed())
temp, err := prepareAppWithEntry("Build-Jdk: 1.8")
Expect(err).ToNot(HaveOccurred())
appPath = temp
})

it.After(func() {
Expect(os.Unsetenv("BP_JVM_VERSION")).To(Succeed())
os.RemoveAll(appPath)
})

it("prefers environment variable over manifest", func() {
jvmVersion := libjvm.JVMVersion{Logger: logger}

cr, err := libpak.NewConfigurationResolver(buildpack, &logger)
Expect(err).ToNot(HaveOccurred())
version, err := jvmVersion.GetJVMVersion(appPath, cr)
Expect(err).ToNot(HaveOccurred())
Expect(version).To(Equal("17"))
})
})

}

func prepareAppWithEntry(entry string) (string, error) {
temp, err := ioutil.TempDir("", "jre-app")
if err != nil {
return "", err
}
err = os.Mkdir(filepath.Join(temp, "META-INF"), 0744)
if err != nil {
return "", err
}
manifest := filepath.Join(temp, "META-INF", "MANIFEST.MF")
manifestContent := []byte(entry)
err = ioutil.WriteFile(manifest, manifestContent, 0644)
if err != nil {
return "", err
}
return temp, nil
}

0 comments on commit eb10f2b

Please sign in to comment.