Inside Activate
...
How To
CustomScript Design Best Practices
16 min
customscripts allow activate services to integrate with external systems during provisioning when services are processed immediately, scripts often run within the context of the original request however, when services are processed on a future effective date, the execution context changes this guide explains how customscripts are executed in activate, why effective dated services behave differently, and how to design scripts that work reliably in all scenarios purpose this document provides guidance on writing customscripts that are safe to use with effective dated services system initiated provisioning reprocessing and retries it highlights common design mistakes and provides clear guidance to prevent them how customscripts are executed when a service is provisioned, activate invokes any customscript defined on the service parameters the script is called by activate orchestrator using the current serviceinstance as the execution context example invocation object r = provisioningsystem evaluator scriptengine call( this, service getparameters("script"), "create", new object\[] { this } ); in this call this represents the current serviceinstance the create, update, or delete method receives the serviceinstance as an argument the serviceinstance represents the service being provisioned and contains the data required to perform provisioning actions effective dated services and job context when a service has a future effective date, it is not processed immediately instead, activate orchestrator processes it automatically on the effective date using a system generated job this is expected behaviour key implications the job executing the service is not the original user initiated job user request payloads are not available on the job job arguments may be empty or system generated effective dated services always run under a system job when processed by activate orchestrator common design pitfalls relying on job context for service data a common mistake is writing customscripts that extract provisioning data from the job context example of incorrect usage string userprincipalname = job arguments getstring("=//job/services/instance/0/user\[userprincipalname]"); this approach may appear to work when the service is processed immediately the script runs in the same job that captured the request however, it fails when the service is processed on its effective date the service is reprocessed the service runs under a system job in these cases, the expected data is no longer present on the job referencing serviceinstances by index another error prone pattern is referencing serviceinstances by position within a job, for example \=//job/services/instance/0 this is unsafe because a job may contain multiple serviceinstances the order of services in the job is not guaranteed the service being processed may not be at the expected index this can result in scripts reading data from the wrong service instance serviceinstances should never be identified by index within a job correct data access pattern customscripts must retrieve all required data from the serviceinstance or related objects, not from the job recommended examples string userprincipalname = srv user userprincipalname; string role = evaluator getstring(srv, "=/data/role"); why this works the serviceinstance reflects the current state of the service service data is populated consistently regardless of job type the script behaves the same for immediate and effective dated processing the serviceinstance is the authoritative source of provisioning data for customscripts using srv job (with caution) the serviceinstance provides a reference to the most recent job that processed or otherwise interacted with it via srv job this can be useful for diagnostic logging correlation identifiers advanced scenarios where job metadata is explicitly required however, this reference must be used sparingly a service may be reprocessed updated evaluated included in background or system jobs as a result, srv job may not represent the original request or the job you expect if data logically belongs to the service, retrieve it from the serviceinstance rather than from srv job why scripts may appear not to run when a customscript relies on job data, failures can be misleading from an operator’s perspective, it may appear that the script did not run the customscript was skipped in reality the script was executed required data was missing internal logic did not complete as expected early return statements can further obscure this behaviour by preventing later logic and logging from executing best practices for customscript design follow these guidelines when authoring customscripts always use the serviceinstance (srv) for service related data avoid referencing job arguments for provisioning logic never identify serviceinstances by index within a job use srv job only when job metadata is explicitly required assume scripts may run under system jobs design scripts to be idempotent where possible avoid early return statements that bypass core logic log clearly when required service data is missing customscript rules of thumb use these rules as a quick check when writing or reviewing customscripts data ownership if the data belongs to the service, read it from the serviceinstance if the data belongs to the user, read it from srv user if the data belongs to the job, question whether you really need it most customscripts should not need to read from the job at all job usage do not rely on job arguments for provisioning logic expect services to run under system jobs, not user initiated jobs use srv job only for logging, diagnostics, or correlation metadata never assume srv job represents the original request service identification never reference serviceinstances by index within a job do not assume a service is at position 0 or any fixed index always work with the serviceinstance passed into the script execution assumptions assume scripts may run on an effective date as part of reprocessing under background or system jobs write scripts that behave consistently regardless of execution context control flow and logging avoid early return statements that bypass core logic log clearly when required service data is missing prefer explicit validation over silent failure mental model the serviceinstance is the unit of provisioning jobs are an execution mechanism, not a data source scripts should describe what to do for this service, not how the request was submitted summary effective dated services are processed by activate orchestrator using system jobs this is expected and by design to ensure customscripts run reliably treat the serviceinstance as the authoritative source of service data avoid job based assumptions in script logic design scripts to function independently of how or when they are executed following these principles ensures consistent provisioning behaviour across immediate, scheduled, and system initiated service processing