Repository: fission/fission (language: go)

Issue:
Missing OwnerReference for dynamically created ressoruces like poolmgr
<!-- Please answer these questions before submitting your issue. Thanks! -->

<!-- Documentation URL: https://fission.io/docs -->
<!-- Troubleshooting guide: https://fission.io/docs/trouble-shooting/ -->

**Fission/Kubernetes version**

<!-- If you tested with other services, for example Istio, please also provide the version of service as well. -->

<pre>
$ fission version
client:
  fission/core:
    BuildDate: "2024-01-14T15:43:35Z"
    GitCommit: 7e8d5dd7
    Version: v1.20.1
server:
  fission/core:
    BuildDate: "2024-05-27T10:51:06Z"
    GitCommit: 0cfe08df
    Version: v1.20.2
$ kubectl version
Client Version: v1.29.1
Kustomize Version: v5.0.4-0.20230601165947-6ce0bf390ce3
Server Version: v1.28.9-eks-036c24b
</pre>

**Kubernetes platform (e.g. Google Kubernetes Engine)**

AWS EKS

**Describe the bug**

Executer doesn't set `OwnerReference` for created ressources like `PoolMgr` (created kind `Deploy`)
As a poolmgr is created based on a env, it would be nice that the kind `Deploy` references the kind `environment` as owner.

Problem is that we use ArgoCD with HELM also for deployment of our fission functions, as the deployment of the pool manager is not child of the environment it gets marked as prune and deleted. You can set a flag to avoid the deletion, but it's still marked as prune.

**To Reproduce**

Create helm charts and add kind `environment` to the templates like that:

```yaml
apiVersion: fission.io/v1
kind: Environment
metadata:
  name: nodejs
  namespace: fission
  annotations:
    argocd.argoproj.io/compare-options: IgnoreExtraneous
  labels:
    app.kubernetes.io/instance: fissionactions
spec:
  builder:
    container:
      name: ""
      resources: {}
  imagepullsecret: ""
  keeparchive: false
  poolsize: 3
  resources: {}
  runtime:
    container:
      name: ""
      resources: {}
    image: fission/node-env
  version: 1
  ```

**Expected result**
`OwnerReference` in created ressources by executer refrencing environment or function (based on execution type)

**Actual result**
No `OwnerReference` in dynamically created ressources.

**Screenshots/Dump file**
![image](https://github.com/fission/fission/assets/1439039/a3b5596f-3041-4fe8-8ea8-222b86403546)




Discussion / hints:
I'm not a Go Coder, but I think it should be added here:

https://github.com/fission/fission/blob/9b978cf2fd88f6fab63db79d3d35e25efc9bce70/pkg/executor/executortype/poolmgr/gp_deployment.go#L61

If that helps anyone who is able to code in context of this project 🙏

Fix patch:
diff --git a/pkg/buildermgr/envwatcher.go b/pkg/buildermgr/envwatcher.go
index 89dcf1f061..d50c6f7dd8 100644
--- a/pkg/buildermgr/envwatcher.go
+++ b/pkg/buildermgr/envwatcher.go
@@ -28,6 +28,7 @@ import (
 	apiv1 "k8s.io/api/core/v1"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/labels"
+	"k8s.io/apimachinery/pkg/runtime/schema"
 	"k8s.io/apimachinery/pkg/types"
 	"k8s.io/apimachinery/pkg/util/intstr"
 	"k8s.io/client-go/kubernetes"
@@ -329,6 +330,13 @@ func (envw *environmentWatcher) createBuilderService(ctx context.Context, env *f
 			Namespace: ns,
 			Name:      name,
 			Labels:    sel,
+			OwnerReferences: []metav1.OwnerReference{
+				*metav1.NewControllerRef(env, schema.GroupVersionKind{
+					Group:   "fission.io",
+					Version: "v1",
+					Kind:    "Environment",
+				}),
+			},
 		},
 		Spec: apiv1.ServiceSpec{
 			Selector: sel,
@@ -440,6 +448,13 @@ func (envw *environmentWatcher) createBuilderDeployment(ctx context.Context, env
 			Namespace: ns,
 			Name:      name,
 			Labels:    sel,
+			OwnerReferences: []metav1.OwnerReference{
+				*metav1.NewControllerRef(env, schema.GroupVersionKind{
+					Group:   "fission.io",
+					Version: "v1",
+					Kind:    "Environment",
+				}),
+			},
 		},
 		Spec: appsv1.DeploymentSpec{
 			Replicas: &replicas,
diff --git a/pkg/executor/executortype/container/containermgr.go b/pkg/executor/executortype/container/containermgr.go
index 391c0b1bff..7bcf205c37 100644
--- a/pkg/executor/executortype/container/containermgr.go
+++ b/pkg/executor/executortype/container/containermgr.go
@@ -421,7 +421,7 @@ func (caaf *Container) fnCreate(ctx context.Context, fn *fv1.Function) (*fscache
 		return nil, fmt.Errorf("error creating deployment %s: %w", objName, err)
 	}
 
-	hpa, err := caaf.hpaops.CreateOrGetHpa(ctx, objName, &fn.Spec.InvokeStrategy.ExecutionStrategy, depl, deployLabels, deployAnnotations)
+	hpa, err := caaf.hpaops.CreateOrGetHpa(ctx, fn, objName, &fn.Spec.InvokeStrategy.ExecutionStrategy, depl, deployLabels, deployAnnotations)
 	if err != nil {
 		caaf.logger.Error("error creating HPA", zap.Error(err), zap.String("hpa", objName))
 		go cleanupFunc(ns, objName)
diff --git a/pkg/executor/executortype/container/deployment.go b/pkg/executor/executortype/container/deployment.go
index 6afaa6ba5c..61b51965c2 100644
--- a/pkg/executor/executortype/container/deployment.go
+++ b/pkg/executor/executortype/container/deployment.go
@@ -27,6 +27,7 @@ import (
 	apiv1 "k8s.io/api/core/v1"
 	k8s_err "k8s.io/apimachinery/pkg/api/errors"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	"k8s.io/apimachinery/pkg/runtime/schema"
 	"k8s.io/apimachinery/pkg/util/intstr"
 
 	fv1 "github.com/fission/fission/pkg/apis/core/v1"
@@ -86,6 +87,7 @@ func (cn *Container) createOrGetDeployment(ctx context.Context, fn *fv1.Function
 	if existingDepl.Annotations[fv1.EXECUTOR_INSTANCEID_LABEL] != cn.instanceID {
 		existingDepl.Annotations = deployment.Annotations
 		existingDepl.Labels = deployment.Labels
+		existingDepl.OwnerReferences = deployment.OwnerReferences
 		existingDepl.Spec.Template.Spec.Containers = deployment.Spec.Template.Spec.Containers
 		existingDepl.Spec.Template.Spec.ServiceAccountName = deployment.Spec.Template.Spec.ServiceAccountName
 		existingDepl.Spec.Template.Spec.TerminationGracePeriodSeconds = deployment.Spec.Template.Spec.TerminationGracePeriodSeconds
@@ -268,6 +270,13 @@ func (cn *Container) getDeploymentSpec(ctx context.Context, fn *fv1.Function, ta
 			Name:        deployName,
 			Labels:      deployLabels,
 			Annotations: deployAnnotations,
+			OwnerReferences: []metav1.OwnerReference{
+				*metav1.NewControllerRef(fn, schema.GroupVersionKind{
+					Group:   "fission.io",
+					Version: "v1",
+					Kind:    "Function",
+				}),
+			},
 		},
 		Spec: appsv1.DeploymentSpec{
 			Replicas: &replicas,
diff --git a/pkg/executor/executortype/container/svc.go b/pkg/executor/executortype/container/svc.go
index c2b8622a41..7f7aaab0d1 100644
--- a/pkg/executor/executortype/container/svc.go
+++ b/pkg/executor/executortype/container/svc.go
@@ -24,6 +24,7 @@ import (
 	apiv1 "k8s.io/api/core/v1"
 	k8s_err "k8s.io/apimachinery/pkg/api/errors"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	"k8s.io/apimachinery/pkg/runtime/schema"
 	"k8s.io/apimachinery/pkg/util/intstr"
 
 	fv1 "github.com/fission/fission/pkg/apis/core/v1"
@@ -54,6 +55,13 @@ func (cn *Container) createOrGetSvc(ctx context.Context, fn *fv1.Function, deplo
 			Name:        svcName,
 			Labels:      deployLabels,
 			Annotations: deployAnnotations,
+			OwnerReferences: []metav1.OwnerReference{
+				*metav1.NewControllerRef(fn, schema.GroupVersionKind{
+					Group:   "fission.io",
+					Version: "v1",
+					Kind:    "Function",
+				}),
+			},
 		},
 		Spec: apiv1.ServiceSpec{
 			Ports: []apiv1.ServicePort{
@@ -74,6 +82,7 @@ func (cn *Container) createOrGetSvc(ctx context.Context, fn *fv1.Function, deplo
 		if existingSvc.Annotations[fv1.EXECUTOR_INSTANCEID_LABEL] != cn.instanceID {
 			existingSvc.Annotations = service.Annotations
 			existingSvc.Labels = service.Labels
+			existingSvc.OwnerReferences = service.OwnerReferences
 			existingSvc.Spec.Ports = service.Spec.Ports
 			existingSvc.Spec.Selector = service.Spec.Selector
 			existingSvc.Spec.Type = service.Spec.Type
diff --git a/pkg/executor/executortype/newdeploy/newdeploy.go b/pkg/executor/executortype/newdeploy/newdeploy.go
index 18d8e340dd..68e35d62e3 100644
--- a/pkg/executor/executortype/newdeploy/newdeploy.go
+++ b/pkg/executor/executortype/newdeploy/newdeploy.go
@@ -29,6 +29,7 @@ import (
 	k8s_err "k8s.io/apimachinery/pkg/api/errors"
 	"k8s.io/apimachinery/pkg/api/resource"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	"k8s.io/apimachinery/pkg/runtime/schema"
 	"k8s.io/apimachinery/pkg/util/intstr"
 	"k8s.io/client-go/kubernetes"
 
@@ -61,6 +62,7 @@ func (deploy *NewDeploy) createOrGetDeployment(ctx context.Context, fn *fv1.Func
 		if existingDepl.Annotations[fv1.EXECUTOR_INSTANCEID_LABEL] != deploy.instanceID {
 			existingDepl.Annotations = deployment.Annotations
 			existingDepl.Labels = deployment.Labels
+			existingDepl.OwnerReferences = deployment.OwnerReferences
 			existingDepl.Spec.Template.Spec.Containers = deployment.Spec.Template.Spec.Containers
 			existingDepl.Spec.Template.Spec.ServiceAccountName = deployment.Spec.Template.Spec.ServiceAccountName
 			existingDepl.Spec.Template.Spec.TerminationGracePeriodSeconds = deployment.Spec.Template.Spec.TerminationGracePeriodSeconds
@@ -249,6 +251,13 @@ func (deploy *NewDeploy) getDeploymentSpec(ctx context.Context, fn *fv1.Function
 			Name:        deployName,
 			Labels:      deployLabels,
 			Annotations: deployAnnotations,
+			OwnerReferences: []metav1.OwnerReference{
+				*metav1.NewControllerRef(fn, schema.GroupVersionKind{
+					Group:   "fission.io",
+					Version: "v1",
+					Kind:    "Function",
+				}),
+			},
 		},
 		Spec: appsv1.DeploymentSpec{
 			Replicas: &replicas,
@@ -323,13 +332,20 @@ func (deploy *NewDeploy) getResources(env *fv1.Environment, fn *fv1.Function) ap
 	return resources
 }
 
-func (deploy *NewDeploy) createOrGetSvc(ctx context.Context, deployLabels map[string]string, deployAnnotations map[string]string, svcName string, svcNamespace string) (*apiv1.Service, error) {
+func (deploy *NewDeploy) createOrGetSvc(ctx context.Context, fn *fv1.Function, deployLabels map[string]string, deployAnnotations map[string]string, svcName string, svcNamespace string) (*apiv1.Service, error) {
 	logger := otelUtils.LoggerWithTraceID(ctx, deploy.logger)
 	service := &apiv1.Service{
 		ObjectMeta: metav1.ObjectMeta{
 			Name:        svcName,
 			Labels:      deployLabels,
 			Annotations: deployAnnotations,
+			OwnerReferences: []metav1.OwnerReference{
+				*metav1.NewControllerRef(fn, schema.GroupVersionKind{
+					Group:   "fission.io",
+					Version: "v1",
+					Kind:    "Function",
+				}),
+			},
 		},
 		Spec: apiv1.ServiceSpec{
 			Ports: []apiv1.ServicePort{
@@ -351,6 +367,7 @@ func (deploy *NewDeploy) createOrGetSvc(ctx context.Context, deployLabels map[st
 		if existingSvc.Annotations[fv1.EXECUTOR_INSTANCEID_LABEL] != deploy.instanceID {
 			existingSvc.Annotations = service.Annotations
 			existingSvc.Labels = service.Labels
+			existingSvc.OwnerReferences = service.OwnerReferences
 			existingSvc.Spec.Ports = service.Spec.Ports
 			existingSvc.Spec.Selector = service.Spec.Selector
 			existingSvc.Spec.Type = service.Spec.Type
diff --git a/pkg/executor/executortype/newdeploy/newdeploymgr.go b/pkg/executor/executortype/newdeploy/newdeploymgr.go
index ac98354651..c81b9de296 100644
--- a/pkg/executor/executortype/newdeploy/newdeploymgr.go
+++ b/pkg/executor/executortype/newdeploy/newdeploymgr.go
@@ -451,7 +451,7 @@ func (deploy *NewDeploy) fnCreate(ctx context.Context, fn *fv1.Function) (*fscac
 	// Since newdeploy waits for pods of deployment to be ready,
 	// change the order of kubeObject creation (create service first,
 	// then deployment) to take advantage of waiting time.
-	svc, err := deploy.createOrGetSvc(ctx, deployLabels, deployAnnotations, objName, ns)
+	svc, err := deploy.createOrGetSvc(ctx, fn, deployLabels, deployAnnotations, objName, ns)
 	if err != nil {
 		deploy.logger.Error("error creating service", zap.Error(err), zap.String("service", objName))
 		go cleanupFunc(context.Background(), ns, objName)
@@ -466,7 +466,7 @@ func (deploy *NewDeploy) fnCreate(ctx context.Context, fn *fv1.Function) (*fscac
 		return nil, fmt.Errorf("error creating deployment %s: %w", objName, err)
 	}
 
-	hpa, err := deploy.hpaops.CreateOrGetHpa(ctx, objName, &fn.Spec.InvokeStrategy.ExecutionStrategy, depl, deployLabels, deployAnnotations)
+	hpa, err := deploy.hpaops.CreateOrGetHpa(ctx, fn, objName, &fn.Spec.InvokeStrategy.ExecutionStrategy, depl, deployLabels, deployAnnotations)
 	if err != nil {
 		deploy.logger.Error("error creating HPA", zap.Error(err), zap.String("hpa", objName))
 		go cleanupFunc(context.Background(), ns, objName)
diff --git a/pkg/executor/executortype/poolmgr/gp_deployment.go b/pkg/executor/executortype/poolmgr/gp_deployment.go
index 4d2f415576..0e7b598a71 100644
--- a/pkg/executor/executortype/poolmgr/gp_deployment.go
+++ b/pkg/executor/executortype/poolmgr/gp_deployment.go
@@ -26,6 +26,7 @@ import (
 	apiv1 "k8s.io/api/core/v1"
 	k8sErrs "k8s.io/apimachinery/pkg/api/errors"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	"k8s.io/apimachinery/pkg/runtime/schema"
 
 	fv1 "github.com/fission/fission/pkg/apis/core/v1"
 	"github.com/fission/fission/pkg/executor/util"
@@ -62,6 +63,13 @@ func (gp *GenericPool) genDeploymentMeta(env *fv1.Environment) metav1.ObjectMeta
 		Name:        getPoolName(env),
 		Labels:      deployLabels,
 		Annotations: deployAnnotations,
+		OwnerReferences: []metav1.OwnerReference{
+			*metav1.NewControllerRef(env, schema.GroupVersionKind{
+				Group:   "fission.io",
+				Version: "v1",
+				Kind:    "Environment",
+			}),
+		},
 	}
 }
 
diff --git a/pkg/executor/util/hpa/hpa.go b/pkg/executor/util/hpa/hpa.go
index aa770a4f57..1ab24d3dba 100644
--- a/pkg/executor/util/hpa/hpa.go
+++ b/pkg/executor/util/hpa/hpa.go
@@ -25,6 +25,7 @@ import (
 	corev1 "k8s.io/api/core/v1"
 	k8s_err "k8s.io/apimachinery/pkg/api/errors"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	"k8s.io/apimachinery/pkg/runtime/schema"
 	"k8s.io/client-go/kubernetes"
 
 	fv1 "github.com/fission/fission/pkg/apis/core/v1"
@@ -72,7 +73,7 @@ func getScaleTargetRef(deployment *appsv1.Deployment) asv2.CrossVersionObjectRef
 	}
 }
 
-func (hpaops *HpaOperations) CreateOrGetHpa(ctx context.Context, hpaName string, execStrategy *fv1.ExecutionStrategy,
+func (hpaops *HpaOperations) CreateOrGetHpa(ctx context.Context, fn *fv1.Function, hpaName string, execStrategy *fv1.ExecutionStrategy,
 	depl *appsv1.Deployment, deployLabels map[string]string, deployAnnotations map[string]string) (*asv2.HorizontalPodAutoscaler, error) {
 
 	if depl == nil {
@@ -103,6 +104,13 @@ func (hpaops *HpaOperations) CreateOrGetHpa(ctx context.Context, hpaName string,
 			Name:        hpaName,
 			Labels:      deployLabels,
 			Annotations: deployAnnotations,
+			OwnerReferences: []metav1.OwnerReference{
+				*metav1.NewControllerRef(fn, schema.GroupVersionKind{
+					Group:   "fission.io",
+					Version: "v1",
+					Kind:    "Function",
+				}),
+			},
 		},
 		Spec: asv2.HorizontalPodAutoscalerSpec{
 			ScaleTargetRef: getScaleTargetRef(depl),
@@ -119,6 +127,7 @@ func (hpaops *HpaOperations) CreateOrGetHpa(ctx context.Context, hpaName string,
 		if existingHpa.Annotations[fv1.EXECUTOR_INSTANCEID_LABEL] != hpaops.instanceID {
 			existingHpa.Annotations = hpa.Annotations
 			existingHpa.Labels = hpa.Labels
+			existingHpa.OwnerReferences = hpa.OwnerReferences
 			existingHpa.Spec = hpa.Spec
 			existingHpa, err = hpaops.kubernetesClient.AutoscalingV2().HorizontalPodAutoscalers(depl.ObjectMeta.Namespace).Update(ctx, existingHpa, metav1.UpdateOptions{})
 			if err != nil {


Test patch:
diff --git a/pkg/executor/util/hpa/hpa_test.go b/pkg/executor/util/hpa/hpa_test.go
index 3010605604..a4b1715578 100644
--- a/pkg/executor/util/hpa/hpa_test.go
+++ b/pkg/executor/util/hpa/hpa_test.go
@@ -25,6 +25,7 @@ import (
 	asv2 "k8s.io/api/autoscaling/v2"
 	corev1 "k8s.io/api/core/v1"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	"k8s.io/apimachinery/pkg/util/uuid"
 	"k8s.io/client-go/kubernetes/fake"
 
 	fv1 "github.com/fission/fission/pkg/apis/core/v1"
@@ -67,7 +68,14 @@ func TestHpaOps(t *testing.T) {
 		"test-annotation": "test-annotation-value",
 	}
 	// Test CreateHPA
-	hpa, err := hpaops.CreateOrGetHpa(ctx, "test-hpa",
+	hpa, err := hpaops.CreateOrGetHpa(ctx,
+		&fv1.Function{
+			ObjectMeta: metav1.ObjectMeta{
+				Name: "test-fn",
+				UID:  uuid.NewUUID(),
+			},
+		},
+		"test-hpa",
 		&fv1.ExecutionStrategy{
 			ExecutorType:          fv1.ExecutorTypeNewdeploy,
 			MinScale:              1,