Skip to content

Commit

Permalink
Merge pull request #375 from sap-contributions/additional-jars
Browse files Browse the repository at this point in the history
Introduce BPI_TOMCAT_ADDITIONAL_JARS to enable adding JARs to CLASSPATH
  • Loading branch information
anthonydahanne authored Oct 26, 2023
2 parents 26ca199 + 77971b8 commit 4c98f58
Show file tree
Hide file tree
Showing 3 changed files with 106 additions and 40 deletions.
25 changes: 24 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ When this buildpack runs on the [Tiny stack](https://paketo.io/docs/concepts/sta
| `$BP_TOMCAT_EXT_CONF_VERSION` | The version of the external configuration package |
| `$BP_TOMCAT_VERSION` | Configure a specific Tomcat version. This value must _exactly_ match a version available in the buildpack so typically it would configured to a wildcard such as `9.*`. |
| `BPL_TOMCAT_ACCESS_LOGGING_ENABLED` | Whether access logging should be activated. Defaults to inactive. |
| `BPI_TOMCAT_ADDITIONAL_JARS` | This should only be used in other buildpacks to include a `jar` to the tomcat classpath. Several `jars` must be separated by `:`. |

### External Configuration Package
The artifacts that the repository provides must be in TAR format and must follow the Tomcat archive structure:
Expand All @@ -69,8 +70,30 @@ The buildpack optionally accepts the following bindings:
| --------------------- | ------- | ------------------------------------------------------------------------------------------------- |
| `<dependency-digest>` | `<uri>` | If needed, the buildpack will fetch the dependency with digest `<dependency-digest>` from `<uri>` |

## Providing Additional JARs to Tomcat

Buildpacks can contribute JARs to the `CLASSPATH` of Tomcat by appending a path to `BPI_TOMCAT_ADDITIONAL_JARS`.

```go
func (s) Contribute(layer libcnb.Layer) (libcnb.Layer, error) {
// Copy dependency into the layer
file := filepath.Join(layer.Path, filepath.Base(s.Dependency.URI))

layer, err := s.LayerContributor.Contribute(layer, func(artifact *os.File) (libcnb.Layer, error) {
if err := sherpa.CopyFile(artifact, file); err != nil {
return libcnb.Layer{}, fmt.Errorf("unable to copy artifact to %s\n%w", file, err)
}
return layer, nil
})

additionalJars := []string{file}
// Add dependency to BPI_TOMCAT_ADDITIONAL_JARS
layer.LaunchEnvironment.Append("BPI_TOMCAT_ADDITIONAL_JARS", ":", strings.Join(additionalJars, ":"))
return layer, nil
}
```

## License
This buildpack is released under version 2.0 of the [Apache License][a].

[a]: http://www.apache.org/licenses/LICENSE-2.0

9 changes: 8 additions & 1 deletion tomcat/base.go
Original file line number Diff line number Diff line change
Expand Up @@ -331,7 +331,14 @@ func (b Base) ContributeLogging(layer libcnb.Layer) error {

b.Logger.Bodyf("Writing %s/bin/setenv.sh", layer.Path)

s := fmt.Sprintf(`CLASSPATH="%s"`, file)
var s string
additionalJars, ok := os.LookupEnv("BPI_TOMCAT_ADDITIONAL_JARS")
if ok {
b.Logger.Bodyf("found BPI_TOMCAT_ADDITIONAL_JARS %q", additionalJars)
s = fmt.Sprintf(`CLASSPATH="%s:%s"`, file, additionalJars)
} else {
s = fmt.Sprintf(`CLASSPATH="%s"`, file)
}

file = filepath.Join(layer.Path, "bin", "setenv.sh")
if err = os.WriteFile(file, []byte(s), 0755); err != nil {
Expand Down
112 changes: 74 additions & 38 deletions tomcat/base_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,15 +48,7 @@ func testBase(t *testing.T, context spec.G, it spec.S) {

ctx.Layers.Path, err = os.MkdirTemp("", "base-layers")
Expect(err).NotTo(HaveOccurred())
})

it.After(func() {
Expect(os.RemoveAll(ctx.Application.Path)).To(Succeed())
Expect(os.RemoveAll(ctx.Buildpack.Path)).To(Succeed())
Expect(os.RemoveAll(ctx.Layers.Path)).To(Succeed())
})

it("contributes catalina base", func() {
Expect(os.MkdirAll(filepath.Join(ctx.Buildpack.Path, "resources"), 0755)).To(Succeed())
Expect(os.WriteFile(filepath.Join(ctx.Buildpack.Path, "resources", "context.xml"), []byte{}, 0644)).
To(Succeed())
Expand All @@ -66,7 +58,15 @@ func testBase(t *testing.T, context spec.G, it spec.S) {
To(Succeed())
Expect(os.WriteFile(filepath.Join(ctx.Buildpack.Path, "resources", "web.xml"), []byte{}, 0644)).
To(Succeed())
})

it.After(func() {
Expect(os.RemoveAll(ctx.Application.Path)).To(Succeed())
Expect(os.RemoveAll(ctx.Buildpack.Path)).To(Succeed())
Expect(os.RemoveAll(ctx.Layers.Path)).To(Succeed())
})

it("contributes catalina base", func() {
accessLoggingDep := libpak.BuildpackDependency{
ID: "tomcat-access-logging-support",
URI: "https://localhost/stub-tomcat-access-logging-support.jar",
Expand Down Expand Up @@ -144,16 +144,6 @@ func testBase(t *testing.T, context spec.G, it spec.S) {
})

it("contributes custom configuration", func() {
Expect(os.MkdirAll(filepath.Join(ctx.Buildpack.Path, "resources"), 0755)).To(Succeed())
Expect(os.WriteFile(filepath.Join(ctx.Buildpack.Path, "resources", "context.xml"), []byte{}, 0644)).
To(Succeed())
Expect(os.WriteFile(filepath.Join(ctx.Buildpack.Path, "resources", "logging.properties"), []byte{}, 0644)).
To(Succeed())
Expect(os.WriteFile(filepath.Join(ctx.Buildpack.Path, "resources", "server.xml"), []byte{}, 0644)).
To(Succeed())
Expect(os.WriteFile(filepath.Join(ctx.Buildpack.Path, "resources", "web.xml"), []byte{}, 0644)).
To(Succeed())

externalConfigurationDep := libpak.BuildpackDependency{
ID: "tomcat-external-configuration",
URI: "https://localhost/stub-external-configuration.tar.gz",
Expand Down Expand Up @@ -219,16 +209,6 @@ func testBase(t *testing.T, context spec.G, it spec.S) {
})

it("contributes custom configuration with directory", func() {
Expect(os.MkdirAll(filepath.Join(ctx.Buildpack.Path, "resources"), 0755)).To(Succeed())
Expect(os.WriteFile(filepath.Join(ctx.Buildpack.Path, "resources", "context.xml"), []byte{}, 0644)).
To(Succeed())
Expect(os.WriteFile(filepath.Join(ctx.Buildpack.Path, "resources", "logging.properties"), []byte{}, 0644)).
To(Succeed())
Expect(os.WriteFile(filepath.Join(ctx.Buildpack.Path, "resources", "server.xml"), []byte{}, 0644)).
To(Succeed())
Expect(os.WriteFile(filepath.Join(ctx.Buildpack.Path, "resources", "web.xml"), []byte{}, 0644)).
To(Succeed())

externalConfigurationDep := libpak.BuildpackDependency{
ID: "tomcat-external-configuration",
URI: "https://localhost/stub-external-configuration-with-directory.tar.gz",
Expand Down Expand Up @@ -295,16 +275,6 @@ func testBase(t *testing.T, context spec.G, it spec.S) {
})

it("environment property source can be disabled", func() {
Expect(os.MkdirAll(filepath.Join(ctx.Buildpack.Path, "resources"), 0755)).To(Succeed())
Expect(os.WriteFile(filepath.Join(ctx.Buildpack.Path, "resources", "context.xml"), []byte{}, 0644)).
To(Succeed())
Expect(os.WriteFile(filepath.Join(ctx.Buildpack.Path, "resources", "logging.properties"), []byte{}, 0644)).
To(Succeed())
Expect(os.WriteFile(filepath.Join(ctx.Buildpack.Path, "resources", "server.xml"), []byte{}, 0644)).
To(Succeed())
Expect(os.WriteFile(filepath.Join(ctx.Buildpack.Path, "resources", "web.xml"), []byte{}, 0644)).
To(Succeed())

accessLoggingDep := libpak.BuildpackDependency{
ID: "tomcat-access-logging-support",
URI: "https://localhost/stub-tomcat-access-logging-support.jar",
Expand Down Expand Up @@ -382,4 +352,70 @@ func testBase(t *testing.T, context spec.G, it spec.S) {
})

})

context("$BPI_TOMCAT_ADDITIONAL_JARS is set", func() {
it.Before(func() {
t.Setenv("BPI_TOMCAT_ADDITIONAL_JARS", "/layers/test-buildpack/foo/bar.jar")
})

it("additional jar is added to classpath", func() {
accessLoggingDep := libpak.BuildpackDependency{
ID: "tomcat-access-logging-support",
URI: "https://localhost/stub-tomcat-access-logging-support.jar",
SHA256: "d723bfe2ba67dfa92b24e3b6c7b2d0e6a963de7313350e306d470e44e330a5d2",
PURL: "pkg:generic/[email protected]",
CPEs: []string{"cpe:2.3:a:cloudfoundry:tomcat-access-logging-support:3.3.0:*:*:*:*:*:*:*"},
}
lifecycleDep := libpak.BuildpackDependency{
ID: "tomcat-lifecycle-support",
URI: "https://localhost/stub-tomcat-lifecycle-support.jar",
SHA256: "723126712c0b22a7fe409664adf1fbb78cf3040e313a82c06696f5058e190534",
PURL: "pkg:generic/[email protected]",
CPEs: []string{"cpe:2.3:a:cloudfoundry:tomcat-lifecycle-support:3.3.0:*:*:*:*:*:*:*"},
}
loggingDep := libpak.BuildpackDependency{
ID: "tomcat-logging-support",
URI: "https://localhost/stub-tomcat-logging-support.jar",
SHA256: "e0a7e163cc9f1ffd41c8de3942c7c6b505090b7484c2ba9be846334e31c44a2c",
PURL: "pkg:generic/[email protected]",
CPEs: []string{"cpe:2.3:a:cloudfoundry:tomcat-logging-support:3.3.0:*:*:*:*:*:*:*"},
}

dc := libpak.DependencyCache{CachePath: "testdata"}

contributor, entries := tomcat.NewBase(
ctx.Application.Path,
ctx.Buildpack.Path,
libpak.ConfigurationResolver{},
"test-context-path",
accessLoggingDep,
nil,
lifecycleDep,
loggingDep,
dc,
)

Expect(entries).To(HaveLen(3))
Expect(entries[0].Name).To(Equal("tomcat-access-logging-support"))
Expect(entries[0].Build).To(BeFalse())
Expect(entries[0].Launch).To(BeTrue())
Expect(entries[1].Name).To(Equal("tomcat-lifecycle-support"))
Expect(entries[1].Build).To(BeFalse())
Expect(entries[1].Launch).To(BeTrue())
Expect(entries[2].Name).To(Equal("tomcat-logging-support"))
Expect(entries[2].Build).To(BeFalse())
Expect(entries[2].Launch).To(BeTrue())

layer, err := ctx.Layers.Layer("test-layer")
Expect(err).NotTo(HaveOccurred())

layer, err = contributor.Contribute(layer)
Expect(err).NotTo(HaveOccurred())

Expect(os.ReadFile(filepath.Join(layer.Path, "bin", "setenv.sh"))).To(Equal(
[]byte(fmt.Sprintf(`CLASSPATH="%s:%s"`, filepath.Join(layer.Path, "bin", "stub-tomcat-logging-support.jar"), "/layers/test-buildpack/foo/bar.jar"))))
})

})

}

0 comments on commit 4c98f58

Please sign in to comment.