Skip to content

Commit

Permalink
feat: Set application name via command line with the .msi installer (#…
Browse files Browse the repository at this point in the history
…2648)

* Initial code

* InnerText, not Value

* Working solution for setting app pool naming

* Cleanup
  • Loading branch information
nr-ahemsath authored Jul 26, 2024
1 parent 0ae54fa commit 369dcba
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/Agent/MsiInstaller/Installer/Product.wxs
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,7 @@ SPDX-License-Identifier: Apache-2.0
<CustomAction Id="SaveDeferredCustomActionData" DllEntry="SaveDeferredCustomActionData" Execute="immediate" Return="check" BinaryRef="CustomActionsDll" />
<CustomAction Id="MigrateConfiguration" DllEntry="MigrateConfiguration" Execute="deferred" Impersonate="no" Return="check" BinaryRef="CustomActionsDll" />
<CustomAction Id="SetLicenseKey" DllEntry="SetLicenseKey" Execute="deferred" Impersonate="no" Return="check" BinaryRef="CustomActionsDll" />
<CustomAction Id="SetAppName" DllEntry="SetAppName" Execute="deferred" Impersonate="no" Return="check" BinaryRef="CustomActionsDll" />
<CustomAction Id="CleanupPreviousInstall" DllEntry="CleanupPreviousInstall" Execute="deferred" Impersonate="no" Return="check" BinaryRef="CustomActionsDll" />
<CustomAction Id="RestartIis" DllEntry="RestartIis" Impersonate="yes" BinaryRef="CustomActionsDll" />
<CustomAction Id="CloseStatusMonitor" DllEntry="CloseStatusMonitor" Impersonate="yes" BinaryRef="CustomActionsDll" />
Expand Down
81 changes: 81 additions & 0 deletions src/Agent/MsiInstaller/InstallerActions/CustomActions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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"] },
Expand All @@ -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;
Expand Down Expand Up @@ -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 <name>appName</name> 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)
{
Expand Down

0 comments on commit 369dcba

Please sign in to comment.