SwiftContainer: add controller#824
Conversation
winiciusallan
left a comment
There was a problem hiding this comment.
Hey @eshulman2, thanks for the PR!
I did a round of review through the API and left other comments inline. Will take some time to look how CRUD operations are being performed and the tests :).
| // comma-separated list of account/container combinations. | ||
| // +kubebuilder:validation:MaxLength:=256 | ||
| // +optional | ||
| ContainerWrite *string `json:"containerWrite,omitempty"` |
| } | ||
|
|
||
| // SwiftContainerResourceSpec contains the desired state of a Swift container. | ||
| type SwiftContainerResourceSpec struct { |
There was a problem hiding this comment.
There are other fields that we could implement in the ResourceSpec, but I'm okay leaving as it is and add them later.
2fb1881 to
c85a5da
Compare
Scaffold the SwiftContainer controller using the controller generator: $ go run ./cmd/scaffold-controller -interactive=false -kind=SwiftContainer -gophercloud-client=NewObjectStorageV1 -gophercloud-module=github.com/gophercloud/gophercloud/v2/openstack/objectstorage/v1/containers -gophercloud-type=Container -openstack-json-object=container
Add the SwiftContainer API, generated clients, OpenStack client wrapper, controller wiring, status writer, and reconciliation logic. Swift containers are name-addressed, so the controller uses the container name as the ORC status ID and adds custom import handling for name-based imports.
Add unit coverage for Swift container import, adoption, creation, validation, and OpenStack client behavior. Add KUTTL suites for minimal and full creation, import success and failure, updates, and name validation, and enable Swift in the E2E environment.
Document SwiftContainer in the resource matrix and generated CRD reference, and add example manifests for create and import workflows.
222add3 to
ab62b5d
Compare
| // and 256 characters long and must not contain forward slashes. | ||
| // +kubebuilder:validation:MinLength:=1 | ||
| // +kubebuilder:validation:MaxLength:=256 | ||
| // +kubebuilder:validation:Pattern:=`^[^/]+$` |
There was a problem hiding this comment.
What do you think of adding a XValidation here instead of a Pattern so we can return a clear message to the user? Something like:
// +kubebuilder:validation:XValidation:rule="self.matches('^[^/]+$')",message="names must no contain forward slashes"| createOpts := containers.CreateOpts{} | ||
|
|
||
| if resource.ContainerRead != "" { | ||
| createOpts.ContainerRead = resource.ContainerRead | ||
| } | ||
| if resource.ContainerWrite != "" { | ||
| createOpts.ContainerWrite = resource.ContainerWrite | ||
| } | ||
| if resource.StoragePolicy != "" { | ||
| createOpts.StoragePolicy = resource.StoragePolicy | ||
| } |
There was a problem hiding this comment.
I think we can extract this code to the following
| createOpts := containers.CreateOpts{} | |
| if resource.ContainerRead != "" { | |
| createOpts.ContainerRead = resource.ContainerRead | |
| } | |
| if resource.ContainerWrite != "" { | |
| createOpts.ContainerWrite = resource.ContainerWrite | |
| } | |
| if resource.StoragePolicy != "" { | |
| createOpts.StoragePolicy = resource.StoragePolicy | |
| } | |
| createOpts := containers.CreateOpts{ | |
| ContainerRead: resource.ContainerRead | |
| ContainerWrite: resource.ContainerWrite | |
| StoragePolicy: resource.StoragePolicy | |
| } |
If the field is an empty string, it won't be parsed into a map in Gophercloud.
https://github.com/gophercloud/gophercloud/blob/main/params.go#L495
| // that when specifying an import by name, the resource MUST already exist. | ||
| // The ORC object will enter an error state if the resource does not exist. | ||
| // +optional | ||
| Name *SwiftContainerName `json:"name,omitempty"` |
There was a problem hiding this comment.
Would you mind explain what is the difference between this Name here (spec.import.name) and in spec.import.filter.name?
There was a problem hiding this comment.
I believe this file is useless for us since we have committed this directory with changes.
| // Swift treats '/' as a path separator in container names, making the name | ||
| // invalid at the API level. Validate explicitly to provide a clear error | ||
| // message rather than a confusing HTTP error from gophercloud. | ||
| if strings.Contains(name, "/") { | ||
| return nil, progress.WrapError( | ||
| orcerrors.Terminal(orcv1alpha1.ConditionReasonInvalidConfiguration, | ||
| "container name must not contain forward slashes")) | ||
| } |
There was a problem hiding this comment.
I believe this is already caught by the CEL validation in the API.
| // MaxLength:=256 marker counts Unicode code points, not bytes, so a name | ||
| // with multi-byte UTF-8 characters can pass API validation yet exceed the | ||
| // byte limit. Validate explicitly here to produce a clear error message. | ||
| if len(name) > 256 { |
There was a problem hiding this comment.
The same as the above validation.
| that the observed state corresponds to the spec. | ||
|
|
||
| Also validate that the OpenStack resource uses the name of the ORC object when | ||
| `spec.resource.name` is not specified (SC-001). |
There was a problem hiding this comment.
I believe this is a downstream reference
| `spec.resource.name` is not specified (SC-001). | |
| `spec.resource.name` is not specified. |
| metadata: | ||
| name: swiftcontainer-create-minimal | ||
| status: | ||
| resource: |
There was a problem hiding this comment.
We're missing storagePolicy here. IIRC, a fresh devstack install use Policy-0 when no default policy is configured.
|
|
||
| Validates that: | ||
| - The OpenStack resource uses the name from `spec.resource.name` when it is | ||
| specified, rather than the ORC object name (SC-002). |
There was a problem hiding this comment.
Downstream reference
| specified, rather than the ORC object name (SC-002). | |
| specified, rather than the ORC object name. |
| - The import filter matches the container with exact name (not a superstring). | ||
| - `status.id` is populated with the imported container name. | ||
| - Adoption from unmanaged import to available state works without recreating | ||
| the container (SC-003). |
There was a problem hiding this comment.
From my search I think this is the last one :)
| the container (SC-003). | |
| the container. |
Summary