diff --git a/.editorconfig b/.editorconfig
index 6daa71388b..9788a79bdd 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -2,21 +2,23 @@ root=true
[*.cs]
trim_trailing_whitespace=true
-insert_final_newline=true
[*]
+charset = utf-8
+end_of_line = lf
indent_style = tab
indent_size = 4
+insert_final_newline=true
[*.cshtml]
indent_style = tab
indent_size = 4
-[*.{fs,fsx}]
+[*.{fs,fsx,yml}]
indent_style = space
indent_size = 4
-[*.{md,markdown,json,js,csproj,fsproj,targets,targets,props,yml}]
+[*.{md,markdown,json,js,csproj,fsproj,targets,targets,props}]
indent_style = space
indent_size = 2
@@ -29,11 +31,86 @@ indent_size = 2
# ---
# ---
-# langugage conventions https://docs.microsoft.com/en-us/visualstudio/ide/editorconfig-code-style-settings-reference#language-conventions
+# language conventions https://docs.microsoft.com/en-us/visualstudio/ide/editorconfig-code-style-settings-reference#language-conventions
# Sort using and Import directives with System.* appearing first
dotnet_sort_system_directives_first = true
+# Style rules
+# https://docs.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/naming-rules?view=vs-2017
+
+# Constants always pascal case
+dotnet_naming_rule.constants_should_be_pascal_case.symbols = consts
+dotnet_naming_rule.constants_should_be_pascal_case.style = consts
+dotnet_naming_rule.constants_should_be_pascal_case.severity = suggestion
+
+dotnet_naming_symbols.consts.applicable_kinds = field
+dotnet_naming_symbols.consts.applicable_accessibilities = *
+dotnet_naming_symbols.consts.required_modifiers = const
+
+dotnet_naming_style.consts.capitalization = pascal_case
+
+# Non-public static fields always pascal case
+dotnet_naming_rule.non_public_static_fields_should_be_pascal_case.symbols = non_public_static_fields
+dotnet_naming_rule.non_public_static_fields_should_be_pascal_case.style = non_public_static_fields
+dotnet_naming_rule.non_public_static_fields_should_be_pascal_case.severity = suggestion
+
+dotnet_naming_symbols.non_public_static_fields.applicable_kinds = field
+dotnet_naming_symbols.non_public_static_fields.applicable_accessibilities = private,protected,internal,protected_internal,private_protected
+dotnet_naming_symbols.non_public_static_fields.required_modifiers = static
+
+dotnet_naming_style.non_public_static_fields.capitalization = pascal_case
+
+# Non-private readonly fields are pascal case
+dotnet_naming_rule.non_private_readonly_fields_should_be_pascal_case.severity = suggestion
+dotnet_naming_rule.non_private_readonly_fields_should_be_pascal_case.symbols = non_private_readonly_fields
+dotnet_naming_rule.non_private_readonly_fields_should_be_pascal_case.style = non_private_readonly_fields
+
+dotnet_naming_symbols.non_private_readonly_fields.applicable_kinds = field
+dotnet_naming_symbols.non_private_readonly_fields.applicable_accessibilities = public,protected,internal,protected_internal,private_protected
+dotnet_naming_symbols.non_private_readonly_fields.required_modifiers = readonly
+
+dotnet_naming_style.non_private_readonly_fields.capitalization = pascal_case
+
+# Private instance fields are camel case prefixed underscore
+dotnet_naming_rule.private_fields_should_be_camelcase_prefix_underscore.symbols = private_fields
+dotnet_naming_rule.private_fields_should_be_camelcase_prefix_underscore.style = private_fields
+dotnet_naming_rule.private_fields_should_be_camelcase_prefix_underscore.severity = suggestion
+
+dotnet_naming_symbols.private_fields.applicable_kinds = field
+dotnet_naming_symbols.private_fields.applicable_accessibilities = private
+
+dotnet_naming_style.private_fields.capitalization = camel_case
+dotnet_naming_style.private_fields.required_prefix = _
+
+# Locals and parameters are camel case
+dotnet_naming_rule.locals.severity = suggestion
+dotnet_naming_rule.locals.symbols = locals
+dotnet_naming_rule.locals.style = locals
+
+dotnet_naming_symbols.locals.applicable_kinds = parameter, local
+
+dotnet_naming_style.locals.capitalization = camel_case
+
+# Local functions are pascal case
+dotnet_naming_rule.local_functions.severity = suggestion
+dotnet_naming_rule.local_functions.symbols = local_functions
+dotnet_naming_rule.local_functions.style = local_functions
+
+dotnet_naming_symbols.local_functions.applicable_kinds = local_function
+
+dotnet_naming_style.local_functions.capitalization = pascal_case
+
+# Public members always pascal case
+dotnet_naming_rule.public_members_should_be_pascal_case.symbols = public_members
+dotnet_naming_rule.public_members_should_be_pascal_case.style = public_members
+dotnet_naming_rule.public_members_should_be_pascal_case.severity = suggestion
+
+dotnet_naming_symbols.public_members.applicable_kinds = property,method,field,event,delegate
+dotnet_naming_symbols.public_members.applicable_accessibilities = public
+
+dotnet_naming_style.public_members.capitalization = pascal_case
+
dotnet_style_qualification_for_field = false:error
dotnet_style_qualification_for_property = false:error
dotnet_style_qualification_for_method = false:error
@@ -82,7 +159,7 @@ csharp_prefer_braces = false:warning
csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async:error
# ---
-# formatting conventions https://docs.microsoft.com/en-us/visualstudio/ide/editorconfig-formatting-conventions
+# formatting conventions https://docs.microsoft.com/en-us/visualstudio/ide/editorconfig-code-style-settings-reference#formatting-conventions
# Newline settings (Allman yo!)
csharp_new_line_before_open_brace = all
@@ -108,15 +185,30 @@ csharp_preserve_single_line_statements = false
csharp_preserve_single_line_blocks = true
# Resharper
-resharper_csharp_braces_for_lock=required_for_complex
-resharper_csharp_braces_for_using=required_for_complex
-resharper_csharp_braces_for_while=required_for_complex
-resharper_csharp_braces_for_foreach=required_for_complex
-resharper_csharp_braces_for_for=required_for_complex
-resharper_csharp_braces_for_fixed=required_for_complex
-resharper_csharp_braces_for_ifelse=required_for_complex
+resharper_csharp_braces_for_lock=required_for_multiline
+resharper_csharp_braces_for_using=required_for_multiline
+resharper_csharp_braces_for_while=required_for_multiline
+resharper_csharp_braces_for_foreach=required_for_multiline
+resharper_csharp_braces_for_for=required_for_multiline
+resharper_csharp_braces_for_fixed=required_for_multiline
+resharper_csharp_braces_for_ifelse=required_for_multiline
resharper_csharp_accessor_owner_body=expression_body
resharper_redundant_case_label_highlighting=do_not_show
resharper_redundant_argument_default_value_highlighting=do_not_show
+
+[Jenkinsfile]
+indent_style = space
+indent_size = 2
+end_of_line = lf
+charset = utf-8
+trim_trailing_whitespace = true
+insert_final_newline = true
+
+[*.{sh,bat,ps1}]
+trim_trailing_whitespace=true
+insert_final_newline=true
+
+[*.sh]
+end_of_line = lf
diff --git a/.gitignore b/.gitignore
index 88f04bb544..192b199099 100644
--- a/.gitignore
+++ b/.gitignore
@@ -20,6 +20,7 @@
*.cache
*.ilk
*.log
+*.nupkg
*.ncrunchsolution
[Bb]in
[Dd]ebug/
@@ -27,20 +28,20 @@ test-results
test-results/*
*.lib
*.sbr
-*.DotSettings.user
+*.DotSettings
obj/
[Rr]elease*/
-!docs/release-notes
_ReSharper*/
_NCrunch*/
[Tt]est[Rr]esult*
.fake/*
.fake
+packages/*
+!.paket/paket.bootstrapper.exe
paket.exe
paket-files/*.cached
-BenchmarkDotNet.Artifacts
build/*
!build/tools
!build/keys
@@ -54,17 +55,15 @@ build/tools/*
!build/*.nuspec
!build/*.png
!build/*.targets
-!build/*.sh
!build/scripts
-.ci/output
-
/dep/Newtonsoft.Json.4.0.2
!docs/build
docs/node_modules
doc/Help
+/src/Osc.Tests.Unit/*.ncrunchproject
*.ncrunchproject
Cache
YamlCache
@@ -79,13 +78,12 @@ launchSettings.json
project.lock.json
.vs
.vs/*
+.vscode/*
+.sonarqube/*
.ionide
.ionide/*
+
.idea/
*.sln.iml
/src/.vs/restore.dg
-# temporary location for doc generation
-docs-temp
-*.binlog
-dotnet-tool/*
diff --git a/Directory.Build.props b/Directory.Build.props
index a161915c04..062e9adf3d 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -22,6 +22,7 @@
See https://github.com/opensearch-project/opensearch-net/releases
https://github.com/opensearch-project/opensearch-net
https://raw.githubusercontent.com/opensearch-project/opensearch-net/main/build/nuget-icon.png
+ Git
diff --git a/Directory.Build.targets b/Directory.Build.targets
index 2a3efcc303..fedd06d16c 100644
--- a/Directory.Build.targets
+++ b/Directory.Build.targets
@@ -1,8 +1,8 @@
-
-
+
+
true
- $(SolutionRoot)\build\keys\keypair.snk
+ $(MSBuildThisFileDirectory)\build\keys\keypair.snk
bin/$(Configuration)/$(TargetFramework)/
diff --git a/MAINTAINERS.md b/MAINTAINERS.md
index 2599f627a0..38b7ab472b 100644
--- a/MAINTAINERS.md
+++ b/MAINTAINERS.md
@@ -18,14 +18,16 @@ This document explains who the maintainers are (see below), what they do in this
## Current Maintainers
-| Maintainer | GitHub ID | Affiliation |
-| ------------------------ | --------------------------------------------------- | ----------- |
-| Anirudha Jadhav | [anirudha](https://github.com/anirudha) | Amazon |
-| Joshua Li | [joshuali925](https://github.com/joshuali925) | Amazon |
-| Alex Meizer | [alexmeizer](https://github.com/alexmeizer) | Bit Quill |
-| Guian Gumpac | [guiangumpac](https://github.com/guiangumpac) | Bit Quill |
-| Raymond Lum | [raymond-lum](https://github.com/raymond-lum) | Bit Quill |
-| Yury Fridlyand | [Yury-Fridlyand](https://github.com/Yury-Fridlyand) | Bit Quill |
+| Maintainer | GitHub ID | Affiliation |
+| ------------------------ | ------------------------------------------------------------------ | ----------- |
+| Anirudha Jadhav | [anirudha](https://github.com/anirudha) | Amazon |
+| Joshua Li | [joshuali925](https://github.com/joshuali925) | Amazon |
+| Guian Gumpac | [guiangumpac](https://github.com/guiangumpac) | Bit Quill |
+| Raymond Lum | [raymond-lum](https://github.com/raymond-lum) | Bit Quill |
+| Yury Fridlyand | [Yury-Fridlyand](https://github.com/Yury-Fridlyand) | Bit Quill |
+| Max Ksyunz | [MaxKsyunz](https://github.com/MaxKsyunz) | Bit Quill |
+| Forest Vey | [forestmvey](https://github.com/forestmvey) | Bit Quill |
+| Mitchell Gale | [MitchellGale-BitQuill](https://github.com/MitchellGale-BitQuill) | Bit Quill |
## Maintainer Responsibilities
diff --git a/OpenSearch.sln b/OpenSearch.sln
index 1ec24fd9eb..d2c0f49b5a 100644
--- a/OpenSearch.sln
+++ b/OpenSearch.sln
@@ -12,10 +12,10 @@ EndProject
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "scripts", "build\scripts\scripts.fsproj", "{D6997ADC-E933-418E-831C-DE1A78897493}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{6C4A2627-AF22-4388-9DF7-7A9AEACFD635}"
-ProjectSection(SolutionItems) = preProject
- tests\Directory.Build.props = tests\Directory.Build.props
- tests\.runsettings = tests\.runsettings
-EndProjectSection
+ ProjectSection(SolutionItems) = preProject
+ tests\Directory.Build.props = tests\Directory.Build.props
+ tests\.runsettings = tests\.runsettings
+ EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tests", "tests\Tests\Tests.csproj", "{5B393962-7586-49BA-BD99-3B1E35F48E94}"
EndProject
@@ -32,47 +32,66 @@ EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tests.ScratchPad", "tests\Tests.ScratchPad\Tests.ScratchPad.csproj", "{CE7AC1D4-15AF-47FB-83FA-F7137DFD9076}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Root", "Root", "{EAE89579-CCA9-45CE-AF83-3DCD98690EA8}"
-ProjectSection(SolutionItems) = preProject
- .editorconfig = .editorconfig
- .gitignore = .gitignore
- global.json = global.json
- nuget.config = nuget.config
- dotnet-tools.json = dotnet-tools.json
-EndProjectSection
+ ProjectSection(SolutionItems) = preProject
+ .editorconfig = .editorconfig
+ .gitignore = .gitignore
+ global.json = global.json
+ nuget.config = nuget.config
+ dotnet-tools.json = dotnet-tools.json
+ EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Markdown", "Markdown", "{2FABB663-F4DB-499A-89F8-3A08828D1D91}"
-ProjectSection(SolutionItems) = preProject
- admins.md = admins.md
- code_of_conduct.md = code_of_conduct.md
- compatibility.md = compatibility.md
- contributing.md = contributing.md
- maintainers.md = maintainers.md
- license.txt = license.txt
- readme.md = readme.md
- releasing.md = releasing.md
- security.md = security.md
- user_guide.md = user_guide.md
-EndProjectSection
+ ProjectSection(SolutionItems) = preProject
+ admins.md = admins.md
+ code_of_conduct.md = code_of_conduct.md
+ compatibility.md = compatibility.md
+ contributing.md = contributing.md
+ maintainers.md = maintainers.md
+ license.txt = license.txt
+ readme.md = readme.md
+ releasing.md = releasing.md
+ security.md = security.md
+ user_guide.md = user_guide.md
+ EndProjectSection
EndProject
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "Tests.YamlRunner", "tests\Tests.YamlRunner\Tests.YamlRunner.fsproj", "{81473437-5722-4829-A5CD-125B17CCA238}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{3EA11364-0513-44B7-AD6D-A675485E7448}"
-ProjectSection(SolutionItems) = preProject
- src\_PublishArtifacts.Build.props = src\_PublishArtifacts.Build.props
-EndProjectSection
+ ProjectSection(SolutionItems) = preProject
+ src\_PublishArtifacts.Build.props = src\_PublishArtifacts.Build.props
+ EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ApiGenerator", "src\ApiGenerator\ApiGenerator.csproj", "{CA508E92-50AE-4858-BD94-8637E88A8FAC}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenSearch.Net.VirtualizedCluster", "src\OpenSearch.Net.VirtualizedCluster\OpenSearch.Net.VirtualizedCluster.csproj", "{CFE97627-8DD3-470B-B7CF-78B62E1D305D}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{29E53C13-34F7-4F0D-8D28-41EF768793E7}"
-ProjectSection(SolutionItems) = preProject
- Directory.Build.props = Directory.Build.props
- Directory.Build.targets = Directory.Build.targets
-EndProjectSection
+ ProjectSection(SolutionItems) = preProject
+ Directory.Build.props = Directory.Build.props
+ Directory.Build.targets = Directory.Build.targets
+ EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenSearch.Client.JsonNetSerializer", "src\OpenSearch.Client.JsonNetSerializer\OpenSearch.Client.JsonNetSerializer.csproj", "{B16AAB37-9FF4-4940-AC7D-437DFD18A6F6}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenSearch.Stack.ArtifactsApiTests", "abstractions\src\OpenSearch.Stack.ArtifactsApiTests\OpenSearch.Stack.ArtifactsApiTests.csproj", "{1F5A7B1A-2566-481F-91B5-A63D7F939973}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "abstractions", "abstractions", "{87ABA679-F3F4-48CE-82B3-1AAE5D0A5935}"
+ ProjectSection(SolutionItems) = preProject
+ abstractions\README.md = abstractions\README.md
+ EndProjectSection
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{ABE3B7EE-5B31-4C9A-976A-AD28D257B147}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenSearch.OpenSearch.Ephemeral", "abstractions\src\OpenSearch.OpenSearch.Ephemeral\OpenSearch.OpenSearch.Ephemeral.csproj", "{31668B33-6157-4A5B-8D4C-18AF760DCA1B}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenSearch.OpenSearch.EphemeralTests", "abstractions\src\OpenSearch.OpenSearch.EphemeralTests\OpenSearch.OpenSearch.EphemeralTests.csproj", "{C80D225C-F072-4B24-9ACE-82EFD9362237}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenSearch.OpenSearch.Managed", "abstractions\src\OpenSearch.OpenSearch.Managed\OpenSearch.OpenSearch.Managed.csproj", "{A9125BAC-71B5-4DC8-879D-1154A0A7DE5C}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenSearch.OpenSearch.Xunit", "abstractions\src\OpenSearch.OpenSearch.Xunit\OpenSearch.OpenSearch.Xunit.csproj", "{39B7E62B-BDDF-46F2-9306-CE5FC68573A2}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenSearch.Stack.ArtifactsApi", "abstractions\src\OpenSearch.Stack.ArtifactsApi\OpenSearch.Stack.ArtifactsApi.csproj", "{E7C0BDC2-28AD-4582-8FEA-0F6327A42C0E}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -102,6 +121,12 @@ Global
{D6997ADC-E933-418E-831C-DE1A78897493} = {29E53C13-34F7-4F0D-8D28-41EF768793E7}
{432D5575-2347-4D3C-BF8C-3E38410C46CA} = {29E53C13-34F7-4F0D-8D28-41EF768793E7}
{B16AAB37-9FF4-4940-AC7D-437DFD18A6F6} = {3EA11364-0513-44B7-AD6D-A675485E7448}
+ {ABE3B7EE-5B31-4C9A-976A-AD28D257B147} = {87ABA679-F3F4-48CE-82B3-1AAE5D0A5935}
+ {31668B33-6157-4A5B-8D4C-18AF760DCA1B} = {ABE3B7EE-5B31-4C9A-976A-AD28D257B147}
+ {C80D225C-F072-4B24-9ACE-82EFD9362237} = {ABE3B7EE-5B31-4C9A-976A-AD28D257B147}
+ {A9125BAC-71B5-4DC8-879D-1154A0A7DE5C} = {ABE3B7EE-5B31-4C9A-976A-AD28D257B147}
+ {39B7E62B-BDDF-46F2-9306-CE5FC68573A2} = {ABE3B7EE-5B31-4C9A-976A-AD28D257B147}
+ {E7C0BDC2-28AD-4582-8FEA-0F6327A42C0E} = {ABE3B7EE-5B31-4C9A-976A-AD28D257B147}
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{5B393962-7586-49BA-BD99-3B1E35F48E94}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
@@ -164,5 +189,29 @@ Global
{B16AAB37-9FF4-4940-AC7D-437DFD18A6F6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B16AAB37-9FF4-4940-AC7D-437DFD18A6F6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B16AAB37-9FF4-4940-AC7D-437DFD18A6F6}.Release|Any CPU.Build.0 = Release|Any CPU
+ {1F5A7B1A-2566-481F-91B5-A63D7F939973}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {1F5A7B1A-2566-481F-91B5-A63D7F939973}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {1F5A7B1A-2566-481F-91B5-A63D7F939973}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {1F5A7B1A-2566-481F-91B5-A63D7F939973}.Release|Any CPU.Build.0 = Release|Any CPU
+ {31668B33-6157-4A5B-8D4C-18AF760DCA1B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {31668B33-6157-4A5B-8D4C-18AF760DCA1B}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {31668B33-6157-4A5B-8D4C-18AF760DCA1B}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {31668B33-6157-4A5B-8D4C-18AF760DCA1B}.Release|Any CPU.Build.0 = Release|Any CPU
+ {C80D225C-F072-4B24-9ACE-82EFD9362237}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {C80D225C-F072-4B24-9ACE-82EFD9362237}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {C80D225C-F072-4B24-9ACE-82EFD9362237}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {C80D225C-F072-4B24-9ACE-82EFD9362237}.Release|Any CPU.Build.0 = Release|Any CPU
+ {A9125BAC-71B5-4DC8-879D-1154A0A7DE5C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {A9125BAC-71B5-4DC8-879D-1154A0A7DE5C}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {A9125BAC-71B5-4DC8-879D-1154A0A7DE5C}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {A9125BAC-71B5-4DC8-879D-1154A0A7DE5C}.Release|Any CPU.Build.0 = Release|Any CPU
+ {39B7E62B-BDDF-46F2-9306-CE5FC68573A2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {39B7E62B-BDDF-46F2-9306-CE5FC68573A2}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {39B7E62B-BDDF-46F2-9306-CE5FC68573A2}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {39B7E62B-BDDF-46F2-9306-CE5FC68573A2}.Release|Any CPU.Build.0 = Release|Any CPU
+ {E7C0BDC2-28AD-4582-8FEA-0F6327A42C0E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {E7C0BDC2-28AD-4582-8FEA-0F6327A42C0E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {E7C0BDC2-28AD-4582-8FEA-0F6327A42C0E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {E7C0BDC2-28AD-4582-8FEA-0F6327A42C0E}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal
diff --git a/abstractions/README.md b/abstractions/README.md
new file mode 100644
index 0000000000..661e579b85
--- /dev/null
+++ b/abstractions/README.md
@@ -0,0 +1,46 @@
+![OpenSearch logo](../OpenSearch.svg)
+
+- [OpenSearch .NET abstractions](#opensearch-net-abstractions)
+ - [OpenSearch.OpenSearch.Managed](#opensearchopensearchmanaged)
+ - [OpenSearch.OpenSearch.Ephemeral](#opensearchopensearchephemeral)
+ - [OpenSearch.OpenSearch.Xunit](#opensearchopensearchxunit)
+ - [OpenSearch.Stack.ArtifactsApi](#opensearchstackartifactsapi)
+
+## Welcome!
+
+# OpenSearch .NET abstractions
+
+You've reached the home for several auxiliary projects from the .NET team within OpenSearch.
+
+Current projects:
+
+### [OpenSearch.OpenSearch.Managed](src/OpenSearch.OpenSearch.Managed/README.md)
+
+Provides an easy to start/stop one or more OpenSearch instances that exists on disk already
+
+### [OpenSearch.OpenSearch.Ephemeral](src/OpenSearch.OpenSearch.Ephemeral/README.md)
+
+Bootstrap (download, install, configure) and run OpenSearch clusters with ease.
+Started nodes are run in a new ephemeral location each time they are started and will clean up after they
+are disposed.
+
+### [OpenSearch.OpenSearch.Xunit](src/OpenSearch.OpenSearch.Xunit/README.md)
+
+Write integration tests against OpenSearch.
+Works with `.NET Core` and `.NET 4.6` and up.
+
+Supports `dotnet xunit`, `dotnet test`, `xunit.console.runner` and tests will be runnable in your IDE through VSTest and jetBrains Rider.
+
+### [OpenSearch.Stack.ArtifactsApi](src/OpenSearch.Stack.ArtifactsApi/README.md)
+
+Library to fetch the url and metadata for released artifacts.
+
+Supports:
+
+1. Snapshots builds
+ * `latest-MAJOR` where `MAJOR` is a single integer representing the major you want
+ * `latest` latest greatest
+
+2. Released versions
+ * `MAJOR.MINOR.PATH` where `MAJOR` is still supported as defined by the EOL policy of OpenSearch.
+ * Note if the version exists but is not yet released it will resolve as a build candidate
diff --git a/abstractions/src/OpenSearch.OpenSearch.Ephemeral/ClusterAuthentication.cs b/abstractions/src/OpenSearch.OpenSearch.Ephemeral/ClusterAuthentication.cs
new file mode 100644
index 0000000000..9f69796b96
--- /dev/null
+++ b/abstractions/src/OpenSearch.OpenSearch.Ephemeral/ClusterAuthentication.cs
@@ -0,0 +1,61 @@
+/* SPDX-License-Identifier: Apache-2.0
+*
+* The OpenSearch Contributors require contributions made to
+* this file be licensed under the Apache-2.0 license or a
+* compatible open source license.
+*/
+/*
+* Modifications Copyright OpenSearch Contributors. See
+* GitHub history for details.
+*
+* Licensed to Elasticsearch B.V. under one or more contributor
+* license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright
+* ownership. Elasticsearch B.V. licenses this file to you under
+* the Apache License, Version 2.0 (the "License"); you may
+* not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+namespace OpenSearch.OpenSearch.Ephemeral
+{
+ ///
+ /// Authentication credentials for the cluster
+ ///
+ public class ClusterAuthentication
+ {
+ ///
+ /// Administrator credentials
+ ///
+ public static Credentials Admin => new Credentials {Username = "admin", Role = "admin"};
+
+ ///
+ /// User credentials
+ ///
+ public static Credentials User => new Credentials {Username = "admin", Role = "admin"};
+
+ ///
+ /// Credentials for all users
+ ///
+ public static Credentials[] AllUsers { get; } = {Admin, User};
+
+ ///
+ /// Authentication credentials
+ ///
+ public class Credentials
+ {
+ public string Username { get; set; }
+ public string Role { get; set; }
+ public string Password => Username;
+ }
+ }
+}
diff --git a/abstractions/src/OpenSearch.OpenSearch.Ephemeral/ClusterFeatures.cs b/abstractions/src/OpenSearch.OpenSearch.Ephemeral/ClusterFeatures.cs
new file mode 100644
index 0000000000..ce36b0d436
--- /dev/null
+++ b/abstractions/src/OpenSearch.OpenSearch.Ephemeral/ClusterFeatures.cs
@@ -0,0 +1,50 @@
+/* SPDX-License-Identifier: Apache-2.0
+*
+* The OpenSearch Contributors require contributions made to
+* this file be licensed under the Apache-2.0 license or a
+* compatible open source license.
+*/
+/*
+* Modifications Copyright OpenSearch Contributors. See
+* GitHub history for details.
+*
+* Licensed to Elasticsearch B.V. under one or more contributor
+* license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright
+* ownership. Elasticsearch B.V. licenses this file to you under
+* the Apache License, Version 2.0 (the "License"); you may
+* not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+using System;
+
+namespace OpenSearch.OpenSearch.Ephemeral
+{
+ ///
+ /// Hints to what features the cluster to be started should have.
+ /// It's up to the to actually bootstrap these features.
+ ///
+ [Flags]
+ public enum ClusterFeatures
+ {
+ ///
+ /// No features
+ ///
+ None = 1 << 0,
+
+ ///
+ /// SSL/TLS for HTTP and Transport layers
+ ///
+ SSL = 1 << 3,
+ }
+}
diff --git a/abstractions/src/OpenSearch.OpenSearch.Ephemeral/EphemeralCluster.cs b/abstractions/src/OpenSearch.OpenSearch.Ephemeral/EphemeralCluster.cs
new file mode 100644
index 0000000000..5f6cae0882
--- /dev/null
+++ b/abstractions/src/OpenSearch.OpenSearch.Ephemeral/EphemeralCluster.cs
@@ -0,0 +1,133 @@
+/* SPDX-License-Identifier: Apache-2.0
+*
+* The OpenSearch Contributors require contributions made to
+* this file be licensed under the Apache-2.0 license or a
+* compatible open source license.
+*/
+/*
+* Modifications Copyright OpenSearch Contributors. See
+* GitHub history for details.
+*
+* Licensed to Elasticsearch B.V. under one or more contributor
+* license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright
+* ownership. Elasticsearch B.V. licenses this file to you under
+* the Apache License, Version 2.0 (the "License"); you may
+* not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using System.Security.Cryptography;
+using System.Text;
+using OpenSearch.OpenSearch.Managed;
+using OpenSearch.Stack.ArtifactsApi;
+
+namespace OpenSearch.OpenSearch.Ephemeral
+{
+ public class EphemeralCluster : EphemeralCluster
+ {
+ public EphemeralCluster(OpenSearchVersion version, int numberOfNodes = 1)
+ : base(new EphemeralClusterConfiguration(version, ServerType.DEFAULT, ClusterFeatures.None, numberOfNodes: numberOfNodes))
+ {
+ }
+
+ public EphemeralCluster(EphemeralClusterConfiguration clusterConfiguration) : base(clusterConfiguration)
+ {
+ }
+ }
+
+ public abstract class EphemeralCluster : ClusterBase,
+ IEphemeralCluster
+ where TConfiguration : EphemeralClusterConfiguration
+ {
+ protected EphemeralCluster(TConfiguration clusterConfiguration) : base(clusterConfiguration) =>
+ Composer = new EphemeralClusterComposer(this);
+
+ protected EphemeralClusterComposer Composer { get; }
+
+ public virtual ICollection NodesUris(string hostName = null)
+ {
+ hostName = hostName ?? (ClusterConfiguration.HttpFiddlerAware && Process.GetProcessesByName("fiddler").Any()
+ ? "ipv4.fiddler"
+ : "localhost");
+ var ssl = ClusterConfiguration.EnableSsl ? "s" : "";
+ return Nodes
+ .Select(n => $"http{ssl}://{hostName}:{n.Port ?? 9200}")
+ .Distinct()
+ .Select(n => new Uri(n))
+ .ToList();
+ }
+
+ public bool CachingAndCachedHomeExists()
+ {
+ if (!ClusterConfiguration.CacheOpenSearchHomeInstallation) return false;
+ var cachedOpenSearchHomeFolder = Path.Combine(FileSystem.LocalFolder, GetCacheFolderName());
+ return Directory.Exists(cachedOpenSearchHomeFolder);
+ }
+
+ public virtual string GetCacheFolderName()
+ {
+ var config = ClusterConfiguration;
+
+ var sb = new StringBuilder();
+ sb.Append(EphemeralClusterComposerBase.InstallationTasks.Count());
+ sb.Append("-");
+ if (config.EnableSsl) sb.Append("ssl");
+ if (config.Plugins != null && config.Plugins.Count > 0)
+ {
+ sb.Append("-");
+ foreach (var p in config.Plugins.OrderBy(p => p.SubProductName))
+ sb.Append(p.SubProductName.ToLowerInvariant());
+ }
+
+ var name = sb.ToString();
+
+ return CalculateSha1(name, Encoding.UTF8);
+ }
+
+ protected override void OnBeforeStart()
+ {
+ Composer.Install();
+ Composer.OnBeforeStart();
+ }
+
+ protected override void OnDispose() => Composer.OnStop();
+
+ protected override void OnAfterStarted() => Composer.OnAfterStart();
+
+ protected override string SeeLogsMessage(string message)
+ {
+ var log = Path.Combine(FileSystem.LogsPath, $"{ClusterConfiguration.ClusterName}.log");
+ if (!File.Exists(log) || ClusterConfiguration.ShowOpenSearchOutputAfterStarted) return message;
+ if (!Started) return message;
+ using (var fileStream = new FileStream(log, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
+ using (var textReader = new StreamReader(fileStream))
+ {
+ var logContents = textReader.ReadToEnd();
+ return message + $" contents of {log}:{Environment.NewLine}" + logContents;
+ }
+ }
+
+ public static string CalculateSha1(string text, Encoding enc)
+ {
+ var buffer = enc.GetBytes(text);
+ var cryptoTransformSha1 = new SHA1CryptoServiceProvider();
+ return BitConverter.ToString(cryptoTransformSha1.ComputeHash(buffer))
+ .Replace("-", "").ToLowerInvariant().Substring(0, 12);
+ }
+ }
+}
diff --git a/abstractions/src/OpenSearch.OpenSearch.Ephemeral/EphemeralClusterComposer.cs b/abstractions/src/OpenSearch.OpenSearch.Ephemeral/EphemeralClusterComposer.cs
new file mode 100644
index 0000000000..bd055f4874
--- /dev/null
+++ b/abstractions/src/OpenSearch.OpenSearch.Ephemeral/EphemeralClusterComposer.cs
@@ -0,0 +1,135 @@
+/* SPDX-License-Identifier: Apache-2.0
+*
+* The OpenSearch Contributors require contributions made to
+* this file be licensed under the Apache-2.0 license or a
+* compatible open source license.
+*/
+/*
+* Modifications Copyright OpenSearch Contributors. See
+* GitHub history for details.
+*
+* Licensed to Elasticsearch B.V. under one or more contributor
+* license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright
+* ownership. Elasticsearch B.V. licenses this file to you under
+* the Apache License, Version 2.0 (the "License"); you may
+* not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+using System;
+using System.Collections.Generic;
+using OpenSearch.OpenSearch.Ephemeral.Tasks;
+using OpenSearch.OpenSearch.Ephemeral.Tasks.AfterNodeStoppedTasks;
+using OpenSearch.OpenSearch.Ephemeral.Tasks.BeforeStartNodeTasks;
+using OpenSearch.OpenSearch.Ephemeral.Tasks.InstallationTasks;
+using OpenSearch.OpenSearch.Ephemeral.Tasks.ValidationTasks;
+using OpenSearch.OpenSearch.Managed.FileSystem;
+
+namespace OpenSearch.OpenSearch.Ephemeral
+{
+ public class EphemeralClusterComposerBase
+ {
+ protected EphemeralClusterComposerBase()
+ {
+ }
+
+ internal static IEnumerable InstallationTasks { get; } = new List
+ {
+ new PrintConfiguration(),
+ new CreateLocalApplicationDirectory(),
+ new CopyCachedOpenSearchInstallation(),
+ new EnsureJavaHomeEnvironmentVariableIsSet(),
+ new DownloadOpenSearchVersion(),
+ new UnzipOpenSearch(),
+ new SetOpenSearchBundledJdkJavaHome(),
+ new InstallPlugins(),
+ new InitialConfiguration()
+ };
+
+ protected static IEnumerable BeforeStart { get; } = new List
+ {
+ new CreateEphemeralDirectory(),
+ new CacheOpenSearchInstallation()
+ };
+
+ protected static IEnumerable NodeStoppedTasks { get; } = new List
+ {
+ new CleanUpDirectoriesAfterNodeStopped()
+ };
+
+ protected static IEnumerable AfterStartedTasks { get; } = new List
+ {
+ new ValidateRunningVersion(),
+ new ValidateClusterStateTask(),
+ new ValidatePluginsTask(),
+ };
+ }
+
+
+ public class EphemeralClusterComposer : EphemeralClusterComposerBase
+ where TConfiguration : EphemeralClusterConfiguration
+ {
+ private readonly object _lock = new object();
+ public EphemeralClusterComposer(IEphemeralCluster cluster) => Cluster = cluster;
+
+ private IEphemeralCluster Cluster { get; }
+
+ private bool NodeStarted { get; set; }
+
+ public void OnStop() => Itterate(NodeStoppedTasks, (t, c, fs) => t.Run(c, NodeStarted), false);
+
+ public void Install() => Itterate(InstallationTasks, (t, c, fs) => t.Run(c));
+
+ public void OnBeforeStart()
+ {
+ var tasks = new List(BeforeStart);
+ if (Cluster.ClusterConfiguration.AdditionalBeforeNodeStartedTasks != null)
+ tasks.AddRange(Cluster.ClusterConfiguration.AdditionalBeforeNodeStartedTasks);
+
+ if (Cluster.ClusterConfiguration.PrintYamlFilesInConfigFolder)
+ tasks.Add(new PrintYamlContents());
+
+ Itterate(tasks, (t, c, fs) => t.Run(c));
+
+ NodeStarted = true;
+ }
+
+ public void OnAfterStart()
+ {
+ if (Cluster.ClusterConfiguration.SkipBuiltInAfterStartTasks) return;
+ var tasks = new List(AfterStartedTasks);
+ if (Cluster.ClusterConfiguration.AdditionalAfterStartedTasks != null)
+ tasks.AddRange(Cluster.ClusterConfiguration.AdditionalAfterStartedTasks);
+ Itterate(tasks, (t, c, fs) => t.Run(c), false);
+ }
+
+ private void Itterate(IEnumerable collection,
+ Action, INodeFileSystem> act, bool callOnStop = true)
+ {
+ lock (_lock)
+ {
+ var cluster = Cluster;
+ foreach (var task in collection)
+ try
+ {
+ act(task, cluster, cluster.FileSystem);
+ }
+ catch (Exception)
+ {
+ if (callOnStop) OnStop();
+ throw;
+ }
+ }
+ }
+ }
+}
diff --git a/abstractions/src/OpenSearch.OpenSearch.Ephemeral/EphemeralClusterConfiguration.cs b/abstractions/src/OpenSearch.OpenSearch.Ephemeral/EphemeralClusterConfiguration.cs
new file mode 100644
index 0000000000..748763faff
--- /dev/null
+++ b/abstractions/src/OpenSearch.OpenSearch.Ephemeral/EphemeralClusterConfiguration.cs
@@ -0,0 +1,102 @@
+/* SPDX-License-Identifier: Apache-2.0
+*
+* The OpenSearch Contributors require contributions made to
+* this file be licensed under the Apache-2.0 license or a
+* compatible open source license.
+*/
+/*
+* Modifications Copyright OpenSearch Contributors. See
+* GitHub history for details.
+*
+* Licensed to Elasticsearch B.V. under one or more contributor
+* license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright
+* ownership. Elasticsearch B.V. licenses this file to you under
+* the Apache License, Version 2.0 (the "License"); you may
+* not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text.RegularExpressions;
+using OpenSearch.OpenSearch.Ephemeral.Plugins;
+using OpenSearch.OpenSearch.Ephemeral.Tasks;
+using OpenSearch.OpenSearch.Managed.Configuration;
+using OpenSearch.Stack.ArtifactsApi;
+using OpenSearch.Stack.ArtifactsApi.Products;
+
+namespace OpenSearch.OpenSearch.Ephemeral
+{
+ public class EphemeralClusterConfiguration : ClusterConfiguration
+ {
+ public EphemeralClusterConfiguration(OpenSearchVersion version, ServerType serverType, OpenSearchPlugins plugins = null,
+ int numberOfNodes = 1)
+ : this(version, serverType, ClusterFeatures.None, plugins, numberOfNodes)
+ {
+ }
+
+ public EphemeralClusterConfiguration(OpenSearchVersion version, ServerType serverType, ClusterFeatures features,
+ OpenSearchPlugins plugins = null, int numberOfNodes = 1)
+ : base(version, serverType, (v, s) => new EphemeralFileSystem(v, s), numberOfNodes, EphemeralClusterName)
+ {
+ Features = features;
+
+ var pluginsList = plugins?.ToList() ?? new List();
+ Plugins = new OpenSearchPlugins(pluginsList);
+ }
+
+ private static string UniqueishSuffix => Guid.NewGuid().ToString("N").Substring(0, 6);
+ private static string EphemeralClusterName => $"ephemeral-cluster-{UniqueishSuffix}";
+
+ ///
+ /// The features supported by the cluster
+ ///
+ public ClusterFeatures Features { get; }
+
+ ///
+ /// The collection of plugins to install
+ ///
+ public OpenSearchPlugins Plugins { get; }
+
+ ///
+ /// Validates that the plugins to install can be installed on the target OpenSearch version.
+ /// This can be useful to fail early when subsequent operations are relying on installation
+ /// succeeding.
+ ///
+ public bool ValidatePluginsToInstall { get; } = true;
+
+ public bool EnableSsl => Features.HasFlag(ClusterFeatures.SSL);
+
+ public IList AdditionalBeforeNodeStartedTasks { get; } = new List();
+
+ public IList AdditionalAfterStartedTasks { get; } = new List();
+
+ ///
+ /// Expert level setting, skips all built-in validation tasks for cases where you need to guarantee your call is the
+ /// first call into the cluster
+ ///
+ public bool SkipBuiltInAfterStartTasks { get; set; }
+
+ /// Bootstrapping HTTP calls should attempt to auto route traffic through fiddler if its running
+ public bool HttpFiddlerAware { get; set; }
+
+ protected virtual string NodePrefix => "ephemeral";
+
+ public override string CreateNodeName(int? node)
+ {
+ var suffix = Guid.NewGuid().ToString("N").Substring(0, 6);
+ return $"{NodePrefix}-node-{suffix}{node}";
+ }
+ }
+}
diff --git a/abstractions/src/OpenSearch.OpenSearch.Ephemeral/EphemeralFileSystem.cs b/abstractions/src/OpenSearch.OpenSearch.Ephemeral/EphemeralFileSystem.cs
new file mode 100644
index 0000000000..9eebfa981c
--- /dev/null
+++ b/abstractions/src/OpenSearch.OpenSearch.Ephemeral/EphemeralFileSystem.cs
@@ -0,0 +1,87 @@
+/* SPDX-License-Identifier: Apache-2.0
+*
+* The OpenSearch Contributors require contributions made to
+* this file be licensed under the Apache-2.0 license or a
+* compatible open source license.
+*/
+/*
+* Modifications Copyright OpenSearch Contributors. See
+* GitHub history for details.
+*
+* Licensed to Elasticsearch B.V. under one or more contributor
+* license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright
+* ownership. Elasticsearch B.V. licenses this file to you under
+* the Apache License, Version 2.0 (the "License"); you may
+* not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+using System.IO;
+using OpenSearch.OpenSearch.Managed.FileSystem;
+using OpenSearch.Stack.ArtifactsApi;
+using OpenSearch.Stack.ArtifactsApi.Products;
+
+namespace OpenSearch.OpenSearch.Ephemeral
+{
+ public class EphemeralFileSystem : NodeFileSystem
+ {
+ public EphemeralFileSystem(OpenSearchVersion version, string clusterName) : base(version,
+ EphemeralHome(version, clusterName)) => ClusterName = clusterName;
+
+ private string ClusterName { get; }
+
+ public string TempFolder => Path.Combine(Path.GetTempPath(), SubFolder, Artifact.LocalFolderName, ClusterName);
+
+ public override string ConfigPath => Path.Combine(TempFolder, "config");
+ public override string LogsPath => Path.Combine(TempFolder, "logs");
+ public override string RepositoryPath => Path.Combine(TempFolder, "repositories");
+ public override string DataPath => Path.Combine(TempFolder, "data");
+
+ //certificates
+ public string CertificateFolderName => "node-certificates";
+ public string CertificateNodeName => "node01";
+ public string ClientCertificateName => "cn=John Doe,ou=example,o=com";
+ public string ClientCertificateFilename => "john_doe";
+
+ public string CertificatesPath => Path.Combine(ConfigPath, CertificateFolderName);
+
+ public string CaCertificate => Path.Combine(CertificatesPath, "ca", "ca") + ".crt";
+
+ public string NodePrivateKey =>
+ Path.Combine(CertificatesPath, CertificateNodeName, CertificateNodeName) + ".key";
+
+ public string NodeCertificate =>
+ Path.Combine(CertificatesPath, CertificateNodeName, CertificateNodeName) + ".crt";
+
+ public string ClientCertificate =>
+ Path.Combine(CertificatesPath, ClientCertificateFilename, ClientCertificateFilename) + ".crt";
+
+ public string ClientPrivateKey =>
+ Path.Combine(CertificatesPath, ClientCertificateFilename, ClientCertificateFilename) + ".key";
+
+ public string UnusedCertificateFolderName => $"unused-{CertificateFolderName}";
+ public string UnusedCertificatesPath => Path.Combine(ConfigPath, UnusedCertificateFolderName);
+ public string UnusedCaCertificate => Path.Combine(UnusedCertificatesPath, "ca", "ca") + ".crt";
+
+ public string UnusedClientCertificate =>
+ Path.Combine(UnusedCertificatesPath, ClientCertificateFilename, ClientCertificateFilename) + ".crt";
+
+
+ protected static string EphemeralHome(OpenSearchVersion version, string clusterName)
+ {
+ var temp = Path.Combine(Path.GetTempPath(), SubFolder,
+ version.Artifact(Product.OpenSearch).LocalFolderName, clusterName);
+ return Path.Combine(temp, "home");
+ }
+ }
+}
diff --git a/abstractions/src/OpenSearch.OpenSearch.Ephemeral/IEphemeralCluster.cs b/abstractions/src/OpenSearch.OpenSearch.Ephemeral/IEphemeralCluster.cs
new file mode 100644
index 0000000000..d97995713a
--- /dev/null
+++ b/abstractions/src/OpenSearch.OpenSearch.Ephemeral/IEphemeralCluster.cs
@@ -0,0 +1,46 @@
+/* SPDX-License-Identifier: Apache-2.0
+*
+* The OpenSearch Contributors require contributions made to
+* this file be licensed under the Apache-2.0 license or a
+* compatible open source license.
+*/
+/*
+* Modifications Copyright OpenSearch Contributors. See
+* GitHub history for details.
+*
+* Licensed to Elasticsearch B.V. under one or more contributor
+* license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright
+* ownership. Elasticsearch B.V. licenses this file to you under
+* the Apache License, Version 2.0 (the "License"); you may
+* not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+using System;
+using System.Collections.Generic;
+using OpenSearch.OpenSearch.Managed;
+
+namespace OpenSearch.OpenSearch.Ephemeral
+{
+ public interface IEphemeralCluster
+ {
+ ICollection NodesUris(string hostName = null);
+ string GetCacheFolderName();
+ bool CachingAndCachedHomeExists();
+ }
+
+ public interface IEphemeralCluster : IEphemeralCluster, ICluster
+ where TConfiguration : EphemeralClusterConfiguration
+ {
+ }
+}
diff --git a/abstractions/src/OpenSearch.OpenSearch.Ephemeral/OpenSearch.OpenSearch.Ephemeral.csproj b/abstractions/src/OpenSearch.OpenSearch.Ephemeral/OpenSearch.OpenSearch.Ephemeral.csproj
new file mode 100644
index 0000000000..ecf5947967
--- /dev/null
+++ b/abstractions/src/OpenSearch.OpenSearch.Ephemeral/OpenSearch.OpenSearch.Ephemeral.csproj
@@ -0,0 +1,18 @@
+
+
+
+ netstandard2.0;net461
+ Provides an EphemeralCluster implementation that can download/bootstrap/run a throwaway customizable OpenSearch cluster
+ opensearch,opensearch,cluster,ephemeral
+ false
+
+ true
+
+
+
+
+
+
+
+
+
diff --git a/abstractions/src/OpenSearch.OpenSearch.Ephemeral/Plugins/OpenSearchPlugins.cs b/abstractions/src/OpenSearch.OpenSearch.Ephemeral/Plugins/OpenSearchPlugins.cs
new file mode 100644
index 0000000000..c74af2f9eb
--- /dev/null
+++ b/abstractions/src/OpenSearch.OpenSearch.Ephemeral/Plugins/OpenSearchPlugins.cs
@@ -0,0 +1,75 @@
+/* SPDX-License-Identifier: Apache-2.0
+*
+* The OpenSearch Contributors require contributions made to
+* this file be licensed under the Apache-2.0 license or a
+* compatible open source license.
+*/
+/*
+* Modifications Copyright OpenSearch Contributors. See
+* GitHub history for details.
+*
+* Licensed to Elasticsearch B.V. under one or more contributor
+* license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright
+* ownership. Elasticsearch B.V. licenses this file to you under
+* the Apache License, Version 2.0 (the "License"); you may
+* not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Linq;
+using OpenSearch.Stack.ArtifactsApi.Products;
+
+namespace OpenSearch.OpenSearch.Ephemeral.Plugins
+{
+ public class OpenSearchPlugins : ReadOnlyCollection
+ {
+ public OpenSearchPlugins(IList list) : base(list)
+ {
+ }
+
+ public OpenSearchPlugins(params OpenSearchPlugin[] list) : base(list)
+ {
+ }
+
+ public static OpenSearchPlugins Supported { get; } =
+ new OpenSearchPlugins(new List
+ {
+ OpenSearchPlugin.AnalysisIcu,
+ OpenSearchPlugin.AnalysisKuromoji,
+ OpenSearchPlugin.AnalysisPhonetic,
+ OpenSearchPlugin.AnalysisSmartCn,
+ OpenSearchPlugin.AnalysisStempel,
+ OpenSearchPlugin.AnalysisUkrainian,
+ OpenSearchPlugin.DiscoveryAzureClassic,
+ OpenSearchPlugin.DiscoveryEC2,
+ OpenSearchPlugin.DiscoveryFile,
+ OpenSearchPlugin.DiscoveryGCE,
+ OpenSearchPlugin.IngestAttachment,
+ OpenSearchPlugin.IngestGeoIp,
+ OpenSearchPlugin.IngestUserAgent,
+ OpenSearchPlugin.MapperAttachment,
+ OpenSearchPlugin.MapperMurmur3,
+ OpenSearchPlugin.MapperSize,
+ OpenSearchPlugin.RepositoryAzure,
+ OpenSearchPlugin.RepositoryGCS,
+ OpenSearchPlugin.RepositoryHDFS,
+ OpenSearchPlugin.RepositoryS3,
+ OpenSearchPlugin.StoreSMB,
+ OpenSearchPlugin.DeleteByQuery,
+ });
+
+ public override string ToString() => string.Join(", ", Items.Select(s => s.SubProductName));
+ }
+}
diff --git a/abstractions/src/OpenSearch.OpenSearch.Ephemeral/README.md b/abstractions/src/OpenSearch.OpenSearch.Ephemeral/README.md
new file mode 100644
index 0000000000..39f5814d22
--- /dev/null
+++ b/abstractions/src/OpenSearch.OpenSearch.Ephemeral/README.md
@@ -0,0 +1,60 @@
+# OpenSearch.Managed.Ephemeral
+
+Bootstrap (download, install, configure) and run OpenSearch clusters with ease.
+Started nodes are run in a new ephemeral location each time they are started and will clean up after they
+are disposed.
+
+
+## EphemeralCluster
+
+A `ClusterBase` implementation from `OpenSearch.Managed` that can:
+
+* download opensearch versions (stable releases, snapshots, build candidates)
+* download opensearch plugins (stable releases, snapshots, build candidates)
+* install opensearch and desired plugins in an ephemeral location. The source downloaded zips are cached
+on disk (LocalAppData).
+* Ships with builtin knowledge on how to enable SSL on the running cluster.
+* Start opensearch using ephemeral locations for OPENSEARCH_HOME and conf/logs/data paths.
+
+
+#### Examples:
+
+The easiest way to get started is by simply passing the version you want to be bootstrapped to `EphemeralCluster`.
+`Start` starts the `OpenSearchNode`'s and waits for them to be started. The default overload waits `2 minutes`.
+
+```csharp
+using (var cluster = new EphemeralCluster("1.0.0"))
+{
+ cluster.Start();
+}
+```
+
+If you want the full configuration possibilities inject a `EphemeralClusterConfiguration` instead:
+
+
+```csharp
+var plugins = new OpenSearchPlugins(OpenSearchPlugin.RepositoryAzure, OpenSearchPlugin.IngestAttachment);
+var config = new EphemeralClusterConfiguration("1.0.0", ServerType.OpenSearch, ClusterFeatures.None, plugins, numberOfNodes: 2);
+using (var cluster = new EphemeralCluster(config))
+{
+ cluster.Start();
+
+ var nodes = cluster.NodesUris();
+ var connectionPool = new StaticConnectionPool(nodes);
+ var settings = new ConnectionSettings(connectionPool).EnableDebugMode();
+ var client = new OpenSearchClient(settings);
+
+ Console.Write(client.CatPlugins().DebugInformation);
+}
+```
+Here we first create a `OpenSearchPlugins` collection of the plugins that we want to bootstrap.
+Then we create an instance of `EphemeralClusterConfiguration` that dictates we want a 2 node cluster
+running opensearch using the previous declared `plugins`.
+
+We then Start the node and after its up create a `OSC` client using the `NodeUris()` that the cluster
+started.
+
+We call `/_cat/plugins` and write `OSC`'s debug information to the console.
+
+When the cluster exits the using block and disposes the cluster all nodes will be shutdown gracefully.
+
diff --git a/abstractions/src/OpenSearch.OpenSearch.Ephemeral/SecurityRealms.cs b/abstractions/src/OpenSearch.OpenSearch.Ephemeral/SecurityRealms.cs
new file mode 100644
index 0000000000..76bf8c751c
--- /dev/null
+++ b/abstractions/src/OpenSearch.OpenSearch.Ephemeral/SecurityRealms.cs
@@ -0,0 +1,37 @@
+/* SPDX-License-Identifier: Apache-2.0
+*
+* The OpenSearch Contributors require contributions made to
+* this file be licensed under the Apache-2.0 license or a
+* compatible open source license.
+*/
+/*
+* Modifications Copyright OpenSearch Contributors. See
+* GitHub history for details.
+*
+* Licensed to Elasticsearch B.V. under one or more contributor
+* license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright
+* ownership. Elasticsearch B.V. licenses this file to you under
+* the Apache License, Version 2.0 (the "License"); you may
+* not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+namespace OpenSearch.OpenSearch.Ephemeral
+{
+ public static class SecurityRealms
+ {
+ public const string FileRealm = "file1";
+
+ public const string PkiRealm = "pki1";
+ }
+}
diff --git a/abstractions/src/OpenSearch.OpenSearch.Ephemeral/Tasks/AfterNodeStoppedTasks/CleanUpDirectoriesAfterNodeStopped.cs b/abstractions/src/OpenSearch.OpenSearch.Ephemeral/Tasks/AfterNodeStoppedTasks/CleanUpDirectoriesAfterNodeStopped.cs
new file mode 100644
index 0000000000..8acaa36384
--- /dev/null
+++ b/abstractions/src/OpenSearch.OpenSearch.Ephemeral/Tasks/AfterNodeStoppedTasks/CleanUpDirectoriesAfterNodeStopped.cs
@@ -0,0 +1,84 @@
+/* SPDX-License-Identifier: Apache-2.0
+*
+* The OpenSearch Contributors require contributions made to
+* this file be licensed under the Apache-2.0 license or a
+* compatible open source license.
+*/
+/*
+* Modifications Copyright OpenSearch Contributors. See
+* GitHub history for details.
+*
+* Licensed to Elasticsearch B.V. under one or more contributor
+* license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright
+* ownership. Elasticsearch B.V. licenses this file to you under
+* the Apache License, Version 2.0 (the "License"); you may
+* not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+using System.IO;
+using OpenSearch.OpenSearch.Managed.ConsoleWriters;
+using ProcNet.Std;
+
+namespace OpenSearch.OpenSearch.Ephemeral.Tasks.AfterNodeStoppedTasks
+{
+ public class CleanUpDirectoriesAfterNodeStopped : IClusterTeardownTask
+ {
+ public void Run(IEphemeralCluster cluster, bool nodeStarted)
+ {
+ var fs = cluster.FileSystem;
+ var w = cluster.Writer;
+ var a = cluster.ClusterConfiguration.Artifact;
+ if (cluster.ClusterConfiguration.NoCleanupAfterNodeStopped)
+ {
+ w.WriteDiagnostic(
+ $"{{{nameof(CleanUpDirectoriesAfterNodeStopped)}}} skipping cleanup as requested on cluster configuration");
+ return;
+ }
+
+ DeleteDirectory(w, "cluster data", fs.DataPath);
+ DeleteDirectory(w, "cluster config", fs.ConfigPath);
+ DeleteDirectory(w, "cluster logs", fs.LogsPath);
+ DeleteDirectory(w, "repositories", fs.RepositoryPath);
+ var efs = fs as EphemeralFileSystem;
+ if (!string.IsNullOrWhiteSpace(efs?.TempFolder))
+ DeleteDirectory(w, "cluster temp folder", efs.TempFolder);
+
+ if (efs != null)
+ {
+ var extractedFolder = Path.Combine(fs.LocalFolder, a.FolderInZip);
+ if (extractedFolder != fs.OpenSearchHome)
+ DeleteDirectory(w, "ephemeral OPENSEARCH_HOME", fs.OpenSearchHome);
+ //if the node was not started delete the cached extractedFolder
+ if (!nodeStarted)
+ DeleteDirectory(w, "cached extracted folder - node failed to start", extractedFolder);
+ }
+
+ //if the node did not start make sure we delete the cached folder as we can not assume its in a good state
+ var cachedOpenSearchHomeFolder = Path.Combine(fs.LocalFolder, cluster.GetCacheFolderName());
+ if (cluster.ClusterConfiguration.CacheOpenSearchHomeInstallation && !nodeStarted)
+ DeleteDirectory(w, "cached installation - node failed to start", cachedOpenSearchHomeFolder);
+ else
+ w.WriteDiagnostic(
+ $"{{{nameof(CleanUpDirectoriesAfterNodeStopped)}}} Leaving [cached folder] on disk: {{{cachedOpenSearchHomeFolder}}}");
+ }
+
+ private static void DeleteDirectory(IConsoleLineHandler w, string description, string path)
+ {
+ if (!Directory.Exists(path)) return;
+ w.WriteDiagnostic(
+ $"{{{nameof(CleanUpDirectoriesAfterNodeStopped)}}} attempting to delete [{description}]: {{{path}}}");
+ Directory.Delete(path, true);
+ }
+ }
+}
diff --git a/abstractions/src/OpenSearch.OpenSearch.Ephemeral/Tasks/BeforeStartNodeTasks/CacheOpenSearchInstallation.cs b/abstractions/src/OpenSearch.OpenSearch.Ephemeral/Tasks/BeforeStartNodeTasks/CacheOpenSearchInstallation.cs
new file mode 100644
index 0000000000..85a0a1fc89
--- /dev/null
+++ b/abstractions/src/OpenSearch.OpenSearch.Ephemeral/Tasks/BeforeStartNodeTasks/CacheOpenSearchInstallation.cs
@@ -0,0 +1,57 @@
+/* SPDX-License-Identifier: Apache-2.0
+*
+* The OpenSearch Contributors require contributions made to
+* this file be licensed under the Apache-2.0 license or a
+* compatible open source license.
+*/
+/*
+* Modifications Copyright OpenSearch Contributors. See
+* GitHub history for details.
+*
+* Licensed to Elasticsearch B.V. under one or more contributor
+* license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright
+* ownership. Elasticsearch B.V. licenses this file to you under
+* the Apache License, Version 2.0 (the "License"); you may
+* not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+using System.IO;
+using OpenSearch.OpenSearch.Managed.ConsoleWriters;
+
+namespace OpenSearch.OpenSearch.Ephemeral.Tasks.BeforeStartNodeTasks
+{
+ public class CacheOpenSearchInstallation : ClusterComposeTask
+ {
+ public override void Run(IEphemeralCluster cluster)
+ {
+ if (!cluster.ClusterConfiguration.CacheOpenSearchHomeInstallation) return;
+
+ var fs = cluster.FileSystem;
+ var cachedOpenSearchHomeFolder = Path.Combine(fs.LocalFolder, cluster.GetCacheFolderName());
+ var cachedOpenSearchConfig = Path.Combine(cachedOpenSearchHomeFolder, "config");
+ if (File.Exists(cachedOpenSearchConfig))
+ {
+ cluster.Writer?.WriteDiagnostic(
+ $"{{{nameof(CacheOpenSearchInstallation)}}} cached home already exists [{cachedOpenSearchHomeFolder}]");
+ return;
+ }
+
+ var source = fs.OpenSearchHome;
+ var target = cachedOpenSearchHomeFolder;
+ cluster.Writer?.WriteDiagnostic(
+ $"{{{nameof(CacheOpenSearchInstallation)}}} caching {{{source}}} to [{target}]");
+ CopyFolder(source, target, false);
+ }
+ }
+}
diff --git a/abstractions/src/OpenSearch.OpenSearch.Ephemeral/Tasks/BeforeStartNodeTasks/CreateEphemeralDirectory.cs b/abstractions/src/OpenSearch.OpenSearch.Ephemeral/Tasks/BeforeStartNodeTasks/CreateEphemeralDirectory.cs
new file mode 100644
index 0000000000..67e77cbc8b
--- /dev/null
+++ b/abstractions/src/OpenSearch.OpenSearch.Ephemeral/Tasks/BeforeStartNodeTasks/CreateEphemeralDirectory.cs
@@ -0,0 +1,85 @@
+/* SPDX-License-Identifier: Apache-2.0
+*
+* The OpenSearch Contributors require contributions made to
+* this file be licensed under the Apache-2.0 license or a
+* compatible open source license.
+*/
+/*
+* Modifications Copyright OpenSearch Contributors. See
+* GitHub history for details.
+*
+* Licensed to Elasticsearch B.V. under one or more contributor
+* license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright
+* ownership. Elasticsearch B.V. licenses this file to you under
+* the Apache License, Version 2.0 (the "License"); you may
+* not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+using System.IO;
+using OpenSearch.OpenSearch.Managed.ConsoleWriters;
+using OpenSearch.OpenSearch.Managed.FileSystem;
+
+namespace OpenSearch.OpenSearch.Ephemeral.Tasks.BeforeStartNodeTasks
+{
+ public class CreateEphemeralDirectory : ClusterComposeTask
+ {
+ public override void Run(IEphemeralCluster cluster)
+ {
+ var fs = cluster.FileSystem;
+ if (!(fs is EphemeralFileSystem f))
+ {
+ cluster.Writer?.WriteDiagnostic(
+ $"{{{nameof(CreateEphemeralDirectory)}}} unexpected IFileSystem implementation {{{fs.GetType()}}}");
+ return;
+ }
+
+ cluster.Writer?.WriteDiagnostic($"{{{nameof(CreateEphemeralDirectory)}}} creating {{{f.TempFolder}}}");
+
+ Directory.CreateDirectory(f.TempFolder);
+
+ if (!Directory.Exists(f.ConfigPath))
+ {
+ cluster.Writer?.WriteDiagnostic(
+ $"{{{nameof(CreateEphemeralDirectory)}}} creating config folder {{{f.ConfigPath}}}");
+ Directory.CreateDirectory(f.ConfigPath);
+ }
+
+ CopyHomeConfigToEphemeralConfig(cluster, f, fs);
+ }
+
+ private static void CopyHomeConfigToEphemeralConfig(IEphemeralCluster cluster,
+ EphemeralFileSystem ephemeralFileSystem, INodeFileSystem fs)
+ {
+ var target = ephemeralFileSystem.ConfigPath;
+ var cachedOpenSearchHomeFolder = Path.Combine(fs.LocalFolder, cluster.GetCacheFolderName());
+ var cachedOpenSearchYaml = Path.Combine(cachedOpenSearchHomeFolder, "config", "opensearch.yaml");
+
+ var homeSource =
+ cluster.ClusterConfiguration.CacheOpenSearchHomeInstallation && File.Exists(cachedOpenSearchYaml)
+ ? cachedOpenSearchHomeFolder
+ : fs.OpenSearchHome;
+ var source = Path.Combine(homeSource, "config");
+ if (!Directory.Exists(source))
+ {
+ cluster.Writer?.WriteDiagnostic(
+ $"{{{nameof(CreateEphemeralDirectory)}}} source config {{{source}}} does not exist nothing to copy");
+ return;
+ }
+
+ cluster.Writer?.WriteDiagnostic(
+ $"{{{nameof(CreateEphemeralDirectory)}}} copying cached {{{source}}} as to [{target}]");
+ CopyFolder(source, target);
+ }
+ }
+}
diff --git a/abstractions/src/OpenSearch.OpenSearch.Ephemeral/Tasks/BeforeStartNodeTasks/PrintYamlContents.cs b/abstractions/src/OpenSearch.OpenSearch.Ephemeral/Tasks/BeforeStartNodeTasks/PrintYamlContents.cs
new file mode 100644
index 0000000000..d525d8eb65
--- /dev/null
+++ b/abstractions/src/OpenSearch.OpenSearch.Ephemeral/Tasks/BeforeStartNodeTasks/PrintYamlContents.cs
@@ -0,0 +1,63 @@
+/* SPDX-License-Identifier: Apache-2.0
+*
+* The OpenSearch Contributors require contributions made to
+* this file be licensed under the Apache-2.0 license or a
+* compatible open source license.
+*/
+/*
+* Modifications Copyright OpenSearch Contributors. See
+* GitHub history for details.
+*
+* Licensed to Elasticsearch B.V. under one or more contributor
+* license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright
+* ownership. Elasticsearch B.V. licenses this file to you under
+* the Apache License, Version 2.0 (the "License"); you may
+* not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+using System.IO;
+using System.Linq;
+using OpenSearch.OpenSearch.Managed.ConsoleWriters;
+
+namespace OpenSearch.OpenSearch.Ephemeral.Tasks.BeforeStartNodeTasks
+{
+ public class PrintYamlContents : ClusterComposeTask
+ {
+ public override void Run(IEphemeralCluster cluster)
+ {
+ var c = cluster.ClusterConfiguration;
+ var v = c.Version;
+ var fs = cluster.FileSystem;
+
+ var files = Directory.GetFiles(fs.ConfigPath, "*.yml", SearchOption.AllDirectories);
+ foreach (var file in files) DumpFile(cluster, file);
+ }
+
+ private static void DumpFile(IEphemeralCluster cluster, string configFile)
+ {
+ if (!File.Exists(configFile))
+ {
+ cluster.Writer.WriteDiagnostic(
+ $"{{{nameof(PrintYamlContents)}}} skipped printing [{configFile}] as it does not exists");
+ return;
+ }
+
+ var fileName = Path.GetFileName(configFile);
+ cluster.Writer.WriteDiagnostic($"{{{nameof(PrintYamlContents)}}} printing [{configFile}]");
+ var lines = File.ReadAllLines(configFile).ToList();
+ foreach (var l in lines.Where(l => !string.IsNullOrWhiteSpace(l) && !l.StartsWith("#")))
+ cluster.Writer.WriteDiagnostic($"{{{nameof(PrintYamlContents)}}} [{fileName}] {l}");
+ }
+ }
+}
diff --git a/abstractions/src/OpenSearch.OpenSearch.Ephemeral/Tasks/IClusterComposeTask.cs b/abstractions/src/OpenSearch.OpenSearch.Ephemeral/Tasks/IClusterComposeTask.cs
new file mode 100644
index 0000000000..3117162100
--- /dev/null
+++ b/abstractions/src/OpenSearch.OpenSearch.Ephemeral/Tasks/IClusterComposeTask.cs
@@ -0,0 +1,270 @@
+/* SPDX-License-Identifier: Apache-2.0
+*
+* The OpenSearch Contributors require contributions made to
+* this file be licensed under the Apache-2.0 license or a
+* compatible open source license.
+*/
+/*
+* Modifications Copyright OpenSearch Contributors. See
+* GitHub history for details.
+*
+* Licensed to Elasticsearch B.V. under one or more contributor
+* license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright
+* ownership. Elasticsearch B.V. licenses this file to you under
+* the Apache License, Version 2.0 (the "License"); you may
+* not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.IO.Compression;
+using System.Linq;
+using System.Net;
+using System.Net.Http;
+using System.Net.Http.Headers;
+using System.Net.Security;
+using System.Runtime.InteropServices;
+using System.Security.Cryptography.X509Certificates;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+using OpenSearch.OpenSearch.Managed.ConsoleWriters;
+using ICSharpCode.SharpZipLib.GZip;
+using ICSharpCode.SharpZipLib.Tar;
+using ProcNet;
+using ProcNet.Std;
+
+namespace OpenSearch.OpenSearch.Ephemeral.Tasks
+{
+ public interface IClusterComposeTask
+ {
+ void Run(IEphemeralCluster cluster);
+ }
+
+ public interface IClusterTeardownTask
+ {
+ ///
+ /// Called when the cluster disposes, used to clean up after itself.
+ ///
+ /// The cluster configuration of the node that was started
+ /// Whether the cluster composer was successful in starting the node
+ void Run(IEphemeralCluster cluster, bool nodeStarted);
+ }
+
+ public abstract class ClusterComposeTask : IClusterComposeTask
+ {
+ protected static bool IsWindows { get; } = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
+ protected static string BinarySuffix => IsWindows ? ".bat" : string.Empty;
+ public abstract void Run(IEphemeralCluster cluster);
+
+ protected static void DownloadFile(string from, string to)
+ {
+ if (File.Exists(to)) return;
+ var http = new HttpClient();
+ using (var stream = http.GetStreamAsync(new Uri(from)).GetAwaiter().GetResult())
+ using (var fileStream = File.Create(to))
+ {
+ stream.CopyTo(fileStream);
+ fileStream.Flush();
+ }
+ }
+
+ protected string GetResponseException(HttpResponseMessage m) =>
+ $"Code: {m?.StatusCode} Reason: {m?.ReasonPhrase} Content: {GetResponseString(m)}";
+
+ protected string GetResponseString(HttpResponseMessage m) =>
+ m?.Content?.ReadAsStringAsync().ConfigureAwait(false).GetAwaiter().GetResult() ?? string.Empty;
+
+ protected HttpResponseMessage Get(IEphemeralCluster cluster, string path,
+ string query) =>
+ Call(cluster, path, query, (c, u, t) => c.GetAsync(u, t));
+
+ protected HttpResponseMessage Post(IEphemeralCluster cluster, string path,
+ string query, string json) =>
+ Call(cluster, path, query,
+ (c, u, t) => c.PostAsync(u, new StringContent(json, Encoding.UTF8, "application/json"), t));
+
+ private HttpResponseMessage Call(
+ IEphemeralCluster cluster,
+ string path,
+ string query,
+ Func> verb)
+ {
+ var q = string.IsNullOrEmpty(query) ? "pretty=true" : query + "&pretty=true";
+ var statusUrl = new UriBuilder(cluster.NodesUris().First()) {Path = path, Query = q}.Uri;
+
+ var tokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(20));
+ var handler = new HttpClientHandler
+ {
+ AutomaticDecompression =
+ DecompressionMethods.Deflate | DecompressionMethods.GZip | DecompressionMethods.None,
+ };
+ cluster.Writer.WriteDiagnostic(
+ $"{{{nameof(Call)}}} [{statusUrl}] SSL: {cluster.ClusterConfiguration.EnableSsl}");
+ if (cluster.ClusterConfiguration.EnableSsl)
+ {
+#if !NETSTANDARD
+ ServicePointManager.ServerCertificateValidationCallback += ServerCertificateValidationCallback;
+#else
+ handler.ServerCertificateCustomValidationCallback += (m, c, cn, p) => true;
+#endif
+ }
+
+ using (var client = new HttpClient(handler) {Timeout = TimeSpan.FromSeconds(20)})
+ {
+ if (cluster.ClusterConfiguration.EnableSsl)
+ {
+ var byteArray =
+ Encoding.ASCII.GetBytes(
+ $"{ClusterAuthentication.Admin.Username}:{ClusterAuthentication.Admin.Password}");
+ client.DefaultRequestHeaders.Authorization =
+ new AuthenticationHeaderValue("Basic", Convert.ToBase64String(byteArray));
+ }
+
+ try
+ {
+ var response = verb(client, statusUrl, tokenSource.Token).ConfigureAwait(false).GetAwaiter()
+ .GetResult();
+ if (!response.IsSuccessStatusCode)
+ {
+ cluster.Writer.WriteDiagnostic(
+ $"{{{nameof(Call)}}} [{statusUrl}] Unsuccessful status code: [{(int) response.StatusCode}]");
+ var body = response.Content.ReadAsStringAsync().GetAwaiter().GetResult();
+ foreach (var l in (body ?? string.Empty).Split('\n', '\r'))
+ cluster.Writer.WriteDiagnostic($"{{{nameof(Call)}}} [{statusUrl}] returned [{l}]");
+ }
+
+ return response;
+ }
+ catch (Exception e)
+ {
+ cluster.Writer.WriteError($"{{{nameof(Call)}}} [{statusUrl}] exception: {e}");
+ throw;
+ }
+ finally
+ {
+#if !NETSTANDARD
+ ServicePointManager.ServerCertificateValidationCallback -= ServerCertificateValidationCallback;
+#endif
+ }
+ }
+ }
+
+ private static bool ServerCertificateValidationCallback(object sender, X509Certificate certificate,
+ X509Chain chain, SslPolicyErrors sslpolicyerrors) => true;
+
+ protected static void WriteFileIfNotExist(string fileLocation, string contents)
+ {
+ if (!File.Exists(fileLocation)) File.WriteAllText(fileLocation, contents);
+ }
+
+ protected static void ExecuteBinary(EphemeralClusterConfiguration config, IConsoleLineHandler writer,
+ string binary, string description, params string[] arguments) =>
+ ExecuteBinaryInternal(config, writer, binary, description, null, arguments);
+
+ protected static void ExecuteBinary(EphemeralClusterConfiguration config, IConsoleLineHandler writer,
+ string binary, string description, StartedHandler startedHandler, params string[] arguments) =>
+ ExecuteBinaryInternal(config, writer, binary, description, startedHandler, arguments);
+
+ private static void ExecuteBinaryInternal(EphemeralClusterConfiguration config, IConsoleLineHandler writer,
+ string binary, string description, StartedHandler startedHandler, params string[] arguments)
+ {
+ var command = $"{{{binary}}} {{{string.Join(" ", arguments)}}}";
+ writer?.WriteDiagnostic($"{{{nameof(ExecuteBinary)}}} starting process [{description}] {command}");
+
+ var timeout = TimeSpan.FromSeconds(420);
+ var processStartArguments = new StartArguments(binary, arguments)
+ {
+ Environment = new Dictionary
+ {
+ {config.FileSystem.ConfigEnvironmentVariableName, config.FileSystem.ConfigPath},
+ {"OPENSEARCH_HOME", config.FileSystem.OpenSearchHome},
+ // Duplicate all env vars for ES_* prefix for backward compatibility with OpenDistro and ElasticSearch;
+ // unused env vars would be just ignored.
+ {config.FileSystem.ConfigEnvironmentVariableName.Replace("OPENSEARCH", "ES"), config.FileSystem.ConfigPath},
+ {"ES_HOME", config.FileSystem.OpenSearchHome}
+ }
+ };
+
+ var result = startedHandler != null
+ ? Proc.Start(processStartArguments, timeout, new ConsoleOutColorWriter(), startedHandler)
+ : Proc.Start(processStartArguments, timeout, new ConsoleOutColorWriter());
+
+ if (!result.Completed)
+ throw new Exception($"Timeout while executing {description} exceeded {timeout}");
+
+ if (result.ExitCode != 0)
+ throw new Exception(
+ $"Expected exit code 0 but received ({result.ExitCode}) while executing {description}: {command}");
+
+ var errorOut = result.ConsoleOut.Where(c => c.Error).ToList();
+
+ if (errorOut.Any(e =>
+ !string.IsNullOrWhiteSpace(e.Line) && !e.Line.Contains("usage of JAVA_HOME is deprecated")) &&
+ !binary.Contains("plugin") && !binary.Contains("cert"))
+ throw new Exception(
+ $"Received error out with exitCode ({result.ExitCode}) while executing {description}: {command}");
+
+ writer?.WriteDiagnostic(
+ $"{{{nameof(ExecuteBinary)}}} finished process [{description}] {{{result.ExitCode}}}");
+ }
+
+ protected static void CopyFolder(string source, string target, bool overwrite = true)
+ {
+ foreach (var sourceDir in Directory.GetDirectories(source, "*", SearchOption.AllDirectories))
+ {
+ var targetDir = sourceDir.Replace(source, target);
+ Directory.CreateDirectory(targetDir);
+ }
+
+ foreach (var sourcePath in Directory.GetFiles(source, "*.*", SearchOption.AllDirectories))
+ {
+ var targetPath = sourcePath.Replace(source, target);
+ if (!overwrite && File.Exists(targetPath)) continue;
+ File.Copy(sourcePath, targetPath, overwrite);
+ }
+ }
+
+ protected static void Extract(string file, string toFolder)
+ {
+ if (file.EndsWith(".zip")) ExtractZip(file, toFolder);
+ else if (file.EndsWith(".tar.gz")) ExtractTarGz(file, toFolder);
+ else if (file.EndsWith(".tar")) ExtractTar(file, toFolder);
+ else throw new Exception("Can not extract:" + file);
+ }
+
+ private static void ExtractTar(string file, string toFolder)
+ {
+ using (var inStream = File.OpenRead(file))
+ using (var tarArchive = TarArchive.CreateInputTarArchive(inStream))
+ tarArchive.ExtractContents(toFolder);
+ }
+
+ private static void ExtractTarGz(string file, string toFolder)
+ {
+ if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
+ using (var inStream = File.OpenRead(file))
+ using (var gzipStream = new GZipInputStream(inStream))
+ using (var tarArchive = TarArchive.CreateInputTarArchive(gzipStream))
+ tarArchive.ExtractContents(toFolder);
+ else
+ //SharpZipLib loses permissions when untarring
+ Proc.Exec("tar", "-xvf", file, "-C", toFolder);
+ }
+
+ private static void ExtractZip(string file, string toFolder) =>
+ ZipFile.ExtractToDirectory(file, toFolder);
+ }
+}
diff --git a/abstractions/src/OpenSearch.OpenSearch.Ephemeral/Tasks/InstallationTasks/CopyCachedOpenSearchInstallation.cs b/abstractions/src/OpenSearch.OpenSearch.Ephemeral/Tasks/InstallationTasks/CopyCachedOpenSearchInstallation.cs
new file mode 100644
index 0000000000..5c7862de44
--- /dev/null
+++ b/abstractions/src/OpenSearch.OpenSearch.Ephemeral/Tasks/InstallationTasks/CopyCachedOpenSearchInstallation.cs
@@ -0,0 +1,51 @@
+/* SPDX-License-Identifier: Apache-2.0
+*
+* The OpenSearch Contributors require contributions made to
+* this file be licensed under the Apache-2.0 license or a
+* compatible open source license.
+*/
+/*
+* Modifications Copyright OpenSearch Contributors. See
+* GitHub history for details.
+*
+* Licensed to Elasticsearch B.V. under one or more contributor
+* license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright
+* ownership. Elasticsearch B.V. licenses this file to you under
+* the Apache License, Version 2.0 (the "License"); you may
+* not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+using System.IO;
+using OpenSearch.OpenSearch.Managed.ConsoleWriters;
+
+namespace OpenSearch.OpenSearch.Ephemeral.Tasks.InstallationTasks
+{
+ public class CopyCachedOpenSearchInstallation : ClusterComposeTask
+ {
+ public override void Run(IEphemeralCluster cluster)
+ {
+ if (!cluster.ClusterConfiguration.CacheOpenSearchHomeInstallation) return;
+
+ var fs = cluster.FileSystem;
+ var cachedOpenSearchHomeFolder = Path.Combine(fs.LocalFolder, cluster.GetCacheFolderName());
+ if (!Directory.Exists(cachedOpenSearchHomeFolder)) return;
+
+ var source = cachedOpenSearchHomeFolder;
+ var target = fs.OpenSearchHome;
+ cluster.Writer?.WriteDiagnostic(
+ $"{{{nameof(CopyCachedOpenSearchInstallation)}}} using cached OPENSEARCH_HOME {{{source}}} and copying it to [{target}]");
+ CopyFolder(source, target);
+ }
+ }
+}
diff --git a/abstractions/src/OpenSearch.OpenSearch.Ephemeral/Tasks/InstallationTasks/CreateLocalApplicationDirectory.cs b/abstractions/src/OpenSearch.OpenSearch.Ephemeral/Tasks/InstallationTasks/CreateLocalApplicationDirectory.cs
new file mode 100644
index 0000000000..35c8e98ec0
--- /dev/null
+++ b/abstractions/src/OpenSearch.OpenSearch.Ephemeral/Tasks/InstallationTasks/CreateLocalApplicationDirectory.cs
@@ -0,0 +1,52 @@
+/* SPDX-License-Identifier: Apache-2.0
+*
+* The OpenSearch Contributors require contributions made to
+* this file be licensed under the Apache-2.0 license or a
+* compatible open source license.
+*/
+/*
+* Modifications Copyright OpenSearch Contributors. See
+* GitHub history for details.
+*
+* Licensed to Elasticsearch B.V. under one or more contributor
+* license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright
+* ownership. Elasticsearch B.V. licenses this file to you under
+* the Apache License, Version 2.0 (the "License"); you may
+* not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+using System.IO;
+using OpenSearch.OpenSearch.Managed.ConsoleWriters;
+
+namespace OpenSearch.OpenSearch.Ephemeral.Tasks.InstallationTasks
+{
+ public class CreateLocalApplicationDirectory : ClusterComposeTask
+ {
+ public override void Run(IEphemeralCluster cluster)
+ {
+ var fs = cluster.FileSystem;
+ if (Directory.Exists(fs.LocalFolder))
+ {
+ cluster.Writer?.WriteDiagnostic(
+ $"{{{nameof(CreateLocalApplicationDirectory)}}} already exists: {{{fs.LocalFolder}}}");
+ return;
+ }
+
+ cluster.Writer?.WriteDiagnostic(
+ $"{{{nameof(CreateLocalApplicationDirectory)}}} creating {{{fs.LocalFolder}}}");
+
+ Directory.CreateDirectory(fs.LocalFolder);
+ }
+ }
+}
diff --git a/abstractions/src/OpenSearch.OpenSearch.Ephemeral/Tasks/InstallationTasks/DownloadOpenSearchVersion.cs b/abstractions/src/OpenSearch.OpenSearch.Ephemeral/Tasks/InstallationTasks/DownloadOpenSearchVersion.cs
new file mode 100644
index 0000000000..e652724364
--- /dev/null
+++ b/abstractions/src/OpenSearch.OpenSearch.Ephemeral/Tasks/InstallationTasks/DownloadOpenSearchVersion.cs
@@ -0,0 +1,60 @@
+/* SPDX-License-Identifier: Apache-2.0
+*
+* The OpenSearch Contributors require contributions made to
+* this file be licensed under the Apache-2.0 license or a
+* compatible open source license.
+*/
+/*
+* Modifications Copyright OpenSearch Contributors. See
+* GitHub history for details.
+*
+* Licensed to Elasticsearch B.V. under one or more contributor
+* license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright
+* ownership. Elasticsearch B.V. licenses this file to you under
+* the Apache License, Version 2.0 (the "License"); you may
+* not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+using System.IO;
+using OpenSearch.OpenSearch.Managed.ConsoleWriters;
+using OpenSearch.Stack.ArtifactsApi.Products;
+
+namespace OpenSearch.OpenSearch.Ephemeral.Tasks.InstallationTasks
+{
+ public class DownloadOpenSearchVersion : ClusterComposeTask
+ {
+ public override void Run(IEphemeralCluster cluster)
+ {
+ if (cluster.CachingAndCachedHomeExists()) return;
+
+ var fs = cluster.FileSystem;
+ var v = cluster.ClusterConfiguration.Version;
+ var a = cluster.ClusterConfiguration.Artifact;
+ var from = v.Artifact(Product.OpenSearch).DownloadUrl;
+ var to = Path.Combine(fs.LocalFolder, a.Archive);
+ if (File.Exists(to))
+ {
+ cluster.Writer?.WriteDiagnostic(
+ $"{{{nameof(DownloadOpenSearchVersion)}}} {v} was already downloaded");
+ return;
+ }
+
+ cluster.Writer?.WriteDiagnostic(
+ $"{{{nameof(DownloadOpenSearchVersion)}}} downloading OpenSearch [{v}] from {{{from}}} {{{to}}}");
+ DownloadFile(from, to);
+ cluster.Writer?.WriteDiagnostic(
+ $"{{{nameof(DownloadOpenSearchVersion)}}} downloaded OpenSearch [{v}] from {{{from}}} {{{to}}}");
+ }
+ }
+}
diff --git a/abstractions/src/OpenSearch.OpenSearch.Ephemeral/Tasks/InstallationTasks/EnsureJavaHomeEnvironmentVariableIsSet.cs b/abstractions/src/OpenSearch.OpenSearch.Ephemeral/Tasks/InstallationTasks/EnsureJavaHomeEnvironmentVariableIsSet.cs
new file mode 100644
index 0000000000..faa8a00641
--- /dev/null
+++ b/abstractions/src/OpenSearch.OpenSearch.Ephemeral/Tasks/InstallationTasks/EnsureJavaHomeEnvironmentVariableIsSet.cs
@@ -0,0 +1,63 @@
+/* SPDX-License-Identifier: Apache-2.0
+*
+* The OpenSearch Contributors require contributions made to
+* this file be licensed under the Apache-2.0 license or a
+* compatible open source license.
+*/
+/*
+* Modifications Copyright OpenSearch Contributors. See
+* GitHub history for details.
+*
+* Licensed to Elasticsearch B.V. under one or more contributor
+* license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright
+* ownership. Elasticsearch B.V. licenses this file to you under
+* the Apache License, Version 2.0 (the "License"); you may
+* not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+using System;
+using System.IO;
+using OpenSearch.OpenSearch.Managed.ConsoleWriters;
+
+namespace OpenSearch.OpenSearch.Ephemeral.Tasks.InstallationTasks
+{
+ public class EnsureJavaHomeEnvironmentVariableIsSet : ClusterComposeTask
+ {
+ public override void Run(IEphemeralCluster cluster)
+ {
+ var fs = cluster.FileSystem;
+
+ var envVarName = cluster.ClusterConfiguration.JavaHomeEnvironmentVariable;
+ var javaHome = Environment.GetEnvironmentVariable(envVarName);
+ var cachedOpenSearchHomeFolder = Path.Combine(fs.LocalFolder, cluster.GetCacheFolderName());
+ var jdkFolder = Path.Combine(cachedOpenSearchHomeFolder, "jdk");
+ if (Directory.Exists(jdkFolder))
+ {
+ //prefer bundled jdk
+ cluster.Writer?.WriteDiagnostic(
+ $"{{{nameof(EnsureJavaHomeEnvironmentVariableIsSet)}}} [{envVarName}] is set to bundled jdk: {{{jdkFolder}}} ");
+ Environment.SetEnvironmentVariable("JAVA_HOME", jdkFolder);
+ }
+ else if (!string.IsNullOrWhiteSpace(javaHome))
+ {
+ cluster.Writer?.WriteDiagnostic(
+ $"{{{nameof(EnsureJavaHomeEnvironmentVariableIsSet)}}} [{envVarName}] is set; clearing value for process to prefer bundled jdk...");
+ Environment.SetEnvironmentVariable(envVarName, null);
+ }
+ else
+ cluster.Writer?.WriteDiagnostic(
+ $"{{{nameof(EnsureJavaHomeEnvironmentVariableIsSet)}}} {envVarName} is not set proceeding or using default JDK");
+ }
+ }
+}
diff --git a/abstractions/src/OpenSearch.OpenSearch.Ephemeral/Tasks/InstallationTasks/InitialConfiguration.cs b/abstractions/src/OpenSearch.OpenSearch.Ephemeral/Tasks/InstallationTasks/InitialConfiguration.cs
new file mode 100644
index 0000000000..c806617546
--- /dev/null
+++ b/abstractions/src/OpenSearch.OpenSearch.Ephemeral/Tasks/InstallationTasks/InitialConfiguration.cs
@@ -0,0 +1,77 @@
+/* SPDX-License-Identifier: Apache-2.0
+*
+* The OpenSearch Contributors require contributions made to
+* this file be licensed under the Apache-2.0 license or a
+* compatible open source license.
+*/
+/*
+* Modifications Copyright OpenSearch Contributors. See
+* GitHub history for details.
+*
+* Licensed to Elasticsearch B.V. under one or more contributor
+* license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright
+* ownership. Elasticsearch B.V. licenses this file to you under
+* the Apache License, Version 2.0 (the "License"); you may
+* not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+using System;
+using System.IO;
+using OpenSearch.OpenSearch.Managed.ConsoleWriters;
+using OpenSearch.Stack.ArtifactsApi;
+
+namespace OpenSearch.OpenSearch.Ephemeral.Tasks.InstallationTasks
+{
+ public class InitialConfiguration : ClusterComposeTask
+ {
+ public override void Run(IEphemeralCluster cluster)
+ {
+ if (cluster.CachingAndCachedHomeExists()) return;
+
+ if (cluster.ClusterConfiguration.Artifact.ServerType == ServerType.ElasticSearch)
+ {
+ cluster.Writer?.WriteDiagnostic($"{{{nameof(Run)}}} skipping for ElasticSearch");
+ return;
+ }
+
+ var fs = cluster.FileSystem;
+ var script = Path.Combine(fs.OpenSearchHome, "server-initial-config.sh");
+
+ if (cluster.ClusterConfiguration.Artifact.ServerType == ServerType.OpenSearch)
+ File.WriteAllText(script, InitialConfigurationOpenSearch.GetConfigurationScript(cluster.ClusterConfiguration.Version));
+ if (cluster.ClusterConfiguration.Artifact.ServerType == ServerType.OpenDistro)
+ File.WriteAllText(script, InitialConfigurationOpenDistro.GetConfigurationScript());
+
+ cluster.Writer?.WriteDiagnostic($"{{{nameof(Run)}}} going to run [server-initial-config.sh]");
+
+ ExecuteBinary(
+ cluster.ClusterConfiguration,
+ cluster.Writer,
+ "/bin/bash",
+ "run initial cluster configuration",
+ script);
+
+ if (!cluster.ClusterConfiguration.EnableSsl)
+ {
+ if (cluster.ClusterConfiguration.Artifact.ServerType == ServerType.OpenSearch)
+ File.AppendAllText(Path.Combine(fs.OpenSearchHome, "config", "opensearch.yml"), "plugins.security.disabled: true");
+ if (cluster.ClusterConfiguration.Artifact.ServerType == ServerType.OpenDistro)
+ File.AppendAllText(Path.Combine(fs.OpenSearchHome, "config", "elasticsearch.yml"), "opendistro_security.disabled: true");
+ }
+
+ if (cluster.ClusterConfiguration.Artifact.ServerType == ServerType.ElasticSearch && cluster.ClusterConfiguration.EnableSsl)
+ throw new NotImplementedException("ElasticSearch with SSL is not supported");
+ }
+ }
+}
diff --git a/abstractions/src/OpenSearch.OpenSearch.Ephemeral/Tasks/InstallationTasks/InitialConfigurationOpenDistro.cs b/abstractions/src/OpenSearch.OpenSearch.Ephemeral/Tasks/InstallationTasks/InitialConfigurationOpenDistro.cs
new file mode 100644
index 0000000000..43647a60b9
--- /dev/null
+++ b/abstractions/src/OpenSearch.OpenSearch.Ephemeral/Tasks/InstallationTasks/InitialConfigurationOpenDistro.cs
@@ -0,0 +1,98 @@
+/* SPDX-License-Identifier: Apache-2.0
+*
+* The OpenSearch Contributors require contributions made to
+* this file be licensed under the Apache-2.0 license or a
+* compatible open source license.
+*/
+/*
+* Modifications Copyright OpenSearch Contributors. See
+* GitHub history for details.
+*
+* Licensed to Elasticsearch B.V. under one or more contributor
+* license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright
+* ownership. Elasticsearch B.V. licenses this file to you under
+* the Apache License, Version 2.0 (the "License"); you may
+* not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+namespace OpenSearch.OpenSearch.Ephemeral.Tasks.InstallationTasks
+{
+ internal class InitialConfigurationOpenDistro
+ {
+ // Actually, it is content of file `opendistro-tar-install.sh` shipped
+ // in the tarball, but due to (1) this file might be changed and
+ // (2) we have to modify the file before execution, because it launches
+ // the server what we want to do on our own, it is decided to have a
+ // snapshot of this file.
+ // The script is taken from v.1.13.3, last 3 lines omitted.
+ public static string GetConfigurationScript() =>
+@"#!/bin/bash
+
+ES_HOME=`dirname $(realpath $0)`; cd $ES_HOME
+ES_KNN_LIB_DIR=$ES_HOME/plugins/opendistro-knn/knn-lib
+##Security Plugin
+bash $ES_HOME/plugins/opendistro_security/tools/install_demo_configuration.sh -y -i -s
+
+##Perf Plugin
+chmod 755 $ES_HOME/plugins/opendistro-performance-analyzer/pa_bin/performance-analyzer-agent
+chmod 755 $ES_HOME/bin/performance-analyzer-agent-cli
+echo ""done security""
+PA_AGENT_JAVA_OPTS=""-Dlog4j.configurationFile=$ES_HOME/plugins/opendistro-performance-analyzer/pa_config/log4j2.xml \
+ -Xms64M -Xmx64M -XX:+UseSerialGC -XX:CICompilerCount=1 -XX:-TieredCompilation -XX:InitialCodeCacheSize=4096 \
+ -XX:InitialBootClassLoaderMetaspaceSize=30720 -XX:MaxRAM=400m""
+
+ES_MAIN_CLASS=""com.amazon.opendistro.elasticsearch.performanceanalyzer.PerformanceAnalyzerApp"" \
+ES_ADDITIONAL_CLASSPATH_DIRECTORIES=plugins/opendistro-performance-analyzer \
+ES_JAVA_OPTS=$PA_AGENT_JAVA_OPTS
+
+if ! grep -q '## OpenDistro Performance Analyzer' $ES_HOME/config/jvm.options; then
+ CLK_TCK=`/usr/bin/getconf CLK_TCK`
+ echo >> $ES_HOME/config/jvm.options
+ echo '## OpenDistro Performance Analyzer' >> $ES_HOME/config/jvm.options
+ echo ""-Dclk.tck=$CLK_TCK"" >> $ES_HOME/config/jvm.options
+ echo ""-Djdk.attach.allowAttachSelf=true"" >> $ES_HOME/config/jvm.options
+ echo ""-Djava.security.policy=$ES_HOME/plugins/opendistro-performance-analyzer/pa_config/es_security.policy"" >> $ES_HOME/config/jvm.options
+fi
+echo ""done plugins""
+
+##Check KNN lib existence in ES TAR distribution
+echo ""Checking kNN library""
+FILE=`ls $ES_KNN_LIB_DIR/libKNNIndex*.so`
+if test -f ""$FILE""; then
+ echo ""FILE EXISTS $FILE""
+else
+ echo ""TEST FAILED OR FILE NOT EXIST $FILE""
+fi
+
+##Set KNN Dylib Path for macOS and *nix systems
+if echo ""$OSTYPE"" | grep -qi ""darwin""; then
+ if echo ""$JAVA_LIBRARY_PATH"" | grep -q ""$ES_KNN_LIB_DIR""; then
+ echo ""KNN lib path has been set""
+ else
+ export JAVA_LIBRARY_PATH=$JAVA_LIBRARY_PATH:$ES_KNN_LIB_DIR
+ echo ""KNN lib path not found, set new path""
+ echo $JAVA_LIBRARY_PATH
+ fi
+else
+ if echo ""$LD_LIBRARY_PATH"" | grep -q ""$ES_KNN_LIB_DIR""; then
+ echo ""KNN lib path has been set""
+ else
+ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$ES_KNN_LIB_DIR
+ echo ""KNN lib path not found, set new path""
+ echo $LD_LIBRARY_PATH
+ fi
+fi
+";
+ }
+}
diff --git a/abstractions/src/OpenSearch.OpenSearch.Ephemeral/Tasks/InstallationTasks/InitialConfigurationOpenSearch.cs b/abstractions/src/OpenSearch.OpenSearch.Ephemeral/Tasks/InstallationTasks/InitialConfigurationOpenSearch.cs
new file mode 100644
index 0000000000..6dd58b203b
--- /dev/null
+++ b/abstractions/src/OpenSearch.OpenSearch.Ephemeral/Tasks/InstallationTasks/InitialConfigurationOpenSearch.cs
@@ -0,0 +1,148 @@
+/* SPDX-License-Identifier: Apache-2.0
+*
+* The OpenSearch Contributors require contributions made to
+* this file be licensed under the Apache-2.0 license or a
+* compatible open source license.
+*/
+/*
+* Modifications Copyright OpenSearch Contributors. See
+* GitHub history for details.
+*
+* Licensed to Elasticsearch B.V. under one or more contributor
+* license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright
+* ownership. Elasticsearch B.V. licenses this file to you under
+* the Apache License, Version 2.0 (the "License"); you may
+* not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+using OpenSearch.Stack.ArtifactsApi;
+
+namespace OpenSearch.OpenSearch.Ephemeral.Tasks.InstallationTasks
+{
+ internal class InitialConfigurationOpenSearch
+ {
+ // Actually, it is content of file `opensearch-tar-install.sh` shipped
+ // in the tarball, but due to (1) this file might be changed and
+ // (2) we have to modify the file before execution, because it launches
+ // the server what we want to do on our own, it is decided to have a
+ // snapshot of this file.
+ // The script is taken from v.1.2.4, last 3 lines omitted.
+ public static string GetConfigurationScript(OpenSearchVersion version)
+ {
+ if (version < (OpenSearchVersion)"2.0.0")
+ return
+@"#!/bin/bash
+
+# Copyright OpenSearch Contributors
+# SPDX-License-Identifier: Apache-2.0
+
+OPENSEARCH_HOME=`dirname $(realpath $0)`; cd $OPENSEARCH_HOME
+KNN_LIB_DIR=$OPENSEARCH_HOME/plugins/opensearch-knn/knnlib
+##Security Plugin
+bash $OPENSEARCH_HOME/plugins/opensearch-security/tools/install_demo_configuration.sh -y -i -s
+
+##Perf Plugin
+chmod 755 $OPENSEARCH_HOME/plugins/opensearch-performance-analyzer/pa_bin/performance-analyzer-agent
+chmod 755 $OPENSEARCH_HOME/bin/performance-analyzer-agent-cli
+echo ""done security""
+PA_AGENT_JAVA_OPTS=""-Dlog4j.configurationFile=$OPENSEARCH_HOME/plugins/opensearch-performance-analyzer/pa_config/log4j2.xml \
+ -Xms64M -Xmx64M -XX:+UseSerialGC -XX:CICompilerCount=1 -XX:-TieredCompilation -XX:InitialCodeCacheSize=4096 \
+ -XX:InitialBootClassLoaderMetaspaceSize=30720 -XX:MaxRAM=400m""
+
+OPENSEARCH_MAIN_CLASS=""org.opensearch.performanceanalyzer.PerformanceAnalyzerApp"" \
+OPENSEARCH_ADDITIONAL_CLASSPATH_DIRECTORIES=plugins/opensearch-performance-analyzer \
+OPENSEARCH_JAVA_OPTS=$PA_AGENT_JAVA_OPTS
+
+if ! grep -q '## OpenSearch Performance Analyzer' $OPENSEARCH_HOME/config/jvm.options; then
+ CLK_TCK=`/usr/bin/getconf CLK_TCK`
+ echo >> $OPENSEARCH_HOME/config/jvm.options
+ echo '## OpenSearch Performance Analyzer' >> $OPENSEARCH_HOME/config/jvm.options
+ echo ""-Dclk.tck=$CLK_TCK"" >> $OPENSEARCH_HOME/config/jvm.options
+ echo ""-Djdk.attach.allowAttachSelf=true"" >> $OPENSEARCH_HOME/config/jvm.options
+ echo ""-Djava.security.policy=$OPENSEARCH_HOME/plugins/opensearch-performance-analyzer/pa_config/opensearch_security.policy"" >> $OPENSEARCH_HOME/config/jvm.options
+fi
+echo ""done plugins""
+
+##Set KNN Dylib Path for macOS and *nix systems
+if echo ""$OSTYPE"" | grep -qi ""darwin""; then
+ if echo ""$JAVA_LIBRARY_PATH"" | grep -q ""$KNN_LIB_DIR""; then
+ echo ""k-NN libraries found in JAVA_LIBRARY_PATH""
+ else
+ export JAVA_LIBRARY_PATH=$JAVA_LIBRARY_PATH:$KNN_LIB_DIR
+ echo ""k-NN libraries not found in JAVA_LIBRARY_PATH. Updating path to: $JAVA_LIBRARY_PATH.""
+ fi
+else
+ if echo ""$LD_LIBRARY_PATH"" | grep -q ""$KNN_LIB_DIR""; then
+ echo ""k-NN libraries found in LD_LIBRARY_PATH""
+ else
+ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$KNN_LIB_DIR
+ echo ""k-NN libraries not found in LD_LIBRARY_PATH. Updating path to: $LD_LIBRARY_PATH.""
+ fi
+fi
+";
+ return
+ //script from 2.0.0
+ @"#!/bin/bash
+
+# Copyright OpenSearch Contributors
+# SPDX-License-Identifier: Apache-2.0
+
+export OPENSEARCH_HOME=`dirname $(realpath $0)`
+export OPENSEARCH_PATH_CONF=$OPENSEARCH_HOME/config
+cd $OPENSEARCH_HOME
+
+KNN_LIB_DIR=$OPENSEARCH_HOME/plugins/opensearch-knn/lib
+##Security Plugin
+bash $OPENSEARCH_HOME/plugins/opensearch-security/tools/install_demo_configuration.sh -y -i -s
+
+echo ""done security""
+PA_AGENT_JAVA_OPTS=""-Dlog4j.configurationFile=$OPENSEARCH_PATH_CONF/opensearch-performance-analyzer/log4j2.xml \
+ -Xms64M -Xmx64M -XX:+UseSerialGC -XX:CICompilerCount=1 -XX:-TieredCompilation -XX:InitialCodeCacheSize=4096 \
+ -XX:MaxRAM=400m""
+
+OPENSEARCH_MAIN_CLASS=""org.opensearch.performanceanalyzer.PerformanceAnalyzerApp"" \
+OPENSEARCH_ADDITIONAL_CLASSPATH_DIRECTORIES=plugins/opensearch-performance-analyzer \
+OPENSEARCH_JAVA_OPTS=$PA_AGENT_JAVA_OPTS
+
+if ! grep -q '## OpenSearch Performance Analyzer' $OPENSEARCH_PATH_CONF/jvm.options; then
+ CLK_TCK=`/usr/bin/getconf CLK_TCK`
+ echo >> $OPENSEARCH_PATH_CONF/jvm.options
+ echo '## OpenSearch Performance Analyzer' >> $OPENSEARCH_PATH_CONF/jvm.options
+ echo ""-Dclk.tck=$CLK_TCK"" >> $OPENSEARCH_PATH_CONF/jvm.options
+ echo ""-Djdk.attach.allowAttachSelf=true"" >> $OPENSEARCH_PATH_CONF/jvm.options
+ echo ""-Djava.security.policy=$OPENSEARCH_PATH_CONF/opensearch-performance-analyzer/opensearch_security.policy"" >> $OPENSEARCH_PATH_CONF/jvm.options
+ echo ""--add-opens=jdk.attach/sun.tools.attach=ALL-UNNAMED"" >> $OPENSEARCH_PATH_CONF/jvm.options
+fi
+echo ""done plugins""
+
+##Set KNN Dylib Path for macOS and *nix systems
+if echo ""$OSTYPE"" | grep -qi ""darwin""; then
+ if echo ""$JAVA_LIBRARY_PATH"" | grep -q ""$KNN_LIB_DIR""; then
+ echo ""k-NN libraries found in JAVA_LIBRARY_PATH""
+ else
+ export JAVA_LIBRARY_PATH=$JAVA_LIBRARY_PATH:$KNN_LIB_DIR
+ echo ""k-NN libraries not found in JAVA_LIBRARY_PATH. Updating path to: $JAVA_LIBRARY_PATH.""
+ fi
+else
+ if echo ""$LD_LIBRARY_PATH"" | grep -q ""$KNN_LIB_DIR""; then
+ echo ""k-NN libraries found in LD_LIBRARY_PATH""
+ else
+ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$KNN_LIB_DIR
+ echo ""k-NN libraries not found in LD_LIBRARY_PATH. Updating path to: $LD_LIBRARY_PATH.""
+ fi
+fi
+";
+ }
+ }
+}
diff --git a/abstractions/src/OpenSearch.OpenSearch.Ephemeral/Tasks/InstallationTasks/InstallPlugins.cs b/abstractions/src/OpenSearch.OpenSearch.Ephemeral/Tasks/InstallationTasks/InstallPlugins.cs
new file mode 100644
index 0000000000..bb8e06049e
--- /dev/null
+++ b/abstractions/src/OpenSearch.OpenSearch.Ephemeral/Tasks/InstallationTasks/InstallPlugins.cs
@@ -0,0 +1,136 @@
+/* SPDX-License-Identifier: Apache-2.0
+*
+* The OpenSearch Contributors require contributions made to
+* this file be licensed under the Apache-2.0 license or a
+* compatible open source license.
+*/
+/*
+* Modifications Copyright OpenSearch Contributors. See
+* GitHub history for details.
+*
+* Licensed to Elasticsearch B.V. under one or more contributor
+* license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright
+* ownership. Elasticsearch B.V. licenses this file to you under
+* the Apache License, Version 2.0 (the "License"); you may
+* not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+using System;
+using System.IO;
+using System.Linq;
+using OpenSearch.OpenSearch.Managed;
+using OpenSearch.OpenSearch.Managed.ConsoleWriters;
+using OpenSearch.OpenSearch.Managed.FileSystem;
+using OpenSearch.Stack.ArtifactsApi;
+using OpenSearch.Stack.ArtifactsApi.Products;
+using ProcNet.Std;
+
+namespace OpenSearch.OpenSearch.Ephemeral.Tasks.InstallationTasks
+{
+ public class InstallPlugins : ClusterComposeTask
+ {
+ public override void Run(IEphemeralCluster cluster)
+ {
+ if (cluster.CachingAndCachedHomeExists()) return;
+
+ var v = cluster.ClusterConfiguration.Version;
+
+ var fs = cluster.FileSystem;
+ var requiredPlugins = cluster.ClusterConfiguration.Plugins;
+
+ if (cluster.ClusterConfiguration.ValidatePluginsToInstall)
+ {
+ var invalidPlugins = requiredPlugins
+ .Where(p => !p.IsValid(v))
+ .Select(p => p.SubProductName).ToList();
+ if (invalidPlugins.Any())
+ throw new OpenSearchCleanExitException(
+ $"Can not install the following plugins for version {v}: {string.Join(", ", invalidPlugins)} ");
+ }
+
+ foreach (var plugin in requiredPlugins)
+ {
+ var includedByDefault = plugin.IsIncludedOutOfTheBox(v);
+ if (includedByDefault)
+ {
+ cluster.Writer?.WriteDiagnostic(
+ $"{{{nameof(Run)}}} SKIP plugin [{plugin.SubProductName}] shipped OOTB as of: {{{plugin.ShippedByDefaultAsOf}}}");
+ continue;
+ }
+
+ var validForCurrentVersion = plugin.IsValid(v);
+ if (!validForCurrentVersion)
+ {
+ cluster.Writer?.WriteDiagnostic(
+ $"{{{nameof(Run)}}} SKIP plugin [{plugin.SubProductName}] not valid for version: {{{v}}}");
+ continue;
+ }
+
+ var alreadyInstalled = AlreadyInstalled(fs, plugin.SubProductName);
+ if (alreadyInstalled)
+ {
+ cluster.Writer?.WriteDiagnostic(
+ $"{{{nameof(Run)}}} SKIP plugin [{plugin.SubProductName}] already installed");
+ continue;
+ }
+
+ cluster.Writer?.WriteDiagnostic(
+ $"{{{nameof(Run)}}} attempting install [{plugin.SubProductName}] as it's not OOTB: {{{plugin.ShippedByDefaultAsOf}}} and valid for {v}: {{{plugin.IsValid(v)}}}");
+
+ if (!Directory.Exists(fs.ConfigPath)) Directory.CreateDirectory(fs.ConfigPath);
+ ExecuteBinary(
+ cluster.ClusterConfiguration,
+ cluster.Writer,
+ fs.PluginBinary,
+ $"install opensearch plugin: {plugin.SubProductName}",
+ "install --batch", GetPluginLocation(plugin, v));
+
+ CopyConfigDirectoryToHomeCacheConfigDirectory(cluster, plugin);
+ }
+ }
+
+ private static string GetPluginLocation(OpenSearchPlugin plugin, OpenSearchVersion v)
+ {
+ // OpenSearch 1.0.0 artifacts were not published. The plugins are built in the workflow and used here.
+ if (v == "1.0.0")
+ // The environment variable is set in the integration workflow in
+ // https://github.com/opensearch-project/opensearch-net/blob/main/.github/workflows/integration.yml
+ return "file://" + Environment.GetEnvironmentVariable("plugins-directory") + $"/{plugin.SubProductName}-{v}.zip";
+ else
+ return plugin.SubProductName;
+ }
+
+ private static void CopyConfigDirectoryToHomeCacheConfigDirectory(
+ IEphemeralCluster cluster, OpenSearchPlugin plugin)
+ {
+ if (!cluster.ClusterConfiguration.CacheOpenSearchHomeInstallation) return;
+ var fs = cluster.FileSystem;
+ var cachedOpenSearchHomeFolder = Path.Combine(fs.LocalFolder, cluster.GetCacheFolderName());
+ var configTarget = Path.Combine(cachedOpenSearchHomeFolder, "config");
+
+ var configPluginPath = Path.Combine(fs.ConfigPath, plugin.SubProductName);
+ var configPluginPathCached = Path.Combine(configTarget, plugin.SubProductName);
+ if (!Directory.Exists(configPluginPath) || Directory.Exists(configPluginPathCached)) return;
+
+ Directory.CreateDirectory(configPluginPathCached);
+ CopyFolder(configPluginPath, configPluginPathCached);
+ }
+
+ private static bool AlreadyInstalled(INodeFileSystem fileSystem, string folderName)
+ {
+ var pluginFolder = Path.Combine(fileSystem.OpenSearchHome, "plugins", folderName);
+ return Directory.Exists(pluginFolder);
+ }
+ }
+}
diff --git a/abstractions/src/OpenSearch.OpenSearch.Ephemeral/Tasks/InstallationTasks/PrintConfiguration.cs b/abstractions/src/OpenSearch.OpenSearch.Ephemeral/Tasks/InstallationTasks/PrintConfiguration.cs
new file mode 100644
index 0000000000..42248300c5
--- /dev/null
+++ b/abstractions/src/OpenSearch.OpenSearch.Ephemeral/Tasks/InstallationTasks/PrintConfiguration.cs
@@ -0,0 +1,76 @@
+/* SPDX-License-Identifier: Apache-2.0
+*
+* The OpenSearch Contributors require contributions made to
+* this file be licensed under the Apache-2.0 license or a
+* compatible open source license.
+*/
+/*
+* Modifications Copyright OpenSearch Contributors. See
+* GitHub history for details.
+*
+* Licensed to Elasticsearch B.V. under one or more contributor
+* license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright
+* ownership. Elasticsearch B.V. licenses this file to you under
+* the Apache License, Version 2.0 (the "License"); you may
+* not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+using System;
+using System.Linq;
+using OpenSearch.OpenSearch.Managed.ConsoleWriters;
+using static OpenSearch.OpenSearch.Ephemeral.ClusterFeatures;
+
+namespace OpenSearch.OpenSearch.Ephemeral.Tasks.InstallationTasks
+{
+ public class PrintConfiguration : ClusterComposeTask
+ {
+ public override void Run(IEphemeralCluster cluster)
+ {
+ var c = cluster.ClusterConfiguration;
+ var version = c.Version;
+
+ string F(ClusterFeatures feature)
+ {
+ return c.Features.HasFlag(feature) ? Enum.GetName(typeof(ClusterFeatures), feature) : string.Empty;
+ }
+
+ var features = string.Join("|",
+ new[] { F(SSL)}.Where(v => !string.IsNullOrWhiteSpace(v)));
+ features = string.IsNullOrWhiteSpace(features) ? "None" : features;
+ cluster.Writer?.WriteDiagnostic(
+ $"{{{nameof(PrintConfiguration)}}} starting {{{version}}} with features [{features}]");
+ cluster.Writer?.WriteDiagnostic(
+ $"{{{nameof(PrintConfiguration)}}} {{{nameof(c.NumberOfNodes)}}} [{c.NumberOfNodes}]");
+ cluster.Writer?.WriteDiagnostic(
+ $"{{{nameof(PrintConfiguration)}}} {{{nameof(c.ClusterName)}}} [{c.ClusterName}]");
+ cluster.Writer?.WriteDiagnostic(
+ $"{{{nameof(PrintConfiguration)}}} {{{nameof(c.EnableSsl)}}} [{c.EnableSsl}]");
+ cluster.Writer?.WriteDiagnostic($"{{{nameof(PrintConfiguration)}}} {{{nameof(c.Plugins)}}} [{c.Plugins}]");
+ cluster.Writer?.WriteDiagnostic(
+ $"{{{nameof(PrintConfiguration)}}} {{{nameof(c.CacheOpenSearchHomeInstallation)}}} [{c.CacheOpenSearchHomeInstallation}]");
+ cluster.Writer?.WriteDiagnostic(
+ $"{{{nameof(PrintConfiguration)}}} {{{nameof(c.ShowOpenSearchOutputAfterStarted)}}} [{c.ShowOpenSearchOutputAfterStarted}]");
+ cluster.Writer?.WriteDiagnostic(
+ $"{{{nameof(PrintConfiguration)}}} {{{nameof(c.ValidatePluginsToInstall)}}} [{c.ValidatePluginsToInstall}]");
+ cluster.Writer?.WriteDiagnostic(
+ $"{{{nameof(PrintConfiguration)}}} {{{nameof(c.PrintYamlFilesInConfigFolder)}}} [{c.PrintYamlFilesInConfigFolder}]");
+ cluster.Writer?.WriteDiagnostic(
+ $"{{{nameof(PrintConfiguration)}}} {{{nameof(c.SkipBuiltInAfterStartTasks)}}} [{c.SkipBuiltInAfterStartTasks}]");
+ cluster.Writer?.WriteDiagnostic(
+ $"{{{nameof(PrintConfiguration)}}} {{{nameof(c.HttpFiddlerAware)}}} [{c.HttpFiddlerAware}]");
+ cluster.Writer?.WriteDiagnostic(
+ $"{{{nameof(PrintConfiguration)}}} {{{nameof(c.NoCleanupAfterNodeStopped)}}} [{c.NoCleanupAfterNodeStopped}]");
+ }
+ }
+}
diff --git a/abstractions/src/OpenSearch.OpenSearch.Ephemeral/Tasks/InstallationTasks/SetOpenSearchBundledJdkJavaHome.cs b/abstractions/src/OpenSearch.OpenSearch.Ephemeral/Tasks/InstallationTasks/SetOpenSearchBundledJdkJavaHome.cs
new file mode 100644
index 0000000000..82a28dac64
--- /dev/null
+++ b/abstractions/src/OpenSearch.OpenSearch.Ephemeral/Tasks/InstallationTasks/SetOpenSearchBundledJdkJavaHome.cs
@@ -0,0 +1,53 @@
+/* SPDX-License-Identifier: Apache-2.0
+*
+* The OpenSearch Contributors require contributions made to
+* this file be licensed under the Apache-2.0 license or a
+* compatible open source license.
+*/
+/*
+* Modifications Copyright OpenSearch Contributors. See
+* GitHub history for details.
+*
+* Licensed to Elasticsearch B.V. under one or more contributor
+* license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright
+* ownership. Elasticsearch B.V. licenses this file to you under
+* the Apache License, Version 2.0 (the "License"); you may
+* not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+using System;
+using System.IO;
+using OpenSearch.OpenSearch.Managed.ConsoleWriters;
+
+namespace OpenSearch.OpenSearch.Ephemeral.Tasks.InstallationTasks
+{
+ public class SetOpenSearchBundledJdkJavaHome : ClusterComposeTask
+ {
+ public override void Run(IEphemeralCluster cluster)
+ {
+ var fs = cluster.FileSystem;
+ var jdkFolder = Path.Combine(fs.OpenSearchHome, "jdk");
+ if (Directory.Exists(jdkFolder))
+ {
+ var envVarName = cluster.ClusterConfiguration.JavaHomeEnvironmentVariable;
+ cluster.Writer?.WriteDiagnostic(
+ $"{{{nameof(SetOpenSearchBundledJdkJavaHome)}}} [{envVarName}] is set to bundled jdk: {{{jdkFolder}}} ");
+ Environment.SetEnvironmentVariable(envVarName, jdkFolder);
+ }
+ else
+ cluster.Writer?.WriteDiagnostic(
+ $"{{{nameof(SetOpenSearchBundledJdkJavaHome)}}} [No bundled jdk found] looked in: {{{jdkFolder}}} ");
+ }
+ }
+}
diff --git a/abstractions/src/OpenSearch.OpenSearch.Ephemeral/Tasks/InstallationTasks/UnzipOpenSearch.cs b/abstractions/src/OpenSearch.OpenSearch.Ephemeral/Tasks/InstallationTasks/UnzipOpenSearch.cs
new file mode 100644
index 0000000000..81a80693f4
--- /dev/null
+++ b/abstractions/src/OpenSearch.OpenSearch.Ephemeral/Tasks/InstallationTasks/UnzipOpenSearch.cs
@@ -0,0 +1,68 @@
+/* SPDX-License-Identifier: Apache-2.0
+*
+* The OpenSearch Contributors require contributions made to
+* this file be licensed under the Apache-2.0 license or a
+* compatible open source license.
+*/
+/*
+* Modifications Copyright OpenSearch Contributors. See
+* GitHub history for details.
+*
+* Licensed to Elasticsearch B.V. under one or more contributor
+* license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright
+* ownership. Elasticsearch B.V. licenses this file to you under
+* the Apache License, Version 2.0 (the "License"); you may
+* not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+using System.IO;
+using OpenSearch.OpenSearch.Managed.ConsoleWriters;
+
+namespace OpenSearch.OpenSearch.Ephemeral.Tasks.InstallationTasks
+{
+ public class UnzipOpenSearch : ClusterComposeTask
+ {
+ public override void Run(IEphemeralCluster cluster)
+ {
+ if (cluster.CachingAndCachedHomeExists()) return;
+
+ var fs = cluster.FileSystem;
+ var v = cluster.ClusterConfiguration.Version;
+ var a = cluster.ClusterConfiguration.Artifact;
+ if (Directory.Exists(fs.OpenSearchHome))
+ {
+ cluster.Writer?.WriteDiagnostic(
+ $"{{{nameof(UnzipOpenSearch)}}} skipping [{fs.OpenSearchHome}] already exists");
+ return;
+ }
+
+ var from = Path.Combine(fs.LocalFolder, a.Archive);
+ var extractedFolder = Path.Combine(fs.LocalFolder, a.FolderInZip);
+ if (!Directory.Exists(extractedFolder))
+ {
+ cluster.Writer?.WriteDiagnostic($"{{{nameof(UnzipOpenSearch)}}} unzipping version [{v}] {{{from}}}");
+ Extract(from, fs.LocalFolder);
+
+ cluster.Writer?.WriteDiagnostic(
+ $"{{{nameof(UnzipOpenSearch)}}} extracted version [{v}] to {{{fs.LocalFolder}}}");
+ }
+
+ if (extractedFolder == fs.OpenSearchHome) return;
+
+ cluster.Writer?.WriteDiagnostic(
+ $"{{{nameof(UnzipOpenSearch)}}} Copying extracted folder {{{extractedFolder}}} => {fs.OpenSearchHome}");
+ CopyFolder(extractedFolder, fs.OpenSearchHome);
+ }
+ }
+}
diff --git a/abstractions/src/OpenSearch.OpenSearch.Ephemeral/Tasks/ValidationTasks/ValidateClusterStateTask.cs b/abstractions/src/OpenSearch.OpenSearch.Ephemeral/Tasks/ValidationTasks/ValidateClusterStateTask.cs
new file mode 100644
index 0000000000..1778867b89
--- /dev/null
+++ b/abstractions/src/OpenSearch.OpenSearch.Ephemeral/Tasks/ValidationTasks/ValidateClusterStateTask.cs
@@ -0,0 +1,47 @@
+/* SPDX-License-Identifier: Apache-2.0
+*
+* The OpenSearch Contributors require contributions made to
+* this file be licensed under the Apache-2.0 license or a
+* compatible open source license.
+*/
+/*
+* Modifications Copyright OpenSearch Contributors. See
+* GitHub history for details.
+*
+* Licensed to Elasticsearch B.V. under one or more contributor
+* license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright
+* ownership. Elasticsearch B.V. licenses this file to you under
+* the Apache License, Version 2.0 (the "License"); you may
+* not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+using System;
+using System.Net;
+using OpenSearch.OpenSearch.Managed.ConsoleWriters;
+
+namespace OpenSearch.OpenSearch.Ephemeral.Tasks.ValidationTasks
+{
+ public class ValidateClusterStateTask : ClusterComposeTask
+ {
+ public override void Run(IEphemeralCluster cluster)
+ {
+ cluster.Writer.WriteDiagnostic(
+ $"{{{nameof(ValidateClusterStateTask)}}} waiting cluster to go into yellow health state");
+ var healthyResponse = Get(cluster, "_cluster/health", "wait_for_status=yellow&timeout=20s");
+ if (healthyResponse == null || healthyResponse.StatusCode != HttpStatusCode.OK)
+ throw new Exception(
+ $"Cluster health waiting for status yellow failed after 20s {GetResponseException(healthyResponse)}");
+ }
+ }
+}
diff --git a/abstractions/src/OpenSearch.OpenSearch.Ephemeral/Tasks/ValidationTasks/ValidatePluginsTask.cs b/abstractions/src/OpenSearch.OpenSearch.Ephemeral/Tasks/ValidationTasks/ValidatePluginsTask.cs
new file mode 100644
index 0000000000..045a53b263
--- /dev/null
+++ b/abstractions/src/OpenSearch.OpenSearch.Ephemeral/Tasks/ValidationTasks/ValidatePluginsTask.cs
@@ -0,0 +1,68 @@
+/* SPDX-License-Identifier: Apache-2.0
+*
+* The OpenSearch Contributors require contributions made to
+* this file be licensed under the Apache-2.0 license or a
+* compatible open source license.
+*/
+/*
+* Modifications Copyright OpenSearch Contributors. See
+* GitHub history for details.
+*
+* Licensed to Elasticsearch B.V. under one or more contributor
+* license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright
+* ownership. Elasticsearch B.V. licenses this file to you under
+* the Apache License, Version 2.0 (the "License"); you may
+* not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+using System;
+using System.Linq;
+using OpenSearch.OpenSearch.Ephemeral.Tasks.InstallationTasks;
+using OpenSearch.OpenSearch.Managed.ConsoleWriters;
+using OpenSearch.Stack.ArtifactsApi;
+
+namespace OpenSearch.OpenSearch.Ephemeral.Tasks.ValidationTasks
+{
+ public class ValidatePluginsTask : ClusterComposeTask
+ {
+ public override void Run(IEphemeralCluster cluster)
+ {
+ var v = cluster.ClusterConfiguration.Version;
+ var requestPlugins = cluster.ClusterConfiguration.Plugins
+ .Where(p => p.IsValid(v))
+ .Where(p => !p.IsIncludedOutOfTheBox(v))
+ .Select(p => p.GetExistsMoniker(v))
+ .ToList();
+ if (!requestPlugins.Any()) return;
+
+ cluster.Writer.WriteDiagnostic(
+ $"{{{nameof(ValidatePluginsTask)}}} validating the cluster is running the requested plugins");
+ var catPlugins = Get(cluster, "_cat/plugins", "h=component");
+ if (catPlugins == null || !catPlugins.IsSuccessStatusCode)
+ throw new Exception(
+ $"Calling _cat/plugins did not result in an OK response {GetResponseException(catPlugins)}");
+
+ var installedPlugins = GetResponseString(catPlugins)
+ .Split(new[] {'\n'}, StringSplitOptions.RemoveEmptyEntries).ToList();
+
+ var missingPlugins = requestPlugins.Except(installedPlugins).ToList();
+ if (!missingPlugins.Any()) return;
+
+ var missingString = string.Join(", ", missingPlugins);
+ var pluginsString = string.Join(", ", installedPlugins);
+ throw new Exception(
+ $"Already running opensearch missed the following plugin(s): {missingString} currently installed: {pluginsString}.");
+ }
+ }
+}
diff --git a/abstractions/src/OpenSearch.OpenSearch.Ephemeral/Tasks/ValidationTasks/ValidateRunningVersion.cs b/abstractions/src/OpenSearch.OpenSearch.Ephemeral/Tasks/ValidationTasks/ValidateRunningVersion.cs
new file mode 100644
index 0000000000..286e0cb294
--- /dev/null
+++ b/abstractions/src/OpenSearch.OpenSearch.Ephemeral/Tasks/ValidationTasks/ValidateRunningVersion.cs
@@ -0,0 +1,81 @@
+/* SPDX-License-Identifier: Apache-2.0
+*
+* The OpenSearch Contributors require contributions made to
+* this file be licensed under the Apache-2.0 license or a
+* compatible open source license.
+*/
+/*
+* Modifications Copyright OpenSearch Contributors. See
+* GitHub history for details.
+*
+* Licensed to Elasticsearch B.V. under one or more contributor
+* license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright
+* ownership. Elasticsearch B.V. licenses this file to you under
+* the Apache License, Version 2.0 (the "License"); you may
+* not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+using System;
+using System.Linq;
+using System.Net.Http;
+using System.Threading;
+using OpenSearch.OpenSearch.Managed.ConsoleWriters;
+using OpenSearch.Stack.ArtifactsApi;
+
+namespace OpenSearch.OpenSearch.Ephemeral.Tasks.ValidationTasks
+{
+ public class ValidateRunningVersion : ClusterComposeTask
+ {
+ public override void Run(IEphemeralCluster cluster)
+ {
+ void WriteDiagnostic(string message) =>
+ cluster.Writer?.WriteDiagnostic($"{{{nameof(ValidateRunningVersion)}}} {message}");
+ var requestedVersion = cluster.ClusterConfiguration.Version;
+ if (cluster.ClusterConfiguration.Artifact.ServerType == ServerType.OpenDistro)
+ //All supported version of OpenDistro are based on ElasticSearch v.7.10.2
+ requestedVersion = OpenSearchVersion.From("7.10.2");
+
+
+ WriteDiagnostic($"validating the cluster is running the requested version: {requestedVersion}");
+
+ HttpResponseMessage catNodes = null;
+ var retryCount = 4;
+ var initialRetryWait = 5;
+ foreach (var retry in Enumerable.Range(1, retryCount))
+ {
+ catNodes = Get(cluster, "_cat/nodes", "h=version");
+ if (catNodes.IsSuccessStatusCode) break;
+ var retryWait = TimeSpan.FromSeconds(initialRetryWait * retry);
+ WriteDiagnostic($"{catNodes.StatusCode} response for GET _cat/nodes. Waiting to retry #{retry}");
+ Thread.Sleep(retryWait);
+ }
+ if (catNodes is not {IsSuccessStatusCode: true})
+ {
+ throw new Exception(
+ $"Calling _cat/nodes for version checking did not result in an OK response {GetResponseException(catNodes)}");
+ }
+
+ var nodeVersions = GetResponseString(catNodes).Split(new[] {'\n'}, StringSplitOptions.RemoveEmptyEntries)
+ .ToList();
+
+ var anchorVersion = $"{requestedVersion.Major}.{requestedVersion.Minor}.{requestedVersion.Patch}";
+ var allOnRequestedVersion = nodeVersions.All(v => v.Trim() == anchorVersion);
+ if (!allOnRequestedVersion)
+ {
+ throw new Exception(
+ $"Not all the running nodes in the cluster are on requested version: {anchorVersion} received: {string.Join(", ", nodeVersions)}");
+ }
+ }
+ }
+}
diff --git a/abstractions/src/OpenSearch.OpenSearch.Ephemeral/packages.lock.json b/abstractions/src/OpenSearch.OpenSearch.Ephemeral/packages.lock.json
new file mode 100644
index 0000000000..f8bdb40018
--- /dev/null
+++ b/abstractions/src/OpenSearch.OpenSearch.Ephemeral/packages.lock.json
@@ -0,0 +1,949 @@
+{
+ "version": 1,
+ "dependencies": {
+ ".NETFramework,Version=v4.6.1": {
+ "Microsoft.NETFramework.ReferenceAssemblies": {
+ "type": "Direct",
+ "requested": "[1.0.0-preview.2, )",
+ "resolved": "1.0.0-preview.2",
+ "contentHash": "m+pJPEO7HyXvrOna5Sr3s77ewXonjYWJTNL6drh8xACnMNxnlqUDKx9HfGeSE9wmfY0lQwppaeZpFTPGaH7kZg==",
+ "dependencies": {
+ "Microsoft.NETFramework.ReferenceAssemblies.net461": "1.0.0-preview.2"
+ }
+ },
+ "SharpZipLib.NETStandard": {
+ "type": "Direct",
+ "requested": "[1.0.7, )",
+ "resolved": "1.0.7",
+ "contentHash": "mYKPizF2CY32RQB8FITYy0e30gVgItFA63SFquruaxq+votwL1T+yOfssK10v4enBcxklr8ks48hS1emw5TTXg=="
+ },
+ "System.Runtime.InteropServices.RuntimeInformation": {
+ "type": "Direct",
+ "requested": "[4.3.0, )",
+ "resolved": "4.3.0",
+ "contentHash": "cbz4YJMqRDR7oLeMRbdYv7mYzc++17lNhScCX0goO2XpGWdvAt60CGN+FHdePUEHCe/Jy9jUlvNAiNdM+7jsOw=="
+ },
+ "Microsoft.Bcl.AsyncInterfaces": {
+ "type": "Transitive",
+ "resolved": "6.0.0",
+ "contentHash": "UcSjPsst+DfAdJGVDsu346FX0ci0ah+lw3WRtn18NUwEqRt70HaOQ7lI72vy3+1LxtqI3T5GWwV39rQSrCzAeg==",
+ "dependencies": {
+ "System.Threading.Tasks.Extensions": "4.5.4"
+ }
+ },
+ "Microsoft.NETFramework.ReferenceAssemblies.net461": {
+ "type": "Transitive",
+ "resolved": "1.0.0-preview.2",
+ "contentHash": "59D9ISjzCpfHG41r5x4BNZNNOCmE2o5YX8vcdOwsqfxOA0+6vQnxZrYq8KtthUU2JSvC13g941rSr5GRaNQOJg=="
+ },
+ "Proc": {
+ "type": "Transitive",
+ "resolved": "0.6.1",
+ "contentHash": "xRSCfgQNoGy60MOuvD2X1euzqvWDoyfpB8NAfVs2E5K5U1I8cA9MvVY6NbUkp5ApbOmVXls2JEPrOn8rQi2Pzg=="
+ },
+ "SemanticVersioning": {
+ "type": "Transitive",
+ "resolved": "0.8.0",
+ "contentHash": "hUCnQL79hU0W6X4jPeMAtGDwoEJeBEZfGBnkT+jPG45lD7KHn4h61HgYN8y1HAjPrXmC5oJcLx3l8ygPJOqvlA=="
+ },
+ "System.Buffers": {
+ "type": "Transitive",
+ "resolved": "4.5.1",
+ "contentHash": "Rw7ijyl1qqRS0YQD/WycNst8hUUMgrMH4FCn1nNm27M4VxchZ1js3fVjQaANHO5f3sN4isvP4a+Met9Y4YomAg=="
+ },
+ "System.Memory": {
+ "type": "Transitive",
+ "resolved": "4.5.4",
+ "contentHash": "1MbJTHS1lZ4bS4FmsJjnuGJOu88ZzTT2rLvrhW7Ygic+pC0NWA+3hgAen0HRdsocuQXCkUTdFn9yHJJhsijDXw==",
+ "dependencies": {
+ "System.Buffers": "4.5.1",
+ "System.Numerics.Vectors": "4.5.0",
+ "System.Runtime.CompilerServices.Unsafe": "4.5.3"
+ }
+ },
+ "System.Net.Http": {
+ "type": "Transitive",
+ "resolved": "4.3.4",
+ "contentHash": "aOa2d51SEbmM+H+Csw7yJOuNZoHkrP2XnAurye5HWYgGVVU54YZDvsLUYRv6h18X3sPnjNCANmN7ZhIPiqMcjA==",
+ "dependencies": {
+ "System.Security.Cryptography.X509Certificates": "4.3.0"
+ }
+ },
+ "System.Numerics.Vectors": {
+ "type": "Transitive",
+ "resolved": "4.5.0",
+ "contentHash": "QQTlPTl06J/iiDbJCiepZ4H//BVraReU4O4EoRw1U02H5TLUIT7xn3GnDp9AXPSlJUDyFs4uWjWafNX6WrAojQ=="
+ },
+ "System.Runtime.CompilerServices.Unsafe": {
+ "type": "Transitive",
+ "resolved": "6.0.0",
+ "contentHash": "/iUeP3tq1S0XdNNoMz5C9twLSrM/TH+qElHkXWaPvuNOt+99G75NrV0OS2EqHx5wMN7popYjpc8oTjC1y16DLg=="
+ },
+ "System.Security.Cryptography.Algorithms": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "W1kd2Y8mYSCgc3ULTAZ0hOP2dSdG5YauTb1089T0/kRcN2MpSAW1izOFROrJgxSlMn3ArsgHXagigyi+ibhevg==",
+ "dependencies": {
+ "System.Security.Cryptography.Primitives": "4.3.0"
+ }
+ },
+ "System.Security.Cryptography.Encoding": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "1DEWjZZly9ae9C79vFwqaO5kaOlI5q+3/55ohmq/7dpDyDfc8lYe7YVxJUZ5MF/NtbkRjwFRo14yM4OEo9EmDw=="
+ },
+ "System.Security.Cryptography.Primitives": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "7bDIyVFNL/xKeFHjhobUAQqSpJq9YTOpbEs6mR233Et01STBMXNAc/V+BM6dwYGc95gVh/Zf+iVXWzj3mE8DWg=="
+ },
+ "System.Security.Cryptography.X509Certificates": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "t2Tmu6Y2NtJ2um0RtcuhP7ZdNNxXEgUm2JeoA/0NvlMjAhKCnM1NX07TDl3244mVp3QU6LPEhT3HTtH1uF7IYw==",
+ "dependencies": {
+ "System.Security.Cryptography.Algorithms": "4.3.0",
+ "System.Security.Cryptography.Encoding": "4.3.0"
+ }
+ },
+ "System.Text.Encodings.Web": {
+ "type": "Transitive",
+ "resolved": "6.0.0",
+ "contentHash": "Vg8eB5Tawm1IFqj4TVK1czJX89rhFxJo9ELqc/Eiq0eXy13RK00eubyU6TJE6y+GQXjyV5gSfiewDUZjQgSE0w==",
+ "dependencies": {
+ "System.Buffers": "4.5.1",
+ "System.Memory": "4.5.4",
+ "System.Runtime.CompilerServices.Unsafe": "6.0.0"
+ }
+ },
+ "System.Text.Json": {
+ "type": "Transitive",
+ "resolved": "6.0.5",
+ "contentHash": "SSH+YYrMpvLcy7Orzb5K1tSyffnFacWahyxCCjYH1PbSHdAF4dekmIetBurFKgtTHDmwEe/J2Csi/7niRH6d/g==",
+ "dependencies": {
+ "Microsoft.Bcl.AsyncInterfaces": "6.0.0",
+ "System.Buffers": "4.5.1",
+ "System.Memory": "4.5.4",
+ "System.Numerics.Vectors": "4.5.0",
+ "System.Runtime.CompilerServices.Unsafe": "6.0.0",
+ "System.Text.Encodings.Web": "6.0.0",
+ "System.Threading.Tasks.Extensions": "4.5.4",
+ "System.ValueTuple": "4.5.0"
+ }
+ },
+ "System.Threading.Tasks.Extensions": {
+ "type": "Transitive",
+ "resolved": "4.5.4",
+ "contentHash": "zteT+G8xuGu6mS+mzDzYXbzS7rd3K6Fjb9RiZlYlJPam2/hU7JCBZBVEcywNuR+oZ1ncTvc/cq0faRr3P01OVg==",
+ "dependencies": {
+ "System.Runtime.CompilerServices.Unsafe": "4.5.3"
+ }
+ },
+ "System.ValueTuple": {
+ "type": "Transitive",
+ "resolved": "4.5.0",
+ "contentHash": "okurQJO6NRE/apDIP23ajJ0hpiNmJ+f0BwOlB/cSqTLQlw5upkf+5+96+iG2Jw40G1fCVCyPz/FhIABUjMR+RQ=="
+ },
+ "opensearch.opensearch.managed": {
+ "type": "Project",
+ "dependencies": {
+ "OpenSearch.Stack.ArtifactsApi": "1.0.0",
+ "Proc": "0.6.1",
+ "System.Net.Http": "4.3.4"
+ }
+ },
+ "opensearch.stack.artifactsapi": {
+ "type": "Project",
+ "dependencies": {
+ "SemanticVersioning": "0.8.0",
+ "System.Net.Http": "4.3.4",
+ "System.Runtime.InteropServices.RuntimeInformation": "4.3.0",
+ "System.Text.Json": "6.0.5"
+ }
+ }
+ },
+ ".NETStandard,Version=v2.0": {
+ "Microsoft.NETFramework.ReferenceAssemblies": {
+ "type": "Direct",
+ "requested": "[1.0.0-preview.2, )",
+ "resolved": "1.0.0-preview.2",
+ "contentHash": "m+pJPEO7HyXvrOna5Sr3s77ewXonjYWJTNL6drh8xACnMNxnlqUDKx9HfGeSE9wmfY0lQwppaeZpFTPGaH7kZg=="
+ },
+ "NETStandard.Library": {
+ "type": "Direct",
+ "requested": "[2.0.3, )",
+ "resolved": "2.0.3",
+ "contentHash": "st47PosZSHrjECdjeIzZQbzivYBJFv6P2nv4cj2ypdI204DO+vZ7l5raGMiX4eXMJ53RfOIg+/s4DHVZ54Nu2A==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0"
+ }
+ },
+ "SharpZipLib.NETStandard": {
+ "type": "Direct",
+ "requested": "[1.0.7, )",
+ "resolved": "1.0.7",
+ "contentHash": "mYKPizF2CY32RQB8FITYy0e30gVgItFA63SFquruaxq+votwL1T+yOfssK10v4enBcxklr8ks48hS1emw5TTXg==",
+ "dependencies": {
+ "NETStandard.Library": "1.6.1"
+ }
+ },
+ "Microsoft.Bcl.AsyncInterfaces": {
+ "type": "Transitive",
+ "resolved": "6.0.0",
+ "contentHash": "UcSjPsst+DfAdJGVDsu346FX0ci0ah+lw3WRtn18NUwEqRt70HaOQ7lI72vy3+1LxtqI3T5GWwV39rQSrCzAeg==",
+ "dependencies": {
+ "System.Threading.Tasks.Extensions": "4.5.4"
+ }
+ },
+ "Microsoft.NETCore.Platforms": {
+ "type": "Transitive",
+ "resolved": "1.1.1",
+ "contentHash": "TMBuzAHpTenGbGgk0SMTwyEkyijY/Eae4ZGsFNYJvAr/LDn1ku3Etp3FPxChmDp5HHF3kzJuoaa08N0xjqAJfQ=="
+ },
+ "Microsoft.NETCore.Targets": {
+ "type": "Transitive",
+ "resolved": "1.1.0",
+ "contentHash": "aOZA3BWfz9RXjpzt0sRJJMjAscAUm3Hoa4UWAfceV9UTYxgwZ1lZt5nO2myFf+/jetYQo4uTP7zS8sJY67BBxg=="
+ },
+ "Microsoft.Win32.Primitives": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "9ZQKCWxH7Ijp9BfahvL2Zyf1cJIk8XYLF6Yjzr2yi0b2cOut/HQ31qf1ThHAgCc3WiZMdnWcfJCgN82/0UunxA==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "Microsoft.NETCore.Targets": "1.1.0",
+ "System.Runtime": "4.3.0"
+ }
+ },
+ "Microsoft.Win32.Registry": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "Lw1/VwLH1yxz6SfFEjVRCN0pnflLEsWgnV4qsdJ512/HhTwnKXUG+zDQ4yTO3K/EJQemGoNaBHX5InISNKTzUQ==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "System.Collections": "4.3.0",
+ "System.Globalization": "4.3.0",
+ "System.Resources.ResourceManager": "4.3.0",
+ "System.Runtime": "4.3.0",
+ "System.Runtime.Extensions": "4.3.0",
+ "System.Runtime.Handles": "4.3.0",
+ "System.Runtime.InteropServices": "4.3.0"
+ }
+ },
+ "Proc": {
+ "type": "Transitive",
+ "resolved": "0.6.1",
+ "contentHash": "xRSCfgQNoGy60MOuvD2X1euzqvWDoyfpB8NAfVs2E5K5U1I8cA9MvVY6NbUkp5ApbOmVXls2JEPrOn8rQi2Pzg==",
+ "dependencies": {
+ "System.Diagnostics.Process": "[4.3.0]",
+ "System.Threading.Thread": "[4.3.0]"
+ }
+ },
+ "runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": {
+ "type": "Transitive",
+ "resolved": "4.3.2",
+ "contentHash": "7VSGO0URRKoMEAq0Sc9cRz8mb6zbyx/BZDEWhgPdzzpmFhkam3fJ1DAGWFXBI4nGlma+uPKpfuMQP5LXRnOH5g=="
+ },
+ "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl": {
+ "type": "Transitive",
+ "resolved": "4.3.2",
+ "contentHash": "0oAaTAm6e2oVH+/Zttt0cuhGaePQYKII1dY8iaqP7CvOpVKgLybKRFvQjXR2LtxXOXTVPNv14j0ot8uV+HrUmw=="
+ },
+ "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl": {
+ "type": "Transitive",
+ "resolved": "4.3.2",
+ "contentHash": "G24ibsCNi5Kbz0oXWynBoRgtGvsw5ZSVEWjv13/KiCAM8C6wz9zzcCniMeQFIkJ2tasjo2kXlvlBZhplL51kGg=="
+ },
+ "runtime.native.System": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "c/qWt2LieNZIj1jGnVNsE2Kl23Ya2aSTBuXMD6V7k9KWr6l16Tqdwq+hJScEpWER9753NWC8h96PaVNY5Ld7Jw==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "Microsoft.NETCore.Targets": "1.1.0"
+ }
+ },
+ "runtime.native.System.Net.Http": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "ZVuZJqnnegJhd2k/PtAbbIcZ3aZeITq3sj06oKfMBSfphW3HDmk/t4ObvbOk/JA/swGR0LNqMksAh/f7gpTROg==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "Microsoft.NETCore.Targets": "1.1.0"
+ }
+ },
+ "runtime.native.System.Security.Cryptography.Apple": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "DloMk88juo0OuOWr56QG7MNchmafTLYWvABy36izkrLI5VledI0rq28KGs1i9wbpeT9NPQrx/wTf8U2vazqQ3Q==",
+ "dependencies": {
+ "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple": "4.3.0"
+ }
+ },
+ "runtime.native.System.Security.Cryptography.OpenSsl": {
+ "type": "Transitive",
+ "resolved": "4.3.2",
+ "contentHash": "QR1OwtwehHxSeQvZKXe+iSd+d3XZNkEcuWMFYa2i0aG1l+lR739HPicKMlTbJst3spmeekDVBUS7SeS26s4U/g==",
+ "dependencies": {
+ "runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2",
+ "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2",
+ "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2",
+ "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2",
+ "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2",
+ "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2",
+ "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2",
+ "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2",
+ "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2",
+ "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2"
+ }
+ },
+ "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl": {
+ "type": "Transitive",
+ "resolved": "4.3.2",
+ "contentHash": "I+GNKGg2xCHueRd1m9PzeEW7WLbNNLznmTuEi8/vZX71HudUbx1UTwlGkiwMri7JLl8hGaIAWnA/GONhu+LOyQ=="
+ },
+ "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl": {
+ "type": "Transitive",
+ "resolved": "4.3.2",
+ "contentHash": "1Z3TAq1ytS1IBRtPXJvEUZdVsfWfeNEhBkbiOCGEl9wwAfsjP2lz3ZFDx5tq8p60/EqbS0HItG5piHuB71RjoA=="
+ },
+ "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "kVXCuMTrTlxq4XOOMAysuNwsXWpYeboGddNGpIgNSZmv1b6r/s/DPk0fYMB7Q5Qo4bY68o48jt4T4y5BVecbCQ=="
+ },
+ "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": {
+ "type": "Transitive",
+ "resolved": "4.3.2",
+ "contentHash": "6mU/cVmmHtQiDXhnzUImxIcDL48GbTk+TsptXyJA+MIOG9LRjPoAQC/qBFB7X+UNyK86bmvGwC8t+M66wsYC8w=="
+ },
+ "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl": {
+ "type": "Transitive",
+ "resolved": "4.3.2",
+ "contentHash": "vjwG0GGcTW/PPg6KVud8F9GLWYuAV1rrw1BKAqY0oh4jcUqg15oYF1+qkGR2x2ZHM4DQnWKQ7cJgYbfncz/lYg=="
+ },
+ "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": {
+ "type": "Transitive",
+ "resolved": "4.3.2",
+ "contentHash": "7KMFpTkHC/zoExs+PwP8jDCWcrK9H6L7soowT80CUx3e+nxP/AFnq0AQAW5W76z2WYbLAYCRyPfwYFG6zkvQRw=="
+ },
+ "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": {
+ "type": "Transitive",
+ "resolved": "4.3.2",
+ "contentHash": "xrlmRCnKZJLHxyyLIqkZjNXqgxnKdZxfItrPkjI+6pkRo5lHX8YvSZlWrSI5AVwLMi4HbNWP7064hcAWeZKp5w=="
+ },
+ "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": {
+ "type": "Transitive",
+ "resolved": "4.3.2",
+ "contentHash": "leXiwfiIkW7Gmn7cgnNcdtNAU70SjmKW3jxGj1iKHOvdn0zRWsgv/l2OJUO5zdGdiv2VRFnAsxxhDgMzofPdWg=="
+ },
+ "SemanticVersioning": {
+ "type": "Transitive",
+ "resolved": "0.8.0",
+ "contentHash": "hUCnQL79hU0W6X4jPeMAtGDwoEJeBEZfGBnkT+jPG45lD7KHn4h61HgYN8y1HAjPrXmC5oJcLx3l8ygPJOqvlA==",
+ "dependencies": {
+ "NETStandard.Library": "1.6.0"
+ }
+ },
+ "System.Buffers": {
+ "type": "Transitive",
+ "resolved": "4.5.1",
+ "contentHash": "Rw7ijyl1qqRS0YQD/WycNst8hUUMgrMH4FCn1nNm27M4VxchZ1js3fVjQaANHO5f3sN4isvP4a+Met9Y4YomAg=="
+ },
+ "System.Collections": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "3Dcj85/TBdVpL5Zr+gEEBUuFe2icOnLalmEh9hfck1PTYbbyWuZgh4fmm2ysCLTrqLQw6t3TgTyJ+VLp+Qb+Lw==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "Microsoft.NETCore.Targets": "1.1.0",
+ "System.Runtime": "4.3.0"
+ }
+ },
+ "System.Collections.Concurrent": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "ztl69Xp0Y/UXCL+3v3tEU+lIy+bvjKNUmopn1wep/a291pVPK7dxBd6T7WnlQqRog+d1a/hSsgRsmFnIBKTPLQ==",
+ "dependencies": {
+ "System.Collections": "4.3.0",
+ "System.Diagnostics.Debug": "4.3.0",
+ "System.Diagnostics.Tracing": "4.3.0",
+ "System.Globalization": "4.3.0",
+ "System.Reflection": "4.3.0",
+ "System.Resources.ResourceManager": "4.3.0",
+ "System.Runtime": "4.3.0",
+ "System.Runtime.Extensions": "4.3.0",
+ "System.Threading": "4.3.0",
+ "System.Threading.Tasks": "4.3.0"
+ }
+ },
+ "System.Diagnostics.Debug": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "ZUhUOdqmaG5Jk3Xdb8xi5kIyQYAA4PnTNlHx1mu9ZY3qv4ELIdKbnL/akbGaKi2RnNUWaZsAs31rvzFdewTj2g==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "Microsoft.NETCore.Targets": "1.1.0",
+ "System.Runtime": "4.3.0"
+ }
+ },
+ "System.Diagnostics.DiagnosticSource": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "tD6kosZnTAGdrEa0tZSuFyunMbt/5KYDnHdndJYGqZoNy00XVXyACd5d6KnE1YgYv3ne2CjtAfNXo/fwEhnKUA==",
+ "dependencies": {
+ "System.Collections": "4.3.0",
+ "System.Diagnostics.Tracing": "4.3.0",
+ "System.Reflection": "4.3.0",
+ "System.Runtime": "4.3.0",
+ "System.Threading": "4.3.0"
+ }
+ },
+ "System.Diagnostics.Process": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "J0wOX07+QASQblsfxmIMFc9Iq7KTXYL3zs2G/Xc704Ylv3NpuVdo6gij6V3PGiptTxqsK0K7CdXenRvKUnkA2g==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "Microsoft.Win32.Primitives": "4.3.0",
+ "Microsoft.Win32.Registry": "4.3.0",
+ "System.Collections": "4.3.0",
+ "System.Diagnostics.Debug": "4.3.0",
+ "System.Globalization": "4.3.0",
+ "System.IO": "4.3.0",
+ "System.IO.FileSystem": "4.3.0",
+ "System.IO.FileSystem.Primitives": "4.3.0",
+ "System.Resources.ResourceManager": "4.3.0",
+ "System.Runtime": "4.3.0",
+ "System.Runtime.Extensions": "4.3.0",
+ "System.Runtime.Handles": "4.3.0",
+ "System.Runtime.InteropServices": "4.3.0",
+ "System.Text.Encoding": "4.3.0",
+ "System.Text.Encoding.Extensions": "4.3.0",
+ "System.Threading": "4.3.0",
+ "System.Threading.Tasks": "4.3.0",
+ "System.Threading.Thread": "4.3.0",
+ "System.Threading.ThreadPool": "4.3.0",
+ "runtime.native.System": "4.3.0"
+ }
+ },
+ "System.Diagnostics.Tracing": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "rswfv0f/Cqkh78rA5S8eN8Neocz234+emGCtTF3lxPY96F+mmmUen6tbn0glN6PMvlKQb9bPAY5e9u7fgPTkKw==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "Microsoft.NETCore.Targets": "1.1.0",
+ "System.Runtime": "4.3.0"
+ }
+ },
+ "System.Globalization": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "kYdVd2f2PAdFGblzFswE4hkNANJBKRmsfa2X5LG2AcWE1c7/4t0pYae1L8vfZ5xvE2nK/R9JprtToA61OSHWIg==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "Microsoft.NETCore.Targets": "1.1.0",
+ "System.Runtime": "4.3.0"
+ }
+ },
+ "System.Globalization.Calendars": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "GUlBtdOWT4LTV3I+9/PJW+56AnnChTaOqqTLFtdmype/L500M2LIyXgmtd9X2P2VOkmJd5c67H5SaC2QcL1bFA==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "Microsoft.NETCore.Targets": "1.1.0",
+ "System.Globalization": "4.3.0",
+ "System.Runtime": "4.3.0"
+ }
+ },
+ "System.Globalization.Extensions": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "FhKmdR6MPG+pxow6wGtNAWdZh7noIOpdD5TwQ3CprzgIE1bBBoim0vbR1+AWsWjQmU7zXHgQo4TWSP6lCeiWcQ==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "System.Globalization": "4.3.0",
+ "System.Resources.ResourceManager": "4.3.0",
+ "System.Runtime": "4.3.0",
+ "System.Runtime.Extensions": "4.3.0",
+ "System.Runtime.InteropServices": "4.3.0"
+ }
+ },
+ "System.IO": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "3qjaHvxQPDpSOYICjUoTsmoq5u6QJAFRUITgeT/4gqkF1bajbSmb1kwSxEA8AHlofqgcKJcM8udgieRNhaJ5Cg==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "Microsoft.NETCore.Targets": "1.1.0",
+ "System.Runtime": "4.3.0",
+ "System.Text.Encoding": "4.3.0",
+ "System.Threading.Tasks": "4.3.0"
+ }
+ },
+ "System.IO.FileSystem": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "3wEMARTnuio+ulnvi+hkRNROYwa1kylvYahhcLk4HSoVdl+xxTFVeVlYOfLwrDPImGls0mDqbMhrza8qnWPTdA==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "Microsoft.NETCore.Targets": "1.1.0",
+ "System.IO": "4.3.0",
+ "System.IO.FileSystem.Primitives": "4.3.0",
+ "System.Runtime": "4.3.0",
+ "System.Runtime.Handles": "4.3.0",
+ "System.Text.Encoding": "4.3.0",
+ "System.Threading.Tasks": "4.3.0"
+ }
+ },
+ "System.IO.FileSystem.Primitives": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "6QOb2XFLch7bEc4lIcJH49nJN2HV+OC3fHDgsLVsBVBk3Y4hFAnOBGzJ2lUu7CyDDFo9IBWkSsnbkT6IBwwiMw==",
+ "dependencies": {
+ "System.Runtime": "4.3.0"
+ }
+ },
+ "System.Linq": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "5DbqIUpsDp0dFftytzuMmc0oeMdQwjcP/EWxsksIz/w1TcFRkZ3yKKz0PqiYFMmEwPSWw+qNVqD7PJ889JzHbw==",
+ "dependencies": {
+ "System.Collections": "4.3.0",
+ "System.Diagnostics.Debug": "4.3.0",
+ "System.Resources.ResourceManager": "4.3.0",
+ "System.Runtime": "4.3.0",
+ "System.Runtime.Extensions": "4.3.0"
+ }
+ },
+ "System.Memory": {
+ "type": "Transitive",
+ "resolved": "4.5.4",
+ "contentHash": "1MbJTHS1lZ4bS4FmsJjnuGJOu88ZzTT2rLvrhW7Ygic+pC0NWA+3hgAen0HRdsocuQXCkUTdFn9yHJJhsijDXw==",
+ "dependencies": {
+ "System.Buffers": "4.5.1",
+ "System.Numerics.Vectors": "4.4.0",
+ "System.Runtime.CompilerServices.Unsafe": "4.5.3"
+ }
+ },
+ "System.Net.Http": {
+ "type": "Transitive",
+ "resolved": "4.3.4",
+ "contentHash": "aOa2d51SEbmM+H+Csw7yJOuNZoHkrP2XnAurye5HWYgGVVU54YZDvsLUYRv6h18X3sPnjNCANmN7ZhIPiqMcjA==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.1",
+ "System.Collections": "4.3.0",
+ "System.Diagnostics.Debug": "4.3.0",
+ "System.Diagnostics.DiagnosticSource": "4.3.0",
+ "System.Diagnostics.Tracing": "4.3.0",
+ "System.Globalization": "4.3.0",
+ "System.Globalization.Extensions": "4.3.0",
+ "System.IO": "4.3.0",
+ "System.IO.FileSystem": "4.3.0",
+ "System.Net.Primitives": "4.3.0",
+ "System.Resources.ResourceManager": "4.3.0",
+ "System.Runtime": "4.3.0",
+ "System.Runtime.Extensions": "4.3.0",
+ "System.Runtime.Handles": "4.3.0",
+ "System.Runtime.InteropServices": "4.3.0",
+ "System.Security.Cryptography.Algorithms": "4.3.0",
+ "System.Security.Cryptography.Encoding": "4.3.0",
+ "System.Security.Cryptography.OpenSsl": "4.3.0",
+ "System.Security.Cryptography.Primitives": "4.3.0",
+ "System.Security.Cryptography.X509Certificates": "4.3.0",
+ "System.Text.Encoding": "4.3.0",
+ "System.Threading": "4.3.0",
+ "System.Threading.Tasks": "4.3.0",
+ "runtime.native.System": "4.3.0",
+ "runtime.native.System.Net.Http": "4.3.0",
+ "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2"
+ }
+ },
+ "System.Net.Primitives": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "qOu+hDwFwoZPbzPvwut2qATe3ygjeQBDQj91xlsaqGFQUI5i4ZnZb8yyQuLGpDGivEPIt8EJkd1BVzVoP31FXA==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "Microsoft.NETCore.Targets": "1.1.0",
+ "System.Runtime": "4.3.0",
+ "System.Runtime.Handles": "4.3.0"
+ }
+ },
+ "System.Numerics.Vectors": {
+ "type": "Transitive",
+ "resolved": "4.5.0",
+ "contentHash": "QQTlPTl06J/iiDbJCiepZ4H//BVraReU4O4EoRw1U02H5TLUIT7xn3GnDp9AXPSlJUDyFs4uWjWafNX6WrAojQ=="
+ },
+ "System.Reflection": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "KMiAFoW7MfJGa9nDFNcfu+FpEdiHpWgTcS2HdMpDvt9saK3y/G4GwprPyzqjFH9NTaGPQeWNHU+iDlDILj96aQ==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "Microsoft.NETCore.Targets": "1.1.0",
+ "System.IO": "4.3.0",
+ "System.Reflection.Primitives": "4.3.0",
+ "System.Runtime": "4.3.0"
+ }
+ },
+ "System.Reflection.Extensions": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "rJkrJD3kBI5B712aRu4DpSIiHRtr6QlfZSQsb0hYHrDCZORXCFjQfoipo2LaMUHoT9i1B7j7MnfaEKWDFmFQNQ==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "Microsoft.NETCore.Targets": "1.1.0",
+ "System.Reflection": "4.3.0",
+ "System.Runtime": "4.3.0"
+ }
+ },
+ "System.Reflection.Primitives": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "5RXItQz5As4xN2/YUDxdpsEkMhvw3e6aNveFXUn4Hl/udNTCNhnKp8lT9fnc3MhvGKh1baak5CovpuQUXHAlIA==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "Microsoft.NETCore.Targets": "1.1.0",
+ "System.Runtime": "4.3.0"
+ }
+ },
+ "System.Resources.ResourceManager": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "/zrcPkkWdZmI4F92gL/TPumP98AVDu/Wxr3CSJGQQ+XN6wbRZcyfSKVoPo17ilb3iOr0cCRqJInGwNMolqhS8A==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "Microsoft.NETCore.Targets": "1.1.0",
+ "System.Globalization": "4.3.0",
+ "System.Reflection": "4.3.0",
+ "System.Runtime": "4.3.0"
+ }
+ },
+ "System.Runtime": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "JufQi0vPQ0xGnAczR13AUFglDyVYt4Kqnz1AZaiKZ5+GICq0/1MH/mO/eAJHt/mHW1zjKBJd7kV26SrxddAhiw==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "Microsoft.NETCore.Targets": "1.1.0"
+ }
+ },
+ "System.Runtime.CompilerServices.Unsafe": {
+ "type": "Transitive",
+ "resolved": "6.0.0",
+ "contentHash": "/iUeP3tq1S0XdNNoMz5C9twLSrM/TH+qElHkXWaPvuNOt+99G75NrV0OS2EqHx5wMN7popYjpc8oTjC1y16DLg=="
+ },
+ "System.Runtime.Extensions": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "guW0uK0fn5fcJJ1tJVXYd7/1h5F+pea1r7FLSOz/f8vPEqbR2ZAknuRDvTQ8PzAilDveOxNjSfr0CHfIQfFk8g==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "Microsoft.NETCore.Targets": "1.1.0",
+ "System.Runtime": "4.3.0"
+ }
+ },
+ "System.Runtime.Handles": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "OKiSUN7DmTWeYb3l51A7EYaeNMnvxwE249YtZz7yooT4gOZhmTjIn48KgSsw2k2lYdLgTKNJw/ZIfSElwDRVgg==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "Microsoft.NETCore.Targets": "1.1.0",
+ "System.Runtime": "4.3.0"
+ }
+ },
+ "System.Runtime.InteropServices": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "uv1ynXqiMK8mp1GM3jDqPCFN66eJ5w5XNomaK2XD+TuCroNTLFGeZ+WCmBMcBDyTFKou3P6cR6J/QsaqDp7fGQ==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "Microsoft.NETCore.Targets": "1.1.0",
+ "System.Reflection": "4.3.0",
+ "System.Reflection.Primitives": "4.3.0",
+ "System.Runtime": "4.3.0",
+ "System.Runtime.Handles": "4.3.0"
+ }
+ },
+ "System.Runtime.InteropServices.RuntimeInformation": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "cbz4YJMqRDR7oLeMRbdYv7mYzc++17lNhScCX0goO2XpGWdvAt60CGN+FHdePUEHCe/Jy9jUlvNAiNdM+7jsOw==",
+ "dependencies": {
+ "System.Reflection": "4.3.0",
+ "System.Reflection.Extensions": "4.3.0",
+ "System.Resources.ResourceManager": "4.3.0",
+ "System.Runtime": "4.3.0",
+ "System.Runtime.InteropServices": "4.3.0",
+ "System.Threading": "4.3.0",
+ "runtime.native.System": "4.3.0"
+ }
+ },
+ "System.Runtime.Numerics": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "yMH+MfdzHjy17l2KESnPiF2dwq7T+xLnSJar7slyimAkUh/gTrS9/UQOtv7xarskJ2/XDSNvfLGOBQPjL7PaHQ==",
+ "dependencies": {
+ "System.Globalization": "4.3.0",
+ "System.Resources.ResourceManager": "4.3.0",
+ "System.Runtime": "4.3.0",
+ "System.Runtime.Extensions": "4.3.0"
+ }
+ },
+ "System.Security.Cryptography.Algorithms": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "W1kd2Y8mYSCgc3ULTAZ0hOP2dSdG5YauTb1089T0/kRcN2MpSAW1izOFROrJgxSlMn3ArsgHXagigyi+ibhevg==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "System.Collections": "4.3.0",
+ "System.IO": "4.3.0",
+ "System.Resources.ResourceManager": "4.3.0",
+ "System.Runtime": "4.3.0",
+ "System.Runtime.Extensions": "4.3.0",
+ "System.Runtime.Handles": "4.3.0",
+ "System.Runtime.InteropServices": "4.3.0",
+ "System.Runtime.Numerics": "4.3.0",
+ "System.Security.Cryptography.Encoding": "4.3.0",
+ "System.Security.Cryptography.Primitives": "4.3.0",
+ "System.Text.Encoding": "4.3.0",
+ "runtime.native.System.Security.Cryptography.Apple": "4.3.0",
+ "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0"
+ }
+ },
+ "System.Security.Cryptography.Cng": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "03idZOqFlsKRL4W+LuCpJ6dBYDUWReug6lZjBa3uJWnk5sPCUXckocevTaUA8iT/MFSrY/2HXkOt753xQ/cf8g==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "System.IO": "4.3.0",
+ "System.Resources.ResourceManager": "4.3.0",
+ "System.Runtime": "4.3.0",
+ "System.Runtime.Extensions": "4.3.0",
+ "System.Runtime.Handles": "4.3.0",
+ "System.Runtime.InteropServices": "4.3.0",
+ "System.Security.Cryptography.Algorithms": "4.3.0",
+ "System.Security.Cryptography.Encoding": "4.3.0",
+ "System.Security.Cryptography.Primitives": "4.3.0",
+ "System.Text.Encoding": "4.3.0"
+ }
+ },
+ "System.Security.Cryptography.Csp": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "X4s/FCkEUnRGnwR3aSfVIkldBmtURMhmexALNTwpjklzxWU7yjMk7GHLKOZTNkgnWnE0q7+BCf9N2LVRWxewaA==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "System.IO": "4.3.0",
+ "System.Reflection": "4.3.0",
+ "System.Resources.ResourceManager": "4.3.0",
+ "System.Runtime": "4.3.0",
+ "System.Runtime.Extensions": "4.3.0",
+ "System.Runtime.Handles": "4.3.0",
+ "System.Runtime.InteropServices": "4.3.0",
+ "System.Security.Cryptography.Algorithms": "4.3.0",
+ "System.Security.Cryptography.Encoding": "4.3.0",
+ "System.Security.Cryptography.Primitives": "4.3.0",
+ "System.Text.Encoding": "4.3.0",
+ "System.Threading": "4.3.0"
+ }
+ },
+ "System.Security.Cryptography.Encoding": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "1DEWjZZly9ae9C79vFwqaO5kaOlI5q+3/55ohmq/7dpDyDfc8lYe7YVxJUZ5MF/NtbkRjwFRo14yM4OEo9EmDw==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "System.Collections": "4.3.0",
+ "System.Collections.Concurrent": "4.3.0",
+ "System.Linq": "4.3.0",
+ "System.Resources.ResourceManager": "4.3.0",
+ "System.Runtime": "4.3.0",
+ "System.Runtime.Extensions": "4.3.0",
+ "System.Runtime.Handles": "4.3.0",
+ "System.Runtime.InteropServices": "4.3.0",
+ "System.Security.Cryptography.Primitives": "4.3.0",
+ "System.Text.Encoding": "4.3.0",
+ "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0"
+ }
+ },
+ "System.Security.Cryptography.OpenSsl": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "h4CEgOgv5PKVF/HwaHzJRiVboL2THYCou97zpmhjghx5frc7fIvlkY1jL+lnIQyChrJDMNEXS6r7byGif8Cy4w==",
+ "dependencies": {
+ "System.Collections": "4.3.0",
+ "System.IO": "4.3.0",
+ "System.Resources.ResourceManager": "4.3.0",
+ "System.Runtime": "4.3.0",
+ "System.Runtime.Extensions": "4.3.0",
+ "System.Runtime.Handles": "4.3.0",
+ "System.Runtime.InteropServices": "4.3.0",
+ "System.Runtime.Numerics": "4.3.0",
+ "System.Security.Cryptography.Algorithms": "4.3.0",
+ "System.Security.Cryptography.Encoding": "4.3.0",
+ "System.Security.Cryptography.Primitives": "4.3.0",
+ "System.Text.Encoding": "4.3.0",
+ "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0"
+ }
+ },
+ "System.Security.Cryptography.Primitives": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "7bDIyVFNL/xKeFHjhobUAQqSpJq9YTOpbEs6mR233Et01STBMXNAc/V+BM6dwYGc95gVh/Zf+iVXWzj3mE8DWg==",
+ "dependencies": {
+ "System.Diagnostics.Debug": "4.3.0",
+ "System.Globalization": "4.3.0",
+ "System.IO": "4.3.0",
+ "System.Resources.ResourceManager": "4.3.0",
+ "System.Runtime": "4.3.0",
+ "System.Threading": "4.3.0",
+ "System.Threading.Tasks": "4.3.0"
+ }
+ },
+ "System.Security.Cryptography.X509Certificates": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "t2Tmu6Y2NtJ2um0RtcuhP7ZdNNxXEgUm2JeoA/0NvlMjAhKCnM1NX07TDl3244mVp3QU6LPEhT3HTtH1uF7IYw==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "System.Collections": "4.3.0",
+ "System.Diagnostics.Debug": "4.3.0",
+ "System.Globalization": "4.3.0",
+ "System.Globalization.Calendars": "4.3.0",
+ "System.IO": "4.3.0",
+ "System.IO.FileSystem": "4.3.0",
+ "System.IO.FileSystem.Primitives": "4.3.0",
+ "System.Resources.ResourceManager": "4.3.0",
+ "System.Runtime": "4.3.0",
+ "System.Runtime.Extensions": "4.3.0",
+ "System.Runtime.Handles": "4.3.0",
+ "System.Runtime.InteropServices": "4.3.0",
+ "System.Runtime.Numerics": "4.3.0",
+ "System.Security.Cryptography.Algorithms": "4.3.0",
+ "System.Security.Cryptography.Cng": "4.3.0",
+ "System.Security.Cryptography.Csp": "4.3.0",
+ "System.Security.Cryptography.Encoding": "4.3.0",
+ "System.Security.Cryptography.OpenSsl": "4.3.0",
+ "System.Security.Cryptography.Primitives": "4.3.0",
+ "System.Text.Encoding": "4.3.0",
+ "System.Threading": "4.3.0",
+ "runtime.native.System": "4.3.0",
+ "runtime.native.System.Net.Http": "4.3.0",
+ "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0"
+ }
+ },
+ "System.Text.Encoding": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "BiIg+KWaSDOITze6jGQynxg64naAPtqGHBwDrLaCtixsa5bKiR8dpPOHA7ge3C0JJQizJE+sfkz1wV+BAKAYZw==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "Microsoft.NETCore.Targets": "1.1.0",
+ "System.Runtime": "4.3.0"
+ }
+ },
+ "System.Text.Encoding.Extensions": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "YVMK0Bt/A43RmwizJoZ22ei2nmrhobgeiYwFzC4YAN+nue8RF6djXDMog0UCn+brerQoYVyaS+ghy9P/MUVcmw==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "Microsoft.NETCore.Targets": "1.1.0",
+ "System.Runtime": "4.3.0",
+ "System.Text.Encoding": "4.3.0"
+ }
+ },
+ "System.Text.Encodings.Web": {
+ "type": "Transitive",
+ "resolved": "6.0.0",
+ "contentHash": "Vg8eB5Tawm1IFqj4TVK1czJX89rhFxJo9ELqc/Eiq0eXy13RK00eubyU6TJE6y+GQXjyV5gSfiewDUZjQgSE0w==",
+ "dependencies": {
+ "System.Buffers": "4.5.1",
+ "System.Memory": "4.5.4",
+ "System.Runtime.CompilerServices.Unsafe": "6.0.0"
+ }
+ },
+ "System.Text.Json": {
+ "type": "Transitive",
+ "resolved": "6.0.5",
+ "contentHash": "SSH+YYrMpvLcy7Orzb5K1tSyffnFacWahyxCCjYH1PbSHdAF4dekmIetBurFKgtTHDmwEe/J2Csi/7niRH6d/g==",
+ "dependencies": {
+ "Microsoft.Bcl.AsyncInterfaces": "6.0.0",
+ "System.Buffers": "4.5.1",
+ "System.Memory": "4.5.4",
+ "System.Numerics.Vectors": "4.5.0",
+ "System.Runtime.CompilerServices.Unsafe": "6.0.0",
+ "System.Text.Encodings.Web": "6.0.0",
+ "System.Threading.Tasks.Extensions": "4.5.4"
+ }
+ },
+ "System.Threading": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "VkUS0kOBcUf3Wwm0TSbrevDDZ6BlM+b/HRiapRFWjM5O0NS0LviG0glKmFK+hhPDd1XFeSdU1GmlLhb2CoVpIw==",
+ "dependencies": {
+ "System.Runtime": "4.3.0",
+ "System.Threading.Tasks": "4.3.0"
+ }
+ },
+ "System.Threading.Tasks": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "LbSxKEdOUhVe8BezB/9uOGGppt+nZf6e1VFyw6v3DN6lqitm0OSn2uXMOdtP0M3W4iMcqcivm2J6UgqiwwnXiA==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "Microsoft.NETCore.Targets": "1.1.0",
+ "System.Runtime": "4.3.0"
+ }
+ },
+ "System.Threading.Tasks.Extensions": {
+ "type": "Transitive",
+ "resolved": "4.5.4",
+ "contentHash": "zteT+G8xuGu6mS+mzDzYXbzS7rd3K6Fjb9RiZlYlJPam2/hU7JCBZBVEcywNuR+oZ1ncTvc/cq0faRr3P01OVg==",
+ "dependencies": {
+ "System.Runtime.CompilerServices.Unsafe": "4.5.3"
+ }
+ },
+ "System.Threading.Thread": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "OHmbT+Zz065NKII/ZHcH9XO1dEuLGI1L2k7uYss+9C1jLxTC9kTZZuzUOyXHayRk+dft9CiDf3I/QZ0t8JKyBQ==",
+ "dependencies": {
+ "System.Runtime": "4.3.0"
+ }
+ },
+ "System.Threading.ThreadPool": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "k/+g4b7vjdd4aix83sTgC9VG6oXYKAktSfNIJUNGxPEj7ryEOfzHHhfnmsZvjxawwcD9HyWXKCXmPjX8U4zeSw==",
+ "dependencies": {
+ "System.Runtime": "4.3.0",
+ "System.Runtime.Handles": "4.3.0"
+ }
+ },
+ "opensearch.opensearch.managed": {
+ "type": "Project",
+ "dependencies": {
+ "OpenSearch.Stack.ArtifactsApi": "1.0.0",
+ "Proc": "0.6.1",
+ "System.Net.Http": "4.3.4"
+ }
+ },
+ "opensearch.stack.artifactsapi": {
+ "type": "Project",
+ "dependencies": {
+ "SemanticVersioning": "0.8.0",
+ "System.Net.Http": "4.3.4",
+ "System.Runtime.InteropServices.RuntimeInformation": "4.3.0",
+ "System.Text.Json": "6.0.5"
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/abstractions/src/OpenSearch.OpenSearch.EphemeralTests/EphemeralClusterTests.cs b/abstractions/src/OpenSearch.OpenSearch.EphemeralTests/EphemeralClusterTests.cs
new file mode 100644
index 0000000000..48dc376658
--- /dev/null
+++ b/abstractions/src/OpenSearch.OpenSearch.EphemeralTests/EphemeralClusterTests.cs
@@ -0,0 +1,81 @@
+/* SPDX-License-Identifier: Apache-2.0
+*
+* The OpenSearch Contributors require contributions made to
+* this file be licensed under the Apache-2.0 license or a
+* compatible open source license.
+*/
+/*
+* Modifications Copyright OpenSearch Contributors. See
+* GitHub history for details.
+*
+* Licensed to Elasticsearch B.V. under one or more contributor
+* license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright
+* ownership. Elasticsearch B.V. licenses this file to you under
+* the Apache License, Version 2.0 (the "License"); you may
+* not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+using System.Collections;
+using System.Collections.Generic;
+using OpenSearch.OpenSearch.Ephemeral;
+using OpenSearch.Stack.ArtifactsApi;
+using Xunit;
+
+namespace OpenSearch.OpenSearch.EphemeralTests
+{
+ public class EphemeralClusterTests
+ {
+ [Theory]
+ [ClassData(typeof(SampleClusters))]
+ public void TestEphemeralCluster(OpenSearchVersion version, ServerType serverType, ClusterFeatures features)
+ {
+ var numberOfNodes = 1;
+ var clusterConfiguration =
+ new EphemeralClusterConfiguration(version, serverType, features, null, numberOfNodes)
+ {
+ ShowOpenSearchOutputAfterStarted = true
+ };
+ using var cluster = new EphemeralCluster(clusterConfiguration);
+ var timeout = new System.TimeSpan(0, 5, 30);
+ using (cluster.Start(timeout))
+ {
+ Assert.True(cluster.Started, "OpenSearch cluster started");
+ foreach (var n in cluster.Nodes)
+ {
+ n.SendControlC();
+ Assert.True(n.WaitForCompletion(timeout), $"Failed to stop node {n.ProcessId}");
+ }
+ }
+ }
+
+ private class SampleClusters : IEnumerable
-
+
diff --git a/tests/Tests.Configuration/packages.lock.json b/tests/Tests.Configuration/packages.lock.json
index 0333d54789..b412476b51 100644
--- a/tests/Tests.Configuration/packages.lock.json
+++ b/tests/Tests.Configuration/packages.lock.json
@@ -6,7 +6,10 @@
"type": "Direct",
"requested": "[1.0.0-preview.2, )",
"resolved": "1.0.0-preview.2",
- "contentHash": "m+pJPEO7HyXvrOna5Sr3s77ewXonjYWJTNL6drh8xACnMNxnlqUDKx9HfGeSE9wmfY0lQwppaeZpFTPGaH7kZg=="
+ "contentHash": "m+pJPEO7HyXvrOna5Sr3s77ewXonjYWJTNL6drh8xACnMNxnlqUDKx9HfGeSE9wmfY0lQwppaeZpFTPGaH7kZg==",
+ "dependencies": {
+ "Microsoft.NETFramework.ReferenceAssemblies.net461": "1.0.0-preview.2"
+ }
},
"NETStandard.Library": {
"type": "Direct",
@@ -17,17 +20,6 @@
"Microsoft.NETCore.Platforms": "1.1.0"
}
},
- "OpenSearch.OpenSearch.Managed": {
- "type": "Direct",
- "requested": "[0.1.0-canary.0.277, )",
- "resolved": "0.1.0-canary.0.277",
- "contentHash": "BoLSf2fiCphayR0TQulvm0m0MISy8kCL+JrPv1QGrlR4YujWAeSi0izb+vnYEWT9+a8IviTMjU2TGZwpcKSuBQ==",
- "dependencies": {
- "OpenSearch.Stack.ArtifactsApi": "0.1.0-canary.0.277",
- "Proc": "0.6.1",
- "System.Net.Http": "4.3.4"
- }
- },
"Microsoft.Bcl.AsyncInterfaces": {
"type": "Transitive",
"resolved": "6.0.0",
@@ -46,6 +38,11 @@
"resolved": "1.1.0",
"contentHash": "aOZA3BWfz9RXjpzt0sRJJMjAscAUm3Hoa4UWAfceV9UTYxgwZ1lZt5nO2myFf+/jetYQo4uTP7zS8sJY67BBxg=="
},
+ "Microsoft.NETFramework.ReferenceAssemblies.net461": {
+ "type": "Transitive",
+ "resolved": "1.0.0-preview.2",
+ "contentHash": "59D9ISjzCpfHG41r5x4BNZNNOCmE2o5YX8vcdOwsqfxOA0+6vQnxZrYq8KtthUU2JSvC13g941rSr5GRaNQOJg=="
+ },
"Microsoft.Win32.Primitives": {
"type": "Transitive",
"resolved": "4.3.0",
@@ -71,17 +68,6 @@
"System.Runtime.InteropServices": "4.3.0"
}
},
- "OpenSearch.Stack.ArtifactsApi": {
- "type": "Transitive",
- "resolved": "0.1.0-canary.0.277",
- "contentHash": "S3Mxf2FhxL/WJg9f0LGoGLmpvRyFCH0HitsC3bDAgBweO9aqSNmpVeAm7DvKHMwGpSAglUL0+pOBvo2dCi/iVg==",
- "dependencies": {
- "SemanticVersioning": "0.8.0",
- "System.Net.Http": "4.3.4",
- "System.Runtime.InteropServices.RuntimeInformation": "4.3.0",
- "System.Text.Json": "6.0.5"
- }
- },
"Proc": {
"type": "Transitive",
"resolved": "0.6.1",
@@ -778,6 +764,23 @@
"System.Runtime": "4.3.0",
"System.Runtime.Handles": "4.3.0"
}
+ },
+ "opensearch.opensearch.managed": {
+ "type": "Project",
+ "dependencies": {
+ "OpenSearch.Stack.ArtifactsApi": "1.0.0",
+ "Proc": "0.6.1",
+ "System.Net.Http": "4.3.4"
+ }
+ },
+ "opensearch.stack.artifactsapi": {
+ "type": "Project",
+ "dependencies": {
+ "SemanticVersioning": "0.8.0",
+ "System.Net.Http": "4.3.4",
+ "System.Runtime.InteropServices.RuntimeInformation": "4.3.0",
+ "System.Text.Json": "6.0.5"
+ }
}
}
}
diff --git a/tests/Tests.Core/Tests.Core.csproj b/tests/Tests.Core/Tests.Core.csproj
index aade4c0dba..9b9879e83a 100644
--- a/tests/Tests.Core/Tests.Core.csproj
+++ b/tests/Tests.Core/Tests.Core.csproj
@@ -16,7 +16,7 @@
-
+
diff --git a/tests/Tests.Core/packages.lock.json b/tests/Tests.Core/packages.lock.json
index c0c166e85c..a8b70a72f9 100644
--- a/tests/Tests.Core/packages.lock.json
+++ b/tests/Tests.Core/packages.lock.json
@@ -27,13 +27,19 @@
"type": "Direct",
"requested": "[16.5.0, )",
"resolved": "16.5.0",
- "contentHash": "yHZOhVSPuGqgHi+KhHiAZqNY08avkQraXKvgKgDU8c/ztmGzw7gmukkv49EaTq6T3xmp4XroWk3gAlbJHMxl8w=="
+ "contentHash": "yHZOhVSPuGqgHi+KhHiAZqNY08avkQraXKvgKgDU8c/ztmGzw7gmukkv49EaTq6T3xmp4XroWk3gAlbJHMxl8w==",
+ "dependencies": {
+ "Microsoft.CodeCoverage": "16.5.0"
+ }
},
"Microsoft.NETFramework.ReferenceAssemblies": {
"type": "Direct",
"requested": "[1.0.0-preview.2, )",
"resolved": "1.0.0-preview.2",
- "contentHash": "m+pJPEO7HyXvrOna5Sr3s77ewXonjYWJTNL6drh8xACnMNxnlqUDKx9HfGeSE9wmfY0lQwppaeZpFTPGaH7kZg=="
+ "contentHash": "m+pJPEO7HyXvrOna5Sr3s77ewXonjYWJTNL6drh8xACnMNxnlqUDKx9HfGeSE9wmfY0lQwppaeZpFTPGaH7kZg==",
+ "dependencies": {
+ "Microsoft.NETFramework.ReferenceAssemblies.net461": "1.0.0-preview.2"
+ }
},
"NETStandard.Library": {
"type": "Direct",
@@ -53,16 +59,6 @@
"Microsoft.TestPlatform.ObjectModel": "15.8.0"
}
},
- "OpenSearch.OpenSearch.Xunit": {
- "type": "Direct",
- "requested": "[0.1.0-canary.0.277, )",
- "resolved": "0.1.0-canary.0.277",
- "contentHash": "hNAJp5xM9ounExLOS+CmLCTCwpPfirZ5rOTY0UfR2AU+19wp4HLKerwjmJV4cAJM0ba6JvzrjLQcnMGYazM0og==",
- "dependencies": {
- "OpenSearch.OpenSearch.Ephemeral": "0.1.0-canary.0.277",
- "xunit": "2.4.2"
- }
- },
"Proc": {
"type": "Direct",
"requested": "[0.6.1, )",
@@ -97,6 +93,11 @@
"System.Threading.Tasks.Extensions": "4.5.4"
}
},
+ "Microsoft.CodeCoverage": {
+ "type": "Transitive",
+ "resolved": "16.5.0",
+ "contentHash": "PM5YLtyN45EyUGePJpaNogndlaQPrMgQQXHKMhMESC6KfSVvt+j7+dxBi8NYC6X6dZVysf7ngwhSW3wwvPJRSQ=="
+ },
"Microsoft.CSharp": {
"type": "Transitive",
"resolved": "4.6.0",
@@ -112,6 +113,11 @@
"resolved": "1.1.0",
"contentHash": "aOZA3BWfz9RXjpzt0sRJJMjAscAUm3Hoa4UWAfceV9UTYxgwZ1lZt5nO2myFf+/jetYQo4uTP7zS8sJY67BBxg=="
},
+ "Microsoft.NETFramework.ReferenceAssemblies.net461": {
+ "type": "Transitive",
+ "resolved": "1.0.0-preview.2",
+ "contentHash": "59D9ISjzCpfHG41r5x4BNZNNOCmE2o5YX8vcdOwsqfxOA0+6vQnxZrYq8KtthUU2JSvC13g941rSr5GRaNQOJg=="
+ },
"Microsoft.TestPlatform.ObjectModel": {
"type": "Transitive",
"resolved": "15.8.0",
@@ -163,36 +169,6 @@
"resolved": "13.0.1",
"contentHash": "ppPFpBcvxdsfUonNcvITKqLl3bqxWbDCZIzDWHzjpdAHRFfZe0Dw9HmA0+za13IdyrgJwpkDTDA9fHaxOrt20A=="
},
- "OpenSearch.OpenSearch.Ephemeral": {
- "type": "Transitive",
- "resolved": "0.1.0-canary.0.277",
- "contentHash": "LAAfOtWvcjoCxUq47BGbwfFst12nsvd3FYDRR9OUfSp69BzevNp3bhAd5O2sdaspBg9MkuOD5Mhp8TvWRHCG7g==",
- "dependencies": {
- "OpenSearch.OpenSearch.Managed": "0.1.0-canary.0.277",
- "SharpZipLib.NETStandard": "1.0.7"
- }
- },
- "OpenSearch.OpenSearch.Managed": {
- "type": "Transitive",
- "resolved": "0.1.0-canary.0.277",
- "contentHash": "BoLSf2fiCphayR0TQulvm0m0MISy8kCL+JrPv1QGrlR4YujWAeSi0izb+vnYEWT9+a8IviTMjU2TGZwpcKSuBQ==",
- "dependencies": {
- "OpenSearch.Stack.ArtifactsApi": "0.1.0-canary.0.277",
- "Proc": "0.6.1",
- "System.Net.Http": "4.3.4"
- }
- },
- "OpenSearch.Stack.ArtifactsApi": {
- "type": "Transitive",
- "resolved": "0.1.0-canary.0.277",
- "contentHash": "S3Mxf2FhxL/WJg9f0LGoGLmpvRyFCH0HitsC3bDAgBweO9aqSNmpVeAm7DvKHMwGpSAglUL0+pOBvo2dCi/iVg==",
- "dependencies": {
- "SemanticVersioning": "0.8.0",
- "System.Net.Http": "4.3.4",
- "System.Runtime.InteropServices.RuntimeInformation": "4.3.0",
- "System.Text.Json": "6.0.5"
- }
- },
"runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": {
"type": "Transitive",
"resolved": "4.3.2",
@@ -1322,10 +1298,41 @@
"System.Reflection.Emit.Lightweight": "4.3.0"
}
},
+ "opensearch.opensearch.ephemeral": {
+ "type": "Project",
+ "dependencies": {
+ "OpenSearch.OpenSearch.Managed": "1.0.0",
+ "SharpZipLib.NETStandard": "1.0.7"
+ }
+ },
+ "opensearch.opensearch.managed": {
+ "type": "Project",
+ "dependencies": {
+ "OpenSearch.Stack.ArtifactsApi": "1.0.0",
+ "Proc": "0.6.1",
+ "System.Net.Http": "4.3.4"
+ }
+ },
+ "opensearch.opensearch.xunit": {
+ "type": "Project",
+ "dependencies": {
+ "OpenSearch.OpenSearch.Ephemeral": "1.0.0",
+ "xunit": "2.4.2"
+ }
+ },
+ "opensearch.stack.artifactsapi": {
+ "type": "Project",
+ "dependencies": {
+ "SemanticVersioning": "0.8.0",
+ "System.Net.Http": "4.3.4",
+ "System.Runtime.InteropServices.RuntimeInformation": "4.3.0",
+ "System.Text.Json": "6.0.5"
+ }
+ },
"tests.configuration": {
"type": "Project",
"dependencies": {
- "OpenSearch.OpenSearch.Managed": "0.1.0-canary.0.277"
+ "OpenSearch.OpenSearch.Managed": "1.0.0"
}
},
"tests.domain": {
@@ -1334,7 +1341,7 @@
"Bogus": "22.1.2",
"Newtonsoft.Json": "13.0.1",
"OpenSearch.Client": "1.0.0",
- "OpenSearch.OpenSearch.Managed": "0.1.0-canary.0.277",
+ "OpenSearch.OpenSearch.Managed": "1.0.0",
"Tests.Configuration": "1.0.0"
}
}
diff --git a/tests/Tests.Domain/Tests.Domain.csproj b/tests/Tests.Domain/Tests.Domain.csproj
index cd224dd1d4..9cce889493 100644
--- a/tests/Tests.Domain/Tests.Domain.csproj
+++ b/tests/Tests.Domain/Tests.Domain.csproj
@@ -11,7 +11,7 @@
-
+
diff --git a/tests/Tests.Domain/packages.lock.json b/tests/Tests.Domain/packages.lock.json
index 11c530080b..21352e24a3 100644
--- a/tests/Tests.Domain/packages.lock.json
+++ b/tests/Tests.Domain/packages.lock.json
@@ -12,7 +12,10 @@
"type": "Direct",
"requested": "[1.0.0-preview.2, )",
"resolved": "1.0.0-preview.2",
- "contentHash": "m+pJPEO7HyXvrOna5Sr3s77ewXonjYWJTNL6drh8xACnMNxnlqUDKx9HfGeSE9wmfY0lQwppaeZpFTPGaH7kZg=="
+ "contentHash": "m+pJPEO7HyXvrOna5Sr3s77ewXonjYWJTNL6drh8xACnMNxnlqUDKx9HfGeSE9wmfY0lQwppaeZpFTPGaH7kZg==",
+ "dependencies": {
+ "Microsoft.NETFramework.ReferenceAssemblies.net461": "1.0.0-preview.2"
+ }
},
"NETStandard.Library": {
"type": "Direct",
@@ -29,17 +32,6 @@
"resolved": "13.0.1",
"contentHash": "ppPFpBcvxdsfUonNcvITKqLl3bqxWbDCZIzDWHzjpdAHRFfZe0Dw9HmA0+za13IdyrgJwpkDTDA9fHaxOrt20A=="
},
- "OpenSearch.OpenSearch.Managed": {
- "type": "Direct",
- "requested": "[0.1.0-canary.0.277, )",
- "resolved": "0.1.0-canary.0.277",
- "contentHash": "BoLSf2fiCphayR0TQulvm0m0MISy8kCL+JrPv1QGrlR4YujWAeSi0izb+vnYEWT9+a8IviTMjU2TGZwpcKSuBQ==",
- "dependencies": {
- "OpenSearch.Stack.ArtifactsApi": "0.1.0-canary.0.277",
- "Proc": "0.6.1",
- "System.Net.Http": "4.3.4"
- }
- },
"Microsoft.Bcl.AsyncInterfaces": {
"type": "Transitive",
"resolved": "6.0.0",
@@ -63,6 +55,11 @@
"resolved": "1.1.0",
"contentHash": "aOZA3BWfz9RXjpzt0sRJJMjAscAUm3Hoa4UWAfceV9UTYxgwZ1lZt5nO2myFf+/jetYQo4uTP7zS8sJY67BBxg=="
},
+ "Microsoft.NETFramework.ReferenceAssemblies.net461": {
+ "type": "Transitive",
+ "resolved": "1.0.0-preview.2",
+ "contentHash": "59D9ISjzCpfHG41r5x4BNZNNOCmE2o5YX8vcdOwsqfxOA0+6vQnxZrYq8KtthUU2JSvC13g941rSr5GRaNQOJg=="
+ },
"Microsoft.Win32.Primitives": {
"type": "Transitive",
"resolved": "4.3.0",
@@ -88,17 +85,6 @@
"System.Runtime.InteropServices": "4.3.0"
}
},
- "OpenSearch.Stack.ArtifactsApi": {
- "type": "Transitive",
- "resolved": "0.1.0-canary.0.277",
- "contentHash": "S3Mxf2FhxL/WJg9f0LGoGLmpvRyFCH0HitsC3bDAgBweO9aqSNmpVeAm7DvKHMwGpSAglUL0+pOBvo2dCi/iVg==",
- "dependencies": {
- "SemanticVersioning": "0.8.0",
- "System.Net.Http": "4.3.4",
- "System.Runtime.InteropServices.RuntimeInformation": "4.3.0",
- "System.Text.Json": "6.0.5"
- }
- },
"Proc": {
"type": "Transitive",
"resolved": "0.6.1",
@@ -842,10 +828,27 @@
"System.Reflection.Emit.Lightweight": "4.3.0"
}
},
+ "opensearch.opensearch.managed": {
+ "type": "Project",
+ "dependencies": {
+ "OpenSearch.Stack.ArtifactsApi": "1.0.0",
+ "Proc": "0.6.1",
+ "System.Net.Http": "4.3.4"
+ }
+ },
+ "opensearch.stack.artifactsapi": {
+ "type": "Project",
+ "dependencies": {
+ "SemanticVersioning": "0.8.0",
+ "System.Net.Http": "4.3.4",
+ "System.Runtime.InteropServices.RuntimeInformation": "4.3.0",
+ "System.Text.Json": "6.0.5"
+ }
+ },
"tests.configuration": {
"type": "Project",
"dependencies": {
- "OpenSearch.OpenSearch.Managed": "0.1.0-canary.0.277"
+ "OpenSearch.OpenSearch.Managed": "1.0.0"
}
}
}
diff --git a/tests/Tests.Reproduce/packages.lock.json b/tests/Tests.Reproduce/packages.lock.json
index 59216b2d2c..20b78b3974 100644
--- a/tests/Tests.Reproduce/packages.lock.json
+++ b/tests/Tests.Reproduce/packages.lock.json
@@ -16,7 +16,10 @@
"type": "Direct",
"requested": "[1.0.0-preview.2, )",
"resolved": "1.0.0-preview.2",
- "contentHash": "m+pJPEO7HyXvrOna5Sr3s77ewXonjYWJTNL6drh8xACnMNxnlqUDKx9HfGeSE9wmfY0lQwppaeZpFTPGaH7kZg=="
+ "contentHash": "m+pJPEO7HyXvrOna5Sr3s77ewXonjYWJTNL6drh8xACnMNxnlqUDKx9HfGeSE9wmfY0lQwppaeZpFTPGaH7kZg==",
+ "dependencies": {
+ "Microsoft.NETFramework.ReferenceAssemblies.net461": "1.0.0-preview.2"
+ }
},
"Bogus": {
"type": "Transitive",
@@ -61,6 +64,11 @@
"resolved": "1.1.0",
"contentHash": "aOZA3BWfz9RXjpzt0sRJJMjAscAUm3Hoa4UWAfceV9UTYxgwZ1lZt5nO2myFf+/jetYQo4uTP7zS8sJY67BBxg=="
},
+ "Microsoft.NETFramework.ReferenceAssemblies.net461": {
+ "type": "Transitive",
+ "resolved": "1.0.0-preview.2",
+ "contentHash": "59D9ISjzCpfHG41r5x4BNZNNOCmE2o5YX8vcdOwsqfxOA0+6vQnxZrYq8KtthUU2JSvC13g941rSr5GRaNQOJg=="
+ },
"Microsoft.TestPlatform.ObjectModel": {
"type": "Transitive",
"resolved": "16.5.0",
@@ -121,45 +129,6 @@
"Microsoft.TestPlatform.ObjectModel": "15.8.0"
}
},
- "OpenSearch.OpenSearch.Ephemeral": {
- "type": "Transitive",
- "resolved": "0.1.0-canary.0.277",
- "contentHash": "LAAfOtWvcjoCxUq47BGbwfFst12nsvd3FYDRR9OUfSp69BzevNp3bhAd5O2sdaspBg9MkuOD5Mhp8TvWRHCG7g==",
- "dependencies": {
- "OpenSearch.OpenSearch.Managed": "0.1.0-canary.0.277",
- "SharpZipLib.NETStandard": "1.0.7"
- }
- },
- "OpenSearch.OpenSearch.Managed": {
- "type": "Transitive",
- "resolved": "0.1.0-canary.0.277",
- "contentHash": "BoLSf2fiCphayR0TQulvm0m0MISy8kCL+JrPv1QGrlR4YujWAeSi0izb+vnYEWT9+a8IviTMjU2TGZwpcKSuBQ==",
- "dependencies": {
- "OpenSearch.Stack.ArtifactsApi": "0.1.0-canary.0.277",
- "Proc": "0.6.1",
- "System.Net.Http": "4.3.4"
- }
- },
- "OpenSearch.OpenSearch.Xunit": {
- "type": "Transitive",
- "resolved": "0.1.0-canary.0.277",
- "contentHash": "hNAJp5xM9ounExLOS+CmLCTCwpPfirZ5rOTY0UfR2AU+19wp4HLKerwjmJV4cAJM0ba6JvzrjLQcnMGYazM0og==",
- "dependencies": {
- "OpenSearch.OpenSearch.Ephemeral": "0.1.0-canary.0.277",
- "xunit": "2.4.2"
- }
- },
- "OpenSearch.Stack.ArtifactsApi": {
- "type": "Transitive",
- "resolved": "0.1.0-canary.0.277",
- "contentHash": "S3Mxf2FhxL/WJg9f0LGoGLmpvRyFCH0HitsC3bDAgBweO9aqSNmpVeAm7DvKHMwGpSAglUL0+pOBvo2dCi/iVg==",
- "dependencies": {
- "SemanticVersioning": "0.8.0",
- "System.Net.Http": "4.3.4",
- "System.Runtime.InteropServices.RuntimeInformation": "4.3.0",
- "System.Text.Json": "6.0.5"
- }
- },
"Proc": {
"type": "Transitive",
"resolved": "0.6.1",
@@ -917,10 +886,41 @@
"System.Diagnostics.DiagnosticSource": "5.0.0"
}
},
+ "opensearch.opensearch.ephemeral": {
+ "type": "Project",
+ "dependencies": {
+ "OpenSearch.OpenSearch.Managed": "1.0.0",
+ "SharpZipLib.NETStandard": "1.0.7"
+ }
+ },
+ "opensearch.opensearch.managed": {
+ "type": "Project",
+ "dependencies": {
+ "OpenSearch.Stack.ArtifactsApi": "1.0.0",
+ "Proc": "0.6.1",
+ "System.Net.Http": "4.3.4"
+ }
+ },
+ "opensearch.opensearch.xunit": {
+ "type": "Project",
+ "dependencies": {
+ "OpenSearch.OpenSearch.Ephemeral": "1.0.0",
+ "xunit": "2.4.2"
+ }
+ },
+ "opensearch.stack.artifactsapi": {
+ "type": "Project",
+ "dependencies": {
+ "SemanticVersioning": "0.8.0",
+ "System.Net.Http": "4.3.4",
+ "System.Runtime.InteropServices.RuntimeInformation": "4.3.0",
+ "System.Text.Json": "6.0.5"
+ }
+ },
"tests.configuration": {
"type": "Project",
"dependencies": {
- "OpenSearch.OpenSearch.Managed": "0.1.0-canary.0.277"
+ "OpenSearch.OpenSearch.Managed": "1.0.0"
}
},
"tests.core": {
@@ -932,7 +932,7 @@
"Microsoft.NET.Test.Sdk": "16.5.0",
"Nullean.VsTest.Pretty.TestLogger": "0.3.0",
"OpenSearch.Client.JsonNetSerializer": "1.0.0",
- "OpenSearch.OpenSearch.Xunit": "0.1.0-canary.0.277",
+ "OpenSearch.OpenSearch.Xunit": "1.0.0",
"Proc": "0.6.1",
"Tests.Domain": "1.0.0",
"xunit": "2.4.2"
@@ -944,7 +944,7 @@
"Bogus": "22.1.2",
"Newtonsoft.Json": "13.0.1",
"OpenSearch.Client": "1.0.0",
- "OpenSearch.OpenSearch.Managed": "0.1.0-canary.0.277",
+ "OpenSearch.OpenSearch.Managed": "1.0.0",
"Tests.Configuration": "1.0.0"
}
}
diff --git a/tests/Tests.ScratchPad/packages.lock.json b/tests/Tests.ScratchPad/packages.lock.json
index 1e49856762..eab77e1ac3 100644
--- a/tests/Tests.ScratchPad/packages.lock.json
+++ b/tests/Tests.ScratchPad/packages.lock.json
@@ -29,7 +29,10 @@
"type": "Direct",
"requested": "[1.0.0-preview.2, )",
"resolved": "1.0.0-preview.2",
- "contentHash": "m+pJPEO7HyXvrOna5Sr3s77ewXonjYWJTNL6drh8xACnMNxnlqUDKx9HfGeSE9wmfY0lQwppaeZpFTPGaH7kZg=="
+ "contentHash": "m+pJPEO7HyXvrOna5Sr3s77ewXonjYWJTNL6drh8xACnMNxnlqUDKx9HfGeSE9wmfY0lQwppaeZpFTPGaH7kZg==",
+ "dependencies": {
+ "Microsoft.NETFramework.ReferenceAssemblies.net461": "1.0.0-preview.2"
+ }
},
"System.Diagnostics.DiagnosticSource": {
"type": "Direct",
@@ -197,6 +200,11 @@
"resolved": "1.1.0",
"contentHash": "aOZA3BWfz9RXjpzt0sRJJMjAscAUm3Hoa4UWAfceV9UTYxgwZ1lZt5nO2myFf+/jetYQo4uTP7zS8sJY67BBxg=="
},
+ "Microsoft.NETFramework.ReferenceAssemblies.net461": {
+ "type": "Transitive",
+ "resolved": "1.0.0-preview.2",
+ "contentHash": "59D9ISjzCpfHG41r5x4BNZNNOCmE2o5YX8vcdOwsqfxOA0+6vQnxZrYq8KtthUU2JSvC13g941rSr5GRaNQOJg=="
+ },
"Microsoft.TestPlatform.ObjectModel": {
"type": "Transitive",
"resolved": "16.5.0",
@@ -251,45 +259,6 @@
"Microsoft.TestPlatform.ObjectModel": "15.8.0"
}
},
- "OpenSearch.OpenSearch.Ephemeral": {
- "type": "Transitive",
- "resolved": "0.1.0-canary.0.277",
- "contentHash": "LAAfOtWvcjoCxUq47BGbwfFst12nsvd3FYDRR9OUfSp69BzevNp3bhAd5O2sdaspBg9MkuOD5Mhp8TvWRHCG7g==",
- "dependencies": {
- "OpenSearch.OpenSearch.Managed": "0.1.0-canary.0.277",
- "SharpZipLib.NETStandard": "1.0.7"
- }
- },
- "OpenSearch.OpenSearch.Managed": {
- "type": "Transitive",
- "resolved": "0.1.0-canary.0.277",
- "contentHash": "BoLSf2fiCphayR0TQulvm0m0MISy8kCL+JrPv1QGrlR4YujWAeSi0izb+vnYEWT9+a8IviTMjU2TGZwpcKSuBQ==",
- "dependencies": {
- "OpenSearch.Stack.ArtifactsApi": "0.1.0-canary.0.277",
- "Proc": "0.6.1",
- "System.Net.Http": "4.3.4"
- }
- },
- "OpenSearch.OpenSearch.Xunit": {
- "type": "Transitive",
- "resolved": "0.1.0-canary.0.277",
- "contentHash": "hNAJp5xM9ounExLOS+CmLCTCwpPfirZ5rOTY0UfR2AU+19wp4HLKerwjmJV4cAJM0ba6JvzrjLQcnMGYazM0og==",
- "dependencies": {
- "OpenSearch.OpenSearch.Ephemeral": "0.1.0-canary.0.277",
- "xunit": "2.4.2"
- }
- },
- "OpenSearch.Stack.ArtifactsApi": {
- "type": "Transitive",
- "resolved": "0.1.0-canary.0.277",
- "contentHash": "S3Mxf2FhxL/WJg9f0LGoGLmpvRyFCH0HitsC3bDAgBweO9aqSNmpVeAm7DvKHMwGpSAglUL0+pOBvo2dCi/iVg==",
- "dependencies": {
- "SemanticVersioning": "0.8.0",
- "System.Net.Http": "4.3.4",
- "System.Runtime.InteropServices.RuntimeInformation": "4.3.0",
- "System.Text.Json": "6.0.5"
- }
- },
"Perfolizer": {
"type": "Transitive",
"resolved": "0.2.1",
@@ -1426,10 +1395,41 @@
"System.Diagnostics.DiagnosticSource": "5.0.0"
}
},
+ "opensearch.opensearch.ephemeral": {
+ "type": "Project",
+ "dependencies": {
+ "OpenSearch.OpenSearch.Managed": "1.0.0",
+ "SharpZipLib.NETStandard": "1.0.7"
+ }
+ },
+ "opensearch.opensearch.managed": {
+ "type": "Project",
+ "dependencies": {
+ "OpenSearch.Stack.ArtifactsApi": "1.0.0",
+ "Proc": "0.6.1",
+ "System.Net.Http": "4.3.4"
+ }
+ },
+ "opensearch.opensearch.xunit": {
+ "type": "Project",
+ "dependencies": {
+ "OpenSearch.OpenSearch.Ephemeral": "1.0.0",
+ "xunit": "2.4.2"
+ }
+ },
+ "opensearch.stack.artifactsapi": {
+ "type": "Project",
+ "dependencies": {
+ "SemanticVersioning": "0.8.0",
+ "System.Net.Http": "4.3.4",
+ "System.Runtime.InteropServices.RuntimeInformation": "4.3.0",
+ "System.Text.Json": "6.0.5"
+ }
+ },
"tests.configuration": {
"type": "Project",
"dependencies": {
- "OpenSearch.OpenSearch.Managed": "0.1.0-canary.0.277"
+ "OpenSearch.OpenSearch.Managed": "1.0.0"
}
},
"tests.core": {
@@ -1441,7 +1441,7 @@
"Microsoft.NET.Test.Sdk": "16.5.0",
"Nullean.VsTest.Pretty.TestLogger": "0.3.0",
"OpenSearch.Client.JsonNetSerializer": "1.0.0",
- "OpenSearch.OpenSearch.Xunit": "0.1.0-canary.0.277",
+ "OpenSearch.OpenSearch.Xunit": "1.0.0",
"Proc": "0.6.1",
"Tests.Domain": "1.0.0",
"xunit": "2.4.2"
@@ -1453,7 +1453,7 @@
"Bogus": "22.1.2",
"Newtonsoft.Json": "13.0.1",
"OpenSearch.Client": "1.0.0",
- "OpenSearch.OpenSearch.Managed": "0.1.0-canary.0.277",
+ "OpenSearch.OpenSearch.Managed": "1.0.0",
"Tests.Configuration": "1.0.0"
}
}
diff --git a/tests/Tests.YamlRunner/packages.lock.json b/tests/Tests.YamlRunner/packages.lock.json
index 7aa8ae06dd..8ce7399c8c 100644
--- a/tests/Tests.YamlRunner/packages.lock.json
+++ b/tests/Tests.YamlRunner/packages.lock.json
@@ -31,7 +31,10 @@
"type": "Direct",
"requested": "[1.0.0-preview.2, )",
"resolved": "1.0.0-preview.2",
- "contentHash": "m+pJPEO7HyXvrOna5Sr3s77ewXonjYWJTNL6drh8xACnMNxnlqUDKx9HfGeSE9wmfY0lQwppaeZpFTPGaH7kZg=="
+ "contentHash": "m+pJPEO7HyXvrOna5Sr3s77ewXonjYWJTNL6drh8xACnMNxnlqUDKx9HfGeSE9wmfY0lQwppaeZpFTPGaH7kZg==",
+ "dependencies": {
+ "Microsoft.NETFramework.ReferenceAssemblies.net461": "1.0.0-preview.2"
+ }
},
"Newtonsoft.Json": {
"type": "Direct",
@@ -78,6 +81,11 @@
"resolved": "1.1.0",
"contentHash": "aOZA3BWfz9RXjpzt0sRJJMjAscAUm3Hoa4UWAfceV9UTYxgwZ1lZt5nO2myFf+/jetYQo4uTP7zS8sJY67BBxg=="
},
+ "Microsoft.NETFramework.ReferenceAssemblies.net461": {
+ "type": "Transitive",
+ "resolved": "1.0.0-preview.2",
+ "contentHash": "59D9ISjzCpfHG41r5x4BNZNNOCmE2o5YX8vcdOwsqfxOA0+6vQnxZrYq8KtthUU2JSvC13g941rSr5GRaNQOJg=="
+ },
"System.Buffers": {
"type": "Transitive",
"resolved": "4.5.1",
diff --git a/tests/Tests/Cat/CatClusterManager/CatClusterManagerApiTests.cs b/tests/Tests/Cat/CatClusterManager/CatClusterManagerApiTests.cs
index c11953cdba..1d0ad42dfb 100644
--- a/tests/Tests/Cat/CatClusterManager/CatClusterManagerApiTests.cs
+++ b/tests/Tests/Cat/CatClusterManager/CatClusterManagerApiTests.cs
@@ -3,7 +3,8 @@
* The OpenSearch Contributors require contributions made to
* this file be licensed under the Apache-2.0 license or a
* compatible open source license.
-*
+*/
+/*
* Modifications Copyright OpenSearch Contributors. See
* GitHub history for details.
*
diff --git a/tests/Tests/Cat/CatClusterManager/CatClusterManagerUrlTests.cs b/tests/Tests/Cat/CatClusterManager/CatClusterManagerUrlTests.cs
index 3e85f55e37..439f039cb4 100644
--- a/tests/Tests/Cat/CatClusterManager/CatClusterManagerUrlTests.cs
+++ b/tests/Tests/Cat/CatClusterManager/CatClusterManagerUrlTests.cs
@@ -3,7 +3,8 @@
* The OpenSearch Contributors require contributions made to
* this file be licensed under the Apache-2.0 license or a
* compatible open source license.
-*
+*/
+/*
* Modifications Copyright OpenSearch Contributors. See
* GitHub history for details.
*
diff --git a/tests/Tests/packages.lock.json b/tests/Tests/packages.lock.json
index 35abc4c3b4..d1d8f230b0 100644
--- a/tests/Tests/packages.lock.json
+++ b/tests/Tests/packages.lock.json
@@ -31,7 +31,10 @@
"type": "Direct",
"requested": "[1.0.0-preview.2, )",
"resolved": "1.0.0-preview.2",
- "contentHash": "m+pJPEO7HyXvrOna5Sr3s77ewXonjYWJTNL6drh8xACnMNxnlqUDKx9HfGeSE9wmfY0lQwppaeZpFTPGaH7kZg=="
+ "contentHash": "m+pJPEO7HyXvrOna5Sr3s77ewXonjYWJTNL6drh8xACnMNxnlqUDKx9HfGeSE9wmfY0lQwppaeZpFTPGaH7kZg==",
+ "dependencies": {
+ "Microsoft.NETFramework.ReferenceAssemblies.net461": "1.0.0-preview.2"
+ }
},
"SemanticVersioning": {
"type": "Direct",
@@ -100,6 +103,11 @@
"resolved": "1.1.0",
"contentHash": "aOZA3BWfz9RXjpzt0sRJJMjAscAUm3Hoa4UWAfceV9UTYxgwZ1lZt5nO2myFf+/jetYQo4uTP7zS8sJY67BBxg=="
},
+ "Microsoft.NETFramework.ReferenceAssemblies.net461": {
+ "type": "Transitive",
+ "resolved": "1.0.0-preview.2",
+ "contentHash": "59D9ISjzCpfHG41r5x4BNZNNOCmE2o5YX8vcdOwsqfxOA0+6vQnxZrYq8KtthUU2JSvC13g941rSr5GRaNQOJg=="
+ },
"Microsoft.TestPlatform.ObjectModel": {
"type": "Transitive",
"resolved": "16.5.0",
@@ -211,45 +219,6 @@
"Microsoft.TestPlatform.ObjectModel": "15.8.0"
}
},
- "OpenSearch.OpenSearch.Ephemeral": {
- "type": "Transitive",
- "resolved": "0.1.0-canary.0.277",
- "contentHash": "LAAfOtWvcjoCxUq47BGbwfFst12nsvd3FYDRR9OUfSp69BzevNp3bhAd5O2sdaspBg9MkuOD5Mhp8TvWRHCG7g==",
- "dependencies": {
- "OpenSearch.OpenSearch.Managed": "0.1.0-canary.0.277",
- "SharpZipLib.NETStandard": "1.0.7"
- }
- },
- "OpenSearch.OpenSearch.Managed": {
- "type": "Transitive",
- "resolved": "0.1.0-canary.0.277",
- "contentHash": "BoLSf2fiCphayR0TQulvm0m0MISy8kCL+JrPv1QGrlR4YujWAeSi0izb+vnYEWT9+a8IviTMjU2TGZwpcKSuBQ==",
- "dependencies": {
- "OpenSearch.Stack.ArtifactsApi": "0.1.0-canary.0.277",
- "Proc": "0.6.1",
- "System.Net.Http": "4.3.4"
- }
- },
- "OpenSearch.OpenSearch.Xunit": {
- "type": "Transitive",
- "resolved": "0.1.0-canary.0.277",
- "contentHash": "hNAJp5xM9ounExLOS+CmLCTCwpPfirZ5rOTY0UfR2AU+19wp4HLKerwjmJV4cAJM0ba6JvzrjLQcnMGYazM0og==",
- "dependencies": {
- "OpenSearch.OpenSearch.Ephemeral": "0.1.0-canary.0.277",
- "xunit": "2.4.2"
- }
- },
- "OpenSearch.Stack.ArtifactsApi": {
- "type": "Transitive",
- "resolved": "0.1.0-canary.0.277",
- "contentHash": "S3Mxf2FhxL/WJg9f0LGoGLmpvRyFCH0HitsC3bDAgBweO9aqSNmpVeAm7DvKHMwGpSAglUL0+pOBvo2dCi/iVg==",
- "dependencies": {
- "SemanticVersioning": "0.8.0",
- "System.Net.Http": "4.3.4",
- "System.Runtime.InteropServices.RuntimeInformation": "4.3.0",
- "System.Text.Json": "6.0.5"
- }
- },
"Proc": {
"type": "Transitive",
"resolved": "0.6.1",
@@ -1335,10 +1304,41 @@
"OpenSearch.Net": "1.0.0"
}
},
+ "opensearch.opensearch.ephemeral": {
+ "type": "Project",
+ "dependencies": {
+ "OpenSearch.OpenSearch.Managed": "1.0.0",
+ "SharpZipLib.NETStandard": "1.0.7"
+ }
+ },
+ "opensearch.opensearch.managed": {
+ "type": "Project",
+ "dependencies": {
+ "OpenSearch.Stack.ArtifactsApi": "1.0.0",
+ "Proc": "0.6.1",
+ "System.Net.Http": "4.3.4"
+ }
+ },
+ "opensearch.opensearch.xunit": {
+ "type": "Project",
+ "dependencies": {
+ "OpenSearch.OpenSearch.Ephemeral": "1.0.0",
+ "xunit": "2.4.2"
+ }
+ },
+ "opensearch.stack.artifactsapi": {
+ "type": "Project",
+ "dependencies": {
+ "SemanticVersioning": "0.8.0",
+ "System.Net.Http": "4.3.4",
+ "System.Runtime.InteropServices.RuntimeInformation": "4.3.0",
+ "System.Text.Json": "6.0.5"
+ }
+ },
"tests.configuration": {
"type": "Project",
"dependencies": {
- "OpenSearch.OpenSearch.Managed": "0.1.0-canary.0.277"
+ "OpenSearch.OpenSearch.Managed": "1.0.0"
}
},
"tests.core": {
@@ -1350,7 +1350,7 @@
"Microsoft.NET.Test.Sdk": "16.5.0",
"Nullean.VsTest.Pretty.TestLogger": "0.3.0",
"OpenSearch.Client.JsonNetSerializer": "1.0.0",
- "OpenSearch.OpenSearch.Xunit": "0.1.0-canary.0.277",
+ "OpenSearch.OpenSearch.Xunit": "1.0.0",
"Proc": "0.6.1",
"Tests.Domain": "1.0.0",
"xunit": "2.4.2"
@@ -1362,7 +1362,7 @@
"Bogus": "22.1.2",
"Newtonsoft.Json": "13.0.1",
"OpenSearch.Client": "1.0.0",
- "OpenSearch.OpenSearch.Managed": "0.1.0-canary.0.277",
+ "OpenSearch.OpenSearch.Managed": "1.0.0",
"Tests.Configuration": "1.0.0"
}
}