public Function BuildRunList() { ReturnType rt = new ReturnType(); Logger.log("info", "Building run list..."); RegistryHelper rh = new RegistryHelper { SubKey = "SOFTWARE\\Blu\\Runtime\\RunList\\" }; rh.DeleteSubKeyTree(); List <object> draftRunlist = (List <object>)ChefEndpoint.Get("nodes/" + ChefConfig.NodeName, "run_list").Object; // TODO: handle roles in the runlist // Only extract recipe[] runlist for now, role[] is not handled yet foreach (string item in draftRunlist) { Cookbook cookbook = new Cookbook(); string recipe = item.StringBetween("recipe[", "]"); string[] runlistItem = Regex.Split(recipe, @"::"); string cookbookName = runlistItem[0]; // Add runlist item to sprint runlist string recipeName = runlistItem.Count() < 2 ? "default" : runlistItem[1]; string sprintRunListItem = SprintData.RunlistPath + "\\" + cookbookName + "\\recipes\\" + recipeName + ".rb"; SprintData.SprintRunList.Add(sprintRunListItem); // Download cookbooks and extract resource/attribute list rt = cookbook.Download(cookbookName, String.Empty, String.Empty, String.Empty, true, true, true); SprintData.ResourceFileList.AddRange(cookbook.ResourceList); SprintData.AttributeFileList.AddRange(cookbook.AttributeList); } return(rt); }
/// <summary> /// Checks if a cookbook supports blu. in metadata: supports 'blu' /// </summary> /// <param name="cookbookName">The name of the cookbook</param> /// <returns>Returns true if cookbook supports blu</returns> private static bool SupportsBlu(string cookbookName) { Dictionary <string, dynamic> platforms = (Dictionary <string, dynamic>)ChefEndpoint.Get("cookbooks/" + cookbookName + "/_latest", "metadata/platforms").Object; return(platforms.ContainsKey("blu")); }
private void btnGet_Click(object sender, EventArgs e) { txtError.Text = String.Empty; try { string path = "/"; if (txtSelect.Text != "") { path = txtPath.Text; } ReturnType rt = ChefEndpoint.Get(txtSelect.Text, path); if (rt.Result == 0) { jvResponse.Json = rt.Data; } else { txtError.Text = rt.Message; } } catch (Exception ex) { txtError.Text = "Unable to GET data: \r\n" + ex.Message + "\r\nCan not find the requested endpoint on the Chef server."; } }
private void ExportSingleNodeRepository(string node, string folder) { ReturnType rt = new ReturnType(); string installedPackages = ""; try { rt = ChefEndpoint.Get("nodes/" + node, "default/app_inventory/installed_packages"); if (rt.Result == 0) { installedPackages = rt.Data; } } catch (Exception ex) { txtError.Text = "Error getting Chef endpoint: " + ex.Message; } if (!string.IsNullOrEmpty(installedPackages)) { try { File.WriteAllText(folder + "\\" + node + ".json", installedPackages); } catch (Exception ex) { txtError.Text = "Error exporting json: " + ex.Message; } } }
private void ExportSoftwareRepository() { string folder = String.Empty; Dictionary <string, dynamic> nodeList = new Dictionary <string, dynamic>(); try { var dialog = new System.Windows.Forms.FolderBrowserDialog(); DialogResult result = dialog.ShowDialog(); if (result == DialogResult.OK) { folder = dialog.SelectedPath; nodeList = (Dictionary <string, dynamic>)ChefEndpoint.Get("nodes", "/").Object; } } catch (Exception ex) { MessageBox.Show("Unable to Export data: \r\n" + ex.Message + "\r\nCan not find the requested endpoint on the Chef server.", "Chef API Path Error", MessageBoxButtons.OK, MessageBoxIcon.Warning); } foreach (var node in nodeList) { ExportSingleNodeRepository(node.Key, folder); } MessageBox.Show("Chef endpoint is exported succcsfully.", "Export", MessageBoxButtons.OK, MessageBoxIcon.Information); }
/// <summary> /// Find version of the cookbook to download, based on the cookbook version operators, e.g. >= /// </summary> /// <param name="cookbookName">Cookbook name</param> /// <param name="version">Cookbook version</param> /// <param name="opr">Operator</param> /// <returns></returns> private static string FindVersion(string cookbookName, string version, string opr) { // If version is not specified, return "_latest" as version switch (version) { case "": return("_latest"); case "latest": return("_latest"); case "_latest": return(version); } // TODO: Make a better implementation of cookbook version requests string foundVersion; Version latestVersion = new Version((String)ChefEndpoint.Get("cookbooks/" + cookbookName + "/_latest", "version").Object); Version requestedVersion = new Version(version); // TODO: fix this if (version == requestedVersion.ToString()) { foundVersion = requestedVersion.ToString(); } switch (opr) { case ">=": foundVersion = latestVersion >= requestedVersion?latestVersion.ToString() : String.Empty; break; case "~>": // returns String.Smily :) foundVersion = latestVersion >= requestedVersion?latestVersion.ToString() : String.Empty; break; // TODO: Cover other cookbook version comparison operators here default: foundVersion = String.Empty; break; } // Can not find a version of this cookbook if (foundVersion == String.Empty) { throw new InvalidOperationException("Can not find cookbook " + cookbookName + " " + opr + " " + version); } return(foundVersion); }
/// <summary> /// ChefApi GET method /// </summary> /// <param name="select">Select endpoint on Chef server</param> /// <param name="path">Search path</param> /// <returns>Chef server reply as dictionary, array or string</returns> public static object Get(string select, string path) { ReturnType rt = ChefEndpoint.Get(select, path); if (rt.Result == 0) { return(rt.Object); } else { throw new System.InvalidOperationException(rt.Message); } }
/// <summary> /// Convert cookbook json object to a dictionary of items /// </summary> /// <param name="cookbookName">Cookbook name</param> /// <param name="version">Cookbook version</param> /// <returns>Dictionary of cookbook items</returns> private static Dictionary <string, dynamic> CookbookToDictionary(string cookbookName, string version) { Dictionary <string, dynamic> cookbook; try { cookbook = (Dictionary <string, dynamic>)ChefEndpoint.Get("cookbooks/" + cookbookName + "/" + version, "/").Object; } catch (Exception ex) { throw new InvalidOperationException("Can not convert cookbook to a dictionary of items, Error : " + ex.Message); } return(cookbook); }
public void Connect() { // Check client connection Dictionary <string, dynamic> client = (Dictionary <string, dynamic>)ChefEndpoint.Get("clients/" + ChefConfig.ClientName, "/").Object; if (client.Count > 0) { // Show logo Host.UI.Write(ConsoleColor.DarkGray, Host.UI.RawUI.BackgroundColor, ChefConfig.BluLogo); Console.WriteLine(); Logger.log("ok", "Connected!"); Logger.log("info", "Client Name: " + ChefConfig.ClientName + " / Organization: " + ChefConfig.Organization); // Save Config ChefConfigurator chefConfigurator = new ChefConfigurator(); chefConfigurator.SaveConfig(); // Check if node exist Dictionary <string, dynamic> node = (Dictionary <string, dynamic>)ChefEndpoint.Get("nodes/" + ChefConfig.NodeName, "/").Object; if (node.Count > 0) { Logger.log("ok", "Recieved Node json for: " + ChefConfig.NodeName); } else { Console.WriteLine(); Logger.log("error", "Unable to retrieve Node data."); Logger.log("info", "You are able to query Chef server by Use-ChefAPI CmdLet, but it seems the Chef node name you provided does not exist."); } } else { Console.WriteLine(); string badNews = "Unable to connect as " + ChefConfig.ClientName + "."; Logger.log("error", badNews + " Please check if Chef client exists and the RSA key is valid."); Terminate(badNews); } }
public Object GetRunList() { Object runList = ChefEndpoint.Get("nodes/" + ChefConfig.NodeName, "run_list").Object; return(runList); }
/// <summary> /// Download a cookbook /// </summary> /// <param name="cookbookName">Cookbook name</param> /// <param name="version">Cookbook version</param> /// <param name="parent">For recursive adding all dependencies</param> /// <param name="opr">Operator e.g >= or ~></param> /// <param name="rewrite">Rewrite the cookbook folder</param> /// <param name="onlyBlu">Download only if it is a Blu cookbook: a cookbook which have [supports 'blu'] in metadata</param> /// <param name="addToRunlist">Add cookbook to the runlist registy key</param> /// <returns></returns> public Function Download( string cookbookName, string version, string parent, string opr, bool rewrite, bool onlyBlu, bool addToRunlist ) { ReturnType rt = new ReturnType(); string cookbookPath = CookbookRoot + "\\" + cookbookName; // Set response to OK now. It will be overridden if there is an error rt.Result = 0; rt.Data = String.Empty; rt.Object = null; rt.Message = String.Empty; if (onlyBlu && !SupportsBlu(cookbookName)) { throw new InvalidOperationException("Cookbook " + cookbookName + " does not suppport blu. Are you missing [supports 'blu'] directive in metadata?"); } if (rewrite) { cookbookPath.EmptyFolder(); } version = FindVersion(cookbookName, version, opr); Dictionary <string, dynamic> cookbook = CookbookToDictionary(cookbookName, version); // Loop through dictionary and find items foreach (KeyValuePair <string, dynamic> entry in cookbook) { // Check if item.key is found in cookbook structure (defined in ChefConfig.cookbookStructure) if (Array.IndexOf(ChefConfig.CookbookStructure, entry.Key) > -1) { try { // Create a list of cookbook item which are valid to download List <object> items = (List <object>)entry.Value; // Put each List item into a dictionary foreach (Dictionary <string, dynamic> item in items) { try { // Create each item path in filesystem string itemPath = Path.GetDirectoryName(cookbookPath + "\\" + item["path"]); if (itemPath != null && !Directory.Exists(itemPath)) { Directory.CreateDirectory(itemPath); } // Download item using (var client = new WebClient()) { // Do not download BluStation.dll from blu_sprint cookbook // This file should already exist in the root, either by Bootstrap or Chef-Client run string itemFileName = Path.GetFileName(item["path"]); if (itemFileName != null && itemFileName.ToUpper() == "BLUSTATION.DLL") { continue; } // Download item client.DownloadFile(item["url"], cookbookPath + "\\" + item["path"]); string itemFolder = Path.GetDirectoryName(item["path"]); string itemPathWindowsFormat = item["path"]; itemPathWindowsFormat = cookbookPath + "\\" + itemPathWindowsFormat.Replace("/", "\\"); // Add item to resource list if (itemFolder != null && itemFolder.ToUpper() == "RESOURCES") { ResourceList.Add(itemPathWindowsFormat); } // Add item to attribute list if (itemFolder != null && itemFolder.ToUpper() == "ATTRIBUTES") { AttributeList.Add(itemPathWindowsFormat); } Logger.log("ok", "Received: " + cookbookName + " -> " + item["path"]); } } catch (Exception ex) { rt.Result = 3; rt.Data = String.Empty; rt.Object = null; rt.Message = "Unable to download: " + cookbookPath + "\\" + item["path"] + " Error: " + ex.Message; return(rt); } } } catch (Exception ex) { rt.Result = 3; rt.Data = String.Empty; rt.Object = null; rt.Message = "Unable to cast cookbook to a list of items, Error : " + ex.Message; return(rt); } } } // Add cookbook to runlist registry key if (addToRunlist) { AddToRunList(cookbookName, cookbookPath, version, parent); } // Recursively download dependencies Dictionary <string, dynamic> cookbookDeps = (Dictionary <string, dynamic>)ChefEndpoint.Get("cookbooks/" + cookbookName + "/" + version, "metadata/dependencies").Object; foreach (KeyValuePair <string, dynamic> dep in cookbookDeps) { string ver = new Regex("[^0-9 .]").Replace(dep.Value, "").Replace(" ", ""); string op = new Regex("[^=~>]").Replace(dep.Value, "").Replace(" ", ""); Download(dep.Key, ver, parent + "\\" + cookbookName, op, rewrite, onlyBlu, addToRunlist); } // Finally return(rt); }
protected override void ProcessRecord() { AppDomain.CurrentDomain.AssemblyResolve += (sender, args) => Assembly.Load(AssemblyResolver.ResolveAssembly(args)); ChefConfigurator chefConfigurator = new ChefConfigurator(); chefConfigurator.LoadConfig(); // Disable API log to console // ChefConfig.apiLog = false; // Default values for Node, Path and Format parameters if (Select == null) { if (string.IsNullOrEmpty(ChefConfig.NodeName)) { Select = "nodes/" + ChefConfig.NodeName; } else { Select = "nodes"; } } else { // Trim the first / from -Endpoint Select = Select.TrimStart('/'); } if (Format == null) { Format = "DICTIONARY"; } if (Path == null) { Path = "/"; } ReturnType rt = ChefEndpoint.Get(Select, Path); if (rt.Result == 0) { // Determine if data is encrypted string key = String.Empty; if (Secret != null) { Format = "SECRET"; key = Secret; } else if (SecretFile != null) { Format = "SECRET"; key = File.ReadAllText(ChefConfig.Root + "\\" + SecretFile); } switch (Format.ToUpper()) { case "JSON": WriteObject(rt.Data); break; case "DICTIONARY": WriteObject(rt.Object); break; default: Logger.log("error", "Output format is not recognized. Accepted values are 'Json', 'Dictionary'"); Terminate("Unrecognized Format"); break; } } else { Terminate(rt.Message); } }
public Function Build() { ReturnType rt; // Check Connection to Chef API Logger.log("info", "Connecting to Chef API..."); rt = ChefEndpoint.Get("nodes/" + ChefConfig.NodeName, "/"); if (rt.Result != 0) { return(rt); } Logger.log("ok", "Connected!"); // Disable apilog after succesfull connection (to keep the log clean and readable) ChefConfig.ApiLog = false; // Clean up // TODO: Do some magic with MD5 instead of simply deleting the folder content Logger.log("info", "Preparing Runtime folder."); SprintData.RunlistPath.EmptyFolder(); SprintData.SprintRunList.Clear(); SprintData.ResourceFileList.Clear(); SprintData.AttributeFileList.Clear(); // Build Runlist (defined in Sprint.Runlist) BuildRunList(); if (rt.Result != 0) { return(rt); } // Import Header (defined in Sprint.Header) ImportHeader(); // Define sprint cookbook depnding of the Mode paramter rt = DefineSprintCookbook(Mode); if (rt.Result != 0) { return(rt); } SprintData.SprintPath = rt.Data; // Import constant variables (defined in Sprint.Constants) ImportConstants(); // Import Attributes (defined in Sprint.Attributes) ImportAttributes(); // Import instant unit tests Logger.log("info", "Reading Test script: blu_sprint::test.blu.rb"); rt = ImportTest(); if (rt.Result != 0) { return(rt); } // Collect Resource Files (defined in SprintData.ResourceFileList) rt = CollectResources(); if (rt.Result != 0) { return(rt); } // Collect Attribute Files (defined in SprintData.AttributeFileList) rt = CollectAttributes(); if (rt.Result != 0) { return(rt); } // Collect Recipes rt = CollectRecipes(); if (rt.Result != 0) { return(rt); } // Build Ruby Stack RubyStack = AttributesStack + Environment.NewLine + RecipeStack; // Compile Sprint Compile(); // Write Ruby stack to RubyStack.rb file System.IO.File.WriteAllText(SprintData.RubyStack, RubyStack); // Write transpiled Resources.psm1 to file System.IO.File.WriteAllText(SprintData.CompiledSprint, SprintPs1Content); // Write transpiled Sprint.ps1 to file System.IO.File.WriteAllText(SprintData.CompiledResources, ResourcesPs1Content); return(rt); }