Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add remotely managed, ephemeral and api options to Windows install script/installer #1437

Merged
merged 6 commits into from
Feb 8, 2024
Merged
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
1 change: 1 addition & 0 deletions .changelog/1437.added.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
+ feat(install): add support for remote management, ephemeral and api url in Windows installer
4 changes: 4 additions & 0 deletions packaging/msi/SumoLogic.wixext/SumoLogic.wixext/Config.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ public class Config
{
public string InstallationToken { get; set; }
public Dictionary<string, string> CollectorFields { get; set; }
public bool RemotelyManaged { get; set; }
public bool Ephemeral { get; set; }
public string OpAmpFolder { get; set; }
public string Api { get; set; }

public Config() {
this.CollectorFields = new Dictionary<string, string>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ public ConfigUpdater(StreamReader streamReader) {

public void Update(Config config)
{
if (config.RemotelyManaged && string.IsNullOrEmpty(config.OpAmpFolder))
{
throw new MissingConfigurationException("OpAmpFolder");
}

YamlMappingNode root = (YamlMappingNode)this.Document.RootNode;

EnsureMapKey(root, "extensions");
Expand All @@ -53,6 +58,48 @@ public void Update(Config config)
collectorFields.Children[field.Key] = field.Value;
}
}

if (config.RemotelyManaged)
{
EnsureMapKey(extensions, "opamp");
YamlMappingNode opamp = (YamlMappingNode)extensions.Children["opamp"];
EnsureScalarKey(opamp, "remote_configuration_directory");
opamp.Children["remote_configuration_directory"] = config.OpAmpFolder;

// Add OpAmp extension to service section
EnsureMapKey(root, "service");
YamlMappingNode service = (YamlMappingNode)root.Children["service"];
EnsureSequenceKey(service, "extensions");
YamlSequenceNode serviceExtensions = (YamlSequenceNode)service.Children["extensions"];
if (!serviceExtensions.Children.Contains("opamp"))
{
serviceExtensions.Children.Add("opamp");
}
}

if (config.Ephemeral)
{
EnsureScalarKey(sumologic, "ephemeral");
sumologic.Children["ephemeral"] = "true";
}

if (!string.IsNullOrEmpty(config.Api))
{
EnsureScalarKey(sumologic, "api_base_url");
sumologic.Children["api_base_url"] = config.Api;
}

// Make sure the sumologic processor node is a map node, otherwise an empty string
// is generated as the value instead of an empty node.
if (root.Children.ContainsKey("processors"))
{
EnsureMapKey(root, "processors");
YamlMappingNode processors = (YamlMappingNode)root.Children["processors"];
if (processors.Children.ContainsKey("sumologic"))
{
EnsureMapKey(processors, "sumologic");
}
}
}

public void Save(StreamWriter streamWriter)
Expand Down Expand Up @@ -100,5 +147,22 @@ private void EnsureScalarKey(YamlMappingNode node, string key)
// Add empty YamlScalarNode to key
node.Children.Add(key, new YamlScalarNode());
}

private void EnsureSequenceKey(YamlMappingNode node, string key)
{
if (node.Children.ContainsKey(key))
{
if (node.Children[key].NodeType == YamlNodeType.Sequence)
{
return;
}

// TODO: is this how we want to handle incorrect node types?
// YamlNode is wrong type, remove it
node.Children.Remove(key);
}
// Add empty YamlScalarNode to key
node.Children.Add(key, new YamlSequenceNode());
}
}
}
76 changes: 65 additions & 11 deletions packaging/msi/SumoLogic.wixext/SumoLogic.wixext/CustomAction.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.IO;
using System.Text.RegularExpressions;
using System.Windows.Forms;
using WixToolset.Dtf.WindowsInstaller;

namespace SumoLogic.wixext
Expand All @@ -13,9 +14,19 @@ public class CustomActions

// WiX property names
private const string pCommonConfigPath = "CommonConfigPath";
private const string pSumoLogicConfigPath = "SumoLogicConfigPath";
private const string pInstallationToken = "InstallationToken";
private const string pInstallToken = "InstallToken";
private const string pTags = "Tags";
private const string pApi = "Api";
private const string pRemotelyManaged = "RemotelyManaged";
private const string pEphemeral = "Ephemeral";
private const string pConfigFolder = "ConfigFolder";
private const string pOpAmpFolder = "OpAmpFolder";
private const string pConfigFragmentsFolder = "ConfigFragmentsFolder";

// WiX features
private const string fRemotelyManaged = "REMOTELYMANAGED";

[CustomAction]
public static ActionResult UpdateConfig(Session session)
Expand All @@ -26,44 +37,60 @@ public static ActionResult UpdateConfig(Session session)
// Validate presence of required WiX properties
if (!session.CustomActionData.ContainsKey(pCommonConfigPath))
{
showErrorMessage(session, ecMissingCustomActionData, pCommonConfigPath);
ShowErrorMessage(session, ecMissingCustomActionData, pCommonConfigPath);
return ActionResult.Failure;
}
if (!session.CustomActionData.ContainsKey(pInstallToken) && !session.CustomActionData.ContainsKey(pInstallationToken))
{
showErrorMessage(session, ecMissingCustomActionData, pInstallationToken);
ShowErrorMessage(session, ecMissingCustomActionData, pInstallationToken);
return ActionResult.Failure;
}
if (!session.CustomActionData.ContainsKey(pTags))
{
showErrorMessage(session, ecMissingCustomActionData, pTags);
ShowErrorMessage(session, ecMissingCustomActionData, pTags);
return ActionResult.Failure;
}

var commonConfigPath = session.CustomActionData[pCommonConfigPath];
var sumoLogicConfigPath = session.CustomActionData[pSumoLogicConfigPath];
var tags = session.CustomActionData[pTags];

var installationToken = "";
if (session.CustomActionData.ContainsKey(pInstallationToken) && session.CustomActionData[pInstallationToken] != "") {
if (session.CustomActionData.ContainsKey(pInstallationToken) && session.CustomActionData[pInstallationToken] != "")
{
installationToken = session.CustomActionData[pInstallationToken];
} else if (session.CustomActionData.ContainsKey(pInstallToken)){
}
else if (session.CustomActionData.ContainsKey(pInstallToken))
{
installationToken = session.CustomActionData[pInstallToken];
}

var remotelyManaged = (session.CustomActionData.ContainsKey(pRemotelyManaged) && session.CustomActionData[pRemotelyManaged] == "true");
var ephemeral = (session.CustomActionData.ContainsKey(pEphemeral) && session.CustomActionData[pEphemeral] == "true");
var opAmpFolder = session.CustomActionData[pOpAmpFolder];
var api = session.CustomActionData[pApi];

if (remotelyManaged && string.IsNullOrEmpty(opAmpFolder))
{
ShowErrorMessage(session, ecMissingCustomActionData, pOpAmpFolder);
return ActionResult.Failure;
}

// Load config from disk and replace values
Config config = new Config();
config.InstallationToken = installationToken;
Config config = new Config { InstallationToken = installationToken, RemotelyManaged = remotelyManaged, Ephemeral = ephemeral,
OpAmpFolder = opAmpFolder, Api = api };
config.SetCollectorFieldsFromTags(tags);

var configFile = remotelyManaged ? sumoLogicConfigPath : commonConfigPath;
try
{
ConfigUpdater configUpdater = new ConfigUpdater(new StreamReader(commonConfigPath));
ConfigUpdater configUpdater = new ConfigUpdater(new StreamReader(configFile));
configUpdater.Update(config);
configUpdater.Save(new StreamWriter(commonConfigPath));
configUpdater.Save(new StreamWriter(configFile));
}
catch (Exception e)
{
showErrorMessage(session, ecConfigError, e.Message);
ShowErrorMessage(session, ecConfigError, e.Message);
return ActionResult.Failure;
}

Expand All @@ -72,7 +99,34 @@ public static ActionResult UpdateConfig(Session session)
return ActionResult.Success;
}

private static void showErrorMessage(Session session, short errCode, string key)
[CustomAction]
public static ActionResult PopulateServiceArguments(Session session)
{
try
{
var configFolder = session.GetTargetPath(pConfigFolder);
var configFragmentsFolder = session.GetTargetPath(pConfigFragmentsFolder);
var remotelyManaged = session.Features.Contains(fRemotelyManaged) && session.Features[fRemotelyManaged].RequestState == InstallState.Local;

if (remotelyManaged)
{
session["SERVICEARGUMENTS"] = " --remote-config \"opamp:" + configFolder + "sumologic.yaml\"";
}
else
{
session["SERVICEARGUMENTS"] = " --config \"" + configFolder + "sumologic.yaml\" --config \"glob:" + configFragmentsFolder + "*.yaml\"";
}
}
catch (Exception e)
{
ShowErrorMessage(session, ecConfigError, e.Message + e.StackTrace);
return ActionResult.Failure;
}

return ActionResult.Success;
}

private static void ShowErrorMessage(Session session, short errCode, string key)
{
Record record = new Record(3);
record.SetInteger(1, errCode);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,9 @@ public class TagValueLengthExceededException : Exception
{
public TagValueLengthExceededException(string message) { }
}

public class MissingConfigurationException : Exception
{
public MissingConfigurationException(string message) { }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ namespace SumoLogicTests
[TestClass]
public class ConfigTests
{
private static Random random = new Random();
private static readonly Random random = new Random();

public static string RandomString(int length)
{
Expand Down
Loading
Loading