Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@
import org.apache.cloudstack.api.response.KubernetesSupportedVersionResponse;
import org.apache.cloudstack.api.response.ListResponse;
import org.apache.cloudstack.context.CallContext;
import org.apache.cloudstack.storage.datastore.db.ImageStoreDao;
import org.apache.cloudstack.storage.datastore.db.ImageStoreVO;
import org.apache.commons.lang3.StringUtils;

import com.cloud.api.query.dao.TemplateJoinDao;
Expand Down Expand Up @@ -80,6 +82,8 @@ public class KubernetesVersionManagerImpl extends ManagerBase implements Kuberne
@Inject
private DataCenterDao dataCenterDao;
@Inject
private ImageStoreDao imageStoreDao;
@Inject
private TemplateApiService templateService;

public static final String MINIMUN_AUTOSCALER_SUPPORTED_VERSION = "1.15.0";
Expand Down Expand Up @@ -316,6 +320,32 @@ public ListResponse<KubernetesSupportedVersionResponse> listKubernetesSupportedV
return createKubernetesSupportedVersionListResponse(versions, versionsAndCount.second());
}

private void validateImageStoreForZone(Long zoneId, boolean directDownload) {
if (directDownload) {
return;
}
if (zoneId != null) {
List<ImageStoreVO> imageStores = imageStoreDao.listStoresByZoneId(zoneId);
if (imageStores == null || imageStores.isEmpty()) {
DataCenterVO zone = dataCenterDao.findById(zoneId);
String zoneName = zone != null ? zone.getName() : String.valueOf(zoneId);
throw new InvalidParameterValueException(String.format("Unable to register Kubernetes version ISO. No image store available in zone: %s", zoneName));
}
} else {
List<DataCenterVO> zones = dataCenterDao.listAllZones();
List<String> zonesWithoutStorage = new ArrayList<>();
for (DataCenterVO zone : zones) {
List<ImageStoreVO> imageStores = imageStoreDao.listStoresByZoneId(zone.getId());
if (imageStores == null || imageStores.isEmpty()) {
zonesWithoutStorage.add(zone.getName());
}
}
if (!zonesWithoutStorage.isEmpty()) {
throw new InvalidParameterValueException(String.format("Unable to register Kubernetes version ISO for all zones. The following zones have no image store: %s", String.join(", ", zonesWithoutStorage)));
}
}
}

@Override
@ActionEvent(eventType = KubernetesVersionEventTypes.EVENT_KUBERNETES_VERSION_ADD,
eventDescription = "Adding Kubernetes supported version")
Expand Down Expand Up @@ -361,6 +391,8 @@ public KubernetesSupportedVersionResponse addKubernetesSupportedVersion(final Ad
}
}

validateImageStoreForZone(zoneId, isDirectDownload);

VMTemplateVO template = null;
try {
VirtualMachineTemplate vmTemplate = registerKubernetesVersionIso(zoneId, name, isoUrl, isoChecksum, isDirectDownload, arch);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,15 @@
// under the License.
package com.cloud.kubernetes.version;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.UUID;

import org.apache.cloudstack.api.response.KubernetesSupportedVersionResponse;
import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine;
import org.apache.cloudstack.storage.datastore.db.ImageStoreDao;
import org.apache.cloudstack.storage.datastore.db.ImageStoreVO;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
Expand All @@ -32,13 +37,22 @@
import com.cloud.api.query.dao.TemplateJoinDao;
import com.cloud.api.query.vo.TemplateJoinVO;
import com.cloud.cpu.CPU;
import com.cloud.dc.DataCenterVO;
import com.cloud.dc.dao.DataCenterDao;
import com.cloud.exception.InvalidParameterValueException;

@RunWith(MockitoJUnitRunner.class)
public class KubernetesVersionManagerImplTest {

@Mock
TemplateJoinDao templateJoinDao;

@Mock
ImageStoreDao imageStoreDao;

@Mock
DataCenterDao dataCenterDao;

@InjectMocks
KubernetesVersionManagerImpl kubernetesVersionManager = new KubernetesVersionManagerImpl();

Expand Down Expand Up @@ -72,4 +86,62 @@ public void testUpdateTemplateDetailsInKubernetesSupportedVersionResponseValidTe
response);
Assert.assertEquals(state.toString(), ReflectionTestUtils.getField(response, "isoState"));
}

@Test
public void testValidateImageStoreForZoneWithDirectDownload() {
ReflectionTestUtils.invokeMethod(kubernetesVersionManager, "validateImageStoreForZone", 1L, true);
}

@Test
public void testValidateImageStoreForZoneWithValidZone() {
Long zoneId = 1L;
List<ImageStoreVO> imageStores = Collections.singletonList(Mockito.mock(ImageStoreVO.class));
Mockito.when(imageStoreDao.listStoresByZoneId(zoneId)).thenReturn(imageStores);

ReflectionTestUtils.invokeMethod(kubernetesVersionManager, "validateImageStoreForZone", zoneId, false);
}

@Test(expected = InvalidParameterValueException.class)
public void testValidateImageStoreForZoneWithNoImageStore() {
Long zoneId = 1L;
DataCenterVO zone = Mockito.mock(DataCenterVO.class);
Mockito.when(zone.getName()).thenReturn("test-zone");
Mockito.when(dataCenterDao.findById(zoneId)).thenReturn(zone);
Mockito.when(imageStoreDao.listStoresByZoneId(zoneId)).thenReturn(Collections.emptyList());

ReflectionTestUtils.invokeMethod(kubernetesVersionManager, "validateImageStoreForZone", zoneId, false);
}

@Test
public void testValidateImageStoreForAllZonesWithAllValid() {
DataCenterVO zone1 = Mockito.mock(DataCenterVO.class);
Mockito.when(zone1.getId()).thenReturn(1L);
DataCenterVO zone2 = Mockito.mock(DataCenterVO.class);
Mockito.when(zone2.getId()).thenReturn(2L);
List<DataCenterVO> zones = Arrays.asList(zone1, zone2);
Mockito.when(dataCenterDao.listAllZones()).thenReturn(zones);

List<ImageStoreVO> imageStores = Collections.singletonList(Mockito.mock(ImageStoreVO.class));
Mockito.when(imageStoreDao.listStoresByZoneId(1L)).thenReturn(imageStores);
Mockito.when(imageStoreDao.listStoresByZoneId(2L)).thenReturn(imageStores);

ReflectionTestUtils.invokeMethod(kubernetesVersionManager, "validateImageStoreForZone", (Long) null, false);
}

@Test(expected = InvalidParameterValueException.class)
public void testValidateImageStoreForAllZonesWithSomeMissingStorage() {
DataCenterVO zone1 = Mockito.mock(DataCenterVO.class);
Mockito.when(zone1.getId()).thenReturn(1L);
DataCenterVO zone2 = Mockito.mock(DataCenterVO.class);
Mockito.when(zone2.getId()).thenReturn(2L);
Mockito.when(zone2.getName()).thenReturn("zone-without-storage");
List<DataCenterVO> zones = Arrays.asList(zone1, zone2);
Mockito.when(dataCenterDao.listAllZones()).thenReturn(zones);

List<ImageStoreVO> imageStores = Collections.singletonList(Mockito.mock(ImageStoreVO.class));
Mockito.when(imageStoreDao.listStoresByZoneId(1L)).thenReturn(imageStores);
Mockito.when(imageStoreDao.listStoresByZoneId(2L)).thenReturn(Collections.emptyList());

ReflectionTestUtils.invokeMethod(kubernetesVersionManager, "validateImageStoreForZone", (Long) null, false);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,9 @@
import com.cloud.utils.db.SearchCriteria;
import com.cloud.utils.exception.CloudRuntimeException;

import org.apache.cloudstack.storage.datastore.db.ImageStoreDao;
import org.apache.cloudstack.storage.datastore.db.ImageStoreVO;

@RunWith(MockitoJUnitRunner.class)
public class KubernetesVersionServiceTest {

Expand All @@ -94,6 +97,8 @@ public class KubernetesVersionServiceTest {
@Mock
private DataCenterDao dataCenterDao;
@Mock
private ImageStoreDao imageStoreDao;
@Mock
private TemplateApiService templateService;

AutoCloseable closeable;
Expand Down Expand Up @@ -123,6 +128,10 @@ public void setUp() throws Exception {
DataCenterVO zone = Mockito.mock(DataCenterVO.class);
when(dataCenterDao.findById(Mockito.anyLong())).thenReturn(zone);

List<ImageStoreVO> imageStores = new ArrayList<>();
imageStores.add(Mockito.mock(ImageStoreVO.class));
when(imageStoreDao.listStoresByZoneId(Mockito.anyLong())).thenReturn(imageStores);

TemplateJoinVO templateJoinVO = Mockito.mock(TemplateJoinVO.class);
when(templateJoinVO.getState()).thenReturn(ObjectInDataStoreStateMachine.State.Ready);
when(templateJoinVO.getArch()).thenReturn(CPU.CPUArch.getDefault());
Expand Down
Loading