Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions api/v1/webspherelibertyapplication_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -567,6 +567,15 @@ type WebSphereLibertyApplicationSemeruCloudCompiler struct {
// Resource requests and limits for the Semeru Cloud Compiler. The CPU defaults to 100m with a limit of 2000m. The memory defaults to 800Mi, with a limit of 1200Mi.
// +operator-sdk:csv:customresourcedefinitions:order=54,type=spec,displayName="Resource Requirements",xDescriptors="urn:alm:descriptor:com.tectonic.ui:resourceRequirements"
Resources *corev1.ResourceRequirements `json:"resources,omitempty"`
// The health settings for the Semeru Cloud Compiler.
// +operator-sdk:csv:customresourcedefinitions:order=55,type=spec,displayName="Health"
Health *WebSphereLibertyApplicationSemeruCloudCompilerHealth `json:"health,omitempty"`
}

type WebSphereLibertyApplicationSemeruCloudCompilerHealth struct {
// The health port for the Semeru Cloud Compiler. Defaults to 38600.
// +operator-sdk:csv:customresourcedefinitions:order=60,type=spec,displayName="Port",xDescriptors="urn:alm:descriptor:com.tectonic.ui:number"
Port *int32 `json:"port,omitempty"`
}

// Defines SemeruCompiler status
Expand Down Expand Up @@ -1373,6 +1382,19 @@ func (scc *WebSphereLibertyApplicationSemeruCloudCompiler) GetReplicas() *int32
return &one
}

// GetHealth returns the Semeru Cloud Compiler Health configuration
func (scc *WebSphereLibertyApplicationSemeruCloudCompiler) GetHealth() *WebSphereLibertyApplicationSemeruCloudCompilerHealth {
return scc.Health
}

func (scch *WebSphereLibertyApplicationSemeruCloudCompilerHealth) GetPort() *int32 {
if scch.Port != nil {
return scch.Port
}
defaultPort := int32(38600)
return &defaultPort
}

// GetTopologySpreadConstraints returns the pod topology spread constraints configuration
func (cr *WebSphereLibertyApplication) GetTopologySpreadConstraints() common.BaseComponentTopologySpreadConstraints {
if cr.Spec.TopologySpreadConstraints == nil {
Expand Down
25 changes: 25 additions & 0 deletions api/v1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ metadata:
capabilities: Auto Pilot
categories: Application Runtime
containerImage: icr.io/cpopen/websphere-liberty-operator:daily
createdAt: "2025-12-03T04:52:57Z"
createdAt: "2026-01-21T21:18:59Z"
description: Deploy and manage containerized Liberty applications
features.operators.openshift.io/disconnected: "true"
olm.skipRange: '>=1.0.0 <1.5.2'
Expand Down Expand Up @@ -607,6 +607,14 @@ spec:
path: semeruCloudCompiler.resources
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:resourceRequirements
- description: The health settings for the Semeru Cloud Compiler.
displayName: Health
path: semeruCloudCompiler.health
- description: The health port for the Semeru Cloud Compiler. Defaults to 38600.
displayName: Port
path: semeruCloudCompiler.health.port
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:number
- description: 'Product edition. Defaults to IBM WebSphere Application Server.
Other options: IBM WebSphere Application Server Liberty Core, IBM WebSphere
Application Server Network Deployment'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5228,6 +5228,15 @@ spec:
enable:
description: Enable the Semeru Cloud Compiler. Defaults to false.
type: boolean
health:
description: The health settings for the Semeru Cloud Compiler.
properties:
port:
description: The health port for the Semeru Cloud Compiler.
Defaults to 38600.
format: int32
type: integer
type: object
replicas:
description: Number of desired pods for the Semeru Cloud Compiler.
Defaults to 1.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5224,6 +5224,15 @@ spec:
enable:
description: Enable the Semeru Cloud Compiler. Defaults to false.
type: boolean
health:
description: The health settings for the Semeru Cloud Compiler.
properties:
port:
description: The health port for the Semeru Cloud Compiler.
Defaults to 38600.
format: int32
type: integer
type: object
replicas:
description: Number of desired pods for the Semeru Cloud Compiler.
Defaults to 1.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -543,6 +543,14 @@ spec:
path: semeruCloudCompiler.resources
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:resourceRequirements
- description: The health settings for the Semeru Cloud Compiler.
displayName: Health
path: semeruCloudCompiler.health
- description: The health port for the Semeru Cloud Compiler. Defaults to 38600.
displayName: Port
path: semeruCloudCompiler.health.port
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:number
- description: 'Product edition. Defaults to IBM WebSphere Application Server.
Other options: IBM WebSphere Application Server Liberty Core, IBM WebSphere
Application Server Network Deployment'
Expand Down
125 changes: 108 additions & 17 deletions internal/controller/semeru_compiler.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,14 +46,65 @@ const (
SemeruGenerationLabelNameSuffix = "/semeru-compiler-generation"
StatusReferenceSemeruGeneration = "semeruGeneration"
StatusReferenceSemeruInstancesCompleted = "semeruInstancesCompleted"
SemeruContainerName = "compiler"
)

// Create the Deployment and Service objects for a Semeru Compiler used by a Websphere Liberty Application
func (r *ReconcileWebSphereLiberty) reconcileSemeruCompiler(wlva *wlv1.WebSphereLibertyApplication) (error, string, bool) {
compilerMeta := metav1.ObjectMeta{
func getCompilerMeta(wlva *wlv1.WebSphereLibertyApplication) metav1.ObjectMeta {
return metav1.ObjectMeta{
Name: getSemeruCompilerNameWithGeneration(wlva),
Namespace: wlva.GetNamespace(),
}
}

func getSemeruDeploymentContainer(deploy *appsv1.Deployment) (corev1.Container, error) {
for _, container := range deploy.Spec.Template.Spec.Containers {
if container.Name == SemeruContainerName {
return container, nil
}
}
return corev1.Container{}, fmt.Errorf("could not find the Semeru Deployment container")
}

// Returns true if the semeru health port configuration has changed otherwise false
func (r *ReconcileWebSphereLiberty) upgradeSemeruHealthPorts(inputMeta metav1.ObjectMeta, wlva *wlv1.WebSphereLibertyApplication) bool {
var healthPort int32 = 38600
if wlva.GetSemeruCloudCompiler().GetHealth() != nil {
healthPort = *wlva.GetSemeruCloudCompiler().GetHealth().GetPort()
}
semeruDeployment := &appsv1.Deployment{ObjectMeta: inputMeta}
if r.GetClient().Get(context.TODO(), types.NamespacedName{Name: semeruDeployment.Name, Namespace: semeruDeployment.Namespace}, semeruDeployment) == nil {
container, err := getSemeruDeploymentContainer(semeruDeployment)
if err != nil {
return false
}
if healthPort == 38400 && len(container.Ports) > 1 {
return true
}
containsHealthPort := false
for _, port := range container.Ports {
if port.ContainerPort == healthPort {
containsHealthPort = true
}
}
if !containsHealthPort {
return true
}
}
return false
}

// Create the Deployment and Service objects for a Semeru Compiler used by a Websphere Liberty Application
func (r *ReconcileWebSphereLiberty) reconcileSemeruCompiler(wlva *wlv1.WebSphereLibertyApplication) (error, string, bool) {
compilerMeta := getCompilerMeta(wlva)

// check for any diffs that require generation changes
if r.isSemeruEnabled(wlva) {
upgradeRequired := r.upgradeSemeruHealthPorts(compilerMeta, wlva)
if upgradeRequired {
createNewSemeruGeneration(wlva) // update generation
compilerMeta = getCompilerMeta(wlva) // adjust compilerMeta to reference the new generation
}
}

currentGeneration := getGeneration(wlva)

Expand Down Expand Up @@ -255,6 +306,8 @@ func (r *ReconcileWebSphereLiberty) deleteCompletedSemeruInstances(wlva *wlv1.We
}

func (r *ReconcileWebSphereLiberty) reconcileSemeruDeployment(wlva *wlv1.WebSphereLibertyApplication, deploy *appsv1.Deployment) {
var port int32 = 38400
var healthPort int32 = 38600
deploy.Labels = getLabels(wlva)
deploy.Spec.Strategy.Type = appsv1.RecreateDeploymentStrategyType

Expand All @@ -276,11 +329,20 @@ func (r *ReconcileWebSphereLiberty) reconcileSemeruDeployment(wlva *wlv1.WebSphe
limitsMemory := getQuantityFromLimitsOrDefault(instanceResources, corev1.ResourceMemory, "1200Mi")
limitsCPU := getQuantityFromLimitsOrDefault(instanceResources, corev1.ResourceCPU, "2000m")

if semeruCloudCompiler.GetHealth() != nil {
healthPort = *semeruCloudCompiler.GetHealth().GetPort()
}
var portIntOrStr intstr.IntOrString
if healthPort == port {
portIntOrStr = intstr.FromInt32(port)
} else {
portIntOrStr = intstr.FromString(fmt.Sprintf("%d-tcp", healthPort))
}
// Liveness probe
livenessProbe := corev1.Probe{
ProbeHandler: corev1.ProbeHandler{
TCPSocket: &corev1.TCPSocketAction{
Port: intstr.FromInt(38400),
Port: portIntOrStr,
},
},
InitialDelaySeconds: 10,
Expand All @@ -291,7 +353,7 @@ func (r *ReconcileWebSphereLiberty) reconcileSemeruDeployment(wlva *wlv1.WebSphe
readinessProbe := corev1.Probe{
ProbeHandler: corev1.ProbeHandler{
TCPSocket: &corev1.TCPSocketAction{
Port: intstr.FromInt(38400),
Port: portIntOrStr,
},
},
InitialDelaySeconds: 5,
Expand All @@ -301,6 +363,22 @@ func (r *ReconcileWebSphereLiberty) reconcileSemeruDeployment(wlva *wlv1.WebSphe
semeruPodMatchLabels := map[string]string{
"app.kubernetes.io/instance": getSemeruCompilerNameWithGeneration(wlva),
}
containerPorts := make([]corev1.ContainerPort, 0)
containerPorts = append(containerPorts, corev1.ContainerPort{
ContainerPort: port,
Protocol: corev1.ProtocolTCP,
})

healthProbesFlag := ""
if healthPort != port {
healthProbesFlag = " -XX:+JITServerHealthProbes" + fmt.Sprintf(" -XX:JITServerHealthProbePort=%d", healthPort)
containerPorts[0].Name = fmt.Sprintf("%d-tcp", port)
containerPorts = append(containerPorts, corev1.ContainerPort{
Name: fmt.Sprintf("%d-tcp", healthPort),
ContainerPort: healthPort,
Protocol: corev1.ProtocolTCP,
})
}
deploy.Spec.Template = corev1.PodTemplateSpec{
ObjectMeta: metav1.ObjectMeta{
Labels: getLabels(wlva),
Expand Down Expand Up @@ -333,16 +411,11 @@ func (r *ReconcileWebSphereLiberty) reconcileSemeruDeployment(wlva *wlv1.WebSphe
},
Containers: []corev1.Container{
{
Name: "compiler",
Name: SemeruContainerName,
Image: wlva.Status.GetImageReference(),
ImagePullPolicy: *wlva.GetPullPolicy(),
Command: []string{"jitserver"},
Ports: []corev1.ContainerPort{
{
ContainerPort: 38400,
Protocol: corev1.ProtocolTCP,
},
},
Ports: containerPorts,
Resources: corev1.ResourceRequirements{
Requests: corev1.ResourceList{
corev1.ResourceMemory: requestsMemory,
Expand All @@ -356,6 +429,7 @@ func (r *ReconcileWebSphereLiberty) reconcileSemeruDeployment(wlva *wlv1.WebSphe
Env: []corev1.EnvVar{
{Name: "OPENJ9_JAVA_OPTIONS", Value: "-XX:+JITServerLogConnections" +
" -XX:+JITServerShareROMClasses" +
healthProbesFlag +
" -XX:JITServerSSLKey=/etc/x509/certs/tls.key" +
" -XX:JITServerSSLCert=/etc/x509/certs/tls.crt"},
},
Expand Down Expand Up @@ -413,16 +487,34 @@ func (r *ReconcileWebSphereLiberty) reconcileSemeruDeployment(wlva *wlv1.WebSphe

func reconcileSemeruService(svc *corev1.Service, wlva *wlv1.WebSphereLibertyApplication) {
var port int32 = 38400
var healthPort int32 = 38600
var timeout int32 = 86400
svc.Labels = getLabels(wlva)
svc.Spec.Selector = getSelectors(wlva)
utils.CustomizeServiceAnnotations(svc)
if len(svc.Spec.Ports) == 0 {
numPorts := len(svc.Spec.Ports)
if numPorts == 0 {
svc.Spec.Ports = append(svc.Spec.Ports, corev1.ServicePort{})
}

svc.Spec.Ports[0].Protocol = corev1.ProtocolTCP
svc.Spec.Ports[0].Port = port
svc.Spec.Ports[0].TargetPort = intstr.FromInt(int(port))
if wlva.GetSemeruCloudCompiler().GetHealth() != nil {
healthPort = *wlva.GetSemeruCloudCompiler().GetHealth().GetPort()
}
if healthPort != port {
numPorts = len(svc.Spec.Ports)
if numPorts == 1 {
svc.Spec.Ports = append(svc.Spec.Ports, corev1.ServicePort{})
}
svc.Spec.Ports[0].Name = fmt.Sprintf("%d-tcp", port)
svc.Spec.Ports[0].TargetPort = intstr.FromString(fmt.Sprintf("%d-tcp", port))
svc.Spec.Ports[1].Name = fmt.Sprintf("%d-tcp", healthPort)
svc.Spec.Ports[1].Protocol = corev1.ProtocolTCP
svc.Spec.Ports[1].Port = healthPort
svc.Spec.Ports[1].TargetPort = intstr.FromString(fmt.Sprintf("%d-tcp", healthPort))
}
svc.Spec.SessionAffinity = corev1.ServiceAffinityClientIP
svc.Spec.SessionAffinityConfig = &corev1.SessionAffinityConfig{
ClientIP: &corev1.ClientIPConfig{
Expand Down Expand Up @@ -585,14 +677,13 @@ func (r *ReconcileWebSphereLiberty) getSemeruJavaOptions(instance *wlv1.WebSpher
certificateLocation = "/var/run/secrets/kubernetes.io/serviceaccount/service-ca.crt"
}
jitServerAddress := instance.Status.SemeruCompiler.ServiceHostname
jitSeverOptions := fmt.Sprintf("-XX:+UseJITServer -XX:+JITServerLogConnections -XX:JITServerAddress=%v -XX:JITServerSSLRootCerts=%v",
jitServerAddress, certificateLocation)
jitServerOptions := fmt.Sprintf("-XX:+UseJITServer -XX:+JITServerLogConnections -XX:JITServerAddress=%v -XX:JITServerSSLRootCerts=%v", jitServerAddress, certificateLocation)

args := []string{
"/bin/bash",
"-c",
"export OPENJ9_JAVA_OPTIONS=\"$OPENJ9_JAVA_OPTIONS " + jitSeverOptions +
"\" && export OPENJ9_RESTORE_JAVA_OPTIONS=\"$OPENJ9_RESTORE_JAVA_OPTIONS " + jitSeverOptions +
"export OPENJ9_JAVA_OPTIONS=\"$OPENJ9_JAVA_OPTIONS " + jitServerOptions +
"\" && export OPENJ9_RESTORE_JAVA_OPTIONS=\"$OPENJ9_RESTORE_JAVA_OPTIONS " + jitServerOptions +
"\" && server run",
}
return args
Expand Down
9 changes: 9 additions & 0 deletions internal/deploy/kubectl/websphereliberty-app-crd.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5227,6 +5227,15 @@ spec:
enable:
description: Enable the Semeru Cloud Compiler. Defaults to false.
type: boolean
health:
description: The health settings for the Semeru Cloud Compiler.
properties:
port:
description: The health port for the Semeru Cloud Compiler.
Defaults to 38600.
format: int32
type: integer
type: object
replicas:
description: Number of desired pods for the Semeru Cloud Compiler.
Defaults to 1.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5227,6 +5227,15 @@ spec:
enable:
description: Enable the Semeru Cloud Compiler. Defaults to false.
type: boolean
health:
description: The health settings for the Semeru Cloud Compiler.
properties:
port:
description: The health port for the Semeru Cloud Compiler.
Defaults to 38600.
format: int32
type: integer
type: object
replicas:
description: Number of desired pods for the Semeru Cloud Compiler.
Defaults to 1.
Expand Down