Skip to content

Commit fd2b8d5

Browse files
Helm Chart (#152)
Co-authored-by: Marc Becker <marc.becker@sap.com>
1 parent 9f526fa commit fd2b8d5

10 files changed

Lines changed: 590 additions & 3 deletions

.gitignore

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ schema.sql
44
schema-nomocks.sql
55
default-env.json
66
openapi.json
7+
.env
8+
.values.yaml
79

810
bin/
911
target/
@@ -31,4 +33,6 @@ hs_err*
3133

3234
*.db
3335

34-
.cdsrc-private.json
36+
.cdsrc-private.json
37+
38+
/chart/

README.md

Lines changed: 177 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@ Welcome to the bookshop-java project. It demonstrates how to build business appl
2121
- [Using IntelliJ Idea (Community and Ultimate)](#using-intellij-idea-community-and-ultimate)
2222
- [Database Setup and Spring Profiles](#database-setup-and-spring-profiles)
2323
- [API_BUSINESS_PARTNER Remote Service and Spring Profiles](#api_business_partner-remote-service-and-spring-profiles)
24-
- [Deploy to SAP Business Technology Platform](#deploy-to-sap-business-technology-platform)
24+
- [Deploy to SAP Business Technology Platform, Cloud Foundry](#deploy-to-sap-business-technology-platform-cloud-foundry)
25+
- [Deploy to SAP Business Technology Platform, Kyma Runtime](#deploy-to-sap-business-technology-platform-kyma-runtime)
26+
- [Setup Authorizations in SAP Business Technology Platform](#setup-authorizations-in-sap-business-technology-platform)
2527
- [Code Tour](#code-tour)
2628
- [Get Support](#get-support)
2729
- [License](#license)
@@ -195,7 +197,7 @@ The behavior of the API_BUSINESS_PARTNER remote service is controlled using prof
195197

196198
The profiles `sandbox` and `destination` can be combined with the `default` profile for [hybrid testing](https://cap.cloud.sap/docs/advanced/hybrid-testing) and with the `cloud` profile when deployed to the cloud.
197199

198-
## Deploy to SAP Business Technology Platform
200+
## Deploy to SAP Business Technology Platform, Cloud Foundry
199201

200202
CAP Java applications can be deployed to the SAP Business Technology Platform either in single tenant or in multitenancy mode. See [Multitenancy in CAP Java](https://cap.cloud.sap/docs/java/multitenancy) for more information.
201203

@@ -220,6 +222,179 @@ Deploy as Multitenant Application:
220222
- Go to another subaccount in your global account, under subscriptions and subscribe to the application you deployed.
221223
- Run `cf map-route bookshop-mt-app <YOUR DOMAIN> --hostname <SUBSCRIBER TENANT>-<ORG>-<SPACE>-bookshop-mt-app` or create and bind the route manually.
222224

225+
Before you can access the UI using the (tenant-specific) URL to the bookshop(-mt)-app application, make sure to [Setup Authorizations in SAP Business Technology Platform](#setup-authorizations-in-sap-business-technology-platform).
226+
227+
## Deploy to SAP Business Technology Platform, Kyma Runtime
228+
229+
**TIP:** You can find more information in the [Deploy Your CAP Application on SAP BTP Kyma Runtime](https://developers.sap.com/mission.btp-deploy-cap-kyma.html) tutorial and in the [Deploy to Kyma/K8s](https://cap.cloud.sap/docs/guides/deployment/deploy-to-kyma) guide of the CAP documentation.
230+
231+
### Preconditions
232+
233+
- BTP Subaccount with Kyma Runtime
234+
- BTP Subaccount with Cloud Foundry Space
235+
- HANA Cloud instance available for your Cloud Foundry space
236+
- BTP Entitlements for: *HANA HDI Services & Container* plan *hdi-shared*, *Launchpad Service* plan *standard*
237+
- Container Registry
238+
- Command Line Tools: `kubectl`, `kubectl-oidc_login`, `pack`, `docker`, `helm`, `cf`
239+
- Logged into Kyma Runtime (with `kubectl` CLI), Cloud Foundry space (with `cf` CLI) and Container Registry (with `docker login`)
240+
- `@sap/cds-dk` >= 6.0.1
241+
242+
### Add Deployment Files
243+
244+
CAP tooling provides your a Helm chart for deployment to Kyma.
245+
246+
Add the CAP Helm chart with the required features to this project:
247+
248+
```bash
249+
cds add helm:hana_deployer
250+
cds add helm:xsuaa
251+
cds add helm:html5_apps_deployer
252+
```
253+
254+
#### Helm chart configuration
255+
256+
This project contains a pre-configured configuration file `values.yaml`, you just need to do the following changes in this file:
257+
258+
- `<your-container-registry>` - full-qualified hostname of your container registry
259+
- `domain`- full-qualified domain name used to access applications in your Kyma cluster
260+
261+
#### Use API_BUSSINESS_PARTNER Remote Service (optional)
262+
263+
You can try the `API_BUSINESS_PARTNER` service with a real S/4HANA system with the following configuration:
264+
265+
1. Create either an on-premise or cloud destination in your subaccount.
266+
267+
2. Add the binding to the destination service for the service (`srv`) to the `values.yaml` file:
268+
269+
```yaml
270+
srv:
271+
...
272+
bindings:
273+
...
274+
destinations:
275+
serviceInstanceName: destinations
276+
```
277+
278+
(The destination service instance is already configured)
279+
280+
3. Set the profiles `cloud` and `destination` active in your `values.yaml` file:
281+
282+
```yaml
283+
srv:
284+
...
285+
env:
286+
SPRING_PROFILES_ACTIVE: cloud,destination
287+
# TODO: To be removed after @sap/cds-dk patch
288+
CDS_ENVIRONMENT_K8S_SERVICEBINDINGS_CONNECTIVITY_SECRETSPATH: '/bindings/connectivity'
289+
CDS_ENVIRONMENT_K8S_SERVICEBINDINGS_CONNECTIVITY_SERVICE: 'connectivity'
290+
```
291+
292+
4. For on-premise only: Add the connectivity service to your Helm chart:
293+
294+
```bash
295+
cds add helm:connectivity
296+
```
297+
298+
*See also: [API_BUSINESS_PARTNER Remote Service and Spring Profiles](#api_business_partner-remote-service-and-spring-profiles)*
299+
300+
### Prepare Kubernetes Namespace
301+
302+
#### Create container registry secret
303+
304+
Create a secret `container-registry` with credentials to access the container registry:
305+
306+
```
307+
bash ./scripts/create-container-registry-secret.sh
308+
```
309+
310+
The *Docker Server* is the full qualified hostname of your container registry.
311+
312+
#### Create a HDI container and a secret
313+
314+
```
315+
bash ./scripts/create-db-secret.sh bookshop-db
316+
```
317+
318+
It will create a HDI container `bookshop-db` on your currently targeted Cloud Foundry space and creates a secret `bookshop-db` with the HDI container's credentials in your current Kubernetes namespace.
319+
320+
### Build
321+
322+
**Build data base deployer image:**
323+
324+
```
325+
cds build --production
326+
327+
pack build $YOUR_CONTAINER_REGISTRY/bookshop-hana-deployer \
328+
--path db \
329+
--buildpack gcr.io/paketo-buildpacks/nodejs \
330+
--builder paketobuildpacks/builder:base
331+
```
332+
333+
(Replace `$YOUR_CONTAINER_REGISTRY` with the full-qualified hostname of your container registry)
334+
335+
336+
**Build image for CAP service:**
337+
338+
```
339+
mvn package
340+
```
341+
342+
```
343+
pack build $YOUR_CONTAINER_REGISTRY/bookshop-srv \
344+
--path srv/target/*-exec.jar \
345+
--buildpack gcr.io/paketo-buildpacks/sap-machine \
346+
--buildpack gcr.io/paketo-buildpacks/java \
347+
--builder paketobuildpacks/builder:base \
348+
--env SPRING_PROFILES_ACTIVE=cloud
349+
```
350+
351+
**Build HTML5 application deployer image:**
352+
353+
```
354+
bash ./scripts/build-ui-image.sh
355+
```
356+
357+
### Push container images
358+
359+
You can push all the container images to your container registry, using:
360+
361+
```
362+
docker push $YOUR_CONTAINER_REGISTRY/bookshop-hana-deployer
363+
364+
docker push $YOUR_CONTAINER_REGISTRY/bookshop-srv
365+
366+
docker push $YOUR_CONTAINER_REGISTRY/bookshop-html5-deployer
367+
```
368+
369+
### Deployment
370+
371+
```
372+
helm upgrade bookshop ./chart --install -f values.yaml
373+
```
374+
375+
### Access the UI
376+
377+
Before you can access the UI you should make sure to [Setup Authorizations in SAP Business Technology Platform](#setup-authorizations-in-sap-business-technology-platform).
378+
379+
1. Create a Launchpad Service subscription in the BTP Cockpit
380+
2. Go to **HTML5 Applications**
381+
3. Start any of the HTML5 applications
382+
383+
Additionally, you can add the UIs to a Launchpad Service site like it is described in in the last two steps of [this tutorial](https://developers.sap.com/tutorials/btp-app-kyma-launchpad-service.html#9aab2dd0-18ea-4ccd-bc44-24e87c845740).
384+
385+
## Setup Authorizations in SAP Business Technology Platform
386+
387+
To access services and UIs that require specific authorizations (e.g. `admin`) you need to assign a corresponding role and role collections to your user in SAP BTP Cockpit.
388+
389+
1. For single-tenant applications open the subaccount where you deployed the `bookshop` application to. For multitenant applications open the subaccount where you subscribed to the `bookshop` application.
390+
2. Navigate to *Security* -> *Roles*
391+
3. Create a role with name `bookshop-admin` based on the `admin` role template of the `bookshop` application:
392+
1. Enter a Business Partner ID of your S/4 system as value for the `businessPartner` attribute. When using the sandbox environment use `10401010`.
393+
4. Navigate to *Security* -> *Role Collections*
394+
5. Create a new role collection `bookshop-admin`:
395+
1. Assign the `bookshop-admin` role to this role collection
396+
2. Assign the role collection to your user
397+
223398
# Code Tour
224399
225400
Take the [guided tour](.tours) in VS Code through our CAP Samples for Java and learn which CAP features are showcased by the different parts of the repository. Just install the [CodeTour extension](https://marketplace.visualstudio.com/items?itemName=vsls-contrib.codetour) for VS Code.

scripts/build-ui-image.sh

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
#!/bin/bash
2+
3+
set -e
4+
cd "$(dirname "$(dirname "$0")")"
5+
6+
npm install --no-save yaml
7+
8+
function value() {
9+
node ./scripts/value.js "$1"
10+
}
11+
12+
function image() {
13+
local REPOSITORY="$(value "$1.image.repository")"
14+
local TAG="$(value "$1.image.tag")"
15+
if [ "$TAG" != "" ]; then
16+
echo "$REPOSITORY:$TAG"
17+
else
18+
echo "$REPOSITORY"
19+
fi
20+
}
21+
22+
rm -rf gen/ui
23+
mkdir -p gen/ui/resources
24+
25+
CLOUD_SERVICE="$(value html5_apps_deployer.cloudService)"
26+
DESTINATIONS="$(value html5_apps_deployer.backendDestinations)"
27+
28+
IMAGE="$(image html5_apps_deployer)"
29+
30+
for APP in app/*; do
31+
if [ -f "$APP/webapp/manifest.json" ]; then
32+
echo "Build $APP..."
33+
echo
34+
35+
rm -rf "gen/$APP"
36+
mkdir -p "gen/app"
37+
cp -r "$APP" gen/app
38+
pushd >/dev/null "gen/$APP"
39+
40+
node ../../../scripts/prepareUiFiles.js $CLOUD_SERVICE $DESTINATIONS
41+
npm install
42+
npx ui5 build preload --clean-dest --config ui5-deploy.yaml --include-task=generateManifestBundle generateCachebusterInfo
43+
cd dist
44+
rm manifest-bundle.zip
45+
mv *.zip ../../../ui/resources
46+
47+
popd >/dev/null
48+
fi
49+
done
50+
51+
cd gen/ui
52+
53+
echo
54+
echo "HTML5 Apps:"
55+
ls -l resources
56+
echo
57+
58+
cat >package.json <<EOF
59+
{
60+
"name": "ui-deployer",
61+
"scripts": { "start": "node node_modules/@sap/html5-app-deployer/index.js" }
62+
}
63+
EOF
64+
65+
npm install @sap/html5-app-deployer
66+
pack build $IMAGE --path . --buildpack gcr.io/paketo-buildpacks/nodejs --builder paketobuildpacks/builder:base
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
#!/bin/bash
2+
3+
read -p "Docker Server: " DOCKER_SERVER
4+
5+
read -p "User ($USER): " DOCKER_USER
6+
if [ "$DOCKER_USER" == "" ]; then
7+
DOCKER_USER="$USER"
8+
fi
9+
10+
if [ "$EMAIL" == "" ]; then
11+
read -p "EMail: " DOCKER_EMAIL
12+
else
13+
read -p "EMail ($EMAIL): " DOCKER_EMAIL
14+
if [ "$DOCKER_EMAIL" == "" ]; then
15+
DOCKER_EMAIL="$EMAIL"
16+
fi
17+
fi
18+
19+
read -sp "API Key: " API_KEY
20+
21+
echo
22+
echo
23+
24+
kubectl create secret docker-registry container-registry \
25+
"--docker-server=$DOCKER_SERVER" \
26+
"--docker-username=$DOCKER_USER" \
27+
"--docker-email=$DOCKER_EMAIL" \
28+
"--docker-password=$API_KEY"

scripts/create-db-secret.sh

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
#!/bin/bash
2+
3+
set -e
4+
cd "$(dirname "$(dirname "$0")")"
5+
6+
npm install --no-save yaml
7+
8+
function value() {
9+
node ./scripts/value.js "$1"
10+
}
11+
12+
NAME="$1"
13+
if [ "$NAME" == "" ]; then
14+
NAME="$(value srv.bindings.db.fromSecret)"
15+
if [ "$NAME" == "" -o "$NAME" == "<nil>" ]; then
16+
echo >&2 "[ERROR] Please either specify the name for the DB secret or maintain it in the Helm chart"
17+
exit 1
18+
fi
19+
fi
20+
21+
SECRET_HEADER="$(cat <<EOF
22+
apiVersion: v1
23+
kind: Secret
24+
metadata:
25+
name: $NAME
26+
type: Opaque
27+
stringData:
28+
type: hana
29+
label: hana
30+
EOF
31+
)"
32+
33+
cf 2>/dev/null >/dev/null service $NAME || cf create-service hana hdi-shared $NAME
34+
while true; do
35+
STATUS="$(cf 2>/dev/null service $NAME | grep status: | head -n 1)"
36+
echo $STATUS
37+
if [[ "$STATUS" = *succeeded* ]]; then
38+
break
39+
fi
40+
sleep 1
41+
done
42+
43+
cf create-service-key $NAME $NAME-key
44+
45+
node "$(dirname "$0")/format-kyma-secret.js" -- "$(echo "$SECRET_HEADER")" "$(cf service-key $NAME $NAME-key)" | kubectl apply -f -
46+
echo
47+
echo "HANA DB Kubernetes secret '$NAME' created."
48+
echo
49+
echo "You can view it using:"
50+
echo
51+
echo "kubectl get secret $NAME -o yaml"
52+
exit 0

scripts/format-kyma-secret.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
const key=JSON.parse(process.argv[4].replace(/^.*/, ""));
2+
const credentials=key.credentials /* new cfcli? */ || key;
3+
console.log(process.argv[3]);
4+
console.log(Object.keys(credentials).map(k => {
5+
if (credentials[k].match(/\n/s))
6+
return (` ${k}: |\n${credentials[k]}`).replace(/\n/gs,"\n ")
7+
else
8+
return ` ${k}: "${credentials[k]}"`
9+
}).join("\n"))

0 commit comments

Comments
 (0)