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
6 changes: 6 additions & 0 deletions api/v1beta/lightrunjavaagent_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,12 @@ type LightrunJavaAgentSpec struct {
// UseSecretsAsMountedFiles determines whether to use secret values as mounted files (true) or as environment variables (false)
// +kubebuilder:default=false
UseSecretsAsMountedFiles bool `json:"useSecretsAsMountedFiles,omitempty"`

// MountLibstdc determines whether to mount libstdc++ libraries from the init container to the application container
// This is useful for Alpine-based images that don't have libstdc++ installed
// +kubebuilder:default=false
// +optional
MountLibstdc bool `json:"mountLibstdc,omitempty"`
}

// LightrunJavaAgentStatus defines the observed state of LightrunJavaAgent
Expand Down
7 changes: 7 additions & 0 deletions charts/lightrun-operator/crds/lightrunjavaagent_crd.yaml
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
Expand Down Expand Up @@ -114,6 +115,12 @@ spec:
- sharedVolumeMountPath
- sharedVolumeName
type: object
mountLibstdc:
default: false
description: |-
MountLibstdc determines whether to mount libstdc++ libraries from the init container to the application container
This is useful for Alpine-based images that don't have libstdc++ installed
type: boolean
secretName:
description: Name of the Secret in the same namespace contains lightrun
key and conmpany id
Expand Down
6 changes: 6 additions & 0 deletions config/crd/bases/agents.lightrun.com_lightrunjavaagents.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,12 @@ spec:
- sharedVolumeMountPath
- sharedVolumeName
type: object
mountLibstdc:
default: false
description: |-
MountLibstdc determines whether to mount libstdc++ libraries from the init container to the application container
This is useful for Alpine-based images that don't have libstdc++ installed
type: boolean
secretName:
description: Name of the Secret in the same namespace contains lightrun
key and conmpany id
Expand Down
116 changes: 100 additions & 16 deletions internal/controller/patch_funcs.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,17 @@ func (r *LightrunJavaAgentReconciler) addVolume(deploymentApplyConfig *appsv1ac.
)
}

// Add libstdc volume if MountLibstdc is true
if lightrunJavaAgent.Spec.MountLibstdc {
volumes = append(volumes,
corev1ac.Volume().
WithName("lightrun-libstdc").
WithEmptyDir(
corev1ac.EmptyDirVolumeSource(),
),
)
}

deploymentApplyConfig.Spec.Template.Spec.WithVolumes(volumes...)
}

Expand All @@ -125,6 +136,12 @@ func (r *LightrunJavaAgentReconciler) addInitContainer(deploymentApplyConfig *ap
corev1ac.VolumeMount().WithName("lightrun-secret").WithMountPath("/etc/lightrun/secret").WithReadOnly(true),
)
}
// If MountLibstdc is enabled, mount the libstdc volume
if spec.MountLibstdc {
volumeMounts = append(volumeMounts,
corev1ac.VolumeMount().WithName("lightrun-libstdc").WithMountPath("/tmp/libstdc/"),
)
}

// Always set LIGHTRUN_SERVER
envVars := []*corev1ac.EnvVarApplyConfiguration{
Expand All @@ -145,6 +162,12 @@ func (r *LightrunJavaAgentReconciler) addInitContainer(deploymentApplyConfig *ap
),
)
}
// If MountLibstdc is enabled, set the MOUNT_LIBSTDC env var to signal the script
if spec.MountLibstdc {
envVars = append(envVars,
corev1ac.EnvVar().WithName("MOUNT_LIBSTDC").WithValue("true"),
)
}

initContainer := corev1ac.Container().
WithName(initContainerName).
Expand Down Expand Up @@ -177,6 +200,7 @@ func (r *LightrunJavaAgentReconciler) addInitContainer(deploymentApplyConfig *ap
},
),
)

if isImagePullPolicyConfigured {
initContainer.WithImagePullPolicy(spec.InitContainer.ImagePullPolicy)
}
Expand All @@ -189,14 +213,32 @@ func (r *LightrunJavaAgentReconciler) patchAppContainers(lightrunJavaAgent *agen
for _, targetContainer := range lightrunJavaAgent.Spec.ContainerSelector {
if targetContainer == container.Name {
found = true
deploymentApplyConfig.Spec.Template.Spec.WithContainers(
corev1ac.Container().
WithName(container.Name).
WithImage(container.Image).
WithVolumeMounts(
corev1ac.VolumeMount().WithMountPath(lightrunJavaAgent.Spec.InitContainer.SharedVolumeMountPath).WithName(lightrunJavaAgent.Spec.InitContainer.SharedVolumeName),
),
)

// Prepare volume mounts
volumeMounts := []*corev1ac.VolumeMountApplyConfiguration{
corev1ac.VolumeMount().WithMountPath(lightrunJavaAgent.Spec.InitContainer.SharedVolumeMountPath).WithName(lightrunJavaAgent.Spec.InitContainer.SharedVolumeName),
}

// Add libstdc volume mount if MountLibstdc is enabled
if lightrunJavaAgent.Spec.MountLibstdc {
volumeMounts = append(volumeMounts,
corev1ac.VolumeMount().WithName("lightrun-libstdc").WithMountPath("/tmp/libstdc").WithReadOnly(true),
)
}

containerConfig := corev1ac.Container().
WithName(container.Name).
WithImage(container.Image).
WithVolumeMounts(volumeMounts...)

// Add LD_LIBRARY_PATH environment variable if MountLibstdc is enabled
if lightrunJavaAgent.Spec.MountLibstdc {
containerConfig.WithEnv(
corev1ac.EnvVar().WithName("LD_LIBRARY_PATH").WithValue("/tmp/libstdc"),
)
}

deploymentApplyConfig.Spec.Template.Spec.WithContainers(containerConfig)
}
}
}
Expand Down Expand Up @@ -317,6 +359,17 @@ func (r *LightrunJavaAgentReconciler) addVolumeToStatefulSet(statefulSetApplyCon
)
}

// Add libstdc volume if MountLibstdc is true
if lightrunJavaAgent.Spec.MountLibstdc {
volumes = append(volumes,
corev1ac.Volume().
WithName("lightrun-libstdc").
WithEmptyDir(
corev1ac.EmptyDirVolumeSource(),
),
)
}

statefulSetApplyConfig.Spec.Template.Spec.WithVolumes(volumes...)
}

Expand All @@ -335,6 +388,12 @@ func (r *LightrunJavaAgentReconciler) addInitContainerToStatefulSet(statefulSetA
corev1ac.VolumeMount().WithName("lightrun-secret").WithMountPath("/etc/lightrun/secret").WithReadOnly(true),
)
}
// If MountLibstdc is enabled, mount the libstdc volume
if spec.MountLibstdc {
volumeMounts = append(volumeMounts,
corev1ac.VolumeMount().WithName("lightrun-libstdc").WithMountPath("/tmp/libstdc/"),
)
}

// Always set LIGHTRUN_SERVER
envVars := []*corev1ac.EnvVarApplyConfiguration{
Expand All @@ -355,6 +414,12 @@ func (r *LightrunJavaAgentReconciler) addInitContainerToStatefulSet(statefulSetA
),
)
}
// If MountLibstdc is enabled, set the MOUNT_LIBSTDC env var to signal the script
if spec.MountLibstdc {
envVars = append(envVars,
corev1ac.EnvVar().WithName("MOUNT_LIBSTDC").WithValue("true"),
)
}

initContainer := corev1ac.Container().
WithName(initContainerName).
Expand Down Expand Up @@ -387,6 +452,7 @@ func (r *LightrunJavaAgentReconciler) addInitContainerToStatefulSet(statefulSetA
},
),
)

if isImagePullPolicyConfigured {
initContainer.WithImagePullPolicy(spec.InitContainer.ImagePullPolicy)
}
Expand All @@ -399,14 +465,32 @@ func (r *LightrunJavaAgentReconciler) patchStatefulSetAppContainers(lightrunJava
for _, targetContainer := range lightrunJavaAgent.Spec.ContainerSelector {
if targetContainer == container.Name {
found = true
statefulSetApplyConfig.Spec.Template.Spec.WithContainers(
corev1ac.Container().
WithName(container.Name).
WithImage(container.Image).
WithVolumeMounts(
corev1ac.VolumeMount().WithMountPath(lightrunJavaAgent.Spec.InitContainer.SharedVolumeMountPath).WithName(lightrunJavaAgent.Spec.InitContainer.SharedVolumeName),
),
)

// Prepare volume mounts
volumeMounts := []*corev1ac.VolumeMountApplyConfiguration{
corev1ac.VolumeMount().WithMountPath(lightrunJavaAgent.Spec.InitContainer.SharedVolumeMountPath).WithName(lightrunJavaAgent.Spec.InitContainer.SharedVolumeName),
}

// Add libstdc volume mount if MountLibstdc is enabled
if lightrunJavaAgent.Spec.MountLibstdc {
volumeMounts = append(volumeMounts,
corev1ac.VolumeMount().WithName("lightrun-libstdc").WithMountPath("/tmp/libstdc").WithReadOnly(true),
)
}

containerConfig := corev1ac.Container().
WithName(container.Name).
WithImage(container.Image).
WithVolumeMounts(volumeMounts...)

// Add LD_LIBRARY_PATH environment variable if MountLibstdc is enabled
if lightrunJavaAgent.Spec.MountLibstdc {
containerConfig.WithEnv(
corev1ac.EnvVar().WithName("LD_LIBRARY_PATH").WithValue("/tmp/libstdc"),
)
}

statefulSetApplyConfig.Spec.Template.Spec.WithContainers(containerConfig)
}
}
}
Expand Down
4 changes: 3 additions & 1 deletion lightrun-init-agent/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ RUN unzip -o /tmp/$FILE -d /agent ;\
# Create secret directory
mkdir -p /etc/lightrun/secret && \
chgrp -R 0 /etc/lightrun/secret && \
chmod -R g=u /etc/lightrun/secret
chmod -R g=u /etc/lightrun/secret && \
# Install libstdc++ for Alpine-based support
apk add --no-cache libstdc++

# Copy and set permissions for update_config.sh before switching user
COPY lightrun-init-agent/update_config.sh /update_config.sh
Expand Down
74 changes: 74 additions & 0 deletions lightrun-init-agent/update_config.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
# 3. Merges configuration files
# 4. Updates configuration with values from files
# 5. Copies the final configuration to destination
# 6. Optionally copies libstdc++ libraries for Alpine-based images

set -e

Expand All @@ -15,6 +16,7 @@ WORK_DIR="${TMP_DIR}/agent-workdir"
FINAL_DEST="${TMP_DIR}/agent"
CONFIG_MAP_DIR="${TMP_DIR}/cm"
SECRET_DIR="/etc/lightrun/secret"
LIBSTDC_DIR="${TMP_DIR}/libstdc"

# Function to get value from either environment variable or file
get_value() {
Expand Down Expand Up @@ -150,8 +152,80 @@ cleanup() {
rm -rf "${WORK_DIR}"
}

# Function to copy libstdc++ libraries
copy_libstdc() {
if [ "${MOUNT_LIBSTDC}" = "true" ]; then
echo "========================================="
echo "COPYING LIBSTDC++ LIBRARIES"
echo "========================================="

# Create the directory
mkdir -p "${LIBSTDC_DIR}"
echo "Created directory: ${LIBSTDC_DIR}"
echo ""

# Search for and copy libstdc++ libraries
echo "Searching for libstdc++ libraries..."
echo "Running as user: $(id)"
echo ""

# List of paths to search
for search_path in /usr/lib /lib /usr/lib64 /lib64 /usr/lib/aarch64-linux-gnu /lib/aarch64-linux-gnu /usr/lib/x86_64-linux-gnu /lib/x86_64-linux-gnu; do
if [ -d "${search_path}" ]; then
echo "Checking ${search_path}..."
# Use ls instead of find for simpler logic
lib_files=$(ls "${search_path}"/libstdc++.so* 2>/dev/null || true)
if [ -n "${lib_files}" ]; then
for lib_file in ${lib_files}; do
if [ -f "${lib_file}" ] || [ -L "${lib_file}" ]; then
echo " Found: ${lib_file}"
# Try to copy following symlinks first, then regular copy
if cp -L "${lib_file}" "${LIBSTDC_DIR}/" 2>/dev/null; then
echo " ✓ Copied (following symlink)"
elif cp "${lib_file}" "${LIBSTDC_DIR}/" 2>/dev/null; then
echo " ✓ Copied (as-is)"
else
echo " ✗ Failed to copy"
fi
fi
done
fi
fi
done

echo ""
echo "----------------------------------------"
echo "Contents of ${LIBSTDC_DIR}:"
if ls -lah "${LIBSTDC_DIR}/" 2>/dev/null; then
echo "----------------------------------------"
else
echo " (empty or not accessible)"
echo "----------------------------------------"
fi

# Count files (excluding . and ..)
lib_count=$(find "${LIBSTDC_DIR}" -maxdepth 1 -type f -o -type l | wc -l)
if [ "${lib_count}" -gt 0 ]; then
echo "✓ Successfully copied ${lib_count} libstdc++ library file(s)"
else
echo "⚠ WARNING: No libstdc++ libraries were copied!"
echo " Debugging information:"
echo " - Checking if libstdc++ is installed:"
apk info libstdc++ 2>/dev/null || echo " libstdc++ package not found"
echo " - Looking for any libstdc++ files:"
find /usr /lib -name '*libstdc++*' 2>/dev/null | head -10 || echo " No files found"
fi

echo "========================================="
echo ""
else
echo "MOUNT_LIBSTDC not set to 'true', skipping libstdc++ library copying"
fi
}

# Main execution
main() {
copy_libstdc
validate_env_vars
setup_working_dir
merge_configs
Expand Down