示例#1
0
 public static async Task <QueryResult <ConsulEntry <T>[]> > ListAsync <T>(this IKVEndpoint endpoint, string prefix,
                                                                           JsonSerializerSettings settings = default, CancellationToken cancellation = default)
 {
     ConsulEntry <T> Deserialize(KVPair content)
     {
         if (content.Value == null || content.Value.Length == 0)
         {
             return(default);
示例#2
0
        /// <summary>
        /// Writes a byte array value to a Consul key.
        /// </summary>
        /// <param name="kv">The key/value endpoint.</param>
        /// <param name="key">The key.</param>
        /// <param name="value">The value.</param>
        /// <param name="cancellationToken">The optional cancellation token.</param>
        /// <returns><c>true</c> on success.</returns>
        public static async Task <bool> PutBytes(this IKVEndpoint kv, string key, byte[] value, CancellationToken cancellationToken = default)
        {
            Covenant.Requires <ArgumentNullException>(!string.IsNullOrEmpty(key));

            var p = new KVPair(key);

            p.Value = value ?? new byte[0];

            return((await kv.Put(p, cancellationToken)).Response);
        }
        /// <summary>
        ///
        /// </summary>
        /// <typeparam name="TResult"></typeparam>
        /// <param name="kvEndpoint"></param>
        /// <param name="key"></param>
        /// <param name="city"></param>
        /// <param name="company"></param>
        /// <param name="ct"></param>
        /// <returns></returns>
        public static async Task <TResult> GetOrDefaultAsync <TResult>(this IKVEndpoint kvEndpoint, string key, string city = null, string company = null, CancellationToken ct = default(CancellationToken))
        {
            QueryResult <KVPair> queryResult = await kvEndpoint.Get(RequestKey(key, city, company), ct);

            if (queryResult.StatusCode != HttpStatusCode.OK)
            {
                queryResult = await kvEndpoint.Get(RequestKey(key, !string.IsNullOrWhiteSpace(city) ? "default" : null, !string.IsNullOrWhiteSpace(company) ? "default" : null), ct);
            }
            return(queryResult.StatusCode == HttpStatusCode.OK ? JsonConvert.DeserializeObject <TResult>(Encoding.UTF8.GetString(queryResult.Response.Value)) : default(TResult));
        }
示例#4
0
        /// <summary>
        /// Reads and parses a key as a <c>bool</c>, returning <c>false</c> if the key doesn't exist.
        /// </summary>
        /// <param name="kv">The key/value endpoint.</param>
        /// <param name="key">The key.</param>
        /// <param name="cancellationToken">The optional cancellation token.</param>
        /// <returns>The parsed value or <c>false</c>.</returns>
        /// <exception cref="FormatException">Thrown if the value is not valid.</exception>
        /// <remarks>
        /// <note>
        /// Any exceptions thrown will be wrapped within an <see cref="AggregateException"/>.
        /// </note>
        /// </remarks>
        public static async Task <bool> GetBoolOrDefault(this IKVEndpoint kv, string key, CancellationToken cancellationToken = default)
        {
            var value = await GetStringOrDefault(kv, key, cancellationToken);

            if (value == null)
            {
                return(false);
            }

            return(NeonHelper.ParseBool(value));
        }
示例#5
0
        /// <summary>
        /// Reads a key as a string, returning <c>null</c> if the key doesn't exist.
        /// </summary>
        /// <param name="kv">The key/value endpoint.</param>
        /// <param name="key">The key.</param>
        /// <param name="cancellationToken">The optional cancellation token.</param>
        /// <returns>The string value or <c>null</c>.</returns>
        /// <remarks>
        /// <note>
        /// Any exceptions thrown will be wrapped within an <see cref="AggregateException"/>.
        /// </note>
        /// </remarks>
        public static async Task <string> GetStringOrDefault(this IKVEndpoint kv, string key, CancellationToken cancellationToken = default)
        {
            Covenant.Requires <ArgumentNullException>(!string.IsNullOrEmpty(key));

            var response = (await kv.Get(key, cancellationToken)).Response;

            if (response == null)
            {
                return(null);
            }

            return(Encoding.UTF8.GetString(response.Value));
        }
示例#6
0
        /// <summary>
        /// Reads and parses a key as an <c>int</c>, throwing an exception if the key doesn't exist.
        /// </summary>
        /// <param name="kv">The key/value endpoint.</param>
        /// <param name="key">The key.</param>
        /// <param name="cancellationToken">The optional cancellation token.</param>
        /// <returns>The parsed value.</returns>
        /// <exception cref="KeyNotFoundException">Thrown if <paramref name="key"/> could not be found.</exception>
        /// <exception cref="FormatException">Thrown if the value is not valid.</exception>
        /// <remarks>
        /// <note>
        /// Any exceptions thrown will be wrapped within an <see cref="AggregateException"/>.
        /// </note>
        /// </remarks>
        public static async Task <int> GetInt(this IKVEndpoint kv, string key, CancellationToken cancellationToken = default)
        {
            var value = await GetString(kv, key, cancellationToken);

            if (int.TryParse(value, out var parsed))
            {
                return(parsed);
            }
            else
            {
                throw new FormatException($"[{value}] is not a valid integer.");
            }
        }
示例#7
0
        /// <summary>
        /// Reads and parses a key as a <c>double</c>, throwing an exception if the key doesn't exist.
        /// </summary>
        /// <param name="kv">The key/value endpoint.</param>
        /// <param name="key">The key.</param>
        /// <param name="cancellationToken">The optional cancellation token.</param>
        /// <returns>The parsed value.</returns>
        /// <exception cref="KeyNotFoundException">Thrown if <paramref name="key"/> could not be found.</exception>
        /// <exception cref="FormatException">Thrown if the value is not valid.</exception>
        /// <remarks>
        /// <note>
        /// Any exceptions thrown will be wrapped within an <see cref="AggregateException"/>.
        /// </note>
        /// </remarks>
        public static async Task <double> GetDouble(this IKVEndpoint kv, string key, CancellationToken cancellationToken = default)
        {
            var input = await GetString(kv, key, cancellationToken);

            if (double.TryParse(input, NumberStyles.AllowDecimalPoint, NumberFormatInfo.InvariantInfo, out var value))
            {
                return(value);
            }
            else
            {
                throw new FormatException($"[{input}] is not a valid double.");
            }
        }
示例#8
0
        /// <summary>
        /// Reads a key as a byte array, throwing an exception if the key doesn't exist.
        /// </summary>
        /// <param name="kv">The key/value endpoint.</param>
        /// <param name="key">The key.</param>
        /// <param name="cancellationToken">The optional cancellation token.</param>
        /// <returns>The byte array value.</returns>
        /// <exception cref="KeyNotFoundException">Thrown if <paramref name="key"/> could not be found.</exception>
        /// <remarks>
        /// <note>
        /// Any exceptions thrown will be wrapped within an <see cref="AggregateException"/>.
        /// </note>
        /// </remarks>
        public static async Task <byte[]> GetBytes(this IKVEndpoint kv, string key, CancellationToken cancellationToken = default)
        {
            Covenant.Requires <ArgumentNullException>(!string.IsNullOrEmpty(key));

            var response = (await kv.Get(key, cancellationToken)).Response;

            if (response == null)
            {
                throw new KeyNotFoundException(key);
            }

            return(response.Value);
        }
示例#9
0
        /// <summary>
        /// Reads and parses a key as a <c>long</c>, throwing an exception if the key doesn't exist.
        /// </summary>
        /// <param name="kv">The key/value endpoint.</param>
        /// <param name="key">The key.</param>
        /// <param name="cancellationToken">The optional cancellation token.</param>
        /// <returns>The parsed value.</returns>
        /// <exception cref="KeyNotFoundException">Thrown if <paramref name="key"/> could not be found.</exception>
        /// <exception cref="FormatException">Thrown if the value is not valid.</exception>
        public static async Task <long> GetLong(this IKVEndpoint kv, string key, CancellationToken cancellationToken = default)
        {
            var input = await GetString(kv, key, cancellationToken);

            if (long.TryParse(input, out var value))
            {
                return(value);
            }
            else
            {
                throw new FormatException($"[{input}] is not a valid long.");
            }
        }
示例#10
0
        public static Task <WriteResult <bool> > PutAsync <T>(this IKVEndpoint endpoint, string key, T value,
                                                              JsonSerializerSettings settings = default, CancellationToken cancellation = default)
        {
            var json = settings == null
                ? JsonConvert.SerializeObject(value)
                : JsonConvert.SerializeObject(value, settings);

            var utf8Bytes = Encoding.UTF8.GetBytes(json);

            return(endpoint.Put(new KVPair(key)
            {
                Value = utf8Bytes
            }, cancellation));
        }
示例#11
0
        /// <summary>
        /// Reads and deserializes a key with a JSON value as a specified type, throwing an exception if the key doesn't exist.
        /// </summary>
        /// <typeparam name="T">The type to be desearialized.</typeparam>
        /// <param name="kv">The key/value endpoint.</param>
        /// <param name="key">The key.</param>
        /// <param name="cancellationToken">The optional cancellation token.</param>
        /// <returns>The parsed <typeparamref name="T"/>.</returns>
        /// <exception cref="KeyNotFoundException">Thrown if <paramref name="key"/> could not be found.</exception>
        /// <exception cref="FormatException">Thrown if the value is not valid.</exception>
        /// <remarks>
        /// <note>
        /// Any exceptions thrown will be wrapped within an <see cref="AggregateException"/>.
        /// </note>
        /// </remarks>
        public static async Task <T> GetObject <T>(this IKVEndpoint kv, string key, CancellationToken cancellationToken = default)
            where T : new()
        {
            var input = await GetString(kv, key, cancellationToken);

            try
            {
                return(NeonHelper.JsonDeserialize <T>(input));
            }
            catch (Exception e)
            {
                throw new FormatException(e.Message, e);
            }
        }
示例#12
0
        /// <summary>
        /// Writes a string value to a Consul key.
        /// </summary>
        /// <param name="kv">The key/value endpoint.</param>
        /// <param name="key">The key.</param>
        /// <param name="value">The value.</param>
        /// <param name="cancellationToken">The optional cancellation token.</param>
        /// <returns><c>true</c> on success.</returns>
        /// <remarks>
        /// This method writes an empty string for <c>null</c> values and writes
        /// the <see cref="object.ToString()"/> results otherwise.
        /// </remarks>
        public static async Task <bool> PutString(this IKVEndpoint kv, string key, object value, CancellationToken cancellationToken = default)
        {
            Covenant.Requires <ArgumentNullException>(!string.IsNullOrEmpty(key));

            var p = new KVPair(key);

            if (value == null)
            {
                value = string.Empty;
            }

            p.Value = Encoding.UTF8.GetBytes(value.ToString());

            return((await kv.Put(p, cancellationToken)).Response);
        }
示例#13
0
        /// <summary>
        /// Reads and parses a key as a <c>long</c>, returning <c>0</c> if the key doesn't exist.
        /// </summary>
        /// <param name="kv">The key/value endpoint.</param>
        /// <param name="key">The key.</param>
        /// <param name="cancellationToken">The optional cancellation token.</param>
        /// <returns>The parsed value or <c>0</c>.</returns>
        /// <exception cref="FormatException">Thrown if the value is not valid.</exception>
        public static async Task <long> GetLongOrDefault(this IKVEndpoint kv, string key, CancellationToken cancellationToken = default)
        {
            var value = await GetString(kv, key, cancellationToken);

            if (value == null)
            {
                return(0);
            }

            if (long.TryParse(value, out var parsed))
            {
                return(parsed);
            }
            else
            {
                throw new FormatException($"[{value}] is not a valid long.");
            }
        }
示例#14
0
        /// <summary>
        /// Reads and deserializes a key with a JSON value as a specified type, returning the default value
        /// if the key doesn't exist.
        /// </summary>
        /// <typeparam name="T">The type to be desearialized.</typeparam>
        /// <param name="kv">The key/value endpoint.</param>
        /// <param name="key">The key.</param>
        /// <param name="cancellationToken">The optional cancellation token.</param>
        /// <returns>The parsed <typeparamref name="T"/> or <c>default(T)</c>.</returns>
        /// <exception cref="FormatException">Thrown if the value is not valid.</exception>
        /// <remarks>
        /// <note>
        /// Any exceptions thrown will be wrapped within an <see cref="AggregateException"/>.
        /// </note>
        /// </remarks>
        public static async Task <T> GetObjectOrDefault <T>(this IKVEndpoint kv, string key, CancellationToken cancellationToken = default)
            where T : new()
        {
            var value = await GetStringOrDefault(kv, key, cancellationToken);

            if (value == null)
            {
                return(default(T));
            }

            try
            {
                return(NeonHelper.JsonDeserialize <T>(value));
            }
            catch (Exception e)
            {
                throw new FormatException(e.Message, e);
            }
        }
示例#15
0
        /// <summary>
        /// Lists the items beneath a path prefix, returning a dictionary with the keys set
        /// to the item names and the values raw bytes.  An empty list if the key doesn't exist.
        /// The result keys will not include the key prefix.
        /// </summary>
        /// <param name="kv">The key/value endpoint.</param>
        /// <param name="keyPrefix">The path prefix.</param>
        /// <param name="cancellationToken">The optional cancellation token.</param>
        /// <returns>The item dictionary.</returns>
        /// <remarks>
        /// <note>
        /// Any exceptions thrown will be wrapped within an <see cref="AggregateException"/>.
        /// </note>
        /// </remarks>
        public static async Task <IDictionary <string, byte[]> > DictionaryOrEmpty(this IKVEndpoint kv, string keyPrefix, CancellationToken cancellationToken = default)
        {
            Covenant.Requires <ArgumentNullException>(!string.IsNullOrEmpty(keyPrefix));

            var response = (await kv.List(keyPrefix, cancellationToken)).Response;
            var output   = new Dictionary <string, byte[]>();

            if (response == null)
            {
                return(output);
            }

            foreach (var item in response)
            {
                output.Add(StripKeyPrefix(item.Key), item.Value);
            }

            return(output);
        }
示例#16
0
        //---------------------------------------------------------------------
        // IKVEndpoint extensions

        /// <summary>
        /// Determines whether a Consul key exists.
        /// </summary>
        /// <param name="kv">The key/value endpoint.</param>
        /// <param name="key">The key.</param>
        /// <param name="cancellationToken">The optional cancellation token.</param>
        /// <returns><c>true</c> if the key exists.</returns>
        public static async Task <bool> Exists(this IKVEndpoint kv, string key, CancellationToken cancellationToken = default)
        {
            Covenant.Requires <ArgumentNullException>(!string.IsNullOrEmpty(key));

            try
            {
                return((await kv.Get(key, cancellationToken)).Response != null);
            }
            catch (Exception e)
            {
                if (e.Contains <KeyNotFoundException>())
                {
                    return(false);
                }
                else
                {
                    throw;
                }
            }
        }
示例#17
0
        /// <summary>
        /// Lists the items beneath a path prefix and deserializes them as JSON objects, returning
        /// <c>null</c> if the key doesn't exist.
        /// </summary>
        /// <typeparam name="T">The item type.</typeparam>
        /// <param name="kv">The key/value endpoint.</param>
        /// <param name="keyPrefix">The path prefix.</param>
        /// <param name="cancellationToken">The optional cancellation token.</param>
        /// <returns>The item list or <c>null</c>.</returns>
        /// <remarks>
        /// <note>
        /// Any exceptions thrown will be wrapped within an <see cref="AggregateException"/>.
        /// </note>
        /// </remarks>
        public static async Task <IEnumerable <T> > ListOrDefault <T>(this IKVEndpoint kv, string keyPrefix, CancellationToken cancellationToken = default)
            where T : new()
        {
            Covenant.Requires <ArgumentNullException>(!string.IsNullOrEmpty(keyPrefix));

            var response = (await kv.List(keyPrefix, cancellationToken)).Response;

            if (response == null)
            {
                return(null);
            }

            var items = new List <T>(response.Length);

            foreach (var item in response)
            {
                items.Add(NeonHelper.JsonDeserialize <T>(Encoding.UTF8.GetString(item.Value)));
            }

            return(items);
        }
        //try to get value from consul configuration source
        public string GetValue(string key)
        {
            IKVEndpoint kv = this.client?.KV;

            try
            {
                key = key.Replace('.', '/');

                var value = kv.Get(nametag + key)?.Result?.Response?.Value;
                if (value == null)
                {
                    return(null);
                }

                return(Encoding.UTF8.GetString(value, 0, value.Length));
            }
            catch
            {
                _logger.LogInformation($"Unable to get value of key '{nametag + key}'");
                return(null);
            }
        }
 public ConsulKeyValueWatcher(IKVEndpoint keyValueEndpoint, IWatcherConfiguration configuration, ILogger log)
 {
     this.keyValueEndpoint = keyValueEndpoint;
     this.configuration    = configuration;
     this.log = log;
 }
示例#20
0
 /// <summary>
 /// Writes a boolean value to a Consul key.
 /// </summary>
 /// <param name="kv">The key/value endpoint.</param>
 /// <param name="key">The key.</param>
 /// <param name="value">The value.</param>
 /// <param name="cancellationToken">The optional cancellation token.</param>
 /// <returns><c>true</c> on success.</returns>
 public static async Task <bool> PutBool(this IKVEndpoint kv, string key, bool value, CancellationToken cancellationToken = default)
 {
     return(await PutString(kv, key, value? "true" : "false", cancellationToken));
 }
示例#21
0
 public ConfigurationRegister(IConsulClient consulClient)
 {
     _consulClient = consulClient;
     _kvEndpoint   = _consulClient.KV;
 }
示例#22
0
        /// <summary>
        /// Lists the items beneath a path prefix and returns a list of the item keys.
        /// </summary>
        /// <param name="kv">The key/value endpoint.</param>
        /// <param name="keyPrefix">The path prefix or <c>null</c> list the root keys.</param>
        /// <param name="mode">Specifies how the keys are to be listed.  This defaults to <see cref="ConsulListMode.FullKey"/>.</param>
        /// <param name="cancellationToken">The optional cancellation token.</param>
        /// <returns>The items or an empty list if the prefix does not exist.</returns>
        public static async Task <IEnumerable <string> > ListKeys(this IKVEndpoint kv, string keyPrefix = null, ConsulListMode mode = ConsulListMode.FullKey, CancellationToken cancellationToken = default)
        {
            keyPrefix = keyPrefix ?? string.Empty;

            var response = (await kv.List(keyPrefix, cancellationToken)).Response;

            if (response == null)
            {
                return(new string[0]);
            }

            if (mode == ConsulListMode.FullKeyRecursive)
            {
                var items = new List <string>(response.Length);

                foreach (var item in response)
                {
                    items.Add(item.Key);
                }

                return(items);
            }
            else
            {
                var items = new HashSet <string>();
                var prefixWithoutSlash = keyPrefix;

                if (prefixWithoutSlash.EndsWith("/"))
                {
                    prefixWithoutSlash = prefixWithoutSlash.Substring(0, prefixWithoutSlash.Length - 1);
                }

                foreach (var item in response)
                {
                    // Trim off any portion of the listed key below the
                    // prefix, including any forward slash.

                    var key = item.Key;

                    if (key.Length < prefixWithoutSlash.Length)
                    {
                        continue;   // Don't think we'll ever see this, but we'll ignore this to be safe.
                    }

                    if (key.Length > prefixWithoutSlash.Length)
                    {
                        var slashPos = key.IndexOf('/', keyPrefix.Length == 0 ? 0 : prefixWithoutSlash.Length + 1);

                        if (slashPos != -1)
                        {
                            key = key.Substring(0, slashPos);
                        }
                    }

                    if (mode == ConsulListMode.PartialKey)
                    {
                        // Remove the key prefix.

                        key = key.Substring(prefixWithoutSlash.Length + 1);
                    }

                    // We may see multiple subkeys beneath a key at this level,
                    // so we'll use the HashSet to verify that we're returning
                    // any given key just once.

                    if (!items.Contains(key))
                    {
                        items.Add(key);
                    }
                }

                return(items);
            }
        }
示例#23
0
 /// <summary>
 /// Writes a long value to a Consul key.
 /// </summary>
 /// <param name="kv">The key/value endpoint.</param>
 /// <param name="key">The key.</param>
 /// <param name="value">The value.</param>
 /// <param name="cancellationToken">The optional cancellation token.</param>
 /// <returns><c>true</c> on success.</returns>
 public static async Task <bool> PutLong(this IKVEndpoint kv, string key, long value, CancellationToken cancellationToken = default)
 {
     return(await PutString(kv, key, value.ToString(), cancellationToken));
 }
示例#24
0
 /// <summary>
 /// Writes a double value to a Consul key.
 /// </summary>
 /// <param name="kv">The key/value endpoint.</param>
 /// <param name="key">The key.</param>
 /// <param name="value">The value.</param>
 /// <param name="cancellationToken">The optional cancellation token.</param>
 /// <returns><c>true</c> on success.</returns>
 public static async Task <bool> PutDouble(this IKVEndpoint kv, string key, double value, CancellationToken cancellationToken = default)
 {
     return(await PutString(kv, key, value.ToString("R", NumberFormatInfo.InvariantInfo), cancellationToken));
 }
示例#25
0
 /// <summary>
 /// Writes an object value as JSON to a Consul key.
 /// </summary>
 /// <param name="kv">The key/value endpoint.</param>
 /// <param name="key">The key.</param>
 /// <param name="value">The value.</param>
 /// <param name="formatting">Optional JSON formatting (defaults to <b>None</b>).</param>
 /// <param name="cancellationToken">The optional cancellation token.</param>
 /// <returns><c>true</c> on success.</returns>
 public static async Task <bool> PutObject(this IKVEndpoint kv, string key, object value, Formatting formatting = Formatting.None, CancellationToken cancellationToken = default)
 {
     return(await PutString(kv, key, NeonHelper.JsonSerialize(value, formatting), cancellationToken));
 }
示例#26
0
        /// <summary>
        /// Reads and parses a key as a <c>bool</c>, throwing an exception if the key doesn't exist.
        /// </summary>
        /// <param name="kv">The key/value endpoint.</param>
        /// <param name="key">The key.</param>
        /// <param name="cancellationToken">The optional cancellation token.</param>
        /// <returns>The parsed value.</returns>
        /// <exception cref="KeyNotFoundException">Thrown if <paramref name="key"/> could not be found.</exception>
        /// <exception cref="FormatException">Thrown if the value is not valid.</exception>
        /// <remarks>
        /// <note>
        /// Any exceptions thrown will be wrapped within an <see cref="AggregateException"/>.
        /// </note>
        /// </remarks>
        public static async Task <bool> GetBool(this IKVEndpoint kv, string key, CancellationToken cancellationToken = default)
        {
            var value = await GetString(kv, key, cancellationToken);

            return(NeonHelper.ParseBool(value));
        }