PageRenderTime 48ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 1ms

/src/ServiceManagement/Compute/Commands.ServiceManagement/IaaS/Extensions/Chef/SetAzureVMChefExtension.cs

https://gitlab.com/jslee1/azure-powershell
C# | 301 lines | 255 code | 24 blank | 22 comment | 10 complexity | 7f5319d494933b8b625d2c691a6ff226 MD5 | raw file
  1. // ----------------------------------------------------------------------------------
  2. //
  3. // Copyright Microsoft Corporation
  4. // Licensed under the Apache License, Version 2.0 (the "License");
  5. // you may not use this file except in compliance with the License.
  6. // You may obtain a copy of the License at
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. // Unless required by applicable law or agreed to in writing, software
  9. // distributed under the License is distributed on an "AS IS" BASIS,
  10. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  11. // See the License for the specific language governing permissions and
  12. // limitations under the License.
  13. // ----------------------------------------------------------------------------------
  14. using System.Management.Automation;
  15. using System.Linq;
  16. using System;
  17. using System.IO;
  18. using System.Text.RegularExpressions;
  19. using Microsoft.WindowsAzure.Commands.ServiceManagement;
  20. using Microsoft.WindowsAzure.Commands.ServiceManagement.Model;
  21. using Microsoft.WindowsAzure.Commands.ServiceManagement.Helpers;
  22. using Microsoft.WindowsAzure.Management.Compute;
  23. namespace Microsoft.WindowsAzure.Commands.ServiceManagement.IaaS.Extensions
  24. {
  25. [Cmdlet(
  26. VerbsCommon.Set,
  27. VirtualMachineChefExtensionNoun,
  28. DefaultParameterSetName = WindowsParameterSetName),
  29. OutputType(
  30. typeof(IPersistentVM))]
  31. public class SetAzureVMChefExtensionCommand : VirtualMachineChefExtensionCmdletBase
  32. {
  33. protected const string LinuxParameterSetName = OS.Linux;
  34. protected const string WindowsParameterSetName = OS.Windows;
  35. [Parameter(
  36. ValueFromPipelineByPropertyName = true,
  37. HelpMessage = "The Extension Version. Default is the latest available version")]
  38. [ValidateNotNullOrEmpty]
  39. public override string Version { get; set; }
  40. [Parameter(
  41. Mandatory = true,
  42. ValueFromPipelineByPropertyName = true,
  43. HelpMessage = "The Chef Server Validation Key File Path.")]
  44. [ValidateNotNullOrEmpty]
  45. public string ValidationPem { get; set; }
  46. [Parameter(
  47. ValueFromPipelineByPropertyName = true,
  48. HelpMessage = "The Chef Server Client Config (ClientRb)File Path.")]
  49. [ValidateNotNullOrEmpty]
  50. public string ClientRb { get; set; }
  51. [Parameter(
  52. ValueFromPipelineByPropertyName = true,
  53. HelpMessage = "The Chef Client bootstrap options in JSON format.")]
  54. [ValidateNotNullOrEmpty]
  55. public string BootstrapOptions { get; set; }
  56. [Parameter(
  57. ValueFromPipelineByPropertyName = true,
  58. HelpMessage = "The Chef Server Node Runlist.")]
  59. [ValidateNotNullOrEmpty]
  60. public string RunList { get; set; }
  61. [Parameter(
  62. ValueFromPipelineByPropertyName = true,
  63. HelpMessage = "The Chef Server Url.")]
  64. [ValidateNotNullOrEmpty]
  65. public string ChefServerUrl { get; set; }
  66. [Parameter(
  67. ValueFromPipelineByPropertyName = true,
  68. HelpMessage = "The Chef ValidationClientName," +
  69. " used to determine whether a chef-client may register with a Chef server.")]
  70. [ValidateNotNullOrEmpty]
  71. public string ValidationClientName { get; set; }
  72. [Parameter(
  73. ValueFromPipelineByPropertyName = true,
  74. HelpMessage = "The Chef Organization name, used to form Validation Client Name.")]
  75. [ValidateNotNullOrEmpty]
  76. public string OrganizationName { get; set; }
  77. [Parameter(
  78. ValueFromPipelineByPropertyName = true,
  79. HelpMessage = "Flag to opt for auto chef-client update. Chef-client update is false by default.")]
  80. [ValidateNotNullOrEmpty]
  81. public SwitchParameter AutoUpdateChefClient { get; set; }
  82. [Parameter(
  83. ValueFromPipelineByPropertyName = true,
  84. HelpMessage = "Delete the chef config files during update/uninstall extension. Default is false.")]
  85. [ValidateNotNullOrEmpty]
  86. public SwitchParameter DeleteChefConfig { get; set; }
  87. [Parameter(
  88. ValueFromPipelineByPropertyName = true,
  89. HelpMessage = "Chef client version to be installed with the extension")]
  90. [ValidateNotNullOrEmpty]
  91. public string BootstrapVersion { get; set; }
  92. [Parameter(
  93. ValueFromPipelineByPropertyName = true,
  94. HelpMessage = "Uninstall Chef client during update/uninstall extension. Default is false.")]
  95. [ValidateNotNullOrEmpty]
  96. public SwitchParameter UninstallChefClient { get; set; }
  97. [Parameter(
  98. Mandatory = true,
  99. ParameterSetName = LinuxParameterSetName,
  100. HelpMessage = "Set extension for Linux.")]
  101. public SwitchParameter Linux { get; set; }
  102. [Parameter(
  103. Mandatory = true,
  104. ParameterSetName = WindowsParameterSetName,
  105. HelpMessage = "Set extension for Windows.")]
  106. public SwitchParameter Windows { get; set; }
  107. internal void ExecuteCommand()
  108. {
  109. SetDefault();
  110. ValidateParameters();
  111. SetPrivateConfig();
  112. SetPublicConfig();
  113. RemovePredicateExtensions();
  114. AddResourceExtension();
  115. WriteObject(VM);
  116. }
  117. private string GetLatestChefExtensionVersion()
  118. {
  119. var extensionList = this.ComputeClient.VirtualMachineExtensions.List();
  120. var version = extensionList.ResourceExtensions.Where(
  121. extension => extension.Publisher == ExtensionDefaultPublisher
  122. && extension.Name == base.extensionName).Max(extension => extension.Version);
  123. string[] separators = {"."};
  124. string majorVersion = version.Split(separators, StringSplitOptions.None)[0];
  125. return majorVersion + ".*";
  126. }
  127. private void SetDefault()
  128. {
  129. bool IsOrganizationNameEmpty = string.IsNullOrEmpty(this.OrganizationName);
  130. // form validation client name using organization name.
  131. if (!IsOrganizationNameEmpty)
  132. {
  133. this.ValidationClientName = this.OrganizationName + "-validator";
  134. }
  135. if (this.Linux.IsPresent)
  136. {
  137. base.extensionName = LinuxExtensionName;
  138. }
  139. else if (this.Windows.IsPresent)
  140. {
  141. base.extensionName = ExtensionDefaultName;
  142. }
  143. this.Version = this.Version ?? GetLatestChefExtensionVersion();
  144. }
  145. private void SetPrivateConfig()
  146. {
  147. this.PrivateConfiguration = string.Format(PrivateConfigurationTemplate,
  148. File.ReadAllText(this.ValidationPem).TrimEnd('\r', '\n'));
  149. }
  150. private void SetPublicConfig()
  151. {
  152. string ClientConfig = string.Empty;
  153. bool IsClientRbEmpty = string.IsNullOrEmpty(this.ClientRb);
  154. bool IsChefServerUrlEmpty = string.IsNullOrEmpty(this.ChefServerUrl);
  155. bool IsValidationClientNameEmpty = string.IsNullOrEmpty(this.ValidationClientName);
  156. bool IsRunListEmpty = string.IsNullOrEmpty(this.RunList);
  157. bool IsBootstrapOptionsEmpty = string.IsNullOrEmpty(this.BootstrapOptions);
  158. string AutoUpdateChefClient = this.AutoUpdateChefClient.IsPresent ? "true" : "false";
  159. string DeleteChefConfig = this.DeleteChefConfig.IsPresent ? "true" : "false";
  160. string BootstrapVersion = this.BootstrapVersion;
  161. string UninstallChefClient = this.UninstallChefClient.IsPresent ? "true" : "false";
  162. //Cases handled:
  163. // 1. When clientRb given by user and:
  164. // 1.1 if ChefServerUrl and ValidationClientName given then append it to end of ClientRb
  165. // 1.2 if ChefServerUrl given then append it to end of ClientRb
  166. // 1.3 if ValidationClientName given then append it to end of ClientRb
  167. // 2. When ClientRb not given but ChefServerUrl and ValidationClientName given by user then
  168. // create ClientRb config using these values.
  169. if (!IsClientRbEmpty)
  170. {
  171. ClientConfig = Regex.Replace(File.ReadAllText(this.ClientRb),
  172. "\"|'", "\\\"").TrimEnd('\r', '\n').Replace("\r\n", "\\r\\n");
  173. // Append ChefServerUrl and ValidationClientName to end of ClientRb
  174. if (!IsChefServerUrlEmpty && !IsValidationClientNameEmpty)
  175. {
  176. string UserConfig = @"
  177. chef_server_url \""{0}\""
  178. validation_client_name \""{1}\""
  179. ";
  180. ClientConfig += string.Format(UserConfig, this.ChefServerUrl, this.ValidationClientName);
  181. }
  182. // Append ChefServerUrl to end of ClientRb
  183. else if (!IsChefServerUrlEmpty)
  184. {
  185. string UserConfig = @"
  186. chef_server_url \""{0}\""
  187. ";
  188. ClientConfig += string.Format(UserConfig, this.ChefServerUrl);
  189. }
  190. // Append ValidationClientName to end of ClientRb
  191. else if (!IsValidationClientNameEmpty)
  192. {
  193. string UserConfig = @"
  194. validation_client_name \""{0}\""
  195. ";
  196. ClientConfig += string.Format(UserConfig, this.ValidationClientName);
  197. }
  198. }
  199. // Create ClientRb config using ChefServerUrl and ValidationClientName
  200. else if (!IsChefServerUrlEmpty && !IsValidationClientNameEmpty)
  201. {
  202. string UserConfig = @"
  203. chef_server_url \""{0}\""
  204. validation_client_name \""{1}\""
  205. ";
  206. ClientConfig = string.Format(UserConfig, this.ChefServerUrl, this.ValidationClientName);
  207. }
  208. if (IsRunListEmpty)
  209. {
  210. if (IsBootstrapOptionsEmpty)
  211. {
  212. this.PublicConfiguration = string.Format("{{{0},{1},{2},{3},{4}}}",
  213. string.Format(AutoUpdateTemplate, AutoUpdateChefClient),
  214. string.Format(DeleteChefConfigTemplate, DeleteChefConfig),
  215. string.Format(ClientRbTemplate, ClientConfig),
  216. string.Format(BootstrapVersionTemplate, BootstrapVersion),
  217. string.Format(UninstallChefClientTemplate, UninstallChefClient));
  218. }
  219. else
  220. {
  221. this.PublicConfiguration = string.Format("{{{0},{1},{2},{3},{4},{5}}}",
  222. string.Format(AutoUpdateTemplate, AutoUpdateChefClient),
  223. string.Format(DeleteChefConfigTemplate, DeleteChefConfig),
  224. string.Format(ClientRbTemplate, ClientConfig),
  225. string.Format(BootStrapOptionsTemplate, this.BootstrapOptions),
  226. string.Format(BootstrapVersionTemplate, BootstrapVersion),
  227. string.Format(UninstallChefClientTemplate, UninstallChefClient));
  228. }
  229. }
  230. else
  231. {
  232. if (IsBootstrapOptionsEmpty)
  233. {
  234. this.PublicConfiguration = string.Format("{{{0},{1},{2},{3},{4},{5}}}",
  235. string.Format(AutoUpdateTemplate, AutoUpdateChefClient),
  236. string.Format(DeleteChefConfigTemplate, DeleteChefConfig),
  237. string.Format(ClientRbTemplate, ClientConfig),
  238. string.Format(RunListTemplate, this.RunList),
  239. string.Format(BootstrapVersionTemplate, BootstrapVersion),
  240. string.Format(UninstallChefClientTemplate, UninstallChefClient));
  241. }
  242. else
  243. {
  244. this.PublicConfiguration = string.Format("{{{0},{1},{2},{3},{4},{5},{6}}}",
  245. string.Format(AutoUpdateTemplate, AutoUpdateChefClient),
  246. string.Format(DeleteChefConfigTemplate, DeleteChefConfig),
  247. string.Format(ClientRbTemplate, ClientConfig),
  248. string.Format(RunListTemplate, this.RunList),
  249. string.Format(BootStrapOptionsTemplate, this.BootstrapOptions),
  250. string.Format(BootstrapVersionTemplate, BootstrapVersion),
  251. string.Format(UninstallChefClientTemplate, UninstallChefClient));
  252. }
  253. }
  254. }
  255. protected override void ValidateParameters()
  256. {
  257. base.ValidateParameters();
  258. bool IsClientRbEmpty = string.IsNullOrEmpty(this.ClientRb);
  259. bool IsChefServerUrlEmpty = string.IsNullOrEmpty(this.ChefServerUrl);
  260. bool IsValidationClientNameEmpty = string.IsNullOrEmpty(this.ValidationClientName);
  261. // Validate ClientRb or ChefServerUrl and ValidationClientName should exist.
  262. if (IsClientRbEmpty && (IsChefServerUrlEmpty || IsValidationClientNameEmpty))
  263. {
  264. throw new ArgumentException(
  265. "Required -ClientRb or -ChefServerUrl and -ValidationClientName options.");
  266. }
  267. }
  268. protected override void ProcessRecord()
  269. {
  270. base.ProcessRecord();
  271. ExecuteCommand();
  272. }
  273. }
  274. }