Пример #1
0
        /// <summary>
        /// Lists the traffic manager rules.
        /// </summary>
        /// <param name="predicate">Optional predicate used to filter the output rules.</param>
        /// <returns>The <see cref="IEnumerable{T}"/> of traffic manager rules.</returns>
        public IEnumerable <TrafficRule> ListRules(Func <TrafficRule, bool> predicate = null)
        {
            var rulesResponse = hive.Consul.Client.KV.ListOrDefault <JObject>($"{proxyManagerPrefix}/conf/{Name}/rules/").Result;

            if (rulesResponse != null)
            {
                var rules = new List <TrafficRule>();

                foreach (var rulebject in rulesResponse)
                {
                    var rule = TrafficRule.ParseJson(rulebject.ToString());

                    if (predicate == null || predicate(rule))
                    {
                        rules.Add(rule);
                    }
                }

                return(rules);
            }
            else
            {
                return(new TrafficRule[0]);
            }
        }
Пример #2
0
        /// <summary>
        /// Validates the header.
        /// </summary>
        /// <param name="context">The validation context.</param>
        /// <param name="rule">The parent rule.</param>
        public void Validate(TrafficValidationContext context, TrafficRule rule)
        {
            if (string.IsNullOrWhiteSpace(Name))
            {
                context.Error($"Rule [{rule.Name}] specifies a NULL or empty [{nameof(TrafficCheckHeader)}.{nameof(TrafficCheckHeader.Name)}].");
            }

            foreach (var ch in Name)
            {
                if (char.IsLetterOrDigit(ch) || ch == '-' || ch == '_')
                {
                    continue;
                }

                context.Error($"Rule [{rule.Name}] specifies a [{nameof(TrafficCheckHeader)}.{nameof(TrafficCheckHeader.Name)}] with the invalid character [{ch}].");
                break;
            }

            if (string.IsNullOrWhiteSpace(Value))
            {
                context.Error($"Rule [{rule.Name}] specifies a NULL [{nameof(TrafficCheckHeader)}.{nameof(TrafficCheckHeader.Value)}].");
            }

            // $todo(jeff.lill):
            //
            // We could try to validate the [Value] property too (e.g. to ensure that it doesn't include "\r\n") but
            // that could be overly restrictive if I'm not careful.  I'm going to leave this be for now.
        }
Пример #3
0
        /// <summary>
        /// Validates the frontend.
        /// </summary>
        /// <param name="context">The validation context.</param>
        /// <param name="rule">The parent rule.</param>
        public void Validate(TrafficValidationContext context, TrafficRule rule)
        {
            // Verify [MaxConnections]

            if (MaxConnections < 0)
            {
                context.Error($"Rule [{rule.Name}] specifies invalid [{nameof(MaxConnections)}={MaxConnections}].");
            }
        }
Пример #4
0
        /// <summary>
        /// Returns a traffic manager rule if it exists.
        /// </summary>
        /// <param name="ruleName">The rule name.</param>
        /// <returns>The <see cref="TrafficRule"/> or <c>null</c>.</returns>
        public TrafficRule GetRule(string ruleName)
        {
            Covenant.Requires <ArgumentException>(HiveDefinition.IsValidName(ruleName));

            var ruleKey = GetProxyRuleKey(ruleName);

            if (hive.Consul.Client.KV.Exists(ruleKey).Result)
            {
                return(TrafficRule.ParseJson(hive.Consul.Client.KV.GetString(ruleKey).Result));
            }
            else
            {
                return(null);
            }
        }
Пример #5
0
        /// <summary>
        /// Adds or updates a traffic manager rule.
        /// </summary>
        /// <param name="rule">The rule definition.</param>
        /// <param name="deferUpdate">
        /// <para>
        /// Optionally defers expicitly notifying the <b>neon-proxy-manager</b> of the
        /// change until <see cref="Update()"/> is called or the <b>neon-proxy-manager</b>
        /// performs the periodic check for changes (which defaults to 60 seconds).  You
        /// may consider passing <paramref name="deferUpdate"/><c>=true</c> when you are
        /// modifying a multiple rules at the same time to avoid making the proxy manager
        /// and proxy instances handle each rule change individually.
        /// </para>
        /// <para>
        /// Instead, you could pass <paramref name="deferUpdate"/><c>=true</c> for all of
        /// the rule changes and then call <see cref="Update()"/> afterwards.
        /// </para>
        /// </param>
        /// <returns>
        /// <c>true</c> if it existed and was updated, <b>false</b>
        /// if the traffic manager rule didn't already exist and was added.
        /// </returns>
        /// <exception cref="HiveDefinitionException">Thrown if the rule is not valid.</exception>
        public bool SetRule(TrafficRule rule, bool deferUpdate = false)
        {
            Covenant.Requires <ArgumentNullException>(rule != null);
            Covenant.Requires <ArgumentNullException>(HiveDefinition.IsValidName(rule.Name));

            if (!IsPublic)
            {
                // Ensure that the [PublicPort] is disabled for non-public rules
                // just to be absolutely sure that these endpoints are not exposed
                // to the Internet for cloud deployments and to avoid operators
                // being freaked out if they see a non-zero port here.

                var httpRule = rule as TrafficHttpRule;

                if (httpRule != null)
                {
                    foreach (var frontEnd in httpRule.Frontends)
                    {
                        frontEnd.PublicPort = 0;
                    }
                }
                else
                {
                    var tcpRule = rule as TrafficTcpRule;

                    if (tcpRule != null)
                    {
                        foreach (var frontEnd in tcpRule.Frontends)
                        {
                            frontEnd.PublicPort = 0;
                        }
                    }
                }
            }

            // $todo(jeff.lill):
            //
            // We're going to minimially ensure that the rule is valid.  It would
            // be better to do full server side validation.

            var context = new TrafficValidationContext(Name, GetSettings())
            {
                ValidateCertificates = false,   // Disable this because we didn't download the certs.
                ValidateResolvers    = false
            };

            rule.Validate(context);
            context.ThrowIfErrors();

            // Publish the rule.

            var ruleKey = GetProxyRuleKey(rule.Name);
            var update  = hive.Consul.Client.KV.Exists(ruleKey).Result;

            // Load the full proxy definition and hive certificates, add/replace
            // the rule being set and then verify that the rule is OK.

            var proxyDefinition = GetDefinition();
            var certificates    = hive.Certificate.GetAll();

            proxyDefinition.Rules[rule.Name] = rule;
            proxyDefinition.Validate(certificates);

            var validationContext = proxyDefinition.Validate(certificates);

            validationContext.ThrowIfErrors();

            // Save the rule to the hive and signal that the
            // load balancers need to be updated.

            hive.Consul.Client.KV.PutObject(ruleKey, rule, Formatting.Indented).Wait();

            if (!deferUpdate)
            {
                Update();
            }

            return(update);
        }