예제 #1
0
        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")})");
        }
예제 #2
0
        public async Task ProcessRecord(string zoneId, ResourceRecordSet record, Amazon.EC2.Model.Instance instance,
                                        bool enabled,
                                        string name,
                                        long ttl,
                                        string address)
        {
            if (!enabled)
            {
                if (record == null)
                {
                    Log($"No need to destroy, record '{name}' does not exists for zone '{zoneId}'. Tags Origin: EC2 Instance {instance.InstanceId} ({instance.GetTagValueOrDefault("Name")})");
                    return; //no need to update, record does not exist
                }
                else
                {
                    Log($"Destroying record {record.Name} linked to EC2 Instance {instance.InstanceId} ({instance.GetTagValueOrDefault("Name")})...");
                    await _R53.DestroyRecord(zoneId, record.Name, record.Type);
                }

                return;
            }

            if (record?.Type == RRType.A &&
                record?.ResourceRecords.Any(r => r.Value == address) == true &&
                record?.TTL == ttl)
            {
                Log($"Correct record already exists for EC2 Instance {instance.InstanceId} ({instance.GetTagValueOrDefault("Name")})");
                return; //no need to update, correct record already exists
            }

            Log($"Updating record of EC2 Instance {instance.InstanceId} ({instance.GetTagValueOrDefault("Name")}), Old Record Name: '{record?.Name}'...");
            await _R53.UpsertRecordAsync(
                zoneId : zoneId,
                Name : name,
                Value : address,
                Type : RRType.A,
                TTL : ttl);
        }
예제 #3
0
        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}");
        }