public async Task <DesignDocument> GetDesignDocumentAsync(string designDocName, DesignDocumentNamespace @namespace, GetDesignDocumentOptions?options = null) { options ??= GetDesignDocumentOptions.Default; var uri = GetUri(designDocName, @namespace); _logger.LogInformation($"Attempting to get design document {_bucketName}/{designDocName} - {uri}"); try { var result = await _client.GetAsync(uri, options.TokenValue).ConfigureAwait(false); if (result.StatusCode == HttpStatusCode.NotFound) { throw new DesignDocumentNotFoundException(_bucketName, designDocName); } result.EnsureSuccessStatusCode(); var content = await result.Content.ReadAsStringAsync().ConfigureAwait(false); var designDocument = JsonConvert.DeserializeObject <DesignDocument>(content); designDocument.Name = designDocName; return(designDocument); } catch (Exception exception) { _logger.LogError(exception, $"Failed to get design document {_bucketName}/{designDocName} - {uri}"); throw; } }
public async Task <Dictionary <string, BucketSettings> > GetAllBucketsAsync(GetAllBucketsOptions?options = null) { options ??= new GetAllBucketsOptions(); var uri = GetUri(); _logger.LogInformation("Attempting to get all buckets - {uri}", _redactor.SystemData(uri)); try { var result = await _client.GetAsync(uri, options.TokenValue).ConfigureAwait(false); result.EnsureSuccessStatusCode(); var content = await result.Content.ReadAsStringAsync().ConfigureAwait(false); var buckets = new Dictionary <string, BucketSettings>(); var json = JArray.Parse(content); foreach (var row in json) { var settings = GetBucketSettings(row); buckets.Add(settings.Name, settings); } return(buckets); } catch (Exception exception) { _logger.LogError(exception, "Failed to get all buckets - {uri}", _redactor.SystemData(uri)); throw; } }
public async Task <UserAndMetaData> GetUserAsync(string username, GetUserOptions?options = null) { options ??= GetUserOptions.Default; var uri = GetUsersUri(options.DomainNameValue, username); _logger.LogInformation("Attempting to get user with username {username} - {uri}", _redactor.UserData(username), _redactor.SystemData(uri)); try { // check user exists before trying to read content var result = await _client.GetAsync(uri, options.TokenValue).ConfigureAwait(false); if (result.StatusCode == HttpStatusCode.NotFound) { throw new UserNotFoundException(username); } result.EnsureSuccessStatusCode(); // get user from result var json = JObject.Parse(await result.Content.ReadAsStringAsync().ConfigureAwait(false)); return(UserAndMetaData.FromJson(json)); } catch (Exception exception) { _logger.LogError(exception, "Error trying to get user with username {username} - {uri}", _redactor.UserData(username), _redactor.SystemData(uri)); throw; } }
public async Task <IEnumerable <SearchIndex> > GetAllIndexesAsync(GetAllSearchIndexesOptions?options = null) { options ??= GetAllSearchIndexesOptions.Default; var baseUri = GetIndexUri(); _logger.LogInformation("Trying to get all indexes - {baseUri}", _redactor.SystemData(baseUri)); try { var result = await _client.GetAsync(baseUri, options.TokenValue).ConfigureAwait(false); result.EnsureSuccessStatusCode(); var json = JObject.Parse(await result.Content.ReadAsStringAsync().ConfigureAwait(false)); return(json["indexDefs"]["indexDefs"].ToObject <Dictionary <string, SearchIndex> >().Values); } catch (Exception exception) { _logger.LogError(exception, "Failed to get all indexes - {baseUri}", _redactor.SystemData(baseUri)); throw; } }
public async Task <IEnumerable <ScopeSpec> > GetAllScopesAsync(GetAllScopesOptions?options = null) { options ??= GetAllScopesOptions.Default; var uri = GetUri(); _logger.LogInformation($"Attempting to get all scopes - {uri}"); try { // get manifest var result = await _client.GetAsync(uri, options.TokenValue).ConfigureAwait(false); result.EnsureSuccessStatusCode(); // check scope & collection exists in manifest var json = JObject.Parse(await result.Content.ReadAsStringAsync().ConfigureAwait(false)); var scopes = json.SelectToken("scopes"); if (scopes.Type != JTokenType.Array) // TODO: remove after SDK beta as per RFC { // older style - scopes is a map return(scopes.Select(scope => { var scopeName = scope.Path.Substring(scope.Path.LastIndexOf(".", StringComparison.InvariantCulture) + 1); var collections = scope.First()["collections"].Select(collection => { var collectionName = collection.Path.Substring(collection.Path.LastIndexOf(".", StringComparison.InvariantCulture) + 1); return new CollectionSpec(scopeName, collectionName); }).ToList(); return new ScopeSpec(scopeName) { Collections = collections }; }).ToList()); } // newer style - scopes is an array return(scopes.Select(scope => new ScopeSpec(scope["name"].Value <string>()) { Collections = scope["collections"].Select(collection => new CollectionSpec(collection["name"].Value <string>(), scope["name"].Value <string>()) ).ToList() }).ToList()); } catch (Exception exception) { _logger.LogError(exception, $"Failed to get all scopes - {uri}"); throw; } }
public async Task <Dictionary <string, int> > GetPendingMutationsAsync(GetPendingAnalyticsMutationsOptions?options = null) { options ??= new GetPendingAnalyticsMutationsOptions(); _logger.LogInformation("Getting pending mutations."); try { var builder = new UriBuilder(_serviceUriProvider.GetRandomManagementUri()); builder.Path += "analytics/node/agg/stats/remaining"; var uri = builder.Uri; var result = await _couchbaseHttpClient.GetAsync(uri, options.TokenValue).ConfigureAwait(false); result.EnsureSuccessStatusCode(); var content = await result.Content.ReadAsStringAsync().ConfigureAwait(false); var json = JToken.Parse(content); return(parseResult(json)); } catch (Exception exception) { _logger.LogError(exception, "Failed to retrieve pending mutations."); throw; } }
public async Task <IEnumerable <ScopeSpec> > GetAllScopesAsync(GetAllScopesOptions?options = null) { options ??= GetAllScopesOptions.Default; var uri = GetUri(); _logger.LogInformation("Attempting to get all scopes - {uri}", _redactor.SystemData(uri)); try { // get manifest var result = await _client.GetAsync(uri, options.TokenValue).ConfigureAwait(false); result.EnsureSuccessStatusCode(); // check scope & collection exists in manifest var json = JObject.Parse(await result.Content.ReadAsStringAsync().ConfigureAwait(false)); var scopes = json.SelectToken("scopes"); return(scopes.Select(scope => new ScopeSpec(scope["name"].Value <string>()) { Collections = scope["collections"].Select(collection => new CollectionSpec(scope["name"].Value <string>(), collection["name"].Value <string>()) { MaxExpiry = collection["maxTTL"] == null ? (TimeSpan?)null : TimeSpan.FromSeconds(collection["maxTTL"].Value <long>()) } ).ToList() }).ToList()); } catch (Exception exception) { _logger.LogError(exception, "Failed to get all scopes - {uri}", _redactor.SystemData(uri)); throw; } }
/// <summary> /// Starts the HTTP streaming connection to the Couchbase Server and gets the latest configuration for a SASL authenticated Bucket. /// </summary> /// <param name="bucketName">The name of the Couchbase Bucket.</param> /// <param name="password">The SASL password used to connect to the Bucket.</param> /// <returns>A <see cref="IConfigInfo"/> object representing the latest configuration.</returns> public override IConfigInfo GetConfig(string bucketName, string username, string password) { var bucketConfiguration = GetOrCreateConfiguration(bucketName); //if the client is using a password make sure the client configuration references it password = string.IsNullOrEmpty(password) ? bucketConfiguration.Password : password; if (string.IsNullOrEmpty(bucketConfiguration.Password)) { bucketConfiguration.Password = password; } StartProvider(bucketName, username, password); var bucketConfig = GetBucketConfig(bucketName, password, username); try { ConfigLock.EnterWriteLock(); IConfigInfo configInfo = null; var nodes = bucketConfig.Nodes.ToList(); while (nodes.Any()) { try { nodes.Shuffle(); var node = nodes.First(); nodes.Remove(node); IBucketConfig newConfig; using (new SynchronizationContextExclusion()) { using (var httpClient = new CouchbaseHttpClient(username, password, ClientConfig)) { // try to get config using terse uri var uri = bucketConfig.GetTerseUri(node, bucketConfiguration.UseSsl); var response = httpClient.GetAsync(uri).Result; if (!response.IsSuccessStatusCode) { // try to get config using verbose uri uri = bucketConfig.GetUri(node, bucketConfiguration.UseSsl); response = httpClient.GetAsync(uri).Result; } // if still not a success, let it throw response.EnsureSuccessStatusCode(); var body = response.Content.ReadAsStringAsync().Result; body = body.Replace("$HOST", uri.Host); newConfig = JsonConvert.DeserializeObject <BucketConfig>(body); } } if (string.IsNullOrWhiteSpace(newConfig.BucketType) && newConfig.BucketCapabilities != null) { newConfig.BucketType = (newConfig.BucketCapabilities.Contains("couchapi", StringComparer.OrdinalIgnoreCase) ? BucketTypeEnum.Couchbase : BucketTypeEnum.Ephemeral).ToString().ToLowerInvariant(); } newConfig.Password = password; newConfig.Username = username; if (ClientConfig.UseSsl) { foreach (var ipEndPoint in bucketConfig.VBucketServerMap.IPEndPoints) { ipEndPoint.Port = ClientConfig.SslPort; } } configInfo = CreateConfigInfo(newConfig, username, password); Configs[bucketName] = configInfo; break; } catch (AggregateException e) { Log.Error(e.InnerException); } catch (IOException e) { Log.Error(e); } } if (configInfo == null) { throw new BucketNotFoundException(); } return(configInfo); } finally { ConfigLock.ExitWriteLock(); } }
/// <summary> /// Starts the streaming connection to couchbase server that will /// listen for configuration changes and then update the client as needed. /// </summary> /// <remarks> /// Should not be used when a <see cref="SynchronizationContext" /> is present on the thread, as this /// could cause deadlocks. This method is currently only used from within a dedicated thread, /// created by <see cref="HttpStreamingProvider.RegisterObserver"/>, so it is safe because there will not /// be a SynchronizationContext present on the thread. /// </remarks> public void ListenForConfigChanges() { var count = 0; //Make a copy of the nodes and shuffle them for randomness var nodes = _bucketConfig.Nodes.ToList(); //if RBAC is being used with >= CB 5.0, then use the username otherwise use the bucket name var bucketNameOrUserName = string.IsNullOrWhiteSpace(_bucketConfig.Username) ? _bucketConfig.Name : _bucketConfig.Username; using (var httpClient = new CouchbaseHttpClient(bucketNameOrUserName, _bucketConfig.Password, _clientConfiguration)) { httpClient.Timeout = Timeout.InfiniteTimeSpan; //This will keep trying until it runs out of servers to try in the cluster while (nodes.ToList().Any()) { try { //If the main thread has canceled, break out of the loop otherwise //the next node in the server list will be tried; but in this case //we want to shut things down and terminate the thread if (_cancellationToken.IsCancellationRequested) { break; } nodes = nodes.Shuffle(); var node = nodes[0]; nodes.Remove(node); var streamingUri = _bucketConfig.GetTerseStreamingUri(node, _bucketConfig.UseSsl); Log.Info("Listening to {0}", streamingUri); var response = httpClient.GetAsync(streamingUri, HttpCompletionOption.ResponseHeadersRead, _cancellationToken) .Result; response.EnsureSuccessStatusCode(); using (var stream = response.Content.ReadAsStreamAsync().Result) { //this will cancel the infinite wait below _cancellationToken.Register(stream.Dispose); stream.ReadTimeout = Timeout.Infinite; using (var reader = new StreamReader(stream, Encoding.UTF8, false)) { string config; while (!_cancellationToken.IsCancellationRequested && ((config = reader.ReadLineAsync().Result) != null)) { if (config != String.Empty) { Log.Info("configuration changed count: {0}", count++); Log.Info("Worker Thread: {0}", Thread.CurrentThread.ManagedThreadId); var config1 = config; Log.Debug("{0}", config1); config = config.Replace("$HOST", streamingUri.Host); var bucketConfig = JsonConvert.DeserializeObject <BucketConfig>(config); bucketConfig.SurrogateHost = GetSurrogateHost(streamingUri); if (_configChangedDelegate != null) { bucketConfig.Password = _bucketConfig.Password; bucketConfig.Username = _bucketConfig.Username; _configChangedDelegate(bucketConfig); } } } } } } catch (AggregateException e) { var exceptions = e.Flatten().InnerExceptions; if (exceptions.OfType <ObjectDisposedException>().Any()) { Log.Info("The config listener has shut down."); } foreach (var ex in exceptions.Where(x => x.GetType() != typeof(ObjectDisposedException))) { Log.Error(ex); } } catch (Exception e) { Log.Error(e); } } } //We tried all nodes in the current configuration, alert the provider that we //need to try to re-bootstrap from the beginning if (nodes.Count == 0) { _errorOccurredDelegate(_bucketConfig); } }