KubernetesHelper

This commit is contained in:
Gytis Trikleris
2018-06-04 13:05:09 +02:00
committed by Ioannis Canellos
parent 655dec96ca
commit a09cd708e5
2 changed files with 259 additions and 0 deletions

View File

@@ -0,0 +1,94 @@
/*
* Copyright 2018 Red Hat, Inc, and individual contributors.
*
* 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.leader;
import java.util.Map;
import io.fabric8.kubernetes.api.model.ConfigMap;
import io.fabric8.kubernetes.api.model.ConfigMapBuilder;
import io.fabric8.kubernetes.api.model.ObjectMeta;
import io.fabric8.kubernetes.api.model.Pod;
import io.fabric8.kubernetes.client.KubernetesClient;
/**
* @author <a href="mailto:gytis@redhat.com">Gytis Trikleris</a>
*/
public class KubernetesHelper {
private static final String PROVIDER_KEY = "provider";
private static final String PROVIDER = "spring-cloud-kubernetes";
private static final String KIND_KEY = "kind";
public static final String KIND = "leaders";
private final LeaderProperties leaderProperties;
private final KubernetesClient kubernetesClient;
public KubernetesHelper(LeaderProperties leaderProperties, KubernetesClient kubernetesClient) {
this.leaderProperties = leaderProperties;
this.kubernetesClient = kubernetesClient;
}
public boolean isPodAlive(String id) {
return kubernetesClient.pods()
.inNamespace(leaderProperties.getNamespace(kubernetesClient.getNamespace()))
.withLabels(leaderProperties.getLabels())
.list()
.getItems()
.stream()
.map(Pod::getMetadata)
.map(ObjectMeta::getName)
.anyMatch(name -> name.equals(id));
}
public ConfigMap getConfigMap() {
return kubernetesClient.configMaps()
.inNamespace(leaderProperties.getNamespace(kubernetesClient.getNamespace()))
.withName(leaderProperties.getConfigMapName())
.get();
}
public void createConfigMap(Map<String, String> data) {
ConfigMap newConfigMap = new ConfigMapBuilder().withNewMetadata()
.withName(leaderProperties.getConfigMapName())
.addToLabels(PROVIDER_KEY, PROVIDER)
.addToLabels(KIND_KEY, KIND)
.endMetadata()
.addToData(data)
.build();
kubernetesClient.configMaps()
.inNamespace(leaderProperties.getNamespace(kubernetesClient.getNamespace()))
.create(newConfigMap);
}
public void updateConfigMap(ConfigMap configMap, Map<String, String> newData) {
ConfigMap newConfigMap = new ConfigMapBuilder(configMap)
.addToData(newData)
.build();
kubernetesClient.configMaps()
.inNamespace(leaderProperties.getNamespace(kubernetesClient.getNamespace()))
.withName(leaderProperties.getConfigMapName())
.lockResourceVersion(configMap.getMetadata().getResourceVersion())
.replace(newConfigMap);
}
}

View File

@@ -0,0 +1,165 @@
package org.springframework.cloud.kubernetes.leader;
import java.util.Collections;
import java.util.Map;
import io.fabric8.kubernetes.api.model.ConfigMap;
import io.fabric8.kubernetes.api.model.ConfigMapList;
import io.fabric8.kubernetes.api.model.DoneableConfigMap;
import io.fabric8.kubernetes.api.model.DoneablePod;
import io.fabric8.kubernetes.api.model.ObjectMeta;
import io.fabric8.kubernetes.api.model.Pod;
import io.fabric8.kubernetes.api.model.PodList;
import io.fabric8.kubernetes.client.KubernetesClient;
import io.fabric8.kubernetes.client.Watch;
import io.fabric8.kubernetes.client.Watcher;
import io.fabric8.kubernetes.client.dsl.FilterWatchListDeletable;
import io.fabric8.kubernetes.client.dsl.MixedOperation;
import io.fabric8.kubernetes.client.dsl.NonNamespaceOperation;
import io.fabric8.kubernetes.client.dsl.PodResource;
import io.fabric8.kubernetes.client.dsl.Replaceable;
import io.fabric8.kubernetes.client.dsl.Resource;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.anyMap;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.verify;
/**
* @author <a href="mailto:gytis@redhat.com">Gytis Trikleris</a>
*/
@RunWith(MockitoJUnitRunner.class)
public class KubernetesHelperTest {
private static final String NAMESPACE = "test-namespace";
private static final String NAME = "test-name";
@Mock
private LeaderProperties mockLeaderProperties;
@Mock
private KubernetesClient mockKubernetesClient;
@Mock
private MixedOperation<Pod, PodList, DoneablePod, PodResource<Pod, DoneablePod>> podMixedOperation;
@Mock
private MixedOperation<ConfigMap, ConfigMapList, DoneableConfigMap, Resource<ConfigMap, DoneableConfigMap>>
configMapMixedOperation;
@Mock
private NonNamespaceOperation<Pod, PodList, DoneablePod, PodResource<Pod, DoneablePod>> podNonNamespaceOperation;
@Mock
private NonNamespaceOperation<ConfigMap, ConfigMapList, DoneableConfigMap, Resource<ConfigMap, DoneableConfigMap>>
configMapNonNamespaceOperation;
@Mock
private FilterWatchListDeletable<Pod, PodList, Boolean, Watch, Watcher<Pod>> podWatchList;
@Mock
private PodList mockPodList;
@Mock
private Pod mockPod;
@Mock
private ObjectMeta mockObjectMeta;
@Mock
private Resource<ConfigMap, DoneableConfigMap> configMapResource;
@Mock
private Replaceable<ConfigMap, ConfigMap> configMapReplaceable;
@Mock
private ConfigMap mockConfigMap;
private KubernetesHelper kubernetesHelper;
@Before
public void before() {
given(mockLeaderProperties.getConfigMapName()).willReturn(NAME);
given(mockLeaderProperties.getNamespace(NAMESPACE)).willReturn(NAMESPACE);
given(mockKubernetesClient.getNamespace()).willReturn(NAMESPACE);
kubernetesHelper = new KubernetesHelper(mockLeaderProperties, mockKubernetesClient);
}
@Test
public void shouldCheckIfPodIsAlive() {
given(mockKubernetesClient.getNamespace()).willReturn(NAMESPACE);
given(mockKubernetesClient.pods()).willReturn(podMixedOperation);
given(podMixedOperation.inNamespace(NAMESPACE)).willReturn(podNonNamespaceOperation);
given(podNonNamespaceOperation.withLabels(anyMap())).willReturn(podWatchList);
given(podWatchList.list()).willReturn(mockPodList);
given(mockPodList.getItems()).willReturn(Collections.singletonList(mockPod));
given(mockPod.getMetadata()).willReturn(mockObjectMeta);
given(mockObjectMeta.getName()).willReturn("test-id");
boolean result = kubernetesHelper.isPodAlive("test-id");
assertThat(result).isTrue();
verify(mockObjectMeta).getName();
}
@Test
public void shouldGetConfigMap() {
given(mockKubernetesClient.configMaps()).willReturn(configMapMixedOperation);
given(configMapMixedOperation.inNamespace(NAMESPACE)).willReturn(configMapNonNamespaceOperation);
given(configMapNonNamespaceOperation.withName(NAME)).willReturn(configMapResource);
given(configMapResource.get()).willReturn(mockConfigMap);
ConfigMap result = kubernetesHelper.getConfigMap();
assertThat(result).isEqualTo(mockConfigMap);
}
@Test
public void shouldCreateConfigMap() {
given(mockKubernetesClient.configMaps()).willReturn(configMapMixedOperation);
given(configMapMixedOperation.inNamespace(NAMESPACE)).willReturn(configMapNonNamespaceOperation);
Map<String, String> data = Collections.singletonMap("test-key", "test-value");
kubernetesHelper.createConfigMap(data);
ArgumentCaptor<ConfigMap> configMapCaptor = ArgumentCaptor.forClass(ConfigMap.class);
verify(configMapNonNamespaceOperation).create(configMapCaptor.capture());
ConfigMap configMap = configMapCaptor.getValue();
ObjectMeta metaData = configMap.getMetadata();
assertThat(metaData.getName()).isEqualTo(NAME);
assertThat(metaData.getLabels()).containsEntry("provider", "spring-cloud-kubernetes");
assertThat(metaData.getLabels()).containsEntry("kind", "leaders");
assertThat(configMap.getData()).containsEntry("test-key", "test-value");
}
@Test
public void shouldUpdateConfigMap() {
given(mockConfigMap.getMetadata()).willReturn(mockObjectMeta);
given(mockObjectMeta.getResourceVersion()).willReturn("test-version");
given(mockKubernetesClient.configMaps()).willReturn(configMapMixedOperation);
given(configMapMixedOperation.inNamespace(NAMESPACE)).willReturn(configMapNonNamespaceOperation);
given(configMapNonNamespaceOperation.withName(NAME)).willReturn(configMapResource);
given(configMapResource.lockResourceVersion("test-version")).willReturn(configMapReplaceable);
Map<String, String> data = Collections.singletonMap("test-key", "test-value");
kubernetesHelper.updateConfigMap(mockConfigMap, data);
ArgumentCaptor<ConfigMap> configMapCaptor = ArgumentCaptor.forClass(ConfigMap.class);
verify(configMapReplaceable).replace(configMapCaptor.capture());
ConfigMap configMap = configMapCaptor.getValue();
assertThat(configMap.getData()).containsEntry("test-key", "test-value");
}
}