Drop job step and Create\Update alert handlers (#636)

* Add Delete Job Step implementation

* Update create\update agent alert handlers to use execution handler

* Cleanup create/update/delete operator request handlers
This commit is contained in:
Karl Burtram
2018-06-13 17:49:11 -07:00
committed by GitHub
parent 8dda34c95a
commit aff0f1afae
24 changed files with 1037 additions and 631 deletions

View File

@@ -7,8 +7,6 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Data; using System.Data;
using System.IO; using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Xml; using System.Xml;
using Microsoft.SqlServer.Management.Common; using Microsoft.SqlServer.Management.Common;
@@ -21,7 +19,6 @@ using Microsoft.SqlTools.ServiceLayer.Connection;
using Microsoft.SqlTools.ServiceLayer.Hosting; using Microsoft.SqlTools.ServiceLayer.Hosting;
using Microsoft.SqlTools.ServiceLayer.Management; using Microsoft.SqlTools.ServiceLayer.Management;
using Microsoft.SqlTools.ServiceLayer.Utility; using Microsoft.SqlTools.ServiceLayer.Utility;
using Microsoft.SqlTools.Utility;
namespace Microsoft.SqlTools.ServiceLayer.Agent namespace Microsoft.SqlTools.ServiceLayer.Agent
{ {
@@ -266,18 +263,6 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
}); });
} }
private Tuple<SqlConnectionInfo, DataTable, ServerConnection> CreateSqlConnection(ConnectionInfo connInfo, String jobId)
{
var sqlConnection = ConnectionService.OpenSqlConnection(connInfo);
var serverConnection = new ServerConnection(sqlConnection);
var server = new Server(serverConnection);
var filter = new JobHistoryFilter();
filter.JobID = new Guid(jobId);
var dt = server.JobServer.EnumJobHistory(filter);
var sqlConnInfo = new SqlConnectionInfo(serverConnection, SqlServer.Management.Common.ConnectionType.SqlConnection);
return new Tuple<SqlConnectionInfo, DataTable, ServerConnection>(sqlConnInfo, dt, serverConnection);
}
internal async Task HandleCreateAgentJobRequest(CreateAgentJobParams parameters, RequestContext<CreateAgentJobResult> requestContext) internal async Task HandleCreateAgentJobRequest(CreateAgentJobParams parameters, RequestContext<CreateAgentJobResult> requestContext)
{ {
var result = await ConfigureAgentJob( var result = await ConfigureAgentJob(
@@ -366,135 +351,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
Success = result.Item1, Success = result.Item1,
ErrorMessage = result.Item2 ErrorMessage = result.Item2
}); });
} }
internal async Task<Tuple<bool, string>> ConfigureAgentJob(
string ownerUri,
AgentJobInfo jobInfo,
ConfigAction configAction,
RunType runType)
{
return await Task<Tuple<bool, string>>.Run(() =>
{
try
{
ConnectionInfo connInfo;
ConnectionServiceInstance.TryFindConnection(
ownerUri,
out connInfo);
CDataContainer dataContainer = CDataContainer.CreateDataContainer(
connInfo,
databaseExists: true);
XmlDocument jobDoc = CreateJobXmlDocument(
dataContainer.Server.Name.ToUpper(),
jobInfo.Name);
dataContainer.Init(jobDoc.InnerXml);
STParameters param = new STParameters(dataContainer.Document);
param.SetParam("job", string.Empty);
param.SetParam("jobid", string.Empty);
var jobData = new JobData(dataContainer, jobInfo);
using (JobActions jobActions = new JobActions(dataContainer, jobData, configAction))
{
var executionHandler = new ExecutonHandler(jobActions);
executionHandler.RunNow(runType, this);
}
return new Tuple<bool, string>(true, string.Empty);
}
catch (Exception ex)
{
return new Tuple<bool, string>(false, ex.ToString());
}
});
}
internal async Task<Tuple<bool, string>> ConfigureAgentJobStep(
string ownerUri,
AgentJobStepInfo stepInfo,
ConfigAction configAction,
RunType runType)
{
return await Task<Tuple<bool, string>>.Run(() =>
{
try
{
if (string.IsNullOrWhiteSpace(stepInfo.JobName))
{
return new Tuple<bool, string>(false, "JobId cannot be null");
}
ConnectionInfo connInfo;
ConnectionServiceInstance.TryFindConnection(
ownerUri,
out connInfo);
CDataContainer dataContainer = CDataContainer.CreateDataContainer(
connInfo,
databaseExists: true);
XmlDocument jobDoc = CreateJobXmlDocument(
dataContainer.Server.Name.ToUpper(),
stepInfo.JobName);
dataContainer.Init(jobDoc.InnerXml);
STParameters param = new STParameters(dataContainer.Document);
param.SetParam("job", string.Empty);
param.SetParam("jobid", string.Empty);
var jobData = new JobData(dataContainer);
using (var jobStep = new JobStepsActions(dataContainer, jobData, stepInfo, configAction))
{
var executionHandler = new ExecutonHandler(jobStep);
executionHandler.RunNow(runType, this);
}
return new Tuple<bool, string>(true, string.Empty);
}
catch (Exception ex)
{
// log exception here
return new Tuple<bool, string>(false, ex.ToString());
}
});
}
public XmlDocument CreateJobXmlDocument(string svrName, string jobName)
{
// XML element strings
const string XmlFormDescElementName = "formdescription";
const string XmlParamsElementName = "params";
const string XmlJobElementName = "job";
const string XmlUrnElementName = "urn";
const string UrnFormatStr = "Server[@Name='{0}']/JobServer[@Name='{0}']/Job[@Name='{1}']";
// Write out XML.
StringWriter textWriter = new StringWriter();
XmlTextWriter xmlWriter = new XmlTextWriter(textWriter);
xmlWriter.WriteStartElement(XmlFormDescElementName);
xmlWriter.WriteStartElement(XmlParamsElementName);
xmlWriter.WriteElementString(XmlJobElementName, jobName);
xmlWriter.WriteElementString(XmlUrnElementName, string.Format(UrnFormatStr, svrName, jobName));
xmlWriter.WriteEndElement();
xmlWriter.WriteEndElement();
xmlWriter.Close();
// Create an XML document.
XmlDocument doc = new XmlDocument();
XmlTextReader rdr = new XmlTextReader(new System.IO.StringReader(textWriter.ToString()));
rdr.MoveToContent();
doc.LoadXml(rdr.ReadOuterXml());
return doc;
}
#endregion // "Jobs Handlers" #endregion // "Jobs Handlers"
@@ -511,9 +368,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
result.Alerts = new List<AgentAlertInfo>().ToArray(); result.Alerts = new List<AgentAlertInfo>().ToArray();
ConnectionInfo connInfo; ConnectionInfo connInfo;
ConnectionServiceInstance.TryFindConnection( ConnectionServiceInstance.TryFindConnection(parameters.OwnerUri, out connInfo);
parameters.OwnerUri,
out connInfo);
if (connInfo != null) if (connInfo != null)
{ {
@@ -525,29 +380,22 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
}); });
} }
private bool ValidateAgentAlertInfo(AgentAlertInfo alert)
{
return alert != null
&& !string.IsNullOrWhiteSpace(alert.JobName);
}
/// <summary> /// <summary>
/// Handle request to create an alert /// Handle request to create an alert
/// </summary> /// </summary>
internal async Task HandleCreateAgentAlertRequest(CreateAgentAlertParams parameters, RequestContext<CreateAgentAlertResult> requestContext) internal async Task HandleCreateAgentAlertRequest(CreateAgentAlertParams parameters, RequestContext<CreateAgentAlertResult> requestContext)
{ {
await Task.Run(async () => var result = await ConfigureAgentAlert(
parameters.OwnerUri,
parameters.Alert,
ConfigAction.Create,
RunType.RunNow);
await requestContext.SendResult(new CreateAgentAlertResult()
{ {
var result = new CreateAgentAlertResult(); Success = result.Item1,
ConnectionInfo connInfo; ErrorMessage = result.Item2
ConnectionServiceInstance.TryFindConnection( });
parameters.OwnerUri,
out connInfo);
CreateOrUpdateAgentAlert(connInfo, parameters.Alert);
await requestContext.SendResult(result);
});
} }
/// <summary> /// <summary>
@@ -555,71 +403,34 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
/// </summary> /// </summary>
internal async Task HandleUpdateAgentAlertRequest(UpdateAgentAlertParams parameters, RequestContext<UpdateAgentAlertResult> requestContext) internal async Task HandleUpdateAgentAlertRequest(UpdateAgentAlertParams parameters, RequestContext<UpdateAgentAlertResult> requestContext)
{ {
await Task.Run(async () => var result = await ConfigureAgentAlert(
parameters.OwnerUri,
parameters.Alert,
ConfigAction.Update,
RunType.RunNow);
await requestContext.SendResult(new UpdateAgentAlertResult()
{ {
var result = new UpdateAgentAlertResult(); Success = result.Item1,
ConnectionInfo connInfo; ErrorMessage = result.Item2
ConnectionServiceInstance.TryFindConnection(
parameters.OwnerUri,
out connInfo);
CreateOrUpdateAgentAlert(connInfo, parameters.Alert);
await requestContext.SendResult(result);
}); });
} }
private void CreateOrUpdateAgentAlert(ConnectionInfo connInfo, AgentAlertInfo alert)
{
if (connInfo != null && ValidateAgentAlertInfo(alert))
{
CDataContainer dataContainer = CDataContainer.CreateDataContainer(connInfo, databaseExists: true);
STParameters param = new STParameters(dataContainer.Document);
param.SetParam("alert", alert.JobName);
using (AgentAlertActions agentAlert = new AgentAlertActions(dataContainer, alert))
{
agentAlert.CreateOrUpdate();
}
}
}
/// <summary> /// <summary>
/// Handle request to delete an alert /// Handle request to delete an alert
/// </summary> /// </summary>
internal async Task HandleDeleteAgentAlertRequest(DeleteAgentAlertParams parameters, RequestContext<ResultStatus> requestContext) internal async Task HandleDeleteAgentAlertRequest(DeleteAgentAlertParams parameters, RequestContext<ResultStatus> requestContext)
{ {
await Task.Run(async () => var result = await ConfigureAgentAlert(
parameters.OwnerUri,
parameters.Alert,
ConfigAction.Drop,
RunType.RunNow);
await requestContext.SendResult(new ResultStatus()
{ {
var result = new ResultStatus(); Success = result.Item1,
try ErrorMessage = result.Item2
{
ConnectionInfo connInfo;
ConnectionServiceInstance.TryFindConnection(
parameters.OwnerUri,
out connInfo);
AgentAlertInfo alert = parameters.Alert;
if (connInfo != null && ValidateAgentAlertInfo(alert))
{
CDataContainer dataContainer = CDataContainer.CreateDataContainer(connInfo, databaseExists: true);
STParameters param = new STParameters(dataContainer.Document);
param.SetParam("alert", alert.JobName);
using (AgentAlertActions agentAlert = new AgentAlertActions(dataContainer, alert))
{
agentAlert.Drop();
result.Success = true;
}
}
}
catch (Exception ex)
{
result.Success = false;
result.ErrorMessage = ex.ToString();
}
await requestContext.SendResult(result);
}); });
} }
@@ -630,41 +441,60 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
internal async Task HandleAgentOperatorsRequest(AgentOperatorsParams parameters, RequestContext<AgentOperatorsResult> requestContext) internal async Task HandleAgentOperatorsRequest(AgentOperatorsParams parameters, RequestContext<AgentOperatorsResult> requestContext)
{ {
await requestContext.SendResult(null); await requestContext.SendResult(null);
} }
internal async Task HandleCreateAgentOperatorRequest(CreateAgentOperatorParams parameters, RequestContext<CreateAgentOperatorResult> requestContext) internal async Task HandleCreateAgentOperatorRequest(
CreateAgentOperatorParams parameters,
RequestContext<AgentOperatorResult> requestContext)
{ {
await Task.Run(async () => var result = await ConfigureAgentOperator(
parameters.OwnerUri,
parameters.Operator,
ConfigAction.Create,
RunType.RunNow);
await requestContext.SendResult(new AgentOperatorResult()
{ {
var result = new CreateAgentOperatorResult(); Success = result.Item1,
ConnectionInfo connInfo; ErrorMessage = result.Item2,
ConnectionServiceInstance.TryFindConnection( Operator = parameters.Operator
parameters.OwnerUri,
out connInfo);
AgentOperatorInfo operatorInfo = parameters.Operator;
CDataContainer dataContainer = CDataContainer.CreateDataContainer(connInfo, databaseExists: true);
STParameters param = new STParameters(dataContainer.Document);
param.SetParam("operator", operatorInfo.Name);
using (AgentOperator agentOperator = new AgentOperator(dataContainer, operatorInfo))
{
agentOperator.CreateOrUpdate();
}
await requestContext.SendResult(result);
}); });
} }
internal async Task HandleUpdateAgentOperatorRequest(UpdateAgentOperatorParams parameters, RequestContext<UpdateAgentOperatorResult> requestContext) internal async Task HandleUpdateAgentOperatorRequest(
UpdateAgentOperatorParams parameters,
RequestContext<AgentOperatorResult> requestContext)
{ {
await requestContext.SendResult(null); var result = await ConfigureAgentOperator(
parameters.OwnerUri,
parameters.Operator,
ConfigAction.Update,
RunType.RunNow);
await requestContext.SendResult(new AgentOperatorResult()
{
Success = result.Item1,
ErrorMessage = result.Item2,
Operator = parameters.Operator
});
} }
internal async Task HandleDeleteAgentOperatorRequest(DeleteAgentOperatorParams parameters, RequestContext<DeleteAgentOperatorResult> requestContext) internal async Task HandleDeleteAgentOperatorRequest(
DeleteAgentOperatorParams parameters,
RequestContext<ResultStatus> requestContext)
{ {
await requestContext.SendResult(null); var result = await ConfigureAgentOperator(
} parameters.OwnerUri,
parameters.Operator,
ConfigAction.Drop,
RunType.RunNow);
await requestContext.SendResult(new ResultStatus()
{
Success = result.Item1,
ErrorMessage = result.Item2
});
}
#endregion // "Operator Handlers" #endregion // "Operator Handlers"
@@ -718,6 +548,140 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
}); });
} }
#endregion // "Proxy Handlers"
#region "Helpers"
internal async Task<Tuple<bool, string>> ConfigureAgentJob(
string ownerUri,
AgentJobInfo jobInfo,
ConfigAction configAction,
RunType runType)
{
return await Task<Tuple<bool, string>>.Run(() =>
{
try
{
JobData jobData;
CDataContainer dataContainer;
CreateJobData(ownerUri, jobInfo.Name, out dataContainer, out jobData, jobInfo);
using (JobActions jobActions = new JobActions(dataContainer, jobData, configAction))
{
var executionHandler = new ExecutonHandler(jobActions);
executionHandler.RunNow(runType, this);
}
return new Tuple<bool, string>(true, string.Empty);
}
catch (Exception ex)
{
return new Tuple<bool, string>(false, ex.ToString());
}
});
}
internal async Task<Tuple<bool, string>> ConfigureAgentJobStep(
string ownerUri,
AgentJobStepInfo stepInfo,
ConfigAction configAction,
RunType runType)
{
return await Task<Tuple<bool, string>>.Run(() =>
{
try
{
if (string.IsNullOrWhiteSpace(stepInfo.JobName))
{
return new Tuple<bool, string>(false, "JobId cannot be null");
}
JobData jobData;
CDataContainer dataContainer;
CreateJobData(ownerUri, stepInfo.JobName, out dataContainer, out jobData);
using (var jobStep = new JobStepsActions(dataContainer, jobData, stepInfo, configAction))
{
var executionHandler = new ExecutonHandler(jobStep);
executionHandler.RunNow(runType, this);
}
return new Tuple<bool, string>(true, string.Empty);
}
catch (Exception ex)
{
// log exception here
return new Tuple<bool, string>(false, ex.ToString());
}
});
}
internal async Task<Tuple<bool, string>> ConfigureAgentAlert(
string ownerUri,
AgentAlertInfo alert,
ConfigAction configAction,
RunType runType)
{
return await Task<Tuple<bool, string>>.Run(() =>
{
try
{
ConnectionInfo connInfo;
ConnectionServiceInstance.TryFindConnection(ownerUri, out connInfo);
CDataContainer dataContainer = CDataContainer.CreateDataContainer(connInfo, databaseExists: true);
STParameters param = new STParameters(dataContainer.Document);
param.SetParam("alert", alert.JobName);
if (alert != null && !string.IsNullOrWhiteSpace(alert.JobName))
{
using (AgentAlertActions agentAlert = new AgentAlertActions(dataContainer, alert, configAction))
{
var executionHandler = new ExecutonHandler(agentAlert);
executionHandler.RunNow(runType, this);
}
}
return new Tuple<bool, string>(true, string.Empty);
}
catch (Exception ex)
{
return new Tuple<bool, string>(false, ex.ToString());
}
});
}
internal async Task<Tuple<bool, string>> ConfigureAgentOperator(
string ownerUri,
AgentOperatorInfo operatorInfo,
ConfigAction configAction,
RunType runType)
{
return await Task<Tuple<bool, string>>.Run(() =>
{
try
{
ConnectionInfo connInfo;
ConnectionServiceInstance.TryFindConnection(ownerUri, out connInfo);
CDataContainer dataContainer = CDataContainer.CreateDataContainer(connInfo, databaseExists: true);
STParameters param = new STParameters(dataContainer.Document);
param.SetParam("operator", operatorInfo.Name);
using (AgentOperatorActions agentOperator = new AgentOperatorActions(dataContainer, operatorInfo, configAction))
{
var executionHandler = new ExecutonHandler(agentOperator);
executionHandler.RunNow(runType, this);
}
return new Tuple<bool, string>(true, string.Empty);
}
catch (Exception ex)
{
return new Tuple<bool, string>(false, ex.ToString());
}
});
}
internal async Task<bool> ConfigureAgentProxy( internal async Task<bool> ConfigureAgentProxy(
string ownerUri, string ownerUri,
string accountName, string accountName,
@@ -763,8 +727,73 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
return false; return false;
} }
}); });
}
private void CreateJobData(
string ownerUri,
string jobName,
out CDataContainer dataContainer,
out JobData jobData,
AgentJobInfo jobInfo = null)
{
ConnectionInfo connInfo;
ConnectionServiceInstance.TryFindConnection(ownerUri, out connInfo);
dataContainer = CDataContainer.CreateDataContainer(connInfo, databaseExists: true);
XmlDocument jobDoc = CreateJobXmlDocument(dataContainer.Server.Name.ToUpper(), jobName);
dataContainer.Init(jobDoc.InnerXml);
STParameters param = new STParameters(dataContainer.Document);
param.SetParam("job", string.Empty);
param.SetParam("jobid", string.Empty);
jobData = new JobData(dataContainer, jobInfo);
} }
#endregion // "Proxy Handlers" public static XmlDocument CreateJobXmlDocument(string svrName, string jobName)
{
// XML element strings
const string XmlFormDescElementName = "formdescription";
const string XmlParamsElementName = "params";
const string XmlJobElementName = "job";
const string XmlUrnElementName = "urn";
const string UrnFormatStr = "Server[@Name='{0}']/JobServer[@Name='{0}']/Job[@Name='{1}']";
// Write out XML.
StringWriter textWriter = new StringWriter();
XmlTextWriter xmlWriter = new XmlTextWriter(textWriter);
xmlWriter.WriteStartElement(XmlFormDescElementName);
xmlWriter.WriteStartElement(XmlParamsElementName);
xmlWriter.WriteElementString(XmlJobElementName, jobName);
xmlWriter.WriteElementString(XmlUrnElementName, string.Format(UrnFormatStr, svrName, jobName));
xmlWriter.WriteEndElement();
xmlWriter.WriteEndElement();
xmlWriter.Close();
// Create an XML document.
XmlDocument doc = new XmlDocument();
XmlTextReader rdr = new XmlTextReader(new System.IO.StringReader(textWriter.ToString()));
rdr.MoveToContent();
doc.LoadXml(rdr.ReadOuterXml());
return doc;
}
private Tuple<SqlConnectionInfo, DataTable, ServerConnection> CreateSqlConnection(ConnectionInfo connInfo, String jobId)
{
var sqlConnection = ConnectionService.OpenSqlConnection(connInfo);
var serverConnection = new ServerConnection(sqlConnection);
var server = new Server(serverConnection);
var filter = new JobHistoryFilter();
filter.JobID = new Guid(jobId);
var dt = server.JobServer.EnumJobHistory(filter);
var sqlConnInfo = new SqlConnectionInfo(serverConnection, SqlServer.Management.Common.ConnectionType.SqlConnection);
return new Tuple<SqlConnectionInfo, DataTable, ServerConnection>(sqlConnInfo, dt, serverConnection);
}
#endregion // "Helpers"
} }
} }

View File

@@ -38,6 +38,14 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent.Contracts
RequestType<AgentOperatorsParams, AgentOperatorsResult>.Create("agent/operators"); RequestType<AgentOperatorsParams, AgentOperatorsResult>.Create("agent/operators");
} }
/// <summary>
/// SQL Agent Operator result
/// </summary>
public class AgentOperatorResult : ResultStatus
{
public AgentOperatorInfo Operator { get; set; }
}
/// <summary> /// <summary>
/// SQL Agent create Operator params /// SQL Agent create Operator params
/// </summary> /// </summary>
@@ -48,13 +56,6 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent.Contracts
public AgentOperatorInfo Operator { get; set; } public AgentOperatorInfo Operator { get; set; }
} }
/// <summary>
/// SQL Agent create Operator result
/// </summary>
public class CreateAgentOperatorResult : ResultStatus
{
}
/// <summary> /// <summary>
/// SQL Agent create Operator request type /// SQL Agent create Operator request type
/// </summary> /// </summary>
@@ -64,38 +65,8 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent.Contracts
/// Request definition /// Request definition
/// </summary> /// </summary>
public static readonly public static readonly
RequestType<CreateAgentOperatorParams, CreateAgentOperatorResult> Type = RequestType<CreateAgentOperatorParams, AgentOperatorResult> Type =
RequestType<CreateAgentOperatorParams, CreateAgentOperatorResult>.Create("agent/createoperator"); RequestType<CreateAgentOperatorParams, AgentOperatorResult>.Create("agent/createoperator");
}
/// <summary>
/// SQL Agent delete Operator params
/// </summary>
public class DeleteAgentOperatorParams : GeneralRequestDetails
{
public string OwnerUri { get; set; }
public AgentOperatorInfo Operator { get; set; }
}
/// <summary>
/// SQL Agent delete Operator result
/// </summary>
public class DeleteAgentOperatorResult : ResultStatus
{
}
/// <summary>
/// SQL Agent delete Operator request type
/// </summary>
public class DeleteAgentOperatorRequest
{
/// <summary>
/// Request definition
/// </summary>
public static readonly
RequestType<DeleteAgentOperatorParams, DeleteAgentOperatorResult> Type =
RequestType<DeleteAgentOperatorParams, DeleteAgentOperatorResult>.Create("agent/deleteoperator");
} }
/// <summary> /// <summary>
@@ -108,13 +79,6 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent.Contracts
public AgentOperatorInfo Operator { get; set; } public AgentOperatorInfo Operator { get; set; }
} }
/// <summary>
/// SQL Agent update Operator result
/// </summary>
public class UpdateAgentOperatorResult : ResultStatus
{
}
/// <summary> /// <summary>
/// SQL Agent update Operator request type /// SQL Agent update Operator request type
/// </summary> /// </summary>
@@ -124,7 +88,30 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent.Contracts
/// Request definition /// Request definition
/// </summary> /// </summary>
public static readonly public static readonly
RequestType<UpdateAgentOperatorParams, UpdateAgentOperatorResult> Type = RequestType<UpdateAgentOperatorParams, AgentOperatorResult> Type =
RequestType<UpdateAgentOperatorParams, UpdateAgentOperatorResult>.Create("agent/updateoperator"); RequestType<UpdateAgentOperatorParams, AgentOperatorResult>.Create("agent/updateoperator");
}
/// <summary>
/// SQL Agent delete Operator params
/// </summary>
public class DeleteAgentOperatorParams : GeneralRequestDetails
{
public string OwnerUri { get; set; }
public AgentOperatorInfo Operator { get; set; }
} }
/// <summary>
/// SQL Agent delete Operator request type
/// </summary>
public class DeleteAgentOperatorRequest
{
/// <summary>
/// Request definition
/// </summary>
public static readonly
RequestType<DeleteAgentOperatorParams, ResultStatus> Type =
RequestType<DeleteAgentOperatorParams, ResultStatus>.Create("agent/deleteoperator");
}
} }

View File

@@ -4,14 +4,8 @@
// //
using System; using System;
using System.Collections;
using System.Data;
using Microsoft.SqlServer.Management.Common; using Microsoft.SqlServer.Management.Common;
using Microsoft.SqlServer.Management.Diagnostics;
using Microsoft.SqlServer.Management.Sdk.Sfc;
using Microsoft.SqlServer.Management.Smo;
using Microsoft.SqlServer.Management.Smo.Agent; using Microsoft.SqlServer.Management.Smo.Agent;
using Microsoft.SqlTools.ServiceLayer.Admin;
using Microsoft.SqlTools.ServiceLayer.Agent.Contracts; using Microsoft.SqlTools.ServiceLayer.Agent.Contracts;
using Microsoft.SqlTools.ServiceLayer.Management; using Microsoft.SqlTools.ServiceLayer.Management;
@@ -27,14 +21,17 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
/// </summary> /// </summary>
private AgentAlertInfo alertInfo = null; private AgentAlertInfo alertInfo = null;
private ConfigAction configAction;
/// <summary> /// <summary>
/// Default constructor that will be used to create dialog /// Default constructor that will be used to create dialog
/// </summary> /// </summary>
/// <param name="dataContainer"></param> /// <param name="dataContainer"></param>
public AgentAlertActions(CDataContainer dataContainer, AgentAlertInfo alertInfo) public AgentAlertActions(CDataContainer dataContainer, AgentAlertInfo alertInfo, ConfigAction configAction)
{ {
this.alertInfo = alertInfo; this.alertInfo = alertInfo;
this.DataContainer = dataContainer; this.DataContainer = dataContainer;
this.configAction = configAction;
} }
private static string GetAlertName(CDataContainer container) private static string GetAlertName(CDataContainer container)
@@ -44,7 +41,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
parameters.SetDocument(container.Document); parameters.SetDocument(container.Document);
if (parameters.GetParam("alert", ref alertName) == false || string.IsNullOrWhiteSpace(alertName)) if (parameters.GetParam("alert", ref alertName) == false || string.IsNullOrWhiteSpace(alertName))
{ {
throw new Exception("SRError.AlertNameCannotBeBlank"); throw new Exception(SR.AlertNameCannotBeBlank);
} }
return alertName.Trim(); return alertName.Trim();
} }
@@ -59,8 +56,18 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
protected override bool DoPreProcessExecution(RunType runType, out ExecutionMode executionResult) protected override bool DoPreProcessExecution(RunType runType, out ExecutionMode executionResult)
{ {
base.DoPreProcessExecution(runType, out executionResult); base.DoPreProcessExecution(runType, out executionResult);
return false; if (this.configAction == ConfigAction.Drop)
} {
Drop();
}
else
{
CreateOrUpdate();
}
// regular execution always takes place
return true;
}
public bool Drop() public bool Drop()
{ {
@@ -136,11 +143,11 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
ApplicationException applicationException; ApplicationException applicationException;
if (createNewAlert) if (createNewAlert)
{ {
applicationException = new ApplicationException("AgentAlertSR.CannotCreateNewAlert", e); applicationException = new ApplicationException(SR.CannotCreateNewAlert, e);
} }
else else
{ {
applicationException = new ApplicationException("AgentAlertSR.CannotAlterAlert", e); applicationException = new ApplicationException(SR.CannotAlterAlert, e);
} }
throw applicationException; throw applicationException;
} }

View File

@@ -0,0 +1,99 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
using System;
using Microsoft.SqlTools.ServiceLayer.Agent.Contracts;
using Microsoft.SqlTools.ServiceLayer.Management;
namespace Microsoft.SqlTools.ServiceLayer.Agent
{
/// <summary>
/// Agent Operators management class
/// </summary>
internal class AgentOperatorActions : ManagementActionBase
{
private AgentOperatorInfo operatorInfo;
private AgentOperatorsData operatorsData = null;
private ConfigAction configAction;
/// <summary>
/// Constructor
/// </summary>
public AgentOperatorActions(
CDataContainer dataContainer,
AgentOperatorInfo operatorInfo,
ConfigAction configAction)
{
if (dataContainer == null)
{
throw new ArgumentNullException("dataContainer");
}
if (operatorInfo == null)
{
throw new ArgumentNullException("operatorInfo");
}
this.operatorInfo = operatorInfo;
this.DataContainer = dataContainer;
this.configAction = configAction;
STParameters parameters = new STParameters();
parameters.SetDocument(dataContainer.Document);
string agentOperatorName = null;
if (parameters.GetParam("operator", ref agentOperatorName))
{
this.operatorsData = new AgentOperatorsData(
dataContainer,
agentOperatorName,
createMode: configAction == ConfigAction.Create);
}
else
{
throw new ArgumentNullException("agentOperatorName");
}
}
/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose(bool disposing)
{
if(disposing)
{
}
base.Dispose(disposing);
}
// <summary>
/// called by PreProcessExecution to enable derived classes to take over execution
/// </summary>
/// <param name="runType"></param>
/// <param name="executionResult"></param>
/// <returns>
/// true if regular execution should take place, false if everything,
/// has been done by this function
/// </returns>
protected override bool DoPreProcessExecution(RunType runType, out ExecutionMode executionResult)
{
base.DoPreProcessExecution(runType, out executionResult);
if (this.configAction == ConfigAction.Drop)
{
var currentOperator = this.operatorsData.Operator;
if (currentOperator != null)
{
currentOperator.DropIfExists();
}
}
else
{
this.operatorsData.ApplyChanges(this.operatorInfo);
}
return false;
}
}
}

View File

@@ -4,158 +4,15 @@
// //
using System; using System;
using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel;
using System.Data; using System.Data;
using System.Diagnostics;
using System.Globalization;
using System.Threading;
using Microsoft.SqlServer.Management.Common; using Microsoft.SqlServer.Management.Common;
using Microsoft.SqlServer.Management.Diagnostics;
using Microsoft.SqlServer.Management.Sdk.Sfc;
using Microsoft.SqlServer.Management.Smo;
using Microsoft.SqlServer.Management.Smo.Agent; using Microsoft.SqlServer.Management.Smo.Agent;
using Microsoft.SqlTools.ServiceLayer.Admin;
using Microsoft.SqlTools.ServiceLayer.Agent.Contracts; using Microsoft.SqlTools.ServiceLayer.Agent.Contracts;
using Microsoft.SqlTools.ServiceLayer.Management; using Microsoft.SqlTools.ServiceLayer.Management;
namespace Microsoft.SqlTools.ServiceLayer.Agent namespace Microsoft.SqlTools.ServiceLayer.Agent
{ {
/// <summary>
/// Agent Operators management class
/// </summary>
internal class AgentOperator : ManagementActionBase
{
private AgentOperatorInfo operatorInfo;
AgentOperatorsData operatorsData = null;
/// <summary>
/// Constructor
/// </summary>
public AgentOperator(CDataContainer dataContainer, AgentOperatorInfo operatorInfo)
{
try
{
if (dataContainer == null)
{
throw new ArgumentNullException("dataContainer");
}
if (operatorInfo == null)
{
throw new ArgumentNullException("operatorInfo");
}
this.operatorInfo = operatorInfo;
this.DataContainer = dataContainer;
STParameters parameters = new STParameters();
parameters.SetDocument(dataContainer.Document);
string agentOperatorName = null;
if (parameters.GetParam("operator", ref agentOperatorName))
{
this.operatorsData = new AgentOperatorsData(dataContainer, agentOperatorName);
}
else
{
throw new ArgumentNullException("agentOperatorName");
}
}
catch(Exception e)
{
throw new ApplicationException("AgentOperatorsSR.FailedToCreateInitializeAgentOperatorDialog", e);
}
}
/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose(bool disposing)
{
if(disposing)
{
}
base.Dispose(disposing);
}
public bool CreateOrUpdate()
{
this.operatorsData.ApplyChanges(this.operatorInfo);
return true;
}
}
#region internal structures
/// <summary>
/// Provides data to be consumed in the job notification grid
/// </summary>
internal struct AgentJobNotificationHelper
{
/// <summary>
/// constructor
/// </summary>
/// <param name="name">job name</param>
/// <param name="notifyEmail"></param>
/// <param name="notifyPager"></param>
public AgentJobNotificationHelper(string name, CompletionAction notifyEmail, CompletionAction notifyPager)
{
this.Name = name;
this.NotifyEmail = notifyEmail;
this.NotifyPager = notifyPager;
}
/// <summary>
/// Name of the job
/// </summary>
public string Name;
/// <summary>
/// job email notification action
/// </summary>
public CompletionAction NotifyEmail;
/// <summary>
/// job pager notification action
/// </summary>
public CompletionAction NotifyPager;
}
/// <summary>
/// Provides data to be consumed in the alert notification grid
/// </summary>
internal struct AgentAlertNotificationHelper
{
/// <summary>
/// constructor
/// </summary>
/// <param name="name">Name of the alert</param>
/// <param name="notifyEmail"></param>
/// <param name="notifyPager"></param>
/// <param name="alert">Alert object</param>
public AgentAlertNotificationHelper(string name, bool notifyEmail, bool notifyPager, Alert alert)
{
this.Name = name;
this.NotifyEmail = notifyEmail;
this.NotifyPager = notifyPager;
this.Alert = alert;
}
/// <summary>
/// Alert name
/// </summary>
public string Name;
/// <summary>
/// Indicates whether the alert will notify the operator through email
/// </summary>
public bool NotifyEmail;
/// <summary>
/// Indicates whether the alert will notify the operator through pager
/// </summary>
public bool NotifyPager;
/// <summary>
/// Alert object. optimisation to stop us having to lookup the alert object when needed
/// </summary>
public Alert Alert;
}
#endregion
/// <summary> /// <summary>
/// Proxy class for the AgentOperators dialog and property pages. /// Proxy class for the AgentOperators dialog and property pages.
/// Performs lazy instantiation of groups of data based around the operators dialog property pages /// Performs lazy instantiation of groups of data based around the operators dialog property pages
@@ -170,7 +27,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
/// <summary> /// <summary>
/// Original operator name. Empty if we are creating a new operator /// Original operator name. Empty if we are creating a new operator
/// </summary> /// </summary>
string originalOperatorName = String.Empty; string originalOperatorName = string.Empty;
/// <summary> /// <summary>
/// Indicates whether we are creating an operator or not /// Indicates whether we are creating an operator or not
/// </summary> /// </summary>
@@ -209,6 +66,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
/// will be null if the alert notifications have not been initialised /// will be null if the alert notifications have not been initialised
/// </summary> /// </summary>
IList<AgentAlertNotificationHelper> alertNotifications; IList<AgentAlertNotificationHelper> alertNotifications;
/// <summary> /// <summary>
/// will be null if the job notifications have not been initialised /// will be null if the job notifications have not been initialised
/// </summary> /// </summary>
@@ -222,6 +80,19 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
#endregion #endregion
#region properties #region properties
/// <summary>
/// the current Operator SMO object
/// </summary>
public Operator Operator
{
get
{
JobServer jobServer = GetJobServer();
return jobServer.Operators[this.originalOperatorName];
}
}
/// <summary> /// <summary>
/// indicates if the data is in create mode /// indicates if the data is in create mode
/// </summary> /// </summary>
@@ -232,6 +103,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
return this.createMode; return this.createMode;
} }
} }
/// <summary> /// <summary>
/// name of the object /// name of the object
/// </summary> /// </summary>
@@ -248,6 +120,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
name = value; name = value;
} }
} }
/// <summary> /// <summary>
/// Indicates if the dataobject is readonly /// Indicates if the dataobject is readonly
/// </summary> /// </summary>
@@ -275,6 +148,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
enabled = value; enabled = value;
} }
} }
/// <summary> /// <summary>
/// email address of this operator /// email address of this operator
/// </summary> /// </summary>
@@ -291,6 +165,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
this.emailAddress = value; this.emailAddress = value;
} }
} }
/// <summary> /// <summary>
/// pager address of this operator /// pager address of this operator
/// </summary> /// </summary>
@@ -324,6 +199,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
this.pagerDays = value; this.pagerDays = value;
} }
} }
/// <summary> /// <summary>
/// Weekday start time for this operator to be active /// Weekday start time for this operator to be active
/// </summary> /// </summary>
@@ -340,6 +216,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
this.weekdayStartTime = value; this.weekdayStartTime = value;
} }
} }
/// <summary> /// <summary>
/// Weekday end time for this operator to be active /// Weekday end time for this operator to be active
/// </summary> /// </summary>
@@ -356,6 +233,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
this.weekdayEndTime = value; this.weekdayEndTime = value;
} }
} }
/// <summary> /// <summary>
/// Saturday start time for this operator to be active /// Saturday start time for this operator to be active
/// </summary> /// </summary>
@@ -372,6 +250,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
this.saturdayStartTime = value; this.saturdayStartTime = value;
} }
} }
/// <summary> /// <summary>
/// Saturday end time for this operator to be active /// Saturday end time for this operator to be active
/// </summary> /// </summary>
@@ -388,6 +267,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
this.saturdayEndTime = value; this.saturdayEndTime = value;
} }
} }
/// <summary> /// <summary>
/// Sunday start time for this operator to be active /// Sunday start time for this operator to be active
/// </summary> /// </summary>
@@ -404,6 +284,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
this.sundayStartTime = value; this.sundayStartTime = value;
} }
} }
/// <summary> /// <summary>
/// Saturday end time for this operator to be active /// Saturday end time for this operator to be active
/// </summary> /// </summary>
@@ -438,6 +319,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
this.alertNotifications = value; this.alertNotifications = value;
} }
} }
/// <summary> /// <summary>
/// Jobs that notify this operator. This has to be set through the jobs dialog and is read only /// Jobs that notify this operator. This has to be set through the jobs dialog and is read only
/// </summary> /// </summary>
@@ -463,6 +345,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
return this.lastEmailDate; return this.lastEmailDate;
} }
} }
/// <summary> /// <summary>
/// Date this operator was last paged /// Date this operator was last paged
/// </summary> /// </summary>
@@ -480,7 +363,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
#region Constructors #region Constructors
public AgentOperatorsData(CDataContainer dataContainer, string operatorName) public AgentOperatorsData(CDataContainer dataContainer, string operatorName, bool createMode)
{ {
if (dataContainer == null) if (dataContainer == null)
{ {
@@ -497,7 +380,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
this.originalOperatorName = operatorName; this.originalOperatorName = operatorName;
this.name = operatorName; this.name = operatorName;
this.createMode = operatorName.Length == 0; this.createMode = createMode;
} }
#endregion #endregion
@@ -541,6 +424,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
this.generalInitialized = true; this.generalInitialized = true;
} }
/// <summary> /// <summary>
/// Load the data for the jobs that notify this operator. Can be called multiple times and will /// Load the data for the jobs that notify this operator. Can be called multiple times and will
/// only load the data initially, or after a reset. /// only load the data initially, or after a reset.
@@ -577,6 +461,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
} }
} }
} }
/// <summary> /// <summary>
/// Load alerts that notify this operator /// Load alerts that notify this operator
/// </summary> /// </summary>
@@ -824,9 +709,9 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
/// </summary> /// </summary>
private void LoadGeneralDefaults() private void LoadGeneralDefaults()
{ {
name = String.Empty; name = string.Empty;
this.emailAddress = String.Empty; this.emailAddress = string.Empty;
this.pagerAddress = String.Empty; this.pagerAddress = string.Empty;
enabled = true; enabled = true;
pagerDays = 0; pagerDays = 0;
@@ -835,6 +720,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
this.generalInitialized = true; this.generalInitialized = true;
} }
/// <summary> /// <summary>
/// Set job notification defaults. This is just an empty list /// Set job notification defaults. This is just an empty list
/// </summary> /// </summary>
@@ -842,6 +728,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
{ {
this.jobNotifications = new List<AgentJobNotificationHelper>(); this.jobNotifications = new List<AgentJobNotificationHelper>();
} }
/// <summary> /// <summary>
/// set the alert notification defaults. This list will contain all of the alerts /// set the alert notification defaults. This list will contain all of the alerts
/// </summary> /// </summary>
@@ -858,6 +745,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
this.alertNotifications.Add(alertNotification); this.alertNotifications.Add(alertNotification);
} }
} }
/// <summary> /// <summary>
/// load defaults for the history page /// load defaults for the history page
/// </summary> /// </summary>
@@ -878,9 +766,9 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
private JobServer GetJobServer() private JobServer GetJobServer()
{ {
JobServer jobServer = this.dataContainer.Server.JobServer; JobServer jobServer = this.dataContainer.Server.JobServer;
if(jobServer == null) if (jobServer == null)
{ {
throw new ApplicationException("AgentOperatorsSR.JobServerIsNotAvailable"); throw new ApplicationException(SR.JobServerIsNotAvailable);
} }
return jobServer; return jobServer;
} }
@@ -894,7 +782,6 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
private Operator GetCurrentOperator() private Operator GetCurrentOperator()
{ {
JobServer jobServer = GetJobServer(); JobServer jobServer = GetJobServer();
Operator currentOperator = jobServer.Operators[this.originalOperatorName]; Operator currentOperator = jobServer.Operators[this.originalOperatorName];
this.createMode = (currentOperator == null); this.createMode = (currentOperator == null);
if (this.createMode) if (this.createMode)
@@ -913,6 +800,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
{ {
return new TimeSpan(dateTime.Hour, dateTime.Minute, dateTime.Second); return new TimeSpan(dateTime.Hour, dateTime.Minute, dateTime.Second);
} }
/// <summary> /// <summary>
/// ///
/// </summary> /// </summary>
@@ -944,4 +832,81 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
} }
#endregion #endregion
} }
#region internal structures
/// <summary>
/// Provides data to be consumed in the job notification grid
/// </summary>
internal struct AgentJobNotificationHelper
{
/// <summary>
/// constructor
/// </summary>
/// <param name="name">job name</param>
/// <param name="notifyEmail"></param>
/// <param name="notifyPager"></param>
public AgentJobNotificationHelper(string name, CompletionAction notifyEmail, CompletionAction notifyPager)
{
this.Name = name;
this.NotifyEmail = notifyEmail;
this.NotifyPager = notifyPager;
}
/// <summary>
/// Name of the job
/// </summary>
public string Name;
/// <summary>
/// job email notification action
/// </summary>
public CompletionAction NotifyEmail;
/// <summary>
/// job pager notification action
/// </summary>
public CompletionAction NotifyPager;
}
/// <summary>
/// Provides data to be consumed in the alert notification grid
/// </summary>
internal struct AgentAlertNotificationHelper
{
/// <summary>
/// constructor
/// </summary>
/// <param name="name">Name of the alert</param>
/// <param name="notifyEmail"></param>
/// <param name="notifyPager"></param>
/// <param name="alert">Alert object</param>
public AgentAlertNotificationHelper(string name, bool notifyEmail, bool notifyPager, Alert alert)
{
this.Name = name;
this.NotifyEmail = notifyEmail;
this.NotifyPager = notifyPager;
this.Alert = alert;
}
/// <summary>
/// Alert name
/// </summary>
public string Name;
/// <summary>
/// Indicates whether the alert will notify the operator through email
/// </summary>
public bool NotifyEmail;
/// <summary>
/// Indicates whether the alert will notify the operator through pager
/// </summary>
public bool NotifyPager;
/// <summary>
/// Alert object. optimisation to stop us having to lookup the alert object when needed
/// </summary>
public Alert Alert;
}
#endregion
} }

View File

@@ -64,7 +64,6 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
private ILogEntry m_currentEntry = null; private ILogEntry m_currentEntry = null;
private int m_index = 0; private int m_index = 0;
private bool m_isClosed = false; private bool m_isClosed = false;
private TypedColumnCollection columnTypes;
private IServiceProvider serviceProvider = null; private IServiceProvider serviceProvider = null;
private static string historyTableDeclaration = "declare @tmp_sp_help_jobhistory table"; private static string historyTableDeclaration = "declare @tmp_sp_help_jobhistory table";

View File

@@ -19,6 +19,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
{ {
private JobStepData data; private JobStepData data;
private JobData jobData; private JobData jobData;
private ConfigAction configAction;
public JobStepsActions( public JobStepsActions(
CDataContainer dataContainer, CDataContainer dataContainer,
@@ -26,17 +27,18 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
AgentJobStepInfo stepInfo, AgentJobStepInfo stepInfo,
ConfigAction configAction) ConfigAction configAction)
{ {
this.configAction = configAction;
this.DataContainer = dataContainer; this.DataContainer = dataContainer;
this.jobData = jobData; this.jobData = jobData;
if (configAction == ConfigAction.Update) if (configAction == ConfigAction.Create)
{ {
JobStep jobStep = GetJobStep(this.jobData, stepInfo.StepName); this.data = new JobStepData(jobData.JobSteps);
this.data = new JobStepData(jobStep, jobData.JobSteps);
} }
else else
{ {
this.data = new JobStepData(jobData.JobSteps); JobStep jobStep = GetJobStep(this.jobData, stepInfo.StepName);
this.data = new JobStepData(jobStep, jobData.JobSteps);
} }
// load properties from AgentJobStepInfo // load properties from AgentJobStepInfo
@@ -48,27 +50,36 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
protected override bool DoPreProcessExecution(RunType runType, out ExecutionMode executionResult) protected override bool DoPreProcessExecution(RunType runType, out ExecutionMode executionResult)
{ {
base.DoPreProcessExecution(runType, out executionResult); base.DoPreProcessExecution(runType, out executionResult);
if (this.configAction == ConfigAction.Drop)
// Make sure the job step name is not blank.
if (this.data.Name == null || this.data.Name.Length == 0)
{ {
throw new Exception(SR.JobStepNameCannotBeBlank); if (this.data.JobStep != null)
}
// Check to make sure that the user has not entered a job step name that already exists.
for (int stepIndex = 0; stepIndex < this.data.Parent.Steps.Count; ++stepIndex)
{
// don't compare if the id's are the same.
if (data.ID != ((JobStepData)this.data.Parent.Steps[stepIndex]).ID && data.Name == ((JobStepData)this.data.Parent.Steps[stepIndex]).Name)
{ {
// Throw an error if the job step name already exists this.data.JobStep.DropIfExists();
throw new Exception(SR.JobStepNameAlreadyExists(this.data.Name));
} }
} }
else
{
// Make sure the job step name is not blank.
if (this.data.Name == null || this.data.Name.Length == 0)
{
throw new Exception(SR.JobStepNameCannotBeBlank);
}
if (runType == RunType.RunNow) // Check to make sure that the user has not entered a job step name that already exists.
{ for (int stepIndex = 0; stepIndex < this.data.Parent.Steps.Count; ++stepIndex)
this.data.ApplyChanges(this.jobData.Job); {
// don't compare if the id's are the same.
if (data.ID != ((JobStepData)this.data.Parent.Steps[stepIndex]).ID && data.Name == ((JobStepData)this.data.Parent.Steps[stepIndex]).Name)
{
// Throw an error if the job step name already exists
throw new Exception(SR.JobStepNameAlreadyExists(this.data.Name));
}
}
if (runType == RunType.RunNow)
{
this.data.ApplyChanges(this.jobData.Job);
}
} }
// regular execution always takes place // regular execution always takes place

View File

@@ -7,7 +7,6 @@ using System;
using System.Collections; using System.Collections;
using System.ComponentModel; using System.ComponentModel;
using System.Diagnostics; using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Globalization; using System.Globalization;
using System.Text; using System.Text;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
@@ -16,6 +15,7 @@ using Microsoft.SqlServer.Management.Diagnostics;
using Microsoft.SqlServer.Management.Sdk.Sfc; using Microsoft.SqlServer.Management.Sdk.Sfc;
using Microsoft.SqlServer.Management.Smo; using Microsoft.SqlServer.Management.Smo;
using Microsoft.SqlServer.Management.Smo.Agent; using Microsoft.SqlServer.Management.Smo.Agent;
using Microsoft.SqlTools.ServiceLayer.Management;
namespace Microsoft.SqlTools.ServiceLayer.Agent namespace Microsoft.SqlTools.ServiceLayer.Agent
{ {
@@ -30,16 +30,16 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
#endregion #endregion
#region private struct members #region private struct members
private String name; private string name;
private String description; private string description;
private System.Int32 id; private int id;
private System.Int32 activeEndDate; private int activeEndDate;
private System.Int32 activeEndTimeOfDay; private int activeEndTimeOfDay;
private System.Int32 activeStartDate; private int activeStartDate;
private System.Int32 activeStartTimeOfDay; private int activeStartTimeOfDay;
private System.Int32 frequencyInterval; private int frequencyInterval;
private System.Int32 frequencyRecurrenceFactor; private int frequencyRecurrenceFactor;
private System.Int32 frequencySubDayInterval; private int frequencySubDayInterval;
private FrequencyTypes frequencyTypes; private FrequencyTypes frequencyTypes;
private FrequencySubDayTypes frequencySubDayTypes; private FrequencySubDayTypes frequencySubDayTypes;
private FrequencyRelativeIntervals frequencyRelativeIntervals; private FrequencyRelativeIntervals frequencyRelativeIntervals;
@@ -289,7 +289,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
{ {
if (this.FrequencyInterval == 0) if (this.FrequencyInterval == 0)
{ {
return String.Empty; return string.Empty;
} }
StringBuilder daysOfWeek = new StringBuilder(); StringBuilder daysOfWeek = new StringBuilder();
@@ -347,7 +347,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
{ {
get get
{ {
string format = String.Empty; string format = string.Empty;
switch (this.FrequencyTypes) switch (this.FrequencyTypes)
{ {
@@ -508,43 +508,43 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
#endregion #endregion
#region public properties #region public properties
public System.Int32 ActiveEndDate public int ActiveEndDate
{ {
get { return activeEndDate; } get { return activeEndDate; }
set { activeEndDate = value; } set { activeEndDate = value; }
} }
public System.Int32 ActiveEndTimeOfDay public int ActiveEndTimeOfDay
{ {
get { return activeEndTimeOfDay; } get { return activeEndTimeOfDay; }
set { activeEndTimeOfDay = value; } set { activeEndTimeOfDay = value; }
} }
public System.Int32 ActiveStartDate public int ActiveStartDate
{ {
get { return activeStartDate; } get { return activeStartDate; }
set { activeStartDate = value; } set { activeStartDate = value; }
} }
public System.Int32 ActiveStartTimeOfDay public int ActiveStartTimeOfDay
{ {
get { return activeStartTimeOfDay; } get { return activeStartTimeOfDay; }
set { activeStartTimeOfDay = value; } set { activeStartTimeOfDay = value; }
} }
public System.Int32 FrequencyInterval public int FrequencyInterval
{ {
get { return frequencyInterval; } get { return frequencyInterval; }
set { frequencyInterval = value; } set { frequencyInterval = value; }
} }
public System.Int32 FrequencyRecurrenceFactor public int FrequencyRecurrenceFactor
{ {
get { return frequencyRecurrenceFactor; } get { return frequencyRecurrenceFactor; }
set { frequencyRecurrenceFactor = value; } set { frequencyRecurrenceFactor = value; }
} }
public System.Int32 FrequencySubDayInterval public int FrequencySubDayInterval
{ {
get { return frequencySubDayInterval; } get { return frequencySubDayInterval; }
set { frequencySubDayInterval = value; } set { frequencySubDayInterval = value; }
@@ -592,7 +592,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
} }
} }
public System.Int32 ID public int ID
{ {
get { return id; } get { return id; }
set { id = value; } set { id = value; }
@@ -1147,16 +1147,16 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
if (jobSchedules != null && version.Major < 9) if (jobSchedules != null && version.Major < 9)
{ {
///Check to see if a duplicate job schedule name has been entered. This condition is permissable // Check to see if a duplicate job schedule name has been entered. This condition is permissable
///in SQL 9, but not in previous versions. // in SQL 9, but not in previous versions.
for (int index = 0; index < jobSchedules.Count; index++) for (int index = 0; index < jobSchedules.Count; index++)
{ {
//If the schedule name matches an existing job, throw an error and ask user to enter another // If the schedule name matches an existing job, throw an error and ask user to enter another
//name. // name.
if (((JobScheduleData)jobSchedules[index]).Name == this.Name && if (((JobScheduleData)jobSchedules[index]).Name == this.Name &&
this.currentName != this.originalName) this.currentName != this.originalName)
{ {
sbError.Append("SRError.ScheduleNameAlreadyExists(this.Name)" + "\n"); sbError.Append(SR.ScheduleNameAlreadyExists(this.Name) + "\n");
break; break;
} }
} }
@@ -1165,40 +1165,39 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
// weekly schdule - ensure that the start date is less than the end date // weekly schdule - ensure that the start date is less than the end date
if (this.ActiveStartDate > this.ActiveEndDate) if (this.ActiveStartDate > this.ActiveEndDate)
{ {
sbError.Append("SRError.StartDateGreaterThanEndDate" + "\n"); sbError.Append(SR.StartDateGreaterThanEndDate + "\n");
} }
//One Time events validations // One Time events validations
if (this.FrequencyTypes == FrequencyTypes.OneTime) if (this.FrequencyTypes == FrequencyTypes.OneTime)
{ {
//Check to make sure that the start time is greater than the baseline // Check to make sure that the start time is greater than the baseline
//date of 01/01/1990 // date of 01/01/1990
if (this.ActiveStartDate < minStartDate) if (this.ActiveStartDate < minStartDate)
{ {
sbError.Append("SRError.InvalidStartDate" + "\n"); sbError.Append(SR.InvalidStartDate + "\n");
} }
} }
//Recurring schdule. Start time must be less than the end time. // Recurring schdule. Start time must be less than the end time.
if (this.FrequencyTypes != FrequencyTypes.OneTime && if (this.FrequencyTypes != FrequencyTypes.OneTime &&
this.FrequencyTypes != FrequencyTypes.OnIdle) this.FrequencyTypes != FrequencyTypes.OnIdle)
{ {
//Check to make sure that the start time is greater than the baseline // Check to make sure that the start time is greater than the baseline
//date of 01/01/1990 // date of 01/01/1990
if (this.ActiveStartDate < minStartDate) if (this.ActiveStartDate < minStartDate)
{ {
sbError.Append("SRError.InvalidStartDate" + "\n"); sbError.Append(SR.InvalidStartDate + "\n");
} }
//Check to ensure that the StartTime != to the EndTime // Check to ensure that the StartTime != to the EndTime
if (this.ActiveStartTime == this.ActiveEndTime) if (this.ActiveStartTime == this.ActiveEndTime)
{ {
sbError.Append("SRError.EndTimeEqualToStartTime" + "\n"); sbError.Append(SR.EndTimeEqualToStartTime + "\n");
} }
} }
// weekly schedule - at least one day should be selected // weekly schedule - at least one day should be selected
@@ -1206,12 +1205,10 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
{ {
if (this.FrequencyInterval == 0) if (this.FrequencyInterval == 0)
{ {
sbError.Append("SRError.InvalidWeeklySchedule" + "\n"); sbError.Append(SR.InvalidWeeklySchedule + "\n");
} }
} }
// $FUTURE add extra checks in future - e.g. 147675 - starttime/endtime startdate/enddate and thier format
// return error // return error
if (sbError.ToString().Length > 0) if (sbError.ToString().Length > 0)
{ {
@@ -1243,6 +1240,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
this.alreadyCreated = false; this.alreadyCreated = false;
} }
} }
/// <summary> /// <summary>
/// Provide context to create a new schedule. /// Provide context to create a new schedule.
/// </summary> /// </summary>
@@ -1259,6 +1257,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
{ {
this.source = schedule; this.source = schedule;
} }
public override string ToString() public override string ToString()
{ {
return this.GetSimpleJobDescription(); return this.GetSimpleJobDescription();
@@ -1322,6 +1321,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
this.alreadyCreated = false; this.alreadyCreated = false;
} }
} }
/// <summary> /// <summary>
/// set defaults assuming no parent. /// set defaults assuming no parent.
/// </summary> /// </summary>
@@ -1362,14 +1362,14 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
#region static constants #region static constants
/// <summary> /// <summary>
/// Maximum date supported by SSMS. /// Maximum date supported
/// This is the same as the culture max date because SQl Agent range is larger than all cultures' ranges. /// This is the same as the culture max date because SQL Agent range is larger than all cultures' ranges.
/// </summary> /// </summary>
public static DateTime MaxAgentDateValue public static DateTime MaxAgentDateValue
{ {
get get
{ {
return DateTime.Now; // Utils.GetMaxCultureDateTime().Date; return Utils.GetMaxCultureDateTime().Date;
} }
} }
/// <summary> /// <summary>

View File

@@ -1,3 +1,4 @@
#if false
// //
// Copyright (c) Microsoft. All rights reserved. // Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information. // Licensed under the MIT license. See LICENSE file in the project root for full license information.
@@ -182,3 +183,4 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
#endregion #endregion
} }
} }
#endif

View File

@@ -1,3 +1,4 @@
#if false
// //
// Copyright (c) Microsoft. All rights reserved. // Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information. // Licensed under the MIT license. See LICENSE file in the project root for full license information.
@@ -605,11 +606,4 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
} }
} }
#endif

View File

@@ -1,3 +1,4 @@
#if false
// //
// Copyright (c) Microsoft. All rights reserved. // Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information. // Licensed under the MIT license. See LICENSE file in the project root for full license information.
@@ -466,3 +467,4 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
#endregion #endregion
} }
} }
#endif

View File

@@ -1,3 +1,4 @@
#if false
// //
// Copyright (c) Microsoft. All rights reserved. // Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information. // Licensed under the MIT license. See LICENSE file in the project root for full license information.
@@ -155,3 +156,4 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
#endregion #endregion
} }
} }
#endif

View File

@@ -1,3 +1,4 @@
#if false
// //
// Copyright (c) Microsoft. All rights reserved. // Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information. // Licensed under the MIT license. See LICENSE file in the project root for full license information.
@@ -250,10 +251,4 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
} }
} }
#endif

View File

@@ -1,3 +1,4 @@
#if false
// //
// Copyright (c) Microsoft. All rights reserved. // Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information. // Licensed under the MIT license. See LICENSE file in the project root for full license information.
@@ -108,3 +109,4 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
#endregion #endregion
} }
} }
#endif

View File

@@ -1,3 +1,4 @@
#if false
// //
// Copyright (c) Microsoft. All rights reserved. // Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information. // Licensed under the MIT license. See LICENSE file in the project root for full license information.
@@ -28,17 +29,6 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
/// </summary> /// </summary>
internal class SqlServerAgentPropertiesJobSystem : ManagementActionBase internal class SqlServerAgentPropertiesJobSystem : ManagementActionBase
{ {
#region Private members
private int shutDownWaitTime;
private bool sysAdminOnly;
private string domainUser = string.Empty;
private string userName = string.Empty;
private string passwdMask = new string('*', 16);
private SecureString securePasswd = new SecureString();
#endregion
#region Implementation #region Implementation
private void ApplyChanges() private void ApplyChanges()
@@ -148,11 +138,4 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
#endregion #endregion
} }
} }
#endif

View File

@@ -4349,6 +4349,78 @@ namespace Microsoft.SqlTools.ServiceLayer
} }
} }
public static string AlertNameCannotBeBlank
{
get
{
return Keys.GetString(Keys.AlertNameCannotBeBlank);
}
}
public static string CannotCreateNewAlert
{
get
{
return Keys.GetString(Keys.CannotCreateNewAlert);
}
}
public static string CannotAlterAlert
{
get
{
return Keys.GetString(Keys.CannotAlterAlert);
}
}
public static string InvalidScheduleTitle
{
get
{
return Keys.GetString(Keys.InvalidScheduleTitle);
}
}
public static string InvalidWeeklySchedule
{
get
{
return Keys.GetString(Keys.InvalidWeeklySchedule);
}
}
public static string StartDateGreaterThanEndDate
{
get
{
return Keys.GetString(Keys.StartDateGreaterThanEndDate);
}
}
public static string StartTimeGreaterThanEndTime
{
get
{
return Keys.GetString(Keys.StartTimeGreaterThanEndTime);
}
}
public static string EndTimeEqualToStartTime
{
get
{
return Keys.GetString(Keys.EndTimeEqualToStartTime);
}
}
public static string InvalidStartDate
{
get
{
return Keys.GetString(Keys.InvalidStartDate);
}
}
public static string ConnectionServiceListDbErrorNotConnected(string uri) public static string ConnectionServiceListDbErrorNotConnected(string uri)
{ {
return Keys.GetString(Keys.ConnectionServiceListDbErrorNotConnected, uri); return Keys.GetString(Keys.ConnectionServiceListDbErrorNotConnected, uri);
@@ -4594,6 +4666,11 @@ namespace Microsoft.SqlTools.ServiceLayer
return Keys.GetString(Keys.JobStepNameAlreadyExists, jobName); return Keys.GetString(Keys.JobStepNameAlreadyExists, jobName);
} }
public static string ScheduleNameAlreadyExists(string scheduleName)
{
return Keys.GetString(Keys.ScheduleNameAlreadyExists, scheduleName);
}
[System.Runtime.CompilerServices.CompilerGeneratedAttribute()] [System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
public class Keys public class Keys
{ {
@@ -6369,6 +6446,36 @@ namespace Microsoft.SqlTools.ServiceLayer
public const string JobStepNameAlreadyExists = "JobStepNameAlreadyExists"; public const string JobStepNameAlreadyExists = "JobStepNameAlreadyExists";
public const string AlertNameCannotBeBlank = "AlertNameCannotBeBlank";
public const string CannotCreateNewAlert = "CannotCreateNewAlert";
public const string CannotAlterAlert = "CannotAlterAlert";
public const string InvalidScheduleTitle = "InvalidScheduleTitle";
public const string InvalidWeeklySchedule = "InvalidWeeklySchedule";
public const string StartDateGreaterThanEndDate = "StartDateGreaterThanEndDate";
public const string StartTimeGreaterThanEndTime = "StartTimeGreaterThanEndTime";
public const string EndTimeEqualToStartTime = "EndTimeEqualToStartTime";
public const string InvalidStartDate = "InvalidStartDate";
public const string ScheduleNameAlreadyExists = "ScheduleNameAlreadyExists";
private Keys() private Keys()
{ } { }

View File

@@ -2522,4 +2522,45 @@
<comment>. <comment>.
Parameters: 0 - jobName (string) </comment> Parameters: 0 - jobName (string) </comment>
</data> </data>
<data name="AlertNameCannotBeBlank" xml:space="preserve">
<value>The name of the alert cannot be blank.</value>
<comment></comment>
</data>
<data name="CannotCreateNewAlert" xml:space="preserve">
<value>Cannot create new alert.</value>
<comment></comment>
</data>
<data name="CannotAlterAlert" xml:space="preserve">
<value>Cannot alter alert.</value>
<comment></comment>
</data>
<data name="InvalidScheduleTitle" xml:space="preserve">
<value>Invalid Schedule</value>
<comment> Schedule error message</comment>
</data>
<data name="InvalidWeeklySchedule" xml:space="preserve">
<value>Select at least one day to be part of this weekly schedule.</value>
<comment></comment>
</data>
<data name="StartDateGreaterThanEndDate" xml:space="preserve">
<value>The job schedule starting date cannot be greater than the ending date.</value>
<comment></comment>
</data>
<data name="StartTimeGreaterThanEndTime" xml:space="preserve">
<value>The job schedule starting time cannot be after the ending time.</value>
<comment></comment>
</data>
<data name="EndTimeEqualToStartTime" xml:space="preserve">
<value>The job schedule ending time must be after the starting time.</value>
<comment></comment>
</data>
<data name="InvalidStartDate" xml:space="preserve">
<value>Start date must be on or after January 1, 1990.</value>
<comment></comment>
</data>
<data name="ScheduleNameAlreadyExists" xml:space="preserve">
<value>There is already a schedule named '{0}' for this job. You must specify a different name.</value>
<comment>.
Parameters: 0 - scheduleName (string) </comment>
</data>
</root> </root>

View File

@@ -888,18 +888,6 @@ InvalidPathError = Cannot access the specified path on the server: {0}
# Profiler # Profiler
ProfilerConnectionNotFound = Connection not found ProfilerConnectionNotFound = Connection not found
############################################################################# #############################################################################
# SQL Agent # SQL Agent
EnableAlertsTitle(String serverName) = Enable Alerts - {0} EnableAlertsTitle(String serverName) = Enable Alerts - {0}
@@ -1016,8 +1004,6 @@ CannotCreateInitializeHistoryPage = Cannot create/initialize History page.
; Exception throw when dialog cannot refresh operator ; Exception throw when dialog cannot refresh operator
CannotResetOperator = Cannot reset operator. CannotResetOperator = Cannot reset operator.
#
; Name of label on notifications page ; Name of label on notifications page
AlertList = Alert list: AlertList = Alert list:
; Name of label on notifications page ; Name of label on notifications page
@@ -1043,7 +1029,6 @@ CannotModifyAlerts = Cannot modify alerts.
; Exception thrown when we cannot create script that modify alerts ; Exception thrown when we cannot create script that modify alerts
CannotCreateScriptForModifyAlerts = Cannot create script for modify alerts. CannotCreateScriptForModifyAlerts = Cannot create script for modify alerts.
;job categories ;job categories
CategoryLocal = [Uncategorized (Local)] CategoryLocal = [Uncategorized (Local)]
CategoryFromMsx = Jobs from MSX CategoryFromMsx = Jobs from MSX
@@ -1069,4 +1054,16 @@ CategoryDataCollector = Data Collector
JobAlreadyExists(string jobName) = A job named '{0}' already exists. Enter a unique name for the job. JobAlreadyExists(string jobName) = A job named '{0}' already exists. Enter a unique name for the job.
JobStepNameCannotBeBlank = The name of the job step cannot be blank. JobStepNameCannotBeBlank = The name of the job step cannot be blank.
JobStepNameAlreadyExists(string jobName) = There is already a step named '{0}' for this job. You must specify a different name. JobStepNameAlreadyExists(string jobName) = There is already a step named '{0}' for this job. You must specify a different name.
AlertNameCannotBeBlank = The name of the alert cannot be blank.
CannotCreateNewAlert = Cannot create new alert.
CannotAlterAlert = Cannot alter alert.
; Schedule error message
InvalidScheduleTitle = Invalid Schedule
InvalidWeeklySchedule = Select at least one day to be part of this weekly schedule.
StartDateGreaterThanEndDate = The job schedule starting date cannot be greater than the ending date.
StartTimeGreaterThanEndTime = The job schedule starting time cannot be after the ending time.
EndTimeEqualToStartTime = The job schedule ending time must be after the starting time.
InvalidStartDate = Start date must be on or after January 1, 1990.
ScheduleNameAlreadyExists(string scheduleName)=There is already a schedule named '{0}' for this job. You must specify a different name.

View File

@@ -2995,6 +2995,57 @@
<note>. <note>.
Parameters: 0 - jobName (string) </note> Parameters: 0 - jobName (string) </note>
</trans-unit> </trans-unit>
<trans-unit id="AlertNameCannotBeBlank">
<source>The name of the alert cannot be blank.</source>
<target state="new">The name of the alert cannot be blank.</target>
<note></note>
</trans-unit>
<trans-unit id="CannotCreateNewAlert">
<source>Cannot create new alert.</source>
<target state="new">Cannot create new alert.</target>
<note></note>
</trans-unit>
<trans-unit id="CannotAlterAlert">
<source>Cannot alter alert.</source>
<target state="new">Cannot alter alert.</target>
<note></note>
</trans-unit>
<trans-unit id="InvalidScheduleTitle">
<source>Invalid Schedule</source>
<target state="new">Invalid Schedule</target>
<note> Schedule error message</note>
</trans-unit>
<trans-unit id="InvalidWeeklySchedule">
<source>Select at least one day to be part of this weekly schedule.</source>
<target state="new">Select at least one day to be part of this weekly schedule.</target>
<note></note>
</trans-unit>
<trans-unit id="StartDateGreaterThanEndDate">
<source>The job schedule starting date cannot be greater than the ending date.</source>
<target state="new">The job schedule starting date cannot be greater than the ending date.</target>
<note></note>
</trans-unit>
<trans-unit id="StartTimeGreaterThanEndTime">
<source>The job schedule starting time cannot be after the ending time.</source>
<target state="new">The job schedule starting time cannot be after the ending time.</target>
<note></note>
</trans-unit>
<trans-unit id="EndTimeEqualToStartTime">
<source>The job schedule ending time must be after the starting time.</source>
<target state="new">The job schedule ending time must be after the starting time.</target>
<note></note>
</trans-unit>
<trans-unit id="InvalidStartDate">
<source>Start date must be on or after January 1, 1990.</source>
<target state="new">Start date must be on or after January 1, 1990.</target>
<note></note>
</trans-unit>
<trans-unit id="ScheduleNameAlreadyExists">
<source>There is already a schedule named '{0}' for this job. You must specify a different name.</source>
<target state="new">There is already a schedule named '{0}' for this job. You must specify a different name.</target>
<note>.
Parameters: 0 - scheduleName (string) </note>
</trans-unit>
</body> </body>
</file> </file>
</xliff> </xliff>

View File

@@ -261,6 +261,21 @@ namespace Microsoft.SqlTools.ServiceLayer.Management
{ {
return "[" + s.Replace("]", "]]") + "]"; return "[" + s.Replace("]", "]]") + "]";
} }
/// <summary>
/// Some calendars, such as the UmAlQuraCalendar, support an upper date range that is earlier than MaxValue.
/// In these cases, trying to access MaxValue in variable assignments or formatting and parsing operations can throw
/// an ArgumentOutOfRangeException. Rather than retrieving the value of DateTime.MaxValue, you can retrieve the value
/// of the specified culture's latest valid date value from the
/// System.Globalization.CultureInfo.DateTimeFormat.Calendar.MaxSupportedDateTime property.
/// http://msdn.microsoft.com/en-us/library/system.datetime.maxvalue(v=VS.90).aspx
/// </summary>
/// <returns></returns>
public static DateTime GetMaxCultureDateTime()
{
CultureInfo currentCulture = System.Threading.Thread.CurrentThread.CurrentCulture;
return currentCulture.DateTimeFormat.Calendar.MaxSupportedDateTime;
}
} }
/// <summary> /// <summary>

View File

@@ -3,21 +3,11 @@
// Licensed under the MIT license. See LICENSE file in the project root for full license information. // Licensed under the MIT license. See LICENSE file in the project root for full license information.
// //
using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.IO;
using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.SqlServer.Management.Smo;
using Microsoft.SqlServer.Management.XEvent;
using Microsoft.SqlTools.Hosting.Protocol; using Microsoft.SqlTools.Hosting.Protocol;
using Microsoft.SqlTools.ServiceLayer.Agent; using Microsoft.SqlTools.ServiceLayer.Agent;
using Microsoft.SqlTools.ServiceLayer.Agent.Contracts; using Microsoft.SqlTools.ServiceLayer.Agent.Contracts;
using Microsoft.SqlTools.ServiceLayer.Connection;
using Microsoft.SqlTools.ServiceLayer.IntegrationTests.Utility; using Microsoft.SqlTools.ServiceLayer.IntegrationTests.Utility;
using Microsoft.SqlTools.ServiceLayer.Profiler;
using Microsoft.SqlTools.ServiceLayer.Profiler.Contracts;
using Microsoft.SqlTools.ServiceLayer.Test.Common; using Microsoft.SqlTools.ServiceLayer.Test.Common;
using Microsoft.SqlTools.ServiceLayer.Utility; using Microsoft.SqlTools.ServiceLayer.Utility;
using Moq; using Moq;
@@ -53,43 +43,44 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.Agent
/// <summary> /// <summary>
/// Verify the default "create agent alert" request handler with valid parameters /// Verify the default "create agent alert" request handler with valid parameters
/// </summary> /// </summary>
// TODO: Fix flaky test. See https://github.com/Microsoft/sqltoolsservice/issues/630 [Fact]
// [Fact]
public async Task TestHandleCreateAgentAlertsRequest() public async Task TestHandleCreateAgentAlertsRequest()
{ {
using (SelfCleaningTempFile queryTempFile = new SelfCleaningTempFile()) using (SelfCleaningTempFile queryTempFile = new SelfCleaningTempFile())
{ {
var connectionResult = await LiveConnectionHelper.InitLiveConnectionInfoAsync("master", queryTempFile.FilePath); // setup
var createContext = new Mock<RequestContext<CreateAgentAlertResult>>();
var deleteContext = new Mock<RequestContext<ResultStatus>>();
var requestParams = new CreateAgentAlertParams var service = new AgentService();
var alert = new AgentAlertInfo()
{ {
OwnerUri = connectionResult.ConnectionInfo.OwnerUri, JobName = "test_update_job",
Alert = new AgentAlertInfo() AlertType = AlertType.SqlServerEvent,
{ Severity = 1
JobName = "Test Job Name"
}
}; };
var requestContext = new Mock<RequestContext<CreateAgentAlertResult>>(); var connectionResult = await LiveConnectionHelper.InitLiveConnectionInfoAsync("master", queryTempFile.FilePath);
await service.HandleDeleteAgentAlertRequest(new DeleteAgentAlertParams()
{
OwnerUri = connectionResult.ConnectionInfo.OwnerUri,
Alert = alert
}, deleteContext.Object);
AgentService service = new AgentService(); // test
await service.HandleCreateAgentAlertRequest(requestParams, requestContext.Object); await service.HandleCreateAgentAlertRequest(new CreateAgentAlertParams
{
OwnerUri = connectionResult.ConnectionInfo.OwnerUri,
Alert = alert
}, createContext.Object);
createContext.VerifyAll();
// var agentAlerts = await AgentTestUtils.GetAgentAlerts(connectionResult.ConnectionInfo.OwnerUri); // cleanup
// if (agentAlerts != null && agentAlerts.Length > 0) await service.HandleDeleteAgentAlertRequest(new DeleteAgentAlertParams()
// { {
// foreach (var agentAlert in agentAlerts) OwnerUri = connectionResult.ConnectionInfo.OwnerUri,
// { Alert = alert
// if (agentAlert.JobName.Equals(alert.JobName)) }, deleteContext.Object);
// {
// await service.HandleDeleteAgentAlertRequest(new DeleteAgentAlertParams()
// {
// OwnerUri = connectionResult.ConnectionInfo.OwnerUri,
// Alert = alert
// }, deleteContext.Object);
// }
// }
// }
} }
} }
@@ -101,6 +92,7 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.Agent
{ {
using (SelfCleaningTempFile queryTempFile = new SelfCleaningTempFile()) using (SelfCleaningTempFile queryTempFile = new SelfCleaningTempFile())
{ {
// setup
var createContext = new Mock<RequestContext<CreateAgentAlertResult>>(); var createContext = new Mock<RequestContext<CreateAgentAlertResult>>();
var updateContext = new Mock<RequestContext<UpdateAgentAlertResult>>(); var updateContext = new Mock<RequestContext<UpdateAgentAlertResult>>();
var deleteContext = new Mock<RequestContext<ResultStatus>>(); var deleteContext = new Mock<RequestContext<ResultStatus>>();
@@ -126,21 +118,21 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.Agent
Alert = alert Alert = alert
}, createContext.Object); }, createContext.Object);
// test
alert.Severity = 2;
await service.HandleUpdateAgentAlertRequest(new UpdateAgentAlertParams() await service.HandleUpdateAgentAlertRequest(new UpdateAgentAlertParams()
{ {
OwnerUri = connectionResult.ConnectionInfo.OwnerUri, OwnerUri = connectionResult.ConnectionInfo.OwnerUri,
Alert = alert Alert = alert
}, updateContext.Object); }, updateContext.Object);
updateContext.VerifyAll();
// cleanup
await service.HandleDeleteAgentAlertRequest(new DeleteAgentAlertParams() await service.HandleDeleteAgentAlertRequest(new DeleteAgentAlertParams()
{ {
OwnerUri = connectionResult.ConnectionInfo.OwnerUri, OwnerUri = connectionResult.ConnectionInfo.OwnerUri,
Alert = alert Alert = alert
}, deleteContext.Object); }, deleteContext.Object);
createContext.VerifyAll();
updateContext.VerifyAll();
deleteContext.VerifyAll();
} }
} }
} }

View File

@@ -64,8 +64,33 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.Agent
await AgentTestUtils.UpdateAgentJobStep(service, connectionResult, stepInfo); await AgentTestUtils.UpdateAgentJobStep(service, connectionResult, stepInfo);
// cleanup // cleanup
await AgentTestUtils.DeleteAgentJob(service, connectionResult, job, verify: false); await AgentTestUtils.DeleteAgentJob(service, connectionResult, job, verify: false);
} }
} }
/// <summary>
/// TestHandleDeleteAgentJobRequest
/// </summary>
[Fact]
public async Task TestHandleDeleteAgentJobStepRequest()
{
using (SelfCleaningTempFile queryTempFile = new SelfCleaningTempFile())
{
// setup
var service = new AgentService();
var connectionResult = await LiveConnectionHelper.InitLiveConnectionInfoAsync("master", queryTempFile.FilePath);
var job = AgentTestUtils.GetTestJobInfo();
await AgentTestUtils.DeleteAgentJob(service, connectionResult, job, verify: false);
await AgentTestUtils.CreateAgentJob(service, connectionResult, job);
var stepInfo = AgentTestUtils.GetTestJobStepInfo(connectionResult, job);
await AgentTestUtils.CreateAgentJobStep(service, connectionResult, stepInfo);
// test
await AgentTestUtils.DeleteAgentJobStep(service, connectionResult, stepInfo);
// cleanup
await AgentTestUtils.DeleteAgentJob(service, connectionResult, job, verify: false);
}
}
} }
} }

View File

@@ -16,34 +16,69 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.Agent
{ {
public class AgentOperatorTests public class AgentOperatorTests
{ {
/// <summary>
/// Verify the default "create agent alert" request handler with valid parameters
/// </summary>
[Fact]
public async Task TestHandleCreateAgentOperatorRequest()
{
using (SelfCleaningTempFile queryTempFile = new SelfCleaningTempFile())
{
// setup
var service = new AgentService();
var operatorInfo = AgentTestUtils.GetTestOperatorInfo();
var connectionResult = await LiveConnectionHelper.InitLiveConnectionInfoAsync("master", queryTempFile.FilePath);
await AgentTestUtils.DeleteAgentOperator(service, connectionResult, operatorInfo);
// test
await AgentTestUtils.CreateAgentOperator(service, connectionResult, operatorInfo);
// cleanup
await AgentTestUtils.DeleteAgentOperator(service, connectionResult, operatorInfo);
}
}
/// <summary> /// <summary>
/// Verify the default "update agent alert" request handler with valid parameters /// TestHandleUpdateAgentOperatorRequest
/// </summary> /// </summary>
//[Fact] [Fact]
public async Task TestHandleUpdateAgentOperatorRequest() public async Task TestHandleUpdateAgentOperatorRequest()
{ {
using (SelfCleaningTempFile queryTempFile = new SelfCleaningTempFile()) using (SelfCleaningTempFile queryTempFile = new SelfCleaningTempFile())
{ {
var createContext = new Mock<RequestContext<CreateAgentOperatorResult>>(); // setup
var service = new AgentService(); var service = new AgentService();
var operatorInfo = new AgentOperatorInfo() var operatorInfo = AgentTestUtils.GetTestOperatorInfo();
{
Id = 10,
Name = "Joe DBA",
EmailAddress = "test@aol.com"
};
var connectionResult = await LiveConnectionHelper.InitLiveConnectionInfoAsync("master", queryTempFile.FilePath); var connectionResult = await LiveConnectionHelper.InitLiveConnectionInfoAsync("master", queryTempFile.FilePath);
await AgentTestUtils.DeleteAgentOperator(service, connectionResult, operatorInfo);
await AgentTestUtils.CreateAgentOperator(service, connectionResult, operatorInfo);
await service.HandleCreateAgentOperatorRequest(new CreateAgentOperatorParams // test
{ operatorInfo.EmailAddress = "updated@email.com";
OwnerUri = connectionResult.ConnectionInfo.OwnerUri, await AgentTestUtils.UpdateAgentOperator(service, connectionResult, operatorInfo);
Operator = operatorInfo
}, createContext.Object);
createContext.VerifyAll(); // cleanup
await AgentTestUtils.DeleteAgentOperator(service, connectionResult, operatorInfo);
}
}
/// <summary>
/// TestHandleDeleteAgentOperatorRequest
/// </summary>
[Fact]
public async Task TestHandleDeleteAgentOperatorRequest()
{
using (SelfCleaningTempFile queryTempFile = new SelfCleaningTempFile())
{
// setup
var service = new AgentService();
var operatorInfo = AgentTestUtils.GetTestOperatorInfo();
var connectionResult = await LiveConnectionHelper.InitLiveConnectionInfoAsync("master", queryTempFile.FilePath);
await AgentTestUtils.DeleteAgentOperator(service, connectionResult, operatorInfo);
await AgentTestUtils.CreateAgentOperator(service, connectionResult, operatorInfo);
// test
await AgentTestUtils.DeleteAgentOperator(service, connectionResult, operatorInfo);
} }
} }
} }

View File

@@ -59,6 +59,16 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.Agent
}; };
} }
internal static AgentOperatorInfo GetTestOperatorInfo()
{
return new AgentOperatorInfo()
{
Id = 10,
Name = "Joe DBA",
EmailAddress = "test@aol.com"
};
}
internal static async Task CreateAgentJob( internal static async Task CreateAgentJob(
AgentService service, AgentService service,
TestConnectionResult connectionResult, TestConnectionResult connectionResult,
@@ -135,6 +145,62 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.Agent
context.VerifyAll(); context.VerifyAll();
} }
internal static async Task DeleteAgentJobStep(
AgentService service,
TestConnectionResult connectionResult,
AgentJobStepInfo stepInfo)
{
var context = new Mock<RequestContext<ResultStatus>>();
await service.HandleDeleteAgentJobStepRequest(new DeleteAgentJobStepParams
{
OwnerUri = connectionResult.ConnectionInfo.OwnerUri,
Step = stepInfo
}, context.Object);
context.VerifyAll();
}
internal static async Task CreateAgentOperator(
AgentService service,
TestConnectionResult connectionResult,
AgentOperatorInfo operatorInfo)
{
var context = new Mock<RequestContext<AgentOperatorResult>>();
await service.HandleCreateAgentOperatorRequest(new CreateAgentOperatorParams
{
OwnerUri = connectionResult.ConnectionInfo.OwnerUri,
Operator = operatorInfo
}, context.Object);
context.VerifyAll();
}
internal static async Task UpdateAgentOperator(
AgentService service,
TestConnectionResult connectionResult,
AgentOperatorInfo operatorInfo)
{
var context = new Mock<RequestContext<AgentOperatorResult>>();
await service.HandleUpdateAgentOperatorRequest(new UpdateAgentOperatorParams
{
OwnerUri = connectionResult.ConnectionInfo.OwnerUri,
Operator = operatorInfo
}, context.Object);
context.VerifyAll();
}
internal static async Task DeleteAgentOperator(
AgentService service,
TestConnectionResult connectionResult,
AgentOperatorInfo operatorInfo)
{
var context = new Mock<RequestContext<ResultStatus>>();
await service.HandleDeleteAgentOperatorRequest(new DeleteAgentOperatorParams
{
OwnerUri = connectionResult.ConnectionInfo.OwnerUri,
Operator = operatorInfo
}, context.Object);
context.VerifyAll();
}
internal static async Task<AgentAlertInfo[]> GetAgentAlerts(string connectionUri) internal static async Task<AgentAlertInfo[]> GetAgentAlerts(string connectionUri)
{ {
var requestParams = new AgentAlertsParams() var requestParams = new AgentAlertsParams()