getAvailableInstances() {
return clientFactory.getAvailableInstances();
diff --git a/external-service-ocp/src/test/java/org/opendevstack/apiservice/externalservice/ocp/integration/OpenshiftApiClientFactoryCacheIntegrationTest.java b/external-service-ocp/src/test/java/org/opendevstack/apiservice/externalservice/ocp/integration/OpenshiftApiClientFactoryCacheIntegrationTest.java
new file mode 100644
index 0000000..ab8620d
--- /dev/null
+++ b/external-service-ocp/src/test/java/org/opendevstack/apiservice/externalservice/ocp/integration/OpenshiftApiClientFactoryCacheIntegrationTest.java
@@ -0,0 +1,119 @@
+package org.opendevstack.apiservice.externalservice.ocp.integration;
+
+import org.opendevstack.apiservice.externalservice.ocp.client.OpenshiftApiClient;
+import org.opendevstack.apiservice.externalservice.ocp.client.OpenshiftApiClientFactory;
+import org.opendevstack.apiservice.externalservice.ocp.exception.OpenshiftException;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.TestPropertySource;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+/**
+ * Integration tests for the {@link OpenshiftApiClientFactory} client cache.
+ *
+ * The {@code @Cacheable} annotation on {@link OpenshiftApiClientFactory#getClient(String)} is only
+ * activated by the Spring AOP proxy, so caching behaviour must be verified with a real
+ * {@link org.springframework.boot.test.context.SpringBootTest} context rather than a plain
+ * Mockito unit test.
+ *
+ *
Tests define two lightweight, fake OpenShift instances via {@link TestPropertySource}.
+ * No real OpenShift connectivity is required – the clients are created but never used to make
+ * API calls.
+ */
+@SpringBootTest(classes = OpenshiftIntegrationTestConfig.class)
+@TestPropertySource(properties = {
+ "externalservices.openshift.instances.dev.api-url=https://api.dev.ocp.example.com:6443",
+ "externalservices.openshift.instances.dev.token=fake-dev-token",
+ "externalservices.openshift.instances.dev.namespace=dev-ns",
+ "externalservices.openshift.instances.dev.trust-all-certificates=true",
+ "externalservices.openshift.instances.staging.api-url=https://api.staging.ocp.example.com:6443",
+ "externalservices.openshift.instances.staging.token=fake-staging-token",
+ "externalservices.openshift.instances.staging.namespace=staging-ns",
+ "externalservices.openshift.instances.staging.trust-all-certificates=true"
+})
+class OpenshiftApiClientFactoryCacheIntegrationTest {
+
+ @Autowired
+ private OpenshiftApiClientFactory factory;
+
+ // -------------------------------------------------------------------------
+ // Same instance name → same cached instance
+ // -------------------------------------------------------------------------
+
+ @Test
+ void getClient_sameInstanceName_returnsCachedInstance() throws OpenshiftException {
+ OpenshiftApiClient first = factory.getClient("dev");
+ OpenshiftApiClient second = factory.getClient("dev");
+
+ assertSame(first, second,
+ "Repeated calls with the same instance name must return the cached client");
+ }
+
+ @Test
+ void getClient_sameInstanceName_multipleCallsAlwaysReturnSameInstance() throws OpenshiftException {
+ OpenshiftApiClient reference = factory.getClient("staging");
+
+ for (int i = 0; i < 5; i++) {
+ assertSame(reference, factory.getClient("staging"),
+ "Call #" + (i + 1) + " should return the same cached client for 'staging'");
+ }
+ }
+
+ // -------------------------------------------------------------------------
+ // Different instance names → different instances
+ // -------------------------------------------------------------------------
+
+ @Test
+ void getClient_differentInstanceNames_returnDifferentInstances() throws OpenshiftException {
+ OpenshiftApiClient dev = factory.getClient("dev");
+ OpenshiftApiClient staging = factory.getClient("staging");
+
+ assertNotSame(dev, staging,
+ "Different instance names must produce distinct client objects");
+ assertEquals("dev", dev.getInstanceName());
+ assertEquals("staging", staging.getInstanceName());
+ }
+
+ // -------------------------------------------------------------------------
+ // Default client is cached
+ // -------------------------------------------------------------------------
+
+ @Test
+ void getDefaultClient_returnsCachedInstance() throws OpenshiftException {
+ OpenshiftApiClient first = factory.getDefaultClient();
+ OpenshiftApiClient second = factory.getDefaultClient();
+
+ assertSame(first, second,
+ "Repeated calls to getDefaultClient must return the cached client");
+ }
+
+ // -------------------------------------------------------------------------
+ // clearCache evicts all entries
+ // -------------------------------------------------------------------------
+
+ @Test
+ void clearCache_evictsAllCachedClients() throws OpenshiftException {
+ OpenshiftApiClient before = factory.getClient("dev");
+
+ factory.clearCache();
+
+ OpenshiftApiClient after = factory.getClient("dev");
+ assertNotSame(before, after,
+ "After clearing cache, a new client instance should be created");
+ }
+
+ // -------------------------------------------------------------------------
+ // Get client with null/blank instance name should throw exception
+ // -------------------------------------------------------------------------
+ @Test
+ void getClient_nullOrBlankInstanceName_throwsExceptionAndDoesNotCache() {
+ assertThrows(OpenshiftException.class, () -> factory.getClient(null),
+ "Calling getClient with null instance name should throw OpenshiftException");
+ assertThrows(OpenshiftException.class, () -> factory.getClient(""),
+ "Calling getClient with blank instance name should throw OpenshiftException");
+ assertThrows(OpenshiftException.class, () -> factory.getClient(" "),
+ "Calling getClient with blank instance name should throw OpenshiftException");
+ }
+}
diff --git a/external-service-ocp/src/test/java/org/opendevstack/apiservice/externalservice/ocp/integration/OpenshiftIntegrationTest.java b/external-service-ocp/src/test/java/org/opendevstack/apiservice/externalservice/ocp/integration/OpenshiftIntegrationTest.java
index d9876a7..b372068 100644
--- a/external-service-ocp/src/test/java/org/opendevstack/apiservice/externalservice/ocp/integration/OpenshiftIntegrationTest.java
+++ b/external-service-ocp/src/test/java/org/opendevstack/apiservice/externalservice/ocp/integration/OpenshiftIntegrationTest.java
@@ -3,13 +3,11 @@
import org.opendevstack.apiservice.externalservice.ocp.exception.OpenshiftException;
import org.opendevstack.apiservice.externalservice.ocp.service.OpenshiftService;
import lombok.extern.slf4j.Slf4j;
-import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable;
import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
-import org.springframework.context.annotation.ComponentScan;
-import org.springframework.context.annotation.Configuration;
import org.springframework.test.context.ActiveProfiles;
import java.util.Map;
@@ -18,125 +16,67 @@
/**
* Integration tests for OpenShift Service
- * These tests require actual OpenShift cluster connectivity
+ *
+ * This test runs against a real OpenShift cluster configured in application-local.yaml.
+ * It requires actual OpenShift connectivity and valid credentials.
*
* To run these tests:
- * 1. Ensure you have proper OpenShift configuration in application-local.yaml or environment variables
- * 2. Make sure the OpenShift token has access to the namespace
- * 3. Remove @Disabled annotation from the test you want to run
- * 4. Run with: mvn test -Dtest=OpenshiftIntegrationTest
+ * 1. Ensure application-local.yaml has valid OpenShift configuration
+ * 2. Set environment variable: OPENSHIFT_INTEGRATION_TEST_ENABLED=true
+ * 3. Set test cluster details:
+ * - OPENSHIFT_TEST_CLUSTER_API_URL (e.g., "https://api.example.ocp.cloud.com:6443")
+ * - OPENSHIFT_TEST_CLUSTER_TOKEN (e.g., "sha256~exampletoken1234567890abcdef")
+ * - OPENSHIFT_TEST_DEFAULT_NAMESPACE (e.g., "example-namespace")
+ * - OPENSHIFT_TEST_INSTANCE (e.g., "cluster-1" or "cluster-2")
+ * - OPENSHIFT_TEST_SECRET_NAME (e.g., "example-secret")
+ * - OPENSHIFT_TEST_PROJECT_NAME (e.g., "example-project")
+ *
+ * Example:
+ * export OPENSHIFT_INTEGRATION_TEST_ENABLED=true
+ * export OPENSHIFT_TEST_CLUSTER_API_URL="https://api.example.ocp.cloud.com:6443"
+ * export OPENSHIFT_TEST_CLUSTER_TOKEN="sha256~exampletoken1234567890abcdef"
+ * export OPENSHIFT_TEST_DEFAULT_NAMESPACE=example-namespace
+ * export OPENSHIFT_TEST_INSTANCE=cluster-1
+ * export OPENSHIFT_TEST_SECRET_NAME=example-secret
+ * export OPENSHIFT_TEST_PROJECT_NAME=example-project
+ *
+ * Then run: mvn test -Dtest=OpenshiftIntegrationTest
*/
-@SpringBootTest(classes = OpenshiftIntegrationTest.TestConfiguration.class)
+@SpringBootTest(classes = OpenshiftIntegrationTestConfig.class)
@ActiveProfiles("local")
+@EnabledIfEnvironmentVariable(named = "OPENSHIFT_INTEGRATION_TEST_ENABLED", matches = "true")
@Slf4j
-@Disabled("Integration tests require actual OpenShift cluster access - enable manually when needed")
class OpenshiftIntegrationTest {
- @Configuration
- @EnableAutoConfiguration
- @ComponentScan(basePackages = "org.opendevstack.apiservice.externalservice.ocp")
- static class TestConfiguration {
- }
@Autowired
private OpenshiftService openshiftService;
- /**
- * Test to retrieve a specific secret from the example-project-cd namespace in cluster-a cluster
- *
- * Before running this test:
- * 1. Ensure OPENSHIFT_CLUSTER_A_API_URL environment variable is set
- * 2. Ensure OPENSHIFT_CLUSTER_A_TOKEN environment variable is set with a valid token
- * 3. Verify the token has access to the example-project-cd namespace
- * 4. Remove @Disabled annotation
- */
- @Test
- @Disabled("Remove this annotation to run the test")
- void testGetTriggerSecretFromRompiCdNamespace() {
- // Configuration
- String instanceName = "cluster-a";
- String namespace = "example-project-cd";
- String secretName = "webhook-proxy";
-
- log.info("Attempting to retrieve secret '{}' from namespace '{}' in instance '{}'",
- secretName, namespace, instanceName);
-
- try {
- // Verify instance is configured
- assertTrue(openshiftService.hasInstance(instanceName),
- "Instance '" + instanceName + "' is not configured");
- log.info("✓ Instance '{}' is configured", instanceName);
-
- // Check if secret exists
- boolean exists = openshiftService.secretExists(instanceName, secretName, namespace);
- assertTrue(exists,
- "Secret '" + secretName + "' does not exist in namespace '" + namespace + "'");
- log.info("✓ Secret '{}' exists in namespace '{}'", secretName, namespace);
-
- // Get the entire secret
- Map secret = openshiftService.getSecret(instanceName, secretName, namespace);
-
- // Assertions
- assertNotNull(secret, "Secret should not be null");
- assertFalse(secret.isEmpty(), "Secret should not be empty");
-
- // Log secret keys (not values for security)
- log.info("✓ Successfully retrieved secret with {} keys", secret.size());
- log.info("Secret keys: {}", secret.keySet());
-
- // Example: Get a specific value from the secret
- if (!secret.isEmpty()) {
- String firstKey = secret.keySet().iterator().next();
- String value = openshiftService.getSecretValue(instanceName, secretName, firstKey, namespace);
- assertNotNull(value, "Secret value should not be null");
- log.info("✓ Successfully retrieved value for key '{}'", firstKey);
- }
-
- } catch (OpenshiftException e) {
- log.error("Failed to retrieve secret", e);
- fail("Should be able to retrieve the secret: " + e.getMessage());
- }
- }
-
- /**
- * Test to get a specific value from the webhook-proxy
- * Customize this test based on the keys you know exist in the secret
- */
- @Test
- @Disabled("Remove this annotation and customize with actual key names")
- void testGetSpecificValueFromTriggerSecret() {
- String instanceName = "cluster-a";
- String namespace = "example-project-cd";
- String secretName = "webhook-proxy";
- String keyName = "trigger-secret"; // Replace with actual key name
-
- log.info("Attempting to retrieve key '{}' from secret '{}'", keyName, secretName);
-
- try {
- String value = openshiftService.getSecretValue(instanceName, secretName, keyName, namespace);
-
- assertNotNull(value, "Secret value should not be null");
- assertFalse(value.isEmpty(), "Secret value should not be empty");
-
- log.info("✓ Successfully retrieved value for key '{}'", keyName);
- log.info("Value length: {} characters", value.length());
-
- } catch (OpenshiftException e) {
- log.error("Failed to retrieve secret value", e);
- fail("Should be able to retrieve the secret value: " + e.getMessage());
- }
+ private String testInstance;
+ private String testNamespace;
+ private String testSecretName;
+ private String testProjectName;
+
+ @BeforeEach
+ void setUp() {
+ // Read test parameters from environment variables
+ testInstance = System.getenv().getOrDefault("OPENSHIFT_TEST_INSTANCE", "cluster-a");
+ testNamespace = System.getenv().getOrDefault("OPENSHIFT_TEST_DEFAULT_NAMESPACE", "example-project-cd");
+ testSecretName = System.getenv().getOrDefault("OPENSHIFT_TEST_SECRET_NAME", "webhook-proxy");
+ testProjectName = System.getenv().getOrDefault("OPENSHIFT_TEST_PROJECT_NAME", "example-project");
+
+ log.info("Running integration tests against OpenShift instance: {}", testInstance);
+ log.info("Test namespace: {}", testNamespace);
+ log.info("Test secret: {}", testSecretName);
+ log.info("Test project: {}", testProjectName);
}
-
- /**
- * Helper test to list all available instances
- */
+
@Test
- @Disabled("Remove this annotation to check configured instances")
- void testListAvailableInstances() {
- log.info("Listing available OpenShift instances");
-
+ void testGetAvailableInstances() {
+ // Act
var instances = openshiftService.getAvailableInstances();
-
+
+ // Assert
assertNotNull(instances, "Available instances should not be null");
assertFalse(instances.isEmpty(), "Should have at least one configured instance");
@@ -144,51 +84,192 @@ void testListAvailableInstances() {
instances.forEach(instance -> {
log.info(" - {}", instance);
});
-
- assertTrue(instances.contains("cluster-a"),
- "cluster-a instance should be configured");
}
-
- /**
- * Test to verify all keys in the webhook-proxy
- * Useful to discover what's inside the secret
- */
+
@Test
- @Disabled("Remove this annotation to discover secret contents")
- void testDiscoverTriggerSecretContents() {
- String instanceName = "cluster-a";
- String namespace = "example-project-cd";
- String secretName = "webhook-proxy";
-
- log.info("Discovering contents of secret '{}'", secretName);
+ void testHasInstance() {
+ // Act
+ boolean hasInstance = openshiftService.hasInstance(testInstance);
+
+ // Assert
+ assertTrue(hasInstance, "Test instance '" + testInstance + "' should be configured");
+ log.info("✓ Instance '{}' is configured", testInstance);
+ }
+
+ @Test
+ void testHasInstance_NonExistent() {
+ // Act
+ boolean hasInstance = openshiftService.hasInstance("nonexistent-instance-xyz");
+
+ // Assert
+ assertFalse(hasInstance, "Non-existent instance should return false");
+ log.info("✓ Non-existent instance correctly returned false");
+ }
+
+ @Test
+ void testHealthCheck() {
+ // Act
+ boolean isHealthy = openshiftService.isHealthy();
+
+ // Assert
+ assertTrue(isHealthy, "OpenShift service should be healthy");
+ log.info("✓ OpenShift service is healthy");
+ }
+
+ // -------------------------------------------------------------------------
+ // Test secret existence.
+ // -------------------------------------------------------------------------
+
+ @Test
+ void testSecretExists_ExistingSecret() throws OpenshiftException {
+ // Act
+ boolean exists = openshiftService.secretExists(testInstance, testSecretName, testNamespace);
+
+ // Assert
+ // Note: This may be true or false depending on the test environment
+ // We just verify the method executes without exception
+ log.info("Secret '{}' exists in namespace '{}': {}", testSecretName, testNamespace, exists);
+ }
+
+ @Test
+ void testSecretExists_NonExistentSecret() throws OpenshiftException {
+ // Arrange
+ String nonExistentSecret = "nonexistent-secret-xyz-12345";
+
+ // Act
+ boolean exists = openshiftService.secretExists(testInstance, nonExistentSecret, testNamespace);
+
+ // Assert
+ assertFalse(exists, "Non-existent secret should return false");
+ log.info("✓ Verified that secret '{}' does not exist", nonExistentSecret);
+ }
+
+ @Test
+ void testSecretExists_NamespaceNotProvided() throws OpenshiftException {
+ // Act
+ boolean exists = openshiftService.secretExists(testInstance, testSecretName);
+
+ // Assert
+ // Note: This may be true or false depending on the default namespace configuration
+ // We just verify the method executes without exception
+ log.info("Secret '{}' exists in default namespace: {}", testSecretName, exists);
+ }
+
+ @Test
+ void testSecretExists_WithConsistentBehavior() throws OpenshiftException {
+ // Act - Check with and without namespace
+ boolean existsWithNamespace = openshiftService.secretExists(testInstance, testSecretName, testNamespace);
+ boolean existsWithoutNamespace = openshiftService.secretExists(testInstance, testSecretName);
+
+ // Assert - Both should return consistent results (either both true or both false)
+ // Note: They may differ if the default namespace is different from the test namespace
+ log.info("Secret '{}' exists with namespace: {}", testSecretName, existsWithNamespace);
+ log.info("Secret '{}' exists without namespace: {}", testSecretName, existsWithoutNamespace);
+ }
+
+ // -------------------------------------------------------------------------
+ // Test secret retrieval.
+ // -------------------------------------------------------------------------
+
+ @Test
+ void testGetSecret_Success() throws OpenshiftException {
+ // Act
+ Map secret = openshiftService.getSecret(testInstance, testSecretName, testNamespace);
+
+ // Assert
+ assertNotNull(secret, "Secret should not be null");
+ log.info("✓ Successfully retrieved secret with {} keys", secret.size());
- try {
- Map secret = openshiftService.getSecret(instanceName, secretName, namespace);
-
- log.info("Secret '{}' contains the following keys:", secretName);
- secret.forEach((key, value) -> {
- log.info(" - Key: '{}', Value length: {} characters", key, value.length());
- });
-
- // Print sanitized info (first and last 2 chars only)
- secret.forEach((key, value) -> {
- String sanitized = sanitizeValue(value);
- log.info(" - {}: {}", key, sanitized);
- });
-
- } catch (OpenshiftException e) {
- log.error("Failed to discover secret contents", e);
- fail("Should be able to retrieve the secret: " + e.getMessage());
- }
+ // Log secret keys (not values for security)
+ log.info("Secret keys: {}", secret.keySet());
+ }
+
+ @Test
+ void testGetSecret_NonExistentSecret() {
+ // Arrange
+ String nonExistentSecret = "nonexistent-secret-xyz-12345";
+
+ // Act & Assert
+ OpenshiftException exception = assertThrows(OpenshiftException.class, () ->
+ openshiftService.getSecret(testInstance, nonExistentSecret, testNamespace)
+ );
+
+ assertTrue(
+ exception.getMessage().contains("Failed to retrieve") ||
+ exception.getMessage().contains("not found"),
+ "Exception should indicate secret not found or retrieval failed"
+ );
+ log.info("Expected exception for non-existent secret: {}", exception.getMessage());
}
-
- /**
- * Sanitize sensitive values for logging
- */
- private String sanitizeValue(String value) {
- if (value == null || value.length() < 4) {
- return "****";
+
+ // -------------------------------------------------------------------------
+ // Test secret value retrieval.
+ // -------------------------------------------------------------------------
+
+ @Test
+ void testGetSecretValue_Success() throws OpenshiftException {
+ // First get the secret to find available keys
+ Map secret = openshiftService.getSecret(testInstance, testSecretName, testNamespace);
+
+ if (!secret.isEmpty()) {
+ // Use the first available key
+ String key = secret.keySet().iterator().next();
+
+ // Act
+ String value = openshiftService.getSecretValue(testInstance, testSecretName, key, testNamespace);
+
+ // Assert
+ assertNotNull(value, "Secret value should not be null");
+ log.info("✓ Successfully retrieved value for key '{}'", key);
+ } else {
+ log.warn("Secret is empty, skipping value retrieval test");
}
- return value.substring(0, 2) + "****" + value.substring(value.length() - 2);
}
+
+ @Test
+ void testGetSecretValue_NonExistentKey() {
+ // Arrange
+ String nonExistentKey = "nonexistent-key-xyz";
+
+ // Act & Assert
+ OpenshiftException exception = assertThrows(OpenshiftException.class, () ->
+ openshiftService.getSecretValue(testInstance, testSecretName, nonExistentKey, testNamespace)
+ );
+
+ assertTrue(
+ exception.getMessage().contains("not found") ||
+ exception.getMessage().contains("Failed"),
+ "Exception should indicate key not found"
+ );
+ log.info("Expected exception for non-existent key: {}", exception.getMessage());
+ }
+
+ // -------------------------------------------------------------------------
+ // Test project existence.
+ // -------------------------------------------------------------------------
+
+
+ @Test
+ void testProjectExists_ExistingProject() throws OpenshiftException {
+ // Act
+ boolean exists = openshiftService.projectExists(testInstance, testProjectName);
+
+ // Assert
+ assertTrue(exists, "Project '" + testProjectName + "' should exist in instance '" + testInstance + "'");
+ log.info("✓ Project '{}' exists in instance '{}'", testProjectName, testInstance);
+ }
+
+ @Test
+ void testProjectExists_NonExistentProject() throws OpenshiftException {
+ // Arrange
+ String nonExistentProject = "nonexistent-project-xyz-12345";
+
+ // Act
+ boolean exists = openshiftService.projectExists(testInstance, nonExistentProject);
+
+ // Assert
+ assertFalse(exists, "Non-existent project should return false");
+ log.info("✓ Verified that project '{}' does not exist", nonExistentProject);
+ }
+
}
diff --git a/external-service-ocp/src/test/java/org/opendevstack/apiservice/externalservice/ocp/integration/OpenshiftIntegrationTestConfig.java b/external-service-ocp/src/test/java/org/opendevstack/apiservice/externalservice/ocp/integration/OpenshiftIntegrationTestConfig.java
new file mode 100644
index 0000000..eff596e
--- /dev/null
+++ b/external-service-ocp/src/test/java/org/opendevstack/apiservice/externalservice/ocp/integration/OpenshiftIntegrationTestConfig.java
@@ -0,0 +1,20 @@
+package org.opendevstack.apiservice.externalservice.ocp.integration;
+
+import org.springframework.boot.SpringBootConfiguration;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.cache.annotation.EnableCaching;
+import org.springframework.context.annotation.ComponentScan;
+
+/**
+ * Test configuration for OpenShift integration tests.
+ * This configuration enables Spring Boot auto-configuration, caching and component scanning
+ * for the OpenShift service module.
+ */
+@SpringBootConfiguration
+@EnableAutoConfiguration
+@EnableCaching
+@ComponentScan(basePackages = "org.opendevstack.apiservice.externalservice.ocp")
+public class OpenshiftIntegrationTestConfig {
+ // Configuration class for integration tests
+ // All beans will be auto-configured by Spring Boot
+}
diff --git a/external-service-ocp/src/test/java/org/opendevstack/apiservice/externalservice/ocp/service/OpenshiftServiceTest.java b/external-service-ocp/src/test/java/org/opendevstack/apiservice/externalservice/ocp/service/OpenshiftServiceTest.java
index 8fe4edc..9f0f64e 100644
--- a/external-service-ocp/src/test/java/org/opendevstack/apiservice/externalservice/ocp/service/OpenshiftServiceTest.java
+++ b/external-service-ocp/src/test/java/org/opendevstack/apiservice/externalservice/ocp/service/OpenshiftServiceTest.java
@@ -84,6 +84,7 @@ void testGetSecretWithNamespace_Success() throws OpenshiftException {
verify(apiClient).getSecret(secretName, namespace);
}
+
@Test
void testGetSecretValue_Success() throws OpenshiftException {
// Arrange
@@ -197,6 +198,63 @@ void testSecretExists_HandlesException() throws OpenshiftException {
verify(apiClient, never()).secretExists(anyString());
}
+ @Test
+ void testProjectExists_ReturnsTrue() throws OpenshiftException {
+ // Arrange
+ String instanceName = "dev";
+ String projectName = "existing-project";
+
+ when(clientFactory.getClient(instanceName)).thenReturn(apiClient);
+ when(apiClient.projectExists(projectName)).thenReturn(true);
+
+ // Act
+ boolean result = openshiftService.projectExists(instanceName, projectName);
+
+ // Assert
+ assertTrue(result);
+ verify(clientFactory).getClient(instanceName);
+ verify(apiClient).projectExists(projectName);
+ }
+
+ @Test
+ void testProjectExists_ReturnsFalse() throws OpenshiftException {
+ // Arrange
+ String instanceName = "dev";
+ String projectName = "non-existing-project";
+
+ when(clientFactory.getClient(instanceName)).thenReturn(apiClient);
+ when(apiClient.projectExists(projectName)).thenReturn(false);
+
+ // Act
+ boolean result = openshiftService.projectExists(instanceName, projectName);
+
+ // Assert
+ assertFalse(result);
+ verify(clientFactory).getClient(instanceName);
+ verify(apiClient).projectExists(projectName);
+ }
+
+ @Test
+ void testProjectExists_ThrowsException() throws OpenshiftException {
+ // Arrange
+ String instanceName = "dev";
+ String projectName = "test-project";
+ String errorMessage = "Connection failed";
+
+ when(clientFactory.getClient(instanceName)).thenReturn(apiClient);
+ when(apiClient.projectExists(projectName)).thenThrow(new OpenshiftException(errorMessage));
+
+ // Act & Assert
+ OpenshiftException exception = assertThrows(
+ OpenshiftException.class,
+ () -> openshiftService.projectExists(instanceName, projectName)
+ );
+
+ assertEquals(errorMessage, exception.getMessage());
+ verify(clientFactory).getClient(instanceName);
+ verify(apiClient).projectExists(projectName);
+ }
+
@Test
void testGetAvailableInstances() {
// Arrange
diff --git a/external-service-ocp/src/test/resources/application-local.yaml b/external-service-ocp/src/test/resources/application-local.yaml
index 3ed8ade..e7ce716 100644
--- a/external-service-ocp/src/test/resources/application-local.yaml
+++ b/external-service-ocp/src/test/resources/application-local.yaml
@@ -3,14 +3,14 @@ logging:
org.opendevstack.apiservice.externalservice.ocp: DEBUG
# OpenShift Configuration for Integration Tests
-externalservice:
+externalservices:
openshift:
instances:
# Cluster A OpenShift instance
cluster-a:
- api-url: ${OPENSHIFT_CLUSTER_A_API_URL:https://api.cluster-a.ocp.example.com:6443}
- token: ${OPENSHIFT_US_TEST_TOKEN:your-token-here}
- namespace: ${OPENSHIFT_US_TEST_NAMESPACE:example-project-cd}
+ api-url: ${OPENSHIFT_TEST_CLUSTER_API_URL:https://api.cluster-a.ocp.example.com:6443}
+ token: ${OPENSHIFT_TEST_CLUSTER_TOKEN:your-token-here}
+ namespace: ${OPENSHIFT_TEST_DEFAULT_NAMESPACE:example-project-cd}
connection-timeout: 30000
read-timeout: 30000
- trust-all-certificates: ${OPENSHIFT_US_TEST_TRUST_ALL:true}
+ trust-all-certificates: ${OPENSHIFT_TEST_TRUST_ALL:true}
diff --git a/launch.json b/launch.json
new file mode 100644
index 0000000..5f969b6
--- /dev/null
+++ b/launch.json
@@ -0,0 +1,28 @@
+
+{
+ "version": "0.2.0",
+ "configurations": [
+ {
+ "type": "java",
+ "name": "Debug (Launch) - ODS API Service",
+ "request": "launch",
+ "mainClass": "org.opendevstack.apiservice.core.DevstackApiServiceApplication",
+ "projectName": "core",
+ "envFile": "${workspaceFolder}/../dev.env"
+ },
+ {
+ "type": "java",
+ "name": "Debug Current Test",
+ "request": "launch",
+ "mainClass": "",
+ "envFile": "${workspaceFolder}/../dev.env"
+ },
+ {
+ "type": "java",
+ "name": "Debug Integration tests",
+ "request": "launch",
+ "mainClass": "",
+ "envFile": "${workspaceFolder}/../dev.env"
+ }
+ ]
+}
diff --git a/settings.json b/settings.json
new file mode 100644
index 0000000..a207644
--- /dev/null
+++ b/settings.json
@@ -0,0 +1,24 @@
+{
+ "chat.promptFilesRecommendations": {
+ "speckit.constitution": true,
+ "speckit.specify": true,
+ "speckit.plan": true,
+ "speckit.tasks": true,
+ "speckit.implement": true
+ },
+ "chat.tools.terminal.autoApprove": {
+ ".specify/scripts/bash/": true,
+ ".specify/scripts/powershell/": true,
+ "./mvnw": true,
+ "mvn clean": true
+ },
+ "java.test.config": {
+ "name": "Integration Tests",
+ "envFile": "${workspaceFolder}/../dev.env",
+ "vmArgs": [
+ "-Dspring.profiles.active=local"
+ ]
+ },
+ "java.configuration.updateBuildConfiguration": "interactive",
+ "java.compile.nullAnalysis.mode": "automatic"
+}