DodoApp: Use one network per external customer
Change-Id: I09864ad24a223b451c5877ad08bbc8960c80d41c
diff --git a/apps/app-runner/Dockerfile b/apps/app-runner/Dockerfile.golang.1.20.0
similarity index 68%
copy from apps/app-runner/Dockerfile
copy to apps/app-runner/Dockerfile.golang.1.20.0
index 964cd31..16f484f 100644
--- a/apps/app-runner/Dockerfile
+++ b/apps/app-runner/Dockerfile.golang.1.20.0
@@ -1,4 +1,4 @@
-FROM golang:1.22.0-bookworm
+FROM golang:1.20.0-alpine3.17
ARG TARGETARCH
diff --git a/apps/app-runner/Dockerfile b/apps/app-runner/Dockerfile.golang.1.22.0
similarity index 68%
rename from apps/app-runner/Dockerfile
rename to apps/app-runner/Dockerfile.golang.1.22.0
index 964cd31..af75fe6 100644
--- a/apps/app-runner/Dockerfile
+++ b/apps/app-runner/Dockerfile.golang.1.22.0
@@ -1,4 +1,4 @@
-FROM golang:1.22.0-bookworm
+FROM golang:1.22.0-alpine3.19
ARG TARGETARCH
diff --git a/apps/app-runner/Makefile b/apps/app-runner/Makefile
index 8a8936a..11a659d 100644
--- a/apps/app-runner/Makefile
+++ b/apps/app-runner/Makefile
@@ -1,7 +1,9 @@
repo_name ?= giolekva
podman ?= docker
ifeq ($(podman), podman)
-manifest_dest=docker://docker.io/$(repo_name)/app-runner:golang-1.22.0
+manifest_dest_golang_1_22_0=docker://docker.io/$(repo_name)/app-runner:golang-1.22.0
+manifest_dest_golang_1_20_0=docker://docker.io/$(repo_name)/app-runner:golang-1.20.0
+manifest_dest_hugo_latest=docker://docker.io/$(repo_name)/app-runner:hugo-latest
endif
clean:
@@ -21,19 +23,36 @@
build_amd64:
/usr/local/go/bin/go build -o app-runner_amd64 *.go
-push_arm64: clean build_arm64
- $(podman) build --platform linux/arm64 --tag=$(repo_name)/app-runner:golang-1.22.0-arm64 .
+# Golang 1.22.0
+
+push_golang_1_22_0_arm64: clean build_arm64
+ $(podman) build --platform linux/arm64 --tag=$(repo_name)/app-runner:golang-1.22.0-arm64 -f Dockerfile.golang.1.22.0 .
$(podman) push $(repo_name)/app-runner:golang-1.22.0-arm64
-push_amd64: clean build_amd64
- $(podman) build --platform linux/amd64 --tag=$(repo_name)/app-runner:golang-1.22.0-amd64 .
+push_golang_1_22_0_amd64: clean build_amd64
+ $(podman) build --platform linux/amd64 --tag=$(repo_name)/app-runner:golang-1.22.0-amd64 -f Dockerfile.golang.1.22.0 .
$(podman) push $(repo_name)/app-runner:golang-1.22.0-amd64
-push: push_arm64 push_amd64
+push_golang_1_22_0: push_golang_1_22_0_arm64 push_golang_1_22_0_amd64
$(podman) manifest create $(repo_name)/app-runner:golang-1.22.0 $(repo_name)/app-runner:golang-1.22.0-arm64 $(repo_name)/app-runner:golang-1.22.0-amd64
- $(podman) manifest push $(repo_name)/app-runner:golang-1.22.0 $(manifest_dest)
+ $(podman) manifest push $(repo_name)/app-runner:golang-1.22.0 $(manifest_dest_golang_1_22_0)
$(podman) manifest rm $(repo_name)/app-runner:golang-1.22.0
+# Golang 1.20.0
+
+push_golang_1_20_0_arm64: clean build_arm64
+ $(podman) build --platform linux/arm64 --tag=$(repo_name)/app-runner:golang-1.20.0-arm64 -f Dockerfile.golang.1.20.0 .
+ $(podman) push $(repo_name)/app-runner:golang-1.20.0-arm64
+
+push_golang_1_20_0_amd64: clean build_amd64
+ $(podman) build --platform linux/amd64 --tag=$(repo_name)/app-runner:golang-1.20.0-amd64 -f Dockerfile.golang.1.20.0 .
+ $(podman) push $(repo_name)/app-runner:golang-1.20.0-amd64
+
+push_golang_1_20_0: push_golang_1_20_0_arm64 push_golang_1_20_0_amd64
+ $(podman) manifest create $(repo_name)/app-runner:golang-1.20.0 $(repo_name)/app-runner:golang-1.20.0-arm64 $(repo_name)/app-runner:golang-1.20.0-amd64
+ $(podman) manifest push $(repo_name)/app-runner:golang-1.20.0 $(manifest_dest_golang_1_20_0)
+ $(podman) manifest rm $(repo_name)/app-runner:golang-1.20.0
+
# Hugo
push_hugo_arm64: clean build_arm64
@@ -46,5 +65,8 @@
push_hugo: push_hugo_arm64 push_hugo_amd64
$(podman) manifest create $(repo_name)/app-runner:hugo-latest $(repo_name)/app-runner:hugo-latest-arm64 $(repo_name)/app-runner:hugo-latest-amd64
- $(podman) manifest push $(repo_name)/app-runner:hugo-latest $(manifest_dest)
+ $(podman) manifest push $(repo_name)/app-runner:hugo-latest $(manifest_dest_hugo_latest)
$(podman) manifest rm $(repo_name)/app-runner:hugo-latest
+
+# all
+push: push_golang_1_22_0 push_golang_1_20_0 push_hugo
diff --git a/core/installer/cmd/dodo_app.go b/core/installer/cmd/dodo_app.go
index 5fc6e3e..f6d9c43 100644
--- a/core/installer/cmd/dodo_app.go
+++ b/core/installer/cmd/dodo_app.go
@@ -195,6 +195,7 @@
nsc,
jc,
env,
+ !dodoAppFlags.external,
)
if err != nil {
return err
diff --git a/core/installer/welcome/app-tmpl/golang-1.20.0/go.mod.gotmpl b/core/installer/welcome/app-tmpl/golang-1.20.0/go.mod.gotmpl
index cafcee0..190c9ac 100755
--- a/core/installer/welcome/app-tmpl/golang-1.20.0/go.mod.gotmpl
+++ b/core/installer/welcome/app-tmpl/golang-1.20.0/go.mod.gotmpl
@@ -1,3 +1,3 @@
module dodo.app
-go 1.20.0
\ No newline at end of file
+go 1.20
\ No newline at end of file
diff --git a/core/installer/welcome/dodo_app.go b/core/installer/welcome/dodo_app.go
index e6f3d37..462a95d 100644
--- a/core/installer/welcome/dodo_app.go
+++ b/core/installer/welcome/dodo_app.go
@@ -33,7 +33,7 @@
const (
ConfigRepoName = "config"
- namespacesFile = "/namespaces.json"
+ appConfigsFile = "/apps.json"
loginPath = "/login"
logoutPath = "/logout"
staticPath = "/static"
@@ -91,9 +91,15 @@
nsc installer.NamespaceCreator
jc installer.JobCreator
workers map[string]map[string]struct{}
- appNs map[string]string
+ appConfigs map[string]appConfig
tmplts dodoAppTmplts
appTmpls AppTmplStore
+ allowNetworkReuse bool
+}
+
+type appConfig struct {
+ Namespace string `json:"namespace"`
+ Network string `json:"network"`
}
// TODO(gio): Initialize appNs on startup
@@ -113,6 +119,7 @@
nsc installer.NamespaceCreator,
jc installer.JobCreator,
env installer.EnvConfig,
+ allowNetworkReuse bool,
) (*DodoAppServer, error) {
tmplts, err := parseTemplatesDodoApp(dodoAppTmplFS)
if err != nil {
@@ -144,18 +151,19 @@
nsc,
jc,
map[string]map[string]struct{}{},
- map[string]string{},
+ map[string]appConfig{},
tmplts,
appTmpls,
+ allowNetworkReuse,
}
config, err := client.GetRepo(ConfigRepoName)
if err != nil {
return nil, err
}
- r, err := config.Reader(namespacesFile)
+ r, err := config.Reader(appConfigsFile)
if err == nil {
defer r.Close()
- if err := json.NewDecoder(r).Decode(&s.appNs); err != nil {
+ if err := json.NewDecoder(r).Decode(&s.appConfigs); err != nil {
return nil, err
}
} else if !errors.Is(err, fs.ErrNotExist) {
@@ -432,7 +440,7 @@
if err != nil {
return
}
- if err := s.updateDodoApp(req.Repository.Name, s.appNs[req.Repository.Name], networks); err != nil {
+ if err := s.updateDodoApp(req.Repository.Name, s.appConfigs[req.Repository.Name].Namespace, networks); err != nil {
if err := s.st.CreateCommit(req.Repository.Name, req.After, err.Error()); err != nil {
fmt.Printf("Error: %s\n", err.Error())
return
@@ -526,7 +534,7 @@
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
- if err := s.CreateApp(user, appName, appType, adminPublicKey, network, subdomain); err != nil {
+ if err := s.createApp(user, appName, appType, network, subdomain); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
@@ -546,6 +554,7 @@
}
func (s *DodoAppServer) handleAPICreateApp(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Access-Control-Allow-Origin", "*")
var req apiCreateAppReq
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
@@ -585,7 +594,7 @@
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
- if err := s.CreateApp(user, appName, req.AppType, req.AdminPublicKey, req.Network, req.Subdomain); err != nil {
+ if err := s.createApp(user, appName, req.AppType, req.Network, req.Subdomain); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
@@ -593,17 +602,32 @@
AppName: appName,
Password: password,
}
- w.Header().Set("Access-Control-Allow-Origin", "*")
if err := json.NewEncoder(w).Encode(resp); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
}
-func (s *DodoAppServer) CreateApp(user, appName, appType, adminPublicKey, network, subdomain string) error {
+func (s *DodoAppServer) isNetworkUseAllowed(network string) bool {
+ if s.allowNetworkReuse {
+ return true
+ }
+ for _, cfg := range s.appConfigs {
+ if strings.ToLower(cfg.Network) == network {
+ return false
+ }
+ }
+ return true
+}
+
+func (s *DodoAppServer) createApp(user, appName, appType, network, subdomain string) error {
s.l.Lock()
defer s.l.Unlock()
fmt.Printf("Creating app: %s\n", appName)
+ network = strings.ToLower(network)
+ if !s.isNetworkUseAllowed(network) {
+ return fmt.Errorf("network already used: %s", network)
+ }
if ok, err := s.client.RepoExists(appName); err != nil {
return err
} else if ok {
@@ -613,7 +637,7 @@
if err != nil {
return err
}
- n, ok := installer.NetworkMap(networks)[strings.ToLower(network)]
+ n, ok := installer.NetworkMap(networks)[network]
if !ok {
return fmt.Errorf("network not found: %s\n", network)
}
@@ -638,26 +662,26 @@
return err
}
namespace := fmt.Sprintf("%s%s%s", s.env.NamespacePrefix, app.Namespace(), suffix)
- s.appNs[appName] = namespace
+ s.appConfigs[appName] = appConfig{namespace, network}
if err := s.updateDodoApp(appName, namespace, networks); err != nil {
return err
}
- repo, err := s.client.GetRepo(ConfigRepoName)
+ configRepo, err := s.client.GetRepo(ConfigRepoName)
if err != nil {
return err
}
hf := installer.NewGitHelmFetcher()
- m, err := installer.NewAppManager(repo, s.nsc, s.jc, hf, "/")
+ m, err := installer.NewAppManager(configRepo, s.nsc, s.jc, hf, "/")
if err != nil {
return err
}
- if err := repo.Do(func(fs soft.RepoFS) (string, error) {
- w, err := fs.Writer(namespacesFile)
+ if err := configRepo.Do(func(fs soft.RepoFS) (string, error) {
+ w, err := fs.Writer(appConfigsFile)
if err != nil {
return "", err
}
defer w.Close()
- if err := json.NewEncoder(w).Encode(s.appNs); err != nil {
+ if err := json.NewEncoder(w).Encode(s.appConfigs); err != nil {
return "", err
}
if _, err := m.Install(
@@ -815,6 +839,9 @@
}
func (s *DodoAppServer) handleAPIPublicData(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Access-Control-Allow-Origin", "*")
+ s.l.Lock()
+ defer s.l.Unlock()
networks, err := s.getNetworks("")
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
@@ -822,7 +849,9 @@
}
var ret publicData
for _, n := range networks {
- ret.Networks = append(ret.Networks, publicNetworkData{n.Name, n.Domain})
+ if s.isNetworkUseAllowed(strings.ToLower(n.Name)) {
+ ret.Networks = append(ret.Networks, publicNetworkData{n.Name, n.Domain})
+ }
}
for _, t := range s.appTmpls.Types() {
ret.Types = append(ret.Types, strings.ReplaceAll(t, "-", ":"))