diff --git a/.github/actions/build-opensearch/action.yml b/.github/actions/build-opensearch/action.yml index 8ad36ee266..9c3d640df0 100644 --- a/.github/actions/build-opensearch/action.yml +++ b/.github/actions/build-opensearch/action.yml @@ -15,7 +15,7 @@ inputs: plugins_output_directory: description: The directory to output the plugins to default: "" -outputs: +outputs: distribution: description: The path to the OpenSearch distribution value: ${{ steps.determine.outputs.distribution }} @@ -36,11 +36,11 @@ runs: ./opensearch/distribution/archives/linux-tar/build/distributions/opensearch-*.tar.gz ./opensearch/plugins/*/build/distributions/*.zip build_script: | - ./gradlew :distribution:archives:linux-tar:assemble -Dbuild.snapshot=${{ inputs.build_snapshot }} + ./gradlew --stacktrace :distribution:archives:linux-tar:assemble -Dbuild.snapshot=${{ inputs.build_snapshot }} PluginList=("analysis-icu" "analysis-kuromoji" "analysis-nori" "analysis-phonetic" "ingest-attachment" "mapper-murmur3") for plugin in ${PluginList[*]}; do - ./gradlew :plugins:$plugin:assemble -Dbuild.snapshot=${{ inputs.build_snapshot }} + ./gradlew --stacktrace :plugins:$plugin:assemble -Dbuild.snapshot=${{ inputs.build_snapshot }} done - name: Determine OpenSearch distribution path and version @@ -62,7 +62,7 @@ runs: cache_key_suffix: ${{ inputs.build_snapshot == 'true' && '-snapshot' || '' }} cached_paths: | ./opensearch-security/build/distributions/opensearch-security-*.zip - build_script: ./gradlew assemble -Dopensearch.version=${{ steps.determine.outputs.version }} -Dbuild.snapshot=${{ inputs.build_snapshot }} + build_script: ./gradlew --stacktrace assemble -Dopensearch.version=${{ steps.determine.outputs.version }} -Dbuild.snapshot=${{ inputs.build_snapshot }} - name: Restore or Build OpenSearch k-NN uses: ./client/.github/actions/cached-git-build @@ -76,7 +76,7 @@ runs: ./opensearch-knn/build/distributions/opensearch-knn-*.zip build_script: | sudo apt-get install -y libopenblas-dev libomp-dev - ./gradlew buildJniLib assemble -Dopensearch.version=${{ steps.determine.outputs.version }} -Dbuild.snapshot=${{ inputs.build_snapshot }} + ./gradlew --stacktrace buildJniLib assemble -Dopensearch.version=${{ steps.determine.outputs.version }} -Dbuild.snapshot=${{ inputs.build_snapshot }} distributions=./build/distributions lib_dir=$distributions/lib mkdir $lib_dir diff --git a/.github/workflows/integration-yaml-tests.yml b/.github/workflows/integration-yaml-tests.yml index fa2b9fcb38..99296a0394 100644 --- a/.github/workflows/integration-yaml-tests.yml +++ b/.github/workflows/integration-yaml-tests.yml @@ -87,7 +87,10 @@ jobs: strategy: fail-fast: false matrix: - opensearch_ref: ['1.x', '2.x', 'main'] + include: + - { opensearch_ref: '1.x', java_version: '11' } + - { opensearch_ref: '2.x', java_version: '17' } + - { opensearch_ref: 'main', java_version: '21' } steps: - name: Checkout Client uses: actions/checkout@v4 @@ -111,8 +114,8 @@ jobs: - name: Set up JDK uses: actions/setup-java@v4 with: - java-version: 21 distribution: 'temurin' + java-version: ${{ matrix.java_version }} - name: Restore or Build OpenSearch id: opensearch_build diff --git a/.github/workflows/integration.yml b/.github/workflows/integration.yml index 9daf1a834a..822bb67924 100644 --- a/.github/workflows/integration.yml +++ b/.github/workflows/integration.yml @@ -50,7 +50,7 @@ jobs: restore-keys: | ${{ runner.os }}-nuget- - - run: "./build.sh integrate $VERSION readonly,replicatedreadonly,writable random:test_only_one --report" + - run: "./build.sh integrate $VERSION readonly,multinode,writable random:test_only_one --report" name: Integration Tests working-directory: client env: @@ -69,10 +69,10 @@ jobs: strategy: fail-fast: false matrix: - opensearch_ref: - - '1.x' - - '2.x' - - 'main' + include: + - { opensearch_ref: '1.x', java_version: '11' } + - { opensearch_ref: '2.x', java_version: '17' } + - { opensearch_ref: 'main', java_version: '21' } steps: - name: Checkout Client @@ -100,6 +100,12 @@ jobs: restore-keys: | ${{ runner.os }}-nuget- + - name: Set up JDK + uses: actions/setup-java@v4 + with: + distribution: 'temurin' + java-version: ${{ matrix.java_version }} + - name: Restore or Build OpenSearch id: opensearch uses: ./client/.github/actions/build-opensearch @@ -109,7 +115,7 @@ jobs: knn_plugin: true plugins_output_directory: ${{ env.OPENSEARCH_PLUGINS_DIRECTORY }} - - run: "./build.sh integrate $OPENSEARCH_VERSION readonly,replicatedreadonly,writable random:test_only_one --report" + - run: "./build.sh integrate $OPENSEARCH_VERSION readonly,multinode,writable random:test_only_one --report" name: Integration Tests working-directory: client env: diff --git a/abstractions/src/OpenSearch.OpenSearch.Managed/ClusterBase.cs b/abstractions/src/OpenSearch.OpenSearch.Managed/ClusterBase.cs index 3cdb74e966..9abf6830d7 100644 --- a/abstractions/src/OpenSearch.OpenSearch.Managed/ClusterBase.cs +++ b/abstractions/src/OpenSearch.OpenSearch.Managed/ClusterBase.cs @@ -75,29 +75,32 @@ protected ClusterBase(TConfiguration clusterConfiguration) ClusterConfiguration = clusterConfiguration; ClusterMoniker = GetType().Name.Replace("Cluster", ""); - NodeConfiguration Modify(NodeConfiguration n, int p) - { - ModifyNodeConfiguration(n, p); - return n; - } - - var nodes = - (from port in Enumerable.Range(ClusterConfiguration.StartingPortNumber, - ClusterConfiguration.NumberOfNodes) - let config = new NodeConfiguration(clusterConfiguration, port, ClusterMoniker) - { - ShowOpenSearchOutputAfterStarted = - clusterConfiguration.ShowOpenSearchOutputAfterStarted, - } - let node = new OpenSearchNode(Modify(config, port)) - { - AssumeStartedOnNotEnoughMasterPing = ClusterConfiguration.NumberOfNodes > 1, - } - select node).ToList(); - - var initialMasterNodes = string.Join(",", nodes.Select(n => n.NodeConfiguration.DesiredNodeName)); - foreach (var node in nodes) - node.NodeConfiguration.InitialMasterNodes(initialMasterNodes); + var nodeConfigs = Enumerable.Range(ClusterConfiguration.StartingPortNumber, ClusterConfiguration.NumberOfNodes) + .Select(port => new NodeConfiguration(ClusterConfiguration, port, ClusterMoniker) + { + ShowOpenSearchOutputAfterStarted = ClusterConfiguration.ShowOpenSearchOutputAfterStarted + }) + .ToArray(); + + var initialClusterManagerNodes = string.Join(",", nodeConfigs.Select(n => n.DesiredNodeName)); + + var nodes = nodeConfigs + .Select(config => + { + if (nodeConfigs.Length > 1) + { + var otherNodes = nodeConfigs + .Where(n => n != config) + .Select(n => $"localhost:{(n.DesiredPort ?? 9200) + 100}"); + config.SeedHosts(string.Join(",", otherNodes)); + } + + config.InitialClusterManagerNodes(initialClusterManagerNodes); + ModifyNodeConfiguration(config, config.DesiredPort ?? 9200); + + return new OpenSearchNode(config) { AssumeStartedOnNotEnoughClusterManagerPing = ClusterConfiguration.NumberOfNodes > 1 }; + }) + .ToArray(); Nodes = new ReadOnlyCollection(nodes); } diff --git a/abstractions/src/OpenSearch.OpenSearch.Managed/Configuration/ClusterConfiguration.cs b/abstractions/src/OpenSearch.OpenSearch.Managed/Configuration/ClusterConfiguration.cs index e74d8bd116..a9ae4cefa0 100644 --- a/abstractions/src/OpenSearch.OpenSearch.Managed/Configuration/ClusterConfiguration.cs +++ b/abstractions/src/OpenSearch.OpenSearch.Managed/Configuration/ClusterConfiguration.cs @@ -90,11 +90,8 @@ public ClusterConfiguration(OpenSearchVersion version, FuncThe node settings to apply to each started node - public NodeSettings DefaultNodeSettings { get; } = new NodeSettings(); + public NodeSettings DefaultNodeSettings { get; } = new(); /// /// Creates a node name diff --git a/abstractions/src/OpenSearch.OpenSearch.Managed/Configuration/NodeConfiguration.cs b/abstractions/src/OpenSearch.OpenSearch.Managed/Configuration/NodeConfiguration.cs index 1e379e1470..4d067242e3 100644 --- a/abstractions/src/OpenSearch.OpenSearch.Managed/Configuration/NodeConfiguration.cs +++ b/abstractions/src/OpenSearch.OpenSearch.Managed/Configuration/NodeConfiguration.cs @@ -28,6 +28,7 @@ using System; using System.Globalization; +using System.IO; using OpenSearch.OpenSearch.Managed.FileSystem; using OpenSearch.Stack.ArtifactsApi; using ProcNet; @@ -49,12 +50,18 @@ public NodeConfiguration(IClusterConfiguration clusterConfigurat ClusterConfiguration = clusterConfiguration; DesiredPort = port; DesiredNodeName = CreateNodeName(port, nodePrefix) ?? clusterConfiguration.CreateNodeName(port); - Settings = new NodeSettings(clusterConfiguration.DefaultNodeSettings); - - if (!string.IsNullOrWhiteSpace(DesiredNodeName)) Settings.Add("node.name", DesiredNodeName); - if (DesiredPort.HasValue) - Settings.Add("http.port", DesiredPort.Value.ToString(CultureInfo.InvariantCulture)); - } + Settings = new NodeSettings(clusterConfiguration.DefaultNodeSettings) + { + { "path.data", Path.Combine(ClusterConfiguration.FileSystem.DataPath, DesiredNodeName) } + }; + + if (!string.IsNullOrWhiteSpace(DesiredNodeName)) Settings.Add("node.name", DesiredNodeName); + if (DesiredPort is { } desiredPort) + { + Settings.Add("http.port", desiredPort.ToString(CultureInfo.InvariantCulture)); + Settings.Add("transport.port", (desiredPort + 100).ToString(CultureInfo.InvariantCulture)); + } + } private IClusterConfiguration ClusterConfiguration { get; } @@ -87,10 +94,15 @@ public Action ModifyStartArguments public OpenSearchVersion Version => ClusterConfiguration.Version; public string[] CommandLineArguments => Settings.ToCommandLineArguments(Version); - public void InitialMasterNodes(string initialMasterNodes) => - Settings.Add("cluster.initial_master_nodes", initialMasterNodes, ">=1.0.0"); + public void SeedHosts(string seedHosts) => Settings.Add("discovery.seed_hosts", seedHosts); + + public void InitialClusterManagerNodes(string initialClusterManagerNodes) + { + Settings.Add("cluster.initial_master_nodes", initialClusterManagerNodes, ">=1.0.0 <2.0.0"); + Settings.Add("cluster.initial_cluster_manager_nodes", initialClusterManagerNodes, ">=2.0.0"); + } - public string AttributeKey(string attribute) + public string AttributeKey(string attribute) { var attr = "attr."; return $"node.{attr}{attribute}"; diff --git a/abstractions/src/OpenSearch.OpenSearch.Managed/OpenSearchNode.cs b/abstractions/src/OpenSearch.OpenSearch.Managed/OpenSearchNode.cs index da8250901a..0ea0a83884 100644 --- a/abstractions/src/OpenSearch.OpenSearch.Managed/OpenSearchNode.cs +++ b/abstractions/src/OpenSearch.OpenSearch.Managed/OpenSearchNode.cs @@ -64,7 +64,7 @@ public OpenSearchNode(OpenSearchVersion version, string openSearchHome = null) /// doing the election. /// Useful to speed up starting multi node clusters /// - public bool AssumeStartedOnNotEnoughMasterPing { get; set; } + public bool AssumeStartedOnNotEnoughClusterManagerPing { get; set; } internal IConsoleLineHandler Writer { get; private set; } @@ -119,7 +119,7 @@ private static void AppendPathEnvVar(string name, string value) private bool AssumedStartedStateChecker(string section, string message) { - if (AssumeStartedOnNotEnoughMasterPing + if (AssumeStartedOnNotEnoughClusterManagerPing && section.Contains("ZenDiscovery") && message.Contains("not enough master nodes discovered during pinging")) return true; diff --git a/abstractions/src/OpenSearch.OpenSearch.Xunit/XunitClusterBase.cs b/abstractions/src/OpenSearch.OpenSearch.Xunit/XunitClusterBase.cs index 2c7f5d15b7..d6576c84bd 100644 --- a/abstractions/src/OpenSearch.OpenSearch.Xunit/XunitClusterBase.cs +++ b/abstractions/src/OpenSearch.OpenSearch.Xunit/XunitClusterBase.cs @@ -33,21 +33,13 @@ namespace OpenSearch.OpenSearch.Xunit /// /// Base class for a cluster that integrates with Xunit tests /// - public abstract class XunitClusterBase : XunitClusterBase - { - protected XunitClusterBase(XunitClusterConfiguration configuration) : base(configuration) - { - } - } + public abstract class XunitClusterBase(XunitClusterConfiguration configuration) + : XunitClusterBase(configuration); /// /// Base class for a cluster that integrates with Xunit tests /// - public abstract class XunitClusterBase : EphemeralCluster - where TConfiguration : XunitClusterConfiguration - { - protected XunitClusterBase(TConfiguration configuration) : base(configuration) - { - } - } + public abstract class XunitClusterBase(TConfiguration configuration) + : EphemeralCluster(configuration) + where TConfiguration : XunitClusterConfiguration; } diff --git a/build/scripts/scripts.fsproj b/build/scripts/scripts.fsproj index e98ae8fc61..253f9523e5 100644 --- a/build/scripts/scripts.fsproj +++ b/build/scripts/scripts.fsproj @@ -32,15 +32,17 @@ license-header-fs.txt + + - + - + diff --git a/src/ApiGenerator/Generator/ApiEndpointFactory.cs b/src/ApiGenerator/Generator/ApiEndpointFactory.cs index 13d3b4887d..5d3f748e6c 100644 --- a/src/ApiGenerator/Generator/ApiEndpointFactory.cs +++ b/src/ApiGenerator/Generator/ApiEndpointFactory.cs @@ -289,6 +289,9 @@ private static string SanitizeDescription(this string description) { if (string.IsNullOrWhiteSpace(description)) return null; + description = Regex.Replace(description, "&", "&"); + description = Regex.Replace(description, "<", "<"); + description = Regex.Replace(description, ">", ">"); description = Regex.Replace(description, @"\s+", " "); if (!description.EndsWith('.')) description += '.'; diff --git a/src/OpenSearch.Client/_Generated/Descriptors.Cluster.cs b/src/OpenSearch.Client/_Generated/Descriptors.Cluster.cs index 426e0af0be..6150a2c27b 100644 --- a/src/OpenSearch.Client/_Generated/Descriptors.Cluster.cs +++ b/src/OpenSearch.Client/_Generated/Descriptors.Cluster.cs @@ -336,7 +336,7 @@ public ClusterHealthDescriptor WaitForActiveShards(string waitforactiveshards) = public ClusterHealthDescriptor WaitForEvents(WaitForEvents? waitforevents) => Qs("wait_for_events", waitforevents); - /// The request waits until the specified number N of nodes is available. It also accepts >=N, <=N, >N and + /// The request waits until the specified number N of nodes is available. It also accepts >=N, <=N, >N and <N. Alternatively, it is possible to use ge(N), le(N), gt(N) and lt(N) notation. public ClusterHealthDescriptor WaitForNodes(string waitfornodes) => Qs("wait_for_nodes", waitfornodes); @@ -350,7 +350,7 @@ public ClusterHealthDescriptor WaitForNoRelocatingShards( bool? waitfornorelocatingshards = true ) => Qs("wait_for_no_relocating_shards", waitfornorelocatingshards); - /// One of green, yellow or red. Will wait (until the timeout provided) until the status of the cluster changes to the one provided or better, i.e. green > yellow > red. By default, will not wait for any status. + /// One of green, yellow or red. Will wait (until the timeout provided) until the status of the cluster changes to the one provided or better, i.e. green > yellow > red. By default, will not wait for any status. public ClusterHealthDescriptor WaitForStatus(HealthStatus? waitforstatus) => Qs("wait_for_status", waitforstatus); } diff --git a/src/OpenSearch.Client/_Generated/Requests.Cluster.cs b/src/OpenSearch.Client/_Generated/Requests.Cluster.cs index 2132bd4bfa..60f7645108 100644 --- a/src/OpenSearch.Client/_Generated/Requests.Cluster.cs +++ b/src/OpenSearch.Client/_Generated/Requests.Cluster.cs @@ -458,8 +458,8 @@ public WaitForEvents? WaitForEvents } /// - /// The request waits until the specified number N of nodes is available. It also accepts >=N, <=N, >N and public string WaitForNodes { @@ -489,7 +489,7 @@ public bool? WaitForNoRelocatingShards /// /// One of green, yellow or red. Will wait (until the timeout provided) until the status of the cluster changes to the one provided or better, - /// i.e. green > yellow > red. By default, will not wait for any status. + /// i.e. green > yellow > red. By default, will not wait for any status. /// public HealthStatus? WaitForStatus { diff --git a/src/OpenSearch.Net/_Generated/Api/RequestParameters/RequestParameters.Cluster.cs b/src/OpenSearch.Net/_Generated/Api/RequestParameters/RequestParameters.Cluster.cs index 2c6f2b3b20..6415954714 100644 --- a/src/OpenSearch.Net/_Generated/Api/RequestParameters/RequestParameters.Cluster.cs +++ b/src/OpenSearch.Net/_Generated/Api/RequestParameters/RequestParameters.Cluster.cs @@ -367,8 +367,8 @@ public WaitForEvents? WaitForEvents } /// - /// The request waits until the specified number N of nodes is available. It also accepts >=N, <=N, >N and public string WaitForNodes { @@ -398,7 +398,7 @@ public bool? WaitForNoRelocatingShards /// /// One of green, yellow or red. Will wait (until the timeout provided) until the status of the cluster changes to the one provided or better, - /// i.e. green > yellow > red. By default, will not wait for any status. + /// i.e. green > yellow > red. By default, will not wait for any status. /// public HealthStatus? WaitForStatus { diff --git a/tests/Tests.Core/ManagedOpenSearch/Clusters/ClientTestClusterBase.cs b/tests/Tests.Core/ManagedOpenSearch/Clusters/ClientTestClusterBase.cs index e5eb2d1e99..b71b7daf08 100644 --- a/tests/Tests.Core/ManagedOpenSearch/Clusters/ClientTestClusterBase.cs +++ b/tests/Tests.Core/ManagedOpenSearch/Clusters/ClientTestClusterBase.cs @@ -41,23 +41,23 @@ namespace Tests.Core.ManagedOpenSearch.Clusters { - public abstract class ClientTestClusterBase : XunitClusterBase, IOpenSearchClientTestCluster - { + public abstract class ClientTestClusterBase(ClientTestClusterConfiguration configuration) + : XunitClusterBase(configuration), + IOpenSearchClientTestCluster + { protected ClientTestClusterBase() : this(new ClientTestClusterConfiguration()) { } protected ClientTestClusterBase(params OpenSearchPlugin[] plugins) : this(new ClientTestClusterConfiguration(plugins)) { } - protected ClientTestClusterBase(ClientTestClusterConfiguration configuration) : base(configuration) { } - - public IOpenSearchClient Client => this.GetOrAddClient(s => ConnectionSettings(s.ApplyDomainSettings())); + public IOpenSearchClient Client => this.GetOrAddClient(s => ConnectionSettings(s.ApplyDomainSettings())); protected virtual ConnectionSettings ConnectionSettings(ConnectionSettings s) => s; protected sealed override void SeedCluster() { - Client.Cluster.Health(new ClusterHealthRequest { WaitForStatus = HealthStatus.Green }); + Client.Cluster.Health(new ClusterHealthRequest { WaitForStatus = HealthStatus.Green }).ShouldBeValid(); SeedNode(); - Client.Cluster.Health(new ClusterHealthRequest { WaitForStatus = HealthStatus.Green }); + Client.Cluster.Health(new ClusterHealthRequest { WaitForStatus = HealthStatus.Green }).ShouldBeValid(); } protected virtual void SeedNode() { } @@ -82,9 +82,12 @@ params OpenSearchPlugin[] plugins Add(AttributeKey("testingcluster"), "true"); Add(AttributeKey("gateway"), "true"); - Add($"script.disable_max_compilations_rate", "true"); + Add("cluster.routing.allocation.disk.watermark.low", "100%"); + Add("cluster.routing.allocation.disk.watermark.high", "100%"); + Add("cluster.routing.allocation.disk.watermark.flood_stage", "100%"); - Add($"script.allowed_types", "inline,stored"); + Add("script.disable_max_compilations_rate", "true"); + Add("script.allowed_types", "inline,stored"); AdditionalBeforeNodeStartedTasks.Add(new WriteAnalysisFiles()); } diff --git a/tests/Tests.Core/ManagedOpenSearch/Clusters/ReadOnlyCluster.cs b/tests/Tests.Core/ManagedOpenSearch/Clusters/ReadOnlyCluster.cs index 26186c3351..23fef6b367 100644 --- a/tests/Tests.Core/ManagedOpenSearch/Clusters/ReadOnlyCluster.cs +++ b/tests/Tests.Core/ManagedOpenSearch/Clusters/ReadOnlyCluster.cs @@ -26,27 +26,17 @@ * under the License. */ -using OpenSearch.Client; using Tests.Core.ManagedOpenSearch.NodeSeeders; using static OpenSearch.Stack.ArtifactsApi.Products.OpenSearchPlugin; -namespace Tests.Core.ManagedOpenSearch.Clusters -{ - public class ReadOnlyCluster : ClientTestClusterBase - { - public ReadOnlyCluster() : base(Knn, MapperMurmur3, Security) { } - - protected override void SeedNode() => new DefaultSeeder(Client).SeedNode(); - } +namespace Tests.Core.ManagedOpenSearch.Clusters; - public class ReplicatedReadOnlyCluster : ClientTestClusterBase - { - public ReplicatedReadOnlyCluster() : base(new ClientTestClusterConfiguration(numberOfNodes: 2, plugins: new[] {Knn, MapperMurmur3, Security})) { } +public class ReadOnlyCluster : ClientTestClusterBase +{ + public ReadOnlyCluster() : base(Knn, MapperMurmur3, Security) { } - protected override void SeedNode() => new DefaultSeeder(Client, new IndexSettings - { - NumberOfShards = 2, - NumberOfReplicas = 1 - }).SeedNode(); - } + protected override void SeedNode() => new DefaultSeeder(Client).SeedNode(); } + +public class MultiNodeCluster() + : ClientTestClusterBase(new ClientTestClusterConfiguration(numberOfNodes: 2, plugins: [Security])); diff --git a/tests/Tests.Core/ManagedOpenSearch/NodeSeeders/DefaultSeeder.cs b/tests/Tests.Core/ManagedOpenSearch/NodeSeeders/DefaultSeeder.cs index 23cc132c64..08ffa5141d 100644 --- a/tests/Tests.Core/ManagedOpenSearch/NodeSeeders/DefaultSeeder.cs +++ b/tests/Tests.Core/ManagedOpenSearch/NodeSeeders/DefaultSeeder.cs @@ -44,8 +44,6 @@ public class DefaultSeeder public const string ProjectsAliasName = "projects-alias"; public const string TestsIndexTemplateName = "osc_tests"; - public const string RemoteClusterName = "remote-cluster"; - public const string PipelineName = "osc-pipeline"; private readonly IIndexSettings _defaultIndexSettings = new IndexSettings() @@ -95,7 +93,6 @@ private async Task SeedNodeAsync(bool alreadySeeded) { // Ensure a clean slate by deleting everything regardless of whether they may already exist await DeleteIndicesAndTemplatesAsync(alreadySeeded).ConfigureAwait(false); - await ClusterSettingsAsync().ConfigureAwait(false); await PutPipeline().ConfigureAwait(false); // and now recreate everything await CreateIndicesAndSeedIndexDataAsync().ConfigureAwait(false); @@ -105,31 +102,10 @@ private async Task SeedNodeNoDataAsync(bool alreadySeeded) { // Ensure a clean slate by deleting everything regardless of whether they may already exist await DeleteIndicesAndTemplatesAsync(alreadySeeded).ConfigureAwait(false); - await ClusterSettingsAsync().ConfigureAwait(false); // and now recreate everything await CreateIndicesAsync().ConfigureAwait(false); } - public async Task ClusterSettingsAsync() - { - var clusterConfiguration = new Dictionary() - { - { "cluster.routing.use_adaptive_replica_selection", true } - }; - - clusterConfiguration += new RemoteClusterConfiguration - { - { RemoteClusterName, "127.0.0.1:9300" } - }; - - var putSettingsResponse = await Client.Cluster.PutSettingsAsync(new ClusterPutSettingsRequest - { - Transient = clusterConfiguration - }).ConfigureAwait(false); - - putSettingsResponse.ShouldBeValid(); - } - public async Task PutPipeline() { var putProcessors = await Client.Ingest.PutPipelineAsync(PipelineName, pi => pi diff --git a/tests/Tests/Cat/CatSegmentReplication/CatSegmentReplicationApiTests.cs b/tests/Tests/Cat/CatSegmentReplication/CatSegmentReplicationApiTests.cs index 1c5aab5b9e..f1dac93704 100644 --- a/tests/Tests/Cat/CatSegmentReplication/CatSegmentReplicationApiTests.cs +++ b/tests/Tests/Cat/CatSegmentReplication/CatSegmentReplicationApiTests.cs @@ -7,6 +7,7 @@ using System; using System.Linq; +using System.Threading; using FluentAssertions; using OpenSearch.Client; using OpenSearch.Net; @@ -20,9 +21,9 @@ namespace Tests.Cat.CatSegmentReplication; [SkipVersion("<2.7.0", "/_cat/segment_replication was added in version 2.7.0")] public class CatSegmentReplicationApiTests - : ApiIntegrationTestBase, ICatSegmentReplicationRequest, CatSegmentReplicationDescriptor, CatSegmentReplicationRequest> + : ApiIntegrationTestBase, ICatSegmentReplicationRequest, CatSegmentReplicationDescriptor, CatSegmentReplicationRequest> { - public CatSegmentReplicationApiTests(ReplicatedReadOnlyCluster cluster, EndpointUsage usage) : base(cluster, usage) { } + public CatSegmentReplicationApiTests(MultiNodeCluster cluster, EndpointUsage usage) : base(cluster, usage) { } private static readonly string IndexName = nameof(CatSegmentReplicationApiTests).ToLower(); @@ -45,9 +46,11 @@ protected override void ExpectResponse(CatResponse response.Records.Should().NotBeEmpty().And.AllSatisfy(r => r.ShardId.Should().StartWith($"[{IndexName}]")); protected override void IntegrationSetup(IOpenSearchClient client, CallUniqueValues values) - { + { var resp = client.Indices.Create(IndexName, d => d .Settings(s => s + .NumberOfShards(1) + .NumberOfReplicas(1) .Setting("index.replication.type", "SEGMENT"))); resp.ShouldBeValid(); @@ -56,9 +59,16 @@ protected override void IntegrationSetup(IOpenSearchClient client, CallUniqueVal .IndexMany(Enumerable.Range(0, 10).Select(i => new Doc { Id = i })) .Refresh(Refresh.WaitFor)); bulkResp.ShouldBeValid(); - } - protected override void IntegrationTeardown(IOpenSearchClient client, CallUniqueValues values) => client.Indices.Delete(IndexName); + var healthResp = client.Cluster.Health(IndexName, d => d + .WaitForStatus(HealthStatus.Green) + .WaitForNodes("2") + .Timeout("30s") + .Level(ClusterHealthLevel.Shards) + .WaitForNoInitializingShards() + .WaitForNoRelocatingShards()); + healthResp.ShouldBeValid(); + } public class Doc {