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()
}
}
}