diff --git a/api/v1/coherencejobresource_types.go b/api/v1/coherencejobresource_types.go index b82e5d5f..b754c123 100644 --- a/api/v1/coherencejobresource_types.go +++ b/api/v1/coherencejobresource_types.go @@ -58,6 +58,10 @@ func (in *CoherenceJob) GetAPIVersion() string { return in.APIVersion } +func (in *CoherenceJob) IsForceExit() bool { + return in.Spec.ForceExit != nil && *in.Spec.ForceExit +} + // GetSpec returns this resource's CoherenceResourceSpec func (in *CoherenceJob) GetSpec() *CoherenceResourceSpec { return &in.Spec.CoherenceResourceSpec @@ -376,6 +380,10 @@ type CoherenceJobResourceSpec struct { // will also be executed on every Pod that becomes ready after that time. // +optional ReadyAction *CoherenceJobProbe `json:"readyAction,omitempty"` + + // ForceExit is a flag to indicate whether the Operator should call System.exit to forcefully exit the process + // when the configured main class completes execution. + ForceExit *bool `json:"forceExit,omitempty"` } // GetRestartPolicy returns the name of the application image to use diff --git a/api/v1/coherenceresource.go b/api/v1/coherenceresource.go index 807f9d23..f6ab8218 100644 --- a/api/v1/coherenceresource.go +++ b/api/v1/coherenceresource.go @@ -85,4 +85,6 @@ type CoherenceResource interface { DeepCopyResource() CoherenceResource // GetAPIVersion returns the TypeMeta API version GetAPIVersion() string + // IsForceExit is a flag to determine whether the Operator calls System.exit when the main class finishes. + IsForceExit() bool } diff --git a/api/v1/coherenceresource_types.go b/api/v1/coherenceresource_types.go index e827f19b..b241115e 100644 --- a/api/v1/coherenceresource_types.go +++ b/api/v1/coherenceresource_types.go @@ -175,6 +175,10 @@ func (in *Coherence) SetReplicas(replicas int32) { } } +func (in *Coherence) IsForceExit() bool { + return false +} + // FindFullyQualifiedPortServiceNames returns a map of the exposed ports of this resource mapped to their Service's // fully qualified domain name. func (in *Coherence) FindFullyQualifiedPortServiceNames() map[string]string { diff --git a/api/v1/coherenceresourcespec_types.go b/api/v1/coherenceresourcespec_types.go index 6ecb081e..8e7ec8a3 100644 --- a/api/v1/coherenceresourcespec_types.go +++ b/api/v1/coherenceresourcespec_types.go @@ -731,6 +731,14 @@ func (in *CoherenceResourceSpec) CreateCoherenceContainer(deployment CoherenceRe c.Env = append(c.Env, in.CreateDefaultEnv(deployment)...) + forceExit := deployment.IsForceExit() + if forceExit { + c.Env = append(c.Env, corev1.EnvVar{ + Name: EnvVarCohForceExit, + Value: "true", + }) + } + in.Application.UpdateCoherenceContainer(&c) if in.Resources != nil { diff --git a/api/v1/constants.go b/api/v1/constants.go index c74c8ac7..2471b1e4 100644 --- a/api/v1/constants.go +++ b/api/v1/constants.go @@ -200,6 +200,7 @@ const ( EnvVarCohMetricsPrefix = "COH_METRICS" EnvVarCohEnabledSuffix = "_ENABLED" EnvVarCohPortSuffix = "_PORT" + EnvVarCohForceExit = "COH_FORCE_EXIT" EnvVarCoherenceLocalPort = "COHERENCE_LOCALPORT" EnvVarCoherenceLocalPortAdjust = "COHERENCE_LOCALPORT_ADJUST" EnvVarEnableIPMonitor = "COH_ENABLE_IPMONITOR" diff --git a/api/v1/zz_generated.deepcopy.go b/api/v1/zz_generated.deepcopy.go index 30cb9604..2ded7e16 100644 --- a/api/v1/zz_generated.deepcopy.go +++ b/api/v1/zz_generated.deepcopy.go @@ -335,6 +335,11 @@ func (in *CoherenceJobResourceSpec) DeepCopyInto(out *CoherenceJobResourceSpec) *out = new(CoherenceJobProbe) (*in).DeepCopyInto(*out) } + if in.ForceExit != nil { + in, out := &in.ForceExit, &out.ForceExit + *out = new(bool) + **out = **in + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CoherenceJobResourceSpec. diff --git a/java/coherence-operator/src/main/java/com/oracle/coherence/k8s/CoherenceVersion.java b/java/coherence-operator/src/main/java/com/oracle/coherence/k8s/CoherenceVersion.java index 6db6f1aa..8a3ad34d 100644 --- a/java/coherence-operator/src/main/java/com/oracle/coherence/k8s/CoherenceVersion.java +++ b/java/coherence-operator/src/main/java/com/oracle/coherence/k8s/CoherenceVersion.java @@ -6,9 +6,7 @@ package com.oracle.coherence.k8s; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - +import com.tangosol.coherence.component.net.memberSet.actualMemberSet.ServiceMemberSet; import com.tangosol.net.CacheFactory; /** @@ -17,9 +15,6 @@ * version is greater than or equal to that version. */ public class CoherenceVersion { - - private static final Pattern PATTERN = Pattern.compile("(\\d*)\\D*(\\d*)\\D*(\\d*)\\D*(\\d*)\\D*(\\d*)\\D*(\\d*)\\D*"); - /** * Private constructor for utility class. */ @@ -54,6 +49,7 @@ public static void main(String[] args) { * @return {@code true} if the actual Coherence version is at least the check version */ public static boolean versionCheck(String coherenceVersion, String... args) { + System.out.print("CoherenceOperator: version check actual=\"" + coherenceVersion + "\" required=\"" + args[0] + '"'); if (coherenceVersion.contains(" ")) { coherenceVersion = coherenceVersion.substring(0, coherenceVersion.indexOf(" ")); } @@ -61,50 +57,27 @@ public static boolean versionCheck(String coherenceVersion, String... args) { coherenceVersion = coherenceVersion.substring(coherenceVersion.indexOf(":") + 1); } - int[] coherenceParts = splitVersion(coherenceVersion); - - if (coherenceParts.length == 0) { - return false; + int[] nCoherenceParts = ServiceMemberSet.toVersionArray(coherenceVersion); + int nActual; + if (nCoherenceParts[0] > 20) { + nActual = ServiceMemberSet.encodeVersion(nCoherenceParts[0], nCoherenceParts[1], nCoherenceParts[2]); } - - int[] versionParts = splitVersion(args[0]); - int partCount = Math.min(coherenceParts.length, versionParts.length); - - if (partCount > 0) { - for (int i = 0; i < partCount; i++) { - if (coherenceParts[i] == versionParts[i]) { - continue; - } - // else versions differ - return coherenceParts[i] > versionParts[i]; - } + else { + nActual = ServiceMemberSet.parseVersion(coherenceVersion); } - // versions are equal - return true; - } - - private static int[] splitVersion(String version) { - Matcher matcher = PATTERN.matcher(version); - int[] count; - - if (matcher.matches()) { - int groupCount = matcher.groupCount(); - count = new int[groupCount]; - - for (int i = 1; i <= groupCount; i++) { - try { - count[i - 1] = Integer.parseInt(matcher.group(i)); - } - catch (NumberFormatException e) { - count[i - 1] = 0; - } - } + int[] nParts = ServiceMemberSet.toVersionArray(args[0]); + int nRequired; + if (nParts[0] > 20) { + nRequired = ServiceMemberSet.encodeVersion(nParts[0], nParts[1], nParts[2]); } else { - count = new int[0]; + nRequired = ServiceMemberSet.parseVersion(args[0]); } + boolean fResult = nActual >= nRequired; - return count; + // versions are equal + System.out.println(" result=" + fResult); + return fResult; } } diff --git a/java/coherence-operator/src/main/java/com/oracle/coherence/k8s/Main.java b/java/coherence-operator/src/main/java/com/oracle/coherence/k8s/Main.java index 9331cf02..5cbb1670 100644 --- a/java/coherence-operator/src/main/java/com/oracle/coherence/k8s/Main.java +++ b/java/coherence-operator/src/main/java/com/oracle/coherence/k8s/Main.java @@ -19,6 +19,8 @@ public class Main { private static final String DEFAULT_MAIN = "$DEFAULT$"; + private static final String PROP_FORCE_EXIT = "coherence.k8s.operator.force.exit"; + private static boolean initialised = false; /** @@ -50,6 +52,11 @@ else if (DEFAULT_MAIN.equals(args[0])) { Class clsMain = Class.forName(sMainClass); Method method = clsMain.getMethod("main", asArgsReal.getClass()); method.invoke(null, (Object) asArgsReal); + + boolean fExit = Boolean.getBoolean(PROP_FORCE_EXIT); + if (fExit) { + System.exit(0); + } } /** diff --git a/java/coherence-operator/src/test/java/com/oracle/coherence/k8s/CoherenceVersionTest.java b/java/coherence-operator/src/test/java/com/oracle/coherence/k8s/CoherenceVersionTest.java index 138e8280..eccc5dde 100644 --- a/java/coherence-operator/src/test/java/com/oracle/coherence/k8s/CoherenceVersionTest.java +++ b/java/coherence-operator/src/test/java/com/oracle/coherence/k8s/CoherenceVersionTest.java @@ -54,7 +54,16 @@ public void shouldBeLess() { @Test public void shouldWorkWithInterimBuild() throws Exception { assertThat(CoherenceVersion.versionCheck("14.1.1.0.15 (101966-Int)", "14.1.1.0.0"), is(true)); - assertThat(CoherenceVersion.versionCheck("14.1.1.0.15 (101966-Int)", "22.06.0"), is(false)); + assertThat(CoherenceVersion.versionCheck("14.1.1.0.15 (101966-Int)", "14.1.1.0.16"), is(false)); + } + + @Test + public void shouldWorkWithCE() throws Exception { + assertThat(CoherenceVersion.versionCheck("14.1.1.0.15", "22.06.1"), is(false)); + assertThat(CoherenceVersion.versionCheck("14.1.1.2206.5", "22.06.6"), is(false)); + assertThat(CoherenceVersion.versionCheck("14.1.1.2206.7", "22.06.7"), is(true)); + assertThat(CoherenceVersion.versionCheck("22.06.5", "22.06.6"), is(false)); + assertThat(CoherenceVersion.versionCheck("22.06.7", "22.06.7"), is(true)); } } diff --git a/pkg/runner/runner.go b/pkg/runner/runner.go index 7617a9f5..3b9677c7 100644 --- a/pkg/runner/runner.go +++ b/pkg/runner/runner.go @@ -294,6 +294,7 @@ func createCommand(details *RunDetails) (string, *exec.Cmd, error) { details.addArgFromEnvVar(v1.EnvVarCohClusterName, "-Dcoherence.cluster") details.addArgFromEnvVar(v1.EnvVarCohCacheConfig, "-Dcoherence.cacheconfig") details.addArgFromEnvVar(v1.EnvVarCohIdentity, "-Dcoherence.k8s.operator.identity") + details.addArgFromEnvVar(v1.EnvVarCohForceExit, "-Dcoherence.k8s.operator.force.exit") details.setSystemPropertyFromEnvVarOrDefault(v1.EnvVarCohHealthPort, "-Dcoherence.k8s.operator.health.port", fmt.Sprintf("%d", v1.DefaultHealthPort)) details.setSystemPropertyFromEnvVarOrDefault(v1.EnvVarCohMgmtPrefix+v1.EnvVarCohPortSuffix, "-Dcoherence.management.http.port", fmt.Sprintf("%d", v1.DefaultManagementPort)) details.setSystemPropertyFromEnvVarOrDefault(v1.EnvVarCohMetricsPrefix+v1.EnvVarCohPortSuffix, "-Dcoherence.metrics.http.port", fmt.Sprintf("%d", v1.DefaultMetricsPort)) @@ -358,15 +359,15 @@ func createCommand(details *RunDetails) (string, *exec.Cmd, error) { cohPre12214(details) } - post2206 := checkCoherenceVersion("22.06.0", details) + post2206 := checkCoherenceVersion("14.1.1.2206.0", details) if post2206 { // at least CE 22.06 cohPost2206(details) } else { - post2006 := checkCoherenceVersion("20.06.0", details) + post2006 := checkCoherenceVersion("14.1.1.2006.0", details) if !post2006 { // pre CE 20.06 - could be 14.1.1.2206 - if post14112206 := checkCoherenceVersion("14.1.1.2206", details); post14112206 { + if post14112206 := checkCoherenceVersion("14.1.1.2206.0", details); post14112206 { // at least 14.1.1.2206 cohPost2206(details) }