Add flavor extra_specs#817
Conversation
d67e89a to
8de585f
Compare
eshulman2
left a comment
There was a problem hiding this comment.
Thanks for the PR, generally LGTM except for the missing interface aliases.
| return deletes | ||
| } | ||
|
|
||
| func (actuator flavorActuator) GetResourceReconcilers(ctx context.Context, orcObject orcObjectPT, osResource *osResourceT, controller generic.ResourceController) ([]resourceReconciler, progress.ReconcileStatus) { |
There was a problem hiding this comment.
flavorActuator now implements ReconcileResourceActuator via GetResourceReconcilers, but the type alias and compile-time assertion are missing. Compare securitygroup/actuator.go which has:
reconcileResourceActuator = interfaces.ReconcileResourceActuator[orcObjectPT, orcObjectT, osResourceT]
// ...
var _ reconcileResourceActuator = securityGroupActuator{}The resourceReconciler alias was added, but reconcileResourceActuator wasn't. Please add:
reconcileResourceActuator = generic.ReconcileResourceActuator[orcObjectPT, orcObjectT, osResourceT]var _ reconcileResourceActuator = flavorActuator{}There was a problem hiding this comment.
To be fair, this was not a big problem. This compile-time assertions are there to help developers and provide quicker feedback loop to ensure the actuator satisfies the interface. It has no functional use.
| } | ||
| } | ||
|
|
||
| func TestExtraSpecUpdates(t *testing.T) { |
There was a problem hiding this comment.
Nice to have: would be great to add a test covering the entire logic of the update function eg. what happens if update succeed but delete fails, etc
| // +kubebuilder:validation:MaxItems:=128 | ||
| // +listType=atomic | ||
| // +optional | ||
| ExtraSpecs []ExtraSpec `json:"extraSpecs,omitempty"` |
There was a problem hiding this comment.
The []ExtraSpec slice has no uniqueness constraint on name. If a user specifies the same name twice, extraSpecsToMap silently uses the last value - no error or warning at admission time.
A CEL validation rule on the field would catch this at admission time:
// +kubebuilder:validation:XValidation:rule="self.all(x, self.filter(y, y.name == x.name).size() == 1)",message="extraSpecs names must be unique"
ExtraSpecs []ExtraSpec `json:"extraSpecs,omitempty"`There was a problem hiding this comment.
Thinking about it, we should probably change the the list type to map.
// extraSpecs is a map of key-value pairs that define extra specifications for the flavor.
// +kubebuilder:validation:MaxItems:=128
// +listType=map
// +listMapKey=name
// +optional
ExtraSpecs []ExtraSpec `json:"extraSpecs,omitempty"`| // +listType=atomic | ||
| // +optional | ||
| ExtraSpecs []VolumeTypeExtraSpec `json:"extraSpecs,omitempty"` | ||
| ExtraSpecs []ExtraSpec `json:"extraSpecs,omitempty"` |
There was a problem hiding this comment.
same as above:
The []ExtraSpec slice has no uniqueness constraint on name. If a user specifies the same name twice, extraSpecsToMap silently uses the last value - no error or warning at admission time.
A CEL validation rule on the field would catch this at admission time:
// +kubebuilder:validation:XValidation:rule="self.all(x, self.filter(y, y.name == x.name).size() == 1)",message="extraSpecs names must be unique"
ExtraSpecs []ExtraSpec `json:"extraSpecs,omitempty"`There was a problem hiding this comment.
There too, this should be change to a map list type, but this should be done in a separate PR.
We'll still need to revert the changes and keep the VolumeTypeExtraSpec type.
8de585f to
597bac6
Compare
Thank you for the review, I added everything requested |
|
@mandre can you please approve the workflow, then I'll re-review |
|
@chess-knight apologies for the lack of input on your PR, I was quite busy lately. I'll review very soon, stay tuned. |
mandre
left a comment
There was a problem hiding this comment.
Oof, this was much more work than I originally expected due to the fact this is actually a separate API call. There are a few critical changes we need to make (use a separate FlavorExtraSpecs stuct, and drop the change from CreateResource) before we can merge.
| // description contains a free form description of the flavor. | ||
| // +kubebuilder:validation:MinLength:=1 | ||
| // +kubebuilder:validation:MaxLength:=65535 | ||
| // +kubebuilder:validation:XValidation:rule="self == oldSelf",message="description is immutable" |
There was a problem hiding this comment.
Just noting that the description should in theory be mutable (https://docs.openstack.org/api-ref/compute/#update-flavor-description) but this is clearly out of scope for this PR.
There was a problem hiding this comment.
Yes, I know about mutable description, but as you said i didn't want to change it with this PR.
| if len(resource.ExtraSpecs) > 0 { | ||
| extraSpecs := extraSpecsToMap(resource.ExtraSpecs) | ||
|
|
||
| _, err = actuator.osClient.CreateFlavorExtraSpecs(ctx, osResource.ID, flavors.ExtraSpecsOpts(extraSpecs)) |
There was a problem hiding this comment.
We can't create the extra spec in CreateResource because this is a different API call that might fail. This should be handled in a separate reconciliation, and we should rely on updateResource instead (or better even, call it reconcileExtraSpecs).
| // +kubebuilder:validation:MaxLength:=64 | ||
| type KeystoneName string | ||
|
|
||
| type ExtraSpec struct { |
There was a problem hiding this comment.
I'm unsure about making the ExtraSpec a common type. The different projects might enforce different rules.
For instance, nova allows spaces in flavors extraspec keys while cinder does not for volumetypes extraspec keys.
BTW, we should add CEL validations for those.
There was a problem hiding this comment.
Should we add this validations as part of this PR? or we will be fine with MaxLength:=255 for now
There was a problem hiding this comment.
In this PR please. We'll tighten up the validation for the volumetype in a separate PR.
| // +kubebuilder:validation:MaxItems:=128 | ||
| // +listType=atomic | ||
| // +optional | ||
| ExtraSpecs []ExtraSpec `json:"extraSpecs,omitempty"` |
There was a problem hiding this comment.
Thinking about it, we should probably change the the list type to map.
// extraSpecs is a map of key-value pairs that define extra specifications for the flavor.
// +kubebuilder:validation:MaxItems:=128
// +listType=map
// +listMapKey=name
// +optional
ExtraSpecs []ExtraSpec `json:"extraSpecs,omitempty"`| // +listType=atomic | ||
| // +optional | ||
| ExtraSpecs []VolumeTypeExtraSpec `json:"extraSpecs,omitempty"` | ||
| ExtraSpecs []ExtraSpec `json:"extraSpecs,omitempty"` |
There was a problem hiding this comment.
There too, this should be change to a map list type, but this should be done in a separate PR.
We'll still need to revert the changes and keep the VolumeTypeExtraSpec type.
| return progress.WrapError(actuator.osClient.DeleteFlavor(ctx, flavor.ID)) | ||
| } | ||
|
|
||
| func (actuator flavorActuator) updateResource(ctx context.Context, obj orcObjectPT, osResource *osResourceT) progress.ReconcileStatus { |
There was a problem hiding this comment.
Let's rename this function to reconcileExtraSpecs, as this is a single concern reconciler.
| } | ||
|
|
||
| if len(updates) > 0 { | ||
| _, err := actuator.osClient.CreateFlavorExtraSpecs( |
There was a problem hiding this comment.
OK, it seems (from the gophercloud comment at least) that nova does an upsert.
The nova doc doesn't state it explicitly.
597bac6 to
38b177f
Compare
mandre
left a comment
There was a problem hiding this comment.
Nice work! just a small nit, then I believe this is ready to merge.
| resource := obj.Spec.Resource | ||
| if resource == nil { | ||
| // Should have been caught by API validation | ||
| return progress.WrapError( |
There was a problem hiding this comment.
Let's just return nil in this case, this would be more consistent with other reconcile functions:
openstack-resource-controller/internal/controllers/trunk/actuator.go
Lines 307 to 309 in 9b8ee08
| "errors" | ||
| "fmt" | ||
| "iter" | ||
| reflect "reflect" |
There was a problem hiding this comment.
I'm surprised this isn't flagged by the linter.
| reflect "reflect" | |
| "reflect" |
|
|
||
| type FlavorExtraSpecStatus struct { | ||
| // name is the name of the extraspec | ||
| // +kubebuilder:validation:Pattern="^[a-zA-Z0-9-_:. ]+$" |
There was a problem hiding this comment.
We don't really care about enforcing a pattern on the status, we'll just return what OpenStack gives us. Not a big deal, though...
Signed-off-by: Roman Hros <roman.hros@dnation.cloud>
38b177f to
0b914d0
Compare
Add
Flavorextra_specs.Closes #738