This is an automated email from the ASF dual-hosted git repository.

DaanHoogland pushed a commit to branch 4.20
in repository https://gitbox.apache.org/repos/asf/cloudstack.git


The following commit(s) were added to refs/heads/4.20 by this push:
     new 2327e83ed3e UI: Fix listing of resources for ASG belonging to a 
project (#13187)
2327e83ed3e is described below

commit 2327e83ed3e707e8a25bb702d94186059f325a8d
Author: Vishesh <[email protected]>
AuthorDate: Mon Sep 7 15:17:57 2026 +0530

    UI: Fix listing of resources for ASG belonging to a project (#13187)
---
 ui/src/utils/util.js                            |  9 ++++
 ui/src/views/compute/AutoScaleDownPolicyTab.vue | 19 ++++++---
 ui/src/views/compute/AutoScaleLoadBalancing.vue | 20 ++++++---
 ui/src/views/compute/AutoScaleUpPolicyTab.vue   | 19 ++++++---
 ui/src/views/compute/AutoScaleVmProfile.vue     | 57 ++++++++++++++++++-------
 5 files changed, 90 insertions(+), 34 deletions(-)

diff --git a/ui/src/utils/util.js b/ui/src/utils/util.js
index d64f3a13764..ec18e0b5d5f 100644
--- a/ui/src/utils/util.js
+++ b/ui/src/utils/util.js
@@ -111,3 +111,12 @@ export function toCsv ({ keys = null, data = null, 
columnDelimiter = ',', lineDe
 
   return result
 }
+
+// Adds the projectid of a project-scoped resource to the given API params, so
+// that listing calls are correctly scoped to the resource's project.
+export function addProjectFilter (params, resource) {
+  if (resource?.projectid) {
+    params.projectid = resource.projectid
+  }
+  return params
+}
diff --git a/ui/src/views/compute/AutoScaleDownPolicyTab.vue 
b/ui/src/views/compute/AutoScaleDownPolicyTab.vue
index 422d1ab1122..e3af0da3370 100644
--- a/ui/src/views/compute/AutoScaleDownPolicyTab.vue
+++ b/ui/src/views/compute/AutoScaleDownPolicyTab.vue
@@ -324,6 +324,7 @@
 
 <script>
 import { api } from '@/api'
+import { addProjectFilter } from '@/utils/util'
 import Status from '@/components/widgets/Status'
 import TooltipButton from '@/components/widgets/TooltipButton'
 import TooltipLabel from '@/components/widgets/TooltipLabel'
@@ -425,10 +426,12 @@ export default {
   methods: {
     fetchInitData () {
       this.loading = true
-      api('listAutoScaleVmGroups', {
+      const params = {
         listAll: true,
         id: this.resource.id
-      }).then(response => {
+      }
+      addProjectFilter(params, this.resource)
+      api('listAutoScaleVmGroups', params).then(response => {
         const lbruleid = 
response.listautoscalevmgroupsresponse?.autoscalevmgroup?.[0]?.lbruleid
         this.policies = 
response.listautoscalevmgroupsresponse?.autoscalevmgroup?.[0]?.scaledownpolicies
         if (this.selectedPolicyId) {
@@ -437,10 +440,12 @@ export default {
           this.policy = this.policies?.[0]
           this.selectedPolicyId = this.policy.id
         }
-        api('listLoadBalancerRules', {
+        const lbParams = {
           listAll: true,
           id: lbruleid
-        }).then(response => {
+        }
+        addProjectFilter(lbParams, this.resource)
+        api('listLoadBalancerRules', lbParams).then(response => {
           const networkid = 
response.listloadbalancerrulesresponse?.loadbalancerrule?.[0]?.networkid
           api('listNetworks', {
             listAll: true,
@@ -464,10 +469,12 @@ export default {
     },
     fetchData () {
       this.loading = true
-      api('listAutoScalePolicies', {
+      const params = {
         listAll: true,
         id: this.selectedPolicyId
-      }).then(response => {
+      }
+      addProjectFilter(params, this.resource)
+      api('listAutoScalePolicies', params).then(response => {
         this.policy = 
response.listautoscalepoliciesresponse?.autoscalepolicy[0]
       }).finally(() => {
         this.loading = false
diff --git a/ui/src/views/compute/AutoScaleLoadBalancing.vue 
b/ui/src/views/compute/AutoScaleLoadBalancing.vue
index 6091689bd35..f5377297c2e 100644
--- a/ui/src/views/compute/AutoScaleLoadBalancing.vue
+++ b/ui/src/views/compute/AutoScaleLoadBalancing.vue
@@ -298,6 +298,7 @@
 <script>
 import { ref, reactive, toRaw, nextTick } from 'vue'
 import { api } from '@/api'
+import { addProjectFilter } from '@/utils/util'
 import { mixinForm } from '@/utils/mixin'
 import Status from '@/components/widgets/Status'
 import TooltipButton from '@/components/widgets/TooltipButton'
@@ -462,12 +463,14 @@ export default {
       this.lbRules = []
       this.stickinessPolicies = []
 
-      api('listLoadBalancerRules', {
+      const params = {
         listAll: true,
         id: this.resource.lbruleid,
         page: this.page,
         pageSize: this.pageSize
-      }).then(response => {
+      }
+      addProjectFilter(params, this.resource)
+      api('listLoadBalancerRules', params).then(response => {
         this.lbRules = response.listloadbalancerrulesresponse.loadbalancerrule 
|| []
         this.totalCount = response.listloadbalancerrulesresponse.count || 0
       }).then(() => {
@@ -518,16 +521,19 @@ export default {
     },
     fetchAutoScaleVMgroups () {
       this.loading = true
-      this.lbRules.forEach(rule => {
-        api('listAutoScaleVmGroups', {
+      const requests = this.lbRules.map(rule => {
+        const params = {
           listAll: true,
           lbruleid: rule.id
-        }).then(response => {
+        }
+        addProjectFilter(params, this.resource)
+        return api('listAutoScaleVmGroups', params).then(response => {
           rule.autoscalevmgroup = 
response.listautoscalevmgroupsresponse?.autoscalevmgroup?.[0]
-        }).finally(() => {
-          this.loading = false
         })
       })
+      Promise.all(requests).finally(() => {
+        this.loading = false
+      })
     },
     returnAlgorithmName (name) {
       switch (name) {
diff --git a/ui/src/views/compute/AutoScaleUpPolicyTab.vue 
b/ui/src/views/compute/AutoScaleUpPolicyTab.vue
index 4ddd67a5d0a..3d0fe3375c0 100644
--- a/ui/src/views/compute/AutoScaleUpPolicyTab.vue
+++ b/ui/src/views/compute/AutoScaleUpPolicyTab.vue
@@ -324,6 +324,7 @@
 
 <script>
 import { api } from '@/api'
+import { addProjectFilter } from '@/utils/util'
 import Status from '@/components/widgets/Status'
 import TooltipButton from '@/components/widgets/TooltipButton'
 import TooltipLabel from '@/components/widgets/TooltipLabel'
@@ -425,10 +426,12 @@ export default {
   methods: {
     fetchInitData () {
       this.loading = true
-      api('listAutoScaleVmGroups', {
+      const params = {
         listAll: true,
         id: this.resource.id
-      }).then(response => {
+      }
+      addProjectFilter(params, this.resource)
+      api('listAutoScaleVmGroups', params).then(response => {
         const lbruleid = 
response.listautoscalevmgroupsresponse?.autoscalevmgroup?.[0]?.lbruleid
         this.policies = 
response.listautoscalevmgroupsresponse?.autoscalevmgroup?.[0]?.scaleuppolicies
         if (this.selectedPolicyId) {
@@ -437,10 +440,12 @@ export default {
           this.policy = this.policies?.[0]
           this.selectedPolicyId = this.policy.id
         }
-        api('listLoadBalancerRules', {
+        const lbParams = {
           listAll: true,
           id: lbruleid
-        }).then(response => {
+        }
+        addProjectFilter(lbParams, this.resource)
+        api('listLoadBalancerRules', lbParams).then(response => {
           const networkid = 
response.listloadbalancerrulesresponse?.loadbalancerrule?.[0]?.networkid
           api('listNetworks', {
             listAll: true,
@@ -464,10 +469,12 @@ export default {
     },
     fetchData () {
       this.loading = true
-      api('listAutoScalePolicies', {
+      const params = {
         listAll: true,
         id: this.selectedPolicyId
-      }).then(response => {
+      }
+      addProjectFilter(params, this.resource)
+      api('listAutoScalePolicies', params).then(response => {
         this.policy = 
response.listautoscalepoliciesresponse?.autoscalepolicy[0]
       }).finally(() => {
         this.loading = false
diff --git a/ui/src/views/compute/AutoScaleVmProfile.vue 
b/ui/src/views/compute/AutoScaleVmProfile.vue
index 20a87065cf4..bdb2ec012b5 100644
--- a/ui/src/views/compute/AutoScaleVmProfile.vue
+++ b/ui/src/views/compute/AutoScaleVmProfile.vue
@@ -62,7 +62,7 @@
           <div class="form__label">
             <tooltip-label :title="$t('label.templatename')" 
:tooltip="createAutoScaleVmProfileApiParams.templateid.description"/>
           </div>
-          {{ getTemplateName(templateid) }}
+          {{ templateName || templateid }}
         </div>
       </div>
       <div class="form">
@@ -199,7 +199,7 @@
     <a-modal
       :title="$t('label.edit.autoscale.vmprofile')"
       :visible="editProfileModalVisible"
-      :afterClose="closeModal"
+      :afterClose="onModalClosed"
       :maskClosable="false"
       :closable="true"
       :footer="null"
@@ -284,7 +284,7 @@
         </div>
       </div>
       <div :span="24" class="action-button">
-        <a-button :loading="loading" @click="closeModal">{{ $t('label.cancel') 
}}</a-button>
+        <a-button :loading="loading" @click="editProfileModalVisible = 
false">{{ $t('label.cancel') }}</a-button>
         <a-button :loading="loading" ref="submit" type="primary" 
@click="updateAutoScaleVmProfile">{{ $t('label.ok') }}</a-button>
       </div>
     </a-modal>
@@ -308,6 +308,7 @@
 
 <script>
 import { api } from '@/api'
+import { addProjectFilter } from '@/utils/util'
 import { isAdmin, isAdminOrDomainAdmin } from '@/role'
 import Status from '@/components/widgets/Status'
 import TooltipButton from '@/components/widgets/TooltipButton'
@@ -338,6 +339,7 @@ export default {
       autoscaleuserid: null,
       expungevmgraceperiod: null,
       templateid: null,
+      templateName: null,
       serviceofferingid: null,
       userdata: null,
       userdataid: null,
@@ -422,6 +424,7 @@ export default {
         domainid: this.resource.domainid,
         account: this.resource.account
       }
+      addProjectFilter(params, this.resource)
       if (isAdmin()) {
         params.templatefilter = 'all'
       } else {
@@ -436,6 +439,7 @@ export default {
         listall: 'true',
         issystem: 'false'
       }
+      addProjectFilter(params, this.resource)
       if (isAdminOrDomainAdmin()) {
         params.isrecursive = 'true'
       }
@@ -446,15 +450,18 @@ export default {
     },
     fetchData () {
       this.loading = true
-      api('listAutoScaleVmProfiles', {
+      const params = {
         listAll: true,
         id: this.resource.vmprofileid
-      }).then(response => {
+      }
+      addProjectFilter(params, this.resource)
+      api('listAutoScaleVmProfiles', params).then(response => {
         this.profileid = 
response.listautoscalevmprofilesresponse?.autoscalevmprofile?.[0]?.id
         this.autoscaleuserid = 
response.listautoscalevmprofilesresponse?.autoscalevmprofile?.[0]?.autoscaleuserid
         this.expungevmgraceperiod = 
response.listautoscalevmprofilesresponse?.autoscalevmprofile?.[0]?.expungevmgraceperiod
         this.serviceofferingid = 
response.listautoscalevmprofilesresponse?.autoscalevmprofile?.[0]?.serviceofferingid
         this.templateid = 
response.listautoscalevmprofilesresponse?.autoscalevmprofile?.[0]?.templateid
+        this.fetchTemplate(this.templateid)
         this.userdata = 
this.decodeUserData(decodeURIComponent(response.listautoscalevmprofilesresponse?.autoscalevmprofile?.[0]?.userdata
 || ''))
         this.userdataid = 
response.listautoscalevmprofilesresponse?.autoscalevmprofile?.[0]?.userdataid
         this.userdataname = 
response.listautoscalevmprofilesresponse?.autoscalevmprofile?.[0]?.userdataname
@@ -468,13 +475,24 @@ export default {
         this.loading = false
       })
     },
-    getTemplateName (templateid) {
-      for (const template of this.templatesList) {
-        if (template.id === templateid) {
-          return template.name
-        }
+    fetchTemplate (templateid) {
+      if (!templateid) {
+        this.templateName = null
+        return
       }
-      return ''
+      const params = {
+        id: templateid,
+        templatefilter: isAdmin() ? 'all' : 'executable'
+      }
+      addProjectFilter(params, this.resource)
+      api('listTemplates', params).then(json => {
+        // Ignore stale responses if templateid changed while this request was 
in flight.
+        if (templateid !== this.templateid) return
+        this.templateName = json.listtemplatesresponse?.template?.[0]?.name || 
templateid
+      }).catch(() => {
+        if (templateid !== this.templateid) return
+        this.templateName = templateid
+      })
     },
     getServiceOfferingName (serviceofferingid) {
       for (const serviceoffering of this.serviceOfferingsList) {
@@ -576,16 +594,21 @@ export default {
         this.$pollJob({
           jobId: response.updateautoscalevmprofileresponse.jobid,
           successMethod: (result) => {
+            this.fetchData()
           },
           errorMessage: this.$t('message.update.autoscale.vm.profile.failed'),
           errorMethod: () => {
+            this.fetchData()
           }
         })
-      }).finally(() => {
+      }).catch(() => {
+        // fetchData() resets loading once the job completes; reset here only 
on submit failure.
         this.loading = false
       })
     },
     updateAutoScaleVmProfile () {
+      if (this.loading) return
+      this.loading = true
       const params = {
         id: this.profileid,
         expungevmgraceperiod: this.expungevmgraceperiod,
@@ -604,12 +627,16 @@ export default {
         this.$pollJob({
           jobId: response.updateautoscalevmprofileresponse.jobid,
           successMethod: (result) => {
+            this.loading = false
+            // Closing the modal triggers afterClose -> onModalClosed, which 
refreshes the data.
+            this.editProfileModalVisible = false
           },
           errorMessage: this.$t('message.update.autoscale.vm.profile.failed'),
           errorMethod: () => {
+            this.loading = false
           }
         })
-      }).finally(() => {
+      }).catch(() => {
         this.loading = false
       })
     },
@@ -617,8 +644,8 @@ export default {
       const decodedData = Buffer.from(userdata, 'base64')
       return decodedData.toString('utf-8')
     },
-    closeModal () {
-      this.editProfileModalVisible = false
+    onModalClosed () {
+      this.fetchData()
     }
   }
 }

Reply via email to