DodoApp: Add network definitions to app.schema.json
Change-Id: Id4c0b9b3e8cfc0475f3ecc0d9b47a6dbf676da6a
diff --git a/core/installer/server/dodo-app/static/schemas/app.schema.json b/core/installer/server/dodo-app/schemas/app.schema.json
similarity index 99%
rename from core/installer/server/dodo-app/static/schemas/app.schema.json
rename to core/installer/server/dodo-app/schemas/app.schema.json
index 5450358..60e4f0c 100644
--- a/core/installer/server/dodo-app/static/schemas/app.schema.json
+++ b/core/installer/server/dodo-app/schemas/app.schema.json
@@ -202,7 +202,7 @@
"properties": {
"network": {
"type": "string",
- "minLength": 1
+ "oneOf": {{ .Networks }}
},
"subdomain": {
"type": "string",
diff --git a/core/installer/server/dodo-app/server.go b/core/installer/server/dodo-app/server.go
index 858afa8..609ce9f 100644
--- a/core/installer/server/dodo-app/server.go
+++ b/core/installer/server/dodo-app/server.go
@@ -16,6 +16,7 @@
"strconv"
"strings"
"sync"
+ ttemplate "text/template"
"time"
"golang.org/x/crypto/bcrypt"
@@ -40,8 +41,8 @@
//go:embed static/*
var staticAssets embed.FS
-//go:embed static/schemas/app.schema.json
-var dodoAppJsonSchema []byte
+//go:embed schemas/app.schema.json
+var dodoAppJsonSchema string
const (
ConfigRepoName = "config"
@@ -123,6 +124,7 @@
fetchUsersAddr string
reconciler tasks.Reconciler
logs map[string]string
+ schemaTmpl *ttemplate.Template
}
type appConfig struct {
@@ -166,6 +168,10 @@
if err != nil {
return nil, err
}
+ schemaTmpl, err := ttemplate.New("app.schema.json").Parse(dodoAppJsonSchema)
+ if err != nil {
+ return nil, err
+ }
s := &Server{
&sync.Mutex{},
st,
@@ -194,6 +200,7 @@
fetchUsersAddr,
reconciler,
map[string]string{},
+ schemaTmpl,
}
config, err := client.GetRepo(ConfigRepoName)
if err != nil {
@@ -230,7 +237,7 @@
go func() {
r := mux.NewRouter()
r.Use(s.mwAuth)
- r.HandleFunc(schemasPath+"app.schema.json", s.handleSchema).Methods(http.MethodGet)
+ r.HandleFunc(schemasPath+"{user}/app.schema.json", s.handleSchema).Methods(http.MethodGet)
r.PathPrefix(staticPath).Handler(server.NewCachingHandler(http.FileServer(http.FS(staticAssets))))
r.HandleFunc(logoutPath, s.handleLogout).Methods(http.MethodGet)
r.HandleFunc(apiPublicData, s.handleAPIPublicData)
@@ -356,9 +363,38 @@
})
}
+type schemaNetwork struct {
+ Value string `json:"const"`
+}
+
func (s *Server) handleSchema(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/schema+json")
- w.Write(dodoAppJsonSchema)
+ vars := mux.Vars(r)
+ user, ok := vars["user"]
+ if !ok {
+ http.Error(w, "no user", http.StatusBadRequest)
+ return
+ }
+ networks, err := s.getNetworks(user)
+ if err != nil {
+ http.Error(w, err.Error(), http.StatusInternalServerError)
+ return
+ }
+ var names []schemaNetwork
+ for _, n := range networks {
+ names = append(names, schemaNetwork{n.Name})
+ }
+ var tmp strings.Builder
+ if err := json.NewEncoder(&tmp).Encode(names); err != nil {
+ http.Error(w, err.Error(), http.StatusInternalServerError)
+ return
+ }
+ if err := s.schemaTmpl.Execute(w, map[string]any{
+ "Networks": tmp.String(),
+ }); err != nil {
+ http.Error(w, err.Error(), http.StatusInternalServerError)
+ return
+ }
}
func (s *Server) handleLogout(w http.ResponseWriter, r *http.Request) {
@@ -1074,7 +1110,7 @@
if err != nil {
return err
}
- files, err := s.renderAppConfigTemplate(appType, n, subdomain)
+ files, err := s.renderAppConfigTemplate(user, appType, n, subdomain)
if err != nil {
return err
}
@@ -1093,7 +1129,7 @@
if err != nil {
return err
}
- network, branchCfg, err := createDevBranchAppConfig(appCfg, toBranch, user)
+ network, branchCfg, err := createDevBranchAppConfig(appCfg, toBranch, user, s.selfPublic)
if err != nil {
return err
}
@@ -1444,13 +1480,13 @@
return ret, nil
}
-func (s *Server) renderAppConfigTemplate(appType string, network installer.Network, subdomain string) (map[string][]byte, error) {
+func (s *Server) renderAppConfigTemplate(user, appType string, network installer.Network, subdomain string) (map[string][]byte, error) {
appType = strings.Replace(appType, ":", "-", 1)
appTmpl, err := s.appTmpls.Find(appType)
if err != nil {
return nil, err
}
- return appTmpl.Render(fmt.Sprintf("%s/schemas/app.schema.json", s.selfPublic), network, subdomain)
+ return appTmpl.Render(fmt.Sprintf("%s/schemas/%s/app.schema.json", s.selfPublic, user), network, subdomain)
}
func generatePassword() string {
@@ -1825,7 +1861,7 @@
return ret, nil
}
-func createDevBranchAppConfig(from []byte, branch, username string) (string, []byte, error) {
+func createDevBranchAppConfig(from []byte, branch, username, publicAddr string) (string, []byte, error) {
cfg, err := installer.ParseCueAppConfig(installer.CueAppData{
"app.cue": from,
})
@@ -1864,6 +1900,7 @@
"enabled": true,
"username": username,
}
+ newCfg["$schema"] = fmt.Sprintf("%s/schemas/%s/app.schema.json", publicAddr, username)
buf, err := json.MarshalIndent(newCfg, "", "\t")
if err != nil {
return "", nil, err
diff --git a/core/installer/server/dodo-app/server_test.go b/core/installer/server/dodo-app/server_test.go
index 8bc0c59..513594e 100644
--- a/core/installer/server/dodo-app/server_test.go
+++ b/core/installer/server/dodo-app/server_test.go
@@ -18,7 +18,7 @@
}
}
}`)
- network, newCfg, err := createDevBranchAppConfig(cfg, "foo", "bar")
+ network, newCfg, err := createDevBranchAppConfig(cfg, "foo", "bar", "https://foo.bar")
if err != nil {
t.Fatal(err)
}