github.com/esnet/gdg@v0.6.1-0.20240412190737-6b6eba9c14d8/internal/service/libraryelements.go (about) 1 package service 2 3 import ( 4 "encoding/json" 5 "errors" 6 "fmt" 7 "github.com/esnet/gdg/internal/config" 8 "github.com/esnet/gdg/internal/service/filters" 9 "github.com/esnet/gdg/internal/tools" 10 "github.com/gosimple/slug" 11 "github.com/grafana/grafana-openapi-client-go/client/library_elements" 12 "github.com/grafana/grafana-openapi-client-go/models" 13 "github.com/tidwall/gjson" 14 "golang.org/x/exp/maps" 15 "golang.org/x/exp/slices" 16 "log" 17 "log/slog" 18 "strings" 19 ) 20 21 const ( 22 listLibraryPanels int64 = 1 23 listLibraryVars int64 = 2 24 ) 25 26 func (s *DashNGoImpl) ListLibraryElementsConnections(filter filters.Filter, connectionID string) []*models.DashboardFullWithMeta { 27 payload, err := s.GetClient().LibraryElements.GetLibraryElementConnections(connectionID) 28 if err != nil { 29 log.Fatalf("unable to retrieve a valid connection for %s", connectionID) 30 } 31 var results []*models.DashboardFullWithMeta 32 33 for _, item := range payload.GetPayload().Result { 34 dashboard, err := s.getDashboardByUid(item.ConnectionUID) 35 if err != nil { 36 slog.Error("failed to retrieve linked Dashboard", "uid", item.ConnectionUID) 37 } 38 results = append(results, dashboard) 39 } 40 41 return results 42 } 43 44 func (s *DashNGoImpl) ListLibraryElements(filter filters.Filter) []*models.LibraryElementDTO { 45 ignoreFilters := config.Config().GetDefaultGrafanaConfig().GetFilterOverrides().IgnoreDashboardFilters 46 folderFilter := NewFolderFilter() 47 if ignoreFilters { 48 folderFilter = nil 49 } 50 51 folderNameMap := getFolderNameIDMap(s.ListFolder(folderFilter)) 52 values := maps.Values(folderNameMap) 53 var buf = strings.Builder{} 54 //Check to see if General should be included 55 //If Ignore Filters OR General is in monitored list, add 0 folder 56 if (!ignoreFilters && slices.Contains(config.Config().GetDefaultGrafanaConfig().GetMonitoredFolders(), DefaultFolderName)) || ignoreFilters { 57 buf.WriteString("0,") 58 } else { 59 buf.WriteString("") 60 } 61 for _, i := range values { 62 buf.WriteString(fmt.Sprintf("%d,", i)) 63 } 64 folderList := buf.String()[:len(buf.String())-1] 65 66 params := library_elements.NewGetLibraryElementsParams() 67 params.FolderFilter = &folderList 68 params.Kind = tools.PtrOf(listLibraryPanels) 69 libraryElements, err := s.GetClient().LibraryElements.GetLibraryElements(params) 70 if err != nil { 71 log.Fatalf("Unable to list Library Elements %v", err) 72 73 } 74 return libraryElements.GetPayload().Result.Elements 75 } 76 77 // DownloadLibraryElements downloads all the Library Elements 78 func (s *DashNGoImpl) DownloadLibraryElements(filter filters.Filter) []string { 79 var ( 80 listing []*models.LibraryElementDTO 81 dsPacked []byte 82 err error 83 dataFiles []string 84 ) 85 86 folderMap := reverseLookUp(getFolderNameIDMap(s.ListFolder(nil))) 87 listing = s.ListLibraryElements(filter) 88 for _, item := range listing { 89 if dsPacked, err = json.MarshalIndent(item, "", " "); err != nil { 90 slog.Error("Unable to serialize object", "err", err, "library-element", item.Name) 91 continue 92 } 93 folderName := DefaultFolderName 94 95 if val, ok := folderMap[item.FolderID]; ok { 96 folderName = val 97 } 98 99 libraryPath := fmt.Sprintf("%s/%s.json", BuildResourceFolder(folderName, config.LibraryElementResource), slug.Make(item.Name)) 100 101 if err = s.storage.WriteFile(libraryPath, dsPacked); err != nil { 102 slog.Error("Unable to write file", "err", err, "library-element", slug.Make(item.Name)) 103 } else { 104 dataFiles = append(dataFiles, libraryPath) 105 } 106 } 107 return dataFiles 108 } 109 110 // UploadLibraryElements uploads all the Library Elements 111 func (s *DashNGoImpl) UploadLibraryElements(filter filters.Filter) []string { 112 var ( 113 exported []string = make([]string, 0) 114 rawLibraryElement []byte 115 folderName string 116 libraryUID string 117 ) 118 119 slog.Info("Reading files from folder", "folder", config.Config().GetDefaultGrafanaConfig().GetPath(config.LibraryElementResource)) 120 filesInDir, err := s.storage.FindAllFiles(config.Config().GetDefaultGrafanaConfig().GetPath(config.LibraryElementResource), true) 121 122 currentLibElements := s.ListLibraryElements(filter) 123 libMapping := make(map[string]*models.LibraryElementDTO, 0) 124 //Build a mapping by UID 125 for ndx, item := range currentLibElements { 126 libMapping[item.UID] = currentLibElements[ndx] 127 } 128 129 if err != nil { 130 slog.Error("failed to list files in directory for library elements", "err", err) 131 } 132 133 for _, file := range filesInDir { 134 fileLocation := file 135 if strings.HasSuffix(file, ".json") { 136 if rawLibraryElement, err = s.storage.ReadFile(fileLocation); err != nil { 137 slog.Error("failed to read file", "file", fileLocation, "err", err) 138 continue 139 } 140 141 Results := gjson.GetManyBytes(rawLibraryElement, "meta.folderName", "uid") 142 143 if Results[0].Exists() { 144 folderName = Results[0].String() 145 } else { 146 slog.Error("Unable to determine folder name of library component, skipping.", "filename", file) 147 continue 148 } 149 //Get UID 150 if Results[1].Exists() { 151 libraryUID = Results[1].String() 152 } else { 153 slog.Error("Unable to determine the library panel UID, attempting to export anyways", "filename", file) 154 } 155 156 if _, ok := libMapping[libraryUID]; ok { 157 slog.Warn("Library already exists, skipping", "filename", file) 158 continue 159 } 160 161 if !slices.Contains(config.Config().GetDefaultGrafanaConfig().GetMonitoredFolders(), folderName) { 162 slog.Warn("Skipping since requested file is not in a folder gdg is configured to manage", "folder", folderName, "file", file) 163 continue 164 } 165 var newLibraryRequest models.CreateLibraryElementCommand 166 167 if err = json.Unmarshal(rawLibraryElement, &newLibraryRequest); err != nil { 168 slog.Error("failed to unmarshall file", "filename", fileLocation, "err", err) 169 continue 170 } 171 172 entity, err := s.GetClient().LibraryElements.CreateLibraryElement(&newLibraryRequest) 173 if err != nil { 174 slog.Error("Failed to create library element", "err", err) 175 } else { 176 exported = append(exported, entity.Payload.Result.Name) 177 } 178 } 179 } 180 return exported 181 } 182 183 // DeleteAllLibraryElements deletes all the Library Elements 184 func (s *DashNGoImpl) DeleteAllLibraryElements(filter filters.Filter) []string { 185 var entries []string 186 libraryElements := s.ListLibraryElements(filter) 187 for _, element := range libraryElements { 188 189 _, err := s.GetClient().LibraryElements.DeleteLibraryElementByUID(element.UID) 190 if err != nil { 191 logEntries := make([]interface{}, 0) 192 var serr *library_elements.DeleteLibraryElementByUIDForbidden 193 if errors.As(err, &serr) { 194 logEntries = append(logEntries, []interface{}{"ErrorMessage", *serr.GetPayload().Message}...) 195 } 196 197 logEntries = append(logEntries, []interface{}{"panel", element.Name}...) 198 slog.Error("Failed to delete library panel", logEntries...) 199 continue 200 } 201 entries = append(entries, element.Name) 202 } 203 204 return entries 205 }