Dodo APP: infrastructure to deploy app by pusing to Git repo
Change-Id: I4034c6893255581b014ddb207c844261cb34202b
diff --git a/core/installer/cmd/dodo_app.go b/core/installer/cmd/dodo_app.go
new file mode 100644
index 0000000..d9f9a69
--- /dev/null
+++ b/core/installer/cmd/dodo_app.go
@@ -0,0 +1,175 @@
+package main
+
+import (
+ "encoding/json"
+ "errors"
+ "fmt"
+ "log"
+ "os"
+
+ "github.com/giolekva/pcloud/core/installer"
+ "github.com/giolekva/pcloud/core/installer/soft"
+ "github.com/giolekva/pcloud/core/installer/welcome"
+
+ "github.com/spf13/cobra"
+)
+
+var dodoAppFlags struct {
+ port int
+ sshKey string
+ repoAddr string
+ self string
+ namespace string
+ envConfig string
+}
+
+func dodoAppCmd() *cobra.Command {
+ cmd := &cobra.Command{
+ Use: "dodo-app",
+ RunE: dodoAppCmdRun,
+ }
+ cmd.Flags().IntVar(
+ &dodoAppFlags.port,
+ "port",
+ 8080,
+ "",
+ )
+ cmd.Flags().StringVar(
+ &dodoAppFlags.repoAddr,
+ "repo-addr",
+ "",
+ "",
+ )
+ cmd.Flags().StringVar(
+ &dodoAppFlags.sshKey,
+ "ssh-key",
+ "",
+ "",
+ )
+ cmd.Flags().StringVar(
+ &dodoAppFlags.self,
+ "self",
+ "",
+ "",
+ )
+ cmd.Flags().StringVar(
+ &dodoAppFlags.namespace,
+ "namespace",
+ "",
+ "",
+ )
+ cmd.Flags().StringVar(
+ &dodoAppFlags.envConfig,
+ "env-config",
+ "",
+ "",
+ )
+ return cmd
+}
+
+func dodoAppCmdRun(cmd *cobra.Command, args []string) error {
+ envConfig, err := os.Open(dodoAppFlags.envConfig)
+ if err != nil {
+ return err
+ }
+ defer envConfig.Close()
+ var env installer.EnvConfig
+ if err := json.NewDecoder(envConfig).Decode(&env); err != nil {
+ return err
+ }
+ sshKey, err := os.ReadFile(dodoAppFlags.sshKey)
+ if err != nil {
+ return err
+ }
+ softClient, err := soft.NewClient(dodoAppFlags.repoAddr, sshKey, log.Default())
+ if err != nil {
+ return err
+ }
+ if err := softClient.AddRepository("app"); err == nil {
+ repo, err := softClient.GetRepo("app")
+ if err != nil {
+ return err
+ }
+ if err := initRepo(repo); err != nil {
+ return err
+ }
+ if err := welcome.UpdateDodoApp(softClient, dodoAppFlags.namespace, string(sshKey), &env); err != nil {
+ return err
+ }
+ if err := softClient.AddWebhook("app", fmt.Sprintf("http://%s/update", dodoAppFlags.self), "--active=true", "--events=push", "--content-type=json"); err != nil {
+ return err
+ }
+ } else if !errors.Is(err, soft.ErrorAlreadyExists) {
+ return err
+ }
+ s := welcome.NewDodoAppServer(dodoAppFlags.port, string(sshKey), softClient, dodoAppFlags.namespace, env)
+ return s.Start()
+}
+
+const goMod = `module dodo.app
+
+go 1.18
+`
+
+const mainGo = `package main
+
+import (
+ "flag"
+ "fmt"
+ "log"
+ "net/http"
+)
+
+var port = flag.Int("port", 8080, "Port to listen on")
+
+func handler(w http.ResponseWriter, r *http.Request) {
+ fmt.Fprintln(w, "Hello from Dodo App!")
+}
+
+func main() {
+ flag.Parse()
+ http.HandleFunc("/", handler)
+ log.Fatal(http.ListenAndServe(fmt.Sprintf(":%d", *port), nil))
+}
+`
+
+const appCue = `app: {
+ type: "golang:1.22.0"
+ run: "main.go"
+ ingress: {
+ network: "Private" // or Public
+ subdomain: "testapp"
+ auth: enabled: false
+ }
+}
+`
+
+func initRepo(repo soft.RepoIO) error {
+ return repo.Do(func(fs soft.RepoFS) (string, error) {
+ {
+ w, err := fs.Writer("go.mod")
+ if err != nil {
+ return "", err
+ }
+ defer w.Close()
+ fmt.Fprint(w, goMod)
+ }
+ {
+ w, err := fs.Writer("main.go")
+ if err != nil {
+ return "", err
+ }
+ defer w.Close()
+ fmt.Fprintf(w, "%s", mainGo)
+ }
+ {
+ w, err := fs.Writer("app.cue")
+ if err != nil {
+ return "", err
+ }
+ defer w.Close()
+ fmt.Fprint(w, appCue)
+ }
+ return "go web app template", nil
+ })
+}
diff --git a/core/installer/cmd/main.go b/core/installer/cmd/main.go
index 5b05381..568efae 100644
--- a/core/installer/cmd/main.go
+++ b/core/installer/cmd/main.go
@@ -28,6 +28,7 @@
rootCmd.AddCommand(welcomeCmd())
rootCmd.AddCommand(rewriteCmd())
rootCmd.AddCommand(launcherCmd())
+ rootCmd.AddCommand(dodoAppCmd())
}
func main() {