blob: 29d19ed6c938bddfa594d4defe4515a5be0b93b3 [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
gio09f8efa2024-06-10 22:35:24 +040084type cachingHandler struct {
85 h http.Handler
86}
87
88func (h cachingHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
89 w.Header().Set("Cache-Control", "max-age=604800")
90 h.h.ServeHTTP(w, r)
91}
92
Giorgi Lekveishvili743fb432023-11-08 17:19:40 +040093func (s *AppManagerServer) Start() error {
gioaa0fcdb2024-06-10 22:19:25 +040094 r := mux.NewRouter()
gio09f8efa2024-06-10 22:35:24 +040095 r.PathPrefix("/static/").Handler(cachingHandler{http.FileServer(http.FS(staticAssets))})
giocb34ad22024-07-11 08:01:13 +040096 r.HandleFunc("/api/networks", s.handleNetworks).Methods(http.MethodGet)
gioaa0fcdb2024-06-10 22:19:25 +040097 r.HandleFunc("/api/app-repo", s.handleAppRepo)
98 r.HandleFunc("/api/app/{slug}/install", s.handleAppInstall).Methods(http.MethodPost)
99 r.HandleFunc("/api/app/{slug}", s.handleApp).Methods(http.MethodGet)
100 r.HandleFunc("/api/instance/{slug}", s.handleInstance).Methods(http.MethodGet)
101 r.HandleFunc("/api/instance/{slug}/update", s.handleAppUpdate).Methods(http.MethodPost)
102 r.HandleFunc("/api/instance/{slug}/remove", s.handleAppRemove).Methods(http.MethodPost)
gioaa0fcdb2024-06-10 22:19:25 +0400103 r.HandleFunc("/app/{slug}", s.handleAppUI).Methods(http.MethodGet)
104 r.HandleFunc("/instance/{slug}", s.handleInstanceUI).Methods(http.MethodGet)
Davit Tabidze780a0d02024-08-05 20:53:26 +0400105 r.HandleFunc("/{pageType}", s.handleAppsList).Methods(http.MethodGet)
106 r.HandleFunc("/", s.handleAppsList).Methods(http.MethodGet)
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400107 fmt.Printf("Starting HTTP server on port: %d\n", s.port)
gioaa0fcdb2024-06-10 22:19:25 +0400108 return http.ListenAndServe(fmt.Sprintf(":%d", s.port), r)
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400109}
110
111type app struct {
gio3cdee592024-04-17 10:15:56 +0400112 Name string `json:"name"`
113 Icon template.HTML `json:"icon"`
114 ShortDescription string `json:"shortDescription"`
115 Slug string `json:"slug"`
116 Instances []installer.AppInstanceConfig `json:"instances,omitempty"`
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400117}
118
giocb34ad22024-07-11 08:01:13 +0400119func (s *AppManagerServer) handleNetworks(w http.ResponseWriter, r *http.Request) {
120 env, err := s.m.Config()
121 if err != nil {
122 http.Error(w, err.Error(), http.StatusInternalServerError)
123 return
124 }
125 networks, err := s.m.CreateNetworks(env)
126 if err != nil {
127 http.Error(w, err.Error(), http.StatusInternalServerError)
128 return
129 }
130 if err := json.NewEncoder(w).Encode(networks); err != nil {
131 http.Error(w, err.Error(), http.StatusInternalServerError)
132 return
133 }
134}
135
gioaa0fcdb2024-06-10 22:19:25 +0400136func (s *AppManagerServer) handleAppRepo(w http.ResponseWriter, r *http.Request) {
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400137 all, err := s.r.GetAll()
138 if err != nil {
gioaa0fcdb2024-06-10 22:19:25 +0400139 http.Error(w, err.Error(), http.StatusInternalServerError)
140 return
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400141 }
142 resp := make([]app, len(all))
143 for i, a := range all {
gio44f621b2024-04-29 09:44:38 +0400144 resp[i] = app{a.Name(), a.Icon(), a.Description(), a.Slug(), nil}
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400145 }
gioaa0fcdb2024-06-10 22:19:25 +0400146 w.Header().Set("Content-Type", "application/json")
147 if err := json.NewEncoder(w).Encode(resp); err != nil {
148 http.Error(w, err.Error(), http.StatusInternalServerError)
149 return
150 }
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400151}
152
gioaa0fcdb2024-06-10 22:19:25 +0400153func (s *AppManagerServer) handleApp(w http.ResponseWriter, r *http.Request) {
154 slug, ok := mux.Vars(r)["slug"]
155 if !ok {
156 http.Error(w, "empty slug", http.StatusBadRequest)
157 return
158 }
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400159 a, err := s.r.Find(slug)
160 if err != nil {
gioaa0fcdb2024-06-10 22:19:25 +0400161 http.Error(w, err.Error(), http.StatusInternalServerError)
162 return
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400163 }
gio308105e2024-04-19 13:12:13 +0400164 instances, err := s.m.FindAllAppInstances(slug)
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400165 if err != nil {
gioaa0fcdb2024-06-10 22:19:25 +0400166 http.Error(w, err.Error(), http.StatusInternalServerError)
167 return
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400168 }
gioaa0fcdb2024-06-10 22:19:25 +0400169 resp := app{a.Name(), a.Icon(), a.Description(), a.Slug(), instances}
170 w.Header().Set("Content-Type", "application/json")
171 if err := json.NewEncoder(w).Encode(resp); err != nil {
172 http.Error(w, err.Error(), http.StatusInternalServerError)
173 return
174 }
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400175}
176
gioaa0fcdb2024-06-10 22:19:25 +0400177func (s *AppManagerServer) handleInstance(w http.ResponseWriter, r *http.Request) {
178 slug, ok := mux.Vars(r)["slug"]
179 if !ok {
180 http.Error(w, "empty slug", http.StatusBadRequest)
181 return
182 }
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400183 instance, err := s.m.FindInstance(slug)
184 if err != nil {
gioaa0fcdb2024-06-10 22:19:25 +0400185 http.Error(w, err.Error(), http.StatusInternalServerError)
186 return
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400187 }
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400188 a, err := s.r.Find(instance.AppId)
189 if err != nil {
gioaa0fcdb2024-06-10 22:19:25 +0400190 http.Error(w, err.Error(), http.StatusInternalServerError)
191 return
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400192 }
gioaa0fcdb2024-06-10 22:19:25 +0400193 resp := app{a.Name(), a.Icon(), a.Description(), a.Slug(), []installer.AppInstanceConfig{*instance}}
194 w.Header().Set("Content-Type", "application/json")
195 if err := json.NewEncoder(w).Encode(resp); err != nil {
196 http.Error(w, err.Error(), http.StatusInternalServerError)
197 return
198 }
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400199}
200
gioaa0fcdb2024-06-10 22:19:25 +0400201func (s *AppManagerServer) handleAppInstall(w http.ResponseWriter, r *http.Request) {
202 slug, ok := mux.Vars(r)["slug"]
203 if !ok {
204 http.Error(w, "empty slug", http.StatusBadRequest)
205 return
206 }
207 contents, err := ioutil.ReadAll(r.Body)
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400208 if err != nil {
gioaa0fcdb2024-06-10 22:19:25 +0400209 http.Error(w, err.Error(), http.StatusInternalServerError)
210 return
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400211 }
212 var values map[string]any
213 if err := json.Unmarshal(contents, &values); err != nil {
gioaa0fcdb2024-06-10 22:19:25 +0400214 http.Error(w, err.Error(), http.StatusInternalServerError)
215 return
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400216 }
Giorgi Lekveishvili743fb432023-11-08 17:19:40 +0400217 log.Printf("Values: %+v\n", values)
gio3cdee592024-04-17 10:15:56 +0400218 a, err := installer.FindEnvApp(s.r, slug)
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400219 if err != nil {
gioaa0fcdb2024-06-10 22:19:25 +0400220 http.Error(w, err.Error(), http.StatusInternalServerError)
221 return
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400222 }
Giorgi Lekveishvili743fb432023-11-08 17:19:40 +0400223 log.Printf("Found application: %s\n", slug)
gio3cdee592024-04-17 10:15:56 +0400224 env, err := s.m.Config()
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400225 if err != nil {
gioaa0fcdb2024-06-10 22:19:25 +0400226 http.Error(w, err.Error(), http.StatusInternalServerError)
227 return
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400228 }
gio3cdee592024-04-17 10:15:56 +0400229 log.Printf("Configuration: %+v\n", env)
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400230 suffixGen := installer.NewFixedLengthRandomSuffixGenerator(3)
gio3af43942024-04-16 08:13:50 +0400231 suffix, err := suffixGen.Generate()
232 if err != nil {
gioaa0fcdb2024-06-10 22:19:25 +0400233 http.Error(w, err.Error(), http.StatusInternalServerError)
234 return
gio3af43942024-04-16 08:13:50 +0400235 }
gio44f621b2024-04-29 09:44:38 +0400236 instanceId := a.Slug() + suffix
gio3cdee592024-04-17 10:15:56 +0400237 appDir := fmt.Sprintf("/apps/%s", instanceId)
238 namespace := fmt.Sprintf("%s%s%s", env.NamespacePrefix, a.Namespace(), suffix)
gio778577f2024-04-29 09:44:38 +0400239 rr, err := s.m.Install(a, instanceId, appDir, namespace, values)
240 if err != nil {
gioaa0fcdb2024-06-10 22:19:25 +0400241 http.Error(w, err.Error(), http.StatusInternalServerError)
242 return
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400243 }
Giorgi Lekveishvilid2f3dca2023-12-20 09:31:30 +0400244 ctx, _ := context.WithTimeout(context.Background(), 2*time.Minute)
245 go s.reconciler.Reconcile(ctx)
gio778577f2024-04-29 09:44:38 +0400246 if _, ok := s.tasks[instanceId]; ok {
247 panic("MUST NOT REACH!")
248 }
249 t := tasks.NewMonitorRelease(s.h, rr)
250 t.OnDone(func(err error) {
251 delete(s.tasks, instanceId)
252 })
253 s.tasks[instanceId] = t
254 go t.Start()
gioaa0fcdb2024-06-10 22:19:25 +0400255 if _, err := fmt.Fprintf(w, "/instance/%s", instanceId); err != nil {
256 http.Error(w, err.Error(), http.StatusInternalServerError)
257 return
258 }
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400259}
260
gioaa0fcdb2024-06-10 22:19:25 +0400261func (s *AppManagerServer) handleAppUpdate(w http.ResponseWriter, r *http.Request) {
262 slug, ok := mux.Vars(r)["slug"]
263 if !ok {
264 http.Error(w, "empty slug", http.StatusBadRequest)
265 return
266 }
gioaa0fcdb2024-06-10 22:19:25 +0400267 contents, err := ioutil.ReadAll(r.Body)
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400268 if err != nil {
gioaa0fcdb2024-06-10 22:19:25 +0400269 http.Error(w, err.Error(), http.StatusInternalServerError)
270 return
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400271 }
272 var values map[string]any
273 if err := json.Unmarshal(contents, &values); err != nil {
gioaa0fcdb2024-06-10 22:19:25 +0400274 http.Error(w, err.Error(), http.StatusInternalServerError)
275 return
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400276 }
gio778577f2024-04-29 09:44:38 +0400277 if _, ok := s.tasks[slug]; ok {
gioaa0fcdb2024-06-10 22:19:25 +0400278 http.Error(w, "Update already in progress", http.StatusBadRequest)
279 return
gio778577f2024-04-29 09:44:38 +0400280 }
giof8843412024-05-22 16:38:05 +0400281 rr, err := s.m.Update(slug, values)
gio778577f2024-04-29 09:44:38 +0400282 if err != nil {
gioaa0fcdb2024-06-10 22:19:25 +0400283 http.Error(w, err.Error(), http.StatusInternalServerError)
284 return
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400285 }
Giorgi Lekveishvilid2f3dca2023-12-20 09:31:30 +0400286 ctx, _ := context.WithTimeout(context.Background(), 2*time.Minute)
287 go s.reconciler.Reconcile(ctx)
gio778577f2024-04-29 09:44:38 +0400288 t := tasks.NewMonitorRelease(s.h, rr)
289 t.OnDone(func(err error) {
290 delete(s.tasks, slug)
291 })
292 s.tasks[slug] = t
293 go t.Start()
gioaa0fcdb2024-06-10 22:19:25 +0400294 if _, err := fmt.Fprintf(w, "/instance/%s", slug); err != nil {
295 http.Error(w, err.Error(), http.StatusInternalServerError)
296 return
297 }
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400298}
299
gioaa0fcdb2024-06-10 22:19:25 +0400300func (s *AppManagerServer) handleAppRemove(w http.ResponseWriter, r *http.Request) {
301 slug, ok := mux.Vars(r)["slug"]
302 if !ok {
303 http.Error(w, "empty slug", http.StatusBadRequest)
304 return
305 }
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400306 if err := s.m.Remove(slug); err != nil {
gioaa0fcdb2024-06-10 22:19:25 +0400307 http.Error(w, err.Error(), http.StatusInternalServerError)
308 return
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400309 }
Giorgi Lekveishvilid2f3dca2023-12-20 09:31:30 +0400310 ctx, _ := context.WithTimeout(context.Background(), 2*time.Minute)
311 go s.reconciler.Reconcile(ctx)
gioaa0fcdb2024-06-10 22:19:25 +0400312 if _, err := fmt.Fprint(w, "/"); err != nil {
313 http.Error(w, err.Error(), http.StatusInternalServerError)
314 return
315 }
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400316}
317
Davit Tabidze3ec24cf2024-05-22 14:06:02 +0400318type PageData struct {
Davit Tabidze780a0d02024-08-05 20:53:26 +0400319 Apps []app
320 CurrentPage string
321 SearchTarget string
322 SearchValue string
Davit Tabidze3ec24cf2024-05-22 14:06:02 +0400323}
324
Davit Tabidze780a0d02024-08-05 20:53:26 +0400325func (s *AppManagerServer) handleAppsList(w http.ResponseWriter, r *http.Request) {
326 pageType := mux.Vars(r)["pageType"]
327 if pageType == "" {
328 pageType = "all"
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400329 }
Davit Tabidze780a0d02024-08-05 20:53:26 +0400330 searchQuery := r.FormValue("query")
331 apps, err := s.r.Filter(searchQuery)
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400332 if err != nil {
gioaa0fcdb2024-06-10 22:19:25 +0400333 http.Error(w, err.Error(), http.StatusInternalServerError)
334 return
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400335 }
Davit Tabidze3ec24cf2024-05-22 14:06:02 +0400336 resp := make([]app, 0)
Davit Tabidze780a0d02024-08-05 20:53:26 +0400337 for _, a := range apps {
Davit Tabidze3ec24cf2024-05-22 14:06:02 +0400338 instances, err := s.m.FindAllAppInstances(a.Slug())
339 if err != nil {
gioaa0fcdb2024-06-10 22:19:25 +0400340 http.Error(w, err.Error(), http.StatusInternalServerError)
341 return
Davit Tabidze3ec24cf2024-05-22 14:06:02 +0400342 }
Davit Tabidze780a0d02024-08-05 20:53:26 +0400343 switch pageType {
344 case "installed":
345 if len(instances) != 0 {
346 resp = append(resp, app{a.Name(), a.Icon(), a.Description(), a.Slug(), instances})
347 }
348 case "not-installed":
349 if len(instances) == 0 {
350 resp = append(resp, app{a.Name(), a.Icon(), a.Description(), a.Slug(), nil})
351 }
352 default:
Davit Tabidze3ec24cf2024-05-22 14:06:02 +0400353 resp = append(resp, app{a.Name(), a.Icon(), a.Description(), a.Slug(), instances})
354 }
355 }
356 data := PageData{
Davit Tabidze780a0d02024-08-05 20:53:26 +0400357 Apps: resp,
358 CurrentPage: pageType,
359 SearchTarget: pageType,
360 SearchValue: searchQuery,
Davit Tabidze3ec24cf2024-05-22 14:06:02 +0400361 }
gioaa0fcdb2024-06-10 22:19:25 +0400362 if err := s.tmpl.index.Execute(w, data); err != nil {
363 http.Error(w, err.Error(), http.StatusInternalServerError)
Davit Tabidze3ec24cf2024-05-22 14:06:02 +0400364 }
Davit Tabidze3ec24cf2024-05-22 14:06:02 +0400365}
366
367type appPageData struct {
gio3cdee592024-04-17 10:15:56 +0400368 App installer.EnvApp
369 Instance *installer.AppInstanceConfig
370 Instances []installer.AppInstanceConfig
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400371 AvailableNetworks []installer.Network
gio778577f2024-04-29 09:44:38 +0400372 Task tasks.Task
Davit Tabidze3ec24cf2024-05-22 14:06:02 +0400373 CurrentPage string
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400374}
375
gioaa0fcdb2024-06-10 22:19:25 +0400376func (s *AppManagerServer) handleAppUI(w http.ResponseWriter, r *http.Request) {
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400377 global, err := s.m.Config()
378 if err != nil {
gioaa0fcdb2024-06-10 22:19:25 +0400379 http.Error(w, err.Error(), http.StatusInternalServerError)
380 return
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400381 }
gioaa0fcdb2024-06-10 22:19:25 +0400382 slug, ok := mux.Vars(r)["slug"]
383 if !ok {
384 http.Error(w, "empty slug", http.StatusBadRequest)
385 return
386 }
gio3cdee592024-04-17 10:15:56 +0400387 a, err := installer.FindEnvApp(s.r, slug)
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400388 if err != nil {
gioaa0fcdb2024-06-10 22:19:25 +0400389 http.Error(w, err.Error(), http.StatusInternalServerError)
390 return
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400391 }
gio308105e2024-04-19 13:12:13 +0400392 instances, err := s.m.FindAllAppInstances(slug)
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400393 if err != nil {
gioaa0fcdb2024-06-10 22:19:25 +0400394 http.Error(w, err.Error(), http.StatusInternalServerError)
395 return
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400396 }
giocb34ad22024-07-11 08:01:13 +0400397 networks, err := s.m.CreateNetworks(global)
398 if err != nil {
399 http.Error(w, err.Error(), http.StatusInternalServerError)
400 return
401 }
Davit Tabidze3ec24cf2024-05-22 14:06:02 +0400402 data := appPageData{
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400403 App: a,
404 Instances: instances,
giocb34ad22024-07-11 08:01:13 +0400405 AvailableNetworks: networks,
Davit Tabidze3ec24cf2024-05-22 14:06:02 +0400406 CurrentPage: a.Name(),
407 }
gioaa0fcdb2024-06-10 22:19:25 +0400408 if err := s.tmpl.app.Execute(w, data); err != nil {
409 http.Error(w, err.Error(), http.StatusInternalServerError)
410 return
411 }
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400412}
413
gioaa0fcdb2024-06-10 22:19:25 +0400414func (s *AppManagerServer) handleInstanceUI(w http.ResponseWriter, r *http.Request) {
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400415 global, err := s.m.Config()
416 if err != nil {
gioaa0fcdb2024-06-10 22:19:25 +0400417 http.Error(w, err.Error(), http.StatusInternalServerError)
418 return
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400419 }
gioaa0fcdb2024-06-10 22:19:25 +0400420 slug, ok := mux.Vars(r)["slug"]
421 if !ok {
422 http.Error(w, "empty slug", http.StatusBadRequest)
423 return
424 }
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400425 instance, err := s.m.FindInstance(slug)
426 if err != nil {
gioaa0fcdb2024-06-10 22:19:25 +0400427 http.Error(w, err.Error(), http.StatusInternalServerError)
428 return
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400429 }
giof8843412024-05-22 16:38:05 +0400430 a, err := s.m.GetInstanceApp(instance.Id)
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400431 if err != nil {
gioaa0fcdb2024-06-10 22:19:25 +0400432 http.Error(w, err.Error(), http.StatusInternalServerError)
433 return
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400434 }
gio44f621b2024-04-29 09:44:38 +0400435 instances, err := s.m.FindAllAppInstances(a.Slug())
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400436 if err != nil {
gioaa0fcdb2024-06-10 22:19:25 +0400437 http.Error(w, err.Error(), http.StatusInternalServerError)
438 return
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400439 }
giocb34ad22024-07-11 08:01:13 +0400440 networks, err := s.m.CreateNetworks(global)
441 if err != nil {
442 http.Error(w, err.Error(), http.StatusInternalServerError)
443 return
444 }
gio778577f2024-04-29 09:44:38 +0400445 t := s.tasks[slug]
Davit Tabidze3ec24cf2024-05-22 14:06:02 +0400446 data := appPageData{
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400447 App: a,
gio778577f2024-04-29 09:44:38 +0400448 Instance: instance,
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400449 Instances: instances,
giocb34ad22024-07-11 08:01:13 +0400450 AvailableNetworks: networks,
gio778577f2024-04-29 09:44:38 +0400451 Task: t,
Davit Tabidze3ec24cf2024-05-22 14:06:02 +0400452 CurrentPage: instance.Id,
453 }
gioaa0fcdb2024-06-10 22:19:25 +0400454 if err := s.tmpl.app.Execute(w, data); err != nil {
455 http.Error(w, err.Error(), http.StatusInternalServerError)
456 return
457 }
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400458}