{"id":27202533,"url":"https://github.com/rhpds/poolboy","last_synced_at":"2025-09-06T18:41:13.385Z","repository":{"id":42445137,"uuid":"197657177","full_name":"rhpds/poolboy","owner":"rhpds","description":"Operator for managing resource claims and provisioning","archived":false,"fork":false,"pushed_at":"2025-08-29T14:59:39.000Z","size":3030,"stargazers_count":11,"open_issues_count":12,"forks_count":10,"subscribers_count":8,"default_branch":"main","last_synced_at":"2025-09-01T06:01:28.990Z","etag":null,"topics":["babylon","gpte"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rhpds.png","metadata":{"files":{"readme":"README.adoc","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2019-07-18T21:07:21.000Z","updated_at":"2025-08-29T14:58:42.000Z","dependencies_parsed_at":"2023-02-02T20:46:20.418Z","dependency_job_id":"613a1f1f-4784-45a9-bac1-a3c18b66ee34","html_url":"https://github.com/rhpds/poolboy","commit_stats":null,"previous_names":["rhpds/poolboy"],"tags_count":104,"template":false,"template_full_name":null,"purl":"pkg:github/rhpds/poolboy","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rhpds%2Fpoolboy","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rhpds%2Fpoolboy/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rhpds%2Fpoolboy/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rhpds%2Fpoolboy/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rhpds","download_url":"https://codeload.github.com/rhpds/poolboy/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rhpds%2Fpoolboy/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":273947585,"owners_count":25196391,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-06T02:00:13.247Z","response_time":2576,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["babylon","gpte"],"created_at":"2025-04-09T22:00:31.413Z","updated_at":"2025-09-06T18:41:13.334Z","avatar_url":"https://github.com/rhpds.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"= Poolboy\n\nimage::docs/poolboy.png[Poolboy Icon,200,200]\n\nPoolboy provides a structure to manage OpenShift resources by allowing users to request resources which are then satisfied by resource providers and from pre-provisioned resource pools.\nThis allows for users to manage resources in a cluster for which they do not have direct access through Kubernetes role-based access controls.\n\n== Poolboy Operation\n\nimage::docs/diagram.png[Poolboy Diagram,500,400]\n\n=== ResourceClaim Creation\n\n. User creates a ResourceClaim which contain a list of resource templates to defines desired resources.\n. The ResourceClaim is matched to a ResourceProvider.\n. The ResourceClaim's resource templates are updated with defaults as defined by the ResourceProvider.\n. Each resource template in the ResourceClaim is checked for validity against the OpenAPIv3 schema in the ResourceProvider.\n. A ResourceHandle from a ResourcePool is matched to the ResourceClaim or a new ResourceHandle is created to satisfy the claim:\n.. To match an existing ResourceHandle each resource template in the ResourceClaim must match the ResourceHandle, excepting any fields specified in the ResourceProvider's `spec.matchIgnore`.\n.. If created automatically, the ResourceHandle resource templates will be copied from the ResourceClaim.\n\n=== ResourceClaim Update\n\n. User updates an existing ResourceClaim\n. Each resource template in the ResourceClaim is checked for validity against the OpenAPIv3 schema in the ResourceProvider.\n. A JSON Patch for each resource template in the ResourceHandle is generated and then the JSON Patch is filtered according to each ResourceProvider's `spec.updateFilters`.\n. Updates are applied to the ResourceHandle.\n\n=== ResourceHandle Creation or Update\n\n. For each resource template in the ResourceHandle a resource definition is generated.\n.. ResourceProvider `spec.override` is applied to each resource template.\n.. The `metadata.name` is determined for each templated resource to match the random suffix appended to ResourceHandle.\n. Create or update the resource\n.. If the resource does not exist, it is created.\n.. If the resource exists then it is updated.\n.. The state of the resource is copied into the ResourceClaim status if a ResourceClaim is bound to the ResourceHandle.\n\n=== Templating\n\nTemplates are supported for ResourceProviders to supply defaults for ResourceClaims and for overrides for resources.\nTemplates are enable for a ResourceProvider by specifying `spec.template.enable` on the ResourceProvider.\nTemplates use https://jinja.palletsprojects.com/en/2.11.x/[Jinja2].\n\nFor ResourceClaim defaults templates may reference:\n\n* `resource_claim` - ResourceClaim object\n* `resource_index` - Resource index in the ResourceClaim `spec.resources`\n* `resource_provider` - ResourceProvider object\n\nFor resource overrides templates may reference:\n\n* `resource_claim` - ResourceClaim object if a ResourceClaim is bound\n* `resource_handle` - ResourceHandle object\n* `resource_index` - Resource index in the ResourceHandle `spec.resources`\n* `resource_provider` - ResourceProvider object\n* `resource_template` - Resource template from ResourceHandle\n* `requester_identity` - OpenShift identity of requester determined from ResourceClaim namespace's `openshift.io/requester` annotation\n* `requester_user` - OpenShift user of requester determined from ResourceClaim namespace's `openshift.io/requester`  annotation\n\nNormally Poolboy creates resources from ResourcePools as soon as the ResourceHandle is created.\nIf the resource needs to reference `resource_claim` then the ResourceProvider may specify `spec.resourceRequiresClaim` to delay resource creation until the ResourceHandle is bound by a ResourceClaim.\n\nAdditionally templates may make use of variables `timestamp` and `timedelta` for date and time calculations.\nExamples:\n\n* `timestamp(\"2021-05-01T12:30:00Z\")` - Parsed timestamp\n* `timestamp(\"2021-05-01T12:30:00Z\").add(\"3h\")` - Interval from parsed timestamp\n* `timestamp.utcnow` - Current UTC timestamp in `%Y-%m-%dT%H:%M:%SZ` format\n* `timestamp.utcnow.add(\"1d\")` - UTC timestamp for this time tomorrow\n* `timestamp.utcnow.datetime` - Python datetime object for UTC now\n* `timedelta(\"10m\")` - Representation of time delta for ten minutes.\n* `timedelta(\"10m\").timedelta` - Python datetime timedelta\n\n=== Lifespan\n\nBy default no lifespan policy is applied to Poolboy resources.\n\nLifespan is configured in ResourceHandles by specifying:\n\n* `default` - Default lifespan to apply to ResourceHandle when it is claimed.\n\n* `maximum` - Maximum lifespan which may be requested in the ResourceClaim calculated from the ResourceClaim the creation timestamp.\n\n* `relativeMaximum` - Maximum lifespan which can be requested in the ResourceClaim relative to the present datetime.\n\nIf both `maximum` and `relativeMaximum` are specified then the effective maximum is whichever is earlier.\nThe calculated lifespan end set in the ResourceHandle lifespan.\n\nThe ResourceClaim can specify a lifespan end which will propagate to the ResourceHandle so long as it is within the maximum limits.\n\nResourcePools can specify lifespan configuration for resource handles they create.\nIn addition to `default`, `maximum`, and `relativeMaximum` the ResourcePool can specify `unclaimed` to specify the lifespan of unclaimed ResourceHandles in the pool.\n\nResourceHandles created dynamically for ResourceClaims get their lifespan configuration from the ResourceProviders.\nIf multiple ResourceProviders are used for a ResourceClaim then the minimum of each of the lifespan configuration options is applied to the ResourceHandle.\n\n== Use Case - Project Babylon Anarchy Operator\n\nPoolboy was designed to manage custom resource types for the\nhttps://github.com/redhat-cop/anarchy[Anarchy operator framework].\nThe Anarchy Operator orchestrates API calls, tracking the state of remote resources in custom resource kinds.\nAs part of Project Babylon, Anarchy is configured to manage cloud resources and environments.\nPoolboy allows for these cloud environments to be pre-provisioned and then claimed by users.\n\nIn Anarchy a cloud environment is represented by the AnarchySubject custom resource kind.\n\n=== Pre-Provisioned Environments\n\nResourcePools allow AnarychSubjects to be pre-created.\nThe scale of a ResourcePool can be adjusted to add or reduce capacity based on expected demand.\nResourceProvider validation and overrides allow for environments to be created on demand while retaining control on what environments can be requested.\n\n=== User Management of Environments\n\nBecause the resource status is monitored and synced to the ResourceClaim status, users are able to track the state of their provisioned environments.\n\nEach AnarchySubject has a `spec.desiredState`. The ResourceProvider `spec.updateFilters` allow this field to be updated while the `spec.validation` OpenAPIv3 check enforces that it can only be set to explicitly permitted values.\n\n== Installation\n\n=== Poolboy Install\n\nInstall from helm template:\n\n----\nhelm template poolboy helm/ | oc apply -f -\n----\n\n== Build\n\n=== OpenShift Build\n\n. Process OpenShift build template to create BuildConfig and ImageStream\n+\n----\noc process --local -f build-template.yaml | oc apply -n poolboy -f -\n----\n\n. Build poolboy image\n+\n----\noc start-build poolboy -n poolboy --from-dir=. --follow\n----\n\n. Deploy Poolboy from build image\n+\n----\nhelm template poolboy helm/ \\\n--set=image.tagOverride=- \\\n--set=image.repository=$(oc get imagestream poolboy -o jsonpath='{.status.tags[?(@.tag==\"latest\")].items[0].dockerImageReference}') \\\n| oc apply -f -\n----\n\n== Credits\n\nPoolboy logo is original art by Lara Ditkoff\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frhpds%2Fpoolboy","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frhpds%2Fpoolboy","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frhpds%2Fpoolboy/lists"}