From a076d22277f011ab8b7e2ec620f9553b27036abd Mon Sep 17 00:00:00 2001 From: Vitor Hugo Homem Marzarotto Date: Wed, 7 May 2025 17:56:36 -0300 Subject: [PATCH 1/6] Adds url kubernetes iso --- .../apache/cloudstack/api/ApiConstants.java | 1 + .../version/KubernetesVersionManagerImpl.java | 12 +++ .../KubernetesSupportedVersionResponse.java | 12 +++ .../version/KubernetesVersionServiceTest.java | 91 +++++++++++++++---- ui/public/locales/en.json | 1 + ui/public/locales/pt_BR.json | 1 + ui/src/config/section/image.js | 8 +- 7 files changed, 103 insertions(+), 23 deletions(-) diff --git a/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java b/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java index efb1ca929caf..a61cb3d8db55 100644 --- a/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java +++ b/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java @@ -1095,6 +1095,7 @@ public class ApiConstants { public static final String DOCKER_REGISTRY_EMAIL = "dockerregistryemail"; public static final String ISO_NAME = "isoname"; public static final String ISO_STATE = "isostate"; + public static final String ISO_URL = "isourl"; public static final String SEMANTIC_VERSION = "semanticversion"; public static final String KUBERNETES_VERSION_ID = "kubernetesversionid"; public static final String KUBERNETES_VERSION_NAME = "kubernetesversionname"; diff --git a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/version/KubernetesVersionManagerImpl.java b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/version/KubernetesVersionManagerImpl.java index 99c9a4de051a..100301d6be74 100644 --- a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/version/KubernetesVersionManagerImpl.java +++ b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/version/KubernetesVersionManagerImpl.java @@ -23,6 +23,7 @@ import javax.inject.Inject; import org.apache.cloudstack.api.ApiCommandResourceType; +import com.cloud.user.Account; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.command.admin.kubernetes.version.AddKubernetesSupportedVersionCmd; import org.apache.cloudstack.api.command.admin.kubernetes.version.DeleteKubernetesSupportedVersionCmd; @@ -119,6 +120,17 @@ private KubernetesSupportedVersionResponse createKubernetesSupportedVersionRespo KubernetesClusterService.MIN_KUBERNETES_VERSION_HA_SUPPORT)>=0); response.setSupportsAutoscaling(versionSupportsAutoscaling(kubernetesSupportedVersion)); updateTemplateDetailsInKubernetesSupportedVersionResponse(kubernetesSupportedVersion, response); + TemplateJoinVO template = templateJoinDao.findById(kubernetesSupportedVersion.getIsoId()); + Account caller = CallContext.current().getCallingAccount(); + boolean isAdmin = accountManager.isRootAdmin(caller.getId()); + if (template != null) { + response.setIsoId(template.getUuid()); + response.setIsoName(template.getName()); + response.setIsoState(template.getState().toString()); + if (isAdmin) { + response.setIsoUrl(template.getUrl()); + } + } response.setCreated(kubernetesSupportedVersion.getCreated()); return response; } diff --git a/plugins/integrations/kubernetes-service/src/main/java/org/apache/cloudstack/api/response/KubernetesSupportedVersionResponse.java b/plugins/integrations/kubernetes-service/src/main/java/org/apache/cloudstack/api/response/KubernetesSupportedVersionResponse.java index a22c77d87568..8fb251841e53 100644 --- a/plugins/integrations/kubernetes-service/src/main/java/org/apache/cloudstack/api/response/KubernetesSupportedVersionResponse.java +++ b/plugins/integrations/kubernetes-service/src/main/java/org/apache/cloudstack/api/response/KubernetesSupportedVersionResponse.java @@ -50,6 +50,10 @@ public class KubernetesSupportedVersionResponse extends BaseResponse { @Param(description = "the name of the binaries ISO for Kubernetes supported version") private String isoName; + @SerializedName(ApiConstants.ISO_URL) + @Param(description = "the URL of the binaries ISO for Kubernetes supported version") + private String isoUrl; + @SerializedName(ApiConstants.ISO_STATE) @Param(description = "the state of the binaries ISO for Kubernetes supported version") private String isoState; @@ -134,6 +138,14 @@ public void setIsoName(String isoName) { this.isoName = isoName; } + public String getIsoUrl() { + return isoUrl; + } + + public void setIsoUrl(String isoUrl) { + this.isoUrl = isoUrl; + } + public String getIsoState() { return isoState; } diff --git a/plugins/integrations/kubernetes-service/src/test/java/com/cloud/kubernetes/version/KubernetesVersionServiceTest.java b/plugins/integrations/kubernetes-service/src/test/java/com/cloud/kubernetes/version/KubernetesVersionServiceTest.java index 455df6b57d42..5778d8142656 100644 --- a/plugins/integrations/kubernetes-service/src/test/java/com/cloud/kubernetes/version/KubernetesVersionServiceTest.java +++ b/plugins/integrations/kubernetes-service/src/test/java/com/cloud/kubernetes/version/KubernetesVersionServiceTest.java @@ -17,6 +17,9 @@ package com.cloud.kubernetes.version; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertNotNull; +import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.Mockito.when; import java.lang.reflect.Field; @@ -25,6 +28,11 @@ import java.util.UUID; import com.cloud.cpu.CPU; +import com.cloud.user.Account; +import com.cloud.user.AccountManager; +import com.cloud.user.AccountVO; +import com.cloud.user.User; +import com.cloud.user.UserVO; import org.apache.cloudstack.api.command.admin.kubernetes.version.AddKubernetesSupportedVersionCmd; import org.apache.cloudstack.api.command.admin.kubernetes.version.DeleteKubernetesSupportedVersionCmd; import org.apache.cloudstack.api.command.admin.kubernetes.version.UpdateKubernetesSupportedVersionCmd; @@ -63,11 +71,6 @@ import com.cloud.storage.dao.VMTemplateDao; import com.cloud.template.TemplateApiService; import com.cloud.template.VirtualMachineTemplate; -import com.cloud.user.Account; -import com.cloud.user.AccountManager; -import com.cloud.user.AccountVO; -import com.cloud.user.User; -import com.cloud.user.UserVO; import com.cloud.utils.Pair; import com.cloud.utils.component.ComponentContext; import com.cloud.utils.db.Filter; @@ -95,6 +98,8 @@ public class KubernetesVersionServiceTest { private DataCenterDao dataCenterDao; @Mock private TemplateApiService templateService; + @Mock + private Account accountMock; AutoCloseable closeable; @@ -124,6 +129,7 @@ public void setUp() throws Exception { when(dataCenterDao.findById(Mockito.anyLong())).thenReturn(zone); TemplateJoinVO templateJoinVO = Mockito.mock(TemplateJoinVO.class); + when(templateJoinVO.getUrl()).thenReturn("https://download.cloudstack.com"); when(templateJoinVO.getState()).thenReturn(ObjectInDataStoreStateMachine.State.Ready); when(templateJoinVO.getArch()).thenReturn(CPU.CPUArch.getDefault()); when(templateJoinDao.findById(Mockito.anyLong())).thenReturn(templateJoinVO); @@ -140,19 +146,66 @@ public void tearDown() throws Exception { @Test public void listKubernetesSupportedVersionsTest() { - ListKubernetesSupportedVersionsCmd cmd = Mockito.mock(ListKubernetesSupportedVersionsCmd.class); - List versionVOs = new ArrayList<>(); - KubernetesSupportedVersionVO versionVO = Mockito.mock(KubernetesSupportedVersionVO.class); - when(versionVO.getSemanticVersion()).thenReturn(KubernetesVersionService.MIN_KUBERNETES_VERSION); - versionVOs.add(versionVO); - when(kubernetesSupportedVersionDao.findById(Mockito.anyLong())).thenReturn(versionVO); - when(kubernetesSupportedVersionDao.searchAndCount(Mockito.any(SearchCriteria.class), - Mockito.any(Filter.class))).thenReturn(new Pair<>(versionVOs, versionVOs.size())); - ListResponse versionsResponse = - kubernetesVersionService.listKubernetesSupportedVersions(cmd); - Assert.assertEquals(versionVOs.size(), versionsResponse.getCount().intValue()); - Assert.assertTrue(CollectionUtils.isNotEmpty(versionsResponse.getResponses())); - Assert.assertEquals(versionVOs.size(), versionsResponse.getResponses().size()); + CallContext callContextMock = Mockito.mock(CallContext.class); + try (MockedStatic callContextMockedStatic = Mockito.mockStatic(CallContext.class)) { + callContextMockedStatic.when(CallContext::current).thenReturn(callContextMock); + final SearchCriteria versionSearchCriteria = Mockito.mock(SearchCriteria.class); + when(callContextMock.getCallingAccount()).thenReturn(accountMock); + ListKubernetesSupportedVersionsCmd cmd = Mockito.mock(ListKubernetesSupportedVersionsCmd.class); + List versionVOs = new ArrayList<>(); + KubernetesSupportedVersionVO versionVO = Mockito.mock(KubernetesSupportedVersionVO.class); + when(versionVO.getSemanticVersion()).thenReturn(KubernetesVersionService.MIN_KUBERNETES_VERSION); + versionVOs.add(versionVO); + when(kubernetesSupportedVersionDao.findById(Mockito.anyLong())).thenReturn(versionVO); + when(kubernetesSupportedVersionDao.searchAndCount(Mockito.any(), Mockito.any(Filter.class))) + .thenReturn(new Pair<>(versionVOs, versionVOs.size())); + ListResponse versionsResponse = + kubernetesVersionService.listKubernetesSupportedVersions(cmd); + Assert.assertEquals(versionVOs.size(), versionsResponse.getCount().intValue()); + Assert.assertTrue(CollectionUtils.isNotEmpty(versionsResponse.getResponses())); + Assert.assertEquals(versionVOs.size(), versionsResponse.getResponses().size()); + } + } + + @Test + public void listKubernetesSupportedVersionsTestWhenAdmin() { + CallContext callContextMock = Mockito.mock(CallContext.class); + try (MockedStatic callContextMockedStatic = Mockito.mockStatic(CallContext.class)) { + callContextMockedStatic.when(CallContext::current).thenReturn(callContextMock); + ListKubernetesSupportedVersionsCmd cmd = Mockito.mock(ListKubernetesSupportedVersionsCmd.class); + List versionVOs = new ArrayList<>(); + KubernetesSupportedVersionVO versionVO = Mockito.mock(KubernetesSupportedVersionVO.class); + when(versionVO.getSemanticVersion()).thenReturn(KubernetesVersionService.MIN_KUBERNETES_VERSION); + versionVOs.add(versionVO); + when(callContextMock.getCallingAccount()).thenReturn(accountMock); + when(kubernetesSupportedVersionDao.findById(Mockito.anyLong())).thenReturn(versionVO); + when(kubernetesSupportedVersionDao.searchAndCount(Mockito.any(), Mockito.any(Filter.class))) + .thenReturn(new Pair<>(versionVOs, versionVOs.size())); + when(accountManager.isRootAdmin(anyLong())).thenReturn(true); + ListResponse response = kubernetesVersionService.listKubernetesSupportedVersions(cmd); + assertNotNull(response.getResponses().get(0).getIsoUrl()); + } + } + + @Test + public void listKubernetesSupportedVersionsTestWhenOtherUser() { + CallContext callContextMock = Mockito.mock(CallContext.class); + try (MockedStatic callContextMockedStatic = Mockito.mockStatic(CallContext.class)) { + callContextMockedStatic.when(CallContext::current).thenReturn(callContextMock); + ListKubernetesSupportedVersionsCmd cmd = Mockito.mock(ListKubernetesSupportedVersionsCmd.class); + List versionVOs = new ArrayList<>(); + KubernetesSupportedVersionVO versionVO = Mockito.mock(KubernetesSupportedVersionVO.class); + when(versionVO.getSemanticVersion()).thenReturn(KubernetesVersionService.MIN_KUBERNETES_VERSION); + versionVOs.add(versionVO); + when(callContextMock.getCallingAccount()).thenReturn(accountMock); + when(kubernetesSupportedVersionDao.findById(Mockito.anyLong())).thenReturn(versionVO); + when(kubernetesSupportedVersionDao.searchAndCount(Mockito.any(), Mockito.any(Filter.class))) + .thenReturn(new Pair<>(versionVOs, versionVOs.size())); + when(accountManager.isRootAdmin(anyLong())).thenReturn(false); + when(accountMock.getId()).thenReturn(2L); + ListResponse response = kubernetesVersionService.listKubernetesSupportedVersions(cmd); + assertNull(response.getResponses().get(0).getIsoUrl()); + } } @Test(expected = InvalidParameterValueException.class) @@ -224,7 +277,7 @@ public void addKubernetesSupportedVersionIsoUrlTest() throws ResourceAllocationE mockedComponentContext.when(() -> ComponentContext.inject(Mockito.any(RegisterIsoCmd.class))).thenReturn( new RegisterIsoCmd()); mockedCallContext.when(CallContext::current).thenReturn(callContext); - + when(callContext.getCallingAccount()).thenReturn(accountMock); when(templateService.registerIso(Mockito.any(RegisterIsoCmd.class))).thenReturn( Mockito.mock(VirtualMachineTemplate.class)); VMTemplateVO templateVO = Mockito.mock(VMTemplateVO.class); diff --git a/ui/public/locales/en.json b/ui/public/locales/en.json index 721d8bacc295..bb52a3390f38 100644 --- a/ui/public/locales/en.json +++ b/ui/public/locales/en.json @@ -1249,6 +1249,7 @@ "label.isoname": "Attached ISO", "label.isos": "ISOs", "label.isostate": "ISO state", +"label.isourl": "ISO URL", "label.ispersistent": "Persistent ", "label.ispublic": "Public", "label.isready": "Ready", diff --git a/ui/public/locales/pt_BR.json b/ui/public/locales/pt_BR.json index 65c657f69d80..4ef0a09f328e 100644 --- a/ui/public/locales/pt_BR.json +++ b/ui/public/locales/pt_BR.json @@ -874,6 +874,7 @@ "label.isoname": "Imagem ISO plugada", "label.isos": "ISOs", "label.isostate": "Estado da ISO", +"label.isourl": "URL da ISO", "label.ispersistent": "Persistente", "label.ispublic": "P\u00fablico", "label.isready": "Pronto", diff --git a/ui/src/config/section/image.js b/ui/src/config/section/image.js index 46dec2e1b249..43ba4c7edac4 100644 --- a/ui/src/config/section/image.js +++ b/ui/src/config/section/image.js @@ -60,9 +60,9 @@ export default { details: () => { var fields = ['name', 'id', 'displaytext', 'checksum', 'hypervisor', 'arch', 'format', 'ostypename', 'size', 'physicalsize', 'isready', 'passwordenabled', 'crossZones', 'templatetype', 'directdownload', 'deployasis', 'ispublic', 'isfeatured', 'isextractable', 'isdynamicallyscalable', 'crosszones', 'type', - 'account', 'domain', 'created', 'userdatadetails', 'userdatapolicy'] + 'account', 'domain', 'created', 'userdatadetails', 'userdatapolicy', 'url'] if (['Admin'].includes(store.getters.userInfo.roletype)) { - fields.push('templatetag', 'templatetype', 'url') + fields.push('templatetag', 'templatetype') } return fields }, @@ -118,10 +118,10 @@ export default { api: 'registerTemplate', icon: 'cloud-upload-outlined', label: 'label.upload.template.from.local', + show: () => { return 'getUploadParamsForTemplate' in store.getters.apis }, docHelp: 'adminguide/templates.html#uploading-templates-and-isos-from-a-local-computer', listView: true, popup: true, - show: () => { return isZoneCreated() && 'getUploadParamsForTemplate' in store.getters.apis }, component: shallowRef(defineAsyncComponent(() => import('@/views/image/RegisterOrUploadTemplate.vue'))) }, { @@ -372,7 +372,7 @@ export default { permission: ['listKubernetesSupportedVersions'], searchFilters: ['zoneid', 'minimumsemanticversion', 'arch'], columns: ['name', 'state', 'semanticversion', 'isostate', 'mincpunumber', 'minmemory', 'arch', 'zonename'], - details: ['name', 'semanticversion', 'supportsautoscaling', 'zoneid', 'zonename', 'isoid', 'isoname', 'isostate', 'arch', 'mincpunumber', 'minmemory', 'supportsha', 'state', 'created'], + details: ['name', 'semanticversion', 'supportsautoscaling', 'zoneid', 'zonename', 'isoid', 'isoname', 'isostate', 'arch', 'mincpunumber', 'minmemory', 'supportsha', 'state', 'created', 'isourl'], tabs: [ { name: 'details', From dcd3e609e363f6054a7dc8f0dc547172d4a6c1c6 Mon Sep 17 00:00:00 2001 From: Vitor Hugo Homem Marzarotto Date: Wed, 14 May 2025 14:51:56 -0300 Subject: [PATCH 2/6] Clean code --- .../version/KubernetesVersionManagerImpl.java | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/version/KubernetesVersionManagerImpl.java b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/version/KubernetesVersionManagerImpl.java index 100301d6be74..e027cbf41e3c 100644 --- a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/version/KubernetesVersionManagerImpl.java +++ b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/version/KubernetesVersionManagerImpl.java @@ -87,7 +87,9 @@ public class KubernetesVersionManagerImpl extends ManagerBase implements Kuberne protected void updateTemplateDetailsInKubernetesSupportedVersionResponse( final KubernetesSupportedVersion kubernetesSupportedVersion, KubernetesSupportedVersionResponse response) { + Account caller = CallContext.current().getCallingAccount(); TemplateJoinVO template = templateJoinDao.findById(kubernetesSupportedVersion.getIsoId()); + boolean isAdmin = accountManager.isRootAdmin(caller.getId()); if (template == null) { return; } @@ -96,6 +98,9 @@ protected void updateTemplateDetailsInKubernetesSupportedVersionResponse( if (template.getState() != null) { response.setIsoState(template.getState().toString()); } + if (isAdmin) { + response.setIsoUrl(template.getUrl()); + } response.setIsoArch(template.getArch().getType()); response.setDirectDownload(template.isDirectDownload()); } @@ -120,17 +125,6 @@ private KubernetesSupportedVersionResponse createKubernetesSupportedVersionRespo KubernetesClusterService.MIN_KUBERNETES_VERSION_HA_SUPPORT)>=0); response.setSupportsAutoscaling(versionSupportsAutoscaling(kubernetesSupportedVersion)); updateTemplateDetailsInKubernetesSupportedVersionResponse(kubernetesSupportedVersion, response); - TemplateJoinVO template = templateJoinDao.findById(kubernetesSupportedVersion.getIsoId()); - Account caller = CallContext.current().getCallingAccount(); - boolean isAdmin = accountManager.isRootAdmin(caller.getId()); - if (template != null) { - response.setIsoId(template.getUuid()); - response.setIsoName(template.getName()); - response.setIsoState(template.getState().toString()); - if (isAdmin) { - response.setIsoUrl(template.getUrl()); - } - } response.setCreated(kubernetesSupportedVersion.getCreated()); return response; } From aa48375820563bd934acdb782406af392bedda59 Mon Sep 17 00:00:00 2001 From: Vitor Hugo Homem Marzarotto Date: Thu, 15 May 2025 16:33:33 -0300 Subject: [PATCH 3/6] Corrects test --- .../KubernetesVersionManagerImplTest.java | 68 ++++++++++++------- 1 file changed, 45 insertions(+), 23 deletions(-) diff --git a/plugins/integrations/kubernetes-service/src/test/java/com/cloud/kubernetes/version/KubernetesVersionManagerImplTest.java b/plugins/integrations/kubernetes-service/src/test/java/com/cloud/kubernetes/version/KubernetesVersionManagerImplTest.java index f827610c3cba..49c67519878e 100644 --- a/plugins/integrations/kubernetes-service/src/test/java/com/cloud/kubernetes/version/KubernetesVersionManagerImplTest.java +++ b/plugins/integrations/kubernetes-service/src/test/java/com/cloud/kubernetes/version/KubernetesVersionManagerImplTest.java @@ -18,13 +18,17 @@ import java.util.UUID; +import com.cloud.user.Account; +import com.cloud.user.AccountManager; import org.apache.cloudstack.api.response.KubernetesSupportedVersionResponse; import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine; +import org.apache.cloudstack.context.CallContext; import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.InjectMocks; import org.mockito.Mock; +import org.mockito.MockedStatic; import org.mockito.Mockito; import org.mockito.junit.MockitoJUnitRunner; import org.springframework.test.util.ReflectionTestUtils; @@ -39,37 +43,55 @@ public class KubernetesVersionManagerImplTest { @Mock TemplateJoinDao templateJoinDao; + @Mock + AccountManager accountManager; + @InjectMocks KubernetesVersionManagerImpl kubernetesVersionManager = new KubernetesVersionManagerImpl(); @Test public void testUpdateTemplateDetailsInKubernetesSupportedVersionResponseNullTemplate() { - KubernetesSupportedVersion kubernetesSupportedVersion = Mockito.mock(KubernetesSupportedVersion.class); - Mockito.when(kubernetesSupportedVersion.getIsoId()).thenReturn(1L); - KubernetesSupportedVersionResponse response = new KubernetesSupportedVersionResponse(); - kubernetesVersionManager.updateTemplateDetailsInKubernetesSupportedVersionResponse(kubernetesSupportedVersion, - response); - Assert.assertNull(ReflectionTestUtils.getField(response, "isoId")); + try (MockedStatic callContextMocked = Mockito.mockStatic(CallContext.class)) { + CallContext callContextMock = Mockito.mock(CallContext.class); + callContextMocked.when(CallContext::current).thenReturn(callContextMock); + Account accountMock = Mockito.mock(Account.class); + Mockito.when(callContextMock.getCallingAccount()).thenReturn(accountMock); + Mockito.when(accountMock.getId()).thenReturn(2L); + + KubernetesSupportedVersion kubernetesSupportedVersion = Mockito.mock(KubernetesSupportedVersion.class); + Mockito.when(kubernetesSupportedVersion.getIsoId()).thenReturn(1L); + KubernetesSupportedVersionResponse response = new KubernetesSupportedVersionResponse(); + kubernetesVersionManager.updateTemplateDetailsInKubernetesSupportedVersionResponse(kubernetesSupportedVersion, + response); + Assert.assertNull(ReflectionTestUtils.getField(response, "isoId")); + } } @Test public void testUpdateTemplateDetailsInKubernetesSupportedVersionResponseValidTemplate() { - KubernetesSupportedVersion kubernetesSupportedVersion = Mockito.mock(KubernetesSupportedVersion.class); - Mockito.when(kubernetesSupportedVersion.getIsoId()).thenReturn(1L); - KubernetesSupportedVersionResponse response = new KubernetesSupportedVersionResponse(); - TemplateJoinVO templateJoinVO = Mockito.mock(TemplateJoinVO.class); - Mockito.when(templateJoinVO.getArch()).thenReturn(CPU.CPUArch.getDefault()); - String uuid = UUID.randomUUID().toString(); - Mockito.when(templateJoinVO.getUuid()).thenReturn(uuid); - Mockito.when(templateJoinDao.findById(1L)).thenReturn(templateJoinVO); - kubernetesVersionManager.updateTemplateDetailsInKubernetesSupportedVersionResponse(kubernetesSupportedVersion, - response); - Assert.assertEquals(uuid, ReflectionTestUtils.getField(response, "isoId")); - Assert.assertNull(ReflectionTestUtils.getField(response, "isoState")); - ObjectInDataStoreStateMachine.State state = ObjectInDataStoreStateMachine.State.Ready; - Mockito.when(templateJoinVO.getState()).thenReturn(state); - kubernetesVersionManager.updateTemplateDetailsInKubernetesSupportedVersionResponse(kubernetesSupportedVersion, - response); - Assert.assertEquals(state.toString(), ReflectionTestUtils.getField(response, "isoState")); + try (MockedStatic callContextMocked = Mockito.mockStatic(CallContext.class)) { + CallContext callContextMock = Mockito.mock(CallContext.class); + callContextMocked.when(CallContext::current).thenReturn(callContextMock); + Account accountMock = Mockito.mock(Account.class); + Mockito.when(callContextMock.getCallingAccount()).thenReturn(accountMock); + Mockito.when(accountMock.getId()).thenReturn(2L); + KubernetesSupportedVersion kubernetesSupportedVersion = Mockito.mock(KubernetesSupportedVersion.class); + Mockito.when(kubernetesSupportedVersion.getIsoId()).thenReturn(1L); + KubernetesSupportedVersionResponse response = new KubernetesSupportedVersionResponse(); + TemplateJoinVO templateJoinVO = Mockito.mock(TemplateJoinVO.class); + Mockito.when(templateJoinVO.getArch()).thenReturn(CPU.CPUArch.getDefault()); + String uuid = UUID.randomUUID().toString(); + Mockito.when(templateJoinVO.getUuid()).thenReturn(uuid); + Mockito.when(templateJoinDao.findById(1L)).thenReturn(templateJoinVO); + kubernetesVersionManager.updateTemplateDetailsInKubernetesSupportedVersionResponse(kubernetesSupportedVersion, + response); + Assert.assertEquals(uuid, ReflectionTestUtils.getField(response, "isoId")); + Assert.assertNull(ReflectionTestUtils.getField(response, "isoState")); + ObjectInDataStoreStateMachine.State state = ObjectInDataStoreStateMachine.State.Ready; + Mockito.when(templateJoinVO.getState()).thenReturn(state); + kubernetesVersionManager.updateTemplateDetailsInKubernetesSupportedVersionResponse(kubernetesSupportedVersion, + response); + Assert.assertEquals(state.toString(), ReflectionTestUtils.getField(response, "isoState")); + } } } From 67225e2539bdd313d0a4e7f03049ce7d6637b814 Mon Sep 17 00:00:00 2001 From: Vitor Hugo Homem Marzarotto Date: Fri, 16 May 2025 16:01:29 -0300 Subject: [PATCH 4/6] Organize import, and clean the code --- .../version/KubernetesVersionManagerImpl.java | 12 ++-- .../KubernetesVersionManagerImplTest.java | 68 +++++++------------ 2 files changed, 29 insertions(+), 51 deletions(-) diff --git a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/version/KubernetesVersionManagerImpl.java b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/version/KubernetesVersionManagerImpl.java index e027cbf41e3c..080f68f22339 100644 --- a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/version/KubernetesVersionManagerImpl.java +++ b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/version/KubernetesVersionManagerImpl.java @@ -23,7 +23,6 @@ import javax.inject.Inject; import org.apache.cloudstack.api.ApiCommandResourceType; -import com.cloud.user.Account; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.command.admin.kubernetes.version.AddKubernetesSupportedVersionCmd; import org.apache.cloudstack.api.command.admin.kubernetes.version.DeleteKubernetesSupportedVersionCmd; @@ -54,6 +53,7 @@ import com.cloud.storage.dao.VMTemplateZoneDao; import com.cloud.template.TemplateApiService; import com.cloud.template.VirtualMachineTemplate; +import com.cloud.user.Account; import com.cloud.user.AccountManager; import com.cloud.utils.Pair; import com.cloud.utils.component.ComponentContext; @@ -86,10 +86,8 @@ public class KubernetesVersionManagerImpl extends ManagerBase implements Kuberne public static final String MINIMUN_AUTOSCALER_SUPPORTED_VERSION = "1.15.0"; protected void updateTemplateDetailsInKubernetesSupportedVersionResponse( - final KubernetesSupportedVersion kubernetesSupportedVersion, KubernetesSupportedVersionResponse response) { - Account caller = CallContext.current().getCallingAccount(); + final KubernetesSupportedVersion kubernetesSupportedVersion, KubernetesSupportedVersionResponse response, boolean isRootAdmin) { TemplateJoinVO template = templateJoinDao.findById(kubernetesSupportedVersion.getIsoId()); - boolean isAdmin = accountManager.isRootAdmin(caller.getId()); if (template == null) { return; } @@ -98,7 +96,7 @@ protected void updateTemplateDetailsInKubernetesSupportedVersionResponse( if (template.getState() != null) { response.setIsoState(template.getState().toString()); } - if (isAdmin) { + if (isRootAdmin) { response.setIsoUrl(template.getUrl()); } response.setIsoArch(template.getArch().getType()); @@ -124,7 +122,9 @@ private KubernetesSupportedVersionResponse createKubernetesSupportedVersionRespo response.setSupportsHA(compareSemanticVersions(kubernetesSupportedVersion.getSemanticVersion(), KubernetesClusterService.MIN_KUBERNETES_VERSION_HA_SUPPORT)>=0); response.setSupportsAutoscaling(versionSupportsAutoscaling(kubernetesSupportedVersion)); - updateTemplateDetailsInKubernetesSupportedVersionResponse(kubernetesSupportedVersion, response); + Account caller = CallContext.current().getCallingAccount(); + boolean isRootAdmin = accountManager.isRootAdmin(caller.getId()); + updateTemplateDetailsInKubernetesSupportedVersionResponse(kubernetesSupportedVersion, response, isRootAdmin); response.setCreated(kubernetesSupportedVersion.getCreated()); return response; } diff --git a/plugins/integrations/kubernetes-service/src/test/java/com/cloud/kubernetes/version/KubernetesVersionManagerImplTest.java b/plugins/integrations/kubernetes-service/src/test/java/com/cloud/kubernetes/version/KubernetesVersionManagerImplTest.java index 49c67519878e..bbec555e8e54 100644 --- a/plugins/integrations/kubernetes-service/src/test/java/com/cloud/kubernetes/version/KubernetesVersionManagerImplTest.java +++ b/plugins/integrations/kubernetes-service/src/test/java/com/cloud/kubernetes/version/KubernetesVersionManagerImplTest.java @@ -18,17 +18,13 @@ import java.util.UUID; -import com.cloud.user.Account; -import com.cloud.user.AccountManager; import org.apache.cloudstack.api.response.KubernetesSupportedVersionResponse; import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine; -import org.apache.cloudstack.context.CallContext; import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.InjectMocks; import org.mockito.Mock; -import org.mockito.MockedStatic; import org.mockito.Mockito; import org.mockito.junit.MockitoJUnitRunner; import org.springframework.test.util.ReflectionTestUtils; @@ -43,55 +39,37 @@ public class KubernetesVersionManagerImplTest { @Mock TemplateJoinDao templateJoinDao; - @Mock - AccountManager accountManager; - @InjectMocks KubernetesVersionManagerImpl kubernetesVersionManager = new KubernetesVersionManagerImpl(); @Test public void testUpdateTemplateDetailsInKubernetesSupportedVersionResponseNullTemplate() { - try (MockedStatic callContextMocked = Mockito.mockStatic(CallContext.class)) { - CallContext callContextMock = Mockito.mock(CallContext.class); - callContextMocked.when(CallContext::current).thenReturn(callContextMock); - Account accountMock = Mockito.mock(Account.class); - Mockito.when(callContextMock.getCallingAccount()).thenReturn(accountMock); - Mockito.when(accountMock.getId()).thenReturn(2L); - - KubernetesSupportedVersion kubernetesSupportedVersion = Mockito.mock(KubernetesSupportedVersion.class); - Mockito.when(kubernetesSupportedVersion.getIsoId()).thenReturn(1L); - KubernetesSupportedVersionResponse response = new KubernetesSupportedVersionResponse(); - kubernetesVersionManager.updateTemplateDetailsInKubernetesSupportedVersionResponse(kubernetesSupportedVersion, - response); - Assert.assertNull(ReflectionTestUtils.getField(response, "isoId")); - } + KubernetesSupportedVersion kubernetesSupportedVersion = Mockito.mock(KubernetesSupportedVersion.class); + Mockito.when(kubernetesSupportedVersion.getIsoId()).thenReturn(1L); + KubernetesSupportedVersionResponse response = new KubernetesSupportedVersionResponse(); + kubernetesVersionManager.updateTemplateDetailsInKubernetesSupportedVersionResponse(kubernetesSupportedVersion, + response, true); + Assert.assertNull(ReflectionTestUtils.getField(response, "isoId")); } @Test public void testUpdateTemplateDetailsInKubernetesSupportedVersionResponseValidTemplate() { - try (MockedStatic callContextMocked = Mockito.mockStatic(CallContext.class)) { - CallContext callContextMock = Mockito.mock(CallContext.class); - callContextMocked.when(CallContext::current).thenReturn(callContextMock); - Account accountMock = Mockito.mock(Account.class); - Mockito.when(callContextMock.getCallingAccount()).thenReturn(accountMock); - Mockito.when(accountMock.getId()).thenReturn(2L); - KubernetesSupportedVersion kubernetesSupportedVersion = Mockito.mock(KubernetesSupportedVersion.class); - Mockito.when(kubernetesSupportedVersion.getIsoId()).thenReturn(1L); - KubernetesSupportedVersionResponse response = new KubernetesSupportedVersionResponse(); - TemplateJoinVO templateJoinVO = Mockito.mock(TemplateJoinVO.class); - Mockito.when(templateJoinVO.getArch()).thenReturn(CPU.CPUArch.getDefault()); - String uuid = UUID.randomUUID().toString(); - Mockito.when(templateJoinVO.getUuid()).thenReturn(uuid); - Mockito.when(templateJoinDao.findById(1L)).thenReturn(templateJoinVO); - kubernetesVersionManager.updateTemplateDetailsInKubernetesSupportedVersionResponse(kubernetesSupportedVersion, - response); - Assert.assertEquals(uuid, ReflectionTestUtils.getField(response, "isoId")); - Assert.assertNull(ReflectionTestUtils.getField(response, "isoState")); - ObjectInDataStoreStateMachine.State state = ObjectInDataStoreStateMachine.State.Ready; - Mockito.when(templateJoinVO.getState()).thenReturn(state); - kubernetesVersionManager.updateTemplateDetailsInKubernetesSupportedVersionResponse(kubernetesSupportedVersion, - response); - Assert.assertEquals(state.toString(), ReflectionTestUtils.getField(response, "isoState")); - } + KubernetesSupportedVersion kubernetesSupportedVersion = Mockito.mock(KubernetesSupportedVersion.class); + Mockito.when(kubernetesSupportedVersion.getIsoId()).thenReturn(1L); + KubernetesSupportedVersionResponse response = new KubernetesSupportedVersionResponse(); + TemplateJoinVO templateJoinVO = Mockito.mock(TemplateJoinVO.class); + Mockito.when(templateJoinVO.getArch()).thenReturn(CPU.CPUArch.getDefault()); + String uuid = UUID.randomUUID().toString(); + Mockito.when(templateJoinVO.getUuid()).thenReturn(uuid); + Mockito.when(templateJoinDao.findById(1L)).thenReturn(templateJoinVO); + kubernetesVersionManager.updateTemplateDetailsInKubernetesSupportedVersionResponse(kubernetesSupportedVersion, + response, true); + Assert.assertEquals(uuid, ReflectionTestUtils.getField(response, "isoId")); + Assert.assertNull(ReflectionTestUtils.getField(response, "isoState")); + ObjectInDataStoreStateMachine.State state = ObjectInDataStoreStateMachine.State.Ready; + Mockito.when(templateJoinVO.getState()).thenReturn(state); + kubernetesVersionManager.updateTemplateDetailsInKubernetesSupportedVersionResponse(kubernetesSupportedVersion, + response, true); + Assert.assertEquals(state.toString(), ReflectionTestUtils.getField(response, "isoState")); } } From 542c8a57135dc52bc86a99f431971fb67091455f Mon Sep 17 00:00:00 2001 From: Henrique Sato Date: Fri, 28 Nov 2025 13:56:38 -0300 Subject: [PATCH 5/6] Address reviews --- .../version/KubernetesVersionManagerImpl.java | 13 +++++++------ .../version/KubernetesVersionServiceTest.java | 1 - ui/src/config/section/image.js | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/version/KubernetesVersionManagerImpl.java b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/version/KubernetesVersionManagerImpl.java index 080f68f22339..7b126b2fba0f 100644 --- a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/version/KubernetesVersionManagerImpl.java +++ b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/version/KubernetesVersionManagerImpl.java @@ -103,7 +103,7 @@ protected void updateTemplateDetailsInKubernetesSupportedVersionResponse( response.setDirectDownload(template.isDirectDownload()); } - private KubernetesSupportedVersionResponse createKubernetesSupportedVersionResponse(final KubernetesSupportedVersion kubernetesSupportedVersion) { + private KubernetesSupportedVersionResponse createKubernetesSupportedVersionResponse(final KubernetesSupportedVersion kubernetesSupportedVersion, boolean isRootAdmin) { KubernetesSupportedVersionResponse response = new KubernetesSupportedVersionResponse(); response.setObjectName("kubernetessupportedversion"); response.setId(kubernetesSupportedVersion.getUuid()); @@ -122,8 +122,6 @@ private KubernetesSupportedVersionResponse createKubernetesSupportedVersionRespo response.setSupportsHA(compareSemanticVersions(kubernetesSupportedVersion.getSemanticVersion(), KubernetesClusterService.MIN_KUBERNETES_VERSION_HA_SUPPORT)>=0); response.setSupportsAutoscaling(versionSupportsAutoscaling(kubernetesSupportedVersion)); - Account caller = CallContext.current().getCallingAccount(); - boolean isRootAdmin = accountManager.isRootAdmin(caller.getId()); updateTemplateDetailsInKubernetesSupportedVersionResponse(kubernetesSupportedVersion, response, isRootAdmin); response.setCreated(kubernetesSupportedVersion.getCreated()); return response; @@ -132,8 +130,11 @@ private KubernetesSupportedVersionResponse createKubernetesSupportedVersionRespo private ListResponse createKubernetesSupportedVersionListResponse( List versions, Integer count) { List responseList = new ArrayList<>(); + Account caller = CallContext.current().getCallingAccount(); + boolean isRootAdmin = accountManager.isRootAdmin(caller.getId()); + for (KubernetesSupportedVersionVO version : versions) { - responseList.add(createKubernetesSupportedVersionResponse(version)); + responseList.add(createKubernetesSupportedVersionResponse(version, isRootAdmin)); } ListResponse response = new ListResponse<>(); response.setResponses(responseList, count); @@ -380,7 +381,7 @@ public KubernetesSupportedVersionResponse addKubernetesSupportedVersion(final Ad supportedVersionVO = kubernetesSupportedVersionDao.persist(supportedVersionVO); CallContext.current().putContextParameter(KubernetesSupportedVersion.class, supportedVersionVO.getUuid()); - return createKubernetesSupportedVersionResponse(supportedVersionVO); + return createKubernetesSupportedVersionResponse(supportedVersionVO, true); } @Override @@ -441,7 +442,7 @@ public KubernetesSupportedVersionResponse updateKubernetesSupportedVersion(final } version = kubernetesSupportedVersionDao.findById(versionId); } - return createKubernetesSupportedVersionResponse(version); + return createKubernetesSupportedVersionResponse(version, true); } @Override diff --git a/plugins/integrations/kubernetes-service/src/test/java/com/cloud/kubernetes/version/KubernetesVersionServiceTest.java b/plugins/integrations/kubernetes-service/src/test/java/com/cloud/kubernetes/version/KubernetesVersionServiceTest.java index 5778d8142656..b874a9a0ffa6 100644 --- a/plugins/integrations/kubernetes-service/src/test/java/com/cloud/kubernetes/version/KubernetesVersionServiceTest.java +++ b/plugins/integrations/kubernetes-service/src/test/java/com/cloud/kubernetes/version/KubernetesVersionServiceTest.java @@ -277,7 +277,6 @@ public void addKubernetesSupportedVersionIsoUrlTest() throws ResourceAllocationE mockedComponentContext.when(() -> ComponentContext.inject(Mockito.any(RegisterIsoCmd.class))).thenReturn( new RegisterIsoCmd()); mockedCallContext.when(CallContext::current).thenReturn(callContext); - when(callContext.getCallingAccount()).thenReturn(accountMock); when(templateService.registerIso(Mockito.any(RegisterIsoCmd.class))).thenReturn( Mockito.mock(VirtualMachineTemplate.class)); VMTemplateVO templateVO = Mockito.mock(VMTemplateVO.class); diff --git a/ui/src/config/section/image.js b/ui/src/config/section/image.js index 43ba4c7edac4..7b08b06c7ee3 100644 --- a/ui/src/config/section/image.js +++ b/ui/src/config/section/image.js @@ -118,10 +118,10 @@ export default { api: 'registerTemplate', icon: 'cloud-upload-outlined', label: 'label.upload.template.from.local', - show: () => { return 'getUploadParamsForTemplate' in store.getters.apis }, docHelp: 'adminguide/templates.html#uploading-templates-and-isos-from-a-local-computer', listView: true, popup: true, + show: () => { return 'getUploadParamsForTemplate' in store.getters.apis }, component: shallowRef(defineAsyncComponent(() => import('@/views/image/RegisterOrUploadTemplate.vue'))) }, { From 7ff3dca97a4970de616ca6fa42cc44e4e51fe826 Mon Sep 17 00:00:00 2001 From: Henrique Sato Date: Fri, 28 Nov 2025 14:28:23 -0300 Subject: [PATCH 6/6] Restore registerTemplate changes --- ui/src/config/section/image.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/src/config/section/image.js b/ui/src/config/section/image.js index 7b08b06c7ee3..3f8286c5fb12 100644 --- a/ui/src/config/section/image.js +++ b/ui/src/config/section/image.js @@ -121,7 +121,7 @@ export default { docHelp: 'adminguide/templates.html#uploading-templates-and-isos-from-a-local-computer', listView: true, popup: true, - show: () => { return 'getUploadParamsForTemplate' in store.getters.apis }, + show: () => { return isZoneCreated() && 'getUploadParamsForTemplate' in store.getters.apis }, component: shallowRef(defineAsyncComponent(() => import('@/views/image/RegisterOrUploadTemplate.vue'))) }, {