-
Notifications
You must be signed in to change notification settings - Fork 48
Expand file tree
/
Copy pathNewServiceControlInstance.cs
More file actions
247 lines (204 loc) · 10.9 KB
/
NewServiceControlInstance.cs
File metadata and controls
247 lines (204 loc) · 10.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
namespace ServiceControl.Management.PowerShell
{
using System;
using System.IO;
using System.Linq;
using System.Management.Automation;
using System.Threading.Tasks;
using ServiceControlInstaller.Engine.Instances;
using ServiceControlInstaller.Engine.Unattended;
using ServiceControlInstaller.Engine.Validation;
using Validation;
using PathInfo = ServiceControlInstaller.Engine.Validation.PathInfo;
[Cmdlet(VerbsCommon.New, "ServiceControlInstance")]
public class NewServiceControlInstance : PSCmdlet
{
[Parameter(Mandatory = true, HelpMessage = "Specify the name of the ServiceControl Instance")]
[ValidateNotNullOrEmpty]
public string Name { get; set; }
[Parameter(Mandatory = true, HelpMessage = "Specify the directory to use for this ServiceControl Instance")]
[ValidateNotNullOrEmpty]
[ValidatePath]
public string InstallPath { get; set; }
[Parameter(Mandatory = true, HelpMessage = "Specify the directory that will contain the RavenDB database for this ServiceControl Instance")]
[ValidateNotNullOrEmpty]
[ValidatePath]
public string DBPath { get; set; }
[Parameter(Mandatory = true, HelpMessage = "Specify the directory to use for this ServiceControl Logs")]
[ValidateNotNullOrEmpty]
[ValidatePath]
public string LogPath { get; set; }
[Parameter(Mandatory = false, HelpMessage = "Specify the hostname to use in the URLACL (defaults to localhost)")]
[ValidateNotNullOrEmpty]
public string HostName { get; set; }
[Parameter(Mandatory = true, HelpMessage = "Specify the port number to listen on. If this is the only ServiceControl instance then 33333 is recommended")]
[ValidateRange(1, 49151)]
public int Port { get; set; }
[Parameter(Mandatory = true, HelpMessage = "Specify the database maintenance port number to listen on. If this is the only ServiceControl instance then 33334 is recommended")]
[ValidateRange(1, 49151)]
public int DatabaseMaintenancePort { get; set; }
[Parameter(Mandatory = false, HelpMessage = "Specify ErrorQueue name to consume messages from. Default is error")]
[ValidateNotNullOrEmpty]
public string ErrorQueue { get; set; }
[Parameter(Mandatory = false, HelpMessage = "Specify Queue name to forward error messages to")]
[ValidateNotNullOrEmpty]
public string ErrorLogQueue { get; set; }
[Parameter(Mandatory = true, HelpMessage = "Specify the NServiceBus Transport to use")]
[ValidateSet(typeof(TransportValuesGenerator))]
public string Transport { get; set; }
[Parameter(Mandatory = false, HelpMessage = "Specify the Windows Service Display name. If unspecified the instance name will be used")]
[ValidateNotNullOrEmpty]
public string DisplayName { get; set; }
[Parameter(Mandatory = false, HelpMessage = "Specify an alternate VirtualDirectory to use. This option is not recommended")]
[ValidateNotNullOrEmpty]
public string VirtualDirectory { get; set; }
[Parameter(Mandatory = false, HelpMessage = "Specify the connection string to use to connect to the queuing system. Can be left blank for MSMQ")]
[ValidateNotNullOrEmpty]
public string ConnectionString { get; set; }
[Parameter(Mandatory = false, HelpMessage = "Specify the description to use on the Windows Service for this instance")]
[ValidateNotNullOrEmpty]
public string Description { get; set; }
[Parameter(Mandatory = false, HelpMessage = "Specify if error messages are forwarded to the queue specified by ErrorLogQueue")]
public SwitchParameter ForwardErrorMessages { get; set; }
[Parameter(HelpMessage = "The Account to run the Windows service. If not specified then LocalSystem is used")]
public string ServiceAccount { get; set; }
[Parameter(HelpMessage = "The password for the ServiceAccount. Do not use for builtin accounts or managed serviceaccount")]
public string ServiceAccountPassword { get; set; }
[Parameter(Mandatory = true, HelpMessage = "Specify the timespan to keep Error Data")]
[ValidateNotNull]
[ValidateTimeSpanRange(MinimumHours = 120, MaximumHours = 1080)] //5 to 45 days
public TimeSpan ErrorRetentionPeriod { get; set; }
[Parameter(Mandatory = false, HelpMessage = "Do not automatically create queues")]
public SwitchParameter SkipQueueCreation { get; set; }
[Parameter(Mandatory = false, HelpMessage = "Specify whether to enable full text search on error messages.")]
public SwitchParameter EnableFullTextSearchOnBodies { get; set; } = true;
[Parameter(Mandatory = false, HelpMessage = "Specify whether to enable integrated ServicePulse instance.")]
public SwitchParameter EnableIntegratedServicePulse { get; set; }
[Parameter(Mandatory = false, HelpMessage = "Reuse the specified log, db, and install paths even if they are not empty")]
public SwitchParameter Force { get; set; }
[Parameter(Mandatory = false, HelpMessage = "Acknowledge mandatory requirements have been met.")]
public string[] Acknowledgements { get; set; }
protected override void BeginProcessing()
{
var transport = ServiceControlCoreTransports.Find(Transport);
var requiresConnectionString = !string.IsNullOrEmpty(transport.SampleConnectionString);
var hasConnectionString = !string.IsNullOrEmpty(ConnectionString);
if (requiresConnectionString && !hasConnectionString)
{
throw new Exception($"ConnectionString is mandatory for '{Transport}'");
}
if (!requiresConnectionString && hasConnectionString)
{
throw new Exception($"'{Transport}' does not use a connection string.");
}
if (!transport.AvailableInSCMU)
{
WriteWarning($"The transport '{Transport}' is deprecated. Consult the corresponding upgrade guide for the selected transport on 'https://docs.particular.net'");
}
if (string.IsNullOrWhiteSpace(HostName))
{
WriteWarning("HostName set to default value 'localhost'");
HostName = "localhost";
}
if (string.IsNullOrWhiteSpace(ErrorQueue))
{
WriteWarning("ErrorQueue set to default value 'error'");
ErrorQueue = "error";
}
if (string.IsNullOrWhiteSpace(ServiceAccount))
{
WriteWarning("ServiceAccount set to default value 'LocalSystem'");
ServiceAccount = "LocalSystem";
}
if (ForwardErrorMessages.ToBool() & string.IsNullOrWhiteSpace(ErrorLogQueue))
{
WriteWarning("ErrorLogQueue set to default value 'error.log'");
ErrorLogQueue = "error.log";
}
}
protected override void ProcessRecord()
{
var details = ServiceControlNewInstance.CreateWithDefaultPersistence();
details.InstallPath = InstallPath;
details.LogPath = LogPath;
details.DBPath = DBPath;
details.Name = Name;
details.InstanceName = Name;
details.DisplayName = string.IsNullOrWhiteSpace(DisplayName) ? Name : DisplayName;
details.ServiceDescription = Description;
details.ServiceAccount = ServiceAccount;
details.ServiceAccountPwd = ServiceAccountPassword;
details.HostName = HostName;
details.Port = Port;
details.DatabaseMaintenancePort = DatabaseMaintenancePort;
details.VirtualDirectory = VirtualDirectory;
details.ErrorQueue = ErrorQueue;
details.ErrorLogQueue = string.IsNullOrWhiteSpace(ErrorLogQueue) ? null : ErrorLogQueue;
details.ForwardErrorMessages = ForwardErrorMessages.ToBool();
details.ErrorRetentionPeriod = ErrorRetentionPeriod;
details.ConnectionString = ConnectionString;
details.TransportPackage = ServiceControlCoreTransports.Find(Transport);
details.SkipQueueCreation = SkipQueueCreation;
details.EnableFullTextSearchOnBodies = EnableFullTextSearchOnBodies;
details.EnableIntegratedServicePulse = EnableIntegratedServicePulse;
var modulePath = Path.GetDirectoryName(MyInvocation.MyCommand.Module.Path);
var logger = new PSLogger(Host);
var installer = new UnattendServiceControlInstaller(logger);
try
{
var checks = new PowerShellCommandChecks(this, Acknowledgements);
if (!checks.CanAddInstance().GetAwaiter().GetResult())
{
return;
}
if (!checks.ValidateNewInstance(details).GetAwaiter().GetResult())
{
return;
}
logger.Info("Module root at " + modulePath);
logger.Info("Installing Service Control instance...");
var result = installer.Add(details, PromptToProceed);
result.Wait();
if (result.Result)
{
var instance = InstanceFinder.FindInstanceByName<ServiceControlInstance>(details.Name);
if (instance != null)
{
WriteObject(PsServiceControl.FromInstance(instance));
}
else
{
throw new Exception("Unknown error creating instance");
}
}
else
{
var msg = "Installer did not run successfully.";
if (details.ReportCard?.HasErrors == true)
{
var errors = details.ReportCard.Errors.Select(e => e);
msg += string.Join(Environment.NewLine, errors);
}
throw new Exception(msg);
}
}
catch (Exception ex)
{
ThrowTerminatingError(new ErrorRecord(ex, null, ErrorCategory.NotSpecified, null));
}
}
Task<bool> PromptToProceed(PathInfo pathInfo)
{
if (!pathInfo.CheckIfEmpty)
{
return Task.FromResult(false);
}
if (!Force.ToBool())
{
throw new EngineValidationException($"The directory specified for {pathInfo.Name} is not empty. Use -Force if you are sure you want to use this path");
}
WriteWarning($"The directory specified for {pathInfo.Name} is not empty but will be used as -Force was specified");
return Task.FromResult(false);
}
}
}