From 3fdee31e08dcaf54fd8ee246814b86b55c546636 Mon Sep 17 00:00:00 2001 From: Zhongwei Li Date: Sun, 30 Nov 2025 08:55:10 +0800 Subject: [PATCH] Initial commit --- .claude-plugin/plugin.json | 12 + README.md | 3 + SKILL.md | 401 +++++++++++++++ plugin.lock.json | 85 +++ references/changelog.md | 400 +++++++++++++++ references/concepts.md | 472 +++++++++++++++++ references/integrations.md | 310 +++++++++++ references/operations.md | 321 ++++++++++++ references/rest-api.md | 937 ++++++++++++++++++++++++++++++++++ references/security.md | 437 ++++++++++++++++ references/setup-guide.md | 397 ++++++++++++++ references/troubleshooting.md | 379 ++++++++++++++ templates/job-creation.json | 76 +++ templates/xs-security.json | 66 +++ 14 files changed, 4296 insertions(+) create mode 100644 .claude-plugin/plugin.json create mode 100644 README.md create mode 100644 SKILL.md create mode 100644 plugin.lock.json create mode 100644 references/changelog.md create mode 100644 references/concepts.md create mode 100644 references/integrations.md create mode 100644 references/operations.md create mode 100644 references/rest-api.md create mode 100644 references/security.md create mode 100644 references/setup-guide.md create mode 100644 references/troubleshooting.md create mode 100644 templates/job-creation.json create mode 100644 templates/xs-security.json diff --git a/.claude-plugin/plugin.json b/.claude-plugin/plugin.json new file mode 100644 index 0000000..2034bd5 --- /dev/null +++ b/.claude-plugin/plugin.json @@ -0,0 +1,12 @@ +{ + "name": "sap-btp-job-scheduling", + "description": "Job Scheduling Service for one-time and recurring jobs on BTP. Covers REST API, cron schedules, OAuth 2.0, Cloud Foundry tasks, and Kyma integration.", + "version": "1.0.0", + "author": { + "name": "Zhongwei Li", + "email": "zhongweili@tubi.tv" + }, + "skills": [ + "./" + ] +} \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..1623be9 --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +# sap-btp-job-scheduling + +Job Scheduling Service for one-time and recurring jobs on BTP. Covers REST API, cron schedules, OAuth 2.0, Cloud Foundry tasks, and Kyma integration. diff --git a/SKILL.md b/SKILL.md new file mode 100644 index 0000000..ac0ca97 --- /dev/null +++ b/SKILL.md @@ -0,0 +1,401 @@ +--- +name: sap-btp-job-scheduling +description: | + This skill provides comprehensive guidance for SAP BTP Job Scheduling Service development, configuration, and operations. + It should be used when creating, managing, or troubleshooting scheduled jobs on SAP Business Technology Platform. + + The skill covers service setup, REST API usage, schedule types and formats, OAuth 2.0 authentication, multitenancy, + Cloud Foundry tasks, Kyma runtime integration, and monitoring with SAP Cloud ALM and Alert Notification Service. + + Keywords: SAP BTP, Job Scheduling, jobscheduler, cron, schedule, recurring jobs, one-time jobs, Cloud Foundry tasks, + CF tasks, Kyma, OAuth 2.0, XSUAA, @sap/jobs-client, REST API, asynchronous jobs, action endpoint, run logs, + SAP Cloud ALM, Alert Notification Service, multitenancy, tenant-aware, BC-CP-CF-JBS +license: GPL-3.0 +metadata: + version: "1.0.1" + last_verified: "2025-11-27" +--- + +# SAP BTP Job Scheduling Service + +## Table of Contents + +- [Overview](#overview) +- [When to Use This Skill](#when-to-use-this-skill) +- [Quick Decision Tree](#quick-decision-tree) +- [Core Concepts](#core-concepts) +- [Service Constraints](#service-constraints) +- [Quick Reference Tables](#quick-reference-tables) + - [Schedule Formats](#schedule-formats) + - [Cron Format (7 fields)](#cron-format-7-fields) + - [Schedule Lifecycle States](#schedule-lifecycle-states) + - [HTTP Methods for Jobs](#http-methods-for-jobs) +- [Best Practices](#best-practices) + - [Scheduling Optimization](#scheduling-optimization) + - [Asynchronous Jobs](#asynchronous-jobs) + - [One-Time Schedules](#one-time-schedules) +- [Authentication Quick Start](#authentication-quick-start) + - [Standard Plan (OAuth 2.0)](#standard-plan-oauth-20) + - [xs-security.json Configuration](#xs-securityjson-configuration) +- [Create Job Example](#create-job-example) +- [Node.js Client Library](#nodejs-client-library) +- [Rate Limits](#rate-limits) +- [Service Behavior](#service-behavior) + - [Outage Recovery](#outage-recovery) + - [Auto-Deactivation Triggers](#auto-deactivation-triggers) +- [Bundled Resources](#bundled-resources) +- [Common Pitfalls](#common-pitfalls) +- [External Resources](#external-resources) +- [Updates and Maintenance](#updates-and-maintenance) + +## Overview + +SAP Job Scheduling Service is a runtime-agnostic platform service for defining and managing one-time and recurring jobs or Cloud Foundry tasks on SAP BTP. It operates across multiple hyperscalers (AWS, Azure, GCP) without requiring application modifications. + +**Documentation Source**: [https://help.sap.com/docs/job-scheduling](https://help.sap.com/docs/job-scheduling) + +**Last Verified**: 2025-11-27 + +## When to Use This Skill + +Use this skill when: + +- **Setting up Job Scheduling Service** on Cloud Foundry or Kyma runtime +- **Creating and managing jobs** via REST API or dashboard +- **Configuring schedules** using cron, date/time, or human-readable formats +- **Implementing asynchronous job execution** for long-running processes +- **Securing action endpoints** with OAuth 2.0 and XSUAA +- **Integrating with SAP Cloud ALM** or Alert Notification Service +- **Developing multitenant applications** with tenant-aware job scheduling +- **Troubleshooting job execution issues** and schedule failures +- **Using the Node.js client library** (@sap/jobs-client) + +## Quick Decision Tree + +### What Task? + +``` +Setup & Configuration +├─ Initial setup prerequisites → references/setup-guide.md +├─ Create service instance +│ ├─ BTP Cockpit → references/setup-guide.md#cockpit +│ ├─ CF CLI → references/setup-guide.md#cf-cli +│ └─ Kyma Dashboard → references/setup-guide.md#kyma +└─ Configure XSUAA scopes → references/security.md + +Job Management +├─ Create jobs → references/rest-api.md#create-job +├─ Configure schedules → references/rest-api.md#schedules +├─ Run logs & monitoring → references/rest-api.md#run-logs +└─ Dashboard operations → references/operations.md#dashboard + +Schedule Configuration +├─ One-time vs recurring → references/concepts.md#schedule-types +├─ Cron format → references/concepts.md#cron-format +├─ Date/time formats → references/concepts.md#date-formats +└─ Human-readable → references/concepts.md#human-readable + +Asynchronous Execution +├─ Async mode flow → references/concepts.md#async-mode +├─ Callback implementation → references/rest-api.md#update-run-log +└─ CF tasks → references/concepts.md#cf-tasks + +Security & Authentication +├─ OAuth 2.0 setup → references/security.md#oauth +├─ XSUAA configuration → references/security.md#xsuaa +└─ Credential rotation → references/security.md#rotation + +Integrations +├─ SAP Cloud ALM → references/integrations.md#cloud-alm +└─ Alert Notification → references/integrations.md#alert-notification + +Troubleshooting +├─ Common errors → references/troubleshooting.md#errors +├─ FAQ → references/troubleshooting.md#faq +└─ Support: BC-CP-CF-JBS + +Version History & Updates +└─ What's New (2021-2025) → references/changelog.md +``` + +## Core Concepts + +### Job +A collection of schedules with an action endpoint. Jobs invoke a configured URL at specified times synchronously (short operations) or asynchronously (long processes). + +### Schedule +A one-time or recurring entity within a job. Supports multiple formats (cron, date/time, human-readable) and has three lifecycle states: SCHEDULED → RUNNING → COMPLETED. + +### Action Endpoint +An HTTP/REST endpoint exposed by your application that the service invokes when schedules trigger. Must be OAuth 2.0 protected in production. + +### Cloud Foundry Task +An app or script that runs independently in its own container. Always executes asynchronously with configurable memory allocation. + +## Service Constraints + +| Constraint | Value | +|------------|-------| +| Minimum schedule interval | 5 minutes | +| Synchronous request timeout | 15 seconds | +| Asynchronous timeout (default) | 30 minutes (configurable up to 7 days) | +| POST request body limit | 100 KB | +| Run log retention | 15 days | +| Service SLA | ~20 minutes from scheduled time | + +## Quick Reference Tables + +### Schedule Formats + +| Format | Example | Use Case | +|--------|---------|----------| +| Cron | `* * * * 10:12 0,30 0` | Every 30 min between 10:00-12:00 | +| Date/Time | `2025-10-20T04:30:00Z` | ISO-8601 one-time execution | +| Human-readable | `tomorrow at 4pm` | Natural language scheduling | +| repeatInterval | `2 hours`, `5 minutes` | Recurring at fixed intervals | +| repeatAt | `4.40pm`, `18:40` | Daily at specific time | + +### Cron Format (7 fields) + +``` +Year Month Day DayOfWeek Hour Minute Second +* * * * * * * +``` + +| Field | Values | Special | +|-------|--------|---------| +| Year | 4-digit (2025) | * = any | +| Month | 1-12 | */a = every a-th | +| Day | -31 to 31 | negative = from end | +| DayOfWeek | mon, tue, wed... | a.y = a-th occurrence | +| Hour | 0-23 | a:b = range | +| Minute | 0-59 | a:b/c = step in range | +| Second | 0-59 | a,b,c = multiple values | + +### Schedule Lifecycle States + +| Phase | States | Description | +|-------|--------|-------------| +| SCHEDULED | SCHEDULED | Queued for future run | +| RUNNING | TRIGGERED, ACK_RECVD, ACK_NOT_RECVD | Executing | +| COMPLETED | SUCCESS, ERROR, REQUEST_ERROR, UNKNOWN | Finished | + +### HTTP Methods for Jobs + +| Method | Endpoint | Purpose | +|--------|----------|---------| +| POST | `/scheduler/jobs` | Create job | +| GET | `/scheduler/jobs` | List all jobs | +| GET | `/scheduler/jobs/{id}` | Get job details | +| PUT | `/scheduler/jobs/{id}` | Update job | +| DELETE | `/scheduler/jobs/{id}` | Delete job | + +## Best Practices + +### Scheduling Optimization + +**Avoid Peak Times:** +- ❌ 0th or 30th second of any minute +- ❌ 0th, 30th, or multiples of 5 minutes +- ❌ Top of each hour +- ❌ Midnight UTC (busiest time) + +**Use Irregular Times:** +- ✅ `01:12:17` instead of `01:00:00` +- ✅ `01:38:37` instead of `01:30:00` + +### Asynchronous Jobs + +1. **Return 202 Accepted immediately** - Don't block the request +2. **Store request headers** - `x-sap-job-id`, `x-sap-job-schedule-id`, `x-sap-job-run-id`, `x-sap-scheduler-host` +3. **Update run log on completion** - Single API call with final status +4. **Handle timeouts** - Default 30 min, configurable up to 7 days + +### One-Time Schedules + +- Use only for testing/validation +- Auto-deactivate after execution +- Use `"time": "now"` for immediate execution + +## Authentication Quick Start + +### Standard Plan (OAuth 2.0) + +```bash +# Get access token +curl -X POST "/oauth/token" \ + -H "Authorization: Basic $(echo -n ':' | base64)" \ + -d "grant_type=client_credentials" + +# Use token in API calls +curl -X GET "[https://jobscheduler-rest./scheduler/jobs"](https://jobscheduler-rest./scheduler/jobs") \ + -H "Authorization: Bearer " \ + -H "Content-Type: application/json" +``` + +### xs-security.json Configuration + +```json +{ + "xsappname": "", + "scopes": [{ + "name": "$XSAPPNAME.JOBSCHEDULER", + "description": "Job Scheduler Scope", + "grant-as-authority-to-apps": ["$XSSERVICENAME()"] + }] +} +``` + +## Create Job Example + +```json +POST /scheduler/jobs +{ + "name": "myJob", + "description": "Process daily reports", + "action": "[https://myapp.cfapps.eu10.hana.ondemand.com/api/process",](https://myapp.cfapps.eu10.hana.ondemand.com/api/process",) + "active": true, + "httpMethod": "POST", + "schedules": [{ + "active": true, + "description": "Daily at 6 AM", + "repeatAt": "6.00am", + "startTime": {"date": "2025-01-01", "format": "YYYY-MM-DD"} + }] +} +``` + +## Node.js Client Library + +**Requirements**: Node.js 14.x or later + +```bash +npm install @sap/jobs-client@1.8.6 +``` + +```javascript +const JobSchedulerClient = require('@sap/jobs-client'); +const scheduler = new JobSchedulerClient.Scheduler(); + +// Create job +scheduler.createJob({ url: vcapServices.jobscheduler[0].credentials.url }, { + name: 'myJob', + action: '[https://myapp.../process',](https://myapp.../process',) + active: true, + httpMethod: 'GET', + schedules: [{ cron: '* * * * 0 0 0', active: true }] +}, (err, result) => { /* handle */ }); +``` + +## Rate Limits + +| Limit Type | Response Code | Header | +|------------|---------------|--------| +| Client limit exceeded | 429 | `retry-after` (seconds) | +| Absolute limit exceeded | 503 | `throttling` (milliseconds) | + +Limits stack - both can apply simultaneously. + +## Service Behavior + +### Outage Recovery + +| Outage Duration | Behavior | +|-----------------|----------| +| < 20 minutes | All missed executions run immediately | +| >= 20 minutes | Only last missed execution runs | + +### Auto-Deactivation Triggers + +- One-time schedule executed +- No valid future dates exist +- Job/schedule endTime reached +- Action endpoint unreachable for 10+ days + +## Reference Files + +### Detailed Guides Available + +1. **references/concepts.md** - Schedule types, formats, lifecycle, async mode, multitenancy +2. **references/rest-api.md** - Complete REST API reference with all endpoints +3. **references/setup-guide.md** - Prerequisites, service instance creation +4. **references/security.md** - OAuth 2.0, XSUAA scopes, credential rotation +5. **references/integrations.md** - Cloud ALM, Alert Notification Service +6. **references/troubleshooting.md** - FAQ, error scenarios, monitoring +7. **references/operations.md** - Dashboard, backup/restore, service behavior +8. **references/changelog.md** - Version history, feature updates (2021-2025) + +### Templates Available + +1. **templates/job-creation.json** - Job creation request template +2. **templates/xs-security.json** - XSUAA configuration template + +## Common Pitfalls + +**Setup:** +- ❌ Missing XSUAA binding before Job Scheduling binding +- ❌ Not granting scopes via `grant-as-authority-to-apps` +- ❌ Using HTTP instead of HTTPS for action endpoints + +**Scheduling:** +- ❌ Using Linux cron format (service uses SAP cron) +- ❌ Scheduling at peak times (00:00, 00:30, etc.) +- ❌ Forgetting UTC timezone (only supported timezone) + +**Async Jobs:** +- ❌ Not returning 202 Accepted immediately +- ❌ Forgetting to call Update Run Log API +- ❌ Multiple status updates instead of single final update + +**Multitenancy:** +- ❌ Using `tenantId` filter with SaaS tenant tokens (returns 400) +- ❌ Missing Job Scheduling as application dependency + +## External Resources + +### SAP Documentation +- **SAP Help Portal**: [https://help.sap.com/docs/job-scheduling](https://help.sap.com/docs/job-scheduling) +- **SAP Developer Center**: [https://developers.sap.com/](https://developers.sap.com/) + +### Support +- **Component**: BC-CP-CF-JBS +- **SAP Trust Center**: Platform status verification +- **Guided Answers**: Self-service troubleshooting + +## Updates and Maintenance + +**Source**: SAP BTP Job Scheduling Service Documentation + +**To Update This Skill**: +1. Check GitHub repository for documentation updates +2. Review What's New section for changes +3. Update affected reference files +4. Update templates if configurations changed +5. Update "Last Verified" date + +**Quarterly Review Recommended**: Check for updates every 3 months + +**Next Review**: 2026-02-27 + +## Bundled Resources + +### Reference Files +1. **references/concepts.md** - Schedule types, formats, lifecycle, async mode, multitenancy (12K lines) +2. **references/rest-api.md** - Complete REST API reference with all endpoints (20K lines) +3. **references/setup-guide.md** - Prerequisites, service instance creation (9K lines) +4. **references/security.md** - OAuth 2.0, XSUAA scopes, credential rotation (11K lines) +5. **references/integrations.md** - Cloud ALM, Alert Notification Service (8K lines) +6. **references/troubleshooting.md** - FAQ, error scenarios, monitoring (9K lines) +7. **references/operations.md** - Dashboard, backup/restore, service behavior (8K lines) +8. **references/changelog.md** - Version history, feature updates (2021-2025) (9K lines) + +### Templates +1. **templates/job-creation.json** - Job creation request template with examples +2. **templates/xs-security.json** - XSUAA configuration template for OAuth scopes + +--- + +**Skill Version**: 1.0.1 +**Last Updated**: 2025-11-27 +**License**: GPL-3.0 +**Maintainer**: SAP Skills Team | [https://github.com/secondsky/sap-skills](https://github.com/secondsky/sap-skills) diff --git a/plugin.lock.json b/plugin.lock.json new file mode 100644 index 0000000..7ece861 --- /dev/null +++ b/plugin.lock.json @@ -0,0 +1,85 @@ +{ + "$schema": "internal://schemas/plugin.lock.v1.json", + "pluginId": "gh:secondsky/sap-skills:skills/sap-btp-job-scheduling", + "normalized": { + "repo": null, + "ref": "refs/tags/v20251128.0", + "commit": "aea73701fe9535444c4fac7d8ddbe3c83e5fbfd1", + "treeHash": "071d953e16ae40978f3dbe266ba74e045fc180ea28c94140c11abed04c32cdb2", + "generatedAt": "2025-11-28T10:28:13.034617Z", + "toolVersion": "publish_plugins.py@0.2.0" + }, + "origin": { + "remote": "git@github.com:zhongweili/42plugin-data.git", + "branch": "master", + "commit": "aa1497ed0949fd50e99e70d6324a29c5b34f9390", + "repoRoot": "/Users/zhongweili/projects/openmind/42plugin-data" + }, + "manifest": { + "name": "sap-btp-job-scheduling", + "description": "Job Scheduling Service for one-time and recurring jobs on BTP. Covers REST API, cron schedules, OAuth 2.0, Cloud Foundry tasks, and Kyma integration.", + "version": "1.0.0" + }, + "content": { + "files": [ + { + "path": "README.md", + "sha256": "e4d58e44164da505a109c360c63e084f85da892ea09590d0d48c8c1194b9a6a5" + }, + { + "path": "SKILL.md", + "sha256": "3885d6d5de0f4e5ec722768676a61aef5d2066521b0334d382a3d9bbfca07b5e" + }, + { + "path": "references/operations.md", + "sha256": "5bb8bddca2d75dc219fc7ae6e0e419d84d803763f35b5968758cf1f07470e268" + }, + { + "path": "references/changelog.md", + "sha256": "d6b59703cdd645c51d4d0e189e8d6de8a73e60922f0da39233b2819bc11936a6" + }, + { + "path": "references/troubleshooting.md", + "sha256": "1b155e3fbc362718f2e08c8b928f12d8a6cf72da7631e1afe295385e620584a8" + }, + { + "path": "references/concepts.md", + "sha256": "a1bad502cca083832548b6bd5245f26423d2396561e59dadc2e5d48833d8416e" + }, + { + "path": "references/integrations.md", + "sha256": "6eb9c93e86791bb6033f708da7b158ee892dd875894847c1c58fadf55fde2add" + }, + { + "path": "references/setup-guide.md", + "sha256": "6c3d6d61ada193d5b6ee971346672c1e53fab640d393b57e7862faef2a97d48e" + }, + { + "path": "references/security.md", + "sha256": "c360fd470aa3af1902c37040e20193fc7d202edd15a8bdd3f0e389011910bd05" + }, + { + "path": "references/rest-api.md", + "sha256": "46fe690354998189a83f7a4110a7a3968b76191851de1549ec156c7b77170f80" + }, + { + "path": ".claude-plugin/plugin.json", + "sha256": "d69022eaa1f9f46c86eac7f3f4c22e3ec94c73d3b24e261182a8d9a802938edc" + }, + { + "path": "templates/job-creation.json", + "sha256": "02f61e6db91f9cc5e3e54457e65043fe8bc58e2ef94a3ac4462bb58e9745ffcb" + }, + { + "path": "templates/xs-security.json", + "sha256": "4f7d37abdbc54bc44c7a9a6e084f0b64b9c847d0b49881077e1678fa75ba4a24" + } + ], + "dirSha256": "071d953e16ae40978f3dbe266ba74e045fc180ea28c94140c11abed04c32cdb2" + }, + "security": { + "scannedAt": null, + "scannerVersion": null, + "flags": [] + } +} \ No newline at end of file diff --git a/references/changelog.md b/references/changelog.md new file mode 100644 index 0000000..0c0430b --- /dev/null +++ b/references/changelog.md @@ -0,0 +1,400 @@ +# SAP BTP Job Scheduling Service - Changelog & Version History + +**Source**: [https://github.com/SAP-docs/sap-btp-job-scheduling-service/tree/main/docs/10---What-s-New](https://github.com/SAP-docs/sap-btp-job-scheduling-service/tree/main/docs/10---What-s-New) +**Last Updated**: 2025-11-22 + +--- + +## Table of Contents + +1. [2025 Updates](#2025-updates) +2. [2024 Updates](#2024-updates) +3. [2023 Updates](#2023-updates) +4. [2022 Updates](#2022-updates) +5. [2021 Updates](#2021-updates) +6. [Feature Summary](#feature-summary) + +--- + +## 2025 Updates + +### August 21, 2025 - Belize Themes Removed + +**Type:** Changed + +**Description:** The older Belize UI themes were discontinued. Users now select from four Horizon options: +- Morning Horizon (Default) +- Evening Horizon +- Horizon High Contrast Black +- Horizon High Contrast White + +**Impact:** Systems automatically migrated users from deprecated themes. + +--- + +### July 24, 2025 - New Event Resource Tags + +**Type:** New Feature + +**Description:** Added three new resource tags for event matching with SAP Alert Notification Service: +- `runStatus` +- `runState` +- `scheduleDescription` + +**Use Case:** Enhanced monitoring and filtering capabilities for job notifications. + +--- + +### June 12, 2025 - Default Theme Changed + +**Type:** Changed + +**Description:** "Morning Horizon" became the standard UI theme, replacing the older Belize default. + +--- + +### May 29, 2025 - Multiple Updates + +**1. Horizon Themes Introduced** + +**Type:** New Feature + +**Description:** Four new theme options available for dashboard customization: +- Morning Horizon +- Evening Horizon +- Horizon High Contrast Black +- Horizon High Contrast White + +--- + +**2. SAP Cloud ALM Integration** + +**Type:** New Feature + +**Description:** New capability enabling direct job status tracking through SAP Cloud ALM's interface. + +**Configuration:** +```json +{ + "calmConfig": { + "enabled": true + } +} +``` + +--- + +**3. One-Time Schedule Cleanup Policy** + +**Type:** New Feature + +**Description:** Unused one-time schedules are now automatically deleted after **30 days of inactivity**. + +**Recommendation:** Use recurring schedules as alternative for persistent scheduling needs. + +**Important:** This is an automatic cleanup - no action required, but be aware that inactive one-time schedules will be removed. + +--- + +## 2024 Updates + +### November 14, 2024 - Service Instance Creation Simplified + +**Type:** Changed + +**Description:** The `enable-xsuaa-support` property now **defaults to enabled**, eliminating manual configuration requirements. + +**Impact:** +- New service instances automatically support XSUAA +- No additional parameters needed during creation +- Simplifies initial setup process + +**Before (Required):** +```json +{ + "enable-xsuaa-support": true +} +``` + +**After (Default behavior):** No parameter needed. + +--- + +## 2023 Updates + +### August 24, 2023 - Kyma Runtime Support + +**Type:** New Feature + +**Description:** Cross-consumption capabilities for Kyma runtime announced. + +**Availability:** Public cloud infrastructure providers only (AWS, Azure, GCP). + +**Environments Supported:** +- Cloud Foundry runtime +- Kyma runtime + +--- + +### July 13, 2023 - Job Filtering in Dashboard + +**Type:** New Feature + +**Description:** Job filtering functionality introduced for the list view. + +**Filter Options:** +- By job name +- By subdomain +- By tenant ID + +--- + +### May 18, 2023 - Two Updates + +**1. Service Key Creation** + +**Type:** New Feature + +**Description:** Service key creation capability added for the standard service plan. + +**Use Case:** Enables credential generation for service instances without application binding. + +**Command:** +```bash +cf create-service-key +``` + +--- + +**2. SAP Alert Notification Integration** + +**Type:** New Feature + +**Description:** Integration with SAP Alert Notification service enabled. + +**Capabilities:** +- Send notifications when jobs succeed +- Send notifications when jobs fail +- Configure via `ansConfig` in job creation + +**Configuration:** +```json +{ + "ansConfig": { + "onSuccess": true, + "onError": true + } +} +``` + +**Availability:** Cloud Foundry only (not Kyma). + +--- + +### February 9, 2023 - Enhanced Table Column Management + +**Type:** New Feature + +**Description:** Enhanced table column management in the Service Dashboard. + +**New Capabilities:** +- Adjust width of any column +- Menu options to view full job/task names +- Toggle between truncated and full-name display + +--- + +## 2022 Updates + +### September 23, 2022 - Asynchronous Timeout Limit + +**Type:** Changed + +**Description:** The Asynchronous Execution Timeout configuration parameter now has a maximum ceiling. + +**Maximum Value:** 604,800 seconds (7 days) + +**Configuration Location:** Service Dashboard → Configurations + +--- + +### February 24, 2022 - REST API Rate Limiting + +**Type:** New Feature + +**Description:** API calls are now subject to rate limits that may delay or deny requests during high load periods. + +**Response Codes:** +| Limit Type | Response Code | Header | +|------------|---------------|--------| +| Client limit | 429 | `retry-after` | +| Absolute limit | 503 | `throttling` | + +**Recovery:** Denied requests can be retried after less than one minute. + +--- + +### February 10, 2022 - Automatic Schedule Deactivation + +**Type:** New Feature + +**Description:** The system now automatically deactivates schedules under certain conditions. + +**Deactivation Triggers:** +- One-time schedule executed +- No valid future dates exist +- Job/schedule endTime reached +- Action endpoint unreachable for 10+ consecutive days + +--- + +### January 27, 2022 - Certificate-Based Service Binding + +**Type:** New Feature + +**Description:** Users can bind service instances using X.509 certificates. + +**Recommendation:** SAP's recommended practice for secure connections. + +**Configuration:** +```json +{ + "credential-type": "x509", + "x509": { + "key-length": 2048, + "validity": 7, + "validity-type": "DAYS" + } +} +``` + +--- + +## 2021 Updates + +### December 16, 2021 - Two Updates + +**1. REST API Rate Limits** + +**Type:** New Feature + +**Description:** Implemented request rate limiting with retry header. + +--- + +**2. Missed Run Behavior** + +**Type:** New Feature + +**Description:** Service now skips all missed executions except the last one during outages exceeding 20 minutes. + +**Behavior:** +| Outage Duration | Behavior | +|-----------------|----------| +| < 20 minutes | All missed runs executed | +| >= 20 minutes | Only last missed run executed | + +**Rationale:** Prevents overwhelming target applications upon recovery. + +--- + +### May 20, 2021 - Custom Identity Provider Support + +**Type:** New Feature + +**Description:** The service extended compatibility to work with custom identity providers alongside platform users. + +**Capabilities:** +- Dashboard management with custom IdP +- Support for federated authentication + +--- + +### February 25, 2021 - CF Task Timeout + +**Type:** New Feature + +**Description:** Asynchronous job execution adopted a 30-minute default timeout limit. + +**Details:** +- Tasks automatically terminated after timeout +- Configurable via Service Dashboard → Configurations +- Maximum: 604,800 seconds (7 days) + +--- + +### December 17, 2020 - Binding Level Secrets + +**Type:** New Feature + +**Description:** New client secrets are automatically generated when applications bind to the service. + +**Benefit:** Enables secret rotation through unbind/rebind cycles. + +**Rotation Process:** +1. `cf unbind-service ` +2. `cf bind-service ` +3. `cf restage ` + +--- + +## Feature Summary + +### Key Capabilities by Year + +| Year | Major Features | +|------|---------------| +| 2025 | Horizon themes, Cloud ALM integration, one-time schedule cleanup | +| 2024 | Simplified XSUAA setup (defaults enabled) | +| 2023 | Kyma support, Alert Notification, service keys, job filtering | +| 2022 | Rate limiting, certificate binding, auto-deactivation, async timeout cap | +| 2021 | Custom IdP, CF task timeout, missed run behavior, binding secrets | + +### Current Feature Set + +**Scheduling:** +- One-time and recurring schedules +- Cron, date/time, human-readable formats +- Automatic cleanup of unused one-time schedules (30 days) + +**Execution:** +- Synchronous (≤15 seconds) +- Asynchronous (up to 7 days timeout) +- Cloud Foundry tasks + +**Security:** +- OAuth 2.0 (XSUAA) - default enabled +- X.509 certificate binding (recommended) +- Custom identity provider support +- Binding-level credential rotation + +**Monitoring:** +- SAP Cloud ALM integration +- SAP Alert Notification Service (CF only) +- Event resource tags (runStatus, runState, scheduleDescription) + +**Management:** +- Service Dashboard with Horizon themes +- REST API with rate limiting +- Node.js client library +- Job filtering by name, subdomain, tenant ID + +**Runtimes:** +- Cloud Foundry +- Kyma (public cloud only) + +--- + +## External References + +### SAP Documentation +- **What's New**: [https://help.sap.com/docs/job-scheduling/sap-job-scheduling-service/what-s-new-for-sap-job-scheduling-service](https://help.sap.com/docs/job-scheduling/sap-job-scheduling-service/what-s-new-for-sap-job-scheduling-service) +- **2023 Archive**: [https://help.sap.com/docs/job-scheduling/sap-job-scheduling-service/2023-what-s-new-for-sap-job-scheduling-service-archive](https://help.sap.com/docs/job-scheduling/sap-job-scheduling-service/2023-what-s-new-for-sap-job-scheduling-service-archive) +- **2022 Archive**: [https://help.sap.com/docs/job-scheduling/sap-job-scheduling-service/2022-what-s-new-for-sap-job-scheduling-service-archive](https://help.sap.com/docs/job-scheduling/sap-job-scheduling-service/2022-what-s-new-for-sap-job-scheduling-service-archive) +- **2021 Archive**: [https://help.sap.com/docs/job-scheduling/sap-job-scheduling-service/2021-what-s-new-for-sap-job-scheduling-service-archive](https://help.sap.com/docs/job-scheduling/sap-job-scheduling-service/2021-what-s-new-for-sap-job-scheduling-service-archive) + +### Source Files +- `what-s-new-for-sap-job-scheduling-service-35dd2f8.md` +- `2023-what-s-new-for-sap-job-scheduling-service-archive-8ff6481.md` +- `2022-what-s-new-for-sap-job-scheduling-service-archive-cd1964a.md` +- `2021-what-s-new-for-sap-job-scheduling-service-archive-78f6a4b.md` diff --git a/references/concepts.md b/references/concepts.md new file mode 100644 index 0000000..2c9499e --- /dev/null +++ b/references/concepts.md @@ -0,0 +1,472 @@ +# SAP BTP Job Scheduling Service - Core Concepts + +**Source**: [https://github.com/SAP-docs/sap-btp-job-scheduling-service/tree/main/docs/20---Concepts](https://github.com/SAP-docs/sap-btp-job-scheduling-service/tree/main/docs/20---Concepts) +**Last Updated**: 2025-11-22 + +--- + +## Table of Contents + +1. [Core Components](#core-components) +2. [Schedule Types](#schedule-types) +3. [Schedule Formats](#schedule-formats) +4. [Schedule Lifecycle](#schedule-lifecycle) +5. [Asynchronous Mode](#asynchronous-mode) +6. [Cloud Foundry Tasks](#cloud-foundry-tasks) +7. [Multitenancy](#multitenancy) +8. [Service Behavior](#service-behavior) + +--- + +## Core Components + +### Job + +A job is a collection of schedules with an action endpoint. Jobs: +- Invoke a configured URL at specified times +- Execute synchronously (short operations, ≤15 seconds) or asynchronously (long processes) +- Service plans are based on the number of schedules within a job +- Names must not contain special characters or only numbers +- Names must be unique per technical user + +### Action Endpoint + +An HTTP or REST endpoint exposed by the application that the service invokes: +- Must be OAuth 2.0 protected in production (standard plan) +- Must use HTTPS for encrypted communication +- Receives job execution requests with authorization headers + +### Schedule + +A one-time or recurring entity within a job: +- Defines when and how often a job runs +- Supports multiple format types (cron, date/time, human-readable) +- Has its own lifecycle states +- Can be activated/deactivated independently + +### Run Log + +Records of job executions: +- Contains execution status, timestamps, and optional messages +- Retained for 15 days before automatic deletion +- Downloadable via API or dashboard + +--- + +## Schedule Types + +### One-Time Schedules + +Execute a single time using: + +**Human-Readable Text:** +``` +"time": "10 hours from now" +"time": "tomorrow at 4pm" +"time": "now" // Immediate execution +"time": "Friday at 2am" +``` + +**Date String Formats:** +``` +"time": "1994-11-05T08:15:30-05:00" // ISO-8601 +"time": "Sat, 05 Nov 1994 08:15:30 GMT" // RFC 2822 +``` + +**Behavior:** +- Auto-deactivate after execution (successful or failed) +- Execute at configured time, overriding job-level startTime +- Execute immediately if scheduled time is past but endTime is future +- Do not execute if both time and endTime are in the past +- **Automatic Cleanup:** Unused one-time schedules are deleted after **30 days of inactivity** (as of May 2025) + +### Recurring Schedules + +Run periodically at specified intervals using: + +**repeatInterval:** +Denotes interval between schedules in human-readable format: +```json +"repeatInterval": "5 minutes" +"repeatInterval": "2 hours" +"repeatInterval": "1 day" +"repeatInterval": "2 weeks" +``` +- Next execution adjusts if previous execution was delayed + +**cron:** +Crontab expression determining execution times: +```json +"cron": "* * * * 9 0 0" // Daily at 9:00:00 AM +"cron": "* * * mon 10 0 0" // Every Monday at 10:00 +``` +- Service assumes 30-day months and 365-day years + +**repeatAt:** +Exact daily execution time: +```json +"repeatAt": "4.40pm" +"repeatAt": "18.40" +"repeatAt": "6.20am" +``` + +**Behavior:** +- If a job exceeds its duration, the next scheduled job still starts on time +- Activating an inactive schedule after planned start triggers immediate execution + +--- + +## Schedule Formats + +### Cron Format (7 Fields) + +SAP Job Scheduling Service uses an extended cron format with seven fields (left to right): + +``` +Year Month Day DayOfWeek Hour Minute Second +``` + +**Field Constraints:** + +| Field | Values | Description | +|-------|--------|-------------| +| Year | 4-digit (e.g., 2025) | Calendar year | +| Month | 1-12 | Calendar month | +| Day | -31 to 31 | Day of month (negative = from end) | +| DayOfWeek | mon, tue, wed, thu, fri, sat, sun | 3-letter abbreviation | +| Hour | 0-23 | Hour of day | +| Minute | 0-59 | Minute of hour | +| Second | 0-59 | Second of minute | + +**Supported Operators:** + +| Operator | Meaning | Example | +|----------|---------|---------| +| `*` | Any value | `* * * * 9 0 0` | +| `*/a` | Every a-th value | `* * * * */2 0 0` (every 2 hours) | +| `a:b` | Range a to b | `* * * * 10:12 0 0` (hours 10-12) | +| `a:b/c` | Every c-th in range | `* * * * 10:12/2 0 0` | +| `a.y` | a-th occurrence of weekday y | `* * * -1.sun 9 0 0` (last Sunday) | +| `a,b,c` | Multiple values | `* * * mon,wed,fri 9 0 0` | + +**Examples:** + +``` +* * * 10:12 */30 0 Every 30 minutes between 10:00-12:00 daily +* * * -1.sun 9 0 0 Last Sunday of each month at 09:00 +* 1,4,7,10 1 * 0 0 0 First day of each quarter at midnight +* * * * 9 30 0 Daily at 9:30 AM +* * 15 * 18 0 0 15th of each month at 6 PM +``` + +**Important**: Service uses SAP cron format, NOT Linux cron format. + +### Date/Time Formats + +**Date Object Format:** + +```json +{ + "startTime": { + "date": "2025-10-20 04:30 +0000", + "format": "YYYY-MM-DD HH:mm Z" + } +} +``` + +**Supported Parsing Tokens:** + +| Token | Description | +|-------|-------------| +| YYYY | 4-digit year | +| YY | 2-digit year | +| M/MM | Month (1-12) | +| MMM/MMMM | Month name | +| D/DD | Day of month | +| H/HH | Hour (24-hour) | +| h/hh | Hour (12-hour) | +| a/A | AM/PM | +| m/mm | Minute | +| s/ss | Second | +| Z/ZZ | Timezone offset | +| X | UNIX timestamp (seconds) | +| x | UNIX timestamp (milliseconds) | + +**Date String Format:** + +Valid ISO-8601 or RFC 2822 representations: +``` +1994-11-05T08:15:30-05:00 // ISO-8601 +Sat, 05 Nov 1994 08:15:30 GMT // RFC 2822 +``` + +### Human-Readable Formats + +**time Parameter:** +``` +"10 hours from now" +"tomorrow at 4pm" +"now" +"Friday at 2am" +"next week" +``` + +**repeatAt Parameter:** +``` +"4.40pm" +"6.20am" +"18:40" +``` + +**repeatInterval Parameter:** +``` +"10 hours" +"2 days" +"5 minutes" +"3 weeks" +"1 month" +``` + +Supports: years, months, weeks, days, hours, minutes, seconds + +--- + +## Schedule Lifecycle + +### Primary States + +| State | Description | +|-------|-------------| +| **SCHEDULED** | Schedule queued for future run | +| **RUNNING** | Schedule actively executing | +| **COMPLETED** | Schedule run finished | + +### Detailed State Transitions + +**During SCHEDULED Phase:** +- `SCHEDULED`: Awaiting execution at future time + +**During RUNNING Phase:** +- `TRIGGERED`: Scheduler triggered request to job action endpoint +- `ACK_RECVD`: Application sent 202 Accepted acknowledgment +- `ACK_NOT_RECVD`: Application failed to acknowledge within timeframe + +**During COMPLETED Phase:** +- `SUCCESS`: Application executed job and replied with success status +- `ERROR`: Application encountered error, sent server error code +- `REQUEST_ERROR`: Error occurred invoking job endpoint +- `UNKNOWN`: Application didn't invoke Update Job Run Log API + +### Cloud Foundry Task States + +**RUNNING Phase:** +- `TRIGGERED`: Task creation initiated +- `ACK_RECVD`: Task creation successful + +**COMPLETED Phase:** +- `SUCCESS`: Task completed successfully +- `ERROR`: Task encountered error +- `TIMEOUT`: Execution exceeded configured timeframe + +--- + +## Asynchronous Mode + +### Overview + +Asynchronous mode handles job runs with large execution times, particularly for action endpoints triggering long-running processes. + +### Request Flow + +1. **Scheduler Invokes Endpoint** with headers: + - `x-sap-job-id`: Job identifier + - `x-sap-job-schedule-id`: Schedule identifier + - `x-sap-job-run-id`: Run identifier + - `x-sap-scheduler-host`: Service host URI + +2. **Application Stores Headers** using suitable mechanism (in-memory or persistent storage) + +3. **Application Returns 202 Accepted** immediately as acknowledgment + +4. **Application Processes Job** asynchronously + +5. **Application Updates Run Log** via callback API with final status + +### Implementation Example + +```javascript +// Receive job request +app.post('/api/process', (req, res) => { + // Extract and store headers + const jobContext = { + jobId: req.headers['x-sap-job-id'], + scheduleId: req.headers['x-sap-job-schedule-id'], + runId: req.headers['x-sap-job-run-id'], + schedulerHost: req.headers['x-sap-scheduler-host'] + }; + + // Store context for later callback + storeJobContext(jobContext); + + // Return immediate acknowledgment + res.status(202).send({ message: 'Accepted' }); + + // Start async processing + processJobAsync(jobContext); +}); + +// After job completion +async function onJobComplete(jobContext, success, message) { + await updateRunLog(jobContext, { success, message }); +} +``` + +### Callback API + +``` +PUT /scheduler/jobs/{jobId}/schedules/{scheduleId}/runs/{runId} + +{ + "success": true, + "message": "Long running operation completed successfully" +} +``` + +### Timeout Handling + +- Default timeout: 30 minutes +- Configurable up to: 604,800 seconds (7 days) +- If application fails to invoke Update API, status reverts to `UNKNOWN` + +### Important Notes + +- Cloud Foundry tasks always run asynchronously +- Server error codes indicate job failure +- Single callback with final status (not multiple updates) + +--- + +## Cloud Foundry Tasks + +### Definition + +An app or script whose code is included as part of a deployed app but runs independently in its own container. + +### Characteristics + +- Designed for minimal resource consumption +- Always execute asynchronously +- Cannot be created via REST API (only dashboard) +- Require Space Developer role for creation +- Memory configurable (default 1GB) + +### Memory Configuration + +Via dashboard JSON options: +```json +{ + "memory_in_mb": 2048 +} +``` + +### Task States + +Same as asynchronous jobs plus: +- `TIMEOUT`: Execution exceeded configured timeframe + +--- + +## Multitenancy + +### Overview + +The service enables deployed multitenant applications to create, view, edit, and delete jobs in the context of subscribed tenants. + +### Prerequisites + +- Application deployed to provider subaccount +- Application bound to SaaS Provisioning service +- Application bound to Job Scheduling service +- Job Scheduling defined as application dependency + +### Tenant Isolation + +**Strict Data Separation:** +- Jobs and schedules created for a SaaS tenant are NOT accessible by other tenants +- Credentials bound to a SaaS tenant access only that tenant's data +- Each tenant maintains its own job and schedule collection + +### Credential Types + +**Provider-Level Credentials (PaaS):** +- Bound to the SAP Job Scheduling service instance +- Can manage ALL jobs across all tenants +- No tenant restrictions + +**Tenant-Specific Credentials (SaaS):** +- Bound to specific tenant +- Access only tenant-specific data +- `tenantId` query parameter returns 400 for SaaS tenant tokens + +### Unsubscription Behavior + +**Single-Instance Setup:** +- All corresponding jobs and schedules deleted when tenant unsubscribes + +**Multi-Application Setup:** +- Data persists until ALL subscriptions removed + +### Token Requirements + +Use client credentials flow with XSUAA to obtain access tokens for job registration and management. + +--- + +## Service Behavior + +### Outage Recovery + +**Under 20 Minutes:** +- All missed executions re-executed immediately when service restores + +**20+ Minutes:** +- All scheduled runs except the last one are skipped +- Prevents overwhelming target applications with excessive requests + +### Service Level Agreement + +Scheduled jobs have approximately 20-minute latency tolerance from their scheduled execution time. + +### Data Retention + +Run logs automatically removed 15 days after generation. Download via API or dashboard before removal. + +### Auto-Deactivation Triggers + +Schedules auto-deactivate when: +- One-time schedule executed (successful or failed) +- No valid future dates exist +- Job/schedule endTime reached +- Action endpoint unreachable for 10+ consecutive days + +### Timezone + +**UTC Only**: No other timezones supported. All schedule times are interpreted as UTC. + +--- + +## External References + +### SAP Documentation +- **Core Concepts**: [https://help.sap.com/docs/job-scheduling/sap-job-scheduling-service/concepts](https://help.sap.com/docs/job-scheduling/sap-job-scheduling-service/concepts) +- **Schedule Formats**: [https://help.sap.com/docs/job-scheduling/sap-job-scheduling-service/schedule-formats](https://help.sap.com/docs/job-scheduling/sap-job-scheduling-service/schedule-formats) +- **Service Behavior**: [https://help.sap.com/docs/job-scheduling/sap-job-scheduling-service/service-behavior](https://help.sap.com/docs/job-scheduling/sap-job-scheduling-service/service-behavior) + +### Source Files +- `concepts-26572ad.md` +- `asynchronous-mode-d9fd81c.md` +- `schedule-types-9cf8c14.md` +- `schedule-formats-54615f0.md` +- `schedule-lifecycle-e1805f2.md` +- `multitenancy-in-sap-job-scheduling-service-464b613.md` +- `service-behavior-d09664b.md` diff --git a/references/integrations.md b/references/integrations.md new file mode 100644 index 0000000..e2a1005 --- /dev/null +++ b/references/integrations.md @@ -0,0 +1,310 @@ +# SAP BTP Job Scheduling Service - Integration Guide + +**Source**: [https://github.com/SAP-docs/sap-btp-job-scheduling-service/tree/main/docs](https://github.com/SAP-docs/sap-btp-job-scheduling-service/tree/main/docs) +**Last Updated**: 2025-11-22 + +--- + +## Table of Contents + +1. [Integration Overview](#integration-overview) +2. [SAP Cloud ALM Integration](#sap-cloud-alm-integration) +3. [SAP Alert Notification Service Integration](#sap-alert-notification-service-integration) + +--- + +## Integration Overview + +SAP Job Scheduling Service integrates with two SAP solutions: + +| Integration | Purpose | Availability | +|-------------|---------|--------------| +| SAP Cloud ALM | Job monitoring and automation | Cloud Foundry & Kyma | +| SAP Alert Notification Service | Event notifications | Cloud Foundry only | + +--- + +## SAP Cloud ALM Integration + +### Overview + +Integration enables monitoring of jobs managed by SAP Job Scheduling service within SAP Cloud ALM. Once activated, all events related to a job and its schedules are visible within SAP Cloud ALM. + +### Prerequisites + +1. SAP Cloud ALM instance configured +2. Job & Automation Monitoring enabled +3. Refer to [SAP Cloud ALM Job Monitoring Setup](https://support.sap.com/en/alm/sap-cloud-alm/operations/expert-portal/job-monitoring/job-automation-monitoring-details.html) + +### Enable via Dashboard + +**Method 1: Actions Column Toggle** + +1. Open Job Scheduling service dashboard +2. Navigate to **Jobs** or **Tasks** +3. Find the job in the list +4. Toggle the Cloud ALM switch in the Actions column +5. Save changes + +**Method 2: During Job/Task Creation** + +1. Create new job or task +2. Enable Cloud ALM monitoring in creation form +3. Complete job creation + +**Method 3: Edit View** + +1. Select existing job +2. Click **Edit** +3. Enable Cloud ALM monitoring toggle +4. Save changes + +### Enable via REST API + +**During Job Creation:** + +```json +POST /scheduler/jobs +{ + "name": "monitoredJob", + "description": "Job with Cloud ALM monitoring", + "action": "[https://myapp.../api/process",](https://myapp.../api/process",) + "active": true, + "httpMethod": "POST", + "calmConfig": { + "enabled": true + }, + "schedules": [{ + "active": true, + "repeatInterval": "1 hour" + }] +} +``` + +**Update Existing Job:** + +```json +PUT /scheduler/jobs/{jobId} +{ + "calmConfig": { + "enabled": true + } +} +``` + +### Configuration Notes + +- CF tasks cannot be created via REST API due to application-specific binding +- `calmConfig` object cannot be empty if provided +- `enabled` must be boolean type + +### Status Display Comparison + +| Job Scheduling Display | Cloud ALM Display | +|------------------------|-------------------| +| Status + State (single column) | Execution Status + Application Status (separate) | + +### Status Mapping + +| Job Scheduling | Cloud ALM Execution Status | Cloud ALM Application Status | +|----------------|---------------------------|------------------------------| +| SCHEDULED | Scheduled | - | +| TRIGGERED | Running | - | +| SUCCESS | Completed | Success | +| ERROR | Completed | Error | +| UNKNOWN | Unknown | Unknown | + +--- + +## SAP Alert Notification Service Integration + +### Overview + +Integration allows jobs and tasks to trigger event notifications through SAP Alert Notification service upon completion, supporting both success and error scenarios. + +### Benefits + +| Benefit | Description | +|---------|-------------| +| Proactive Monitoring | Immediate alerts for job outcomes | +| Operational Efficiency | Automatic recovery process initiation | +| Team Notification | Alert relevant stakeholders | +| Status Tracking | Track success, errors, timeouts, failures | + +### Availability + +**Supported:** Cloud Foundry runtime only + +**Not Supported:** Kyma runtime + +### Prerequisites + +1. SAP Alert Notification service enabled in subaccount +2. Alert Notification service instance created +3. Event types configured: + - `JobSchedulerJobExecution` + - `JobSchedulerTaskExecution` + +### Setup Steps + +**Step 1: Create Alert Notification Instance** + +1. Navigate to **Services** → **Instances and Subscriptions** +2. Create new **Alert Notification** service instance +3. Open service instance dashboard + +**Step 2: Configure Actions** + +1. In Alert Notification dashboard, go to **Actions** +2. Create action (e.g., Email, Webhook) +3. Configure action parameters + +**Step 3: Configure Conditions** + +1. Go to **Conditions** +2. Create condition for job events +3. Set event type filter: + - `JobSchedulerJobExecution` for jobs + - `JobSchedulerTaskExecution` for CF tasks + +**Step 4: Configure Subscriptions** + +1. Go to **Subscriptions** +2. Create subscription linking condition to action +3. Activate subscription + +### Enable via Dashboard + +**During Job Creation:** + +1. Create new job in Job Scheduling dashboard +2. Under **SAP Alert Notification Service Events**: + - Toggle **Success** for success notifications + - Toggle **Error** for error notifications +3. Save job + +**For Existing Jobs:** + +1. Select job in dashboard +2. Click **Edit** +3. Enable notification toggles +4. Save changes + +### Enable via REST API + +**During Job Creation:** + +```json +POST /scheduler/jobs +{ + "name": "alertedJob", + "description": "Job with alert notifications", + "action": "[https://myapp.../api/process",](https://myapp.../api/process",) + "active": true, + "httpMethod": "POST", + "ansConfig": { + "onSuccess": true, + "onError": true + }, + "schedules": [{ + "active": true, + "cron": "* * * * 9 0 0" + }] +} +``` + +**Update Existing Job:** + +```json +PUT /scheduler/jobs/{jobId} +{ + "ansConfig": { + "onSuccess": false, + "onError": true + } +} +``` + +### ansConfig Parameters + +| Parameter | Type | Description | +|-----------|------|-------------| +| onSuccess | boolean | Send notification on successful execution | +| onError | boolean | Send notification on failed execution | + +### Event Types + +| Event Type | Triggered By | +|------------|--------------| +| `JobSchedulerJobExecution` | HTTP endpoint job completion | +| `JobSchedulerTaskExecution` | Cloud Foundry task completion | + +### Alert Events Include + +- Job name and ID +- Schedule ID +- Execution status (Success/Error) +- Timestamp +- Error details (for failures) + +### Testing Integration + +1. Open Job Scheduling dashboard +2. Select **Jobs** +3. Create test job with: + - All required fields + - **Error** or **Success** toggle enabled + - One-time schedule with `"time": "now"` +4. Save and execute job +5. Verify: + - Job execution in run logs + - Notification received via configured action + +### Troubleshooting + +| Issue | Cause | Solution | +|-------|-------|----------| +| No notifications | Event type not configured | Add event types in ANS dashboard | +| Wrong recipients | Action misconfigured | Review action configuration | +| Delayed notifications | ANS processing time | Normal, check ANS logs | +| Missing events | ansConfig not set | Update job with ansConfig | + +--- + +## Integration Configuration Summary + +### REST API Parameters + +| Integration | Parameter | Structure | +|-------------|-----------|-----------| +| SAP Cloud ALM | `calmConfig` | `{ "enabled": boolean }` | +| Alert Notification | `ansConfig` | `{ "onSuccess": boolean, "onError": boolean }` | + +### Dashboard Options + +| Integration | Location | Options | +|-------------|----------|---------| +| SAP Cloud ALM | Actions column / Edit view | Toggle on/off | +| Alert Notification | SAP Alert Notification Service Events | Success toggle, Error toggle | + +### Compatibility Matrix + +| Feature | Cloud Foundry | Kyma | +|---------|---------------|------| +| SAP Cloud ALM | Yes | Yes | +| Alert Notification | Yes | No | + +--- + +## External References + +### SAP Documentation +- **Integration Scenarios**: [https://help.sap.com/docs/job-scheduling/sap-job-scheduling-service/integration-scenarios](https://help.sap.com/docs/job-scheduling/sap-job-scheduling-service/integration-scenarios) +- **SAP Cloud ALM Integration**: [https://help.sap.com/docs/job-scheduling/sap-job-scheduling-service/integration-with-sap-cloud-alm](https://help.sap.com/docs/job-scheduling/sap-job-scheduling-service/integration-with-sap-cloud-alm) +- **Alert Notification Integration**: [https://help.sap.com/docs/job-scheduling/sap-job-scheduling-service/integration-with-sap-alert-notification-service-for-sap-btp](https://help.sap.com/docs/job-scheduling/sap-job-scheduling-service/integration-with-sap-alert-notification-service-for-sap-btp) +- **SAP Cloud ALM Job Monitoring**: [https://support.sap.com/en/alm/sap-cloud-alm/operations/expert-portal/job-monitoring/job-automation-monitoring-details.html](https://support.sap.com/en/alm/sap-cloud-alm/operations/expert-portal/job-monitoring/job-automation-monitoring-details.html) + +### Source Files +- `integration-scenarios-faeec3a.md` +- `integration-with-sap-cloud-alm-f82790e.md` +- `integration-with-sap-alert-notification-service-for-sap-btp-972ef35.md` diff --git a/references/operations.md b/references/operations.md new file mode 100644 index 0000000..028ec6a --- /dev/null +++ b/references/operations.md @@ -0,0 +1,321 @@ +# SAP BTP Job Scheduling Service - Operations Guide + +**Source**: [https://github.com/SAP-docs/sap-btp-job-scheduling-service/tree/main/docs](https://github.com/SAP-docs/sap-btp-job-scheduling-service/tree/main/docs) +**Last Updated**: 2025-11-22 + +--- + +## Table of Contents + +1. [Service Dashboard](#service-dashboard) +2. [Service Behavior](#service-behavior) +3. [Backup and Restore](#backup-and-restore) +4. [Accessibility Features](#accessibility-features) + +--- + +## Service Dashboard + +### Overview + +The dashboard enables management of jobs, tasks, and schedules for a service instance. + +### Access Methods + +**Via SAP BTP Cockpit:** +1. Navigate to subaccount +2. Go to **Services** → **Instances and Subscriptions** +3. Select Job Scheduling instance +4. Click **View Dashboard** (via Service Bindings) + +**Via CF CLI:** +```bash +cf service +``` + +Dashboard URL appears in output. + +### Required Roles + +| Runtime | Role | Access Level | +|---------|------|--------------| +| Cloud Foundry | SpaceDeveloper | Full access | +| Cloud Foundry | SpaceAuditor/SpaceManager/OrgManager/SpaceSupporter | Read-only | +| Kyma | SAP_Job_Scheduling_Service_Admin | Full access | +| Kyma | SAP_Job_Scheduling_Service_Viewer | Read-only | + +### Dashboard Features + +#### Configuration Management + +| Setting | Description | Max Value | +|---------|-------------|-----------| +| Async Timeout | Timeout for async job execution | 604,800 seconds (7 days) | + +#### Job Operations + +| Operation | Description | +|-----------|-------------| +| Create | Create new job with action endpoint | +| Edit | Modify job properties | +| Deactivate | Disable job execution | +| Delete | Remove job and all data | +| Search | Filter by name, subdomain, tenant ID | +| Cloud ALM | Enable/disable monitoring | + +#### Task Operations + +| Operation | Description | +|-----------|-------------| +| Create | Create new CF task | +| Edit | Modify task properties | +| Memory | Configure task memory (JSON options) | +| Alert Notification | Enable/disable alerts (CF only) | + +#### Schedule Operations + +| Operation | Description | +|-----------|-------------| +| Create | Add schedule to job/task | +| Edit | Modify schedule parameters | +| Activate/Deactivate | Enable/disable schedule | +| Delete | Remove schedule | +| View History | See execution history | +| View Run Logs | See detailed execution logs | + +### Dashboard UI Elements + +**Main Sections:** +- Configurations panel +- Jobs/Tasks listing +- Schedule creation interface +- Event history viewer +- Run logs display + +**Column Features:** +- Sortable (ascending/descending) +- Resizable widths +- Job name navigation +- Full-name display option + +### Downloading Run Logs + +1. Select job in dashboard +2. Choose specific schedule +3. View run logs +4. Click download option + +**Note:** Logs auto-delete after 15 days. + +--- + +## Service Behavior + +### Execution Timing + +#### Service Level Agreement + +Scheduled jobs have approximately **20-minute tolerance** from their scheduled execution time. + +#### Outage Recovery + +| Outage Duration | Behavior | +|-----------------|----------| +| < 20 minutes | All missed executions run immediately | +| >= 20 minutes | Only last missed execution runs | + +**Rationale:** Prevents overwhelming target applications with excessive requests upon recovery. + +### Schedule Auto-Deactivation + +Schedules automatically deactivate when: + +| Trigger | Description | +|---------|-------------| +| One-time executed | After successful or failed execution | +| No future dates | All possible execution times passed | +| endTime reached | Job or schedule end time in past | +| Endpoint unreachable | Action endpoint unreachable 10+ consecutive days | + +### Request Handling + +| Constraint | Value | +|------------|-------| +| POST body limit | 100 KB | +| 413 response | Body size exceeded | +| Timezone | UTC only | +| Pagination default | 10 items | +| Pagination max | 200 items | + +### Data Retention + +| Data Type | Retention | Notes | +|-----------|-----------|-------| +| Run logs | 15 days | Auto-deleted | +| Jobs/Schedules | Indefinite | Until deleted | +| Configurations | Indefinite | Until instance deleted | + +--- + +## Backup and Restore + +### Capabilities + +The service supports restoration of accidentally deleted items: + +| Restorable | Not Restorable | +|------------|----------------| +| Job configurations | Run logs | +| Task configurations | Same-day deletions | +| Schedule configurations | - | + +### Restored Item State + +| Property | Restored Value | +|----------|----------------| +| active | `false` (requires manual reactivation) | +| All other settings | Original values | + +### Restoration Time Windows + +| Region | Maximum Window | +|--------|----------------| +| AWS | 14 days | +| Azure | 14 days | +| GCP | 7 days | + +### Same-Day Limitation + +**Jobs and schedules created, modified, or deleted on the same day cannot be restored** due to daily backup dependency. + +### Restoration Procedures + +#### For Deleted Service Instances + +Submit SAP support case with: +- Tenant ID of subaccount +- Deletion timestamp +- Old instance GUID (from Space Events audit logs) +- New empty instance GUID for recovery + +#### For Deleted Subscriptions + +Submit SAP support case with: +- Tenant ID +- Deletion timestamp +- Provider instance GUID + +Then: +1. Create new subscription +2. Wait for restoration completion + +### Getting Instance GUID + +**Via CF CLI:** +```bash +cf service --guid +``` + +**Via Audit Logs:** +1. Access Cloud Foundry audit logs +2. Filter for Space Events +3. Find DELETE event for service instance +4. Extract instance GUID from event details + +--- + +## Accessibility Features + +### UI Themes + +The service offers four theme options: + +| Theme | Description | +|-------|-------------| +| Morning Horizon | Default light theme | +| Evening Horizon | Dark theme | +| Horizon High Contrast Black | Accessibility - high contrast dark | +| Horizon High Contrast White | Accessibility - high contrast light | + +### Changing Theme + +1. Select email/profile in upper right corner +2. Choose **Change Theme** +3. Select preferred theme + +### Screen Reader Support + +Available through SAPUI5 accessibility framework: +- Screen reader compatibility +- Keyboard navigation options +- ARIA labels and roles + +### BTP Cockpit Accessibility + +Job Scheduling Service inherits accessibility features from SAP BTP cockpit: +- Keyboard shortcuts +- Focus management +- High contrast modes + +### Documentation Resources + +- SAP BTP Cockpit accessibility features (SAP Help Portal) +- SAPUI5 accessibility guidance for end users + +--- + +## Operational Best Practices + +### Scheduling + +| Practice | Recommendation | +|----------|----------------| +| Avoid peak seconds | Don't use 0 or 30 | +| Avoid peak minutes | Don't use 0, 30, or multiples of 5 | +| Avoid top of hour | High demand periods | +| Avoid midnight UTC | Busiest time | +| Use irregular times | e.g., 01:12:17 vs 01:00:00 | + +### Monitoring + +| Approach | Method | +|----------|--------| +| Dashboard | Manual review of run logs | +| Cloud ALM | Automated monitoring | +| Alert Notification | Event-driven alerts | +| REST API | Programmatic log retrieval | + +### Maintenance + +| Task | Frequency | +|------|-----------| +| Download critical logs | Before 15-day retention | +| Review failed jobs | Daily/Weekly | +| Credential rotation | Quarterly | +| Verify scope grants | After XSUAA changes | + +### Capacity Planning + +| Factor | Consideration | +|--------|---------------| +| Schedule count | Service plan based on schedules | +| Execution frequency | Rate limits apply | +| Run log volume | 15-day auto-deletion | +| Memory (CF tasks) | Default 1GB, configurable | + +--- + +## External References + +### SAP Documentation +- **Dashboard**: [https://help.sap.com/docs/job-scheduling/sap-job-scheduling-service/manage-jobs-tasks-and-schedules-with-service-dashboard](https://help.sap.com/docs/job-scheduling/sap-job-scheduling-service/manage-jobs-tasks-and-schedules-with-service-dashboard) +- **Service Behavior**: [https://help.sap.com/docs/job-scheduling/sap-job-scheduling-service/service-behavior](https://help.sap.com/docs/job-scheduling/sap-job-scheduling-service/service-behavior) +- **Backup and Restore**: [https://help.sap.com/docs/job-scheduling/sap-job-scheduling-service/backup-and-restore](https://help.sap.com/docs/job-scheduling/sap-job-scheduling-service/backup-and-restore) +- **Accessibility**: [https://help.sap.com/docs/job-scheduling/sap-job-scheduling-service/accessibility-features-in-sap-job-scheduling-service](https://help.sap.com/docs/job-scheduling/sap-job-scheduling-service/accessibility-features-in-sap-job-scheduling-service) + +### Source Files +- `manage-jobs-tasks-and-schedules-with-service-dashboard-132fd06.md` +- `service-behavior-d09664b.md` +- `backup-and-restore-87102ab.md` +- `accessibility-features-in-sap-job-scheduling-service-12aa90f.md` +- `best-practices-7b3f014.md` diff --git a/references/rest-api.md b/references/rest-api.md new file mode 100644 index 0000000..fddf174 --- /dev/null +++ b/references/rest-api.md @@ -0,0 +1,937 @@ +# SAP BTP Job Scheduling Service - REST API Reference + +**Source**: [https://github.com/SAP-docs/sap-btp-job-scheduling-service/tree/main/docs/40---Using-JOB-SCHDULR-TITLE](https://github.com/SAP-docs/sap-btp-job-scheduling-service/tree/main/docs/40---Using-JOB-SCHDULR-TITLE) +**Last Updated**: 2025-11-22 + +--- + +## Table of Contents + +1. [API Overview](#api-overview) +2. [Authentication](#authentication) +3. [Rate Limits](#rate-limits) +4. [Job APIs](#job-apis) +5. [Schedule APIs](#schedule-apis) +6. [Run Log APIs](#run-log-apis) +7. [Node.js Client Library](#nodejs-client-library) +8. [Java Client Library (XS Advanced)](#java-client-library-xs-advanced) + +--- + +## API Overview + +### Base URL + +``` +[https://jobscheduler-rest.](https://jobscheduler-rest.) +``` + +Example landscapes: +- `eu10.hana.ondemand.com` +- `us10.hana.ondemand.com` +- `ap10.hana.ondemand.com` + +### General Constraints + +| Constraint | Value | +|------------|-------| +| Request body size limit | 100 KB | +| Content-Type | `application/json` | +| Timezone | UTC only | +| Pagination default | 10 items | +| Maximum pagination | 200 items | + +### Request Headers + +``` +Authorization: Bearer +Content-Type: application/json +``` + +--- + +## Authentication + +### Lite Plan (HTTP Basic) + +```bash +curl -X GET "[https://jobscheduler-rest./scheduler/jobs"](https://jobscheduler-rest./scheduler/jobs") \ + -u ":" \ + -H "Content-Type: application/json" +``` + +Credentials from `VCAP_SERVICES`: +- `user`: Username +- `password`: Password + +### Standard Plan (OAuth 2.0) + +**Token Acquisition - Client Credentials:** + +```bash +# Get access token +curl -X POST "/oauth/token" \ + -H "Authorization: Basic $(echo -n ':' | base64)" \ + -H "Content-Type: application/x-www-form-urlencoded" \ + -d "grant_type=client_credentials" +``` + +Response: +```json +{ + "access_token": "eyJhbGciOiJSUzI1...", + "token_type": "bearer", + "expires_in": 43199 +} +``` + +**Token Acquisition - Certificate-Based:** + +```bash +curl -X POST "/oauth/token" \ + --cert /path/to/certificate.pem \ + --key /path/to/key.pem \ + -d "grant_type=client_credentials&client_id=" +``` + +**Using Token:** + +```bash +curl -X GET "[https://jobscheduler-rest./scheduler/jobs"](https://jobscheduler-rest./scheduler/jobs") \ + -H "Authorization: Bearer " \ + -H "Content-Type: application/json" +``` + +### Credential Types + +| Type | Authentication | Source | +|------|----------------|--------| +| binding-secret | clientid + clientsecret | VCAP_SERVICES | +| x509 | certificate + key | VCAP_SERVICES | + +### Token Caching + +Tokens cached up to 12 hours. Scope changes may take time to propagate. + +--- + +## Rate Limits + +### Limit Types + +| Limit | Response | Header | +|-------|----------|--------| +| Client limit | 429 Too Many Requests | `retry-after` (seconds) | +| Absolute limit | 503 Service Unavailable | `throttling` (milliseconds) | + +### Throttling Behavior + +- When limits approached: Response delayed, `throttling` header indicates delay +- When client limit exceeded: 429 response with `retry-after` +- When absolute limit exceeded: 503 response + +### Recovery + +- Both limits stack (combine) +- `retry-after` typically < 60 seconds +- Implement exponential backoff for retries + +--- + +## Job APIs + +### Create Job + +**Endpoint:** `POST /scheduler/jobs` + +**Request Body:** + +| Parameter | Required | Type | Description | +|-----------|----------|------|-------------| +| name | Yes | string | Job name (no special chars, not only numbers) | +| description | Yes | string | Job description | +| action | Yes | string | Fully qualified URL endpoint | +| active | Yes | boolean | Activation status | +| httpMethod | Yes | string | GET, POST, PUT, or DELETE | +| schedules | Yes | array | One or more schedules | +| startTime | No | string/object | Job start time | +| endTime | No | string/object/null | Job end time | +| ansConfig | No | object | Alert Notification config | +| calmConfig | No | object | Cloud ALM config | + +**Schedule Parameters:** + +| Parameter | Required | Type | Description | +|-----------|----------|------|-------------| +| active | Yes | boolean | Schedule activation | +| description | No | string | Schedule description | +| data | No | object | Payload for action endpoint | +| startTime | No | string/object | Schedule start | +| endTime | No | string/object | Schedule end | +| cron | No | string | Cron expression | +| time | No | string | One-time execution | +| repeatInterval | No | string | Recurring interval | +| repeatAt | No | string | Daily execution time | + +**Note:** Specify at most ONE scheduling mode (cron, time, repeatInterval, repeatAt). + +**Example Request:** + +```json +POST /scheduler/jobs +{ + "name": "salesReportJob", + "description": "Generate daily sales report", + "action": "[https://myapp.cfapps.eu10.hana.ondemand.com/api/reports/sales",](https://myapp.cfapps.eu10.hana.ondemand.com/api/reports/sales",) + "active": true, + "httpMethod": "POST", + "schedules": [{ + "active": true, + "description": "Daily at 6 AM UTC", + "repeatAt": "6.00am", + "startTime": { + "date": "2025-01-01", + "format": "YYYY-MM-DD" + } + }], + "ansConfig": { + "onSuccess": false, + "onError": true + }, + "calmConfig": { + "enabled": true + } +} +``` + +**Response (201 Created):** + +```json +{ + "name": "salesReportJob", + "description": "Generate daily sales report", + "action": "[https://myapp.cfapps.eu10.hana.ondemand.com/api/reports/sales",](https://myapp.cfapps.eu10.hana.ondemand.com/api/reports/sales",) + "active": true, + "httpMethod": "POST", + "_id": 42, + "schedules": [{ + "scheduleId": "5f58c2fb-a428-4f4b-9e1d-312e3be8952c", + "active": true, + "type": "recurring" + }] +} +``` + +Location header: `/scheduler/jobs/42` + +**Error Response (400):** + +```json +{ + "error": { + "code": "INVALID_REQUEST", + "message": "Invalid data provided", + "type": "VALIDATION_ERROR", + "detailedError": "Job name must not contain special characters" + } +} +``` + +### Retrieve All Jobs + +**Endpoint:** `GET /scheduler/jobs` + +**Query Parameters:** + +| Parameter | Type | Description | +|-----------|------|-------------| +| name | string | Filter by job name | +| jobId | number | Filter by job ID | +| jobType | string | HTTP_ENDPOINT or CF_TASK | +| page_size | number | Results per page (default 10) | +| offset | number | Jobs to skip (default 1) | +| tenantId | string | Filter by tenant (XSUAA token required) | + +**OData-Style Filtering:** + +``` +GET /scheduler/jobs?$filter=name eq 'myJob' +GET /scheduler/jobs?$filter=contains(name, 'report') +GET /scheduler/jobs?$filter=name eq 'job1' or name eq 'job2' +``` + +Operators: `eq`, `contains()`, `and`, `or` + +**Response (200):** + +```json +{ + "total": 25, + "results": [ + { + "_id": 1, + "name": "salesReportJob", + "description": "...", + "action": "...", + "active": true, + "httpMethod": "POST", + "jobType": "HTTP_ENDPOINT", + "createdAt": "2025-01-15T10:30:00Z", + "modifiedAt": "2025-01-20T14:00:00Z" + } + ], + "prev_url": null, + "next_url": "/scheduler/jobs?offset=11&page_size=10" +} +``` + +### Retrieve Job Details + +**Endpoints:** +- `GET /scheduler/jobs/{jobId}` +- `GET /scheduler/jobs?jobId={jobId}` +- `GET /scheduler/jobs?name={jobName}` + +**Query Parameters:** + +| Parameter | Type | Description | +|-----------|------|-------------| +| displaySchedules | boolean | Include schedule details | + +**Example:** + +``` +GET /scheduler/jobs/42?displaySchedules=true +``` + +**Response (200):** + +```json +{ + "_id": 42, + "name": "salesReportJob", + "description": "Generate daily sales report", + "action": "[https://myapp.../api/reports/sales",](https://myapp.../api/reports/sales",) + "active": true, + "httpMethod": "POST", + "startTime": null, + "endTime": null, + "signatureVersion": 0, + "ansConfig": { "onSuccess": false, "onError": true }, + "calmConfig": { "enabled": true }, + "schedules": [{ + "scheduleId": "5f58c2fb-...", + "description": "Daily at 6 AM UTC", + "type": "recurring", + "repeatAt": "6.00am", + "active": true, + "startTime": { "date": "2025-01-01", "format": "YYYY-MM-DD" } + }] +} +``` + +### Configure Job (Update) + +**Endpoint:** `PUT /scheduler/jobs/{jobId}` + +**Request Body:** + +All parameters optional except at least one must be provided: + +```json +PUT /scheduler/jobs/42 +{ + "active": false, + "description": "Updated description", + "httpMethod": "GET" +} +``` + +**Response (200):** + +```json +{ + "success": true +} +``` + +### Configure Job by Name (Create or Update) + +**Endpoint:** `PUT /scheduler/jobs/{name}` + +**Purpose:** Update an existing job or create a new one using the job name as identifier. + +**Path Parameter:** +- `name` (string, required): Job name to update or create + +**Request Body:** + +| Parameter | Required | Type | Default | Description | +|-----------|----------|------|---------|-------------| +| description | No | string | empty | Job description | +| active | No | boolean | false | Activation status | +| action | Yes (create) | string | - | Action endpoint URL | +| httpMethod | No | string | POST | GET, POST, PUT, DELETE | +| endTime | No | string/object/null | null | Job end time | +| ansConfig | No | object | - | Alert Notification config | +| calmConfig | No | object | - | Cloud ALM config | + +**Important:** The job name in the request URI must match the job name in the request body. + +**Example Request:** + +```json +PUT /scheduler/jobs/dailyReport +{ + "name": "dailyReport", + "description": "Generate daily sales report", + "action": "[https://myapp.../api/reports",](https://myapp.../api/reports",) + "active": true, + "httpMethod": "POST" +} +``` + +**Response Codes:** + +| Code | Description | +|------|-------------| +| 200 | Job updated successfully | +| 201 | New job created | +| 400 | Invalid data (validation errors) | + +--- + +### Delete Job + +**Endpoint:** `DELETE /scheduler/jobs/{jobId}` + +**Behavior:** +- Removes job and all associated data +- Terminates all schedules (active and inactive) +- Deletes all run logs + +**Example:** + +``` +DELETE /scheduler/jobs/42 +``` + +**Response (200):** + +```json +{ + "success": true +} +``` + +**Response (404):** Invalid job ID + +--- + +## Schedule APIs + +### Create Schedule + +**Endpoint:** `POST /scheduler/jobs/{jobId}/schedules` + +**Request Body:** + +```json +{ + "active": true, + "description": "Every 2 hours", + "repeatInterval": "2 hours", + "startTime": { + "date": "2025-01-01", + "format": "YYYY-MM-DD" + }, + "data": { + "customParam": "value" + } +} +``` + +**Response (201):** + +```json +{ + "scheduleId": "cb5c9def-e2a0-4294-8a51-61e4db373f99", + "description": "Every 2 hours", + "type": "recurring", + "repeatInterval": "2 hours", + "active": true, + "startTime": "2025-01-01T00:00:00.000Z", + "jobId": 42 +} +``` + +### Retrieve Schedules + +**Endpoint:** `GET /scheduler/jobs/{jobId}/schedules` + +**Query Parameters:** + +| Parameter | Type | Default | +|-----------|------|---------| +| page_size | number | 10 | +| offset | number | 1 | + +### Retrieve Schedule Details + +**Endpoint:** `GET /scheduler/jobs/{jobId}/schedules/{scheduleId}` + +**Path Parameters:** + +| Parameter | Type | Description | +|-----------|------|-------------| +| jobId | integer | Job identifier | +| scheduleId | string | Schedule identifier | + +**Query Parameters:** + +| Parameter | Type | Description | +|-----------|------|-------------| +| displayLogs | boolean | Return schedule run logs (max 200) | + +**Example:** + +``` +GET /scheduler/jobs/42/schedules/cb5c9def-...?displayLogs=true +``` + +**Response (200):** + +```json +{ + "scheduleId": "cb5c9def-e2a0-4294-8a51-61e4db373f99", + "description": "Every 2 hours", + "data": {}, + "type": "recurring", + "cron": null, + "repeatInterval": "2 hours", + "active": true, + "startTime": "2025-01-01T00:00:00.000Z", + "endTime": null, + "nextRunAt": "2025-01-20T14:00:00.000Z", + "logs": [ + { + "runId": "ea16b621-...", + "executionTimestamp": "2025-01-20T12:00:05Z", + "httpStatus": 200, + "runStatus": "COMPLETED", + "runState": "SUCCESS" + } + ] +} +``` + +**Response (404):** Invalid Job ID + +--- + +### Configure Schedule + +**Endpoint:** `PUT /scheduler/jobs/{jobId}/schedules/{scheduleId}` + +**Constraint:** Cannot change scheduling modes (e.g., cron to repeatInterval). Only update values within same mode. + +**Request:** + +```json +PUT /scheduler/jobs/42/schedules/cb5c9def-... +{ + "active": false, + "repeatInterval": "4 hours" +} +``` + +### Delete Schedule + +**Endpoint:** `DELETE /scheduler/jobs/{jobId}/schedules/{scheduleId}` + +### Delete All Schedules + +**Endpoint:** `DELETE /scheduler/jobs/{jobId}/schedules` + +### Activate/Deactivate All Schedules + +**Endpoint:** `POST /scheduler/jobs/{jobId}/schedules/activationStatus` + +**Request:** + +```json +{ + "activationStatus": true // or false +} +``` + +**Response:** + +```json +{ + "success": true +} +``` + +--- + +## Run Log APIs + +### Retrieve Run Logs + +**Endpoint:** `GET /scheduler/jobs/{jobId}/schedules/{scheduleId}/runs` + +**Query Parameters:** + +| Parameter | Type | Default | Max | +|-----------|------|---------|-----| +| page_size | number | 10 | 200 | +| offset | number | 1 | - | + +**Response (200):** + +```json +{ + "total": 150, + "results": [{ + "runId": "ea16b621-eaa8-4824-8629-ff6e6221bb56", + "runText": "Completed successfully", + "httpStatus": 200, + "executionTimestamp": "2025-01-20T06:00:05Z", + "scheduleTimestamp": "2025-01-20T06:00:00Z", + "completionTimestamp": "2025-01-20T06:00:10Z", + "runStatus": "COMPLETED", + "runState": "SUCCESS" + }], + "prev_url": null, + "next_url": "/scheduler/jobs/42/schedules/.../runs?offset=11" +} +``` + +**Timestamp Meanings:** + +| Timestamp | Description | +|-----------|-------------| +| scheduleTimestamp | When schedule was picked up for calculation | +| executionTimestamp | When scheduler invoked action endpoint | +| completionTimestamp | When scheduler received response | + +### Retrieve Run Log Details + +**Endpoint:** `GET /scheduler/jobs/{jobId}/schedules/{scheduleId}/runs/{runId}` + +**Path Parameters:** + +| Parameter | Type | Description | +|-----------|------|-------------| +| jobId | integer | Job identifier | +| scheduleId | string | Schedule identifier | +| runId | string | Run identifier | + +**Example:** + +``` +GET /scheduler/jobs/2/schedules/5f58c2fb-.../runs/5646889BB133728EE10000000A61A0D8 +``` + +**Response (200):** + +```json +{ + "runId": "5646889BB133728EE10000000A61A0D8", + "runText": "Job completed successfully", + "httpStatus": 200, + "executionTimestamp": "2025-01-20T06:00:05Z", + "scheduleTimestamp": "2025-01-20T06:00:00Z", + "completionTimestamp": "2025-01-20T06:00:10Z", + "runStatus": "COMPLETED", + "runState": "SUCCESS" +} +``` + +**Response (404):** Invalid Job ID + +--- + +### Update Run Log (Async Callback) + +**Endpoint:** `PUT /scheduler/jobs/{jobId}/schedules/{scheduleId}/runs/{runId}` + +**Purpose:** Application callback to report async job completion status. + +**Request:** + +```json +{ + "success": true, + "message": "Processing completed: 1000 records processed" +} +``` + +**Response (200):** + +```json +{ + "success": true +} +``` + +**Implementation Notes:** +- IDs come from request headers during job invocation +- Single callback per run (not multiple updates) +- If not called, status becomes `UNKNOWN` after timeout + +--- + +## Node.js Client Library + +### Installation + +```bash +npm install @sap/jobs-client +``` + +**Minimum Version:** 1.6.3 (for x509 certificate support) + +### Initialization + +```javascript +const JobSchedulerClient = require('@sap/jobs-client'); +const scheduler = new JobSchedulerClient.Scheduler(); + +// Get credentials from VCAP_SERVICES +const vcapServices = JSON.parse(process.env.VCAP_SERVICES); +const jobSchedulerCredentials = vcapServices.jobscheduler[0].credentials; +``` + +### Job Management Methods + +**createJob:** + +```javascript +scheduler.createJob({ + url: jobSchedulerCredentials.url +}, { + name: 'myJob', + description: 'My scheduled job', + action: '[https://myapp.../api/process',](https://myapp.../api/process',) + active: true, + httpMethod: 'POST', + schedules: [{ + cron: '* * * * 9 0 0', + active: true, + description: 'Daily at 9 AM' + }] +}, (error, result) => { + if (error) { + console.error('Error:', error); + } else { + console.log('Job created:', result); + } +}); +``` + +**fetchJob:** + +```javascript +scheduler.fetchJob({ + url: jobSchedulerCredentials.url, + jobId: 42 // or jobName: 'myJob' +}, (error, result) => { /* ... */ }); +``` + +**updateJob:** + +```javascript +scheduler.updateJob({ + url: jobSchedulerCredentials.url, + jobId: 42 +}, { + active: false +}, (error, result) => { /* ... */ }); +``` + +**deleteJob:** + +```javascript +scheduler.deleteJob({ + url: jobSchedulerCredentials.url, + jobId: 42 +}, (error, result) => { /* ... */ }); +``` + +**fetchAllJobs:** + +```javascript +scheduler.fetchAllJobs({ + url: jobSchedulerCredentials.url +}, (error, result) => { /* ... */ }); +``` + +**getJobCount:** + +```javascript +scheduler.getJobCount({ + url: jobSchedulerCredentials.url +}, (error, result) => { + console.log('Active jobs:', result.activeJobs); + console.log('Inactive jobs:', result.inactiveJobs); +}); +``` + +### Schedule Management Methods + +```javascript +// Create schedule +scheduler.createJobSchedule({ + url: jobSchedulerCredentials.url, + jobId: 42 +}, { + repeatInterval: '2 hours', + active: true +}, callback); + +// Update schedule +scheduler.updateJobSchedule({ + url: jobSchedulerCredentials.url, + jobId: 42, + scheduleId: 'cb5c9def-...' +}, { + active: false +}, callback); + +// Delete schedule +scheduler.deleteJobSchedule({ + url: jobSchedulerCredentials.url, + jobId: 42, + scheduleId: 'cb5c9def-...' +}, callback); + +// Fetch schedules +scheduler.fetchJobSchedules({ + url: jobSchedulerCredentials.url, + jobId: 42 +}, callback); + +// Bulk operations +scheduler.activateAllSchedules({ url, jobId }, callback); +scheduler.deactivateAllSchedules({ url, jobId }, callback); +scheduler.deleteAllJobSchedules({ url, jobId }, callback); +``` + +### Run Log Methods + +```javascript +// Update run log (async callback) +scheduler.updateJobRunLog({ + url: jobSchedulerCredentials.url, + jobId: jobId, + scheduleId: scheduleId, + runId: runId +}, { + success: true, + message: 'Processing completed' +}, callback); + +// Get run logs +scheduler.getRunLogs({ + url: jobSchedulerCredentials.url, + jobId: 42, + scheduleId: 'cb5c9def-...' +}, callback); + +// Get action logs +scheduler.getJobActionLogs({ url, jobId }, callback); +scheduler.getScheduleActionLogs({ url, jobId, scheduleId }, callback); +``` + +### Complete Example + +```javascript +const express = require('express'); +const JobSchedulerClient = require('@sap/jobs-client'); + +const app = express(); +const scheduler = new JobSchedulerClient.Scheduler(); +const credentials = JSON.parse(process.env.VCAP_SERVICES).jobscheduler[0].credentials; + +// Async job endpoint +app.post('/api/process', (req, res) => { + const jobId = req.headers['x-sap-job-id']; + const scheduleId = req.headers['x-sap-job-schedule-id']; + const runId = req.headers['x-sap-job-run-id']; + + // Acknowledge immediately + res.status(202).json({ message: 'Accepted' }); + + // Process asynchronously + processAsync() + .then(() => { + scheduler.updateJobRunLog({ + url: credentials.url, + jobId: parseInt(jobId), + scheduleId, + runId + }, { + success: true, + message: 'Completed successfully' + }, (err) => { + if (err) console.error('Failed to update run log:', err); + }); + }) + .catch((error) => { + scheduler.updateJobRunLog({ + url: credentials.url, + jobId: parseInt(jobId), + scheduleId, + runId + }, { + success: false, + message: error.message + }, (err) => { + if (err) console.error('Failed to update run log:', err); + }); + }); +}); + +async function processAsync() { + // Long-running operation +} + +app.listen(process.env.PORT || 3000); +``` + +--- + +## Java Client Library (XS Advanced) + +### Overview + +A Java Client Library (`java-js-client`) is available for SAP HANA Platform XS Advanced environments. + +**Use Case:** For Java-based applications running on SAP HANA XS Advanced. + +**Note:** This library is specific to XS Advanced and not for general Cloud Foundry Java applications. For Cloud Foundry Java apps, use the REST API directly with standard HTTP clients. + +### Availability + +Available through SAP's internal package registry for XS Advanced development. + +--- + +## External References + +### SAP Documentation +- **REST API Reference**: [https://help.sap.com/docs/job-scheduling/sap-job-scheduling-service/sap-job-scheduling-service-rest-apis](https://help.sap.com/docs/job-scheduling/sap-job-scheduling-service/sap-job-scheduling-service-rest-apis) +- **Node.js Client**: [https://www.npmjs.com/package/@sap/jobs-client](https://www.npmjs.com/package/@sap/jobs-client) +- **Java Client (XS Advanced)**: Available via SAP HANA XS Advanced documentation +- **Authentication**: [https://help.sap.com/docs/job-scheduling/sap-job-scheduling-service/authentication](https://help.sap.com/docs/job-scheduling/sap-job-scheduling-service/authentication) + +### Source Files +- `sap-job-scheduling-service-rest-apis-c513d2d.md` +- `authentication-5dca60b.md` +- `rate-limits-a9cb164.md` +- `create-job-2c1ecb6.md` +- `retrieve-all-jobs-b4d3719.md` +- `node-js-client-library-9b86127.md` +- All schedule and run log documentation files diff --git a/references/security.md b/references/security.md new file mode 100644 index 0000000..2322392 --- /dev/null +++ b/references/security.md @@ -0,0 +1,437 @@ +# SAP BTP Job Scheduling Service - Security Guide + +**Source**: [https://github.com/SAP-docs/sap-btp-job-scheduling-service/tree/main/docs/50---Security](https://github.com/SAP-docs/sap-btp-job-scheduling-service/tree/main/docs/50---Security) +**Last Updated**: 2025-11-22 + +--- + +## Table of Contents + +1. [Security Overview](#security-overview) +2. [OAuth 2.0 Authentication](#oauth-20-authentication) +3. [XSUAA Configuration](#xsuaa-configuration) +4. [Scope Management](#scope-management) +5. [Credential Rotation](#credential-rotation) +6. [Data Protection](#data-protection) +7. [Best Practices](#best-practices) + +--- + +## Security Overview + +### Authentication Methods + +| Service Plan | Authentication | Protocol | +|--------------|----------------|----------| +| lite | HTTP Basic Auth | HTTPS | +| standard | OAuth 2.0 | HTTPS | + +### Security Architecture + +``` +┌─────────────────┐ OAuth Token ┌──────────────────┐ +│ Job Scheduling │ ───────────────── │ Your App │ +│ Service │ │ (Action Endpoint)│ +└────────┬────────┘ └────────┬─────────┘ + │ │ + │ Token Request │ Token Validation + │ │ + └──────────────┬──────────────────────┘ + │ + ┌────────┴────────┐ + │ XSUAA │ + │ (Token Issuer) │ + └─────────────────┘ +``` + +### Key Security Features + +- OAuth 2.0 protected communication for API access +- OAuth 2.0 protected job action endpoint invocation +- Token-based authentication with configurable scopes +- Support for X.509 certificate-based authentication +- Credential rotation via binding/unbinding + +--- + +## OAuth 2.0 Authentication + +### Token Flow for Job Execution + +1. **Job Scheduling requests token** from XSUAA using service credentials +2. **XSUAA validates credentials** and returns access token with granted scopes +3. **Job Scheduling calls action endpoint** with Bearer token in Authorization header +4. **Application validates token** using bound XSUAA instance +5. **Application processes request** if token is valid + +### Token Acquisition + +**Client Credentials Flow (clientsecret):** + +```bash +curl -X POST "[https:///oauth/token"](https:///oauth/token") \ + -H "Authorization: Basic $(echo -n ':' | base64)" \ + -H "Content-Type: application/x-www-form-urlencoded" \ + -d "grant_type=client_credentials" +``` + +**Certificate-Based Authentication:** + +```bash +curl -X POST "[https:///oauth/token"](https:///oauth/token") \ + --cert /path/to/certificate.pem \ + --key /path/to/key.pem \ + -H "Content-Type: application/x-www-form-urlencoded" \ + -d "grant_type=client_credentials&client_id=" +``` + +### Token Response + +```json +{ + "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...", + "token_type": "bearer", + "expires_in": 43199, + "scope": "uaa.resource my-app.JOBSCHEDULER", + "jti": "abc123..." +} +``` + +### Token Caching + +- Tokens cached for up to **12 hours** +- Scope changes may take time to propagate +- If scope names change, cached tokens may cause errors + +--- + +## XSUAA Configuration + +### xs-security.json Structure + +```json +{ + "xsappname": "", + "tenant-mode": "dedicated", + "scopes": [ + { + "name": "$XSAPPNAME.JOBSCHEDULER", + "description": "Job Scheduler Scope", + "grant-as-authority-to-apps": [ + "$XSSERVICENAME()" + ] + } + ], + "authorities": [ + "$XSAPPNAME.JOBSCHEDULER" + ] +} +``` + +### Configuration Elements + +| Element | Purpose | +|---------|---------| +| `xsappname` | Unique application identifier | +| `tenant-mode` | Multitenancy mode (dedicated/shared) | +| `scopes` | OAuth scopes definition | +| `grant-as-authority-to-apps` | Grant scope to other services | +| `authorities` | Scopes the app can request | + +### Variable Substitution + +| Variable | Resolves To | +|----------|-------------| +| `$XSAPPNAME` | Value of `xsappname` field | +| `$XSSERVICENAME(name)` | Service instance identifier | + +### Create/Update XSUAA Instance + +**Create:** + +```bash +cf create-service xsuaa application my-xsuaa -c xs-security.json +``` + +**Update:** + +```bash +cf update-service my-xsuaa -c xs-security.json +``` + +**Bind:** + +```bash +cf bind-service my-app my-xsuaa +cf restage my-app +``` + +--- + +## Scope Management + +### Granting Scopes to Job Scheduling + +The `grant-as-authority-to-apps` property enables Job Scheduling to obtain your application's scopes: + +```json +{ + "scopes": [{ + "name": "$XSAPPNAME.JOBSCHEDULER", + "description": "Job Scheduler Scope", + "grant-as-authority-to-apps": [ + "$XSSERVICENAME(my-jobscheduler)" + ] + }] +} +``` + +### Multiple Scopes + +Grant multiple scopes if your application requires different permissions: + +```json +{ + "scopes": [ + { + "name": "$XSAPPNAME.JobRead", + "description": "Read job data", + "grant-as-authority-to-apps": ["$XSSERVICENAME(my-jobscheduler)"] + }, + { + "name": "$XSAPPNAME.JobWrite", + "description": "Write job data", + "grant-as-authority-to-apps": ["$XSSERVICENAME(my-jobscheduler)"] + } + ] +} +``` + +### Verifying Scope Grants + +**Get Token Manually:** + +```bash +# Get token using Job Scheduling credentials +curl -X POST "/oauth/token" \ + -H "Authorization: Basic $(echo -n ':' | base64)" \ + -d "grant_type=client_credentials" +``` + +**Decode Token (jwt.io or similar):** + +Check the `scope` claim includes your granted scopes. + +### Troubleshooting Scope Issues + +| Issue | Cause | Solution | +|-------|-------|----------| +| Scope not in token | Not granted | Update xs-security.json | +| 401 on action endpoint | Token invalid | Verify XSUAA binding | +| Scope grant delayed | Token caching | Wait up to 12 hours | + +--- + +## Credential Rotation + +### Process Overview + +Credentials are binding-level, meaning new credentials are created each time you bind the service. + +### Rotation Steps + +**1. Unbind Service:** + +```bash +cf unbind-service my-app my-jobscheduler +``` + +**2. Rebind Service:** + +```bash +cf bind-service my-app my-jobscheduler +``` + +**3. Restage Application:** + +```bash +cf restage my-app +``` + +### Key Points + +| Aspect | Behavior | +|--------|----------| +| Old credentials | Invalidated immediately on unbind | +| New credentials | Generated automatically on rebind | +| Token requests | Will fail with old credentials after unbind | +| Downtime | Brief during restage | + +### X.509 Certificate Rotation + +For certificate-based bindings: + +```bash +# Unbind +cf unbind-service my-app my-jobscheduler + +# Rebind with new certificate parameters +cf bind-service my-app my-jobscheduler -c parameters.json + +# Restage +cf restage my-app +``` + +Certificate parameters.json: + +```json +{ + "credential-type": "x509", + "x509": { + "key-length": 2048, + "validity": 30, + "validity-type": "DAYS" + } +} +``` + +### Zero-Downtime Rotation (Advanced) + +For production systems requiring zero downtime: + +1. Create second service binding (if supported) +2. Update application to use new binding +3. Remove old binding + +--- + +## Data Protection + +### Personal Data Handling + +The Job Scheduling service does **not** provide technical capabilities to support collection, processing, and storage of personal data. + +### Fields NOT Intended for Personal Data + +| Field | Risk | +|-------|------| +| Job names | Visible in logs and dashboard | +| Schedule descriptions | Stored in service database | +| Response message text | Stored in run logs | +| Custom data payloads | Passed to action endpoints | + +### Compliance Considerations + +- Data protection requires case-by-case evaluation +- Organizations must assess specific legal requirements +- SAP does not provide legal advice +- System landscape configuration affects compliance + +### Run Log Retention + +- Run logs automatically deleted after **15 days** +- Download logs before deletion if needed for compliance +- Consider data classification before including sensitive info + +--- + +## Best Practices + +### HTTPS Requirements + +- **Always use HTTPS** for action endpoints in production +- HTTP allowed only for development/testing +- Dashboard enforces HTTPS requirement for job creation + +### Scope Naming + +- Use descriptive, consistent scope names +- Include purpose in scope descriptions +- Follow naming conventions: `$XSAPPNAME.` + +### Credential Management + +| Practice | Recommendation | +|----------|----------------| +| Storage | Never hardcode credentials | +| Rotation | Rotate quarterly minimum | +| X.509 | Prefer certificates over secrets | +| Validity | Set appropriate certificate validity | + +### Token Validation + +Implement proper token validation in action endpoints: + +```javascript +const xsenv = require('@sap/xsenv'); +const passport = require('passport'); +const { JWTStrategy } = require('@sap/xssec'); + +// Configure passport with XSUAA +const services = xsenv.getServices({ uaa: { tag: 'xsuaa' } }); +passport.use(new JWTStrategy(services.uaa)); + +// Protect endpoint +app.post('/api/process', + passport.authenticate('JWT', { session: false }), + (req, res) => { + // Validate specific scope + if (!req.authInfo.checkScope('$XSAPPNAME.JOBSCHEDULER')) { + return res.status(403).send('Forbidden'); + } + // Process request + } +); +``` + +**Required packages:** +```bash +npm install @sap/xsenv @sap/xssec passport +``` + +### Cloud Foundry Tasks + +- CF tasks use Cloud Foundry UAA (CFUAA), not XSUAA +- XSUAA binding not required for CF task creation +- Space Developer role required for task management + +--- + +## Security Checklist + +### Initial Setup + +- [ ] XSUAA instance created with xs-security.json +- [ ] Scopes defined with appropriate descriptions +- [ ] `grant-as-authority-to-apps` configured for Job Scheduling +- [ ] XSUAA bound to application before Job Scheduling +- [ ] Application restaged after bindings + +### Action Endpoint + +- [ ] HTTPS enabled (required for production) +- [ ] Token validation implemented +- [ ] Scope verification in endpoint handler +- [ ] Error handling for auth failures + +### Ongoing Operations + +- [ ] Credential rotation scheduled (quarterly) +- [ ] Token caching behavior understood +- [ ] Run log retention policy defined +- [ ] Personal data handling documented + +--- + +## External References + +### SAP Documentation +- **Security Overview**: [https://help.sap.com/docs/job-scheduling/sap-job-scheduling-service/security](https://help.sap.com/docs/job-scheduling/sap-job-scheduling-service/security) +- **Secure Access**: [https://help.sap.com/docs/job-scheduling/sap-job-scheduling-service/secure-access](https://help.sap.com/docs/job-scheduling/sap-job-scheduling-service/secure-access) +- **XSUAA Documentation**: [https://help.sap.com/docs/btp/sap-business-technology-platform/security](https://help.sap.com/docs/btp/sap-business-technology-platform/security) + +### Source Files +- `security-9fb8213.md` +- `secure-access-745ca50.md` +- `define-and-grant-scopes-to-sap-job-scheduling-service-08933d3.md` +- `credential-rotation-ed3bf28.md` diff --git a/references/setup-guide.md b/references/setup-guide.md new file mode 100644 index 0000000..8ee0e5d --- /dev/null +++ b/references/setup-guide.md @@ -0,0 +1,397 @@ +# SAP BTP Job Scheduling Service - Setup Guide + +**Source**: [https://github.com/SAP-docs/sap-btp-job-scheduling-service/tree/main/docs](https://github.com/SAP-docs/sap-btp-job-scheduling-service/tree/main/docs) +**Last Updated**: 2025-11-22 + +--- + +## Table of Contents + +1. [Prerequisites](#prerequisites) +2. [Service Plans](#service-plans) +3. [Create Service Instance - BTP Cockpit](#create-service-instance---btp-cockpit) +4. [Create Service Instance - CF CLI](#create-service-instance---cf-cli) +5. [Create Service Instance - Kyma Dashboard](#create-service-instance---kyma-dashboard) +6. [XSUAA Configuration](#xsuaa-configuration) +7. [Complete Setup Workflow](#complete-setup-workflow) + +--- + +## Prerequisites + +### Account Requirements + +| Requirement | Description | +|-------------|-------------| +| Global Account | SAP BTP global account | +| Subaccount | At least one subaccount with CF or Kyma enabled | +| Administrator Role | Global account administrator | +| Quota | Purchased quota for Job Scheduling and XSUAA services | + +### Service Entitlements + +| Service | Plan | Purpose | +|---------|------|---------| +| SAP Job Scheduling Service | standard | Job scheduling functionality | +| SAP Authorization and Trust Management (XSUAA) | application | OAuth 2.0 authentication | + +### Cloud Foundry Requirements + +- Created a Cloud Foundry space +- Assigned as Space Developer in your space +- Application deployed with exposed action endpoint +- Application and service in the same CF space (co-location required) + +### Kyma Requirements + +- Kyma environment enabled in subaccount +- Namespace created +- One of these roles: + - `SAP_Job_Scheduling_Service_Admin` + - `SAP_Job_Scheduling_Service_Viewer` + +--- + +## Service Plans + +### Standard Plan + +The only available plan for SAP Job Scheduling Service. + +| Feature | Value | +|---------|-------| +| Authentication | OAuth 2.0 | +| Service Name | `jobscheduler` | +| Plan Name | `standard` | +| Custom Parameters | None required (see below) | + +**Note (November 2024 Update):** The `enable-xsuaa-support` property now **defaults to enabled**. No additional parameters are required during service instance creation. Previously, this had to be explicitly set. + +--- + +## Create Service Instance - BTP Cockpit + +### Prerequisites + +- Logged on to SAP BTP cockpit +- Quota assigned to subaccount + +### Step-by-Step Instructions + +**Step 1: Access Service Marketplace** + +1. Navigate to your subaccount +2. Go to **Services** → **Service Marketplace** +3. Locate **Job Scheduling Service** + +**Step 2: Create Instance** + +1. Click on Job Scheduling Service tile +2. Open **Actions** menu +3. Select **Create** +4. New Instance wizard launches + +**Step 3: Configure Instance** + +| Field | Value | +|-------|-------| +| Service Plan | standard (only option) | +| Instance Name | Your custom name (e.g., `my-jobscheduler`) | +| Parameters | None available | + +**Step 4: Complete Creation** + +1. Click **Next** through Parameters step (no customization available) +2. Review details +3. Click **Create** + +**Step 5: Bind to Application** + +1. Go to **Service Instances** +2. Select your new instance +3. Click **Bind Application** +4. Select your deployed Cloud Foundry application + +--- + +## Create Service Instance - CF CLI + +### Prerequisites + +- CF CLI installed +- Logged into Cloud Foundry (`cf login`) +- Application deployed + +### Commands + +**1. Verify Service Availability:** + +```bash +cf marketplace +``` + +Look for `jobscheduler` in the output. + +**2. Create Service Instance:** + +```bash +cf create-service jobscheduler standard my-jobscheduler +``` + +**3. Bind Service - Basic:** + +```bash +cf bind-service my-app my-jobscheduler +``` + +**4. Bind Service - With X.509 Certificate:** + +Create `parameters.json`: +```json +{ + "credential-type": "x509", + "x509": { + "key-length": 2048, + "validity": 7, + "validity-type": "DAYS" + } +} +``` + +Bind with parameters: +```bash +cf bind-service my-app my-jobscheduler -c parameters.json +``` + +**5. Restage Application:** + +```bash +cf restage my-app +``` + +**6. Verify Binding:** + +```bash +cf env my-app +``` + +Check `VCAP_SERVICES` for `jobscheduler` credentials. + +### VCAP_SERVICES Structure + +**Standard Binding (clientsecret):** + +```json +{ + "jobscheduler": [{ + "credentials": { + "url": "[https://jobscheduler-rest.cfapps.eu10.hana.ondemand.com",](https://jobscheduler-rest.cfapps.eu10.hana.ondemand.com",) + "uaa": { + "url": "[https://xxx.authentication.eu10.hana.ondemand.com",](https://xxx.authentication.eu10.hana.ondemand.com",) + "clientid": "sb-xxx", + "clientsecret": "xxx" + } + } + }] +} +``` + +**X.509 Binding:** + +```json +{ + "jobscheduler": [{ + "credentials": { + "url": "[https://jobscheduler-rest.cfapps.eu10.hana.ondemand.com",](https://jobscheduler-rest.cfapps.eu10.hana.ondemand.com",) + "uaa": { + "certurl": "[https://xxx.authentication.cert.eu10.hana.ondemand.com",](https://xxx.authentication.cert.eu10.hana.ondemand.com",) + "clientid": "sb-xxx", + "certificate": "-----BEGIN CERTIFICATE-----\n...", + "key": "-----BEGIN RSA PRIVATE KEY-----\n..." + } + } + }] +} +``` + +--- + +## Create Service Instance - Kyma Dashboard + +### Prerequisites + +- Logged on to SAP BTP cockpit +- Kyma environment enabled + +### Step-by-Step Instructions + +**Step 1: Access Kyma Dashboard** + +1. Navigate to your subaccount +2. Click **Link to Dashboard** in Kyma Environment section + +**Step 2: Select Namespace** + +1. Choose your target namespace + +**Step 3: Create Service Instance** + +1. Go to **Service Instances** section +2. Click **Create** +3. Fill in details: + +| Field | Value | +|-------|-------| +| Service Name | `jobscheduler` | +| Plan | `standard` | +| Instance Name | Your custom name | + +**Step 4: Create Service Binding** + +1. Navigate to **Service Bindings** +2. Click **Create** +3. Select your service instance +4. Provide binding name + +**Step 5: Mount Service in Application** + +Connect the service binding to your application deployment using SAP BTP Operator module. + +### Kyma-Specific Notes + +- Use SAP BTP Operator for service management +- Service bindings mounted as Kubernetes secrets +- Refer to Kyma documentation for detailed deployment patterns + +--- + +## XSUAA Configuration + +### Purpose + +XSUAA provides OAuth 2.0 authentication for job action endpoints. Job Scheduling Service needs scope grants to call protected endpoints. + +### xs-security.json Template + +```json +{ + "xsappname": "my-app", + "tenant-mode": "dedicated", + "scopes": [ + { + "name": "$XSAPPNAME.JOBSCHEDULER", + "description": "Job Scheduler Scope", + "grant-as-authority-to-apps": [ + "$XSSERVICENAME(my-jobscheduler)" + ] + } + ], + "authorities": [ + "$XSAPPNAME.JOBSCHEDULER" + ] +} +``` + +### Key Configuration Elements + +| Element | Description | +|---------|-------------| +| `$XSAPPNAME` | Automatically replaced with app name | +| `$XSSERVICENAME(instance)` | References Job Scheduling instance | +| `grant-as-authority-to-apps` | Grants scope to Job Scheduling service | + +### Apply Configuration + +**Create XSUAA Instance:** + +```bash +cf create-service xsuaa application my-xsuaa -c xs-security.json +``` + +**Update Existing Instance:** + +```bash +cf update-service my-xsuaa -c xs-security.json +``` + +**Bind XSUAA to Application:** + +```bash +cf bind-service my-app my-xsuaa +cf restage my-app +``` + +### Scope Grant Workflow + +1. Application defines scope in `xs-security.json` +2. Scope granted to Job Scheduling service via `grant-as-authority-to-apps` +3. Job Scheduling obtains token from UAA with granted scope +4. Job Scheduling includes token when calling action endpoint +5. Application validates token using bound XSUAA instance + +--- + +## Complete Setup Workflow + +### Recommended Order + +``` +1. Deploy Application + └─ Expose action endpoint (HTTPS) + +2. Create XSUAA Instance + └─ Configure xs-security.json with scope grants + └─ cf create-service xsuaa application my-xsuaa -c xs-security.json + +3. Bind XSUAA to Application + └─ cf bind-service my-app my-xsuaa + +4. Create Job Scheduling Instance + └─ cf create-service jobscheduler standard my-jobscheduler + +5. Bind Job Scheduling to Application + └─ cf bind-service my-app my-jobscheduler + +6. Restage Application + └─ cf restage my-app + +7. Create Jobs via REST API or Dashboard +``` + +### Verification Checklist + +- [ ] Application deployed and accessible +- [ ] Action endpoint exposed and working +- [ ] XSUAA instance created with correct scopes +- [ ] XSUAA bound to application +- [ ] Job Scheduling instance created +- [ ] Job Scheduling bound to application +- [ ] Application restaged +- [ ] VCAP_SERVICES contains both services +- [ ] Can obtain OAuth token successfully +- [ ] Can access Job Scheduling dashboard + +### Common Setup Errors + +| Error | Cause | Solution | +|-------|-------|----------| +| Service not found | Missing entitlement | Add quota to subaccount | +| 401 Unauthorized | Missing scope grant | Update xs-security.json | +| 403 Forbidden | Wrong space | Ensure co-location | +| Instance not visible | Not bound | Bind service to app | + +--- + +## External References + +### SAP Documentation +- **Initial Setup**: [https://help.sap.com/docs/job-scheduling/sap-job-scheduling-service/initial-setup](https://help.sap.com/docs/job-scheduling/sap-job-scheduling-service/initial-setup) +- **Getting Started**: [https://help.sap.com/docs/job-scheduling/sap-job-scheduling-service/getting-started](https://help.sap.com/docs/job-scheduling/sap-job-scheduling-service/getting-started) +- **XSUAA Documentation**: [https://help.sap.com/docs/btp/sap-business-technology-platform/security](https://help.sap.com/docs/btp/sap-business-technology-platform/security) + +### Source Files +- `initial-setup-0adb655.md` +- `create-a-service-instance-in-sap-btp-cockpit-e267ab6.md` +- `create-a-service-instance-using-cf-cli-cb56f9e.md` +- `create-a-service-instance-in-the-kyma-dashboard-224a49a.md` +- `getting-started-02e4e8b.md` diff --git a/references/troubleshooting.md b/references/troubleshooting.md new file mode 100644 index 0000000..eb12c3c --- /dev/null +++ b/references/troubleshooting.md @@ -0,0 +1,379 @@ +# SAP BTP Job Scheduling Service - Troubleshooting Guide + +**Source**: [https://github.com/SAP-docs/sap-btp-job-scheduling-service/tree/main/docs](https://github.com/SAP-docs/sap-btp-job-scheduling-service/tree/main/docs) +**Last Updated**: 2025-11-22 + +--- + +## Table of Contents + +1. [Support Information](#support-information) +2. [Common Error Scenarios](#common-error-scenarios) +3. [Schedule Issues](#schedule-issues) +4. [Authentication Issues](#authentication-issues) +5. [Cloud Foundry Task Issues](#cloud-foundry-task-issues) +6. [Dashboard Access Issues](#dashboard-access-issues) +7. [Frequently Asked Questions](#frequently-asked-questions) + +--- + +## Support Information + +### Support Component + +**Component:** `BC-CP-CF-JBS` + +Use this component when creating SAP support tickets. + +### Self-Service Resources + +1. **SAP Trust Center** - Check platform status +2. **Guided Answers Tool** - Documented troubleshooting scenarios +3. **Platform Updates and Notifications** - Cloud Foundry environment updates + +### Escalation Path + +1. Check FAQ and troubleshooting scenarios +2. Verify platform status via SAP Trust Center +3. Use Guided Answers for common issues +4. Submit incident via SAP Support with component BC-CP-CF-JBS + +--- + +## Common Error Scenarios + +### Service Unavailability + +**Symptoms:** +- Service missing from marketplace +- Service not visible in cockpit + +**Diagnostic Steps:** +1. Verify service availability in your region (SAP BTP service portfolio) +2. Confirm quota assigned to subaccount +3. Check Space Developer role assignment + +**Solutions:** + +| Cause | Solution | +|-------|----------| +| No quota | Review [Managing Entitlements and Quotas](https://help.sap.com/viewer/65de2977205c403bbc107264b8eccf4b/Cloud/en-US/c8248745dde24afb91479361de336111.html) | +| Region unavailable | Create subaccount in supported region | +| Missing role | Request Space Developer role | + +### REST API Authentication Errors + +**Error:** HTTP Status Code 401 + +**Diagnostic Steps:** +1. Validate credentials being passed +2. Check token expiration +3. Verify correct endpoint URL + +**Solutions:** + +| Cause | Solution | +|-------|----------| +| Invalid credentials | Re-check VCAP_SERVICES values | +| Expired token | Request new token | +| Wrong endpoint | Use URL from service binding | + +### OAuth Scope Issues + +**Symptoms:** +- Granted scopes not in Job Scheduling tokens +- 403 Forbidden when calling action endpoint + +**Diagnostic Steps:** +1. Manually retrieve token using Job Scheduling credentials: + ```bash + curl -X POST "/oauth/token" \ + -H "Authorization: Basic " \ + -d "grant_type=client_credentials" + ``` +2. Decode token and verify scope claim +3. Note: Tokens cached up to 12 hours + +**Solutions:** + +| Cause | Solution | +|-------|----------| +| Missing grant | Update `grant-as-authority-to-apps` in xs-security.json | +| Stale cache | Wait up to 12 hours for token refresh | +| Wrong binding | Verify Job Scheduling instance name matches | + +--- + +## Schedule Issues + +### Schedule Fails to Execute + +**Possible Causes:** + +| Cause | Description | +|-------|-------------| +| Invalid format | Date-time or cron format incorrect | +| Past endTime | Schedule endTime is in the past | +| Wrong timezone | Service uses UTC only | +| Auto-deactivated | See auto-deactivation triggers below | + +### Auto-Deactivation Triggers + +Schedules automatically deactivate when: + +1. **One-time schedule executed** - Successful or failed +2. **No valid future dates** - All possible execution times passed +3. **endTime reached** - Job or schedule end time in past +4. **Endpoint unreachable** - Action endpoint unreachable for 10+ consecutive days + +### ACK_NOT_RECVD Status + +**Meaning:** Application hasn't updated the run log after processing. + +**Solution:** +- Implement async callback properly +- Call Update Job Run Log API after completion: + ``` + PUT /scheduler/jobs/{jobId}/schedules/{scheduleId}/runs/{runId} + { + "success": true, + "message": "Completed" + } + ``` + +### Immediate Execution + +**To execute a job immediately:** + +Create one-time schedule with: +```json +{ + "time": "now" +} +``` + +### Cron Format Errors + +**Common Mistake:** Using Linux cron format + +**Correct:** SAP cron format (7 fields): +``` +[Year] [Month] [Day] [DayOfWeek] [Hour] [Minute] [Second] +``` + +**Example with field mapping:** +``` +* * * * 9 0 0 +Year Month Day DayOfWeek Hour Minute Second +// Daily at 9:00:00 AM UTC (SAP format) +``` + +NOT: +``` +0 9 * * * // Linux format (5 fields) - will NOT work +``` + +**Note:** `*` is a wildcard meaning "any value" for that field. + +### Timezone Issues + +**Note:** Service operates in **UTC only**. No other timezones supported. + +Convert local times to UTC before scheduling. + +--- + +## Authentication Issues + +### 401 Unauthorized + +**Check List:** +- [ ] Correct OAuth token in Authorization header +- [ ] Token not expired +- [ ] Using Bearer token format +- [ ] Correct endpoint URL + +### 403 Forbidden + +**Check List:** +- [ ] Scope granted via `grant-as-authority-to-apps` +- [ ] xs-security.json updated and service restarted +- [ ] Application validates token correctly +- [ ] Same space for app and service (co-location) + +### Dashboard Authorization Error (500) + +**Symptom:** 500 error when accessing dashboard + +**Solution:** +Grant permissions at UAA login route: +``` +[https://uaa.cf..hana.ondemand.com/profile](https://uaa.cf..hana.ondemand.com/profile) +``` + +Example: `[https://uaa.cf.eu10.hana.ondemand.com/profile`](https://uaa.cf.eu10.hana.ondemand.com/profile`) + +--- + +## Cloud Foundry Task Issues + +### Unsuccessful Task Creation + +**Diagnostic Steps:** +1. Check organization memory quota: + ```bash + cf org --guid + cf curl "/v2/organizations//memory_usage" + ``` +2. Verify total available memory exceeds task requirements +3. Review application logs: + ```bash + cf logs --recent + ``` + +**Solutions:** + +| Cause | Solution | +|-------|----------| +| Insufficient quota | Request additional memory quota | +| Memory too high | Configure task memory via dashboard | + +### Configure Task Memory + +In dashboard, use JSON options: +```json +{ + "memory_in_mb": 512 +} +``` + +Default: 1024 MB (1 GB) + +### CF Task Limitations + +- Cannot create CF tasks via REST API +- Requires Space Developer role +- Must use dashboard for task creation +- Tasks always run asynchronously + +--- + +## Dashboard Access Issues + +### Prerequisites + +- Space Developer role (full access) +- OR one of: SpaceAuditor, SpaceManager, OrgManager, SpaceSupporter (read-only) + +### Access Methods + +**Via BTP Cockpit:** +1. Navigate to subaccount +2. Go to **Service Instances** +3. Select Job Scheduling instance +4. Click **View Dashboard** or access via Service Bindings + +**Via CF CLI:** +```bash +cf service +``` + +Look for dashboard URL in output. + +### Kyma Dashboard Access + +Requires one of: +- `SAP_Job_Scheduling_Service_Admin` +- `SAP_Job_Scheduling_Service_Viewer` + +--- + +## Frequently Asked Questions + +### General + +**Q: What is the support component?** +A: BC-CP-CF-JBS + +**Q: What are the prerequisites?** +A: Access to service in CF marketplace and xsuaa service for jobs with action endpoints. + +**Q: What is the SLA?** +A: Scheduled jobs have approximately 20 minutes tolerance from scheduled execution time. + +**Q: What do units on SAP Store represent?** +A: Each unit represents one creatable service instance. + +### Multitenancy + +**Q: How does multitenancy work?** +A: Multitenant applications can register jobs on behalf of subscribed tenants while maintaining tenant context awareness during execution. + +**Q: What tokens are needed for multitenancy?** +A: Use client credentials flow with XSUAA to obtain access tokens. + +**Q: What about tenantId filtering?** +A: The `tenantId` query parameter filters jobs when using client credentials tokens, but returns 400 for SaaS tenant tokens. + +### Schedules + +**Q: Why did my schedule auto-deactivate?** +A: One-time schedules deactivate after execution, recurring schedules deactivate when no valid future dates exist, endTime reached, or action endpoint unreachable for 10+ days. + +**Q: What is ACK_NOT_RECVD?** +A: The application hasn't updated the run log after async processing. Call the Update Run Log API. + +**Q: How do I execute immediately?** +A: Create one-time schedule with `"time": "now"`. + +**Q: What cron format is used?** +A: SAP cron format (7 fields), NOT Linux cron format. + +### API + +**Q: Can CF tasks be created via REST API?** +A: No, only developers with Space Developer role can create them through the dashboard's Tasks section. + +**Q: What is the request body size limit?** +A: 100 KB. Exceeding returns HTTP 413. + +**Q: What timezone is used?** +A: UTC only. No other timezones supported. + +### Data + +**Q: How long are run logs retained?** +A: 15 days, then automatically deleted. + +**Q: Can deleted jobs be restored?** +A: Yes, within time limits (14 days AWS/Azure, 7 days GCP). Same-day deletions cannot be restored. + +--- + +## Error Code Reference + +| Code | Meaning | Solution | +|------|---------|----------| +| 400 | Invalid request data | Check request body format | +| 401 | Unauthorized | Check credentials/token | +| 403 | Forbidden | Check scope grants | +| 404 | Not found | Verify job/schedule ID | +| 413 | Request too large | Reduce body size (<100KB) | +| 429 | Rate limit exceeded | Wait for retry-after period | +| 500 | Server error | Check dashboard auth | +| 503 | Service unavailable | Wait for throttling period | + +--- + +## External References + +### SAP Documentation +- **FAQ**: [https://help.sap.com/docs/job-scheduling/sap-job-scheduling-service/frequently-asked-questions](https://help.sap.com/docs/job-scheduling/sap-job-scheduling-service/frequently-asked-questions) +- **Troubleshooting**: [https://help.sap.com/docs/job-scheduling/sap-job-scheduling-service/troubleshooting-scenarios](https://help.sap.com/docs/job-scheduling/sap-job-scheduling-service/troubleshooting-scenarios) +- **Monitoring**: [https://help.sap.com/docs/job-scheduling/sap-job-scheduling-service/monitoring-and-troubleshooting](https://help.sap.com/docs/job-scheduling/sap-job-scheduling-service/monitoring-and-troubleshooting) +- **Guided Answers**: [https://ga.support.sap.com/](https://ga.support.sap.com/) + +### Source Files +- `frequently-asked-questions-d72c276.md` +- `troubleshooting-scenarios-b05dc8c.md` +- `monitoring-and-troubleshooting-bd573bd.md` diff --git a/templates/job-creation.json b/templates/job-creation.json new file mode 100644 index 0000000..18dd626 --- /dev/null +++ b/templates/job-creation.json @@ -0,0 +1,76 @@ +{ + "_comment": "SAP BTP Job Scheduling Service - Job Creation Template", + "_documentation": "https://help.sap.com/docs/job-scheduling/sap-job-scheduling-service/create-job", + "_instructions": [ + "1. Replace all [PLACEHOLDER] values with your actual values", + "2. Remove _comment, _documentation, _instructions fields before submitting", + "3. Choose ONE scheduling mode per schedule: cron, time, repeatInterval, or repeatAt", + "4. Use HTTPS for action endpoints in production", + "5. All times are interpreted as UTC" + ], + + "name": "[JOB_NAME]", + "description": "[JOB_DESCRIPTION]", + "action": "https://[YOUR_APP].[LANDSCAPE].hana.ondemand.com/api/[ENDPOINT]", + "active": true, + "httpMethod": "POST", + + "startTime": { + "date": "[YYYY-MM-DD]", + "format": "YYYY-MM-DD" + }, + + "endTime": null, + + "schedules": [ + { + "_comment_schedule_type": "OPTION 1: Recurring with cron (7-field SAP format)", + "_cron_format": "SAP format: [Year] [Month] [Day] [DayOfWeek] [Hour] [Minute] [Second]", + "active": true, + "description": "[SCHEDULE_DESCRIPTION]", + "cron": "* * * * [HOUR] [MINUTE] [SECOND]", + "startTime": { + "date": "[YYYY-MM-DD]", + "format": "YYYY-MM-DD" + }, + "data": { + "_comment": "Custom payload sent to action endpoint", + "param1": "value1" + } + } + ], + + "_alternative_schedule_types": { + "one_time": { + "time": "now", + "_or": "2025-12-31T23:59:59Z", + "_or_human": "tomorrow at 4pm" + }, + "repeat_interval": { + "repeatInterval": "2 hours", + "_examples": ["5 minutes", "1 day", "2 weeks"] + }, + "repeat_at": { + "repeatAt": "6.00am", + "_examples": ["4.40pm", "18:30", "6.20am"] + }, + "cron_examples": { + "daily_9am": "* * * * 9 0 0", + "every_monday_10am": "* * * mon 10 0 0", + "last_sunday_monthly": "* * * -1.sun 9 0 0", + "every_30_min_10_to_12": "* * * * 10:12 0,30 0", + "first_of_month_6pm": "* * 1 * 18 0 0" + } + }, + + "ansConfig": { + "_comment": "SAP Alert Notification Service (Cloud Foundry only)", + "onSuccess": false, + "onError": true + }, + + "calmConfig": { + "_comment": "SAP Cloud ALM monitoring", + "enabled": true + } +} diff --git a/templates/xs-security.json b/templates/xs-security.json new file mode 100644 index 0000000..f8ed640 --- /dev/null +++ b/templates/xs-security.json @@ -0,0 +1,66 @@ +{ + "_comment": "SAP XSUAA Configuration Template for Job Scheduling Service", + "_documentation": "https://help.sap.com/docs/job-scheduling/sap-job-scheduling-service/define-and-grant-scopes-to-sap-job-scheduling-service", + "_instructions": [ + "1. Replace [APP_NAME] with your application name", + "2. Replace [JOBSCHEDULER_INSTANCE] with your Job Scheduling service instance name", + "3. Remove all _comment and _instructions fields before deployment", + "4. Create/update XSUAA: cf create-service xsuaa application my-xsuaa -c xs-security.json", + "5. Bind to app: cf bind-service my-app my-xsuaa && cf restage my-app" + ], + + "xsappname": "[APP_NAME]", + "tenant-mode": "dedicated", + + "scopes": [ + { + "name": "$XSAPPNAME.JOBSCHEDULER", + "description": "Job Scheduler Scope - Allows Job Scheduling service to invoke action endpoints", + "grant-as-authority-to-apps": [ + "$XSSERVICENAME([JOBSCHEDULER_INSTANCE])" + ] + } + ], + + "authorities": [ + "$XSAPPNAME.JOBSCHEDULER" + ], + + "_additional_scopes_example": { + "_comment": "Add more scopes if your app needs different permission levels", + "scopes": [ + { + "name": "$XSAPPNAME.JobRead", + "description": "Read job data", + "grant-as-authority-to-apps": ["$XSSERVICENAME([JOBSCHEDULER_INSTANCE])"] + }, + { + "name": "$XSAPPNAME.JobWrite", + "description": "Write job data", + "grant-as-authority-to-apps": ["$XSSERVICENAME([JOBSCHEDULER_INSTANCE])"] + } + ] + }, + + "_multitenant_example": { + "_comment": "For multitenant applications", + "tenant-mode": "shared", + "scopes": [ + { + "name": "$XSAPPNAME.JOBSCHEDULER", + "description": "Job Scheduler Scope", + "grant-as-authority-to-apps": ["$XSSERVICENAME([JOBSCHEDULER_INSTANCE])"] + }, + { + "name": "$XSAPPNAME.Callback", + "description": "Tenant callback scope", + "grant-as-authority-to-apps": ["sap-provisioning"] + } + ] + }, + + "_variable_reference": { + "$XSAPPNAME": "Resolves to the value of xsappname field", + "$XSSERVICENAME(name)": "Resolves to the service instance identifier" + } +}