diff --git a/ozgcloud-elasticsearch-operator/src/main/java/de/ozgcloud/operator/ElasticsearchReconciler.java b/ozgcloud-elasticsearch-operator/src/main/java/de/ozgcloud/operator/ElasticsearchReconciler.java new file mode 100644 index 0000000000000000000000000000000000000000..eefba5312435b2562de3c3f4eabfd42227082030 --- /dev/null +++ b/ozgcloud-elasticsearch-operator/src/main/java/de/ozgcloud/operator/ElasticsearchReconciler.java @@ -0,0 +1,58 @@ +package de.ozgcloud.operator; + +import org.apache.commons.collections.MapUtils; +import org.springframework.stereotype.Component; + +import io.fabric8.kubernetes.api.model.Secret; +import io.javaoperatorsdk.operator.api.reconciler.Cleaner; +import io.javaoperatorsdk.operator.api.reconciler.Context; +import io.javaoperatorsdk.operator.api.reconciler.ControllerConfiguration; +import io.javaoperatorsdk.operator.api.reconciler.DeleteControl; +import io.javaoperatorsdk.operator.api.reconciler.Reconciler; +import io.javaoperatorsdk.operator.api.reconciler.UpdateControl; +import lombok.RequiredArgsConstructor; +import lombok.extern.java.Log; + +@Log +@RequiredArgsConstructor +@ControllerConfiguration +@Component +public class ElasticsearchReconciler implements Reconciler<OzgCloudElasticsearchCustomResource>, Cleaner<OzgCloudElasticsearchCustomResource> { + + private final OzgCloudElasticsearchService searchService; + + @Override + public UpdateControl<OzgCloudElasticsearchCustomResource> reconcile(OzgCloudElasticsearchCustomResource resource, Context<OzgCloudElasticsearchCustomResource> context) { + try { + log.info("Reconcile user " + resource.getCRDName() + "..."); + var namespace = resource.getMetadata().getNamespace(); + var secret = searchService.getOrCreateCredentialSecret(resource, context); + searchService.createIndexIfMissing(namespace); + searchService.createSecurityRoleIfMissing(namespace); + searchService.checkSecurityUser(namespace, getPassword(secret)); + log.info("Reconcile user successful."); + return OzgCloudElasticsearchUpdateControlBuilder.fromResource(resource).withStatus(CustomResourceStatus.OK).build(); + } catch (Exception e) { + log.info("Reconcile user failed: " + e); + return buildExceptionUpdateControl(resource, e); + } + } + + private String getPassword(Secret secret) { + return MapUtils.getString(secret.getStringData(), OzgCloudElasticsearchSecretHelper.SECRET_PASSWORD_FIELD); + } + + UpdateControl<OzgCloudElasticsearchCustomResource> buildExceptionUpdateControl(OzgCloudElasticsearchCustomResource resource, Exception e) { + return OzgCloudElasticsearchUpdateControlBuilder + .fromResource(resource) + .withStatus(CustomResourceStatus.ERROR) + .withReschedule(OperatorConfig.RECONCILER_RETRY_SECONDS_ON_ERROR) + .withMessage(e.getMessage()) + .build(); + } + + @Override + public DeleteControl cleanup(OzgCloudElasticsearchCustomResource resource, Context<OzgCloudElasticsearchCustomResource> context) { + return DeleteControl.defaultDelete(); + } +} \ No newline at end of file diff --git a/ozgcloud-elasticsearch-operator/src/main/java/de/ozgcloud/operator/IndicesPrivilege.java b/ozgcloud-elasticsearch-operator/src/main/java/de/ozgcloud/operator/IndicesPrivilege.java new file mode 100644 index 0000000000000000000000000000000000000000..d7312ee608e05021f9892da996f20fb4e4fe1f8c --- /dev/null +++ b/ozgcloud-elasticsearch-operator/src/main/java/de/ozgcloud/operator/IndicesPrivilege.java @@ -0,0 +1,14 @@ +package de.ozgcloud.operator; + +import lombok.Getter; + +public enum IndicesPrivilege { + ALL("all"); + + @Getter + private String value; + + private IndicesPrivilege(String value) { + this.value = value; + } +} diff --git a/ozgcloud-elasticsearch-operator/src/main/java/de/ozgcloud/operator/user/ElasticsearchCustomResource.java b/ozgcloud-elasticsearch-operator/src/main/java/de/ozgcloud/operator/OzgCloudElasticsearchCustomResource.java similarity index 86% rename from ozgcloud-elasticsearch-operator/src/main/java/de/ozgcloud/operator/user/ElasticsearchCustomResource.java rename to ozgcloud-elasticsearch-operator/src/main/java/de/ozgcloud/operator/OzgCloudElasticsearchCustomResource.java index bbc1a13547f8f36bf1cb8d5d76dec45cb96698cb..efc7b303ec1e4a98148aeda5fb11c42df120d282 100644 --- a/ozgcloud-elasticsearch-operator/src/main/java/de/ozgcloud/operator/user/ElasticsearchCustomResource.java +++ b/ozgcloud-elasticsearch-operator/src/main/java/de/ozgcloud/operator/OzgCloudElasticsearchCustomResource.java @@ -21,9 +21,8 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -package de.ozgcloud.operator.user; +package de.ozgcloud.operator; -import de.ozgcloud.operator.ElasticsearchCustomResourceStatus; import io.fabric8.kubernetes.api.model.Namespaced; import io.fabric8.kubernetes.client.CustomResource; import io.fabric8.kubernetes.model.annotation.Group; @@ -38,5 +37,5 @@ import io.fabric8.kubernetes.model.annotation.Version; @Singular("ozgcloudelasticsearch") @Plural("ozgcloudelasticsearchs") @SuppressWarnings("serial") -class ElasticsearchCustomResource extends CustomResource<ElasticsearchSpec, ElasticsearchCustomResourceStatus> implements Namespaced { +class OzgCloudElasticsearchCustomResource extends CustomResource<OzgCloudElasticsearchSpec, OzgCloudElasticsearchCustomResourceStatus> implements Namespaced { } diff --git a/ozgcloud-elasticsearch-operator/src/main/java/de/ozgcloud/operator/ElasticsearchCustomResourceStatus.java b/ozgcloud-elasticsearch-operator/src/main/java/de/ozgcloud/operator/OzgCloudElasticsearchCustomResourceStatus.java similarity index 93% rename from ozgcloud-elasticsearch-operator/src/main/java/de/ozgcloud/operator/ElasticsearchCustomResourceStatus.java rename to ozgcloud-elasticsearch-operator/src/main/java/de/ozgcloud/operator/OzgCloudElasticsearchCustomResourceStatus.java index ba83ac455294675888c09acd9f52844724987dc6..a6c0d28c255870b29b6bb28ea4127d14e8a1368e 100644 --- a/ozgcloud-elasticsearch-operator/src/main/java/de/ozgcloud/operator/ElasticsearchCustomResourceStatus.java +++ b/ozgcloud-elasticsearch-operator/src/main/java/de/ozgcloud/operator/OzgCloudElasticsearchCustomResourceStatus.java @@ -38,7 +38,7 @@ import lombok.Setter; @NoArgsConstructor @AllArgsConstructor @JsonIgnoreProperties(ignoreUnknown = true) -public class ElasticsearchCustomResourceStatus extends ObservedGenerationAwareStatus { +public class OzgCloudElasticsearchCustomResourceStatus extends ObservedGenerationAwareStatus { private CustomResourceStatus status; diff --git a/ozgcloud-elasticsearch-operator/src/main/java/de/ozgcloud/operator/common/elasticsearch/OzgCloudElasticsearchProperties.java b/ozgcloud-elasticsearch-operator/src/main/java/de/ozgcloud/operator/OzgCloudElasticsearchProperties.java similarity index 71% rename from ozgcloud-elasticsearch-operator/src/main/java/de/ozgcloud/operator/common/elasticsearch/OzgCloudElasticsearchProperties.java rename to ozgcloud-elasticsearch-operator/src/main/java/de/ozgcloud/operator/OzgCloudElasticsearchProperties.java index e758ef042d45c46e4fee049ccd7f6132493ddb33..f6568e219c557555aa8a16aae562b767932955b1 100644 --- a/ozgcloud-elasticsearch-operator/src/main/java/de/ozgcloud/operator/common/elasticsearch/OzgCloudElasticsearchProperties.java +++ b/ozgcloud-elasticsearch-operator/src/main/java/de/ozgcloud/operator/OzgCloudElasticsearchProperties.java @@ -1,4 +1,4 @@ -package de.ozgcloud.operator.common.elasticsearch; +package de.ozgcloud.operator; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Configuration; @@ -8,13 +8,14 @@ import lombok.Setter; @Getter @Setter -@ConfigurationProperties("ozgcloud.elastic") +@ConfigurationProperties("ozgcloud.elasticsearch") @Configuration public class OzgCloudElasticsearchProperties { private String namespace; private String secretName; - private String secretData; + private String secretDataKey; + private String secretCredentialsName; private String host; private String address; private int port; diff --git a/ozgcloud-elasticsearch-operator/src/main/java/de/ozgcloud/operator/user/ElasticsearchSecretHelper.java b/ozgcloud-elasticsearch-operator/src/main/java/de/ozgcloud/operator/OzgCloudElasticsearchSecretHelper.java similarity index 90% rename from ozgcloud-elasticsearch-operator/src/main/java/de/ozgcloud/operator/user/ElasticsearchSecretHelper.java rename to ozgcloud-elasticsearch-operator/src/main/java/de/ozgcloud/operator/OzgCloudElasticsearchSecretHelper.java index a4c137ea63a12948a87aa67027d86aa4f2839915..a0622267326704fdb51a0bd307056432c60b8709 100644 --- a/ozgcloud-elasticsearch-operator/src/main/java/de/ozgcloud/operator/user/ElasticsearchSecretHelper.java +++ b/ozgcloud-elasticsearch-operator/src/main/java/de/ozgcloud/operator/OzgCloudElasticsearchSecretHelper.java @@ -1,9 +1,8 @@ -package de.ozgcloud.operator.user; +package de.ozgcloud.operator; import org.apache.commons.lang3.RandomStringUtils; import org.springframework.stereotype.Component; -import de.ozgcloud.operator.common.elasticsearch.OzgCloudElasticsearchProperties; import io.fabric8.kubernetes.api.model.ObjectMeta; import io.fabric8.kubernetes.api.model.Secret; import io.fabric8.kubernetes.api.model.SecretBuilder; @@ -11,7 +10,7 @@ import lombok.RequiredArgsConstructor; @RequiredArgsConstructor @Component -public class ElasticsearchSecretHelper { +public class OzgCloudElasticsearchSecretHelper { static final String SECRET_TYPE = "Opaque"; static final String SECRET_ADDRESS_FIELD = "address"; diff --git a/ozgcloud-elasticsearch-operator/src/main/java/de/ozgcloud/operator/OzgCloudElasticsearchService.java b/ozgcloud-elasticsearch-operator/src/main/java/de/ozgcloud/operator/OzgCloudElasticsearchService.java new file mode 100644 index 0000000000000000000000000000000000000000..6d04c3ae0bac0312cd34e7a473bd6bb602beadd1 --- /dev/null +++ b/ozgcloud-elasticsearch-operator/src/main/java/de/ozgcloud/operator/OzgCloudElasticsearchService.java @@ -0,0 +1,104 @@ +package de.ozgcloud.operator; + +import java.util.Objects; + +import org.springframework.stereotype.Component; + +import de.ozgcloud.operator.PutRoleRequestData.IndicesPrivilegesData; +import de.ozgcloud.operator.common.elasticsearch.ElasticsearchRemoteService; +import de.ozgcloud.operator.common.kubernetes.KubernetesRemoteService; +import io.fabric8.kubernetes.api.model.Secret; +import io.fabric8.kubernetes.client.dsl.Resource; +import io.fabric8.kubernetes.client.extension.ResourceAdapter; +import io.javaoperatorsdk.operator.api.reconciler.Context; +import lombok.RequiredArgsConstructor; +import lombok.extern.java.Log; + +@Log +@RequiredArgsConstructor +@Component +public class OzgCloudElasticsearchService { + + private final OzgCloudElasticsearchSecretHelper secretHelper; + private final OzgCloudElasticsearchProperties properties; + + private final ElasticsearchRemoteService remoteService; + + private final KubernetesRemoteService kubernetesService; + + public Secret getOrCreateCredentialSecret(OzgCloudElasticsearchCustomResource resource, Context<OzgCloudElasticsearchCustomResource> context) { + try { + log.info("Get or create secret..."); + var namespace = resource.getMetadata().getNamespace(); + var secretResource = getCredentialsSecretResource(namespace); + + if (Objects.isNull(secretResource.get())) { + log.info("Secret not exists, create one..."); + createCredentialSecret(secretResource, namespace); + log.info("Secret creation successful."); + } + log.info("Secret already exists, return existing."); + return secretResource.get(); + } catch (Exception e) { + log.info("Secret creation failed: " + e); + throw e; + } + } + + private Resource<Secret> getCredentialsSecretResource(String namespace) { + return kubernetesService.getSecretResource(namespace, properties.getSecretCredentialsName()); + } + + private void createCredentialSecret(Resource<Secret> resource, String namespace) { + createAdapter(resource).create(secretHelper.buildCredentialSecret(namespace, properties.getSecretCredentialsName())); + } + + ResourceAdapter<Secret> createAdapter(Resource<Secret> resource) { + return new ResourceAdapter<Secret>(resource); + } + +// curl -k -X PUT -u elastic:$ELASTICSEARCH_PASSWORD -H 'Content-Type: application/json' 'https://ozg-search-cluster-es-http:9200/'$ES_NS_USER + public void createIndexIfMissing(String name) throws Exception { + log.info("Check index..."); + if(!remoteService.existsIndex(name)) { + remoteService.createIndex(name); + } + log.info("Check index successful."); + } + +// curl -k -X POST -u elastic:$ELASTICSEARCH_PASSWORD -H 'Content-Type: application/json' +// 'https://ozg-search-cluster-es-http:9200/_security/role/'$ES_NS_USER -d '{ "indices": [ { "names": [ "'$ES_NS_USER'*" ], "privileges": ["all"] } ] }' + public void createSecurityRoleIfMissing(String roleName) throws Exception { + log.info("Check security role..."); + if(!remoteService.existsSecurityRole(roleName)) { + remoteService.createSecurityRole(buildPutRoleRequestData(roleName)); + } + log.info("Check security role successful."); + } + + PutRoleRequestData buildPutRoleRequestData(String roleName){ + return PutRoleRequestData.builder().name(roleName).indivesPrivilegesData(buildIndicesPrivilegesData(roleName)).build(); + } + + private IndicesPrivilegesData buildIndicesPrivilegesData(String roleName) { + return IndicesPrivilegesData.builder().names(roleName).privileges(IndicesPrivilege.ALL.getValue()).build(); + } + +// curl -k -X POST -u elastic:$ELASTICSEARCH_PASSWORD -H 'Content-Type: application/json' +// 'https://ozg-search-cluster-es-http:9200/_security/user/'$ES_NS_USER -d '{"password" : "'$ES_NS_PASSWORD'" ,"roles" : [ "'$ES_NS_USER'" ]}' + public void checkSecurityUser(String namespace, String password) throws Exception { + log.info("Check security user..."); + if(!remoteService.existsSecurityUser(namespace)) { + remoteService.createSecurityUser(buildPutUserRequestData(namespace, password)); + } + log.info("Check security user successful."); + } + + PutUserRequestData buildPutUserRequestData(String namespace, String password){ + return PutUserRequestData.builder().username(namespace).roles(namespace).password(password).build(); + } + + public void deleteIndexIfExists(String name) { + + } +} \ No newline at end of file diff --git a/ozgcloud-elasticsearch-operator/src/main/java/de/ozgcloud/operator/user/ElasticsearchSpec.java b/ozgcloud-elasticsearch-operator/src/main/java/de/ozgcloud/operator/OzgCloudElasticsearchSpec.java similarity index 94% rename from ozgcloud-elasticsearch-operator/src/main/java/de/ozgcloud/operator/user/ElasticsearchSpec.java rename to ozgcloud-elasticsearch-operator/src/main/java/de/ozgcloud/operator/OzgCloudElasticsearchSpec.java index fb7fb3acc01a49fbc0ba0373a2e447b3f5d4b03a..eb622b13e91c206da326948673a402dac2b2638f 100644 --- a/ozgcloud-elasticsearch-operator/src/main/java/de/ozgcloud/operator/user/ElasticsearchSpec.java +++ b/ozgcloud-elasticsearch-operator/src/main/java/de/ozgcloud/operator/OzgCloudElasticsearchSpec.java @@ -21,7 +21,7 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -package de.ozgcloud.operator.user; +package de.ozgcloud.operator; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; @@ -33,6 +33,6 @@ import lombok.Setter; @Setter @Builder @JsonIgnoreProperties(ignoreUnknown = true) -class ElasticsearchSpec { +class OzgCloudElasticsearchSpec { } diff --git a/ozgcloud-elasticsearch-operator/src/main/java/de/ozgcloud/operator/OzgCloudElasticsearchUpdateControlBuilder.java b/ozgcloud-elasticsearch-operator/src/main/java/de/ozgcloud/operator/OzgCloudElasticsearchUpdateControlBuilder.java new file mode 100644 index 0000000000000000000000000000000000000000..22702728bc06914e35e1ba171b8194cbc1aedc78 --- /dev/null +++ b/ozgcloud-elasticsearch-operator/src/main/java/de/ozgcloud/operator/OzgCloudElasticsearchUpdateControlBuilder.java @@ -0,0 +1,61 @@ +package de.ozgcloud.operator; + +import java.time.Duration; +import java.util.Optional; + +import io.javaoperatorsdk.operator.api.reconciler.UpdateControl; + +class OzgCloudElasticsearchUpdateControlBuilder { + + private OzgCloudElasticsearchCustomResource resource; + + private CustomResourceStatus status; + private Optional<String> message = Optional.empty(); + + private boolean reschedule = false; + private Duration scheduleDuration; + + public OzgCloudElasticsearchUpdateControlBuilder(OzgCloudElasticsearchCustomResource resource) { + this.resource = resource; + } + + public static OzgCloudElasticsearchUpdateControlBuilder fromResource(OzgCloudElasticsearchCustomResource resource) { + return new OzgCloudElasticsearchUpdateControlBuilder(resource); + } + + public OzgCloudElasticsearchUpdateControlBuilder withStatus(CustomResourceStatus status) { + this.status = status; + return this; + } + + public OzgCloudElasticsearchUpdateControlBuilder withMessage(String message) { + this.message = Optional.ofNullable(message); + return this; + } + + public OzgCloudElasticsearchUpdateControlBuilder withReschedule(Duration duration) { + this.reschedule = true; + this.scheduleDuration = duration; + return this; + } + + public UpdateControl<OzgCloudElasticsearchCustomResource> build() { + resource.setStatus(buildElasticCustomResourceStatus()); + + return buildUpdateControl(); + } + + private OzgCloudElasticsearchCustomResourceStatus buildElasticCustomResourceStatus() { + var userStatus = OzgCloudElasticsearchCustomResourceStatus.builder().status(status); + message.ifPresent(userStatus::message); + + return userStatus.build(); + } + + private UpdateControl<OzgCloudElasticsearchCustomResource> buildUpdateControl() { + if (reschedule) { + return UpdateControl.updateStatus(resource).rescheduleAfter(scheduleDuration); + } + return UpdateControl.updateStatus(resource); + } +} diff --git a/ozgcloud-elasticsearch-operator/src/main/java/de/ozgcloud/operator/user/PutRoleRequestData.java b/ozgcloud-elasticsearch-operator/src/main/java/de/ozgcloud/operator/PutRoleRequestData.java similarity index 90% rename from ozgcloud-elasticsearch-operator/src/main/java/de/ozgcloud/operator/user/PutRoleRequestData.java rename to ozgcloud-elasticsearch-operator/src/main/java/de/ozgcloud/operator/PutRoleRequestData.java index 05dfbc64ecd1f9dd9467fe3b873ed81f97f0b181..276a2c0ba05d7fe17b450f9fe98e157b08045559 100644 --- a/ozgcloud-elasticsearch-operator/src/main/java/de/ozgcloud/operator/user/PutRoleRequestData.java +++ b/ozgcloud-elasticsearch-operator/src/main/java/de/ozgcloud/operator/PutRoleRequestData.java @@ -1,4 +1,4 @@ -package de.ozgcloud.operator.user; +package de.ozgcloud.operator; import lombok.Builder; import lombok.Getter; diff --git a/ozgcloud-elasticsearch-operator/src/main/java/de/ozgcloud/operator/user/PutUserRequestData.java b/ozgcloud-elasticsearch-operator/src/main/java/de/ozgcloud/operator/PutUserRequestData.java similarity index 85% rename from ozgcloud-elasticsearch-operator/src/main/java/de/ozgcloud/operator/user/PutUserRequestData.java rename to ozgcloud-elasticsearch-operator/src/main/java/de/ozgcloud/operator/PutUserRequestData.java index 73d60a685ffc19645be2f3ae49be27cb03aa4917..2ca925bd250d71679f88da96e565e5667cec9061 100644 --- a/ozgcloud-elasticsearch-operator/src/main/java/de/ozgcloud/operator/user/PutUserRequestData.java +++ b/ozgcloud-elasticsearch-operator/src/main/java/de/ozgcloud/operator/PutUserRequestData.java @@ -1,4 +1,4 @@ -package de.ozgcloud.operator.user; +package de.ozgcloud.operator; import lombok.Builder; import lombok.Getter; diff --git a/ozgcloud-elasticsearch-operator/src/main/java/de/ozgcloud/operator/common/elasticsearch/OzgCloudElasticsearchClient.java b/ozgcloud-elasticsearch-operator/src/main/java/de/ozgcloud/operator/common/elasticsearch/ElasticsearchClientConfiguration.java similarity index 87% rename from ozgcloud-elasticsearch-operator/src/main/java/de/ozgcloud/operator/common/elasticsearch/OzgCloudElasticsearchClient.java rename to ozgcloud-elasticsearch-operator/src/main/java/de/ozgcloud/operator/common/elasticsearch/ElasticsearchClientConfiguration.java index de31f4bcd5afacd1c8fb40ccac30e46e186e483c..51bde5505538d43921dd3050ba226fbdd647de6f 100644 --- a/ozgcloud-elasticsearch-operator/src/main/java/de/ozgcloud/operator/common/elasticsearch/OzgCloudElasticsearchClient.java +++ b/ozgcloud-elasticsearch-operator/src/main/java/de/ozgcloud/operator/common/elasticsearch/ElasticsearchClientConfiguration.java @@ -14,20 +14,21 @@ import org.springframework.context.annotation.Scope; import co.elastic.clients.elasticsearch.ElasticsearchClient; import co.elastic.clients.json.jackson.JacksonJsonpMapper; import co.elastic.clients.transport.rest_client.RestClientTransport; -import de.ozgcloud.operator.common.kubernetes.KubernetesService; +import de.ozgcloud.operator.OzgCloudElasticsearchProperties; +import de.ozgcloud.operator.common.kubernetes.KubernetesRemoteService; @Configuration -public class OzgCloudElasticsearchClient { +public class ElasticsearchClientConfiguration { @Autowired - private KubernetesService kubernetesService; + private KubernetesRemoteService kubernetesService; @Autowired private OzgCloudElasticsearchProperties elasticSearchProperties; @Bean @Scope("singleton") ElasticsearchClient createElasticsearchClient() { - var credentialsProvider = createCredentialsProvider(elasticSearchProperties.getSecretData(), getPassword()); + var credentialsProvider = createCredentialsProvider(elasticSearchProperties.getSecretDataKey(), getPassword()); var restClient = buildRestClient(credentialsProvider); var transport = createRestClientTransport(restClient); return new ElasticsearchClient(transport); @@ -55,7 +56,7 @@ public class OzgCloudElasticsearchClient { String getPassword() { var resource = kubernetesService.getSecretResource(elasticSearchProperties.getNamespace(), elasticSearchProperties.getSecretName()); - var password = MapUtils.getString(resource.get().getStringData(), elasticSearchProperties.getSecretData()); + var password = MapUtils.getString(resource.get().getStringData(), elasticSearchProperties.getSecretDataKey()); return password; } } \ No newline at end of file diff --git a/ozgcloud-elasticsearch-operator/src/main/java/de/ozgcloud/operator/common/elasticsearch/OzgCloudElasticsearchRemoteService.java b/ozgcloud-elasticsearch-operator/src/main/java/de/ozgcloud/operator/common/elasticsearch/ElasticsearchRemoteService.java similarity index 81% rename from ozgcloud-elasticsearch-operator/src/main/java/de/ozgcloud/operator/common/elasticsearch/OzgCloudElasticsearchRemoteService.java rename to ozgcloud-elasticsearch-operator/src/main/java/de/ozgcloud/operator/common/elasticsearch/ElasticsearchRemoteService.java index 5dc245d58d83df76e485be624375778d89fa7ccb..86a21f2b9f144643a53c739ae77fec53223e6560 100644 --- a/ozgcloud-elasticsearch-operator/src/main/java/de/ozgcloud/operator/common/elasticsearch/OzgCloudElasticsearchRemoteService.java +++ b/ozgcloud-elasticsearch-operator/src/main/java/de/ozgcloud/operator/common/elasticsearch/ElasticsearchRemoteService.java @@ -13,22 +13,22 @@ import co.elastic.clients.elasticsearch.security.GetUserRequest; import co.elastic.clients.elasticsearch.security.IndicesPrivileges; import co.elastic.clients.elasticsearch.security.PutRoleRequest; import co.elastic.clients.elasticsearch.security.PutUserRequest; -import de.ozgcloud.operator.user.PutRoleRequestData; -import de.ozgcloud.operator.user.PutUserRequestData; +import de.ozgcloud.operator.PutRoleRequestData; +import de.ozgcloud.operator.PutUserRequestData; import lombok.RequiredArgsConstructor; import lombok.extern.java.Log; @Log @RequiredArgsConstructor @Component -class OzgCloudElasticsearchRemoteService { +public class ElasticsearchRemoteService { private final ElasticsearchClient client; public boolean existsIndex(String index) throws Exception { try { log.info("Exists index " + index + "..."); - var exists = client.indices().exists(createExistsRequestOf(index)).value(); + var exists = client.indices().exists(createExistsRequest(index)).value(); log.info("Exists index: " + exists); return exists; } catch (ElasticsearchException | IOException e) { @@ -37,7 +37,7 @@ class OzgCloudElasticsearchRemoteService { } } - private ExistsRequest createExistsRequestOf(String index) { + ExistsRequest createExistsRequest(String index) { return ExistsRequest.of(builder -> builder.index(index)); } @@ -53,18 +53,18 @@ class OzgCloudElasticsearchRemoteService { } public boolean existsSecurityRole(String roleName) throws Exception { - var role = client.security().getRole(createGetRoleRequestOf(roleName)); + var role = client.security().getRole(createGetRoleRequest(roleName)); return !role.result().isEmpty(); } - private GetRoleRequest createGetRoleRequestOf(String name) { + GetRoleRequest createGetRoleRequest(String name) { return GetRoleRequest.of(builder -> builder.name(name)); } public void createSecurityRole(PutRoleRequestData requestData) throws Exception { try { log.info("Create SecurityRole " + requestData.getName() + "..."); - client.security().putRole(createPutRoleRequestOf(requestData)); + client.security().putRole(createPutRoleRequest(requestData)); log.info("Create SecurityRole successful."); } catch(Exception e) { log.log(Level.SEVERE, "Create SecurityRole failed." + e); @@ -72,7 +72,7 @@ class OzgCloudElasticsearchRemoteService { } } - PutRoleRequest createPutRoleRequestOf(PutRoleRequestData requestData) { + PutRoleRequest createPutRoleRequest(PutRoleRequestData requestData) { return PutRoleRequest.of(requestBuilder -> buildRequest(requestBuilder, requestData)); } @@ -91,18 +91,18 @@ class OzgCloudElasticsearchRemoteService { } public boolean existsSecurityUser(String userName) throws Exception { - var user = client.security().getUser(createGetUserRequestOf(userName)); + var user = client.security().getUser(createGetUserRequest(userName)); return !user.result().isEmpty(); } - private GetUserRequest createGetUserRequestOf(String userName) { + private GetUserRequest createGetUserRequest(String userName) { return GetUserRequest.of(builder -> builder.username(userName)); } public void createSecurityUser(PutUserRequestData requestData) throws Exception { try { log.info("Create SecurityUser " + requestData.getUsername() + "..."); - client.security().putUser(createPutUserRequestOf(requestData)); + client.security().putUser(createPutUserRequest(requestData)); log.info("Create SecurityUser successful."); } catch(Exception e) { log.log(Level.SEVERE, "Create SecurityUser failed." + e); @@ -110,7 +110,7 @@ class OzgCloudElasticsearchRemoteService { } } - PutUserRequest createPutUserRequestOf(PutUserRequestData requestData) { + PutUserRequest createPutUserRequest(PutUserRequestData requestData) { return PutUserRequest.of(requestBuilder -> buildPutUserRequest(requestBuilder, requestData)); } diff --git a/ozgcloud-elasticsearch-operator/src/main/java/de/ozgcloud/operator/common/elasticsearch/OzgCloudElasticsearchService.java b/ozgcloud-elasticsearch-operator/src/main/java/de/ozgcloud/operator/common/elasticsearch/OzgCloudElasticsearchService.java deleted file mode 100644 index 06982f71f21c0839c70131ed095e804422b6268b..0000000000000000000000000000000000000000 --- a/ozgcloud-elasticsearch-operator/src/main/java/de/ozgcloud/operator/common/elasticsearch/OzgCloudElasticsearchService.java +++ /dev/null @@ -1,60 +0,0 @@ -package de.ozgcloud.operator.common.elasticsearch; - -import org.springframework.stereotype.Component; - -import de.ozgcloud.operator.user.PutRoleRequestData; -import de.ozgcloud.operator.user.PutRoleRequestData.IndicesPrivilegesData; -import de.ozgcloud.operator.user.PutUserRequestData; -import lombok.RequiredArgsConstructor; -import lombok.extern.java.Log; - -@Log -@RequiredArgsConstructor -@Component -public class OzgCloudElasticsearchService { - - static final String PRIVILEGES_ALL = "all"; - - private final OzgCloudElasticsearchRemoteService remoteService; - -// curl -k -X PUT -u elastic:$ELASTICSEARCH_PASSWORD -H 'Content-Type: application/json' 'https://ozg-search-cluster-es-http:9200/'$ES_NS_USER - public void checkIndex(String namespace) throws Exception { - log.info("Check index..."); - if(!remoteService.existsIndex(namespace)) { - remoteService.createIndex(namespace); - } - log.info("Check index successful."); - } - -// curl -k -X POST -u elastic:$ELASTICSEARCH_PASSWORD -H 'Content-Type: application/json' -// 'https://ozg-search-cluster-es-http:9200/_security/role/'$ES_NS_USER -d '{ "indices": [ { "names": [ "'$ES_NS_USER'*" ], "privileges": ["all"] } ] }' - public void checkSecurityRole(String namespace) throws Exception { - log.info("Check security role..."); - if(!remoteService.existsSecurityRole(namespace)) { - remoteService.createSecurityRole(buildPutRoleRequestData(namespace)); - } - log.info("Check security role successful."); - } - - PutRoleRequestData buildPutRoleRequestData(String namespace){ - return PutRoleRequestData.builder().name(namespace).indivesPrivilegesData(buildIndicesPrivilegesData(namespace)).build(); - } - - private IndicesPrivilegesData buildIndicesPrivilegesData(String namespace) { - return IndicesPrivilegesData.builder().names(namespace).privileges(PRIVILEGES_ALL).build(); - } - -// curl -k -X POST -u elastic:$ELASTICSEARCH_PASSWORD -H 'Content-Type: application/json' -// 'https://ozg-search-cluster-es-http:9200/_security/user/'$ES_NS_USER -d '{"password" : "'$ES_NS_PASSWORD'" ,"roles" : [ "'$ES_NS_USER'" ]}' - public void checkSecurityUser(String namespace, String password) throws Exception { - log.info("Check security user..."); - if(!remoteService.existsSecurityUser(namespace)) { - remoteService.createSecurityUser(buildPutUserRequestData(namespace, password)); - } - log.info("Check security user successful."); - } - - PutUserRequestData buildPutUserRequestData(String namespace, String password){ - return PutUserRequestData.builder().username(namespace).roles(namespace).password(password).build(); - } -} \ No newline at end of file diff --git a/ozgcloud-elasticsearch-operator/src/main/java/de/ozgcloud/operator/common/kubernetes/KubernetesService.java b/ozgcloud-elasticsearch-operator/src/main/java/de/ozgcloud/operator/common/kubernetes/KubernetesRemoteService.java similarity index 92% rename from ozgcloud-elasticsearch-operator/src/main/java/de/ozgcloud/operator/common/kubernetes/KubernetesService.java rename to ozgcloud-elasticsearch-operator/src/main/java/de/ozgcloud/operator/common/kubernetes/KubernetesRemoteService.java index c0cffc712d6d1992d92e190741353f4ab317dc6d..c8d4bd2e85fc7f380f650bc974775984809b9b80 100644 --- a/ozgcloud-elasticsearch-operator/src/main/java/de/ozgcloud/operator/common/kubernetes/KubernetesService.java +++ b/ozgcloud-elasticsearch-operator/src/main/java/de/ozgcloud/operator/common/kubernetes/KubernetesRemoteService.java @@ -9,7 +9,7 @@ import lombok.RequiredArgsConstructor; @RequiredArgsConstructor @Component -public class KubernetesService { +public class KubernetesRemoteService { private final KubernetesClient client; diff --git a/ozgcloud-elasticsearch-operator/src/main/java/de/ozgcloud/operator/user/ElasticsearchReconciler.java b/ozgcloud-elasticsearch-operator/src/main/java/de/ozgcloud/operator/user/ElasticsearchReconciler.java deleted file mode 100644 index cf7b0085235ab83dd26c515d4c0145c2f4fd6e4e..0000000000000000000000000000000000000000 --- a/ozgcloud-elasticsearch-operator/src/main/java/de/ozgcloud/operator/user/ElasticsearchReconciler.java +++ /dev/null @@ -1,55 +0,0 @@ -package de.ozgcloud.operator.user; - -import org.apache.commons.collections.MapUtils; -import org.springframework.stereotype.Component; - -import de.ozgcloud.operator.CustomResourceStatus; -import de.ozgcloud.operator.OperatorConfig; -import de.ozgcloud.operator.common.elasticsearch.OzgCloudElasticsearchService; -import io.fabric8.kubernetes.api.model.Secret; -import io.javaoperatorsdk.operator.api.reconciler.Context; -import io.javaoperatorsdk.operator.api.reconciler.ControllerConfiguration; -import io.javaoperatorsdk.operator.api.reconciler.Reconciler; -import io.javaoperatorsdk.operator.api.reconciler.UpdateControl; -import lombok.RequiredArgsConstructor; -import lombok.extern.java.Log; - -@Log -@RequiredArgsConstructor -@ControllerConfiguration -@Component -public class ElasticsearchReconciler implements Reconciler<ElasticsearchCustomResource> { - - private final ElasticsearchService service; - private final OzgCloudElasticsearchService searchService; - - @Override - public UpdateControl<ElasticsearchCustomResource> reconcile(ElasticsearchCustomResource resource, Context<ElasticsearchCustomResource> context) { - try { - log.info("Reconcile user " + resource.getCRDName() + "..."); - var namespace = resource.getMetadata().getNamespace(); - var secret = service.getOrCreateCredentialSecret(resource, context); - searchService.checkIndex(namespace); - searchService.checkSecurityRole(namespace); - searchService.checkSecurityUser(namespace, getPassword(secret)); - log.info("Reconcile user successful."); - return ElasticsearchUpdateControlBuilder.fromResource(resource).withStatus(CustomResourceStatus.OK).build(); - } catch (Exception e) { - log.info("Reconcile user failed: " + e); - return buildExceptionUpdateControl(resource, e); - } - } - - private String getPassword(Secret secret) { - return MapUtils.getString(secret.getStringData(), ElasticsearchSecretHelper.SECRET_PASSWORD_FIELD); - } - - UpdateControl<ElasticsearchCustomResource> buildExceptionUpdateControl(ElasticsearchCustomResource resource, Exception e) { - return ElasticsearchUpdateControlBuilder - .fromResource(resource) - .withStatus(CustomResourceStatus.ERROR) - .withReschedule(OperatorConfig.RECONCILER_RETRY_SECONDS_ON_ERROR) - .withMessage(e.getMessage()) - .build(); - } -} \ No newline at end of file diff --git a/ozgcloud-elasticsearch-operator/src/main/java/de/ozgcloud/operator/user/ElasticsearchService.java b/ozgcloud-elasticsearch-operator/src/main/java/de/ozgcloud/operator/user/ElasticsearchService.java deleted file mode 100644 index edf9c5da53432325077c31d597dc1b36892dffb0..0000000000000000000000000000000000000000 --- a/ozgcloud-elasticsearch-operator/src/main/java/de/ozgcloud/operator/user/ElasticsearchService.java +++ /dev/null @@ -1,56 +0,0 @@ -package de.ozgcloud.operator.user; - -import java.util.Objects; - -import org.springframework.stereotype.Component; - -import de.ozgcloud.operator.common.kubernetes.KubernetesService; -import io.fabric8.kubernetes.api.model.Secret; -import io.fabric8.kubernetes.client.dsl.Resource; -import io.fabric8.kubernetes.client.extension.ResourceAdapter; -import io.javaoperatorsdk.operator.api.reconciler.Context; -import lombok.RequiredArgsConstructor; -import lombok.extern.java.Log; - -@Log -@RequiredArgsConstructor -@Component -class ElasticsearchService { - - static final String ELASTIC_USER_SECRET_NAME = "elasticsearch-credentials"; - - private final ElasticsearchSecretHelper secretHelper; - - private final KubernetesService kubernetesService; - - public Secret getOrCreateCredentialSecret(ElasticsearchCustomResource resource, Context<ElasticsearchCustomResource> context) { - try { - log.info("Get or create secret..."); - var namespace = resource.getMetadata().getNamespace(); - var secretResource = getSecretResource(namespace); - - if (Objects.isNull(secretResource.get())) { - log.info("Secret not exists, create one..."); - createCredentialSecret(secretResource, namespace); - log.info("Secret creation successful."); - } - log.info("Secret already exists, return existing."); - return secretResource.get(); - } catch (Exception e) { - log.info("Secret creation failed: " + e); - throw e; - } - } - - private Resource<Secret> getSecretResource(String namespace) { - return kubernetesService.getSecretResource(namespace, ELASTIC_USER_SECRET_NAME); - } - - private void createCredentialSecret(Resource<Secret> resource, String namespace) { - createAdapter(resource).create(secretHelper.buildCredentialSecret(namespace, ELASTIC_USER_SECRET_NAME)); - } - - ResourceAdapter<Secret> createAdapter(Resource<Secret> resource) { - return new ResourceAdapter<Secret>(resource); - } -} \ No newline at end of file diff --git a/ozgcloud-elasticsearch-operator/src/main/java/de/ozgcloud/operator/user/ElasticsearchUpdateControlBuilder.java b/ozgcloud-elasticsearch-operator/src/main/java/de/ozgcloud/operator/user/ElasticsearchUpdateControlBuilder.java deleted file mode 100644 index 0c5e2c456fdd3816f6cfc27f1f18a0c8a3c18a70..0000000000000000000000000000000000000000 --- a/ozgcloud-elasticsearch-operator/src/main/java/de/ozgcloud/operator/user/ElasticsearchUpdateControlBuilder.java +++ /dev/null @@ -1,63 +0,0 @@ -package de.ozgcloud.operator.user; - -import java.time.Duration; -import java.util.Optional; - -import de.ozgcloud.operator.CustomResourceStatus; -import de.ozgcloud.operator.ElasticsearchCustomResourceStatus; -import io.javaoperatorsdk.operator.api.reconciler.UpdateControl; - -class ElasticsearchUpdateControlBuilder { - - private ElasticsearchCustomResource resource; - - private CustomResourceStatus status; - private Optional<String> message = Optional.empty(); - - private boolean reschedule = false; - private Duration scheduleDuration; - - public ElasticsearchUpdateControlBuilder(ElasticsearchCustomResource resource) { - this.resource = resource; - } - - public static ElasticsearchUpdateControlBuilder fromResource(ElasticsearchCustomResource resource) { - return new ElasticsearchUpdateControlBuilder(resource); - } - - public ElasticsearchUpdateControlBuilder withStatus(CustomResourceStatus status) { - this.status = status; - return this; - } - - public ElasticsearchUpdateControlBuilder withMessage(String message) { - this.message = Optional.ofNullable(message); - return this; - } - - public ElasticsearchUpdateControlBuilder withReschedule(Duration duration) { - this.reschedule = true; - this.scheduleDuration = duration; - return this; - } - - public UpdateControl<ElasticsearchCustomResource> build() { - resource.setStatus(buildElasticCustomResourceStatus()); - - return buildUpdateControl(); - } - - private ElasticsearchCustomResourceStatus buildElasticCustomResourceStatus() { - var userStatus = ElasticsearchCustomResourceStatus.builder().status(status); - message.ifPresent(userStatus::message); - - return userStatus.build(); - } - - private UpdateControl<ElasticsearchCustomResource> buildUpdateControl() { - if (reschedule) { - return UpdateControl.updateStatus(resource).rescheduleAfter(scheduleDuration); - } - return UpdateControl.updateStatus(resource); - } -} diff --git a/ozgcloud-elasticsearch-operator/src/main/resources/application.yml b/ozgcloud-elasticsearch-operator/src/main/resources/application.yml index 1154419c5a8c12808b905389395e025d716d4381..345acebec473da1bfe624ab59652c2c31880180f 100644 --- a/ozgcloud-elasticsearch-operator/src/main/resources/application.yml +++ b/ozgcloud-elasticsearch-operator/src/main/resources/application.yml @@ -1,8 +1,9 @@ ozgcloud: - elastic: + elasticsearch: namespace: elastic-system secretName: ozg-search-cluster-es-elastic-user - secretData: elastic + secretDataKey: elastic + secretCredentialsName: elasticsearch-credentials host: https://ozg-search-cluster-es-http address: ozg-search-cluster-es-http.elastic-system port: 9200 \ No newline at end of file diff --git a/ozgcloud-elasticsearch-operator/src/test/java/de/ozgcloud/operator/ElasticOperatorApplicationTest.java b/ozgcloud-elasticsearch-operator/src/test/java/de/ozgcloud/operator/ElasticOperatorApplicationTest.java deleted file mode 100644 index 46680e71500a169bafc453c472785e907ff0eafe..0000000000000000000000000000000000000000 --- a/ozgcloud-elasticsearch-operator/src/test/java/de/ozgcloud/operator/ElasticOperatorApplicationTest.java +++ /dev/null @@ -1,46 +0,0 @@ -package de.ozgcloud.operator; - -//import org.junit.jupiter.api.BeforeAll; -//import org.junit.jupiter.api.Test; -//import org.springframework.beans.factory.annotation.Autowired; -// -//import io.fabric8.kubernetes.api.model.ConfigMap; -//import io.fabric8.kubernetes.api.model.ConfigMapBuilder; -//import io.fabric8.kubernetes.client.Config; -//import io.fabric8.kubernetes.client.KubernetesClient; -//import io.specto.hoverfly.junit.core.Hoverfly; -// -//@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) -//@ExtendWith(HoverflyExtension.class) -//class ElasticOperatorApplicationTest { -// -// @Test -// void contextLoads() { // NOSONAR -// } -// -// @Autowired -// KubernetesClient client; -// -// @BeforeAll -// static void setup(Hoverfly hoverfly) { -// System.setProperty(Config.KUBERNETES_TRUST_CERT_SYSTEM_PROPERTY, "true"); -// System.setProperty(Config.KUBERNETES_AUTH_TRYKUBECONFIG_SYSTEM_PROPERTY, "false"); -// System.setProperty(Config.KUBERNETES_AUTH_TRYSERVICEACCOUNT_SYSTEM_PROPERTY, -// "false"); -// System.setProperty(Config.KUBERNETES_HTTP2_DISABLE, "true"); -// System.setProperty(Config.KUBERNETES_NAMESPACE_SYSTEM_PROPERTY, "default"); -// -//// hoverfly.simulate(SimulationSource.dsl(service("kubernetes.default.svc") -//// .get("/api/v1/namespaces/default/configmaps/department") -//// .willReturn(success().body(json(buildConfigMap()))))); -// } -// -// private static ConfigMap buildConfigMap() { -// return new ConfigMapBuilder().withNewMetadata() -// .withName("department").withNamespace("default") -// .endMetadata() -// .addToData("application.properties", -// "spring.data.mongodb.uri=mongodb://localhost:27017/test") -// .build(); -// } -//} diff --git a/ozgcloud-elasticsearch-operator/src/test/java/de/ozgcloud/operator/ElasticsearchCustomResourceStatusTestFactory.java b/ozgcloud-elasticsearch-operator/src/test/java/de/ozgcloud/operator/ElasticsearchCustomResourceStatusTestFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..c3e4eb3f132a2914615670b7948c2cef29648a9f --- /dev/null +++ b/ozgcloud-elasticsearch-operator/src/test/java/de/ozgcloud/operator/ElasticsearchCustomResourceStatusTestFactory.java @@ -0,0 +1,15 @@ +package de.ozgcloud.operator; + +public class ElasticsearchCustomResourceStatusTestFactory { + + public final static CustomResourceStatus STATUS = CustomResourceStatus.OK; + + public static OzgCloudElasticsearchCustomResourceStatus create() { + return createBuilder().build(); + } + + public static OzgCloudElasticsearchCustomResourceStatus.OzgCloudElasticsearchCustomResourceStatusBuilder createBuilder() { + return OzgCloudElasticsearchCustomResourceStatus.builder() + .status(STATUS); + } +} \ No newline at end of file diff --git a/ozgcloud-elasticsearch-operator/src/test/java/de/ozgcloud/operator/ElasticsearchCustomResourceTestFactory.java b/ozgcloud-elasticsearch-operator/src/test/java/de/ozgcloud/operator/ElasticsearchCustomResourceTestFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..0fd331661da3b583401a11c1c9d3ba1c979c90e1 --- /dev/null +++ b/ozgcloud-elasticsearch-operator/src/test/java/de/ozgcloud/operator/ElasticsearchCustomResourceTestFactory.java @@ -0,0 +1,13 @@ +package de.ozgcloud.operator; + +import de.ozgcloud.operator.OzgCloudElasticsearchCustomResource; + +public class ElasticsearchCustomResourceTestFactory { + + public static OzgCloudElasticsearchCustomResource create() { + var resource = new OzgCloudElasticsearchCustomResource(); + resource.setStatus(ElasticsearchCustomResourceStatusTestFactory.create()); + resource.setMetadata(ObjectMetaTestFactory.create()); + return resource; + } +} \ No newline at end of file diff --git a/ozgcloud-elasticsearch-operator/src/test/java/de/ozgcloud/operator/user/ElasticsearchReconcilerITCase.java b/ozgcloud-elasticsearch-operator/src/test/java/de/ozgcloud/operator/ElasticsearchReconcilerITCase.java similarity index 98% rename from ozgcloud-elasticsearch-operator/src/test/java/de/ozgcloud/operator/user/ElasticsearchReconcilerITCase.java rename to ozgcloud-elasticsearch-operator/src/test/java/de/ozgcloud/operator/ElasticsearchReconcilerITCase.java index 890f2c3016a9554332617c79b9e65d46ba0eef0b..66f872dd9f706bd3052598a5a6797cc73659f3e0 100644 --- a/ozgcloud-elasticsearch-operator/src/test/java/de/ozgcloud/operator/user/ElasticsearchReconcilerITCase.java +++ b/ozgcloud-elasticsearch-operator/src/test/java/de/ozgcloud/operator/ElasticsearchReconcilerITCase.java @@ -1,4 +1,4 @@ -package de.ozgcloud.operator.user; +package de.ozgcloud.operator; import static org.assertj.core.api.Assertions.*; diff --git a/ozgcloud-elasticsearch-operator/src/test/java/de/ozgcloud/operator/user/ElasticsearchReconcilerTest.java b/ozgcloud-elasticsearch-operator/src/test/java/de/ozgcloud/operator/ElasticsearchReconcilerTest.java similarity index 69% rename from ozgcloud-elasticsearch-operator/src/test/java/de/ozgcloud/operator/user/ElasticsearchReconcilerTest.java rename to ozgcloud-elasticsearch-operator/src/test/java/de/ozgcloud/operator/ElasticsearchReconcilerTest.java index df095e430a96e168c6ed6c56b2aa4da8d56bb2fe..033ffdb860c496d419393df5afec31926c2a8c70 100644 --- a/ozgcloud-elasticsearch-operator/src/test/java/de/ozgcloud/operator/user/ElasticsearchReconcilerTest.java +++ b/ozgcloud-elasticsearch-operator/src/test/java/de/ozgcloud/operator/ElasticsearchReconcilerTest.java @@ -1,4 +1,4 @@ -package de.ozgcloud.operator.user; +package de.ozgcloud.operator; import static org.assertj.core.api.Assertions.*; import static org.mockito.ArgumentMatchers.*; @@ -12,8 +12,6 @@ import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.Spy; -import de.ozgcloud.operator.CustomResourceStatus; -import de.ozgcloud.operator.common.elasticsearch.OzgCloudElasticsearchService; import de.ozgcloud.operator.common.kubernetes.NamespaceTestFactory; import de.ozgcloud.operator.common.kubernetes.SecretTestFactory; import io.fabric8.kubernetes.api.model.Secret; @@ -27,8 +25,6 @@ class ElasticsearchReconcilerTest { @InjectMocks private ElasticsearchReconciler reconciler; @Mock - private ElasticsearchService service; - @Mock private OzgCloudElasticsearchService searchService; @DisplayName("Reconcile") @@ -36,12 +32,12 @@ class ElasticsearchReconcilerTest { class TestReconcile { @Mock - private Context<ElasticsearchCustomResource> context; + private Context<OzgCloudElasticsearchCustomResource> context; - private final ElasticsearchCustomResource resource = ElasticsearchCustomResourceTestFactory.create(); + private final OzgCloudElasticsearchCustomResource resource = ElasticsearchCustomResourceTestFactory.create(); private final static String PASSWORD = "dummyPassword"; - private final Secret secret = SecretTestFactory.createBuilder().addToStringData(ElasticsearchSecretHelper.SECRET_PASSWORD_FIELD, PASSWORD).build(); + private final Secret secret = SecretTestFactory.createBuilder().addToStringData(OzgCloudElasticsearchSecretHelper.SECRET_PASSWORD_FIELD, PASSWORD).build(); @DisplayName("process flow") @Nested @@ -49,14 +45,14 @@ class ElasticsearchReconcilerTest { @BeforeEach void mockCredentialSecret() { - when(service.getOrCreateCredentialSecret(any(), any())).thenReturn(secret); + when(searchService.getOrCreateCredentialSecret(any(), any())).thenReturn(secret); } @Test void shouldGetCredentialSecret() { reconcile(); - verify(service).getOrCreateCredentialSecret(resource, context); + verify(searchService).getOrCreateCredentialSecret(resource, context); } @SneakyThrows @@ -64,7 +60,7 @@ class ElasticsearchReconcilerTest { void shouldCheckIndex() { reconcile(); - verify(searchService).checkIndex(NamespaceTestFactory.NAMESPACE); + verify(searchService).createIndexIfMissing(NamespaceTestFactory.NAMESPACE); } @SneakyThrows @@ -72,7 +68,7 @@ class ElasticsearchReconcilerTest { void shouldCheckSecurityRole() { reconcile(); - verify(searchService).checkSecurityRole(NamespaceTestFactory.NAMESPACE); + verify(searchService).createSecurityRoleIfMissing(NamespaceTestFactory.NAMESPACE); } @SneakyThrows @@ -92,7 +88,7 @@ class ElasticsearchReconcilerTest { @BeforeEach void mock() { - when(service.getOrCreateCredentialSecret(any(), any())).thenThrow(exception); + when(searchService.getOrCreateCredentialSecret(any(), any())).thenThrow(exception); } @Test @@ -104,7 +100,7 @@ class ElasticsearchReconcilerTest { } @SneakyThrows - private UpdateControl<ElasticsearchCustomResource> reconcile() { + private UpdateControl<OzgCloudElasticsearchCustomResource> reconcile() { return reconciler.reconcile(resource, context); } @@ -112,7 +108,7 @@ class ElasticsearchReconcilerTest { @Nested class TestBuildExceptionUpdateControl { - private final ElasticsearchCustomResource resource = ElasticsearchCustomResourceTestFactory.create(); + private final OzgCloudElasticsearchCustomResource resource = ElasticsearchCustomResourceTestFactory.create(); private final static String EXCEPTION_MESSAGE = "ExeptionMessage"; private final Exception exception = new RuntimeException(EXCEPTION_MESSAGE); @@ -144,9 +140,26 @@ class ElasticsearchReconcilerTest { assertThat(updateControl.getResource().getStatus().getMessage()).isEqualTo(EXCEPTION_MESSAGE); } - private UpdateControl<ElasticsearchCustomResource> buildExceptionUpdateControl() { + private UpdateControl<OzgCloudElasticsearchCustomResource> buildExceptionUpdateControl() { return reconciler.buildExceptionUpdateControl(resource, exception); } } } + + @DisplayName("Cleanup") + @Nested + class TestCleanup { + + @Mock + private Context<OzgCloudElasticsearchCustomResource> context; + + private final OzgCloudElasticsearchCustomResource resource = ElasticsearchCustomResourceTestFactory.create(); + + @Test + void shouldReturnDeleteControl(){ + var deleteControl = reconciler.cleanup(resource, context); + + assertThat(deleteControl).isNotNull(); + } + } } \ No newline at end of file diff --git a/ozgcloud-elasticsearch-operator/src/test/java/de/ozgcloud/operator/user/ElasticsearchSecretBuilderTest.java b/ozgcloud-elasticsearch-operator/src/test/java/de/ozgcloud/operator/ElasticsearchSecretBuilderTest.java similarity index 72% rename from ozgcloud-elasticsearch-operator/src/test/java/de/ozgcloud/operator/user/ElasticsearchSecretBuilderTest.java rename to ozgcloud-elasticsearch-operator/src/test/java/de/ozgcloud/operator/ElasticsearchSecretBuilderTest.java index 38b451c2bee42b6168c0f255767ebe52a2f1c791..2d5e6fa62fe3a8a2fca20d681feb40bb8124db80 100644 --- a/ozgcloud-elasticsearch-operator/src/test/java/de/ozgcloud/operator/user/ElasticsearchSecretBuilderTest.java +++ b/ozgcloud-elasticsearch-operator/src/test/java/de/ozgcloud/operator/ElasticsearchSecretBuilderTest.java @@ -1,4 +1,4 @@ -package de.ozgcloud.operator.user; +package de.ozgcloud.operator; import static org.assertj.core.api.Assertions.*; import static org.mockito.Mockito.*; @@ -11,7 +11,7 @@ import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.Spy; -import de.ozgcloud.operator.common.elasticsearch.OzgCloudElasticsearchProperties; +import de.ozgcloud.operator.OzgCloudElasticsearchSecretHelper; import de.ozgcloud.operator.common.kubernetes.NamespaceTestFactory; import de.ozgcloud.operator.common.kubernetes.SecretTestFactory; import io.fabric8.kubernetes.api.model.Secret; @@ -20,7 +20,7 @@ class ElasticsearchSecretBuilderTest { @Spy @InjectMocks - private ElasticsearchSecretHelper builder; + private OzgCloudElasticsearchSecretHelper builder; @Mock private OzgCloudElasticsearchProperties properties; @@ -41,7 +41,7 @@ class ElasticsearchSecretBuilderTest { void shouldContainType() { var secret = buildCredentialSecret(); - assertThat(secret.getType()).isEqualTo(ElasticsearchSecretHelper.SECRET_TYPE); + assertThat(secret.getType()).isEqualTo(OzgCloudElasticsearchSecretHelper.SECRET_TYPE); } @DisplayName("metadata") @@ -71,7 +71,7 @@ class ElasticsearchSecretBuilderTest { void shouldBeSet() { var secret = buildCredentialSecret(); - assertThat(secret.getStringData()).containsEntry(ElasticsearchSecretHelper.SECRET_ADDRESS_FIELD, String.format("%s:%s", ADDRESS, PORT)); + assertThat(secret.getStringData()).containsEntry(OzgCloudElasticsearchSecretHelper.SECRET_ADDRESS_FIELD, String.format("%s:%s", ADDRESS, PORT)); } @Test @@ -93,22 +93,22 @@ class ElasticsearchSecretBuilderTest { void shouldContainIndex() { var secret = buildCredentialSecret(); - assertThat(secret.getStringData()).containsEntry(ElasticsearchSecretHelper.SECRET_INDEX_FIELD, NamespaceTestFactory.NAMESPACE); + assertThat(secret.getStringData()).containsEntry(OzgCloudElasticsearchSecretHelper.SECRET_INDEX_FIELD, NamespaceTestFactory.NAMESPACE); } @Test void shouldContainPassword() { var secret = buildCredentialSecret(); - assertThat(secret.getStringData()).containsKey(ElasticsearchSecretHelper.SECRET_PASSWORD_FIELD); - assertThat(secret.getStringData().get(ElasticsearchSecretHelper.SECRET_PASSWORD_FIELD)).isNotNull(); + assertThat(secret.getStringData()).containsKey(OzgCloudElasticsearchSecretHelper.SECRET_PASSWORD_FIELD); + assertThat(secret.getStringData().get(OzgCloudElasticsearchSecretHelper.SECRET_PASSWORD_FIELD)).isNotNull(); } @Test void shouldContainUsername() { var secret = buildCredentialSecret(); - assertThat(secret.getStringData()).containsEntry(ElasticsearchSecretHelper.SECRET_USERNAME_FIELD, NamespaceTestFactory.NAMESPACE); + assertThat(secret.getStringData()).containsEntry(OzgCloudElasticsearchSecretHelper.SECRET_USERNAME_FIELD, NamespaceTestFactory.NAMESPACE); } private Secret buildCredentialSecret() { diff --git a/ozgcloud-elasticsearch-operator/src/test/java/de/ozgcloud/operator/user/IndicesPrivilegesDataTestFactory.java b/ozgcloud-elasticsearch-operator/src/test/java/de/ozgcloud/operator/IndicesPrivilegesDataTestFactory.java similarity index 71% rename from ozgcloud-elasticsearch-operator/src/test/java/de/ozgcloud/operator/user/IndicesPrivilegesDataTestFactory.java rename to ozgcloud-elasticsearch-operator/src/test/java/de/ozgcloud/operator/IndicesPrivilegesDataTestFactory.java index e6056bb7e1408c660612997278f42e44731e800b..9333775ebdc8fc9b1ffcb510e09b78781519ae90 100644 --- a/ozgcloud-elasticsearch-operator/src/test/java/de/ozgcloud/operator/user/IndicesPrivilegesDataTestFactory.java +++ b/ozgcloud-elasticsearch-operator/src/test/java/de/ozgcloud/operator/IndicesPrivilegesDataTestFactory.java @@ -1,13 +1,13 @@ -package de.ozgcloud.operator.user; +package de.ozgcloud.operator; import com.thedeanda.lorem.LoremIpsum; -import de.ozgcloud.operator.user.PutRoleRequestData.IndicesPrivilegesData; +import de.ozgcloud.operator.PutRoleRequestData.IndicesPrivilegesData; public class IndicesPrivilegesDataTestFactory { public static final String NAME = LoremIpsum.getInstance().getFirstName(); - public static final String PRIVILEGES = "all"; + public static final String PRIVILEGES = IndicesPrivilege.ALL.getValue(); public static IndicesPrivilegesData create() { return createBuilder().build(); diff --git a/ozgcloud-elasticsearch-operator/src/test/java/de/ozgcloud/operator/user/ObjectMetaTestFactory.java b/ozgcloud-elasticsearch-operator/src/test/java/de/ozgcloud/operator/ObjectMetaTestFactory.java similarity index 90% rename from ozgcloud-elasticsearch-operator/src/test/java/de/ozgcloud/operator/user/ObjectMetaTestFactory.java rename to ozgcloud-elasticsearch-operator/src/test/java/de/ozgcloud/operator/ObjectMetaTestFactory.java index 9a1a120460dd9c720841c45c4542ad1757f1e880..c86a0813c25cd1cf7c0315db3078f1af8df934d1 100644 --- a/ozgcloud-elasticsearch-operator/src/test/java/de/ozgcloud/operator/user/ObjectMetaTestFactory.java +++ b/ozgcloud-elasticsearch-operator/src/test/java/de/ozgcloud/operator/ObjectMetaTestFactory.java @@ -1,4 +1,4 @@ -package de.ozgcloud.operator.user; +package de.ozgcloud.operator; import de.ozgcloud.operator.common.kubernetes.NamespaceTestFactory; import io.fabric8.kubernetes.api.model.ObjectMeta; diff --git a/ozgcloud-elasticsearch-operator/src/test/java/de/ozgcloud/operator/OzgCloudElasticsearchServiceTest.java b/ozgcloud-elasticsearch-operator/src/test/java/de/ozgcloud/operator/OzgCloudElasticsearchServiceTest.java new file mode 100644 index 0000000000000000000000000000000000000000..88be60a5c1c5469f95c3fd6a0046044ec9b115eb --- /dev/null +++ b/ozgcloud-elasticsearch-operator/src/test/java/de/ozgcloud/operator/OzgCloudElasticsearchServiceTest.java @@ -0,0 +1,249 @@ +package de.ozgcloud.operator; + +import static de.ozgcloud.operator.common.kubernetes.NamespaceTestFactory.*; +import static org.assertj.core.api.Assertions.*; +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.Mockito.*; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Spy; + +import de.ozgcloud.operator.common.elasticsearch.ElasticsearchRemoteService; +import de.ozgcloud.operator.common.kubernetes.KubernetesRemoteService; +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.client.dsl.Resource; +import io.fabric8.kubernetes.client.extension.ResourceAdapter; +import io.javaoperatorsdk.operator.api.reconciler.Context; +import lombok.SneakyThrows; + +class OzgCloudElasticsearchServiceTest { + + @Spy + @InjectMocks + private OzgCloudElasticsearchService service; + @Mock + private ElasticsearchRemoteService remoteService; + @Mock + private OzgCloudElasticsearchSecretHelper secretHelper; + @Mock + private OzgCloudElasticsearchProperties properties; + @Mock + private KubernetesRemoteService kubernetesService; + + @DisplayName("Get or create secret") + @Nested + class TestGetOrCreateSecret { + + @Mock + private Context<OzgCloudElasticsearchCustomResource> context; + @Mock + private ResourceAdapter<Secret> resourceAdapter; + @Mock + private Resource<Secret> secretResource; + + private final Secret secret = SecretTestFactory.create(); + + private final OzgCloudElasticsearchCustomResource resource = ElasticsearchCustomResourceTestFactory.create(); + + @BeforeEach + void mock() { + when(kubernetesService.getSecretResource(any(), any())).thenReturn(secretResource); + when(secretResource.get()).thenReturn(secret); + when(properties.getSecretCredentialsName()).thenReturn(IndicesPrivilegesDataTestFactory.PRIVILEGES); + } + + @Test + void shouldGetSecret() { + service.getOrCreateCredentialSecret(resource, context); + + verify(kubernetesService).getSecretResource(NamespaceTestFactory.NAMESPACE, IndicesPrivilegesDataTestFactory.PRIVILEGES); + } + + @DisplayName("on existing") + @Nested + class TestOnExisting { + + @Test + void shouldReturnSecret() { + var secret = service.getOrCreateCredentialSecret(resource, context); + + assertThat(secret).isNotNull(); + } + } + + @DisplayName("on missing secret") + @Nested + class TestOnMissingSecret { + + @BeforeEach + void mock() { + when(secretResource.get()).thenReturn(null); + + doReturn(resourceAdapter).when(service).createAdapter(any()); + } + + @Test + void shouldBuildSecret() { + service.getOrCreateCredentialSecret(resource, context); + + verify(secretHelper).buildCredentialSecret(NamespaceTestFactory.NAMESPACE, IndicesPrivilegesDataTestFactory.PRIVILEGES); + } + + @Test + void shouldCreateSecret() { + when(secretHelper.buildCredentialSecret(any(), any())).thenReturn(secret); + + service.getOrCreateCredentialSecret(resource, context); + + verify(resourceAdapter).create(secret); + } + } + } + + @DisplayName("Create index if missing") + @Nested + class TestCreateIndexIfMissing { + + @SneakyThrows + @Test + void shouldCheckIfIndexExists() { + service.createIndexIfMissing(NAMESPACE); + + verify(remoteService).existsIndex(NAMESPACE); + } + + @SneakyThrows + @Test + void shouldCreateIndexIfMissing() { + when(remoteService.existsIndex(any())).thenReturn(false); + + service.createIndexIfMissing(NAMESPACE); + + verify(remoteService).createIndex(NAMESPACE); + } + } + + @DisplayName("Check security role if missing") + @Nested + class TestCheckSecurityRoleIfMissing { + + private final PutRoleRequestData putRoleRequest = PutRoleRequestDataTestFactory.create(); + + @SneakyThrows + @Test + void shouldCheckIfSecurityRoleExists() { + service.createSecurityRoleIfMissing(NAMESPACE); + + verify(remoteService).existsSecurityRole(NAMESPACE); + } + + @SneakyThrows + @Test + void shouldCreateSecurityRoleIfMissing() { + when(remoteService.existsSecurityRole(any())).thenReturn(false); + doReturn(putRoleRequest).when(service).buildPutRoleRequestData(any()); + + service.createSecurityRoleIfMissing(NAMESPACE); + + verify(remoteService).createSecurityRole(putRoleRequest); + } + + @DisplayName("create put role request data") + @Nested + class TestCreatePutRoleRequestData { + + @Test + void shouldContainName() { + var requestData = buildPutRoleRequestData(); + + assertThat(requestData.getName()).isEqualTo(NAMESPACE); + } + + @DisplayName("indices privileges data") + @Nested + class TestIndicesPrivilegesData { + + @Test + void shouldContainName() { + var requestData = buildPutRoleRequestData(); + + assertThat(requestData.getIndivesPrivilegesData().getNames()).isEqualTo(NAMESPACE); + } + + @Test + void shouldContainPrivileges() { + var requestData = buildPutRoleRequestData(); + + assertThat(requestData.getIndivesPrivilegesData().getPrivileges()).isEqualTo(IndicesPrivilegesDataTestFactory.PRIVILEGES); + } + } + + private PutRoleRequestData buildPutRoleRequestData() { + return service.buildPutRoleRequestData(NAMESPACE); + } + } + } + + @DisplayName("Create security user if missing") + @Nested + class TestCheckSecurityUserIfMissing { + + private final PutUserRequestData putUserRequestData = PutUserRequestDataTestFactory.create(); + + @SneakyThrows + @Test + void shouldCheckIfSecurityUserExists() { + service.checkSecurityUser(NAMESPACE, PutUserRequestDataTestFactory.PASSWORD); + + verify(remoteService).existsSecurityUser(NAMESPACE); + } + + @SneakyThrows + @Test + void shouldCreateSecurityUserIfMissing() { + when(remoteService.existsSecurityUser(any())).thenReturn(false); + doReturn(putUserRequestData).when(service).buildPutUserRequestData(any(), any()); + + service.checkSecurityUser(NAMESPACE, PutUserRequestDataTestFactory.PASSWORD); + + verify(remoteService).createSecurityUser(putUserRequestData); + } + + @DisplayName("create put user request data") + @Nested + class TestCreatePutUserRequestData { + + @Test + void shouldContainUsername() { + var requestData = buildPutUserRequestData(); + + assertThat(requestData.getUsername()).isEqualTo(NAMESPACE); + } + + @Test + void shouldContainRoles() { + var requestData = buildPutUserRequestData(); + + assertThat(requestData.getRoles()).isEqualTo(NAMESPACE); + } + + @Test + void shouldContainPassword() { + var requestData = buildPutUserRequestData(); + + assertThat(requestData.getPassword()).isEqualTo(PutUserRequestDataTestFactory.PASSWORD); + } + + private PutUserRequestData buildPutUserRequestData() { + return service.buildPutUserRequestData(NAMESPACE, PutUserRequestDataTestFactory.PASSWORD); + } + } + } +} \ No newline at end of file diff --git a/ozgcloud-elasticsearch-operator/src/test/java/de/ozgcloud/operator/user/PutRoleRequestDataTestFactory.java b/ozgcloud-elasticsearch-operator/src/test/java/de/ozgcloud/operator/PutRoleRequestDataTestFactory.java similarity index 85% rename from ozgcloud-elasticsearch-operator/src/test/java/de/ozgcloud/operator/user/PutRoleRequestDataTestFactory.java rename to ozgcloud-elasticsearch-operator/src/test/java/de/ozgcloud/operator/PutRoleRequestDataTestFactory.java index a8fe8c7744b03d3629c90b2d45787435a97ece0e..b190f6b80f179d06264c7d7445a24ad738689352 100644 --- a/ozgcloud-elasticsearch-operator/src/test/java/de/ozgcloud/operator/user/PutRoleRequestDataTestFactory.java +++ b/ozgcloud-elasticsearch-operator/src/test/java/de/ozgcloud/operator/PutRoleRequestDataTestFactory.java @@ -1,7 +1,9 @@ -package de.ozgcloud.operator.user; +package de.ozgcloud.operator; import com.thedeanda.lorem.LoremIpsum; +import de.ozgcloud.operator.PutRoleRequestData; + public class PutRoleRequestDataTestFactory { public static final String NAME = LoremIpsum.getInstance().getFirstName(); diff --git a/ozgcloud-elasticsearch-operator/src/test/java/de/ozgcloud/operator/user/PutUserRequestDataTestFactory.java b/ozgcloud-elasticsearch-operator/src/test/java/de/ozgcloud/operator/PutUserRequestDataTestFactory.java similarity index 76% rename from ozgcloud-elasticsearch-operator/src/test/java/de/ozgcloud/operator/user/PutUserRequestDataTestFactory.java rename to ozgcloud-elasticsearch-operator/src/test/java/de/ozgcloud/operator/PutUserRequestDataTestFactory.java index bb4ce94ba2c31f43f7443032202c40f01bed9e01..0c8fc65a96eac4761f82b126be7af594ca6c58ac 100644 --- a/ozgcloud-elasticsearch-operator/src/test/java/de/ozgcloud/operator/user/PutUserRequestDataTestFactory.java +++ b/ozgcloud-elasticsearch-operator/src/test/java/de/ozgcloud/operator/PutUserRequestDataTestFactory.java @@ -1,4 +1,6 @@ -package de.ozgcloud.operator.user; +package de.ozgcloud.operator; + +import org.apache.commons.lang3.RandomStringUtils; import com.thedeanda.lorem.LoremIpsum; @@ -6,7 +8,7 @@ public class PutUserRequestDataTestFactory { public static final String USERNAME = LoremIpsum.getInstance().getFirstName(); public static final String ROLES = LoremIpsum.getInstance().getWords(1); - public static final String PASSWORD = LoremIpsum.getInstance().getWords(1); + public static final String PASSWORD = RandomStringUtils.randomAlphanumeric(6); public static PutUserRequestData create() { return createBuilder().build(); diff --git a/ozgcloud-elasticsearch-operator/src/test/java/de/ozgcloud/operator/common/elasticsearch/ElasticsearchRemoteServiceITCase.java b/ozgcloud-elasticsearch-operator/src/test/java/de/ozgcloud/operator/common/elasticsearch/ElasticsearchRemoteServiceITCase.java new file mode 100644 index 0000000000000000000000000000000000000000..db47f4c02addcf9b2abb334818210b036dd1d68c --- /dev/null +++ b/ozgcloud-elasticsearch-operator/src/test/java/de/ozgcloud/operator/common/elasticsearch/ElasticsearchRemoteServiceITCase.java @@ -0,0 +1,244 @@ +package de.ozgcloud.operator.common.elasticsearch; + +import static org.assertj.core.api.Assertions.*; + +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +import co.elastic.clients.elasticsearch.ElasticsearchClient; +import co.elastic.clients.elasticsearch.indices.DeleteIndexRequest; +import co.elastic.clients.elasticsearch.indices.ExistsRequest; +import co.elastic.clients.elasticsearch.security.DeleteRoleRequest; +import co.elastic.clients.elasticsearch.security.DeleteUserRequest; +import co.elastic.clients.elasticsearch.security.GetRoleRequest; +import co.elastic.clients.elasticsearch.security.GetUserRequest; +import de.ozgcloud.operator.PutRoleRequestDataTestFactory; +import de.ozgcloud.operator.PutUserRequestDataTestFactory; +import lombok.SneakyThrows; + +class ElasticsearchRemoteServiceITCase { + + private static final String INDEX_NAME = "test_index"; + + private final ElasticsearchClient client = ElasticsearchTestClient.create(); + private final ElasticsearchRemoteService service = new ElasticsearchRemoteService(client); + + @BeforeAll + public static void startContainer() { + ElasticsearchTestClient.ELASTICSEARCH_CONTAINER.start(); + } + + @AfterAll + public static void stopContainer() { + ElasticsearchTestClient.ELASTICSEARCH_CONTAINER.stop(); + } + + @DisplayName("Exists index") + @Nested + class TestExistsIndex { + + @DisplayName("on existing") + @Nested + class TestOnExisting { + + @SneakyThrows + @BeforeEach + private void initIndex() { + createIndex(); + } + + @AfterEach + void cleanup() { + deleteIndex(); + } + + @SneakyThrows + @Test + void shouldReturnTrue() { + var exists = service.existsIndex(INDEX_NAME); + + assertThat(exists).isTrue(); + } + } + + @SneakyThrows + @Test + void shouldReturnFalseIfMissing() { + var exists = service.existsIndex(INDEX_NAME); + + assertThat(exists).isFalse(); + } + } + + @DisplayName("Create index") + @Nested + class TestCreateIndex { + + @AfterEach + void cleanup() { + deleteIndex(); + } + + @SneakyThrows + @Test + void shouldCreateIndex() { + service.createIndex(INDEX_NAME); + + assertThat(existsIndex()).isTrue(); + } + + @SneakyThrows + private boolean existsIndex() { + return client.indices().exists(ExistsRequest.of(builder -> builder.index(INDEX_NAME))).value(); + } + } + + @SneakyThrows + private void deleteIndex() { + client.indices().delete(DeleteIndexRequest.of(builder -> builder.index(INDEX_NAME))); + } + + @DisplayName("Exists security role") + @Nested + class TestExistsSecurityRole { + + @DisplayName("on existing") + @Nested + class TestOnExisting { + + @SneakyThrows + @BeforeEach + private void initSecurityRole() { + createIndex(); + client.security().putRole(service.createPutRoleRequest(PutRoleRequestDataTestFactory.create())); + } + + @AfterEach + void cleanup() { + deleteIndex(); + } + + @SneakyThrows + @Test + void shouldReturnTrue() { + var exists = service.existsSecurityRole(PutRoleRequestDataTestFactory.NAME); + + assertThat(exists).isTrue(); + } + } + + @SneakyThrows + @Test + void shouldReturnFalseIfMissing() { + var exists = service.existsSecurityRole(PutRoleRequestDataTestFactory.NAME); + + assertThat(exists).isFalse(); + } + } + + @DisplayName("Create security role") + @Nested + class TestCreateSecurityRole { + + @AfterEach + void cleanup() { + deleteSecurityRole(); + } + + @SneakyThrows + @Test + void shouldCreateSecurityRole() { + service.createSecurityRole(PutRoleRequestDataTestFactory.create()); + + assertThat(existsSecurityRole()).isTrue(); + } + + @SneakyThrows + private boolean existsSecurityRole() { + var role = client.security().getRole(GetRoleRequest.of(builder -> builder.name(PutRoleRequestDataTestFactory.NAME))); + return !role.result().isEmpty(); + } + + @SneakyThrows + private void deleteSecurityRole() { + client.security().deleteRole(DeleteRoleRequest.of(builder -> builder.name(PutRoleRequestDataTestFactory.NAME))); + } + } + + @DisplayName("Exists security user") + @Nested + class TestExistsSecurityUser { + + @DisplayName("on existing") + @Nested + class TestOnExisting { + + @SneakyThrows + @BeforeEach + private void initSecurityUser() { + createIndex(); + client.security().putUser(service.createPutUserRequest(PutUserRequestDataTestFactory.create())); + } + + @AfterEach + void cleanup() { + deleteIndex(); + } + + @SneakyThrows + @Test + void shouldReturnTrue() { + var exists = service.existsSecurityUser(PutUserRequestDataTestFactory.USERNAME); + + assertThat(exists).isTrue(); + } + } + + @SneakyThrows + @Test + void shouldReturnFalseIfMissing() { + var exists = service.existsSecurityUser(PutUserRequestDataTestFactory.USERNAME); + + assertThat(exists).isFalse(); + } + } + + @SneakyThrows + private void createIndex() { + client.indices().create(builder -> builder.index(INDEX_NAME)); + } + + @DisplayName("Create security user") + @Nested + class TestCreateSecurityUser { + + @AfterEach + void cleanup() { + deleteSecurityUser(); + } + + @SneakyThrows + @Test + void shouldCreateSecurityUser() { + service.createSecurityUser(PutUserRequestDataTestFactory.create()); + + assertThat(existsSecurityUser()).isTrue(); + } + + @SneakyThrows + private boolean existsSecurityUser() { + var user = client.security().getUser(GetUserRequest.of(builder -> builder.username(PutUserRequestDataTestFactory.USERNAME))); + return !user.result().isEmpty(); + } + + @SneakyThrows + private void deleteSecurityUser() { + client.security().deleteUser(DeleteUserRequest.of(builder -> builder.username(PutUserRequestDataTestFactory.USERNAME))); + } + } +} \ No newline at end of file diff --git a/ozgcloud-elasticsearch-operator/src/test/java/de/ozgcloud/operator/common/elasticsearch/ElasticsearchRemoteServiceTest.java b/ozgcloud-elasticsearch-operator/src/test/java/de/ozgcloud/operator/common/elasticsearch/ElasticsearchRemoteServiceTest.java new file mode 100644 index 0000000000000000000000000000000000000000..b095c72ea381d25fc67f21d6f1eb1ccef5944b88 --- /dev/null +++ b/ozgcloud-elasticsearch-operator/src/test/java/de/ozgcloud/operator/common/elasticsearch/ElasticsearchRemoteServiceTest.java @@ -0,0 +1,126 @@ +package de.ozgcloud.operator.common.elasticsearch; + +import static org.assertj.core.api.Assertions.*; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Spy; + +import com.thedeanda.lorem.LoremIpsum; + +import co.elastic.clients.elasticsearch.ElasticsearchClient; +import de.ozgcloud.operator.IndicesPrivilegesDataTestFactory; +import de.ozgcloud.operator.PutRoleRequestDataTestFactory; +import de.ozgcloud.operator.PutUserRequestDataTestFactory; + +class ElasticsearchRemoteServiceTest { + + @Spy + @InjectMocks + private ElasticsearchRemoteService service; + @Mock + private ElasticsearchClient client; + + @DisplayName("Create security role") + @Nested + class TestCreateIndex { + + @DisplayName("create exists request") + @Nested + class TestCreateExistsRequest { + + private static final String INDEX = LoremIpsum.getInstance().getFirstName(); + + @Test + void shouldHaveIndex() { + var request = service.createExistsRequest(INDEX); + + assertThat(request.index()).containsExactly(INDEX); + } + } + } + + @DisplayName("Create get role request") + @Nested + class TestCreateGetRoleRequest { + + private static final String NAME = LoremIpsum.getInstance().getFirstName(); + + @Test + void shouldHaveName() { + var request = service.createGetRoleRequest(NAME); + + assertThat(request.name()).containsExactly(NAME); + } + } + + @DisplayName("Create security role") + @Nested + class TestCreateSecurityRole { + + @DisplayName("create put role request") + @Nested + class TestCreatePutRoleRequest { + + @Test + void shouldHaveName() { + var request = service.createPutRoleRequest(PutRoleRequestDataTestFactory.create()); + + assertThat(request.name()).isEqualTo(PutRoleRequestDataTestFactory.NAME); + } + + @DisplayName("indices privileges") + @Nested + class TestIndicesPrivileges { + + @Test + void shouldHaveName() { + var request = service.createPutRoleRequest(PutRoleRequestDataTestFactory.create()); + + assertThat(request.indices().get(0).names()).containsExactly(IndicesPrivilegesDataTestFactory.NAME); + } + + @Test + void shouldHavePrivileges() { + var request = service.createPutRoleRequest(PutRoleRequestDataTestFactory.create()); + + assertThat(request.indices().get(0).privileges()).containsExactly(IndicesPrivilegesDataTestFactory.PRIVILEGES); + } + } + } + } + + @DisplayName("Create security user") + @Nested + class TestCreateSecurityUser { + + @DisplayName("create put user request") + @Nested + class TestCreatePutUserRequest { + + @Test + void shouldHaveName() { + var request = service.createPutUserRequest(PutUserRequestDataTestFactory.create()); + + assertThat(request.username()).isEqualTo(PutUserRequestDataTestFactory.USERNAME); + } + + @Test + void shouldHaveRoles() { + var request = service.createPutUserRequest(PutUserRequestDataTestFactory.create()); + + assertThat(request.roles()).containsExactly(PutUserRequestDataTestFactory.ROLES); + } + + @Test + void shouldHavePassword() { + var request = service.createPutUserRequest(PutUserRequestDataTestFactory.create()); + + assertThat(request.password()).isEqualTo(PutUserRequestDataTestFactory.PASSWORD); + } + } + } +} \ No newline at end of file diff --git a/ozgcloud-elasticsearch-operator/src/test/java/de/ozgcloud/operator/common/elasticsearch/ElasticsearchTestClient.java b/ozgcloud-elasticsearch-operator/src/test/java/de/ozgcloud/operator/common/elasticsearch/ElasticsearchTestClient.java new file mode 100644 index 0000000000000000000000000000000000000000..ac592cd1c66251c7d8185afaf8496f0fbb314583 --- /dev/null +++ b/ozgcloud-elasticsearch-operator/src/test/java/de/ozgcloud/operator/common/elasticsearch/ElasticsearchTestClient.java @@ -0,0 +1,59 @@ +package de.ozgcloud.operator.common.elasticsearch; + +import java.time.Duration; +import java.time.temporal.ChronoUnit; + +import org.apache.http.HttpHost; +import org.apache.http.auth.AuthScope; +import org.apache.http.auth.UsernamePasswordCredentials; +import org.apache.http.impl.client.BasicCredentialsProvider; +import org.elasticsearch.client.RestClient; +import org.testcontainers.elasticsearch.ElasticsearchContainer; + +import co.elastic.clients.elasticsearch.ElasticsearchClient; +import co.elastic.clients.json.jackson.JacksonJsonpMapper; +import co.elastic.clients.transport.rest_client.RestClientTransport; + +public class ElasticsearchTestClient { + + private static final String IMAGE_NAME = "docker.elastic.co/elasticsearch/elasticsearch:8.11.3"; + private static final String USER = "elastic"; + private static final String PASSWORD = "s3cret"; + private static final int PORT = 9200; + private static final String SCHEME = "https"; + private static final Duration STARTUP_TIMEOUT = Duration.of(2, ChronoUnit.MINUTES); + + public static final ElasticsearchContainer ELASTICSEARCH_CONTAINER = new ElasticsearchContainer(IMAGE_NAME) + .withExposedPorts(PORT) + .withPassword(PASSWORD) + .withStartupTimeout(STARTUP_TIMEOUT); + + public static ElasticsearchClient create() { + var transport = new RestClientTransport(buildRestClient(), new JacksonJsonpMapper()); + return new ElasticsearchClient(transport); + } + + private static RestClient buildRestClient() { + var host = new HttpHost("localhost", ELASTICSEARCH_CONTAINER.getMappedPort(PORT), SCHEME); + var credentialsProvider = buildCredentialsProvider(); + var builder = RestClient.builder(host); + + builder.setHttpClientConfigCallback(clientBuilder -> { + clientBuilder.setSSLContext(ELASTICSEARCH_CONTAINER.createSslContextFromCa()); + clientBuilder.setDefaultCredentialsProvider(credentialsProvider); + return clientBuilder; + }); +// builder.setNodeSelector(INGEST_NODE_SELECTOR); +// final ObjectMapper mapper = new ObjectMapper(); +// mapper.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE); +// mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); + return builder.build(); + } + + private static BasicCredentialsProvider buildCredentialsProvider() { + var credentialsProvider = new BasicCredentialsProvider(); + credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(USER, PASSWORD)); + return credentialsProvider; + } + +} diff --git a/ozgcloud-elasticsearch-operator/src/test/java/de/ozgcloud/operator/common/elasticsearch/OzgCloudElasticsearchRemoteServiceITCase.java b/ozgcloud-elasticsearch-operator/src/test/java/de/ozgcloud/operator/common/elasticsearch/OzgCloudElasticsearchRemoteServiceITCase.java deleted file mode 100644 index 7493298aea4d592a5d395b64e7bd33ec533a7ae4..0000000000000000000000000000000000000000 --- a/ozgcloud-elasticsearch-operator/src/test/java/de/ozgcloud/operator/common/elasticsearch/OzgCloudElasticsearchRemoteServiceITCase.java +++ /dev/null @@ -1,70 +0,0 @@ -package de.ozgcloud.operator.common.elasticsearch; - -import static org.mockito.Mockito.*; - -import java.time.Duration; -import java.time.temporal.ChronoUnit; - -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Nested; -import org.junit.jupiter.api.Test; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.Spy; -import org.testcontainers.elasticsearch.ElasticsearchContainer; - -import de.ozgcloud.operator.common.kubernetes.KubernetesService; -import lombok.SneakyThrows; - -class OzgCloudElasticsearchRemoteServiceITCase { - - @Spy - @InjectMocks - private OzgCloudElasticsearchRemoteService service; - @Mock - private OzgCloudElasticsearchProperties elasticSearchProperties; - @Mock - private KubernetesService kubernetesService; - - private static final String DOCKER_IMAGE_NAME = "docker.elastic.co/elasticsearch/elasticsearch:8.11.3"; - private static final String CONTAINER_PASSWORD = "s3cret"; - private static final String CONTAINER_NAME = "elastic"; - - @Disabled("FIXME: Connection Refused") - @DisplayName("Exists index") - @Nested - class TestExistsIndex { - - @SneakyThrows - @Test - void shouldTest() { - when(elasticSearchProperties.getHost()).thenReturn("localhost"); - when(elasticSearchProperties.getPort()).thenReturn(9200); - when(elasticSearchProperties.getSecretData()).thenReturn(CONTAINER_NAME); -// doReturn(CONTAINER_PASSWORD).when(service).getPassword(); - -// var client = service.createClient(CONTAINER_NAME, CONTAINER_PASSWORD); - - try (var container = createContainer()) { - container.getEnvMap().remove("xpack.security.enabled"); -// container.setWaitStrategy(new LogMessageWaitStrategy().withRegEx(".*\"message\":\"started\".*")); - container.start(); - - try { -// client.indices().create(builder -> builder.index("test")); - } catch(Exception e) { - e.printStackTrace(); - } - container.stop(); - } - } - - private static ElasticsearchContainer createContainer() { - return new ElasticsearchContainer(DOCKER_IMAGE_NAME) - .withExposedPorts(9200) - .withPassword(CONTAINER_PASSWORD) - .withStartupTimeout(Duration.of(2, ChronoUnit.MINUTES)); - } - } -} \ No newline at end of file diff --git a/ozgcloud-elasticsearch-operator/src/test/java/de/ozgcloud/operator/common/elasticsearch/OzgCloudElasticsearchRemoteServiceTest.java b/ozgcloud-elasticsearch-operator/src/test/java/de/ozgcloud/operator/common/elasticsearch/OzgCloudElasticsearchRemoteServiceTest.java deleted file mode 100644 index 726babacc70d5c29adc136cdea682cc969f4768a..0000000000000000000000000000000000000000 --- a/ozgcloud-elasticsearch-operator/src/test/java/de/ozgcloud/operator/common/elasticsearch/OzgCloudElasticsearchRemoteServiceTest.java +++ /dev/null @@ -1,91 +0,0 @@ -package de.ozgcloud.operator.common.elasticsearch; - -import static org.assertj.core.api.Assertions.*; - -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Nested; -import org.junit.jupiter.api.Test; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.Spy; - -import co.elastic.clients.elasticsearch.ElasticsearchClient; -import de.ozgcloud.operator.user.IndicesPrivilegesDataTestFactory; -import de.ozgcloud.operator.user.PutRoleRequestDataTestFactory; -import de.ozgcloud.operator.user.PutUserRequestDataTestFactory; - -class OzgCloudElasticsearchRemoteServiceTest { - - @Spy - @InjectMocks - private OzgCloudElasticsearchRemoteService service; - @Mock - private ElasticsearchClient client; - - @DisplayName("Create security role") - @Nested - class TestCreateSecurityRole { - - @DisplayName("create put role request of") - @Nested - class TestCreatePutRoleRequestOf { - - @Test - void shouldHaveName() { - var request = service.createPutRoleRequestOf(PutRoleRequestDataTestFactory.create()); - - assertThat(request.name()).isEqualTo(PutRoleRequestDataTestFactory.NAME); - } - - @DisplayName("indices privileges") - @Nested - class TestIndicesPrivileges { - - @Test - void shouldHaveName() { - var request = service.createPutRoleRequestOf(PutRoleRequestDataTestFactory.create()); - - assertThat(request.indices().get(0).names()).containsExactly(IndicesPrivilegesDataTestFactory.NAME); - } - - @Test - void shouldHavePrivileges() { - var request = service.createPutRoleRequestOf(PutRoleRequestDataTestFactory.create()); - - assertThat(request.indices().get(0).privileges()).containsExactly(IndicesPrivilegesDataTestFactory.PRIVILEGES); - } - } - } - } - - @DisplayName("Create security user") - @Nested - class TestCreateSecurityUser { - - @DisplayName("create put user request of") - @Nested - class TestCreatePutUserRequestOf { - - @Test - void shouldHaveName() { - var request = service.createPutUserRequestOf(PutUserRequestDataTestFactory.create()); - - assertThat(request.username()).isEqualTo(PutUserRequestDataTestFactory.USERNAME); - } - - @Test - void shouldHaveRoles() { - var request = service.createPutUserRequestOf(PutUserRequestDataTestFactory.create()); - - assertThat(request.roles()).containsExactly(PutUserRequestDataTestFactory.ROLES); - } - - @Test - void shouldHavePassword() { - var request = service.createPutUserRequestOf(PutUserRequestDataTestFactory.create()); - - assertThat(request.password()).isEqualTo(PutUserRequestDataTestFactory.PASSWORD); - } - } - } -} \ No newline at end of file diff --git a/ozgcloud-elasticsearch-operator/src/test/java/de/ozgcloud/operator/common/elasticsearch/OzgCloudElasticsearchServiceTest.java b/ozgcloud-elasticsearch-operator/src/test/java/de/ozgcloud/operator/common/elasticsearch/OzgCloudElasticsearchServiceTest.java deleted file mode 100644 index e3d604520ca9501d812874f50349199e58737eea..0000000000000000000000000000000000000000 --- a/ozgcloud-elasticsearch-operator/src/test/java/de/ozgcloud/operator/common/elasticsearch/OzgCloudElasticsearchServiceTest.java +++ /dev/null @@ -1,161 +0,0 @@ -package de.ozgcloud.operator.common.elasticsearch; - -import static de.ozgcloud.operator.common.kubernetes.NamespaceTestFactory.*; -import static org.assertj.core.api.Assertions.*; -import static org.mockito.ArgumentMatchers.*; -import static org.mockito.Mockito.*; - -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Nested; -import org.junit.jupiter.api.Test; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.Spy; - -import de.ozgcloud.operator.user.PutRoleRequestData; -import de.ozgcloud.operator.user.PutRoleRequestDataTestFactory; -import de.ozgcloud.operator.user.PutUserRequestData; -import de.ozgcloud.operator.user.PutUserRequestDataTestFactory; -import lombok.SneakyThrows; - -class OzgCloudElasticsearchServiceTest { - - @Spy - @InjectMocks - private OzgCloudElasticsearchService service; - @Mock - private OzgCloudElasticsearchRemoteService remoteService; - - @DisplayName("Check index") - @Nested - class TestCheckIndex { - - @SneakyThrows - @Test - void shouldCheckIfIndexExists() { - service.checkIndex(NAMESPACE); - - verify(remoteService).existsIndex(NAMESPACE); - } - - @SneakyThrows - @Test - void shouldCreateIndexIfMissing() { - when(remoteService.existsIndex(any())).thenReturn(false); - - service.checkIndex(NAMESPACE); - - verify(remoteService).createIndex(NAMESPACE); - } - } - - @DisplayName("Check security role") - @Nested - class TestCheckSecurityRole { - - private final PutRoleRequestData putRoleRequest = PutRoleRequestDataTestFactory.create(); - - @SneakyThrows - @Test - void shouldCheckIfSecurityRoleExists() { - service.checkSecurityRole(NAMESPACE); - - verify(remoteService).existsSecurityRole(NAMESPACE); - } - - @SneakyThrows - @Test - void shouldCreateSecurityRoleIfMissing() { - when(remoteService.existsSecurityRole(any())).thenReturn(false); - doReturn(putRoleRequest).when(service).buildPutRoleRequestData(any()); - - service.checkSecurityRole(NAMESPACE); - - verify(remoteService).createSecurityRole(putRoleRequest); - } - - @DisplayName("create put role request data") - @Nested - class TestCreatePutRoleRequestData { - - @Test - void shouldContainName() { - var requestData = service.buildPutRoleRequestData(NAMESPACE); - - assertThat(requestData.getName()).isEqualTo(NAMESPACE); - } - - @DisplayName("indices privileges data") - @Nested - class TestIndicesPrivilegesData { - - @Test - void shouldContainName() { - var request = service.buildPutRoleRequestData(NAMESPACE); - - assertThat(request.getIndivesPrivilegesData().getNames()).isEqualTo(NAMESPACE); - } - - @Test - void shouldContainPrivileges() { - var request = service.buildPutRoleRequestData(NAMESPACE); - - assertThat(request.getIndivesPrivilegesData().getPrivileges()).isEqualTo(OzgCloudElasticsearchService.PRIVILEGES_ALL); - } - } - } - } - - @DisplayName("Check security user") - @Nested - class TestCheckSecurityUser { - - private final static String PASSWORD = "DummyPassword"; - private final PutUserRequestData putUserRequestData = PutUserRequestDataTestFactory.create(); - - @SneakyThrows - @Test - void shouldCheckIfSecurityUserExists() { - service.checkSecurityUser(NAMESPACE, PASSWORD); - - verify(remoteService).existsSecurityUser(NAMESPACE); - } - - @SneakyThrows - @Test - void shouldCreateSecurityUserIfMissing() { - when(remoteService.existsSecurityUser(any())).thenReturn(false); - doReturn(putUserRequestData).when(service).buildPutUserRequestData(any(), any()); - - service.checkSecurityUser(NAMESPACE, PASSWORD); - - verify(remoteService).createSecurityUser(putUserRequestData); - } - - @DisplayName("create put user request data") - @Nested - class TestCreatePutUserRequestData { - - @Test - void shouldContainUsername() { - var request = service.buildPutUserRequestData(NAMESPACE, PASSWORD); - - assertThat(request.getUsername()).isEqualTo(NAMESPACE); - } - - @Test - void shouldContainRoles() { - var request = service.buildPutUserRequestData(NAMESPACE, PASSWORD); - - assertThat(request.getRoles()).isEqualTo(NAMESPACE); - } - - @Test - void shouldContainPassword() { - var request = service.buildPutUserRequestData(NAMESPACE, PASSWORD); - - assertThat(request.getPassword()).isEqualTo(PASSWORD); - } - } - } -} \ No newline at end of file diff --git a/ozgcloud-elasticsearch-operator/src/test/java/de/ozgcloud/operator/common/elasticsearch/OzgCloudElasticsearchTest2.java b/ozgcloud-elasticsearch-operator/src/test/java/de/ozgcloud/operator/common/elasticsearch/OzgCloudElasticsearchTest2.java deleted file mode 100644 index ec3b7643461ac694a2c78f977d919a193fcf17c6..0000000000000000000000000000000000000000 --- a/ozgcloud-elasticsearch-operator/src/test/java/de/ozgcloud/operator/common/elasticsearch/OzgCloudElasticsearchTest2.java +++ /dev/null @@ -1,115 +0,0 @@ -package de.ozgcloud.operator.common.elasticsearch; - -import java.time.Duration; -import java.time.temporal.ChronoUnit; - -import org.apache.http.HttpHost; -import org.apache.http.auth.AuthScope; -import org.apache.http.auth.UsernamePasswordCredentials; -import org.apache.http.impl.client.BasicCredentialsProvider; -import org.elasticsearch.client.RestClient; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Nested; -import org.junit.jupiter.api.Test; -import org.testcontainers.elasticsearch.ElasticsearchContainer; - -import co.elastic.clients.elasticsearch.ElasticsearchClient; -import co.elastic.clients.json.jackson.JacksonJsonpMapper; -import co.elastic.clients.transport.rest_client.RestClientTransport; -import lombok.SneakyThrows; - -public class OzgCloudElasticsearchTest2 { - - private static final String IMAGE_NAME = "docker.elastic.co/elasticsearch/elasticsearch:8.11.3"; - private static final String USER = "elastic"; - private static final String PASSWORD = "s3cret"; - private static final int PORT = 9200; - private static final String SCHEME = "https"; - - private static final ElasticsearchContainer container = new ElasticsearchContainer(IMAGE_NAME) - .withExposedPorts(PORT) - .withPassword(PASSWORD) -// .waitingFor(Wait.forHttps("/").withStartupTimeout(Duration.of(2, ChronoUnit.MINUTES))) - .withStartupTimeout(Duration.of(2, ChronoUnit.MINUTES)); - - private static final String INDEX_NAME = "test_index"; - private static ElasticsearchClient client; - private static RestClient restClient; - - @BeforeAll - public static void startContainer() throws Exception { - container.start(); - - restClient = buildRestClient(); - - client = buildClient(); - } - - private static RestClient buildRestClient() { - var host = new HttpHost("localhost", container.getMappedPort(PORT), SCHEME); - var credentialsProvider = buildCredentialsProvider(); - var builder = RestClient.builder(host); - - builder.setHttpClientConfigCallback(clientBuilder -> { - clientBuilder.setSSLContext(container.createSslContextFromCa()); - clientBuilder.setDefaultCredentialsProvider(credentialsProvider); - return clientBuilder; - }); -// builder.setNodeSelector(INGEST_NODE_SELECTOR); -// final ObjectMapper mapper = new ObjectMapper(); -// mapper.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE); -// mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); - return builder.build(); - } - - private static BasicCredentialsProvider buildCredentialsProvider() { - var credentialsProvider = new BasicCredentialsProvider(); - credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(USER, PASSWORD)); - return credentialsProvider; - } - - private static ElasticsearchClient buildClient() { -// var transport = new RestClientTransport(restClient, new JacksonJsonpMapper(mapper)); - var transport = new RestClientTransport(restClient, new JacksonJsonpMapper()); - return new ElasticsearchClient(transport); - } - - @DisplayName("Exists index") - @Nested - class TestExistsIndex { - - @Test - void shouldReturnTrueIfExists() { - - } - - @Test - void shouldReturnFalseIfMissing() { - - } - } - - @DisplayName("Create index") - @Nested - class TestCreateIndex { - - @Test - void shouldCreateIndex() { - - } - } - - @SneakyThrows - @Test - void shouldCreateIndex() { - client.indices().create(builder -> builder.index(INDEX_NAME)); - } - - @SneakyThrows - @AfterAll - public static void closeResources() { - restClient.close(); - } -} \ No newline at end of file diff --git a/ozgcloud-elasticsearch-operator/src/test/java/de/ozgcloud/operator/common/kubernetes/KubernetesServiceITCase.java b/ozgcloud-elasticsearch-operator/src/test/java/de/ozgcloud/operator/common/kubernetes/KubernetesRemoteServiceITCase.java similarity index 60% rename from ozgcloud-elasticsearch-operator/src/test/java/de/ozgcloud/operator/common/kubernetes/KubernetesServiceITCase.java rename to ozgcloud-elasticsearch-operator/src/test/java/de/ozgcloud/operator/common/kubernetes/KubernetesRemoteServiceITCase.java index 88de1719b1fa9bf4e6c29a9b5c75a353fe3f0d01..847b78880357e5939b4112a7e5131274d697a90e 100644 --- a/ozgcloud-elasticsearch-operator/src/test/java/de/ozgcloud/operator/common/kubernetes/KubernetesServiceITCase.java +++ b/ozgcloud-elasticsearch-operator/src/test/java/de/ozgcloud/operator/common/kubernetes/KubernetesRemoteServiceITCase.java @@ -2,7 +2,6 @@ package de.ozgcloud.operator.common.kubernetes; import static org.assertj.core.api.Assertions.*; -import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; @@ -12,15 +11,10 @@ import io.fabric8.kubernetes.client.extension.ResourceAdapter; import io.javaoperatorsdk.jenvtest.junit.EnableKubeAPIServer; @EnableKubeAPIServer -class KubernetesServiceITCase { +class KubernetesRemoteServiceITCase { private static KubernetesClient client; - private static KubernetesService service; - - @BeforeAll - static void init() { - service = new KubernetesService(client); - } + private final KubernetesRemoteService service = new KubernetesRemoteService(client); @DisplayName("Get secret resource") @Nested @@ -42,17 +36,17 @@ class KubernetesServiceITCase { assertThat(resource.get()).isNotNull(); } - } - - private void createNamespace() { - var resource = client.namespaces().withName(NamespaceTestFactory.NAMESPACE); - var adapter = new ResourceAdapter<>(resource); - adapter.create(NamespaceTestFactory.create()); - } - - private void createSecret() { - var resource = client.secrets().inNamespace(NamespaceTestFactory.NAMESPACE).withName(SecretTestFactory.NAME); - var adapter = new ResourceAdapter<>(resource); - adapter.create(SecretTestFactory.create()); + + private void createNamespace() { + var resource = client.namespaces().withName(NamespaceTestFactory.NAMESPACE); + var adapter = new ResourceAdapter<>(resource); + adapter.create(NamespaceTestFactory.create()); + } + + private void createSecret() { + var resource = client.secrets().inNamespace(NamespaceTestFactory.NAMESPACE).withName(SecretTestFactory.NAME); + var adapter = new ResourceAdapter<>(resource); + adapter.create(SecretTestFactory.create()); + } } } \ No newline at end of file diff --git a/ozgcloud-elasticsearch-operator/src/test/java/de/ozgcloud/operator/common/kubernetes/KubernetesServiceTest.java b/ozgcloud-elasticsearch-operator/src/test/java/de/ozgcloud/operator/common/kubernetes/KubernetesRemoteServiceTest.java similarity index 91% rename from ozgcloud-elasticsearch-operator/src/test/java/de/ozgcloud/operator/common/kubernetes/KubernetesServiceTest.java rename to ozgcloud-elasticsearch-operator/src/test/java/de/ozgcloud/operator/common/kubernetes/KubernetesRemoteServiceTest.java index e93286d3f7300b6e263cf87629b70cf59f2da79f..1d650f5b76e9fe1e0af7a0ec8a6c412cf35efd34 100644 --- a/ozgcloud-elasticsearch-operator/src/test/java/de/ozgcloud/operator/common/kubernetes/KubernetesServiceTest.java +++ b/ozgcloud-elasticsearch-operator/src/test/java/de/ozgcloud/operator/common/kubernetes/KubernetesRemoteServiceTest.java @@ -13,19 +13,19 @@ import io.fabric8.kubernetes.client.KubernetesClient; import io.fabric8.kubernetes.client.extension.ResourceAdapter; import io.fabric8.kubernetes.client.server.mock.KubernetesServer; -class KubernetesServiceTest { +class KubernetesRemoteServiceTest { @Rule private KubernetesServer server; private KubernetesClient client; - private KubernetesService service; + private KubernetesRemoteService service; @BeforeEach void init() { server = new KubernetesServer(true, true); server.before(); client = server.getClient(); - service = new KubernetesService(client); + service = new KubernetesRemoteService(client); } @DisplayName("Get secret") diff --git a/ozgcloud-elasticsearch-operator/src/test/java/de/ozgcloud/operator/user/ElasticsearchCustomResourceStatusTestFactory.java b/ozgcloud-elasticsearch-operator/src/test/java/de/ozgcloud/operator/user/ElasticsearchCustomResourceStatusTestFactory.java deleted file mode 100644 index 8f2251433d7cd603fc22f3cb39f5bd3ca09010df..0000000000000000000000000000000000000000 --- a/ozgcloud-elasticsearch-operator/src/test/java/de/ozgcloud/operator/user/ElasticsearchCustomResourceStatusTestFactory.java +++ /dev/null @@ -1,18 +0,0 @@ -package de.ozgcloud.operator.user; - -import de.ozgcloud.operator.CustomResourceStatus; -import de.ozgcloud.operator.ElasticsearchCustomResourceStatus; - -public class ElasticsearchCustomResourceStatusTestFactory { - - public final static CustomResourceStatus STATUS = CustomResourceStatus.OK; - - public static ElasticsearchCustomResourceStatus create() { - return createBuilder().build(); - } - - public static ElasticsearchCustomResourceStatus.ElasticsearchCustomResourceStatusBuilder createBuilder() { - return ElasticsearchCustomResourceStatus.builder() - .status(STATUS); - } -} \ No newline at end of file diff --git a/ozgcloud-elasticsearch-operator/src/test/java/de/ozgcloud/operator/user/ElasticsearchCustomResourceTestFactory.java b/ozgcloud-elasticsearch-operator/src/test/java/de/ozgcloud/operator/user/ElasticsearchCustomResourceTestFactory.java deleted file mode 100644 index 544b2d99df08f6295324d064c0b625a816aba806..0000000000000000000000000000000000000000 --- a/ozgcloud-elasticsearch-operator/src/test/java/de/ozgcloud/operator/user/ElasticsearchCustomResourceTestFactory.java +++ /dev/null @@ -1,11 +0,0 @@ -package de.ozgcloud.operator.user; - -public class ElasticsearchCustomResourceTestFactory { - - public static ElasticsearchCustomResource create() { - var resource = new ElasticsearchCustomResource(); - resource.setStatus(ElasticsearchCustomResourceStatusTestFactory.create()); - resource.setMetadata(ObjectMetaTestFactory.create()); - return resource; - } -} \ No newline at end of file diff --git a/ozgcloud-elasticsearch-operator/src/test/java/de/ozgcloud/operator/user/ElasticsearchServiceTest.java b/ozgcloud-elasticsearch-operator/src/test/java/de/ozgcloud/operator/user/ElasticsearchServiceTest.java deleted file mode 100644 index 61182868a044c83d85e8c2474a8ff38df8e81f27..0000000000000000000000000000000000000000 --- a/ozgcloud-elasticsearch-operator/src/test/java/de/ozgcloud/operator/user/ElasticsearchServiceTest.java +++ /dev/null @@ -1,101 +0,0 @@ -package de.ozgcloud.operator.user; - -import static org.assertj.core.api.Assertions.*; -import static org.mockito.ArgumentMatchers.*; -import static org.mockito.Mockito.*; - -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Nested; -import org.junit.jupiter.api.Test; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.Spy; - -import de.ozgcloud.operator.common.kubernetes.KubernetesService; -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.client.dsl.Resource; -import io.fabric8.kubernetes.client.extension.ResourceAdapter; -import io.javaoperatorsdk.operator.api.reconciler.Context; - -class ElasticsearchServiceTest { - - @Spy - @InjectMocks - private ElasticsearchService service; - @Mock - private ElasticsearchSecretHelper secretHelper; - @Mock - private KubernetesService kubernetesService; - - @DisplayName("Check secret") - @Nested - class TestCheckSecret { - - @Mock - private Context<ElasticsearchCustomResource> context; - @Mock - private ResourceAdapter<Secret> resourceAdapter; - @Mock - private Resource<Secret> secretResource; - - private final Secret secret = SecretTestFactory.create(); - - private final ElasticsearchCustomResource resource = ElasticsearchCustomResourceTestFactory.create(); - - @BeforeEach - void mock() { - when(kubernetesService.getSecretResource(any(), any())).thenReturn(secretResource); - when(secretResource.get()).thenReturn(secret); - } - - @Test - void shouldGetSecret() { - service.getOrCreateCredentialSecret(resource, context); - - verify(kubernetesService).getSecretResource(NamespaceTestFactory.NAMESPACE, ElasticsearchService.ELASTIC_USER_SECRET_NAME); - } - - @DisplayName("on existing") - @Nested - class TestOnExisting { - - @Test - void shouldReturnSecret() { - var secret = service.getOrCreateCredentialSecret(resource, context); - - assertThat(secret).isNotNull(); - } - } - - @DisplayName("on missing secret") - @Nested - class TestOnMissingSecret { - - @BeforeEach - void mock() { - when(secretResource.get()).thenReturn(null); - - doReturn(resourceAdapter).when(service).createAdapter(any()); - } - - @Test - void shouldBuildSecret() { - service.getOrCreateCredentialSecret(resource, context); - - verify(secretHelper).buildCredentialSecret(NamespaceTestFactory.NAMESPACE, ElasticsearchService.ELASTIC_USER_SECRET_NAME); - } - - @Test - void shouldCreateSecret() { - when(secretHelper.buildCredentialSecret(any(), any())).thenReturn(secret); - - service.getOrCreateCredentialSecret(resource, context); - - verify(resourceAdapter).create(secret); - } - } - } -} \ No newline at end of file