AppRunner: Reload app on configuration change
Change-Id: I2c5ea0eaf3453815c8c89c9290edba250ca4fbaa
diff --git a/apps/app-runner/main.go b/apps/app-runner/main.go
index b11a977..6aa487c 100644
--- a/apps/app-runner/main.go
+++ b/apps/app-runner/main.go
@@ -11,6 +11,7 @@
"path/filepath"
"strings"
"syscall"
+ "time"
"golang.org/x/crypto/ssh"
@@ -94,6 +95,19 @@
}, nil
}
+func readRunConfiguration(p string) []Command {
+ r, err := os.Open(p)
+ if err != nil {
+ panic(err)
+ }
+ defer r.Close()
+ var cmds []Command
+ if err := json.NewDecoder(r).Decode(&cmds); err != nil {
+ log.Fatal(err)
+ }
+ return cmds
+}
+
func main() {
flag.Parse()
self, ok := os.LookupEnv("SELF_IP")
@@ -121,15 +135,7 @@
panic(err)
}
}
- r, err := os.Open(*runCfg)
- if err != nil {
- panic(err)
- }
- defer r.Close()
- var cmds []Command
- if err := json.NewDecoder(r).Decode(&cmds); err != nil {
- panic(err)
- }
+ cmds := readRunConfiguration(*runCfg)
s := NewServer(*agentMode, *port, *appId, *service, id, *repoAddr, *branch, *rootDir, signer, *appDir, cmds, self, *managerAddr)
go func() {
if err := s.Start(); err != nil {
@@ -139,8 +145,51 @@
os.Exit(0)
}
}()
+ go func() {
+ for {
+ time.Sleep(30 * time.Second)
+ newCmds := readRunConfiguration(*runCfg)
+ if commandsChanged(cmds, newCmds) {
+ s.UpdateRunCommands(newCmds)
+ cmds = newCmds
+ }
+ }
+ }()
sigChan := make(chan os.Signal, 1)
signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)
<-sigChan
s.Stop()
}
+
+func commandsChanged(a, b []Command) bool {
+ if len(a) != len(b) {
+ return true
+ }
+ for i, x := range a {
+ y := b[i]
+ if x.Bin != y.Bin {
+ return true
+ }
+ if len(x.Args) != len(y.Args) {
+ return true
+ }
+ for j, k := range x.Args {
+ l := y.Args[j]
+ if k != l {
+ return true
+ }
+ }
+ if !*agentMode {
+ if len(x.Env) != len(y.Env) {
+ return true
+ }
+ for j, k := range x.Env {
+ l := y.Env[j]
+ if k != l {
+ return true
+ }
+ }
+ }
+ }
+ return false
+}
diff --git a/apps/app-runner/server.go b/apps/app-runner/server.go
index 44e86fc..080a134 100644
--- a/apps/app-runner/server.go
+++ b/apps/app-runner/server.go
@@ -128,6 +128,13 @@
}
}
+func (s *Server) UpdateRunCommands(runCommands []Command) {
+ s.l.Lock()
+ defer s.l.Unlock()
+ s.runCommands = runCommands
+ s.run()
+}
+
func (s *Server) handleQuit(w http.ResponseWriter, r *http.Request) {
go s.Stop()
}
diff --git a/charts/app-runner/templates/install.yaml b/charts/app-runner/templates/install.yaml
index 8bc558b..212fc85 100644
--- a/charts/app-runner/templates/install.yaml
+++ b/charts/app-runner/templates/install.yaml
@@ -57,8 +57,8 @@
metadata:
name: {{ .Values.name }}-app
namespace: {{ .Release.Namespace }}
- annotations:
- dodo.cloud/config-checksum: {{ sha256sum .Values.runCfg }}
+ # annotations:
+ # dodo.cloud/config-checksum: {{ sha256sum .Values.runCfg }}
spec:
selector:
matchLabels:
@@ -68,8 +68,8 @@
metadata:
labels:
app: {{ .Values.name }}-app
- annotations:
- dodo.cloud/config-checksum: {{ sha256sum .Values.runCfg }}
+ # annotations:
+ # dodo.cloud/config-checksum: {{ sha256sum .Values.runCfg }}
spec:
runtimeClassName: {{ .Values.runtimeClassName }}
volumes:
diff --git a/core/installer/app_configs/dodo_app.cue b/core/installer/app_configs/dodo_app.cue
index 4ec89ea..c763d4b 100644
--- a/core/installer/app_configs/dodo_app.cue
+++ b/core/installer/app_configs/dodo_app.cue
@@ -451,13 +451,8 @@
lastCmdEnv: [...string]
runConfiguration: [{
- bin: "npm"
- args: ["install"]
+ bin: "npm install"
},
- {
- bin: "npm"
- args: ["ci"]
- },
for c in preBuildCommands {
{
bin: c.bin
@@ -466,12 +461,10 @@
}
},
{
- bin: "npm"
- args: ["run", "build"]
+ bin: "npm run build"
env: lastCmdEnv
}, {
- bin: "node"
- args: ["./\(buildPath)/index.js"]
+ bin: "npm run start"
env: lastCmdEnv
}]
@@ -507,19 +500,18 @@
name: "claude"
anthropicApiKey?: string
}
- _geminiApiKey?: string
- _anthropicApiKey?: string
+ _llmApiKey?: string
if model.name == "gemini" && model.geminiApiKey != _|_ {
- _geminiApiKey: model.geminiApiKey
+ _llmApiKey: model.geminiApiKey
}
if model.name == "gemini" && model.geminiApiKey == _|_ && input.geminiApiKey != _|_ {
- _geminiApiKey: input.geminiApiKey
+ _llmApiKey: input.geminiApiKey
}
if model.name == "claude" && model.anthropicApiKey != _|_ {
- _anthropicApiKey: model.anthropicApiKey
+ _llmApiKey: model.anthropicApiKey
}
if model.name == "claude" && model.anthropicApiKey == _|_ && input.anthropicApiKey != _|_ {
- _anthropicApiKey: input.anthropicApiKey
+ _llmApiKey: input.anthropicApiKey
}
agentPort: 2001
@@ -552,18 +544,10 @@
}, {
name: "DODO_API_BASE_ADDR"
value: input.managerAddr
- },
- if _geminiApiKey != _|_ {
- name: "GEMINI_API_KEY"
- value: _geminiApiKey
- },
- if _anthropicApiKey != _|_ {
- name: "ANTHROPIC_API_KEY"
- value: _anthropicApiKey
- },
- ]
+ }]
...
}
+
rootDir: "/dodo/volume/\(_name)-apps"
lastCmdEnv: [...string]
@@ -571,7 +555,7 @@
_sessionId: input["sketch_\(name)_session_id"]
runConfiguration: [{
- bin: "sketch -verbose -unsafe -skaband-addr=\"\" -addr=\"0.0.0.0:2001\" -model=\(model.name) -session-id=\"\(_sessionId)\""
+ bin: "sketch -verbose -unsafe -skaband-addr=\"\" -addr=\"0.0.0.0:2001\" -model=\(model.name) -llm-api-key=\"(_llmApiKey)\" -session-id=\"\(_sessionId)\""
env: lastCmdEnv
}]
}