blob: e032393973d95e60fff676049f1b89d881f32fe6 [file] [log] [blame]
gio0eaf2712024-04-14 13:08:46 +04001package welcome
2
3import (
4 "encoding/json"
5 "fmt"
6 "io"
7 "net/http"
8 "strings"
9 "time"
10
11 "github.com/giolekva/pcloud/core/installer"
12 "github.com/giolekva/pcloud/core/installer/soft"
13)
14
15type DodoAppServer struct {
16 port int
17 sshKey string
18 client soft.Client
19 namespace string
20 env installer.EnvConfig
giof8843412024-05-22 16:38:05 +040021 jc installer.JobCreator
gio266c04f2024-07-03 14:18:45 +040022 workers map[string]map[string]struct{}
gio0eaf2712024-04-14 13:08:46 +040023}
24
25func NewDodoAppServer(
26 port int,
27 sshKey string,
28 client soft.Client,
29 namespace string,
giof8843412024-05-22 16:38:05 +040030 jc installer.JobCreator,
gio0eaf2712024-04-14 13:08:46 +040031 env installer.EnvConfig,
32) *DodoAppServer {
33 return &DodoAppServer{
34 port,
35 sshKey,
36 client,
37 namespace,
38 env,
giof8843412024-05-22 16:38:05 +040039 jc,
gio266c04f2024-07-03 14:18:45 +040040 map[string]map[string]struct{}{},
gio0eaf2712024-04-14 13:08:46 +040041 }
42}
43
44func (s *DodoAppServer) Start() error {
45 http.HandleFunc("/update", s.handleUpdate)
46 http.HandleFunc("/register-worker", s.handleRegisterWorker)
gio70be3e52024-06-26 18:27:19 +040047 http.HandleFunc("/api/add-admin-key", s.handleAddAdminKey)
gio0eaf2712024-04-14 13:08:46 +040048 return http.ListenAndServe(fmt.Sprintf(":%d", s.port), nil)
49}
50
51type updateReq struct {
gio266c04f2024-07-03 14:18:45 +040052 Ref string `json:"ref"`
53 Repository struct {
54 Name string `json:"name"`
55 } `json:"repository"`
gio0eaf2712024-04-14 13:08:46 +040056}
57
58func (s *DodoAppServer) handleUpdate(w http.ResponseWriter, r *http.Request) {
59 fmt.Println("update")
60 var req updateReq
61 var contents strings.Builder
62 io.Copy(&contents, r.Body)
63 c := contents.String()
64 fmt.Println(c)
65 if err := json.NewDecoder(strings.NewReader(c)).Decode(&req); err != nil {
66 fmt.Println(err)
67 return
68 }
gio266c04f2024-07-03 14:18:45 +040069 if req.Ref != "refs/heads/master" || strings.HasPrefix(req.Repository.Name, "dodo") {
gio0eaf2712024-04-14 13:08:46 +040070 return
71 }
72 go func() {
73 time.Sleep(20 * time.Second)
gio266c04f2024-07-03 14:18:45 +040074 if err := UpdateDodoApp(req.Repository.Name, s.client, s.namespace, s.sshKey, s.jc, &s.env); err != nil {
gio0eaf2712024-04-14 13:08:46 +040075 fmt.Println(err)
76 }
77 }()
gio266c04f2024-07-03 14:18:45 +040078 for addr, _ := range s.workers[req.Repository.Name] {
gio0eaf2712024-04-14 13:08:46 +040079 go func() {
80 // TODO(gio): make port configurable
81 http.Get(fmt.Sprintf("http://%s:3000/update", addr))
82 }()
83 }
84}
85
86type registerWorkerReq struct {
gio266c04f2024-07-03 14:18:45 +040087 AppId string `json:"appId"`
gio0eaf2712024-04-14 13:08:46 +040088 Address string `json:"address"`
89}
90
91func (s *DodoAppServer) handleRegisterWorker(w http.ResponseWriter, r *http.Request) {
92 var req registerWorkerReq
93 if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
94 http.Error(w, err.Error(), http.StatusInternalServerError)
95 return
96 }
gio266c04f2024-07-03 14:18:45 +040097 if _, ok := s.workers[req.AppId]; !ok {
98 s.workers[req.AppId] = map[string]struct{}{}
99 }
100 s.workers[req.AppId][req.Address] = struct{}{}
gio0eaf2712024-04-14 13:08:46 +0400101}
102
gio70be3e52024-06-26 18:27:19 +0400103type addAdminKeyReq struct {
104 Public string `json:"public"`
105}
106
107func (s *DodoAppServer) handleAddAdminKey(w http.ResponseWriter, r *http.Request) {
108 var req addAdminKeyReq
109 if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
110 http.Error(w, err.Error(), http.StatusBadRequest)
111 return
112 }
113 if err := s.client.AddPublicKey("admin", req.Public); err != nil {
114 http.Error(w, err.Error(), http.StatusInternalServerError)
115 return
116 }
117}
118
gio266c04f2024-07-03 14:18:45 +0400119func UpdateDodoApp(name string, client soft.Client, namespace string, sshKey string, jc installer.JobCreator, env *installer.EnvConfig) error {
120 repo, err := client.GetRepo(name)
gio0eaf2712024-04-14 13:08:46 +0400121 if err != nil {
122 return err
123 }
giof8843412024-05-22 16:38:05 +0400124 nsc := installer.NewNoOpNamespaceCreator()
gio0eaf2712024-04-14 13:08:46 +0400125 if err != nil {
126 return err
127 }
giof8843412024-05-22 16:38:05 +0400128 hf := installer.NewGitHelmFetcher()
129 m, err := installer.NewAppManager(repo, nsc, jc, hf, "/.dodo")
gio0eaf2712024-04-14 13:08:46 +0400130 if err != nil {
131 return err
132 }
133 appCfg, err := soft.ReadFile(repo, "app.cue")
134 fmt.Println(string(appCfg))
135 if err != nil {
136 return err
137 }
138 app, err := installer.NewDodoApp(appCfg)
139 if err != nil {
140 return err
141 }
giof8843412024-05-22 16:38:05 +0400142 lg := installer.GitRepositoryLocalChartGenerator{"app", namespace}
giof71a0832024-06-27 14:45:45 +0400143 if _, err := m.Install(
144 app,
145 "app",
146 "/.dodo/app",
147 namespace,
148 map[string]any{
149 "repoAddr": repo.FullAddress(),
gio266c04f2024-07-03 14:18:45 +0400150 "appId": name,
giof71a0832024-06-27 14:45:45 +0400151 "sshPrivateKey": sshKey,
152 },
153 installer.WithConfig(env),
154 installer.WithLocalChartGenerator(lg),
155 installer.WithBranch("dodo"),
156 installer.WithForce(),
157 ); err != nil {
gio0eaf2712024-04-14 13:08:46 +0400158 return err
159 }
160 return nil
161}