public async Task Process(Dictionary <HostedZone, ResourceRecordSet[]> zones, Amazon.EC2.Model.Instance instance) { Log($"Processing and Veryfying Route53 Recors for EC2 Instance {instance.InstanceId}, Name: {instance.GetTagValueOrDefault("Name")}"); var disableAll = instance.GetTagValueOrDefault("Route53 Disable All").ToBoolOrDefault(false); await ParallelEx.ForAsync(0, _maxRoutesPerInstance, async i => { var suffix = i == 0 ? "" : $" {i - 1}"; var name = instance.GetTagValueOrDefault($"Route53 Name{suffix}"); var type = instance.GetTagValueOrDefault($"Route53 Address{suffix}").CoalesceNullOrEmpty("public").ToLower(); string address = null; if (type == "public") { address = instance.PublicIpAddress; } else if (type == "private") { address = instance.PrivateIpAddress; } else { Log($"Invalid Tag: 'Route53 Address{suffix}' expected 'public' or 'private' but was '{type}', Tags Origin: EC2 Instance {instance.InstanceId} ({instance.GetTagValueOrDefault("Name")})"); return; } var enabled = !disableAll && //not globally disabled !address.IsNullOrEmpty() && //has valid public or private IP instance.State.Name == InstanceStateName.Running && //instance is running instance.GetTagValueOrDefault($"Route53 Enable{suffix}").ToBoolOrDefault(false); //is locally enabled var zoneId = instance.GetTagValueOrDefault($"Route53 Zone{suffix}"); var ttl = instance.GetTagValueOrDefault($"Route53 TTL{suffix}").ToIntOrDefault(60); if (!name.IsNullOrEmpty() && zones.Any(z => z.Key.Id.Contains(zoneId))) { var zone = zones.First(z => z.Key.Id.Contains(zoneId)); var recordName = $"{name.Trim(' ', '.')}.{zone.Key.Name.Trim(' ', '.')}"; //for whatever reason those names end with dot once they are saved... var record = zone.Value.FirstOrDefault(r => r.Name.Equals($"{recordName}.", StringComparison.InvariantCultureIgnoreCase)); var ex = await ProcessRecord(zoneId, record, instance, enabled, recordName, ttl, address).CatchExceptionAsync(); if (ex != null) { Log($"Failed during Update or Validation of Route53 record for EC2 Instance {instance.InstanceId} ({instance.GetTagValueOrDefault("Name")}), ZoneId: {zoneId}, Name: {name}, Old Record Name: {record?.Name}, Enable: {enabled}, TTL: {ttl}, Address: {address}, Error: {ex.JsonSerializeAsPrettyException()}"); } } }); Log($"Finished Processing and Veryfying Route53 Recors for EC2 Instance {instance.InstanceId} ({instance.GetTagValueOrDefault("Name")})"); }
public async Task Process(Amazon.EC2.Model.Instance instance, ILambdaLogger logger) { if (!instance.Tags.Any(x => x.Key.Contains("Auto"))) { return; } logger.Log($"Processing Update and Tag Validation of EC2 Instance {instance.InstanceId}, Name: {instance.GetTagValueOrDefault("Name")}"); var disableAll = instance.GetTagValueOrDefault("Terminator Disable All").ToBoolOrDefault(false); if (!disableAll) { var targetGroups = instance.GetTagValueOrDefault($"Target Groups") ?? instance.GetTagValueOrDefault($"TG"); var targetGroupsList = new List <(string name, int port)>(); if (!targetGroups.IsNullOrEmpty()) { var arrTGNames = targetGroups.Split(','); var arrTGPorts = targetGroups.Split(','); while (arrTGNames.Length > arrTGPorts.Length) //extrapolate by last or default 80 { arrTGPorts = arrTGPorts.Merge(((arrTGPorts?.Length ?? 0) > 0) ? arrTGPorts[arrTGPorts.Length - 1] : "80"); } while (arrTGPorts.Length > arrTGNames.Length) //extrapolate names by last { arrTGNames = arrTGNames.Merge(arrTGNames[arrTGNames.Length - 1]); } for (int i = 0; i < arrTGNames.Length; i++) { var tg = arrTGNames[i]?.Trim(" ")?.Split(':'); if (tg.IsNullOrEmpty() || tg.Length != 2 || tg[0].IsNullOrWhitespace() || tg[1].IsNullOrWhitespace() || !tg[1].ToIntOrDefault(-1).InClosedInterval(1, 65535)) { logger.Log($"WARINING!!! Invalid Target Groups (TG) Name definition '{(arrTGNames[i] ?? "undefined")}' for instance {instance.InstanceId}."); continue; } targetGroupsList.Add((tg[0].Trim(" "), tg[1].ToInt32())); } } await ParallelEx.ForAsync(0, _maxPeriodsPerInstance, async i => { var suffix = i == 0 ? " 1" : $" {i + 1}"; var disabled = instance.GetTagValueOrDefault($"Terminator Disable{suffix}").ToBoolOrDefault(false); if (disabled) { return; } var cOn = instance.GetTagValueOrDefault($"Auto On{suffix}"); var cOff = instance.GetTagValueOrDefault($"Auto Off{suffix}"); var cKill = instance.GetTagValueOrDefault($"Auto Kill{suffix}"); var cTargetGroupRegister = instance.GetTagValueOrDefault($"Auto TGR{suffix}"); var cTargetGroupDeregister = instance.GetTagValueOrDefault($"Auto TGD{suffix}"); if (cOn.IsNullOrEmpty() && cOff.IsNullOrEmpty() && cKill.IsNullOrEmpty() && cTargetGroupRegister.IsNullOrEmpty() && cTargetGroupDeregister.IsNullOrEmpty()) { return; //skip no instance control tagg's were found } var ex = await ProcessTags(instance, cOn: cOn, cOff: cOff, cKill: cKill, cTargetGroupRegister: cTargetGroupRegister, cTargetGroupDeregister: cTargetGroupDeregister, targetGroups: targetGroupsList, logger: logger).CatchExceptionAsync(); if (ex != null) { logger.Log($"Failed Update or Tag Validation of EC2 Instance {instance.InstanceId} ({instance.GetTagValueOrDefault("Name")}), Auto On: '{cOn}', Auto Off: '{cOff}', Auto Kill: '{cKill}', Exception: {ex.JsonSerializeAsPrettyException()}"); } }); } logger.Log($"Finished Processing and Tag Validation of EC2 Instance {instance.InstanceId} ({instance.GetTagValueOrDefault("Name")}), DisableAll: {disableAll}"); }