/* How to use: eyede useStorage --databaseHost=localhost --databaseName=dev0 --databaseUser=postgres --databasePassword=**** --topLevelProjectID=ret-edge-dev0-foreman --chariotTopic=chariot-rides */ package usestorage import ( "context" "database/sql" "encoding/json" "errors" "fmt" "io" "os" "strings" "cloud.google.com/go/storage" "google.golang.org/api/iterator" corev1 "k8s.io/api/core/v1" eyedeUtils "edge-infra.dev/hack/tools/eyede/utils" "edge-infra.dev/pkg/edge/api/utils" "edge-infra.dev/pkg/edge/info" ) const ( edgeInfoConfigMapMatcher = "{\"kind\":\"ConfigMap\",\"apiVersion\":\"v1\",\"metadata\":{\"name\":\"edge-info\"" updateClusterWithLocation = "UPDATE clusters SET location = $1 WHERE cluster_edge_id = $2" ) func UpdateEdgeInfoConfigMapsInStorage(ctx context.Context, db *sql.DB, projectID, foremanProjectID, topic, edgeAPIURL string, dryRun bool) bool { client, err := storage.NewClient(ctx) if err != nil { fmt.Println("an error occurred creating storage client", err) os.Exit(1) } bucket := client.Bucket(projectID) it := bucket.Objects(ctx, nil) for { attrs, err := it.Next() if err == iterator.Done { break } if err != nil { switch { case errors.Is(err, storage.ErrBucketNotExist): return true case errors.Is(err, storage.ErrObjectNotExist): continue default: fmt.Println("an error occurred", projectID, err) os.Exit(1) } } if isChariotObject(attrs.Name) { //nolint:nestif data := readObject(ctx, bucket, attrs.Name) if isEdgeInfoConfigMap(data) { edgeInfoConfigmap := objectToConfigMap(data) edgeInfo := &info.EdgeInfo{} edgeInfo = edgeInfo.FromConfigMap(edgeInfoConfigmap) edgeInfo.EdgeAPIEndpoint = edgeAPIURL edgeCM := edgeInfo.ToConfigMap() edgeConfigMapString, err := info.ConfigMapToString(edgeCM) if err != nil { fmt.Println("error converting configmap to string", err) os.Exit(1) } fmt.Println(string(edgeConfigMapString)) fmt.Println("") if !dryRun { configMap := utils.ToBase64(edgeConfigMapString) chariotMessage := eyedeUtils.CreateChariotMessage(edgeInfo.ProjectID, edgeInfo.ClusterEdgeID, eyedeUtils.Filter, configMap) err = eyedeUtils.InvokeChariot(ctx, foremanProjectID, topic, chariotMessage) if err != nil { fmt.Println("failed to send configmap to chariot", err) os.Exit(1) } //Update the cluster location in the database _, err = db.ExecContext(ctx, updateClusterWithLocation, edgeInfo.Location, edgeInfo.ClusterEdgeID) if err != nil { fmt.Println("error occurred updating the location of cluster in the database", edgeInfo.Store, edgeInfo.ClusterEdgeID) } } } } } return false } func readObject(ctx context.Context, bucket *storage.BucketHandle, objectName string) []byte { obj := bucket.Object(objectName) rdr, err := obj.NewReader(ctx) if err != nil { fmt.Println("failed to create reader for file in chariot folder", objectName, err) os.Exit(1) } data, err := io.ReadAll(rdr) if err != nil || rdr.Close() != nil { fmt.Println("failed to read file in chariot folder", objectName, err) os.Exit(1) } return data } func isChariotObject(objectName string) bool { return strings.Contains(objectName, eyedeUtils.Filter) } func isEdgeInfoConfigMap(fileContents []byte) bool { return strings.Contains(string(fileContents), edgeInfoConfigMapMatcher) } func objectToConfigMap(data []byte) *corev1.ConfigMap { edgeInfoConfigmap := &corev1.ConfigMap{} err := json.Unmarshal(data, edgeInfoConfigmap) if err != nil { fmt.Println("failed to unmarshal object to configmap", err) os.Exit(1) } return edgeInfoConfigmap }