Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug]: Overriding CouchbaseBuilder's default configurations resets enabled services #1039

Closed
dadz01-betsson opened this issue Nov 1, 2023 · 15 comments
Labels
question Have you tried our Slack workspace (https://testcontainers.slack.com)?

Comments

@dadz01-betsson
Copy link

Testcontainers version

3.5.0

Using the latest Testcontainers version?

Yes

Host OS

Windows

Host arch

x64

.NET version

6.0.14

Docker version

Client:
 Version:           24.0.2-rd
 API version:       1.43
 Go version:        go1.20.4
 Git commit:        e63f5fa
 Built:             Fri May 26 16:43:15 2023
 OS/Arch:           windows/amd64
 Context:           default

Server: Docker Desktop 4.24.1 (123237)
 Engine:
  Version:          24.0.6
  API version:      1.43 (minimum version 1.12)
  Go version:       go1.20.7
  Git commit:       1a79695
  Built:            Mon Sep  4 12:32:16 2023
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          1.6.22
  GitCommit:        8165feabfdfe38c65b599c4993d227328c231fca
 runc:
  Version:          1.1.8
  GitCommit:        v1.1.8-0-g82f18fe
 docker-init:
  Version:          0.19.0
  GitCommit:        de40ad0

Docker info

Client:
 Version:    24.0.2-rd
 Context:    default
 Debug Mode: false
 Plugins:
  buildx: Docker Buildx (Docker Inc.)
    Version:  v0.11.2-desktop.5
    Path:     C:\Program Files\Docker\cli-plugins\docker-buildx.exe
  compose: Docker Compose (Docker Inc.)
    Version:  v2.22.0-desktop.2
    Path:     C:\Program Files\Docker\cli-plugins\docker-compose.exe
  dev: Docker Dev Environments (Docker Inc.)
    Version:  v0.1.0
    Path:     C:\Program Files\Docker\cli-plugins\docker-dev.exe
  extension: Manages Docker extensions (Docker Inc.)
    Version:  v0.2.20
    Path:     C:\Program Files\Docker\cli-plugins\docker-extension.exe
  init: Creates Docker-related starter files for your project (Docker Inc.)
    Version:  v0.1.0-beta.8
    Path:     C:\Program Files\Docker\cli-plugins\docker-init.exe
  sbom: View the packaged-based Software Bill Of Materials (SBOM) for an image (Anchore Inc.)
    Version:  0.6.0
    Path:     C:\Program Files\Docker\cli-plugins\docker-sbom.exe
  scan: Docker Scan (Docker Inc.)
    Version:  v0.26.0
    Path:     C:\Program Files\Docker\cli-plugins\docker-scan.exe
  scout: Docker Scout (Docker Inc.)
    Version:  v1.0.7
    Path:     C:\Program Files\Docker\cli-plugins\docker-scout.exe

Server:
 Containers: 2
  Running: 2
  Paused: 0
  Stopped: 0
 Images: 3
 Server Version: 24.0.6
 Storage Driver: overlay2
  Backing Filesystem: extfs
  Supports d_type: true
  Using metacopy: false
  Native Overlay Diff: true
  userxattr: false
 Logging Driver: json-file
 Cgroup Driver: cgroupfs
 Cgroup Version: 1
 Plugins:
  Volume: local
  Network: bridge host ipvlan macvlan null overlay
  Log: awslogs fluentd gcplogs gelf journald json-file local logentries splunk syslog
 Swarm: inactive
 Runtimes: io.containerd.runc.v2 runc
 Default Runtime: runc
 Init Binary: docker-init
 containerd version: 8165feabfdfe38c65b599c4993d227328c231fca
 runc version: v1.1.8-0-g82f18fe
 init version: de40ad0
 Security Options:
  seccomp
   Profile: unconfined
 Kernel Version: 5.15.90.1-microsoft-standard-WSL2
 Operating System: Docker Desktop
 OSType: linux
 Architecture: x86_64
 CPUs: 20
 Total Memory: 15.46GiB
 Name: docker-desktop
 ID: bec855d3-715d-498f-81c7-e0112e9df5f3
 Docker Root Dir: /var/lib/docker
 Debug Mode: false
 HTTP Proxy: http.docker.internal:3128
 HTTPS Proxy: http.docker.internal:3128
 No Proxy: hubproxy.docker.internal
 Experimental: false
 Insecure Registries:
  hubproxy.docker.internal:5555
  127.0.0.0/8
 Live Restore Enabled: false

WARNING: No blkio throttle.read_bps_device support
WARNING: No blkio throttle.write_bps_device support
WARNING: No blkio throttle.read_iops_device support
WARNING: No blkio throttle.write_iops_device support
WARNING: daemon is not using the default seccomp profile

What happened?

I want to create bucket and use couchbase SDK together with Testcontainers. When writing basic code for setting up the container and create bucket I getting not very detailed exception.

Couchbase.Core.Exceptions.KeyValue.SocketNotAvailableException:
ChannelConnectionPool at
Couchbase.Core.ClusterContext.GetOrCreateBucketLockedAsync(String
name) at Program.

$(String[] args) in
\ConsoleApp4\ConsoleApp4\Program.cs:line 24

Code to repro:
Csproj:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net6.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="CouchbaseNetClient" Version="3.4.12" />
    <PackageReference Include="Testcontainers" Version="3.5.0" />
    <PackageReference Include="Testcontainers.Couchbase" Version="3.5.0" />
  </ItemGroup>

</Project>

Program.cs



using Couchbase;
using Testcontainers.Couchbase;


const string TestBucketName = "Test";

CouchbaseContainer CouchbaseContainer
    = new CouchbaseBuilder()
        .Build();
try
{
    await CouchbaseContainer.StartAsync();
    var options = new ClusterOptions
    {
        UserName = CouchbaseBuilder.DefaultUsername,
        Password = CouchbaseBuilder.DefaultPassword,
    };

    var connectionString = CouchbaseContainer.GetConnectionString();
    var cluster = await Cluster.ConnectAsync(connectionString, options);

    var bucket = await cluster.BucketAsync(TestBucketName);
    var collection = await bucket.DefaultCollectionAsync();
}
catch (Exception e)
{
    await CouchbaseContainer.DisposeAsync();
    Console.WriteLine(e);
  
}

Relevant log output

No response

Additional information

I tried to create bucket from the UI and it worked.

@dadz01-betsson dadz01-betsson added the bug Something isn't working label Nov 1, 2023
@HofmeisterAn
Copy link
Collaborator

Well, the bucket does not exist, nor do you create it. Use the default generated bucket:

_couchbaseContainer.Buckets.Single().Name

Or create one:

var bucketSettings = new BucketSettings();
bucketSettings.Name = TestBucketName;
bucketSettings.FlushEnabled = false;
bucketSettings.ReplicaIndexes = true;
bucketSettings.RamQuotaMB = 100;
bucketSettings.NumReplicas = 0;

await cluster.Buckets.CreateBucketAsync(bucketSettings)
    .ConfigureAwait(false);

@HofmeisterAn HofmeisterAn added question Have you tried our Slack workspace (https://testcontainers.slack.com)? and removed bug Something isn't working labels Nov 1, 2023
@dadz01-betsson
Copy link
Author

Well, the bucket does not exist, nor do you create it. Use the default generated bucket:

_couchbaseContainer.Buckets.Single().Name

Or create one:

var bucketSettings = new BucketSettings();
bucketSettings.Name = TestBucketName;
bucketSettings.FlushEnabled = false;
bucketSettings.ReplicaIndexes = true;
bucketSettings.RamQuotaMB = 100;
bucketSettings.NumReplicas = 0;

await cluster.Buckets.CreateBucketAsync(bucketSettings)
    .ConfigureAwait(false);

@HofmeisterAn Thanks, however await cluster.BucketAsync(TestBucketName); Implementation suggest that it will create bucket if it does not exists.

If I create new one as you suggested and want get default collection (to be able to query/add things ) from created bucket with following code:

 var bucket = await cluster.BucketAsync(TestBucketName);
 var collection = await bucket.DefaultCollectionAsync();

I still getting the same error.

@HofmeisterAn
Copy link
Collaborator

The following lines work fine. You need to wait until the bucket is created. It is not available immediately. I am not a Couchbase expert, but I do not think these issues are related to the module implementation.

await cluster.Buckets.CreateBucketAsync(bucketSettings)
    .ConfigureAwait(false);

await Task.Delay(TimeSpan.FromSeconds(5))
    .ConfigureAwait(false);

var bucket = await cluster.BucketAsync(bucketName)
    .ConfigureAwait(false);

var collection = await bucket.DefaultCollectionAsync()
    .ConfigureAwait(false);

@dadz01-betsson
Copy link
Author

dadz01-betsson commented Nov 1, 2023

The following lines work fine. You need to wait until the bucket is created. It is not available immediately. I am not a Couchbase expert, but I do not think these issues are related to the module implementation.

await cluster.Buckets.CreateBucketAsync(bucketSettings)
    .ConfigureAwait(false);

await Task.Delay(TimeSpan.FromSeconds(5))
    .ConfigureAwait(false);

var bucket = await cluster.BucketAsync(bucketName)
    .ConfigureAwait(false);

var collection = await bucket.DefaultCollectionAsync()
    .ConfigureAwait(false);

Is this really working for you ? This sample is giving me still the same error:

using Couchbase;
using Couchbase.Management.Buckets;
using Testcontainers.Couchbase;


string TestBucketName = "Test";

CouchbaseContainer CouchbaseContainer
    = new CouchbaseBuilder()
        .WithPortBinding(8091, 8091)
        .Build();
try
{
    await CouchbaseContainer.StartAsync();
    var options = new ClusterOptions
    {
        UserName = CouchbaseBuilder.DefaultUsername,
        Password = CouchbaseBuilder.DefaultPassword,
    };

    var connectionString = CouchbaseContainer.GetConnectionString(); 
    
    var cluster = await Cluster.ConnectAsync(connectionString, options);

    var bucketSettings = new BucketSettings
    {
        Name = TestBucketName,
        FlushEnabled = false,
        ReplicaIndexes = true,
        RamQuotaMB = 100,
        NumReplicas = 0
    };

    await cluster.Buckets.CreateBucketAsync(bucketSettings)
        .ConfigureAwait(false);

    await Task.Delay(TimeSpan.FromSeconds(5))
        .ConfigureAwait(false);

    var bucket = await cluster.BucketAsync(TestBucketName)
        .ConfigureAwait(false);

    var collection = await bucket.DefaultCollectionAsync()
        .ConfigureAwait(false);
}
catch (Exception e)
{
    await CouchbaseContainer.DisposeAsync();
    Console.WriteLine(e.ToString());
  
}```

![Error](https://github.com/testcontainers/testcontainers-dotnet/assets/136716460/78218de9-405d-4f39-8092-fe9842595592)

@HofmeisterAn
Copy link
Collaborator

Ah, I see. Remove the .WithPortBinding(8091, 8091) line for now. It appears that this line is overriding the enabled services (_enabledServices is empty with your configuration). I can fix it later.

@HofmeisterAn HofmeisterAn changed the title [Bug]: Default configuration of couchbase does not work. [Bug]: Overriding CouchbaseBuilder's default configurations resets enabled services Nov 1, 2023
@HofmeisterAn HofmeisterAn added bug Something isn't working and removed question Have you tried our Slack workspace (https://testcontainers.slack.com)? labels Nov 1, 2023
@dadz01-betsson
Copy link
Author

Thank you for suggestion but still I having the same behaviour.

using Couchbase;
using Couchbase.Management.Buckets;
using Testcontainers.Couchbase;


string TestBucketName = "Test";

CouchbaseContainer CouchbaseContainer
    = new CouchbaseBuilder()
        .Build();
try
{
    await CouchbaseContainer.StartAsync();
    var options = new ClusterOptions
    {
        UserName = CouchbaseBuilder.DefaultUsername,
        Password = CouchbaseBuilder.DefaultPassword,
    };

    var connectionString = CouchbaseContainer.GetConnectionString(); 
    
    var cluster = await Cluster.ConnectAsync(connectionString, options);

    var bucketSettings = new BucketSettings
    {
        Name = TestBucketName,
        FlushEnabled = false,
        ReplicaIndexes = true,
        RamQuotaMB = 100,
        NumReplicas = 0
    };

    await cluster.Buckets.CreateBucketAsync(bucketSettings)
        .ConfigureAwait(false);

    await Task.Delay(TimeSpan.FromSeconds(5))
        .ConfigureAwait(false);

    var bucket = await cluster.BucketAsync(TestBucketName)
        .ConfigureAwait(false);

    var collection = await bucket.DefaultCollectionAsync()
        .ConfigureAwait(false);
}
catch (Exception e)
{
    await CouchbaseContainer.DisposeAsync();
    Console.WriteLine(e.ToString());
  
}

image

@HofmeisterAn
Copy link
Collaborator

Can you please share the full stack trace? Without overriding the default configurations, it looks good.

image

@dadz01-betsson
Copy link
Author

Message:

ChannelConnectionPool

Stacktrace:

at Couchbase.Core.ClusterContext.GetOrCreateBucketLockedAsync(String name)
at Program.

$(String[] args) in ~\repos\ConsoleApp4\ConsoleApp4\Program.cs:line 41

After digging a bit I think this is comming from here: https://github.com/couchbase/couchbase-net-client/blob/master/src/Couchbase/Core/IO/Connections/Channels/ChannelConnectionPool.cs#L197

@HofmeisterAn
Copy link
Collaborator

Have you checked the web front-end to see if the bucket exists after some time? It is possible that it is still being created, and it may just require some additional time. Internally, we use the following lines to detect when the default bucket is finally created:

var waitUntilBucketIsCreated = DockerResourceConfiguration.Buckets.Aggregate(Wait.ForUnixContainer(), (waitStrategy, bucket)
=> waitStrategy.UntilHttpRequestIsSucceeded(request
=> request
.ForPath("/pools/default/buckets/" + bucket.Name)
.ForPort(MgmtPort)
.ForResponseMessageMatching(AllServicesEnabledAsync)
.WithHeader(_basicAuthenticationHeader.Key, _basicAuthenticationHeader.Value)))
.Build()
.Last();

@dadz01-betsson
Copy link
Author

I checked the UI (but this requires to expose port 8091) and its there.
image

Ive added infinite loop which will check is bucket exists and breaks when its created but result is exactly the same as before:

using Couchbase;
using Couchbase.Management.Buckets;
using Testcontainers.Couchbase;


string TestBucketName = "Test";

CouchbaseContainer CouchbaseContainer
    = new CouchbaseBuilder()
     //   .WithPortBinding(8091, 8091)
        .Build();
try
{
    await CouchbaseContainer.StartAsync();
    var options = new ClusterOptions
    {
        UserName = CouchbaseBuilder.DefaultUsername,
        Password = CouchbaseBuilder.DefaultPassword,
    };

    var connectionString = CouchbaseContainer.GetConnectionString(); 
    
    var cluster = await Cluster.ConnectAsync(connectionString, options);

    var bucketSettings = new BucketSettings
    {
        Name = TestBucketName,
        FlushEnabled = false,
        ReplicaIndexes = true,
        RamQuotaMB = 100,
        NumReplicas = 0
    };

    await cluster.Buckets.CreateBucketAsync(bucketSettings)
        .ConfigureAwait(false);

    while (true)
    {
       var buckets=  await cluster.Buckets.GetAllBucketsAsync();
       if (buckets.ContainsKey(TestBucketName))
       {
           break;
       }

       await Task.Delay(TimeSpan.FromSeconds(5));
    }

    var bucket = await cluster.BucketAsync(TestBucketName)
        .ConfigureAwait(false);

    var collection = await bucket.DefaultCollectionAsync()
        .ConfigureAwait(false);
}
catch (Exception e)
{
    await CouchbaseContainer.DisposeAsync();
    Console.WriteLine(e.ToString());
  
}

@HofmeisterAn
Copy link
Collaborator

HofmeisterAn commented Nov 1, 2023

but this requires to expose port 8091

Actually, it does not. You can obtain the randomly assigned host port from the inspect results, and the log messages contain a link to the web front-end as well.

Ive added infinite loop which will check is bucket exists and breaks when its created but result is exactly the same as before:

This confirms my supposition. Just because the bucket exists does not mean it is ready to use. If I create a bucket and immediately check the "/pools/default/buckets/" + bucketName API, I get a response similar to:

{
    "name": "Test",
    "nodes": []
}

However, when I wait a couple of seconds, I get:

{
    "name": "Test",
    "nodes": [
        {
            "status": "healthy",
            "services": [
                "fts",
                "index",
                "kv",
                "n1ql"
            ]
        }
    ]
}

Despite the issue I mentioned regarding overriding the default configuration, I do not see any other issues. I am sorry. I do not know how I can help you further.

@dadz01-betsson
Copy link
Author

Thanks @HofmeisterAn. But even when I run this code on default bucket (which is I assume created already, because there is wait strategy) I am getting same error.

using Couchbase;
using Couchbase.Management.Buckets;
using Testcontainers.Couchbase;


CouchbaseContainer CouchbaseContainer
    = new CouchbaseBuilder()
        .Build();
try
{
    await CouchbaseContainer.StartAsync();
    var options = new ClusterOptions
    {
        UserName = CouchbaseBuilder.DefaultUsername,
        Password = CouchbaseBuilder.DefaultPassword,
    };

    var connectionString = CouchbaseContainer.GetConnectionString();

    var cluster = await Cluster.ConnectAsync(connectionString, options);
    var defaultBucket = (await cluster.Buckets.GetAllBucketsAsync()).Single();

    var bucket = await cluster.BucketAsync(defaultBucket.Key)
        .ConfigureAwait(false);

    var collection = await bucket.DefaultCollectionAsync()
        .ConfigureAwait(false);
}
catch (Exception e)
{
    await CouchbaseContainer.DisposeAsync();
    Console.WriteLine(e.ToString());

}

image

@HofmeisterAn HofmeisterAn added question Have you tried our Slack workspace (https://testcontainers.slack.com)? and removed bug Something isn't working labels Nov 1, 2023
@HofmeisterAn
Copy link
Collaborator

As mentioned in SO#77396534, this appears to be a bug in the client. I encountered the same error with the latest client version. Downgrading the client to 3.4.3 resolved the issue. I recommend that you create an upstream issue in the Couchbase .NET client repository and share the test case reproducer leveraging Testcontainers.

@dadz01-betsson
Copy link
Author

I will do that, thanks a lot for your help @HofmeisterAn.

@HofmeisterAn
Copy link
Collaborator

I will close this issue for now. If there is anything to do or to fix on the side of TC for .NET, do not hesitate to reopen the issue again or create a new one. Unfortunately, Couchbase's upstream repository does not allow creating issues. This is the related ticket, I think: NCBC-3545.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Have you tried our Slack workspace (https://testcontainers.slack.com)?
Projects
None yet
Development

No branches or pull requests

2 participants