This repository is the php-opencloud/openstack SDK: a PHP client for multiple OpenStack services. The public entry point is src/OpenStack.php, which creates versioned service objects through shared builder logic in src/Common/.
The project follows semantic versioning and still supports PHP ^7.2.5 || ^8.0. Keep changes narrowly scoped and avoid API breaks unless the task explicitly requires them.
src/Common/: shared API, resource, service, auth, error, JSON-schema, and transport infrastructure.<Service>/<version>/: versioned SDK surface for each OpenStack service. Most service folders contain:Api.php: declarative operation definitions (method,path,params, optionaljsonKey)Params.php: parameter schemas and wire-format metadataService.php: top-level user-facing service methodsModels/: resource classes with behavior and hydration rules
tests/unit/: mocked unit tests, usually mirroring thesrc/namespace layout.tests/sample/: integration-style tests that execute files fromsamples/.samples/: runnable examples; these double as integration-test inputs.doc/: Sphinx/reStructuredText documentation..github/workflows/: CI definitions for formatting, unit tests, and integration tests.
When adding or changing SDK functionality, preserve the existing layering:
- Define or update the REST operation in
Api.php. - Add or reuse parameter definitions in
Params.php. - Expose the behavior from
Service.phpif it is part of the top-level service API. - Implement resource behavior in
Models/*when the operation belongs on a model instance. - Add unit tests and, for user-facing flows, a sample plus sample test when practical.
Specific patterns used throughout the codebase:
Service.phpmethods are intentionally thin. They usually create a model, populate it, or delegate toenumerate(...).- Resource classes commonly extend
OpenStack\Common\Resource\OperatorResource, set$resourceKey,$resourcesKey, and$markerKey, and useexecute(...)pluspopulateFromResponse(...). - API field renames are handled with
$aliasesandAliasobjects instead of ad hoc mapping code. - Operation option arrays are documented with
{@see \Namespace\Api::methodName}docblocks. Keep those references accurate when signatures change. - Reuse shared abstractions in
src/Common/before introducing service-specific helpers.
The SDK is tested against PHP 7.2 through 8.4 in CI. Do not introduce syntax or standard-library dependencies that require newer PHP versions than 7.2.5.
In practice, avoid:
- union types
- attributes
- constructor property promotion
- enums
matchreadonly- typed properties
- named arguments in code examples or tests
Follow the surrounding file for declare(strict_types=1);. Many src/ files use it, but not every file in the repository does.
There are no Composer scripts in this repository; run tools directly from vendor/bin.
Primary local checks:
composer install
vendor/bin/parallel-lint --exclude vendor .
vendor/bin/phpunit --configuration phpunit.xml.dist
vendor/bin/php-cs-fixer fix --dry-run --diffAdditional checks when relevant:
composer normalize
vendor/bin/phpunit --configuration phpunit.sample.xml.distNotes:
- CI runs unit tests against both lowest and highest dependency sets, so avoid relying on the latest transitive behavior only.
- Integration tests require a live OpenStack environment, the environment variables from
env_test.sh.dist, and an image namedcirros. php-cs-fixeris configured forsrc/,samples/, and.php-cs-fixer.dist.php; tests are not auto-formatted by that config, so keep test edits manually consistent with surrounding code.
Unit tests usually extend tests/unit/TestCase.php.
Follow the existing test style:
- set
rootFixturesDirinsetUp()when the test uses fixture responses - use
mockRequest(...)to assert HTTP method, path, body, headers, and returned response - store larger or realistic HTTP responses as
.respfiles under a nearbyFixtures/directory - mirror the production namespace and folder layout where possible
Prefer adding focused tests around the exact operation being changed instead of broad cross-service rewrites.
samples/ are executable examples and are also exercised by tests/sample/. When you add a new user-facing capability, consider whether it should have:
- a sample under the matching service/version folder in
samples/ - a corresponding sample test under
tests/sample/ - documentation in
doc/services/if the feature is part of the supported public workflow
All code snippets used in the docs must live in samples/ rather than being maintained only inline in .rst files, and they must be covered by the sample test suite.
Sample tests typically create a temporary PHP file from a template and require_once it, so keep samples self-contained and readable.
When adding sample tests, prefer reusing resources created earlier in the same test file instead of provisioning duplicate ones. In practice, testCreate should return the created resource, dependent tests should consume it via @depends, and cleanup should happen in the final testDelete.
User docs live in doc/ and use Sphinx plus reStructuredText. If a change affects public behavior, examples, or supported options, update docs as needed.
Typical doc build:
pip install -r doc/requirements.txt
make -C doc html- Prefer small, service-scoped changes over broad refactors.
- Preserve public method names and option shapes unless the task explicitly calls for a breaking change.
- Keep docblocks accurate for public APIs and option arrays.
- Reuse existing fixtures, sample patterns, and helper methods before inventing new ones.
- If
composer.jsonchanges, runcomposer normalizebecause CI auto-normalizes that file.