Azure Config Generator
 All Classes Namespaces Files Functions Variables Properties
FileGenerator.cs
Go to the documentation of this file.
1 using System;
2 using System.Collections.Generic;
3 using System.Diagnostics;
4 using System.IO;
5 using System.Linq;
6 using System.Text;
7 using System.Threading.Tasks;
8 using System.Xml;
9 using System.Xml.Linq;
10 using System.Xml.XPath;
11 
12 namespace FUSE.AzureConfig.Tasks
13 {
14  public class FileGenerator
15  {
16  public const string DefaultEnvName = "__DEFAULT__";
17 
18  public const string CsdefName = "ServiceDefinition.csdef";
19  public const string CscfgNameFmt = "ServiceConfiguration.{0}cscfg";
20 
21  public void AlterCsdef(AzureConfig config, string csdefPath, string outPath = null)
22  {
23  if (!Directory.Exists(csdefPath))
24  throw new ArgumentException(csdefPath + " must exist");
25 
26  outPath = outPath ?? csdefPath;
27  if (!Directory.Exists(outPath))
28  throw new ArgumentException(outPath + " must exist");
29 
30  var doc = XDocument.Load(Path.Combine(csdefPath, CsdefName));
31  var rootNS = GetRootNamespace(doc);
32  foreach (var role in config.Roles)
33  {
34  var roleName = role.Value.RoleName;
35  var roleNode = (from e in doc.Descendants()
36  where (string)e.Attribute("name") == roleName
37  select e).FirstOrDefault();
38  if (roleNode == null)
39  throw new ArgumentException("Unable to find role " + roleName);
40  else
41  {
42  var settings = roleNode.Element(rootNS + "ConfigurationSettings");
43  if (settings == null)
44  {
45  Trace.TraceWarning("Adding ConfigurationSettings node for {0}", roleName);
46  settings = new XElement(rootNS + "ConfigurationSettings");
47  roleNode.Add(settings);
48  }
49  foreach (var setting in role.Value.ConfigurationSettingKeys.OrderBy(x => x))
50  {
51  AddOrUpdateSetting(settings, rootNS, setting);
52  }
53  }
54  }
55  using (var writer = XmlWriter.Create(Path.Combine(outPath, CsdefName), new XmlWriterSettings() { Indent = true }))
56  doc.WriteTo(writer);
57  }
58 
59  public void AlterCscfgs(AzureConfig config, string cscfgPath, string outPath = null)
60  {
61  if (!Directory.Exists(cscfgPath))
62  throw new ArgumentException(cscfgPath + " must exist");
63 
64  outPath = outPath ?? cscfgPath;
65  if (!Directory.Exists(outPath))
66  throw new ArgumentException(outPath + " must exist");
67 
68  foreach (var env in config.Environments)
69  {
70  var envName = env.Value.EnvName;
71  // Load "baseline" cscfg
72  var doc = XDocument.Load(Path.Combine(cscfgPath, string.Format(CscfgNameFmt, "")));
73  var rootNS = GetRootNamespace(doc);
74  foreach (var role in env.Value.Roles)
75  {
76  var roleName = role.Value.RoleName;
77  var roleNode = (from e in doc.Descendants()
78  where (string)e.Attribute("name") == roleName
79  select e).FirstOrDefault();
80  if (roleNode == null)
81  throw new ArgumentException("Unable to find role " + roleName);
82  else
83  {
84  var instances = roleNode.Element(rootNS + "Instances");
85  if (instances == null)
86  {
87  Trace.TraceWarning("Adding Instances node for {0}", roleName);
88  instances = new XElement(rootNS + "Instances");
89  roleNode.AddFirst(instances);
90  }
91  var countAttr = instances.Attribute("count");
92  if (countAttr == null)
93  {
94  countAttr = new XAttribute("count", role.Value.Instances);
95  instances.Add(countAttr);
96  }
97  else
98  {
99  countAttr.Value = role.Value.Instances.ToString();
100  }
101 
102  var settings = roleNode.Element(rootNS + "ConfigurationSettings");
103  if (settings == null)
104  {
105  Trace.TraceWarning("Adding ConfigurationSettings node for {0}", roleName);
106  settings = new XElement(rootNS + "ConfigurationSettings");
107  roleNode.Add(settings);
108  }
109  foreach (var setting in role.Value.ConfigSettings.Settings.OrderBy(x => x.Key))
110  {
111  AddOrUpdateSetting(settings, rootNS, setting.Key, setting.Value);
112  }
113  foreach (var setting in role.Value.ConfigSettings.MissingSettings.OrderBy(x => x))
114  {
115  AddOrUpdateSetting(settings, rootNS, setting, string.Empty);
116  }
117  }
118  }
119  var cscfgName = string.Format(CscfgNameFmt, envName == DefaultEnvName ? "" : envName + ".");
120  using (var writer = XmlWriter.Create(Path.Combine(outPath, cscfgName), new XmlWriterSettings() { Indent = true }))
121  doc.WriteTo(writer);
122  }
123  }
124 
125  public static XNamespace GetRootNamespace(XDocument doc)
126  {
127  var namespaces = doc.Root.Attributes().Where(x => x.IsNamespaceDeclaration)
128  .GroupBy(x => x.Name.Namespace == XNamespace.None ? string.Empty : x.Name.LocalName)
129  .ToDictionary(x => x.Key, x => x.First());
130  return namespaces[""].Value;
131  }
132 
133  private void AddOrUpdateSetting(XElement settingsElt, XNamespace ns, string name, string value = null)
134  {
135  var existing = (from e in settingsElt.Elements()
136  where (string)e.Attribute("name") == name
137  select e).FirstOrDefault();
138  if (value == null)
139  {
140  if (existing == null)
141  settingsElt.Add(new XElement(ns + "Setting", new XAttribute("name", name)));
142  }
143  else
144  {
145  if (existing == null)
146  settingsElt.Add(new XElement(ns + "Setting", new XAttribute("name", name), new XAttribute("value", value)));
147  else
148  {
149  var valueAttr = existing.Attribute(ns + "value");
150  if (valueAttr == null)
151  throw new ArgumentException("Passed in value, found Setting entry for " + name + ", but it had no value attribute");
152  valueAttr.Value = value;
153  }
154  }
155  }
156 
157  }
158 }
Processed Azure configuration
Definition: AzureConfig.cs:12
static XNamespace GetRootNamespace(XDocument doc)
void AlterCscfgs(AzureConfig config, string cscfgPath, string outPath=null)
void AlterCsdef(AzureConfig config, string csdefPath, string outPath=null)