From aff0f1afae2979ac17d0ba0073634a08c100a507 Mon Sep 17 00:00:00 2001 From: Karl Burtram Date: Wed, 13 Jun 2018 17:49:11 -0700 Subject: [PATCH] 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 --- .../Agent/AgentService.cs | 519 +++++++++--------- .../Agent/Contracts/AgentOperatorRequest.cs | 83 ++- .../Agent/Jobs/AgentAlertActions.cs | 31 +- .../Agent/Jobs/AgentOperatorActions.cs | 99 ++++ ...{AgentOperator.cs => AgentOperatorData.cs} | 269 ++++----- .../Agent/Jobs/JobHistoryItem.cs | 1 - .../Agent/Jobs/JobStepsActions.cs | 51 +- .../Agent/Jobs/ScheduleData.cs | 88 +-- .../Agent/Jobs/ScheduleScriptExecution.cs | 2 + .../Jobs/SqlServerAgentPropertiesAdvanced.cs | 10 +- .../SqlServerAgentPropertiesAlertSystem.cs | 2 + .../SqlServerAgentPropertiesConnection.cs | 2 + .../Jobs/SqlServerAgentPropertiesGeneral.cs | 9 +- .../Jobs/SqlServerAgentPropertiesHistory.cs | 2 + .../Jobs/SqlServerAgentPropertiesJobSystem.cs | 21 +- .../Localization/sr.cs | 107 ++++ .../Localization/sr.resx | 41 ++ .../Localization/sr.strings | 29 +- .../Localization/sr.xlf | 51 ++ .../Management/Common/Utils.cs | 15 + .../Agent/AgentAlertTests.cs | 74 ++- .../Agent/AgentJobStepTests.cs | 27 +- .../Agent/AgentOperatorTests.cs | 69 ++- .../Agent/AgentTestUtils.cs | 66 +++ 24 files changed, 1037 insertions(+), 631 deletions(-) create mode 100644 src/Microsoft.SqlTools.ServiceLayer/Agent/Jobs/AgentOperatorActions.cs rename src/Microsoft.SqlTools.ServiceLayer/Agent/Jobs/{AgentOperator.cs => AgentOperatorData.cs} (91%) diff --git a/src/Microsoft.SqlTools.ServiceLayer/Agent/AgentService.cs b/src/Microsoft.SqlTools.ServiceLayer/Agent/AgentService.cs index f4bbbdf2..ed97b173 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Agent/AgentService.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Agent/AgentService.cs @@ -7,8 +7,6 @@ using System; using System.Collections.Generic; using System.Data; using System.IO; -using System.Linq; -using System.Text; using System.Threading.Tasks; using System.Xml; using Microsoft.SqlServer.Management.Common; @@ -21,7 +19,6 @@ using Microsoft.SqlTools.ServiceLayer.Connection; using Microsoft.SqlTools.ServiceLayer.Hosting; using Microsoft.SqlTools.ServiceLayer.Management; using Microsoft.SqlTools.ServiceLayer.Utility; -using Microsoft.SqlTools.Utility; namespace Microsoft.SqlTools.ServiceLayer.Agent { @@ -266,18 +263,6 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent }); } - private Tuple 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(sqlConnInfo, dt, serverConnection); - } - internal async Task HandleCreateAgentJobRequest(CreateAgentJobParams parameters, RequestContext requestContext) { var result = await ConfigureAgentJob( @@ -366,135 +351,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent Success = result.Item1, ErrorMessage = result.Item2 }); - } - - internal async Task> ConfigureAgentJob( - string ownerUri, - AgentJobInfo jobInfo, - ConfigAction configAction, - RunType runType) - { - return await Task>.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(true, string.Empty); - } - catch (Exception ex) - { - return new Tuple(false, ex.ToString()); - } - }); - } - - internal async Task> ConfigureAgentJobStep( - string ownerUri, - AgentJobStepInfo stepInfo, - ConfigAction configAction, - RunType runType) - { - return await Task>.Run(() => - { - try - { - if (string.IsNullOrWhiteSpace(stepInfo.JobName)) - { - return new Tuple(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(true, string.Empty); - } - catch (Exception ex) - { - // log exception here - return new Tuple(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" @@ -511,9 +368,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent result.Alerts = new List().ToArray(); ConnectionInfo connInfo; - ConnectionServiceInstance.TryFindConnection( - parameters.OwnerUri, - out connInfo); + ConnectionServiceInstance.TryFindConnection(parameters.OwnerUri, out connInfo); if (connInfo != null) { @@ -525,29 +380,22 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent }); } - private bool ValidateAgentAlertInfo(AgentAlertInfo alert) - { - return alert != null - && !string.IsNullOrWhiteSpace(alert.JobName); - } - /// /// Handle request to create an alert /// internal async Task HandleCreateAgentAlertRequest(CreateAgentAlertParams parameters, RequestContext 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(); - ConnectionInfo connInfo; - ConnectionServiceInstance.TryFindConnection( - parameters.OwnerUri, - out connInfo); - - CreateOrUpdateAgentAlert(connInfo, parameters.Alert); - - await requestContext.SendResult(result); - }); + Success = result.Item1, + ErrorMessage = result.Item2 + }); } /// @@ -555,71 +403,34 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent /// internal async Task HandleUpdateAgentAlertRequest(UpdateAgentAlertParams parameters, RequestContext 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(); - ConnectionInfo connInfo; - ConnectionServiceInstance.TryFindConnection( - parameters.OwnerUri, - out connInfo); - - CreateOrUpdateAgentAlert(connInfo, parameters.Alert); - - await requestContext.SendResult(result); + Success = result.Item1, + ErrorMessage = result.Item2 }); } - 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(); - } - } - } - /// /// Handle request to delete an alert /// internal async Task HandleDeleteAgentAlertRequest(DeleteAgentAlertParams parameters, RequestContext 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(); - try - { - 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); + Success = result.Item1, + ErrorMessage = result.Item2 }); } @@ -630,41 +441,60 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent internal async Task HandleAgentOperatorsRequest(AgentOperatorsParams parameters, RequestContext requestContext) { await requestContext.SendResult(null); - } + } - internal async Task HandleCreateAgentOperatorRequest(CreateAgentOperatorParams parameters, RequestContext requestContext) + internal async Task HandleCreateAgentOperatorRequest( + CreateAgentOperatorParams parameters, + RequestContext 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(); - ConnectionInfo connInfo; - ConnectionServiceInstance.TryFindConnection( - 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); + Success = result.Item1, + ErrorMessage = result.Item2, + Operator = parameters.Operator }); } - internal async Task HandleUpdateAgentOperatorRequest(UpdateAgentOperatorParams parameters, RequestContext requestContext) + internal async Task HandleUpdateAgentOperatorRequest( + UpdateAgentOperatorParams parameters, + RequestContext 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 requestContext) + internal async Task HandleDeleteAgentOperatorRequest( + DeleteAgentOperatorParams parameters, + RequestContext 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" @@ -718,6 +548,140 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent }); } + #endregion // "Proxy Handlers" + + + #region "Helpers" + + internal async Task> ConfigureAgentJob( + string ownerUri, + AgentJobInfo jobInfo, + ConfigAction configAction, + RunType runType) + { + return await Task>.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(true, string.Empty); + } + catch (Exception ex) + { + return new Tuple(false, ex.ToString()); + } + }); + } + + internal async Task> ConfigureAgentJobStep( + string ownerUri, + AgentJobStepInfo stepInfo, + ConfigAction configAction, + RunType runType) + { + return await Task>.Run(() => + { + try + { + if (string.IsNullOrWhiteSpace(stepInfo.JobName)) + { + return new Tuple(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(true, string.Empty); + } + catch (Exception ex) + { + // log exception here + return new Tuple(false, ex.ToString()); + } + }); + } + + internal async Task> ConfigureAgentAlert( + string ownerUri, + AgentAlertInfo alert, + ConfigAction configAction, + RunType runType) + { + return await Task>.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(true, string.Empty); + } + catch (Exception ex) + { + return new Tuple(false, ex.ToString()); + } + }); + } + + internal async Task> ConfigureAgentOperator( + string ownerUri, + AgentOperatorInfo operatorInfo, + ConfigAction configAction, + RunType runType) + { + return await Task>.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(true, string.Empty); + } + catch (Exception ex) + { + return new Tuple(false, ex.ToString()); + } + }); + } + internal async Task ConfigureAgentProxy( string ownerUri, string accountName, @@ -763,8 +727,73 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent 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 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(sqlConnInfo, dt, serverConnection); + } + + #endregion // "Helpers" } } diff --git a/src/Microsoft.SqlTools.ServiceLayer/Agent/Contracts/AgentOperatorRequest.cs b/src/Microsoft.SqlTools.ServiceLayer/Agent/Contracts/AgentOperatorRequest.cs index c9aa4ce0..0946706a 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Agent/Contracts/AgentOperatorRequest.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Agent/Contracts/AgentOperatorRequest.cs @@ -38,6 +38,14 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent.Contracts RequestType.Create("agent/operators"); } + /// + /// SQL Agent Operator result + /// + public class AgentOperatorResult : ResultStatus + { + public AgentOperatorInfo Operator { get; set; } + } + /// /// SQL Agent create Operator params /// @@ -48,13 +56,6 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent.Contracts public AgentOperatorInfo Operator { get; set; } } - /// - /// SQL Agent create Operator result - /// - public class CreateAgentOperatorResult : ResultStatus - { - } - /// /// SQL Agent create Operator request type /// @@ -64,38 +65,8 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent.Contracts /// Request definition /// public static readonly - RequestType Type = - RequestType.Create("agent/createoperator"); - } - - /// - /// SQL Agent delete Operator params - /// - public class DeleteAgentOperatorParams : GeneralRequestDetails - { - public string OwnerUri { get; set; } - - public AgentOperatorInfo Operator { get; set; } - } - - /// - /// SQL Agent delete Operator result - /// - public class DeleteAgentOperatorResult : ResultStatus - { - } - - /// - /// SQL Agent delete Operator request type - /// - public class DeleteAgentOperatorRequest - { - /// - /// Request definition - /// - public static readonly - RequestType Type = - RequestType.Create("agent/deleteoperator"); + RequestType Type = + RequestType.Create("agent/createoperator"); } /// @@ -108,13 +79,6 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent.Contracts public AgentOperatorInfo Operator { get; set; } } - /// - /// SQL Agent update Operator result - /// - public class UpdateAgentOperatorResult : ResultStatus - { - } - /// /// SQL Agent update Operator request type /// @@ -124,7 +88,30 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent.Contracts /// Request definition /// public static readonly - RequestType Type = - RequestType.Create("agent/updateoperator"); + RequestType Type = + RequestType.Create("agent/updateoperator"); + } + + /// + /// SQL Agent delete Operator params + /// + public class DeleteAgentOperatorParams : GeneralRequestDetails + { + public string OwnerUri { get; set; } + + public AgentOperatorInfo Operator { get; set; } } + + /// + /// SQL Agent delete Operator request type + /// + public class DeleteAgentOperatorRequest + { + /// + /// Request definition + /// + public static readonly + RequestType Type = + RequestType.Create("agent/deleteoperator"); + } } diff --git a/src/Microsoft.SqlTools.ServiceLayer/Agent/Jobs/AgentAlertActions.cs b/src/Microsoft.SqlTools.ServiceLayer/Agent/Jobs/AgentAlertActions.cs index 7ce3161e..cb9343f9 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Agent/Jobs/AgentAlertActions.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Agent/Jobs/AgentAlertActions.cs @@ -4,14 +4,8 @@ // using System; -using System.Collections; -using System.Data; 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.SqlTools.ServiceLayer.Admin; using Microsoft.SqlTools.ServiceLayer.Agent.Contracts; using Microsoft.SqlTools.ServiceLayer.Management; @@ -27,14 +21,17 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent /// private AgentAlertInfo alertInfo = null; + private ConfigAction configAction; + /// /// Default constructor that will be used to create dialog /// /// - public AgentAlertActions(CDataContainer dataContainer, AgentAlertInfo alertInfo) + public AgentAlertActions(CDataContainer dataContainer, AgentAlertInfo alertInfo, ConfigAction configAction) { this.alertInfo = alertInfo; this.DataContainer = dataContainer; + this.configAction = configAction; } private static string GetAlertName(CDataContainer container) @@ -44,7 +41,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent parameters.SetDocument(container.Document); if (parameters.GetParam("alert", ref alertName) == false || string.IsNullOrWhiteSpace(alertName)) { - throw new Exception("SRError.AlertNameCannotBeBlank"); + throw new Exception(SR.AlertNameCannotBeBlank); } return alertName.Trim(); } @@ -59,8 +56,18 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent protected override bool DoPreProcessExecution(RunType runType, out ExecutionMode 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() { @@ -136,11 +143,11 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent ApplicationException applicationException; if (createNewAlert) { - applicationException = new ApplicationException("AgentAlertSR.CannotCreateNewAlert", e); + applicationException = new ApplicationException(SR.CannotCreateNewAlert, e); } else { - applicationException = new ApplicationException("AgentAlertSR.CannotAlterAlert", e); + applicationException = new ApplicationException(SR.CannotAlterAlert, e); } throw applicationException; } diff --git a/src/Microsoft.SqlTools.ServiceLayer/Agent/Jobs/AgentOperatorActions.cs b/src/Microsoft.SqlTools.ServiceLayer/Agent/Jobs/AgentOperatorActions.cs new file mode 100644 index 00000000..7a8cc2a9 --- /dev/null +++ b/src/Microsoft.SqlTools.ServiceLayer/Agent/Jobs/AgentOperatorActions.cs @@ -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 +{ + /// + /// Agent Operators management class + /// + internal class AgentOperatorActions : ManagementActionBase + { + private AgentOperatorInfo operatorInfo; + private AgentOperatorsData operatorsData = null; + private ConfigAction configAction; + + /// + /// Constructor + /// + 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"); + } + } + + /// + /// Clean up any resources being used. + /// + protected override void Dispose(bool disposing) + { + if(disposing) + { + } + base.Dispose(disposing); + } + + // + /// called by PreProcessExecution to enable derived classes to take over execution + /// + /// + /// + /// + /// true if regular execution should take place, false if everything, + /// has been done by this function + /// + 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; + } + } +} diff --git a/src/Microsoft.SqlTools.ServiceLayer/Agent/Jobs/AgentOperator.cs b/src/Microsoft.SqlTools.ServiceLayer/Agent/Jobs/AgentOperatorData.cs similarity index 91% rename from src/Microsoft.SqlTools.ServiceLayer/Agent/Jobs/AgentOperator.cs rename to src/Microsoft.SqlTools.ServiceLayer/Agent/Jobs/AgentOperatorData.cs index c26ad534..c8433a4e 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Agent/Jobs/AgentOperator.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Agent/Jobs/AgentOperatorData.cs @@ -4,158 +4,15 @@ // using System; -using System.Collections; using System.Collections.Generic; -using System.ComponentModel; using System.Data; -using System.Diagnostics; -using System.Globalization; -using System.Threading; 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.SqlTools.ServiceLayer.Admin; using Microsoft.SqlTools.ServiceLayer.Agent.Contracts; using Microsoft.SqlTools.ServiceLayer.Management; namespace Microsoft.SqlTools.ServiceLayer.Agent { - /// - /// Agent Operators management class - /// - internal class AgentOperator : ManagementActionBase - { - private AgentOperatorInfo operatorInfo; - - AgentOperatorsData operatorsData = null; - - /// - /// Constructor - /// - 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); - } - } - - /// - /// Clean up any resources being used. - /// - protected override void Dispose(bool disposing) - { - if(disposing) - { - } - base.Dispose(disposing); - } - - public bool CreateOrUpdate() - { - this.operatorsData.ApplyChanges(this.operatorInfo); - return true; - } - } - - #region internal structures - /// - /// Provides data to be consumed in the job notification grid - /// - internal struct AgentJobNotificationHelper - { - /// - /// constructor - /// - /// job name - /// - /// - public AgentJobNotificationHelper(string name, CompletionAction notifyEmail, CompletionAction notifyPager) - { - this.Name = name; - this.NotifyEmail = notifyEmail; - this.NotifyPager = notifyPager; - } - /// - /// Name of the job - /// - public string Name; - /// - /// job email notification action - /// - public CompletionAction NotifyEmail; - /// - /// job pager notification action - /// - public CompletionAction NotifyPager; - } - /// - /// Provides data to be consumed in the alert notification grid - /// - internal struct AgentAlertNotificationHelper - { - /// - /// constructor - /// - /// Name of the alert - /// - /// - /// Alert object - public AgentAlertNotificationHelper(string name, bool notifyEmail, bool notifyPager, Alert alert) - { - this.Name = name; - this.NotifyEmail = notifyEmail; - this.NotifyPager = notifyPager; - this.Alert = alert; - } - /// - /// Alert name - /// - public string Name; - /// - /// Indicates whether the alert will notify the operator through email - /// - public bool NotifyEmail; - /// - /// Indicates whether the alert will notify the operator through pager - /// - public bool NotifyPager; - /// - /// Alert object. optimisation to stop us having to lookup the alert object when needed - /// - public Alert Alert; - } - #endregion /// /// Proxy class for the AgentOperators dialog and 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 /// /// Original operator name. Empty if we are creating a new operator /// - string originalOperatorName = String.Empty; + string originalOperatorName = string.Empty; /// /// Indicates whether we are creating an operator or not /// @@ -209,6 +66,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent /// will be null if the alert notifications have not been initialised /// IList alertNotifications; + /// /// will be null if the job notifications have not been initialised /// @@ -222,6 +80,19 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent #endregion #region properties + + /// + /// the current Operator SMO object + /// + public Operator Operator + { + get + { + JobServer jobServer = GetJobServer(); + return jobServer.Operators[this.originalOperatorName]; + } + } + /// /// indicates if the data is in create mode /// @@ -232,6 +103,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent return this.createMode; } } + /// /// name of the object /// @@ -248,6 +120,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent name = value; } } + /// /// Indicates if the dataobject is readonly /// @@ -275,6 +148,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent enabled = value; } } + /// /// email address of this operator /// @@ -291,6 +165,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent this.emailAddress = value; } } + /// /// pager address of this operator /// @@ -324,6 +199,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent this.pagerDays = value; } } + /// /// Weekday start time for this operator to be active /// @@ -340,6 +216,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent this.weekdayStartTime = value; } } + /// /// Weekday end time for this operator to be active /// @@ -356,6 +233,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent this.weekdayEndTime = value; } } + /// /// Saturday start time for this operator to be active /// @@ -372,6 +250,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent this.saturdayStartTime = value; } } + /// /// Saturday end time for this operator to be active /// @@ -388,6 +267,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent this.saturdayEndTime = value; } } + /// /// Sunday start time for this operator to be active /// @@ -404,6 +284,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent this.sundayStartTime = value; } } + /// /// Saturday end time for this operator to be active /// @@ -438,6 +319,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent this.alertNotifications = value; } } + /// /// Jobs that notify this operator. This has to be set through the jobs dialog and is read only /// @@ -463,6 +345,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent return this.lastEmailDate; } } + /// /// Date this operator was last paged /// @@ -480,7 +363,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent #region Constructors - public AgentOperatorsData(CDataContainer dataContainer, string operatorName) + public AgentOperatorsData(CDataContainer dataContainer, string operatorName, bool createMode) { if (dataContainer == null) { @@ -497,7 +380,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent this.originalOperatorName = operatorName; this.name = operatorName; - this.createMode = operatorName.Length == 0; + this.createMode = createMode; } #endregion @@ -541,6 +424,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent this.generalInitialized = true; } + /// /// 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. @@ -577,6 +461,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent } } } + /// /// Load alerts that notify this operator /// @@ -824,9 +709,9 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent /// private void LoadGeneralDefaults() { - name = String.Empty; - this.emailAddress = String.Empty; - this.pagerAddress = String.Empty; + name = string.Empty; + this.emailAddress = string.Empty; + this.pagerAddress = string.Empty; enabled = true; pagerDays = 0; @@ -835,6 +720,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent this.generalInitialized = true; } + /// /// Set job notification defaults. This is just an empty list /// @@ -842,6 +728,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent { this.jobNotifications = new List(); } + /// /// set the alert notification defaults. This list will contain all of the alerts /// @@ -858,6 +745,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent this.alertNotifications.Add(alertNotification); } } + /// /// load defaults for the history page /// @@ -878,9 +766,9 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent private JobServer GetJobServer() { JobServer jobServer = this.dataContainer.Server.JobServer; - if(jobServer == null) + if (jobServer == null) { - throw new ApplicationException("AgentOperatorsSR.JobServerIsNotAvailable"); + throw new ApplicationException(SR.JobServerIsNotAvailable); } return jobServer; } @@ -894,7 +782,6 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent private Operator GetCurrentOperator() { JobServer jobServer = GetJobServer(); - Operator currentOperator = jobServer.Operators[this.originalOperatorName]; this.createMode = (currentOperator == null); if (this.createMode) @@ -913,6 +800,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent { return new TimeSpan(dateTime.Hour, dateTime.Minute, dateTime.Second); } + /// /// /// @@ -944,4 +832,81 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent } #endregion } + +#region internal structures + /// + /// Provides data to be consumed in the job notification grid + /// + internal struct AgentJobNotificationHelper + { + /// + /// constructor + /// + /// job name + /// + /// + public AgentJobNotificationHelper(string name, CompletionAction notifyEmail, CompletionAction notifyPager) + { + this.Name = name; + this.NotifyEmail = notifyEmail; + this.NotifyPager = notifyPager; + } + + /// + /// Name of the job + /// + public string Name; + + /// + /// job email notification action + /// + public CompletionAction NotifyEmail; + + /// + /// job pager notification action + /// + public CompletionAction NotifyPager; + } + + /// + /// Provides data to be consumed in the alert notification grid + /// + internal struct AgentAlertNotificationHelper + { + /// + /// constructor + /// + /// Name of the alert + /// + /// + /// Alert object + public AgentAlertNotificationHelper(string name, bool notifyEmail, bool notifyPager, Alert alert) + { + this.Name = name; + this.NotifyEmail = notifyEmail; + this.NotifyPager = notifyPager; + this.Alert = alert; + } + + /// + /// Alert name + /// + public string Name; + + /// + /// Indicates whether the alert will notify the operator through email + /// + public bool NotifyEmail; + + /// + /// Indicates whether the alert will notify the operator through pager + /// + public bool NotifyPager; + + /// + /// Alert object. optimisation to stop us having to lookup the alert object when needed + /// + public Alert Alert; + } + #endregion } diff --git a/src/Microsoft.SqlTools.ServiceLayer/Agent/Jobs/JobHistoryItem.cs b/src/Microsoft.SqlTools.ServiceLayer/Agent/Jobs/JobHistoryItem.cs index 9730732b..0ca4be2b 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Agent/Jobs/JobHistoryItem.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Agent/Jobs/JobHistoryItem.cs @@ -64,7 +64,6 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent private ILogEntry m_currentEntry = null; private int m_index = 0; private bool m_isClosed = false; - private TypedColumnCollection columnTypes; private IServiceProvider serviceProvider = null; private static string historyTableDeclaration = "declare @tmp_sp_help_jobhistory table"; diff --git a/src/Microsoft.SqlTools.ServiceLayer/Agent/Jobs/JobStepsActions.cs b/src/Microsoft.SqlTools.ServiceLayer/Agent/Jobs/JobStepsActions.cs index e8208801..16f410b3 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Agent/Jobs/JobStepsActions.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Agent/Jobs/JobStepsActions.cs @@ -19,6 +19,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent { private JobStepData data; private JobData jobData; + private ConfigAction configAction; public JobStepsActions( CDataContainer dataContainer, @@ -26,17 +27,18 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent AgentJobStepInfo stepInfo, ConfigAction configAction) { + this.configAction = configAction; this.DataContainer = dataContainer; this.jobData = jobData; - if (configAction == ConfigAction.Update) + if (configAction == ConfigAction.Create) { - JobStep jobStep = GetJobStep(this.jobData, stepInfo.StepName); - this.data = new JobStepData(jobStep, jobData.JobSteps); + this.data = new JobStepData(jobData.JobSteps); } 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 @@ -48,27 +50,36 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent protected override bool DoPreProcessExecution(RunType runType, out ExecutionMode executionResult) { base.DoPreProcessExecution(runType, out executionResult); - - // Make sure the job step name is not blank. - if (this.data.Name == null || this.data.Name.Length == 0) + if (this.configAction == ConfigAction.Drop) { - throw new Exception(SR.JobStepNameCannotBeBlank); - } - - // 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) + if (this.data.JobStep != null) { - // Throw an error if the job step name already exists - throw new Exception(SR.JobStepNameAlreadyExists(this.data.Name)); + this.data.JobStep.DropIfExists(); } } + 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) - { - this.data.ApplyChanges(this.jobData.Job); + // 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 + throw new Exception(SR.JobStepNameAlreadyExists(this.data.Name)); + } + } + + if (runType == RunType.RunNow) + { + this.data.ApplyChanges(this.jobData.Job); + } } // regular execution always takes place diff --git a/src/Microsoft.SqlTools.ServiceLayer/Agent/Jobs/ScheduleData.cs b/src/Microsoft.SqlTools.ServiceLayer/Agent/Jobs/ScheduleData.cs index 12f13e80..815ef299 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Agent/Jobs/ScheduleData.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Agent/Jobs/ScheduleData.cs @@ -7,7 +7,6 @@ using System; using System.Collections; using System.ComponentModel; using System.Diagnostics; -using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.Text; using System.Text.RegularExpressions; @@ -16,6 +15,7 @@ using Microsoft.SqlServer.Management.Diagnostics; using Microsoft.SqlServer.Management.Sdk.Sfc; using Microsoft.SqlServer.Management.Smo; using Microsoft.SqlServer.Management.Smo.Agent; +using Microsoft.SqlTools.ServiceLayer.Management; namespace Microsoft.SqlTools.ServiceLayer.Agent { @@ -30,16 +30,16 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent #endregion #region private struct members - private String name; - private String description; - private System.Int32 id; - private System.Int32 activeEndDate; - private System.Int32 activeEndTimeOfDay; - private System.Int32 activeStartDate; - private System.Int32 activeStartTimeOfDay; - private System.Int32 frequencyInterval; - private System.Int32 frequencyRecurrenceFactor; - private System.Int32 frequencySubDayInterval; + private string name; + private string description; + private int id; + private int activeEndDate; + private int activeEndTimeOfDay; + private int activeStartDate; + private int activeStartTimeOfDay; + private int frequencyInterval; + private int frequencyRecurrenceFactor; + private int frequencySubDayInterval; private FrequencyTypes frequencyTypes; private FrequencySubDayTypes frequencySubDayTypes; private FrequencyRelativeIntervals frequencyRelativeIntervals; @@ -289,7 +289,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent { if (this.FrequencyInterval == 0) { - return String.Empty; + return string.Empty; } StringBuilder daysOfWeek = new StringBuilder(); @@ -347,7 +347,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent { get { - string format = String.Empty; + string format = string.Empty; switch (this.FrequencyTypes) { @@ -508,43 +508,43 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent #endregion #region public properties - public System.Int32 ActiveEndDate + public int ActiveEndDate { get { return activeEndDate; } set { activeEndDate = value; } } - public System.Int32 ActiveEndTimeOfDay + public int ActiveEndTimeOfDay { get { return activeEndTimeOfDay; } set { activeEndTimeOfDay = value; } } - public System.Int32 ActiveStartDate + public int ActiveStartDate { get { return activeStartDate; } set { activeStartDate = value; } } - public System.Int32 ActiveStartTimeOfDay + public int ActiveStartTimeOfDay { get { return activeStartTimeOfDay; } set { activeStartTimeOfDay = value; } } - public System.Int32 FrequencyInterval + public int FrequencyInterval { get { return frequencyInterval; } set { frequencyInterval = value; } } - public System.Int32 FrequencyRecurrenceFactor + public int FrequencyRecurrenceFactor { get { return frequencyRecurrenceFactor; } set { frequencyRecurrenceFactor = value; } } - public System.Int32 FrequencySubDayInterval + public int FrequencySubDayInterval { get { return frequencySubDayInterval; } set { frequencySubDayInterval = value; } @@ -592,7 +592,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent } } - public System.Int32 ID + public int ID { get { return id; } set { id = value; } @@ -1147,16 +1147,16 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent if (jobSchedules != null && version.Major < 9) { - ///Check to see if a duplicate job schedule name has been entered. This condition is permissable - ///in SQL 9, but not in previous versions. + // Check to see if a duplicate job schedule name has been entered. This condition is permissable + // in SQL 9, but not in previous versions. 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 - //name. + // If the schedule name matches an existing job, throw an error and ask user to enter another + // name. if (((JobScheduleData)jobSchedules[index]).Name == this.Name && this.currentName != this.originalName) { - sbError.Append("SRError.ScheduleNameAlreadyExists(this.Name)" + "\n"); + sbError.Append(SR.ScheduleNameAlreadyExists(this.Name) + "\n"); break; } } @@ -1165,40 +1165,39 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent // weekly schdule - ensure that the start date is less than the end date 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) { - //Check to make sure that the start time is greater than the baseline - //date of 01/01/1990 + // Check to make sure that the start time is greater than the baseline + // date of 01/01/1990 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 && this.FrequencyTypes != FrequencyTypes.OnIdle) { - //Check to make sure that the start time is greater than the baseline - //date of 01/01/1990 + // Check to make sure that the start time is greater than the baseline + // date of 01/01/1990 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) { - sbError.Append("SRError.EndTimeEqualToStartTime" + "\n"); + sbError.Append(SR.EndTimeEqualToStartTime + "\n"); } - } // weekly schedule - at least one day should be selected @@ -1206,12 +1205,10 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent { 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 if (sbError.ToString().Length > 0) { @@ -1243,6 +1240,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent this.alreadyCreated = false; } } + /// /// Provide context to create a new schedule. /// @@ -1259,6 +1257,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent { this.source = schedule; } + public override string ToString() { return this.GetSimpleJobDescription(); @@ -1322,6 +1321,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent this.alreadyCreated = false; } } + /// /// set defaults assuming no parent. /// @@ -1362,14 +1362,14 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent #region static constants /// - /// Maximum date supported by SSMS. - /// This is the same as the culture max date because SQl Agent range is larger than all cultures' ranges. + /// Maximum date supported + /// This is the same as the culture max date because SQL Agent range is larger than all cultures' ranges. /// public static DateTime MaxAgentDateValue { get { - return DateTime.Now; // Utils.GetMaxCultureDateTime().Date; + return Utils.GetMaxCultureDateTime().Date; } } /// diff --git a/src/Microsoft.SqlTools.ServiceLayer/Agent/Jobs/ScheduleScriptExecution.cs b/src/Microsoft.SqlTools.ServiceLayer/Agent/Jobs/ScheduleScriptExecution.cs index b793877f..80c00198 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Agent/Jobs/ScheduleScriptExecution.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Agent/Jobs/ScheduleScriptExecution.cs @@ -1,3 +1,4 @@ +#if false // // Copyright (c) Microsoft. All rights reserved. // 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 } } +#endif \ No newline at end of file diff --git a/src/Microsoft.SqlTools.ServiceLayer/Agent/Jobs/SqlServerAgentPropertiesAdvanced.cs b/src/Microsoft.SqlTools.ServiceLayer/Agent/Jobs/SqlServerAgentPropertiesAdvanced.cs index 14377e0a..11d847cc 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Agent/Jobs/SqlServerAgentPropertiesAdvanced.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Agent/Jobs/SqlServerAgentPropertiesAdvanced.cs @@ -1,3 +1,4 @@ +#if false // // Copyright (c) Microsoft. All rights reserved. // 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 \ No newline at end of file diff --git a/src/Microsoft.SqlTools.ServiceLayer/Agent/Jobs/SqlServerAgentPropertiesAlertSystem.cs b/src/Microsoft.SqlTools.ServiceLayer/Agent/Jobs/SqlServerAgentPropertiesAlertSystem.cs index 40237721..9898b665 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Agent/Jobs/SqlServerAgentPropertiesAlertSystem.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Agent/Jobs/SqlServerAgentPropertiesAlertSystem.cs @@ -1,3 +1,4 @@ +#if false // // Copyright (c) Microsoft. All rights reserved. // 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 } } +#endif \ No newline at end of file diff --git a/src/Microsoft.SqlTools.ServiceLayer/Agent/Jobs/SqlServerAgentPropertiesConnection.cs b/src/Microsoft.SqlTools.ServiceLayer/Agent/Jobs/SqlServerAgentPropertiesConnection.cs index 702f8a59..7534fcbf 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Agent/Jobs/SqlServerAgentPropertiesConnection.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Agent/Jobs/SqlServerAgentPropertiesConnection.cs @@ -1,3 +1,4 @@ +#if false // // Copyright (c) Microsoft. All rights reserved. // 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 } } +#endif \ No newline at end of file diff --git a/src/Microsoft.SqlTools.ServiceLayer/Agent/Jobs/SqlServerAgentPropertiesGeneral.cs b/src/Microsoft.SqlTools.ServiceLayer/Agent/Jobs/SqlServerAgentPropertiesGeneral.cs index 7bf13f24..3df27080 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Agent/Jobs/SqlServerAgentPropertiesGeneral.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Agent/Jobs/SqlServerAgentPropertiesGeneral.cs @@ -1,3 +1,4 @@ +#if false // // Copyright (c) Microsoft. All rights reserved. // 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 \ No newline at end of file diff --git a/src/Microsoft.SqlTools.ServiceLayer/Agent/Jobs/SqlServerAgentPropertiesHistory.cs b/src/Microsoft.SqlTools.ServiceLayer/Agent/Jobs/SqlServerAgentPropertiesHistory.cs index 6718a525..2e0857aa 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Agent/Jobs/SqlServerAgentPropertiesHistory.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Agent/Jobs/SqlServerAgentPropertiesHistory.cs @@ -1,3 +1,4 @@ +#if false // // Copyright (c) Microsoft. All rights reserved. // 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 } } +#endif \ No newline at end of file diff --git a/src/Microsoft.SqlTools.ServiceLayer/Agent/Jobs/SqlServerAgentPropertiesJobSystem.cs b/src/Microsoft.SqlTools.ServiceLayer/Agent/Jobs/SqlServerAgentPropertiesJobSystem.cs index 19b9052f..93c9a559 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Agent/Jobs/SqlServerAgentPropertiesJobSystem.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Agent/Jobs/SqlServerAgentPropertiesJobSystem.cs @@ -1,3 +1,4 @@ +#if false // // Copyright (c) Microsoft. All rights reserved. // 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 /// 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 private void ApplyChanges() @@ -148,11 +138,4 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent #endregion } } - - - - - - - - +#endif \ No newline at end of file diff --git a/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.cs b/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.cs index a58767e3..c128241a 100755 --- a/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.cs @@ -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) { return Keys.GetString(Keys.ConnectionServiceListDbErrorNotConnected, uri); @@ -4594,6 +4666,11 @@ namespace Microsoft.SqlTools.ServiceLayer return Keys.GetString(Keys.JobStepNameAlreadyExists, jobName); } + public static string ScheduleNameAlreadyExists(string scheduleName) + { + return Keys.GetString(Keys.ScheduleNameAlreadyExists, scheduleName); + } + [System.Runtime.CompilerServices.CompilerGeneratedAttribute()] public class Keys { @@ -6369,6 +6446,36 @@ namespace Microsoft.SqlTools.ServiceLayer 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() { } diff --git a/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.resx b/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.resx index 402d1d77..99bf277d 100755 --- a/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.resx +++ b/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.resx @@ -2522,4 +2522,45 @@ . Parameters: 0 - jobName (string) + + The name of the alert cannot be blank. + + + + Cannot create new alert. + + + + Cannot alter alert. + + + + Invalid Schedule + Schedule error message + + + Select at least one day to be part of this weekly schedule. + + + + The job schedule starting date cannot be greater than the ending date. + + + + The job schedule starting time cannot be after the ending time. + + + + The job schedule ending time must be after the starting time. + + + + Start date must be on or after January 1, 1990. + + + + There is already a schedule named '{0}' for this job. You must specify a different name. + . + Parameters: 0 - scheduleName (string) + diff --git a/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.strings b/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.strings index 9e0b4c20..c46dc8ec 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.strings +++ b/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.strings @@ -888,18 +888,6 @@ InvalidPathError = Cannot access the specified path on the server: {0} # Profiler ProfilerConnectionNotFound = Connection not found - - - - - - - - - - - - ############################################################################# # SQL Agent EnableAlertsTitle(String serverName) = Enable Alerts - {0} @@ -1016,8 +1004,6 @@ CannotCreateInitializeHistoryPage = Cannot create/initialize History page. ; Exception throw when dialog cannot refresh operator CannotResetOperator = Cannot reset operator. - -# ; Name of label on notifications page AlertList = Alert list: ; Name of label on notifications page @@ -1043,7 +1029,6 @@ CannotModifyAlerts = Cannot modify alerts. ; Exception thrown when we cannot create script that modify alerts CannotCreateScriptForModifyAlerts = Cannot create script for modify alerts. - ;job categories CategoryLocal = [Uncategorized (Local)] 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. 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. \ No newline at end of file +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. \ No newline at end of file diff --git a/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.xlf b/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.xlf index 58c5ff15..4c0f2dea 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.xlf +++ b/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.xlf @@ -2995,6 +2995,57 @@ . Parameters: 0 - jobName (string) + + The name of the alert cannot be blank. + The name of the alert cannot be blank. + + + + Cannot create new alert. + Cannot create new alert. + + + + Cannot alter alert. + Cannot alter alert. + + + + Invalid Schedule + Invalid Schedule + Schedule error message + + + Select at least one day to be part of this weekly schedule. + Select at least one day to be part of this weekly schedule. + + + + The job schedule starting date cannot be greater than the ending date. + The job schedule starting date cannot be greater than the ending date. + + + + The job schedule starting time cannot be after the ending time. + The job schedule starting time cannot be after the ending time. + + + + The job schedule ending time must be after the starting time. + The job schedule ending time must be after the starting time. + + + + Start date must be on or after January 1, 1990. + Start date must be on or after January 1, 1990. + + + + There is already a schedule named '{0}' for this job. You must specify a different name. + There is already a schedule named '{0}' for this job. You must specify a different name. + . + Parameters: 0 - scheduleName (string) + \ No newline at end of file diff --git a/src/Microsoft.SqlTools.ServiceLayer/Management/Common/Utils.cs b/src/Microsoft.SqlTools.ServiceLayer/Management/Common/Utils.cs index b5db08d8..a64db0b3 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Management/Common/Utils.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Management/Common/Utils.cs @@ -261,6 +261,21 @@ namespace Microsoft.SqlTools.ServiceLayer.Management { return "[" + s.Replace("]", "]]") + "]"; } + + /// + /// 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 + /// + /// + public static DateTime GetMaxCultureDateTime() + { + CultureInfo currentCulture = System.Threading.Thread.CurrentThread.CurrentCulture; + return currentCulture.DateTimeFormat.Calendar.MaxSupportedDateTime; + } } /// diff --git a/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/Agent/AgentAlertTests.cs b/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/Agent/AgentAlertTests.cs index 3acb5c17..70c219ef 100644 --- a/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/Agent/AgentAlertTests.cs +++ b/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/Agent/AgentAlertTests.cs @@ -3,21 +3,11 @@ // 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 Microsoft.SqlServer.Management.Smo; -using Microsoft.SqlServer.Management.XEvent; using Microsoft.SqlTools.Hosting.Protocol; using Microsoft.SqlTools.ServiceLayer.Agent; using Microsoft.SqlTools.ServiceLayer.Agent.Contracts; -using Microsoft.SqlTools.ServiceLayer.Connection; 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.Utility; using Moq; @@ -53,43 +43,44 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.Agent /// /// Verify the default "create agent alert" request handler with valid parameters /// - // TODO: Fix flaky test. See https://github.com/Microsoft/sqltoolsservice/issues/630 - // [Fact] + [Fact] public async Task TestHandleCreateAgentAlertsRequest() { using (SelfCleaningTempFile queryTempFile = new SelfCleaningTempFile()) { - var connectionResult = await LiveConnectionHelper.InitLiveConnectionInfoAsync("master", queryTempFile.FilePath); + // setup + var createContext = new Mock>(); + var deleteContext = new Mock>(); - var requestParams = new CreateAgentAlertParams + var service = new AgentService(); + var alert = new AgentAlertInfo() { - OwnerUri = connectionResult.ConnectionInfo.OwnerUri, - Alert = new AgentAlertInfo() - { - JobName = "Test Job Name" - } + JobName = "test_update_job", + AlertType = AlertType.SqlServerEvent, + Severity = 1 }; - var requestContext = new Mock>(); + 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(); - await service.HandleCreateAgentAlertRequest(requestParams, requestContext.Object); + // test + await service.HandleCreateAgentAlertRequest(new CreateAgentAlertParams + { + OwnerUri = connectionResult.ConnectionInfo.OwnerUri, + Alert = alert + }, createContext.Object); + createContext.VerifyAll(); - // var agentAlerts = await AgentTestUtils.GetAgentAlerts(connectionResult.ConnectionInfo.OwnerUri); - // if (agentAlerts != null && agentAlerts.Length > 0) - // { - // foreach (var agentAlert in agentAlerts) - // { - // if (agentAlert.JobName.Equals(alert.JobName)) - // { - // await service.HandleDeleteAgentAlertRequest(new DeleteAgentAlertParams() - // { - // OwnerUri = connectionResult.ConnectionInfo.OwnerUri, - // Alert = alert - // }, deleteContext.Object); - // } - // } - // } + // cleanup + 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()) { + // setup var createContext = new Mock>(); var updateContext = new Mock>(); var deleteContext = new Mock>(); @@ -126,21 +118,21 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.Agent Alert = alert }, createContext.Object); + // test + alert.Severity = 2; await service.HandleUpdateAgentAlertRequest(new UpdateAgentAlertParams() { OwnerUri = connectionResult.ConnectionInfo.OwnerUri, Alert = alert }, updateContext.Object); + updateContext.VerifyAll(); + // cleanup await service.HandleDeleteAgentAlertRequest(new DeleteAgentAlertParams() { OwnerUri = connectionResult.ConnectionInfo.OwnerUri, Alert = alert }, deleteContext.Object); - - createContext.VerifyAll(); - updateContext.VerifyAll(); - deleteContext.VerifyAll(); } } } diff --git a/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/Agent/AgentJobStepTests.cs b/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/Agent/AgentJobStepTests.cs index 80a4d2d8..225ba692 100644 --- a/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/Agent/AgentJobStepTests.cs +++ b/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/Agent/AgentJobStepTests.cs @@ -64,8 +64,33 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.Agent await AgentTestUtils.UpdateAgentJobStep(service, connectionResult, stepInfo); // cleanup - await AgentTestUtils.DeleteAgentJob(service, connectionResult, job, verify: false); + await AgentTestUtils.DeleteAgentJob(service, connectionResult, job, verify: false); } } + + /// + /// TestHandleDeleteAgentJobRequest + /// + [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); + } + } } } diff --git a/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/Agent/AgentOperatorTests.cs b/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/Agent/AgentOperatorTests.cs index 34460540..adb62f7d 100644 --- a/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/Agent/AgentOperatorTests.cs +++ b/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/Agent/AgentOperatorTests.cs @@ -16,34 +16,69 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.Agent { public class AgentOperatorTests { + /// + /// Verify the default "create agent alert" request handler with valid parameters + /// + [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); + } + } /// - /// Verify the default "update agent alert" request handler with valid parameters + /// TestHandleUpdateAgentOperatorRequest /// - //[Fact] + [Fact] public async Task TestHandleUpdateAgentOperatorRequest() { using (SelfCleaningTempFile queryTempFile = new SelfCleaningTempFile()) { - var createContext = new Mock>(); - + // setup var service = new AgentService(); - var operatorInfo = new AgentOperatorInfo() - { - Id = 10, - Name = "Joe DBA", - EmailAddress = "test@aol.com" - }; - + var operatorInfo = AgentTestUtils.GetTestOperatorInfo(); 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 - { - OwnerUri = connectionResult.ConnectionInfo.OwnerUri, - Operator = operatorInfo - }, createContext.Object); + // test + operatorInfo.EmailAddress = "updated@email.com"; + await AgentTestUtils.UpdateAgentOperator(service, connectionResult, operatorInfo); - createContext.VerifyAll(); + // cleanup + await AgentTestUtils.DeleteAgentOperator(service, connectionResult, operatorInfo); + } + } + + /// + /// TestHandleDeleteAgentOperatorRequest + /// + [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); } } } diff --git a/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/Agent/AgentTestUtils.cs b/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/Agent/AgentTestUtils.cs index 98d015fd..f897187f 100644 --- a/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/Agent/AgentTestUtils.cs +++ b/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/Agent/AgentTestUtils.cs @@ -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( AgentService service, TestConnectionResult connectionResult, @@ -135,6 +145,62 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.Agent context.VerifyAll(); } + internal static async Task DeleteAgentJobStep( + AgentService service, + TestConnectionResult connectionResult, + AgentJobStepInfo stepInfo) + { + var context = new Mock>(); + 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>(); + 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>(); + 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>(); + await service.HandleDeleteAgentOperatorRequest(new DeleteAgentOperatorParams + { + OwnerUri = connectionResult.ConnectionInfo.OwnerUri, + Operator = operatorInfo + }, context.Object); + context.VerifyAll(); + } + internal static async Task GetAgentAlerts(string connectionUri) { var requestParams = new AgentAlertsParams()