diff --git a/Makefile b/Makefile index 254883859..c4fd3cb92 100644 --- a/Makefile +++ b/Makefile @@ -194,3 +194,8 @@ cli-install: @echo "Installing odigos from source. version: $(ODIGOS_CLI_VERSION)" go run -tags=embed_manifests ./cli install --version $(ODIGOS_CLI_VERSION) + +.PHONY: cli-upgrade +cli-upgrade: + @echo "Installing odigos from source. version: $(ODIGOS_CLI_VERSION)" + go run -tags=embed_manifests ./cli upgrade --version $(ODIGOS_CLI_VERSION) --yes \ No newline at end of file diff --git a/api/config/crd/bases/odigos.io_instrumentedapplications.yaml b/api/config/crd/bases/odigos.io_instrumentedapplications.yaml index 35fdec10f..ef69bab68 100644 --- a/api/config/crd/bases/odigos.io_instrumentedapplications.yaml +++ b/api/config/crd/bases/odigos.io_instrumentedapplications.yaml @@ -110,6 +110,8 @@ spec: - unknown - ignored type: string + runtimeVersion: + type: string required: - containerName - language diff --git a/api/generated/odigos/applyconfiguration/odigos/v1alpha1/runtimedetailsbycontainer.go b/api/generated/odigos/applyconfiguration/odigos/v1alpha1/runtimedetailsbycontainer.go index 5a78388c2..017462743 100644 --- a/api/generated/odigos/applyconfiguration/odigos/v1alpha1/runtimedetailsbycontainer.go +++ b/api/generated/odigos/applyconfiguration/odigos/v1alpha1/runtimedetailsbycontainer.go @@ -24,9 +24,10 @@ import ( // RuntimeDetailsByContainerApplyConfiguration represents an declarative configuration of the RuntimeDetailsByContainer type for use // with apply. type RuntimeDetailsByContainerApplyConfiguration struct { - ContainerName *string `json:"containerName,omitempty"` - Language *common.ProgrammingLanguage `json:"language,omitempty"` - EnvVars []EnvVarApplyConfiguration `json:"envVars,omitempty"` + ContainerName *string `json:"containerName,omitempty"` + Language *common.ProgrammingLanguage `json:"language,omitempty"` + RuntimeVersion *string `json:"runtimeVersion,omitempty"` + EnvVars []EnvVarApplyConfiguration `json:"envVars,omitempty"` } // RuntimeDetailsByContainerApplyConfiguration constructs an declarative configuration of the RuntimeDetailsByContainer type for use with @@ -51,6 +52,14 @@ func (b *RuntimeDetailsByContainerApplyConfiguration) WithLanguage(value common. return b } +// WithRuntimeVersion sets the RuntimeVersion field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the RuntimeVersion field is set to the value of the last call. +func (b *RuntimeDetailsByContainerApplyConfiguration) WithRuntimeVersion(value string) *RuntimeDetailsByContainerApplyConfiguration { + b.RuntimeVersion = &value + return b +} + // WithEnvVars adds the given value to the EnvVars field in the declarative configuration // and returns the receiver, so that objects can be build by chaining "With" function invocations. // If called multiple times, values provided by each call will be appended to the EnvVars field. diff --git a/api/odigos/v1alpha1/instrumentedapplication_types.go b/api/odigos/v1alpha1/instrumentedapplication_types.go index 674f8e4d4..2548dcddf 100644 --- a/api/odigos/v1alpha1/instrumentedapplication_types.go +++ b/api/odigos/v1alpha1/instrumentedapplication_types.go @@ -21,41 +21,42 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) -//+kubebuilder:object:generate=true +// +kubebuilder:object:generate=true type ConfigOption struct { - OptionKey string `json:"optionKey"` + OptionKey string `json:"optionKey"` SpanKind common.SpanKind `json:"spanKind"` } -//+kubebuilder:object:generate=true +// +kubebuilder:object:generate=true type InstrumentationLibraryOptions struct { - LibraryName string `json:"libraryName"` - Options []ConfigOption `json:"options"` + LibraryName string `json:"libraryName"` + Options []ConfigOption `json:"options"` } -//+kubebuilder:object:generate=true +// +kubebuilder:object:generate=true type EnvVar struct { Name string `json:"name"` Value string `json:"value"` } -//+kubebuilder:object:generate=true +// +kubebuilder:object:generate=true type RuntimeDetailsByContainer struct { - ContainerName string `json:"containerName"` - Language common.ProgrammingLanguage `json:"language"` - EnvVars []EnvVar `json:"envVars,omitempty"` + ContainerName string `json:"containerName"` + Language common.ProgrammingLanguage `json:"language"` + RuntimeVersion string `json:"runtimeVersion,omitempty"` + EnvVars []EnvVar `json:"envVars,omitempty"` } // +kubebuilder:object:generate=true type OptionByContainer struct { - ContainerName string `json:"containerName"` + ContainerName string `json:"containerName"` InstrumentationLibraries []InstrumentationLibraryOptions `json:"instrumentationsLibraries"` } // InstrumentedApplicationSpec defines the desired state of InstrumentedApplication type InstrumentedApplicationSpec struct { RuntimeDetails []RuntimeDetailsByContainer `json:"runtimeDetails,omitempty"` - Options []OptionByContainer `json:"options,omitempty"` + Options []OptionByContainer `json:"options,omitempty"` } // InstrumentedApplicationStatus defines the observed state of InstrumentedApplication diff --git a/common/lang_detection.go b/common/lang_detection.go index afc27115a..a1cfe0ec2 100644 --- a/common/lang_detection.go +++ b/common/lang_detection.go @@ -1,5 +1,10 @@ package common +type ProgramLanguageDetails struct { + Language ProgrammingLanguage + RuntimeVersion string +} + // +kubebuilder:validation:Enum=java;python;go;dotnet;javascript;mysql;unknown;ignored type ProgrammingLanguage string diff --git a/helm/odigos/templates/crds/instrumentedapplications.yaml b/helm/odigos/templates/crds/instrumentedapplications.yaml index 626f00e6d..fe1a215eb 100644 --- a/helm/odigos/templates/crds/instrumentedapplications.yaml +++ b/helm/odigos/templates/crds/instrumentedapplications.yaml @@ -112,6 +112,8 @@ spec: - unknown - ignored type: string + runtimeVersion: + type: string required: - containerName - language diff --git a/odiglet/debug.Dockerfile b/odiglet/debug.Dockerfile index cc6805583..780411f4a 100644 --- a/odiglet/debug.Dockerfile +++ b/odiglet/debug.Dockerfile @@ -1,12 +1,52 @@ FROM python:3.11 AS python-builder +ARG ODIGOS_VERSION WORKDIR /python-instrumentation -ADD odiglet/agents/python/requirements.txt . -RUN mkdir workspace && pip install --target workspace -r requirements.txt +COPY ../agents/python ./agents/python +RUN echo "VERSION = \"$ODIGOS_VERSION\";" > ./agents/python/configurator/version.py +RUN mkdir workspace && pip install ./agents/python/ --target workspace -FROM node:16 AS nodejs-builder + +######### Node.js Native Community Agent ######### +# +# The Node.js agent is built in multiple stages so it can be built with either upstream +# @odigos/opentelemetry-node or with a local clone to test changes during development. +# The implemntation is based on the following blog post: +# https://www.docker.com/blog/dockerfiles-now-support-multiple-build-contexts/ + +# The first build stage 'nodejs-agent-native-community-clone' clones the agent sources from github main branch. +FROM alpine AS nodejs-agent-native-community-clone +RUN apk add git +WORKDIR /src +ARG NODEJS_AGENT_VERSION=main +RUN git clone https://github.com/odigos-io/opentelemetry-node.git && cd opentelemetry-node && git checkout $NODEJS_AGENT_VERSION + +# The second build stage 'nodejs-agent-native-community-src' prepares the actual code we are going to compile and embed in odiglet. +# By default, it uses the previous 'nodejs-agent-native-community-src' stage, but one can override it by setting the +# --build-context nodejs-agent-native-community-src=../opentelemetry-node flag in the docker build command. +# This allows us to nobe the agent sources and test changes during development. +# The output of this stage is the resolved source code to be used in the next stage. +FROM scratch AS nodejs-agent-native-community-src +COPY --from=nodejs-agent-native-community-clone /src/opentelemetry-node / + +# The third build stage 'nodejs-agent-native-community-builder' compiles the agent sources and prepares the final output. +# it COPY from the previous 'nodejs-agent-native-community-src' stage, so it can be used with either the upstream or local sources. +# The output of this stage is the compiled agent code in: +# - package source code in '/nodejs-instrumentation/build/src' directory. +# - all required dependencies in '/nodejs-instrumentation/prod_node_modules' directory. +# These artifacts are later copied into the odiglet final image to be mounted into auto-instrumented pods at runtime. +FROM node:18 AS nodejs-agent-native-community-builder +ARG ODIGOS_VERSION WORKDIR /nodejs-instrumentation -COPY odiglet/agents/nodejs . -RUN npm install +COPY --from=nodejs-agent-native-community-src /package.json /yarn.lock ./ +# prepare the production node_modules content in a separate directory +RUN yarn --production --frozen-lockfile +RUN mv node_modules ./prod_node_modules +# install all dependencies including dev so we can yarn compile +RUN yarn --frozen-lockfile +COPY --from=nodejs-agent-native-community-src / ./ +# inject the actual version into the agent code +RUN echo "export const VERSION = \"$ODIGOS_VERSION\";" > ./src/version.ts +RUN yarn compile FROM busybox:1.36.1 AS dotnet-builder WORKDIR /dotnet-instrumentation @@ -23,13 +63,14 @@ RUN ARCH_SUFFIX=$(cat /tmp/arch_suffix) && \ unzip opentelemetry-dotnet-instrumentation-linux-glibc-${ARCH_SUFFIX}.zip && \ rm opentelemetry-dotnet-instrumentation-linux-glibc-${ARCH_SUFFIX}.zip -FROM --platform=$BUILDPLATFORM keyval/odiglet-base:v1.5 as builder +FROM --platform=$BUILDPLATFORM keyval/odiglet-base:v1.5 AS builder WORKDIR /go/src/github.com/odigos-io/odigos # Copyy local modules required by the build COPY api/ api/ COPY common/ common/ COPY k8sutils/ k8sutils/ COPY procdiscovery/ procdiscovery/ +COPY opampserver/ opampserver/ WORKDIR /go/src/github.com/odigos-io/odigos/odiglet COPY odiglet/ . @@ -52,7 +93,9 @@ RUN chmod 644 /instrumentations/java/javaagent.jar COPY --from=python-builder /python-instrumentation/workspace /instrumentations/python # NodeJS -COPY --from=nodejs-builder /nodejs-instrumentation/build/workspace /instrumentations/nodejs +COPY --from=nodejs-agent-native-community-builder /nodejs-instrumentation/build/src /instrumentations/nodejs +COPY --from=nodejs-agent-native-community-builder /nodejs-instrumentation/prod_node_modules /instrumentations/nodejs/node_modules + # .NET COPY --from=dotnet-builder /dotnet-instrumentation /instrumentations/dotnet diff --git a/odiglet/pkg/kube/runtime_details/inspection.go b/odiglet/pkg/kube/runtime_details/inspection.go index 0a0c43ed0..bbfb80428 100644 --- a/odiglet/pkg/kube/runtime_details/inspection.go +++ b/odiglet/pkg/kube/runtime_details/inspection.go @@ -93,13 +93,13 @@ func runtimeInspection(pods []corev1.Pod, ignoredContainers []string) ([]odigosv continue } - var lang common.ProgrammingLanguage + programLanguageDetails := common.ProgramLanguageDetails{Language: common.UnknownProgrammingLanguage} var inspectProc *procdiscovery.Details var detectErr error for _, proc := range processes { - lang, detectErr = inspectors.DetectLanguage(proc) - if detectErr == nil && lang != common.UnknownProgrammingLanguage { + programLanguageDetails, detectErr = inspectors.DetectLanguage(proc) + if detectErr == nil && programLanguageDetails.Language != common.UnknownProgrammingLanguage { inspectProc = &proc break } @@ -108,22 +108,24 @@ func runtimeInspection(pods []corev1.Pod, ignoredContainers []string) ([]odigosv envs := make([]odigosv1.EnvVar, 0) if inspectProc == nil { log.Logger.V(0).Info("unable to detect language for any process", "pod", pod.Name, "container", container.Name, "namespace", pod.Namespace) - lang = common.UnknownProgrammingLanguage + programLanguageDetails.Language = common.UnknownProgrammingLanguage } else { if len(processes) > 1 { log.Logger.V(0).Info("multiple processes found in pod container, only taking the first one with detected language into account", "pod", pod.Name, "container", container.Name, "namespace", pod.Namespace) } + // Convert map to slice for k8s format - envs = make([]odigosv1.EnvVar, 0, len(inspectProc.Envs)) - for envName, envValue := range inspectProc.Envs { + envs = make([]odigosv1.EnvVar, 0, len(inspectProc.Environments.DetailedEnvs)) + for envName, envValue := range inspectProc.Environments.OverwriteEnvs { envs = append(envs, odigosv1.EnvVar{Name: envName, Value: envValue}) } } resultsMap[container.Name] = odigosv1.RuntimeDetailsByContainer{ - ContainerName: container.Name, - Language: lang, - EnvVars: envs, + ContainerName: container.Name, + Language: programLanguageDetails.Language, + RuntimeVersion: programLanguageDetails.RuntimeVersion, + EnvVars: envs, } } } diff --git a/procdiscovery/pkg/inspectors/dotnet/dotnet.go b/procdiscovery/pkg/inspectors/dotnet/dotnet.go index b58724773..ad5d0bb4a 100644 --- a/procdiscovery/pkg/inspectors/dotnet/dotnet.go +++ b/procdiscovery/pkg/inspectors/dotnet/dotnet.go @@ -16,14 +16,16 @@ const ( dotnet = "DOTNET" ) -func (d *DotnetInspector) Inspect(p *process.Details) (common.ProgrammingLanguage, bool) { +func (d *DotnetInspector) Inspect(p *process.Details) (common.ProgramLanguageDetails, bool) { + var programLanguageDetails common.ProgramLanguageDetails data, err := os.ReadFile(fmt.Sprintf("/proc/%d/environ", p.ProcessID)) if err == nil { environ := string(data) if strings.Contains(environ, aspnet) || strings.Contains(environ, dotnet) { - return common.DotNetProgrammingLanguage, true + programLanguageDetails.Language = common.DotNetProgrammingLanguage + return programLanguageDetails, true } } - return "", false + return programLanguageDetails, false } diff --git a/procdiscovery/pkg/inspectors/golang/golang.go b/procdiscovery/pkg/inspectors/golang/golang.go index 7a53ec194..3bc04d421 100644 --- a/procdiscovery/pkg/inspectors/golang/golang.go +++ b/procdiscovery/pkg/inspectors/golang/golang.go @@ -10,12 +10,18 @@ import ( type GolangInspector struct{} -func (g *GolangInspector) Inspect(p *process.Details) (common.ProgrammingLanguage, bool) { +func (g *GolangInspector) Inspect(p *process.Details) (common.ProgramLanguageDetails, bool) { + var programLanguageDetails common.ProgramLanguageDetails file := fmt.Sprintf("/proc/%d/exe", p.ProcessID) - _, err := buildinfo.ReadFile(file) + buildInfo, err := buildinfo.ReadFile(file) if err != nil { - return "", false + return programLanguageDetails, false } - return common.GoProgrammingLanguage, true + programLanguageDetails.Language = common.GoProgrammingLanguage + if buildInfo != nil { + programLanguageDetails.RuntimeVersion = buildInfo.GoVersion + } + + return programLanguageDetails, true } diff --git a/procdiscovery/pkg/inspectors/java/java.go b/procdiscovery/pkg/inspectors/java/java.go index 6e1a0096d..8a275a3ff 100644 --- a/procdiscovery/pkg/inspectors/java/java.go +++ b/procdiscovery/pkg/inspectors/java/java.go @@ -11,10 +11,17 @@ type JavaInspector struct{} const processName = "java" -func (j *JavaInspector) Inspect(p *process.Details) (common.ProgrammingLanguage, bool) { - if strings.Contains(p.ExeName, processName) || strings.Contains(p.CmdLine, processName) { - return common.JavaProgrammingLanguage, true +func (j *JavaInspector) Inspect(proc *process.Details) (common.ProgramLanguageDetails, bool) { + var programLanguageDetails common.ProgramLanguageDetails + + if strings.Contains(proc.ExeName, processName) || strings.Contains(proc.CmdLine, processName) { + programLanguageDetails.Language = common.JavaProgrammingLanguage + if value, exists := proc.GetDetailedEnvsValue(process.JavaVersionConst); exists { + programLanguageDetails.RuntimeVersion = value + } + + return programLanguageDetails, true } - return "", false + return programLanguageDetails, false } diff --git a/procdiscovery/pkg/inspectors/langdetect.go b/procdiscovery/pkg/inspectors/langdetect.go index 77c020ff8..8b114a2ee 100644 --- a/procdiscovery/pkg/inspectors/langdetect.go +++ b/procdiscovery/pkg/inspectors/langdetect.go @@ -22,7 +22,7 @@ func (e ErrLanguageDetectionConflict) Error() string { } type inspector interface { - Inspect(process *process.Details) (common.ProgrammingLanguage, bool) + Inspect(process *process.Details) (common.ProgramLanguageDetails, bool) } var inspectorsList = []inspector{ @@ -37,23 +37,28 @@ var inspectorsList = []inspector{ // DetectLanguage returns the detected language for the process or // common.UnknownProgrammingLanguage if the language could not be detected, in which case error == nil // if error or language detectors disagree common.UnknownProgrammingLanguage is also returned -func DetectLanguage(process process.Details) (common.ProgrammingLanguage, error) { - detectedLanguage := common.UnknownProgrammingLanguage +func DetectLanguage(process process.Details) (common.ProgramLanguageDetails, error) { + detectedProgramLanguageDetails := common.ProgramLanguageDetails{ + Language: common.UnknownProgrammingLanguage, + } + for _, i := range inspectorsList { - language, detected := i.Inspect(&process) + languageDetails, detected := i.Inspect(&process) if detected { - if detectedLanguage == common.UnknownProgrammingLanguage { - detectedLanguage = language + if detectedProgramLanguageDetails.Language == common.UnknownProgrammingLanguage { + detectedProgramLanguageDetails = languageDetails continue } - return common.UnknownProgrammingLanguage, ErrLanguageDetectionConflict{ - languages: [2]common.ProgrammingLanguage{ - detectedLanguage, - language, - }, - } + return common.ProgramLanguageDetails{ + Language: common.UnknownProgrammingLanguage, + }, ErrLanguageDetectionConflict{ + languages: [2]common.ProgrammingLanguage{ + detectedProgramLanguageDetails.Language, + languageDetails.Language, + }, + } } } - return detectedLanguage, nil + return detectedProgramLanguageDetails, nil } diff --git a/procdiscovery/pkg/inspectors/mysql/mysql.go b/procdiscovery/pkg/inspectors/mysql/mysql.go index 11766e069..ae141a8b6 100644 --- a/procdiscovery/pkg/inspectors/mysql/mysql.go +++ b/procdiscovery/pkg/inspectors/mysql/mysql.go @@ -13,10 +13,12 @@ type MySQLInspector struct{} const MySQLProcessName = "mysqld" -func (j *MySQLInspector) Inspect(p *process.Details) (common.ProgrammingLanguage, bool) { +func (j *MySQLInspector) Inspect(p *process.Details) (common.ProgramLanguageDetails, bool) { + var programLanguageDetails common.ProgramLanguageDetails if strings.HasSuffix(p.ExeName, MySQLProcessName) || strings.HasSuffix(p.CmdLine, MySQLProcessName) { - return common.MySQLProgrammingLanguage, true + programLanguageDetails.Language = common.MySQLProgrammingLanguage + return programLanguageDetails, true } - return "", false + return programLanguageDetails, false } diff --git a/procdiscovery/pkg/inspectors/nodejs/nodejs.go b/procdiscovery/pkg/inspectors/nodejs/nodejs.go index f8f3ba043..378617a94 100644 --- a/procdiscovery/pkg/inspectors/nodejs/nodejs.go +++ b/procdiscovery/pkg/inspectors/nodejs/nodejs.go @@ -11,10 +11,17 @@ type NodejsInspector struct{} const nodeProcessName = "node" -func (n *NodejsInspector) Inspect(process *process.Details) (common.ProgrammingLanguage, bool) { - if strings.Contains(process.ExeName, nodeProcessName) || strings.Contains(process.CmdLine, nodeProcessName) { - return common.JavascriptProgrammingLanguage, true +func (n *NodejsInspector) Inspect(proc *process.Details) (common.ProgramLanguageDetails, bool) { + var programLanguageDetails common.ProgramLanguageDetails + + if strings.Contains(proc.ExeName, nodeProcessName) || strings.Contains(proc.CmdLine, nodeProcessName) { + programLanguageDetails.Language = common.JavascriptProgrammingLanguage + if value, exists := proc.GetDetailedEnvsValue(process.NodeVersionConst); exists { + programLanguageDetails.RuntimeVersion = value + } + + return programLanguageDetails, true } - return "", false + return programLanguageDetails, false } diff --git a/procdiscovery/pkg/inspectors/python/python.go b/procdiscovery/pkg/inspectors/python/python.go index 6eac846f2..dcdad063a 100644 --- a/procdiscovery/pkg/inspectors/python/python.go +++ b/procdiscovery/pkg/inspectors/python/python.go @@ -11,10 +11,16 @@ type PythonInspector struct{} const pythonProcessName = "python" -func (p *PythonInspector) Inspect(process *process.Details) (common.ProgrammingLanguage, bool) { - if strings.Contains(process.ExeName, pythonProcessName) || strings.Contains(process.CmdLine, pythonProcessName) { - return common.PythonProgrammingLanguage, true +func (p *PythonInspector) Inspect(proc *process.Details) (common.ProgramLanguageDetails, bool) { + var programLanguageDetails common.ProgramLanguageDetails + if strings.Contains(proc.ExeName, pythonProcessName) || strings.Contains(proc.CmdLine, pythonProcessName) { + programLanguageDetails.Language = common.PythonProgrammingLanguage + if value, exists := proc.GetDetailedEnvsValue(process.PythonVersionConst); exists { + programLanguageDetails.RuntimeVersion = value + } + + return programLanguageDetails, true } - return "", false + return programLanguageDetails, false } diff --git a/procdiscovery/pkg/process/process.go b/procdiscovery/pkg/process/process.go index 8bb7ce069..95184e874 100644 --- a/procdiscovery/pkg/process/process.go +++ b/procdiscovery/pkg/process/process.go @@ -10,12 +10,34 @@ import ( "github.com/odigos-io/odigos/common/envOverwrite" ) +const NodeVersionConst = "NODE_VERSION" +const PythonVersionConst = "PYTHON_VERSION" +const JavaVersionConst = "JAVA_VERSION" + +// envDetailsMap is a map of environment variables and their separators +var envDetailsMap = map[string]struct{}{NodeVersionConst: {}, PythonVersionConst: {}, JavaVersionConst: {}} + type Details struct { - ProcessID int - ExeName string - CmdLine string - // Envs only contains the environment variables that we are interested in - Envs map[string]string + ProcessID int + ExeName string + CmdLine string + Environments ProcessEnvs +} + +type ProcessEnvs struct { + DetailedEnvs map[string]string + // OverwriteEnvs only contains environment variables that Odigos is using for auto-instrumentation and may need to be overwritten + OverwriteEnvs map[string]string +} + +func (d *Details) GetDetailedEnvsValue(key string) (string, bool) { + value, exists := d.Environments.DetailedEnvs[key] + return value, exists +} + +func (d *Details) GetOverwriteEnvsValue(key string) (string, bool) { + value, exists := d.Environments.OverwriteEnvs[key] + return value, exists } // Find all processes in the system. @@ -60,10 +82,10 @@ func GetPidDetails(pid int) Details { envVars := getRelevantEnvVars(pid) return Details{ - ProcessID: pid, - ExeName: exeName, - CmdLine: cmdLine, - Envs: envVars, + ProcessID: pid, + ExeName: exeName, + CmdLine: cmdLine, + Environments: envVars, } } @@ -95,24 +117,26 @@ func getCommandLine(pid int) string { } } -func getRelevantEnvVars(pid int) map[string]string { +func getRelevantEnvVars(pid int) ProcessEnvs { envFileName := fmt.Sprintf("/proc/%d/environ", pid) fileContent, err := os.ReadFile(envFileName) if err != nil { // TODO: if we fail to read the environment variables, we should probably return an error // which will cause the process to be skipped and not instrumented? - return nil + return ProcessEnvs{} } r := bufio.NewReader(strings.NewReader(string(fileContent))) - result := make(map[string]string) // We only care about the environment variables that we might overwrite - relevantEnvVars := make(map[string]interface{}) + relevantOverwriteEnvVars := make(map[string]interface{}) for k := range envOverwrite.EnvValuesMap { - relevantEnvVars[k] = nil + relevantOverwriteEnvVars[k] = nil } + overWriteEnvsResult := make(map[string]string) + detailedEnvsResult := make(map[string]string) + for { // The entries are separated by // null bytes ('\0'), and there may be a null byte at the end. @@ -120,7 +144,7 @@ func getRelevantEnvVars(pid int) map[string]string { if err == io.EOF { break } else if err != nil { - return nil + return ProcessEnvs{} } str = strings.TrimRight(str, "\x00") @@ -130,10 +154,20 @@ func getRelevantEnvVars(pid int) map[string]string { continue } - if _, ok := relevantEnvVars[envParts[0]]; ok { - result[envParts[0]] = envParts[1] + if _, ok := relevantOverwriteEnvVars[envParts[0]]; ok { + overWriteEnvsResult[envParts[0]] = envParts[1] + } + + if _, ok := envDetailsMap[envParts[0]]; ok { + detailedEnvsResult[envParts[0]] = envParts[1] } + + } + + envs := ProcessEnvs{ + OverwriteEnvs: overWriteEnvsResult, + DetailedEnvs: detailedEnvsResult, } - return result + return envs } diff --git a/tests/e2e/helm-chart/assert-runtime-detected.yaml b/tests/e2e/helm-chart/assert-runtime-detected.yaml index f0894f78a..dfc26e8a2 100644 --- a/tests/e2e/helm-chart/assert-runtime-detected.yaml +++ b/tests/e2e/helm-chart/assert-runtime-detected.yaml @@ -13,6 +13,7 @@ spec: runtimeDetails: - containerName: coupon language: javascript + runtimeVersion: 18.3.0 --- apiVersion: odigos.io/v1alpha1 kind: InstrumentedApplication @@ -29,6 +30,7 @@ spec: runtimeDetails: - containerName: frontend language: java + runtimeVersion: jdk-17.0.11+9 --- apiVersion: odigos.io/v1alpha1 kind: InstrumentedApplication @@ -45,6 +47,7 @@ spec: runtimeDetails: - containerName: inventory language: python + runtimeVersion: 3.11.9 --- apiVersion: odigos.io/v1alpha1 kind: InstrumentedApplication @@ -61,6 +64,7 @@ spec: runtimeDetails: - containerName: membership language: go + runtimeVersion: go1.21.4 --- apiVersion: odigos.io/v1alpha1 kind: InstrumentedApplication