Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
ea98fac
chore: refactoring
nurtai325 May 4, 2026
daabb7b
chore: refactoring
nurtai325 May 4, 2026
0a6025b
chore: refactoring
nurtai325 May 4, 2026
197d75c
chore: refactoring
nurtai325 May 5, 2026
383a252
chore: refactoring
nurtai325 May 5, 2026
a61f289
chore: refactoring
nurtai325 May 5, 2026
a270791
chore: refactoring
nurtai325 May 5, 2026
f41f7a6
chore: refactoring
nurtai325 May 5, 2026
a347249
chore: refactoring
nurtai325 May 5, 2026
22fc313
chore: refactoring
nurtai325 May 5, 2026
c87d188
chore: refactoring
nurtai325 May 5, 2026
4d4617c
chore: refactoring
nurtai325 May 6, 2026
6497c3c
chore: refactoring
nurtai325 May 6, 2026
5173dbe
chore: refactoring
nurtai325 May 8, 2026
5aba50b
chore: refactoring
nurtai325 May 8, 2026
132130b
chore: refactoring
nurtai325 May 8, 2026
380aeac
chore: refactoring
nurtai325 May 11, 2026
b874720
chore: refactoring
nurtai325 May 12, 2026
1ae531a
chore: refactoring
nurtai325 May 12, 2026
0dc896f
Merge branch 'main' into feature/m2m-rest-client
nurtai325 May 12, 2026
f6cd5b2
chore: refactoring
nurtai325 May 12, 2026
86bf004
chore: refactoring
nurtai325 May 12, 2026
a8897e8
chore: refactoring
nurtai325 May 12, 2026
f0897e7
chore: refactoring
nurtai325 May 12, 2026
77b3a61
chore: refactoring
nurtai325 May 12, 2026
f2a998c
chore: refactoring
nurtai325 May 13, 2026
8426ff5
chore: refactoring
nurtai325 May 13, 2026
f2d784c
chore: refactoring
nurtai325 May 13, 2026
4f42660
Revert "chore: refactoring"
nurtai325 May 14, 2026
5f2ea5a
Revert "chore: refactoring"
nurtai325 May 14, 2026
2b22e4d
Revert "chore: refactoring"
nurtai325 May 14, 2026
751d097
chore: refactoring
nurtai325 May 14, 2026
4c9bc06
chore: refactoring
nurtai325 May 14, 2026
e22b5a6
chore: refactoring
nurtai325 May 14, 2026
280adfc
chore: refactoring
nurtai325 May 14, 2026
0291c1f
chore: refactoring
nurtai325 May 18, 2026
7747c3b
chore: refactoring
nurtai325 May 18, 2026
19e3ef9
chore: refactoring
nurtai325 May 18, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,12 @@
import org.springframework.cloud.config.client.ConfigClientAutoConfiguration;
import org.springframework.context.annotation.Configuration;

import com.netcracker.cloud.security.common.DummyM2MManagerConfiguration;
import org.springframework.context.annotation.Import;

@Configuration
@EnableServiceDbaasPostgresql
@EnableAutoConfiguration(exclude = {DataElasticsearchAutoConfiguration.class, ConfigClientAutoConfiguration.class})
@Import(DummyM2MManagerConfiguration.class)
public class TestApplicationOnRestTemplate extends BaseApplicationOnRestTemplate {
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ public class AbstractMongoEvolution {
private static final Logger LOGGER = LoggerFactory.getLogger(AbstractMongoEvolution.class);

private static final long INITIAL_VERSION = 0;
public static final String TRACKER_ID = "singleton_evolution_tracker";
public static final String TRACKER_COLLECTION = "_schema_evolution";
public static final String TRACKER_KEY_UPDATE_START = "startTime";
public static final String TRACKER_KEY_UPDATE_END = "endTime";
Expand Down Expand Up @@ -112,14 +113,14 @@ protected void doEvolve(AnnotationProcessor processor) throws Exception {
/* insert current DB version at start */
boolean startUpdate = insertUpdateFlag(updatesTracker, currentVersion, true);
if (startUpdate) {
updateFieldWithMongoCurrentDate(updatesTracker, TRACKER_KEY_UPDATE_START, null);
updateFieldWithMongoCurrentDate(updatesTracker, TRACKER_KEY_UPDATE_LAST, null);
updateFieldWithMongoCurrentDate(updatesTracker, TRACKER_KEY_UPDATE_START, new BasicDBObject("_id", TRACKER_ID));
updateFieldWithMongoCurrentDate(updatesTracker, TRACKER_KEY_UPDATE_LAST, new BasicDBObject("_id", TRACKER_ID));
processor.applyChanges(currentVersion);

/* insert expected version at finish */
finishUpdate = insertUpdateFlag(updatesTracker, expectedVersion, false);
if (finishUpdate) {
updateFieldWithMongoCurrentDate(updatesTracker, TRACKER_KEY_UPDATE_END, null);
updateFieldWithMongoCurrentDate(updatesTracker, TRACKER_KEY_UPDATE_END, new BasicDBObject("_id", TRACKER_ID));
}
} else {
try {
Expand Down Expand Up @@ -177,6 +178,7 @@ public static void updateFieldWithMongoCurrentDate(MongoCollection<Document> col

public Document createTrackerCollectionRecord(long dateStart, long dateEnd, boolean in_progress, long version) {
return new Document()
.append("_id", TRACKER_ID)
.append(TRACKER_KEY_UPDATE_START, dateStart)
.append(TRACKER_IN_PROGRESS, in_progress)
.append(TRACKER_KEY_UPDATE_END, dateEnd)
Expand All @@ -186,8 +188,11 @@ public Document createTrackerCollectionRecord(long dateStart, long dateEnd, bool

public boolean isDatabaseUpdateLockAlive() {
MongoCollection<Document> updatesTracker = database.getCollection(TRACKER_COLLECTION);
long lastUpdateStatusTimeMillis = 1000L * (((BsonTimestamp) updatesTracker.find().
first().get(TRACKER_KEY_UPDATE_LAST))
Document doc = updatesTracker.find(Filters.eq("_id", TRACKER_ID)).first();
if (doc == null) {
return false;
}
long lastUpdateStatusTimeMillis = 1000L * (((BsonTimestamp) doc.get(TRACKER_KEY_UPDATE_LAST))
.getTime());
long currentTimeMillis = currentTimeMillis();
long millisecDiff = currentTimeMillis - lastUpdateStatusTimeMillis;
Expand All @@ -197,19 +202,16 @@ public boolean isDatabaseUpdateLockAlive() {
public boolean isUpdateInProgress() throws Exception {
MongoCollection<Document> updatesTracker = database.getCollection(TRACKER_COLLECTION);
try {
FindIterable<Document> docs = updatesTracker.find();
Document doc;
if (!docs.iterator().hasNext()) {
Document doc = updatesTracker.find(Filters.eq("_id", TRACKER_ID)).first();
if (doc == null) {
long currentTime = currentTimeMillis();
doc = createTrackerCollectionRecord(currentTime, currentTime, false, INITIAL_VERSION);

updatesTracker.createIndex(new Document(TRACKER_IN_PROGRESS, 1), new IndexOptions().unique(true));
updatesTracker.insertOne(doc);

updateFieldWithMongoCurrentDate(updatesTracker, TRACKER_KEY_UPDATE_START, null);
updateFieldWithMongoCurrentDate(updatesTracker, TRACKER_KEY_UPDATE_END, null);
} else {
doc = docs.first();
updateFieldWithMongoCurrentDate(updatesTracker, TRACKER_KEY_UPDATE_START, new BasicDBObject("_id", TRACKER_ID));
updateFieldWithMongoCurrentDate(updatesTracker, TRACKER_KEY_UPDATE_END, new BasicDBObject("_id", TRACKER_ID));
}

return (boolean) doc.get(TRACKER_IN_PROGRESS);
Expand Down Expand Up @@ -248,7 +250,11 @@ boolean insertUpdateFlag(MongoCollection<Document> collection, Long expectedVers
newDoc.append(TRACKER_KEY_UPDATE_END, currentTime);
}

Document previousDoc = collection.findOneAndUpdate(Filters.eq(TRACKER_IN_PROGRESS, !updateInProgress),
Document previousDoc = collection.findOneAndUpdate(
Filters.and(
Filters.eq("_id", TRACKER_ID),
Filters.eq(TRACKER_IN_PROGRESS, !updateInProgress)
),
new Document("$set", newDoc));

return (null == previousDoc) ? false : true;
Expand All @@ -268,7 +274,7 @@ boolean insertUpdateFlag(MongoCollection<Document> collection, Long expectedVers

public Long getDbCurrentVersion() {
MongoCollection<Document> updatesTracker = database.getCollection(TRACKER_COLLECTION);
Document doc = updatesTracker.find().first();
Document doc = updatesTracker.find(Filters.eq("_id", TRACKER_ID)).first();
return (Long) doc.get(TRACKER_CURRENT_VERSION);
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.netcracker.cloud.mongoevolution.java;

import com.mongodb.BasicDBObject;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.model.Filters;
import org.bson.BsonTimestamp;
Expand Down Expand Up @@ -158,15 +159,28 @@ void evolveErrorDataBase() throws Exception {

@Test
void isDatabaseUpdateLockAliveTest() {
// Use a generous threshold for time-based tests to avoid flakiness in CI
long gracePeriodSeconds = 5;

Document doc1 = new Document()
.append("_id", AbstractMongoEvolution.TRACKER_ID)
.append(MongoEvolution.TRACKER_KEY_UPDATE_LAST, new BsonTimestamp((int) getCurrentTimeInSeconds(), 0));
mongoCollection.insertOne(doc1);
assertTrue(mongoEvolution.isDatabaseUpdateLockAlive());

assertTrue(mongoEvolution.isDatabaseUpdateLockAlive(), "Lock should be alive when updated just now");

mongoCollection.deleteOne(Filters.eq("_id", doc1.get("_id")));

// Ensure the timestamp is definitely in the past, beyond the threshold
long pastTime = getCurrentTimeInSeconds() - (mongoEvolution.getWaitTimeMillisecForUpdateStatusTask() / 1000 + gracePeriodSeconds);
Document doc2 = new Document()
.append(MongoEvolution.TRACKER_KEY_UPDATE_LAST, new BsonTimestamp((int) (getCurrentTimeInSeconds() - mongoEvolution.getWaitTimeMillisecForUpdateStatusTask() / 1000), 0));
.append("_id", AbstractMongoEvolution.TRACKER_ID)
.append(MongoEvolution.TRACKER_KEY_UPDATE_LAST, new BsonTimestamp((int) pastTime, 0));

mongoCollection.insertOne(doc2);
assertFalse(mongoEvolution.isDatabaseUpdateLockAlive());

assertFalse(mongoEvolution.isDatabaseUpdateLockAlive(), "Lock should be considered dead when timestamp is significantly in the past");

mongoCollection.deleteOne(doc2);
}

Expand Down Expand Up @@ -204,12 +218,14 @@ void saveEntryInChangeLogTest() {

@Test
void updateFieldWithMongoCurrentDateTest() {
Document dtest = new Document().append("TestField1", "Test Field 1").append("TestimeField", getCurrentTimeInSeconds() - 8);
Document dtest = new Document()
.append("_id", AbstractMongoEvolution.TRACKER_ID)
.append("TestField1", "Test Field 1").append("TestimeField", getCurrentTimeInSeconds() - 8);
mongoCollection.insertOne(dtest);
long before = getCurrentTimeInSeconds();
MongoEvolution.updateFieldWithMongoCurrentDate(mongoCollection, "TestimeField", null);
MongoEvolution.updateFieldWithMongoCurrentDate(mongoCollection, "TestimeField", new BasicDBObject("_id", AbstractMongoEvolution.TRACKER_ID));
long after = getCurrentTimeInSeconds();
long updtime = ((BsonTimestamp) mongoCollection.find().first().get("TestimeField")).getTime();
long updtime = ((BsonTimestamp) mongoCollection.find(Filters.eq("_id", AbstractMongoEvolution.TRACKER_ID)).first().get("TestimeField")).getTime();
assertTrue((updtime >= before && updtime <= after));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,13 @@
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
</dependency>
<!--TEst-->
<dependency>
<groupId>com.netcracker.cloud.security.core.utils</groupId>
<artifactId>k8s-utils</artifactId>
<version>3.1.0-SNAPSHOT</version>
</dependency>

<!--TEst-->
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
import com.fasterxml.jackson.module.paramnames.ParameterNamesModule;
import com.netcracker.cloud.quarkus.security.auth.M2MManager;
import com.netcracker.cloud.security.core.auth.Token;
import com.netcracker.cloud.security.core.utils.tls.TlsUtils;
import com.netcracker.cloud.security.core.utils.k8s.M2MClientFactory;
import okhttp3.*;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.eclipse.microprofile.config.Config;
Expand Down Expand Up @@ -36,7 +36,8 @@ public class ConfigServerClientImpl implements ConfigServerClient {
private URL url;

public ConfigServerClientImpl(String csUrl) throws MalformedURLException {
client = new OkHttpClient.Builder()
client = M2MClientFactory.getM2mOkHttpClient(() -> M2MManager.getInstance().getToken().getTokenValue())
.newBuilder()
.connectionSpecs(Collections.singletonList(
csUrl.startsWith("https") ? ConnectionSpec.COMPATIBLE_TLS : ConnectionSpec.CLEARTEXT)
)
Expand Down Expand Up @@ -87,9 +88,7 @@ private String processRequest(Request request) throws IOException {
int count = 1;
while (true) {
try {
Token token = M2MManager.getInstance().getToken();
request = request.newBuilder()
.addHeader("Authorization", token.getTokenType() + " " + token.getTokenValue())
.build();
Response response = client.newCall(request).execute();
return response.body().string();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,11 @@
<groupId>com.netcracker.cloud.security.core.utils</groupId>
<artifactId>tls-utils</artifactId>
</dependency>
<dependency>
<groupId>com.netcracker.cloud.security.core.utils</groupId>
<artifactId>k8s-utils</artifactId>
<version>3.1.0-SNAPSHOT</version>
</dependency>
<!--Test-->
<dependency>
<groupId>io.quarkus</groupId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,14 @@ public class DbaasClientProducer {

@Produces
@DefaultBean
public DbaasClient dbaaSClient(DbaasClientConfig dbaasClientConfig) {
public DbaasClient dbaaSClient(SecurityConfig securityConfig, DbaasClientConfig dbaasClientConfig) {
if (dbaasClientConfig.dbaasUrl().isPresent() && dbaasClientConfig.dbaasUsername().isPresent() && dbaasClientConfig.dbaasPassword().isPresent()) {
log.debug("Create dbaas client with basic auth");
return new BasicDbaaSClient(dbaasClientConfig).build();
}

log.debug("Create dbaas client with m2m auth");
return new M2MDbaaSClient(dbaasClientConfig).build();
return new M2MDbaaSClient(securityConfig, dbaasClientConfig).build();

}
}
Original file line number Diff line number Diff line change
@@ -1,40 +1,53 @@
package com.netcracker.cloud.dbaas.common.config;

import jakarta.enterprise.context.ApplicationScoped;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import com.netcracker.cloud.context.propagation.core.ContextManager;
import com.netcracker.cloud.dbaas.client.DbaaSClientOkHttpImpl;
import com.netcracker.cloud.dbaas.client.DbaasClient;
import com.netcracker.cloud.framework.contexts.tenant.TenantContextObject;
import com.netcracker.cloud.quarkus.security.auth.M2MManager;
import com.netcracker.cloud.security.core.auth.Token;
import com.netcracker.cloud.security.core.utils.k8s.M2MClientFactory;
import com.netcracker.cloud.security.core.utils.tls.TlsUtils;
import jakarta.enterprise.context.ApplicationScoped;
import lombok.extern.slf4j.Slf4j;
import okhttp3.OkHttpClient;
import okhttp3.Request;

import java.util.Optional;

import static com.netcracker.cloud.dbaas.common.config.DbaasClientConfig.DEFAULT_DBAAS_AGENT_ADDRESS;
import static com.netcracker.cloud.framework.contexts.tenant.BaseTenantProvider.TENANT_CONTEXT_NAME;

@Slf4j
@ApplicationScoped
public class M2MDbaaSClient {
private DbaasClientConfig config;
private static final int MAX_RETRIES = 3;
private static final long INITIAL_RETRY_DELAY = 500;

public M2MDbaaSClient(DbaasClientConfig config) {
this.config = config;
private final SecurityConfig securityConfig;
private final DbaasClientConfig dbaasConfig;

public M2MDbaaSClient(SecurityConfig securityConfig, DbaasClientConfig dbaasConfig) {
this.securityConfig = securityConfig;
this.dbaasConfig = dbaasConfig;
}

public DbaasClient build() {
String url = config.dbaasAgentUrl().orElse(DEFAULT_DBAAS_AGENT_ADDRESS);
OkHttpClient httpClient = new OkHttpClient.Builder()
String dbaasAgentUrl = dbaasConfig.dbaasAgentUrl().orElse(DEFAULT_DBAAS_AGENT_ADDRESS);

String dbaasUrl = dbaasAgentUrl;
if(securityConfig.k8sEnabled()) {
if(dbaasConfig.dbaasUrl().isEmpty()) {
log.warn("DBaaS address is not available, falling back to dbaas-agent. Specify 'api.dbaas.address' property to DBaaS url");
}
dbaasUrl = dbaasConfig.dbaasUrl().orElse(dbaasAgentUrl);
}

OkHttpClient httpClient = M2MClientFactory.getDbaasOkHttpClient(() -> M2MManager.getInstance().getToken().getTokenValue());

httpClient = httpClient.newBuilder()
.addInterceptor(chain -> {
Request original = chain.request();
Token token = M2MManager.getInstance().getToken();
String credentials = token.getTokenType() + " " + token.getTokenValue();
Request.Builder requestBuilder = original.newBuilder()
.addHeader("Authorization", credentials);
Request.Builder requestBuilder = original.newBuilder();
Optional<TenantContextObject> tenantContextData = ContextManager.getSafe(TENANT_CONTEXT_NAME);
if (tenantContextData.isPresent() && tenantContextData.get().getTenant() != null) {
requestBuilder.addHeader("tenant", tenantContextData.get().getTenant());
Expand All @@ -44,6 +57,6 @@ public DbaasClient build() {
.addInterceptor(new RetryInterceptor(MAX_RETRIES, INITIAL_RETRY_DELAY))
.sslSocketFactory(TlsUtils.getSslContext().getSocketFactory(), TlsUtils.getTrustManager())
.build();
return new DbaaSClientOkHttpImpl(url, httpClient);
return new DbaaSClientOkHttpImpl(dbaasUrl, httpClient);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.netcracker.cloud.dbaas.common.config;

import io.smallrye.config.ConfigMapping;
import io.smallrye.config.WithDefault;
import io.smallrye.config.WithName;

@ConfigMapping(prefix = "security.m2m")
public interface SecurityConfig {
/**
* kubernetes tokens authentication enabled
*/
@WithName("kubernetes.enabled")
@WithDefault("false")
boolean k8sEnabled();
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,18 @@
class M2MDbaaSClientTest {
private M2MDbaaSClient m2MDbaaSClient;
private static final String DB_AGENT_URL = "http://dbaas-agent:8080";
private static final String DB_AGGREGATOR_URL = "http://dbaas-aggregator:8080";

@BeforeEach
void setUp() {
DbaasClientConfig config = mock(DbaasClientConfig.class);
when(config.dbaasAgentUrl()).thenReturn(Optional.of(DB_AGENT_URL));
m2MDbaaSClient = new M2MDbaaSClient(config);
SecurityConfig securityConfig = mock(SecurityConfig.class);
when(securityConfig.k8sEnabled()).thenReturn(true);

DbaasClientConfig dbaasConfig = mock(DbaasClientConfig.class);
when(dbaasConfig.dbaasAgentUrl()).thenReturn(Optional.of(DB_AGENT_URL));
when(dbaasConfig.dbaasUrl()).thenReturn(Optional.of(DB_AGGREGATOR_URL));

m2MDbaaSClient = new M2MDbaaSClient(securityConfig, dbaasConfig);
}
@Test
void testBuild() throws NoSuchFieldException, IllegalAccessException {
Expand All @@ -29,8 +36,6 @@ void testBuild() throws NoSuchFieldException, IllegalAccessException {
clientField.setAccessible(true);
OkHttpClient clientValue = (OkHttpClient) clientField.get(client);
assertNotNull(client);
assertEquals(2, clientValue.interceptors().size());
assertEquals(3, clientValue.interceptors().size());
}
}


Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,12 @@
<groupId>com.netcracker.cloud.security.core.utils</groupId>
<artifactId>tls-utils</artifactId>
</dependency>
<!--Test-->
<dependency>
<groupId>com.netcracker.cloud.security.core.utils</groupId>
<artifactId>k8s-utils</artifactId>
<version>3.1.0-SNAPSHOT</version>
</dependency>
<!--Test-->
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-junit</artifactId>
Expand Down
Loading
Loading