Skip to content

Commit

Permalink
COH-24004 - The Operator runner should support the JIB JVM argument f…
Browse files Browse the repository at this point in the history
…iles (#507)
  • Loading branch information
dhirupandey authored Sep 24, 2021
1 parent 8e03f50 commit 86b5c28
Show file tree
Hide file tree
Showing 4 changed files with 285 additions and 5 deletions.
2 changes: 1 addition & 1 deletion java/operator-test-helidon/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@
<version>${version.plugin.jib}</version>
<configuration>
<container>
<mainClass>io.helidon.microprofile.cdi.com.oracle.coherence.k8s.testing.Main</mainClass>
<mainClass>io.helidon.microprofile.server.Main</mainClass>
</container>
<!-- MUST use packaged mode for Helidon CDI application -->
<containerizingMode>packaged</containerizingMode>
Expand Down
11 changes: 11 additions & 0 deletions pkg/runner/cmd_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,17 @@ func server(details *RunDetails, _ *cobra.Command) {
// If the main class environment variable is set then use that
// otherwise run Coherence DCS.
mc, found := details.lookupEnv(v1.EnvVarAppMainClass)
appDir := details.getenvOrDefault(v1.EnvVarCohAppDir, "/app")
jibMainClassFileName := appDir + "/jib-main-class-file"
fi, err := os.Stat(jibMainClassFileName)
mainCls := ""
if err == nil && (fi.Size() != 0) {
mainCls = readFirstLineFromFile(jibMainClassFileName, fi)
}
if !found && (len(mainCls) != 0) {
mc = mainCls
found = true
}
switch {
case found && details.AppType != AppTypeSpring:
// we have a main class specified, and we're not a Spring Boot app
Expand Down
34 changes: 30 additions & 4 deletions pkg/runner/runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
package runner

import (
"bufio"
"bytes"
"context"
"fmt"
Expand Down Expand Up @@ -273,10 +274,18 @@ func createCommand(details *RunDetails) (string, *exec.Cmd, error) {
// are running a Spring Boot application.
if !details.isBuildPacks() && details.AppType != AppTypeSpring && details.isEnvTrueOrBlank(v1.EnvVarJvmClasspathJib) {
appDir := details.getenvOrDefault(v1.EnvVarCohAppDir, "/app")
details.addClasspathIfExists(appDir + "/resources")
details.addClasspathIfExists(appDir + "/classes")
details.addJarsToClasspath(appDir + "/classpath")
details.addJarsToClasspath(appDir + "/libs")
fi, e := os.Stat(appDir + "/jib-classpath-file")
if e == nil && (fi.Size() != 0) {
clsPath := readFirstLineFromFile(appDir+"/jib-classpath-file", fi)
if len(clsPath) != 0 {
details.addClasspath(clsPath)
}
} else {
details.addClasspathIfExists(appDir + "/resources")
details.addClasspathIfExists(appDir + "/classes")
details.addJarsToClasspath(appDir + "/classpath")
details.addJarsToClasspath(appDir + "/libs")
}
}

// Add the Operator Utils jar to the classpath
Expand Down Expand Up @@ -557,6 +566,23 @@ func createJavaCommand(javaCmd string, details *RunDetails) (*exec.Cmd, error) {
return _createJavaCommand(javaCmd, details, args)
}

func readFirstLineFromFile(fqfn string, fi os.FileInfo) string {
log.Info(fmt.Sprintf("%s size=%d", fi.Name(), fi.Size()))
file, _ := os.Open(fqfn)
scanner := bufio.NewScanner(file)
scanner.Split(bufio.ScanLines)
var text []string
for scanner.Scan() {
text = append(text, scanner.Text())
}
file.Close()
if len(text) == 0 {
return ""
}
log.Info(fmt.Sprintf("First Line of the %s:\n%s\n", fi.Name(), text[0]))
return text[0]
}

func createSpringBootCommand(javaCmd string, details *RunDetails) (*exec.Cmd, error) {
if details.isBuildPacks() {
return _createBuildPackCommand(details, SpringBootMain, details.getSpringBootArgs())
Expand Down
243 changes: 243 additions & 0 deletions pkg/runner/runner_jvm_jibclasspath_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,243 @@
/*
* Copyright (c) 2020, 2021 Oracle and/or its affiliates.
* Licensed under the Universal Permissive License v 1.0 as shown at
* http://oss.oracle.com/licenses/upl.
*/

package runner

import (
"bufio"
"fmt"
. "github.com/onsi/gomega"
coh "github.com/oracle/coherence-operator/api/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/utils/pointer"
"os"
"testing"
)

func TestJibClasspath(t *testing.T) {
g := NewGomegaWithT(t)

d := &coh.Coherence{
ObjectMeta: metav1.ObjectMeta{Name: "test"},
Spec: coh.CoherenceResourceSpec{
JVM: &coh.JVMSpec{
UseJibClasspath: pointer.BoolPtr(true),
},
},
}

args := []string{"server", "--dry-run"}
env := EnvVarsFromDeployment(d)

expectedCommand := GetJavaCommand()
expectedArgs := GetMinimalExpectedArgs()

e, err := ExecuteWithArgs(env, args)
g.Expect(err).NotTo(HaveOccurred())
g.Expect(e).NotTo(BeNil())
g.Expect(e.OsCmd).NotTo(BeNil())

g.Expect(e.OsCmd.Dir).To(Equal(TestAppDir))
g.Expect(e.OsCmd.Path).To(Equal(expectedCommand))
g.Expect(e.OsCmd.Args).To(ConsistOf(expectedArgs))
}

func TestJibClasspathFile(t *testing.T) {
g := NewGomegaWithT(t)

d := &coh.Coherence{
ObjectMeta: metav1.ObjectMeta{Name: "test"},
Spec: coh.CoherenceResourceSpec{
JVM: &coh.JVMSpec{
UseJibClasspath: pointer.BoolPtr(true),
},
},
}

args := []string{"server", "--dry-run"}
env := EnvVarsFromDeployment(d)

expectedCommand := GetJavaCommand()
f := createJibClasspathFile()
defer os.Remove(f.Name())
expectedArgs := GetMinimalExpectedArgsWithAppClasspathFile()

e, err := ExecuteWithArgs(env, args)
g.Expect(err).NotTo(HaveOccurred())
g.Expect(e).NotTo(BeNil())
g.Expect(e.OsCmd).NotTo(BeNil())

g.Expect(e.OsCmd.Dir).To(Equal(TestAppDir))
g.Expect(e.OsCmd.Path).To(Equal(expectedCommand))
g.Expect(e.OsCmd.Args).To(ConsistOf(expectedArgs))
}

func TestJibMainClassFile(t *testing.T) {
g := NewGomegaWithT(t)

d := &coh.Coherence{
ObjectMeta: metav1.ObjectMeta{Name: "test"},
Spec: coh.CoherenceResourceSpec{
JVM: &coh.JVMSpec{
UseJibClasspath: pointer.BoolPtr(true),
},
},
}

args := []string{"server", "--dry-run"}
env := EnvVarsFromDeployment(d)

expectedCommand := GetJavaCommand()
f := createJibMainClassFile()
defer os.Remove(f.Name())
expectedArgs := GetMinimalExpectedArgsWithAppMainClassFile()

e, err := ExecuteWithArgs(env, args)
g.Expect(err).NotTo(HaveOccurred())
g.Expect(e).NotTo(BeNil())
g.Expect(e.OsCmd).NotTo(BeNil())

g.Expect(e.OsCmd.Dir).To(Equal(TestAppDir))
g.Expect(e.OsCmd.Path).To(Equal(expectedCommand))
g.Expect(e.OsCmd.Args).To(ConsistOf(expectedArgs))
}

func TestJibClasspathFileAndMainClassFile(t *testing.T) {
g := NewGomegaWithT(t)

d := &coh.Coherence{
ObjectMeta: metav1.ObjectMeta{Name: "test"},
Spec: coh.CoherenceResourceSpec{
JVM: &coh.JVMSpec{
UseJibClasspath: pointer.BoolPtr(true),
},
},
}

args := []string{"server", "--dry-run"}
env := EnvVarsFromDeployment(d)

expectedCommand := GetJavaCommand()
f1 := createJibClasspathFile()
defer os.Remove(f1.Name())
f2 := createJibMainClassFile()
defer os.Remove(f2.Name())
expectedArgs := GetMinimalExpectedArgsWithAppClasspathFileAndMainClassFile()

e, err := ExecuteWithArgs(env, args)
g.Expect(err).NotTo(HaveOccurred())
g.Expect(e).NotTo(BeNil())
g.Expect(e.OsCmd).NotTo(BeNil())

g.Expect(e.OsCmd.Dir).To(Equal(TestAppDir))
g.Expect(e.OsCmd.Path).To(Equal(expectedCommand))
g.Expect(e.OsCmd.Args).To(ConsistOf(expectedArgs))
}

func createJibClasspathFile() *os.File {
f, err := os.Create(TestAppDir + string(os.PathSeparator) + "jib-classpath-file")
if err != nil {
fmt.Print(err)
os.Exit(1)
}

_, err = f.WriteString(fmt.Sprintf("%s/classpath/*:%s/libs/*", TestAppDir, TestAppDir))
if err != nil {
fmt.Print(err)
os.Exit(1)
}
err = f.Close()
if err != nil {
fmt.Print(err)
os.Exit(1)
}

return f
}

func createJibMainClassFile() *os.File {
f, err := os.Create(TestAppDir + string(os.PathSeparator) + "jib-main-class-file")
if err != nil {
fmt.Print(err)
os.Exit(1)
}

_, err = f.WriteString("com.tangosol.net.DefaultCacheServer")
if err != nil {
fmt.Print(err)
os.Exit(1)
}
err = f.Close()
if err != nil {
fmt.Print(err)
os.Exit(1)
}

return f
}

func GetMinimalExpectedArgsWithAppClasspathFile() []string {
fileName := fmt.Sprintf("%s/jib-classpath-file", TestAppDir)
cp := readFirstLine(fileName)
args := []string{
GetJavaCommand(),
"-cp",
cp + ":/coherence-operator/utils/lib/coherence-operator.jar:/coherence-operator/utils/config",
}

return append(AppendCommonExpectedArgs(args),
"com.oracle.coherence.k8s.Main",
"com.tangosol.net.DefaultCacheServer")
}

func GetMinimalExpectedArgsWithAppMainClassFile() []string {
cp := fmt.Sprintf("%s/resources:%s/classes:%s/classpath/bar2.JAR:%s/classpath/foo2.jar:%s/libs/bar1.JAR:%s/libs/foo1.jar",
TestAppDir, TestAppDir, TestAppDir, TestAppDir, TestAppDir, TestAppDir)

args := []string{
GetJavaCommand(),
"-cp",
cp + ":/coherence-operator/utils/lib/coherence-operator.jar:/coherence-operator/utils/config",
}

fileName := fmt.Sprintf("%s/jib-main-class-file", TestAppDir)
mainCls := readFirstLine(fileName)
return append(AppendCommonExpectedArgs(args),
"com.oracle.coherence.k8s.Main",
mainCls)
}

func GetMinimalExpectedArgsWithAppClasspathFileAndMainClassFile() []string {
fileName := fmt.Sprintf("%s/jib-classpath-file", TestAppDir)
cp := readFirstLine(fileName)

args := []string{
GetJavaCommand(),
"-cp",
cp + ":/coherence-operator/utils/lib/coherence-operator.jar:/coherence-operator/utils/config",
}

fileName = fmt.Sprintf("%s/jib-main-class-file", TestAppDir)
mainCls := readFirstLine(fileName)
return append(AppendCommonExpectedArgs(args),
"com.oracle.coherence.k8s.Main",
mainCls)
}

func readFirstLine(fqfn string) string {
file, _ := os.Open(fqfn)
scanner := bufio.NewScanner(file)
scanner.Split(bufio.ScanLines)
var text []string
for scanner.Scan() {
text = append(text, scanner.Text())
}
file.Close()
if len(text) == 0 {
return ""
}
return text[0]
}

0 comments on commit 86b5c28

Please sign in to comment.