/* How to use: cicterminals useDatabase --databaseHost=localhost --databaseName=dev0 --databaseUser=postgres --topLevelProjectID=ret-edge-dev0-foreman --chariotTopic=chariot-rides */ package usedatabase import ( "context" "database/sql" "encoding/json" "fmt" "os" "edge-infra.dev/hack/tools/cicterminals/cicterminals" "edge-infra.dev/pkg/edge/api/graph/mapper" "edge-infra.dev/pkg/edge/api/graph/model" query "edge-infra.dev/pkg/edge/api/sql" "edge-infra.dev/pkg/edge/api/utils" ) // CreateIENode calls getClusters which queries the database and creates the IENodes func CreateIENode(ctx context.Context, db *sql.DB, projectID, foremanProjectID, cicClusterEdgeID, topic string, dryRun bool) bool { return getClusters(ctx, db, projectID, foremanProjectID, cicClusterEdgeID, topic, dryRun) } func getClusters(ctx context.Context, db *sql.DB, projectID, foremanProjectID, cicClusterEdgeID, topic string, dryRun bool) bool { rows, err := db.QueryContext(ctx, cicterminals.GetClustersForBanner, projectID) if err != nil { fmt.Fprintf(os.Stderr, "error getting banner's clusters for project %s: %s\n", projectID, err) return true } for rows.Next() { var clusterEdgeID string err := rows.Scan(&clusterEdgeID) if err != nil { fmt.Fprintf(os.Stderr, "error scanning cluster vars for cluster %s: %s\n", clusterEdgeID, err) continue } getTerminals(ctx, db, clusterEdgeID, projectID, foremanProjectID, cicClusterEdgeID, topic, dryRun) } return true } // getTerminals gets all the terminals for the associated clusterEdgeID, fetches the // cluster network services, and terminal interfaces. Creates a new IENode resource // for the terminal and sends the IENode to chariot with the correct folder location // for the cluster infra cluster. func getTerminals(ctx context.Context, db *sql.DB, clusterEdgeID, projectID, foremanProjectID, cicClusterEdgeID, topic string, dryRun bool) { clusterNetworkServices, err := getClusterNetworkServices(ctx, db, clusterEdgeID) if err != nil { fmt.Fprintf(os.Stderr, "error finding cluster network services for cluster %s: %s\n", clusterEdgeID, err) return } var edgeVersion string row := db.QueryRowContext(ctx, cicterminals.GetClusterEdgeVersion, clusterEdgeID) err = row.Scan(&edgeVersion) if err != nil { fmt.Fprintf(os.Stderr, "error getting edge version for cluster %s: %s\n", clusterEdgeID, err) return } rows, err := db.QueryContext(ctx, cicterminals.GetTerminalsForCluster, clusterEdgeID) if err != nil { fmt.Fprintf(os.Stderr, "error getting cluster's terminals %s: %s\n", clusterEdgeID, err) return } for rows.Next() { var terminal model.Terminal err := rows.Scan(&terminal.TerminalID, &terminal.Lane, &terminal.Role, &terminal.ClusterEdgeID, &terminal.Hostname, &terminal.Class) if err != nil { fmt.Fprintf(os.Stderr, "error scanning terminal vars %s: %s\n", clusterEdgeID, err) continue } interfaces, err := getInterfaces(ctx, db, terminal.TerminalID) if err != nil { fmt.Fprintf(os.Stderr, "error finding interfaces for terminal %s: %s\n", terminal.TerminalID, err) continue } terminal.Interfaces = interfaces ienode := mapper.TerminalToCICIENode(&terminal, clusterNetworkServices, make(map[string]string, 0), edgeVersion) ienodebytes, err := json.Marshal(ienode) if err != nil { fmt.Fprintf(os.Stderr, "error converting IENode to bytes %s: %s\n", terminal.TerminalID, err) continue } fmt.Println(string(ienodebytes)) fmt.Println("") if !dryRun { ienodebase64 := utils.ToBase64(ienodebytes) chariotMessage := cicterminals.CreateChariotMessage(projectID, cicClusterEdgeID, cicterminals.Filter, ienodebase64) err = cicterminals.InvokeChariot(ctx, foremanProjectID, topic, chariotMessage) if err != nil { fmt.Fprintf(os.Stderr, "failed to send configmap to chariot %s: %s\n", terminal.TerminalID, err) continue } } } } func getInterfaces(ctx context.Context, db *sql.DB, terminalID string) ([]*model.TerminalInterface, error) { var interfaces []*model.TerminalInterface rows, err := db.QueryContext(ctx, query.GetTerminalInterfaceByTerminalIDQuery, terminalID) if err != nil { return nil, err } for rows.Next() { var tInterface model.TerminalInterface err := rows.Scan(&tInterface.TerminalInterfaceID, &tInterface.MacAddress, &tInterface.Dhcp4, &tInterface.Dhcp6, &tInterface.Gateway4, &tInterface.Gateway6, &tInterface.TerminalID) if err != nil { return nil, err } addresses, err := getAddresses(ctx, db, tInterface.TerminalInterfaceID) if err != nil { return nil, err } tInterface.Addresses = addresses interfaces = append(interfaces, &tInterface) } return interfaces, rows.Err() } func getAddresses(ctx context.Context, db *sql.DB, interfaceID string) ([]*model.TerminalAddress, error) { var addresses []*model.TerminalAddress rows, err := db.QueryContext(ctx, query.GetTerminalAddressByInterfaceIDQuery, interfaceID) if err != nil { return nil, err } for rows.Next() { var address model.TerminalAddress err := rows.Scan(&address.TerminalAddressID, &address.IP, &address.PrefixLen, &address.Family, &address.TerminalInterfaceID) if err != nil { return nil, err } addresses = append(addresses, &address) } return addresses, rows.Err() } func getClusterNetworkServices(ctx context.Context, db *sql.DB, clusterEdgeID string) ([]*model.ClusterNetworkServiceInfo, error) { var clusterNetworkServices []*model.ClusterNetworkServiceInfo rows, err := db.QueryContext(ctx, query.GetClusterNetworkServices, clusterEdgeID) if err != nil { return nil, err } for rows.Next() { var networkService model.ClusterNetworkServiceInfo err := rows.Scan(&networkService.NetworkServiceID, &networkService.IP, &networkService.Family, &networkService.ServiceType, &networkService.Priority) if err != nil { return nil, err } clusterNetworkServices = append(clusterNetworkServices, &networkService) } return clusterNetworkServices, nil }