Turning Three Manual Chores Into Buttons
Goal
In resource.customizations.actions.<그룹>_<종류> (group, then kind) of argocd-cm, you write discovery.lua and an action definition to create resource actions, dim buttons depending on the situation, and actually put the changes the action makes onto the kwok cluster.
Why it matters
If you do GitOps properly, the things done by hand in production should disappear, but a few remain to the end — pausing for a moment, bringing Pods up again, raising something by one notch. If a person does these with kubectl, the repository and the cluster diverge, and if you block them entirely, a more dangerous workaround appears. Resource actions are a device that turns just those few things into buttons on the screen and brings them under permissions and audit records. There are two key design points here. First, an action does not change the repository — so if automatic synchronization is on, it goes back at the next reconcile. Second, what to offer as a button is gathered in one place, discovery.lua. Since this code, not the screen, makes the judgment of turning buttons on and off by looking at the state, you can prevent by design the incident of stopping something already stopped.
Steps
- In
/root/ga-actions/deploy.yaml, in thega-actionsnamespace, create a Deploymentweb—spec.replicas2, one container (web, imagenginx:1.25), and the selector and label areapp: web./root/ga-actions/argocd-cm.yamlis an empty ConfigMap withdata: {}. Save the output ofargocd admin settings resource-overrides list-actions /root/ga-actions/deploy.yaml --argocd-cm-path /root/ga-actions/argocd-cm.yamlto/root/ga-actions/none.txt. - In
/root/ga-actions/w-running.yaml, create, ofexample.com/v1, aWidget— the name isw-running, the namespace isga-actions,spec.sizeis 3, andstatus.phaseisRunning. In/root/ga-actions/argocd-cm-pause.yaml, put the keyresource.customizations.actions.example.com_Widget, havediscovery.luaput out one action,pause, and write indefinitionsthat action'saction.lua(which setsspec.pausedto true). Save thelist-actionsoutput to/root/ga-actions/list-pause.txt. - Save the output of
argocd admin settings resource-overrides run-action /root/ga-actions/w-running.yaml pause --argocd-cm-path /root/ga-actions/argocd-cm-pause.yamlto/root/ga-actions/run-pause.txt. You must seepaused: trueadded in the output. - Create
/root/ga-actions/w-paused.yaml— the name isw-paused,spec.sizeis 3,spec.pausedis true, andstatus.phaseisPaused. In/root/ga-actions/argocd-cm-toggle.yaml, put two actions,pauseandresume, and havediscovery.lua, depending on the value ofspec.paused, attachdisabledso that only one of the two can be used. Save thelist-actionsoutput for the two samples to/root/ga-actions/list-running.txtand/root/ga-actions/list-paused.txtrespectively. - In
/root/ga-actions/argocd-cm-scale.yaml, putscale-upin addition to the two actions of step 4 — it increasesspec.sizeby 1. On a paused widget, this action must also be dimmed. Save the output of running, onw-running.yaml,scale-upto/root/ga-actions/run-scale.txt. You must see 3 change to 4. - In
/root/ga-actions/argocd-cm-full.yaml, leave the widget actions of step 5 as they are, and make one more key,resource.customizations.actions.apps_Deployment. The action name ispin-image, and it changes the first container's image tonginx:1.27-hardened. Save the output of running this action ondeploy.yamlto/root/ga-actions/run-pin.txt. - On the kwok cluster, create the namespace
ga-actionsand applydeploy.yaml. Then create and apply a manifest/root/ga-actions/deploy-pinned.yamlthat reflects the change the step 6 action told you about — the cluster'swebcontainer image must become the value the action decided. - In
/root/ga-actions/actions-matrix.tsv, write four or more lines of<샘플파일이름>\t<동작이름>\t<바뀐 필드에서 찾을 글자>(sample file name, action name, string to look for in the changed field) — three or more action names must appear./root/ga-actions/check-actions.shreads this table, runs each action with/root/ga-actions/argocd-cm-full.yaml, printsOK …if the output has that string andMISMATCH …if not to standard output only, and must end with a non-zero code if even one line is wrong. Save that output to/root/ga-actions/actions-result.txt.
Notes
- The key name is
resource.customizations.actions.<그룹>_<종류>(group, then kind) and the separator is an underscore. - Two items,
discovery.luaanddefinitions, go inside the value. - discovery.lua returns a table keyed by action names, and if you put
{["disabled"] = true}in a value, it is dimmed. - Array indices in Lua start at 1 — the first container is
containers[1]. - Common mistake: expecting built-in actions to show up in
list-actions. This command reads only the ConfigMap. - Reference: https://argo-cd.readthedocs.io/en/stable/operator-manual/resource_actions/
This command looks only at the ConfigMap
In /root/ga-actions/deploy.yaml, in the ga-actions namespace, create a Deployment web — spec.replicas 2, one container (web, image nginx:1.25), and the selector and label are app: web. /root/ga-actions/argocd-cm.yaml is an empty ConfigMap with data: {}. Save the output of argocd admin settings resource-overrides list-actions /root/ga-actions/deploy.yaml --argocd-cm-path /root/ga-actions/argocd-cm.yaml to /root/ga-actions/none.txt.
On the Argo CD screen, a Deployment shows buttons such as restart. But the output of this command is different — if you think about what this command reads, you can see why. The later steps keep using these two files as material.
The code that decides which buttons to show
In /root/ga-actions/w-running.yaml, create, of example.com/v1, a Widget — the name is w-running, the namespace is ga-actions, spec.size is 3, and status.phase is Running. In /root/ga-actions/argocd-cm-pause.yaml, put the key resource.customizations.actions.example.com_Widget, have discovery.lua put out one action, pause, and write in definitions that action's action.lua (which sets spec.paused to true). Save the list-actions output to /root/ga-actions/list-pause.txt.
Two items, discovery.lua and definitions, go inside the value of one key. discovery returns a table keyed by names, and definitions is a list with names and action.lua. A resource with no spec can come in too, so check in action.lua.
When you run the action, the changed field comes out
Save the output of argocd admin settings resource-overrides run-action /root/ga-actions/w-running.yaml pause --argocd-cm-path /root/ga-actions/argocd-cm-pause.yaml to /root/ga-actions/run-pause.txt. You must see paused: true added in the output.
This command does not return the changed resource whole but shows only what changed. So you can see at a glance what else the action touched besides what it intended — that is exactly the part to be most careful about when writing an action.
Dim buttons depending on the situation
Create /root/ga-actions/w-paused.yaml — the name is w-paused, spec.size is 3, spec.paused is true, and status.phase is Paused. In /root/ga-actions/argocd-cm-toggle.yaml, put two actions, pause and resume, and have discovery.lua, depending on the value of spec.paused, attach disabled so that only one of the two can be used. Save the list-actions output for the two samples to /root/ga-actions/list-running.txt and /root/ga-actions/list-paused.txt respectively.
If you put {["disabled"] = true} in the value of the table that discovery.lua returns, that action is dimmed. A button that stops something already stopped invites incidents, so it is this code, not the screen, that turns things on and off by looking at the state.
An action that reads a value and computes
In /root/ga-actions/argocd-cm-scale.yaml, put scale-up in addition to the two actions of step 4 — it increases spec.size by 1. On a paused widget, this action must also be dimmed. Save the output of running, on w-running.yaml, scale-up to /root/ga-actions/run-scale.txt. You must see 3 change to 4.
action.lua can read the resource and compute. What to watch out for here is when the value is absent — adding 1 to nil kills the script. The samples of this lab always have size, but for a rule you will actually use, you must put in a check.
Attach my action to a built-in kind too
In /root/ga-actions/argocd-cm-full.yaml, leave the widget actions of step 5 as they are, and make one more key, resource.customizations.actions.apps_Deployment. The action name is pin-image, and it changes the first container's image to nginx:1.27-hardened. Save the output of running this action on deploy.yaml to /root/ga-actions/run-pin.txt.
Array indices in Lua start not at 0 but at 1 — containers[1] is the first container. If you attach a user action to a built-in kind, one more button appears on the screen, and the built-in actions remain as they are.
Put the result the action made on the real cluster
On the kwok cluster, create the namespace ga-actions and apply deploy.yaml. Then create and apply a manifest /root/ga-actions/deploy-pinned.yaml that reflects the change the step 6 action told you about — the cluster's web container image must become the value the action decided.
run-action does not save the changed resource; it only tells you what would change. In the real Argo CD, the controller applies that result, but here a person reflects the same change into a manifest and puts it up. If the namespace does not exist, the apply fails.
Bundle what the actions do into a table and run a regression check
In /root/ga-actions/actions-matrix.tsv, write four or more lines of <샘플파일이름>\t<동작이름>\t<바뀐 필드에서 찾을 글자> (sample file name, action name, string to look for in the changed field) — three or more action names must appear. /root/ga-actions/check-actions.sh reads this table, runs each action with /root/ga-actions/argocd-cm-full.yaml, prints OK … if the output has that string and MISMATCH … if not to standard output only, and must end with a non-zero code if even one line is wrong. Save that output to /root/ga-actions/actions-result.txt.
An action is code that is forgotten once written, and on the day the resource schema changes, it quietly starts touching the wrong field. With a table, a red light appears that very day. If the script writes files itself, it overwrites the student's outputs when the grader runs it again, so send to standard output only.