一键导入
new-controller
Create a new ORC controller for an OpenStack resource. Use when adding support for a new OpenStack resource type (e.g., LoadBalancer, FloatingIP).
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Create a new ORC controller for an OpenStack resource. Use when adding support for a new OpenStack resource type (e.g., LoadBalancer, FloatingIP).
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Review ORC controller code for Kubernetes best practices and ORC conventions. Use after implementing or modifying a controller.
Add a dependency on another ORC resource to a controller. Use when a resource needs to reference or wait for another resource (e.g., Subnet depends on Network).
Write an enhancement proposal for a new ORC feature. Use for significant new features, breaking changes, or cross-cutting architectural changes.
Run ORC tests (unit tests, linting, and E2E tests). Use after making changes to verify correctness.
Update an existing ORC controller. Use when adding fields, making fields mutable, adding tag support, or improving error handling.
Draft release notes for a new ORC version. Use when preparing a release to generate changelog and GitHub release body from git history.
| name | new-controller |
| description | Create a new ORC controller for an OpenStack resource. Use when adding support for a new OpenStack resource type (e.g., LoadBalancer, FloatingIP). |
| disable-model-invocation | true |
Create a new ORC controller for an OpenStack resource.
IMPORTANT: Complete ALL steps in order. Do not stop after implementing TODOs - you must also write E2E tests and run them. Ask the user for E2E_OSCLOUDS path if needed to run tests.
Ask the user one by one about:
E2E_OSCLOUDS path to a clouds.yaml for running E2E tests locally? (If not, local E2E testing will be skipped)Before scaffolding, research the resource to understand the exact field names:
go doc <gophercloud-module>.<Type>
go doc <gophercloud-module>.CreateOpts
Look at a similar existing controller for patterns (if user provided one):
*_types.go for API structureactuator.go for implementation patternsNote the exact field names from gophercloud - use these when defining API types:
VipSubnetID, name the ORC field VipSubnetRef (not just SubnetRef)FlavorID, name the ORC field FlavorRefVip, Source, Destination etc.IMPORTANT: Build a single scaffolding command using the user's answers and the flags reference below. Run it exactly ONCE (user will be prompted to approve).
Use the field names discovered in Step 1 to inform your implementation later.
Required flags:
| Flag | Description | Example |
|---|---|---|
-kind | The Kind of the new resource (PascalCase) | VolumeBackup, FloatingIP |
-gophercloud-client | The gophercloud function to instantiate a client | NewBlockStorageV3, NewNetworkV2 |
-gophercloud-module | Full gophercloud module import path | github.com/gophercloud/gophercloud/v2/openstack/blockstorage/v3/backups |
Optional flags:
| Flag | Description | Default |
|---|---|---|
-gophercloud-type | The gophercloud struct type name | Same as -kind |
-openstack-json-object | Object name in OpenStack JSON responses | snake_case of kind (e.g., volume_backup) |
-available-polling-period | Polling period in seconds while waiting for resource to become available | 0 (available immediately) |
-deleting-polling-period | Polling period in seconds while waiting for resource to be deleted | 0 (deleted immediately) |
-required-create-dependency | Required dependency for creation (can repeat flag for multiple) | none |
-optional-create-dependency | Optional dependency for creation (can repeat flag for multiple) | none |
-import-dependency | Dependency for import filter (can repeat flag for multiple) | none |
-interactive | Run in interactive mode | true (set to false for scripted use) |
| Service | Client Function | Module Path Prefix |
|---|---|---|
| Compute | NewComputeV2 | github.com/gophercloud/gophercloud/v2/openstack/compute/v2/... |
| Network | NewNetworkV2 | github.com/gophercloud/gophercloud/v2/openstack/networking/v2/... |
| Block Storage | NewBlockStorageV3 | github.com/gophercloud/gophercloud/v2/openstack/blockstorage/v3/... |
| Identity | NewIdentityV3 | github.com/gophercloud/gophercloud/v2/openstack/identity/v3/... |
| Image | NewImageV2 | github.com/gophercloud/gophercloud/v2/openstack/image/v2/... |
# Example with dependencies - adapt based on user's answers
go run ./cmd/scaffold-controller -interactive=false \
-kind=Port \
-gophercloud-client=NewNetworkV2 \
-gophercloud-module=github.com/gophercloud/gophercloud/v2/openstack/networking/v2/ports \
-required-create-dependency=Network \
-optional-create-dependency=Subnet \
-optional-create-dependency=SecurityGroup \
-import-dependency=Network
After scaffolding completes, run code generation:
make generate
Commit the scaffolding with the command used:
git add .
git commit -m "$(cat <<'EOF'
Scaffolding for the VolumeBackup controller
$ go run ./cmd/scaffold-controller -interactive=false \
-kind=VolumeBackup \
-gophercloud-client=NewBlockStorageV3 \
-gophercloud-module=github.com/gophercloud/gophercloud/v2/openstack/blockstorage/v3/backups
EOF
)"
Add the new resource to cmd/resource-generator/main.go in the resources slice:
var resources []templateFields = []templateFields{
// ... existing resources (keep alphabetically sorted) ...
{
Name: "VolumeBackup",
},
}
Then regenerate to create the zz_generated.*.go files:
make generate
Update these files in internal/scope/:
Add interface method:
NewYourResourceClient() (osclients.YourResourceClient, error)
Implement the constructor:
func (s *providerScope) NewYourResourceClient() (osclients.YourResourceClient, error) {
return osclients.NewYourResourceClient(s.provider)
}
Add mock client field and implementation for testing.
Add to cmd/manager/main.go:
import (
yourresourcecontroller "github.com/k-orc/openstack-resource-controller/v2/internal/controllers/yourresource"
)
// In controllers slice:
controllers := []interfaces.Controller{
// ...
yourresourcecontroller.New(scopeFactory),
}
Reference Documentation: For detailed patterns and rationale, see:
website/docs/development/controller-implementation.md - Progressing condition, ReconcileStatus, error handling, dependencieswebsite/docs/development/api-design.md - Filter, ResourceSpec, ResourceStatus conventionswebsite/docs/development/coding-standards.md - Code organization, naming, loggingFind all scaffolding TODOs:
grep -r "TODO(scaffolding)" api/v1alpha1/ internal/controllers/<kind>/
Use the exact field names from gophercloud discovered in Step 1.
Define:
<Kind>ResourceSpec - Creation parameters with validation markers<Kind>Filter - Import filter with MinProperties:=1<Kind>ResourceStatus - Observed state fieldsImplement:
CreateResource() - Build CreateOpts, call OpenStack APIDeleteResource() - Call delete APIListOSResourcesForImport() - Apply filter to list resultsListOSResourcesForAdoption() - Match by spec fieldsGetResourceReconcilers() - (if resource supports updates)ReconcileResourceActuator is optional: The generic reconciler detects it via type assertion at runtime — there is no factory method to implement. To opt in, add the reconcileResourceActuator type alias and interface assertion in actuator.go, then implement GetResourceReconcilers on the actuator struct:
type (
reconcileResourceActuator = interfaces.ReconcileResourceActuator[orcObjectPT, osResourceT]
resourceReconciler = interfaces.ResourceReconciler[orcObjectPT, osResourceT]
)
var _ reconcileResourceActuator = myActuator{}
func (actuator myActuator) GetResourceReconcilers(ctx context.Context, orcObject orcObjectPT, osResource *osResourceT, controller interfaces.ResourceController) ([]resourceReconciler, progress.ReconcileStatus) {
return []resourceReconciler{
actuator.updateResource,
}, nil
}
If the resource is fully immutable (no mutable fields, no tags, no sub-resources), skip this entirely — the generic reconciler will not call it.
Follow the patterns in patterns.md when implementing the actuator and API types.
Implement:
ResourceAvailableStatus() - When is resource available?ApplyResourceStatus() - Map OpenStack fields to statusThis step is required - do not skip it.
Complete the scaffolded API validation test in test/apivalidations/<kind>_test.go by adding tests for any resource-specific validations (enums, numeric ranges, tag uniqueness, format validation, cross-field rules). Look for TODO(scaffolding) markers in the generated file.
Complete the E2E test stubs in internal/controllers/<kind>/tests/ and run tests following testing
make generate runmake generate run (creates zz_generated files)make generate runs cleanlymake lint passesmake test passes