windsource / picus

Connects to Woodpecker CI and dynamically creates an agent in the cloud.
MIT License
39 stars 4 forks source link

Selective scope #5

Closed windsource closed 11 months ago

windsource commented 1 year ago

Currently Picus assumes to be the only one adding agents to Woodpecker. This should be changed such that existing agents should be taken into account. So Picus shall support adding an agent when existing agents cannot handle the load. Also Picus shall be able to be configured to listen only to specifc platforms and/or labels and handle agents only for that scope.

Lerentis commented 12 months ago

I have never written anything in rust so i probably would not be big help in the actual implementation, but how about a design proposal:

Define a kv pair as selector:

Assume i have configured PICUS_AGENT_WOODPECKER_FILTER_LABELS: type=picus so any new agent that will be added gets this label (ref).

In the pipelines:

In the pipeline that should bind to this specific agent one can configure

labels:
    type: picus

the woodpecker endpoint api/queue/info returns these labels:

{
  "pending": [
    {
      "id": "146",
      "data": "REDACTED",
      "labels": {
        "repo": "REDACTED",
        "type": "picus"
      },
      "dependencies": null,
      "run_on": null,
      "dep_status": {},
      "agent_id": 0
    }
  ],
  "waiting_on_deps": null,
  "running": null,
  "stats": {
    "worker_count": 40,
    "pending_count": 1,
    "waiting_on_deps_count": 0,
    "running_count": 0,
    "completed_count": 0
  },
  "paused": false
}

now picus could check for a condition where it has created workers that match this kv combination and create a new agent if there is none or reuse an existing instance if it is still available. in hetzner and in aws the kv pair could even be added to the instance so the data could directly be matched against the dedicated API. with that picus does not even have to hold any additional state.

wdyt @windsource ?

windsource commented 12 months ago

@Lerentis thanks for the analysis. That sounds like a good plan. I am still planning to implement this feature but I am not sure when I will have the time. So if anyone is willing to create a PR that would help.

windsource commented 11 months ago

Storing the filter labels on instances seems to be not that easy. Hetzner only allows certain characters (, is not allowed) for labels and the length is limited to 63 characters.

Lerentis commented 11 months ago

Similar limitations apply to k8s as well. I was proposing this as both hetzner and aws are supporting this and kops is using labels similar (as in as a selector). Imo it would be okay to simply fail if a user is configuring something unsupported by the cloud provider

windsource commented 11 months ago

I think there is no need to store the filter labels on the instance when the labels are passed to picus. I am currently preparing a PR.

To understand filter labels I have performed the following tests:

Scenario 1

No WOODPECKER_FILTER_LABELS applied to an agent.

Pipeline:

labels:
  type: picus

Result: Agent will not pick this pipeline.

Scenario 2

WOODPECKER_FILTER_LABELS=type=picus.

Pipeline:

labels:
  type: picus

Result: Agent picks that pipeline.

Scenario 3

WOODPECKER_FILTER_LABELS=type=picus.

Pipeline:

labels:
  type: picus
  foo: bar

Result: Agent will not pick that pipeline.

Scenario 4

WOODPECKER_FILTER_LABELS=type=picus.

Pipeline has no labels set.

Result: Agent will pick that pipeline.

Scenario 5

WOODPECKER_FILTER_LABELS=type=picus and agent has platform=linux/amd64

Pipeline for arm64:

labels:
  type: picus
  platform: linux/arm64

Result: Agent will not pick that pipeline (at least with version next-5b3bba726d)

windsource commented 11 months ago

The release v0.6.0 contains the new feature. Note that you need two more environment variables for Picus:

See README.md for details.