Skip to content

Commit 81fdd7a

Browse files
Merge pull request #215 from IBM/improve-gallery-and-pps-sample
Improve gallery and pps sample
2 parents 9c4b9c0 + 1e75a7c commit 81fdd7a

File tree

10 files changed

+103
-115
lines changed

10 files changed

+103
-115
lines changed

gallery/app/app.js

Lines changed: 27 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,11 @@ if (process.env.MOUNT_LOCATION || existsSync("/mnt/bucket")) {
1515
GALLERY_PATH = process.env.MOUNT_LOCATION || "/mnt/bucket";
1616
}
1717

18+
function sendResponse(res, statusCode, responseMessage) {
19+
res.statusCode = statusCode;
20+
return res.end(responseMessage);
21+
}
22+
1823
function getFunctionEndpoint() {
1924
if (!process.env.COLORIZER) {
2025
return undefined;
@@ -57,13 +62,9 @@ async function handleHttpReq(req, res) {
5762
pageContent = await readFile(`${basePath}/page.html`);
5863
} catch (err) {
5964
console.log(`Error reading page: ${err.message}`);
60-
res.statusCode = 503;
61-
res.end(`Error reading page: ${err.message}`);
62-
return;
65+
return sendResponse(res, 503, `Error reading page: ${err.message}`);
6366
}
64-
res.statusCode = 200;
65-
res.end(pageContent);
66-
return;
67+
return sendResponse(res, 200, pageContent);
6768
}
6869

6970
// This handler exposes the set of features that are available
@@ -91,9 +92,7 @@ async function handleHttpReq(req, res) {
9192
if (reqPath === "/change-colors") {
9293
req.on("error", (err) => {
9394
console.log(`Error reading body: ${err.message}`);
94-
res.statusCode = 503;
95-
res.end(`Error reading body: ${err.message}`);
96-
return;
95+
return sendResponse(res, 503, `Error reading body: ${err.message}`);
9796
});
9897
let bodyBuf = Buffer.alloc(0);
9998
req.on("data", (chunkBuf) => {
@@ -107,14 +106,15 @@ async function handleHttpReq(req, res) {
107106
invokeColorizeFunction(payload.imageId)
108107
.then((response) => {
109108
console.log(`Colorizer function has been invoked successfully: '${JSON.stringify(response)}'`);
110-
res.statusCode = 200;
111-
res.end();
109+
return sendResponse(res, 200);
112110
})
113-
.catch((reason) => {
114-
console.error(`Error colorizing image '${payload.imageId}'`, reason);
115-
res.statusCode = 503;
116-
res.end(`Error changing color of image '${payload.imageId}': ${reason}`);
117-
return;
111+
.catch((err) => {
112+
console.error(`Error colorizing image '${payload.imageId}'`, err);
113+
114+
if (err.message.indexOf("Access is denied due to invalid credentials") > -1) {
115+
return sendResponse(res, 403, `Failed due to access permission issues`);
116+
}
117+
return sendResponse(res, 503, `Error changing color of image '${payload.imageId}': ${err.message}`);
118118
});
119119
});
120120
return;
@@ -125,9 +125,7 @@ async function handleHttpReq(req, res) {
125125
console.info("Uploading to COS ...");
126126
req.on("error", (err) => {
127127
console.log(`Error reading body: ${err.message}`);
128-
res.statusCode = 503;
129-
res.end(`Error reading body: ${err.message}`);
130-
return;
128+
return sendResponse(res, 503, `Error reading body: ${err.message}`);
131129
});
132130
let bodyBuf = Buffer.alloc(0);
133131
req.on("data", (chunkBuf) => {
@@ -138,14 +136,10 @@ async function handleHttpReq(req, res) {
138136
try {
139137
await writeFile(`${GALLERY_PATH}/gallery-pic-${Date.now()}.png`, bodyBuf, {});
140138
res.setHeader("Content-Type", "application/json");
141-
res.statusCode = 200;
142-
res.end(`{"done": "true"}`);
143-
return;
139+
return sendResponse(res, 200, `{"done": "true"}`);
144140
} catch (err) {
145141
console.log(`Error uploading picture: ${err}`);
146-
res.statusCode = 503;
147-
res.end(`Error uploading picture: ${err}`);
148-
return;
142+
return sendResponse(res, 503, `Error uploading picture: ${err}`);
149143
}
150144
});
151145
return;
@@ -165,14 +159,11 @@ async function handleHttpReq(req, res) {
165159
});
166160

167161
res.setHeader("Content-Type", "application/json");
168-
res.statusCode = 200;
169-
res.end(JSON.stringify(galleryContents));
162+
return sendResponse(res, 200, JSON.stringify(galleryContents));
170163
} catch (err) {
171164
console.log(`Error listing gallery content: ${err}`);
172-
res.statusCode = 503;
173-
res.end(`Error listing gallery content: ${err}`);
165+
return sendResponse(res, 503, `Error listing gallery content: ${err}`);
174166
}
175-
return;
176167
}
177168

178169
// Handler for deleting all items in the gallery
@@ -184,12 +175,10 @@ async function handleHttpReq(req, res) {
184175
await unlink(`${GALLERY_PATH}/${file}`);
185176
}
186177
res.setHeader("Content-Type", "application/json");
187-
res.statusCode = 200;
188-
res.end(`{"done": "true"}`);
178+
return sendResponse(res, 200, `{"done": "true"}`);
189179
} catch (err) {
190180
console.log(`Error deleting gallery content: ${err}`);
191-
res.statusCode = 503;
192-
res.end(`Error deleting gallery content: ${err}`);
181+
return sendResponse(res, 503, `Error deleting gallery content: ${err}`);
193182
}
194183
return;
195184
}
@@ -206,9 +195,7 @@ async function handleHttpReq(req, res) {
206195
return fd.createReadStream().pipe(res);
207196
} catch (err) {
208197
console.error(`Error streaming gallery content '${pictureId}'`, err);
209-
res.statusCode = 503;
210-
res.end(`Error streaming gallery content: ${err}`);
211-
return;
198+
return sendResponse(res, 503, `Error streaming gallery content: ${err}`);
212199
}
213200
}
214201

@@ -218,23 +205,18 @@ async function handleHttpReq(req, res) {
218205
}
219206
if (reqPath.includes("..")) {
220207
console.log(`Bad path "${reqPath}"`);
221-
res.statusCode = 404;
222-
res.end("Bad path");
223-
return;
208+
return sendResponse(res, 404, "Bad path");
224209
}
225210
// serve file at basePath/reqPath
226211
let pageContent;
227212
try {
228213
pageContent = await readFile(`${basePath}/${reqPath}`);
229214
} catch (err) {
230215
console.log(`Error reading file: ${err.message}`);
231-
res.statusCode = 404;
232-
res.end(`Error reading file: ${err.message}`);
233-
return;
216+
return sendResponse(res, 404, `Error reading file: ${err.message}`);
234217
}
235218
res.setHeader("Content-Type", mimetypeByExtension[(reqPath.match(/\.([^.]+)$/) || [])[1]] || "text/plain");
236-
res.statusCode = 200;
237-
res.end(pageContent);
219+
return sendResponse(res, 200, pageContent);
238220
}
239221

240222
const server = createServer(handleHttpReq);

gallery/app/page.html

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,10 @@ <h1 class="title">Code Engine Gallery Demo</h1>
4848
<span id="gallery-title-text">My Gallery</span>
4949
<div id="gallery-cta-buttons"><button data-clear class="cta-clear">Clear</button></div>
5050
</div>
51-
<div id="gallery-subtitle" class="hidden"><span>Click on individual images to change their colors.</span></div>
51+
<div id="gallery-subtitle" class="hidden">
52+
<span>Click on individual images to change their colors.</span>
53+
<span data-colorizer class="colorizer"></span>
54+
</div>
5255
<div id="gallery" class="row" ></div>
5356
</div>
5457
</div>

gallery/app/page.js

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
const ne = ["file_input", "add", "picture_preview", "progress", "upload", "clear"].reduce((p, c) => {
1+
const ne = ["file_input", "add", "picture_preview", "progress", "upload", "clear", "colorizer"].reduce((p, c) => {
22
p[c] = document.querySelector(`[data-${c.replace("_", "-")}]`);
33
return p;
44
}, Object.create(null));
@@ -178,22 +178,29 @@ function listGalleryContent() {
178178
console.info(`setting onclick handler for '${id}'`);
179179
img.onclick = async () => {
180180
console.info(`colorizer for '${id}'`);
181+
ne.colorizer.innerText = "Colorizing ...";
181182

182183
const currentImage = document.getElementById(id);
183184

184185
// adding the disabled classname will let the image appear as not clickable
185186
currentImage.className = "gallery-pic colorizable disabled";
186187
try {
187188
// trigger the color change
188-
await fetch("/change-colors", {
189+
const colorizeResp = await fetch("/change-colors", {
189190
method: "POST",
190191
headers: {
191192
"Content-Type": "application/json",
192193
},
193194
body: `{"imageId": "${id}"}`,
194195
});
196+
if (colorizeResp.status != 200) {
197+
ne.colorizer.innerText = await colorizeResp.text();
198+
} else {
199+
ne.colorizer.innerText = "";
200+
}
195201
} catch (err) {
196202
console.error(`Failed to change color of image '${id}'`, err);
203+
ne.colorizer.innerText = err.message;
197204
} finally {
198205
currentImage.className = "gallery-pic colorizable";
199206
}

gallery/function/function.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -93,9 +93,9 @@ async function main(args) {
9393
console.log(`Uploaded updated '${imageId}'`);
9494

9595
return sendJSONResponse(200, `{"success": "true"}`);
96-
} catch (reason) {
97-
console.error(`Error changing colors of ${imageId}`, reason);
98-
return sendJSONResponse(503, `{"error":"Error changing colors: ${reason}"}`);
96+
} catch (err) {
97+
console.error(`Error changing colors of ${imageId}`, err);
98+
return sendJSONResponse(503, `{"error":"Error changing colors: ${err.message}"}`);
9999
}
100100
}
101101

private-path-to-vpc-vsi/ce-app/go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
module github.com/IBM/CodeEngine/ce-satellite-connector
1+
module github.com/IBM/CodeEngine/ce-private-path
22

33
go 1.23.0
44

private-path-to-vpc-vsi/ce-app/main.go

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"net/http"
1010
"os"
1111
"os/signal"
12+
"strings"
1213
"syscall"
1314
"time"
1415

@@ -17,7 +18,7 @@ import (
1718

1819
var dbClient = connectToDb()
1920

20-
type Friendship struct {
21+
type GuestbookEntry struct {
2122
Name string `json:"name"`
2223
Created int64 `json:"created"`
2324
Greeting string `json:"greeting"`
@@ -41,39 +42,49 @@ func connectToDb() *sql.DB {
4142
// This func will handle all incoming HTTP requests
4243
func HandleHTTP(w http.ResponseWriter, r *http.Request) {
4344

44-
friendships := []Friendship{}
45+
guestbookEntries := []GuestbookEntry{}
4546
var (
4647
name string
4748
created_at int64
4849
greeting string
4950
)
50-
Debug("Fetching all friendship records ...")
51-
rows, sqlErr := dbClient.Query("SELECT name, created_at, greeting FROM myfriendships")
51+
Debug("Fetching all guestbook entries ...")
52+
rows, sqlErr := dbClient.Query("SELECT name, created_at, greeting FROM guestbook")
5253
if sqlErr != nil {
53-
log.Printf("Retrieving friendship records failed - err: " + sqlErr.Error())
54+
log.Printf("Retrieving guestbook entries failed - err: " + sqlErr.Error())
55+
if strings.Contains(sqlErr.Error(), "dial tcp") {
56+
w.WriteHeader(502)
57+
fmt.Fprintf(w, "Can't reach '%s'", os.Getenv("PGHOST"))
58+
return
59+
}
5460
w.WriteHeader(500)
61+
fmt.Fprintf(w, "%s", sqlErr.Error())
62+
return
5563
}
5664
defer rows.Close()
5765
for rows.Next() {
5866
err := rows.Scan(&name, &created_at, &greeting)
5967
if err != nil {
60-
log.Printf("Scanning friendship record failed - err: " + err.Error())
68+
log.Printf("Scanning guestbook entries failed - err: " + err.Error())
6169
w.WriteHeader(500)
70+
fmt.Fprintf(w, "%s", err.Error())
71+
return
6272
}
63-
log.Println("Retrieved friendship records", name, created_at, greeting)
64-
friendships = append(friendships, Friendship{Name: name, Created: created_at, Greeting: greeting})
73+
log.Println("Retrieved guestbook records", name, created_at, greeting)
74+
guestbookEntries = append(guestbookEntries, GuestbookEntry{Name: name, Created: created_at, Greeting: greeting})
6575
}
6676

67-
Debug("Fetched %d friendship records", len(friendships))
68-
bytes, err := json.Marshal(&friendships)
77+
Debug("Fetched %d guestbook entries", len(guestbookEntries))
78+
bytes, err := json.Marshal(&guestbookEntries)
6979
if err != nil {
7080
log.Printf("Failed to marshal response - err: " + err.Error())
7181
w.WriteHeader(500)
82+
fmt.Fprintf(w, "%s", err.Error())
83+
return
7284
}
7385

7486
w.Header().Add("Content-Type", "application/json")
7587
fmt.Fprintf(w, "%s", string(bytes))
76-
7788
}
7889

7990
func main() {
@@ -96,6 +107,7 @@ func main() {
96107

97108
<-signals
98109
Debug("shutting down server")
110+
dbClient.Close()
99111
if err := srv.Shutdown(ctx); err != nil {
100112
log.Fatalf("failed to shutdown server: %v", err)
101113
}

private-path-to-vpc-vsi/ce-job/job.mjs

Lines changed: 28 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,29 +4,46 @@ import { LoremIpsum } from "lorem-ipsum";
44
const { Client } = pkg;
55

66
console.log("Connecting to PostgreSQL instance...");
7+
8+
const client = new Client({
9+
user: process.env.PGUSER,
10+
password: process.env.PGPASSWORD,
11+
host: process.env.PGHOST,
12+
database: process.env.PGDATABASE,
13+
port: process.env.PGPORT,
14+
});
715
try {
8-
const client = new Client({
9-
user: process.env.PGUSER,
10-
password: process.env.PGPASSWORD,
11-
host: process.env.PGHOST,
12-
database: process.env.PGDATABASE,
13-
port: process.env.PGPORT,
14-
});
1516
await client.connect();
1617

17-
console.log("Creating myfriendships table if it does not exist...");
18-
await client.query("CREATE TABLE IF NOT EXISTS myfriendships (id SERIAL PRIMARY KEY, name varchar(256) NOT NULL, created_at bigint NOT NULL, greeting text);");
18+
console.log("Creating guestbook table if it does not exist...");
19+
await client.query(
20+
"CREATE TABLE IF NOT EXISTS guestbook (id SERIAL PRIMARY KEY, name varchar(256) NOT NULL, created_at bigint NOT NULL, greeting text);"
21+
);
1922

20-
console.log("Writing into myfriendships table...");
21-
await client.query("INSERT INTO myfriendships (name,created_at,greeting) VALUES ($1,$2,$3);", [
23+
console.log("Writing into guestbook table...");
24+
await client.query("INSERT INTO guestbook (name,created_at,greeting) VALUES ($1,$2,$3);", [
2225
process.env.HOSTNAME,
2326
Date.now(),
2427
new LoremIpsum().generateWords(5),
2528
]);
2629

30+
if (process.env.ACTION === "cleanup") {
31+
console.log("Cleaning up table content...");
32+
await client.query("DELETE FROM guestbook;");
33+
}
34+
2735
await client.end();
2836
console.log("Done!");
2937
} catch (err) {
3038
console.error("Failed to connect to PostgreSQL instance", err);
39+
40+
if(client) {
41+
try {
42+
await client.end();
43+
} catch(error) {
44+
// just do it
45+
}
46+
}
47+
3148
process.exit(1);
3249
}

0 commit comments

Comments
 (0)