From 369dcbab4f3fa59354f683bae16b711f45be2387 Mon Sep 17 00:00:00 2001 From: Alex Hemsath <57361211+nr-ahemsath@users.noreply.github.com> Date: Fri, 26 Jul 2024 09:33:07 -0700 Subject: [PATCH] feat: Set application name via command line with the .msi installer (#2648) * Initial code * InnerText, not Value * Working solution for setting app pool naming * Cleanup --- src/Agent/MsiInstaller/Installer/Product.wxs | 1 + .../InstallerActions/CustomActions.cs | 81 +++++++++++++++++++ 2 files changed, 82 insertions(+) diff --git a/src/Agent/MsiInstaller/Installer/Product.wxs b/src/Agent/MsiInstaller/Installer/Product.wxs index 4eae44f16..333e7f645 100644 --- a/src/Agent/MsiInstaller/Installer/Product.wxs +++ b/src/Agent/MsiInstaller/Installer/Product.wxs @@ -172,6 +172,7 @@ SPDX-License-Identifier: Apache-2.0 + diff --git a/src/Agent/MsiInstaller/InstallerActions/CustomActions.cs b/src/Agent/MsiInstaller/InstallerActions/CustomActions.cs index 86bcecd30..25c6212bc 100644 --- a/src/Agent/MsiInstaller/InstallerActions/CustomActions.cs +++ b/src/Agent/MsiInstaller/InstallerActions/CustomActions.cs @@ -35,6 +35,8 @@ public static ActionResult SaveDeferredCustomActionData(Session session) var customActionData = new CustomActionData { { "NR_LICENSE_KEY", session["NR_LICENSE_KEY"] }, + { "NR_APP_NAME", session["NR_APP_NAME"] }, + { "NR_USE_APP_POOL_NAMING", session["NR_USE_APP_POOL_NAMING"] }, { "NETAGENTCOMMONFOLDER", session["NETAGENTCOMMONFOLDER"] }, { "LOGSFOLDER", session["LOGSFOLDER"] }, { "NETAGENTFOLDER", session["NETAGENTFOLDER"] }, @@ -43,6 +45,7 @@ public static ActionResult SaveDeferredCustomActionData(Session session) session.DoAction("MigrateConfiguration", customActionData); session.DoAction("SetLicenseKey", customActionData); + session.DoAction("SetAppName", customActionData); session.DoAction("CleanupPreviousInstall", customActionData); return ActionResult.Success; @@ -111,6 +114,84 @@ public static ActionResult SetLicenseKey(Session session) return ActionResult.Success; } + [CustomAction] + public static ActionResult SetAppName(Session session) + { + try + { + var path = session.CustomActionData["NETAGENTCOMMONFOLDER"] + @"\newrelic.config"; + + // appName will be an empty string if the property wasn't set via the command line, + // OR if the property was set with an empty string (NR_APP_NAME="") + var appName = session.CustomActionData["NR_APP_NAME"]; + var useAppPoolNaming = session.CustomActionData["NR_USE_APP_POOL_NAMING"].Equals(bool.TrueString, StringComparison.CurrentCultureIgnoreCase) + || session.CustomActionData["NR_USE_APP_POOL_NAMING"].Equals("1"); + + session.Log($"SetAppName: appName={appName}, useAppPoolNaming={useAppPoolNaming}"); + if (string.IsNullOrEmpty(appName) && !useAppPoolNaming) + { + session.Log("NR_APP_NAME was not set or was set to an empty string, and NR_USE_APP_POOL_NAMING was not set or was not set to true. Application name not modified."); + return ActionResult.Success; + } + + var document = new XmlDocument(); + document.Load(path); + var namespaceManager = new XmlNamespaceManager(document.NameTable); + namespaceManager.AddNamespace("newrelic-config", "urn:newrelic-config"); + + var applicationNode = document.SelectSingleNode("/newrelic-config:configuration/newrelic-config:application", namespaceManager); + if (applicationNode == null) + { + session.Log("Unable to locate /configuration/application node in newrelic.config. Application name not set."); + return ActionResult.Success; + } + + // NR_USE_APP_POOL_NAMING takes precedence over anything set in NR_APP_NAME + if (useAppPoolNaming) + { + session.Log("NR_APP_NAME = UseAppPoolNaming, deleting name nodes from application element"); + var childNodes = applicationNode.ChildNodes; + foreach (XmlNode childNode in childNodes) + { + session.Log($"found child node with name {childNode.Name}"); + if (childNode.Name.Equals("name")) + { + session.Log("Deleting 'name' node"); + applicationNode.RemoveChild(childNode); + } + } + document.Save(session.CustomActionData["NETAGENTCOMMONFOLDER"] + @"\newrelic.config"); + session.Log("newrelic.config saved with application name elements removed."); + return ActionResult.Success; + } + + // If we get here, NR_USE_APP_POOL_NAMING was not set or not set to true, + // and NR_APP_NAME has a non-empty value. Set the app name to NR_APP_NAME. + // If no appName node exists, create it + XmlNode applicationNameNode; + applicationNameNode = document.SelectSingleNode("/newrelic-config:configuration/newrelic-config:application/newrelic-config:name", namespaceManager); + if (applicationNameNode == null) + { + session.Log("Unable to locate existing /configuration/application/name node in newrelic.config, creating a new one."); + var newNameNode = document.CreateElement("name", "urn:newrelic-config"); + applicationNameNode = applicationNode.AppendChild(newNameNode); + } + session.Log("/configuration/application/name node found or created in newrelic.config"); + + applicationNameNode.InnerText = appName; + session.Log("Application name set to " + appName); + + document.Save(session.CustomActionData["NETAGENTCOMMONFOLDER"] + @"\newrelic.config"); + session.Log("newrelic.config saved with updated application name."); + } + catch (Exception exception) + { + session.Log("Exception while attempting to set the application name in newrelic.config.\n{0}", exception); + } + + return ActionResult.Success; + } + [CustomAction] public static ActionResult CleanupPreviousInstall(Session session) {