|
1 | | -using KustoSchemaTools.Model; |
| 1 | +using Kusto.Language; |
| 2 | +using KustoSchemaTools.Model; |
2 | 3 | using Microsoft.Extensions.Logging; |
3 | 4 | using System.Data; |
| 5 | +using System.Text; |
4 | 6 |
|
5 | 7 | namespace KustoSchemaTools.Changes |
6 | 8 | { |
@@ -175,6 +177,133 @@ private static List<IChange> GenerateScriptCompareChanges<T>(Database oldState, |
175 | 177 |
|
176 | 178 | return tmp; |
177 | 179 | } |
| 180 | + |
| 181 | + public static List<IChange> GenerateFollowerChanges(FollowerDatabase oldState, FollowerDatabase newState, ILogger log) |
| 182 | + { |
| 183 | + |
| 184 | + |
| 185 | + List<IChange> result = |
| 186 | + [ |
| 187 | + .. GenerateFollowerCachingChanges(oldState, newState, db => db.Tables, "Table", "table"), |
| 188 | + .. GenerateFollowerCachingChanges(oldState, newState, db => db.MaterializedViews, "MV", "materialized-view"), |
| 189 | + |
| 190 | + ]; |
| 191 | + if (oldState.Cache.DefaultHotCache != newState.Cache.DefaultHotCache) |
| 192 | + { |
| 193 | + if (newState.Cache.DefaultHotCache != null) |
| 194 | + { |
| 195 | + result.Add(new BasicChange("FollowerDatabase", "ChangeDefaultHotCache", $"From {oldState.Cache.DefaultHotCache} to {newState.Cache.DefaultHotCache}", new List<DatabaseScriptContainer> |
| 196 | + { |
| 197 | + new DatabaseScriptContainer(new DatabaseScript($".alter follower database {newState.DatabaseName} policy caching hot = {newState.Cache.DefaultHotCache}", 0), "FollowerChangeDefaultHotCache") |
| 198 | + })); |
| 199 | + } |
| 200 | + else |
| 201 | + { |
| 202 | + result.Add(new BasicChange("FollowerDatabase", "DeleteDefaultHotCache", $"Remove Default Hot Cache", new List<DatabaseScriptContainer> |
| 203 | + { |
| 204 | + new DatabaseScriptContainer(new DatabaseScript($".delete follower database {newState.DatabaseName} policy caching", 0), "FollowerDeleteDefaultHotCache") |
| 205 | + })); |
| 206 | + } |
| 207 | + } |
| 208 | + |
| 209 | + return result; |
| 210 | + |
| 211 | + |
| 212 | + |
| 213 | + /* |
| 214 | + * public class FollowerDatabase |
| 215 | + { |
| 216 | + public required string DatabaseName { get; set; } |
| 217 | + public FollowerCache Cache { get; set; } = new FollowerCache(); |
| 218 | + public FollowerPermissions Permissions { get; set; } = new FollowerPermissions(); |
| 219 | + } |
| 220 | +
|
| 221 | + public class FollowerPermissions |
| 222 | + { |
| 223 | + public FollowerModificationKind? ModificationKind { get; set; } |
| 224 | + public List<AADObject> Viewers { get; set; } = new List<AADObject>(); |
| 225 | + public List<AADObject> Admins { get; set; } = new List<AADObject>(); |
| 226 | + } |
| 227 | +
|
| 228 | + public class FollowerCache |
| 229 | + { |
| 230 | + public string? DefaultHotCache { get; set; } |
| 231 | + public FollowerModificationKind? ModificationKind { get; set; } |
| 232 | + public Dictionary<string, string> Tables { get; set; } = new Dictionary<string, string>(); |
| 233 | + public Dictionary<string, string> MaterializedViews { get; set; } = new Dictionary<string, string>(); |
| 234 | + } |
| 235 | +
|
| 236 | + public enum FollowerModificationKind |
| 237 | + { |
| 238 | + None, |
| 239 | + Union, |
| 240 | + Replace |
| 241 | + } |
| 242 | + */ |
| 243 | + |
| 244 | + |
| 245 | + return result; |
| 246 | + } |
| 247 | + |
| 248 | + private static List<IChange> GenerateFollowerCachingChanges(FollowerDatabase oldState, FollowerDatabase newState, Func<FollowerCache, Dictionary<string,string>> selector, string type, string kustoType) |
| 249 | + { |
| 250 | + var result = new List<IChange>(); |
| 251 | + var oldEntities = selector(oldState.Cache); |
| 252 | + var newEntities = selector(newState.Cache); |
| 253 | + |
| 254 | + |
| 255 | + var removedPolicyScripts = oldEntities.Keys.Except(newEntities.Keys) |
| 256 | + .Select(itm => |
| 257 | + new |
| 258 | + { |
| 259 | + Name = itm, |
| 260 | + Script = new DatabaseScriptContainer(new DatabaseScript($".delete follower database {newState.DatabaseName} {kustoType} {itm} policy caching", 0), $"FollowerDelete{type}CachingPolicies") |
| 261 | + }) |
| 262 | + .ToList(); |
| 263 | + var changedPolicyScripts = newEntities |
| 264 | + .Where(itm => oldEntities.ContainsKey(itm.Key) == false |
| 265 | + || oldEntities[itm.Key] != itm.Value) |
| 266 | + .Select(itm => new |
| 267 | + { |
| 268 | + Name = itm.Key, |
| 269 | + From = oldEntities.ContainsKey(itm.Key) ? oldEntities[itm.Key] : "default", |
| 270 | + To = itm.Value, |
| 271 | + Script = new DatabaseScriptContainer(new DatabaseScript($".alter follower database {newState.DatabaseName} {kustoType} {itm.Key} policy caching hot = {itm.Value}", 0), $"FollowerChange{type}CachingPolicies") |
| 272 | + }) |
| 273 | + .ToList(); |
| 274 | + |
| 275 | + if (removedPolicyScripts.Any()) |
| 276 | + { |
| 277 | + result.Add(new Heading($"Deleted {type} Caching Policies")); |
| 278 | + |
| 279 | + var deletedPolicies = string.Join("\n", removedPolicyScripts.Select(itm => $"* {itm.Name}")); |
| 280 | + |
| 281 | + result.Add(new BasicChange( |
| 282 | + "FollowerDatabase", |
| 283 | + $"Delete{type}CachingPolicy", |
| 284 | + deletedPolicies, |
| 285 | + removedPolicyScripts.Select(itm => itm.Script).ToList())); |
| 286 | + } |
| 287 | + if (changedPolicyScripts.Any()) |
| 288 | + { |
| 289 | + result.Add(new Heading($"Changed {type} Caching Policies")); |
| 290 | + |
| 291 | + var changePolicies = new StringBuilder(); |
| 292 | + changePolicies.AppendLine($"{type} | From | To"); |
| 293 | + foreach (var change in changedPolicyScripts) |
| 294 | + { |
| 295 | + changePolicies.AppendLine($"{change.Name} | {change.From} | {change.To}"); |
| 296 | + } |
| 297 | + |
| 298 | + result.Add(new BasicChange( |
| 299 | + "FollowerDatabase", |
| 300 | + $"Change{type}CachingPolicy", |
| 301 | + changePolicies.ToString(), |
| 302 | + changedPolicyScripts.Select(itm => itm.Script).ToList())); |
| 303 | + } |
| 304 | + |
| 305 | + return result; |
| 306 | + } |
178 | 307 | } |
179 | 308 |
|
180 | 309 | } |
0 commit comments