package handler import ( "context" "database/sql" "encoding/json" "fmt" "io" "net/http" "strconv" "time" "vctp/db/queries" models "vctp/server/models" ) func (h *Handler) VmMoveEvent(w http.ResponseWriter, r *http.Request) { params := queries.CreateUpdateParams{} var unixTimestamp int64 ctx := context.Background() reqBody, err := io.ReadAll(r.Body) if err != nil { h.Logger.Error("Invalid data received", "error", err) fmt.Fprintf(w, "Invalid data received") w.WriteHeader(http.StatusInternalServerError) return } else { //h.Logger.Debug("received input data", "length", len(reqBody)) } // Decode the JSON body into CloudEventReceived struct var event models.CloudEventReceived if err := json.Unmarshal(reqBody, &event); err != nil { h.Logger.Error("unable to unmarshal json", "error", err) prettyPrint(reqBody) w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusInternalServerError) json.NewEncoder(w).Encode(map[string]string{ "status": "ERROR", "message": fmt.Sprintf("Unable to unmarshal JSON in request body: '%s'", err), }) return } else { h.Logger.Debug("successfully decoded JSON") //prettyPrint(event) } if event.CloudEvent.Data.OldParent == nil || event.CloudEvent.Data.NewParent == nil { h.Logger.Error("No resource pool data found in cloud event") prettyPrint(event) w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusBadRequest) json.NewEncoder(w).Encode(map[string]string{ "status": "ERROR", "message": fmt.Sprintf("CloudEvent missing resource pool data"), }) return } h.Logger.Debug("Checking inventory table for VM record") invParams := queries.GetInventoryVmIdParams{ VmId: sql.NullString{String: event.CloudEvent.Data.VM.VM.Value, Valid: event.CloudEvent.Data.VM.VM.Value != ""}, DatacenterName: sql.NullString{String: event.CloudEvent.Data.Datacenter.Name, Valid: event.CloudEvent.Data.Datacenter.Name != ""}, } invResult, err := h.Database.Queries().GetInventoryVmId(ctx, invParams) if err != nil { h.Logger.Error("unable to find existing inventory record for this VM", "error", err) // TODO - how to handle? } else { params.InventoryId = sql.NullInt64{Int64: invResult.Iid, Valid: invResult.Iid > 0} } // Parse the datetime string to a time.Time object eventTime, err := time.Parse(time.RFC3339, event.CloudEvent.Data.CreatedTime) if err != nil { h.Logger.Warn("unable to convert cloud event time to timestamp", "error", err) unixTimestamp = time.Now().Unix() } else { // Convert to Unix timestamp unixTimestamp = eventTime.Unix() } // populate other parameters for the Update database record params.NewResourcePool = sql.NullString{String: event.CloudEvent.Data.NewParent.Name, Valid: event.CloudEvent.Data.NewParent.Name != ""} params.UpdateType = "move" params.EventId = sql.NullString{String: event.CloudEvent.ID, Valid: event.CloudEvent.ID != ""} params.EventKey = sql.NullString{String: strconv.Itoa(event.CloudEvent.Data.Key), Valid: event.CloudEvent.Data.Key > 0} params.UpdateTime = sql.NullInt64{Int64: unixTimestamp, Valid: unixTimestamp > 0} params.UserName = sql.NullString{String: event.CloudEvent.Data.UserName, Valid: event.CloudEvent.Data.UserName != ""} // Create the Update database record result, err := h.Database.Queries().CreateUpdate(ctx, params) if err != nil { h.Logger.Error("unable to perform database insert", "error", err) w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusInternalServerError) json.NewEncoder(w).Encode(map[string]string{ "status": "ERROR", "message": fmt.Sprintf("Unable to insert move event into database: '%s'", err), }) return } else { h.Logger.Debug("created database record", "insert_result", result) w.WriteHeader(http.StatusOK) //fmt.Fprintf(w, "Processed update event: %v\n", result) json.NewEncoder(w).Encode(map[string]string{ "status": "OK", "message": fmt.Sprintf("Successfully processed move event"), }) return } }