/// <summary> /// Constructor /// </summary> /// <param name="options">options to initialize</param> public EtcdClient(EtcdClientOpitions options) { if (options == null) throw new ArgumentNullException("options"); if (options.Urls == null || options.Urls.Length == 0) throw new ArgumentException("`EtcdClientOpitions.Urls` does not contain valid url"); WebRequestHandler handler = new WebRequestHandler() { UseProxy = options.UseProxy, AllowAutoRedirect = false, AllowPipelining = true, CachePolicy = new HttpRequestCachePolicy(HttpRequestCacheLevel.NoCacheNoStore), }; if (options.X509Certificate != null) handler.ClientCertificates.Add(options.X509Certificate); AuthenticationHeaderValue authenticationHeaderValue = null; if( !string.IsNullOrWhiteSpace(options.Username) && !string.IsNullOrWhiteSpace(options.Password) ) { string auth = string.Format("{0}:{1}", options.Username, options.Password); authenticationHeaderValue = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(ASCIIEncoding.ASCII.GetBytes(auth))); } _jsonDeserializer = options.JsonDeserializer == null ? new DefaultJsonDeserializer() : options.JsonDeserializer; if (options.IgnoreCertificateError) handler.ServerCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) => { return true; }; HttpClientEx [] httpClients = options.Urls.Select(u => { if (string.IsNullOrWhiteSpace(u)) throw new ArgumentNullException("`urls` array contains empty url"); HttpClientEx httpClient = new HttpClientEx(handler); httpClient.BaseAddress = new Uri(u); httpClient.DefaultRequestHeaders.Authorization = authenticationHeaderValue; return httpClient; }).ToArray(); // make the clients as a ring, so that we can try the next one when one fails if( httpClients.Length > 1 ) { for( int i = httpClients.Length - 2; i >= 0; i--) { httpClients[i].Next = httpClients[i + 1]; } } httpClients[httpClients.Length - 1].Next = httpClients[0]; // pick a client randomly _currentClient = httpClients[DateTime.UtcNow.Ticks % httpClients.Length]; }
/// <summary> /// Constructor /// </summary> /// <param name="options">options to initialize</param> public EtcdClient(EtcdClientOpitions options) { if (options == null) { throw new ArgumentNullException("options"); } if (options.Urls == null || options.Urls.Length == 0) { throw new ArgumentException("`EtcdClientOpitions.Urls` does not contain valid url"); } #if NET45 WebRequestHandler handler = new WebRequestHandler() { UseProxy = options.UseProxy, AllowAutoRedirect = false, AllowPipelining = true, CachePolicy = new HttpRequestCachePolicy(HttpRequestCacheLevel.NoCacheNoStore), }; if (options.X509Certificate != null) { handler.ClientCertificates.Add(options.X509Certificate); } #endif AuthenticationHeaderValue authenticationHeaderValue = null; if (!string.IsNullOrWhiteSpace(options.Username) && !string.IsNullOrWhiteSpace(options.Password)) { string auth = string.Format("{0}:{1}", options.Username, options.Password); authenticationHeaderValue = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(ASCIIEncoding.ASCII.GetBytes(auth))); } _jsonDeserializer = options.JsonDeserializer == null ? new DefaultJsonDeserializer() : options.JsonDeserializer; #if NET45 if (options.IgnoreCertificateError) { handler.ServerCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) => { return(true); } } ; #endif HttpClientEx [] httpClients = options.Urls.Select(u => { if (string.IsNullOrWhiteSpace(u)) { throw new ArgumentNullException("`urls` array contains empty url"); } #if NET45 HttpClientEx httpClient = new HttpClientEx(handler); #else HttpClientEx httpClient = new HttpClientEx(); #endif httpClient.BaseAddress = new Uri(u); httpClient.DefaultRequestHeaders.Authorization = authenticationHeaderValue; return(httpClient); }).ToArray(); // make the clients as a ring, so that we can try the next one when one fails if (httpClients.Length > 1) { for (int i = httpClients.Length - 2; i >= 0; i--) { httpClients[i].Next = httpClients[i + 1]; } } httpClients[httpClients.Length - 1].Next = httpClients[0]; // pick a client randomly _currentClient = httpClients[DateTime.UtcNow.Ticks % httpClients.Length]; }
static async Task DoSample() { EtcdClientOpitions options = new EtcdClientOpitions() { Urls = new string[] { "https://etcd0.em", "https://etcd1.em", "https://etcd2.em" }, Username = "******", Password = "******", UseProxy = false, IgnoreCertificateError = true, // If the ectd server is running with self-signed SSL certificate and we can ignore the SSL error //X509Certificate = new X509Certificate2(@"client.p12"), // client cerificate JsonDeserializer = new NewtonsoftJsonDeserializer(), }; EtcdClient etcdClient = new EtcdClient(options); string key = "/my/key"; string value; // query the value of the node using GetNodeValueAsync try { value = await etcdClient.GetNodeValueAsync(key); Console.WriteLine("The value of `{0}` is `{1}`", key, value); } catch(EtcdCommonException.KeyNotFound) { Console.WriteLine("Key `{0}` does not exist", key); } // update the value using SetNodeAsync EtcdResponse resp = await etcdClient.SetNodeAsync(key, "some value"); Console.WriteLine("Key `{0}` is changed, modifiedIndex={1}", key, resp.Node.ModifiedIndex); // query the node using GetNodeAsync resp = await etcdClient.GetNodeAsync(key, ignoreKeyNotFoundException: true); if (resp == null || resp.Node == null) Console.WriteLine("Key `{0}` does not exist", key); else Console.WriteLine("The value of `{0}` is `{1}`", key, resp.Node.Value); ////////////////////////////////////////////////////////// List<Task<EtcdResponse>> tasks = new List<Task<EtcdResponse>>(); key = "/in-order-queue"; // start monitoring the expire event WatchChanges(etcdClient, key); // create 5 in-order nodes, TTL = 3 second for (int i = 0; i < 5; i++) { tasks.Add( etcdClient.CreateInOrderNodeAsync(key, i.ToString(), ttl: 3) ); } await Task.WhenAll(tasks); // list the in-order nodes resp = await etcdClient.GetNodeAsync(key, false, recursive: true, sorted:true); if (resp.Node.Nodes != null) { foreach (var node in resp.Node.Nodes) { Console.WriteLine("`{0}` = {1}", node.Key, node.Value); } } ///////////////////////////////////////////////////////////// key = "/my/cas-test"; value = Guid.NewGuid().ToString(); try { resp = await etcdClient.CreateNodeAsync(key, value, null, dir : false); Console.WriteLine("Key `{0}` is created with value {1}", key, value); } catch (EtcdCommonException.NodeExist) { Console.WriteLine("Key `{0}` already exists", key); } long prevIndex = 1; try { resp = await etcdClient.CompareAndSwapNodeAsync(key, value, "new value"); Console.WriteLine("Key `{0}` is updated to `{1}`", key, resp.Node.Value); prevIndex = resp.Node.ModifiedIndex; } catch (EtcdCommonException.KeyNotFound) { Console.WriteLine("Key `{0}` does not exists", key); } catch (EtcdCommonException.TestFailed) { Console.WriteLine("Key `{0}` can not be updated because the supplied previous value is incorrect", key); } try { resp = await etcdClient.CompareAndSwapNodeAsync(key, prevIndex, "new value2"); Console.WriteLine("Key `{0}` is updated to `{1}`", key, resp.Node.Value); } catch (EtcdCommonException.KeyNotFound) { Console.WriteLine("Key `{0}` does not exists", key); } catch (EtcdCommonException.TestFailed) { Console.WriteLine("Key `{0}` can not be updated because the supplied previous index is incorrect", key); } try { resp = await etcdClient.CompareAndDeleteNodeAsync(key, prevIndex+1); Console.WriteLine("Key `{0}` is deleted", key); } catch (EtcdCommonException.KeyNotFound) { Console.WriteLine("Key `{0}` does not exists", key); } catch (EtcdCommonException.TestFailed) { Console.WriteLine("Key `{0}` can not be deleted because the supplied previous index is incorrect", key); } if (prevIndex == 1) // the previous CAS failed { try { resp = await etcdClient.CompareAndDeleteNodeAsync(key, "new value2"); Console.WriteLine("Key `{0}` is deleted", key); } catch (EtcdCommonException.KeyNotFound) { Console.WriteLine("Key `{0}` does not exists", key); } catch (EtcdCommonException.TestFailed) { Console.WriteLine("Key `{0}` can not be deleted because the supplied previous value is incorrect", key); etcdClient.DeleteNodeAsync(key, ignoreKeyNotFoundException: true).Wait(); } } }