PageRenderTime 39ms CodeModel.GetById 10ms RepoModel.GetById 0ms app.codeStats 1ms

/src/ServiceManagement/Services/Commands.Utilities/Common/ServiceSettings.cs

https://gitlab.com/jslee1/azure-powershell
C# | 385 lines | 269 code | 49 blank | 67 comment | 30 complexity | 8d284eb338cba09015c8228c6b21a029 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;
  15. using System.Diagnostics;
  16. using System.IO;
  17. using System.Linq;
  18. using System.Text;
  19. using System.Web.Script.Serialization;
  20. using Microsoft.WindowsAzure.Commands.Common.Properties;
  21. using Microsoft.WindowsAzure.Commands.ServiceManagement.Model;
  22. using Microsoft.WindowsAzure.Commands.Utilities.Common;
  23. using Microsoft.Azure.Commands.Common.Authentication;
  24. namespace Microsoft.WindowsAzure.Commands.Utilities.CloudService
  25. {
  26. public class ServiceSettings
  27. {
  28. /// <summary>
  29. /// Minimum length of a valid storage account name.
  30. /// http://msdn.microsoft.com/en-us/library/windowsazure/hh264518.aspx
  31. /// </summary>
  32. private const int MinimumStorageAccountNameLength = 3;
  33. /// <summary>
  34. /// Maximum length of a valid storage account name.
  35. /// http://msdn.microsoft.com/en-us/library/windowsazure/hh264518.aspx
  36. /// </summary>
  37. private const int MaximumStorageAccountNameLength = 24;
  38. // Flag indicating whether the ServiceSettings have already been loaded
  39. // and should begin validating any properties (which is used to allow
  40. // the deserializer to set empty values without tripping validation)
  41. private bool _shouldValidate = false;
  42. public string Slot
  43. {
  44. get { return _slot; }
  45. set
  46. {
  47. if (_shouldValidate)
  48. {
  49. Validate.ValidateStringIsNullOrEmpty(value, "Slot");
  50. if (!DeploymentSlotType.Production.Equals(value, StringComparison.OrdinalIgnoreCase) &&
  51. !DeploymentSlotType.Staging.Equals(value, StringComparison.OrdinalIgnoreCase))
  52. {
  53. throw new ArgumentException(string.Format(Resources.InvalidServiceSettingElement, "Slot"));
  54. }
  55. }
  56. _slot = value ?? string.Empty;
  57. }
  58. }
  59. private string _slot = null;
  60. public string Location
  61. {
  62. get { return _location; }
  63. set
  64. {
  65. if (_shouldValidate)
  66. {
  67. Validate.ValidateStringIsNullOrEmpty(value, "Location");
  68. }
  69. _location = value ?? string.Empty;
  70. }
  71. }
  72. private string _location = null;
  73. public string Subscription
  74. {
  75. get { return _subscription; }
  76. set
  77. {
  78. if (_shouldValidate)
  79. {
  80. Validate.ValidateStringIsNullOrEmpty(value, "Subscription");
  81. }
  82. _subscription = value ?? string.Empty;
  83. }
  84. }
  85. private string _subscription = null;
  86. public string StorageServiceName
  87. {
  88. get { return _storageAccountName; }
  89. set
  90. {
  91. if (_shouldValidate)
  92. {
  93. Validate.ValidateStringIsNullOrEmpty(value, "StorageAccountName");
  94. }
  95. _storageAccountName = value ?? string.Empty;
  96. }
  97. }
  98. private string _storageAccountName = null;
  99. public string AffinityGroup
  100. {
  101. get { return _affinityGroup; }
  102. set
  103. {
  104. if (_shouldValidate)
  105. {
  106. Validate.ValidateStringIsNullOrEmpty(value, "AffinityGroup");
  107. }
  108. _affinityGroup = value ?? string.Empty;
  109. }
  110. }
  111. private string _affinityGroup = null;
  112. public static string DefaultLocation { get; set; }
  113. public ServiceSettings()
  114. {
  115. _slot = string.Empty;
  116. _location = string.Empty;
  117. _affinityGroup = string.Empty;
  118. _subscription = string.Empty;
  119. _storageAccountName = string.Empty;
  120. }
  121. public static ServiceSettings Load(string path)
  122. {
  123. Validate.ValidateFileFull(path, Resources.ServiceSettings);
  124. string text = FileUtilities.DataStore.ReadFileAsText(path);
  125. ServiceSettings settings = new JavaScriptSerializer().Deserialize<ServiceSettings>(text);
  126. settings._shouldValidate = true;
  127. return settings;
  128. }
  129. public static ServiceSettings LoadDefault(
  130. string path,
  131. string slot,
  132. string location,
  133. string affinityGroup,
  134. string subscription,
  135. string storageAccountName,
  136. string suppliedServiceName,
  137. string serviceDefinitionName,
  138. out string serviceName)
  139. {
  140. ServiceSettings local;
  141. ServiceSettings defaultServiceSettings = new ServiceSettings();
  142. if (string.IsNullOrEmpty(path) || !File.Exists(path))
  143. {
  144. local = new ServiceSettings();
  145. }
  146. else
  147. {
  148. Validate.ValidateFileFull(path, Resources.ServiceSettings);
  149. local = Load(path);
  150. }
  151. defaultServiceSettings._slot = GetDefaultSlot(local.Slot, null, slot);
  152. defaultServiceSettings._location = GetDefaultLocation(local.Location, location);
  153. defaultServiceSettings._subscription = GetDefaultSubscription(local.Subscription, subscription);
  154. serviceName = GetServiceName(suppliedServiceName, serviceDefinitionName);
  155. defaultServiceSettings._storageAccountName = GetDefaultStorageName(local.StorageServiceName, null, storageAccountName, serviceName).ToLower();
  156. defaultServiceSettings._affinityGroup = affinityGroup;
  157. return defaultServiceSettings;
  158. }
  159. private static string GetServiceName(string suppliedServiceName, string serviceDefinitionName)
  160. {
  161. // If user supplied value as parameter then return it
  162. //
  163. if (!string.IsNullOrEmpty(suppliedServiceName))
  164. {
  165. return suppliedServiceName;
  166. }
  167. // Check to see if you have service name from *csdef
  168. //
  169. if (string.IsNullOrEmpty(serviceDefinitionName))
  170. {
  171. // This line will be touched only if the cmd running doesn't require service name
  172. //
  173. return string.Empty;
  174. }
  175. return serviceDefinitionName;
  176. }
  177. private static string GetDefaultStorageName(string localStorageName, string globalStorageAccountName, string storageAccountName, string serviceName)
  178. {
  179. Debug.Assert(serviceName != null, "serviceName cannot be null.");
  180. string name = serviceName;
  181. // If user supplied value as parameter then return it
  182. if (!string.IsNullOrEmpty(storageAccountName))
  183. {
  184. name = storageAccountName;
  185. }
  186. // User already has value in local service settings
  187. else if (!string.IsNullOrEmpty(localStorageName))
  188. {
  189. name = localStorageName;
  190. }
  191. // User already has value in global service settings
  192. else if (!string.IsNullOrEmpty(globalStorageAccountName))
  193. {
  194. name = globalStorageAccountName;
  195. }
  196. // If none of previous succeed, use service name as storage account name
  197. else if (!string.IsNullOrEmpty(serviceName))
  198. {
  199. name = SanitizeStorageAccountName(serviceName);
  200. }
  201. name = name.ToLower();
  202. ValidateStorageAccountName(name);
  203. return name;
  204. }
  205. /// <summary>
  206. /// Sanitize a name for use as a storage account name.
  207. /// </summary>
  208. /// <param name="name">The potential storage account name.</param>
  209. /// <returns>The sanitized storage account name.</returns>
  210. private static string SanitizeStorageAccountName(string name)
  211. {
  212. // Replace any non-letters or non-digits with their hex equivalent
  213. StringBuilder builder = new StringBuilder(name.Length);
  214. foreach (char ch in name)
  215. {
  216. if (char.IsLetter(ch) || char.IsDigit(ch))
  217. {
  218. builder.Append(ch);
  219. }
  220. else
  221. {
  222. builder.AppendFormat("x{0:X}", (ushort)ch);
  223. }
  224. }
  225. // Trim the sanitized name to at most 24 characters.
  226. name = builder.ToString(
  227. 0,
  228. Math.Min(builder.Length, MaximumStorageAccountNameLength));
  229. return name;
  230. }
  231. /// <summary>
  232. /// Validate that the storage account name contains only lower case
  233. /// letters or numbers and is between 3 and 24 characters in length
  234. /// (per http://msdn.microsoft.com/en-us/library/windowsazure/hh264518.aspx)
  235. /// unless the string is empty (which can happen if it wasn't provided
  236. /// or generated).
  237. /// </summary>
  238. /// <param name="name">The storage account name.</param>
  239. private static void ValidateStorageAccountName(string name)
  240. {
  241. if (!string.IsNullOrEmpty(name) &&
  242. (!name.All(c => char.IsLower(c) || char.IsDigit(c)) ||
  243. name.Length < MinimumStorageAccountNameLength ||
  244. name.Length > MaximumStorageAccountNameLength))
  245. {
  246. throw new ArgumentException(string.Format(Resources.ServiceSettings_ValidateStorageAccountName_InvalidName, name));
  247. }
  248. }
  249. private static string GetDefaultSubscription(string localSubscription, string subscription)
  250. {
  251. // If user supplied value as parameter then return it
  252. //
  253. if (!string.IsNullOrEmpty(subscription))
  254. {
  255. return subscription;
  256. }
  257. // User already has value in local service settings
  258. //
  259. if (!string.IsNullOrEmpty(localSubscription))
  260. {
  261. return localSubscription;
  262. }
  263. return null;
  264. }
  265. private static string GetDefaultLocation(string localLocation, string location)
  266. {
  267. // If user supplied value as parameter then return it
  268. //
  269. if (!string.IsNullOrEmpty(location))
  270. {
  271. return location.ToLower();
  272. }
  273. // User already has value in local service settings
  274. //
  275. if (!string.IsNullOrEmpty(localLocation))
  276. {
  277. return localLocation.ToLower();
  278. }
  279. // If none of previous succeed, get the default environment location.
  280. //
  281. return DefaultLocation;
  282. }
  283. private static string GetDefaultSlot(string localSlot, string globalSlot, string slot)
  284. {
  285. // If user supplied value as parameter then return it
  286. //
  287. if (!string.IsNullOrEmpty(slot))
  288. {
  289. if (DeploymentSlotType.Production.Equals(slot, StringComparison.OrdinalIgnoreCase) ||
  290. DeploymentSlotType.Staging.Equals(slot, StringComparison.OrdinalIgnoreCase))
  291. {
  292. return slot.ToLower();
  293. }
  294. throw new ArgumentException(string.Format(Resources.InvalidServiceSettingElement, "Slot"));
  295. }
  296. // User already has value in local service settings
  297. //
  298. if (!string.IsNullOrEmpty(localSlot))
  299. {
  300. return localSlot.ToLower();
  301. }
  302. // User already has value in global service settings
  303. //
  304. if (!string.IsNullOrEmpty(globalSlot))
  305. {
  306. return globalSlot.ToLower();
  307. }
  308. // If none of previous succeed, use Production as default slot
  309. //
  310. return DeploymentSlotType.Production;
  311. }
  312. public void Save(string path)
  313. {
  314. Validate.ValidateStringIsNullOrEmpty(path, Resources.ServiceSettings);
  315. Validate.ValidateDirectoryFull(Path.GetDirectoryName(path), Resources.ServiceSettings);
  316. FileUtilities.DataStore.WriteFile(path, new JavaScriptSerializer().Serialize(this));
  317. }
  318. public override bool Equals(object obj)
  319. {
  320. ServiceSettings other = (ServiceSettings)obj;
  321. return
  322. Location.Equals(other.Location) &&
  323. Slot.Equals(other.Slot) &&
  324. StorageServiceName.Equals(other.StorageServiceName) &&
  325. Subscription.Equals(other.Subscription);
  326. }
  327. public override int GetHashCode()
  328. {
  329. return
  330. Location.GetHashCode() ^
  331. Slot.GetHashCode() ^
  332. StorageServiceName.GetHashCode() ^
  333. Subscription.GetHashCode();
  334. }
  335. }
  336. }