/// <summary> /// Loads Blu configuration from registry HKLM\\Software\\Blu\\Config /// </summary> /// <returns></returns> public Function LoadConfig() { ReturnType rt = new ReturnType(); RegistryHelper rh = new RegistryHelper { SubKey = "SOFTWARE\\Blu\\Config" }; try { ChefConfig.OrganizationUri = new Uri(rh.Read("OrganizationUri")); ChefConfig.Organization = rh.Read("Organization"); ChefConfig.ClientName = rh.Read("ClientName"); ChefConfig.NodeName = rh.Read("NodeName"); ChefConfig.Validator = rh.Read("Validator"); ChefConfig.ValidationKey = rh.Read("ValidationKey"); ChefConfig.ClientPath = rh.Read("ClientPath"); ChefConfig.ClientRb = rh.Read("ClientRb"); ChefConfig.ClientPem = rh.Read("ClientPem"); ChefConfig.DevPath = rh.Read("DevPath"); rt.Result = 0; rt.Data = String.Empty; rt.Object = null; rt.Message = "Configuration is loaded from HKLM\\Software\\BluApi\\Config"; } catch (Exception ex) { rt.Result = 3; rt.Data = String.Empty; rt.Object = null; rt.Message = "Unable to load configuration from registry. Error: " + ex.Message; } return(rt); }
public Function Add(string clientName) { ReturnType rt = new ReturnType(); Logger.log("info", "Attempting to create client: " + clientName); ChefRequest cr = new ChefRequest(); Dictionary<string, string> dictClient = new Dictionary<string, string>() { { "name", clientName }, { "admin", "false" } }; string json = JsonConvert.SerializeObject(dictClient, Formatting.Indented); string response = cr.Post(ChefConfig.Validator, "clients", json); if (response.Contains("409") && response.Contains("Conflict")) { rt.Result = 3; rt.Message = "Client already exists."; return rt; } else if (response.Contains("BEGIN RSA PRIVATE KEY")) { KeyHelper kh = new KeyHelper(); rt = kh.Format(response); return rt; } else { rt.Result = 4; rt.Message = "Error creating Client, API response: " + response; return rt; } }
public Function CollectAttributes() { ReturnType rt = new ReturnType { Result = 0 }; Logger.log("info", "Compiling attributes in runlist..."); try { foreach (var attributeFilePath in SprintData.AttributeFileList) { AttributesStack += Environment.NewLine; AttributesStack += "#---------------------------------------------------------------" + Environment.NewLine;; AttributesStack += "# " + attributeFilePath + Environment.NewLine; AttributesStack += "#---------------------------------------------------------------" + Environment.NewLine;; AttributesStack += Environment.NewLine; string[] lines = File.ReadAllLines(attributeFilePath); foreach (string line in lines) { AttributesStack += line.Trim() + Environment.NewLine; } } } catch (Exception ex) { rt.Result = 3; rt.Message = ex.Message; return(rt); } return(rt); }
public Function Delete(string clientName) { ReturnType rt = new ReturnType(); Logger.log("info", "Attempting to delete client: " + clientName); ChefRequest cr = new ChefRequest(); string response = cr.Delete(ChefConfig.Validator, "clients/" + clientName); if (response.Contains("Response status code does not indicate success")) { rt.Result = 4; rt.Data = null; rt.Object = null; rt.Message = "Unable to delete client."; } else { rt.Result = 0; rt.Data = response; rt.Object = null; rt.Message = "Client: " + clientName + " is deleted."; } return rt; }
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); }
protected override void ProcessRecord() { AppDomain.CurrentDomain.AssemblyResolve += (sender, args) => Assembly.Load(AssemblyResolver.ResolveAssembly(args)); ChefConfigurator chefConfigurator = new ChefConfigurator(); chefConfigurator.LoadConfig(); // ChefConfig.apiLog = false; // Default -Version to _latest if (Version == null) { Version = "_latest"; } Cookbook cookbook = new Cookbook(); ReturnType rt = cookbook.Download(Name, Version); if (rt.Result == 0) { Logger.log("ok", "Added cookbook: " + Name + "[" + Version + "] to cookbook path."); } else { Logger.log("error", rt.Message); Logger.log("error", "There is an error adding cookbook: " + Name + "[" + Version + "]."); Terminate(rt.Message); } }
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."; } }
/// <summary> /// Saves Blu configuration to registry HKLM\\Software\\Blu\\Config /// </summary> /// <returns></returns> public Function SaveConfig() { ReturnType rt = new ReturnType(); RegistryHelper rh = new RegistryHelper { SubKey = "SOFTWARE\\Blu\\Config" }; try { rh.Write("OrganizationUri", ChefConfig.OrganizationUri.ToString()); rh.Write("Organization", ChefConfig.Organization); rh.Write("ClientName", ChefConfig.ClientName); rh.Write("NodeName", ChefConfig.NodeName); rh.Write("Validator", ChefConfig.Validator); rh.Write("ValidationKey", ChefConfig.ValidationKey); rh.Write("ClientPath", ChefConfig.ClientPath); rh.Write("ClientRb", ChefConfig.ClientName); rh.Write("ClientPem", ChefConfig.ClientPem); rh.Write("DevPath", ChefConfig.DevPath); rt.Result = 0; rt.Data = String.Empty; rt.Object = null; rt.Message = "Configuration is saved to HKLM\\Software\\BluApi\\Config"; } catch (Exception ex) { rt.Result = 3; rt.Data = String.Empty; rt.Object = null; rt.Message = "Unable to save configuration to registry. Error: " + ex.Message; } return(rt); }
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; } } }
public Function Delete(string nodeName) { ReturnType rt = new ReturnType(); Logger.log("info", "Attempting to delete node: " + nodeName); ChefRequest cr = new ChefRequest(); string response = cr.Delete(ChefConfig.Validator, "nodes/" + nodeName); if (response.Contains("Response status code does not indicate success")) { rt.Result = 4; rt.Data = String.Empty; rt.Object = null; rt.Message = "Unable to delete node."; } else { rt.Result = 0; rt.Data = String.Empty; rt.Object = null; rt.Message = "Node: " + nodeName + " is deleted."; } return(rt); }
private void ProcessConfiguration() { // Validating Parameters, logging and exit process if validation returns FATAL ReturnType rt = ValidateOrg(); Logger.log(rt); if (rt.Result == 4) { Terminate(rt.Message); } rt = ValidateClient(); Logger.log(rt); if (rt.Result == 4) { Terminate(rt.Message); } rt = ValidateNode(); Logger.log(rt); if (rt.Result == 4) { Terminate(rt.Message); } rt = ValidateKey(); Logger.log(rt); if (rt.Result == 4) { Terminate(rt.Message); } Connect(); }
/// <summary> /// Saves node object to node_objec.json (ChefConfig.NodeObject) /// </summary> /// <param name="json">node object as json (string)</param> /// <returns>Multiple type rt. rt.Result 0 is success, 3 if failed</returns> public Function SaveNodeObject(string json) { ReturnType rt = new ReturnType { Result = 0 }; if (string.IsNullOrEmpty(json)) { rt.Result = 3; rt.Message = "Node object (json) string can not be empty."; return(rt); } try { File.WriteAllText(json + @"\node_object.json", SprintData.NodeObject); } catch (Exception ex) { rt.Result = 3; rt.Message = ex.Message; return(rt); } return(rt); }
/// <summary> /// Sets ChefConfig.Validator and ChefConfig.ClientName /// </summary> /// <returns>RT: rt.Result 0 as result and rt.Message </returns> public Function ValidateNode() { ReturnType rt = new ReturnType(); ChefConfig.NodeName = Node; rt.Result = 0; rt.Data = String.Empty; rt.Object = null; rt.Message = "Using Node Name: " + ChefConfig.NodeName; return(rt); }
/// <summary> /// Generate method /// </summary> /// <param name="rootNode">root node as AST node</param> /// <returns>Multiple Type rt (result as rt.Dictionary)</returns> public Function Generate(AstNode rootNode) { ReturnType rt = new ReturnType(); _result.Clear(); _result.Add("attributes", new Dictionary <string, dynamic>()); _result.Add("resources", new Dictionary <string, dynamic>()); _result.Add("notifiers", new Dictionary <string, dynamic>()); RootNode(rootNode); rt.Dictionary = _result; return(rt); }
/// <summary> /// Sets ChefConfig.Validator and ChefConfig.ClientName /// </summary> /// <returns>RT: rt.Result 0 as result and rt.Message </returns> public Function ValidateClient() { ReturnType rt = new ReturnType(); ChefConfig.Validator = Client; ChefConfig.ClientName = Client; rt.Result = 0; rt.Data = String.Empty; rt.Object = null; rt.Message = "Using Client Name: " + ChefConfig.ClientName; return(rt); }
/// <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> /// ValidateOrg is validator function for Org parameter. /// </summary> /// <returns></returns> public Function ValidateOrg() { ReturnType rt = new ReturnType(); // Check if Uri is absolute if (!Uri.IsWellFormedUriString(Org, UriKind.Absolute)) { rt.Result = 4; rt.Data = String.Empty; rt.Object = null; rt.Message = "Uri is not well formatted. Check the provided Uri in your browser."; return(rt); } // Check if Uri can be converted to System.Uri try { ChefConfig.OrganizationUri = new Uri(Org); } catch (Exception ex) { rt.Result = 4; rt.Data = String.Empty; rt.Object = null; rt.Message = "Org Parameter is invalid. Can not convert " + Org + " to System.Uri. " + ex.Message + " Check the provided Uri in your browser."; return(rt); } // Check if we can extract organization name from Uri string organization = Org.Substring(Org.LastIndexOf("/", StringComparison.Ordinal) + 1, Org.Length - Org.LastIndexOf("/", StringComparison.Ordinal) - 1); if (organization == "") { rt.Result = 4; rt.Data = String.Empty; rt.Object = null; rt.Message = "Organization name is empty or Uri contains trailing slashes. Remove trailing slashes from the Organization Uri."; return(rt); } else { ChefConfig.Organization = organization; // Organization Name is set ChefConfig.OrganizationUri = new Uri(Org); // Organization Uri is set rt.Result = 0; rt.Data = String.Empty; rt.Object = null; rt.Message = "Using Organization Name: " + ChefConfig.Organization + " and Uri: " + ChefConfig.OrganizationUri; return(rt); } }
/// <summary> /// Extracts blu script (script between [Blu] tags) from a resource /// </summary> /// <param name="scriptPath">Absolute path to recipe file</param> /// <returns>Multiple type rt. rt.Result 0 or 3 for success and failure. rd.Data is the extracted script.</returns> public Function ExtactBluScript(string scriptPath) { ReturnType rt = new ReturnType { Result = 0 }; string[] lines = File.ReadAllLines(scriptPath); int begin = 0; int end = 0; string data = String.Empty; try { for (int i = 0; i < lines.Length; i++) { if (lines[i].StartsWith("=begin") && lines[i + 1].StartsWith("[Blu]")) { begin = i + 2; } if (lines[i].StartsWith("=end") && lines[i - 1].StartsWith("[Blu]")) { end = i - 2; } } for (int i = begin; i < end; i++) { data += lines[i] + Environment.NewLine; } data = data.Trim(); if (string.IsNullOrEmpty(data)) { rt.Result = 3; rt.Message = "Can not find blu script in the recipe " + scriptPath + ". [Blu] tags are missing in the recipe."; return(rt); } rt.Result = 0; rt.Data = data; return(rt); } catch (Exception ex) { rt.Result = 3; rt.Message = ex.Message; return(rt); } }
/// <summary> /// Main Processing function of the CmdLet /// </summary> protected override void ProcessRecord() { AppDomain.CurrentDomain.AssemblyResolve += (sender, args) => Assembly.Load(AssemblyResolver.ResolveAssembly(args)); ChefConfigurator chefConfigurator = new ChefConfigurator(); ReturnType rt = chefConfigurator.LoadConfig(); if (rt.Result == 0) { // Configuration is loaded from registry, try to connect Connect(); } else { ProcessConfiguration(); } }
public Function Add(string clientName, bool force) { ReturnType rt = Add(clientName); switch (rt.Result) { case 0: return rt; case 3: if (force) { Logger.log("warn", "Client already exists and -Force key is provided. Trying to delete and recreate client."); rt = Delete(clientName); if (rt.Result == 0) rt = Add(clientName); return rt; } break; } return rt; }
public Function CollectRecipes() { ReturnType rt = new ReturnType { Result = 0 }; Logger.log("info", "Compiling recipes in runlist..."); foreach (string sprintRunlistItem in SprintData.SprintRunList) { // Ignore blu_sprint cookbook when compiling recipes if (sprintRunlistItem.Contains("blu_sprint")) { continue; } // Add runlist item to recipes stack if (File.Exists(sprintRunlistItem)) { RecipeStack += Environment.NewLine; RecipeStack += "#---------------------------------------------------------------" + Environment.NewLine; RecipeStack += "# " + sprintRunlistItem + Environment.NewLine; RecipeStack += "#---------------------------------------------------------------" + Environment.NewLine; RecipeStack += Environment.NewLine; string[] lines = File.ReadAllLines(sprintRunlistItem); foreach (string line in lines) { RecipeStack += line.Trim() + Environment.NewLine; } } else { rt.Result = 3; rt.Message = "Runlist item does not exist: " + sprintRunlistItem; return(rt); } } return(rt); }
public Function ValidateValidator() // funny name: we are validating if the parameter -Validator is correct :) { ReturnType rt = new ReturnType(); if (Validator != null) { ChefConfig.Validator = Validator; rt.Result = 0; rt.Data = String.Empty; rt.Object = null; rt.Message = "Using Validator Name: " + ChefConfig.Validator; } else { ChefConfig.Validator = ChefConfig.Organization + "-validator"; rt.Result = 1; rt.Data = String.Empty; rt.Object = null; rt.Message = "Validator parameter is not provided, switching to default validator: " + ChefConfig.Validator; } return(rt); }
/// <summary> /// Checks if a development version of blu_sprint cookbook exists /// Determines sprintPath (absolute path to blu_sprint cookbook) /// </summary> /// <returns>Multiple type rt (sprintPath as rt.Data)</returns> public Function DefineSprintCookbook(string mode) { ReturnType rt = new ReturnType(); string sprintPath; // Check if Mode is dev and development version of blu_sprint exists if (mode.ToUpper() == "DEV" && ChefConfig.DevPath != "UNSET" && Directory.Exists(ChefConfig.DevPath + "\\blu_sprint")) { Logger.log("info", "Development version of blu_sprint exist. Starting local Sprint for development."); sprintPath = ChefConfig.DevPath + "\\blu_sprint"; rt.Result = 0; rt.Data = sprintPath; return(rt); } else { // Development version of blu_sprint does not exist, use the live version sprintPath = SprintData.RunlistPath + "\\blu_sprint"; rt.Result = 0; rt.Data = sprintPath; return(rt); } }
// ══════════════════════════ // Start Process // ══════════════════════════ /// <summary> /// ProcessRecord: if mandatory parameters are present, process CmdLet /// </summary> protected override void ProcessRecord() { AppDomain.CurrentDomain.AssemblyResolve += (sender, args) => Assembly.Load(AssemblyResolver.ResolveAssembly(args)); Logger.log("start", "Invoke-Bootstrap"); // Validating Parameters, logging and exit process if validation returns FATAL ReturnType rt = ValidateOrg(); Logger.log(rt); if (rt.Result == 4) { Terminate(rt.Message); } rt = ValidateNode(); Logger.log(rt); if (rt.Result == 4) { Terminate(rt.Message); } rt = ValidateValidator(); Logger.log(rt); if (rt.Result == 4) { Terminate(rt.Message); } rt = ValidateKey(); Logger.log(rt); if (rt.Result == 4) { Terminate(rt.Message); } Bootstrap(); }
public Function Add(string nodeName, string environment, List <string> runlist, List <string> roles, bool force) { ReturnType rt = Add(nodeName, environment, runlist, roles); switch (rt.Result) { case 0: return(rt); case 3: if (force) { Logger.log("warn", "Node already exists and -Force key is provided. Trying to delete and recreate node."); rt = Delete(nodeName); if (rt.Result == 0) { rt = Add(nodeName, environment, runlist, roles); } return(rt); } break; } return(rt); }
public Function ValidateNode() { ReturnType rt = new ReturnType(); // Setting ChefConfig.nodeName ChefConfig.NodeName = Node; if (Node.Length <= 3) { // Warn if nodeNames is shorter than 3 letters rt.Result = 2; rt.Data = String.Empty; rt.Object = null; rt.Message = "Node name is shorter than 3 letters."; } else { rt.Result = 0; rt.Data = String.Empty; rt.Object = null; rt.Message = "Using Node Name: " + ChefConfig.NodeName; } return(rt); }
public Function Add(string nodeName, string environment, List <string> runlist, List <string> roles) { ReturnType rt = new ReturnType(); Logger.log("info", "Attempting to create node: " + nodeName); ChefRequest cr = new ChefRequest(); // Convert runlist[] and roles[] to List run_list List <string> runList = new List <string>(); foreach (string run in runlist) { runList.Add("recipe[" + run + "]"); } foreach (string role in roles) { runList.Add("role[" + role + "]"); } if (string.IsNullOrEmpty(environment)) { environment = "_default"; } Dictionary <string, dynamic> dictNode = new Dictionary <string, dynamic>() { { "name", nodeName }, { "chef_type", "node" }, { "json_class", "Chef::Node" }, // { "attributes", dict_node_attributes}, { "chef_environment", environment } }; if (runList.Count > 0) { dictNode.Add("run_list", runList); } string json = JsonConvert.SerializeObject(dictNode, Formatting.Indented); Logger.log("info", "Attempting to create Chef Node by POST the following json:"); Logger.log("data", json); string response = cr.Post(ChefConfig.Validator, "nodes", json); if (response.Contains("409") && response.Contains("Conflict")) { rt.Result = 3; rt.Data = String.Empty; rt.Object = null; rt.Message = "Node already exists."; return(rt); } if (response.Contains("uri")) { rt.Result = 0; rt.Data = String.Empty; rt.Object = null; rt.Message = "Chef Node: " + nodeName + " is created succesfully."; return(rt); } rt.Result = 4; rt.Data = String.Empty; rt.Object = null; rt.Message = "Error creating Node, API response: " + response; 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); } }
/// <summary> /// Either -Key or -Key file should be used and validated /// </summary> /// <returns>Multi type (ReturnType)</returns> public Function ValidateKey() { ReturnType rt = new ReturnType(); // KeyPath is not provided. if (KeyPath == null) { if (File.Exists(ChefConfig.Root + @"\client.pem")) { ChefConfig.ClientPem = ChefConfig.Root + @"\client.pem"; rt.Result = 0; rt.Data = String.Empty; rt.Object = null; rt.Message = "Key Parameter is not provided, switching to default: " + ChefConfig.ClientPem; } else { rt.Result = 4; rt.Data = String.Empty; rt.Object = null; rt.Message = "Key Parameter is not provided and default .\\client.pem file can not be found."; } } // KeyPath is provided. else { if (File.Exists(KeyPath)) { ChefConfig.ClientPem = KeyPath; ChefConfig.ValidationKey = "UNSET"; // Unset validation key as string, we are using .pem file reader. rt.Result = 0; rt.Data = String.Empty; rt.Object = null; rt.Message = "Using RSA Key : " + ChefConfig.ClientPem; } else if (File.Exists(ChefConfig.Root + "\\" + KeyPath)) { ChefConfig.ClientPem = ChefConfig.Root + "\\" + KeyPath; ChefConfig.ValidationKey = "UNSET"; rt.Result = 0; rt.Data = String.Empty; rt.Object = null; rt.Message = "Using RSA Key : " + ChefConfig.ClientPem; } else { rt.Result = 4; rt.Data = String.Empty; rt.Object = null; rt.Message = "RSA Key file " + KeyPath + " not found."; } } // Tried all KeyPath but not found the file, let's try -Key parameter if (rt.Result == 4) { if (Key != null && Key.Contains("-----BEGIN RSA PRIVATE KEY-----") && Key.Contains("-----END RSA PRIVATE KEY-----") && Key.Length > 1000 ) { rt.Result = 0; rt.Data = String.Empty; rt.Object = null; rt.Message = "RSA Key seems to be OK, let's try using this Key."; ChefConfig.ClientPem = "UNSET"; // Unset .pem path, we are using RSA key as string. ChefConfig.ValidationKey = Key; } else { // Unset both and don't bother signing and sending a request to Chef server. ChefConfig.ClientPem = "UNSET"; ChefConfig.ValidationKey = "UNSET"; rt.Result = 4; rt.Data = String.Empty; rt.Object = null; rt.Message = "RSA Key is not correctly formatted and KeyPath is also not helping much. Please check your RSA key."; } } return(rt); }
/// <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); }