blob: 0423403395a91bb2a5d4efb7069009e9f591461e [file] [log] [blame]
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +04001package welcome
2
3import (
Giorgi Lekveishvilid2f3dca2023-12-20 09:31:30 +04004 "context"
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +04005 "embed"
6 "encoding/json"
7 "fmt"
8 "html/template"
9 "io/ioutil"
10 "log"
11 "net/http"
Giorgi Lekveishvilid2f3dca2023-12-20 09:31:30 +040012 "time"
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +040013
14 "github.com/Masterminds/sprig/v3"
gioaa0fcdb2024-06-10 22:19:25 +040015 "github.com/gorilla/mux"
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +040016
17 "github.com/giolekva/pcloud/core/installer"
Giorgi Lekveishvilid2f3dca2023-12-20 09:31:30 +040018 "github.com/giolekva/pcloud/core/installer/tasks"
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +040019)
20
Davit Tabidze3ec24cf2024-05-22 14:06:02 +040021//go:embed appmanager-tmpl/*
22var appTmpls embed.FS
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +040023
24type AppManagerServer struct {
Giorgi Lekveishvilid2f3dca2023-12-20 09:31:30 +040025 port int
26 m *installer.AppManager
Giorgi Lekveishvili08af67a2024-01-18 08:53:05 +040027 r installer.AppRepository
Giorgi Lekveishvilid2f3dca2023-12-20 09:31:30 +040028 reconciler tasks.Reconciler
gio778577f2024-04-29 09:44:38 +040029 h installer.HelmReleaseMonitor
30 tasks map[string]tasks.Task
Davit Tabidze3ec24cf2024-05-22 14:06:02 +040031 tmpl tmplts
32}
33
34type tmplts struct {
35 index *template.Template
36 app *template.Template
37}
38
39func parseTemplatesAppManager(fs embed.FS) (tmplts, error) {
40 base, err := template.New("base.html").Funcs(template.FuncMap(sprig.FuncMap())).ParseFS(fs, "appmanager-tmpl/base.html")
41 if err != nil {
42 return tmplts{}, err
43 }
44 parse := func(path string) (*template.Template, error) {
45 if b, err := base.Clone(); err != nil {
46 return nil, err
47 } else {
48 return b.ParseFS(fs, path)
49 }
50 }
51 index, err := parse("appmanager-tmpl/index.html")
52 if err != nil {
53 return tmplts{}, err
54 }
55 app, err := parse("appmanager-tmpl/app.html")
56 if err != nil {
57 return tmplts{}, err
58 }
59 return tmplts{index, app}, nil
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +040060}
61
62func NewAppManagerServer(
63 port int,
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +040064 m *installer.AppManager,
Giorgi Lekveishvili08af67a2024-01-18 08:53:05 +040065 r installer.AppRepository,
Giorgi Lekveishvilid2f3dca2023-12-20 09:31:30 +040066 reconciler tasks.Reconciler,
gio778577f2024-04-29 09:44:38 +040067 h installer.HelmReleaseMonitor,
Davit Tabidze3ec24cf2024-05-22 14:06:02 +040068) (*AppManagerServer, error) {
69 tmpl, err := parseTemplatesAppManager(appTmpls)
70 if err != nil {
71 return nil, err
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +040072 }
Davit Tabidze3ec24cf2024-05-22 14:06:02 +040073 return &AppManagerServer{
74 port: port,
75 m: m,
76 r: r,
77 reconciler: reconciler,
78 h: h,
79 tasks: make(map[string]tasks.Task),
80 tmpl: tmpl,
81 }, nil
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +040082}
83
Giorgi Lekveishvili743fb432023-11-08 17:19:40 +040084func (s *AppManagerServer) Start() error {
gioaa0fcdb2024-06-10 22:19:25 +040085 r := mux.NewRouter()
86 r.PathPrefix("/static/").Handler(http.FileServer(http.FS(staticAssets)))
87 r.HandleFunc("/api/app-repo", s.handleAppRepo)
88 r.HandleFunc("/api/app/{slug}/install", s.handleAppInstall).Methods(http.MethodPost)
89 r.HandleFunc("/api/app/{slug}", s.handleApp).Methods(http.MethodGet)
90 r.HandleFunc("/api/instance/{slug}", s.handleInstance).Methods(http.MethodGet)
91 r.HandleFunc("/api/instance/{slug}/update", s.handleAppUpdate).Methods(http.MethodPost)
92 r.HandleFunc("/api/instance/{slug}/remove", s.handleAppRemove).Methods(http.MethodPost)
93 r.HandleFunc("/", s.handleIndex).Methods(http.MethodGet)
94 r.HandleFunc("/not-installed", s.handleNotInstalledApps).Methods(http.MethodGet)
95 r.HandleFunc("/installed", s.handleInstalledApps).Methods(http.MethodGet)
96 r.HandleFunc("/app/{slug}", s.handleAppUI).Methods(http.MethodGet)
97 r.HandleFunc("/instance/{slug}", s.handleInstanceUI).Methods(http.MethodGet)
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +040098 fmt.Printf("Starting HTTP server on port: %d\n", s.port)
gioaa0fcdb2024-06-10 22:19:25 +040099 return http.ListenAndServe(fmt.Sprintf(":%d", s.port), r)
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400100}
101
102type app struct {
gio3cdee592024-04-17 10:15:56 +0400103 Name string `json:"name"`
104 Icon template.HTML `json:"icon"`
105 ShortDescription string `json:"shortDescription"`
106 Slug string `json:"slug"`
107 Instances []installer.AppInstanceConfig `json:"instances,omitempty"`
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400108}
109
gioaa0fcdb2024-06-10 22:19:25 +0400110func (s *AppManagerServer) handleAppRepo(w http.ResponseWriter, r *http.Request) {
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400111 all, err := s.r.GetAll()
112 if err != nil {
gioaa0fcdb2024-06-10 22:19:25 +0400113 http.Error(w, err.Error(), http.StatusInternalServerError)
114 return
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400115 }
116 resp := make([]app, len(all))
117 for i, a := range all {
gio44f621b2024-04-29 09:44:38 +0400118 resp[i] = app{a.Name(), a.Icon(), a.Description(), a.Slug(), nil}
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400119 }
gioaa0fcdb2024-06-10 22:19:25 +0400120 w.Header().Set("Content-Type", "application/json")
121 if err := json.NewEncoder(w).Encode(resp); err != nil {
122 http.Error(w, err.Error(), http.StatusInternalServerError)
123 return
124 }
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400125}
126
gioaa0fcdb2024-06-10 22:19:25 +0400127func (s *AppManagerServer) handleApp(w http.ResponseWriter, r *http.Request) {
128 slug, ok := mux.Vars(r)["slug"]
129 if !ok {
130 http.Error(w, "empty slug", http.StatusBadRequest)
131 return
132 }
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400133 a, err := s.r.Find(slug)
134 if err != nil {
gioaa0fcdb2024-06-10 22:19:25 +0400135 http.Error(w, err.Error(), http.StatusInternalServerError)
136 return
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400137 }
gio308105e2024-04-19 13:12:13 +0400138 instances, err := s.m.FindAllAppInstances(slug)
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400139 if err != nil {
gioaa0fcdb2024-06-10 22:19:25 +0400140 http.Error(w, err.Error(), http.StatusInternalServerError)
141 return
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400142 }
gioaa0fcdb2024-06-10 22:19:25 +0400143 resp := app{a.Name(), a.Icon(), a.Description(), a.Slug(), instances}
144 w.Header().Set("Content-Type", "application/json")
145 if err := json.NewEncoder(w).Encode(resp); err != nil {
146 http.Error(w, err.Error(), http.StatusInternalServerError)
147 return
148 }
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400149}
150
gioaa0fcdb2024-06-10 22:19:25 +0400151func (s *AppManagerServer) handleInstance(w http.ResponseWriter, r *http.Request) {
152 slug, ok := mux.Vars(r)["slug"]
153 if !ok {
154 http.Error(w, "empty slug", http.StatusBadRequest)
155 return
156 }
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400157 instance, err := s.m.FindInstance(slug)
158 if err != nil {
gioaa0fcdb2024-06-10 22:19:25 +0400159 http.Error(w, err.Error(), http.StatusInternalServerError)
160 return
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400161 }
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400162 a, err := s.r.Find(instance.AppId)
163 if err != nil {
gioaa0fcdb2024-06-10 22:19:25 +0400164 http.Error(w, err.Error(), http.StatusInternalServerError)
165 return
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400166 }
gioaa0fcdb2024-06-10 22:19:25 +0400167 resp := app{a.Name(), a.Icon(), a.Description(), a.Slug(), []installer.AppInstanceConfig{*instance}}
168 w.Header().Set("Content-Type", "application/json")
169 if err := json.NewEncoder(w).Encode(resp); err != nil {
170 http.Error(w, err.Error(), http.StatusInternalServerError)
171 return
172 }
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400173}
174
gioaa0fcdb2024-06-10 22:19:25 +0400175func (s *AppManagerServer) handleAppInstall(w http.ResponseWriter, r *http.Request) {
176 slug, ok := mux.Vars(r)["slug"]
177 if !ok {
178 http.Error(w, "empty slug", http.StatusBadRequest)
179 return
180 }
181 contents, err := ioutil.ReadAll(r.Body)
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400182 if err != nil {
gioaa0fcdb2024-06-10 22:19:25 +0400183 http.Error(w, err.Error(), http.StatusInternalServerError)
184 return
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400185 }
186 var values map[string]any
187 if err := json.Unmarshal(contents, &values); err != nil {
gioaa0fcdb2024-06-10 22:19:25 +0400188 http.Error(w, err.Error(), http.StatusInternalServerError)
189 return
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400190 }
Giorgi Lekveishvili743fb432023-11-08 17:19:40 +0400191 log.Printf("Values: %+v\n", values)
gio3cdee592024-04-17 10:15:56 +0400192 a, err := installer.FindEnvApp(s.r, slug)
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400193 if err != nil {
gioaa0fcdb2024-06-10 22:19:25 +0400194 http.Error(w, err.Error(), http.StatusInternalServerError)
195 return
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400196 }
Giorgi Lekveishvili743fb432023-11-08 17:19:40 +0400197 log.Printf("Found application: %s\n", slug)
gio3cdee592024-04-17 10:15:56 +0400198 env, err := s.m.Config()
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400199 if err != nil {
gioaa0fcdb2024-06-10 22:19:25 +0400200 http.Error(w, err.Error(), http.StatusInternalServerError)
201 return
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400202 }
gio3cdee592024-04-17 10:15:56 +0400203 log.Printf("Configuration: %+v\n", env)
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400204 suffixGen := installer.NewFixedLengthRandomSuffixGenerator(3)
gio3af43942024-04-16 08:13:50 +0400205 suffix, err := suffixGen.Generate()
206 if err != nil {
gioaa0fcdb2024-06-10 22:19:25 +0400207 http.Error(w, err.Error(), http.StatusInternalServerError)
208 return
gio3af43942024-04-16 08:13:50 +0400209 }
gio44f621b2024-04-29 09:44:38 +0400210 instanceId := a.Slug() + suffix
gio3cdee592024-04-17 10:15:56 +0400211 appDir := fmt.Sprintf("/apps/%s", instanceId)
212 namespace := fmt.Sprintf("%s%s%s", env.NamespacePrefix, a.Namespace(), suffix)
gio778577f2024-04-29 09:44:38 +0400213 rr, err := s.m.Install(a, instanceId, appDir, namespace, values)
214 if err != nil {
gioaa0fcdb2024-06-10 22:19:25 +0400215 http.Error(w, err.Error(), http.StatusInternalServerError)
216 return
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400217 }
Giorgi Lekveishvilid2f3dca2023-12-20 09:31:30 +0400218 ctx, _ := context.WithTimeout(context.Background(), 2*time.Minute)
219 go s.reconciler.Reconcile(ctx)
gio778577f2024-04-29 09:44:38 +0400220 if _, ok := s.tasks[instanceId]; ok {
221 panic("MUST NOT REACH!")
222 }
223 t := tasks.NewMonitorRelease(s.h, rr)
224 t.OnDone(func(err error) {
225 delete(s.tasks, instanceId)
226 })
227 s.tasks[instanceId] = t
228 go t.Start()
gioaa0fcdb2024-06-10 22:19:25 +0400229 if _, err := fmt.Fprintf(w, "/instance/%s", instanceId); err != nil {
230 http.Error(w, err.Error(), http.StatusInternalServerError)
231 return
232 }
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400233}
234
gioaa0fcdb2024-06-10 22:19:25 +0400235func (s *AppManagerServer) handleAppUpdate(w http.ResponseWriter, r *http.Request) {
236 slug, ok := mux.Vars(r)["slug"]
237 if !ok {
238 http.Error(w, "empty slug", http.StatusBadRequest)
239 return
240 }
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400241 appConfig, err := s.m.AppConfig(slug)
242 if err != nil {
gioaa0fcdb2024-06-10 22:19:25 +0400243 http.Error(w, err.Error(), http.StatusInternalServerError)
244 return
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400245 }
gioaa0fcdb2024-06-10 22:19:25 +0400246 contents, err := ioutil.ReadAll(r.Body)
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400247 if err != nil {
gioaa0fcdb2024-06-10 22:19:25 +0400248 http.Error(w, err.Error(), http.StatusInternalServerError)
249 return
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400250 }
251 var values map[string]any
252 if err := json.Unmarshal(contents, &values); err != nil {
gioaa0fcdb2024-06-10 22:19:25 +0400253 http.Error(w, err.Error(), http.StatusInternalServerError)
254 return
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400255 }
gio3cdee592024-04-17 10:15:56 +0400256 a, err := installer.FindEnvApp(s.r, appConfig.AppId)
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400257 if err != nil {
gioaa0fcdb2024-06-10 22:19:25 +0400258 http.Error(w, err.Error(), http.StatusInternalServerError)
259 return
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400260 }
gio778577f2024-04-29 09:44:38 +0400261 if _, ok := s.tasks[slug]; ok {
gioaa0fcdb2024-06-10 22:19:25 +0400262 http.Error(w, "Update already in progress", http.StatusBadRequest)
263 return
gio778577f2024-04-29 09:44:38 +0400264 }
265 rr, err := s.m.Update(a, slug, values)
266 if err != nil {
gioaa0fcdb2024-06-10 22:19:25 +0400267 http.Error(w, err.Error(), http.StatusInternalServerError)
268 return
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400269 }
Giorgi Lekveishvilid2f3dca2023-12-20 09:31:30 +0400270 ctx, _ := context.WithTimeout(context.Background(), 2*time.Minute)
271 go s.reconciler.Reconcile(ctx)
gio778577f2024-04-29 09:44:38 +0400272 t := tasks.NewMonitorRelease(s.h, rr)
273 t.OnDone(func(err error) {
274 delete(s.tasks, slug)
275 })
276 s.tasks[slug] = t
277 go t.Start()
gioaa0fcdb2024-06-10 22:19:25 +0400278 if _, err := fmt.Fprintf(w, "/instance/%s", slug); err != nil {
279 http.Error(w, err.Error(), http.StatusInternalServerError)
280 return
281 }
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400282}
283
gioaa0fcdb2024-06-10 22:19:25 +0400284func (s *AppManagerServer) handleAppRemove(w http.ResponseWriter, r *http.Request) {
285 slug, ok := mux.Vars(r)["slug"]
286 if !ok {
287 http.Error(w, "empty slug", http.StatusBadRequest)
288 return
289 }
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400290 if err := s.m.Remove(slug); err != nil {
gioaa0fcdb2024-06-10 22:19:25 +0400291 http.Error(w, err.Error(), http.StatusInternalServerError)
292 return
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400293 }
Giorgi Lekveishvilid2f3dca2023-12-20 09:31:30 +0400294 ctx, _ := context.WithTimeout(context.Background(), 2*time.Minute)
295 go s.reconciler.Reconcile(ctx)
gioaa0fcdb2024-06-10 22:19:25 +0400296 if _, err := fmt.Fprint(w, "/"); err != nil {
297 http.Error(w, err.Error(), http.StatusInternalServerError)
298 return
299 }
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400300}
301
Davit Tabidze3ec24cf2024-05-22 14:06:02 +0400302type PageData struct {
303 Apps []app
304 CurrentPage string
305}
306
gioaa0fcdb2024-06-10 22:19:25 +0400307func (s *AppManagerServer) handleIndex(w http.ResponseWriter, r *http.Request) {
Davit Tabidze3ec24cf2024-05-22 14:06:02 +0400308 all, err := s.r.GetAll()
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400309 if err != nil {
Davit Tabidze3ec24cf2024-05-22 14:06:02 +0400310 log.Printf("all apps: %v", err)
gioaa0fcdb2024-06-10 22:19:25 +0400311 http.Error(w, err.Error(), http.StatusInternalServerError)
312 return
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400313 }
Davit Tabidze3ec24cf2024-05-22 14:06:02 +0400314 resp := make([]app, 0)
315 for _, a := range all {
316 instances, err := s.m.FindAllAppInstances(a.Slug())
317 if err != nil {
gioaa0fcdb2024-06-10 22:19:25 +0400318 http.Error(w, err.Error(), http.StatusInternalServerError)
319 return
Davit Tabidze3ec24cf2024-05-22 14:06:02 +0400320 }
321 resp = append(resp, app{a.Name(), a.Icon(), a.Description(), a.Slug(), instances})
322 }
323 data := PageData{
324 Apps: resp,
325 CurrentPage: "ALL",
326 }
gioaa0fcdb2024-06-10 22:19:25 +0400327 if err := s.tmpl.index.Execute(w, data); err != nil {
Davit Tabidze3ec24cf2024-05-22 14:06:02 +0400328 log.Printf("executing template: %v", err)
gioaa0fcdb2024-06-10 22:19:25 +0400329 http.Error(w, err.Error(), http.StatusInternalServerError)
330 return
Davit Tabidze3ec24cf2024-05-22 14:06:02 +0400331 }
Davit Tabidze3ec24cf2024-05-22 14:06:02 +0400332}
333
gioaa0fcdb2024-06-10 22:19:25 +0400334func (s *AppManagerServer) handleNotInstalledApps(w http.ResponseWriter, r *http.Request) {
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400335 all, err := s.r.GetAll()
336 if err != nil {
gioaa0fcdb2024-06-10 22:19:25 +0400337 http.Error(w, err.Error(), http.StatusInternalServerError)
338 return
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400339 }
Davit Tabidze3ec24cf2024-05-22 14:06:02 +0400340 resp := make([]app, 0)
341 for _, a := range all {
342 instances, err := s.m.FindAllAppInstances(a.Slug())
343 if err != nil {
gioaa0fcdb2024-06-10 22:19:25 +0400344 http.Error(w, err.Error(), http.StatusInternalServerError)
345 return
Davit Tabidze3ec24cf2024-05-22 14:06:02 +0400346 }
347 if len(instances) == 0 {
348 resp = append(resp, app{a.Name(), a.Icon(), a.Description(), a.Slug(), nil})
349 }
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400350 }
Davit Tabidze3ec24cf2024-05-22 14:06:02 +0400351 data := PageData{
352 Apps: resp,
353 CurrentPage: "NOT_INSTALLED",
354 }
gioaa0fcdb2024-06-10 22:19:25 +0400355 if err := s.tmpl.index.Execute(w, data); err != nil {
356 http.Error(w, err.Error(), http.StatusInternalServerError)
357 return
Davit Tabidze3ec24cf2024-05-22 14:06:02 +0400358 }
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400359}
360
gioaa0fcdb2024-06-10 22:19:25 +0400361func (s *AppManagerServer) handleInstalledApps(w http.ResponseWriter, r *http.Request) {
Davit Tabidze3ec24cf2024-05-22 14:06:02 +0400362 all, err := s.r.GetAll()
363 if err != nil {
gioaa0fcdb2024-06-10 22:19:25 +0400364 http.Error(w, err.Error(), http.StatusInternalServerError)
365 return
Davit Tabidze3ec24cf2024-05-22 14:06:02 +0400366 }
367 resp := make([]app, 0)
368 for _, a := range all {
369 instances, err := s.m.FindAllAppInstances(a.Slug())
370 if err != nil {
gioaa0fcdb2024-06-10 22:19:25 +0400371 http.Error(w, err.Error(), http.StatusInternalServerError)
372 return
Davit Tabidze3ec24cf2024-05-22 14:06:02 +0400373 }
374 if len(instances) != 0 {
375 resp = append(resp, app{a.Name(), a.Icon(), a.Description(), a.Slug(), instances})
376 }
377 }
378 data := PageData{
379 Apps: resp,
380 CurrentPage: "INSTALLED",
381 }
gioaa0fcdb2024-06-10 22:19:25 +0400382 if err := s.tmpl.index.Execute(w, data); err != nil {
383 http.Error(w, err.Error(), http.StatusInternalServerError)
384 return
Davit Tabidze3ec24cf2024-05-22 14:06:02 +0400385 }
Davit Tabidze3ec24cf2024-05-22 14:06:02 +0400386}
387
388type appPageData struct {
gio3cdee592024-04-17 10:15:56 +0400389 App installer.EnvApp
390 Instance *installer.AppInstanceConfig
391 Instances []installer.AppInstanceConfig
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400392 AvailableNetworks []installer.Network
gio778577f2024-04-29 09:44:38 +0400393 Task tasks.Task
Davit Tabidze3ec24cf2024-05-22 14:06:02 +0400394 CurrentPage string
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400395}
396
gioaa0fcdb2024-06-10 22:19:25 +0400397func (s *AppManagerServer) handleAppUI(w http.ResponseWriter, r *http.Request) {
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400398 global, err := s.m.Config()
399 if err != nil {
gioaa0fcdb2024-06-10 22:19:25 +0400400 http.Error(w, err.Error(), http.StatusInternalServerError)
401 return
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400402 }
gioaa0fcdb2024-06-10 22:19:25 +0400403 slug, ok := mux.Vars(r)["slug"]
404 if !ok {
405 http.Error(w, "empty slug", http.StatusBadRequest)
406 return
407 }
gio3cdee592024-04-17 10:15:56 +0400408 a, err := installer.FindEnvApp(s.r, slug)
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400409 if err != nil {
gioaa0fcdb2024-06-10 22:19:25 +0400410 http.Error(w, err.Error(), http.StatusInternalServerError)
411 return
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400412 }
gio308105e2024-04-19 13:12:13 +0400413 instances, err := s.m.FindAllAppInstances(slug)
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400414 if err != nil {
gioaa0fcdb2024-06-10 22:19:25 +0400415 http.Error(w, err.Error(), http.StatusInternalServerError)
416 return
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400417 }
Davit Tabidze3ec24cf2024-05-22 14:06:02 +0400418 data := appPageData{
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400419 App: a,
420 Instances: instances,
421 AvailableNetworks: installer.CreateNetworks(global),
Davit Tabidze3ec24cf2024-05-22 14:06:02 +0400422 CurrentPage: a.Name(),
423 }
gioaa0fcdb2024-06-10 22:19:25 +0400424 if err := s.tmpl.app.Execute(w, data); err != nil {
425 http.Error(w, err.Error(), http.StatusInternalServerError)
426 return
427 }
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400428}
429
gioaa0fcdb2024-06-10 22:19:25 +0400430func (s *AppManagerServer) handleInstanceUI(w http.ResponseWriter, r *http.Request) {
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400431 global, err := s.m.Config()
432 if err != nil {
gioaa0fcdb2024-06-10 22:19:25 +0400433 http.Error(w, err.Error(), http.StatusInternalServerError)
434 return
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400435 }
gioaa0fcdb2024-06-10 22:19:25 +0400436 slug, ok := mux.Vars(r)["slug"]
437 if !ok {
438 http.Error(w, "empty slug", http.StatusBadRequest)
439 return
440 }
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400441 instance, err := s.m.FindInstance(slug)
442 if err != nil {
gioaa0fcdb2024-06-10 22:19:25 +0400443 http.Error(w, err.Error(), http.StatusInternalServerError)
444 return
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400445 }
gio3cdee592024-04-17 10:15:56 +0400446 a, err := installer.FindEnvApp(s.r, instance.AppId)
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400447 if err != nil {
gioaa0fcdb2024-06-10 22:19:25 +0400448 http.Error(w, err.Error(), http.StatusInternalServerError)
449 return
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400450 }
gio44f621b2024-04-29 09:44:38 +0400451 instances, err := s.m.FindAllAppInstances(a.Slug())
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400452 if err != nil {
gioaa0fcdb2024-06-10 22:19:25 +0400453 http.Error(w, err.Error(), http.StatusInternalServerError)
454 return
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400455 }
gio778577f2024-04-29 09:44:38 +0400456 t := s.tasks[slug]
Davit Tabidze3ec24cf2024-05-22 14:06:02 +0400457 data := appPageData{
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400458 App: a,
gio778577f2024-04-29 09:44:38 +0400459 Instance: instance,
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400460 Instances: instances,
461 AvailableNetworks: installer.CreateNetworks(global),
gio778577f2024-04-29 09:44:38 +0400462 Task: t,
Davit Tabidze3ec24cf2024-05-22 14:06:02 +0400463 CurrentPage: instance.Id,
464 }
gioaa0fcdb2024-06-10 22:19:25 +0400465 if err := s.tmpl.app.Execute(w, data); err != nil {
466 http.Error(w, err.Error(), http.StatusInternalServerError)
467 return
468 }
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400469}