Skip to content

Commit 8ec6a1c

Browse files
committed
Add "bucket explorer" to helloworld app
Add some fileserver and upload handler to the helloworld app. Those will only be served if a bucket is mounted at a specific location
1 parent 050de23 commit 8ec6a1c

File tree

1 file changed

+92
-6
lines changed

1 file changed

+92
-6
lines changed

helloworld/helloworld.go

Lines changed: 92 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222
"os"
2323
"os/exec"
2424
"os/signal"
25+
"path/filepath"
2526
"sort"
2627
"strconv"
2728
"strings"
@@ -35,6 +36,9 @@ func Curl(url string) (string, error) {
3536
return string(res), err
3637
}
3738

39+
const bucketDir = "/mnt/bucket"
40+
const bucketServePath = "/bucket"
41+
3842
var GlobalDebug = (os.Getenv("DEBUG") != "")
3943
var envs = []string{}
4044
var msg = ""
@@ -56,6 +60,7 @@ func Debug(doit bool, format string, args ...interface{}) {
5660

5761
// Just print an cool essage to the Writer that's passed in
5862
func PrintMessage(w io.Writer, showAll bool) {
63+
// http://patorjk.com/software/taag/#p=display&f=Graceful&t=Code%0AEngine
5964
fmt.Fprintf(w, "%s:\n", msg)
6065
fmt.Fprintln(w, `. ___ __ ____ ____`)
6166
fmt.Fprintln(w, `./ __)/ \( \( __)`)
@@ -84,6 +89,16 @@ func PrintMessage(w io.Writer, showAll bool) {
8489
}
8590
fmt.Fprintf(w, "%s\n", env)
8691
}
92+
93+
if IsBucketMounted() {
94+
fmt.Fprintf(w, "--------------\n")
95+
fmt.Fprintf(w, "\n")
96+
fmt.Fprintf(w, "Deteceted a mounted COS bucket under '%s'.\n", bucketDir)
97+
fmt.Fprintf(w, "Feel free to explore!\n")
98+
if !IsJob() {
99+
fmt.Fprintf(w, "https://%s%s\n", AppURL(), bucketServePath)
100+
}
101+
}
87102
}
88103

89104
// This func will handle all incoming HTTP requests
@@ -145,13 +160,82 @@ func HandleHTTP(w http.ResponseWriter, r *http.Request) {
145160
// But if there is a body, echo it back to the client.
146161
if len(body) == 0 {
147162
w.Header().Add("Content-Type", "text/plain")
148-
// http://patorjk.com/software/taag/#p=display&f=Graceful&t=Code%0AEngine
149163
PrintMessage(w, showAll)
150164
} else {
151165
fmt.Fprintf(w, string(body)+"\n")
152166
}
153167
}
154168

169+
func IsJob() bool {
170+
// If we're being run as a Batch Jobthen the JOB_INDEX env var will be set.
171+
return os.Getenv("JOB_INDEX") != ""
172+
}
173+
174+
func AppURL() string {
175+
return fmt.Sprintf("%s.%s.%s", os.Getenv("CE_APP"), os.Getenv("CE_SUBDOMAIN"), os.Getenv("CE_DOMAIN"))
176+
}
177+
178+
func IsBucketMounted() bool {
179+
info, err := os.Stat(bucketDir)
180+
return err == nil && info.IsDir()
181+
}
182+
183+
func NewBucketRouter() http.Handler {
184+
mux := http.NewServeMux()
185+
186+
mux.HandleFunc("/", BucketLandingPageHandler)
187+
mux.HandleFunc("/upload", FileUploadHandler)
188+
189+
fileServer := http.FileServer(http.Dir(bucketDir))
190+
mux.Handle("/files/", http.StripPrefix("/files/", fileServer))
191+
192+
return http.StripPrefix(bucketServePath, mux)
193+
}
194+
195+
func BucketLandingPageHandler(w http.ResponseWriter, r *http.Request) {
196+
w.Header().Set("Content-Type", "text/html; charset=utf-8")
197+
fmt.Fprintf(w, `
198+
<h2>Bucket Explorer</h2>
199+
<p>Use this form to upload files to the bucket mounted at '%s'.</p>
200+
<form action="%s/upload" method="post" enctype="multipart/form-data">
201+
<input type="file" name="file" id="file">
202+
<input type="submit" value="Upload File">
203+
</form>
204+
<br>
205+
<h3><a href="%s/files/">Browse Uploaded Files</a></h3>
206+
`, bucketDir, bucketServePath, bucketServePath)
207+
}
208+
209+
func FileUploadHandler(w http.ResponseWriter, r *http.Request) {
210+
if r.Method != http.MethodPost {
211+
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
212+
return
213+
}
214+
215+
file, handler, err := r.FormFile("file")
216+
if err != nil {
217+
http.Error(w, "Error retrieving the file", http.StatusBadRequest)
218+
return
219+
}
220+
defer file.Close()
221+
222+
dstPath := filepath.Join(bucketDir, handler.Filename)
223+
dst, err := os.Create(dstPath)
224+
if err != nil {
225+
http.Error(w, "Unable to create the file for writing", http.StatusInternalServerError)
226+
return
227+
}
228+
defer dst.Close()
229+
230+
if _, err := io.Copy(dst, file); err != nil {
231+
http.Error(w, "Unable to copy file content", http.StatusInternalServerError)
232+
return
233+
}
234+
235+
Debug(false, "Successfully uploaded file: %s", handler.Filename)
236+
http.Redirect(w, r, bucketServePath, http.StatusSeeOther)
237+
}
238+
155239
func main() {
156240
ctx := context.Background()
157241
signals := make(chan os.Signal, 1)
@@ -208,12 +292,10 @@ func main() {
208292
Debug(false, "Envs:\n%s", strings.Join(envs, "\n"))
209293

210294
// Real work.
211-
// If we're being run as a Batch Jobthen the JOB_INDEX env var
212-
// will be set. In which case, just print the message to stdout.
295+
// If we're being run as a Batch Job just print the message to stdout.
213296
// Otherwise we're an App and we need to start the HTTP server
214297
// to processing incoming requests
215-
if jobIndex := os.Getenv("JOB_INDEX"); jobIndex != "" {
216-
298+
if IsJob() {
217299
// Jobs can be either started in 'task' mode and run to completion or in 'daemon' mode which
218300
jobMode := os.Getenv("JOB_MODE")
219301

@@ -234,7 +316,7 @@ func main() {
234316
time.Sleep(time.Duration(sleepDuration) * time.Second)
235317
}
236318

237-
fmt.Printf("Hello from helloworld! I'm a %s job! Index: %s of %s\n\n", jobMode, jobIndex, os.Getenv("JOB_ARRAY_SIZE"))
319+
fmt.Printf("Hello from helloworld! I'm a %s job! Index: %s of %s\n\n", jobMode, os.Getenv("JOB_INDEX"), os.Getenv("JOB_ARRAY_SIZE"))
238320
PrintMessage(os.Stdout, os.Getenv("SHOW") == "")
239321

240322
// If the 'CRASH' or 'FAIL' env vars are set then crash!
@@ -255,6 +337,10 @@ func main() {
255337
// Debug the http handler for all requests
256338
http.HandleFunc("/", HandleHTTP)
257339

340+
if IsBucketMounted() {
341+
http.Handle(bucketServePath+"/", NewBucketRouter())
342+
}
343+
258344
// HTTP_DELAY will pause for 'delay' seconds before starting the
259345
// HTTP server. This is useful for simulating a long readiness probe
260346
if delay := os.Getenv("HTTP_DELAY"); delay != "" {

0 commit comments

Comments
 (0)