TT Lab
Get started
Learn Learning paths Courses

GitOps and Argo CD

Turning Three Manual Chores Into Buttons

Continue in TT Lab

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

  1. 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.
  2. 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.
  3. 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.
  4. 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.
  5. 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.
  6. 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.
  7. 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.
  8. 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.

Notes

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.