Skip to content

Commit 0872a51

Browse files
committed
test(seaweedfs): add lifecycle tests for endpoint default/override persistence
Add SeaweedFSObjectStoreLifeCycleImplTest covering the endpoint persistence behavior: defaulted s3Url/iamUrl are not persisted (so the driver resolves them from the current store URL at runtime), explicit overrides are retained, and a mix of explicit s3Url with defaulted iamUrl persists only s3Url. Also covers missing credentials, unexpected provider name, and missing details validation failures.
1 parent 67aa7af commit 0872a51

1 file changed

Lines changed: 184 additions & 0 deletions

File tree

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
// Licensed to the Apache Software Foundation (ASF) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The ASF licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
// SPDX-License-Identifier: Apache-2.0
18+
package org.apache.cloudstack.storage.datastore.lifecycle;
19+
20+
import static org.junit.Assert.assertEquals;
21+
import static org.junit.Assert.assertFalse;
22+
import static org.junit.Assert.assertNotNull;
23+
import static org.junit.Assert.assertThrows;
24+
import static org.junit.Assert.assertTrue;
25+
import static org.mockito.ArgumentMatchers.anyMap;
26+
import static org.mockito.Mockito.verify;
27+
import static org.mockito.Mockito.when;
28+
29+
import java.util.HashMap;
30+
import java.util.Map;
31+
32+
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
33+
import org.apache.cloudstack.storage.datastore.db.ObjectStoreVO;
34+
import org.apache.cloudstack.storage.datastore.util.SeaweedFSObjectStoreUtil;
35+
import org.apache.cloudstack.storage.object.ObjectStoreEntity;
36+
import org.apache.cloudstack.storage.object.datastore.ObjectStoreHelper;
37+
import org.apache.cloudstack.storage.object.datastore.ObjectStoreProviderManager;
38+
import org.junit.After;
39+
import org.junit.Before;
40+
import org.junit.Test;
41+
import org.junit.runner.RunWith;
42+
import org.mockito.ArgumentCaptor;
43+
import org.mockito.Mock;
44+
import org.mockito.MockedStatic;
45+
import org.mockito.Mockito;
46+
import org.mockito.MockitoAnnotations;
47+
import org.mockito.Spy;
48+
import org.mockito.junit.MockitoJUnitRunner;
49+
50+
import com.cloud.utils.exception.CloudRuntimeException;
51+
52+
@RunWith(MockitoJUnitRunner.class)
53+
public class SeaweedFSObjectStoreLifeCycleImplTest {
54+
55+
@Spy
56+
SeaweedFSObjectStoreLifeCycleImpl lifecycle = new SeaweedFSObjectStoreLifeCycleImpl();
57+
58+
@Mock
59+
ObjectStoreHelper objectStoreHelper;
60+
@Mock
61+
ObjectStoreProviderManager objectStoreMgr;
62+
@Mock
63+
ObjectStoreVO objectStoreVo;
64+
@Mock
65+
ObjectStoreEntity objectStoreEntity;
66+
67+
static String TEST_STORE_NAME = "testStore";
68+
static String TEST_URL = "http://s3-endpoint";
69+
static String TEST_PROVIDER_NAME = "SeaweedFS";
70+
static String TEST_ACCESS_KEY = "admin-access-key";
71+
static String TEST_SECRET_KEY = "admin-secret-key";
72+
static String TEST_S3_URL_OVERRIDE = "http://s3-override:8333";
73+
static String TEST_IAM_URL_OVERRIDE = "http://iam-override:8111";
74+
75+
Map<String, String> detailsMap;
76+
Map<String, Object> dsInfos;
77+
78+
MockedStatic<SeaweedFSObjectStoreUtil> mockStatic;
79+
80+
private AutoCloseable closeable;
81+
82+
@Before
83+
public void setUp() {
84+
closeable = MockitoAnnotations.openMocks(this);
85+
86+
mockStatic = Mockito.mockStatic(SeaweedFSObjectStoreUtil.class);
87+
mockStatic.when(() -> SeaweedFSObjectStoreUtil.validateS3Url(org.mockito.ArgumentMatchers.anyString())).thenAnswer(i -> null);
88+
mockStatic.when(() -> SeaweedFSObjectStoreUtil.validateIAMUrl(org.mockito.ArgumentMatchers.anyString())).thenAnswer(i -> null);
89+
90+
lifecycle.objectStoreHelper = objectStoreHelper;
91+
lifecycle.objectStoreMgr = objectStoreMgr;
92+
93+
detailsMap = new HashMap<>();
94+
detailsMap.put(SeaweedFSObjectStoreUtil.STORE_DETAILS_KEY_ACCESS_KEY, TEST_ACCESS_KEY);
95+
detailsMap.put(SeaweedFSObjectStoreUtil.STORE_DETAILS_KEY_SECRET_KEY, TEST_SECRET_KEY);
96+
97+
dsInfos = new HashMap<>();
98+
dsInfos.put(SeaweedFSObjectStoreUtil.STORE_KEY_NAME, TEST_STORE_NAME);
99+
dsInfos.put(SeaweedFSObjectStoreUtil.STORE_KEY_URL, TEST_URL);
100+
dsInfos.put(SeaweedFSObjectStoreUtil.STORE_KEY_PROVIDER_NAME, TEST_PROVIDER_NAME);
101+
dsInfos.put(SeaweedFSObjectStoreUtil.STORE_KEY_SIZE, 0L);
102+
dsInfos.put(SeaweedFSObjectStoreUtil.STORE_KEY_DETAILS, detailsMap);
103+
104+
when(objectStoreVo.getId()).thenReturn(1L);
105+
when(objectStoreHelper.createObjectStore(anyMap(), anyMap())).thenReturn(objectStoreVo);
106+
when(objectStoreMgr.getObjectStore(1L)).thenReturn(objectStoreEntity);
107+
}
108+
109+
@After
110+
public void tearDown() throws Exception {
111+
mockStatic.close();
112+
closeable.close();
113+
}
114+
115+
@Test
116+
public void testInitializeDefaultEndpointsNotPersisted() {
117+
// No s3Url/iamUrl in details — should default to store URL and NOT persist
118+
DataStore ds = lifecycle.initialize(dsInfos);
119+
assertNotNull(ds);
120+
121+
ArgumentCaptor<Map<String, String>> detailsArg = ArgumentCaptor.forClass((Class<Map<String, String>>) (Class<?>) Map.class);
122+
verify(objectStoreHelper).createObjectStore(anyMap(), detailsArg.capture());
123+
Map<String, String> persistedDetails = detailsArg.getValue();
124+
// Defaulted endpoints must not be persisted so the driver resolves
125+
// them from the current store URL at runtime.
126+
assertFalse(persistedDetails.containsKey(SeaweedFSObjectStoreUtil.STORE_DETAILS_KEY_S3_URL));
127+
assertFalse(persistedDetails.containsKey(SeaweedFSObjectStoreUtil.STORE_DETAILS_KEY_IAM_URL));
128+
}
129+
130+
@Test
131+
public void testInitializeExplicitEndpointsPersisted() {
132+
detailsMap.put(SeaweedFSObjectStoreUtil.STORE_DETAILS_KEY_S3_URL, TEST_S3_URL_OVERRIDE);
133+
detailsMap.put(SeaweedFSObjectStoreUtil.STORE_DETAILS_KEY_IAM_URL, TEST_IAM_URL_OVERRIDE);
134+
135+
DataStore ds = lifecycle.initialize(dsInfos);
136+
assertNotNull(ds);
137+
138+
ArgumentCaptor<Map<String, String>> detailsArg = ArgumentCaptor.forClass((Class<Map<String, String>>) (Class<?>) Map.class);
139+
verify(objectStoreHelper).createObjectStore(anyMap(), detailsArg.capture());
140+
Map<String, String> persistedDetails = detailsArg.getValue();
141+
assertEquals(TEST_S3_URL_OVERRIDE, persistedDetails.get(SeaweedFSObjectStoreUtil.STORE_DETAILS_KEY_S3_URL));
142+
assertEquals(TEST_IAM_URL_OVERRIDE, persistedDetails.get(SeaweedFSObjectStoreUtil.STORE_DETAILS_KEY_IAM_URL));
143+
}
144+
145+
@Test
146+
public void testInitializeOnlyS3UrlExplicit() {
147+
// s3Url explicit, iamUrl defaulted — only s3Url should be persisted
148+
detailsMap.put(SeaweedFSObjectStoreUtil.STORE_DETAILS_KEY_S3_URL, TEST_S3_URL_OVERRIDE);
149+
150+
DataStore ds = lifecycle.initialize(dsInfos);
151+
assertNotNull(ds);
152+
153+
ArgumentCaptor<Map<String, String>> detailsArg = ArgumentCaptor.forClass((Class<Map<String, String>>) (Class<?>) Map.class);
154+
verify(objectStoreHelper).createObjectStore(anyMap(), detailsArg.capture());
155+
Map<String, String> persistedDetails = detailsArg.getValue();
156+
assertEquals(TEST_S3_URL_OVERRIDE, persistedDetails.get(SeaweedFSObjectStoreUtil.STORE_DETAILS_KEY_S3_URL));
157+
assertFalse(persistedDetails.containsKey(SeaweedFSObjectStoreUtil.STORE_DETAILS_KEY_IAM_URL));
158+
}
159+
160+
@Test
161+
public void testInitializeMissingCredentials() {
162+
detailsMap.remove(SeaweedFSObjectStoreUtil.STORE_DETAILS_KEY_ACCESS_KEY);
163+
detailsMap.remove(SeaweedFSObjectStoreUtil.STORE_DETAILS_KEY_SECRET_KEY);
164+
165+
CloudRuntimeException thrown = assertThrows(CloudRuntimeException.class, () -> lifecycle.initialize(dsInfos));
166+
assertTrue(thrown.getMessage().contains("missing"));
167+
}
168+
169+
@Test
170+
public void testInitializeUnexpectedProviderName() {
171+
dsInfos.put(SeaweedFSObjectStoreUtil.STORE_KEY_PROVIDER_NAME, "bad provider");
172+
173+
CloudRuntimeException thrown = assertThrows(CloudRuntimeException.class, () -> lifecycle.initialize(dsInfos));
174+
assertTrue(thrown.getMessage().contains("Unexpected providerName"));
175+
}
176+
177+
@Test
178+
public void testInitializeMissingDetails() {
179+
dsInfos.remove(SeaweedFSObjectStoreUtil.STORE_KEY_DETAILS);
180+
181+
CloudRuntimeException thrown = assertThrows(CloudRuntimeException.class, () -> lifecycle.initialize(dsInfos));
182+
assertTrue(thrown.getMessage().contains("details"));
183+
}
184+
}

0 commit comments

Comments
 (0)