public string Execute(Recipe recipe) { if (recipe == null) { throw new ArgumentNullException("recipe"); } if (!recipe.RecipeSteps.Any()) { Logger.Information("Recipe '{0}' contains no steps. No work has been scheduled."); return null; } var executionId = Guid.NewGuid().ToString("n"); ThreadContext.Properties["ExecutionId"] = executionId; try { Logger.Information("Executing recipe '{0}'.", recipe.Name); _recipeExecuteEventHandler.ExecutionStart(executionId, recipe); foreach (var recipeStep in recipe.RecipeSteps) { _recipeStepQueue.Enqueue(executionId, recipeStep); _recipeStepResultRecordRepository.Create(new RecipeStepResultRecord { ExecutionId = executionId, RecipeName = recipe.Name, StepId = recipeStep.Id, StepName = recipeStep.Name }); } _recipeScheduler.ScheduleWork(executionId); return executionId; } finally { ThreadContext.Properties["ExecutionId"] = null; } }
public RecipeComparisonResult Compare(Recipe left, Recipe right, Func<XElement, XElement, bool> comparison) { var leftParts = left.RecipeSteps.Where(s => s.Name == "Data").SingleOrDefault().Step.Elements(); var rightParts = right.RecipeSteps.Where(s => s.Name == "Data").SingleOrDefault().Step.Elements(); var matching = new List<ContentPair>(); var unmatched = new List<ContentPair>(); bool matched = false; // enumerate content items for (int leftIndex = 0; leftIndex < leftParts.Count(); leftIndex++) { matched = false; var leftPart = leftParts.ElementAt(leftIndex); for (int rightIndex = 0; rightIndex < rightParts.Count(); rightIndex++) { var rightPart = rightParts.ElementAt(rightIndex); if (comparison(leftPart, rightPart)) { matching.Add(new ContentPair(leftPart, rightPart)); matched = true; } } if (!matched) { unmatched.Add(new ContentPair(leftPart, null)); } } unmatched.AddRange( rightParts.Where(part => !matching.Any(pair => pair.Right == part)) .Select(part => new ContentPair(null, part))); return new RecipeComparisonResult(matching, unmatched); }
public Recipe ParseRecipe(string recipeText) { var recipe = new Recipe(); try { var recipeSteps = new List<RecipeStep>(); TextReader textReader = new StringReader(recipeText); var recipeTree = XElement.Load(textReader, LoadOptions.PreserveWhitespace); textReader.Close(); foreach (var element in recipeTree.Elements()) { // Recipe mETaDaTA if (element.Name.LocalName == "Recipe") { foreach (var metadataElement in element.Elements()) { switch (metadataElement.Name.LocalName) { case "Name": recipe.Name = metadataElement.Value; break; case "Description": recipe.Description = metadataElement.Value; break; case "Author": recipe.Author = metadataElement.Value; break; case "WebSite": recipe.WebSite = metadataElement.Value; break; case "Version": recipe.Version = metadataElement.Value; break; case "IsSetupRecipe": recipe.IsSetupRecipe = !string.IsNullOrEmpty(metadataElement.Value) ? bool.Parse(metadataElement.Value) : false; break; case "ExportUtc": recipe.ExportUtc = !string.IsNullOrEmpty(metadataElement.Value) ? (DateTime?)XmlConvert.ToDateTime(metadataElement.Value, XmlDateTimeSerializationMode.Utc) : null; break; case "Tags": recipe.Tags = metadataElement.Value; break; default: Logger.Error("Unrecognized recipe metadata element {0} encountered. Skipping.", metadataElement.Name.LocalName); break; } } } // Recipe step else { var recipeStep = new RecipeStep { Name = element.Name.LocalName, Step = element }; recipeSteps.Add(recipeStep); } } recipe.RecipeSteps = recipeSteps; } catch (Exception exception) { Logger.Error(exception, "Parsing recipe failed. Recipe text was: {0}.", recipeText); throw; } return recipe; }
public string Execute(Recipe recipe) { var executionId = _recipeManager.Execute(recipe); // Only need to update the shell if work was actually done. if(executionId != null) UpdateShell(); return executionId; }
public Recipe ParseRecipe(XDocument recipeDocument) { var recipe = new Recipe(); var recipeSteps = new List<RecipeStep>(); var stepId = 0; foreach (var element in recipeDocument.Root.Elements()) { // Recipe metadata. if (element.Name.LocalName == "Recipe") { foreach (var metadataElement in element.Elements()) { switch (metadataElement.Name.LocalName) { case "Name": recipe.Name = metadataElement.Value; break; case "Description": recipe.Description = metadataElement.Value; break; case "Author": recipe.Author = metadataElement.Value; break; case "WebSite": recipe.WebSite = metadataElement.Value; break; case "Version": recipe.Version = metadataElement.Value; break; case "IsSetupRecipe": recipe.IsSetupRecipe = !string.IsNullOrEmpty(metadataElement.Value) ? bool.Parse(metadataElement.Value) : false; break; case "ExportUtc": recipe.ExportUtc = !string.IsNullOrEmpty(metadataElement.Value) ? (DateTime?)XmlConvert.ToDateTime(metadataElement.Value, XmlDateTimeSerializationMode.Utc) : null; break; case "Category": recipe.Category = metadataElement.Value; break; case "Tags": recipe.Tags = metadataElement.Value; break; default: Logger.Warning("Unrecognized recipe metadata element '{0}' encountered; skipping.", metadataElement.Name.LocalName); break; } } } // Recipe step. else { var recipeStep = new RecipeStep(id: (++stepId).ToString(CultureInfo.InvariantCulture), recipeName: recipe.Name, name: element.Name.LocalName, step: element ); recipeSteps.Add(recipeStep); } } recipe.RecipeSteps = recipeSteps; return recipe; }
private void EnqueueRecipe(string executionId, Recipe recipe) { foreach (var recipeStep in recipe.RecipeSteps) { _recipeStepQueue.Enqueue(executionId, recipeStep); _recipeStepResultRecordRepository.Create(new RecipeStepResultRecord { ExecutionId = executionId, RecipeName = recipe.Name, StepId = recipeStep.Id, StepName = recipeStep.Name }); } }
public string Execute(Recipe recipe) { if (recipe == null) return null; var executionId = Guid.NewGuid().ToString("n"); _recipeJournal.ExecutionStart(executionId); foreach (var recipeStep in recipe.RecipeSteps) { _recipeStepQueue.Enqueue(executionId, recipeStep); } _recipeScheduler.ScheduleWork(executionId); return executionId; }
public ActionResult InstallPackageDetailsPOST(PackagingInstallViewModel packagingInstallViewModel, string redirectUrl) { if (_shellSettings.Name != ShellSettings.DefaultName || !Services.Authorizer.Authorize(StandardPermissions.SiteOwner, T("Not authorized to add sources"))) return new HttpUnauthorizedResult(); try { if (_recipeHarvester != null && _recipeManager != null) { IEnumerable<Recipe> recipes = _recipeHarvester.HarvestRecipes(packagingInstallViewModel.ExtensionDescriptor.Id) .Where(loadedRecipe => packagingInstallViewModel.Recipes.FirstOrDefault(recipeViewModel => recipeViewModel.Execute && recipeViewModel.Recipe.Name.Equals(loadedRecipe.Name)) != null); foreach (Recipe recipe in recipes) { try { _recipeManager.Execute(recipe); } catch { Services.Notifier.Error(T("Recipes contains {0} unsupported module installation steps.", recipe.Name)); } } } // Enable selected features if (packagingInstallViewModel.Features.Count > 0) { IEnumerable<string> featureIds = packagingInstallViewModel.Features .Where(feature => feature.Enable) .Select(feature => feature.FeatureDescriptor.Id); // Enable the features and its dependencies using recipes, so that they are run after the module's recipes var recipe = new Recipe { RecipeSteps = featureIds.Select( x => new RecipeStep { Name = "Feature", Step = new XElement("Feature", new XAttribute("enable", x)) }) }; _recipeManager.Execute(recipe); } } catch (Exception exception) { Services.Notifier.Error(T("Post installation steps failed with error: {0}", exception.Message)); } return Redirect(redirectUrl); }
private IOrderedEnumerable<IGrouping<string, IGrouping<XElement, ContentPair>>> BuildRemoteOnlyViewModel(Recipe localRecipe, Recipe remoteRecipe) { var contentTypeComparer = new ContentTypeContentComparer(); var identifierComparer = new IdentifierContentComparer(); var layerNameComparer = new LayerNameComparer(); var comparison = new RecipeComparer().Compare(localRecipe, remoteRecipe, (left, right) => contentTypeComparer.IsMatch(left, right) && (identifierComparer.IsMatch(left, right) || layerNameComparer.IsMatch(left, right))); var localonly = comparison.Unmatched .Where(pair => pair.Left == null) .OrderBy(pair => pair.Right.DisplayLabel()) .OrderBy(pair => pair.Right.PartType()) .GroupBy(pair => pair.Right) .GroupBy(layer => layer.Key.LayerName()) .OrderBy(layer => layer.Key); return localonly; }
private IOrderedEnumerable<IGrouping<string, IGrouping<XElement, ContentPair>>> BuildMismatchesViewModel(Recipe localRecipe, Recipe remoteRecipe) { var contentTypeComparer = new ContentTypeContentComparer(); var identityComparer = new IdentifierContentComparer(); var layerComparer = new LayerNameComparer(); var mismatched = new RecipeComparer() .Compare(localRecipe, remoteRecipe, (left, right) => contentTypeComparer.IsMatch(left, right) /*&& layerComparer.IsMatch(left,right)*/ && (!localRecipe.RecipeSteps.SingleOrDefault(step=>step.Name=="Data").Step.Elements() .Any(element=>element.Attribute("Id").Value.Equals(right.Attribute("Id").Value, StringComparison.InvariantCulture)) || !remoteRecipe.RecipeSteps.SingleOrDefault(step=>step.Name=="Data").Step.Elements() .Any(element=>element.Attribute("Id").Value.Equals(left.Attribute("Id").Value, StringComparison.InvariantCulture))) && (_softComparers.Where(comparer => comparer.IsMatch(left, right)).Count() > 1)) .Matching // all items of same type and title, body or layer name match .Where(pair => !identityComparer.IsMatch(pair.Left, pair.Right)); // where the identifier is different var groupedMismatches = mismatched .GroupBy(pair => pair.Left) .GroupBy(set => set.Key.LayerName()) .OrderBy(layer => layer.Key); return groupedMismatches; }
private IOrderedEnumerable<IGrouping<string, IGrouping<XElement, ContentPair>>> BuildDifferencesViewModel(Recipe localRecipe, Recipe remoteRecipe) { var matched = new RecipeComparer().Compare(localRecipe, remoteRecipe, (left, right) => _hardComparers.All(comparer => comparer.IsMatch(left, right)) && _softComparers.Any(comparer => !comparer.IsMatch(left, right, true))); var differences = matched.Matching .OrderBy(pair => pair.Left.DisplayLabel()) .OrderBy(pair => pair.Left.PartType()) .GroupBy(pair => pair.Left) .GroupBy(layer => layer.Key.LayerName()) .OrderBy(layer => layer.Key); return differences; }
private void CheckRecipeSteps(Recipe recipe) { foreach (var step in recipe.RecipeSteps) { switch (step.Name) { case "Metadata": case "Settings": case "Data": break; default: throw new InvalidOperationException(T("Step {0} is not a supported import step.", step.Name).Text); } } }
void IRecipeExecuteEventHandler.ExecutionStart(string executionId, Recipe recipe) { }