Skip to content
Snippets Groups Projects
Commit 69890d5c authored by OZGCloud's avatar OZGCloud
Browse files

OZG-4453 revert stringData -> data; using data for encoding and string for plane text

parent 1b239d60
No related branches found
No related tags found
No related merge requests found
package de.ozgcloud.operator;
import java.util.Base64;
import java.util.logging.Level;
import org.apache.commons.collections.MapUtils;
......@@ -19,12 +20,13 @@ import lombok.extern.java.Log;
@RequiredArgsConstructor
@ControllerConfiguration
@Component
public class ElasticsearchReconciler implements Reconciler<OzgCloudElasticsearchCustomResource>, Cleaner<OzgCloudElasticsearchCustomResource> {
public class ElasticsearchReconciler implements Reconciler<OzgCloudElasticsearchCustomResource>, Cleaner<OzgCloudElasticsearchCustomResource> {
private final OzgCloudElasticsearchService service;
@Override
public UpdateControl<OzgCloudElasticsearchCustomResource> reconcile(OzgCloudElasticsearchCustomResource resource, Context<OzgCloudElasticsearchCustomResource> context) {
public UpdateControl<OzgCloudElasticsearchCustomResource> reconcile(OzgCloudElasticsearchCustomResource resource,
Context<OzgCloudElasticsearchCustomResource> context) {
try {
log.info("Reconcile user " + resource.getCRDName() + "...");
var namespace = resource.getMetadata().getNamespace();
......@@ -40,15 +42,24 @@ public class ElasticsearchReconciler implements Reconciler<OzgCloudElasticsearch
return buildExceptionUpdateControl(resource, exception);
}
}
private String getPassword(Secret secret) {
String getPassword(Secret secret) {
log.info("get password for elastic user...");
log.info(String.format("from secret string map: %s", secret.getStringData()));
log.info(String.format("from secret data map: %s", secret.getData()));
return MapUtils.getString(secret.getData(), OzgCloudElasticsearchSecretHelper.CREDENTIAL_SECRET_PASSWORD_FIELD);
return decode(MapUtils.getString(secret.getData(), OzgCloudElasticsearchSecretHelper.CREDENTIAL_SECRET_PASSWORD_FIELD));
}
UpdateControl<OzgCloudElasticsearchCustomResource> buildExceptionUpdateControl(OzgCloudElasticsearchCustomResource resource, Exception exception) {
private String decode(String encodedPassword) {
try {
return new String(Base64.getDecoder().decode(encodedPassword));
} catch (Exception e) {
throw new RuntimeException("Could not decode password from secret.");
}
}
UpdateControl<OzgCloudElasticsearchCustomResource> buildExceptionUpdateControl(OzgCloudElasticsearchCustomResource resource,
Exception exception) {
return OzgCloudElasticsearchUpdateControlBuilder
.fromResource(resource)
.withStatus(CustomResourceStatus.ERROR)
......@@ -56,7 +67,7 @@ public class ElasticsearchReconciler implements Reconciler<OzgCloudElasticsearch
.withMessage(exception.getMessage())
.build();
}
@Override
public DeleteControl cleanup(OzgCloudElasticsearchCustomResource resource, Context<OzgCloudElasticsearchCustomResource> context) {
var namespace = resource.getMetadata().getNamespace();
......@@ -65,7 +76,7 @@ public class ElasticsearchReconciler implements Reconciler<OzgCloudElasticsearch
service.deleteSecurityRoleIfExists(namespace);
service.deleteIndexIfExists(namespace);
return DeleteControl.defaultDelete();
} catch(Exception e) {
} catch (Exception e) {
log.log(Level.INFO, String.format("Could not cleanup elasticsearch resource in namespace %s. %n %s", namespace, e));
return DeleteControl.defaultDelete();
}
......
......@@ -13,37 +13,37 @@ import lombok.RequiredArgsConstructor;
public class OzgCloudElasticsearchSecretHelper {
static final String SECRET_TYPE = "Opaque";
static final String CREDENTIAL_SECRET_ADDRESS_FIELD = "address";
static final String CREDENTIAL_SECRET_INDEX_FIELD = "index";
static final String CREDENTIAL_SECRET_PASSWORD_FIELD = "password";
static final String CREDENTIAL_SECRET_USERNAME_FIELD = "username";
static final String CERTIFICATE_SECRET_DATA_KEY = "ca.crt";
static final int PASSWORD_LENGTH = 15;
private final OzgCloudElasticsearchProperties properties;
public Secret buildCredentialSecret(String namespace, String name) {
return new SecretBuilder()
.withType(SECRET_TYPE)
.withMetadata(createMetaData(name, namespace))
.addToData(CREDENTIAL_SECRET_ADDRESS_FIELD, buildSecretAddress())
.addToData(CREDENTIAL_SECRET_INDEX_FIELD, namespace)
.addToData(CREDENTIAL_SECRET_PASSWORD_FIELD, generatePassword())
.addToData(CREDENTIAL_SECRET_USERNAME_FIELD, namespace)
.addToStringData(CREDENTIAL_SECRET_ADDRESS_FIELD, buildSecretAddress())
.addToStringData(CREDENTIAL_SECRET_INDEX_FIELD, namespace)
.addToStringData(CREDENTIAL_SECRET_PASSWORD_FIELD, generatePassword())
.addToStringData(CREDENTIAL_SECRET_USERNAME_FIELD, namespace)
.build();
}
private String buildSecretAddress() {
return String.format("%s:%s", properties.getServer().getHost(), properties.getServer().getPort());
}
private String generatePassword() {
return RandomStringUtils.randomAlphabetic(PASSWORD_LENGTH);
}
public Secret buildCertificateSecret(String namespace, String data) {
return new SecretBuilder()
.withType(SECRET_TYPE)
......@@ -51,7 +51,7 @@ public class OzgCloudElasticsearchSecretHelper {
.addToData(CERTIFICATE_SECRET_DATA_KEY, data)
.build();
}
private ObjectMeta createMetaData(String name, String namespace) {
var metadata = new ObjectMeta();
metadata.setName(name);
......
......@@ -4,6 +4,9 @@ import static org.assertj.core.api.Assertions.*;
import static org.mockito.ArgumentMatchers.*;
import static org.mockito.Mockito.*;
import java.util.Base64;
import java.util.Map;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
......@@ -12,9 +15,12 @@ import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Spy;
import com.thedeanda.lorem.LoremIpsum;
import de.ozgcloud.operator.common.kubernetes.NamespaceTestFactory;
import de.ozgcloud.operator.common.kubernetes.SecretTestFactory;
import io.fabric8.kubernetes.api.model.Secret;
import io.fabric8.kubernetes.api.model.SecretBuilder;
import io.javaoperatorsdk.operator.api.reconciler.Context;
import io.javaoperatorsdk.operator.api.reconciler.UpdateControl;
import lombok.SneakyThrows;
......@@ -30,167 +36,196 @@ class ElasticsearchReconcilerTest {
@DisplayName("Reconcile")
@Nested
class TestReconcile {
@Mock
private Context<OzgCloudElasticsearchCustomResource> context;
private final OzgCloudElasticsearchCustomResource resource = ElasticsearchCustomResourceTestFactory.create();
private final static String PASSWORD = "dummyPassword";
private final Secret secret = SecretTestFactory.createBuilder().addToData(OzgCloudElasticsearchSecretHelper.CREDENTIAL_SECRET_PASSWORD_FIELD, PASSWORD).build();
private final static String PASSWORD = new String(Base64.getEncoder().encode("dummyPassword".getBytes()));
private final static String DECODED_PASSWORD = new String(Base64.getDecoder().decode(PASSWORD));
private final Secret secret = SecretTestFactory.createBuilder()
.addToData(OzgCloudElasticsearchSecretHelper.CREDENTIAL_SECRET_PASSWORD_FIELD, PASSWORD).build();
@DisplayName("process flow")
@Nested
class TestProcessFlow {
@BeforeEach
void mockCredentialSecret() {
when(service.getOrCreateCredentialSecret(any(), any())).thenReturn(secret);
}
@Test
void shouldGetCredentialSecret() {
reconcile();
verify(service).getOrCreateCredentialSecret(resource, context);
}
@SneakyThrows
@Test
void shouldCreateIndexIfMissing() {
reconcile();
verify(service).createIndexIfMissing(NamespaceTestFactory.NAMESPACE);
}
@SneakyThrows
@Test
void shouldCreateecurityRoleIfMissing() {
reconcile();
verify(service).createSecurityRoleIfMissing(NamespaceTestFactory.NAMESPACE);
}
@SneakyThrows
@Test
void shouldCallCreateSecurityUserIfMissing() {
reconcile();
verify(service).createSecurityUserIfMissing(NamespaceTestFactory.NAMESPACE, PASSWORD);
verify(service).createSecurityUserIfMissing(NamespaceTestFactory.NAMESPACE, DECODED_PASSWORD);
}
@SneakyThrows
@Test
void shouldCallCreateCertificateIfMissing() {
reconcile();
verify(service).createCertificateIfMissing(NamespaceTestFactory.NAMESPACE);
}
}
@DisplayName("on exception")
@Nested
class TestOnException {
private final Exception exception = new RuntimeException();
@BeforeEach
void mock() {
when(service.getOrCreateCredentialSecret(any(), any())).thenThrow(exception);
}
@Test
void shouldBuildExceptionUpdateControl() {
reconcile();
verify(reconciler).buildExceptionUpdateControl(resource, exception);
}
}
@SneakyThrows
private UpdateControl<OzgCloudElasticsearchCustomResource> reconcile() {
return reconciler.reconcile(resource, context);
}
@DisplayName("build exception update control")
@Nested
class TestBuildExceptionUpdateControl {
private final OzgCloudElasticsearchCustomResource resource = ElasticsearchCustomResourceTestFactory.create();
private final static String EXCEPTION_MESSAGE = "ExeptionMessage";
private final Exception exception = new RuntimeException(EXCEPTION_MESSAGE);
@Test
void shouldContainResource() {
var updateControl = buildExceptionUpdateControl();
assertThat(updateControl.getResource()).isEqualTo(resource);
}
@Test
void shouldContainUpdateStatus() {
var updateControl = buildExceptionUpdateControl();
assertThat(updateControl.getResource().getStatus().getStatus()).isEqualTo(CustomResourceStatus.ERROR);
}
@Test
void shouldContainReschedule() {
var updateControl = buildExceptionUpdateControl();
assertThat(updateControl.getScheduleDelay()).hasValue(60000L);
}
@Test
void shouldContainMessage() {
var updateControl = buildExceptionUpdateControl();
assertThat(updateControl.getResource().getStatus().getMessage()).isEqualTo(EXCEPTION_MESSAGE);
}
private UpdateControl<OzgCloudElasticsearchCustomResource> buildExceptionUpdateControl() {
return reconciler.buildExceptionUpdateControl(resource, exception);
}
}
@DisplayName("get password")
@Nested
class TestGetPassword {
private static final String SECRET_PASSWORD = LoremIpsum.getInstance().getWords(1);
@Test
void shouldReturnPasssowrd() {
var secret = buildSecret();
var password = reconciler.getPassword(secret);
assertThat(password).isEqualTo(SECRET_PASSWORD);
}
private Secret buildSecret() {
return new SecretBuilder()
.addToData(Map.of(OzgCloudElasticsearchSecretHelper.CREDENTIAL_SECRET_PASSWORD_FIELD,
encodeStringBase64(SECRET_PASSWORD)))
.build();
}
private String encodeStringBase64(String string) {
return Base64.getEncoder().encodeToString(string.getBytes());
}
}
}
@DisplayName("Cleanup")
@Nested
class TestCleanup {
@Mock
private Context<OzgCloudElasticsearchCustomResource> context;
private final OzgCloudElasticsearchCustomResource resource = ElasticsearchCustomResourceTestFactory.create();
@SneakyThrows
@Test
void shouldDeleteSecurityUser() {
reconciler.cleanup(resource, context);
verify(service).deleteSecurityUserIfExists(NamespaceTestFactory.NAMESPACE);
}
@SneakyThrows
@Test
void shouldDeleteSecurityRole() {
reconciler.cleanup(resource, context);
verify(service).deleteSecurityRoleIfExists(NamespaceTestFactory.NAMESPACE);
}
@SneakyThrows
@Test
void shouldDeleteIndex() {
reconciler.cleanup(resource, context);
verify(service).deleteIndexIfExists(NamespaceTestFactory.NAMESPACE);
}
@Test
void shouldReturnDeleteControl(){
void shouldReturnDeleteControl() {
var deleteControl = reconciler.cleanup(resource, context);
assertThat(deleteControl).isNotNull();
}
}
......
......@@ -25,146 +25,149 @@ class OzgCloudElasticsearchSecretHelperTest {
private OzgCloudElasticsearchSecretHelper builder;
@Mock
private OzgCloudElasticsearchProperties properties;
@DisplayName("Build credential secret")
@Nested
class TestBuildCredentialsSecret {
private final static String HOST = "dummyHost";
private final static int PORT = 42;
@Mock
private OzgCloudElasticsearchServerProperties serverProperties;
@BeforeEach
void mockProperties() {
when(properties.getServer()).thenReturn(serverProperties);
when(serverProperties.getHost()).thenReturn(HOST);
when(serverProperties.getPort()).thenReturn(PORT);
}
@Test
void shouldContainType() {
var secret = buildCredentialSecret();
assertThat(secret.getType()).isEqualTo(OzgCloudElasticsearchSecretHelper.SECRET_TYPE);
}
@DisplayName("metadata")
@Nested
class TestMetadata {
@Test
void shouldContainName() {
var secret = buildCredentialSecret();
assertThat(secret.getMetadata().getName()).isEqualTo(SecretTestFactory.NAME);
}
@Test
void shouldContainNamespace() {
var secret = buildCredentialSecret();
assertThat(secret.getMetadata().getNamespace()).isEqualTo(NamespaceTestFactory.NAMESPACE);
}
}
@DisplayName("address")
@Nested
class TestAddress {
@Test
void shouldBeSet() {
var secret = buildCredentialSecret();
assertThat(secret.getData()).containsEntry(OzgCloudElasticsearchSecretHelper.CREDENTIAL_SECRET_ADDRESS_FIELD, String.format("%s:%s", HOST, PORT));
assertThat(secret.getStringData()).containsEntry(OzgCloudElasticsearchSecretHelper.CREDENTIAL_SECRET_ADDRESS_FIELD,
String.format("%s:%s", HOST, PORT));
}
@Test
void shouldGetHostFromProperties() {
buildCredentialSecret();
verify(serverProperties).getHost();
}
@Test
void shouldGetPortFromPorperties() {
buildCredentialSecret();
verify(serverProperties).getPort();
}
}
@Test
void shouldContainIndex() {
var secret = buildCredentialSecret();
assertThat(secret.getData()).containsEntry(OzgCloudElasticsearchSecretHelper.CREDENTIAL_SECRET_INDEX_FIELD, NamespaceTestFactory.NAMESPACE);
assertThat(secret.getStringData()).containsEntry(OzgCloudElasticsearchSecretHelper.CREDENTIAL_SECRET_INDEX_FIELD,
NamespaceTestFactory.NAMESPACE);
}
@Test
void shouldContainPassword() {
var secret = buildCredentialSecret();
assertThat(secret.getData()).containsKey(OzgCloudElasticsearchSecretHelper.CREDENTIAL_SECRET_PASSWORD_FIELD);
assertThat(secret.getData().get(OzgCloudElasticsearchSecretHelper.CREDENTIAL_SECRET_PASSWORD_FIELD)).isNotNull();
assertThat(secret.getStringData()).containsKey(OzgCloudElasticsearchSecretHelper.CREDENTIAL_SECRET_PASSWORD_FIELD);
assertThat(secret.getStringData().get(OzgCloudElasticsearchSecretHelper.CREDENTIAL_SECRET_PASSWORD_FIELD)).isNotNull();
}
@Test
void shouldContainUsername() {
var secret = buildCredentialSecret();
assertThat(secret.getData()).containsEntry(OzgCloudElasticsearchSecretHelper.CREDENTIAL_SECRET_USERNAME_FIELD, NamespaceTestFactory.NAMESPACE);
assertThat(secret.getStringData()).containsEntry(OzgCloudElasticsearchSecretHelper.CREDENTIAL_SECRET_USERNAME_FIELD,
NamespaceTestFactory.NAMESPACE);
}
private Secret buildCredentialSecret() {
return builder.buildCredentialSecret(NamespaceTestFactory.NAMESPACE, SecretTestFactory.NAME);
}
}
@DisplayName("Build certificate secret")
@Nested
class TestBuildCertificatSecret {
private static final String DATA = "fgdrgsgreg";
@Test
void shouldHaveType() {
var secret = builder.buildCertificateSecret(NamespaceTestFactory.NAMESPACE, DATA);
assertThat(secret.getType()).isEqualTo(OzgCloudElasticsearchSecretHelper.SECRET_TYPE);
}
@DisplayName("metadata")
@Nested
class TestMetadata {
private static final String CERTIFICATE_SECRET_NAME = "rfgsgrgsr";
@BeforeEach
void mock() {
when(properties.getCertificateSecretName()).thenReturn(CERTIFICATE_SECRET_NAME);
}
@Test
void shouldContainName() {
var secret = builder.buildCertificateSecret(NamespaceTestFactory.NAMESPACE, DATA);
assertThat(secret.getMetadata().getName()).isEqualTo(CERTIFICATE_SECRET_NAME);
}
@Test
void shouldContainNamespace() {
var secret = builder.buildCertificateSecret(NamespaceTestFactory.NAMESPACE, DATA);
assertThat(secret.getMetadata().getNamespace()).isEqualTo(NamespaceTestFactory.NAMESPACE);
}
}
@Test
void shouldHaveCaCrtData() {
var secret = builder.buildCertificateSecret(NamespaceTestFactory.NAMESPACE, DATA);
assertThat(secret.getData()).containsExactly(Map.entry(OzgCloudElasticsearchSecretHelper.CERTIFICATE_SECRET_DATA_KEY, DATA));
}
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment