databus23 / helm-diff

A helm plugin that shows a diff explaining what a helm upgrade would change
Apache License 2.0
2.69k stars 279 forks source link

diff doesn't work for imported resources? #639

Open AndriiOmelianenko opened 3 months ago

AndriiOmelianenko commented 3 months ago

hello, I'm trying to create a helm chart for existing resources in the cluster with the least breaking changes as possible. So let's say I have a single resource to import (for simplicity):

$ kubectl get sa sa-test -o yaml
apiVersion: v1
imagePullSecrets:
- name: image-pull-secret
kind: ServiceAccount
metadata:
  name: sa-test
  namespace: test

My steps:

  1. install an "empty" chart, with no resources (this is to trick helm diff upgrade to work)
  2. import resources with labels/annotations
    kubectl annotate $KIND $NAME  meta.helm.sh/release-name=$RELEASE_NAME --overwrite
    kubectl annotate $KIND $NAME  meta.helm.sh/release-namespace=$NAMESPACE --overwrite
    kubectl label $KIND $NAME  app.kubernetes.io/managed-by=Helm --overwrite
  3. run helm diff upgrade and see the differences, to tune my chart/values.

But in my case, I get this:

$ helm diff upgrade test ./microservice -f test.values.yaml --namespace test
test, sa-test, ServiceAccount (v1) has been added:
-
+ # Source: microservice/templates/serviceaccount.yaml
+ apiVersion: v1
+ kind: ServiceAccount
+ metadata:
+   name: sa-test
+   labels:
+     helm.sh/chart: microservice-0.1.0
+     app.kubernetes.io/name: microservice
+     app.kubernetes.io/instance: test
+     app.kubernetes.io/version: "0.1.0"
+     app.kubernetes.io/managed-by: Helm
+ automountServiceAccountToken: true

What am I doing wrong?

AndriiOmelianenko commented 3 months ago

regarding step #1 , without it, I get this:

$ helm diff upgrade test ./microservice -f test.values.yaml --namespace test --install
********************

    Release was not present in Helm.  Diff will show entire contents as new.

********************
test, sa-test, ServiceAccount (v1) has been added:
-
+ # Source: microservice/templates/serviceaccount.yaml
+ apiVersion: v1
+ kind: ServiceAccount
+ metadata:
+   name: sa-test
+   labels:
+     helm.sh/chart: microservice-0.1.0
+     app.kubernetes.io/name: microservice
+     app.kubernetes.io/instance: test
+     app.kubernetes.io/version: "0.1.0"
+     app.kubernetes.io/managed-by: Helm
+ # automountServiceAccountToken: true
AndriiOmelianenko commented 3 months ago

here is even simpler flow:

$ kubectl create sa sa-test1
serviceaccount/sa-test1 created

$ kubectl annotate sa sa-test1 meta.helm.sh/release-name=test
kubectl annotate sa sa-test1 meta.helm.sh/release-namespace=test-development
kubectl label sa sa-test1 app.kubernetes.io/managed-by=Helm
serviceaccount/sa-test1 annotated
serviceaccount/sa-test1 annotated
serviceaccount/sa-test1 labeled

$ kubectl get sa sa-test1 -o yaml
apiVersion: v1
imagePullSecrets:
- name: image-pull-secret
kind: ServiceAccount
metadata:
  annotations:
    meta.helm.sh/release-name: test
    meta.helm.sh/release-namespace: test-development
  creationTimestamp: "2024-07-04T16:31:53Z"
  labels:
    app.kubernetes.io/managed-by: Helm
  name: sa-test1
  namespace: test-development
  resourceVersion: "6009049282"
  uid: 273f63a5-d649-4b35-b4f0-15fce043e6e4

$ helm diff upgrade --install test ./microservice -f dev-test.values.yaml --namespace test-development
********************

    Release was not present in Helm.  Diff will show entire contents as new.

********************
test-development, sa-test1, ServiceAccount (v1) has been added:
-
+ # Source: microservice/templates/serviceaccount.yaml
+ apiVersion: v1
+ kind: ServiceAccount
+ metadata:
+   name: sa-test1
+   labels:
+     helm.sh/chart: microservice-0.1.0
+     app.kubernetes.io/name: microservice
+     app.kubernetes.io/instance: test
+     app.kubernetes.io/version: "0.1.0"
+     app.kubernetes.io/managed-by: Helm

what am I missing?

yxxhero commented 3 months ago

@AndriiOmelianenko what's your expected?

AndriiOmelianenko commented 3 months ago

hi @yxxhero I was able to figure out a workaround using helm-diff + another helm plugin called adopt

if I run adopt first (which in my understanding creates a release + puts labels and annotations over existing resource), and then follow by diff - the diff is properly displayed:

$ helm diff upgrade --install test ./microservice -f dev-test.values.yaml --namespace test-development
test-development, sa-test1, ServiceAccount (v1) has changed:
- # Source: templates/serviceaccounts-0.yaml
+ # Source: microservice/templates/serviceaccount.yaml
  apiVersion: v1
- imagePullSecrets:
- - name: image-pull-secret
  kind: ServiceAccount
  metadata:
+   name: sa-test1
    labels:
+     helm.sh/chart: microservice-0.1.0
+     app.kubernetes.io/name: microservice
+     app.kubernetes.io/instance: test
+     app.kubernetes.io/version: "0.1.0"
      app.kubernetes.io/managed-by: Helm
-   name: sa-test1
-   namespace: test-development
+ # automountServiceAccountToken: true

I wonder why the same doesn't work if I just label and annotate resources myself

yxxhero commented 3 months ago

helm-diff is a plugin for Helm that is used to compare differences between two versions of Helm charts. By default, helm-diff performs its analysis by comparing the local Chart version with the version in the remote repository, and it does not interact directly with the resources deployed in the Kubernetes cluster. When using helm-diff, its main functions are:

  1. To compare the configurations and templates of two chart versions to identify the differences between them.
  2. To display which Kubernetes resources would change if an upgrade to the new version were to be performed. However, helm-diff does not directly interact with the Kubernetes cluster; it does not read the actual state of the resources running in the cluster. It simply analyzes the chart information saved in the Helm Release Secret and the current chart directory to show the differences. If you want to compare the actual resources running in the Kubernetes cluster with the Helm templates, you might need to use other tools or methods, such as manually comparing with kubectl command-line tool, or using other specialized tools for cluster resource versioning and reconciliation. Understanding the capabilities and limitations of each tool when dealing with Kubernetes cluster resources and Helm charts is crucial for effectively managing and deploying your applications.