Skip to content

Commit 2e61267

Browse files
author
ebracha
committed
feat: use resource actions for auto-sync toggle instead of update permission (#21564)
Signed-off-by: Eli Bracha <[email protected]>
1 parent d016dbe commit 2e61267

File tree

7 files changed

+175
-15
lines changed

7 files changed

+175
-15
lines changed
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
tests:
2+
- given:
3+
apiVersion: argoproj.io/v1alpha1
4+
kind: Application
5+
metadata:
6+
name: test-app
7+
spec:
8+
syncPolicy:
9+
automated:
10+
enabled: true
11+
prune: true
12+
selfHeal: true
13+
when:
14+
action: toggle-auto-sync
15+
expect:
16+
spec:
17+
syncPolicy:
18+
automated:
19+
enabled: false
20+
prune: true
21+
selfHeal: true
22+
23+
- given:
24+
apiVersion: argoproj.io/v1alpha1
25+
kind: Application
26+
metadata:
27+
name: test-app
28+
spec:
29+
syncPolicy:
30+
automated:
31+
enabled: false
32+
prune: true
33+
selfHeal: true
34+
when:
35+
action: toggle-auto-sync
36+
expect:
37+
spec:
38+
syncPolicy:
39+
automated:
40+
enabled: true
41+
prune: true
42+
selfHeal: true
43+
44+
- given:
45+
apiVersion: argoproj.io/v1alpha1
46+
kind: Application
47+
metadata:
48+
name: test-app
49+
spec: {}
50+
when:
51+
action: toggle-auto-sync
52+
expect:
53+
spec:
54+
syncPolicy:
55+
automated:
56+
enabled: false
57+
prune: false
58+
selfHeal: false
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
actions = {}
2+
actions["toggle-auto-sync"] = {}
3+
return actions
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
function toggleAutoSync(obj)
2+
if obj.spec.syncPolicy and obj.spec.syncPolicy.automated then
3+
obj.spec.syncPolicy.automated = nil
4+
if not next(obj.spec.syncPolicy) then
5+
obj.spec.syncPolicy = nil
6+
end
7+
else
8+
if not obj.spec.syncPolicy then
9+
obj.spec.syncPolicy = {}
10+
end
11+
obj.spec.syncPolicy.automated = {
12+
enabled = true
13+
}
14+
end
15+
return obj
16+
end
17+
18+
return toggleAutoSync(obj)
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
health_status = {}
2+
if obj.status ~= nil then
3+
if obj.status.health ~= nil then
4+
health_status.status = obj.status.health.status
5+
health_status.message = obj.status.health.message
6+
end
7+
end
8+
if health_status.status == nil then
9+
health_status.status = "Progressing"
10+
health_status.message = "Waiting for application to be reconciled"
11+
end
12+
return health_status
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
tests = {
2+
{
3+
given = {
4+
status = {
5+
health = {
6+
status = "Healthy",
7+
message = "Application is healthy"
8+
}
9+
}
10+
},
11+
want = {
12+
status = "Healthy",
13+
message = "Application is healthy"
14+
}
15+
},
16+
{
17+
given = {
18+
status = {
19+
health = {
20+
status = "Degraded",
21+
message = "Application has issues"
22+
}
23+
}
24+
},
25+
want = {
26+
status = "Degraded",
27+
message = "Application has issues"
28+
}
29+
},
30+
{
31+
given = {},
32+
want = {
33+
status = "Progressing",
34+
message = "Waiting for application to be reconciled"
35+
}
36+
}
37+
}
38+
39+
for _, test in ipairs(tests) do
40+
local state = health(test.given)
41+
if state.status ~= test.want.status then
42+
error(string.format("Expected status %s but got %s", test.want.status, state.status))
43+
end
44+
if state.message ~= test.want.message then
45+
error(string.format("Expected message '%s' but got '%s'", test.want.message, state.message))
46+
end
47+
end

server/application/application.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2380,6 +2380,13 @@ func (s *Server) getUnstructuredLiveResourceOrApp(ctx context.Context, rbacReque
23802380
if err != nil {
23812381
return nil, nil, nil, nil, err
23822382
}
2383+
2384+
app.SetGroupVersionKind(schema.GroupVersionKind{
2385+
Group: applicationType.Group,
2386+
Version: v1alpha1.SchemeGroupVersion.Version,
2387+
Kind: applicationType.ApplicationKind,
2388+
})
2389+
23832390
if err = s.enf.EnforceErr(ctx.Value("claims"), rbac.ResourceApplications, rbacRequest, app.RBACName(s.ns)); err != nil {
23842391
return nil, nil, nil, nil, err
23852392
}

ui/src/app/applications/components/application-summary/application-summary.tsx

Lines changed: 30 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -377,12 +377,24 @@ export const ApplicationSummary = (props: ApplicationSummaryProps) => {
377377
if (confirmed) {
378378
try {
379379
setChangeSync(true);
380-
const updatedApp = JSON.parse(JSON.stringify(props.app)) as models.Application;
381-
if (!updatedApp.spec.syncPolicy) {
382-
updatedApp.spec.syncPolicy = {};
383-
}
384-
updatedApp.spec.syncPolicy.automated = {prune, selfHeal};
385-
await updateApp(updatedApp, {validate: false});
380+
const resource: models.ResourceNode = {
381+
name: props.app.metadata.name,
382+
namespace: props.app.metadata.namespace ,
383+
kind: 'Application',
384+
group: 'argoproj.io',
385+
version: props.app.apiVersion,
386+
parentRefs: [] as models.ResourceRef[],
387+
info: [] as models.InfoItem[],
388+
resourceVersion: props.app.metadata.resourceVersion,
389+
uid: props.app.metadata.uid,
390+
};
391+
392+
await services.applications.runResourceAction(
393+
props.app.metadata.name,
394+
props.app.metadata.namespace,
395+
resource,
396+
'toggle-auto-sync'
397+
);
386398
} catch (e) {
387399
ctx.notifications.show({
388400
content: <ErrorNotification title={`Unable to "${confirmationTitle.replace(/\?/g, '')}:`} e={e} />,
@@ -394,17 +406,20 @@ export const ApplicationSummary = (props: ApplicationSummaryProps) => {
394406
}
395407
}
396408

397-
async function unsetAutoSync(ctx: ContextApis) {
398-
const confirmed = await ctx.popup.confirm('Disable Auto-Sync?', 'Are you sure you want to disable automated application synchronization');
409+
async function setAutoSyncPolicy(ctx: ContextApis, confirmationTitle: string, confirmationText: string, prune: boolean, selfHeal: boolean) {
410+
const confirmed = await ctx.popup.confirm(confirmationTitle, confirmationText);
399411
if (confirmed) {
400412
try {
401413
setChangeSync(true);
402414
const updatedApp = JSON.parse(JSON.stringify(props.app)) as models.Application;
403-
updatedApp.spec.syncPolicy.automated = null;
415+
if (!updatedApp.spec.syncPolicy) {
416+
updatedApp.spec.syncPolicy = {};
417+
}
418+
updatedApp.spec.syncPolicy.automated = {prune, selfHeal};
404419
await updateApp(updatedApp, {validate: false});
405420
} catch (e) {
406421
ctx.notifications.show({
407-
content: <ErrorNotification title='Unable to disable Auto-Sync' e={e} />,
422+
content: <ErrorNotification title={`Unable to "${confirmationTitle.replace(/\?/g, '')}:`} e={e} />,
408423
type: NotificationType.Error
409424
});
410425
} finally {
@@ -510,7 +525,7 @@ export const ApplicationSummary = (props: ApplicationSummaryProps) => {
510525
<div className='columns small-3'>{(app.spec.syncPolicy && app.spec.syncPolicy.automated && <span>AUTOMATED</span>) || <span>NONE</span>}</div>
511526
<div className='columns small-9'>
512527
{(app.spec.syncPolicy && app.spec.syncPolicy.automated && (
513-
<button className='argo-button argo-button--base' onClick={() => unsetAutoSync(ctx)}>
528+
<button className='argo-button argo-button--base' onClick={() => setAutoSync(ctx, 'Disable Auto-Sync?', 'Are you sure you want to disable automated application synchronization', false, false)}>
514529
<Spinner show={changeSync} style={{marginRight: '5px'}} />
515530
Disable Auto-Sync
516531
</button>
@@ -536,7 +551,7 @@ export const ApplicationSummary = (props: ApplicationSummaryProps) => {
536551
<button
537552
className='argo-button argo-button--base'
538553
onClick={() =>
539-
setAutoSync(
554+
setAutoSyncPolicy(
540555
ctx,
541556
'Disable Prune Resources?',
542557
'Are you sure you want to disable resource pruning during automated application synchronization?',
@@ -550,7 +565,7 @@ export const ApplicationSummary = (props: ApplicationSummaryProps) => {
550565
<button
551566
className='argo-button argo-button--base'
552567
onClick={() =>
553-
setAutoSync(
568+
setAutoSyncPolicy(
554569
ctx,
555570
'Enable Prune Resources?',
556571
'Are you sure you want to enable resource pruning during automated application synchronization?',
@@ -570,7 +585,7 @@ export const ApplicationSummary = (props: ApplicationSummaryProps) => {
570585
<button
571586
className='argo-button argo-button--base'
572587
onClick={() =>
573-
setAutoSync(
588+
setAutoSyncPolicy(
574589
ctx,
575590
'Disable Self Heal?',
576591
'Are you sure you want to disable automated self healing?',
@@ -584,7 +599,7 @@ export const ApplicationSummary = (props: ApplicationSummaryProps) => {
584599
<button
585600
className='argo-button argo-button--base'
586601
onClick={() =>
587-
setAutoSync(
602+
setAutoSyncPolicy(
588603
ctx,
589604
'Enable Self Heal?',
590605
'Are you sure you want to enable automated self healing?',

0 commit comments

Comments
 (0)