srv/package.json
& srv/package-lock.json
files to the root of our project."scripts": {
"start": "node ./srv/server.js",
"deploy:sqlite": "cds deploy -2 sqlite::memory:"
},
"engines": {
"node": "^12 || ^14"
},
"cds": {
"requires": {
"db": {
"kind": "sqlite",
"credentials": {
"database": ":memory"
}
}
},
"features": {
"in_memory_db": true
}
}
npm add @sap/cds
npm add sqlite3 --save-dev
srv/server.js
to serve our cds definitions and temporarily comment out our xsuaa service.const cds = require('@sap/cds');
....
xsenv.loadEnv();
....
/*
passport.use('JWT', new xssec.JWTStrategy(services.uaa));
app.use(passport.initialize());
app.use(passport.authenticate('JWT', {
session: false
}));
*/
cds.connect();
cds.serve().in(app);
db/tenant-model.cds
file with whatever entity your SaaS model sells. cuid represents an automatically assigned guid by @Sisn/cds on creation.namespace mt.tacoshop;
using {cuid} from '@sap/cds/common';
type tCurrency : String(3);
aspect aValue {
value : Decimal(10,3);
currency : tCurrency;
};
entity Taco: cuid, aValue {
type : String(50);
};
db/data/mt.tacoshop.Taco.csv
file and give a few lines of data.ID,type,value,currency
fe23a844-7dc1-11ec-90d6-0242ac120003,Free Sample,0.00,USD
fe23ab28-7dc1-11ec-90d6-0242ac120003,Homemade,1.50,USD
srv/tenant-model.cds
file, as long as the naming convention matches our db/<filename>.cds, CDS will automatically pick this up and expose it as a V4 oData service.using mt.tacoshop as mt from '../db/tenant-model';
service CatalogService @(path : '/Tenant/Catalog') {
entity Tacos as projection on mt.Taco;
}
npm install
npm run deploy:sqlite
npm run start
default-env.json
file and paste in your environment variables. Structure should look somethining like below. Note you wont be able to view this in our sample repo as it contains sensitive data.{
"VCAP_SERVICES": {
"saas-registry": [
{
"label": "saas-registry",
"provider": null,
"plan": "application",
"name": "mt-tacoshop-registry",
"tags": ["SaaS"],
"credentials": {
....
}"
}
],
"xsuaa": [
{
"label": "xsuaa",
"provider": null,
"plan": "application",
"name": "mt-tacoshop-uaa",
"tags": ["xsuaa"],
"credentials": {
...
},
"syslog_drain_url": null,
"volume_mounts": []
}
],
"destination": [
{
"label": "destination",
"provider": null,
"plan": "lite",
"name": "mt-tacoshop-dest",
"tags": ["destination","conn","connsvc"],
"credentials": {
...
},
"syslog_drain_url": null,
"volume_mounts": []
}
]
}
}
cds build
gen
directory in your project. We'll want to use the gen directory For BTP deployments. Update our mta.yaml to use the gen/srv
during deployment. This is a good time to also enable-parallel-deployments and keep-existing-routes.ID: mt-tacoshop
_schema-version: "3.1"
version: 0.0.4
parameters:
enable-parallel-deployments: true
keep-existing-routes: true
modules:
- name: mt-tacoshop-srv
type: nodejs
path: gen/srv
parameters:
memory: 256M
disk-quota: 512M
provides:
- name: srv_api
properties:
url: ${default-url}
requires:
- name: mt-tacoshop-uaa
- name: mt-tacoshop-registry
- name: mt-tacoshop-dest
# Use postgres/example user/password credentials
version: '3.1'
services:
db:
image: postgres:alpine
restart: always
environment:
POSTGRES_PASSWORD: postgres
# volumes:
# - ./db/data:/tmp/data
# - ./db/init:/docker-entrypoint-initdb.d/
ports:
- '5432:5432'
adminer:
image: adminer
restart: always
ports:
- 8080:8080
FROM node:14-buster-slim
RUN apt-get update && apt-get upgrade -y && nodejs -v && npm -v
# causes an error with node:14-buster-slim
# RUN apt-get --no-install-recommends -y install openjdk-11-jre
WORKDIR /usr/src/app
COPY gen/srv/package.json .
COPY package-lock.json .
RUN npm ci
COPY gen/srv .
COPY app app/
RUN find app -name '*.cds' | xargs rm -f
EXPOSE 4004
# Not needed with node:14-buster-slim
#RUN groupadd --gid 1000 node \
# && useradd --uid 1000 --gid node --shell /bin/bash --create-home node \
# && mkdir tmp \
# && chown node -R tmp
USER node
CMD [ "npm", "start" ]
"user-provided": [
{
"label": "user-provided",
"name": "pg-bookshop-database",
"tags": ["relational", "database", "plain"],
"instance_name": "mt-tacoshop-db",
"credentials": {
"host": "localhost",
"port": "5432",
"database": "tacoshop",
"user": "postgres",
"password": "postgres",
"schema": "public"
}
}
],
"cds": {
"requires": {
"db": {
"kind": "database"
},
"database": {
"dialect": "plain",
"impl": "cds-pg",
"model": [
"srv"
]
}
},
"migrations": {
"db": {
"multitenant": true,
"schema": {
"default": "public",
"clone": "_cdsdbm_clone",
"reference": "_cdsdbm_ref",
"tenants": ["c21a0f01a094445a97616901eda6b86a"]
},
"deploy": {
"tmpFile": "tmp/_autodeploy.json",
"undeployFile": "db/undeploy.json"
}
}
}
npm add cds-pg
npm add cds-dbm --save-dev
"devDependencies": {
"cds-dbm": "github:austinkloske22/cds-dbm#main",
}
npm install
cd node_modules/cds-dbm
npm install
npm run build
sudo chmod 755 ./dist/cli.js
"docker:start:pg": "docker-compose -f docker-compose.yml up -d",
"deploy:pg": "node_modules/cds-dbm/dist/cli.js deploy --create-db",
"deploy:pg:load": "node_modules/cds-dbm/dist/cli.js deploy --load-via delta"
npm run docker:start:pg
npm run deploy:pg
cf create-user-provided-service mt-tacoshop-db -t "relational, database, plain" -p '{
"database": "tacoshop",
"host": "postgresaws1.********.**-****-1.rds.amazonaws.com",
"user": "postgres",
"password": "********",
"port": 5432,
"schema": "public" }'
- name: mt-tacoshop-srv
type: nodejs
path: gen/srv
parameters:
memory: 256M
disk-quota: 512M
provides:
- name: srv_api
properties:
url: ${default-url}
requires:
- name: mt-tacoshop-uaa
- name: mt-tacoshop-registry
- name: mt-tacoshop-dest
- name: mt-tacoshop-db
resources:
- name: mt-tacoshop-db
type: org.cloudfoundry.existing-service
app/xs-app.json
{
"welcomeFile": "index.html",
"authenticationMethod": "route",
"routes": [
{
"source": "^/srv/(.*)$",
"authenticationType": "xsuaa",
"scope": "$XSAPPNAME.User",
"destination": "srv"
},
{
"source": "^/Tenant/(.*)$",
"authenticationType": "xsuaa",
"scope": "$XSAPPNAME.User",
"destination": "srv"
},
{
"source": "^/(.*)",
"authenticationType": "none",
"localDir": "resources"
}
]
}
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Multitenant Tacoshop</title>
</head>
<body>
<h2>Multitenant Tacoshop SaaS</h2>
<a href="https://blogs.sap.com/srv/info">Info</a><br>
<a href="https://blogs.sap.com/srv/subscriptions">Subscriptions</a><br>
<a href="https://blogs.sap.com/srv/destinations?destination=mydest">Destinations</a><br>
<a href="https://blogs.sap.com/Tenant/Catalog/Tacos">Tacos</a><br>
</body>
</html>
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
User | Count |
---|---|
20 | |
10 | |
9 | |
5 | |
4 | |
4 | |
3 | |
3 | |
3 | |
2 |