From 5c43ce28ae96fcd4cf68274d3105c9e94e3cabba Mon Sep 17 00:00:00 2001 From: bduranleau-nr <106178551+bduranleau-nr@users.noreply.github.com> Date: Wed, 9 Oct 2024 12:38:33 -0500 Subject: [PATCH] feat(php): add initcontainer build and bundle logic (#84) * feat(php): add initcontainer build and bundle logic * fix: add download script * chore: improve arg clarity * Update src/php/php-agent-download.sh Co-authored-by: Timothy Pansino <11214426+TimPansino@users.noreply.github.com> * fix: narrow architecture matching * chore: include invalid values in log output * chore: double quotes to prevent globbing * chore: address shellcheck feedback * chore: double quote to prevent globbing * chore: output libc on failure for debugging * add vm composer ini --------- Co-authored-by: Timothy Pansino <11214426+TimPansino@users.noreply.github.com> --- src/php/Dockerfile | 16 +++-- src/php/k8s-php-install.sh | 78 ++++++++++++++++++++++ src/php/newrelic.ini | 5 ++ src/php/nr_env_to_ini.sh | 14 ++++ src/php/nrini.mapping | 121 ++++++++++++++++++++++++++++++++++ src/php/php-agent-download.sh | 27 ++++++++ 6 files changed, 255 insertions(+), 6 deletions(-) create mode 100644 src/php/k8s-php-install.sh create mode 100644 src/php/newrelic.ini create mode 100644 src/php/nr_env_to_ini.sh create mode 100644 src/php/nrini.mapping create mode 100644 src/php/php-agent-download.sh diff --git a/src/php/Dockerfile b/src/php/Dockerfile index c939efd..4e1a686 100644 --- a/src/php/Dockerfile +++ b/src/php/Dockerfile @@ -2,13 +2,17 @@ # - Download the newrelic php artefacts to `/instrumentation` directory. This is required as when instrumenting the pod, # one init container will be created to copy the files to your app's container. # - Grant the necessary access to the files in the `/instrumentation` directory. -FROM alpine:latest@sha256:77726ef6b57ddf65bb551896826ec38bc3e53f75cdde31354fbffb4f25238ebd as build -RUN apk update && apk add ca-certificates -ARG version -ARG architecture -ARG php +FROM alpine:latest@sha256:77726ef6b57ddf65bb551896826ec38bc3e53f75cdde31354fbffb4f25238ebd AS build +RUN apk update && apk add ca-certificates && apk add --no-cache bash +ARG AGENT_VERSION +ARG LIBC WORKDIR /instrumentation -RUN wget -c "https://download.newrelic.com/php_agent/release/newrelic-${php}-${version}-${architecture}.tar.gz" -O - | tar -xz --strip-components 1 +COPY php-agent-download.sh k8s-php-install.sh nr_env_to_ini.sh nrini.mapping ./ +RUN chmod +x php-agent-download.sh k8s-php-install.sh nr_env_to_ini.sh +RUN ./php-agent-download.sh $LIBC $AGENT_VERSION +RUN rm php-agent-download.sh +RUN mkdir php-agent php-agent/bin php-agent/ext php-agent/ini php-agent/logs +COPY newrelic.ini ./php-agent/ini/ FROM busybox:latest@sha256:9ae97d36d26566ff84e8893c64a6dc4fe8ca6d1144bf5b87b2b85a32def253c7 COPY --from=build /instrumentation /instrumentation diff --git a/src/php/k8s-php-install.sh b/src/php/k8s-php-install.sh new file mode 100644 index 0000000..68e5355 --- /dev/null +++ b/src/php/k8s-php-install.sh @@ -0,0 +1,78 @@ +#!/bin/sh + +ZEND_API_NO=$1 # zend representation of the PHP version number +AGENT_FILEPATH=/newrelic-instrumentation/agent +DAEMON_FILEPATH=/newrelic-instrumentation/daemon +INSTALL_LOG=/newrelic-instrumentation/newrelic-install.log + +log() { + msg="$1" + timestamp=$(date +"%m-%d-%Y %T") + echo "${timestamp} : ${msg}" >>${INSTALL_LOG} +} + +if [ -z "${ZEND_API_NO}" ]; then + log "Missing Zend api number. Exiting." + exit 1 +fi + +log "Installing New Relic PHP Agent for the K8S Agent Operator" + +# +# Determine the architecture we are executing on. +# +arch=$( (uname -m) 2>/dev/null) || arch="unknown" +case "${arch}" in + aarch64 | arm64) arch=aarch64 ;; + x86_64 | amd64) arch=x64 ;; +esac + +# exit if arch is unsupported +if [ "${arch}" != "x64" ] && [ "${arch}" != "aarch64" ]; then + msg=$( + cat <>$output_file +fi + +while IFS=':' read -r envvar inivar; do + if [ -n "$(printenv "$envvar")" ]; then + echo "$inivar=$(printenv "$envvar")" >>$output_file + fi +done <"$map_file" diff --git a/src/php/nrini.mapping b/src/php/nrini.mapping new file mode 100644 index 0000000..2374027 --- /dev/null +++ b/src/php/nrini.mapping @@ -0,0 +1,121 @@ +NEW_RELIC_ENABLED:newrelic.enabled +NEW_RELIC_LICENSE:newrelic.license +NEW_RELIC_LOGFILE:newrelic.logfile +NEW_RELIC_LOGLEVEL:newrelic.loglevel +NEW_RELIC_HIGH_SECURITY:newrelic.high_security +NEW_RELIC_APPNAME:newrelic.appname +NEW_RELIC_PROCESS_HOST_DISPLAY_NAME:newrelic.process_host.display_name +NEW_RELIC_DAEMON_LOGFILE:newrelic.daemon.logfile +NEW_RELIC_DAEMON_LOGLEVEL:newrelic.daemon.loglevel +NEW_RELIC_DAEMON_ADDRESS:newrelic.daemon.address +NEW_RELIC_DAEMON_SSL_CA_BUNDLE:newrelic.daemon.ssl_ca_bundle +NEW_RELIC_DAEMON_SSL_CA_PATH:newrelic.daemon.ssl_ca_path +NEW_RELIC_DAEMON_PROXY:newrelic.daemon.proxy +NEW_RELIC_DAEMON_PIDFILE:newrelic.daemon.pidfile +NEW_RELIC_DAEMON_LOCATION:newrelic.daemon.location +NEW_RELIC_DAEMON_COLLECTOR_HOST:newrelic.daemon.collector_host +NEW_RELIC_DAEMON_DONT_LAUNCH:newrelic.daemon.dont_launch +NEW_RELIC_DAEMON_UTILIZATION_DETECT_AWS:newrelic.daemon.utilization.detect_aws +NEW_RELIC_DAEMON_UTILIZATION_DETECT_AZURE:newrelic.daemon.utilization.detect_azure +NEW_RELIC_DAEMON_UTILIZATION_DETECT_GCP:newrelic.daemon.utilization.detect_gcp +NEW_RELIC_DAEMON_UTILIZATION_DETECT_PCF:newrelic.daemon.utilization.detect_pcf +NEW_RELIC_DAEMON_UTILIZATION_DETECT_DOCKER:newrelic.daemon.utilization.detect_docker +NEW_RELIC_DAEMON_UTILIZATION_DETECT_KUBERNETES:newrelic.daemon.utilization.detect_kubernetes +NEW_RELIC_DAEMON_APP_TIMEOUT:newrelic.daemon.app_timeout +NEW_RELIC_DAEMON_APP_CONNECT_TIMEOUT:newrelic.daemon.app_connect_timeout +NEW_RELIC_DAEMON_START_TIMEOUT:newrelic.daemon.start_timeout +NEW_RELIC_ERROR_COLLECTOR_ENABLED:newrelic.error_collector.enabled +NEW_RELIC_ERROR_COLLECTOR_IGNORE_USER_EXCEPTION_HANDLER:newrelic.error_collector.ignore_user_exception_handler +NEW_RELIC_ERROR_COLLECTOR_IGNORE_EXCEPTIONS:newrelic.error_collector.ignore_exceptions +NEW_RELIC_ERROR_COLLECTOR_IGNORE_ERRORS:newrelic.error_collector.ignore_errors +NEW_RELIC_ERROR_COLLECTOR_RECORD_DATABASE_ERRORS:newrelic.error_collector.record_database_errors +NEW_RELIC_ERROR_COLLECTOR_PRIORITIZE_API_ERRORS:newrelic.error_collector.prioritize_api_errors +NEW_RELIC_BROWSER_MONITORING_AUTO_INSTRUMENT:newrelic.browser_monitoring.auto_instrument +NEW_RELIC_TRANSACTION_TRACER_ENABLED:newrelic.transaction_tracer.enabled +NEW_RELIC_TRANSACTION_TRACER_THRESHOLD:newrelic.transaction_tracer.threshold +NEW_RELIC_TRANSACTION_TRACER_DETAIL:newrelic.transaction_tracer.detail +NEW_RELIC_TRANSACTION_TRACER_SLOW_SQL:newrelic.transaction_tracer.slow_sql +NEW_RELIC_TRANSACTION_TRACER_STACK_TRACE_THRESHOLD:newrelic.transaction_tracer.stack_trace_threshold +NEW_RELIC_TRANSACTION_TRACER_EXPLAIN_ENABLED:newrelic.transaction_tracer.explain_enabled +NEW_RELIC_TRANSACTION_TRACER_EXPLAIN_THRESHOLD:newrelic.transaction_tracer.explain_threshold +NEW_RELIC_TRANSACTION_TRACER_RECORD_SQL:newrelic.transaction_tracer.record_sql +NEW_RELIC_TRANSACTION_TRACER_CUSTOM:newrelic.transaction_tracer.custom +NEW_RELIC_TRANSACTION_TRACER_INTERNAL_FUNCTIONS_ENABLED:newrelic.transaction_tracer.internal_functions_enabled +NEW_RELIC_FRAMEWORK:newrelic.framework +NEW_RELIC_WEBTRANSACTION_NAME_REMOVE_TRAILING_PATH:newrelic.webtransaction.name.remove_trailing_path +NEW_RELIC_WEBTRANSACTION_NAME_FUNCTIONS:newrelic.webtransaction.name.functions +NEW_RELIC_WEBTRANSACTION_NAME_FILES:newrelic.webtransaction.name.files +NEW_RELIC_DAEMON_AUDITLOG:newrelic.daemon.auditlog +NEW_RELIC_TRANSACTION_EVENTS_ENABLED:newrelic.transaction_events.enabled +NEW_RELIC_ATTRIBUTES_ENABLED:newrelic.attributes.enabled +NEW_RELIC_TRANSACTION_EVENTS_ATTRIBUTES_ENABLED:newrelic.transaction_events.attributes.enabled +NEW_RELIC_TRANSACTION_TRACER_ATTRIBUTES_ENABLED:newrelic.transaction_tracer.attributes.enabled +NEW_RELIC_ERROR_COLLECTOR_ATTRIBUTES_ENABLED:newrelic.error_collector.attributes.enabled +NEW_RELIC_BROWSER_MONITORING_ATTRIBUTES_ENABLED:newrelic.browser_monitoring.attributes.enabled +NEW_RELIC_SPAN_EVENTS_ATTRIBUTES_ENABLED:newrelic.span_events.attributes.enabled +NEW_RELIC_ATTRIBUTES_INCLUDE:newrelic.attributes.include +NEW_RELIC_ATTRIBUTES_EXCLUDE:newrelic.attributes.exclude +NEW_RELIC_TRANSACTION_EVENTS_ATTRIBUTES_INCLUDE:newrelic.transaction_events.attributes.include +NEW_RELIC_TRANSACTION_EVENTS_ATTRIBUTES_EXCLUDE:newrelic.transaction_events.attributes.exclude +NEW_RELIC_TRANSACTION_TRACER_ATTRIBUTES_INCLUDE:newrelic.transaction_tracer.attributes.include +NEW_RELIC_TRANSACTION_TRACER_ATTRIBUTES_EXCLUDE:newrelic.transaction_tracer.attributes.exclude +NEW_RELIC_ERROR_COLLECTOR_ATTRIBUTES_INCLUDE:newrelic.error_collector.attributes.include +NEW_RELIC_ERROR_COLLECTOR_ATTRIBUTES_EXCLUDE:newrelic.error_collector.attributes.exclude +NEW_RELIC_BROWSER_MONITORING_ATTRIBUTES_INCLUDE:newrelic.browser_monitoring.attributes.include +NEW_RELIC_BROWSER_MONITORING_ATTRIBUTES_EXCLUDE:newrelic.browser_monitoring.attributes.exclude +NEW_RELIC_SPAN_EVENTS_ATTRIBUTES_INCLUDE:newrelic.span_events.attributes.include +NEW_RELIC_SPAN_EVENTS_ATTRIBUTES_EXCLUDE:newrelic.span_events.attributes.exclude +NEW_RELIC_FEATURE_FLAG:newrelic.feature_flag +NEW_RELIC_CUSTOM_INSIGHTS_EVENTS_ENABLED:newrelic.custom_insights_events.enabled +NEW_RELIC_CUSTOM_INSIGHTS_EVENTS_MAX_SAMPLES_STORED:newrelic.custom_events.max_samples_stored +NEW_RELIC_LABELS:newrelic.labels +NEW_RELIC_SYNTHETICS_ENABLED:newrelic.synthetics.enabled +NEW_RELIC_CROSS_APPLICATION_TRACER_ENABLED:newrelic.cross_application_tracer.enabled +NEW_RELIC_DISTRIBUTED_TRACING_ENABLED:newrelic.distributed_tracing_enabled +NEW_RELIC_DISTRIBUTED_TRACING_EXCLUDE_NEWRELIC_HEADER:newrelic.distributed_tracing_exclude_newrelic_header +NEW_RELIC_SPAN_EVENTS_ENABLED:newrelic.span_events_enabled +NEW_RELIC_SPAN_EVENTS_MAX_SAMPLES_STORED:newrelic.span_events.max_samples_stored +NEW_RELIC_INFINITE_TRACING_TRACE_OBSERVER_HOST:newrelic.infinite_tracing.trace_observer.host +NEW_RELIC_INFINITE_TRACING_TRACE_OBSERVER_PORT:newrelic.infinite_tracing.trace_observer.port +NEW_RELIC_INFINITE_TRACING_SPAN_EVENTS_QUEUE_SIZE:newrelic.infinite_tracing.span_events.queue_size +NEW_RELIC_TRANSACTION_TRACER_GATHER_INPUT_QUERIES:newrelic.transaction_tracer.gather_input_queries +NEW_RELIC_ERROR_COLLECTOR_CAPTURE_EVENTS:newrelic.error_collector.capture_events +NEW_RELIC_GUZZLE_ENABLED:newrelic.guzzle.enabled +NEW_RELIC_PHPUNIT_EVENTS_ENABLED:newrelic.phpunit_events.enabled +NEW_RELIC_DATASTORE_TRACER_INSTANCE_REPORTING_ENABLED:newrelic.datastore_tracer.instance_reporting.enabled +NEW_RELIC_DATASTORE_TRACER_DATABASE_NAME_REPORTING_ENABLED:newrelic.datastore_tracer.database_name_reporting.enabled +NEW_RELIC_SECURITY_POLICIES_TOKEN:newrelic.security_policies_token +NEW_RELIC_PRELOAD_FRAMEWORK_LIBRARY_DETECTION:newrelic.preload_framework_library_detection +NEW_RELIC_TRANSACTION_TRACER_MAX_SEGMENTS_WEB:newrelic.transaction_tracer.max_segments_web +NEW_RELIC_TRANSACTION_TRACER_MAX_SEGMENTS_CLI:newrelic.transaction_tracer.max_segments_cli +NEW_RELIC_FRAMEWORK_DRUPAL_MODULES:newrelic.framework.drupal.modules +NEW_RELIC_FRAMEWORK_WORDPRESS_HOOKS:newrelic.framework.wordpress.hooks +NEW_RELIC_FRAMEWORK_WORDPRESS_HOOKS_OPTIONS:newrelic.framework.wordpress.hooks.options +NEW_RELIC_FRAMEWORK_WORDPRESS_HOOKS_THRESHOLD:newrelic.framework.wordpress.hooks.threshold +NEW_RELIC_APPLICATION_LOGGING_ENABLED:newrelic.application_logging.enabled +NEW_RELIC_APPLICATION_LOGGING_FORWARDING_ENABLED:newrelic.application_logging.forwarding.enabled +NEW_RELIC_APPLICATION_LOGGING_FORWARDING_MAX_SAMPLES_STORED:newrelic.application_logging.forwarding.max_samples_stored +NEW_RELIC_APPLICATION_LOGGING_FORWARDING_LOG_LEVEL:newrelic.application_logging.forwarding.log_level +NEW_RELIC_APPLICATION_LOGGING_LOCAL_DECORATING_ENABLED:newrelic.application_logging.local_decorating.enabled +NEW_RELIC_APPLICATION_LOGGING_METRICS_ENABLED:newrelic.application_logging.metrics.enabled +NEW_RELIC_APPLICATION_LOGGING_FORWARDING_CONTEXT_DATA_ENABLED:newrelic.application_logging.forwarding.context_data.enabled +NEW_RELIC_APPLICATION_LOGGING_FORWARDING_CONTEXT_DATA_INCLUDE:newrelic.application_logging.forwarding.context_data.include +NEW_RELIC_APPLICATION_LOGGING_FORWARDING_CONTEXT_DATA_EXCLUDE:newrelic.application_logging.forwarding.context_data.exclude +NEW_RELIC_CODE_LEVEL_METRICS_ENABLED:newrelic.code_level_metrics.enabled +NEW_RELIC_VULNERABILITY_MANAGEMENT_PACKAGE_DETECTION_ENABLED:newrelic.vulnerability_management.package_detection.enabled +NEW_RELIC_VULNERABILITY_MANAGEMENT_COMPOSER_API_ENABLED:newrelic.vulnerability_management.composer_api.enabled +NEW_RELIC_FEATURE_FLAG:newrelic.feature_flag +NEW_RELIC_SPECIAL:newrelic.special +NEW_RELIC_SPECIAL_APPINFO_TIMEOUT:newrelic.special.appinfo_timeout +NEW_RELIC_DAEMON_SPECIAL_CURL_VERBOSE:newrelic.daemon.special.curl_verbose +NEW_RELIC_DAEMON_SPECIAL_INTEGRATION:newrelic.daemon.special.integration +NEW_RELIC_SPECIAL_DISABLE_INSTRUMENTATION:newrelic.special.disable_instrumentation +NEW_RELIC_SPECIAL_EXPENSIVE_NODE_MIN:newrelic.special.expensive_node_min +NEW_RELIC_SPECIAL_MAX_NESTING_LEVEL:newrelic.special.max_nesting_level +NEW_RELIC_SPECIAL_ENABLE_EXTENSION_INSTRUMENTATION:newrelic.special.enable_extension_instrumentation +NEW_RELIC_BROWSER_MONITORING_DEBUG:newrelic.browser_monitoring.debug +NEW_RELIC_BROWSER_MONITORING_LOADER:newrelic.browser_monitoring.loader +NEW_RELIC_INFINITE_TRACING_SPAN_EVENTS_AGENT_QUEUE_SIZE:newrelic.infinite_tracing.span_events.agent_queue.size +NEW_RELIC_INFINITE_TRACING_SPAN_EVENTS_AGENT_QUEUE_TIMEOUT:newrelic.infinite_tracing.span_events.agent_queue.timeout +NEW_RELIC_FRAMEWORK_WORDPRESS_HOOKS_SKIP_FILENAME:newrelic.framework.wordpress.hooks_skip_filename +NEW_RELIC_DISTRIBUTED_TRACING_PAD_TRACE_ID:newrelic.distributed_tracing.pad_trace_id diff --git a/src/php/php-agent-download.sh b/src/php/php-agent-download.sh new file mode 100644 index 0000000..f604e58 --- /dev/null +++ b/src/php/php-agent-download.sh @@ -0,0 +1,27 @@ +#!/bin/bash + +libc=$1 +version=$2 + +if [ -z "$libc" ]; then + echo "'libc' argument not supplied. Defaulting to 'gnu'" + libc="gnu" +elif [[ ! $libc =~ ^(musl|gnu)$ ]]; then + echo "error: invalid 'libc' argument provided: ${libc}. Exiting." + exit 1 +fi + +if [ -z "$version" ]; then + latest=$(wget -c https://download.newrelic.com/php_agent/release/ -O - | grep newrelic-php5 | cut -d '-' -f 3 | head -n 1) + url="https://download.newrelic.com/php_agent/release/newrelic-php5-${latest}-linux" +else + url="https://download.newrelic.com/php_agent/archive/${version}/newrelic-php5-${version}-linux" +fi + +if [ "$libc" = 'musl' ]; then + url+="-musl.tar.gz" +else + url+=".tar.gz" +fi + +wget -c "${url}" -O - | tar -xz --strip-components 1