diff --git a/gallery/app/app.js b/gallery/app/app.js
index 8f133a0b0..7d47b8bcf 100644
--- a/gallery/app/app.js
+++ b/gallery/app/app.js
@@ -15,6 +15,11 @@ if (process.env.MOUNT_LOCATION || existsSync("/mnt/bucket")) {
GALLERY_PATH = process.env.MOUNT_LOCATION || "/mnt/bucket";
}
+function sendResponse(res, statusCode, responseMessage) {
+ res.statusCode = statusCode;
+ return res.end(responseMessage);
+}
+
function getFunctionEndpoint() {
if (!process.env.COLORIZER) {
return undefined;
@@ -57,13 +62,9 @@ async function handleHttpReq(req, res) {
pageContent = await readFile(`${basePath}/page.html`);
} catch (err) {
console.log(`Error reading page: ${err.message}`);
- res.statusCode = 503;
- res.end(`Error reading page: ${err.message}`);
- return;
+ return sendResponse(res, 503, `Error reading page: ${err.message}`);
}
- res.statusCode = 200;
- res.end(pageContent);
- return;
+ return sendResponse(res, 200, pageContent);
}
// This handler exposes the set of features that are available
@@ -91,9 +92,7 @@ async function handleHttpReq(req, res) {
if (reqPath === "/change-colors") {
req.on("error", (err) => {
console.log(`Error reading body: ${err.message}`);
- res.statusCode = 503;
- res.end(`Error reading body: ${err.message}`);
- return;
+ return sendResponse(res, 503, `Error reading body: ${err.message}`);
});
let bodyBuf = Buffer.alloc(0);
req.on("data", (chunkBuf) => {
@@ -107,14 +106,15 @@ async function handleHttpReq(req, res) {
invokeColorizeFunction(payload.imageId)
.then((response) => {
console.log(`Colorizer function has been invoked successfully: '${JSON.stringify(response)}'`);
- res.statusCode = 200;
- res.end();
+ return sendResponse(res, 200);
})
- .catch((reason) => {
- console.error(`Error colorizing image '${payload.imageId}'`, reason);
- res.statusCode = 503;
- res.end(`Error changing color of image '${payload.imageId}': ${reason}`);
- return;
+ .catch((err) => {
+ console.error(`Error colorizing image '${payload.imageId}'`, err);
+
+ if (err.message.indexOf("Access is denied due to invalid credentials") > -1) {
+ return sendResponse(res, 403, `Failed due to access permission issues`);
+ }
+ return sendResponse(res, 503, `Error changing color of image '${payload.imageId}': ${err.message}`);
});
});
return;
@@ -125,9 +125,7 @@ async function handleHttpReq(req, res) {
console.info("Uploading to COS ...");
req.on("error", (err) => {
console.log(`Error reading body: ${err.message}`);
- res.statusCode = 503;
- res.end(`Error reading body: ${err.message}`);
- return;
+ return sendResponse(res, 503, `Error reading body: ${err.message}`);
});
let bodyBuf = Buffer.alloc(0);
req.on("data", (chunkBuf) => {
@@ -138,14 +136,10 @@ async function handleHttpReq(req, res) {
try {
await writeFile(`${GALLERY_PATH}/gallery-pic-${Date.now()}.png`, bodyBuf, {});
res.setHeader("Content-Type", "application/json");
- res.statusCode = 200;
- res.end(`{"done": "true"}`);
- return;
+ return sendResponse(res, 200, `{"done": "true"}`);
} catch (err) {
console.log(`Error uploading picture: ${err}`);
- res.statusCode = 503;
- res.end(`Error uploading picture: ${err}`);
- return;
+ return sendResponse(res, 503, `Error uploading picture: ${err}`);
}
});
return;
@@ -165,14 +159,11 @@ async function handleHttpReq(req, res) {
});
res.setHeader("Content-Type", "application/json");
- res.statusCode = 200;
- res.end(JSON.stringify(galleryContents));
+ return sendResponse(res, 200, JSON.stringify(galleryContents));
} catch (err) {
console.log(`Error listing gallery content: ${err}`);
- res.statusCode = 503;
- res.end(`Error listing gallery content: ${err}`);
+ return sendResponse(res, 503, `Error listing gallery content: ${err}`);
}
- return;
}
// Handler for deleting all items in the gallery
@@ -184,12 +175,10 @@ async function handleHttpReq(req, res) {
await unlink(`${GALLERY_PATH}/${file}`);
}
res.setHeader("Content-Type", "application/json");
- res.statusCode = 200;
- res.end(`{"done": "true"}`);
+ return sendResponse(res, 200, `{"done": "true"}`);
} catch (err) {
console.log(`Error deleting gallery content: ${err}`);
- res.statusCode = 503;
- res.end(`Error deleting gallery content: ${err}`);
+ return sendResponse(res, 503, `Error deleting gallery content: ${err}`);
}
return;
}
@@ -206,9 +195,7 @@ async function handleHttpReq(req, res) {
return fd.createReadStream().pipe(res);
} catch (err) {
console.error(`Error streaming gallery content '${pictureId}'`, err);
- res.statusCode = 503;
- res.end(`Error streaming gallery content: ${err}`);
- return;
+ return sendResponse(res, 503, `Error streaming gallery content: ${err}`);
}
}
@@ -218,9 +205,7 @@ async function handleHttpReq(req, res) {
}
if (reqPath.includes("..")) {
console.log(`Bad path "${reqPath}"`);
- res.statusCode = 404;
- res.end("Bad path");
- return;
+ return sendResponse(res, 404, "Bad path");
}
// serve file at basePath/reqPath
let pageContent;
@@ -228,13 +213,10 @@ async function handleHttpReq(req, res) {
pageContent = await readFile(`${basePath}/${reqPath}`);
} catch (err) {
console.log(`Error reading file: ${err.message}`);
- res.statusCode = 404;
- res.end(`Error reading file: ${err.message}`);
- return;
+ return sendResponse(res, 404, `Error reading file: ${err.message}`);
}
res.setHeader("Content-Type", mimetypeByExtension[(reqPath.match(/\.([^.]+)$/) || [])[1]] || "text/plain");
- res.statusCode = 200;
- res.end(pageContent);
+ return sendResponse(res, 200, pageContent);
}
const server = createServer(handleHttpReq);
diff --git a/gallery/app/page.html b/gallery/app/page.html
index bffc2ceab..164de476d 100644
--- a/gallery/app/page.html
+++ b/gallery/app/page.html
@@ -48,7 +48,10 @@
Code Engine Gallery Demo
My Gallery
- Click on individual images to change their colors.
+
+ Click on individual images to change their colors.
+
+
diff --git a/gallery/app/page.js b/gallery/app/page.js
index bb2d19394..a5350dc1c 100644
--- a/gallery/app/page.js
+++ b/gallery/app/page.js
@@ -1,4 +1,4 @@
-const ne = ["file_input", "add", "picture_preview", "progress", "upload", "clear"].reduce((p, c) => {
+const ne = ["file_input", "add", "picture_preview", "progress", "upload", "clear", "colorizer"].reduce((p, c) => {
p[c] = document.querySelector(`[data-${c.replace("_", "-")}]`);
return p;
}, Object.create(null));
@@ -178,6 +178,7 @@ function listGalleryContent() {
console.info(`setting onclick handler for '${id}'`);
img.onclick = async () => {
console.info(`colorizer for '${id}'`);
+ ne.colorizer.innerText = "Colorizing ...";
const currentImage = document.getElementById(id);
@@ -185,15 +186,21 @@ function listGalleryContent() {
currentImage.className = "gallery-pic colorizable disabled";
try {
// trigger the color change
- await fetch("/change-colors", {
+ const colorizeResp = await fetch("/change-colors", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: `{"imageId": "${id}"}`,
});
+ if (colorizeResp.status != 200) {
+ ne.colorizer.innerText = await colorizeResp.text();
+ } else {
+ ne.colorizer.innerText = "";
+ }
} catch (err) {
console.error(`Failed to change color of image '${id}'`, err);
+ ne.colorizer.innerText = err.message;
} finally {
currentImage.className = "gallery-pic colorizable";
}
diff --git a/gallery/function/function.js b/gallery/function/function.js
index 8cbda9018..509ed7d23 100644
--- a/gallery/function/function.js
+++ b/gallery/function/function.js
@@ -93,9 +93,9 @@ async function main(args) {
console.log(`Uploaded updated '${imageId}'`);
return sendJSONResponse(200, `{"success": "true"}`);
- } catch (reason) {
- console.error(`Error changing colors of ${imageId}`, reason);
- return sendJSONResponse(503, `{"error":"Error changing colors: ${reason}"}`);
+ } catch (err) {
+ console.error(`Error changing colors of ${imageId}`, err);
+ return sendJSONResponse(503, `{"error":"Error changing colors: ${err.message}"}`);
}
}
diff --git a/private-path-to-vpc-vsi/ce-app/go.mod b/private-path-to-vpc-vsi/ce-app/go.mod
index 3f6dc51b8..bff2499af 100644
--- a/private-path-to-vpc-vsi/ce-app/go.mod
+++ b/private-path-to-vpc-vsi/ce-app/go.mod
@@ -1,4 +1,4 @@
-module github.com/IBM/CodeEngine/ce-satellite-connector
+module github.com/IBM/CodeEngine/ce-private-path
go 1.23.0
diff --git a/private-path-to-vpc-vsi/ce-app/main.go b/private-path-to-vpc-vsi/ce-app/main.go
index 5c08a58a8..814993819 100644
--- a/private-path-to-vpc-vsi/ce-app/main.go
+++ b/private-path-to-vpc-vsi/ce-app/main.go
@@ -9,6 +9,7 @@ import (
"net/http"
"os"
"os/signal"
+ "strings"
"syscall"
"time"
@@ -17,7 +18,7 @@ import (
var dbClient = connectToDb()
-type Friendship struct {
+type GuestbookEntry struct {
Name string `json:"name"`
Created int64 `json:"created"`
Greeting string `json:"greeting"`
@@ -41,39 +42,49 @@ func connectToDb() *sql.DB {
// This func will handle all incoming HTTP requests
func HandleHTTP(w http.ResponseWriter, r *http.Request) {
- friendships := []Friendship{}
+ guestbookEntries := []GuestbookEntry{}
var (
name string
created_at int64
greeting string
)
- Debug("Fetching all friendship records ...")
- rows, sqlErr := dbClient.Query("SELECT name, created_at, greeting FROM myfriendships")
+ Debug("Fetching all guestbook entries ...")
+ rows, sqlErr := dbClient.Query("SELECT name, created_at, greeting FROM guestbook")
if sqlErr != nil {
- log.Printf("Retrieving friendship records failed - err: " + sqlErr.Error())
+ log.Printf("Retrieving guestbook entries failed - err: " + sqlErr.Error())
+ if strings.Contains(sqlErr.Error(), "dial tcp") {
+ w.WriteHeader(502)
+ fmt.Fprintf(w, "Can't reach '%s'", os.Getenv("PGHOST"))
+ return
+ }
w.WriteHeader(500)
+ fmt.Fprintf(w, "%s", sqlErr.Error())
+ return
}
defer rows.Close()
for rows.Next() {
err := rows.Scan(&name, &created_at, &greeting)
if err != nil {
- log.Printf("Scanning friendship record failed - err: " + err.Error())
+ log.Printf("Scanning guestbook entries failed - err: " + err.Error())
w.WriteHeader(500)
+ fmt.Fprintf(w, "%s", err.Error())
+ return
}
- log.Println("Retrieved friendship records", name, created_at, greeting)
- friendships = append(friendships, Friendship{Name: name, Created: created_at, Greeting: greeting})
+ log.Println("Retrieved guestbook records", name, created_at, greeting)
+ guestbookEntries = append(guestbookEntries, GuestbookEntry{Name: name, Created: created_at, Greeting: greeting})
}
- Debug("Fetched %d friendship records", len(friendships))
- bytes, err := json.Marshal(&friendships)
+ Debug("Fetched %d guestbook entries", len(guestbookEntries))
+ bytes, err := json.Marshal(&guestbookEntries)
if err != nil {
log.Printf("Failed to marshal response - err: " + err.Error())
w.WriteHeader(500)
+ fmt.Fprintf(w, "%s", err.Error())
+ return
}
w.Header().Add("Content-Type", "application/json")
fmt.Fprintf(w, "%s", string(bytes))
-
}
func main() {
@@ -96,6 +107,7 @@ func main() {
<-signals
Debug("shutting down server")
+ dbClient.Close()
if err := srv.Shutdown(ctx); err != nil {
log.Fatalf("failed to shutdown server: %v", err)
}
diff --git a/private-path-to-vpc-vsi/ce-job/job.mjs b/private-path-to-vpc-vsi/ce-job/job.mjs
index a5bcec4e9..b7811df5c 100644
--- a/private-path-to-vpc-vsi/ce-job/job.mjs
+++ b/private-path-to-vpc-vsi/ce-job/job.mjs
@@ -4,29 +4,46 @@ import { LoremIpsum } from "lorem-ipsum";
const { Client } = pkg;
console.log("Connecting to PostgreSQL instance...");
+
+const client = new Client({
+ user: process.env.PGUSER,
+ password: process.env.PGPASSWORD,
+ host: process.env.PGHOST,
+ database: process.env.PGDATABASE,
+ port: process.env.PGPORT,
+});
try {
- const client = new Client({
- user: process.env.PGUSER,
- password: process.env.PGPASSWORD,
- host: process.env.PGHOST,
- database: process.env.PGDATABASE,
- port: process.env.PGPORT,
- });
await client.connect();
- console.log("Creating myfriendships table if it does not exist...");
- 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);");
+ console.log("Creating guestbook table if it does not exist...");
+ await client.query(
+ "CREATE TABLE IF NOT EXISTS guestbook (id SERIAL PRIMARY KEY, name varchar(256) NOT NULL, created_at bigint NOT NULL, greeting text);"
+ );
- console.log("Writing into myfriendships table...");
- await client.query("INSERT INTO myfriendships (name,created_at,greeting) VALUES ($1,$2,$3);", [
+ console.log("Writing into guestbook table...");
+ await client.query("INSERT INTO guestbook (name,created_at,greeting) VALUES ($1,$2,$3);", [
process.env.HOSTNAME,
Date.now(),
new LoremIpsum().generateWords(5),
]);
+ if (process.env.ACTION === "cleanup") {
+ console.log("Cleaning up table content...");
+ await client.query("DELETE FROM guestbook;");
+ }
+
await client.end();
console.log("Done!");
} catch (err) {
console.error("Failed to connect to PostgreSQL instance", err);
+
+ if(client) {
+ try {
+ await client.end();
+ } catch(error) {
+ // just do it
+ }
+ }
+
process.exit(1);
}
diff --git a/private-path-to-vpc-vsi/docs/code-engine-private-path---component-diagram.drawio b/private-path-to-vpc-vsi/docs/code-engine-private-path---component-diagram.drawio
index 241ee66b5..4baa75b22 100644
--- a/private-path-to-vpc-vsi/docs/code-engine-private-path---component-diagram.drawio
+++ b/private-path-to-vpc-vsi/docs/code-engine-private-path---component-diagram.drawio
@@ -1,6 +1,6 @@
-
+
@@ -244,42 +244,9 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
-
-
-
diff --git a/private-path-to-vpc-vsi/run b/private-path-to-vpc-vsi/run
index 311247799..f41f88ae8 100755
--- a/private-path-to-vpc-vsi/run
+++ b/private-path-to-vpc-vsi/run
@@ -11,8 +11,8 @@ DEBUG_MODE="${DEBUG_MODE:=false}"
# Dependent variables
resource_group_name="${NAME_PREFIX}--rg"
ce_project_name="${NAME_PREFIX}--ce-project"
-ce_job_name="friendship-book-writer"
-ce_app_name="friendship-book-api"
+ce_job_name="guestbook-writer"
+ce_app_name="guestbook-api"
ce_db_credentials="db-credentials"
vpc_name="${NAME_PREFIX}--is-vpc"
vsi_originserver_name="${NAME_PREFIX}--is-vsi-originserver"
@@ -387,7 +387,7 @@ ibmcloud ce project select --name $ce_project_name --kubecfg
#
# Create the private path integration
-ce_vpegatewayconnection_name=friendship-book-api-integration
+ce_vpegatewayconnection_name=guestbook-integration
kubectl apply -f - <