ConfigMapLockRepository

This commit is contained in:
Gytis Trikleris
2018-05-24 17:33:23 +02:00
committed by Ioannis Canellos
parent e50eb097f0
commit 561bc9d00c
4 changed files with 278 additions and 0 deletions

View File

@@ -87,6 +87,7 @@
<module>spring-cloud-starter-kubernetes-zipkin</module>
<module>spring-cloud-starter-kubernetes-all</module>
<module>spring-cloud-kubernetes-examples</module>
<module>spring-cloud-kubernetes-lock</module>
</modules>
<dependencyManagement>

View File

@@ -0,0 +1,74 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (C) 2018 to the original authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-kubernetes</artifactId>
<version>0.3.0.BUILD-SNAPSHOT</version>
</parent>
<artifactId>spring-cloud-kubernetes-lock</artifactId>
<name>Spring Cloud Kubernetes :: Lock</name>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-kubernetes-core</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-core</artifactId>
</dependency>
<dependency>
<groupId>org.jboss.arquillian.junit</groupId>
<artifactId>arquillian-junit-standalone</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.arquillian.cube</groupId>
<artifactId>arquillian-cube-kubernetes</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.arquillian.cube</groupId>
<artifactId>arquillian-cube-requirement</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>${maven-failsafe-plugin.version}</version>
</plugin>
</plugins>
</build>
</project>

View File

@@ -0,0 +1,116 @@
/*
* Copyright (C) 2018 to the original authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.kubernetes.lock;
import java.util.List;
import java.util.stream.Collectors;
import io.fabric8.kubernetes.api.model.ConfigMap;
import io.fabric8.kubernetes.api.model.ConfigMapBuilder;
import io.fabric8.kubernetes.client.KubernetesClient;
import io.fabric8.kubernetes.client.KubernetesClientException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ConfigMapLockRepository {
static final String CONFIG_MAP_PREFIX = "lock";
static final String HOLDER_KEY = "holder";
static final String EXPIRATION_KEY = "expiration";
private static final String PROVIDER_LABEL = "provider";
private static final String PROVIDER_LABEL_VALUE = "spring-cloud-kubernetes";
private static final String KIND_LABEL = "kind";
private static final String KIND_LABEL_VALUE = "lock";
private static final Logger LOGGER = LoggerFactory.getLogger(ConfigMapLockRepository.class);
private KubernetesClient kubernetesClient;
private String namespace;
public ConfigMapLockRepository(KubernetesClient kubernetesClient, String namespace) {
this.kubernetesClient = kubernetesClient;
this.namespace = namespace;
}
public ConfigMap get(String name) {
return kubernetesClient.configMaps()
.inNamespace(namespace)
.withName(getConfigMapName(name))
.get();
}
public boolean create(String name, String holder, long expiration) {
ConfigMap configMap = new ConfigMapBuilder().withNewMetadata()
.withName(getConfigMapName(name))
.addToLabels(PROVIDER_LABEL, PROVIDER_LABEL_VALUE)
.addToLabels(KIND_LABEL, KIND_LABEL_VALUE)
.endMetadata()
.addToData(HOLDER_KEY, holder)
.addToData(EXPIRATION_KEY, String.valueOf(expiration))
// TODO add information about the creator
.build();
try {
kubernetesClient.configMaps()
.inNamespace(namespace)
.create(configMap);
} catch (KubernetesClientException e) {
LOGGER.warn("Failed to create ConfigMap for name '{}': ", name, e.getMessage());
return false;
}
return true;
}
public void deleteAll() {
kubernetesClient.configMaps()
.inNamespace(namespace)
.withLabel(PROVIDER_LABEL, PROVIDER_LABEL_VALUE)
.withLabel(KIND_LABEL, KIND_LABEL_VALUE)
.delete();
}
public void deleteExpired() {
long now = System.currentTimeMillis();
// TODO check that it was created by this process
List<ConfigMap> configMaps = kubernetesClient.configMaps()
.inNamespace(namespace)
.withLabel(PROVIDER_LABEL, PROVIDER_LABEL_VALUE)
.withLabel(KIND_LABEL, KIND_LABEL_VALUE)
.list()
.getItems()
.stream()
.filter(c -> Long.valueOf(c.getData().get("expiration")) < now)
.collect(Collectors.toList());
kubernetesClient.configMaps()
.inNamespace(namespace)
.delete(configMaps);
}
private String getConfigMapName(String name) {
return String.format("%s-%s", CONFIG_MAP_PREFIX, name);
}
}

View File

@@ -0,0 +1,87 @@
package org.springframework.cloud.kubernetes.lock;
import java.util.Map;
import io.fabric8.kubernetes.api.model.ConfigMap;
import io.fabric8.kubernetes.client.KubernetesClient;
import org.arquillian.cube.kubernetes.api.Session;
import org.arquillian.cube.kubernetes.impl.requirement.RequiresKubernetes;
import org.jboss.arquillian.junit.Arquillian;
import org.jboss.arquillian.test.api.ArquillianResource;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.assertj.core.api.Assertions.assertThat;
@RunWith(Arquillian.class)
@RequiresKubernetes
public class ConfigMapLockRepositoryIT {
@ArquillianResource
private KubernetesClient kubernetesClient;
@ArquillianResource
private Session session;
private ConfigMapLockRepository repository;
@Before
public void before() {
repository = new ConfigMapLockRepository(kubernetesClient, session.getNamespace());
}
@After
public void after() {
deleteConfigMap("test-name");
deleteConfigMap("test-name-2");
}
@Test
public void shouldCreateConfigMap() {
long expiration = System.currentTimeMillis();
boolean result = repository.create("test-name", "test-holder", expiration);
assertThat(result).isTrue();
ConfigMap configMap = repository.get("test-name");
Map<String, String> data = configMap.getData();
assertThat(data).containsEntry(ConfigMapLockRepository.HOLDER_KEY, "test-holder");
assertThat(data).containsEntry(ConfigMapLockRepository.EXPIRATION_KEY, String.valueOf(expiration));
}
@Test
public void shouldNotOverwriteConfigMap() {
boolean firstResult = repository.create("test-name", "test-holder", 0);
assertThat(firstResult).isTrue();
boolean secondResult = repository.create("test-name", "test-holder", 0);
assertThat(secondResult).isFalse();
}
@Test
public void shouldDeleteAllConfigMaps() {
repository.create("test-name", "test-holder", 0);
repository.create("test-name-2", "test-holder-2", 0);
repository.deleteAll();
assertThat(repository.get("test-name")).isNull();
assertThat(repository.get("test-name-2")).isNull();
}
@Test
public void shouldDeleteExpiredConfigMaps() {
repository.create("test-name", "test-holder", System.currentTimeMillis() - 1);
repository.create("test-name-2", "test-holder-2", System.currentTimeMillis() + 10000);
repository.deleteExpired();
assertThat(repository.get("test-name")).isNull();
assertThat(repository.get("test-name-2")).isNotNull();
}
private void deleteConfigMap(String name) {
kubernetesClient.configMaps()
.inNamespace(session.getNamespace())
.withName(String.format("%s-%s", ConfigMapLockRepository.CONFIG_MAP_PREFIX, name))
.delete();
}
}