Policy
Last updated
Last updated
The lunar_policy
Python package provides utilities for working with Lunar policies, allowing you to load, query, and make assertions about component metadata, such as the .
For the reference documentation check out:
The package is available through pip:
Earthly Lunar executes policies in an environment set up with the following variables:
LUNAR_HUB_HOST
: The host of the Lunar Hub.
LUNAR_HUB_INSECURE
: Whether to skip SSL verification of the Lunar Hub.
LUNAR_POLICY_NAME
: The name of the policy being executed.
LUNAR_INITIATIVE_NAME
: The name of the initiative the policy belongs to.
LUNAR_POLICY_OWNER
: The owner of the policy.
LUNAR_COMPONENT_ID
: The ID of the component being checked in github.com/.../...
format.
LUNAR_COMPONENT_DOMAIN
: The domain of the component.
LUNAR_COMPONENT_OWNER
: The owner of the component.
LUNAR_COMPONENT_PR
: The PR number of the component, if applicable.
LUNAR_COMPONENT_GIT_SHA
: The Git SHA of the component that the policy is being executed for.
LUNAR_COMPONENT_TAGS
: The tags of the component.
LUNAR_COMPONENT_META
: The metadata of the component as a JSON object.
Any secrets set in the Lunar Hub for the policy, via LUNAR_POLICY_SECRETS=<name>=<value>;...
.
The Policy SDK provides several key classes to help you write policies:
To execute a policy locally for testing purposes, you can use the lunar
CLI.
If you would like to use the real component JSON of one of your components, you can do so via the command:
Lunar makes a clear distinction between missing component JSON data and failing component JSON data. This is needed under the hood to be able to provide partial policy results while collectors are still running. Policies that have enough data will provide accurate results, while policies that don't have enough data will report a "no-data" status.
When some or all of the component JSON data required for assertions is not present, policies use the NoDataError
exception mechanism to report this status. The Check
API handles this scenario automatically by catching this exception in the with
context manager, setting the check status to "no-data".
When writing policies, you should:
Be aware that your policy might run against components where the expected data is not present
Know that the Check
context manager will catch NoDataError
exceptions and set the status to "no-data"
Multiple checks in the same block will continue to execute even if previous checks raise NoDataError
This approach ensures that policies don't incorrectly fail when run against components that legitimately don't have specific data (for example, because a collector has not had the chance to run yet).
Below are examples demonstrating different approaches to handling missing data in policies:
This approach incorrectly assumes all fields exist after retrieving an object, which can lead to errors when data is missing:
This approach explicitly raises NoData
when fields don't exist:
This approach uses targeted field access and relies on the Check API to handle missing data automatically:
Let's assume that we have the following policy:
Here's an example showing how to write unit tests:
You can run the test with:
The Check
class provides a fluent interface for making assertions about policy data. It tracks accessed data within the component JSON for traceability purposes. For detailed reference, see the .
The Path
class is used to pass JSONPath expressions to assertion methods of Check. For detailed reference, see the .
The ComponentData
class is used to initialize a Check
instance with component metadata from different sources. For detailed reference, see the .
The NoDataError
exception is used to indicate that required data for a policy check is missing. For detailed reference, see the .
When a policy is executed through Lunar Hub, Lunar passes in the relevant context via some environment variables. This context includes the for the component that is being checked. When you create a Check
instance, the library automatically loads this data under the hood.