Skip to content

Commit 933c487

Browse files
committed
Adding bwc test
Signed-off-by: Tarun-kishore <[email protected]>
1 parent 4771d53 commit 933c487

File tree

2 files changed

+222
-1
lines changed

2 files changed

+222
-1
lines changed
Lines changed: 221 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,221 @@
1+
/*
2+
* Copyright OpenSearch Contributors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package org.opensearch.indexmanagement.bwc
7+
8+
import org.opensearch.common.settings.Settings
9+
import org.opensearch.indexmanagement.snapshotmanagement.SnapshotManagementRestTestCase
10+
import java.util.Locale
11+
12+
class SMBackwardsCompatibilityIT : SnapshotManagementRestTestCase() {
13+
private val testIndexName = javaClass.simpleName.lowercase(Locale.ROOT)
14+
15+
private enum class ClusterType {
16+
OLD,
17+
MIXED,
18+
UPGRADED,
19+
;
20+
21+
companion object {
22+
fun parse(value: String): ClusterType = when (value) {
23+
"old_cluster" -> OLD
24+
"mixed_cluster" -> MIXED
25+
"upgraded_cluster" -> UPGRADED
26+
else -> throw AssertionError("Unknown cluster type: $value")
27+
}
28+
}
29+
}
30+
31+
private fun getPluginUri(): String = when (CLUSTER_TYPE) {
32+
ClusterType.OLD -> "_nodes/$CLUSTER_NAME-0/plugins"
33+
ClusterType.MIXED -> {
34+
when (System.getProperty("tests.rest.bwcsuite_round")) {
35+
"second" -> "_nodes/$CLUSTER_NAME-1/plugins"
36+
"third" -> "_nodes/$CLUSTER_NAME-2/plugins"
37+
else -> "_nodes/$CLUSTER_NAME-0/plugins"
38+
}
39+
}
40+
ClusterType.UPGRADED -> "_nodes/plugins"
41+
}
42+
43+
companion object {
44+
private val CLUSTER_TYPE = ClusterType.parse(System.getProperty("tests.rest.bwcsuite"))
45+
private val CLUSTER_NAME = System.getProperty("tests.clustername")
46+
}
47+
48+
override fun preserveIndicesUponCompletion(): Boolean = true
49+
50+
override fun preserveReposUponCompletion(): Boolean = true
51+
52+
override fun preserveTemplatesUponCompletion(): Boolean = true
53+
54+
override fun restClientSettings(): Settings = Settings.builder()
55+
.put(super.restClientSettings())
56+
// increase the timeout here to 90 seconds to handle long waits for a green
57+
// cluster health. the waits for green need to be longer than a minute to
58+
// account for delayed shards
59+
.put(CLIENT_SOCKET_TIMEOUT, "90s")
60+
.build()
61+
62+
@Throws(Exception::class)
63+
@Suppress("UNCHECKED_CAST")
64+
fun `test snapshot management backwards compatibility`() {
65+
val traditionalPolicyName = "${testIndexName}_traditional"
66+
val deletionOnlyPolicyName = "${testIndexName}_deletion_only"
67+
val patternPolicyName = "${testIndexName}_pattern"
68+
69+
val uri = getPluginUri()
70+
val responseMap = getAsMap(uri)["nodes"] as Map<String, Map<String, Any>>
71+
for (response in responseMap.values) {
72+
val plugins = response["plugins"] as List<Map<String, Any>>
73+
val pluginNames = plugins.map { plugin -> plugin["name"] }.toSet()
74+
when (CLUSTER_TYPE) {
75+
ClusterType.OLD -> {
76+
assertTrue(pluginNames.contains("opendistro-index-management") || pluginNames.contains("opensearch-index-management"))
77+
78+
createRepository("test-repo")
79+
80+
// Create traditional policy with both creation and deletion (pre-3.2.0 format)
81+
createTraditionalPolicy(traditionalPolicyName)
82+
83+
// Verify traditional policy works
84+
val traditionalPolicy = getSMPolicy(traditionalPolicyName)
85+
assertNotNull("Traditional policy creation should exist", traditionalPolicy.creation)
86+
assertNotNull("Traditional policy deletion should exist", traditionalPolicy.deletion)
87+
}
88+
ClusterType.MIXED -> {
89+
assertTrue(pluginNames.contains("opensearch-index-management"))
90+
91+
// Verify traditional policy still works during rolling upgrade
92+
val traditionalPolicy = getSMPolicy(traditionalPolicyName)
93+
assertNotNull("Traditional policy creation should exist", traditionalPolicy.creation)
94+
assertNotNull("Traditional policy deletion should exist", traditionalPolicy.deletion)
95+
}
96+
ClusterType.UPGRADED -> {
97+
assertTrue(pluginNames.contains("opensearch-index-management"))
98+
99+
// Verify traditional policy still works after full upgrade
100+
val traditionalPolicy = getSMPolicy(traditionalPolicyName)
101+
assertNotNull("Traditional policy creation should exist", traditionalPolicy.creation)
102+
assertNotNull("Traditional policy deletion should exist", traditionalPolicy.deletion)
103+
104+
// Now test new features on upgraded cluster
105+
106+
// Create deletion-only policy (3.2.0+ feature)
107+
createDeletionOnlyPolicy(deletionOnlyPolicyName)
108+
val deletionOnlyPolicy = getSMPolicy(deletionOnlyPolicyName)
109+
assertNull("Deletion-only policy creation should be null", deletionOnlyPolicy.creation)
110+
assertNotNull("Deletion-only policy deletion should exist", deletionOnlyPolicy.deletion)
111+
112+
// Create policy with snapshot pattern (3.2.0+ feature)
113+
createPatternPolicy(patternPolicyName)
114+
val patternPolicy = getSMPolicy(patternPolicyName)
115+
assertNotNull("Pattern policy creation should exist", patternPolicy.creation)
116+
assertNotNull("Pattern policy deletion should exist", patternPolicy.deletion)
117+
assertEquals("Pattern policy should have snapshot pattern", "external-backup-*", patternPolicy.deletion?.snapshotPattern)
118+
}
119+
}
120+
break
121+
}
122+
}
123+
124+
private fun createTraditionalPolicy(policyName: String) {
125+
val policy = """
126+
{
127+
"sm_policy": {
128+
"name": "$policyName",
129+
"description": "Traditional SM policy with creation and deletion",
130+
"creation": {
131+
"schedule": {
132+
"cron": {
133+
"expression": "0 1 * * *",
134+
"timezone": "UTC"
135+
}
136+
}
137+
},
138+
"deletion": {
139+
"schedule": {
140+
"cron": {
141+
"expression": "0 2 * * *",
142+
"timezone": "UTC"
143+
}
144+
},
145+
"condition": {
146+
"max_age": "7d",
147+
"min_count": 1
148+
}
149+
},
150+
"snapshot_config": {
151+
"repository": "test-repo"
152+
}
153+
}
154+
}
155+
""".trimIndent()
156+
createSMPolicyJson(policy, policyName)
157+
}
158+
159+
private fun createDeletionOnlyPolicy(policyName: String) {
160+
val policy = """
161+
{
162+
"sm_policy": {
163+
"name": "$policyName",
164+
"description": "Deletion-only SM policy (3.2.0+ feature)",
165+
"deletion": {
166+
"schedule": {
167+
"cron": {
168+
"expression": "0 2 * * *",
169+
"timezone": "UTC"
170+
}
171+
},
172+
"condition": {
173+
"max_age": "14d",
174+
"min_count": 2
175+
}
176+
},
177+
"snapshot_config": {
178+
"repository": "test-repo"
179+
}
180+
}
181+
}
182+
""".trimIndent()
183+
createSMPolicyJson(policy, policyName)
184+
}
185+
186+
private fun createPatternPolicy(policyName: String) {
187+
val policy = """
188+
{
189+
"sm_policy": {
190+
"name": "$policyName",
191+
"description": "SM policy with snapshot pattern (3.2.0+ feature)",
192+
"creation": {
193+
"schedule": {
194+
"cron": {
195+
"expression": "0 1 * * *",
196+
"timezone": "UTC"
197+
}
198+
}
199+
},
200+
"deletion": {
201+
"schedule": {
202+
"cron": {
203+
"expression": "0 2 * * *",
204+
"timezone": "UTC"
205+
}
206+
},
207+
"condition": {
208+
"max_age": "30d",
209+
"min_count": 3
210+
},
211+
"snapshot_pattern": "external-backup-*"
212+
},
213+
"snapshot_config": {
214+
"repository": "test-repo"
215+
}
216+
}
217+
}
218+
""".trimIndent()
219+
createSMPolicyJson(policy, policyName)
220+
}
221+
}

src/test/kotlin/org/opensearch/indexmanagement/snapshotmanagement/SnapshotManagementRestTestCase.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ import java.time.Instant.now
3838
abstract class SnapshotManagementRestTestCase : IndexManagementRestTestCase() {
3939
@After
4040
fun clearIndicesAfterEachTest() {
41-
wipeAllIndices()
41+
wipeAllIndices(skip = isBWCTest)
4242
}
4343

4444
var timeout: Instant = Instant.ofEpochSecond(20)

0 commit comments

Comments
 (0)