1- # IBM Cloud Code Engine - Integrate Cloud Object Storage and PostgreSQL through a job and an event subscription
1+ # IBM Cloud Code Engine - Integrate Cloud Object Storage and PostgreSQL through a app and an event subscription
22
33This sample demonstrates how to read CSV files hosted on a IBM Cloud Object Storage and save their contents line by line into relational PostgreSQL database.
44
@@ -7,123 +7,52 @@ This sample demonstrates how to read CSV files hosted on a IBM Cloud Object Stor
77Make sure the following [ IBM Cloud CLI] ( https://cloud.ibm.com/docs/cli/reference/ibmcloud?topic=cloud-cli-getting-started ) and the following list of plugins are installed
88- ` ibmcloud plugin install code-engine `
99- ` ibmcloud plugin install cloud-object-storage `
10+ - ` ibmcloud plugin install secrets-manager `
1011
1112Install ` jq ` . On MacOS, you can use following [ brew formulae] ( https://formulae.brew.sh/formula/jq ) to do a ` brew install jq ` .
12- ## CLI Setup
1313
14- Login to IBM Cloud via the CLI
15- ```
16- ibmcloud login
17- ```
14+ ## Setting up all IBM Cloud Service instances
1815
19- Target the ` ca-tor ` region:
16+ * Login to IBM Cloud via the CLI and target the ` ca-tor ` region:
2017```
2118export REGION=ca-tor
22- ibmcloud -r $REGION
23- ```
24-
25- Create the project:
26- ```
27- ibmcloud code-engine project create -n ce-objectstorage-to-sql
28- ```
29-
30- Store the project guid:
31- ```
32- export CE_ID=$(ibmcloud ce project current -o json | jq -r .guid)
33- ```
34-
35- Create the job:
36- ```
37- ibmcloud code-engine job create \
38- --name csv-to-sql \
39- --source ./ \
40- --retrylimit 0 \
41- --cpu 0.25 \
42- --memory 0.5G \
43- --wait
19+ export RESOURCE_GROUP=Default
20+ ibmcloud login -r ${REGION} -g $RESOURCE_GROUP
4421```
4522
46- Create the app:
47- ```
48- ibmcloud code-engine app create \
49- --name csv-to-sql-app \
50- --source ./ \
51- --cpu 0.25 \
52- --memory 0.5G \
53- --env COS_REGION=eu-es \
54- --env COS_TRUSTED_PROFILE_NAME=code-engine-cos-access \
55- --env SM_TRUSTED_PROFILE_NAME=code-engine-sm-access \
56- --env SM_SERVICE_URL=https://4e61488a-b76f-4d44-ba0e-ed2489d8a57a.private.eu-es.secrets-manager.appdomain.cloud \
57- --env SM_PG_SECRET_ID=04abb32c-bbe3-a069-e4c4-8899853ef053
23+ * Create the Code Engine project
5824```
25+ export CE_INSTANCE_NAME=cos-to-sql--ce
26+ ibmcloud code-engine project create -n ${CE_INSTANCE_NAME}
5927
60- Create the COS instance:
61- ```
62- ibmcloud resource service-instance-create csv-to-sql-cos cloud-object-storage standard global
28+ export CE_INSTANCE_GUID=$(ibmcloud ce project current -o json | jq -r .guid)
29+ export CE_INSTANCE_ID=$(ibmcloud resource service-instance ${CE_INSTANCE_NAME} --output json | jq -r '.[0] | .id')
6330```
6431
65- Store the COS CRN:
66- ```
67- export COS_ID=$(ibmcloud resource service-instance csv-to-sql-cos --output json | jq -r '.[0] | .id')
32+ * Create the COS instance
6833```
34+ export COS_INSTANCE_NAME=cos-to-sql--cos
35+ ibmcloud resource service-instance-create ${COS_INSTANCE_NAME} cloud-object-storage standard global
6936
70- Create an authorization policy to allow the Code Engine project receive events from COS:
71- ```
72- ibmcloud iam authorization-policy-create codeengine cloud-object-storage \
73- "Notifications Manager" \
74- --source-service-instance-id $CE_ID \
75- --target-service-instance-id $COS_ID
37+ export COS_INSTANCE_ID=$(ibmcloud resource service-instance ${COS_INSTANCE_NAME} --output json | jq -r '.[0] | .id')
7638```
7739
78- Create a COS bucket:
40+ * Create a COS bucket
7941```
80- ibmcloud cos config crn --crn $COS_ID --force
42+ ibmcloud cos config crn --crn ${COS_INSTANCE_ID} --force
8143ibmcloud cos config auth --method IAM
82- ibmcloud cos config region --region $REGION
83- ibmcloud cos config endpoint-url --url s3.$REGION.cloud-object-storage.appdomain.cloud
84- export BUCKET=$CE_ID -csv-to-sql
44+ ibmcloud cos config region --region ${ REGION}
45+ ibmcloud cos config endpoint-url --url s3.${ REGION} .cloud-object-storage.appdomain.cloud
46+ export COS_BUCKET_NAME=${CE_INSTANCE_GUID} -csv-to-sql
8547ibmcloud cos bucket-create \
8648 --class smart \
87- --bucket $BUCKET
88- ```
89-
90- Creating a trusted profile that grants a Code Engine Job access to your COS bucket
91- ```
92- REGION=eu-es
93- RESOURCE_GROUP=Default
94- COS_INSTANCE_NAME=csv-to-sql-cos
95- COS_BUCKET=$CE_ID-csv-to-sql
96- CE_PROJECT_NAME=ce-objectstorage-to-sql
97- JOB_NAME=csv-to-sql
98- TRUSTED_PROFILE_NAME=code-engine-cos-access
99-
100- CE_PROJECT_CRN=$(ibmcloud resource service-instance ${CE_PROJECT_NAME} --location ${REGION} -g ${RESOURCE_GROUP} --crn 2>/dev/null | grep ':codeengine:')
101- COS_INSTANCE_ID=$(ibmcloud resource service-instance ${COS_INSTANCE_NAME} --crn 2>/dev/null | grep ':cloud-object-storage:')
102-
103- ibmcloud iam trusted-profile-create ${TRUSTED_PROFILE_NAME}
104- ibmcloud iam trusted-profile-link-create ${TRUSTED_PROFILE_NAME} --name ce-job-${JOB_NAME} --cr-type CE --link-crn ${CE_PROJECT_CRN} --link-component-type job --link-component-name ${JOB_NAME}
105- ibmcloud iam trusted-profile-policy-create ${TRUSTED_PROFILE_NAME} --roles "Content Reader" --service-name cloud-object-storage --service-instance ${COS_INSTANCE_ID} --resource-type bucket --resource ${COS_BUCKET}
106- ```
107-
108- Create the subscription for all COS events:
109- ```
110- ibmcloud ce sub cos create \
111- --name coswatch \
112- --bucket $BUCKET \
113- --destination csv-to-sql \
114- --destination-type job
115-
116- ibmcloud ce sub cos create \
117- --name coswatch \
118- --bucket $BUCKET \
119- --destination csv-to-sql-app \
120- --destination-type app \
121- --path /cos-to-sql
49+ --bucket $COS_BUCKET_NAME
12250```
12351
124- Create a PostgreSQL service instance:
52+ * Create the PostgreSQL instance
12553```
126- ibmcloud resource service-instance-create csv-to-sql-postgresql databases-for-postgresql standard $REGION --service-endpoints private -p \
54+ export DB_INSTANCE_NAME=cos-to-sql--pg
55+ ibmcloud resource service-instance-create $DB_INSTANCE_NAME databases-for-postgresql standard ${REGION} --service-endpoints private -p \
12756 '{
12857 "disk_encryption_instance_crn": "none",
12958 "disk_encryption_key_crn": "none",
@@ -135,90 +64,113 @@ ibmcloud resource service-instance-create csv-to-sql-postgresql databases-for-po
13564 "service-endpoints": "private",
13665 "version": "16"
13766}'
138- ```
13967
140- Create a trusted profile that grants this Code Engine job access to the COS instance
68+ export DB_INSTANCE_ID=$(ibmcloud resource service-instance $DB_INSTANCE_NAME --location ${REGION} --output json | jq -r '.[0] | .id')
14169```
142- REGION=eu-es
143- RESOURCE_GROUP=Default
144- COS_INSTANCE_NAME=my-first-cos
145- COS_BUCKET=my-first-bucket-31292
146- CE_PROJECT_NAME=trusted-profiles-test
147- JOB_NAME=list-cos-files
148- COS_TRUSTED_PROFILE_NAME=code-engine-cos-access
149- SM_TRUSTED_PROFILE_NAME=code-engine-sm-access
150- SM_SERVICE_URL=https://4e61488a-b76f-4d44-ba0e-ed2489d8a57a.private.eu-es.secrets-manager.appdomain.cloud
151- SM_PG_SECRET_ID=
15270
153- CE_PROJECT_CRN=$(ibmcloud resource service-instance ${CE_PROJECT_NAME} --location ${REGION} -g ${RESOURCE_GROUP} --crn 2>/dev/null | grep ':codeengine:')
154- COS_INSTANCE_ID=$(ibmcloud resource service-instance ${COS_INSTANCE_NAME} --crn 2>/dev/null | grep ':cloud-object-storage:')
71+ * Create the Secrets Manager instance
72+ ```
73+ export SM_INSTANCE_NAME=cos-to-sql--sm
74+ ibmcloud resource service-instance-create $SM_INSTANCE_NAME secrets-manager 7713c3a8-3be8-4a9a-81bb-ee822fcaac3d ${REGION} -p \
75+ '{
76+ "allowed_network": "public-and-private"
77+ }'
15578
156- ibmcloud iam trusted-profile-create ${TRUSTED_PROFILE_NAME}
157- ibmcloud iam trusted-profile-link-create ${TRUSTED_PROFILE_NAME} --name ce-job-${JOB_NAME } --cr-type CE --link-crn ${CE_PROJECT_CRN} --link-component-type job --link-component-name ${JOB_NAME}
158- ibmcloud iam trusted-profile-policy-create ${TRUSTED_PROFILE_NAME} --roles "Content Reader" --service-name cloud-object-storage --service-instance ${COS_INSTANCE_ID} --resource-type bucket --resource ${COS_BUCKET}
79+ export SM_INSTANCE_ID=$( ibmcloud resource service-instance $SM_INSTANCE_NAME --location ${REGION} --output json | jq -r '.[0] | .id')
80+ export SM_INSTANCE_GUID=$( ibmcloud resource service-instance $SM_INSTANCE_NAME --location ${REGION } --output json | jq -r '.[0] | .guid')
81+ export SECRETS_MANAGER_URL=https://$SM_INSTANCE_GUID.${REGION}.secrets-manager.appdomain.cloud
15982```
16083
161- Update the job by adding a binding to the PostgreSQL instance:
84+ * Create a S2S policy "Key Manager" between SM and the DB
16285```
163- ibmcloud code-engine job update \
164- --name csv-to-sql \
165- --trusted-profiles-enabled true \
166- --env COS_REGION=${REGION} \
167- --env COS_TRUSTED_PROFILE_NAME=${COS_TRUSTED_PROFILE_NAME} \
168- --env SM_TRUSTED_PROFILE_NAME=${SM_TRUSTED_PROFILE_NAME}\
169- --env SM_SERVICE_URL=${SM_SERVICE_URL} \
170- --env SM_PG_SECRET_ID=${SM_PG_SECRET_ID}
86+ ibmcloud iam authorization-policy-create secrets-manager databases-for-postgresql \
87+ "Key Manager" \
88+ --source-service-instance-id $SM_INSTANCE_ID \
89+ --target-service-instance-id $DB_INSTANCE_ID
17190```
17291
173- Create a Secrets Manager instance
174- ```
175- ibmcloud resource service-instance-create credential-store secrets-manager 7713c3a8-3be8-4a9a-81bb-ee822fcaac3d eu-es -p \
176- '{
177- "allowed_network": "private-only"
178- }'
92+ * Create the service credential to access the PostgreSQL instance
17993```
94+ SM_SECRET_FOR_PG_NAME=pg-access-credentials
95+ ibmcloud secrets-manager secret-create --secret-type="service_credentials" --secret-name="$SM_SECRET_FOR_PG_NAME" --secret-source-service="{\"instance\": {\"crn\": \"$DB_INSTANCE_ID\"},\"parameters\": {},\"role\": {\"crn\": \"crn:v1:bluemix:public:iam::::serviceRole:Writer\"}}"
18096
181- // Create a Trusted Profile for Secrets Manager
97+ export SM_SECRET_FOR_PG_ID=$(ibmcloud sm secret-by-name --name $SM_SECRET_FOR_PG_NAME --secret-type service_credentials --secret-group-name default --output JSON|jq -r '.id')
98+ ```
18299
183- // Create a S2S policy "Key Manager" between SM and the DB
184100
185- // Create a service credential for PG with automatic key rotation
101+ * Create the Code Engine app:
102+ ```
103+ export CE_APP_NAME=csv-to-sql
104+ export TRUSTED_PROFILE_FOR_COS_NAME=cos-to-sql--ce-to-cos-access
105+ export TRUSTED_PROFILE_FOR_SM_NAME=cos-to-sql--ce-to-sm-access
186106
107+ ibmcloud code-engine app create \
108+ --name ${CE_APP_NAME} \
109+ --source ./ \
110+ --cpu 0.25 \
111+ --memory 0.5G \
112+ --trusted-profiles-enabled="true" \
113+ --probe-ready type=http \
114+ --probe-ready path=/readiness \
115+ --probe-ready interval=30 \
116+ --env COS_REGION=${REGION} \
117+ --env COS_TRUSTED_PROFILE_NAME=${TRUSTED_PROFILE_FOR_COS_NAME} \
118+ --env SM_TRUSTED_PROFILE_NAME=${TRUSTED_PROFILE_FOR_SM_NAME} \
119+ --env SM_SERVICE_URL=${SECRETS_MANAGER_URL} \
120+ --env SM_PG_SECRET_ID=${SM_SECRET_FOR_PG_ID}
121+ ```
187122
123+ ## Trusted Profile setup
188124
189- // ibmcloud secrets-manager secret-by-name --secret-type service_credentials --name pg-credentials --secret-group-name --service-url https://4e61488a-b76f-4d44-ba0e-ed2489d8a57a.private.eu-es.secrets-manager.appdomain.cloud
125+ * Create a trusted profile that grants a Code Engine app access to your COS bucket
126+ ```
127+ ibmcloud iam trusted-profile-create ${TRUSTED_PROFILE_FOR_COS_NAME}
128+ ibmcloud iam trusted-profile-link-create ${TRUSTED_PROFILE_FOR_COS_NAME} --name ce-app-${CE_APP_NAME} --cr-type CE --link-crn ${CE_INSTANCE_ID} --link-component-type application --link-component-name ${CE_APP_NAME}
129+ ibmcloud iam trusted-profile-policy-create ${TRUSTED_PROFILE_FOR_COS_NAME} --roles "Content Reader" --service-name cloud-object-storage --service-instance ${COS_INSTANCE_ID} --resource-type bucket --resource ${COS_BUCKET_NAME}
130+ ```
190131
191- // https://github.com/IBM/secrets-manager-node-sdk
192132
193- Upload a CSV file to COS, to initate an event that leads to a job execution:
133+ * Create the trusted profile to access Secrets Manager
194134```
195- ibmcloud cos object-put \
196- --bucket $BUCKET \
197- --key users.csv \
198- --body ./samples/users.csv \
199- --content-type text/csv
135+ ibmcloud iam trusted-profile-create ${TRUSTED_PROFILE_FOR_SM_NAME}
136+ ibmcloud iam trusted-profile-link-create ${TRUSTED_PROFILE_FOR_SM_NAME} --name ce-app-${CE_APP_NAME} --cr-type CE --link-crn ${CE_INSTANCE_ID} --link-component-type application --link-component-name ${CE_APP_NAME}
137+ ibmcloud iam trusted-profile-policy-create ${TRUSTED_PROFILE_FOR_SM_NAME} --roles "SecretsReader" --service-name secrets-manager --service-instance ${SM_INSTANCE_ID}
200138```
201139
202- List all jobs to determine the one, that processes the COS bucket update:
140+ ## Setting up eventing
141+
142+ * Create an authorization policy to allow the Code Engine project receive events from COS:
203143```
204- ibmcloud code-engine jobrun list \
205- --job csv-to-sql \
206- --sort-by age
144+ ibmcloud iam authorization-policy-create codeengine cloud-object-storage \
145+ "Notifications Manager" \
146+ --source-service-instance-id ${CE_INSTANCE_ID} \
147+ --target-service-instance-id ${COS_INSTANCE_ID}
207148```
208149
209- Inspect the job execution by opening the logs :
150+ * Create the subscription for all COS events :
210151```
211- ibmcloud code-engine jobrun logs \
212- --name <jobrun-name>
152+ ibmcloud ce sub cos create \
153+ --name "coswatch-${CE_APP_NAME}" \
154+ --bucket ${COS_BUCKET_NAME} \
155+ --destination ${CE_APP_NAME} \
156+ --destination-type app \
157+ --path /cos-to-sql
213158```
214159
215- Or do the two commands in one, using this one-liner:
160+ ## Verify the solution
161+
162+ * Upload a CSV file to COS, to initate an event that leads to a job execution:
216163```
217- jobrunname=$(ibmcloud ce jr list -j csv-to-sql -s age -o json | jq -r '.items[0] | .metadata.name') && ibmcloud ce jr logs -n $jobrunname -f
164+ ibmcloud cos object-put \
165+ --bucket ${COS_BUCKET_NAME} \
166+ --key users.csv \
167+ --body ./samples/users.csv \
168+ --content-type text/csv
218169```
219170
220-
171+ * Inspect the app execution by opening the logs:
172+ ```
173+ ibmcloud code-engine app logs \
174+ --name ${CE_APP_NAME} \
175+ --follow
221176```
222- kubectl patch jobdefinitions csv-to-sql --type='json' -p='[{"op": "add", "path": "/spec/template/mountComputeResourceToken", "value":true}]'
223- kubectl patch ksvc csv-to-sql-app --type='json' -p='[{"op": "add", "path": "/spec/template/metadata/annotations/codeengine.cloud.ibm.com~1mount-compute-resource-token", "value":"true"}]'
224- ```
0 commit comments