-
Notifications
You must be signed in to change notification settings - Fork 163
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Include chart annotations as event metadata #514
base: main
Are you sure you want to change the base?
Include chart annotations as event metadata #514
Conversation
3e11ad1
to
d82ad5e
Compare
Extend the registered event after the Helm reconciliation to include the chart annotations (if any) in the existing metadata field of the event body. `event` function defines now a new `metadata *chart.Metadata` parameter with this metadata. The fields defined in the chart annotations are merged to the already defined `meta` map in the `event` function, along with the already existing `revision` field. These fields are merged at the root level; so the `meta` map will have n + 1 fields, where n is the number of annotations the chart has defined. With the current notifications, is hard to be aware of what exactly was deployed, as just the Helm chart revision is included in the payload. If I wanted to know what specific change (or changeset) has been rolled out, it wouldn't be possible with the current setup. A workaround could be to abuse the chart `version` semver, but of course with several drawbacks, like needing to keep a 1-1 relationship between the char and app versions, having to come up with some specific encoding, having it to decode on the other end if a generic webhook receiver has been configured, and just probably being a bad practice. It's probably reasonable to be able to plug some arbitrary data into the event delivered by Flux, specially considering that the Helm charts already provide annotations for this. By including the chart annotations as part of the metadata, users can enrich their notifications as they wish by including the data they consider necessary for their own use cases. Doing it with the chart annotations, the user experience doesn't change, as the chart needs to be updated for making a release anyways, and the data can be set at that point; or just left it empty otherwise if it's not needed. The annotations must be in string:string format according to the Helm specification itself, so no complex nested structures are allowed. Prior to these changes, if nested annotations are specified in the chart, the Helm upgrade already fails with no registered event, so there's no check done regarding this matter. Signed-off-by: Julen Pardo <[email protected]>
d82ad5e
to
aec55b2
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @julenpardo for this contribution.
I think we need to prefix all keys with helm
to avoid collisions in notification-controller. This PR will have to wait till end of August as Hidde is in vacation and he will probably want this to be merged into the dev branch.
@stefanprodan thanks a lot for such a quick response! Should we then wait for Hidde to discuss how to prefix the keys? |
Thank you for your contribution @julenpardo. I am interested in adding this to the current refactoring work which lives in |
Thanks a lot @hiddeco for checking it and the heads up! |
Hello, this MR has been sitting here for a long time. This feature would be great, as we have same use case as @julenpardo. |
Hi @julenpardo thanks for putting this together, it's gonna be very useful! A question: Where exactly do these chart annotations come from? Do they come from the I would really appreciate a way in which I could specify metadata in my Is your intention to also cover something like that or very similar? Could you please provide an example on where would I put my annotations/metadata exactly? Thanks one more time!! |
This PR extends the Helm release controller to include Chart
annotations
in the registered event as metadata, along with the Chart revision already included.This is my first Go code, so feel free to give opinionated feedback :)
Rationale
Use case
With the current notifications, is hard to be aware of what exactly was deployed, as just the Helm chart revision is included in the payload. If I wanted to know what specific change (or changeset) has been rolled out, it wouldn't be possible with the current setup. A workaround could be to abuse the chart
version
semver, but of course with several drawbacks, like needing to keep a 1-1 relationship between the char and app versions, having to come up with some specific encoding, having it to decode on the other end if a generic webhook receiver has been configured, and just probably being a bad practice.It's probably reasonable to be able to plug some arbitrary data into the event delivered by Flux, specially considering that the Helm charts already provide annotations for this. I had a look into the open issues and it's something that was mentioned several times (#412 and #256 just to mention a couple of examples).
By including the chart annotations as part of the metadata, users can enrich their notifications as they wish by including the data they consider necessary for their own use cases.
Doing it with the chart annotations, the user experience doesn't change, as the chart needs to be updated for making a release anyways, and the data can be set at that point; or just left it empty otherwise if it's not needed, as they're optional.
Changes
The calls to the
event
function fromreconcile
are done passingnil
as the chart is not loaded yet at that point.The annotations are merged in the root of the
event
map instead of having a nested structure, for simplicity, e.g. the payload looks like:Instead of
It's assumed that the annotations is a plain string:string map, with no nested structures, according to the Helm specification. Setting annotations in a different format will make the Helm release fail itself (
ArtifactFailed
error), with no registered event by the Helm release controller, so there's no point on checking for these.Summary of changes
metadata *chart.Metadata
parameter toevent
function incontrollers/helmrelease_controller.go
reconcile
function, modify the calls toevent
in to pass anil
value for this new paramreconcileRelease
function, modify the calls toevent
in passingchart.Metadata
event
function, initialize emptymeta
map at the beginningevent
function, iterate through the newly addedchart.Metadata
parameter if not null, and merge the data to themeta
map that gets send as part of the eventTesting
Manual testing
Below are the steps I followed for testing it with a local k8s cluster. The infrastructure and source code repositores I've used are private, but they're just the minimal for configuring helm releases and alerts, and a simple API server to make test releases for, respectively. I can provide more details if needed.
The source code contains an endpoint for which the HelmRelease notifications are configured for, which logs the request payload, so that there's no need for another service for the notifications in order to check the payload.
The following versions of the tools were used:
Setting the local cluster up
Start minikube:
(Once the cluster is up, the source code docker image needs to be built loaded to minikube).
On the infra repository, bootstrap Flux:
Running the Helm controller
Scale the already running Helm controller down:
Forward the source and notification controllers:
Run the controller specifying the event address. Apparently the controller doesn't look for an environment variable for it unlike with the source controller, so I had to figure out how to do it, and I manually tweaked the Makefile the following way for testing purposes (I'm not sure of what the best workflow for this is):
Finally, run the controller:
export SOURCE_CONTROLLER_LOCALHOST=localhost:8081 make run
Test: watch logs for Helm releases
Watch the logs of the
fastapi-example
pod:kubectl logs -n fastapi -f $(kubectl get pods -n fastapi -o=name)
In the
fastapi-example
project directory, define a new Helm release by bumpingversion
incharts/Chart.yaml
. Also add some annotations, e.g.:Commit, push and wait for the Helm controller to make the upgrade. Once done, the notification endpoint should have been hit, and the
fastapi-example
log output should show the payload including the annotations withinmetadata
:(The
Helm upgrade has started
has been omitted for convenience, but the same metadata is included in the payload).Make another release this time without any annotations, to check that everything is still okay without them, and check the logs:
Unit and regression testing
I didn't add any automated tests mainly because currently there's no coverage for the flow for
reconcileRelease
, so I'm not sure of what would the best approach be to tackle this, and not end up being a pull request of adding tests rather than a feature. But suggestions are welcome.