vmware-tanzu / cartographer

Cartographer is a Supply Chain Choreographer.
https://cartographer.sh
Apache License 2.0
447 stars 64 forks source link

Allow a process through which to propagate labels down to children objects #439

Open voor opened 2 years ago

voor commented 2 years ago

Description of problem

The Cartographer workload creates a whole host of other objects based on the clustersupplychains, this results in lots of objects that correctly have the owner references:

  ownerReferences:
  - apiVersion: carto.run/v1alpha1
    blockOwnerDeletion: true
    controller: true
    kind: Workload
    name: sample-rabbitmq-app
    uid: 903d8c28-48dc-4785-ae9e-3bb66e3554a2

And have cartographer's labels:

  labels:
    app.kubernetes.io/component: image-scan
    app.kubernetes.io/part-of: sample-rabbitmq-app
    carto.run/cluster-supply-chain-name: source-test-scan-to-url
    carto.run/cluster-template-name: image-scanner-template
    carto.run/resource-name: image-scanner
    carto.run/template-kind: ClusterImageTemplate
    carto.run/workload-name: sample-rabbitmq-app
    carto.run/workload-namespace: apps
    scanpolicies.scst-scan.apps.tanzu.vmware.com: scan-policy
    scantemplates.scst-scan.apps.tanzu.vmware.com: private-image-scan-template

But I want to put my own propagated labels, specifically from the workload:

  labels:
    kapp.k14s.io/app: "1638467264654767328"
    kapp.k14s.io/association: v1.732ad0107ef31c7d67839ae1cc40ad49

I am able to use ownershiplabelrules so Cartographer does not need to take the labels from the workload metadata. (It can, if that makes sense to you, but I don't want to restrict that line of thinking)

Proposed solution

<Please describe your proposed solution, preferably in the following style:>

Given the desire to propagate user created labels to child objects
When a workload populates some field **(this does not need to be the labels on the workload)** with labels
Then those labels are added to the child objects

Example

For example, if I was to have:

kind: Workload
metadata:
  name: example
spec:
  iAmBadAtNamingThingsLabels:
    bob: alice
    another: example

Then an implementation of ClusterSourceTemplate could do something like this:

(this is quasicode it's really not tested or functional)

  ytt: |
    #@ load("@ytt:data", "data")

    ...

    #@ if hasattr(data.values.workload.spec.source, "git"):
    apiVersion: source.toolkit.fluxcd.io/v1beta1
    kind: GitRepository
    metadata:
      name: #@ data.values.workload.metadata.name
      labels:
        app.kubernetes.io/component: source
        #@ if/end hasattr(data.values.workload.metadata, "labels") and hasattr(data.values.workload.metadata.labels, "app.kubernetes.io/part-of"):
        app.kubernetes.io/part-of: #@ data.values.workload.metadata.labels["app.kubernetes.io/part-of"]
        #@ if hasattr(data.values.workload.spec.iAmBadAtNamingThingsLabels, "labels")
        #@ for label in data.values.workload.spec.iAmBadAtNamingThingsLabels:
        label
        #@ end
        #@ end

Additional Context

I would like to be able to see all objects associated with a Workload using kapp inspect.

github-actions[bot] commented 2 years ago

Hello @voor! Welcome to the Cartographer community and thank you for opening your first issue, we appreciate your contributions

waciumawanjohi commented 2 years ago

@voor Can you accomplish what you want by leveraging params in your workload?

E.g. instead of this workload (which is not possible today):

kind: Workload
metadata:
  name: example
spec:
  iAmBadAtNamingThingsLabels:
    bob: alice
    another: example

Use this workload (which is possible today):

kind: Workload
metadata:
  name: example
spec:
  params:
    iAmBadAtNamingThingsLabels:
      bob: alice
      another: example
voor commented 2 years ago

I should probably preference this with the fact I'm not a ClusterSourceTemplate author, so while it might be possible in Cartographer, it would need to be better advertised to creators of those templates that label propagation is something that should be added and supported. It might be easier to explicitly put something like that into Cartographer, though.

scothis commented 2 years ago

I'm in favor of propagating all labels from the parent (Workload) resource down to the resources stamped out by a Cartographer template. This is easy for the .metadata.labels because they are in a common location for every k8s resource. However, this becomes trickier when your resource is a Deployment and you also want the labels to end up on the Pod. In that case the labels need to be set at .spec.template.spec.metadata.labels (in addition to .metadata.labels). But for a CronJob, that location changes to .spec.jobTemplate.spec.template.metadata.labels. Other resources could be yet more different.

Long story short, the component template needs to participate in where the labels land on the stamped resource. What could be helpful is for Cartographer to compute the set of labels it thinks should be applied to the resource (parent labels +. cartographer labels) and pass those as part of the template context to the stamper. The template can decide how to apply the labels. The stamper can follow up to define/override an "essential" set of labels on .metadata.labels as it sees fit; similar to setting .metadata.ownerReferences, or how labels are applied today.