Sample code that demonstrates SAP HANA Cloud official nodejs driver calls from a kyma function
- handler.js
const hana = require("@sap/hana-client");
const { PerformanceObserver, performance } = require('perf_hooks');
const util = require('util');
const StringBuilder = require("string-builder");
async function hanacloud(event) {
let queryString = event.extensions.request.query;
console.log('queryString: ', queryString)
const urlParams = new URLSearchParams(queryString);
const connOptions_hdi = {
serverNode: '*************.hana.prod-****.hanacloud.ondemand.com:443',
encrypt: "true",
sslValidateCertificate: "false",
uid: '*****************_RT',
pwd: '*************',
};
const connOptions_hanadb = {
serverNode: '***************.hana.prod-****.hanacloud.ondemand.com:443',
encrypt: "true",
sslValidateCertificate: "false",
uid: 'DBADMIN',
pwd: 'pwd',
};
const connOptions = urlParams.has('hdi') ? connOptions_hdi : connOptions_hanadb;
var t0 = performance.now();
var dbConnection;
try {
dbConnection = await hana.createConnection();
} catch (err) {
console.error(err);
return err.toString();
}
const schema = '9DD0EC1FFFD24E1D94E742C25A384AED';
console.log(urlParams.has('sql'));
const sqlStatement1 = "SELECT * FROM TABLES WHERE SCHEMA_NAME = " + "\'" + schema+ "\'" ;
const sqlStatement2 = "SELECT * FROM SCHEMAS";
const sqlStatement3 = "SELECT * FROM SYS.M_DATABASES";
const sqlStatement4 = "SELECT * FROM SYS.M_SERVICES";
const sqlStatement5 = "SELECT * FROM EFFECTIVE_PRIVILEGE_GRANTEES WHERE (OBJECT_TYPE = 'SYSTEMPRIVILEGE') AND (PRIVILEGE = 'EXPORT' OR PRIVILEGE='IMPORT')";
const sqlStatement6 = "SELECT * FROM USERS";
const sqlStatement7 = "alter user DBADMIN DISABLE PASSWORD LIFETIME";
const sqlStatement8 = "select * from users where password_change_time is null and user_name not like '_SYS%' and user_name not like 'XSS%' order by PASSWORD_CHANGE_TIME asc";
var sqlStatement = sqlStatement1;
if (urlParams.has('sql')) {
switch(urlParams.get('sql')) {
case "1" : sqlStatement = sqlStatement1; break;
case "2" : sqlStatement = sqlStatement2; break;
case "3" : sqlStatement = sqlStatement3; break;
case "4" : sqlStatement = sqlStatement4; break;
case "5" : sqlStatement = sqlStatement5; break;
case "6" : sqlStatement = sqlStatement6; break;
case "7" : sqlStatement = sqlStatement7; break;
case "8" : sqlStatement = sqlStatement8; break;
}
}
var resultset = 0;
var resultset2 = 0;
var perfcounter = 0;
try {
console.log('dbConnection.connect')
await dbConnection.connect(connOptions);
} catch(err) {
console.error(err);
return err.toString();
}
var execError = null;
try {
console.log('dbConnection.exec')
const rows = await dbConnection.exec(sqlStatement)
resultset = rows;
resultset2 = util.inspect(rows, { colors: false });
console.log(resultset);
var t1 = performance.now();
perfcounter = "number of rows: " + rows.length + " time in msec " + (t1 - t0);
console.log(resultset);
} catch (err) {
console.error(err);
execError = err;
}
try {
console.log('dbConnection.disconnect')
await dbConnection.disconnect();
if (execError !== null) return execError.toString();
} catch (err) {
console.error(err);
return err.toString();
}
let sb = new StringBuilder();
sb.appendFormat("sqlStatement : {0}", sqlStatement);
sb.appendLine();
sb.appendFormat("perfcounter : {0}", perfcounter);
sb.appendLine();
return sb.append(resultset2).toString();
}
module.exports = {
main: async function (event, context) {
const message = `Hello World`
+ ` from the Kyma Function ${context["function-name"]}`
+ ` running on ${context.runtime}!`;
console.log(message);
const endpoint = event.extensions.request.path;
switch (endpoint) {
case "/hanacloud":
return hanacloud(event);
}
console.log(event.endpoint);
return message;
}
}
- package.json
{
"name": "hana-cloud",
"version": "1.0.0",
"dependencies": {
"@sap/hana-client":"latest",
"util": "^0.12.5",
"perf_hooks": "^0.0.1",
"string-builder": "^0.1.8"
},
"devDependencies": {
}
}
In order to be able to run this function you may need to override the function base image as follows:
if the image override is not applied the function may simply fail when trying to connect to hana db as follows:
> nodejs16-runtime@0.1.0 start
> node server.js
user code loaded in 1sec 399.877434ms
Hello World from the Kyma Function hana-cloud running on nodejs16!
queryString: { sql: '4' }
true
dbConnection.connect
............... this does not go through ...................
npm notice
npm notice New major version of npm available! 8.19.3 -> 9.4.1
npm notice Changelog: <https://github.com/npm/cli/releases/tag/v9.4.1>
npm notice Run `npm install -g npm@9.4.1` to update!
npm notice
npm ERR! path /usr/src/app
npm ERR! command failed
npm ERR! signal SIGSEGV
npm ERR! command sh -c -- node server.js
npm ERR! A complete log of this run can be found in:
npm ERR! /tmp/_logs/2023-02-03T08_56_49_266Z-debug-0.log
Additionally, the following issue provides more details: kyma-project/kyma#16674
- nodejs16 override image: tiosouji/hc:bullseye-slim16
- nodejs14 override image: tiosouji/hc:bullseye-slim14
FROM node:16.19.0-bullseye-slim
ARG NODE_ENV
ENV NODE_ENV $NODE_ENV
ENV npm_config_cache /tmp/
RUN mkdir -p /usr/src/app \
&& mkdir -p /usr/src/app/lib
WORKDIR /usr/src/app
COPY package.json /usr/src/app/
RUN npm install && npm cache clean --force \
&& apt-get update \
&& apt-get install -y openssl python make g++
COPY lib /usr/src/app/lib
COPY server.js /usr/src/app/server.js
CMD ["npm", "start"]
EXPOSE 8888
and the build command:
docker build --platform amd64 -t tiosouji/hc:bullseye-slim16 -f ./Dockerfile.custom.nodejs16 .
FROM node:14.21.2-bullseye-slim
COPY docker-entrypoint.sh /usr/local/bin/
ENTRYPOINT ["docker-entrypoint.sh"]
# Serverless
LABEL source = git@github.com:kyma-project/kyma.git
COPY kubeless/ /
WORKDIR /kubeless_rt/
RUN npm install && npm cache clean --force \
&& apt-get update \
&& apt-get install -y openssl python make g++
USER 1000
CMD ["node", "kubeless.js"]
and the build command:
docker build --platform amd64 -t tiosouji/hc:bullseye-slim14 -f ./Dockerfile.custom.nodejs14 .
Power of serverless with SAP BTP, Kyma runtime. Base image override. | SAP Blogs
Connect Using the SAP HANA Node.js Interface | SAP Developer Tutorials