github.com/GoogleCloudPlatform/testgrid@v0.0.174/pkg/api/v1/config.go (about) 1 /* 2 Copyright 2021 The TestGrid Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package v1 18 19 import ( 20 "context" 21 "fmt" 22 "net/http" 23 "sort" 24 25 "github.com/go-chi/chi" 26 "github.com/sirupsen/logrus" 27 28 "github.com/GoogleCloudPlatform/testgrid/config" 29 apipb "github.com/GoogleCloudPlatform/testgrid/pb/api/v1" 30 ) 31 32 const scopeParam = "scope" 33 34 // queryParams returns only the query parameters in the request that need to be passed through to links 35 func queryParams(scope string) string { 36 if scope != "" { 37 return fmt.Sprintf("?scope=%s", scope) 38 } 39 return "" 40 } 41 42 // ListDashboardGroup returns every dashboard group in TestGrid 43 func (s *Server) ListDashboardGroups(ctx context.Context, req *apipb.ListDashboardGroupsRequest) (*apipb.ListDashboardGroupsResponse, error) { 44 c, err := s.getConfig(ctx, logrus.WithContext(ctx), req.GetScope()) 45 if err != nil { 46 return nil, err 47 } 48 c.Mutex.RLock() 49 defer c.Mutex.RUnlock() 50 51 var resp apipb.ListDashboardGroupsResponse 52 for name := range c.Config.DashboardGroups { 53 rsc := apipb.Resource{ 54 Name: name, 55 Link: fmt.Sprintf("/dashboard-groups/%s%s", config.Normalize(name), queryParams(req.GetScope())), 56 } 57 resp.DashboardGroups = append(resp.DashboardGroups, &rsc) 58 } 59 60 sort.SliceStable(resp.DashboardGroups, func(i, j int) bool { 61 return resp.DashboardGroups[i].Name < resp.DashboardGroups[j].Name 62 }) 63 64 return &resp, nil 65 } 66 67 // ListDashboardGroupHTTP returns every dashboard group in TestGrid 68 // Response json: ListDashboardGroupResponse 69 func (s Server) ListDashboardGroupHTTP(w http.ResponseWriter, r *http.Request) { 70 req := apipb.ListDashboardGroupsRequest{ 71 Scope: r.URL.Query().Get(scopeParam), 72 } 73 74 groups, err := s.ListDashboardGroups(r.Context(), &req) 75 if err != nil { 76 http.Error(w, err.Error(), http.StatusNotFound) 77 return 78 } 79 80 s.writeJSON(w, groups) 81 } 82 83 // GetDashboardGroup returns a given dashboard group 84 func (s *Server) GetDashboardGroup(ctx context.Context, req *apipb.GetDashboardGroupRequest) (*apipb.GetDashboardGroupResponse, error) { 85 c, err := s.getConfig(ctx, logrus.WithContext(ctx), req.GetScope()) 86 if err != nil { 87 return nil, err 88 } 89 c.Mutex.RLock() 90 defer c.Mutex.RUnlock() 91 92 dashGroupName := c.NormalDashboardGroup[config.Normalize(req.GetDashboardGroup())] 93 group := c.Config.DashboardGroups[dashGroupName] 94 95 if group != nil { 96 result := apipb.GetDashboardGroupResponse{} 97 for _, dash := range group.DashboardNames { 98 rsc := apipb.Resource{ 99 Name: dash, 100 Link: fmt.Sprintf("/dashboards/%s%s", config.Normalize(dash), queryParams(req.GetScope())), 101 } 102 result.Dashboards = append(result.Dashboards, &rsc) 103 } 104 sort.SliceStable(result.Dashboards, func(i, j int) bool { 105 return result.Dashboards[i].Name < result.Dashboards[j].Name 106 }) 107 return &result, nil 108 } 109 110 return nil, fmt.Errorf("Dashboard group %q not found", req.GetDashboardGroup()) 111 } 112 113 // GetDashboardGroupHTTP returns a given dashboard group 114 // Response json: GetDashboardGroupResponse 115 func (s Server) GetDashboardGroupHTTP(w http.ResponseWriter, r *http.Request) { 116 req := apipb.GetDashboardGroupRequest{ 117 Scope: r.URL.Query().Get(scopeParam), 118 DashboardGroup: chi.URLParam(r, "dashboard-group"), 119 } 120 resp, err := s.GetDashboardGroup(r.Context(), &req) 121 if err != nil { 122 http.Error(w, err.Error(), http.StatusNotFound) 123 return 124 } 125 s.writeJSON(w, resp) 126 } 127 128 // ListDashboard returns every dashboard in TestGrid 129 func (s *Server) ListDashboards(ctx context.Context, req *apipb.ListDashboardsRequest) (*apipb.ListDashboardsResponse, error) { 130 c, err := s.getConfig(ctx, logrus.WithContext(ctx), req.GetScope()) 131 if err != nil { 132 return nil, err 133 } 134 c.Mutex.RLock() 135 defer c.Mutex.RUnlock() 136 137 // TODO(sultan-duisenbay): consider moving this to config snapshot or cached config 138 dashboardsToGroups := make(map[string]string) 139 for _, groupConfig := range c.Config.DashboardGroups { 140 for _, dashboardName := range groupConfig.DashboardNames { 141 dashboardsToGroups[dashboardName] = groupConfig.Name 142 } 143 } 144 145 var resp apipb.ListDashboardsResponse 146 for name := range c.Config.Dashboards { 147 rsc := apipb.DashboardResource{ 148 Name: name, 149 Link: fmt.Sprintf("/dashboards/%s%s", config.Normalize(name), queryParams(req.GetScope())), 150 DashboardGroupName: dashboardsToGroups[name], 151 } 152 resp.Dashboards = append(resp.Dashboards, &rsc) 153 } 154 sort.SliceStable(resp.Dashboards, func(i, j int) bool { 155 return resp.Dashboards[i].Name < resp.Dashboards[j].Name 156 }) 157 158 return &resp, nil 159 } 160 161 // ListDashboardsHTTP returns every dashboard in TestGrid 162 // Response json: ListDashboardResponse 163 func (s Server) ListDashboardsHTTP(w http.ResponseWriter, r *http.Request) { 164 req := apipb.ListDashboardsRequest{ 165 Scope: r.URL.Query().Get(scopeParam), 166 } 167 168 dashboards, err := s.ListDashboards(r.Context(), &req) 169 if err != nil { 170 http.Error(w, err.Error(), http.StatusNotFound) 171 return 172 } 173 174 s.writeJSON(w, dashboards) 175 } 176 177 // GetDashboard returns a given dashboard 178 func (s *Server) GetDashboard(ctx context.Context, req *apipb.GetDashboardRequest) (*apipb.GetDashboardResponse, error) { 179 c, err := s.getConfig(ctx, logrus.WithContext(ctx), req.GetScope()) 180 if err != nil { 181 return nil, err 182 } 183 c.Mutex.RLock() 184 defer c.Mutex.RUnlock() 185 186 dashboardName := c.NormalDashboard[config.Normalize(req.GetDashboard())] 187 dashboard := c.Config.Dashboards[dashboardName] 188 189 if dashboard != nil { 190 result := apipb.GetDashboardResponse{ 191 DefaultTab: dashboard.DefaultTab, 192 HighlightToday: dashboard.HighlightToday, 193 SuppressFailingTabs: dashboard.DownplayFailingTabs, 194 Notifications: dashboard.Notifications, 195 } 196 return &result, nil 197 } 198 199 return nil, fmt.Errorf("Dashboard %q not found", req.GetDashboard()) 200 } 201 202 // GetDashboardHTTP returns a given dashboard 203 // Response json: GetDashboardResponse 204 func (s Server) GetDashboardHTTP(w http.ResponseWriter, r *http.Request) { 205 req := apipb.GetDashboardRequest{ 206 Scope: r.URL.Query().Get(scopeParam), 207 Dashboard: chi.URLParam(r, "dashboard"), 208 } 209 resp, err := s.GetDashboard(r.Context(), &req) 210 if err != nil { 211 http.Error(w, err.Error(), http.StatusNotFound) 212 return 213 } 214 s.writeJSON(w, resp) 215 } 216 217 // ListDashboardTabs returns a given dashboard tabs 218 func (s *Server) ListDashboardTabs(ctx context.Context, req *apipb.ListDashboardTabsRequest) (*apipb.ListDashboardTabsResponse, error) { 219 c, err := s.getConfig(ctx, logrus.WithContext(ctx), req.GetScope()) 220 if err != nil { 221 return nil, err 222 } 223 c.Mutex.RLock() 224 defer c.Mutex.RUnlock() 225 226 dashboardName := c.NormalDashboard[config.Normalize((req.GetDashboard()))] 227 dashboard := c.Config.Dashboards[dashboardName] 228 229 if dashboard != nil { 230 var dashboardTabsResponse apipb.ListDashboardTabsResponse 231 232 for _, tab := range dashboard.DashboardTab { 233 rsc := apipb.Resource{ 234 Name: tab.Name, 235 Link: fmt.Sprintf("/dashboards/%s/tabs/%s%s", config.Normalize(dashboard.Name), config.Normalize(tab.Name), queryParams(req.GetScope())), 236 } 237 dashboardTabsResponse.DashboardTabs = append(dashboardTabsResponse.DashboardTabs, &rsc) 238 } 239 sort.SliceStable(dashboardTabsResponse.DashboardTabs, func(i, j int) bool { 240 return dashboardTabsResponse.DashboardTabs[i].Name < dashboardTabsResponse.DashboardTabs[j].Name 241 }) 242 return &dashboardTabsResponse, nil 243 } 244 return nil, fmt.Errorf("Dashboard %q not found", req.GetDashboard()) 245 } 246 247 // ListDashboardTabsHTTP returns a given dashboard tabs 248 // Response json: ListDashboardTabsResponse 249 func (s Server) ListDashboardTabsHTTP(w http.ResponseWriter, r *http.Request) { 250 req := apipb.ListDashboardTabsRequest{ 251 Scope: r.URL.Query().Get(scopeParam), 252 Dashboard: chi.URLParam(r, "dashboard"), 253 } 254 255 resp, err := s.ListDashboardTabs(r.Context(), &req) 256 if err != nil { 257 http.Error(w, err.Error(), http.StatusNotFound) 258 return 259 } 260 s.writeJSON(w, resp) 261 }