public async Task <IClusterNode> GetUnassignedNodeAsync(HostEndpoint endpoint) { var dnsResolver = ServiceProvider.GetRequiredService <IDnsResolver>(); var ipAddress = await dnsResolver.GetIpAddressAsync(endpoint.Host, CancellationToken).ConfigureAwait(false); return(Nodes.FirstOrDefault( x => !x.IsAssigned && x.EndPoint.Address.Equals(ipAddress))); }
public void GetEndPoint_WithoutPort_ExpectedResult(string server, string expectedHost) { // Act var(hostName, port) = HostEndpoint.Parse(server); // Assert Assert.Equal(expectedHost, hostName); Assert.Null(port); }
public async Task <IClusterNode> CreateAndConnectAsync(HostEndpoint endPoint, CancellationToken cancellationToken = default) { var ipEndPoint = await _ipEndPointService.GetIpEndPointAsync(endPoint.Host, endPoint.Port.GetValueOrDefault(), cancellationToken).ConfigureAwait(false); var clusterNode = new ClusterNode(_clusterContext, _connectionPoolFactory, _logger, _transcoder, _circuitBreaker, _saslMechanismFactory, _redactor, ipEndPoint) { BootstrapEndpoint = endPoint }; //ensure server calls are made to set the state await clusterNode.InitializeAsync().ConfigureAwait(false); return(clusterNode); }
public async Task <IClusterNode> CreateAndConnectAsync(HostEndpoint endPoint, BucketType bucketType, NodeAdapter?nodeAdapter, CancellationToken cancellationToken = default) { var ipEndPoint = await _ipEndPointService.GetIpEndPointAsync(endPoint.Host, endPoint.Port.GetValueOrDefault(), cancellationToken).ConfigureAwait(false); //for recording k/v latencies per request var valueRecorder = _meter.ValueRecorder(OuterRequestSpans.ServiceSpan.Kv.Name); var clusterNode = new ClusterNode(_clusterContext, _connectionPoolFactory, _logger, _operationBuilderPool, _circuitBreaker, _saslMechanismFactory, _redactor, ipEndPoint, bucketType, nodeAdapter, _tracer, valueRecorder) { BootstrapEndpoint = endPoint }; //ensure server calls are made to set the state await clusterNode.InitializeAsync().ConfigureAwait(false); return(clusterNode); }
public async Task ScopeAsync_Throws_NotSupportedException_When_Name_Is_Not_Default() { var localhost = HostEndpoint.Parse("10.112.192.102:8091"); var bucketConfig = ResourceHelper.ReadResource("mycache.json", InternalSerializationContext.Default.BucketConfig); bucketConfig.Nodes.RemoveAt(1); var mockClusterNode = new Mock <IClusterNode>(); mockClusterNode.Setup(x => x.EndPoint).Returns(new HostEndpointWithPort("127.0.0.1", 8091)); mockClusterNode.Setup(x => x.SelectBucketAsync(It.IsAny <string>(), It.IsAny <CancellationToken>())).Returns(Task.CompletedTask); var mockHttpClusterMap = new Mock <HttpClusterMapBase>(); mockHttpClusterMap.Setup(x => x.GetClusterMapAsync("default", localhost, CancellationToken.None)). Returns(Task.FromResult(bucketConfig)); var bucket = CreateMemcachedBucket(); await bucket.BootstrapAsync(mockClusterNode.Object).ConfigureAwait(false); Assert.Throws <NotSupportedException>(() => bucket.Scope("xxxx")); }
private async IAsyncEnumerable <IPEndPoint> GetIpEndPointsAsync(IEnumerable <string> serverList, [EnumeratorCancellation] CancellationToken cancellationToken) { foreach (var server in serverList) { var(hostName, port) = HostEndpoint.Parse(server); if (port == null) { // Should not happen with data from BucketConfig ThrowHelper.ThrowInvalidOperationException("Server list is missing port numbers."); } var ipEndPoint = await _ipEndPointService.GetIpEndPointAsync(hostName, port.Value, cancellationToken) .ConfigureAwait(false); if (ipEndPoint == null) { ThrowHelper.ThrowArgumentException($"Unable to resolve '{server}'.", nameof(serverList)); } yield return(ipEndPoint); } }
public Task <IClusterNode> CreateAndConnectAsync(HostEndpoint endPoint, BucketType bucketType, CancellationToken cancellationToken = default) { return(CreateAndConnectAsync(endPoint, bucketType, null, cancellationToken)); }
public async Task BootstrapGlobalAsync() { if (ClusterOptions.ConnectionStringValue == null) { throw new InvalidOperationException("ConnectionString has not been set."); } if (ClusterOptions.ConnectionStringValue.IsValidDnsSrv()) { try { // Always try to use DNS SRV to bootstrap if connection string is valid // It can be disabled by returning an empty URI list from IDnsResolver var dnsResolver = ServiceProvider.GetRequiredService <IDnsResolver>(); var bootstrapUri = ClusterOptions.ConnectionStringValue.GetDnsBootStrapUri(); var servers = (await dnsResolver.GetDnsSrvEntriesAsync(bootstrapUri, CancellationToken).ConfigureAwait(false)).ToList(); if (servers.Any()) { _logger.LogInformation( $"Successfully retrieved DNS SRV entries: [{_redactor.SystemData(string.Join(",", servers))}]"); ClusterOptions.ConnectionStringValue = new ConnectionString(ClusterOptions.ConnectionStringValue, servers); } } catch (Exception exception) { _logger.LogInformation(exception, "Error trying to retrieve DNS SRV entries."); } } //Try to bootstrap each node in the servers list - either from DNS-SRV lookup or from client configuration foreach (var server in ClusterOptions.ConnectionStringValue.GetBootstrapEndpoints(ClusterOptions.EnableTls)) { _logger.LogDebug("Bootstrapping with node {server}", server.Host); var node = await _clusterNodeFactory. CreateAndConnectAsync(server, BucketType.Couchbase, CancellationToken). ConfigureAwait(false); try { GlobalConfig = await node.GetClusterMap().ConfigureAwait(false); } catch (CouchbaseException e) { if (e.Context is KeyValueErrorContext ctx) { if (ctx.Status == ResponseStatus.BucketNotConnected) { AddNode(node); //GCCCP is not supported - pre-6.5 server fall back to CCCP like SDK 2 return; } } } try { //Server is 6.5 and greater and supports GC3P so loop through the global config and //create the nodes that are not associated with any buckets via Select Bucket. GlobalConfig.IsGlobal = true; GlobalConfig.NetworkResolution = ClusterOptions.NetworkResolution; foreach (var nodeAdapter in GlobalConfig.GetNodes()) //Initialize cluster nodes for global services { //log any alternate address mapping _logger.LogInformation(nodeAdapter.ToString()); if (server.Host.Equals(nodeAdapter.Hostname)) //this is the bootstrap node so update { node.NodesAdapter = nodeAdapter; SupportsCollections = node.Supports(ServerFeatures.Collections); AddNode(node); } else { var hostEndpoint = HostEndpoint.Create(nodeAdapter, ClusterOptions); var newNode = await _clusterNodeFactory .CreateAndConnectAsync(hostEndpoint, BucketType.Couchbase, nodeAdapter, CancellationToken).ConfigureAwait(false); SupportsCollections = node.Supports(ServerFeatures.Collections); AddNode(newNode); } } } catch (Exception e) { _logger.LogDebug("Attempted bootstrapping on endpoint {endpoint} has failed.", e, server); } } }
public IClusterNode GetUnassignedNode(HostEndpoint endpoint, BucketType bucketType) { return(Nodes.FirstOrDefault( x => !x.IsAssigned && x.BootstrapEndpoint.Equals(endpoint) && x.BucketType == bucketType)); }
public override async Task <BucketConfig> GetClusterMapAsync(string bucketName, HostEndpoint hostEndpoint, CancellationToken cancellationToken) { var uri = new UriBuilder { Scheme = _context.ClusterOptions.EffectiveEnableTls ? Uri.UriSchemeHttps : Uri.UriSchemeHttp, Host = hostEndpoint.Host, Port = _context.ClusterOptions.EffectiveEnableTls ? _context.ClusterOptions.BootstrapHttpPortTls : _context.ClusterOptions.BootstrapHttpPort, Path = Path + bucketName }; using (var response = await _httpClient.GetAsync(uri.Uri, cancellationToken).ConfigureAwait(false)) { response.EnsureSuccessStatusCode(); var json = await response.Content.ReadAsStringAsync().ConfigureAwait(false); var bucketConfig = JsonConvert.DeserializeObject <BucketConfig>(json); bucketConfig.ReplacePlaceholderWithBootstrapHost(uri.Host); return(bucketConfig); } }
public abstract Task <BucketConfig> GetClusterMapAsync(string bucketName, HostEndpoint hostEndpoint, CancellationToken cancellationToken);
public async Task <IConnection> CreateAndConnectAsync(IPEndPoint endPoint, HostEndpoint hostEndpoint, CancellationToken cancellationToken = default) { var socket = new Socket(endPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp); try { var connectTask = socket.ConnectAsync(endPoint); var whichTask = await Task .WhenAny(connectTask, Task.Delay(_clusterOptions.KvConnectTimeout, cancellationToken)) .ConfigureAwait(false); if (whichTask != connectTask) { // Was a timeout const int connectionTimedOut = 10060; throw new SocketException(connectionTimedOut); } } catch { socket.Dispose(); throw; } #if NETCOREAPP_GTE_3_0 _multiplexLogger.LogDebug("Setting TCP Keep-Alives using SocketOptions - enable keep-alives {EnableTcpKeepAlives}, time {TcpKeepAliveTime}, interval {TcpKeepAliveInterval}.", _clusterOptions.EnableTcpKeepAlives, _clusterOptions.TcpKeepAliveTime, _clusterOptions.TcpKeepAliveInterval); if (!socket.TryEnableKeepAlives(_clusterOptions.EnableTcpKeepAlives, (int)_clusterOptions.TcpKeepAliveTime.TotalSeconds, (int)_clusterOptions.TcpKeepAliveInterval.TotalSeconds, out string setKeepAliveMessage) ) { _multiplexLogger.LogWarning(setKeepAliveMessage); } #else _multiplexLogger.LogDebug( "Setting TCP Keep-Alives using Socket.IOControl on {endpoint} - enable tcp keep-alives {EnableTcpKeepAlives}, time {TcpKeepAliveTime}, interval {TcpKeepAliveInterval}", endPoint, _clusterOptions.EnableTcpKeepAlives, _clusterOptions.TcpKeepAliveTime, _clusterOptions.TcpKeepAliveInterval); if (!socket.TrySetKeepAlives(_clusterOptions.EnableTcpKeepAlives, (uint)_clusterOptions.TcpKeepAliveTime.TotalMilliseconds, (uint)_clusterOptions.TcpKeepAliveInterval.TotalMilliseconds, out var setKeepAliveMessage) ) { _multiplexLogger.LogWarning(setKeepAliveMessage); } #endif if (_clusterOptions.EffectiveEnableTls) { var sslStream = new SslStream(new NetworkStream(socket, true), false, _clusterOptions.KvCertificateCallbackValidation); //Check if were using x509 auth, if so fetch the certificates X509Certificate2Collection?certs = null; if (_clusterOptions.X509CertificateFactory != null) { certs = _clusterOptions.X509CertificateFactory.GetCertificates(); if (certs == null || certs.Count == 0) { throw new AuthenticationException( "No certificates matching the X509FindType and specified FindValue were found in the Certificate Store."); } if (_sslLogger.IsEnabled(LogLevel.Debug)) { foreach (var cert in certs) { _sslLogger.LogDebug("Cert sent {cert.FriendlyName} - Thumbprint {cert.Thumbprint}", cert.FriendlyName, cert.Thumbprint); } _sslLogger.LogDebug("Sending {certs.Count} certificates to the server.", certs.Count); } } //The endpoint we are connecting to var targetHost = _clusterOptions.ForceIpAsTargetHost ? endPoint.Address.ToString() : hostEndpoint.Host; //create the sslstream with appropriate authentication await sslStream.AuthenticateAsClientAsync(targetHost, certs, SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12, _clusterOptions.EnableCertificateRevocation) .ConfigureAwait(false); var isSecure = sslStream.IsAuthenticated && sslStream.IsSigned && sslStream.IsEncrypted; _sslLogger.LogDebug("IsAuthenticated {0} on {1}", sslStream.IsAuthenticated, targetHost); _sslLogger.LogDebug("IsSigned {0} on {1}", sslStream.IsSigned, targetHost); _sslLogger.LogDebug("IsEncrypted {0} on {1}", sslStream.IsEncrypted, targetHost); //punt if we cannot successfully authenticate if (!isSecure) { throw new AuthenticationException($"The SSL/TLS connection could not be authenticated on [{targetHost}]."); } return(new SslConnection(sslStream, socket.LocalEndPoint, socket.RemoteEndPoint, _sslLogger, _multiplexLogger)); } return(new MultiplexingConnection(socket, _multiplexLogger)); }
public async Task BootstrapGlobalAsync() { if (ClusterOptions.ConnectionStringValue == null) { throw new InvalidOperationException("ConnectionString has not been set."); } if (ClusterOptions.ConnectionStringValue.IsValidDnsSrv()) { try { // Always try to use DNS SRV to bootstrap if connection string is valid // It can be disabled by returning an empty URI list from IDnsResolver var dnsResolver = ServiceProvider.GetRequiredService <IDnsResolver>(); var bootstrapUri = ClusterOptions.ConnectionStringValue.GetDnsBootStrapUri(); var servers = (await dnsResolver.GetDnsSrvEntriesAsync(bootstrapUri, CancellationToken).ConfigureAwait(false)).ToList(); if (servers.Any()) { _logger.LogInformation( $"Successfully retrieved DNS SRV entries: [{_redactor.SystemData(string.Join(",", servers))}]"); ClusterOptions.ConnectionStringValue = new ConnectionString(ClusterOptions.ConnectionStringValue, servers); } } catch (Exception exception) { _logger.LogInformation(exception, "Error trying to retrieve DNS SRV entries."); } } foreach (var server in ClusterOptions.ConnectionStringValue.GetBootstrapEndpoints(ClusterOptions.EnableTls)) { var node = await _clusterNodeFactory.CreateAndConnectAsync(server, CancellationToken).ConfigureAwait(false); GlobalConfig = await node.GetClusterMap().ConfigureAwait(false); if (GlobalConfig == null) { AddNode(node); //GCCCP is not supported - pre-6.5 server fall back to CCCP like SDK 2 } else { GlobalConfig.IsGlobal = true; foreach (var nodeAdapter in GlobalConfig.GetNodes()) //Initialize cluster nodes for global services { if (server.Host.Equals(nodeAdapter.Hostname)) //this is the bootstrap node so update { node.NodesAdapter = nodeAdapter; SupportsCollections = node.Supports(ServerFeatures.Collections); AddNode(node); } else { var hostEndpoint = HostEndpoint.Create(nodeAdapter, ClusterOptions); var newNode = await _clusterNodeFactory.CreateAndConnectAsync(hostEndpoint, CancellationToken).ConfigureAwait(false); newNode.NodesAdapter = nodeAdapter; SupportsCollections = node.Supports(ServerFeatures.Collections); AddNode(newNode); } } } } }
public Task <IConnection> CreateAndConnectAsync(IPEndPoint endPoint, HostEndpoint hostEndpoint, CancellationToken cancellationToken = default) { return(Task.FromResult <IConnection>(new MockConnection())); }