Context propagation for InstanceManager Status and Delete 13/142713/1
authorFiete Ostkamp <fiete.ostkamp@telekom.de>
Tue, 9 Dec 2025 09:46:09 +0000 (10:46 +0100)
committerFiete Ostkamp <fiete.ostkamp@telekom.de>
Tue, 9 Dec 2025 09:51:07 +0000 (10:51 +0100)
- enhance the Status and Delete methods of the InstanceManager
  interface to require the context paramater
- this is done to validate the approach and see if the handler
  and db related spans are then connected in one trace
- the other methods of the interface will follow once that works [0]

[0] this is also done because the diff of changes would become quite large
    if everything would be changed at once

Issue-ID: MULTICLOUD-1538
Change-Id: Ia1ec590f3326773e0df1e6cefba97711975bbf48
Signed-off-by: Fiete Ostkamp <fiete.ostkamp@telekom.de>
src/k8splugin/api/brokerhandler.go
src/k8splugin/api/instancehandler.go
src/k8splugin/api/instancehandler_test.go
src/k8splugin/go.mod
src/k8splugin/internal/app/instance.go
src/k8splugin/internal/app/instance_test.go
src/k8splugin/internal/app/subscription.go

index ecfde8c..e95c1c8 100644 (file)
@@ -276,7 +276,7 @@ func (b brokerInstanceHandler) deleteHandler(w http.ResponseWriter, r *http.Requ
        vars := mux.Vars(r)
        instanceID := vars["instID"]
 
-       err := b.client.Delete(instanceID)
+       err := b.client.Delete(r.Context(), instanceID)
        if err != nil {
                http.Error(w, err.Error(), http.StatusInternalServerError)
                return
index dd5fd0d..4e67acf 100644 (file)
@@ -211,7 +211,7 @@ func (i instanceHandler) statusHandler(w http.ResponseWriter, r *http.Request) {
        vars := mux.Vars(r)
        id := vars["instID"]
 
-       resp, err := i.client.Status(id, true)
+       resp, err := i.client.Status(r.Context(), id, true)
        if err != nil {
                log.Error("Error getting Status", log.Fields{
                        "error": err,
@@ -314,7 +314,7 @@ func (i instanceHandler) deleteHandler(w http.ResponseWriter, r *http.Request) {
        vars := mux.Vars(r)
        id := vars["instID"]
 
-       err := i.client.Delete(id)
+       err := i.client.Delete(r.Context(), id)
        if err != nil {
                log.Error("Error Deleting Instance", log.Fields{
                        "error": err,
index f06af44..af867e4 100644 (file)
@@ -15,6 +15,7 @@ package api
 
 import (
        "bytes"
+       "context"
        "encoding/json"
        "io"
        "io/ioutil"
@@ -35,9 +36,9 @@ import (
        "k8s.io/apimachinery/pkg/runtime/schema"
 )
 
-//Creating an embedded interface via anonymous variable
-//This allows us to make mockDB satisfy the DatabaseConnection
-//interface even if we are not implementing all the methods in it
+// Creating an embedded interface via anonymous variable
+// This allows us to make mockDB satisfy the DatabaseConnection
+// interface even if we are not implementing all the methods in it
 type mockInstanceClient struct {
        app.InstanceManager
        // Items and err will be used to customize each test
@@ -72,7 +73,7 @@ func (m *mockInstanceClient) Query(id, apiVersion, kind, name, labels string) (a
        return m.statusItem, nil
 }
 
-func (m *mockInstanceClient) Status(id string, checkReady bool) (app.InstanceStatus, error) {
+func (m *mockInstanceClient) Status(ctx context.Context, id string, checkReady bool) (app.InstanceStatus, error) {
        if m.err != nil {
                return app.InstanceStatus{}, m.err
        }
@@ -96,7 +97,7 @@ func (m *mockInstanceClient) Find(rbName string, ver string, profile string, lab
        return m.miniitems, nil
 }
 
-func (m *mockInstanceClient) Delete(id string) error {
+func (m *mockInstanceClient) Delete(ctx context.Context, id string) error {
        return m.err
 }
 
index 99ac69a..81fc5c3 100644 (file)
@@ -13,7 +13,7 @@ require (
        go.etcd.io/etcd/client/v3 v3.5.3
        go.mongodb.org/mongo-driver v1.7.5
        go.opentelemetry.io/contrib/instrumentation/github.com/gorilla/mux/otelmux v0.24.0
-       go.opentelemetry.io/contrib/instrumentation/go.mongodb.org/mongo-driver/mongo/otelmongo v0.24.0 // indirect
+       go.opentelemetry.io/contrib/instrumentation/go.mongodb.org/mongo-driver/mongo/otelmongo v0.24.0
        go.opentelemetry.io/otel v1.2.0
        go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.2.0
        go.opentelemetry.io/otel/sdk v1.2.0
index 9455e23..cd06a43 100644 (file)
@@ -121,11 +121,11 @@ type InstanceManager interface {
        Upgrade(id string, u UpgradeRequest) (InstanceResponse, error)
        Get(id string) (InstanceResponse, error)
        GetFull(id string) (InstanceDbData, error)
-       Status(id string, checkReady bool) (InstanceStatus, error)
+       Status(ctx context.Context, id string, checkReady bool) (InstanceStatus, error)
        Query(id, apiVersion, kind, name, labels string) (InstanceStatus, error)
        List(rbname, rbversion, profilename string) ([]InstanceMiniResponse, error)
        Find(rbName string, ver string, profile string, labelKeys map[string]string) ([]InstanceMiniResponse, error)
-       Delete(id string) error
+       Delete(ctx context.Context, id string) error
        RecoverCreateOrDelete(id string) error
 }
 
@@ -491,7 +491,7 @@ func (v *InstanceClient) Upgrade(id string, u UpgradeRequest) (InstanceResponse,
        if currentInstance.Request.CloudRegion != u.CloudRegion {
                newInstance, err := v.Create(i, "")
                if err == nil {
-                       err = v.Delete(id)
+                       err = v.Delete(context.TODO(), id)
                        if err == nil {
                                newInstanceDb, err := v.GetFull(newInstance.ID)
                                oldKey := InstanceKey{
@@ -510,7 +510,7 @@ func (v *InstanceClient) Upgrade(id string, u UpgradeRequest) (InstanceResponse,
                                }
                                return newInstance, nil
                        } else {
-                               err2 := v.Delete(newInstance.ID)
+                               err2 := v.Delete(context.TODO(), newInstance.ID)
                                if err2 != nil {
                                        log.Printf("Delete of the instance from the new region failed with error %s", err2.Error())
                                }
@@ -813,13 +813,13 @@ func (v *InstanceClient) Query(id, apiVersion, kind, name, labels string) (Insta
 }
 
 // Status returns the status for the instance
-func (v *InstanceClient) Status(id string, checkReady bool) (InstanceStatus, error) {
+func (v *InstanceClient) Status(ctx context.Context, id string, checkReady bool) (InstanceStatus, error) {
        //Read the status from the DB
        key := InstanceKey{
                ID: id,
        }
 
-       value, err := db.DBconn.Read(context.TODO(), v.storeName, key, v.tagInst)
+       value, err := db.DBconn.Read(ctx, v.storeName, key, v.tagInst)
        if err != nil {
                return InstanceStatus{}, pkgerrors.Wrap(err, "Get Instance")
        }
@@ -1071,7 +1071,7 @@ func (v *InstanceClient) Find(rbName string, version string, profile string, lab
 }
 
 // Delete the Instance from database
-func (v *InstanceClient) Delete(id string) error {
+func (v *InstanceClient) Delete(ctx context.Context, id string) error {
        inst, err := v.GetFull(id)
        if err != nil {
                return pkgerrors.Wrap(err, "Error getting Instance")
@@ -1081,7 +1081,7 @@ func (v *InstanceClient) Delete(id string) error {
        }
        if inst.Status == "DELETED" {
                //The instance is deleted when the plugin comes back -> just remove from Db
-               err = db.DBconn.Delete(context.TODO(), v.storeName, key, v.tagInst)
+               err = db.DBconn.Delete(ctx, v.storeName, key, v.tagInst)
                if err != nil {
                        log.Printf("Delete Instance DB Entry for release %s has error.", inst.ReleaseName)
                }
@@ -1100,7 +1100,7 @@ func (v *InstanceClient) Delete(id string) error {
 
        inst.Status = "PRE-DELETE"
        inst.HookProgress = ""
-       err = db.DBconn.Update(context.TODO(), v.storeName, key, v.tagInst, inst)
+       err = db.DBconn.Update(ctx, v.storeName, key, v.tagInst, inst)
        if err != nil {
                log.Printf("Update Instance DB Entry for release %s has error.", inst.ReleaseName)
        }
@@ -1111,7 +1111,7 @@ func (v *InstanceClient) Delete(id string) error {
                if err != nil {
                        log.Printf("  Instance: %s, Error running pre-delete hooks error: %s", id, err)
                        inst.Status = "PRE-DELETE-FAILED"
-                       err2 := db.DBconn.Update(context.TODO(), v.storeName, key, v.tagInst, inst)
+                       err2 := db.DBconn.Update(ctx, v.storeName, key, v.tagInst, inst)
                        if err2 != nil {
                                log.Printf("Update Instance DB Entry for release %s has error.", inst.ReleaseName)
                        }
@@ -1120,7 +1120,7 @@ func (v *InstanceClient) Delete(id string) error {
        }
 
        inst.Status = "DELETING"
-       err = db.DBconn.Update(context.TODO(), v.storeName, key, v.tagInst, inst)
+       err = db.DBconn.Update(ctx, v.storeName, key, v.tagInst, inst)
        if err != nil {
                log.Printf("Update Instance DB Entry for release %s has error.", inst.ReleaseName)
        }
@@ -1149,7 +1149,7 @@ func (v *InstanceClient) Delete(id string) error {
                        log.Printf(err.Error())
                }
 
-               err = db.DBconn.Delete(context.TODO(), v.storeName, key, v.tagInst)
+               err = db.DBconn.Delete(ctx, v.storeName, key, v.tagInst)
                if err != nil {
                        return pkgerrors.Wrap(err, "Delete Instance")
                }
@@ -1158,7 +1158,7 @@ func (v *InstanceClient) Delete(id string) error {
        return nil
 }
 
-//Continue the instantiation
+// Continue the instantiation
 func (v *InstanceClient) RecoverCreateOrDelete(id string) error {
        instance, err := v.GetFull(id)
        if err != nil {
index 86955fa..611c31e 100644 (file)
@@ -15,6 +15,7 @@ limitations under the License.
 package app
 
 import (
+       "context"
        "encoding/base64"
        "io/ioutil"
        "log"
@@ -747,7 +748,7 @@ func TestInstanceDelete(t *testing.T) {
 
                ic := NewInstanceClient()
                id := "HaKpys8e"
-               err := ic.Delete(id)
+               err := ic.Delete(context.TODO(), id)
                if err != nil {
                        t.Fatalf("TestInstanceDelete returned an error (%s)", err)
                }
@@ -790,14 +791,14 @@ func TestInstanceDelete(t *testing.T) {
 
                ic := NewInstanceClient()
                id := "non-existing"
-               err := ic.Delete(id)
+               err := ic.Delete(context.TODO(), id)
                if err == nil {
                        t.Fatal("Expected error, got pass", err)
                }
        })
 }
 
-//TODO: add a test when pre-hook is failed (if possible)
+// TODO: add a test when pre-hook is failed (if possible)
 func TestInstanceWithHookCreate(t *testing.T) {
        err := LoadMockPlugins(utils.LoadedPlugins)
        if err != nil {
index ff2cec4..e353ca8 100644 (file)
@@ -652,7 +652,7 @@ func runNotifyThread(instanceId, subName string) {
                        } else {
                                timeInSeconds = 5
                        }
-                       newStatus, err := v.Status(instanceId, false)
+                       newStatus, err := v.Status(context.Background(), instanceId, false)
                        if err != nil {
                                log.Error("Error getting current status", log.Fields{
                                        "error":    err.Error(),