package dashboard import ( "fmt" "net/http" ) type ipsPageData struct { PageData Items []ipQueueItem FIPSettleSeconds int } type ipDetailData struct { PageData Detail ipDetailResponse } func (s *Server) handleIPsPage(w http.ResponseWriter, r *http.Request) { items, err := s.CA.ListIPs(r.Context()) settings, settingsErr := s.CA.GetOrchestratorSettings(r.Context()) if err == nil { err = settingsErr } data := ipsPageData{Items: items, FIPSettleSeconds: settings.FIPSettleSeconds} data.ActiveNav = "ips" data.Banner = bannerFor(err) s.renderPage(w, "ips_page", data) } func (s *Server) handleIPDetail(w http.ResponseWriter, r *http.Request) { ip := r.PathValue("ip") detail, err := s.CA.GetIP(r.Context(), ip) data := ipDetailData{Detail: detail} data.ActiveNav = "ips" data.Banner = bannerFor(err) s.renderPage(w, "ip_detail_page", data) } // renderIPsTable re-fetches the current queue and renders the ips_table // fragment, tagging actionErr (if any) on the shared error banner. Called // after every mutating /ips/* request so the table always reflects true // current state regardless of whether the mutation itself succeeded. func (s *Server) renderIPsTable(w http.ResponseWriter, r *http.Request, actionErr error) { items, listErr := s.CA.ListIPs(r.Context()) if actionErr == nil { actionErr = listErr } settings, settingsErr := s.CA.GetOrchestratorSettings(r.Context()) if actionErr == nil { actionErr = settingsErr } s.renderFragment(w, "ips_table", ipsPageData{Items: items, FIPSettleSeconds: settings.FIPSettleSeconds}, actionErr) } func (s *Server) handleIPsSubmit(w http.ResponseWriter, r *http.Request) { if err := r.ParseForm(); err != nil { s.renderIPsTable(w, r, fmt.Errorf("invalid form: %w", err)) return } addresses := splitList(r.PostFormValue("addresses")) if len(addresses) == 0 { s.renderIPsTable(w, r, &apiErr{Status: http.StatusBadRequest, Message: "укажите хотя бы один адрес"}) return } _, err := s.CA.SubmitIPs(r.Context(), addresses) s.renderIPsTable(w, r, err) } func (s *Server) handleIPRecheck(w http.ResponseWriter, r *http.Request) { ip := r.PathValue("ip") _, err := s.CA.SubmitIPs(r.Context(), []string{ip}) s.renderIPsTable(w, r, err) } func (s *Server) handleIPCancel(w http.ResponseWriter, r *http.Request) { ip := r.PathValue("ip") err := s.CA.CancelIP(r.Context(), ip) s.renderIPsTable(w, r, err) } func (s *Server) handleIPDelete(w http.ResponseWriter, r *http.Request) { ip := r.PathValue("ip") err := s.CA.DeleteIP(r.Context(), ip) s.renderIPsTable(w, r, err) } func (s *Server) handleIPsDeleteSelected(w http.ResponseWriter, r *http.Request) { if err := r.ParseForm(); err != nil { s.renderIPsTable(w, r, fmt.Errorf("invalid form: %w", err)) return } addresses := r.Form["addresses"] if len(addresses) == 0 { s.renderIPsTable(w, r, &apiErr{Status: http.StatusBadRequest, Message: "ничего не выбрано"}) return } _, err := s.CA.DeleteIPs(r.Context(), addresses) s.renderIPsTable(w, r, err) } func (s *Server) handleIPsRecheckSelected(w http.ResponseWriter, r *http.Request) { if err := r.ParseForm(); err != nil { s.renderIPsTable(w, r, fmt.Errorf("invalid form: %w", err)) return } addresses := r.Form["addresses"] if len(addresses) == 0 { s.renderIPsTable(w, r, &apiErr{Status: http.StatusBadRequest, Message: "ничего не выбрано"}) return } _, err := s.CA.SubmitIPs(r.Context(), addresses) s.renderIPsTable(w, r, err) } func (s *Server) handleIPsClear(w http.ResponseWriter, r *http.Request) { _, err := s.CA.ClearQueue(r.Context()) s.renderIPsTable(w, r, err) } // handleIPsScan lists the OpenStack project's free (unassociated) floating // IPs and submits them to the check queue in one step — see // client.ScanFloatingIPs. func (s *Server) handleIPsScan(w http.ResponseWriter, r *http.Request) { _, err := s.CA.ScanFloatingIPs(r.Context()) s.renderIPsTable(w, r, err) }