public HttpResponseMessage Post(ScriptJobDescriptor descriptor)
        {
            if (!ModelState.IsValid)
                return Request.CreateResponse(HttpStatusCode.BadRequest, this.GetValidationErrorMessages());

            var result = _scriptExecutionService.ExecuteScript(descriptor);

            return Request.CreateResponse(HttpStatusCode.OK, result);
        }
        public ScriptExecutionResult ExecuteScript(ScriptJobDescriptor descriptor)
        {
            var result = new ScriptExecutionResult();

            try
            {
                var scriptType = descriptor.ScriptType.ToEnum<ScriptType>();
                var scriptBody = descriptor.ScriptBody;

                if (descriptor.RemoteExecution)
                {
                    if (!descriptor.TargetID.HasValue)
                        throw new Exception("Target not specified.");
                    var target = _targetService.GetByKey(descriptor.TargetID.Value);

                    result.Output = this.ExecuteScriptRemotely(scriptBody, scriptType,
                        target.ComputerName, target.PortNumber, target.TargetKey);
                }
                else
                {
                    result.Output = this.ExecuteScriptLocally(scriptBody, scriptType);
                }

                result.IsSuccessful = this.IsSuccessful(descriptor, result.Output);
            }
            catch (Exception ex)
            {
                Log.Exception(ex);

                foreach (var error in ex.GetExceptionTreeAsFlatList())
                {
                    result.Output += error.Message + Environment.NewLine;
                    result.Output += error.StackTrace;
                }
            }

            return result;
        }
        private void ExecuteDeploymentSteps(DeploymentJob job)
        {
            var planSteps = _deploymentPlanStepService.GetEnabledForDeploymentPlan(job.DeploymentPlanID)
                .OrderBy(s => s.ExecutionOrder)
                .ToList();

            if (planSteps.IsNullOrEmpty())
                return;

            var targetGroupIDs = _targetGroupService.GetAllForProject(job.ProjectID)
                .OrderBy(g => g.Name)
                .Select(g => g.TargetGroupID)
                .ToArray();

            var environmentName = _projectEnvironmentService.GetByKey(job.ProjectEnvironmentID)
                .Name;

            foreach (var planStep in planSteps)
            {
                var jobStep = new DeploymentJobStep
                    {
                        DeploymentJobID = job.DeploymentJobID,
                        DeploymentPlanStepID = planStep.DeploymentPlanStepID,
                        Status = DeploymentStatus.Running,
                        StartTime = DateTime.UtcNow,
                        ExecutionReference = Guid.NewGuid()
                    };
                _deploymentJobStepService.Insert(jobStep);

                try
                {
                    var script = _scriptService.GetWithParameters(planStep.ScriptID);

                    if (planStep.AllTargetGroups)
                    {
                        this.ExecuteDeploymentStepOnTargets(script, planStep, job, environmentName,
                            jobStep.DeploymentJobStepID, targetGroupIDs);
                    }
                    else if (planStep.TargetGroupID.HasValue)
                    {
                        this.ExecuteDeploymentStepOnTargets(script, planStep, job, environmentName,
                            jobStep.DeploymentJobStepID, planStep.TargetGroupID.Value);
                    }
                    else  // Execute on deployment server
                    {
                        jobStep.ExecutedScript = _variableService.ResolveVariables(
                            script, planStep, job, environmentName);
                        jobStep.ExecutionOutput = "Waiting for output...";
                        _deploymentJobStepService.Update(jobStep);

                        var descriptor = new ScriptJobDescriptor
                            {
                                ScriptType = script.ScriptType,
                                ScriptBody = jobStep.ExecutedScript,
                                SuccessKeywords = script.SuccessKeywords,
                                FailureKeywords = script.FailureKeywords
                            };
                        var result = _scriptExecutionService.ExecuteScript(descriptor);

                        jobStep.ExecutionOutput = result.Output;
                        if (!result.IsSuccessful)
                            throw new Exception("Script execution on deployment server was not successful.");
                    }

                    jobStep.Status = DeploymentStatus.Finished;
                }
                catch (Exception ex)
                {
                    jobStep.Status = DeploymentStatus.Failed;
                    throw new Exception("Deployment step [{0}] failed.".FormatString(planStep.Name), ex);
                }
                finally
                {
                    jobStep.EndTime = DateTime.UtcNow;
                    _deploymentJobStepService.Update(jobStep);
                }
            }
        }
        private void ExecuteDeploymentStepOnTargets(
            Script script, DeploymentPlanStep planStep, DeploymentJob job, string environmentName,
            int deploymentJobStepID, params short[] targetGroupIDs)
        {
            foreach (var targetGroupID in targetGroupIDs)
            {
                var targetGroupEnvironmentID = _targetGroupEnvironmentService
                    .GetCombinationID(targetGroupID, job.ProjectEnvironmentID);

                var projectTargets = _projectTargetService
                    .GetAllForTargetGroupAndEnvironment(targetGroupID, job.ProjectEnvironmentID)
                    .OrderBy(t => t.Target.Name)
                    .ToList();

                foreach (var projectTarget in projectTargets)
                {
                    var targetID = projectTarget.TargetID;

                    var jobStepTarget = new DeploymentJobStepTarget
                    {
                        DeploymentJobStepID = deploymentJobStepID,
                        TargetID = targetID,
                        Status = DeploymentStatus.Running,
                        StartTime = DateTime.UtcNow,
                        ExecutionReference = Guid.NewGuid()
                    };
                    _deploymentJobStepTargetService.Insert(jobStepTarget);

                    var target = _targetService.GetWithCredential(targetID);

                    try
                    {
                        var username = target.UsernameWithDomain;
                        var password = _credentialService.DecryptPassword(target.Credential.Password);
                        var tempPassword = Guid.NewGuid().ToString();

                        var scriptBody = _variableService.ResolveVariables(script, planStep, job, environmentName,
                            targetGroupID, targetGroupEnvironmentID, projectTarget.ProjectTargetID,
                            target.ComputerName, username, tempPassword);

                        // Don't log real password.
                        jobStepTarget.ExecutedScript = scriptBody.Replace(tempPassword, "**********");
                        jobStepTarget.ExecutionOutput = "Waiting for output...";
                        _deploymentJobStepTargetService.Update(jobStepTarget);

                        scriptBody = scriptBody.Replace(tempPassword, password);

                        var descriptor = new ScriptJobDescriptor
                        {
                            ScriptType = script.ScriptType,
                            ScriptBody = scriptBody,
                            SuccessKeywords = script.SuccessKeywords,
                            FailureKeywords = script.FailureKeywords,
                            RemoteExecution = planStep.RemoteExecution,
                            TargetID = target.TargetID
                        };
                        var result = _scriptExecutionService.ExecuteScript(descriptor);

                        jobStepTarget.ExecutionOutput = result.Output;
                        if (!result.IsSuccessful)
                            throw new Exception("Script execution on target [{0}] was not successful."
                                .FormatString(target.Name));

                        jobStepTarget.Status = DeploymentStatus.Finished;
                    }
                    catch (Exception ex)
                    {
                        jobStepTarget.Status = DeploymentStatus.Failed;
                        throw new Exception("Deployment step [{0}] failed for target [{1}]."
                            .FormatString(planStep.Name, target.Name), ex);
                    }
                    finally
                    {
                        jobStepTarget.EndTime = DateTime.UtcNow;
                        _deploymentJobStepTargetService.Update(jobStepTarget);
                    }
                }
            }
        }
        private bool IsSuccessful(ScriptJobDescriptor descriptor, string output)
        {
            if (!output.IsNullOrWhiteSpace())
                output = output.ToUpperInvariant();  // Prepare for case-insensitive comparison.

            var isSuccessful = true;

            if (!descriptor.SuccessKeywords.IsNullOrWhiteSpace())
            {
                isSuccessful = false;  // We'll have to prove it's successful.

                if (!output.IsNullOrWhiteSpace())
                {
                    var lines = this.PrepareLines(descriptor.SuccessKeywords);
                    if (!lines.IsNullOrEmpty())
                    {
                        if ((descriptor.SuccessKeywordsAllRequired && lines.All(l => output.Contains(l)))
                            || (!descriptor.SuccessKeywordsAllRequired && lines.Any(l => output.Contains(l))))
                        {
                            isSuccessful = true;
                        }
                    }
                }
            }

            if (!descriptor.FailureKeywords.IsNullOrWhiteSpace()
                && !output.IsNullOrWhiteSpace())
            {
                var lines = this.PrepareLines(descriptor.FailureKeywords);
                if (!lines.IsNullOrEmpty())
                {
                    if ((descriptor.FailureKeywordsAllRequired && lines.All(l => output.Contains(l)))
                        || (!descriptor.FailureKeywordsAllRequired && lines.Any(l => output.Contains(l))))
                    {
                        isSuccessful = false;
                    }
                }
            }

            return isSuccessful;
        }