diff --git a/.gitignore b/.gitignore
index e859277d7..d8a4b3110 100644
--- a/.gitignore
+++ b/.gitignore
@@ -42,3 +42,6 @@ __pycache__/
/bundle/
bundle.Dockerfile
+
+# Forge workflow state (do not commit)
+.forge/
diff --git a/api/v1alpha1/common_types.go b/api/v1alpha1/common_types.go
index 4afeb5fbb..e3d7d3f42 100644
--- a/api/v1alpha1/common_types.go
+++ b/api/v1alpha1/common_types.go
@@ -98,6 +98,18 @@ type NeutronStatusMetadata struct {
// +kubebuilder:validation:MaxLength:=253
type KubernetesNameRef string
+// CommonStatus defines status fields that are common to all ORC resources.
+type CommonStatus struct {
+ // lastSyncTime is the timestamp of the last successful reconciliation
+ // that fetched state from OpenStack. It is updated each time the
+ // controller successfully reads the resource state from the OpenStack
+ // API. It is not updated on reconciliations that do not contact
+ // OpenStack (e.g. when the object is being deleted and is waiting for
+ // dependents to be removed).
+ // +optional
+ LastSyncTime *metav1.Time `json:"lastSyncTime,omitempty"`
+}
+
// +kubebuilder:validation:MinLength:=1
// +kubebuilder:validation:MaxLength:=64
type KeystoneName string
diff --git a/api/v1alpha1/controller_options.go b/api/v1alpha1/controller_options.go
index d0908b10e..78dced2c4 100644
--- a/api/v1alpha1/controller_options.go
+++ b/api/v1alpha1/controller_options.go
@@ -16,6 +16,10 @@ limitations under the License.
package v1alpha1
+import (
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+)
+
// +kubebuilder:validation:Enum:=managed;unmanaged
type ManagementPolicy string
@@ -63,3 +67,24 @@ func (o *ManagedOptions) GetOnDelete() OnDelete {
}
return o.OnDelete
}
+
+// CommonOptions defines options which apply to all ORC objects regardless of
+// management policy.
+type CommonOptions struct {
+ // resyncPeriod defines how frequently the controller will re-reconcile this
+ // resource even when no changes have been detected. This implements a
+ // two-tier resolution: the per-resource value takes precedence over the
+ // global controller default; if neither is set, periodic resync is
+ // disabled. The value must be a valid Go duration string, e.g. "10m", "1h".
+ // +optional
+ ResyncPeriod *metav1.Duration `json:"resyncPeriod,omitempty"` //nolint:kubeapilinter // metav1.Duration is appropriate for user-facing duration config
+}
+
+// GetResyncPeriod returns the resync period from CommonOptions. If called on a
+// nil receiver it safely returns nil.
+func (o *CommonOptions) GetResyncPeriod() *metav1.Duration {
+ if o == nil {
+ return nil
+ }
+ return o.ResyncPeriod
+}
diff --git a/api/v1alpha1/zz_generated.addressscope-resource.go b/api/v1alpha1/zz_generated.addressscope-resource.go
index a61636c7d..ac5493ef8 100644
--- a/api/v1alpha1/zz_generated.addressscope-resource.go
+++ b/api/v1alpha1/zz_generated.addressscope-resource.go
@@ -75,6 +75,14 @@ type AddressScopeSpec struct {
// +optional
ManagedOptions *ManagedOptions `json:"managedOptions,omitempty"`
+ // resyncPeriod defines how frequently the controller will re-reconcile
+ // this resource even when no changes have been detected. This overrides
+ // the global default resync period. The value must be a valid Go duration
+ // string, e.g. "10m", "1h". Set to "0s" to disable periodic resync for
+ // this resource.
+ // +optional
+ ResyncPeriod *metav1.Duration `json:"resyncPeriod,omitempty"` //nolint:kubeapilinter // metav1.Duration is appropriate for user-facing duration config
+
// cloudCredentialsRef points to a secret containing OpenStack credentials
// +required
CloudCredentialsRef CloudCredentialsReference `json:"cloudCredentialsRef,omitzero"`
@@ -112,6 +120,13 @@ type AddressScopeStatus struct {
// resource contains the observed state of the OpenStack resource.
// +optional
Resource *AddressScopeResourceStatus `json:"resource,omitempty"`
+
+ // lastSyncTime is the timestamp of the last successful reconciliation
+ // that fetched state from OpenStack. It is updated each time the
+ // controller successfully reads the resource state from the OpenStack
+ // API.
+ // +optional
+ LastSyncTime *metav1.Time `json:"lastSyncTime,omitempty"`
}
var _ ObjectWithConditions = &AddressScope{}
diff --git a/api/v1alpha1/zz_generated.applicationcredential-resource.go b/api/v1alpha1/zz_generated.applicationcredential-resource.go
index d949c84d0..ba8889b90 100644
--- a/api/v1alpha1/zz_generated.applicationcredential-resource.go
+++ b/api/v1alpha1/zz_generated.applicationcredential-resource.go
@@ -75,6 +75,14 @@ type ApplicationCredentialSpec struct {
// +optional
ManagedOptions *ManagedOptions `json:"managedOptions,omitempty"`
+ // resyncPeriod defines how frequently the controller will re-reconcile
+ // this resource even when no changes have been detected. This overrides
+ // the global default resync period. The value must be a valid Go duration
+ // string, e.g. "10m", "1h". Set to "0s" to disable periodic resync for
+ // this resource.
+ // +optional
+ ResyncPeriod *metav1.Duration `json:"resyncPeriod,omitempty"` //nolint:kubeapilinter // metav1.Duration is appropriate for user-facing duration config
+
// cloudCredentialsRef points to a secret containing OpenStack credentials
// +required
CloudCredentialsRef CloudCredentialsReference `json:"cloudCredentialsRef,omitzero"`
@@ -112,6 +120,13 @@ type ApplicationCredentialStatus struct {
// resource contains the observed state of the OpenStack resource.
// +optional
Resource *ApplicationCredentialResourceStatus `json:"resource,omitempty"`
+
+ // lastSyncTime is the timestamp of the last successful reconciliation
+ // that fetched state from OpenStack. It is updated each time the
+ // controller successfully reads the resource state from the OpenStack
+ // API.
+ // +optional
+ LastSyncTime *metav1.Time `json:"lastSyncTime,omitempty"`
}
var _ ObjectWithConditions = &ApplicationCredential{}
diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go
index 6f5bf196d..1f3890bc4 100644
--- a/api/v1alpha1/zz_generated.deepcopy.go
+++ b/api/v1alpha1/zz_generated.deepcopy.go
@@ -227,6 +227,11 @@ func (in *AddressScopeSpec) DeepCopyInto(out *AddressScopeSpec) {
*out = new(ManagedOptions)
**out = **in
}
+ if in.ResyncPeriod != nil {
+ in, out := &in.ResyncPeriod, &out.ResyncPeriod
+ *out = new(v1.Duration)
+ **out = **in
+ }
out.CloudCredentialsRef = in.CloudCredentialsRef
}
@@ -260,6 +265,10 @@ func (in *AddressScopeStatus) DeepCopyInto(out *AddressScopeStatus) {
*out = new(AddressScopeResourceStatus)
(*in).DeepCopyInto(*out)
}
+ if in.LastSyncTime != nil {
+ in, out := &in.LastSyncTime, &out.LastSyncTime
+ *out = (*in).DeepCopy()
+ }
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AddressScopeStatus.
@@ -638,6 +647,11 @@ func (in *ApplicationCredentialSpec) DeepCopyInto(out *ApplicationCredentialSpec
*out = new(ManagedOptions)
**out = **in
}
+ if in.ResyncPeriod != nil {
+ in, out := &in.ResyncPeriod, &out.ResyncPeriod
+ *out = new(v1.Duration)
+ **out = **in
+ }
out.CloudCredentialsRef = in.CloudCredentialsRef
}
@@ -671,6 +685,10 @@ func (in *ApplicationCredentialStatus) DeepCopyInto(out *ApplicationCredentialSt
*out = new(ApplicationCredentialResourceStatus)
(*in).DeepCopyInto(*out)
}
+ if in.LastSyncTime != nil {
+ in, out := &in.LastSyncTime, &out.LastSyncTime
+ *out = (*in).DeepCopy()
+ }
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApplicationCredentialStatus.
@@ -698,6 +716,45 @@ func (in *CloudCredentialsReference) DeepCopy() *CloudCredentialsReference {
return out
}
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *CommonOptions) DeepCopyInto(out *CommonOptions) {
+ *out = *in
+ if in.ResyncPeriod != nil {
+ in, out := &in.ResyncPeriod, &out.ResyncPeriod
+ *out = new(v1.Duration)
+ **out = **in
+ }
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CommonOptions.
+func (in *CommonOptions) DeepCopy() *CommonOptions {
+ if in == nil {
+ return nil
+ }
+ out := new(CommonOptions)
+ in.DeepCopyInto(out)
+ return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *CommonStatus) DeepCopyInto(out *CommonStatus) {
+ *out = *in
+ if in.LastSyncTime != nil {
+ in, out := &in.LastSyncTime, &out.LastSyncTime
+ *out = (*in).DeepCopy()
+ }
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CommonStatus.
+func (in *CommonStatus) DeepCopy() *CommonStatus {
+ if in == nil {
+ return nil
+ }
+ out := new(CommonStatus)
+ in.DeepCopyInto(out)
+ return out
+}
+
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Domain) DeepCopyInto(out *Domain) {
*out = *in
@@ -875,6 +932,11 @@ func (in *DomainSpec) DeepCopyInto(out *DomainSpec) {
*out = new(ManagedOptions)
**out = **in
}
+ if in.ResyncPeriod != nil {
+ in, out := &in.ResyncPeriod, &out.ResyncPeriod
+ *out = new(v1.Duration)
+ **out = **in
+ }
out.CloudCredentialsRef = in.CloudCredentialsRef
}
@@ -908,6 +970,10 @@ func (in *DomainStatus) DeepCopyInto(out *DomainStatus) {
*out = new(DomainResourceStatus)
(*in).DeepCopyInto(*out)
}
+ if in.LastSyncTime != nil {
+ in, out := &in.LastSyncTime, &out.LastSyncTime
+ *out = (*in).DeepCopy()
+ }
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DomainStatus.
@@ -1087,6 +1153,11 @@ func (in *EndpointSpec) DeepCopyInto(out *EndpointSpec) {
*out = new(ManagedOptions)
**out = **in
}
+ if in.ResyncPeriod != nil {
+ in, out := &in.ResyncPeriod, &out.ResyncPeriod
+ *out = new(v1.Duration)
+ **out = **in
+ }
out.CloudCredentialsRef = in.CloudCredentialsRef
}
@@ -1120,6 +1191,10 @@ func (in *EndpointStatus) DeepCopyInto(out *EndpointStatus) {
*out = new(EndpointResourceStatus)
(*in).DeepCopyInto(*out)
}
+ if in.LastSyncTime != nil {
+ in, out := &in.LastSyncTime, &out.LastSyncTime
+ *out = (*in).DeepCopy()
+ }
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EndpointStatus.
@@ -1494,6 +1569,11 @@ func (in *FlavorSpec) DeepCopyInto(out *FlavorSpec) {
*out = new(ManagedOptions)
**out = **in
}
+ if in.ResyncPeriod != nil {
+ in, out := &in.ResyncPeriod, &out.ResyncPeriod
+ *out = new(v1.Duration)
+ **out = **in
+ }
out.CloudCredentialsRef = in.CloudCredentialsRef
}
@@ -1527,6 +1607,10 @@ func (in *FlavorStatus) DeepCopyInto(out *FlavorStatus) {
*out = new(FlavorResourceStatus)
(*in).DeepCopyInto(*out)
}
+ if in.LastSyncTime != nil {
+ in, out := &in.LastSyncTime, &out.LastSyncTime
+ *out = (*in).DeepCopy()
+ }
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FlavorStatus.
@@ -1758,6 +1842,11 @@ func (in *FloatingIPSpec) DeepCopyInto(out *FloatingIPSpec) {
*out = new(ManagedOptions)
**out = **in
}
+ if in.ResyncPeriod != nil {
+ in, out := &in.ResyncPeriod, &out.ResyncPeriod
+ *out = new(v1.Duration)
+ **out = **in
+ }
out.CloudCredentialsRef = in.CloudCredentialsRef
}
@@ -1791,6 +1880,10 @@ func (in *FloatingIPStatus) DeepCopyInto(out *FloatingIPStatus) {
*out = new(FloatingIPResourceStatus)
(*in).DeepCopyInto(*out)
}
+ if in.LastSyncTime != nil {
+ in, out := &in.LastSyncTime, &out.LastSyncTime
+ *out = (*in).DeepCopy()
+ }
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FloatingIPStatus.
@@ -1975,6 +2068,11 @@ func (in *GroupSpec) DeepCopyInto(out *GroupSpec) {
*out = new(ManagedOptions)
**out = **in
}
+ if in.ResyncPeriod != nil {
+ in, out := &in.ResyncPeriod, &out.ResyncPeriod
+ *out = new(v1.Duration)
+ **out = **in
+ }
out.CloudCredentialsRef = in.CloudCredentialsRef
}
@@ -2008,6 +2106,10 @@ func (in *GroupStatus) DeepCopyInto(out *GroupStatus) {
*out = new(GroupResourceStatus)
**out = **in
}
+ if in.LastSyncTime != nil {
+ in, out := &in.LastSyncTime, &out.LastSyncTime
+ *out = (*in).DeepCopy()
+ }
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GroupStatus.
@@ -2502,6 +2604,11 @@ func (in *ImageSpec) DeepCopyInto(out *ImageSpec) {
*out = new(ManagedOptions)
**out = **in
}
+ if in.ResyncPeriod != nil {
+ in, out := &in.ResyncPeriod, &out.ResyncPeriod
+ *out = new(v1.Duration)
+ **out = **in
+ }
out.CloudCredentialsRef = in.CloudCredentialsRef
}
@@ -2535,6 +2642,10 @@ func (in *ImageStatus) DeepCopyInto(out *ImageStatus) {
*out = new(ImageResourceStatus)
(*in).DeepCopyInto(*out)
}
+ if in.LastSyncTime != nil {
+ in, out := &in.LastSyncTime, &out.LastSyncTime
+ *out = (*in).DeepCopy()
+ }
in.ImageStatusExtra.DeepCopyInto(&out.ImageStatusExtra)
}
@@ -2730,6 +2841,11 @@ func (in *KeyPairSpec) DeepCopyInto(out *KeyPairSpec) {
*out = new(ManagedOptions)
**out = **in
}
+ if in.ResyncPeriod != nil {
+ in, out := &in.ResyncPeriod, &out.ResyncPeriod
+ *out = new(v1.Duration)
+ **out = **in
+ }
out.CloudCredentialsRef = in.CloudCredentialsRef
}
@@ -2763,6 +2879,10 @@ func (in *KeyPairStatus) DeepCopyInto(out *KeyPairStatus) {
*out = new(KeyPairResourceStatus)
**out = **in
}
+ if in.LastSyncTime != nil {
+ in, out := &in.LastSyncTime, &out.LastSyncTime
+ *out = (*in).DeepCopy()
+ }
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KeyPairStatus.
@@ -3059,6 +3179,11 @@ func (in *NetworkSpec) DeepCopyInto(out *NetworkSpec) {
*out = new(ManagedOptions)
**out = **in
}
+ if in.ResyncPeriod != nil {
+ in, out := &in.ResyncPeriod, &out.ResyncPeriod
+ *out = new(v1.Duration)
+ **out = **in
+ }
out.CloudCredentialsRef = in.CloudCredentialsRef
}
@@ -3092,6 +3217,10 @@ func (in *NetworkStatus) DeepCopyInto(out *NetworkStatus) {
*out = new(NetworkResourceStatus)
(*in).DeepCopyInto(*out)
}
+ if in.LastSyncTime != nil {
+ in, out := &in.LastSyncTime, &out.LastSyncTime
+ *out = (*in).DeepCopy()
+ }
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NetworkStatus.
@@ -3415,6 +3544,11 @@ func (in *PortSpec) DeepCopyInto(out *PortSpec) {
*out = new(ManagedOptions)
**out = **in
}
+ if in.ResyncPeriod != nil {
+ in, out := &in.ResyncPeriod, &out.ResyncPeriod
+ *out = new(v1.Duration)
+ **out = **in
+ }
out.CloudCredentialsRef = in.CloudCredentialsRef
}
@@ -3448,6 +3582,10 @@ func (in *PortStatus) DeepCopyInto(out *PortStatus) {
*out = new(PortResourceStatus)
(*in).DeepCopyInto(*out)
}
+ if in.LastSyncTime != nil {
+ in, out := &in.LastSyncTime, &out.LastSyncTime
+ *out = (*in).DeepCopy()
+ }
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PortStatus.
@@ -3653,6 +3791,11 @@ func (in *ProjectSpec) DeepCopyInto(out *ProjectSpec) {
*out = new(ManagedOptions)
**out = **in
}
+ if in.ResyncPeriod != nil {
+ in, out := &in.ResyncPeriod, &out.ResyncPeriod
+ *out = new(v1.Duration)
+ **out = **in
+ }
out.CloudCredentialsRef = in.CloudCredentialsRef
}
@@ -3686,6 +3829,10 @@ func (in *ProjectStatus) DeepCopyInto(out *ProjectStatus) {
*out = new(ProjectResourceStatus)
(*in).DeepCopyInto(*out)
}
+ if in.LastSyncTime != nil {
+ in, out := &in.LastSyncTime, &out.LastSyncTime
+ *out = (*in).DeepCopy()
+ }
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProjectStatus.
@@ -3890,6 +4037,11 @@ func (in *RoleSpec) DeepCopyInto(out *RoleSpec) {
*out = new(ManagedOptions)
**out = **in
}
+ if in.ResyncPeriod != nil {
+ in, out := &in.ResyncPeriod, &out.ResyncPeriod
+ *out = new(v1.Duration)
+ **out = **in
+ }
out.CloudCredentialsRef = in.CloudCredentialsRef
}
@@ -3923,6 +4075,10 @@ func (in *RoleStatus) DeepCopyInto(out *RoleStatus) {
*out = new(RoleResourceStatus)
**out = **in
}
+ if in.LastSyncTime != nil {
+ in, out := &in.LastSyncTime, &out.LastSyncTime
+ *out = (*in).DeepCopy()
+ }
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RoleStatus.
@@ -4264,6 +4420,11 @@ func (in *RouterSpec) DeepCopyInto(out *RouterSpec) {
*out = new(ManagedOptions)
**out = **in
}
+ if in.ResyncPeriod != nil {
+ in, out := &in.ResyncPeriod, &out.ResyncPeriod
+ *out = new(v1.Duration)
+ **out = **in
+ }
out.CloudCredentialsRef = in.CloudCredentialsRef
}
@@ -4297,6 +4458,10 @@ func (in *RouterStatus) DeepCopyInto(out *RouterStatus) {
*out = new(RouterResourceStatus)
(*in).DeepCopyInto(*out)
}
+ if in.LastSyncTime != nil {
+ in, out := &in.LastSyncTime, &out.LastSyncTime
+ *out = (*in).DeepCopy()
+ }
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RouterStatus.
@@ -4577,6 +4742,11 @@ func (in *SecurityGroupSpec) DeepCopyInto(out *SecurityGroupSpec) {
*out = new(ManagedOptions)
**out = **in
}
+ if in.ResyncPeriod != nil {
+ in, out := &in.ResyncPeriod, &out.ResyncPeriod
+ *out = new(v1.Duration)
+ **out = **in
+ }
out.CloudCredentialsRef = in.CloudCredentialsRef
}
@@ -4610,6 +4780,10 @@ func (in *SecurityGroupStatus) DeepCopyInto(out *SecurityGroupStatus) {
*out = new(SecurityGroupResourceStatus)
(*in).DeepCopyInto(*out)
}
+ if in.LastSyncTime != nil {
+ in, out := &in.LastSyncTime, &out.LastSyncTime
+ *out = (*in).DeepCopy()
+ }
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SecurityGroupStatus.
@@ -4892,6 +5066,11 @@ func (in *ServerGroupSpec) DeepCopyInto(out *ServerGroupSpec) {
*out = new(ManagedOptions)
**out = **in
}
+ if in.ResyncPeriod != nil {
+ in, out := &in.ResyncPeriod, &out.ResyncPeriod
+ *out = new(v1.Duration)
+ **out = **in
+ }
out.CloudCredentialsRef = in.CloudCredentialsRef
}
@@ -4925,6 +5104,10 @@ func (in *ServerGroupStatus) DeepCopyInto(out *ServerGroupStatus) {
*out = new(ServerGroupResourceStatus)
(*in).DeepCopyInto(*out)
}
+ if in.LastSyncTime != nil {
+ in, out := &in.LastSyncTime, &out.LastSyncTime
+ *out = (*in).DeepCopy()
+ }
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServerGroupStatus.
@@ -5213,6 +5396,11 @@ func (in *ServerSpec) DeepCopyInto(out *ServerSpec) {
*out = new(ManagedOptions)
**out = **in
}
+ if in.ResyncPeriod != nil {
+ in, out := &in.ResyncPeriod, &out.ResyncPeriod
+ *out = new(v1.Duration)
+ **out = **in
+ }
out.CloudCredentialsRef = in.CloudCredentialsRef
}
@@ -5246,6 +5434,10 @@ func (in *ServerStatus) DeepCopyInto(out *ServerStatus) {
*out = new(ServerResourceStatus)
(*in).DeepCopyInto(*out)
}
+ if in.LastSyncTime != nil {
+ in, out := &in.LastSyncTime, &out.LastSyncTime
+ *out = (*in).DeepCopy()
+ }
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServerStatus.
@@ -5470,6 +5662,11 @@ func (in *ServiceSpec) DeepCopyInto(out *ServiceSpec) {
*out = new(ManagedOptions)
**out = **in
}
+ if in.ResyncPeriod != nil {
+ in, out := &in.ResyncPeriod, &out.ResyncPeriod
+ *out = new(v1.Duration)
+ **out = **in
+ }
out.CloudCredentialsRef = in.CloudCredentialsRef
}
@@ -5503,6 +5700,10 @@ func (in *ServiceStatus) DeepCopyInto(out *ServiceStatus) {
*out = new(ServiceResourceStatus)
(*in).DeepCopyInto(*out)
}
+ if in.LastSyncTime != nil {
+ in, out := &in.LastSyncTime, &out.LastSyncTime
+ *out = (*in).DeepCopy()
+ }
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceStatus.
@@ -5814,6 +6015,11 @@ func (in *SubnetSpec) DeepCopyInto(out *SubnetSpec) {
*out = new(ManagedOptions)
**out = **in
}
+ if in.ResyncPeriod != nil {
+ in, out := &in.ResyncPeriod, &out.ResyncPeriod
+ *out = new(v1.Duration)
+ **out = **in
+ }
out.CloudCredentialsRef = in.CloudCredentialsRef
}
@@ -5847,6 +6053,10 @@ func (in *SubnetStatus) DeepCopyInto(out *SubnetStatus) {
*out = new(SubnetResourceStatus)
(*in).DeepCopyInto(*out)
}
+ if in.LastSyncTime != nil {
+ in, out := &in.LastSyncTime, &out.LastSyncTime
+ *out = (*in).DeepCopy()
+ }
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SubnetStatus.
@@ -6078,6 +6288,11 @@ func (in *TrunkSpec) DeepCopyInto(out *TrunkSpec) {
*out = new(ManagedOptions)
**out = **in
}
+ if in.ResyncPeriod != nil {
+ in, out := &in.ResyncPeriod, &out.ResyncPeriod
+ *out = new(v1.Duration)
+ **out = **in
+ }
out.CloudCredentialsRef = in.CloudCredentialsRef
}
@@ -6111,6 +6326,10 @@ func (in *TrunkStatus) DeepCopyInto(out *TrunkStatus) {
*out = new(TrunkResourceStatus)
(*in).DeepCopyInto(*out)
}
+ if in.LastSyncTime != nil {
+ in, out := &in.LastSyncTime, &out.LastSyncTime
+ *out = (*in).DeepCopy()
+ }
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TrunkStatus.
@@ -6360,6 +6579,11 @@ func (in *UserSpec) DeepCopyInto(out *UserSpec) {
*out = new(ManagedOptions)
**out = **in
}
+ if in.ResyncPeriod != nil {
+ in, out := &in.ResyncPeriod, &out.ResyncPeriod
+ *out = new(v1.Duration)
+ **out = **in
+ }
out.CloudCredentialsRef = in.CloudCredentialsRef
}
@@ -6393,6 +6617,10 @@ func (in *UserStatus) DeepCopyInto(out *UserStatus) {
*out = new(UserResourceStatus)
**out = **in
}
+ if in.LastSyncTime != nil {
+ in, out := &in.LastSyncTime, &out.LastSyncTime
+ *out = (*in).DeepCopy()
+ }
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new UserStatus.
@@ -6681,6 +6909,11 @@ func (in *VolumeSpec) DeepCopyInto(out *VolumeSpec) {
*out = new(ManagedOptions)
**out = **in
}
+ if in.ResyncPeriod != nil {
+ in, out := &in.ResyncPeriod, &out.ResyncPeriod
+ *out = new(v1.Duration)
+ **out = **in
+ }
out.CloudCredentialsRef = in.CloudCredentialsRef
}
@@ -6714,6 +6947,10 @@ func (in *VolumeStatus) DeepCopyInto(out *VolumeStatus) {
*out = new(VolumeResourceStatus)
(*in).DeepCopyInto(*out)
}
+ if in.LastSyncTime != nil {
+ in, out := &in.LastSyncTime, &out.LastSyncTime
+ *out = (*in).DeepCopy()
+ }
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VolumeStatus.
@@ -6948,6 +7185,11 @@ func (in *VolumeTypeSpec) DeepCopyInto(out *VolumeTypeSpec) {
*out = new(ManagedOptions)
**out = **in
}
+ if in.ResyncPeriod != nil {
+ in, out := &in.ResyncPeriod, &out.ResyncPeriod
+ *out = new(v1.Duration)
+ **out = **in
+ }
out.CloudCredentialsRef = in.CloudCredentialsRef
}
@@ -6981,6 +7223,10 @@ func (in *VolumeTypeStatus) DeepCopyInto(out *VolumeTypeStatus) {
*out = new(VolumeTypeResourceStatus)
(*in).DeepCopyInto(*out)
}
+ if in.LastSyncTime != nil {
+ in, out := &in.LastSyncTime, &out.LastSyncTime
+ *out = (*in).DeepCopy()
+ }
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VolumeTypeStatus.
diff --git a/api/v1alpha1/zz_generated.domain-resource.go b/api/v1alpha1/zz_generated.domain-resource.go
index ae2e5fc4e..32a35fa14 100644
--- a/api/v1alpha1/zz_generated.domain-resource.go
+++ b/api/v1alpha1/zz_generated.domain-resource.go
@@ -75,6 +75,14 @@ type DomainSpec struct {
// +optional
ManagedOptions *ManagedOptions `json:"managedOptions,omitempty"`
+ // resyncPeriod defines how frequently the controller will re-reconcile
+ // this resource even when no changes have been detected. This overrides
+ // the global default resync period. The value must be a valid Go duration
+ // string, e.g. "10m", "1h". Set to "0s" to disable periodic resync for
+ // this resource.
+ // +optional
+ ResyncPeriod *metav1.Duration `json:"resyncPeriod,omitempty"` //nolint:kubeapilinter // metav1.Duration is appropriate for user-facing duration config
+
// cloudCredentialsRef points to a secret containing OpenStack credentials
// +required
CloudCredentialsRef CloudCredentialsReference `json:"cloudCredentialsRef,omitzero"`
@@ -112,6 +120,13 @@ type DomainStatus struct {
// resource contains the observed state of the OpenStack resource.
// +optional
Resource *DomainResourceStatus `json:"resource,omitempty"`
+
+ // lastSyncTime is the timestamp of the last successful reconciliation
+ // that fetched state from OpenStack. It is updated each time the
+ // controller successfully reads the resource state from the OpenStack
+ // API.
+ // +optional
+ LastSyncTime *metav1.Time `json:"lastSyncTime,omitempty"`
}
var _ ObjectWithConditions = &Domain{}
diff --git a/api/v1alpha1/zz_generated.endpoint-resource.go b/api/v1alpha1/zz_generated.endpoint-resource.go
index 0fcc28d2d..7276e59a0 100644
--- a/api/v1alpha1/zz_generated.endpoint-resource.go
+++ b/api/v1alpha1/zz_generated.endpoint-resource.go
@@ -75,6 +75,14 @@ type EndpointSpec struct {
// +optional
ManagedOptions *ManagedOptions `json:"managedOptions,omitempty"`
+ // resyncPeriod defines how frequently the controller will re-reconcile
+ // this resource even when no changes have been detected. This overrides
+ // the global default resync period. The value must be a valid Go duration
+ // string, e.g. "10m", "1h". Set to "0s" to disable periodic resync for
+ // this resource.
+ // +optional
+ ResyncPeriod *metav1.Duration `json:"resyncPeriod,omitempty"` //nolint:kubeapilinter // metav1.Duration is appropriate for user-facing duration config
+
// cloudCredentialsRef points to a secret containing OpenStack credentials
// +required
CloudCredentialsRef CloudCredentialsReference `json:"cloudCredentialsRef,omitzero"`
@@ -112,6 +120,13 @@ type EndpointStatus struct {
// resource contains the observed state of the OpenStack resource.
// +optional
Resource *EndpointResourceStatus `json:"resource,omitempty"`
+
+ // lastSyncTime is the timestamp of the last successful reconciliation
+ // that fetched state from OpenStack. It is updated each time the
+ // controller successfully reads the resource state from the OpenStack
+ // API.
+ // +optional
+ LastSyncTime *metav1.Time `json:"lastSyncTime,omitempty"`
}
var _ ObjectWithConditions = &Endpoint{}
diff --git a/api/v1alpha1/zz_generated.flavor-resource.go b/api/v1alpha1/zz_generated.flavor-resource.go
index 6ae9d1fd8..879040146 100644
--- a/api/v1alpha1/zz_generated.flavor-resource.go
+++ b/api/v1alpha1/zz_generated.flavor-resource.go
@@ -75,6 +75,14 @@ type FlavorSpec struct {
// +optional
ManagedOptions *ManagedOptions `json:"managedOptions,omitempty"`
+ // resyncPeriod defines how frequently the controller will re-reconcile
+ // this resource even when no changes have been detected. This overrides
+ // the global default resync period. The value must be a valid Go duration
+ // string, e.g. "10m", "1h". Set to "0s" to disable periodic resync for
+ // this resource.
+ // +optional
+ ResyncPeriod *metav1.Duration `json:"resyncPeriod,omitempty"` //nolint:kubeapilinter // metav1.Duration is appropriate for user-facing duration config
+
// cloudCredentialsRef points to a secret containing OpenStack credentials
// +required
CloudCredentialsRef CloudCredentialsReference `json:"cloudCredentialsRef,omitzero"`
@@ -112,6 +120,13 @@ type FlavorStatus struct {
// resource contains the observed state of the OpenStack resource.
// +optional
Resource *FlavorResourceStatus `json:"resource,omitempty"`
+
+ // lastSyncTime is the timestamp of the last successful reconciliation
+ // that fetched state from OpenStack. It is updated each time the
+ // controller successfully reads the resource state from the OpenStack
+ // API.
+ // +optional
+ LastSyncTime *metav1.Time `json:"lastSyncTime,omitempty"`
}
var _ ObjectWithConditions = &Flavor{}
diff --git a/api/v1alpha1/zz_generated.floatingip-resource.go b/api/v1alpha1/zz_generated.floatingip-resource.go
index d502e9b65..ccb45982f 100644
--- a/api/v1alpha1/zz_generated.floatingip-resource.go
+++ b/api/v1alpha1/zz_generated.floatingip-resource.go
@@ -75,6 +75,14 @@ type FloatingIPSpec struct {
// +optional
ManagedOptions *ManagedOptions `json:"managedOptions,omitempty"`
+ // resyncPeriod defines how frequently the controller will re-reconcile
+ // this resource even when no changes have been detected. This overrides
+ // the global default resync period. The value must be a valid Go duration
+ // string, e.g. "10m", "1h". Set to "0s" to disable periodic resync for
+ // this resource.
+ // +optional
+ ResyncPeriod *metav1.Duration `json:"resyncPeriod,omitempty"` //nolint:kubeapilinter // metav1.Duration is appropriate for user-facing duration config
+
// cloudCredentialsRef points to a secret containing OpenStack credentials
// +required
CloudCredentialsRef CloudCredentialsReference `json:"cloudCredentialsRef,omitzero"`
@@ -112,6 +120,13 @@ type FloatingIPStatus struct {
// resource contains the observed state of the OpenStack resource.
// +optional
Resource *FloatingIPResourceStatus `json:"resource,omitempty"`
+
+ // lastSyncTime is the timestamp of the last successful reconciliation
+ // that fetched state from OpenStack. It is updated each time the
+ // controller successfully reads the resource state from the OpenStack
+ // API.
+ // +optional
+ LastSyncTime *metav1.Time `json:"lastSyncTime,omitempty"`
}
var _ ObjectWithConditions = &FloatingIP{}
diff --git a/api/v1alpha1/zz_generated.group-resource.go b/api/v1alpha1/zz_generated.group-resource.go
index 653bea813..395abaa17 100644
--- a/api/v1alpha1/zz_generated.group-resource.go
+++ b/api/v1alpha1/zz_generated.group-resource.go
@@ -75,6 +75,14 @@ type GroupSpec struct {
// +optional
ManagedOptions *ManagedOptions `json:"managedOptions,omitempty"`
+ // resyncPeriod defines how frequently the controller will re-reconcile
+ // this resource even when no changes have been detected. This overrides
+ // the global default resync period. The value must be a valid Go duration
+ // string, e.g. "10m", "1h". Set to "0s" to disable periodic resync for
+ // this resource.
+ // +optional
+ ResyncPeriod *metav1.Duration `json:"resyncPeriod,omitempty"` //nolint:kubeapilinter // metav1.Duration is appropriate for user-facing duration config
+
// cloudCredentialsRef points to a secret containing OpenStack credentials
// +required
CloudCredentialsRef CloudCredentialsReference `json:"cloudCredentialsRef,omitzero"`
@@ -112,6 +120,13 @@ type GroupStatus struct {
// resource contains the observed state of the OpenStack resource.
// +optional
Resource *GroupResourceStatus `json:"resource,omitempty"`
+
+ // lastSyncTime is the timestamp of the last successful reconciliation
+ // that fetched state from OpenStack. It is updated each time the
+ // controller successfully reads the resource state from the OpenStack
+ // API.
+ // +optional
+ LastSyncTime *metav1.Time `json:"lastSyncTime,omitempty"`
}
var _ ObjectWithConditions = &Group{}
diff --git a/api/v1alpha1/zz_generated.image-resource.go b/api/v1alpha1/zz_generated.image-resource.go
index e9a65eff8..a4f65e183 100644
--- a/api/v1alpha1/zz_generated.image-resource.go
+++ b/api/v1alpha1/zz_generated.image-resource.go
@@ -76,6 +76,14 @@ type ImageSpec struct {
// +optional
ManagedOptions *ManagedOptions `json:"managedOptions,omitempty"`
+ // resyncPeriod defines how frequently the controller will re-reconcile
+ // this resource even when no changes have been detected. This overrides
+ // the global default resync period. The value must be a valid Go duration
+ // string, e.g. "10m", "1h". Set to "0s" to disable periodic resync for
+ // this resource.
+ // +optional
+ ResyncPeriod *metav1.Duration `json:"resyncPeriod,omitempty"` //nolint:kubeapilinter // metav1.Duration is appropriate for user-facing duration config
+
// cloudCredentialsRef points to a secret containing OpenStack credentials
// +required
CloudCredentialsRef CloudCredentialsReference `json:"cloudCredentialsRef,omitzero"`
@@ -114,6 +122,13 @@ type ImageStatus struct {
// +optional
Resource *ImageResourceStatus `json:"resource,omitempty"`
+ // lastSyncTime is the timestamp of the last successful reconciliation
+ // that fetched state from OpenStack. It is updated each time the
+ // controller successfully reads the resource state from the OpenStack
+ // API.
+ // +optional
+ LastSyncTime *metav1.Time `json:"lastSyncTime,omitempty"`
+
ImageStatusExtra `json:",inline"`
}
diff --git a/api/v1alpha1/zz_generated.keypair-resource.go b/api/v1alpha1/zz_generated.keypair-resource.go
index 57d13fde6..e58659632 100644
--- a/api/v1alpha1/zz_generated.keypair-resource.go
+++ b/api/v1alpha1/zz_generated.keypair-resource.go
@@ -75,6 +75,14 @@ type KeyPairSpec struct {
// +optional
ManagedOptions *ManagedOptions `json:"managedOptions,omitempty"`
+ // resyncPeriod defines how frequently the controller will re-reconcile
+ // this resource even when no changes have been detected. This overrides
+ // the global default resync period. The value must be a valid Go duration
+ // string, e.g. "10m", "1h". Set to "0s" to disable periodic resync for
+ // this resource.
+ // +optional
+ ResyncPeriod *metav1.Duration `json:"resyncPeriod,omitempty"` //nolint:kubeapilinter // metav1.Duration is appropriate for user-facing duration config
+
// cloudCredentialsRef points to a secret containing OpenStack credentials
// +required
CloudCredentialsRef CloudCredentialsReference `json:"cloudCredentialsRef,omitzero"`
@@ -112,6 +120,13 @@ type KeyPairStatus struct {
// resource contains the observed state of the OpenStack resource.
// +optional
Resource *KeyPairResourceStatus `json:"resource,omitempty"`
+
+ // lastSyncTime is the timestamp of the last successful reconciliation
+ // that fetched state from OpenStack. It is updated each time the
+ // controller successfully reads the resource state from the OpenStack
+ // API.
+ // +optional
+ LastSyncTime *metav1.Time `json:"lastSyncTime,omitempty"`
}
var _ ObjectWithConditions = &KeyPair{}
diff --git a/api/v1alpha1/zz_generated.network-resource.go b/api/v1alpha1/zz_generated.network-resource.go
index bc60852dc..57d3e8f62 100644
--- a/api/v1alpha1/zz_generated.network-resource.go
+++ b/api/v1alpha1/zz_generated.network-resource.go
@@ -75,6 +75,14 @@ type NetworkSpec struct {
// +optional
ManagedOptions *ManagedOptions `json:"managedOptions,omitempty"`
+ // resyncPeriod defines how frequently the controller will re-reconcile
+ // this resource even when no changes have been detected. This overrides
+ // the global default resync period. The value must be a valid Go duration
+ // string, e.g. "10m", "1h". Set to "0s" to disable periodic resync for
+ // this resource.
+ // +optional
+ ResyncPeriod *metav1.Duration `json:"resyncPeriod,omitempty"` //nolint:kubeapilinter // metav1.Duration is appropriate for user-facing duration config
+
// cloudCredentialsRef points to a secret containing OpenStack credentials
// +required
CloudCredentialsRef CloudCredentialsReference `json:"cloudCredentialsRef,omitzero"`
@@ -112,6 +120,13 @@ type NetworkStatus struct {
// resource contains the observed state of the OpenStack resource.
// +optional
Resource *NetworkResourceStatus `json:"resource,omitempty"`
+
+ // lastSyncTime is the timestamp of the last successful reconciliation
+ // that fetched state from OpenStack. It is updated each time the
+ // controller successfully reads the resource state from the OpenStack
+ // API.
+ // +optional
+ LastSyncTime *metav1.Time `json:"lastSyncTime,omitempty"`
}
var _ ObjectWithConditions = &Network{}
diff --git a/api/v1alpha1/zz_generated.port-resource.go b/api/v1alpha1/zz_generated.port-resource.go
index 8b1c25ca4..3d9202059 100644
--- a/api/v1alpha1/zz_generated.port-resource.go
+++ b/api/v1alpha1/zz_generated.port-resource.go
@@ -75,6 +75,14 @@ type PortSpec struct {
// +optional
ManagedOptions *ManagedOptions `json:"managedOptions,omitempty"`
+ // resyncPeriod defines how frequently the controller will re-reconcile
+ // this resource even when no changes have been detected. This overrides
+ // the global default resync period. The value must be a valid Go duration
+ // string, e.g. "10m", "1h". Set to "0s" to disable periodic resync for
+ // this resource.
+ // +optional
+ ResyncPeriod *metav1.Duration `json:"resyncPeriod,omitempty"` //nolint:kubeapilinter // metav1.Duration is appropriate for user-facing duration config
+
// cloudCredentialsRef points to a secret containing OpenStack credentials
// +required
CloudCredentialsRef CloudCredentialsReference `json:"cloudCredentialsRef,omitzero"`
@@ -112,6 +120,13 @@ type PortStatus struct {
// resource contains the observed state of the OpenStack resource.
// +optional
Resource *PortResourceStatus `json:"resource,omitempty"`
+
+ // lastSyncTime is the timestamp of the last successful reconciliation
+ // that fetched state from OpenStack. It is updated each time the
+ // controller successfully reads the resource state from the OpenStack
+ // API.
+ // +optional
+ LastSyncTime *metav1.Time `json:"lastSyncTime,omitempty"`
}
var _ ObjectWithConditions = &Port{}
diff --git a/api/v1alpha1/zz_generated.project-resource.go b/api/v1alpha1/zz_generated.project-resource.go
index 33fce32e2..0b2305e87 100644
--- a/api/v1alpha1/zz_generated.project-resource.go
+++ b/api/v1alpha1/zz_generated.project-resource.go
@@ -75,6 +75,14 @@ type ProjectSpec struct {
// +optional
ManagedOptions *ManagedOptions `json:"managedOptions,omitempty"`
+ // resyncPeriod defines how frequently the controller will re-reconcile
+ // this resource even when no changes have been detected. This overrides
+ // the global default resync period. The value must be a valid Go duration
+ // string, e.g. "10m", "1h". Set to "0s" to disable periodic resync for
+ // this resource.
+ // +optional
+ ResyncPeriod *metav1.Duration `json:"resyncPeriod,omitempty"` //nolint:kubeapilinter // metav1.Duration is appropriate for user-facing duration config
+
// cloudCredentialsRef points to a secret containing OpenStack credentials
// +required
CloudCredentialsRef CloudCredentialsReference `json:"cloudCredentialsRef,omitzero"`
@@ -112,6 +120,13 @@ type ProjectStatus struct {
// resource contains the observed state of the OpenStack resource.
// +optional
Resource *ProjectResourceStatus `json:"resource,omitempty"`
+
+ // lastSyncTime is the timestamp of the last successful reconciliation
+ // that fetched state from OpenStack. It is updated each time the
+ // controller successfully reads the resource state from the OpenStack
+ // API.
+ // +optional
+ LastSyncTime *metav1.Time `json:"lastSyncTime,omitempty"`
}
var _ ObjectWithConditions = &Project{}
diff --git a/api/v1alpha1/zz_generated.role-resource.go b/api/v1alpha1/zz_generated.role-resource.go
index 5891a418b..4e764a2b9 100644
--- a/api/v1alpha1/zz_generated.role-resource.go
+++ b/api/v1alpha1/zz_generated.role-resource.go
@@ -75,6 +75,14 @@ type RoleSpec struct {
// +optional
ManagedOptions *ManagedOptions `json:"managedOptions,omitempty"`
+ // resyncPeriod defines how frequently the controller will re-reconcile
+ // this resource even when no changes have been detected. This overrides
+ // the global default resync period. The value must be a valid Go duration
+ // string, e.g. "10m", "1h". Set to "0s" to disable periodic resync for
+ // this resource.
+ // +optional
+ ResyncPeriod *metav1.Duration `json:"resyncPeriod,omitempty"` //nolint:kubeapilinter // metav1.Duration is appropriate for user-facing duration config
+
// cloudCredentialsRef points to a secret containing OpenStack credentials
// +required
CloudCredentialsRef CloudCredentialsReference `json:"cloudCredentialsRef,omitzero"`
@@ -112,6 +120,13 @@ type RoleStatus struct {
// resource contains the observed state of the OpenStack resource.
// +optional
Resource *RoleResourceStatus `json:"resource,omitempty"`
+
+ // lastSyncTime is the timestamp of the last successful reconciliation
+ // that fetched state from OpenStack. It is updated each time the
+ // controller successfully reads the resource state from the OpenStack
+ // API.
+ // +optional
+ LastSyncTime *metav1.Time `json:"lastSyncTime,omitempty"`
}
var _ ObjectWithConditions = &Role{}
diff --git a/api/v1alpha1/zz_generated.router-resource.go b/api/v1alpha1/zz_generated.router-resource.go
index 68d83bd53..bfb82e3ab 100644
--- a/api/v1alpha1/zz_generated.router-resource.go
+++ b/api/v1alpha1/zz_generated.router-resource.go
@@ -75,6 +75,14 @@ type RouterSpec struct {
// +optional
ManagedOptions *ManagedOptions `json:"managedOptions,omitempty"`
+ // resyncPeriod defines how frequently the controller will re-reconcile
+ // this resource even when no changes have been detected. This overrides
+ // the global default resync period. The value must be a valid Go duration
+ // string, e.g. "10m", "1h". Set to "0s" to disable periodic resync for
+ // this resource.
+ // +optional
+ ResyncPeriod *metav1.Duration `json:"resyncPeriod,omitempty"` //nolint:kubeapilinter // metav1.Duration is appropriate for user-facing duration config
+
// cloudCredentialsRef points to a secret containing OpenStack credentials
// +required
CloudCredentialsRef CloudCredentialsReference `json:"cloudCredentialsRef,omitzero"`
@@ -112,6 +120,13 @@ type RouterStatus struct {
// resource contains the observed state of the OpenStack resource.
// +optional
Resource *RouterResourceStatus `json:"resource,omitempty"`
+
+ // lastSyncTime is the timestamp of the last successful reconciliation
+ // that fetched state from OpenStack. It is updated each time the
+ // controller successfully reads the resource state from the OpenStack
+ // API.
+ // +optional
+ LastSyncTime *metav1.Time `json:"lastSyncTime,omitempty"`
}
var _ ObjectWithConditions = &Router{}
diff --git a/api/v1alpha1/zz_generated.securitygroup-resource.go b/api/v1alpha1/zz_generated.securitygroup-resource.go
index ac0a921a6..d6b09ff4f 100644
--- a/api/v1alpha1/zz_generated.securitygroup-resource.go
+++ b/api/v1alpha1/zz_generated.securitygroup-resource.go
@@ -75,6 +75,14 @@ type SecurityGroupSpec struct {
// +optional
ManagedOptions *ManagedOptions `json:"managedOptions,omitempty"`
+ // resyncPeriod defines how frequently the controller will re-reconcile
+ // this resource even when no changes have been detected. This overrides
+ // the global default resync period. The value must be a valid Go duration
+ // string, e.g. "10m", "1h". Set to "0s" to disable periodic resync for
+ // this resource.
+ // +optional
+ ResyncPeriod *metav1.Duration `json:"resyncPeriod,omitempty"` //nolint:kubeapilinter // metav1.Duration is appropriate for user-facing duration config
+
// cloudCredentialsRef points to a secret containing OpenStack credentials
// +required
CloudCredentialsRef CloudCredentialsReference `json:"cloudCredentialsRef,omitzero"`
@@ -112,6 +120,13 @@ type SecurityGroupStatus struct {
// resource contains the observed state of the OpenStack resource.
// +optional
Resource *SecurityGroupResourceStatus `json:"resource,omitempty"`
+
+ // lastSyncTime is the timestamp of the last successful reconciliation
+ // that fetched state from OpenStack. It is updated each time the
+ // controller successfully reads the resource state from the OpenStack
+ // API.
+ // +optional
+ LastSyncTime *metav1.Time `json:"lastSyncTime,omitempty"`
}
var _ ObjectWithConditions = &SecurityGroup{}
diff --git a/api/v1alpha1/zz_generated.server-resource.go b/api/v1alpha1/zz_generated.server-resource.go
index 011c5896d..a86f7f1f9 100644
--- a/api/v1alpha1/zz_generated.server-resource.go
+++ b/api/v1alpha1/zz_generated.server-resource.go
@@ -75,6 +75,14 @@ type ServerSpec struct {
// +optional
ManagedOptions *ManagedOptions `json:"managedOptions,omitempty"`
+ // resyncPeriod defines how frequently the controller will re-reconcile
+ // this resource even when no changes have been detected. This overrides
+ // the global default resync period. The value must be a valid Go duration
+ // string, e.g. "10m", "1h". Set to "0s" to disable periodic resync for
+ // this resource.
+ // +optional
+ ResyncPeriod *metav1.Duration `json:"resyncPeriod,omitempty"` //nolint:kubeapilinter // metav1.Duration is appropriate for user-facing duration config
+
// cloudCredentialsRef points to a secret containing OpenStack credentials
// +required
CloudCredentialsRef CloudCredentialsReference `json:"cloudCredentialsRef,omitzero"`
@@ -112,6 +120,13 @@ type ServerStatus struct {
// resource contains the observed state of the OpenStack resource.
// +optional
Resource *ServerResourceStatus `json:"resource,omitempty"`
+
+ // lastSyncTime is the timestamp of the last successful reconciliation
+ // that fetched state from OpenStack. It is updated each time the
+ // controller successfully reads the resource state from the OpenStack
+ // API.
+ // +optional
+ LastSyncTime *metav1.Time `json:"lastSyncTime,omitempty"`
}
var _ ObjectWithConditions = &Server{}
diff --git a/api/v1alpha1/zz_generated.servergroup-resource.go b/api/v1alpha1/zz_generated.servergroup-resource.go
index 9f478e276..202207e25 100644
--- a/api/v1alpha1/zz_generated.servergroup-resource.go
+++ b/api/v1alpha1/zz_generated.servergroup-resource.go
@@ -75,6 +75,14 @@ type ServerGroupSpec struct {
// +optional
ManagedOptions *ManagedOptions `json:"managedOptions,omitempty"`
+ // resyncPeriod defines how frequently the controller will re-reconcile
+ // this resource even when no changes have been detected. This overrides
+ // the global default resync period. The value must be a valid Go duration
+ // string, e.g. "10m", "1h". Set to "0s" to disable periodic resync for
+ // this resource.
+ // +optional
+ ResyncPeriod *metav1.Duration `json:"resyncPeriod,omitempty"` //nolint:kubeapilinter // metav1.Duration is appropriate for user-facing duration config
+
// cloudCredentialsRef points to a secret containing OpenStack credentials
// +required
CloudCredentialsRef CloudCredentialsReference `json:"cloudCredentialsRef,omitzero"`
@@ -112,6 +120,13 @@ type ServerGroupStatus struct {
// resource contains the observed state of the OpenStack resource.
// +optional
Resource *ServerGroupResourceStatus `json:"resource,omitempty"`
+
+ // lastSyncTime is the timestamp of the last successful reconciliation
+ // that fetched state from OpenStack. It is updated each time the
+ // controller successfully reads the resource state from the OpenStack
+ // API.
+ // +optional
+ LastSyncTime *metav1.Time `json:"lastSyncTime,omitempty"`
}
var _ ObjectWithConditions = &ServerGroup{}
diff --git a/api/v1alpha1/zz_generated.service-resource.go b/api/v1alpha1/zz_generated.service-resource.go
index 0c0182818..92b237248 100644
--- a/api/v1alpha1/zz_generated.service-resource.go
+++ b/api/v1alpha1/zz_generated.service-resource.go
@@ -75,6 +75,14 @@ type ServiceSpec struct {
// +optional
ManagedOptions *ManagedOptions `json:"managedOptions,omitempty"`
+ // resyncPeriod defines how frequently the controller will re-reconcile
+ // this resource even when no changes have been detected. This overrides
+ // the global default resync period. The value must be a valid Go duration
+ // string, e.g. "10m", "1h". Set to "0s" to disable periodic resync for
+ // this resource.
+ // +optional
+ ResyncPeriod *metav1.Duration `json:"resyncPeriod,omitempty"` //nolint:kubeapilinter // metav1.Duration is appropriate for user-facing duration config
+
// cloudCredentialsRef points to a secret containing OpenStack credentials
// +required
CloudCredentialsRef CloudCredentialsReference `json:"cloudCredentialsRef,omitzero"`
@@ -112,6 +120,13 @@ type ServiceStatus struct {
// resource contains the observed state of the OpenStack resource.
// +optional
Resource *ServiceResourceStatus `json:"resource,omitempty"`
+
+ // lastSyncTime is the timestamp of the last successful reconciliation
+ // that fetched state from OpenStack. It is updated each time the
+ // controller successfully reads the resource state from the OpenStack
+ // API.
+ // +optional
+ LastSyncTime *metav1.Time `json:"lastSyncTime,omitempty"`
}
var _ ObjectWithConditions = &Service{}
diff --git a/api/v1alpha1/zz_generated.subnet-resource.go b/api/v1alpha1/zz_generated.subnet-resource.go
index 0151f3064..f67e8bca7 100644
--- a/api/v1alpha1/zz_generated.subnet-resource.go
+++ b/api/v1alpha1/zz_generated.subnet-resource.go
@@ -75,6 +75,14 @@ type SubnetSpec struct {
// +optional
ManagedOptions *ManagedOptions `json:"managedOptions,omitempty"`
+ // resyncPeriod defines how frequently the controller will re-reconcile
+ // this resource even when no changes have been detected. This overrides
+ // the global default resync period. The value must be a valid Go duration
+ // string, e.g. "10m", "1h". Set to "0s" to disable periodic resync for
+ // this resource.
+ // +optional
+ ResyncPeriod *metav1.Duration `json:"resyncPeriod,omitempty"` //nolint:kubeapilinter // metav1.Duration is appropriate for user-facing duration config
+
// cloudCredentialsRef points to a secret containing OpenStack credentials
// +required
CloudCredentialsRef CloudCredentialsReference `json:"cloudCredentialsRef,omitzero"`
@@ -112,6 +120,13 @@ type SubnetStatus struct {
// resource contains the observed state of the OpenStack resource.
// +optional
Resource *SubnetResourceStatus `json:"resource,omitempty"`
+
+ // lastSyncTime is the timestamp of the last successful reconciliation
+ // that fetched state from OpenStack. It is updated each time the
+ // controller successfully reads the resource state from the OpenStack
+ // API.
+ // +optional
+ LastSyncTime *metav1.Time `json:"lastSyncTime,omitempty"`
}
var _ ObjectWithConditions = &Subnet{}
diff --git a/api/v1alpha1/zz_generated.trunk-resource.go b/api/v1alpha1/zz_generated.trunk-resource.go
index eb4c5e844..7a34b26f2 100644
--- a/api/v1alpha1/zz_generated.trunk-resource.go
+++ b/api/v1alpha1/zz_generated.trunk-resource.go
@@ -75,6 +75,14 @@ type TrunkSpec struct {
// +optional
ManagedOptions *ManagedOptions `json:"managedOptions,omitempty"`
+ // resyncPeriod defines how frequently the controller will re-reconcile
+ // this resource even when no changes have been detected. This overrides
+ // the global default resync period. The value must be a valid Go duration
+ // string, e.g. "10m", "1h". Set to "0s" to disable periodic resync for
+ // this resource.
+ // +optional
+ ResyncPeriod *metav1.Duration `json:"resyncPeriod,omitempty"` //nolint:kubeapilinter // metav1.Duration is appropriate for user-facing duration config
+
// cloudCredentialsRef points to a secret containing OpenStack credentials
// +required
CloudCredentialsRef CloudCredentialsReference `json:"cloudCredentialsRef,omitzero"`
@@ -112,6 +120,13 @@ type TrunkStatus struct {
// resource contains the observed state of the OpenStack resource.
// +optional
Resource *TrunkResourceStatus `json:"resource,omitempty"`
+
+ // lastSyncTime is the timestamp of the last successful reconciliation
+ // that fetched state from OpenStack. It is updated each time the
+ // controller successfully reads the resource state from the OpenStack
+ // API.
+ // +optional
+ LastSyncTime *metav1.Time `json:"lastSyncTime,omitempty"`
}
var _ ObjectWithConditions = &Trunk{}
diff --git a/api/v1alpha1/zz_generated.user-resource.go b/api/v1alpha1/zz_generated.user-resource.go
index b109c1d3f..8a8d8f9a3 100644
--- a/api/v1alpha1/zz_generated.user-resource.go
+++ b/api/v1alpha1/zz_generated.user-resource.go
@@ -75,6 +75,14 @@ type UserSpec struct {
// +optional
ManagedOptions *ManagedOptions `json:"managedOptions,omitempty"`
+ // resyncPeriod defines how frequently the controller will re-reconcile
+ // this resource even when no changes have been detected. This overrides
+ // the global default resync period. The value must be a valid Go duration
+ // string, e.g. "10m", "1h". Set to "0s" to disable periodic resync for
+ // this resource.
+ // +optional
+ ResyncPeriod *metav1.Duration `json:"resyncPeriod,omitempty"` //nolint:kubeapilinter // metav1.Duration is appropriate for user-facing duration config
+
// cloudCredentialsRef points to a secret containing OpenStack credentials
// +required
CloudCredentialsRef CloudCredentialsReference `json:"cloudCredentialsRef,omitzero"`
@@ -112,6 +120,13 @@ type UserStatus struct {
// resource contains the observed state of the OpenStack resource.
// +optional
Resource *UserResourceStatus `json:"resource,omitempty"`
+
+ // lastSyncTime is the timestamp of the last successful reconciliation
+ // that fetched state from OpenStack. It is updated each time the
+ // controller successfully reads the resource state from the OpenStack
+ // API.
+ // +optional
+ LastSyncTime *metav1.Time `json:"lastSyncTime,omitempty"`
}
var _ ObjectWithConditions = &User{}
diff --git a/api/v1alpha1/zz_generated.volume-resource.go b/api/v1alpha1/zz_generated.volume-resource.go
index 9451474fb..34b11445c 100644
--- a/api/v1alpha1/zz_generated.volume-resource.go
+++ b/api/v1alpha1/zz_generated.volume-resource.go
@@ -75,6 +75,14 @@ type VolumeSpec struct {
// +optional
ManagedOptions *ManagedOptions `json:"managedOptions,omitempty"`
+ // resyncPeriod defines how frequently the controller will re-reconcile
+ // this resource even when no changes have been detected. This overrides
+ // the global default resync period. The value must be a valid Go duration
+ // string, e.g. "10m", "1h". Set to "0s" to disable periodic resync for
+ // this resource.
+ // +optional
+ ResyncPeriod *metav1.Duration `json:"resyncPeriod,omitempty"` //nolint:kubeapilinter // metav1.Duration is appropriate for user-facing duration config
+
// cloudCredentialsRef points to a secret containing OpenStack credentials
// +required
CloudCredentialsRef CloudCredentialsReference `json:"cloudCredentialsRef,omitzero"`
@@ -112,6 +120,13 @@ type VolumeStatus struct {
// resource contains the observed state of the OpenStack resource.
// +optional
Resource *VolumeResourceStatus `json:"resource,omitempty"`
+
+ // lastSyncTime is the timestamp of the last successful reconciliation
+ // that fetched state from OpenStack. It is updated each time the
+ // controller successfully reads the resource state from the OpenStack
+ // API.
+ // +optional
+ LastSyncTime *metav1.Time `json:"lastSyncTime,omitempty"`
}
var _ ObjectWithConditions = &Volume{}
diff --git a/api/v1alpha1/zz_generated.volumetype-resource.go b/api/v1alpha1/zz_generated.volumetype-resource.go
index 5f583a2bd..183cec59a 100644
--- a/api/v1alpha1/zz_generated.volumetype-resource.go
+++ b/api/v1alpha1/zz_generated.volumetype-resource.go
@@ -75,6 +75,14 @@ type VolumeTypeSpec struct {
// +optional
ManagedOptions *ManagedOptions `json:"managedOptions,omitempty"`
+ // resyncPeriod defines how frequently the controller will re-reconcile
+ // this resource even when no changes have been detected. This overrides
+ // the global default resync period. The value must be a valid Go duration
+ // string, e.g. "10m", "1h". Set to "0s" to disable periodic resync for
+ // this resource.
+ // +optional
+ ResyncPeriod *metav1.Duration `json:"resyncPeriod,omitempty"` //nolint:kubeapilinter // metav1.Duration is appropriate for user-facing duration config
+
// cloudCredentialsRef points to a secret containing OpenStack credentials
// +required
CloudCredentialsRef CloudCredentialsReference `json:"cloudCredentialsRef,omitzero"`
@@ -112,6 +120,13 @@ type VolumeTypeStatus struct {
// resource contains the observed state of the OpenStack resource.
// +optional
Resource *VolumeTypeResourceStatus `json:"resource,omitempty"`
+
+ // lastSyncTime is the timestamp of the last successful reconciliation
+ // that fetched state from OpenStack. It is updated each time the
+ // controller successfully reads the resource state from the OpenStack
+ // API.
+ // +optional
+ LastSyncTime *metav1.Time `json:"lastSyncTime,omitempty"`
}
var _ ObjectWithConditions = &VolumeType{}
diff --git a/cmd/manager/main.go b/cmd/manager/main.go
index c8a624acc..273f017be 100644
--- a/cmd/manager/main.go
+++ b/cmd/manager/main.go
@@ -80,6 +80,9 @@ func main() {
flag.IntVar(&orcOpts.ScopeCacheMaxSize, "scope-cache-max-size", 10,
"The maximum credentials count the operator should keep in cache. "+
"Setting this value to 0 means no cache.")
+ flag.DurationVar(&orcOpts.DefaultResyncPeriod, "default-resync-period", 0,
+ "Default resync period for all resources. Set to 0 to disable. "+
+ "Can be overridden per-resource via spec.resyncPeriod.")
flag.StringVar(&defaultCACertsPath, "default-ca-certs", "",
"The path to a PEM-encoded CA Certificate file to supply as default for OpenStack API requests.")
flag.Func("namespace", "A namespace that the controller watches to reconcile ORC objects. "+
diff --git a/cmd/models-schema/zz_generated.openapi.go b/cmd/models-schema/zz_generated.openapi.go
index 557911992..6f845fe43 100644
--- a/cmd/models-schema/zz_generated.openapi.go
+++ b/cmd/models-schema/zz_generated.openapi.go
@@ -55,6 +55,8 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA
"github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ApplicationCredentialSpec": schema_openstack_resource_controller_v2_api_v1alpha1_ApplicationCredentialSpec(ref),
"github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ApplicationCredentialStatus": schema_openstack_resource_controller_v2_api_v1alpha1_ApplicationCredentialStatus(ref),
"github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.CloudCredentialsReference": schema_openstack_resource_controller_v2_api_v1alpha1_CloudCredentialsReference(ref),
+ "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.CommonOptions": schema_openstack_resource_controller_v2_api_v1alpha1_CommonOptions(ref),
+ "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.CommonStatus": schema_openstack_resource_controller_v2_api_v1alpha1_CommonStatus(ref),
"github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.Domain": schema_openstack_resource_controller_v2_api_v1alpha1_Domain(ref),
"github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.DomainFilter": schema_openstack_resource_controller_v2_api_v1alpha1_DomainFilter(ref),
"github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.DomainImport": schema_openstack_resource_controller_v2_api_v1alpha1_DomainImport(ref),
@@ -876,6 +878,12 @@ func schema_openstack_resource_controller_v2_api_v1alpha1_AddressScopeSpec(ref c
Ref: ref("github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ManagedOptions"),
},
},
+ "resyncPeriod": {
+ SchemaProps: spec.SchemaProps{
+ Description: "resyncPeriod defines how frequently the controller will re-reconcile this resource even when no changes have been detected. This overrides the global default resync period. The value must be a valid Go duration string, e.g. \"10m\", \"1h\". Set to \"0s\" to disable periodic resync for this resource.",
+ Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.Duration"),
+ },
+ },
"cloudCredentialsRef": {
SchemaProps: spec.SchemaProps{
Description: "cloudCredentialsRef points to a secret containing OpenStack credentials",
@@ -888,7 +896,7 @@ func schema_openstack_resource_controller_v2_api_v1alpha1_AddressScopeSpec(ref c
},
},
Dependencies: []string{
- "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.AddressScopeImport", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.AddressScopeResourceSpec", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.CloudCredentialsReference", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ManagedOptions"},
+ "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.AddressScopeImport", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.AddressScopeResourceSpec", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.CloudCredentialsReference", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ManagedOptions", "k8s.io/apimachinery/pkg/apis/meta/v1.Duration"},
}
}
@@ -936,11 +944,17 @@ func schema_openstack_resource_controller_v2_api_v1alpha1_AddressScopeStatus(ref
Ref: ref("github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.AddressScopeResourceStatus"),
},
},
+ "lastSyncTime": {
+ SchemaProps: spec.SchemaProps{
+ Description: "lastSyncTime is the timestamp of the last successful reconciliation that fetched state from OpenStack. It is updated each time the controller successfully reads the resource state from the OpenStack API.",
+ Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.Time"),
+ },
+ },
},
},
},
Dependencies: []string{
- "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.AddressScopeResourceStatus", "k8s.io/apimachinery/pkg/apis/meta/v1.Condition"},
+ "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.AddressScopeResourceStatus", "k8s.io/apimachinery/pkg/apis/meta/v1.Condition", "k8s.io/apimachinery/pkg/apis/meta/v1.Time"},
}
}
@@ -1537,6 +1551,12 @@ func schema_openstack_resource_controller_v2_api_v1alpha1_ApplicationCredentialS
Ref: ref("github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ManagedOptions"),
},
},
+ "resyncPeriod": {
+ SchemaProps: spec.SchemaProps{
+ Description: "resyncPeriod defines how frequently the controller will re-reconcile this resource even when no changes have been detected. This overrides the global default resync period. The value must be a valid Go duration string, e.g. \"10m\", \"1h\". Set to \"0s\" to disable periodic resync for this resource.",
+ Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.Duration"),
+ },
+ },
"cloudCredentialsRef": {
SchemaProps: spec.SchemaProps{
Description: "cloudCredentialsRef points to a secret containing OpenStack credentials",
@@ -1549,7 +1569,7 @@ func schema_openstack_resource_controller_v2_api_v1alpha1_ApplicationCredentialS
},
},
Dependencies: []string{
- "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ApplicationCredentialImport", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ApplicationCredentialResourceSpec", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.CloudCredentialsReference", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ManagedOptions"},
+ "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ApplicationCredentialImport", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ApplicationCredentialResourceSpec", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.CloudCredentialsReference", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ManagedOptions", "k8s.io/apimachinery/pkg/apis/meta/v1.Duration"},
}
}
@@ -1597,11 +1617,17 @@ func schema_openstack_resource_controller_v2_api_v1alpha1_ApplicationCredentialS
Ref: ref("github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ApplicationCredentialResourceStatus"),
},
},
+ "lastSyncTime": {
+ SchemaProps: spec.SchemaProps{
+ Description: "lastSyncTime is the timestamp of the last successful reconciliation that fetched state from OpenStack. It is updated each time the controller successfully reads the resource state from the OpenStack API.",
+ Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.Time"),
+ },
+ },
},
},
},
Dependencies: []string{
- "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ApplicationCredentialResourceStatus", "k8s.io/apimachinery/pkg/apis/meta/v1.Condition"},
+ "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ApplicationCredentialResourceStatus", "k8s.io/apimachinery/pkg/apis/meta/v1.Condition", "k8s.io/apimachinery/pkg/apis/meta/v1.Time"},
}
}
@@ -1633,6 +1659,48 @@ func schema_openstack_resource_controller_v2_api_v1alpha1_CloudCredentialsRefere
}
}
+func schema_openstack_resource_controller_v2_api_v1alpha1_CommonOptions(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Description: "CommonOptions defines options which apply to all ORC objects regardless of management policy.",
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "resyncPeriod": {
+ SchemaProps: spec.SchemaProps{
+ Description: "resyncPeriod defines how frequently the controller will re-reconcile this resource even when no changes have been detected. This implements a two-tier resolution: the per-resource value takes precedence over the global controller default; if neither is set, periodic resync is disabled. The value must be a valid Go duration string, e.g. \"10m\", \"1h\".",
+ Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.Duration"),
+ },
+ },
+ },
+ },
+ },
+ Dependencies: []string{
+ "k8s.io/apimachinery/pkg/apis/meta/v1.Duration"},
+ }
+}
+
+func schema_openstack_resource_controller_v2_api_v1alpha1_CommonStatus(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Description: "CommonStatus defines status fields that are common to all ORC resources.",
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "lastSyncTime": {
+ SchemaProps: spec.SchemaProps{
+ Description: "lastSyncTime is the timestamp of the last successful reconciliation that fetched state from OpenStack. It is updated each time the controller successfully reads the resource state from the OpenStack API. It is not updated on reconciliations that do not contact OpenStack (e.g. when the object is being deleted and is waiting for dependents to be removed).",
+ Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.Time"),
+ },
+ },
+ },
+ },
+ },
+ Dependencies: []string{
+ "k8s.io/apimachinery/pkg/apis/meta/v1.Time"},
+ }
+}
+
func schema_openstack_resource_controller_v2_api_v1alpha1_Domain(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
@@ -1890,6 +1958,12 @@ func schema_openstack_resource_controller_v2_api_v1alpha1_DomainSpec(ref common.
Ref: ref("github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ManagedOptions"),
},
},
+ "resyncPeriod": {
+ SchemaProps: spec.SchemaProps{
+ Description: "resyncPeriod defines how frequently the controller will re-reconcile this resource even when no changes have been detected. This overrides the global default resync period. The value must be a valid Go duration string, e.g. \"10m\", \"1h\". Set to \"0s\" to disable periodic resync for this resource.",
+ Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.Duration"),
+ },
+ },
"cloudCredentialsRef": {
SchemaProps: spec.SchemaProps{
Description: "cloudCredentialsRef points to a secret containing OpenStack credentials",
@@ -1902,7 +1976,7 @@ func schema_openstack_resource_controller_v2_api_v1alpha1_DomainSpec(ref common.
},
},
Dependencies: []string{
- "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.CloudCredentialsReference", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.DomainImport", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.DomainResourceSpec", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ManagedOptions"},
+ "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.CloudCredentialsReference", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.DomainImport", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.DomainResourceSpec", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ManagedOptions", "k8s.io/apimachinery/pkg/apis/meta/v1.Duration"},
}
}
@@ -1950,11 +2024,17 @@ func schema_openstack_resource_controller_v2_api_v1alpha1_DomainStatus(ref commo
Ref: ref("github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.DomainResourceStatus"),
},
},
+ "lastSyncTime": {
+ SchemaProps: spec.SchemaProps{
+ Description: "lastSyncTime is the timestamp of the last successful reconciliation that fetched state from OpenStack. It is updated each time the controller successfully reads the resource state from the OpenStack API.",
+ Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.Time"),
+ },
+ },
},
},
},
Dependencies: []string{
- "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.DomainResourceStatus", "k8s.io/apimachinery/pkg/apis/meta/v1.Condition"},
+ "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.DomainResourceStatus", "k8s.io/apimachinery/pkg/apis/meta/v1.Condition", "k8s.io/apimachinery/pkg/apis/meta/v1.Time"},
}
}
@@ -2252,6 +2332,12 @@ func schema_openstack_resource_controller_v2_api_v1alpha1_EndpointSpec(ref commo
Ref: ref("github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ManagedOptions"),
},
},
+ "resyncPeriod": {
+ SchemaProps: spec.SchemaProps{
+ Description: "resyncPeriod defines how frequently the controller will re-reconcile this resource even when no changes have been detected. This overrides the global default resync period. The value must be a valid Go duration string, e.g. \"10m\", \"1h\". Set to \"0s\" to disable periodic resync for this resource.",
+ Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.Duration"),
+ },
+ },
"cloudCredentialsRef": {
SchemaProps: spec.SchemaProps{
Description: "cloudCredentialsRef points to a secret containing OpenStack credentials",
@@ -2264,7 +2350,7 @@ func schema_openstack_resource_controller_v2_api_v1alpha1_EndpointSpec(ref commo
},
},
Dependencies: []string{
- "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.CloudCredentialsReference", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.EndpointImport", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.EndpointResourceSpec", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ManagedOptions"},
+ "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.CloudCredentialsReference", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.EndpointImport", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.EndpointResourceSpec", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ManagedOptions", "k8s.io/apimachinery/pkg/apis/meta/v1.Duration"},
}
}
@@ -2312,11 +2398,17 @@ func schema_openstack_resource_controller_v2_api_v1alpha1_EndpointStatus(ref com
Ref: ref("github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.EndpointResourceStatus"),
},
},
+ "lastSyncTime": {
+ SchemaProps: spec.SchemaProps{
+ Description: "lastSyncTime is the timestamp of the last successful reconciliation that fetched state from OpenStack. It is updated each time the controller successfully reads the resource state from the OpenStack API.",
+ Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.Time"),
+ },
+ },
},
},
},
Dependencies: []string{
- "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.EndpointResourceStatus", "k8s.io/apimachinery/pkg/apis/meta/v1.Condition"},
+ "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.EndpointResourceStatus", "k8s.io/apimachinery/pkg/apis/meta/v1.Condition", "k8s.io/apimachinery/pkg/apis/meta/v1.Time"},
}
}
@@ -3004,6 +3096,12 @@ func schema_openstack_resource_controller_v2_api_v1alpha1_FlavorSpec(ref common.
Ref: ref("github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ManagedOptions"),
},
},
+ "resyncPeriod": {
+ SchemaProps: spec.SchemaProps{
+ Description: "resyncPeriod defines how frequently the controller will re-reconcile this resource even when no changes have been detected. This overrides the global default resync period. The value must be a valid Go duration string, e.g. \"10m\", \"1h\". Set to \"0s\" to disable periodic resync for this resource.",
+ Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.Duration"),
+ },
+ },
"cloudCredentialsRef": {
SchemaProps: spec.SchemaProps{
Description: "cloudCredentialsRef points to a secret containing OpenStack credentials",
@@ -3016,7 +3114,7 @@ func schema_openstack_resource_controller_v2_api_v1alpha1_FlavorSpec(ref common.
},
},
Dependencies: []string{
- "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.CloudCredentialsReference", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.FlavorImport", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.FlavorResourceSpec", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ManagedOptions"},
+ "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.CloudCredentialsReference", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.FlavorImport", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.FlavorResourceSpec", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ManagedOptions", "k8s.io/apimachinery/pkg/apis/meta/v1.Duration"},
}
}
@@ -3064,11 +3162,17 @@ func schema_openstack_resource_controller_v2_api_v1alpha1_FlavorStatus(ref commo
Ref: ref("github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.FlavorResourceStatus"),
},
},
+ "lastSyncTime": {
+ SchemaProps: spec.SchemaProps{
+ Description: "lastSyncTime is the timestamp of the last successful reconciliation that fetched state from OpenStack. It is updated each time the controller successfully reads the resource state from the OpenStack API.",
+ Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.Time"),
+ },
+ },
},
},
},
Dependencies: []string{
- "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.FlavorResourceStatus", "k8s.io/apimachinery/pkg/apis/meta/v1.Condition"},
+ "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.FlavorResourceStatus", "k8s.io/apimachinery/pkg/apis/meta/v1.Condition", "k8s.io/apimachinery/pkg/apis/meta/v1.Time"},
}
}
@@ -3567,6 +3671,12 @@ func schema_openstack_resource_controller_v2_api_v1alpha1_FloatingIPSpec(ref com
Ref: ref("github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ManagedOptions"),
},
},
+ "resyncPeriod": {
+ SchemaProps: spec.SchemaProps{
+ Description: "resyncPeriod defines how frequently the controller will re-reconcile this resource even when no changes have been detected. This overrides the global default resync period. The value must be a valid Go duration string, e.g. \"10m\", \"1h\". Set to \"0s\" to disable periodic resync for this resource.",
+ Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.Duration"),
+ },
+ },
"cloudCredentialsRef": {
SchemaProps: spec.SchemaProps{
Description: "cloudCredentialsRef points to a secret containing OpenStack credentials",
@@ -3579,7 +3689,7 @@ func schema_openstack_resource_controller_v2_api_v1alpha1_FloatingIPSpec(ref com
},
},
Dependencies: []string{
- "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.CloudCredentialsReference", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.FloatingIPImport", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.FloatingIPResourceSpec", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ManagedOptions"},
+ "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.CloudCredentialsReference", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.FloatingIPImport", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.FloatingIPResourceSpec", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ManagedOptions", "k8s.io/apimachinery/pkg/apis/meta/v1.Duration"},
}
}
@@ -3627,11 +3737,17 @@ func schema_openstack_resource_controller_v2_api_v1alpha1_FloatingIPStatus(ref c
Ref: ref("github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.FloatingIPResourceStatus"),
},
},
+ "lastSyncTime": {
+ SchemaProps: spec.SchemaProps{
+ Description: "lastSyncTime is the timestamp of the last successful reconciliation that fetched state from OpenStack. It is updated each time the controller successfully reads the resource state from the OpenStack API.",
+ Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.Time"),
+ },
+ },
},
},
},
Dependencies: []string{
- "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.FloatingIPResourceStatus", "k8s.io/apimachinery/pkg/apis/meta/v1.Condition"},
+ "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.FloatingIPResourceStatus", "k8s.io/apimachinery/pkg/apis/meta/v1.Condition", "k8s.io/apimachinery/pkg/apis/meta/v1.Time"},
}
}
@@ -3892,6 +4008,12 @@ func schema_openstack_resource_controller_v2_api_v1alpha1_GroupSpec(ref common.R
Ref: ref("github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ManagedOptions"),
},
},
+ "resyncPeriod": {
+ SchemaProps: spec.SchemaProps{
+ Description: "resyncPeriod defines how frequently the controller will re-reconcile this resource even when no changes have been detected. This overrides the global default resync period. The value must be a valid Go duration string, e.g. \"10m\", \"1h\". Set to \"0s\" to disable periodic resync for this resource.",
+ Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.Duration"),
+ },
+ },
"cloudCredentialsRef": {
SchemaProps: spec.SchemaProps{
Description: "cloudCredentialsRef points to a secret containing OpenStack credentials",
@@ -3904,7 +4026,7 @@ func schema_openstack_resource_controller_v2_api_v1alpha1_GroupSpec(ref common.R
},
},
Dependencies: []string{
- "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.CloudCredentialsReference", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.GroupImport", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.GroupResourceSpec", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ManagedOptions"},
+ "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.CloudCredentialsReference", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.GroupImport", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.GroupResourceSpec", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ManagedOptions", "k8s.io/apimachinery/pkg/apis/meta/v1.Duration"},
}
}
@@ -3952,11 +4074,17 @@ func schema_openstack_resource_controller_v2_api_v1alpha1_GroupStatus(ref common
Ref: ref("github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.GroupResourceStatus"),
},
},
+ "lastSyncTime": {
+ SchemaProps: spec.SchemaProps{
+ Description: "lastSyncTime is the timestamp of the last successful reconciliation that fetched state from OpenStack. It is updated each time the controller successfully reads the resource state from the OpenStack API.",
+ Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.Time"),
+ },
+ },
},
},
},
Dependencies: []string{
- "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.GroupResourceStatus", "k8s.io/apimachinery/pkg/apis/meta/v1.Condition"},
+ "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.GroupResourceStatus", "k8s.io/apimachinery/pkg/apis/meta/v1.Condition", "k8s.io/apimachinery/pkg/apis/meta/v1.Time"},
}
}
@@ -4693,6 +4821,12 @@ func schema_openstack_resource_controller_v2_api_v1alpha1_ImageSpec(ref common.R
Ref: ref("github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ManagedOptions"),
},
},
+ "resyncPeriod": {
+ SchemaProps: spec.SchemaProps{
+ Description: "resyncPeriod defines how frequently the controller will re-reconcile this resource even when no changes have been detected. This overrides the global default resync period. The value must be a valid Go duration string, e.g. \"10m\", \"1h\". Set to \"0s\" to disable periodic resync for this resource.",
+ Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.Duration"),
+ },
+ },
"cloudCredentialsRef": {
SchemaProps: spec.SchemaProps{
Description: "cloudCredentialsRef points to a secret containing OpenStack credentials",
@@ -4705,7 +4839,7 @@ func schema_openstack_resource_controller_v2_api_v1alpha1_ImageSpec(ref common.R
},
},
Dependencies: []string{
- "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.CloudCredentialsReference", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ImageImport", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ImageResourceSpec", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ManagedOptions"},
+ "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.CloudCredentialsReference", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ImageImport", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ImageResourceSpec", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ManagedOptions", "k8s.io/apimachinery/pkg/apis/meta/v1.Duration"},
}
}
@@ -4753,6 +4887,12 @@ func schema_openstack_resource_controller_v2_api_v1alpha1_ImageStatus(ref common
Ref: ref("github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ImageResourceStatus"),
},
},
+ "lastSyncTime": {
+ SchemaProps: spec.SchemaProps{
+ Description: "lastSyncTime is the timestamp of the last successful reconciliation that fetched state from OpenStack. It is updated each time the controller successfully reads the resource state from the OpenStack API.",
+ Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.Time"),
+ },
+ },
"downloadAttempts": {
SchemaProps: spec.SchemaProps{
Description: "downloadAttempts is the number of times the controller has attempted to download the image contents",
@@ -4764,7 +4904,7 @@ func schema_openstack_resource_controller_v2_api_v1alpha1_ImageStatus(ref common
},
},
Dependencies: []string{
- "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ImageResourceStatus", "k8s.io/apimachinery/pkg/apis/meta/v1.Condition"},
+ "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ImageResourceStatus", "k8s.io/apimachinery/pkg/apis/meta/v1.Condition", "k8s.io/apimachinery/pkg/apis/meta/v1.Time"},
}
}
@@ -5045,6 +5185,12 @@ func schema_openstack_resource_controller_v2_api_v1alpha1_KeyPairSpec(ref common
Ref: ref("github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ManagedOptions"),
},
},
+ "resyncPeriod": {
+ SchemaProps: spec.SchemaProps{
+ Description: "resyncPeriod defines how frequently the controller will re-reconcile this resource even when no changes have been detected. This overrides the global default resync period. The value must be a valid Go duration string, e.g. \"10m\", \"1h\". Set to \"0s\" to disable periodic resync for this resource.",
+ Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.Duration"),
+ },
+ },
"cloudCredentialsRef": {
SchemaProps: spec.SchemaProps{
Description: "cloudCredentialsRef points to a secret containing OpenStack credentials",
@@ -5057,7 +5203,7 @@ func schema_openstack_resource_controller_v2_api_v1alpha1_KeyPairSpec(ref common
},
},
Dependencies: []string{
- "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.CloudCredentialsReference", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.KeyPairImport", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.KeyPairResourceSpec", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ManagedOptions"},
+ "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.CloudCredentialsReference", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.KeyPairImport", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.KeyPairResourceSpec", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ManagedOptions", "k8s.io/apimachinery/pkg/apis/meta/v1.Duration"},
}
}
@@ -5105,11 +5251,17 @@ func schema_openstack_resource_controller_v2_api_v1alpha1_KeyPairStatus(ref comm
Ref: ref("github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.KeyPairResourceStatus"),
},
},
+ "lastSyncTime": {
+ SchemaProps: spec.SchemaProps{
+ Description: "lastSyncTime is the timestamp of the last successful reconciliation that fetched state from OpenStack. It is updated each time the controller successfully reads the resource state from the OpenStack API.",
+ Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.Time"),
+ },
+ },
},
},
},
Dependencies: []string{
- "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.KeyPairResourceStatus", "k8s.io/apimachinery/pkg/apis/meta/v1.Condition"},
+ "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.KeyPairResourceStatus", "k8s.io/apimachinery/pkg/apis/meta/v1.Condition", "k8s.io/apimachinery/pkg/apis/meta/v1.Time"},
}
}
@@ -5701,6 +5853,12 @@ func schema_openstack_resource_controller_v2_api_v1alpha1_NetworkSpec(ref common
Ref: ref("github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ManagedOptions"),
},
},
+ "resyncPeriod": {
+ SchemaProps: spec.SchemaProps{
+ Description: "resyncPeriod defines how frequently the controller will re-reconcile this resource even when no changes have been detected. This overrides the global default resync period. The value must be a valid Go duration string, e.g. \"10m\", \"1h\". Set to \"0s\" to disable periodic resync for this resource.",
+ Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.Duration"),
+ },
+ },
"cloudCredentialsRef": {
SchemaProps: spec.SchemaProps{
Description: "cloudCredentialsRef points to a secret containing OpenStack credentials",
@@ -5713,7 +5871,7 @@ func schema_openstack_resource_controller_v2_api_v1alpha1_NetworkSpec(ref common
},
},
Dependencies: []string{
- "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.CloudCredentialsReference", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ManagedOptions", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.NetworkImport", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.NetworkResourceSpec"},
+ "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.CloudCredentialsReference", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ManagedOptions", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.NetworkImport", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.NetworkResourceSpec", "k8s.io/apimachinery/pkg/apis/meta/v1.Duration"},
}
}
@@ -5761,11 +5919,17 @@ func schema_openstack_resource_controller_v2_api_v1alpha1_NetworkStatus(ref comm
Ref: ref("github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.NetworkResourceStatus"),
},
},
+ "lastSyncTime": {
+ SchemaProps: spec.SchemaProps{
+ Description: "lastSyncTime is the timestamp of the last successful reconciliation that fetched state from OpenStack. It is updated each time the controller successfully reads the resource state from the OpenStack API.",
+ Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.Time"),
+ },
+ },
},
},
},
Dependencies: []string{
- "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.NetworkResourceStatus", "k8s.io/apimachinery/pkg/apis/meta/v1.Condition"},
+ "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.NetworkResourceStatus", "k8s.io/apimachinery/pkg/apis/meta/v1.Condition", "k8s.io/apimachinery/pkg/apis/meta/v1.Time"},
}
}
@@ -6514,6 +6678,12 @@ func schema_openstack_resource_controller_v2_api_v1alpha1_PortSpec(ref common.Re
Ref: ref("github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ManagedOptions"),
},
},
+ "resyncPeriod": {
+ SchemaProps: spec.SchemaProps{
+ Description: "resyncPeriod defines how frequently the controller will re-reconcile this resource even when no changes have been detected. This overrides the global default resync period. The value must be a valid Go duration string, e.g. \"10m\", \"1h\". Set to \"0s\" to disable periodic resync for this resource.",
+ Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.Duration"),
+ },
+ },
"cloudCredentialsRef": {
SchemaProps: spec.SchemaProps{
Description: "cloudCredentialsRef points to a secret containing OpenStack credentials",
@@ -6526,7 +6696,7 @@ func schema_openstack_resource_controller_v2_api_v1alpha1_PortSpec(ref common.Re
},
},
Dependencies: []string{
- "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.CloudCredentialsReference", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ManagedOptions", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.PortImport", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.PortResourceSpec"},
+ "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.CloudCredentialsReference", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ManagedOptions", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.PortImport", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.PortResourceSpec", "k8s.io/apimachinery/pkg/apis/meta/v1.Duration"},
}
}
@@ -6574,11 +6744,17 @@ func schema_openstack_resource_controller_v2_api_v1alpha1_PortStatus(ref common.
Ref: ref("github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.PortResourceStatus"),
},
},
+ "lastSyncTime": {
+ SchemaProps: spec.SchemaProps{
+ Description: "lastSyncTime is the timestamp of the last successful reconciliation that fetched state from OpenStack. It is updated each time the controller successfully reads the resource state from the OpenStack API.",
+ Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.Time"),
+ },
+ },
},
},
},
Dependencies: []string{
- "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.PortResourceStatus", "k8s.io/apimachinery/pkg/apis/meta/v1.Condition"},
+ "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.PortResourceStatus", "k8s.io/apimachinery/pkg/apis/meta/v1.Condition", "k8s.io/apimachinery/pkg/apis/meta/v1.Time"},
}
}
@@ -6973,6 +7149,12 @@ func schema_openstack_resource_controller_v2_api_v1alpha1_ProjectSpec(ref common
Ref: ref("github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ManagedOptions"),
},
},
+ "resyncPeriod": {
+ SchemaProps: spec.SchemaProps{
+ Description: "resyncPeriod defines how frequently the controller will re-reconcile this resource even when no changes have been detected. This overrides the global default resync period. The value must be a valid Go duration string, e.g. \"10m\", \"1h\". Set to \"0s\" to disable periodic resync for this resource.",
+ Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.Duration"),
+ },
+ },
"cloudCredentialsRef": {
SchemaProps: spec.SchemaProps{
Description: "cloudCredentialsRef points to a secret containing OpenStack credentials",
@@ -6985,7 +7167,7 @@ func schema_openstack_resource_controller_v2_api_v1alpha1_ProjectSpec(ref common
},
},
Dependencies: []string{
- "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.CloudCredentialsReference", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ManagedOptions", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ProjectImport", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ProjectResourceSpec"},
+ "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.CloudCredentialsReference", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ManagedOptions", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ProjectImport", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ProjectResourceSpec", "k8s.io/apimachinery/pkg/apis/meta/v1.Duration"},
}
}
@@ -7033,11 +7215,17 @@ func schema_openstack_resource_controller_v2_api_v1alpha1_ProjectStatus(ref comm
Ref: ref("github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ProjectResourceStatus"),
},
},
+ "lastSyncTime": {
+ SchemaProps: spec.SchemaProps{
+ Description: "lastSyncTime is the timestamp of the last successful reconciliation that fetched state from OpenStack. It is updated each time the controller successfully reads the resource state from the OpenStack API.",
+ Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.Time"),
+ },
+ },
},
},
},
Dependencies: []string{
- "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ProjectResourceStatus", "k8s.io/apimachinery/pkg/apis/meta/v1.Condition"},
+ "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ProjectResourceStatus", "k8s.io/apimachinery/pkg/apis/meta/v1.Condition", "k8s.io/apimachinery/pkg/apis/meta/v1.Time"},
}
}
@@ -7331,6 +7519,12 @@ func schema_openstack_resource_controller_v2_api_v1alpha1_RoleSpec(ref common.Re
Ref: ref("github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ManagedOptions"),
},
},
+ "resyncPeriod": {
+ SchemaProps: spec.SchemaProps{
+ Description: "resyncPeriod defines how frequently the controller will re-reconcile this resource even when no changes have been detected. This overrides the global default resync period. The value must be a valid Go duration string, e.g. \"10m\", \"1h\". Set to \"0s\" to disable periodic resync for this resource.",
+ Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.Duration"),
+ },
+ },
"cloudCredentialsRef": {
SchemaProps: spec.SchemaProps{
Description: "cloudCredentialsRef points to a secret containing OpenStack credentials",
@@ -7343,7 +7537,7 @@ func schema_openstack_resource_controller_v2_api_v1alpha1_RoleSpec(ref common.Re
},
},
Dependencies: []string{
- "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.CloudCredentialsReference", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ManagedOptions", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.RoleImport", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.RoleResourceSpec"},
+ "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.CloudCredentialsReference", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ManagedOptions", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.RoleImport", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.RoleResourceSpec", "k8s.io/apimachinery/pkg/apis/meta/v1.Duration"},
}
}
@@ -7391,11 +7585,17 @@ func schema_openstack_resource_controller_v2_api_v1alpha1_RoleStatus(ref common.
Ref: ref("github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.RoleResourceStatus"),
},
},
+ "lastSyncTime": {
+ SchemaProps: spec.SchemaProps{
+ Description: "lastSyncTime is the timestamp of the last successful reconciliation that fetched state from OpenStack. It is updated each time the controller successfully reads the resource state from the OpenStack API.",
+ Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.Time"),
+ },
+ },
},
},
},
Dependencies: []string{
- "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.RoleResourceStatus", "k8s.io/apimachinery/pkg/apis/meta/v1.Condition"},
+ "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.RoleResourceStatus", "k8s.io/apimachinery/pkg/apis/meta/v1.Condition", "k8s.io/apimachinery/pkg/apis/meta/v1.Time"},
}
}
@@ -8072,6 +8272,12 @@ func schema_openstack_resource_controller_v2_api_v1alpha1_RouterSpec(ref common.
Ref: ref("github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ManagedOptions"),
},
},
+ "resyncPeriod": {
+ SchemaProps: spec.SchemaProps{
+ Description: "resyncPeriod defines how frequently the controller will re-reconcile this resource even when no changes have been detected. This overrides the global default resync period. The value must be a valid Go duration string, e.g. \"10m\", \"1h\". Set to \"0s\" to disable periodic resync for this resource.",
+ Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.Duration"),
+ },
+ },
"cloudCredentialsRef": {
SchemaProps: spec.SchemaProps{
Description: "cloudCredentialsRef points to a secret containing OpenStack credentials",
@@ -8084,7 +8290,7 @@ func schema_openstack_resource_controller_v2_api_v1alpha1_RouterSpec(ref common.
},
},
Dependencies: []string{
- "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.CloudCredentialsReference", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ManagedOptions", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.RouterImport", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.RouterResourceSpec"},
+ "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.CloudCredentialsReference", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ManagedOptions", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.RouterImport", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.RouterResourceSpec", "k8s.io/apimachinery/pkg/apis/meta/v1.Duration"},
}
}
@@ -8132,11 +8338,17 @@ func schema_openstack_resource_controller_v2_api_v1alpha1_RouterStatus(ref commo
Ref: ref("github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.RouterResourceStatus"),
},
},
+ "lastSyncTime": {
+ SchemaProps: spec.SchemaProps{
+ Description: "lastSyncTime is the timestamp of the last successful reconciliation that fetched state from OpenStack. It is updated each time the controller successfully reads the resource state from the OpenStack API.",
+ Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.Time"),
+ },
+ },
},
},
},
Dependencies: []string{
- "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.RouterResourceStatus", "k8s.io/apimachinery/pkg/apis/meta/v1.Condition"},
+ "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.RouterResourceStatus", "k8s.io/apimachinery/pkg/apis/meta/v1.Condition", "k8s.io/apimachinery/pkg/apis/meta/v1.Time"},
}
}
@@ -8725,6 +8937,12 @@ func schema_openstack_resource_controller_v2_api_v1alpha1_SecurityGroupSpec(ref
Ref: ref("github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ManagedOptions"),
},
},
+ "resyncPeriod": {
+ SchemaProps: spec.SchemaProps{
+ Description: "resyncPeriod defines how frequently the controller will re-reconcile this resource even when no changes have been detected. This overrides the global default resync period. The value must be a valid Go duration string, e.g. \"10m\", \"1h\". Set to \"0s\" to disable periodic resync for this resource.",
+ Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.Duration"),
+ },
+ },
"cloudCredentialsRef": {
SchemaProps: spec.SchemaProps{
Description: "cloudCredentialsRef points to a secret containing OpenStack credentials",
@@ -8737,7 +8955,7 @@ func schema_openstack_resource_controller_v2_api_v1alpha1_SecurityGroupSpec(ref
},
},
Dependencies: []string{
- "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.CloudCredentialsReference", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ManagedOptions", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.SecurityGroupImport", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.SecurityGroupResourceSpec"},
+ "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.CloudCredentialsReference", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ManagedOptions", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.SecurityGroupImport", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.SecurityGroupResourceSpec", "k8s.io/apimachinery/pkg/apis/meta/v1.Duration"},
}
}
@@ -8785,11 +9003,17 @@ func schema_openstack_resource_controller_v2_api_v1alpha1_SecurityGroupStatus(re
Ref: ref("github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.SecurityGroupResourceStatus"),
},
},
+ "lastSyncTime": {
+ SchemaProps: spec.SchemaProps{
+ Description: "lastSyncTime is the timestamp of the last successful reconciliation that fetched state from OpenStack. It is updated each time the controller successfully reads the resource state from the OpenStack API.",
+ Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.Time"),
+ },
+ },
},
},
},
Dependencies: []string{
- "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.SecurityGroupResourceStatus", "k8s.io/apimachinery/pkg/apis/meta/v1.Condition"},
+ "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.SecurityGroupResourceStatus", "k8s.io/apimachinery/pkg/apis/meta/v1.Condition", "k8s.io/apimachinery/pkg/apis/meta/v1.Time"},
}
}
@@ -9284,6 +9508,12 @@ func schema_openstack_resource_controller_v2_api_v1alpha1_ServerGroupSpec(ref co
Ref: ref("github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ManagedOptions"),
},
},
+ "resyncPeriod": {
+ SchemaProps: spec.SchemaProps{
+ Description: "resyncPeriod defines how frequently the controller will re-reconcile this resource even when no changes have been detected. This overrides the global default resync period. The value must be a valid Go duration string, e.g. \"10m\", \"1h\". Set to \"0s\" to disable periodic resync for this resource.",
+ Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.Duration"),
+ },
+ },
"cloudCredentialsRef": {
SchemaProps: spec.SchemaProps{
Description: "cloudCredentialsRef points to a secret containing OpenStack credentials",
@@ -9296,7 +9526,7 @@ func schema_openstack_resource_controller_v2_api_v1alpha1_ServerGroupSpec(ref co
},
},
Dependencies: []string{
- "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.CloudCredentialsReference", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ManagedOptions", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ServerGroupImport", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ServerGroupResourceSpec"},
+ "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.CloudCredentialsReference", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ManagedOptions", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ServerGroupImport", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ServerGroupResourceSpec", "k8s.io/apimachinery/pkg/apis/meta/v1.Duration"},
}
}
@@ -9344,11 +9574,17 @@ func schema_openstack_resource_controller_v2_api_v1alpha1_ServerGroupStatus(ref
Ref: ref("github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ServerGroupResourceStatus"),
},
},
+ "lastSyncTime": {
+ SchemaProps: spec.SchemaProps{
+ Description: "lastSyncTime is the timestamp of the last successful reconciliation that fetched state from OpenStack. It is updated each time the controller successfully reads the resource state from the OpenStack API.",
+ Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.Time"),
+ },
+ },
},
},
},
Dependencies: []string{
- "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ServerGroupResourceStatus", "k8s.io/apimachinery/pkg/apis/meta/v1.Condition"},
+ "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ServerGroupResourceStatus", "k8s.io/apimachinery/pkg/apis/meta/v1.Condition", "k8s.io/apimachinery/pkg/apis/meta/v1.Time"},
}
}
@@ -9932,6 +10168,12 @@ func schema_openstack_resource_controller_v2_api_v1alpha1_ServerSpec(ref common.
Ref: ref("github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ManagedOptions"),
},
},
+ "resyncPeriod": {
+ SchemaProps: spec.SchemaProps{
+ Description: "resyncPeriod defines how frequently the controller will re-reconcile this resource even when no changes have been detected. This overrides the global default resync period. The value must be a valid Go duration string, e.g. \"10m\", \"1h\". Set to \"0s\" to disable periodic resync for this resource.",
+ Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.Duration"),
+ },
+ },
"cloudCredentialsRef": {
SchemaProps: spec.SchemaProps{
Description: "cloudCredentialsRef points to a secret containing OpenStack credentials",
@@ -9944,7 +10186,7 @@ func schema_openstack_resource_controller_v2_api_v1alpha1_ServerSpec(ref common.
},
},
Dependencies: []string{
- "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.CloudCredentialsReference", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ManagedOptions", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ServerImport", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ServerResourceSpec"},
+ "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.CloudCredentialsReference", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ManagedOptions", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ServerImport", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ServerResourceSpec", "k8s.io/apimachinery/pkg/apis/meta/v1.Duration"},
}
}
@@ -9992,11 +10234,17 @@ func schema_openstack_resource_controller_v2_api_v1alpha1_ServerStatus(ref commo
Ref: ref("github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ServerResourceStatus"),
},
},
+ "lastSyncTime": {
+ SchemaProps: spec.SchemaProps{
+ Description: "lastSyncTime is the timestamp of the last successful reconciliation that fetched state from OpenStack. It is updated each time the controller successfully reads the resource state from the OpenStack API.",
+ Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.Time"),
+ },
+ },
},
},
},
Dependencies: []string{
- "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ServerResourceStatus", "k8s.io/apimachinery/pkg/apis/meta/v1.Condition"},
+ "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ServerResourceStatus", "k8s.io/apimachinery/pkg/apis/meta/v1.Condition", "k8s.io/apimachinery/pkg/apis/meta/v1.Time"},
}
}
@@ -10318,6 +10566,12 @@ func schema_openstack_resource_controller_v2_api_v1alpha1_ServiceSpec(ref common
Ref: ref("github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ManagedOptions"),
},
},
+ "resyncPeriod": {
+ SchemaProps: spec.SchemaProps{
+ Description: "resyncPeriod defines how frequently the controller will re-reconcile this resource even when no changes have been detected. This overrides the global default resync period. The value must be a valid Go duration string, e.g. \"10m\", \"1h\". Set to \"0s\" to disable periodic resync for this resource.",
+ Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.Duration"),
+ },
+ },
"cloudCredentialsRef": {
SchemaProps: spec.SchemaProps{
Description: "cloudCredentialsRef points to a secret containing OpenStack credentials",
@@ -10330,7 +10584,7 @@ func schema_openstack_resource_controller_v2_api_v1alpha1_ServiceSpec(ref common
},
},
Dependencies: []string{
- "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.CloudCredentialsReference", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ManagedOptions", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ServiceImport", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ServiceResourceSpec"},
+ "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.CloudCredentialsReference", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ManagedOptions", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ServiceImport", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ServiceResourceSpec", "k8s.io/apimachinery/pkg/apis/meta/v1.Duration"},
}
}
@@ -10378,11 +10632,17 @@ func schema_openstack_resource_controller_v2_api_v1alpha1_ServiceStatus(ref comm
Ref: ref("github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ServiceResourceStatus"),
},
},
+ "lastSyncTime": {
+ SchemaProps: spec.SchemaProps{
+ Description: "lastSyncTime is the timestamp of the last successful reconciliation that fetched state from OpenStack. It is updated each time the controller successfully reads the resource state from the OpenStack API.",
+ Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.Time"),
+ },
+ },
},
},
},
Dependencies: []string{
- "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ServiceResourceStatus", "k8s.io/apimachinery/pkg/apis/meta/v1.Condition"},
+ "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ServiceResourceStatus", "k8s.io/apimachinery/pkg/apis/meta/v1.Condition", "k8s.io/apimachinery/pkg/apis/meta/v1.Time"},
}
}
@@ -11090,6 +11350,12 @@ func schema_openstack_resource_controller_v2_api_v1alpha1_SubnetSpec(ref common.
Ref: ref("github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ManagedOptions"),
},
},
+ "resyncPeriod": {
+ SchemaProps: spec.SchemaProps{
+ Description: "resyncPeriod defines how frequently the controller will re-reconcile this resource even when no changes have been detected. This overrides the global default resync period. The value must be a valid Go duration string, e.g. \"10m\", \"1h\". Set to \"0s\" to disable periodic resync for this resource.",
+ Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.Duration"),
+ },
+ },
"cloudCredentialsRef": {
SchemaProps: spec.SchemaProps{
Description: "cloudCredentialsRef points to a secret containing OpenStack credentials",
@@ -11102,7 +11368,7 @@ func schema_openstack_resource_controller_v2_api_v1alpha1_SubnetSpec(ref common.
},
},
Dependencies: []string{
- "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.CloudCredentialsReference", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ManagedOptions", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.SubnetImport", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.SubnetResourceSpec"},
+ "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.CloudCredentialsReference", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ManagedOptions", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.SubnetImport", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.SubnetResourceSpec", "k8s.io/apimachinery/pkg/apis/meta/v1.Duration"},
}
}
@@ -11150,11 +11416,17 @@ func schema_openstack_resource_controller_v2_api_v1alpha1_SubnetStatus(ref commo
Ref: ref("github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.SubnetResourceStatus"),
},
},
+ "lastSyncTime": {
+ SchemaProps: spec.SchemaProps{
+ Description: "lastSyncTime is the timestamp of the last successful reconciliation that fetched state from OpenStack. It is updated each time the controller successfully reads the resource state from the OpenStack API.",
+ Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.Time"),
+ },
+ },
},
},
},
Dependencies: []string{
- "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.SubnetResourceStatus", "k8s.io/apimachinery/pkg/apis/meta/v1.Condition"},
+ "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.SubnetResourceStatus", "k8s.io/apimachinery/pkg/apis/meta/v1.Condition", "k8s.io/apimachinery/pkg/apis/meta/v1.Time"},
}
}
@@ -11660,6 +11932,12 @@ func schema_openstack_resource_controller_v2_api_v1alpha1_TrunkSpec(ref common.R
Ref: ref("github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ManagedOptions"),
},
},
+ "resyncPeriod": {
+ SchemaProps: spec.SchemaProps{
+ Description: "resyncPeriod defines how frequently the controller will re-reconcile this resource even when no changes have been detected. This overrides the global default resync period. The value must be a valid Go duration string, e.g. \"10m\", \"1h\". Set to \"0s\" to disable periodic resync for this resource.",
+ Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.Duration"),
+ },
+ },
"cloudCredentialsRef": {
SchemaProps: spec.SchemaProps{
Description: "cloudCredentialsRef points to a secret containing OpenStack credentials",
@@ -11672,7 +11950,7 @@ func schema_openstack_resource_controller_v2_api_v1alpha1_TrunkSpec(ref common.R
},
},
Dependencies: []string{
- "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.CloudCredentialsReference", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ManagedOptions", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.TrunkImport", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.TrunkResourceSpec"},
+ "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.CloudCredentialsReference", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ManagedOptions", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.TrunkImport", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.TrunkResourceSpec", "k8s.io/apimachinery/pkg/apis/meta/v1.Duration"},
}
}
@@ -11720,11 +11998,17 @@ func schema_openstack_resource_controller_v2_api_v1alpha1_TrunkStatus(ref common
Ref: ref("github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.TrunkResourceStatus"),
},
},
+ "lastSyncTime": {
+ SchemaProps: spec.SchemaProps{
+ Description: "lastSyncTime is the timestamp of the last successful reconciliation that fetched state from OpenStack. It is updated each time the controller successfully reads the resource state from the OpenStack API.",
+ Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.Time"),
+ },
+ },
},
},
},
Dependencies: []string{
- "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.TrunkResourceStatus", "k8s.io/apimachinery/pkg/apis/meta/v1.Condition"},
+ "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.TrunkResourceStatus", "k8s.io/apimachinery/pkg/apis/meta/v1.Condition", "k8s.io/apimachinery/pkg/apis/meta/v1.Time"},
}
}
@@ -12122,6 +12406,12 @@ func schema_openstack_resource_controller_v2_api_v1alpha1_UserSpec(ref common.Re
Ref: ref("github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ManagedOptions"),
},
},
+ "resyncPeriod": {
+ SchemaProps: spec.SchemaProps{
+ Description: "resyncPeriod defines how frequently the controller will re-reconcile this resource even when no changes have been detected. This overrides the global default resync period. The value must be a valid Go duration string, e.g. \"10m\", \"1h\". Set to \"0s\" to disable periodic resync for this resource.",
+ Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.Duration"),
+ },
+ },
"cloudCredentialsRef": {
SchemaProps: spec.SchemaProps{
Description: "cloudCredentialsRef points to a secret containing OpenStack credentials",
@@ -12134,7 +12424,7 @@ func schema_openstack_resource_controller_v2_api_v1alpha1_UserSpec(ref common.Re
},
},
Dependencies: []string{
- "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.CloudCredentialsReference", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ManagedOptions", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.UserImport", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.UserResourceSpec"},
+ "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.CloudCredentialsReference", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ManagedOptions", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.UserImport", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.UserResourceSpec", "k8s.io/apimachinery/pkg/apis/meta/v1.Duration"},
}
}
@@ -12182,11 +12472,17 @@ func schema_openstack_resource_controller_v2_api_v1alpha1_UserStatus(ref common.
Ref: ref("github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.UserResourceStatus"),
},
},
+ "lastSyncTime": {
+ SchemaProps: spec.SchemaProps{
+ Description: "lastSyncTime is the timestamp of the last successful reconciliation that fetched state from OpenStack. It is updated each time the controller successfully reads the resource state from the OpenStack API.",
+ Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.Time"),
+ },
+ },
},
},
},
Dependencies: []string{
- "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.UserResourceStatus", "k8s.io/apimachinery/pkg/apis/meta/v1.Condition"},
+ "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.UserResourceStatus", "k8s.io/apimachinery/pkg/apis/meta/v1.Condition", "k8s.io/apimachinery/pkg/apis/meta/v1.Time"},
}
}
@@ -12760,6 +13056,12 @@ func schema_openstack_resource_controller_v2_api_v1alpha1_VolumeSpec(ref common.
Ref: ref("github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ManagedOptions"),
},
},
+ "resyncPeriod": {
+ SchemaProps: spec.SchemaProps{
+ Description: "resyncPeriod defines how frequently the controller will re-reconcile this resource even when no changes have been detected. This overrides the global default resync period. The value must be a valid Go duration string, e.g. \"10m\", \"1h\". Set to \"0s\" to disable periodic resync for this resource.",
+ Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.Duration"),
+ },
+ },
"cloudCredentialsRef": {
SchemaProps: spec.SchemaProps{
Description: "cloudCredentialsRef points to a secret containing OpenStack credentials",
@@ -12772,7 +13074,7 @@ func schema_openstack_resource_controller_v2_api_v1alpha1_VolumeSpec(ref common.
},
},
Dependencies: []string{
- "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.CloudCredentialsReference", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ManagedOptions", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.VolumeImport", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.VolumeResourceSpec"},
+ "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.CloudCredentialsReference", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ManagedOptions", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.VolumeImport", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.VolumeResourceSpec", "k8s.io/apimachinery/pkg/apis/meta/v1.Duration"},
}
}
@@ -12820,11 +13122,17 @@ func schema_openstack_resource_controller_v2_api_v1alpha1_VolumeStatus(ref commo
Ref: ref("github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.VolumeResourceStatus"),
},
},
+ "lastSyncTime": {
+ SchemaProps: spec.SchemaProps{
+ Description: "lastSyncTime is the timestamp of the last successful reconciliation that fetched state from OpenStack. It is updated each time the controller successfully reads the resource state from the OpenStack API.",
+ Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.Time"),
+ },
+ },
},
},
},
Dependencies: []string{
- "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.VolumeResourceStatus", "k8s.io/apimachinery/pkg/apis/meta/v1.Condition"},
+ "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.VolumeResourceStatus", "k8s.io/apimachinery/pkg/apis/meta/v1.Condition", "k8s.io/apimachinery/pkg/apis/meta/v1.Time"},
}
}
@@ -13189,6 +13497,12 @@ func schema_openstack_resource_controller_v2_api_v1alpha1_VolumeTypeSpec(ref com
Ref: ref("github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ManagedOptions"),
},
},
+ "resyncPeriod": {
+ SchemaProps: spec.SchemaProps{
+ Description: "resyncPeriod defines how frequently the controller will re-reconcile this resource even when no changes have been detected. This overrides the global default resync period. The value must be a valid Go duration string, e.g. \"10m\", \"1h\". Set to \"0s\" to disable periodic resync for this resource.",
+ Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.Duration"),
+ },
+ },
"cloudCredentialsRef": {
SchemaProps: spec.SchemaProps{
Description: "cloudCredentialsRef points to a secret containing OpenStack credentials",
@@ -13201,7 +13515,7 @@ func schema_openstack_resource_controller_v2_api_v1alpha1_VolumeTypeSpec(ref com
},
},
Dependencies: []string{
- "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.CloudCredentialsReference", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ManagedOptions", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.VolumeTypeImport", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.VolumeTypeResourceSpec"},
+ "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.CloudCredentialsReference", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.ManagedOptions", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.VolumeTypeImport", "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.VolumeTypeResourceSpec", "k8s.io/apimachinery/pkg/apis/meta/v1.Duration"},
}
}
@@ -13249,11 +13563,17 @@ func schema_openstack_resource_controller_v2_api_v1alpha1_VolumeTypeStatus(ref c
Ref: ref("github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.VolumeTypeResourceStatus"),
},
},
+ "lastSyncTime": {
+ SchemaProps: spec.SchemaProps{
+ Description: "lastSyncTime is the timestamp of the last successful reconciliation that fetched state from OpenStack. It is updated each time the controller successfully reads the resource state from the OpenStack API.",
+ Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.Time"),
+ },
+ },
},
},
},
Dependencies: []string{
- "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.VolumeTypeResourceStatus", "k8s.io/apimachinery/pkg/apis/meta/v1.Condition"},
+ "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.VolumeTypeResourceStatus", "k8s.io/apimachinery/pkg/apis/meta/v1.Condition", "k8s.io/apimachinery/pkg/apis/meta/v1.Time"},
}
}
diff --git a/cmd/resource-generator/data/adapter.template b/cmd/resource-generator/data/adapter.template
index 7bec457ee..2c0839577 100644
--- a/cmd/resource-generator/data/adapter.template
+++ b/cmd/resource-generator/data/adapter.template
@@ -17,6 +17,8 @@ limitations under the License.
package {{ .NameLower }}
import (
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+
orcv1alpha1 "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1"
"github.com/k-orc/openstack-resource-controller/v2/internal/controllers/generic/interfaces"
)
@@ -54,6 +56,14 @@ func (f adapterT) GetManagedOptions() *orcv1alpha1.ManagedOptions {
return f.Spec.ManagedOptions
}
+func (f adapterT) GetResyncPeriod() *metav1.Duration {
+ return f.Spec.ResyncPeriod
+}
+
+func (f adapterT) GetLastSyncTime() *metav1.Time {
+ return f.Status.LastSyncTime
+}
+
func (f adapterT) GetStatusID() *string {
return f.Status.ID
}
@@ -76,6 +86,10 @@ func (f adapterT) GetImportFilter() *filterT {
return f.Spec.Import.Filter
}
+func (f adapterT) IsImported() bool {
+ return f.GetImportID() != nil || f.GetImportFilter() != nil
+}
+
{{- if not .IsNotNamed }}
// getResourceName returns the name of the OpenStack resource we should use.
diff --git a/cmd/resource-generator/data/api.template b/cmd/resource-generator/data/api.template
index 9abb00d7a..21b575216 100644
--- a/cmd/resource-generator/data/api.template
+++ b/cmd/resource-generator/data/api.template
@@ -90,6 +90,14 @@ type {{ .Name }}Spec struct {
// +optional
ManagedOptions *ManagedOptions `json:"managedOptions,omitempty"`
+ // resyncPeriod defines how frequently the controller will re-reconcile
+ // this resource even when no changes have been detected. This overrides
+ // the global default resync period. The value must be a valid Go duration
+ // string, e.g. "10m", "1h". Set to "0s" to disable periodic resync for
+ // this resource.
+ // +optional
+ ResyncPeriod *metav1.Duration `json:"resyncPeriod,omitempty"` //nolint:kubeapilinter // metav1.Duration is appropriate for user-facing duration config
+
// cloudCredentialsRef points to a secret containing OpenStack credentials
// +required
CloudCredentialsRef CloudCredentialsReference `json:"cloudCredentialsRef,omitzero"`
@@ -127,6 +135,13 @@ type {{ .Name }}Status struct {
// resource contains the observed state of the OpenStack resource.
// +optional
Resource *{{ .Name }}ResourceStatus `json:"resource,omitempty"`
+
+ // lastSyncTime is the timestamp of the last successful reconciliation
+ // that fetched state from OpenStack. It is updated each time the
+ // controller successfully reads the resource state from the OpenStack
+ // API.
+ // +optional
+ LastSyncTime *metav1.Time `json:"lastSyncTime,omitempty"`
{{- if .StatusExtraType }}
{{ .StatusExtraType }} `json:",inline"`
diff --git a/config/crd/bases/openstack.k-orc.cloud_addressscopes.yaml b/config/crd/bases/openstack.k-orc.cloud_addressscopes.yaml
index a63c83ef2..6d4549de5 100644
--- a/config/crd/bases/openstack.k-orc.cloud_addressscopes.yaml
+++ b/config/crd/bases/openstack.k-orc.cloud_addressscopes.yaml
@@ -204,6 +204,14 @@ spec:
required:
- ipVersion
type: object
+ resyncPeriod:
+ description: |-
+ resyncPeriod defines how frequently the controller will re-reconcile
+ this resource even when no changes have been detected. This overrides
+ the global default resync period. The value must be a valid Go duration
+ string, e.g. "10m", "1h". Set to "0s" to disable periodic resync for
+ this resource.
+ type: string
required:
- cloudCredentialsRef
type: object
@@ -303,6 +311,14 @@ spec:
description: id is the unique identifier of the OpenStack resource.
maxLength: 1024
type: string
+ lastSyncTime:
+ description: |-
+ lastSyncTime is the timestamp of the last successful reconciliation
+ that fetched state from OpenStack. It is updated each time the
+ controller successfully reads the resource state from the OpenStack
+ API.
+ format: date-time
+ type: string
resource:
description: resource contains the observed state of the OpenStack
resource.
diff --git a/config/crd/bases/openstack.k-orc.cloud_applicationcredentials.yaml b/config/crd/bases/openstack.k-orc.cloud_applicationcredentials.yaml
index c3d4c5dce..7a45f30da 100644
--- a/config/crd/bases/openstack.k-orc.cloud_applicationcredentials.yaml
+++ b/config/crd/bases/openstack.k-orc.cloud_applicationcredentials.yaml
@@ -251,6 +251,14 @@ spec:
x-kubernetes-validations:
- message: ApplicationCredentialResourceSpec is immutable
rule: self == oldSelf
+ resyncPeriod:
+ description: |-
+ resyncPeriod defines how frequently the controller will re-reconcile
+ this resource even when no changes have been detected. This overrides
+ the global default resync period. The value must be a valid Go duration
+ string, e.g. "10m", "1h". Set to "0s" to disable periodic resync for
+ this resource.
+ type: string
required:
- cloudCredentialsRef
type: object
@@ -350,6 +358,14 @@ spec:
description: id is the unique identifier of the OpenStack resource.
maxLength: 1024
type: string
+ lastSyncTime:
+ description: |-
+ lastSyncTime is the timestamp of the last successful reconciliation
+ that fetched state from OpenStack. It is updated each time the
+ controller successfully reads the resource state from the OpenStack
+ API.
+ format: date-time
+ type: string
resource:
description: resource contains the observed state of the OpenStack
resource.
diff --git a/config/crd/bases/openstack.k-orc.cloud_domains.yaml b/config/crd/bases/openstack.k-orc.cloud_domains.yaml
index 9c9fc2c82..a3ad77736 100644
--- a/config/crd/bases/openstack.k-orc.cloud_domains.yaml
+++ b/config/crd/bases/openstack.k-orc.cloud_domains.yaml
@@ -168,6 +168,14 @@ spec:
minLength: 1
type: string
type: object
+ resyncPeriod:
+ description: |-
+ resyncPeriod defines how frequently the controller will re-reconcile
+ this resource even when no changes have been detected. This overrides
+ the global default resync period. The value must be a valid Go duration
+ string, e.g. "10m", "1h". Set to "0s" to disable periodic resync for
+ this resource.
+ type: string
required:
- cloudCredentialsRef
type: object
@@ -267,6 +275,14 @@ spec:
description: id is the unique identifier of the OpenStack resource.
maxLength: 1024
type: string
+ lastSyncTime:
+ description: |-
+ lastSyncTime is the timestamp of the last successful reconciliation
+ that fetched state from OpenStack. It is updated each time the
+ controller successfully reads the resource state from the OpenStack
+ API.
+ format: date-time
+ type: string
resource:
description: resource contains the observed state of the OpenStack
resource.
diff --git a/config/crd/bases/openstack.k-orc.cloud_endpoints.yaml b/config/crd/bases/openstack.k-orc.cloud_endpoints.yaml
index efddd5c20..4d7a80e74 100644
--- a/config/crd/bases/openstack.k-orc.cloud_endpoints.yaml
+++ b/config/crd/bases/openstack.k-orc.cloud_endpoints.yaml
@@ -194,6 +194,14 @@ spec:
- serviceRef
- url
type: object
+ resyncPeriod:
+ description: |-
+ resyncPeriod defines how frequently the controller will re-reconcile
+ this resource even when no changes have been detected. This overrides
+ the global default resync period. The value must be a valid Go duration
+ string, e.g. "10m", "1h". Set to "0s" to disable periodic resync for
+ this resource.
+ type: string
required:
- cloudCredentialsRef
type: object
@@ -293,6 +301,14 @@ spec:
description: id is the unique identifier of the OpenStack resource.
maxLength: 1024
type: string
+ lastSyncTime:
+ description: |-
+ lastSyncTime is the timestamp of the last successful reconciliation
+ that fetched state from OpenStack. It is updated each time the
+ controller successfully reads the resource state from the OpenStack
+ API.
+ format: date-time
+ type: string
resource:
description: resource contains the observed state of the OpenStack
resource.
diff --git a/config/crd/bases/openstack.k-orc.cloud_flavors.yaml b/config/crd/bases/openstack.k-orc.cloud_flavors.yaml
index e2e9c08c6..17e4e0e89 100644
--- a/config/crd/bases/openstack.k-orc.cloud_flavors.yaml
+++ b/config/crd/bases/openstack.k-orc.cloud_flavors.yaml
@@ -226,6 +226,14 @@ spec:
x-kubernetes-validations:
- message: FlavorResourceSpec is immutable
rule: self == oldSelf
+ resyncPeriod:
+ description: |-
+ resyncPeriod defines how frequently the controller will re-reconcile
+ this resource even when no changes have been detected. This overrides
+ the global default resync period. The value must be a valid Go duration
+ string, e.g. "10m", "1h". Set to "0s" to disable periodic resync for
+ this resource.
+ type: string
required:
- cloudCredentialsRef
type: object
@@ -325,6 +333,14 @@ spec:
description: id is the unique identifier of the OpenStack resource.
maxLength: 1024
type: string
+ lastSyncTime:
+ description: |-
+ lastSyncTime is the timestamp of the last successful reconciliation
+ that fetched state from OpenStack. It is updated each time the
+ controller successfully reads the resource state from the OpenStack
+ API.
+ format: date-time
+ type: string
resource:
description: resource contains the observed state of the OpenStack
resource.
diff --git a/config/crd/bases/openstack.k-orc.cloud_floatingips.yaml b/config/crd/bases/openstack.k-orc.cloud_floatingips.yaml
index 51574f4f1..c1f4df951 100644
--- a/config/crd/bases/openstack.k-orc.cloud_floatingips.yaml
+++ b/config/crd/bases/openstack.k-orc.cloud_floatingips.yaml
@@ -313,6 +313,14 @@ spec:
- message: Exactly one of 'floatingNetworkRef' or 'floatingSubnetRef'
must be set
rule: has(self.floatingNetworkRef) != has(self.floatingSubnetRef)
+ resyncPeriod:
+ description: |-
+ resyncPeriod defines how frequently the controller will re-reconcile
+ this resource even when no changes have been detected. This overrides
+ the global default resync period. The value must be a valid Go duration
+ string, e.g. "10m", "1h". Set to "0s" to disable periodic resync for
+ this resource.
+ type: string
required:
- cloudCredentialsRef
type: object
@@ -412,6 +420,14 @@ spec:
description: id is the unique identifier of the OpenStack resource.
maxLength: 1024
type: string
+ lastSyncTime:
+ description: |-
+ lastSyncTime is the timestamp of the last successful reconciliation
+ that fetched state from OpenStack. It is updated each time the
+ controller successfully reads the resource state from the OpenStack
+ API.
+ format: date-time
+ type: string
resource:
description: resource contains the observed state of the OpenStack
resource.
diff --git a/config/crd/bases/openstack.k-orc.cloud_groups.yaml b/config/crd/bases/openstack.k-orc.cloud_groups.yaml
index 9418c3ded..678d0fdb1 100644
--- a/config/crd/bases/openstack.k-orc.cloud_groups.yaml
+++ b/config/crd/bases/openstack.k-orc.cloud_groups.yaml
@@ -173,6 +173,14 @@ spec:
minLength: 1
type: string
type: object
+ resyncPeriod:
+ description: |-
+ resyncPeriod defines how frequently the controller will re-reconcile
+ this resource even when no changes have been detected. This overrides
+ the global default resync period. The value must be a valid Go duration
+ string, e.g. "10m", "1h". Set to "0s" to disable periodic resync for
+ this resource.
+ type: string
required:
- cloudCredentialsRef
type: object
@@ -272,6 +280,14 @@ spec:
description: id is the unique identifier of the OpenStack resource.
maxLength: 1024
type: string
+ lastSyncTime:
+ description: |-
+ lastSyncTime is the timestamp of the last successful reconciliation
+ that fetched state from OpenStack. It is updated each time the
+ controller successfully reads the resource state from the OpenStack
+ API.
+ format: date-time
+ type: string
resource:
description: resource contains the observed state of the OpenStack
resource.
diff --git a/config/crd/bases/openstack.k-orc.cloud_images.yaml b/config/crd/bases/openstack.k-orc.cloud_images.yaml
index 39cfc79ad..738090796 100644
--- a/config/crd/bases/openstack.k-orc.cloud_images.yaml
+++ b/config/crd/bases/openstack.k-orc.cloud_images.yaml
@@ -541,6 +541,14 @@ spec:
- community
type: string
type: object
+ resyncPeriod:
+ description: |-
+ resyncPeriod defines how frequently the controller will re-reconcile
+ this resource even when no changes have been detected. This overrides
+ the global default resync period. The value must be a valid Go duration
+ string, e.g. "10m", "1h". Set to "0s" to disable periodic resync for
+ this resource.
+ type: string
required:
- cloudCredentialsRef
type: object
@@ -647,6 +655,14 @@ spec:
description: id is the unique identifier of the OpenStack resource.
maxLength: 1024
type: string
+ lastSyncTime:
+ description: |-
+ lastSyncTime is the timestamp of the last successful reconciliation
+ that fetched state from OpenStack. It is updated each time the
+ controller successfully reads the resource state from the OpenStack
+ API.
+ format: date-time
+ type: string
resource:
description: resource contains the observed state of the OpenStack
resource.
diff --git a/config/crd/bases/openstack.k-orc.cloud_keypairs.yaml b/config/crd/bases/openstack.k-orc.cloud_keypairs.yaml
index c02878ff7..30970153c 100644
--- a/config/crd/bases/openstack.k-orc.cloud_keypairs.yaml
+++ b/config/crd/bases/openstack.k-orc.cloud_keypairs.yaml
@@ -169,6 +169,14 @@ spec:
required:
- publicKey
type: object
+ resyncPeriod:
+ description: |-
+ resyncPeriod defines how frequently the controller will re-reconcile
+ this resource even when no changes have been detected. This overrides
+ the global default resync period. The value must be a valid Go duration
+ string, e.g. "10m", "1h". Set to "0s" to disable periodic resync for
+ this resource.
+ type: string
required:
- cloudCredentialsRef
type: object
@@ -268,6 +276,14 @@ spec:
description: id is the unique identifier of the OpenStack resource.
maxLength: 1024
type: string
+ lastSyncTime:
+ description: |-
+ lastSyncTime is the timestamp of the last successful reconciliation
+ that fetched state from OpenStack. It is updated each time the
+ controller successfully reads the resource state from the OpenStack
+ API.
+ format: date-time
+ type: string
resource:
description: resource contains the observed state of the OpenStack
resource.
diff --git a/config/crd/bases/openstack.k-orc.cloud_networks.yaml b/config/crd/bases/openstack.k-orc.cloud_networks.yaml
index ac5f02b8b..3ac48f8a2 100644
--- a/config/crd/bases/openstack.k-orc.cloud_networks.yaml
+++ b/config/crd/bases/openstack.k-orc.cloud_networks.yaml
@@ -310,6 +310,14 @@ spec:
type: array
x-kubernetes-list-type: set
type: object
+ resyncPeriod:
+ description: |-
+ resyncPeriod defines how frequently the controller will re-reconcile
+ this resource even when no changes have been detected. This overrides
+ the global default resync period. The value must be a valid Go duration
+ string, e.g. "10m", "1h". Set to "0s" to disable periodic resync for
+ this resource.
+ type: string
required:
- cloudCredentialsRef
type: object
@@ -409,6 +417,14 @@ spec:
description: id is the unique identifier of the OpenStack resource.
maxLength: 1024
type: string
+ lastSyncTime:
+ description: |-
+ lastSyncTime is the timestamp of the last successful reconciliation
+ that fetched state from OpenStack. It is updated each time the
+ controller successfully reads the resource state from the OpenStack
+ API.
+ format: date-time
+ type: string
resource:
description: resource contains the observed state of the OpenStack
resource.
diff --git a/config/crd/bases/openstack.k-orc.cloud_ports.yaml b/config/crd/bases/openstack.k-orc.cloud_ports.yaml
index 9018183f8..1ee9e53b4 100644
--- a/config/crd/bases/openstack.k-orc.cloud_ports.yaml
+++ b/config/crd/bases/openstack.k-orc.cloud_ports.yaml
@@ -425,6 +425,14 @@ spec:
set to Disabled
rule: 'has(self.portSecurity) && self.portSecurity == ''Disabled''
? !has(self.allowedAddressPairs) : true'
+ resyncPeriod:
+ description: |-
+ resyncPeriod defines how frequently the controller will re-reconcile
+ this resource even when no changes have been detected. This overrides
+ the global default resync period. The value must be a valid Go duration
+ string, e.g. "10m", "1h". Set to "0s" to disable periodic resync for
+ this resource.
+ type: string
required:
- cloudCredentialsRef
type: object
@@ -524,6 +532,14 @@ spec:
description: id is the unique identifier of the OpenStack resource.
maxLength: 1024
type: string
+ lastSyncTime:
+ description: |-
+ lastSyncTime is the timestamp of the last successful reconciliation
+ that fetched state from OpenStack. It is updated each time the
+ controller successfully reads the resource state from the OpenStack
+ API.
+ format: date-time
+ type: string
resource:
description: resource contains the observed state of the OpenStack
resource.
diff --git a/config/crd/bases/openstack.k-orc.cloud_projects.yaml b/config/crd/bases/openstack.k-orc.cloud_projects.yaml
index e673b6217..d7126d544 100644
--- a/config/crd/bases/openstack.k-orc.cloud_projects.yaml
+++ b/config/crd/bases/openstack.k-orc.cloud_projects.yaml
@@ -233,6 +233,14 @@ spec:
type: array
x-kubernetes-list-type: set
type: object
+ resyncPeriod:
+ description: |-
+ resyncPeriod defines how frequently the controller will re-reconcile
+ this resource even when no changes have been detected. This overrides
+ the global default resync period. The value must be a valid Go duration
+ string, e.g. "10m", "1h". Set to "0s" to disable periodic resync for
+ this resource.
+ type: string
required:
- cloudCredentialsRef
type: object
@@ -332,6 +340,14 @@ spec:
description: id is the unique identifier of the OpenStack resource.
maxLength: 1024
type: string
+ lastSyncTime:
+ description: |-
+ lastSyncTime is the timestamp of the last successful reconciliation
+ that fetched state from OpenStack. It is updated each time the
+ controller successfully reads the resource state from the OpenStack
+ API.
+ format: date-time
+ type: string
resource:
description: resource contains the observed state of the OpenStack
resource.
diff --git a/config/crd/bases/openstack.k-orc.cloud_roles.yaml b/config/crd/bases/openstack.k-orc.cloud_roles.yaml
index 4ec04bfa5..849c66d1b 100644
--- a/config/crd/bases/openstack.k-orc.cloud_roles.yaml
+++ b/config/crd/bases/openstack.k-orc.cloud_roles.yaml
@@ -173,6 +173,14 @@ spec:
minLength: 1
type: string
type: object
+ resyncPeriod:
+ description: |-
+ resyncPeriod defines how frequently the controller will re-reconcile
+ this resource even when no changes have been detected. This overrides
+ the global default resync period. The value must be a valid Go duration
+ string, e.g. "10m", "1h". Set to "0s" to disable periodic resync for
+ this resource.
+ type: string
required:
- cloudCredentialsRef
type: object
@@ -272,6 +280,14 @@ spec:
description: id is the unique identifier of the OpenStack resource.
maxLength: 1024
type: string
+ lastSyncTime:
+ description: |-
+ lastSyncTime is the timestamp of the last successful reconciliation
+ that fetched state from OpenStack. It is updated each time the
+ controller successfully reads the resource state from the OpenStack
+ API.
+ format: date-time
+ type: string
resource:
description: resource contains the observed state of the OpenStack
resource.
diff --git a/config/crd/bases/openstack.k-orc.cloud_routers.yaml b/config/crd/bases/openstack.k-orc.cloud_routers.yaml
index 7dade737e..355cf480d 100644
--- a/config/crd/bases/openstack.k-orc.cloud_routers.yaml
+++ b/config/crd/bases/openstack.k-orc.cloud_routers.yaml
@@ -300,6 +300,14 @@ spec:
type: array
x-kubernetes-list-type: set
type: object
+ resyncPeriod:
+ description: |-
+ resyncPeriod defines how frequently the controller will re-reconcile
+ this resource even when no changes have been detected. This overrides
+ the global default resync period. The value must be a valid Go duration
+ string, e.g. "10m", "1h". Set to "0s" to disable periodic resync for
+ this resource.
+ type: string
required:
- cloudCredentialsRef
type: object
@@ -399,6 +407,14 @@ spec:
description: id is the unique identifier of the OpenStack resource.
maxLength: 1024
type: string
+ lastSyncTime:
+ description: |-
+ lastSyncTime is the timestamp of the last successful reconciliation
+ that fetched state from OpenStack. It is updated each time the
+ controller successfully reads the resource state from the OpenStack
+ API.
+ format: date-time
+ type: string
resource:
description: resource contains the observed state of the OpenStack
resource.
diff --git a/config/crd/bases/openstack.k-orc.cloud_securitygroups.yaml b/config/crd/bases/openstack.k-orc.cloud_securitygroups.yaml
index 19eb7d8f9..fe66e9775 100644
--- a/config/crd/bases/openstack.k-orc.cloud_securitygroups.yaml
+++ b/config/crd/bases/openstack.k-orc.cloud_securitygroups.yaml
@@ -375,6 +375,14 @@ spec:
type: array
x-kubernetes-list-type: set
type: object
+ resyncPeriod:
+ description: |-
+ resyncPeriod defines how frequently the controller will re-reconcile
+ this resource even when no changes have been detected. This overrides
+ the global default resync period. The value must be a valid Go duration
+ string, e.g. "10m", "1h". Set to "0s" to disable periodic resync for
+ this resource.
+ type: string
required:
- cloudCredentialsRef
type: object
@@ -474,6 +482,14 @@ spec:
description: id is the unique identifier of the OpenStack resource.
maxLength: 1024
type: string
+ lastSyncTime:
+ description: |-
+ lastSyncTime is the timestamp of the last successful reconciliation
+ that fetched state from OpenStack. It is updated each time the
+ controller successfully reads the resource state from the OpenStack
+ API.
+ format: date-time
+ type: string
resource:
description: resource contains the observed state of the OpenStack
resource.
diff --git a/config/crd/bases/openstack.k-orc.cloud_servergroups.yaml b/config/crd/bases/openstack.k-orc.cloud_servergroups.yaml
index c0bdb3ced..dc71ceed7 100644
--- a/config/crd/bases/openstack.k-orc.cloud_servergroups.yaml
+++ b/config/crd/bases/openstack.k-orc.cloud_servergroups.yaml
@@ -181,6 +181,14 @@ spec:
policy
rule: 'has(self.rules) && self.rules.maxServerPerHost > 0 ? self.policy
== ''anti-affinity'' : true'
+ resyncPeriod:
+ description: |-
+ resyncPeriod defines how frequently the controller will re-reconcile
+ this resource even when no changes have been detected. This overrides
+ the global default resync period. The value must be a valid Go duration
+ string, e.g. "10m", "1h". Set to "0s" to disable periodic resync for
+ this resource.
+ type: string
required:
- cloudCredentialsRef
type: object
@@ -280,6 +288,14 @@ spec:
description: id is the unique identifier of the OpenStack resource.
maxLength: 1024
type: string
+ lastSyncTime:
+ description: |-
+ lastSyncTime is the timestamp of the last successful reconciliation
+ that fetched state from OpenStack. It is updated each time the
+ controller successfully reads the resource state from the OpenStack
+ API.
+ format: date-time
+ type: string
resource:
description: resource contains the observed state of the OpenStack
resource.
diff --git a/config/crd/bases/openstack.k-orc.cloud_servers.yaml b/config/crd/bases/openstack.k-orc.cloud_servers.yaml
index 501e39ae2..f34afe56f 100644
--- a/config/crd/bases/openstack.k-orc.cloud_servers.yaml
+++ b/config/crd/bases/openstack.k-orc.cloud_servers.yaml
@@ -385,6 +385,14 @@ spec:
rule: has(self.imageRef) || has(self.bootVolume)
- message: imageRef and bootVolume are mutually exclusive
rule: '!(has(self.imageRef) && has(self.bootVolume))'
+ resyncPeriod:
+ description: |-
+ resyncPeriod defines how frequently the controller will re-reconcile
+ this resource even when no changes have been detected. This overrides
+ the global default resync period. The value must be a valid Go duration
+ string, e.g. "10m", "1h". Set to "0s" to disable periodic resync for
+ this resource.
+ type: string
required:
- cloudCredentialsRef
type: object
@@ -484,6 +492,14 @@ spec:
description: id is the unique identifier of the OpenStack resource.
maxLength: 1024
type: string
+ lastSyncTime:
+ description: |-
+ lastSyncTime is the timestamp of the last successful reconciliation
+ that fetched state from OpenStack. It is updated each time the
+ controller successfully reads the resource state from the OpenStack
+ API.
+ format: date-time
+ type: string
resource:
description: resource contains the observed state of the OpenStack
resource.
diff --git a/config/crd/bases/openstack.k-orc.cloud_services.yaml b/config/crd/bases/openstack.k-orc.cloud_services.yaml
index 8c5f96c75..0686c5416 100644
--- a/config/crd/bases/openstack.k-orc.cloud_services.yaml
+++ b/config/crd/bases/openstack.k-orc.cloud_services.yaml
@@ -177,6 +177,14 @@ spec:
required:
- type
type: object
+ resyncPeriod:
+ description: |-
+ resyncPeriod defines how frequently the controller will re-reconcile
+ this resource even when no changes have been detected. This overrides
+ the global default resync period. The value must be a valid Go duration
+ string, e.g. "10m", "1h". Set to "0s" to disable periodic resync for
+ this resource.
+ type: string
required:
- cloudCredentialsRef
type: object
@@ -276,6 +284,14 @@ spec:
description: id is the unique identifier of the OpenStack resource.
maxLength: 1024
type: string
+ lastSyncTime:
+ description: |-
+ lastSyncTime is the timestamp of the last successful reconciliation
+ that fetched state from OpenStack. It is updated each time the
+ controller successfully reads the resource state from the OpenStack
+ API.
+ format: date-time
+ type: string
resource:
description: resource contains the observed state of the OpenStack
resource.
diff --git a/config/crd/bases/openstack.k-orc.cloud_subnets.yaml b/config/crd/bases/openstack.k-orc.cloud_subnets.yaml
index 5ff2ede1a..0c2d3dadc 100644
--- a/config/crd/bases/openstack.k-orc.cloud_subnets.yaml
+++ b/config/crd/bases/openstack.k-orc.cloud_subnets.yaml
@@ -466,6 +466,14 @@ spec:
- ipVersion
- networkRef
type: object
+ resyncPeriod:
+ description: |-
+ resyncPeriod defines how frequently the controller will re-reconcile
+ this resource even when no changes have been detected. This overrides
+ the global default resync period. The value must be a valid Go duration
+ string, e.g. "10m", "1h". Set to "0s" to disable periodic resync for
+ this resource.
+ type: string
required:
- cloudCredentialsRef
type: object
@@ -565,6 +573,14 @@ spec:
description: id is the unique identifier of the OpenStack resource.
maxLength: 1024
type: string
+ lastSyncTime:
+ description: |-
+ lastSyncTime is the timestamp of the last successful reconciliation
+ that fetched state from OpenStack. It is updated each time the
+ controller successfully reads the resource state from the OpenStack
+ API.
+ format: date-time
+ type: string
resource:
description: resource contains the observed state of the OpenStack
resource.
diff --git a/config/crd/bases/openstack.k-orc.cloud_trunks.yaml b/config/crd/bases/openstack.k-orc.cloud_trunks.yaml
index aefa17223..c7aca9156 100644
--- a/config/crd/bases/openstack.k-orc.cloud_trunks.yaml
+++ b/config/crd/bases/openstack.k-orc.cloud_trunks.yaml
@@ -312,6 +312,14 @@ spec:
required:
- portRef
type: object
+ resyncPeriod:
+ description: |-
+ resyncPeriod defines how frequently the controller will re-reconcile
+ this resource even when no changes have been detected. This overrides
+ the global default resync period. The value must be a valid Go duration
+ string, e.g. "10m", "1h". Set to "0s" to disable periodic resync for
+ this resource.
+ type: string
required:
- cloudCredentialsRef
type: object
@@ -411,6 +419,14 @@ spec:
description: id is the unique identifier of the OpenStack resource.
maxLength: 1024
type: string
+ lastSyncTime:
+ description: |-
+ lastSyncTime is the timestamp of the last successful reconciliation
+ that fetched state from OpenStack. It is updated each time the
+ controller successfully reads the resource state from the OpenStack
+ API.
+ format: date-time
+ type: string
resource:
description: resource contains the observed state of the OpenStack
resource.
diff --git a/config/crd/bases/openstack.k-orc.cloud_users.yaml b/config/crd/bases/openstack.k-orc.cloud_users.yaml
index e9dc0fa8c..a5e5955c0 100644
--- a/config/crd/bases/openstack.k-orc.cloud_users.yaml
+++ b/config/crd/bases/openstack.k-orc.cloud_users.yaml
@@ -198,6 +198,14 @@ spec:
x-kubernetes-validations:
- message: passwordRef may not be removed once set
rule: '!has(oldSelf.passwordRef) || has(self.passwordRef)'
+ resyncPeriod:
+ description: |-
+ resyncPeriod defines how frequently the controller will re-reconcile
+ this resource even when no changes have been detected. This overrides
+ the global default resync period. The value must be a valid Go duration
+ string, e.g. "10m", "1h". Set to "0s" to disable periodic resync for
+ this resource.
+ type: string
required:
- cloudCredentialsRef
type: object
@@ -297,6 +305,14 @@ spec:
description: id is the unique identifier of the OpenStack resource.
maxLength: 1024
type: string
+ lastSyncTime:
+ description: |-
+ lastSyncTime is the timestamp of the last successful reconciliation
+ that fetched state from OpenStack. It is updated each time the
+ controller successfully reads the resource state from the OpenStack
+ API.
+ format: date-time
+ type: string
resource:
description: resource contains the observed state of the OpenStack
resource.
diff --git a/config/crd/bases/openstack.k-orc.cloud_volumes.yaml b/config/crd/bases/openstack.k-orc.cloud_volumes.yaml
index 500dec639..a6f1a991e 100644
--- a/config/crd/bases/openstack.k-orc.cloud_volumes.yaml
+++ b/config/crd/bases/openstack.k-orc.cloud_volumes.yaml
@@ -238,6 +238,14 @@ spec:
required:
- size
type: object
+ resyncPeriod:
+ description: |-
+ resyncPeriod defines how frequently the controller will re-reconcile
+ this resource even when no changes have been detected. This overrides
+ the global default resync period. The value must be a valid Go duration
+ string, e.g. "10m", "1h". Set to "0s" to disable periodic resync for
+ this resource.
+ type: string
required:
- cloudCredentialsRef
type: object
@@ -337,6 +345,14 @@ spec:
description: id is the unique identifier of the OpenStack resource.
maxLength: 1024
type: string
+ lastSyncTime:
+ description: |-
+ lastSyncTime is the timestamp of the last successful reconciliation
+ that fetched state from OpenStack. It is updated each time the
+ controller successfully reads the resource state from the OpenStack
+ API.
+ format: date-time
+ type: string
resource:
description: resource contains the observed state of the OpenStack
resource.
diff --git a/config/crd/bases/openstack.k-orc.cloud_volumetypes.yaml b/config/crd/bases/openstack.k-orc.cloud_volumetypes.yaml
index 384a5f215..1f1edb85a 100644
--- a/config/crd/bases/openstack.k-orc.cloud_volumetypes.yaml
+++ b/config/crd/bases/openstack.k-orc.cloud_volumetypes.yaml
@@ -192,6 +192,14 @@ spec:
pattern: ^[^,]+$
type: string
type: object
+ resyncPeriod:
+ description: |-
+ resyncPeriod defines how frequently the controller will re-reconcile
+ this resource even when no changes have been detected. This overrides
+ the global default resync period. The value must be a valid Go duration
+ string, e.g. "10m", "1h". Set to "0s" to disable periodic resync for
+ this resource.
+ type: string
required:
- cloudCredentialsRef
type: object
@@ -291,6 +299,14 @@ spec:
description: id is the unique identifier of the OpenStack resource.
maxLength: 1024
type: string
+ lastSyncTime:
+ description: |-
+ lastSyncTime is the timestamp of the last successful reconciliation
+ that fetched state from OpenStack. It is updated each time the
+ controller successfully reads the resource state from the OpenStack
+ API.
+ format: date-time
+ type: string
resource:
description: resource contains the observed state of the OpenStack
resource.
diff --git a/enhancements/drift-detection.md b/enhancements/drift-detection.md
index 8c2196907..a602f5756 100644
--- a/enhancements/drift-detection.md
+++ b/enhancements/drift-detection.md
@@ -2,10 +2,10 @@
| Field | Value |
|-------|-------|
-| **Status** | implementable |
+| **Status** | implemented |
| **Author(s)** | @eshulman |
| **Created** | 2026-02-03 |
-| **Last Updated** | 2026-02-03 |
+| **Last Updated** | 2026-02-10 |
| **Tracking Issue** | TBD |
## Summary
@@ -227,7 +227,7 @@ Drift detection covers all **mutable fields** that ORC actuators implement updat
**Mitigation**:
- Disabled by default; when enabled, recommend conservative intervals (e.g., 10 hours)
-- Add random jitter to resync times to avoid thundering herd: since reconciliation already uses "requeue after X duration", jitter simply adds a random offset (e.g., ±10%) to the resync period, spreading resyncs over time rather than having them fire simultaneously
+- Add random jitter to resync times to avoid thundering herd: since reconciliation already uses "requeue after X duration", jitter simply adds a random offset (e.g., [0%, +20%]) to the resync period, spreading resyncs over time rather than having them fire simultaneously
- Allow operators to disable or lengthen resync for stable resources
### Controller Resource Consumption
@@ -275,3 +275,37 @@ Implement a watcher that periodically lists all resources from OpenStack and com
## Implementation History
- 2026-02-03: Enhancement proposed
+- 2026-02-03: Implemented — all tasks completed
+
+### Implemented Components
+
+The following have been implemented:
+
+**API Changes**
+- Added `spec.resyncPeriod` field (`*metav1.Duration`) to all ORC resource types
+- Added `status.lastSyncTime` field (`*metav1.Time`) to all ORC resource types
+
+**Periodic Resync**
+- `shouldReconcile` updated to check `lastSyncTime` against `resyncPeriod` for time-based resync
+- Jitter ([0%, +20%]) applied to resync scheduling via `resync.CalculateJitteredDuration`
+- `status.lastSyncTime` written on every successful reconciliation cycle
+- Resources in terminal error state are not rescheduled
+
+**External Deletion Handling**
+- `IsImported()` method added to `APIObjectAdapter` interface (all resource adapters)
+- `GetOrCreateOSResource` branches on management policy and import status when 404 is received:
+ - Managed, non-imported resources → `(nil, nil)` to trigger recreation
+ - Unmanaged or imported resources → terminal error
+- `status.ClearStatusID` clears `status.id` before recreation (using JSON merge patch with explicit `null`)
+- `reconcileNormal` handles the `(nil, nil)` recreation signal from `GetOrCreateOSResource`
+
+**E2E Tests**
+- `network-resync-period`: verifies `lastSyncTime` is updated after configured period
+- `network-resync-disabled`: verifies `lastSyncTime` is not updated when `resyncPeriod: 0`
+- `network-resync-terminal-error`: verifies terminal errors are not rescheduled
+- `network-resync-jitter`: verifies independent jitter-based scheduling for multiple resources
+- `network-external-deletion`: verifies managed ORC-created network is recreated with new ID after external deletion
+- `network-external-deletion-import`: verifies imported network enters terminal error state after external deletion
+
+**Documentation**
+- `website/docs/user-guide/drift-detection.md`: user-facing documentation covering external deletion behavior, resync configuration, verification steps, and implications for dependent resources
diff --git a/internal/controllers/addressscope/controller.go b/internal/controllers/addressscope/controller.go
index daa8694e6..718aa0f8b 100644
--- a/internal/controllers/addressscope/controller.go
+++ b/internal/controllers/addressscope/controller.go
@@ -19,6 +19,7 @@ package addressscope
import (
"context"
"errors"
+ "time"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/builder"
@@ -40,17 +41,22 @@ const controllerName = "addressscope"
// +kubebuilder:rbac:groups=openstack.k-orc.cloud,resources=addressscopes/status,verbs=get;update;patch
type addressscopeReconcilerConstructor struct {
- scopeFactory scope.Factory
+ scopeFactory scope.Factory
+ defaultResyncPeriod time.Duration
}
func New(scopeFactory scope.Factory) interfaces.Controller {
- return addressscopeReconcilerConstructor{scopeFactory: scopeFactory}
+ return &addressscopeReconcilerConstructor{scopeFactory: scopeFactory}
}
func (addressscopeReconcilerConstructor) GetName() string {
return controllerName
}
+func (c *addressscopeReconcilerConstructor) SetDefaultResyncPeriod(d time.Duration) {
+ c.defaultResyncPeriod = d
+}
+
var projectDependency = dependency.NewDeletionGuardDependency[*orcv1alpha1.AddressScopeList, *orcv1alpha1.Project](
"spec.resource.projectRef",
func(addressscope *orcv1alpha1.AddressScope) []string {
@@ -75,7 +81,7 @@ var projectImportDependency = dependency.NewDependency[*orcv1alpha1.AddressScope
)
// SetupWithManager sets up the controller with the Manager.
-func (c addressscopeReconcilerConstructor) SetupWithManager(ctx context.Context, mgr ctrl.Manager, options controller.Options) error {
+func (c *addressscopeReconcilerConstructor) SetupWithManager(ctx context.Context, mgr ctrl.Manager, options controller.Options) error {
log := ctrl.LoggerFrom(ctx)
k8sClient := mgr.GetClient()
@@ -109,6 +115,6 @@ func (c addressscopeReconcilerConstructor) SetupWithManager(ctx context.Context,
return err
}
- r := reconciler.NewController(controllerName, mgr.GetClient(), c.scopeFactory, addressscopeHelperFactory{}, addressscopeStatusWriter{})
+ r := reconciler.NewController(controllerName, mgr.GetClient(), c.scopeFactory, addressscopeHelperFactory{}, addressscopeStatusWriter{}, c.defaultResyncPeriod)
return builder.Complete(&r)
}
diff --git a/internal/controllers/addressscope/zz_generated.adapter.go b/internal/controllers/addressscope/zz_generated.adapter.go
index 768861dbd..0bd29eab0 100644
--- a/internal/controllers/addressscope/zz_generated.adapter.go
+++ b/internal/controllers/addressscope/zz_generated.adapter.go
@@ -18,6 +18,8 @@ limitations under the License.
package addressscope
import (
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+
orcv1alpha1 "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1"
"github.com/k-orc/openstack-resource-controller/v2/internal/controllers/generic/interfaces"
)
@@ -55,6 +57,14 @@ func (f adapterT) GetManagedOptions() *orcv1alpha1.ManagedOptions {
return f.Spec.ManagedOptions
}
+func (f adapterT) GetResyncPeriod() *metav1.Duration {
+ return f.Spec.ResyncPeriod
+}
+
+func (f adapterT) GetLastSyncTime() *metav1.Time {
+ return f.Status.LastSyncTime
+}
+
func (f adapterT) GetStatusID() *string {
return f.Status.ID
}
@@ -77,6 +87,10 @@ func (f adapterT) GetImportFilter() *filterT {
return f.Spec.Import.Filter
}
+func (f adapterT) IsImported() bool {
+ return f.GetImportID() != nil || f.GetImportFilter() != nil
+}
+
// getResourceName returns the name of the OpenStack resource we should use.
// This method is not implemented as part of APIObjectAdapter as it is intended
// to be used by resource actuators, which don't use the adapter.
diff --git a/internal/controllers/applicationcredential/controller.go b/internal/controllers/applicationcredential/controller.go
index 4e41a989f..c39cf1d47 100644
--- a/internal/controllers/applicationcredential/controller.go
+++ b/internal/controllers/applicationcredential/controller.go
@@ -19,6 +19,7 @@ package applicationcredential
import (
"context"
"errors"
+ "time"
corev1 "k8s.io/api/core/v1"
ctrl "sigs.k8s.io/controller-runtime"
@@ -94,17 +95,22 @@ var (
)
type applicationcredentialReconcilerConstructor struct {
- scopeFactory scope.Factory
+ scopeFactory scope.Factory
+ defaultResyncPeriod time.Duration
}
func New(scopeFactory scope.Factory) interfaces.Controller {
- return applicationcredentialReconcilerConstructor{scopeFactory: scopeFactory}
+ return &applicationcredentialReconcilerConstructor{scopeFactory: scopeFactory}
}
func (applicationcredentialReconcilerConstructor) GetName() string {
return controllerName
}
+func (c *applicationcredentialReconcilerConstructor) SetDefaultResyncPeriod(d time.Duration) {
+ c.defaultResyncPeriod = d
+}
+
var userDependency = dependency.NewDeletionGuardDependency[*orcv1alpha1.ApplicationCredentialList, *orcv1alpha1.User](
"spec.resource.userRef",
func(applicationcredential *orcv1alpha1.ApplicationCredential) []string {
@@ -129,7 +135,7 @@ var userImportDependency = dependency.NewDependency[*orcv1alpha1.ApplicationCred
)
// SetupWithManager sets up the controller with the Manager.
-func (c applicationcredentialReconcilerConstructor) SetupWithManager(ctx context.Context, mgr ctrl.Manager, options controller.Options) error {
+func (c *applicationcredentialReconcilerConstructor) SetupWithManager(ctx context.Context, mgr ctrl.Manager, options controller.Options) error {
log := ctrl.LoggerFrom(ctx)
k8sClient := mgr.GetClient()
@@ -195,6 +201,6 @@ func (c applicationcredentialReconcilerConstructor) SetupWithManager(ctx context
return err
}
- r := reconciler.NewController(controllerName, mgr.GetClient(), c.scopeFactory, applicationcredentialHelperFactory{}, applicationcredentialStatusWriter{})
+ r := reconciler.NewController(controllerName, mgr.GetClient(), c.scopeFactory, applicationcredentialHelperFactory{}, applicationcredentialStatusWriter{}, c.defaultResyncPeriod)
return builder.Complete(&r)
}
diff --git a/internal/controllers/applicationcredential/zz_generated.adapter.go b/internal/controllers/applicationcredential/zz_generated.adapter.go
index 55f0b5346..2d8b88c7e 100644
--- a/internal/controllers/applicationcredential/zz_generated.adapter.go
+++ b/internal/controllers/applicationcredential/zz_generated.adapter.go
@@ -18,6 +18,8 @@ limitations under the License.
package applicationcredential
import (
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+
orcv1alpha1 "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1"
"github.com/k-orc/openstack-resource-controller/v2/internal/controllers/generic/interfaces"
)
@@ -55,6 +57,14 @@ func (f adapterT) GetManagedOptions() *orcv1alpha1.ManagedOptions {
return f.Spec.ManagedOptions
}
+func (f adapterT) GetResyncPeriod() *metav1.Duration {
+ return f.Spec.ResyncPeriod
+}
+
+func (f adapterT) GetLastSyncTime() *metav1.Time {
+ return f.Status.LastSyncTime
+}
+
func (f adapterT) GetStatusID() *string {
return f.Status.ID
}
@@ -77,6 +87,10 @@ func (f adapterT) GetImportFilter() *filterT {
return f.Spec.Import.Filter
}
+func (f adapterT) IsImported() bool {
+ return f.GetImportID() != nil || f.GetImportFilter() != nil
+}
+
// getResourceName returns the name of the OpenStack resource we should use.
// This method is not implemented as part of APIObjectAdapter as it is intended
// to be used by resource actuators, which don't use the adapter.
diff --git a/internal/controllers/domain/controller.go b/internal/controllers/domain/controller.go
index 38c831aa2..6dfee5eb0 100644
--- a/internal/controllers/domain/controller.go
+++ b/internal/controllers/domain/controller.go
@@ -19,6 +19,7 @@ package domain
import (
"context"
"errors"
+ "time"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/controller"
@@ -37,19 +38,24 @@ const controllerName = "domain"
// +kubebuilder:rbac:groups=openstack.k-orc.cloud,resources=domains/status,verbs=get;update;patch
type domainReconcilerConstructor struct {
- scopeFactory scope.Factory
+ scopeFactory scope.Factory
+ defaultResyncPeriod time.Duration
}
func New(scopeFactory scope.Factory) interfaces.Controller {
- return domainReconcilerConstructor{scopeFactory: scopeFactory}
+ return &domainReconcilerConstructor{scopeFactory: scopeFactory}
}
func (domainReconcilerConstructor) GetName() string {
return controllerName
}
+func (c *domainReconcilerConstructor) SetDefaultResyncPeriod(d time.Duration) {
+ c.defaultResyncPeriod = d
+}
+
// SetupWithManager sets up the controller with the Manager.
-func (c domainReconcilerConstructor) SetupWithManager(ctx context.Context, mgr ctrl.Manager, options controller.Options) error {
+func (c *domainReconcilerConstructor) SetupWithManager(ctx context.Context, mgr ctrl.Manager, options controller.Options) error {
log := ctrl.LoggerFrom(ctx)
builder := ctrl.NewControllerManagedBy(mgr).
@@ -63,6 +69,6 @@ func (c domainReconcilerConstructor) SetupWithManager(ctx context.Context, mgr c
return err
}
- r := reconciler.NewController(controllerName, mgr.GetClient(), c.scopeFactory, domainHelperFactory{}, domainStatusWriter{})
+ r := reconciler.NewController(controllerName, mgr.GetClient(), c.scopeFactory, domainHelperFactory{}, domainStatusWriter{}, c.defaultResyncPeriod)
return builder.Complete(&r)
}
diff --git a/internal/controllers/domain/zz_generated.adapter.go b/internal/controllers/domain/zz_generated.adapter.go
index 6a386af72..049bf7f3b 100644
--- a/internal/controllers/domain/zz_generated.adapter.go
+++ b/internal/controllers/domain/zz_generated.adapter.go
@@ -18,6 +18,8 @@ limitations under the License.
package domain
import (
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+
orcv1alpha1 "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1"
"github.com/k-orc/openstack-resource-controller/v2/internal/controllers/generic/interfaces"
)
@@ -55,6 +57,14 @@ func (f adapterT) GetManagedOptions() *orcv1alpha1.ManagedOptions {
return f.Spec.ManagedOptions
}
+func (f adapterT) GetResyncPeriod() *metav1.Duration {
+ return f.Spec.ResyncPeriod
+}
+
+func (f adapterT) GetLastSyncTime() *metav1.Time {
+ return f.Status.LastSyncTime
+}
+
func (f adapterT) GetStatusID() *string {
return f.Status.ID
}
@@ -77,6 +87,10 @@ func (f adapterT) GetImportFilter() *filterT {
return f.Spec.Import.Filter
}
+func (f adapterT) IsImported() bool {
+ return f.GetImportID() != nil || f.GetImportFilter() != nil
+}
+
// getResourceName returns the name of the OpenStack resource we should use.
// This method is not implemented as part of APIObjectAdapter as it is intended
// to be used by resource actuators, which don't use the adapter.
diff --git a/internal/controllers/endpoint/controller.go b/internal/controllers/endpoint/controller.go
index f1939076e..727cb1025 100644
--- a/internal/controllers/endpoint/controller.go
+++ b/internal/controllers/endpoint/controller.go
@@ -19,6 +19,7 @@ package endpoint
import (
"context"
"errors"
+ "time"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/builder"
@@ -40,17 +41,22 @@ const controllerName = "endpoint"
// +kubebuilder:rbac:groups=openstack.k-orc.cloud,resources=endpoints/status,verbs=get;update;patch
type endpointReconcilerConstructor struct {
- scopeFactory scope.Factory
+ scopeFactory scope.Factory
+ defaultResyncPeriod time.Duration
}
func New(scopeFactory scope.Factory) interfaces.Controller {
- return endpointReconcilerConstructor{scopeFactory: scopeFactory}
+ return &endpointReconcilerConstructor{scopeFactory: scopeFactory}
}
func (endpointReconcilerConstructor) GetName() string {
return controllerName
}
+func (c *endpointReconcilerConstructor) SetDefaultResyncPeriod(d time.Duration) {
+ c.defaultResyncPeriod = d
+}
+
var serviceDependency = dependency.NewDeletionGuardDependency[*orcv1alpha1.EndpointList, *orcv1alpha1.Service](
"spec.resource.serviceRef",
func(endpoint *orcv1alpha1.Endpoint) []string {
@@ -75,7 +81,7 @@ var serviceImportDependency = dependency.NewDependency[*orcv1alpha1.EndpointList
)
// SetupWithManager sets up the controller with the Manager.
-func (c endpointReconcilerConstructor) SetupWithManager(ctx context.Context, mgr ctrl.Manager, options controller.Options) error {
+func (c *endpointReconcilerConstructor) SetupWithManager(ctx context.Context, mgr ctrl.Manager, options controller.Options) error {
log := ctrl.LoggerFrom(ctx)
k8sClient := mgr.GetClient()
@@ -109,6 +115,6 @@ func (c endpointReconcilerConstructor) SetupWithManager(ctx context.Context, mgr
return err
}
- r := reconciler.NewController(controllerName, mgr.GetClient(), c.scopeFactory, endpointHelperFactory{}, endpointStatusWriter{})
+ r := reconciler.NewController(controllerName, mgr.GetClient(), c.scopeFactory, endpointHelperFactory{}, endpointStatusWriter{}, c.defaultResyncPeriod)
return builder.Complete(&r)
}
diff --git a/internal/controllers/endpoint/zz_generated.adapter.go b/internal/controllers/endpoint/zz_generated.adapter.go
index fe95ab43f..8e623451a 100644
--- a/internal/controllers/endpoint/zz_generated.adapter.go
+++ b/internal/controllers/endpoint/zz_generated.adapter.go
@@ -18,6 +18,8 @@ limitations under the License.
package endpoint
import (
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+
orcv1alpha1 "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1"
"github.com/k-orc/openstack-resource-controller/v2/internal/controllers/generic/interfaces"
)
@@ -55,6 +57,14 @@ func (f adapterT) GetManagedOptions() *orcv1alpha1.ManagedOptions {
return f.Spec.ManagedOptions
}
+func (f adapterT) GetResyncPeriod() *metav1.Duration {
+ return f.Spec.ResyncPeriod
+}
+
+func (f adapterT) GetLastSyncTime() *metav1.Time {
+ return f.Status.LastSyncTime
+}
+
func (f adapterT) GetStatusID() *string {
return f.Status.ID
}
@@ -76,3 +86,7 @@ func (f adapterT) GetImportFilter() *filterT {
}
return f.Spec.Import.Filter
}
+
+func (f adapterT) IsImported() bool {
+ return f.GetImportID() != nil || f.GetImportFilter() != nil
+}
diff --git a/internal/controllers/flavor/adapter_test.go b/internal/controllers/flavor/adapter_test.go
new file mode 100644
index 000000000..f182dbc9e
--- /dev/null
+++ b/internal/controllers/flavor/adapter_test.go
@@ -0,0 +1,66 @@
+package flavor
+
+import (
+ "testing"
+
+ "k8s.io/utils/ptr"
+
+ orcv1alpha1 "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1"
+)
+
+func TestFlavorAdapterIsImported(t *testing.T) {
+ tests := []struct {
+ name string
+ spec orcv1alpha1.FlavorSpec
+ want bool
+ }{
+ {
+ name: "no import - created by ORC",
+ spec: orcv1alpha1.FlavorSpec{
+ Resource: &orcv1alpha1.FlavorResourceSpec{},
+ },
+ want: false,
+ },
+ {
+ name: "import is nil - created by ORC",
+ spec: orcv1alpha1.FlavorSpec{
+ Import: nil,
+ },
+ want: false,
+ },
+ {
+ name: "import with non-nil ID",
+ spec: orcv1alpha1.FlavorSpec{
+ Import: &orcv1alpha1.FlavorImport{
+ ID: ptr.To("some-uuid-1234"),
+ },
+ },
+ want: true,
+ },
+ {
+ name: "import with non-nil filter",
+ spec: orcv1alpha1.FlavorSpec{
+ Import: &orcv1alpha1.FlavorImport{
+ Filter: &orcv1alpha1.FlavorFilter{
+ Name: (*orcv1alpha1.OpenStackName)(ptr.To("my-flavor")),
+ },
+ },
+ },
+ want: true,
+ },
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ adapter := flavorAdapter{
+ Flavor: &orcv1alpha1.Flavor{
+ Spec: tt.spec,
+ },
+ }
+ got := adapter.IsImported()
+ if got != tt.want {
+ t.Errorf("IsImported() = %v, want %v", got, tt.want)
+ }
+ })
+ }
+}
diff --git a/internal/controllers/flavor/controller.go b/internal/controllers/flavor/controller.go
index 3b3cd459d..0f76371dd 100644
--- a/internal/controllers/flavor/controller.go
+++ b/internal/controllers/flavor/controller.go
@@ -19,6 +19,7 @@ package flavor
import (
"context"
"errors"
+ "time"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/controller"
@@ -37,19 +38,24 @@ const controllerName = "flavor"
// +kubebuilder:rbac:groups=openstack.k-orc.cloud,resources=flavors/status,verbs=get;update;patch
type flavorReconcilerConstructor struct {
- scopeFactory scope.Factory
+ scopeFactory scope.Factory
+ defaultResyncPeriod time.Duration
}
func New(scopeFactory scope.Factory) interfaces.Controller {
- return flavorReconcilerConstructor{scopeFactory: scopeFactory}
+ return &flavorReconcilerConstructor{scopeFactory: scopeFactory}
}
func (flavorReconcilerConstructor) GetName() string {
return controllerName
}
+func (c *flavorReconcilerConstructor) SetDefaultResyncPeriod(d time.Duration) {
+ c.defaultResyncPeriod = d
+}
+
// SetupWithManager sets up the controller with the Manager.
-func (c flavorReconcilerConstructor) SetupWithManager(ctx context.Context, mgr ctrl.Manager, options controller.Options) error {
+func (c *flavorReconcilerConstructor) SetupWithManager(ctx context.Context, mgr ctrl.Manager, options controller.Options) error {
log := ctrl.LoggerFrom(ctx)
builder := ctrl.NewControllerManagedBy(mgr).
@@ -63,6 +69,6 @@ func (c flavorReconcilerConstructor) SetupWithManager(ctx context.Context, mgr c
return err
}
- r := reconciler.NewController(controllerName, mgr.GetClient(), c.scopeFactory, flavorHelperFactory{}, flavorStatusWriter{})
+ r := reconciler.NewController(controllerName, mgr.GetClient(), c.scopeFactory, flavorHelperFactory{}, flavorStatusWriter{}, c.defaultResyncPeriod)
return builder.Complete(&r)
}
diff --git a/internal/controllers/flavor/zz_generated.adapter.go b/internal/controllers/flavor/zz_generated.adapter.go
index 936fc6735..7c83f8ad7 100644
--- a/internal/controllers/flavor/zz_generated.adapter.go
+++ b/internal/controllers/flavor/zz_generated.adapter.go
@@ -18,6 +18,8 @@ limitations under the License.
package flavor
import (
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+
orcv1alpha1 "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1"
"github.com/k-orc/openstack-resource-controller/v2/internal/controllers/generic/interfaces"
)
@@ -55,6 +57,14 @@ func (f adapterT) GetManagedOptions() *orcv1alpha1.ManagedOptions {
return f.Spec.ManagedOptions
}
+func (f adapterT) GetResyncPeriod() *metav1.Duration {
+ return f.Spec.ResyncPeriod
+}
+
+func (f adapterT) GetLastSyncTime() *metav1.Time {
+ return f.Status.LastSyncTime
+}
+
func (f adapterT) GetStatusID() *string {
return f.Status.ID
}
@@ -77,6 +87,10 @@ func (f adapterT) GetImportFilter() *filterT {
return f.Spec.Import.Filter
}
+func (f adapterT) IsImported() bool {
+ return f.GetImportID() != nil || f.GetImportFilter() != nil
+}
+
// getResourceName returns the name of the OpenStack resource we should use.
// This method is not implemented as part of APIObjectAdapter as it is intended
// to be used by resource actuators, which don't use the adapter.
diff --git a/internal/controllers/floatingip/controller.go b/internal/controllers/floatingip/controller.go
index 6cf68e27b..a573ec340 100644
--- a/internal/controllers/floatingip/controller.go
+++ b/internal/controllers/floatingip/controller.go
@@ -19,6 +19,7 @@ package floatingip
import (
"context"
"errors"
+ "time"
"k8s.io/utils/ptr"
ctrl "sigs.k8s.io/controller-runtime"
@@ -39,17 +40,22 @@ import (
// +kubebuilder:rbac:groups=openstack.k-orc.cloud,resources=floatingips/status,verbs=get;update;patch
type floatingipReconcilerConstructor struct {
- scopeFactory scope.Factory
+ scopeFactory scope.Factory
+ defaultResyncPeriod time.Duration
}
func New(scopeFactory scope.Factory) interfaces.Controller {
- return floatingipReconcilerConstructor{scopeFactory: scopeFactory}
+ return &floatingipReconcilerConstructor{scopeFactory: scopeFactory}
}
func (floatingipReconcilerConstructor) GetName() string {
return controllerName
}
+func (c *floatingipReconcilerConstructor) SetDefaultResyncPeriod(d time.Duration) {
+ c.defaultResyncPeriod = d
+}
+
const controllerName = "floatingip"
var (
@@ -136,7 +142,7 @@ var (
)
// SetupWithManager sets up the controller with the Manager.
-func (c floatingipReconcilerConstructor) SetupWithManager(ctx context.Context, mgr ctrl.Manager, options controller.Options) error {
+func (c *floatingipReconcilerConstructor) SetupWithManager(ctx context.Context, mgr ctrl.Manager, options controller.Options) error {
log := mgr.GetLogger().WithValues("controller", controllerName)
k8sClient := mgr.GetClient()
@@ -217,6 +223,6 @@ func (c floatingipReconcilerConstructor) SetupWithManager(ctx context.Context, m
return err
}
- r := reconciler.NewController(controllerName, k8sClient, c.scopeFactory, floatingipHelperFactory{}, floatingipStatusWriter{})
+ r := reconciler.NewController(controllerName, k8sClient, c.scopeFactory, floatingipHelperFactory{}, floatingipStatusWriter{}, c.defaultResyncPeriod)
return builder.Complete(&r)
}
diff --git a/internal/controllers/floatingip/zz_generated.adapter.go b/internal/controllers/floatingip/zz_generated.adapter.go
index c0ff372fb..62a707dbf 100644
--- a/internal/controllers/floatingip/zz_generated.adapter.go
+++ b/internal/controllers/floatingip/zz_generated.adapter.go
@@ -18,6 +18,8 @@ limitations under the License.
package floatingip
import (
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+
orcv1alpha1 "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1"
"github.com/k-orc/openstack-resource-controller/v2/internal/controllers/generic/interfaces"
)
@@ -55,6 +57,14 @@ func (f adapterT) GetManagedOptions() *orcv1alpha1.ManagedOptions {
return f.Spec.ManagedOptions
}
+func (f adapterT) GetResyncPeriod() *metav1.Duration {
+ return f.Spec.ResyncPeriod
+}
+
+func (f adapterT) GetLastSyncTime() *metav1.Time {
+ return f.Status.LastSyncTime
+}
+
func (f adapterT) GetStatusID() *string {
return f.Status.ID
}
@@ -76,3 +86,7 @@ func (f adapterT) GetImportFilter() *filterT {
}
return f.Spec.Import.Filter
}
+
+func (f adapterT) IsImported() bool {
+ return f.GetImportID() != nil || f.GetImportFilter() != nil
+}
diff --git a/internal/controllers/generic/interfaces/adapter.go b/internal/controllers/generic/interfaces/adapter.go
index 319e19c10..d19da8078 100644
--- a/internal/controllers/generic/interfaces/adapter.go
+++ b/internal/controllers/generic/interfaces/adapter.go
@@ -33,9 +33,18 @@ type APIObjectAdapter[orcObjectPT any, resourceSpecT any, filterT any] interface
GetManagementPolicy() orcv1alpha1.ManagementPolicy
GetManagedOptions() *orcv1alpha1.ManagedOptions
+ GetResyncPeriod() *metav1.Duration
+ GetLastSyncTime() *metav1.Time
GetStatusID() *string
GetResourceSpec() *resourceSpecT
GetImportID() *string
GetImportFilter() *filterT
+
+ // IsImported returns true if the resource was imported (rather than created
+ // by ORC). A resource is considered imported if it has a non-nil importID or
+ // a non-nil importFilter. This is used to decide how to handle external
+ // deletion: imported resources result in a terminal error, while ORC-created
+ // resources are recreated.
+ IsImported() bool
}
diff --git a/internal/controllers/generic/interfaces/controller.go b/internal/controllers/generic/interfaces/controller.go
index 87f81ccef..6872a592b 100644
--- a/internal/controllers/generic/interfaces/controller.go
+++ b/internal/controllers/generic/interfaces/controller.go
@@ -18,6 +18,7 @@ package interfaces
import (
"context"
+ "time"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
@@ -31,6 +32,14 @@ type Controller interface {
GetName() string
}
+// ResyncConfigurable is an optional interface that Controller implementations
+// may satisfy to receive the operator-level default resync period. The manager
+// calls SetDefaultResyncPeriod before SetupWithManager so that the value is
+// available when the controller is built.
+type ResyncConfigurable interface {
+ SetDefaultResyncPeriod(time.Duration)
+}
+
type ResourceController interface {
GetName() string
diff --git a/internal/controllers/generic/interfaces/status.go b/internal/controllers/generic/interfaces/status.go
index b577a364f..7a34c6e3b 100644
--- a/internal/controllers/generic/interfaces/status.go
+++ b/internal/controllers/generic/interfaces/status.go
@@ -35,10 +35,12 @@ type ORCApplyConfig[objectApplyPT any, statusApplyPT ORCStatusApplyConfig[status
}
// ORCStatusApplyConfig is an interface implemented by the status of any apply
-// configuration for an ORC API object. It has Conditions and an ID field.
+// configuration for an ORC API object. It has Conditions, an ID field, and a
+// LastSyncTime field.
type ORCStatusApplyConfig[statusApplyPT any] interface {
WithConditions(...*applyconfigv1.ConditionApplyConfiguration) statusApplyPT
WithID(id string) statusApplyPT
+ WithLastSyncTime(metav1.Time) statusApplyPT
}
// ResourceStatusWriter defines methods for writing an ORC object status
diff --git a/internal/controllers/generic/reconciler/controller.go b/internal/controllers/generic/reconciler/controller.go
index 7571519cd..bb3104b8a 100644
--- a/internal/controllers/generic/reconciler/controller.go
+++ b/internal/controllers/generic/reconciler/controller.go
@@ -19,6 +19,7 @@ package reconciler
import (
"context"
"fmt"
+ "time"
apierrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/api/meta"
@@ -29,6 +30,7 @@ import (
orcv1alpha1 "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1"
"github.com/k-orc/openstack-resource-controller/v2/internal/controllers/generic/interfaces"
"github.com/k-orc/openstack-resource-controller/v2/internal/controllers/generic/progress"
+ "github.com/k-orc/openstack-resource-controller/v2/internal/controllers/generic/resync"
"github.com/k-orc/openstack-resource-controller/v2/internal/controllers/generic/status"
"github.com/k-orc/openstack-resource-controller/v2/internal/logging"
"github.com/k-orc/openstack-resource-controller/v2/internal/scope"
@@ -58,13 +60,15 @@ func NewController[
name string, k8sClient client.Client, scopeFactory scope.Factory,
helperFactory interfaces.ResourceHelperFactory[orcObjectPT, orcObjectT, resourceSpecT, filterT, osResourceT],
statusWriter interfaces.ResourceStatusWriter[orcObjectPT, *osResourceT, objectApplyPT, statusApplyPT],
+ defaultResyncPeriod time.Duration,
) Controller[orcObjectPT, orcObjectT, resourceSpecT, filterT, objectApplyPT, statusApplyPT, statusApplyT, osResourceT] {
return Controller[orcObjectPT, orcObjectT, resourceSpecT, filterT, objectApplyPT, statusApplyPT, statusApplyT, osResourceT]{
- name: name,
- client: k8sClient,
- scopeFactory: scopeFactory,
- helperFactory: helperFactory,
- statusWriter: statusWriter,
+ name: name,
+ client: k8sClient,
+ scopeFactory: scopeFactory,
+ helperFactory: helperFactory,
+ statusWriter: statusWriter,
+ defaultResyncPeriod: defaultResyncPeriod,
}
}
@@ -91,6 +95,13 @@ type Controller[
helperFactory interfaces.ResourceHelperFactory[orcObjectPT, orcObjectT, resourceSpecT, filterT, osResourceT]
statusWriter interfaces.ResourceStatusWriter[orcObjectPT, *osResourceT, objectApplyPT, statusApplyPT]
+
+ // defaultResyncPeriod is the operator-level default resync period passed
+ // from the manager options. It is used as the fallback in
+ // resync.DetermineResyncPeriod when a resource does not specify its own
+ // spec.resyncPeriod. A value of 0 means periodic resync is disabled by
+ // default.
+ defaultResyncPeriod time.Duration
}
func (c *Controller[_, _, _, _, _, _, _, _]) GetName() string {
@@ -140,10 +151,22 @@ func (c *Controller[
// - Progressing condition is present and False, but observedGeneration is old -> reconcile
// - Progressing condition is false and observedGeneration is up to date -> do not reconcile
//
+// If resyncPeriod > 0, periodic resync is also considered:
+// - If lastSyncTime is nil (never synced), reconcile immediately.
+// - If time.Since(lastSyncTime) >= resyncPeriod, a resync is due: reconcile.
+// - If time.Since(lastSyncTime) < resyncPeriod, the next resync is not yet due:
+// do not reconcile (unless condition-based logic above requires it).
+//
+// When resyncPeriod <= 0 (disabled), resync logic is not applied and the
+// existing condition-based behaviour is unchanged.
+//
+// The resync check uses the persisted lastSyncTime so that controller restarts
+// respect the time already elapsed, preventing a thundering herd (TS-015).
+//
// If shouldReconcile is preventing an object from being reconciled which should
// be reconciled, consider if that object's actuator is correctly returning a
// ProgressStatus indicating that the reconciliation should continue.
-func shouldReconcile(obj orcv1alpha1.ObjectWithConditions) bool {
+func shouldReconcile(obj orcv1alpha1.ObjectWithConditions, lastSyncTime *metav1.Time, resyncPeriod time.Duration) bool {
progressing := meta.FindStatusCondition(obj.GetConditions(), orcv1alpha1.ConditionProgressing)
if progressing == nil {
return true
@@ -153,7 +176,22 @@ func shouldReconcile(obj orcv1alpha1.ObjectWithConditions) bool {
return true
}
- return progressing.ObservedGeneration != obj.GetGeneration()
+ if progressing.ObservedGeneration != obj.GetGeneration() {
+ return true
+ }
+
+ // Condition-based check says no reconcile is needed. Now check if a
+ // periodic resync is due.
+ if resyncPeriod > 0 {
+ // Never synced: reconcile immediately.
+ if lastSyncTime == nil {
+ return true
+ }
+ // Resync is due when the elapsed time has reached the period.
+ return time.Since(lastSyncTime.Time) >= resyncPeriod
+ }
+
+ return false
}
func (c *Controller[
@@ -168,7 +206,8 @@ func (c *Controller[
// We do this here rather than in a predicate because predicates only cover
// a single watch. Doing it here means we cover all sources of
// reconciliation, including our dependencies.
- if !shouldReconcile(objAdapter.GetObject()) {
+ effectiveResyncPeriod := resync.DetermineResyncPeriod(objAdapter.GetResyncPeriod(), c.defaultResyncPeriod)
+ if !shouldReconcile(objAdapter.GetObject(), objAdapter.GetLastSyncTime(), effectiveResyncPeriod) {
log.V(logging.Verbose).Info("Status is up to date: not reconciling")
return reconcileStatus
}
@@ -200,8 +239,17 @@ func (c *Controller[
}
if osResource == nil {
- // Programming error: if we don't have a resource we should either have an error or be waiting on something
- return reconcileStatus.WithError(fmt.Errorf("oResource is not set, but no wait events or error"))
+ // GetOrCreateOSResource returns (nil, nil) when a managed, non-imported
+ // resource is detected as externally deleted. Clear status.id so the
+ // next reconciliation enters the standard creation path and assigns a
+ // new ID after the resource is recreated.
+ if objAdapter.GetStatusID() != nil {
+ log.V(logging.Info).Info("Clearing status.id after external deletion to enable recreation")
+ if err := status.ClearStatusID(ctx, c, objAdapter.GetObject()); err != nil {
+ return reconcileStatus.WithError(fmt.Errorf("clearing status ID after external deletion: %w", err))
+ }
+ }
+ return reconcileStatus.WithProgressMessage("OpenStack resource was deleted externally; will recreate on next reconcile")
}
if objAdapter.GetStatusID() == nil {
@@ -229,6 +277,14 @@ func (c *Controller[
}
}
+ // Schedule a resync requeue when the effective resync period is configured,
+ // there is no terminal error, and no other requeue is already pending (TS-006,
+ // TS-008, TS-012). Positive-only jitter of [0%, +20%] is applied to spread
+ // load across resources sharing the same period.
+ if resync.ShouldScheduleResync(effectiveResyncPeriod, reconcileStatus) {
+ reconcileStatus = reconcileStatus.WithRequeue(resync.CalculateJitteredDuration(effectiveResyncPeriod))
+ }
+
return reconcileStatus
}
diff --git a/internal/controllers/generic/reconciler/controller_test.go b/internal/controllers/generic/reconciler/controller_test.go
new file mode 100644
index 000000000..455f9139d
--- /dev/null
+++ b/internal/controllers/generic/reconciler/controller_test.go
@@ -0,0 +1,483 @@
+/*
+Copyright 2025 The ORC Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package reconciler
+
+import (
+ "testing"
+ "time"
+
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+
+ orcv1alpha1 "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1"
+ "github.com/k-orc/openstack-resource-controller/v2/internal/controllers/generic/progress"
+ "github.com/k-orc/openstack-resource-controller/v2/internal/controllers/generic/resync"
+ orcerrors "github.com/k-orc/openstack-resource-controller/v2/internal/util/errors"
+)
+
+// makeObj creates a Flavor object with the given generation and conditions,
+// satisfying orcv1alpha1.ObjectWithConditions.
+func makeObj(generation int64, conditions []metav1.Condition) orcv1alpha1.ObjectWithConditions {
+ f := &orcv1alpha1.Flavor{}
+ f.Generation = generation
+ f.Status.Conditions = conditions
+ return f
+}
+
+// makeProgressingCondition returns a Progressing condition with the given
+// status and observedGeneration.
+func makeProgressingCondition(status metav1.ConditionStatus, observedGeneration int64) metav1.Condition { //nolint:unparam
+ return metav1.Condition{
+ Type: orcv1alpha1.ConditionProgressing,
+ Status: status,
+ ObservedGeneration: observedGeneration,
+ Reason: "Test",
+ }
+}
+
+// agoPtr returns a *metav1.Time that is d in the past.
+func agoPtr(d time.Duration) *metav1.Time {
+ t := metav1.NewTime(time.Now().Add(-d))
+ return &t
+}
+
+// nowPtr returns a *metav1.Time set to approximately now.
+func nowPtr() *metav1.Time {
+ t := metav1.Now()
+ return &t
+}
+
+func TestShouldReconcile_ConditionBased(t *testing.T) {
+ t.Parallel()
+
+ tests := []struct {
+ name string
+ generation int64
+ conditions []metav1.Condition
+ lastSyncTime *metav1.Time
+ resyncPeriod time.Duration
+ want bool
+ }{
+ {
+ name: "no conditions: should reconcile",
+ generation: 1,
+ conditions: nil,
+ want: true,
+ },
+ {
+ name: "Progressing=True up-to-date: should reconcile",
+ generation: 1,
+ conditions: []metav1.Condition{
+ makeProgressingCondition(metav1.ConditionTrue, 1),
+ },
+ want: true,
+ },
+ {
+ name: "Progressing=False up-to-date resync disabled: should not reconcile",
+ generation: 1,
+ conditions: []metav1.Condition{
+ makeProgressingCondition(metav1.ConditionFalse, 1),
+ },
+ resyncPeriod: 0,
+ want: false,
+ },
+ {
+ name: "Progressing=False stale generation: should reconcile",
+ generation: 2,
+ conditions: []metav1.Condition{
+ makeProgressingCondition(metav1.ConditionFalse, 1),
+ },
+ want: true,
+ },
+ }
+
+ for _, tc := range tests {
+ t.Run(tc.name, func(t *testing.T) {
+ t.Parallel()
+
+ obj := makeObj(tc.generation, tc.conditions)
+ got := shouldReconcile(obj, tc.lastSyncTime, tc.resyncPeriod)
+ if got != tc.want {
+ t.Errorf("shouldReconcile() = %v, want %v", got, tc.want)
+ }
+ })
+ }
+}
+
+func TestShouldReconcile_ResyncDisabled(t *testing.T) {
+ t.Parallel()
+
+ // An up-to-date Progressing=False condition prevents reconciliation when
+ // resync is disabled (resyncPeriod <= 0).
+ obj := makeObj(1, []metav1.Condition{
+ makeProgressingCondition(metav1.ConditionFalse, 1),
+ })
+
+ tests := []struct {
+ name string
+ resyncPeriod time.Duration
+ lastSyncTime *metav1.Time
+ }{
+ {
+ name: "resyncPeriod=0 nil lastSyncTime",
+ resyncPeriod: 0,
+ lastSyncTime: nil,
+ },
+ {
+ name: "resyncPeriod=0 old lastSyncTime",
+ resyncPeriod: 0,
+ lastSyncTime: agoPtr(24 * time.Hour),
+ },
+ {
+ name: "negative resyncPeriod",
+ resyncPeriod: -1 * time.Minute,
+ lastSyncTime: nil,
+ },
+ }
+
+ for _, tc := range tests {
+ t.Run(tc.name, func(t *testing.T) {
+ t.Parallel()
+ got := shouldReconcile(obj, tc.lastSyncTime, tc.resyncPeriod)
+ if got {
+ t.Errorf("shouldReconcile() = true; want false when resync disabled (resyncPeriod=%v)", tc.resyncPeriod)
+ }
+ })
+ }
+}
+
+func TestShouldReconcile_ResyncEnabled_NilLastSyncTime(t *testing.T) {
+ t.Parallel()
+
+ // When resyncPeriod > 0 and lastSyncTime is nil (never synced), reconcile
+ // immediately (TS-015: persisted time is absent → treat as overdue).
+ obj := makeObj(1, []metav1.Condition{
+ makeProgressingCondition(metav1.ConditionFalse, 1),
+ })
+
+ got := shouldReconcile(obj, nil, 10*time.Minute)
+ if !got {
+ t.Error("shouldReconcile() = false; want true when lastSyncTime is nil and resyncPeriod > 0")
+ }
+}
+
+func TestShouldReconcile_ResyncEnabled_PeriodElapsed(t *testing.T) {
+ t.Parallel()
+
+ // When time.Since(lastSyncTime) >= resyncPeriod, a resync is due.
+ obj := makeObj(1, []metav1.Condition{
+ makeProgressingCondition(metav1.ConditionFalse, 1),
+ })
+
+ // Last synced 20 minutes ago, period is 10 minutes.
+ got := shouldReconcile(obj, agoPtr(20*time.Minute), 10*time.Minute)
+ if !got {
+ t.Error("shouldReconcile() = false; want true when time.Since(lastSyncTime) >= resyncPeriod")
+ }
+}
+
+func TestShouldReconcile_ResyncEnabled_PeriodNotElapsed(t *testing.T) {
+ t.Parallel()
+
+ // When time.Since(lastSyncTime) < resyncPeriod, no resync is due.
+ obj := makeObj(1, []metav1.Condition{
+ makeProgressingCondition(metav1.ConditionFalse, 1),
+ })
+
+ // Last synced 2 minutes ago, period is 10 minutes.
+ got := shouldReconcile(obj, agoPtr(2*time.Minute), 10*time.Minute)
+ if got {
+ t.Error("shouldReconcile() = true; want false when time.Since(lastSyncTime) < resyncPeriod")
+ }
+}
+
+func TestShouldReconcile_ResyncEnabled_JustPastPeriod(t *testing.T) {
+ t.Parallel()
+
+ // Boundary condition: just past the period should trigger resync (>= semantics).
+ obj := makeObj(1, []metav1.Condition{
+ makeProgressingCondition(metav1.ConditionFalse, 1),
+ })
+
+ resyncPeriod := 10 * time.Minute
+ // Add a small extra to ensure we're past the boundary even accounting for
+ // time elapsed during test execution.
+ lastSyncTime := agoPtr(resyncPeriod + 100*time.Millisecond)
+
+ got := shouldReconcile(obj, lastSyncTime, resyncPeriod)
+ if !got {
+ t.Error("shouldReconcile() = false; want true when time.Since(lastSyncTime) is just past resyncPeriod")
+ }
+}
+
+func TestShouldReconcile_ResyncEnabled_ProgressingTrue_IgnoresResyncNotElapsed(t *testing.T) {
+ t.Parallel()
+
+ // Progressing=True always triggers reconciliation even if resync period has
+ // not elapsed yet (condition-based logic takes priority for positive cases).
+ obj := makeObj(1, []metav1.Condition{
+ makeProgressingCondition(metav1.ConditionTrue, 1),
+ })
+
+ // lastSyncTime is very recent, so resync would say "false".
+ // But Progressing=True means we must reconcile anyway.
+ got := shouldReconcile(obj, nowPtr(), time.Hour)
+ if !got {
+ t.Error("shouldReconcile() = false; want true when Progressing=True regardless of resync period")
+ }
+}
+
+func TestShouldReconcile_ResyncEnabled_ControllerRestart_PersistsLastSyncTime(t *testing.T) {
+ t.Parallel()
+
+ // Thundering-herd prevention (TS-015): after a controller restart,
+ // lastSyncTime is read from the persisted Kubernetes status. If the
+ // persisted time is recent, shouldReconcile should return false so the
+ // controller does not immediately hammer OpenStack for all resources at once.
+ obj := makeObj(1, []metav1.Condition{
+ makeProgressingCondition(metav1.ConditionFalse, 1),
+ })
+
+ resyncPeriod := 30 * time.Minute
+ // Simulated: last sync was 5 minutes ago (persisted from before restart).
+ lastSyncTime := agoPtr(5 * time.Minute)
+
+ got := shouldReconcile(obj, lastSyncTime, resyncPeriod)
+ if got {
+ t.Error("shouldReconcile() = true; want false: controller should respect persisted lastSyncTime after restart (TS-015)")
+ }
+}
+
+func TestShouldReconcile_ExistingBehaviorUnchanged_ResyncPeriodZero(t *testing.T) {
+ t.Parallel()
+
+ // When resyncPeriod is 0 (disabled), shouldReconcile behaves exactly as it
+ // did before the resync feature was added: only condition-based logic applies.
+ tests := []struct {
+ name string
+ generation int64
+ conditions []metav1.Condition
+ want bool
+ }{
+ {
+ name: "no conditions",
+ generation: 1,
+ want: true,
+ },
+ {
+ name: "progressing true",
+ generation: 1,
+ conditions: []metav1.Condition{makeProgressingCondition(metav1.ConditionTrue, 1)},
+ want: true,
+ },
+ {
+ name: "progressing false up-to-date",
+ generation: 1,
+ conditions: []metav1.Condition{makeProgressingCondition(metav1.ConditionFalse, 1)},
+ want: false,
+ },
+ {
+ name: "progressing false stale",
+ generation: 2,
+ conditions: []metav1.Condition{makeProgressingCondition(metav1.ConditionFalse, 1)},
+ want: true,
+ },
+ }
+
+ for _, tc := range tests {
+ t.Run(tc.name, func(t *testing.T) {
+ t.Parallel()
+
+ obj := makeObj(tc.generation, tc.conditions)
+ // resyncPeriod=0 and nil lastSyncTime: pure condition-based behaviour.
+ got := shouldReconcile(obj, nil, 0)
+ if got != tc.want {
+ t.Errorf("shouldReconcile() = %v, want %v (existing behaviour should be unchanged)", got, tc.want)
+ }
+ })
+ }
+}
+
+// scheduleResyncRequeue simulates the resync scheduling logic added to the end
+// of reconcileNormal:
+//
+// if resync.ShouldScheduleResync(effectiveResyncPeriod, reconcileStatus) {
+// reconcileStatus = reconcileStatus.WithRequeue(resync.CalculateJitteredDuration(effectiveResyncPeriod))
+// }
+//
+// This helper allows the following tests to verify the combined behaviour of
+// ShouldScheduleResync and CalculateJitteredDuration without requiring a full
+// Kubernetes environment.
+func scheduleResyncRequeue(reconcileStatus progress.ReconcileStatus, period time.Duration) progress.ReconcileStatus {
+ if resync.ShouldScheduleResync(period, reconcileStatus) {
+ reconcileStatus = reconcileStatus.WithRequeue(resync.CalculateJitteredDuration(period))
+ }
+ return reconcileStatus
+}
+
+// TestResyncRequeue_ScheduledWhenPeriodPositive verifies that a resync requeue
+// is added to a clean ReconcileStatus when resyncPeriod > 0 (TS-006).
+func TestResyncRequeue_ScheduledWhenPeriodPositive(t *testing.T) {
+ t.Parallel()
+
+ const period = 10 * time.Minute
+
+ // A clean (nil) ReconcileStatus represents a successful reconciliation with
+ // no errors and no pending requeue.
+ var rs progress.ReconcileStatus
+ rs = scheduleResyncRequeue(rs, period)
+
+ requeue := rs.GetRequeue()
+ if requeue == 0 {
+ t.Fatal("expected a non-zero requeue duration after resync scheduling; got 0")
+ }
+
+ // The requeue must be within the jitter range [period*1.0, period*1.2) (TS-006).
+ lo := time.Duration(float64(period) * 1.0)
+ hi := time.Duration(float64(period) * 1.2)
+ if requeue < lo || requeue > hi {
+ t.Errorf("resync requeue %v is outside jitter range [%v, %v]", requeue, lo, hi)
+ }
+}
+
+// TestResyncRequeue_NotScheduledWhenPeriodZero verifies that no resync requeue
+// is added when resyncPeriod is zero (disabled).
+func TestResyncRequeue_NotScheduledWhenPeriodZero(t *testing.T) {
+ t.Parallel()
+
+ var rs progress.ReconcileStatus
+ rs = scheduleResyncRequeue(rs, 0)
+
+ if requeue := rs.GetRequeue(); requeue != 0 {
+ t.Errorf("expected no requeue when resyncPeriod=0; got %v", requeue)
+ }
+}
+
+// TestResyncRequeue_NotScheduledWhenPeriodNegative verifies that no resync
+// requeue is added when resyncPeriod is negative (effectively disabled).
+func TestResyncRequeue_NotScheduledWhenPeriodNegative(t *testing.T) {
+ t.Parallel()
+
+ var rs progress.ReconcileStatus
+ rs = scheduleResyncRequeue(rs, -1*time.Minute)
+
+ if requeue := rs.GetRequeue(); requeue != 0 {
+ t.Errorf("expected no requeue when resyncPeriod<0; got %v", requeue)
+ }
+}
+
+// TestResyncRequeue_NotScheduledWhenTerminalError verifies that no resync
+// requeue is scheduled when the ReconcileStatus contains a terminal error
+// (TS-008). Terminal errors indicate the resource is in a non-retryable state;
+// resyncing would be pointless and wasteful.
+func TestResyncRequeue_NotScheduledWhenTerminalError(t *testing.T) {
+ t.Parallel()
+
+ const period = 10 * time.Minute
+
+ termErr := orcerrors.Terminal(orcv1alpha1.ConditionReasonInvalidConfiguration, "invalid config", nil)
+ rs := progress.WrapError(termErr)
+ rs = scheduleResyncRequeue(rs, period)
+
+ if requeue := rs.GetRequeue(); requeue != 0 {
+ t.Errorf("expected no resync requeue on terminal error; got %v", requeue)
+ }
+}
+
+// TestResyncRequeue_NotScheduledWhenRequeueAlreadyPending verifies that no
+// additional resync requeue is scheduled when one is already set (TS-012).
+// This prevents redundant requeues when the reconciler is already waiting on
+// an OpenStack event or dependency.
+func TestResyncRequeue_NotScheduledWhenRequeueAlreadyPending(t *testing.T) {
+ t.Parallel()
+
+ const period = 10 * time.Minute
+ const existingRequeue = 5 * time.Second
+
+ // Simulate a reconcile status that already has a short requeue (e.g., waiting
+ // for an OpenStack resource to become ready).
+ rs := progress.NewReconcileStatus().WithRequeue(existingRequeue)
+ rs = scheduleResyncRequeue(rs, period)
+
+ // The existing requeue must be preserved unchanged; no extra requeue added.
+ if requeue := rs.GetRequeue(); requeue != existingRequeue {
+ t.Errorf("expected existing requeue %v to be preserved; got %v", existingRequeue, requeue)
+ }
+}
+
+// TestResyncRequeue_JitterIsApplied verifies that multiple scheduling calls
+// with the same period produce different requeue durations (jitter is random),
+// and all values are within the expected [+0%, +20%] range (TS-006).
+func TestResyncRequeue_JitterIsApplied(t *testing.T) {
+ t.Parallel()
+
+ const samples = 200
+ period := time.Hour
+
+ lo := time.Duration(float64(period) * 1.0)
+ hi := time.Duration(float64(period) * 1.2)
+
+ unique := make(map[time.Duration]struct{}, samples)
+ for i := range samples {
+ var rs progress.ReconcileStatus
+ rs = scheduleResyncRequeue(rs, period)
+ d := rs.GetRequeue()
+ if d < lo || d > hi {
+ t.Errorf("sample %d: requeue %v outside jitter range [%v, %v]", i, d, lo, hi)
+ }
+ unique[d] = struct{}{}
+ }
+
+ // With 200 samples from a continuous distribution, we expect nearly all
+ // values to be distinct. Require at least 90% uniqueness.
+ minUnique := samples * 9 / 10
+ if len(unique) < minUnique {
+ t.Errorf("jitter appears non-random: only %d unique values out of %d samples (want >= %d)", len(unique), samples, minUnique)
+ }
+}
+
+// TestResyncRequeue_RequeueTimingRange verifies the requeue timing over many
+// samples remains within the [+0%, +20%] jitter window, functioning as an
+// integration check of the scheduling logic used in reconcileNormal (TS-006).
+func TestResyncRequeue_RequeueTimingRange(t *testing.T) {
+ t.Parallel()
+
+ periods := []time.Duration{
+ time.Minute,
+ 10 * time.Minute,
+ time.Hour,
+ 24 * time.Hour,
+ }
+
+ for _, period := range periods {
+ t.Run(period.String(), func(t *testing.T) {
+ t.Parallel()
+
+ lo := time.Duration(float64(period) * 1.0)
+ hi := time.Duration(float64(period) * 1.2)
+
+ for i := range 50 {
+ var rs progress.ReconcileStatus
+ rs = scheduleResyncRequeue(rs, period)
+ d := rs.GetRequeue()
+ if d < lo || d > hi {
+ t.Errorf("sample %d: period=%v requeue=%v outside [%v, %v]",
+ i, period, d, lo, hi)
+ }
+ }
+ })
+ }
+}
diff --git a/internal/controllers/generic/reconciler/resource_actions.go b/internal/controllers/generic/reconciler/resource_actions.go
index 49f4598b1..595605e5a 100644
--- a/internal/controllers/generic/reconciler/resource_actions.go
+++ b/internal/controllers/generic/reconciler/resource_actions.go
@@ -70,7 +70,16 @@ func GetOrCreateOSResource[
osResource, reconcileStatus := actuator.GetOSResourceByID(ctx, *resourceID)
if needsReschedule, err := reconcileStatus.NeedsReschedule(); needsReschedule {
if orcerrors.IsNotFound(err) {
- // An OpenStack resource we previously referenced has been deleted unexpectedly. We can't recover from this.
+ // The OpenStack resource referenced by status.id no longer exists.
+ // For managed, non-imported resources we trigger recreation by returning
+ // nil with no error: the caller will clear status.id and re-enter the
+ // creation path on the next reconcile.
+ // For unmanaged resources or resources that were originally imported we
+ // cannot recreate them, so we return a terminal error.
+ if objAdapter.GetManagementPolicy() == orcv1alpha1.ManagementPolicyManaged && !objAdapter.IsImported() {
+ log.V(logging.Info).Info("OpenStack resource was deleted externally; will signal caller to clear status ID and trigger recreation")
+ return nil, nil
+ }
return osResource, progress.WrapError(
orcerrors.Terminal(orcv1alpha1.ConditionReasonUnrecoverableError, "resource has been deleted from OpenStack"))
} else {
diff --git a/internal/controllers/generic/reconciler/resource_actions_test.go b/internal/controllers/generic/reconciler/resource_actions_test.go
new file mode 100644
index 000000000..ceed2ead4
--- /dev/null
+++ b/internal/controllers/generic/reconciler/resource_actions_test.go
@@ -0,0 +1,217 @@
+/*
+Copyright 2025 The ORC Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+// Package reconciler contains unit tests for external deletion handling in
+// GetOrCreateOSResource.
+//
+// These tests cover all combinations of management policy and import status
+// when a resource's OpenStack counterpart is not found (404), verifying that:
+//
+// - Managed, ORC-created resources trigger recreation (return nil, nil)
+// - Managed, imported-by-ID resources return a terminal error
+// - Managed, imported-by-filter resources return a terminal error
+// - Unmanaged resources return a terminal error
+// - Managed, existing resources continue through the normal update flow
+package reconciler
+
+import (
+ "context"
+ "errors"
+ "testing"
+
+ "github.com/go-logr/logr"
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ "k8s.io/utils/ptr"
+
+ orcv1alpha1 "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1"
+ orcerrors "github.com/k-orc/openstack-resource-controller/v2/internal/util/errors"
+)
+
+// --------------------------------------------------------------------------
+// Helpers for building test Flavors used in external-deletion tests.
+//
+// All helpers pre-set the controller finalizer so that GetOrCreateOSResource
+// does not attempt to call the Kubernetes client to add it.
+// --------------------------------------------------------------------------
+
+// managedFlavorImportedByFilter builds a managed Flavor that was imported via
+// a filter (has a non-nil import.Filter) and whose status.ID is already set.
+// When GetOSResourceByID returns a not-found error, IsImported() returns true
+// because GetImportFilter() is non-nil, so the controller must return a
+// terminal error rather than triggering recreation.
+func managedFlavorImportedByFilter(statusID string) fakeAdapter {
+ return fakeAdapter{
+ Flavor: &orcv1alpha1.Flavor{
+ ObjectMeta: metav1.ObjectMeta{
+ Name: "test-flavor",
+ Namespace: "default",
+ Finalizers: []string{finalizerFor()},
+ },
+ Spec: orcv1alpha1.FlavorSpec{
+ ManagementPolicy: orcv1alpha1.ManagementPolicyManaged,
+ Import: &orcv1alpha1.FlavorImport{
+ Filter: &orcv1alpha1.FlavorFilter{
+ Name: ptr.To[orcv1alpha1.OpenStackName]("my-flavor"),
+ },
+ },
+ },
+ Status: orcv1alpha1.FlavorStatus{
+ ID: ptr.To(statusID),
+ },
+ },
+ }
+}
+
+// --------------------------------------------------------------------------
+// External deletion tests — all use GetOrCreateOSResource directly.
+// --------------------------------------------------------------------------
+
+// TestGetOrCreateOSResource_ExternalDeletion_ManagedOrcCreated verifies that
+// when a managed, ORC-created resource (not imported) is externally deleted,
+// GetOrCreateOSResource returns (nil, nil) to signal the caller should clear
+// status.ID and trigger recreation on the next reconcile.
+func TestGetOrCreateOSResource_ExternalDeletion_ManagedOrcCreated(t *testing.T) {
+ t.Parallel()
+
+ const resourceID = "orc-created-flavor-id"
+
+ actuator := &noWriteActuator{t: t, readByIDErr: notFoundErr()}
+ adapter := managedFlavorWithStatusID(resourceID)
+
+ got, rs := GetOrCreateOSResource(context.Background(), logr.Discard(), &fakeResourceController{}, adapter, actuator)
+
+ // Expect (nil, nil): caller will clear status.id and trigger recreation.
+ needsReschedule, err := rs.NeedsReschedule()
+ if needsReschedule {
+ t.Fatalf("expected no rescheduling for externally-deleted managed resource (recreation path), got needsReschedule=%v err=%v", needsReschedule, err)
+ }
+ if got != nil {
+ t.Errorf("expected nil osResource for recreation path, got %v", got)
+ }
+ if !actuator.getByIDCalled {
+ t.Error("GetOSResourceByID was not called: controller must attempt to fetch the resource")
+ }
+}
+
+// TestGetOrCreateOSResource_ExternalDeletion_ManagedImportedByID verifies that
+// when a managed resource originally imported by ID is externally deleted, the
+// controller returns a terminal error. Recreation is not possible for imported
+// resources because we cannot know the original creation parameters.
+func TestGetOrCreateOSResource_ExternalDeletion_ManagedImportedByID(t *testing.T) {
+ t.Parallel()
+
+ const resourceID = "imported-by-id-flavor-id"
+
+ actuator := &noWriteActuator{t: t, readByIDErr: notFoundErr()}
+ adapter := managedFlavorImportedByID(resourceID)
+
+ _, rs := GetOrCreateOSResource(context.Background(), logr.Discard(), &fakeResourceController{}, adapter, actuator)
+
+ _, err := rs.NeedsReschedule()
+ if err == nil {
+ t.Fatal("expected a terminal error for externally-deleted imported-by-ID resource, got nil")
+ }
+
+ var termErr *orcerrors.TerminalError
+ if !errors.As(err, &termErr) {
+ t.Errorf("expected a TerminalError for externally-deleted imported-by-ID resource, got %T: %v", err, err)
+ }
+ if !actuator.getByIDCalled {
+ t.Error("GetOSResourceByID was not called")
+ }
+}
+
+// TestGetOrCreateOSResource_ExternalDeletion_ManagedImportedByFilter verifies
+// that when a managed resource originally imported via a filter is externally
+// deleted, the controller returns a terminal error. As with import-by-ID,
+// recreation is not possible.
+func TestGetOrCreateOSResource_ExternalDeletion_ManagedImportedByFilter(t *testing.T) {
+ t.Parallel()
+
+ const resourceID = "imported-by-filter-flavor-id"
+
+ actuator := &noWriteActuator{t: t, readByIDErr: notFoundErr()}
+ adapter := managedFlavorImportedByFilter(resourceID)
+
+ _, rs := GetOrCreateOSResource(context.Background(), logr.Discard(), &fakeResourceController{}, adapter, actuator)
+
+ _, err := rs.NeedsReschedule()
+ if err == nil {
+ t.Fatal("expected a terminal error for externally-deleted imported-by-filter resource, got nil")
+ }
+
+ var termErr *orcerrors.TerminalError
+ if !errors.As(err, &termErr) {
+ t.Errorf("expected a TerminalError for externally-deleted imported-by-filter resource, got %T: %v", err, err)
+ }
+ if !actuator.getByIDCalled {
+ t.Error("GetOSResourceByID was not called")
+ }
+}
+
+// TestGetOrCreateOSResource_ExternalDeletion_Unmanaged verifies that when an
+// unmanaged resource is externally deleted (404), the controller returns a
+// terminal error instead of calling CreateResource.
+func TestGetOrCreateOSResource_ExternalDeletion_Unmanaged(t *testing.T) {
+ t.Parallel()
+
+ const resourceID = "unmanaged-deleted-flavor-id"
+
+ actuator := &noWriteActuator{t: t, readByIDErr: notFoundErr()}
+ adapter := unmanagedFlavorWithStatusID(resourceID)
+
+ _, rs := GetOrCreateOSResource(context.Background(), logr.Discard(), &fakeResourceController{}, adapter, actuator)
+
+ _, err := rs.NeedsReschedule()
+ if err == nil {
+ t.Fatal("expected a terminal error for externally-deleted unmanaged resource, got nil")
+ }
+
+ var termErr *orcerrors.TerminalError
+ if !errors.As(err, &termErr) {
+ t.Errorf("expected a TerminalError for externally-deleted unmanaged resource, got %T: %v", err, err)
+ }
+ if !actuator.getByIDCalled {
+ t.Error("GetOSResourceByID was not called: controller must attempt to fetch the resource")
+ }
+}
+
+// TestGetOrCreateOSResource_ExternalDeletion_ManagedResourceExists verifies
+// the normal update flow: when a managed, ORC-created resource still exists in
+// OpenStack, GetOrCreateOSResource returns the resource with a nil reconcile
+// status so the caller proceeds with reconciliation (no recreation, no error).
+func TestGetOrCreateOSResource_ExternalDeletion_ManagedResourceExists(t *testing.T) {
+ t.Parallel()
+
+ const resourceID = "existing-managed-flavor-id"
+ osResource := &fakeOSResource{ID: resourceID}
+
+ actuator := &noWriteActuator{t: t, readByIDResult: osResource}
+ adapter := managedFlavorWithStatusID(resourceID)
+
+ got, rs := GetOrCreateOSResource(context.Background(), logr.Discard(), &fakeResourceController{}, adapter, actuator)
+
+ needsReschedule, err := rs.NeedsReschedule()
+ if needsReschedule {
+ t.Fatalf("expected no rescheduling for existing resource, got needsReschedule=%v err=%v", needsReschedule, err)
+ }
+ if got == nil || got.ID != resourceID {
+ t.Errorf("expected osResource with ID=%q, got %v", resourceID, got)
+ }
+ if !actuator.getByIDCalled {
+ t.Error("GetOSResourceByID was not called")
+ }
+}
diff --git a/internal/controllers/generic/reconciler/resource_actions_unmanaged_test.go b/internal/controllers/generic/reconciler/resource_actions_unmanaged_test.go
new file mode 100644
index 000000000..5aefb135d
--- /dev/null
+++ b/internal/controllers/generic/reconciler/resource_actions_unmanaged_test.go
@@ -0,0 +1,569 @@
+/*
+Copyright 2025 The ORC Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+// Package reconciler contains integration tests verifying that unmanaged ORC
+// resources do not invoke any OpenStack write operations during periodic resync.
+//
+// Acceptance criteria covered (TS-007):
+// - Unmanaged resources update status without invoking actuator updates.
+// - Unmanaged resources still fetch current OpenStack state (read-only).
+// - CreateResource is NEVER called for unmanaged resources.
+// - Actuator reconcilers (GetResourceReconcilers) are NEVER called for
+// unmanaged resources (this is enforced in reconcileNormal).
+//
+// The tests use thin mock types for the actuator so that any unexpected call to
+// a write method (CreateResource) causes the test to fail immediately.
+package reconciler
+
+import (
+ "context"
+ "errors"
+ "iter"
+ "testing"
+
+ "github.com/go-logr/logr"
+ "github.com/gophercloud/gophercloud/v2"
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ "k8s.io/apimachinery/pkg/types"
+ "k8s.io/utils/ptr"
+ "sigs.k8s.io/controller-runtime/pkg/client"
+
+ orcv1alpha1 "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1"
+ "github.com/k-orc/openstack-resource-controller/v2/internal/controllers/generic/interfaces"
+ "github.com/k-orc/openstack-resource-controller/v2/internal/controllers/generic/progress"
+ "github.com/k-orc/openstack-resource-controller/v2/internal/scope"
+ orcerrors "github.com/k-orc/openstack-resource-controller/v2/internal/util/errors"
+ orcstrings "github.com/k-orc/openstack-resource-controller/v2/internal/util/strings"
+)
+
+// --------------------------------------------------------------------------
+// Minimal fake OpenStack resource type used in these tests.
+// --------------------------------------------------------------------------
+
+// fakeOSResource is a stand-in for any OpenStack resource (e.g. flavors.Flavor).
+type fakeOSResource struct {
+ ID string
+}
+
+// --------------------------------------------------------------------------
+// Mock actuator that enforces "no write operations" (TS-007).
+//
+// GetOSResourceByID and ListOSResourcesForImport are read-only operations and
+// are expected to be called for unmanaged resources. CreateResource is a write
+// operation; calling it causes the test to fail immediately.
+// --------------------------------------------------------------------------
+
+type noWriteActuator struct {
+ t *testing.T
+
+ // readByIDResult is returned by GetOSResourceByID.
+ readByIDResult *fakeOSResource
+ readByIDErr error
+
+ // listResult is returned by ListOSResourcesForImport.
+ listResult []*fakeOSResource
+
+ // Track which read methods were called so tests can assert that OpenStack
+ // state was actually fetched.
+ getByIDCalled bool
+ listCalled bool
+}
+
+var _ interfaces.CreateResourceActuator[*orcv1alpha1.Flavor, orcv1alpha1.Flavor, orcv1alpha1.FlavorFilter, fakeOSResource] = &noWriteActuator{}
+
+func (a *noWriteActuator) GetResourceID(r *fakeOSResource) string {
+ return r.ID
+}
+
+// GetOSResourceByID is a read-only operation: allowed for unmanaged resources.
+func (a *noWriteActuator) GetOSResourceByID(_ context.Context, _ string) (*fakeOSResource, progress.ReconcileStatus) {
+ a.getByIDCalled = true
+ if a.readByIDErr != nil {
+ return nil, progress.WrapError(a.readByIDErr)
+ }
+ return a.readByIDResult, nil
+}
+
+// ListOSResourcesForAdoption is only called in the creation flow for managed
+// resources; for unmanaged resources this path should not be reached when
+// statusID or importID is set.
+func (a *noWriteActuator) ListOSResourcesForAdoption(_ context.Context, _ *orcv1alpha1.Flavor) (iter.Seq2[*fakeOSResource, error], bool) {
+ // Return false to signal "no adoption" — this is a safe, read-only path.
+ return nil, false
+}
+
+// ListOSResourcesForImport is a read-only operation: allowed for unmanaged
+// resources using filter-based import.
+func (a *noWriteActuator) ListOSResourcesForImport(_ context.Context, _ *orcv1alpha1.Flavor, _ orcv1alpha1.FlavorFilter) (iter.Seq2[*fakeOSResource, error], progress.ReconcileStatus) {
+ a.listCalled = true
+ return func(yield func(*fakeOSResource, error) bool) {
+ for _, r := range a.listResult {
+ if !yield(r, nil) {
+ return
+ }
+ }
+ }, nil
+}
+
+// CreateResource is a write operation: MUST NOT be called for unmanaged resources (TS-007).
+func (a *noWriteActuator) CreateResource(_ context.Context, _ *orcv1alpha1.Flavor) (*fakeOSResource, progress.ReconcileStatus) {
+ a.t.Fatal("CreateResource was called for an unmanaged resource: this is a write operation and MUST NOT be invoked (TS-007)")
+ return nil, nil
+}
+
+// --------------------------------------------------------------------------
+// fakeAdapter implements interfaces.APIObjectAdapter for *orcv1alpha1.Flavor.
+// It delegates all metav1.Object methods to the underlying Flavor (which
+// embeds metav1.ObjectMeta and therefore implements metav1.Object).
+// --------------------------------------------------------------------------
+
+type fakeAdapter struct {
+ *orcv1alpha1.Flavor
+}
+
+// Ensure fakeAdapter implements APIObjectAdapter at compile time.
+var _ interfaces.APIObjectAdapter[*orcv1alpha1.Flavor, orcv1alpha1.FlavorResourceSpec, orcv1alpha1.FlavorFilter] = fakeAdapter{}
+
+// metav1.Object — all methods delegate to the embedded Flavor (which embeds
+// metav1.ObjectMeta). We override only the methods not provided by embedding
+// because embedding a non-pointer would copy the object and lose write-backs.
+
+func (a fakeAdapter) GetUID() types.UID { return a.Flavor.GetUID() }
+func (a fakeAdapter) SetUID(uid types.UID) { a.Flavor.SetUID(uid) }
+func (a fakeAdapter) GetResourceVersion() string { return a.Flavor.GetResourceVersion() }
+func (a fakeAdapter) SetResourceVersion(v string) { a.Flavor.SetResourceVersion(v) }
+func (a fakeAdapter) GetGeneration() int64 { return a.Flavor.GetGeneration() }
+func (a fakeAdapter) SetGeneration(gen int64) { a.Flavor.SetGeneration(gen) }
+func (a fakeAdapter) GetFinalizers() []string { return a.Flavor.GetFinalizers() }
+func (a fakeAdapter) SetFinalizers(f []string) { a.Flavor.SetFinalizers(f) }
+
+// APIObjectAdapter-specific methods.
+func (a fakeAdapter) GetObject() *orcv1alpha1.Flavor { return a.Flavor }
+
+func (a fakeAdapter) GetManagementPolicy() orcv1alpha1.ManagementPolicy {
+ return a.Spec.ManagementPolicy
+}
+
+func (a fakeAdapter) GetManagedOptions() *orcv1alpha1.ManagedOptions {
+ return a.Spec.ManagedOptions
+}
+
+func (a fakeAdapter) GetResyncPeriod() *metav1.Duration {
+ return a.Spec.ResyncPeriod
+}
+
+func (a fakeAdapter) GetLastSyncTime() *metav1.Time {
+ return a.Status.LastSyncTime
+}
+
+func (a fakeAdapter) GetStatusID() *string {
+ return a.Status.ID
+}
+
+func (a fakeAdapter) GetResourceSpec() *orcv1alpha1.FlavorResourceSpec {
+ return a.Spec.Resource
+}
+
+func (a fakeAdapter) GetImportID() *string {
+ if a.Spec.Import == nil {
+ return nil
+ }
+ return a.Spec.Import.ID
+}
+
+func (a fakeAdapter) GetImportFilter() *orcv1alpha1.FlavorFilter {
+ if a.Spec.Import == nil {
+ return nil
+ }
+ return a.Spec.Import.Filter
+}
+
+func (a fakeAdapter) IsImported() bool {
+ return a.GetImportID() != nil || a.GetImportFilter() != nil
+}
+
+// --------------------------------------------------------------------------
+// fakeResourceController satisfies ResourceController for tests that pre-set
+// the finalizer on the ORC object so that no Kubernetes Patch is needed.
+// --------------------------------------------------------------------------
+
+type fakeResourceController struct{}
+
+var _ ResourceController = &fakeResourceController{}
+
+func (c *fakeResourceController) GetName() string { return "test-controller" }
+
+// GetK8sClient returns nil. If a Kubernetes Patch call is reached during a
+// test, the nil dereference will cause a panic — signalling a bug in either
+// the test setup (finalizer not pre-set) or the reconciler.
+func (c *fakeResourceController) GetK8sClient() client.Client { return nil }
+
+func (c *fakeResourceController) GetScopeFactory() scope.Factory { return nil }
+
+// --------------------------------------------------------------------------
+// Helpers for building test Flavors.
+//
+// All helpers pre-set the controller finalizer so that GetOrCreateOSResource
+// does not attempt to call the Kubernetes client to add it.
+// --------------------------------------------------------------------------
+
+const testControllerName = "test-controller"
+
+// finalizerFor returns the controller finalizer string for testControllerName.
+func finalizerFor() string {
+ return orcstrings.GetFinalizerName(testControllerName)
+}
+
+// unmanagedFlavorWithStatusID builds an unmanaged Flavor whose status.ID is
+// already set (the normal periodic-resync case).
+func unmanagedFlavorWithStatusID(statusID string) fakeAdapter {
+ return fakeAdapter{
+ Flavor: &orcv1alpha1.Flavor{
+ ObjectMeta: metav1.ObjectMeta{
+ Name: "test-flavor",
+ Namespace: "default",
+ Finalizers: []string{finalizerFor()},
+ },
+ Spec: orcv1alpha1.FlavorSpec{
+ ManagementPolicy: orcv1alpha1.ManagementPolicyUnmanaged,
+ Import: &orcv1alpha1.FlavorImport{
+ ID: ptr.To(statusID),
+ },
+ },
+ Status: orcv1alpha1.FlavorStatus{
+ ID: ptr.To(statusID),
+ },
+ },
+ }
+}
+
+// unmanagedFlavorWithImportID builds an unmanaged Flavor that specifies an
+// importID but has no statusID yet (before first reconcile).
+func unmanagedFlavorWithImportID(importID string) fakeAdapter {
+ return fakeAdapter{
+ Flavor: &orcv1alpha1.Flavor{
+ ObjectMeta: metav1.ObjectMeta{
+ Name: "test-flavor",
+ Namespace: "default",
+ Finalizers: []string{finalizerFor()},
+ },
+ Spec: orcv1alpha1.FlavorSpec{
+ ManagementPolicy: orcv1alpha1.ManagementPolicyUnmanaged,
+ Import: &orcv1alpha1.FlavorImport{
+ ID: ptr.To(importID),
+ },
+ },
+ },
+ }
+}
+
+// unmanagedFlavorWithFilter builds an unmanaged Flavor using filter-based
+// import with no statusID.
+func unmanagedFlavorWithFilter(filter orcv1alpha1.FlavorFilter) fakeAdapter {
+ return fakeAdapter{
+ Flavor: &orcv1alpha1.Flavor{
+ ObjectMeta: metav1.ObjectMeta{
+ Name: "test-flavor",
+ Namespace: "default",
+ Finalizers: []string{finalizerFor()},
+ },
+ Spec: orcv1alpha1.FlavorSpec{
+ ManagementPolicy: orcv1alpha1.ManagementPolicyUnmanaged,
+ Import: &orcv1alpha1.FlavorImport{
+ Filter: &filter,
+ },
+ },
+ },
+ }
+}
+
+// unmanagedFlavorNoImport builds an unmanaged Flavor with neither statusID nor
+// import — an invalid configuration that API validation normally prevents.
+func unmanagedFlavorNoImport() fakeAdapter {
+ return fakeAdapter{
+ Flavor: &orcv1alpha1.Flavor{
+ ObjectMeta: metav1.ObjectMeta{
+ Name: "test-flavor",
+ Namespace: "default",
+ Finalizers: []string{finalizerFor()},
+ },
+ Spec: orcv1alpha1.FlavorSpec{
+ ManagementPolicy: orcv1alpha1.ManagementPolicyUnmanaged,
+ },
+ },
+ }
+}
+
+// managedFlavorWithStatusID builds a managed (non-imported) Flavor whose
+// status.ID is already set (the normal steady-state case).
+func managedFlavorWithStatusID(statusID string) fakeAdapter {
+ return fakeAdapter{
+ Flavor: &orcv1alpha1.Flavor{
+ ObjectMeta: metav1.ObjectMeta{
+ Name: "test-flavor",
+ Namespace: "default",
+ Finalizers: []string{finalizerFor()},
+ },
+ Spec: orcv1alpha1.FlavorSpec{
+ ManagementPolicy: orcv1alpha1.ManagementPolicyManaged,
+ Resource: &orcv1alpha1.FlavorResourceSpec{},
+ },
+ Status: orcv1alpha1.FlavorStatus{
+ ID: ptr.To(statusID),
+ },
+ },
+ }
+}
+
+// managedFlavorImportedByID builds a managed Flavor that was imported by ID
+// (has a non-nil import.ID) and whose status.ID is already set.
+func managedFlavorImportedByID(statusID string) fakeAdapter {
+ return fakeAdapter{
+ Flavor: &orcv1alpha1.Flavor{
+ ObjectMeta: metav1.ObjectMeta{
+ Name: "test-flavor",
+ Namespace: "default",
+ Finalizers: []string{finalizerFor()},
+ },
+ Spec: orcv1alpha1.FlavorSpec{
+ ManagementPolicy: orcv1alpha1.ManagementPolicyManaged,
+ Import: &orcv1alpha1.FlavorImport{
+ ID: ptr.To(statusID),
+ },
+ },
+ Status: orcv1alpha1.FlavorStatus{
+ ID: ptr.To(statusID),
+ },
+ },
+ }
+}
+
+// notFoundErr returns a gophercloud not-found error that orcerrors.IsNotFound
+// will recognise.
+func notFoundErr() error {
+ return gophercloud.ErrResourceNotFound{Name: "missing-id", ResourceType: "flavor"}
+}
+
+// --------------------------------------------------------------------------
+// Tests
+// --------------------------------------------------------------------------
+
+// TestGetOrCreateOSResource_UnmanagedByStatusID verifies that for an unmanaged
+// resource whose status.ID is already set (the periodic resync case), only
+// GetOSResourceByID is called. No write operation (CreateResource) must be
+// invoked (TS-007: unmanaged resources update status without invoking actuator
+// updates).
+func TestGetOrCreateOSResource_UnmanagedByStatusID(t *testing.T) {
+ t.Parallel()
+
+ const resourceID = "test-flavor-id"
+ osResource := &fakeOSResource{ID: resourceID}
+
+ actuator := &noWriteActuator{t: t, readByIDResult: osResource}
+ adapter := unmanagedFlavorWithStatusID(resourceID)
+
+ got, rs := GetOrCreateOSResource(context.Background(), logr.Discard(), &fakeResourceController{}, adapter, actuator)
+
+ if needsReschedule, err := rs.NeedsReschedule(); needsReschedule {
+ t.Fatalf("unexpected reconcile status: needsReschedule=%v err=%v", needsReschedule, err)
+ }
+ if got == nil || got.ID != resourceID {
+ t.Errorf("got resource %v, want ID=%q", got, resourceID)
+ }
+ // Verify OpenStack state was fetched (acceptance criterion: unmanaged
+ // resources still fetch current OpenStack state).
+ if !actuator.getByIDCalled {
+ t.Error("GetOSResourceByID was not called: unmanaged resources must still fetch current OpenStack state")
+ }
+ if actuator.listCalled {
+ t.Error("ListOSResourcesForImport was unexpectedly called")
+ }
+}
+
+// TestGetOrCreateOSResource_UnmanagedByImportID verifies that for an unmanaged
+// resource using import-by-ID (no statusID yet), GetOSResourceByID is called
+// as a read-only operation and CreateResource is never invoked (TS-007).
+func TestGetOrCreateOSResource_UnmanagedByImportID(t *testing.T) {
+ t.Parallel()
+
+ const importID = "imported-flavor-id"
+ osResource := &fakeOSResource{ID: importID}
+
+ actuator := &noWriteActuator{t: t, readByIDResult: osResource}
+ adapter := unmanagedFlavorWithImportID(importID)
+
+ got, rs := GetOrCreateOSResource(context.Background(), logr.Discard(), &fakeResourceController{}, adapter, actuator)
+
+ if needsReschedule, err := rs.NeedsReschedule(); needsReschedule {
+ t.Fatalf("unexpected reconcile status: needsReschedule=%v err=%v", needsReschedule, err)
+ }
+ if got == nil || got.ID != importID {
+ t.Errorf("got resource %v, want ID=%q", got, importID)
+ }
+ if !actuator.getByIDCalled {
+ t.Error("GetOSResourceByID was not called: unmanaged resources must still fetch current OpenStack state")
+ }
+}
+
+// TestGetOrCreateOSResource_UnmanagedByFilter verifies that for an unmanaged
+// resource using filter-based import, ListOSResourcesForImport is called as a
+// read-only operation and CreateResource is never invoked (TS-007).
+func TestGetOrCreateOSResource_UnmanagedByFilter(t *testing.T) {
+ t.Parallel()
+
+ osResource := &fakeOSResource{ID: "filter-flavor-id"}
+ filter := orcv1alpha1.FlavorFilter{
+ Name: ptr.To[orcv1alpha1.OpenStackName]("my-flavor"),
+ }
+
+ actuator := &noWriteActuator{t: t, listResult: []*fakeOSResource{osResource}}
+ adapter := unmanagedFlavorWithFilter(filter)
+
+ got, rs := GetOrCreateOSResource(context.Background(), logr.Discard(), &fakeResourceController{}, adapter, actuator)
+
+ if needsReschedule, err := rs.NeedsReschedule(); needsReschedule {
+ t.Fatalf("unexpected reconcile status: needsReschedule=%v err=%v", needsReschedule, err)
+ }
+ if got == nil || got.ID != osResource.ID {
+ t.Errorf("got resource %v, want ID=%q", got, osResource.ID)
+ }
+ if !actuator.listCalled {
+ t.Error("ListOSResourcesForImport was not called: unmanaged resources must still fetch current OpenStack state")
+ }
+}
+
+// TestGetOrCreateOSResource_UnmanagedNoImport verifies that an unmanaged
+// resource with no import configuration returns a terminal error without calling
+// CreateResource (TS-007). API validation should prevent this state in
+// production, but the reconciler must handle it safely.
+func TestGetOrCreateOSResource_UnmanagedNoImport(t *testing.T) {
+ t.Parallel()
+
+ actuator := &noWriteActuator{t: t}
+ adapter := unmanagedFlavorNoImport()
+
+ _, rs := GetOrCreateOSResource(context.Background(), logr.Discard(), &fakeResourceController{}, adapter, actuator)
+
+ _, err := rs.NeedsReschedule()
+ if err == nil {
+ t.Fatal("expected a terminal error for unmanaged resource with no import, got nil")
+ }
+
+ // Verify it is a TerminalError so the controller does not retry uselessly.
+ var termErr *orcerrors.TerminalError
+ if !errors.As(err, &termErr) {
+ t.Errorf("expected a TerminalError, got %T: %v", err, err)
+ }
+
+ if actuator.getByIDCalled {
+ t.Error("GetOSResourceByID was unexpectedly called")
+ }
+ if actuator.listCalled {
+ t.Error("ListOSResourcesForImport was unexpectedly called")
+ }
+}
+
+// TestGetOrCreateOSResource_UnmanagedStatusIDDeleted verifies that when an
+// unmanaged resource's OpenStack resource has been deleted externally (the
+// controller receives a not-found error), the controller returns a terminal
+// error rather than calling CreateResource (TS-007).
+func TestGetOrCreateOSResource_UnmanagedStatusIDDeleted(t *testing.T) {
+ t.Parallel()
+
+ const resourceID = "deleted-flavor-id"
+
+ // Simulate OpenStack returning a 404 / not-found.
+ actuator := &noWriteActuator{t: t, readByIDErr: notFoundErr()}
+ adapter := unmanagedFlavorWithStatusID(resourceID)
+
+ _, rs := GetOrCreateOSResource(context.Background(), logr.Discard(), &fakeResourceController{}, adapter, actuator)
+
+ _, err := rs.NeedsReschedule()
+ if err == nil {
+ t.Fatal("expected an error when OpenStack resource is not found, got nil")
+ }
+
+ // The error must be terminal: the resource was deleted externally and cannot
+ // be recovered by the controller.
+ var termErr *orcerrors.TerminalError
+ if !errors.As(err, &termErr) {
+ t.Errorf("expected a TerminalError for externally-deleted resource, got %T: %v", err, err)
+ }
+
+ // The controller must still have attempted to fetch the resource.
+ if !actuator.getByIDCalled {
+ t.Error("GetOSResourceByID was not called: the controller should attempt to fetch the resource before concluding it is gone")
+ }
+}
+
+// TestGetOrCreateOSResource_ManagedStatusIDDeleted verifies that when a
+// managed (non-imported) resource's OpenStack resource has been deleted
+// externally, the controller returns (nil, nil) to trigger recreation rather
+// than a terminal error.
+func TestGetOrCreateOSResource_ManagedStatusIDDeleted(t *testing.T) {
+ t.Parallel()
+
+ const resourceID = "deleted-managed-flavor-id"
+
+ // Simulate OpenStack returning a 404 / not-found.
+ actuator := &noWriteActuator{t: t, readByIDErr: notFoundErr()}
+ adapter := managedFlavorWithStatusID(resourceID)
+
+ got, rs := GetOrCreateOSResource(context.Background(), logr.Discard(), &fakeResourceController{}, adapter, actuator)
+
+ // Expect (nil, nil): status.id should be cleared and recreation triggered.
+ needsReschedule, err := rs.NeedsReschedule()
+ if needsReschedule {
+ t.Fatalf("expected no rescheduling (nil reconcileStatus) for externally-deleted managed resource, got needsReschedule=%v err=%v", needsReschedule, err)
+ }
+ if got != nil {
+ t.Errorf("expected nil osResource for recreation path, got %v", got)
+ }
+
+ // The controller must still have attempted to fetch the resource.
+ if !actuator.getByIDCalled {
+ t.Error("GetOSResourceByID was not called")
+ }
+}
+
+// TestGetOrCreateOSResource_ManagedImportedByIDDeleted verifies that when a
+// managed resource that was imported by ID has been deleted externally, the
+// controller returns a terminal error (cannot recreate an imported resource).
+func TestGetOrCreateOSResource_ManagedImportedByIDDeleted(t *testing.T) {
+ t.Parallel()
+
+ const resourceID = "deleted-imported-flavor-id"
+
+ // Simulate OpenStack returning a 404 / not-found.
+ actuator := &noWriteActuator{t: t, readByIDErr: notFoundErr()}
+ adapter := managedFlavorImportedByID(resourceID)
+
+ _, rs := GetOrCreateOSResource(context.Background(), logr.Discard(), &fakeResourceController{}, adapter, actuator)
+
+ _, err := rs.NeedsReschedule()
+ if err == nil {
+ t.Fatal("expected a terminal error for externally-deleted imported resource, got nil")
+ }
+
+ var termErr *orcerrors.TerminalError
+ if !errors.As(err, &termErr) {
+ t.Errorf("expected a TerminalError for externally-deleted imported resource, got %T: %v", err, err)
+ }
+
+ if !actuator.getByIDCalled {
+ t.Error("GetOSResourceByID was not called")
+ }
+}
diff --git a/internal/controllers/generic/resync/config.go b/internal/controllers/generic/resync/config.go
new file mode 100644
index 000000000..3d957533a
--- /dev/null
+++ b/internal/controllers/generic/resync/config.go
@@ -0,0 +1,44 @@
+/*
+Copyright 2024 The ORC Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+// Package resync provides helpers for determining the effective resync period
+// for ORC controllers, implementing the configuration resolution hierarchy.
+package resync
+
+import (
+ "time"
+
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+)
+
+// DetermineResyncPeriod resolves the effective resync period using the
+// following hierarchy:
+//
+// 1. If specValue is non-nil and non-zero, return its duration (per-resource
+// override takes precedence).
+// 2. If specValue is explicitly zero (0s), return 0 (resync is disabled
+// regardless of the global default).
+// 3. If specValue is nil, return globalDefault.
+//
+// A return value of 0 means periodic resync is disabled.
+func DetermineResyncPeriod(specValue *metav1.Duration, globalDefault time.Duration) time.Duration {
+ if specValue != nil {
+ // Explicit spec value: use it unconditionally (zero means disabled).
+ return specValue.Duration
+ }
+ // No per-resource override: fall back to the global default.
+ return globalDefault
+}
diff --git a/internal/controllers/generic/resync/config_test.go b/internal/controllers/generic/resync/config_test.go
new file mode 100644
index 000000000..4d3b740d7
--- /dev/null
+++ b/internal/controllers/generic/resync/config_test.go
@@ -0,0 +1,82 @@
+/*
+Copyright 2024 The ORC Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package resync
+
+import (
+ "testing"
+ "time"
+
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+)
+
+func TestDetermineResyncPeriod(t *testing.T) {
+ t.Parallel()
+
+ tests := []struct {
+ name string
+ specValue *metav1.Duration
+ globalDefault time.Duration
+ want time.Duration
+ }{
+ {
+ // TS-004: spec nil, global disabled → disabled
+ name: "spec nil, global 0, returns 0 (disabled)",
+ specValue: nil,
+ globalDefault: 0,
+ want: 0,
+ },
+ {
+ // TS-005: spec nil, global set → use global
+ name: "spec nil, global 1h, returns 1h",
+ specValue: nil,
+ globalDefault: time.Hour,
+ want: time.Hour,
+ },
+ {
+ // TS-010: spec overrides global
+ name: "spec 30m, global 1h, returns 30m (spec overrides)",
+ specValue: &metav1.Duration{Duration: 30 * time.Minute},
+ globalDefault: time.Hour,
+ want: 30 * time.Minute,
+ },
+ {
+ // TS-004 variant: explicit 0s in spec disables resync regardless of global
+ name: "spec 0s (explicit), global 1h, returns 0 (explicitly disabled)",
+ specValue: &metav1.Duration{Duration: 0},
+ globalDefault: time.Hour,
+ want: 0,
+ },
+ {
+ // TS-010 variant: spec enables resync even when global is disabled
+ name: "spec 2h, global 0, returns 2h (spec enables despite global disabled)",
+ specValue: &metav1.Duration{Duration: 2 * time.Hour},
+ globalDefault: 0,
+ want: 2 * time.Hour,
+ },
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ t.Parallel()
+
+ got := DetermineResyncPeriod(tt.specValue, tt.globalDefault)
+ if got != tt.want {
+ t.Errorf("DetermineResyncPeriod() = %v, want %v", got, tt.want)
+ }
+ })
+ }
+}
diff --git a/internal/controllers/generic/resync/scheduler.go b/internal/controllers/generic/resync/scheduler.go
new file mode 100644
index 000000000..9d51be0b4
--- /dev/null
+++ b/internal/controllers/generic/resync/scheduler.go
@@ -0,0 +1,90 @@
+/*
+Copyright 2024 The ORC Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package resync
+
+import (
+ "errors"
+ "math/rand/v2"
+ "time"
+
+ "github.com/k-orc/openstack-resource-controller/v2/internal/controllers/generic/progress"
+ orcerrors "github.com/k-orc/openstack-resource-controller/v2/internal/util/errors"
+)
+
+const (
+ // jitterFactor is the fraction added to the base duration as positive-only
+ // jitter. A value of 0.1 means the jitter range is [0%, +20%], producing
+ // values in [base*1.0, base*1.2). Positive-only jitter ensures the requeue
+ // always fires after resyncPeriod has elapsed, so shouldReconcile always
+ // returns true when the requeue fires.
+ jitterFactor = 0.1
+)
+
+// CalculateJitteredDuration returns a duration in the range [base*1.0, base*1.2)
+// using uniform random positive-only jitter. Jitter prevents thundering-herd
+// problems when many resources share the same resync period: each resource
+// independently picks a slightly different schedule so they do not all reconcile
+// at once.
+//
+// Positive-only jitter guarantees the returned duration is always >= base,
+// ensuring the requeue fires after resyncPeriod has elapsed and shouldReconcile
+// returns true when the requeue fires.
+//
+// Each call produces an independent random value, so multiple resources calling
+// this function with the same base will receive different durations (TS-011).
+func CalculateJitteredDuration(base time.Duration) time.Duration {
+ // rand.Float64() returns a value in [0.0, 1.0).
+ // Multiplying by 2*jitterFactor gives [0.0, 0.2).
+ // Adding 1.0 gives a multiplier in [1.0, 1.2).
+ // This ensures the result is always >= base.
+ multiplier := 1.0 + rand.Float64()*2*jitterFactor //nolint:gosec // math/rand/v2 is fine for jitter
+ return time.Duration(float64(base) * multiplier)
+}
+
+// ShouldScheduleResync reports whether a periodic resync should be scheduled
+// based on the effective resync period and the current reconcile status.
+//
+// It returns false (do not schedule) when:
+// - resyncPeriod <= 0: periodic resync is disabled (TS-007).
+// - reconcileStatus contains a terminal error: the resource is in a
+// non-retryable error state; resync would be pointless (TS-008).
+// - reconcileStatus already requests a requeue: another reconcile is
+// already pending so a resync requeue would be redundant (TS-012).
+//
+// When it returns true, the caller should schedule a requeue after
+// CalculateJitteredDuration(resyncPeriod).
+func ShouldScheduleResync(resyncPeriod time.Duration, reconcileStatus progress.ReconcileStatus) bool {
+ // Resync disabled.
+ if resyncPeriod <= 0 {
+ return false
+ }
+
+ // Terminal error: no further reconciles will help.
+ if err := reconcileStatus.GetError(); err != nil {
+ var terminalError *orcerrors.TerminalError
+ if errors.As(err, &terminalError) {
+ return false
+ }
+ }
+
+ // Another requeue is already pending; avoid adding a redundant one.
+ if reconcileStatus.GetRequeue() > 0 {
+ return false
+ }
+
+ return true
+}
diff --git a/internal/controllers/generic/resync/scheduler_test.go b/internal/controllers/generic/resync/scheduler_test.go
new file mode 100644
index 000000000..b9584a061
--- /dev/null
+++ b/internal/controllers/generic/resync/scheduler_test.go
@@ -0,0 +1,216 @@
+/*
+Copyright 2024 The ORC Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package resync
+
+import (
+ "fmt"
+ "testing"
+ "time"
+
+ orcv1alpha1 "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1"
+ "github.com/k-orc/openstack-resource-controller/v2/internal/controllers/generic/progress"
+ orcerrors "github.com/k-orc/openstack-resource-controller/v2/internal/util/errors"
+)
+
+// TestCalculateJitteredDuration_Range verifies that the returned duration is
+// always within [base*1.0, base*1.2) across many calls (acceptance criterion).
+func TestCalculateJitteredDuration_Range(t *testing.T) {
+ t.Parallel()
+
+ const (
+ base = 10 * time.Minute
+ samples = 1000
+ )
+
+ lo := time.Duration(float64(base) * 1.0)
+ hi := time.Duration(float64(base) * 1.2)
+
+ for i := range samples {
+ d := CalculateJitteredDuration(base)
+ if d < lo || d > hi {
+ t.Errorf("sample %d: CalculateJitteredDuration(%v) = %v, want in [%v, %v]", i, base, d, lo, hi)
+ }
+ }
+}
+
+// TestCalculateJitteredDuration_Uniformity verifies that the jitter
+// distribution is statistically uniform by checking that all 10 buckets across
+// [base*1.0, base*1.2) are populated with at least 1/20th of the expected
+// frequency (very conservative check to avoid flakiness while still catching
+// obvious bias).
+func TestCalculateJitteredDuration_Uniformity(t *testing.T) {
+ t.Parallel()
+
+ const (
+ base = time.Hour
+ samples = 10000
+ buckets = 10
+ )
+
+ lo := float64(base) * 1.0
+ hi := float64(base) * (1 + 2*jitterFactor)
+ width := (hi - lo) / buckets
+
+ counts := make([]int, buckets)
+ for range samples {
+ d := CalculateJitteredDuration(base)
+ idx := int((float64(d) - lo) / width)
+ // Clamp to handle floating-point edge at the top of the range.
+ if idx >= buckets {
+ idx = buckets - 1
+ }
+ if idx < 0 {
+ idx = 0
+ }
+ counts[idx]++
+ }
+
+ // Each bucket should receive roughly samples/buckets hits. Require at
+ // least 1/3 of the expected count to avoid flakiness while catching bias.
+ minExpected := (samples / buckets) / 3
+ for i, c := range counts {
+ if c < minExpected {
+ t.Errorf("bucket %d: count %d is below minimum expected %d (distribution is not uniform)", i, c, minExpected)
+ }
+ }
+}
+
+// TestCalculateJitteredDuration_Independence verifies that multiple resources
+// receive independent jitter values (TS-011): calling the function twice with
+// the same base should produce different values in the vast majority of cases.
+func TestCalculateJitteredDuration_Independence(t *testing.T) {
+ t.Parallel()
+
+ const (
+ base = time.Hour
+ samples = 100
+ )
+
+ unique := make(map[time.Duration]struct{}, samples)
+ for range samples {
+ d := CalculateJitteredDuration(base)
+ unique[d] = struct{}{}
+ }
+
+ // Expect nearly all samples to be distinct. Allow for at most 5%
+ // collisions (extremely conservative; in practice collisions are
+ // essentially impossible with nanosecond precision).
+ minUnique := samples * 95 / 100
+ if len(unique) < minUnique {
+ t.Errorf("CalculateJitteredDuration produced only %d unique values out of %d samples (expected >= %d); values may not be independent", len(unique), samples, minUnique)
+ }
+}
+
+// TestCalculateJitteredDuration_ZeroBase verifies behaviour with a zero base.
+func TestCalculateJitteredDuration_ZeroBase(t *testing.T) {
+ t.Parallel()
+
+ if d := CalculateJitteredDuration(0); d != 0 {
+ t.Errorf("CalculateJitteredDuration(0) = %v, want 0", d)
+ }
+}
+
+// TestShouldScheduleResync covers all documented return-false conditions and
+// the happy path.
+func TestShouldScheduleResync(t *testing.T) {
+ t.Parallel()
+
+ terminalErr := orcerrors.Terminal(orcv1alpha1.ConditionReasonInvalidConfiguration, "bad config")
+ transientErr := fmt.Errorf("transient error")
+
+ tests := []struct {
+ name string
+ resyncPeriod time.Duration
+ reconcileStatus progress.ReconcileStatus
+ want bool
+ }{
+ {
+ // TS-007: resync disabled globally
+ name: "resyncPeriod 0, nil status, returns false",
+ resyncPeriod: 0,
+ reconcileStatus: nil,
+ want: false,
+ },
+ {
+ // resyncPeriod negative: treated as disabled
+ name: "resyncPeriod negative, nil status, returns false",
+ resyncPeriod: -time.Second,
+ reconcileStatus: nil,
+ want: false,
+ },
+ {
+ // TS-008: terminal error → no resync
+ name: "terminal error in status, returns false",
+ resyncPeriod: time.Hour,
+ reconcileStatus: progress.WrapError(terminalErr),
+ want: false,
+ },
+ {
+ // TS-012: requeue already pending → resync is redundant
+ name: "requeue already pending in status, returns false",
+ resyncPeriod: time.Hour,
+ reconcileStatus: progress.NewReconcileStatus().WithRequeue(5 * time.Second),
+ want: false,
+ },
+ {
+ // Happy path: positive period, no terminal error, no pending requeue
+ name: "positive period, nil status, returns true",
+ resyncPeriod: time.Hour,
+ reconcileStatus: nil,
+ want: true,
+ },
+ {
+ // Happy path: transient (non-terminal) error should not suppress resync
+ name: "transient error in status, returns true",
+ resyncPeriod: time.Hour,
+ reconcileStatus: progress.WrapError(transientErr),
+ want: true,
+ },
+ {
+ // Happy path: progress message with no requeue should not suppress resync
+ name: "progress message only, no requeue, returns true",
+ resyncPeriod: time.Hour,
+ reconcileStatus: progress.NewReconcileStatus().WithProgressMessage("waiting for dependency"),
+ want: true,
+ },
+ {
+ // Terminal error takes precedence even when period is positive
+ name: "terminal error with progress message, returns false",
+ resyncPeriod: time.Hour,
+ reconcileStatus: progress.WrapError(terminalErr).WithProgressMessage("some message"),
+ want: false,
+ },
+ {
+ // Requeue takes precedence when period is positive
+ name: "requeue pending with progress message, returns false",
+ resyncPeriod: 30 * time.Minute,
+ reconcileStatus: progress.NewReconcileStatus().WithRequeue(10 * time.Second).WithProgressMessage("waiting"),
+ want: false,
+ },
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ t.Parallel()
+
+ got := ShouldScheduleResync(tt.resyncPeriod, tt.reconcileStatus)
+ if got != tt.want {
+ t.Errorf("ShouldScheduleResync(%v, ...) = %v, want %v", tt.resyncPeriod, got, tt.want)
+ }
+ })
+ }
+}
diff --git a/internal/controllers/generic/status/conditions.go b/internal/controllers/generic/status/conditions.go
index 9ac683150..b154509f1 100644
--- a/internal/controllers/generic/status/conditions.go
+++ b/internal/controllers/generic/status/conditions.go
@@ -40,6 +40,15 @@ func SetCommonConditions[T any](
reconcileStatus progress.ReconcileStatus,
now metav1.Time,
) {
+ // Terminal errors make the resource definitively unavailable.
+ // Override Unknown → False so Available matches the error severity.
+ if availableStatus != metav1.ConditionTrue {
+ var terminalErr *orcerrors.TerminalError
+ if errors.As(reconcileStatus.GetError(), &terminalErr) {
+ availableStatus = metav1.ConditionFalse
+ }
+ }
+
availableCondition := applyconfigv1.Condition().
WithType(orcv1alpha1.ConditionAvailable).
WithStatus(availableStatus).
diff --git a/internal/controllers/generic/status/conditions_test.go b/internal/controllers/generic/status/conditions_test.go
new file mode 100644
index 000000000..266695fa8
--- /dev/null
+++ b/internal/controllers/generic/status/conditions_test.go
@@ -0,0 +1,155 @@
+/*
+Copyright 2025 The ORC Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package status
+
+import (
+ "testing"
+
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+
+ orcv1alpha1 "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1"
+ "github.com/k-orc/openstack-resource-controller/v2/internal/controllers/generic/progress"
+ orcerrors "github.com/k-orc/openstack-resource-controller/v2/internal/util/errors"
+ orcapplyconfigv1alpha1 "github.com/k-orc/openstack-resource-controller/v2/pkg/clients/applyconfiguration/api/v1alpha1"
+)
+
+// TestSetCommonConditions_TerminalErrorOverridesUnknownToFalse verifies that
+// when ResourceAvailableStatus returns ConditionUnknown and a terminal error is
+// present, SetCommonConditions overrides the Available condition to False.
+//
+// This is the fix for the network-external-deletion-import CI failure: when an
+// imported network is externally deleted, ORC sets a terminal error but
+// ResourceAvailableStatus returns ConditionUnknown (because Status.ID is set
+// but the OS resource is nil). The Available condition must be False, not
+// Unknown, when a terminal error is present.
+func TestSetCommonConditions_TerminalErrorOverridesUnknownToFalse(t *testing.T) {
+ t.Parallel()
+
+ flavor := &orcv1alpha1.Flavor{
+ ObjectMeta: metav1.ObjectMeta{
+ Name: "test-flavor",
+ Namespace: "default",
+ },
+ }
+
+ termErr := orcerrors.Terminal(orcv1alpha1.ConditionReasonUnrecoverableError, "resource has been deleted from OpenStack", nil)
+ reconcileStatus := progress.WrapError(termErr)
+
+ applyConfigStatus := orcapplyconfigv1alpha1.FlavorStatus()
+ now := metav1.Now()
+
+ // Call SetCommonConditions with ConditionUnknown (as ResourceAvailableStatus
+ // returns when osResource==nil and Status.ID!=nil) and a terminal error.
+ SetCommonConditions(flavor, applyConfigStatus, metav1.ConditionUnknown, reconcileStatus, now)
+
+ // Find the Available condition in the resulting apply configuration.
+ var availableCondition *metav1.ConditionStatus
+ for i := range applyConfigStatus.Conditions {
+ if applyConfigStatus.Conditions[i].Type != nil && *applyConfigStatus.Conditions[i].Type == orcv1alpha1.ConditionAvailable {
+ availableCondition = applyConfigStatus.Conditions[i].Status
+ break
+ }
+ }
+
+ if availableCondition == nil {
+ t.Fatal("Available condition not set in apply configuration")
+ }
+
+ if *availableCondition != metav1.ConditionFalse {
+ t.Errorf("Available condition status = %q; want %q (terminal error should override Unknown → False)",
+ *availableCondition, metav1.ConditionFalse)
+ }
+}
+
+// TestSetCommonConditions_TerminalErrorWithFalseRemainingFalse verifies that
+// when ResourceAvailableStatus already returns ConditionFalse and a terminal
+// error is present, the Available condition remains False (not changed).
+func TestSetCommonConditions_TerminalErrorWithFalseRemainingFalse(t *testing.T) {
+ t.Parallel()
+
+ flavor := &orcv1alpha1.Flavor{
+ ObjectMeta: metav1.ObjectMeta{
+ Name: "test-flavor",
+ Namespace: "default",
+ },
+ }
+
+ termErr := orcerrors.Terminal(orcv1alpha1.ConditionReasonUnrecoverableError, "resource has been deleted from OpenStack", nil)
+ reconcileStatus := progress.WrapError(termErr)
+
+ applyConfigStatus := orcapplyconfigv1alpha1.FlavorStatus()
+ now := metav1.Now()
+
+ // Call SetCommonConditions with ConditionFalse (resource not found, no ID).
+ SetCommonConditions(flavor, applyConfigStatus, metav1.ConditionFalse, reconcileStatus, now)
+
+ var availableCondition *metav1.ConditionStatus
+ for i := range applyConfigStatus.Conditions {
+ if applyConfigStatus.Conditions[i].Type != nil && *applyConfigStatus.Conditions[i].Type == orcv1alpha1.ConditionAvailable {
+ availableCondition = applyConfigStatus.Conditions[i].Status
+ break
+ }
+ }
+
+ if availableCondition == nil {
+ t.Fatal("Available condition not set in apply configuration")
+ }
+
+ if *availableCondition != metav1.ConditionFalse {
+ t.Errorf("Available condition status = %q; want %q", *availableCondition, metav1.ConditionFalse)
+ }
+}
+
+// TestSetCommonConditions_NoTerminalErrorKeepsUnknown verifies that when
+// ResourceAvailableStatus returns ConditionUnknown and no terminal error is
+// present (e.g. a transient error or progress), the Available condition remains
+// Unknown.
+func TestSetCommonConditions_NoTerminalErrorKeepsUnknown(t *testing.T) {
+ t.Parallel()
+
+ flavor := &orcv1alpha1.Flavor{
+ ObjectMeta: metav1.ObjectMeta{
+ Name: "test-flavor",
+ Namespace: "default",
+ },
+ }
+
+ // Transient error (not terminal) — Available should remain Unknown.
+ reconcileStatus := progress.NewReconcileStatus().WithProgressMessage("waiting for OpenStack")
+
+ applyConfigStatus := orcapplyconfigv1alpha1.FlavorStatus()
+ now := metav1.Now()
+
+ SetCommonConditions(flavor, applyConfigStatus, metav1.ConditionUnknown, reconcileStatus, now)
+
+ var availableCondition *metav1.ConditionStatus
+ for i := range applyConfigStatus.Conditions {
+ if applyConfigStatus.Conditions[i].Type != nil && *applyConfigStatus.Conditions[i].Type == orcv1alpha1.ConditionAvailable {
+ availableCondition = applyConfigStatus.Conditions[i].Status
+ break
+ }
+ }
+
+ if availableCondition == nil {
+ t.Fatal("Available condition not set in apply configuration")
+ }
+
+ if *availableCondition != metav1.ConditionUnknown {
+ t.Errorf("Available condition status = %q; want %q (no terminal error should not change Unknown)",
+ *availableCondition, metav1.ConditionUnknown)
+ }
+}
diff --git a/internal/controllers/generic/status/status.go b/internal/controllers/generic/status/status.go
index 4776d16ae..9dac58c7d 100644
--- a/internal/controllers/generic/status/status.go
+++ b/internal/controllers/generic/status/status.go
@@ -62,6 +62,28 @@ func SetStatusID[
return controller.GetK8sClient().Status().Patch(ctx, orcObject, applyconfigs.Patch(types.MergePatchType, applyConfig))
}
+// ClearStatusID clears the status.id field of an ORC object using a JSON merge
+// patch. This is necessary when an externally deleted managed resource is
+// detected: clearing the ID allows the next reconciliation to enter the
+// standard creation path and assign a new ID after the resource is recreated.
+//
+// A JSON merge patch with an explicit null value is required because the
+// generated apply configuration types use omitempty on the ID field, meaning a
+// nil pointer would simply omit the field rather than clear it.
+func ClearStatusID(ctx context.Context, controller interfaces.ResourceController, orcObject client.Object) error {
+ patch := client.RawPatch(types.MergePatchType, []byte(`{"status":{"id":null}}`))
+ return controller.GetK8sClient().Status().Patch(ctx, orcObject, patch)
+}
+
+// shouldSetLastSyncTime reports whether lastSyncTime should be set on a status
+// update. It returns true only when the reconciliation completed successfully:
+// the reconcileStatus contains neither errors nor progress messages. A requeue
+// alone (e.g., for a periodic resync) does not prevent the update.
+func shouldSetLastSyncTime(reconcileStatus progress.ReconcileStatus) bool {
+ needsReschedule, _ := reconcileStatus.NeedsReschedule()
+ return !needsReschedule
+}
+
func UpdateStatus[
orcObjectPT interface {
client.Object
@@ -100,6 +122,13 @@ func UpdateStatus[
reconcileStatus = reconcileStatus.WithReconcileStatus(availableReconcileStatus)
SetCommonConditions(orcObject, applyConfigStatus, available, reconcileStatus, now)
+ // Set lastSyncTime only on successful reconciliation: no errors and no
+ // progress messages indicate that the controller successfully fetched the
+ // resource state from OpenStack (TS-009, TS-013).
+ if shouldSetLastSyncTime(reconcileStatus) {
+ applyConfigStatus.WithLastSyncTime(now)
+ }
+
// Patch orcObject with the status transaction
k8sClient := controller.GetK8sClient()
ssaFieldOwner := orcstrings.GetSSAFieldOwnerWithTxn(controller.GetName(), orcstrings.SSATransactionStatus)
diff --git a/internal/controllers/generic/status/status_test.go b/internal/controllers/generic/status/status_test.go
new file mode 100644
index 000000000..22b986486
--- /dev/null
+++ b/internal/controllers/generic/status/status_test.go
@@ -0,0 +1,230 @@
+/*
+Copyright 2025 The ORC Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package status
+
+import (
+ "context"
+ "errors"
+ "testing"
+ "time"
+
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ "k8s.io/apimachinery/pkg/runtime"
+ "k8s.io/apimachinery/pkg/types"
+ "k8s.io/utils/ptr"
+ "sigs.k8s.io/controller-runtime/pkg/client"
+ "sigs.k8s.io/controller-runtime/pkg/client/fake"
+
+ orcv1alpha1 "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1"
+ "github.com/k-orc/openstack-resource-controller/v2/internal/controllers/generic/interfaces"
+ "github.com/k-orc/openstack-resource-controller/v2/internal/controllers/generic/progress"
+ "github.com/k-orc/openstack-resource-controller/v2/internal/scope"
+ orcerrors "github.com/k-orc/openstack-resource-controller/v2/internal/util/errors"
+)
+
+// TestShouldSetLastSyncTime_SuccessfulReconciliation verifies that lastSyncTime
+// is set when reconcileStatus is nil (clean success, no errors, no progress
+// messages). This is the common case after a successful OpenStack API read
+// (TS-009, TS-013).
+func TestShouldSetLastSyncTime_SuccessfulReconciliation(t *testing.T) {
+ t.Parallel()
+
+ // nil ReconcileStatus represents a clean, successful reconciliation.
+ var rs progress.ReconcileStatus
+ if !shouldSetLastSyncTime(rs) {
+ t.Error("shouldSetLastSyncTime(nil) = false; want true for successful reconciliation")
+ }
+}
+
+// TestShouldSetLastSyncTime_WithRequeueOnly verifies that a requeue alone
+// (e.g., for a periodic resync) does not prevent lastSyncTime from being set.
+// A pending requeue without errors or progress messages still counts as a
+// successful reconciliation cycle (TS-009).
+func TestShouldSetLastSyncTime_WithRequeueOnly(t *testing.T) {
+ t.Parallel()
+
+ // A requeue alone does not contribute to NeedsReschedule.
+ rs := progress.NewReconcileStatus().WithRequeue(10 * time.Minute)
+ if !shouldSetLastSyncTime(rs) {
+ t.Error("shouldSetLastSyncTime(requeue-only) = false; want true: requeue alone should not prevent lastSyncTime update")
+ }
+}
+
+// TestShouldSetLastSyncTime_WithError verifies that lastSyncTime is NOT set
+// when reconcileStatus contains an error. An error means the controller did not
+// successfully complete the reconciliation cycle (TS-009, TS-013).
+func TestShouldSetLastSyncTime_WithError(t *testing.T) {
+ t.Parallel()
+
+ rs := progress.WrapError(errors.New("transient openstack error"))
+ if shouldSetLastSyncTime(rs) {
+ t.Error("shouldSetLastSyncTime(error) = true; want false: errors should prevent lastSyncTime update")
+ }
+}
+
+// TestShouldSetLastSyncTime_WithTerminalError verifies that lastSyncTime is NOT
+// set when reconcileStatus contains a terminal error. Terminal errors indicate
+// a non-retryable failure; the reconciliation did not succeed (TS-009, TS-013).
+func TestShouldSetLastSyncTime_WithTerminalError(t *testing.T) {
+ t.Parallel()
+
+ termErr := orcerrors.Terminal(orcv1alpha1.ConditionReasonInvalidConfiguration, "invalid configuration", nil)
+ rs := progress.WrapError(termErr)
+ if shouldSetLastSyncTime(rs) {
+ t.Error("shouldSetLastSyncTime(terminal error) = true; want false: terminal errors should prevent lastSyncTime update")
+ }
+}
+
+// TestShouldSetLastSyncTime_WithProgressMessage verifies that lastSyncTime is
+// NOT set when reconcileStatus contains a progress message. Progress messages
+// indicate that the reconciliation is still ongoing (waiting on a dependency,
+// resource not yet ready, etc.) and has not completed successfully (TS-009,
+// TS-013).
+func TestShouldSetLastSyncTime_WithProgressMessage(t *testing.T) {
+ t.Parallel()
+
+ rs := progress.NewReconcileStatus().WithProgressMessage("waiting for resource to become active")
+ if shouldSetLastSyncTime(rs) {
+ t.Error("shouldSetLastSyncTime(progress message) = true; want false: progress messages should prevent lastSyncTime update")
+ }
+}
+
+// TestShouldSetLastSyncTime_WithErrorAndProgressMessage verifies that
+// lastSyncTime is NOT set when reconcileStatus contains both an error and a
+// progress message. Either alone should be sufficient to suppress the update.
+func TestShouldSetLastSyncTime_WithErrorAndProgressMessage(t *testing.T) {
+ t.Parallel()
+
+ rs := progress.WrapError(errors.New("API error")).WithProgressMessage("still waiting")
+ if shouldSetLastSyncTime(rs) {
+ t.Error("shouldSetLastSyncTime(error+progress) = true; want false: any non-success condition should prevent lastSyncTime update")
+ }
+}
+
+// --------------------------------------------------------------------------
+// fakeStatusController implements interfaces.ResourceController for
+// ClearStatusID tests. It wraps a real fake.Client to allow status patch calls.
+// --------------------------------------------------------------------------
+
+type fakeStatusController struct {
+ k8sClient client.Client
+}
+
+var _ interfaces.ResourceController = &fakeStatusController{}
+
+func (c *fakeStatusController) GetName() string { return "test-status-controller" }
+func (c *fakeStatusController) GetK8sClient() client.Client { return c.k8sClient }
+func (c *fakeStatusController) GetScopeFactory() scope.Factory { return nil }
+
+// TestClearStatusID_SendsMergePatchWithNullID verifies that ClearStatusID
+// issues a JSON merge patch that sets status.id to null. The function is
+// expected to be called by reconcileNormal when an externally deleted managed
+// resource is detected (GetOrCreateOSResource returns nil, nil).
+func TestClearStatusID_SendsMergePatchWithNullID(t *testing.T) {
+ t.Parallel()
+
+ const resourceID = "some-os-id"
+
+ // Build a Flavor with status.ID already set (simulating a managed resource
+ // whose OpenStack counterpart was deleted externally).
+ flavor := &orcv1alpha1.Flavor{
+ ObjectMeta: metav1.ObjectMeta{
+ Name: "test-flavor",
+ Namespace: "default",
+ UID: types.UID("test-uid"),
+ },
+ Status: orcv1alpha1.FlavorStatus{
+ ID: ptr.To(resourceID),
+ },
+ }
+
+ // Register the Flavor scheme so the fake client can handle it.
+ scheme := runtime.NewScheme()
+ if err := orcv1alpha1.AddToScheme(scheme); err != nil {
+ t.Fatalf("failed to add orcv1alpha1 to scheme: %v", err)
+ }
+
+ fakeClient := fake.NewClientBuilder().
+ WithScheme(scheme).
+ WithStatusSubresource(&orcv1alpha1.Flavor{}).
+ WithObjects(flavor).
+ Build()
+
+ controller := &fakeStatusController{k8sClient: fakeClient}
+
+ // Call ClearStatusID: should patch status.id to null.
+ if err := ClearStatusID(context.Background(), controller, flavor); err != nil {
+ t.Fatalf("ClearStatusID returned unexpected error: %v", err)
+ }
+
+ // Fetch the updated Flavor and verify status.ID is now nil.
+ updated := &orcv1alpha1.Flavor{}
+ if err := fakeClient.Get(context.Background(), client.ObjectKey{Name: "test-flavor", Namespace: "default"}, updated); err != nil {
+ t.Fatalf("failed to get updated flavor: %v", err)
+ }
+
+ if updated.Status.ID != nil {
+ t.Errorf("status.id = %q after ClearStatusID; want nil (cleared)", *updated.Status.ID)
+ }
+}
+
+// TestClearStatusID_GroupVersionResource verifies that ClearStatusID targets
+// the status subresource (i.e., calls Status().Patch rather than Patch).
+// This is an indirect check: if ClearStatusID called the main Patch instead of
+// Status().Patch, the fake client with WithStatusSubresource would not update
+// the status and the ID would remain set.
+func TestClearStatusID_IdempotentWhenAlreadyNil(t *testing.T) {
+ t.Parallel()
+
+ // Flavor with no status.ID (already cleared or never set).
+ flavor := &orcv1alpha1.Flavor{
+ ObjectMeta: metav1.ObjectMeta{
+ Name: "test-flavor",
+ Namespace: "default",
+ UID: types.UID("test-uid"),
+ },
+ // Status.ID is nil by default.
+ }
+
+ scheme := runtime.NewScheme()
+ if err := orcv1alpha1.AddToScheme(scheme); err != nil {
+ t.Fatalf("failed to add orcv1alpha1 to scheme: %v", err)
+ }
+
+ fakeClient := fake.NewClientBuilder().
+ WithScheme(scheme).
+ WithStatusSubresource(&orcv1alpha1.Flavor{}).
+ WithObjects(flavor).
+ Build()
+
+ controller := &fakeStatusController{k8sClient: fakeClient}
+
+ // ClearStatusID should succeed even when status.id is already nil.
+ if err := ClearStatusID(context.Background(), controller, flavor); err != nil {
+ t.Fatalf("ClearStatusID returned unexpected error on already-nil ID: %v", err)
+ }
+
+ // Status.ID should remain nil.
+ updated := &orcv1alpha1.Flavor{}
+ if err := fakeClient.Get(context.Background(), client.ObjectKey{Name: "test-flavor", Namespace: "default"}, updated); err != nil {
+ t.Fatalf("failed to get flavor after ClearStatusID: %v", err)
+ }
+
+ if updated.Status.ID != nil {
+ t.Errorf("status.id = %q after ClearStatusID on already-nil ID; want nil", *updated.Status.ID)
+ }
+}
diff --git a/internal/controllers/group/controller.go b/internal/controllers/group/controller.go
index 043a22e44..b5378e044 100644
--- a/internal/controllers/group/controller.go
+++ b/internal/controllers/group/controller.go
@@ -19,6 +19,7 @@ package group
import (
"context"
"errors"
+ "time"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/builder"
@@ -40,17 +41,22 @@ const controllerName = "group"
// +kubebuilder:rbac:groups=openstack.k-orc.cloud,resources=groups/status,verbs=get;update;patch
type groupReconcilerConstructor struct {
- scopeFactory scope.Factory
+ scopeFactory scope.Factory
+ defaultResyncPeriod time.Duration
}
func New(scopeFactory scope.Factory) interfaces.Controller {
- return groupReconcilerConstructor{scopeFactory: scopeFactory}
+ return &groupReconcilerConstructor{scopeFactory: scopeFactory}
}
func (groupReconcilerConstructor) GetName() string {
return controllerName
}
+func (c *groupReconcilerConstructor) SetDefaultResyncPeriod(d time.Duration) {
+ c.defaultResyncPeriod = d
+}
+
var domainDependency = dependency.NewDeletionGuardDependency[*orcv1alpha1.GroupList, *orcv1alpha1.Domain](
"spec.resource.domainRef",
func(group *orcv1alpha1.Group) []string {
@@ -75,7 +81,7 @@ var domainImportDependency = dependency.NewDependency[*orcv1alpha1.GroupList, *o
)
// SetupWithManager sets up the controller with the Manager.
-func (c groupReconcilerConstructor) SetupWithManager(ctx context.Context, mgr ctrl.Manager, options controller.Options) error {
+func (c *groupReconcilerConstructor) SetupWithManager(ctx context.Context, mgr ctrl.Manager, options controller.Options) error {
log := ctrl.LoggerFrom(ctx)
k8sClient := mgr.GetClient()
@@ -109,6 +115,6 @@ func (c groupReconcilerConstructor) SetupWithManager(ctx context.Context, mgr ct
return err
}
- r := reconciler.NewController(controllerName, mgr.GetClient(), c.scopeFactory, groupHelperFactory{}, groupStatusWriter{})
+ r := reconciler.NewController(controllerName, mgr.GetClient(), c.scopeFactory, groupHelperFactory{}, groupStatusWriter{}, c.defaultResyncPeriod)
return builder.Complete(&r)
}
diff --git a/internal/controllers/group/zz_generated.adapter.go b/internal/controllers/group/zz_generated.adapter.go
index be06e584f..a0dcb76bf 100644
--- a/internal/controllers/group/zz_generated.adapter.go
+++ b/internal/controllers/group/zz_generated.adapter.go
@@ -18,6 +18,8 @@ limitations under the License.
package group
import (
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+
orcv1alpha1 "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1"
"github.com/k-orc/openstack-resource-controller/v2/internal/controllers/generic/interfaces"
)
@@ -55,6 +57,14 @@ func (f adapterT) GetManagedOptions() *orcv1alpha1.ManagedOptions {
return f.Spec.ManagedOptions
}
+func (f adapterT) GetResyncPeriod() *metav1.Duration {
+ return f.Spec.ResyncPeriod
+}
+
+func (f adapterT) GetLastSyncTime() *metav1.Time {
+ return f.Status.LastSyncTime
+}
+
func (f adapterT) GetStatusID() *string {
return f.Status.ID
}
@@ -77,6 +87,10 @@ func (f adapterT) GetImportFilter() *filterT {
return f.Spec.Import.Filter
}
+func (f adapterT) IsImported() bool {
+ return f.GetImportID() != nil || f.GetImportFilter() != nil
+}
+
// getResourceName returns the name of the OpenStack resource we should use.
// This method is not implemented as part of APIObjectAdapter as it is intended
// to be used by resource actuators, which don't use the adapter.
diff --git a/internal/controllers/image/controller.go b/internal/controllers/image/controller.go
index 2416fa823..f70f3ccdf 100644
--- a/internal/controllers/image/controller.go
+++ b/internal/controllers/image/controller.go
@@ -49,19 +49,24 @@ const (
)
type imageReconcilerConstructor struct {
- scopeFactory scope.Factory
+ scopeFactory scope.Factory
+ defaultResyncPeriod time.Duration
}
func New(scopeFactory scope.Factory) interfaces.Controller {
- return imageReconcilerConstructor{scopeFactory: scopeFactory}
+ return &imageReconcilerConstructor{scopeFactory: scopeFactory}
}
func (imageReconcilerConstructor) GetName() string {
return controllerName
}
+func (c *imageReconcilerConstructor) SetDefaultResyncPeriod(d time.Duration) {
+ c.defaultResyncPeriod = d
+}
+
// SetupWithManager sets up the controller with the Manager.
-func (c imageReconcilerConstructor) SetupWithManager(ctx context.Context, mgr ctrl.Manager, options controller.Options) error {
+func (c *imageReconcilerConstructor) SetupWithManager(ctx context.Context, mgr ctrl.Manager, options controller.Options) error {
log := ctrl.LoggerFrom(ctx)
builder := ctrl.NewControllerManagedBy(mgr).
@@ -75,6 +80,6 @@ func (c imageReconcilerConstructor) SetupWithManager(ctx context.Context, mgr ct
return err
}
- r := reconciler.NewController(controllerName, mgr.GetClient(), c.scopeFactory, imageHelperFactory{}, imageStatusWriter{})
+ r := reconciler.NewController(controllerName, mgr.GetClient(), c.scopeFactory, imageHelperFactory{}, imageStatusWriter{}, c.defaultResyncPeriod)
return builder.Complete(&r)
}
diff --git a/internal/controllers/image/zz_generated.adapter.go b/internal/controllers/image/zz_generated.adapter.go
index fe096571b..3b08097d6 100644
--- a/internal/controllers/image/zz_generated.adapter.go
+++ b/internal/controllers/image/zz_generated.adapter.go
@@ -18,6 +18,8 @@ limitations under the License.
package image
import (
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+
orcv1alpha1 "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1"
"github.com/k-orc/openstack-resource-controller/v2/internal/controllers/generic/interfaces"
)
@@ -55,6 +57,14 @@ func (f adapterT) GetManagedOptions() *orcv1alpha1.ManagedOptions {
return f.Spec.ManagedOptions
}
+func (f adapterT) GetResyncPeriod() *metav1.Duration {
+ return f.Spec.ResyncPeriod
+}
+
+func (f adapterT) GetLastSyncTime() *metav1.Time {
+ return f.Status.LastSyncTime
+}
+
func (f adapterT) GetStatusID() *string {
return f.Status.ID
}
@@ -77,6 +87,10 @@ func (f adapterT) GetImportFilter() *filterT {
return f.Spec.Import.Filter
}
+func (f adapterT) IsImported() bool {
+ return f.GetImportID() != nil || f.GetImportFilter() != nil
+}
+
// getResourceName returns the name of the OpenStack resource we should use.
// This method is not implemented as part of APIObjectAdapter as it is intended
// to be used by resource actuators, which don't use the adapter.
diff --git a/internal/controllers/keypair/controller.go b/internal/controllers/keypair/controller.go
index 64cc7cb73..2d14c04cd 100644
--- a/internal/controllers/keypair/controller.go
+++ b/internal/controllers/keypair/controller.go
@@ -19,6 +19,7 @@ package keypair
import (
"context"
"errors"
+ "time"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/controller"
@@ -37,19 +38,24 @@ const controllerName = "keypair"
// +kubebuilder:rbac:groups=openstack.k-orc.cloud,resources=keypairs/status,verbs=get;update;patch
type keypairReconcilerConstructor struct {
- scopeFactory scope.Factory
+ scopeFactory scope.Factory
+ defaultResyncPeriod time.Duration
}
func New(scopeFactory scope.Factory) interfaces.Controller {
- return keypairReconcilerConstructor{scopeFactory: scopeFactory}
+ return &keypairReconcilerConstructor{scopeFactory: scopeFactory}
}
func (keypairReconcilerConstructor) GetName() string {
return controllerName
}
+func (c *keypairReconcilerConstructor) SetDefaultResyncPeriod(d time.Duration) {
+ c.defaultResyncPeriod = d
+}
+
// SetupWithManager sets up the controller with the Manager.
-func (c keypairReconcilerConstructor) SetupWithManager(ctx context.Context, mgr ctrl.Manager, options controller.Options) error {
+func (c *keypairReconcilerConstructor) SetupWithManager(ctx context.Context, mgr ctrl.Manager, options controller.Options) error {
log := ctrl.LoggerFrom(ctx)
builder := ctrl.NewControllerManagedBy(mgr).
@@ -63,6 +69,6 @@ func (c keypairReconcilerConstructor) SetupWithManager(ctx context.Context, mgr
return err
}
- r := reconciler.NewController(controllerName, mgr.GetClient(), c.scopeFactory, keypairHelperFactory{}, keypairStatusWriter{})
+ r := reconciler.NewController(controllerName, mgr.GetClient(), c.scopeFactory, keypairHelperFactory{}, keypairStatusWriter{}, c.defaultResyncPeriod)
return builder.Complete(&r)
}
diff --git a/internal/controllers/keypair/zz_generated.adapter.go b/internal/controllers/keypair/zz_generated.adapter.go
index d3b72644c..e58d5fab7 100644
--- a/internal/controllers/keypair/zz_generated.adapter.go
+++ b/internal/controllers/keypair/zz_generated.adapter.go
@@ -18,6 +18,8 @@ limitations under the License.
package keypair
import (
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+
orcv1alpha1 "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1"
"github.com/k-orc/openstack-resource-controller/v2/internal/controllers/generic/interfaces"
)
@@ -55,6 +57,14 @@ func (f adapterT) GetManagedOptions() *orcv1alpha1.ManagedOptions {
return f.Spec.ManagedOptions
}
+func (f adapterT) GetResyncPeriod() *metav1.Duration {
+ return f.Spec.ResyncPeriod
+}
+
+func (f adapterT) GetLastSyncTime() *metav1.Time {
+ return f.Status.LastSyncTime
+}
+
func (f adapterT) GetStatusID() *string {
return f.Status.ID
}
@@ -77,6 +87,10 @@ func (f adapterT) GetImportFilter() *filterT {
return f.Spec.Import.Filter
}
+func (f adapterT) IsImported() bool {
+ return f.GetImportID() != nil || f.GetImportFilter() != nil
+}
+
// getResourceName returns the name of the OpenStack resource we should use.
// This method is not implemented as part of APIObjectAdapter as it is intended
// to be used by resource actuators, which don't use the adapter.
diff --git a/internal/controllers/network/controller.go b/internal/controllers/network/controller.go
index a9795133e..f08fdaf0f 100644
--- a/internal/controllers/network/controller.go
+++ b/internal/controllers/network/controller.go
@@ -19,6 +19,7 @@ package network
import (
"context"
"errors"
+ "time"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/builder"
@@ -65,11 +66,12 @@ var (
)
type networkReconcilerConstructor struct {
- scopeFactory scope.Factory
+ scopeFactory scope.Factory
+ defaultResyncPeriod time.Duration
}
func New(scopeFactory scope.Factory) interfaces.Controller {
- return networkReconcilerConstructor{
+ return &networkReconcilerConstructor{
scopeFactory: scopeFactory,
}
}
@@ -78,8 +80,12 @@ func (networkReconcilerConstructor) GetName() string {
return controllerName
}
+func (c *networkReconcilerConstructor) SetDefaultResyncPeriod(d time.Duration) {
+ c.defaultResyncPeriod = d
+}
+
// SetupWithManager sets up the controller with the Manager.
-func (c networkReconcilerConstructor) SetupWithManager(ctx context.Context, mgr ctrl.Manager, options controller.Options) error {
+func (c *networkReconcilerConstructor) SetupWithManager(ctx context.Context, mgr ctrl.Manager, options controller.Options) error {
log := ctrl.LoggerFrom(ctx)
k8sClient := mgr.GetClient()
@@ -113,6 +119,6 @@ func (c networkReconcilerConstructor) SetupWithManager(ctx context.Context, mgr
return err
}
- r := reconciler.NewController(controllerName, mgr.GetClient(), c.scopeFactory, networkHelperFactory{}, networkStatusWriter{})
+ r := reconciler.NewController(controllerName, mgr.GetClient(), c.scopeFactory, networkHelperFactory{}, networkStatusWriter{}, c.defaultResyncPeriod)
return builder.Complete(&r)
}
diff --git a/internal/controllers/network/tests/network-external-deletion-import/00-assert.yaml b/internal/controllers/network/tests/network-external-deletion-import/00-assert.yaml
new file mode 100644
index 000000000..1a9230468
--- /dev/null
+++ b/internal/controllers/network/tests/network-external-deletion-import/00-assert.yaml
@@ -0,0 +1,14 @@
+---
+# Verify the external network is available before proceeding with the import.
+apiVersion: openstack.k-orc.cloud/v1alpha1
+kind: Network
+metadata:
+ name: network-external-deletion-import-external
+status:
+ conditions:
+ - type: Available
+ status: "True"
+ reason: Success
+ - type: Progressing
+ status: "False"
+ reason: Success
diff --git a/internal/controllers/network/tests/network-external-deletion-import/00-create-external.yaml b/internal/controllers/network/tests/network-external-deletion-import/00-create-external.yaml
new file mode 100644
index 000000000..124ecc841
--- /dev/null
+++ b/internal/controllers/network/tests/network-external-deletion-import/00-create-external.yaml
@@ -0,0 +1,15 @@
+---
+# Create a managed network in OpenStack via ORC. This network will later be
+# imported as an unmanaged resource, then deleted externally to verify that
+# ORC produces a terminal error (rather than recreating it).
+apiVersion: openstack.k-orc.cloud/v1alpha1
+kind: Network
+metadata:
+ name: network-external-deletion-import-external
+spec:
+ cloudCredentialsRef:
+ cloudName: openstack
+ secretName: openstack-clouds
+ managementPolicy: managed
+ resource:
+ description: Network from "external-deletion-import" test
diff --git a/internal/controllers/network/tests/network-external-deletion-import/00-secret.yaml b/internal/controllers/network/tests/network-external-deletion-import/00-secret.yaml
new file mode 100644
index 000000000..f0fb63e85
--- /dev/null
+++ b/internal/controllers/network/tests/network-external-deletion-import/00-secret.yaml
@@ -0,0 +1,5 @@
+apiVersion: kuttl.dev/v1beta1
+kind: TestStep
+commands:
+ - command: kubectl create secret generic openstack-clouds --from-file=clouds.yaml=${E2E_KUTTL_OSCLOUDS} ${E2E_KUTTL_CACERT_OPT}
+ namespaced: true
diff --git a/internal/controllers/network/tests/network-external-deletion-import/01-assert.yaml b/internal/controllers/network/tests/network-external-deletion-import/01-assert.yaml
new file mode 100644
index 000000000..4429a2653
--- /dev/null
+++ b/internal/controllers/network/tests/network-external-deletion-import/01-assert.yaml
@@ -0,0 +1,22 @@
+---
+# Verify the imported network is available, confirming the import succeeded.
+apiVersion: openstack.k-orc.cloud/v1alpha1
+kind: Network
+metadata:
+ name: network-external-deletion-import
+status:
+ conditions:
+ - type: Available
+ status: "True"
+ reason: Success
+ - type: Progressing
+ status: "False"
+ reason: Success
+ resource:
+ name: network-external-deletion-import-external
+ description: Network from "external-deletion-import" test
+ adminStateUp: true
+ external: false
+ portSecurityEnabled: true
+ shared: false
+ status: ACTIVE
diff --git a/internal/controllers/network/tests/network-external-deletion-import/01-import-resource.yaml b/internal/controllers/network/tests/network-external-deletion-import/01-import-resource.yaml
new file mode 100644
index 000000000..a87f147bf
--- /dev/null
+++ b/internal/controllers/network/tests/network-external-deletion-import/01-import-resource.yaml
@@ -0,0 +1,19 @@
+---
+# Import the external network into ORC as an unmanaged resource. The import
+# filter uses the unique description to identify the network created in step 00.
+# A short resyncPeriod ensures ORC checks the network state periodically, so
+# external deletion is detected without requiring a manual trigger.
+apiVersion: openstack.k-orc.cloud/v1alpha1
+kind: Network
+metadata:
+ name: network-external-deletion-import
+spec:
+ cloudCredentialsRef:
+ cloudName: openstack
+ secretName: openstack-clouds
+ managementPolicy: unmanaged
+ # resyncPeriod of 10s ensures ORC detects the external deletion quickly.
+ resyncPeriod: 10s
+ import:
+ filter:
+ description: Network from "external-deletion-import" test
diff --git a/internal/controllers/network/tests/network-external-deletion-import/02-assert.yaml b/internal/controllers/network/tests/network-external-deletion-import/02-assert.yaml
new file mode 100644
index 000000000..40d2ed438
--- /dev/null
+++ b/internal/controllers/network/tests/network-external-deletion-import/02-assert.yaml
@@ -0,0 +1,28 @@
+---
+# After the OpenStack network is deleted externally, ORC detects on the next
+# reconcile (within the configured resyncPeriod of 10s) that the resource
+# referenced by status.id no longer exists.
+#
+# Because the resource was originally imported (IsImported() == true), ORC
+# cannot recreate it. Instead it returns a terminal error, which sets both
+# Progressing and Available to False with reason UnrecoverableError.
+#
+# The terminal error prevents any further reconciliation until the spec changes.
+apiVersion: kuttl.dev/v1beta1
+kind: TestAssert
+timeout: 300
+---
+apiVersion: openstack.k-orc.cloud/v1alpha1
+kind: Network
+metadata:
+ name: network-external-deletion-import
+status:
+ conditions:
+ - type: Available
+ message: resource has been deleted from OpenStack
+ status: "False"
+ reason: UnrecoverableError
+ - type: Progressing
+ message: resource has been deleted from OpenStack
+ status: "False"
+ reason: UnrecoverableError
diff --git a/internal/controllers/network/tests/network-external-deletion-import/02-delete-from-openstack.yaml b/internal/controllers/network/tests/network-external-deletion-import/02-delete-from-openstack.yaml
new file mode 100644
index 000000000..04097ee02
--- /dev/null
+++ b/internal/controllers/network/tests/network-external-deletion-import/02-delete-from-openstack.yaml
@@ -0,0 +1,23 @@
+---
+# Delete the OpenStack network directly (bypassing ORC). We get the OpenStack
+# ID from the unmanaged import's status.id and use the OpenStack CLI to remove
+# the network without going through ORC.
+#
+# After this deletion, the unmanaged ORC object (network-external-deletion-import)
+# still has status.id pointing to the now-deleted network. On the next reconcile
+# (triggered by the resyncPeriod), ORC calls GetOSResourceByID and gets NotFound.
+# Since the resource was originally imported (IsImported() == true), ORC cannot
+# recreate it and instead sets a terminal error (UnrecoverableError).
+apiVersion: kuttl.dev/v1beta1
+kind: TestStep
+commands:
+ - script: |
+ # Get the OpenStack ID referenced by the imported (unmanaged) ORC object.
+ NETWORK_ID=$(kubectl get network.openstack.k-orc.cloud network-external-deletion-import \
+ -n ${NAMESPACE} \
+ -o jsonpath='{.status.id}')
+
+ # Delete the network directly in OpenStack, bypassing ORC.
+ cd $(dirname ${E2E_KUTTL_OSCLOUDS})
+ export OS_CLOUD=openstack
+ openstack network delete "${NETWORK_ID}"
diff --git a/internal/controllers/network/tests/network-external-deletion-import/README.md b/internal/controllers/network/tests/network-external-deletion-import/README.md
new file mode 100644
index 000000000..d0969093f
--- /dev/null
+++ b/internal/controllers/network/tests/network-external-deletion-import/README.md
@@ -0,0 +1,27 @@
+# External deletion of an imported (unmanaged) Network produces a terminal error
+
+## Step 00
+
+Create an external managed Network that will be used as the import target,
+and wait for it to become available in OpenStack.
+
+## Step 01
+
+Import the external network into ORC as an unmanaged resource (using an import
+filter). Verify the import succeeds and the network is available.
+
+## Step 02
+
+Delete the external OpenStack network directly (bypassing ORC). On the next
+reconcile, ORC detects that the network referenced by `status.id` no longer
+exists in OpenStack. Because the resource was originally imported (unmanaged),
+ORC cannot recreate it - instead it sets a terminal error condition
+(`UnrecoverableError`) with the message "resource has been deleted from
+OpenStack". No further reconciliation occurs.
+
+## Reference
+
+Tests the external deletion handling for imported/unmanaged resources as
+described in `resource_actions.go`: when a resource was originally imported
+and is found to be missing from OpenStack, ORC returns a terminal error instead
+of attempting recreation.
diff --git a/internal/controllers/network/tests/network-external-deletion/00-assert.yaml b/internal/controllers/network/tests/network-external-deletion/00-assert.yaml
new file mode 100644
index 000000000..ca5fe390e
--- /dev/null
+++ b/internal/controllers/network/tests/network-external-deletion/00-assert.yaml
@@ -0,0 +1,41 @@
+---
+# Verify the network is available and has a status.id set (OpenStack network ID).
+# Record the original ID so we can compare after recreation in step 01.
+apiVersion: kuttl.dev/v1beta1
+kind: TestAssert
+resourceRefs:
+ - apiVersion: openstack.k-orc.cloud/v1alpha1
+ kind: Network
+ name: network-external-deletion
+ ref: network
+assertAll:
+ # Verify the OpenStack ID is set before we delete the network externally.
+ - celExpr: "has(network.status.id) && network.status.id != ''"
+commands:
+ - script: |
+ # Save the original OpenStack network ID for comparison in step 01.
+ kubectl get network.openstack.k-orc.cloud network-external-deletion \
+ -n ${NAMESPACE} \
+ -o jsonpath='{.status.id}' \
+ > /tmp/network-external-deletion-original-id
+---
+apiVersion: openstack.k-orc.cloud/v1alpha1
+kind: Network
+metadata:
+ name: network-external-deletion
+status:
+ conditions:
+ - type: Available
+ status: "True"
+ reason: Success
+ - type: Progressing
+ status: "False"
+ reason: Success
+ resource:
+ name: network-external-deletion
+ description: Network from "external-deletion" test
+ adminStateUp: true
+ external: false
+ portSecurityEnabled: true
+ shared: false
+ status: ACTIVE
diff --git a/internal/controllers/network/tests/network-external-deletion/00-create-resource.yaml b/internal/controllers/network/tests/network-external-deletion/00-create-resource.yaml
new file mode 100644
index 000000000..95d4833ba
--- /dev/null
+++ b/internal/controllers/network/tests/network-external-deletion/00-create-resource.yaml
@@ -0,0 +1,18 @@
+---
+# Create a managed Network resource and wait for ORC to create it in OpenStack.
+# A short resyncPeriod ensures ORC checks the network state periodically, so
+# external deletion is detected without requiring a manual trigger.
+apiVersion: openstack.k-orc.cloud/v1alpha1
+kind: Network
+metadata:
+ name: network-external-deletion
+spec:
+ cloudCredentialsRef:
+ cloudName: openstack
+ secretName: openstack-clouds
+ managementPolicy: managed
+ # resyncPeriod of 10s ensures ORC detects the external deletion quickly
+ # without requiring a watch event or manual trigger.
+ resyncPeriod: 10s
+ resource:
+ description: Network from "external-deletion" test
diff --git a/internal/controllers/network/tests/network-external-deletion/00-secret.yaml b/internal/controllers/network/tests/network-external-deletion/00-secret.yaml
new file mode 100644
index 000000000..f0fb63e85
--- /dev/null
+++ b/internal/controllers/network/tests/network-external-deletion/00-secret.yaml
@@ -0,0 +1,5 @@
+apiVersion: kuttl.dev/v1beta1
+kind: TestStep
+commands:
+ - command: kubectl create secret generic openstack-clouds --from-file=clouds.yaml=${E2E_KUTTL_OSCLOUDS} ${E2E_KUTTL_CACERT_OPT}
+ namespaced: true
diff --git a/internal/controllers/network/tests/network-external-deletion/01-assert.yaml b/internal/controllers/network/tests/network-external-deletion/01-assert.yaml
new file mode 100644
index 000000000..22ab21b1f
--- /dev/null
+++ b/internal/controllers/network/tests/network-external-deletion/01-assert.yaml
@@ -0,0 +1,50 @@
+---
+# After the OpenStack network is deleted externally, ORC detects the deletion
+# via the configured resyncPeriod (10s). ORC clears status.id and recreates the
+# network in OpenStack. Verify that:
+# 1. The network is available again with correct conditions and resource status.
+# 2. The OpenStack ID (status.id) has changed - a brand-new network was created.
+#
+# The timeout is set generously to allow for the resyncPeriod to elapse, the
+# deletion to be detected, and the new network to be created and reach ACTIVE.
+apiVersion: kuttl.dev/v1beta1
+kind: TestAssert
+timeout: 300
+resourceRefs:
+ - apiVersion: openstack.k-orc.cloud/v1alpha1
+ kind: Network
+ name: network-external-deletion
+ ref: network
+assertAll:
+ # The new OpenStack ID must be set and non-empty.
+ - celExpr: "has(network.status.id) && network.status.id != ''"
+commands:
+ - script: |
+ ORIGINAL=$(cat /tmp/network-external-deletion-original-id)
+ CURRENT=$(kubectl get network.openstack.k-orc.cloud network-external-deletion \
+ -n ${NAMESPACE} \
+ -o jsonpath='{.status.id}')
+ # Succeed only when both IDs are set and the new ID differs from the original,
+ # confirming that ORC detected the external deletion and recreated the network.
+ [ -n "${ORIGINAL}" ] && [ -n "${CURRENT}" ] && [ "${CURRENT}" != "${ORIGINAL}" ]
+---
+apiVersion: openstack.k-orc.cloud/v1alpha1
+kind: Network
+metadata:
+ name: network-external-deletion
+status:
+ conditions:
+ - type: Available
+ status: "True"
+ reason: Success
+ - type: Progressing
+ status: "False"
+ reason: Success
+ resource:
+ name: network-external-deletion
+ description: Network from "external-deletion" test
+ adminStateUp: true
+ external: false
+ portSecurityEnabled: true
+ shared: false
+ status: ACTIVE
diff --git a/internal/controllers/network/tests/network-external-deletion/01-delete-from-openstack.yaml b/internal/controllers/network/tests/network-external-deletion/01-delete-from-openstack.yaml
new file mode 100644
index 000000000..b932ef0ce
--- /dev/null
+++ b/internal/controllers/network/tests/network-external-deletion/01-delete-from-openstack.yaml
@@ -0,0 +1,16 @@
+---
+# Delete the network directly in OpenStack, bypassing ORC.
+# This simulates an external deletion event (e.g., an operator accidentally
+# deleting the resource, or a garbage-collection script removing it).
+# The resyncPeriod configured on the ORC object ensures ORC will detect
+# the deletion within the configured period (10s) without needing a manual trigger.
+apiVersion: kuttl.dev/v1beta1
+kind: TestStep
+commands:
+ - script: |
+ NETWORK_ID=$(cat /tmp/network-external-deletion-original-id)
+
+ # Delete the network directly in OpenStack, bypassing ORC.
+ cd $(dirname ${E2E_KUTTL_OSCLOUDS})
+ export OS_CLOUD=openstack
+ openstack network delete "${NETWORK_ID}"
diff --git a/internal/controllers/network/tests/network-external-deletion/README.md b/internal/controllers/network/tests/network-external-deletion/README.md
new file mode 100644
index 000000000..0ebe9310b
--- /dev/null
+++ b/internal/controllers/network/tests/network-external-deletion/README.md
@@ -0,0 +1,29 @@
+# External deletion and recreation of a managed Network
+
+## Step 00
+
+Create a managed Network resource with a short `resyncPeriod` (10s) and wait
+for ORC to create it in OpenStack and report it as available. Record the
+OpenStack network ID assigned by ORC.
+
+The `resyncPeriod` ensures ORC checks the network state periodically, allowing
+it to detect external deletion without requiring a manual trigger or watch event.
+
+## Step 01
+
+Delete the OpenStack network directly (bypassing ORC). ORC detects the deletion
+on the next periodic resync (within 10s), clears `status.id`, and recreates
+the network in OpenStack on the following reconcile.
+
+Verify that:
+- The network is available again with correct conditions and resource status.
+- The OpenStack ID in `status.id` has changed (a new network was created,
+ confirming ORC detected the external deletion and recreated the resource).
+
+## Reference
+
+Tests the external deletion handling for managed resources as described in
+`internal/controllers/generic/reconciler/resource_actions.go`: when a managed,
+non-imported resource is found to be missing from OpenStack (the ID in
+`status.id` no longer exists), ORC clears `status.id` and recreates the
+resource on the next reconcile.
diff --git a/internal/controllers/network/tests/network-resync-disabled/00-assert.yaml b/internal/controllers/network/tests/network-resync-disabled/00-assert.yaml
new file mode 100644
index 000000000..9b0edfd06
--- /dev/null
+++ b/internal/controllers/network/tests/network-resync-disabled/00-assert.yaml
@@ -0,0 +1,33 @@
+---
+# Verify the network is available and lastSyncTime has been set after the
+# initial reconciliation, even with resyncPeriod=0 (disabled periodic resync).
+apiVersion: kuttl.dev/v1beta1
+kind: TestAssert
+resourceRefs:
+ - apiVersion: openstack.k-orc.cloud/v1alpha1
+ kind: Network
+ name: network-resync-disabled
+ ref: network
+assertAll:
+ - celExpr: "has(network.status.lastSyncTime)"
+ - celExpr: "network.status.lastSyncTime != ''"
+---
+apiVersion: openstack.k-orc.cloud/v1alpha1
+kind: Network
+metadata:
+ name: network-resync-disabled
+status:
+ resource:
+ name: network-resync-disabled
+ adminStateUp: true
+ external: false
+ portSecurityEnabled: true
+ shared: false
+ status: ACTIVE
+ conditions:
+ - type: Available
+ status: "True"
+ reason: Success
+ - type: Progressing
+ status: "False"
+ reason: Success
diff --git a/internal/controllers/network/tests/network-resync-disabled/00-create-resource.yaml b/internal/controllers/network/tests/network-resync-disabled/00-create-resource.yaml
new file mode 100644
index 000000000..3e1cf5fff
--- /dev/null
+++ b/internal/controllers/network/tests/network-resync-disabled/00-create-resource.yaml
@@ -0,0 +1,13 @@
+apiVersion: openstack.k-orc.cloud/v1alpha1
+kind: Network
+metadata:
+ name: network-resync-disabled
+spec:
+ cloudCredentialsRef:
+ cloudName: openstack
+ secretName: openstack-clouds
+ managementPolicy: managed
+ # resyncPeriod of 0s explicitly disables periodic resync. The controller
+ # should reconcile the resource once on creation and then not reschedule.
+ resyncPeriod: 0s
+ resource: {}
diff --git a/internal/controllers/network/tests/network-resync-disabled/00-secret.yaml b/internal/controllers/network/tests/network-resync-disabled/00-secret.yaml
new file mode 100644
index 000000000..f0fb63e85
--- /dev/null
+++ b/internal/controllers/network/tests/network-resync-disabled/00-secret.yaml
@@ -0,0 +1,5 @@
+apiVersion: kuttl.dev/v1beta1
+kind: TestStep
+commands:
+ - command: kubectl create secret generic openstack-clouds --from-file=clouds.yaml=${E2E_KUTTL_OSCLOUDS} ${E2E_KUTTL_CACERT_OPT}
+ namespaced: true
diff --git a/internal/controllers/network/tests/network-resync-disabled/01-assert.yaml b/internal/controllers/network/tests/network-resync-disabled/01-assert.yaml
new file mode 100644
index 000000000..a645a3f05
--- /dev/null
+++ b/internal/controllers/network/tests/network-resync-disabled/01-assert.yaml
@@ -0,0 +1,15 @@
+---
+# Verify the network is still available and stable after the waiting period.
+# No changes should have occurred since no resync was triggered.
+apiVersion: openstack.k-orc.cloud/v1alpha1
+kind: Network
+metadata:
+ name: network-resync-disabled
+status:
+ conditions:
+ - type: Available
+ status: "True"
+ reason: Success
+ - type: Progressing
+ status: "False"
+ reason: Success
diff --git a/internal/controllers/network/tests/network-resync-disabled/01-check-no-resync.yaml b/internal/controllers/network/tests/network-resync-disabled/01-check-no-resync.yaml
new file mode 100644
index 000000000..a74663299
--- /dev/null
+++ b/internal/controllers/network/tests/network-resync-disabled/01-check-no-resync.yaml
@@ -0,0 +1,17 @@
+apiVersion: kuttl.dev/v1beta1
+kind: TestStep
+# Record the current lastSyncTime, sleep for 15 seconds (longer than even a
+# fast resync period would trigger), then verify that lastSyncTime has NOT
+# changed. This confirms that resyncPeriod=0 prevents periodic re-reconciliation.
+commands:
+ - script: |
+ INITIAL=$(kubectl get network.openstack.k-orc.cloud network-resync-disabled \
+ -n ${NAMESPACE} \
+ -o jsonpath='{.status.lastSyncTime}')
+ # Sleep longer than any reasonable minimum resync period to confirm no resync fires.
+ sleep 15
+ CURRENT=$(kubectl get network.openstack.k-orc.cloud network-resync-disabled \
+ -n ${NAMESPACE} \
+ -o jsonpath='{.status.lastSyncTime}')
+ # Fail if lastSyncTime changed (would indicate an unexpected resync).
+ [ "${INITIAL}" = "${CURRENT}" ]
diff --git a/internal/controllers/network/tests/network-resync-disabled/README.md b/internal/controllers/network/tests/network-resync-disabled/README.md
new file mode 100644
index 000000000..d97bfc2ff
--- /dev/null
+++ b/internal/controllers/network/tests/network-resync-disabled/README.md
@@ -0,0 +1,21 @@
+# Network with resyncPeriod=0 disables periodic resync
+
+## Step 00
+
+Create a network with `resyncPeriod: 0s` (disabled periodic resync) and verify that:
+- The network becomes available with correct conditions.
+- `lastSyncTime` is set in the status after the first successful reconciliation.
+ (Even with resync disabled, the controller always records the initial sync time.)
+
+## Step 01
+
+Wait for a period longer than the minimum resync period and verify that
+`lastSyncTime` has NOT changed. When `resyncPeriod` is 0 (disabled), the
+controller does not schedule additional reconciliations, so `lastSyncTime`
+should remain stable after the initial reconciliation.
+
+## Reference
+
+Tests that setting `resyncPeriod: 0s` (or omitting resyncPeriod) disables
+periodic resync scheduling. The resource is still reconciled on events (spec
+changes, dependency updates) but not on a timer.
diff --git a/internal/controllers/network/tests/network-resync-jitter/00-assert.yaml b/internal/controllers/network/tests/network-resync-jitter/00-assert.yaml
new file mode 100644
index 000000000..f19a692d1
--- /dev/null
+++ b/internal/controllers/network/tests/network-resync-jitter/00-assert.yaml
@@ -0,0 +1,61 @@
+---
+# Verify all three networks are available and each has lastSyncTime set after
+# the initial successful reconciliation.
+apiVersion: kuttl.dev/v1beta1
+kind: TestAssert
+resourceRefs:
+ - apiVersion: openstack.k-orc.cloud/v1alpha1
+ kind: Network
+ name: network-resync-jitter-1
+ ref: network1
+ - apiVersion: openstack.k-orc.cloud/v1alpha1
+ kind: Network
+ name: network-resync-jitter-2
+ ref: network2
+ - apiVersion: openstack.k-orc.cloud/v1alpha1
+ kind: Network
+ name: network-resync-jitter-3
+ ref: network3
+assertAll:
+ - celExpr: "has(network1.status.lastSyncTime) && network1.status.lastSyncTime != ''"
+ - celExpr: "has(network2.status.lastSyncTime) && network2.status.lastSyncTime != ''"
+ - celExpr: "has(network3.status.lastSyncTime) && network3.status.lastSyncTime != ''"
+---
+apiVersion: openstack.k-orc.cloud/v1alpha1
+kind: Network
+metadata:
+ name: network-resync-jitter-1
+status:
+ conditions:
+ - type: Available
+ status: "True"
+ reason: Success
+ - type: Progressing
+ status: "False"
+ reason: Success
+---
+apiVersion: openstack.k-orc.cloud/v1alpha1
+kind: Network
+metadata:
+ name: network-resync-jitter-2
+status:
+ conditions:
+ - type: Available
+ status: "True"
+ reason: Success
+ - type: Progressing
+ status: "False"
+ reason: Success
+---
+apiVersion: openstack.k-orc.cloud/v1alpha1
+kind: Network
+metadata:
+ name: network-resync-jitter-3
+status:
+ conditions:
+ - type: Available
+ status: "True"
+ reason: Success
+ - type: Progressing
+ status: "False"
+ reason: Success
diff --git a/internal/controllers/network/tests/network-resync-jitter/00-create-resources.yaml b/internal/controllers/network/tests/network-resync-jitter/00-create-resources.yaml
new file mode 100644
index 000000000..87bc8a883
--- /dev/null
+++ b/internal/controllers/network/tests/network-resync-jitter/00-create-resources.yaml
@@ -0,0 +1,39 @@
+---
+# Create three networks all sharing the same resyncPeriod to exercise jitter
+# scheduling. Each network will be independently scheduled with [0%, +20%] jitter,
+# preventing them from all reconciling simultaneously.
+apiVersion: openstack.k-orc.cloud/v1alpha1
+kind: Network
+metadata:
+ name: network-resync-jitter-1
+spec:
+ cloudCredentialsRef:
+ cloudName: openstack
+ secretName: openstack-clouds
+ managementPolicy: managed
+ resyncPeriod: 10s
+ resource: {}
+---
+apiVersion: openstack.k-orc.cloud/v1alpha1
+kind: Network
+metadata:
+ name: network-resync-jitter-2
+spec:
+ cloudCredentialsRef:
+ cloudName: openstack
+ secretName: openstack-clouds
+ managementPolicy: managed
+ resyncPeriod: 10s
+ resource: {}
+---
+apiVersion: openstack.k-orc.cloud/v1alpha1
+kind: Network
+metadata:
+ name: network-resync-jitter-3
+spec:
+ cloudCredentialsRef:
+ cloudName: openstack
+ secretName: openstack-clouds
+ managementPolicy: managed
+ resyncPeriod: 10s
+ resource: {}
diff --git a/internal/controllers/network/tests/network-resync-jitter/00-secret.yaml b/internal/controllers/network/tests/network-resync-jitter/00-secret.yaml
new file mode 100644
index 000000000..f0fb63e85
--- /dev/null
+++ b/internal/controllers/network/tests/network-resync-jitter/00-secret.yaml
@@ -0,0 +1,5 @@
+apiVersion: kuttl.dev/v1beta1
+kind: TestStep
+commands:
+ - command: kubectl create secret generic openstack-clouds --from-file=clouds.yaml=${E2E_KUTTL_OSCLOUDS} ${E2E_KUTTL_CACERT_OPT}
+ namespaced: true
diff --git a/internal/controllers/network/tests/network-resync-jitter/01-assert.yaml b/internal/controllers/network/tests/network-resync-jitter/01-assert.yaml
new file mode 100644
index 000000000..bcb506b9e
--- /dev/null
+++ b/internal/controllers/network/tests/network-resync-jitter/01-assert.yaml
@@ -0,0 +1,31 @@
+---
+# After the resync period elapses, all three networks should have been
+# independently re-reconciled. This assert waits (up to the timeout) for all
+# three lastSyncTime values to advance beyond their recorded initial values,
+# confirming that jitter-based scheduling works for multiple concurrent resources.
+#
+# Note: We verify that each resource independently reschedules (all update
+# their lastSyncTime), rather than testing for exact timestamp differences.
+# Exact jitter measurement is covered by unit tests; this E2E test verifies
+# the end-to-end resync flow for concurrent resources.
+apiVersion: kuttl.dev/v1beta1
+kind: TestAssert
+timeout: 240
+commands:
+ - script: |
+ INIT1=$(cat /tmp/network-resync-jitter-1-initial-sync-time)
+ INIT2=$(cat /tmp/network-resync-jitter-2-initial-sync-time)
+ INIT3=$(cat /tmp/network-resync-jitter-3-initial-sync-time)
+
+ CUR1=$(kubectl get network.openstack.k-orc.cloud network-resync-jitter-1 \
+ -n ${NAMESPACE} -o jsonpath='{.status.lastSyncTime}')
+ CUR2=$(kubectl get network.openstack.k-orc.cloud network-resync-jitter-2 \
+ -n ${NAMESPACE} -o jsonpath='{.status.lastSyncTime}')
+ CUR3=$(kubectl get network.openstack.k-orc.cloud network-resync-jitter-3 \
+ -n ${NAMESPACE} -o jsonpath='{.status.lastSyncTime}')
+
+ # All three must have updated their lastSyncTime, demonstrating that
+ # each resource was independently re-reconciled after the resync period.
+ [ "${CUR1}" != "${INIT1}" ] && \
+ [ "${CUR2}" != "${INIT2}" ] && \
+ [ "${CUR3}" != "${INIT3}" ]
diff --git a/internal/controllers/network/tests/network-resync-jitter/01-record-sync-times.yaml b/internal/controllers/network/tests/network-resync-jitter/01-record-sync-times.yaml
new file mode 100644
index 000000000..9ff679a17
--- /dev/null
+++ b/internal/controllers/network/tests/network-resync-jitter/01-record-sync-times.yaml
@@ -0,0 +1,18 @@
+apiVersion: kuttl.dev/v1beta1
+kind: TestStep
+# Record the current lastSyncTime for all three networks so that the following
+# assert can detect when each network has been independently re-reconciled.
+commands:
+ - script: |
+ kubectl get network.openstack.k-orc.cloud network-resync-jitter-1 \
+ -n ${NAMESPACE} \
+ -o jsonpath='{.status.lastSyncTime}' \
+ > /tmp/network-resync-jitter-1-initial-sync-time
+ kubectl get network.openstack.k-orc.cloud network-resync-jitter-2 \
+ -n ${NAMESPACE} \
+ -o jsonpath='{.status.lastSyncTime}' \
+ > /tmp/network-resync-jitter-2-initial-sync-time
+ kubectl get network.openstack.k-orc.cloud network-resync-jitter-3 \
+ -n ${NAMESPACE} \
+ -o jsonpath='{.status.lastSyncTime}' \
+ > /tmp/network-resync-jitter-3-initial-sync-time
diff --git a/internal/controllers/network/tests/network-resync-jitter/README.md b/internal/controllers/network/tests/network-resync-jitter/README.md
new file mode 100644
index 000000000..bdc44e0d6
--- /dev/null
+++ b/internal/controllers/network/tests/network-resync-jitter/README.md
@@ -0,0 +1,31 @@
+# Jitter spreads reconciliation times across multiple resources
+
+## Step 00
+
+Create three networks that all share the same `resyncPeriod` (10s). Once all
+three become available, each will have a `lastSyncTime` that records when the
+controller last successfully reconciled them.
+
+## Step 01
+
+Record the initial `lastSyncTime` for all three networks.
+
+## Step 02
+
+After the resync period elapses, verify that all three networks have been
+independently re-reconciled (i.e., all three `lastSyncTime` values have been
+updated to newer timestamps).
+
+The test verifies that all three resources are scheduled for resync
+independently. The jitter mechanism ([0%, +20%]) ensures they are not all
+re-reconciled at exactly the same instant, which would cause a thundering-herd
+effect. Because the [0%, +20%] jitter applied to a 10s period produces scheduling
+spread of up to +2s, we check that all three networks successfully re-synced
+(demonstrating independent scheduling) rather than requiring exact timestamp
+differences (which would be flaky at sub-second granularity).
+
+## Reference
+
+Tests the jitter-based resync scheduling feature (TS-011): multiple resources
+with the same `resyncPeriod` should be independently scheduled rather than
+all reconciling simultaneously.
diff --git a/internal/controllers/network/tests/network-resync-period/00-assert.yaml b/internal/controllers/network/tests/network-resync-period/00-assert.yaml
new file mode 100644
index 000000000..87b71da85
--- /dev/null
+++ b/internal/controllers/network/tests/network-resync-period/00-assert.yaml
@@ -0,0 +1,33 @@
+---
+# Verify the network is available and lastSyncTime has been set after the first
+# successful reconciliation.
+apiVersion: kuttl.dev/v1beta1
+kind: TestAssert
+resourceRefs:
+ - apiVersion: openstack.k-orc.cloud/v1alpha1
+ kind: Network
+ name: network-resync-period
+ ref: network
+assertAll:
+ - celExpr: "has(network.status.lastSyncTime)"
+ - celExpr: "network.status.lastSyncTime != ''"
+---
+apiVersion: openstack.k-orc.cloud/v1alpha1
+kind: Network
+metadata:
+ name: network-resync-period
+status:
+ resource:
+ name: network-resync-period
+ adminStateUp: true
+ external: false
+ portSecurityEnabled: true
+ shared: false
+ status: ACTIVE
+ conditions:
+ - type: Available
+ status: "True"
+ reason: Success
+ - type: Progressing
+ status: "False"
+ reason: Success
diff --git a/internal/controllers/network/tests/network-resync-period/00-create-resource.yaml b/internal/controllers/network/tests/network-resync-period/00-create-resource.yaml
new file mode 100644
index 000000000..b912f6527
--- /dev/null
+++ b/internal/controllers/network/tests/network-resync-period/00-create-resource.yaml
@@ -0,0 +1,13 @@
+apiVersion: openstack.k-orc.cloud/v1alpha1
+kind: Network
+metadata:
+ name: network-resync-period
+spec:
+ cloudCredentialsRef:
+ cloudName: openstack
+ secretName: openstack-clouds
+ managementPolicy: managed
+ # resyncPeriod of 10s ensures the resource is re-reconciled quickly, making
+ # the test fast while still demonstrating periodic resync behaviour.
+ resyncPeriod: 10s
+ resource: {}
diff --git a/internal/controllers/network/tests/network-resync-period/00-secret.yaml b/internal/controllers/network/tests/network-resync-period/00-secret.yaml
new file mode 100644
index 000000000..f0fb63e85
--- /dev/null
+++ b/internal/controllers/network/tests/network-resync-period/00-secret.yaml
@@ -0,0 +1,5 @@
+apiVersion: kuttl.dev/v1beta1
+kind: TestStep
+commands:
+ - command: kubectl create secret generic openstack-clouds --from-file=clouds.yaml=${E2E_KUTTL_OSCLOUDS} ${E2E_KUTTL_CACERT_OPT}
+ namespaced: true
diff --git a/internal/controllers/network/tests/network-resync-period/01-assert.yaml b/internal/controllers/network/tests/network-resync-period/01-assert.yaml
new file mode 100644
index 000000000..d01b16814
--- /dev/null
+++ b/internal/controllers/network/tests/network-resync-period/01-assert.yaml
@@ -0,0 +1,18 @@
+---
+# After the resyncPeriod (10s) elapses, the controller reconciles again and
+# updates lastSyncTime. This assertion waits (up to the kuttl step timeout)
+# for lastSyncTime to advance beyond the value recorded in step 01.
+#
+# The kuttl assert timeout gives plenty of time for the resync period to
+# elapse and the reconciliation to complete.
+apiVersion: kuttl.dev/v1beta1
+kind: TestAssert
+timeout: 180
+commands:
+ - script: |
+ INITIAL=$(cat /tmp/network-resync-period-initial-sync-time)
+ CURRENT=$(kubectl get network.openstack.k-orc.cloud network-resync-period \
+ -n ${NAMESPACE} \
+ -o jsonpath='{.status.lastSyncTime}')
+ # Succeed only when lastSyncTime has been updated to a newer value.
+ [ -n "${INITIAL}" ] && [ -n "${CURRENT}" ] && [ "${CURRENT}" != "${INITIAL}" ]
diff --git a/internal/controllers/network/tests/network-resync-period/01-record-sync-time.yaml b/internal/controllers/network/tests/network-resync-period/01-record-sync-time.yaml
new file mode 100644
index 000000000..a4ccd63fe
--- /dev/null
+++ b/internal/controllers/network/tests/network-resync-period/01-record-sync-time.yaml
@@ -0,0 +1,10 @@
+apiVersion: kuttl.dev/v1beta1
+kind: TestStep
+# Record the current lastSyncTime so that the following assert can detect
+# when the controller performs a second reconciliation (updating lastSyncTime).
+commands:
+ - script: |
+ kubectl get network.openstack.k-orc.cloud network-resync-period \
+ -n ${NAMESPACE} \
+ -o jsonpath='{.status.lastSyncTime}' \
+ > /tmp/network-resync-period-initial-sync-time
diff --git a/internal/controllers/network/tests/network-resync-period/README.md b/internal/controllers/network/tests/network-resync-period/README.md
new file mode 100644
index 000000000..bbd61a107
--- /dev/null
+++ b/internal/controllers/network/tests/network-resync-period/README.md
@@ -0,0 +1,18 @@
+# Network resync after configured period
+
+## Step 00
+
+Create a network with a short `resyncPeriod` (10s) and verify that:
+- The network becomes available with correct conditions.
+- `lastSyncTime` is set in the status after the first successful reconciliation.
+
+## Step 01
+
+Wait for the resync period to elapse, then verify that `lastSyncTime` is updated
+to a newer timestamp. This confirms that the controller re-reconciles the network
+after the configured period and writes a fresh `lastSyncTime`.
+
+## Reference
+
+Tests the resync scheduling feature: a resource with a configured `resyncPeriod`
+should be periodically re-reconciled and `lastSyncTime` updated accordingly.
diff --git a/internal/controllers/network/tests/network-resync-terminal-error/00-assert.yaml b/internal/controllers/network/tests/network-resync-terminal-error/00-assert.yaml
new file mode 100644
index 000000000..3788843dd
--- /dev/null
+++ b/internal/controllers/network/tests/network-resync-terminal-error/00-assert.yaml
@@ -0,0 +1,26 @@
+---
+apiVersion: openstack.k-orc.cloud/v1alpha1
+kind: Network
+metadata:
+ name: network-resync-terminal-error-external-1
+status:
+ conditions:
+ - type: Available
+ status: "True"
+ reason: Success
+ - type: Progressing
+ status: "False"
+ reason: Success
+---
+apiVersion: openstack.k-orc.cloud/v1alpha1
+kind: Network
+metadata:
+ name: network-resync-terminal-error-external-2
+status:
+ conditions:
+ - type: Available
+ status: "True"
+ reason: Success
+ - type: Progressing
+ status: "False"
+ reason: Success
diff --git a/internal/controllers/network/tests/network-resync-terminal-error/00-create-resources.yaml b/internal/controllers/network/tests/network-resync-terminal-error/00-create-resources.yaml
new file mode 100644
index 000000000..76142252d
--- /dev/null
+++ b/internal/controllers/network/tests/network-resync-terminal-error/00-create-resources.yaml
@@ -0,0 +1,26 @@
+---
+# Create two networks with the same description so that an import filter
+# matching on that description will be ambiguous (multiple results).
+apiVersion: openstack.k-orc.cloud/v1alpha1
+kind: Network
+metadata:
+ name: network-resync-terminal-error-external-1
+spec:
+ cloudCredentialsRef:
+ cloudName: openstack
+ secretName: openstack-clouds
+ managementPolicy: managed
+ resource:
+ description: Network from "resync-terminal-error" test
+---
+apiVersion: openstack.k-orc.cloud/v1alpha1
+kind: Network
+metadata:
+ name: network-resync-terminal-error-external-2
+spec:
+ cloudCredentialsRef:
+ cloudName: openstack
+ secretName: openstack-clouds
+ managementPolicy: managed
+ resource:
+ description: Network from "resync-terminal-error" test
diff --git a/internal/controllers/network/tests/network-resync-terminal-error/00-secret.yaml b/internal/controllers/network/tests/network-resync-terminal-error/00-secret.yaml
new file mode 100644
index 000000000..f0fb63e85
--- /dev/null
+++ b/internal/controllers/network/tests/network-resync-terminal-error/00-secret.yaml
@@ -0,0 +1,5 @@
+apiVersion: kuttl.dev/v1beta1
+kind: TestStep
+commands:
+ - command: kubectl create secret generic openstack-clouds --from-file=clouds.yaml=${E2E_KUTTL_OSCLOUDS} ${E2E_KUTTL_CACERT_OPT}
+ namespaced: true
diff --git a/internal/controllers/network/tests/network-resync-terminal-error/01-assert.yaml b/internal/controllers/network/tests/network-resync-terminal-error/01-assert.yaml
new file mode 100644
index 000000000..c565120a1
--- /dev/null
+++ b/internal/controllers/network/tests/network-resync-terminal-error/01-assert.yaml
@@ -0,0 +1,29 @@
+---
+# Verify the import fails with a terminal error (InvalidConfiguration) and
+# that lastSyncTime is NOT set (no successful reconciliation occurred).
+apiVersion: kuttl.dev/v1beta1
+kind: TestAssert
+resourceRefs:
+ - apiVersion: openstack.k-orc.cloud/v1alpha1
+ kind: Network
+ name: network-resync-terminal-error
+ ref: network
+assertAll:
+ # lastSyncTime must NOT be set: the reconciliation never succeeded, so
+ # there is no time of last successful sync to record.
+ - celExpr: "!has(network.status.lastSyncTime)"
+---
+apiVersion: openstack.k-orc.cloud/v1alpha1
+kind: Network
+metadata:
+ name: network-resync-terminal-error
+status:
+ conditions:
+ - type: Available
+ message: found more than one matching OpenStack resource during import
+ status: "False"
+ reason: InvalidConfiguration
+ - type: Progressing
+ message: found more than one matching OpenStack resource during import
+ status: "False"
+ reason: InvalidConfiguration
diff --git a/internal/controllers/network/tests/network-resync-terminal-error/01-import-resource.yaml b/internal/controllers/network/tests/network-resync-terminal-error/01-import-resource.yaml
new file mode 100644
index 000000000..e4f9360f7
--- /dev/null
+++ b/internal/controllers/network/tests/network-resync-terminal-error/01-import-resource.yaml
@@ -0,0 +1,20 @@
+---
+# Attempt to import a network with a filter matching both external networks.
+# This will result in a terminal error (InvalidConfiguration) because the
+# filter is ambiguous. A resyncPeriod is set to verify that the terminal error
+# prevents the resync scheduler from enqueuing further reconciliations.
+apiVersion: openstack.k-orc.cloud/v1alpha1
+kind: Network
+metadata:
+ name: network-resync-terminal-error
+spec:
+ cloudCredentialsRef:
+ cloudName: openstack
+ secretName: openstack-clouds
+ managementPolicy: unmanaged
+ # resyncPeriod is configured so we can verify it is suppressed by the
+ # terminal error (the scheduler must not fire for a resource in this state).
+ resyncPeriod: 10s
+ import:
+ filter:
+ description: Network from "resync-terminal-error" test
diff --git a/internal/controllers/network/tests/network-resync-terminal-error/02-assert.yaml b/internal/controllers/network/tests/network-resync-terminal-error/02-assert.yaml
new file mode 100644
index 000000000..3daa80e6c
--- /dev/null
+++ b/internal/controllers/network/tests/network-resync-terminal-error/02-assert.yaml
@@ -0,0 +1,29 @@
+---
+# After waiting longer than the configured resyncPeriod, the resource must
+# still be in the terminal error state and lastSyncTime must still be absent.
+# This confirms that the periodic resync scheduler correctly skips resources
+# that have a terminal error (TS-008).
+apiVersion: kuttl.dev/v1beta1
+kind: TestAssert
+resourceRefs:
+ - apiVersion: openstack.k-orc.cloud/v1alpha1
+ kind: Network
+ name: network-resync-terminal-error
+ ref: network
+assertAll:
+ - celExpr: "!has(network.status.lastSyncTime)"
+---
+apiVersion: openstack.k-orc.cloud/v1alpha1
+kind: Network
+metadata:
+ name: network-resync-terminal-error
+status:
+ conditions:
+ - type: Available
+ message: found more than one matching OpenStack resource during import
+ status: "False"
+ reason: InvalidConfiguration
+ - type: Progressing
+ message: found more than one matching OpenStack resource during import
+ status: "False"
+ reason: InvalidConfiguration
diff --git a/internal/controllers/network/tests/network-resync-terminal-error/02-check-no-resync.yaml b/internal/controllers/network/tests/network-resync-terminal-error/02-check-no-resync.yaml
new file mode 100644
index 000000000..d43838ba0
--- /dev/null
+++ b/internal/controllers/network/tests/network-resync-terminal-error/02-check-no-resync.yaml
@@ -0,0 +1,9 @@
+apiVersion: kuttl.dev/v1beta1
+kind: TestStep
+# Wait for longer than the configured resyncPeriod (10s) to verify that the
+# terminal error state prevents the resync scheduler from firing.
+# If the scheduler incorrectly fires, the controller would reconcile again,
+# potentially changing the condition message or setting lastSyncTime.
+commands:
+ - script: |
+ sleep 15
diff --git a/internal/controllers/network/tests/network-resync-terminal-error/README.md b/internal/controllers/network/tests/network-resync-terminal-error/README.md
new file mode 100644
index 000000000..df2e5e9d0
--- /dev/null
+++ b/internal/controllers/network/tests/network-resync-terminal-error/README.md
@@ -0,0 +1,30 @@
+# Terminal error resources don't resync
+
+## Step 00
+
+Create two networks with identical descriptions so that an import filter
+matching on that description will find multiple results.
+
+## Step 01
+
+Attempt to import a network using a filter that matches both of the networks
+created in step 00. This causes a terminal error (InvalidConfiguration) because
+the import is ambiguous: the controller found more than one matching resource.
+
+Also configure `resyncPeriod: 10s` on the failing resource to verify that the
+terminal error state prevents the resync scheduler from enqueuing additional
+reconciliations.
+
+## Step 02
+
+Wait 15 seconds (longer than the configured resyncPeriod) and verify that the
+resource remains in the terminal error state. Specifically:
+- Conditions still show InvalidConfiguration (terminal error unchanged).
+- `lastSyncTime` is NOT set, because no successful reconciliation has occurred.
+- The resource has NOT been re-reconciled (if resync fired, it might clear the
+ error or change the condition message).
+
+## Reference
+
+Tests that resources in a terminal error state are excluded from the periodic
+resync scheduler, as specified by acceptance criterion TS-008.
diff --git a/internal/controllers/network/zz_generated.adapter.go b/internal/controllers/network/zz_generated.adapter.go
index 771518735..74283c14d 100644
--- a/internal/controllers/network/zz_generated.adapter.go
+++ b/internal/controllers/network/zz_generated.adapter.go
@@ -18,6 +18,8 @@ limitations under the License.
package network
import (
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+
orcv1alpha1 "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1"
"github.com/k-orc/openstack-resource-controller/v2/internal/controllers/generic/interfaces"
)
@@ -55,6 +57,14 @@ func (f adapterT) GetManagedOptions() *orcv1alpha1.ManagedOptions {
return f.Spec.ManagedOptions
}
+func (f adapterT) GetResyncPeriod() *metav1.Duration {
+ return f.Spec.ResyncPeriod
+}
+
+func (f adapterT) GetLastSyncTime() *metav1.Time {
+ return f.Status.LastSyncTime
+}
+
func (f adapterT) GetStatusID() *string {
return f.Status.ID
}
@@ -77,6 +87,10 @@ func (f adapterT) GetImportFilter() *filterT {
return f.Spec.Import.Filter
}
+func (f adapterT) IsImported() bool {
+ return f.GetImportID() != nil || f.GetImportFilter() != nil
+}
+
// getResourceName returns the name of the OpenStack resource we should use.
// This method is not implemented as part of APIObjectAdapter as it is intended
// to be used by resource actuators, which don't use the adapter.
diff --git a/internal/controllers/port/controller.go b/internal/controllers/port/controller.go
index ae0d73b37..1d58b480f 100644
--- a/internal/controllers/port/controller.go
+++ b/internal/controllers/port/controller.go
@@ -20,6 +20,7 @@ import (
"context"
"errors"
"fmt"
+ "time"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
@@ -256,19 +257,24 @@ func serverToPortMapFunc(ctx context.Context, k8sClient client.Client) handler.M
}
type portReconcilerConstructor struct {
- scopeFactory scope.Factory
+ scopeFactory scope.Factory
+ defaultResyncPeriod time.Duration
}
func New(scopeFactory scope.Factory) interfaces.Controller {
- return portReconcilerConstructor{scopeFactory: scopeFactory}
+ return &portReconcilerConstructor{scopeFactory: scopeFactory}
}
func (portReconcilerConstructor) GetName() string {
return controllerName
}
+func (c *portReconcilerConstructor) SetDefaultResyncPeriod(d time.Duration) {
+ c.defaultResyncPeriod = d
+}
+
// SetupWithManager sets up the controller with the Manager.
-func (c portReconcilerConstructor) SetupWithManager(ctx context.Context, mgr ctrl.Manager, options controller.Options) error {
+func (c *portReconcilerConstructor) SetupWithManager(ctx context.Context, mgr ctrl.Manager, options controller.Options) error {
log := mgr.GetLogger().WithValues("controller", controllerName)
k8sClient := mgr.GetClient()
@@ -351,6 +357,6 @@ func (c portReconcilerConstructor) SetupWithManager(ctx context.Context, mgr ctr
return err
}
- r := reconciler.NewController(controllerName, k8sClient, c.scopeFactory, portHelperFactory{}, portStatusWriter{})
+ r := reconciler.NewController(controllerName, k8sClient, c.scopeFactory, portHelperFactory{}, portStatusWriter{}, c.defaultResyncPeriod)
return builder.Complete(&r)
}
diff --git a/internal/controllers/port/zz_generated.adapter.go b/internal/controllers/port/zz_generated.adapter.go
index 1cafbd343..0f97ce9b4 100644
--- a/internal/controllers/port/zz_generated.adapter.go
+++ b/internal/controllers/port/zz_generated.adapter.go
@@ -18,6 +18,8 @@ limitations under the License.
package port
import (
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+
orcv1alpha1 "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1"
"github.com/k-orc/openstack-resource-controller/v2/internal/controllers/generic/interfaces"
)
@@ -55,6 +57,14 @@ func (f adapterT) GetManagedOptions() *orcv1alpha1.ManagedOptions {
return f.Spec.ManagedOptions
}
+func (f adapterT) GetResyncPeriod() *metav1.Duration {
+ return f.Spec.ResyncPeriod
+}
+
+func (f adapterT) GetLastSyncTime() *metav1.Time {
+ return f.Status.LastSyncTime
+}
+
func (f adapterT) GetStatusID() *string {
return f.Status.ID
}
@@ -77,6 +87,10 @@ func (f adapterT) GetImportFilter() *filterT {
return f.Spec.Import.Filter
}
+func (f adapterT) IsImported() bool {
+ return f.GetImportID() != nil || f.GetImportFilter() != nil
+}
+
// getResourceName returns the name of the OpenStack resource we should use.
// This method is not implemented as part of APIObjectAdapter as it is intended
// to be used by resource actuators, which don't use the adapter.
diff --git a/internal/controllers/project/controller.go b/internal/controllers/project/controller.go
index 116b2024e..74dddc532 100644
--- a/internal/controllers/project/controller.go
+++ b/internal/controllers/project/controller.go
@@ -19,6 +19,7 @@ package project
import (
"context"
"errors"
+ "time"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/builder"
@@ -40,17 +41,22 @@ const controllerName = "project"
// +kubebuilder:rbac:groups=openstack.k-orc.cloud,resources=projects/status,verbs=get;update;patch
type projectReconcilerConstructor struct {
- scopeFactory scope.Factory
+ scopeFactory scope.Factory
+ defaultResyncPeriod time.Duration
}
func New(scopeFactory scope.Factory) interfaces.Controller {
- return projectReconcilerConstructor{scopeFactory: scopeFactory}
+ return &projectReconcilerConstructor{scopeFactory: scopeFactory}
}
func (projectReconcilerConstructor) GetName() string {
return controllerName
}
+func (c *projectReconcilerConstructor) SetDefaultResyncPeriod(d time.Duration) {
+ c.defaultResyncPeriod = d
+}
+
var domainDependency = dependency.NewDeletionGuardDependency[*orcv1alpha1.ProjectList, *orcv1alpha1.Domain](
"spec.resource.domainRef",
func(project *orcv1alpha1.Project) []string {
@@ -75,7 +81,7 @@ var domainImportDependency = dependency.NewDependency[*orcv1alpha1.ProjectList,
)
// SetupWithManager sets up the controller with the Manager.
-func (c projectReconcilerConstructor) SetupWithManager(ctx context.Context, mgr ctrl.Manager, options controller.Options) error {
+func (c *projectReconcilerConstructor) SetupWithManager(ctx context.Context, mgr ctrl.Manager, options controller.Options) error {
log := ctrl.LoggerFrom(ctx)
k8sClient := mgr.GetClient()
@@ -109,6 +115,6 @@ func (c projectReconcilerConstructor) SetupWithManager(ctx context.Context, mgr
return err
}
- r := reconciler.NewController(controllerName, mgr.GetClient(), c.scopeFactory, projectHelperFactory{}, projectStatusWriter{})
+ r := reconciler.NewController(controllerName, mgr.GetClient(), c.scopeFactory, projectHelperFactory{}, projectStatusWriter{}, c.defaultResyncPeriod)
return builder.Complete(&r)
}
diff --git a/internal/controllers/project/zz_generated.adapter.go b/internal/controllers/project/zz_generated.adapter.go
index fea8a21c1..a3dc06ba3 100644
--- a/internal/controllers/project/zz_generated.adapter.go
+++ b/internal/controllers/project/zz_generated.adapter.go
@@ -18,6 +18,8 @@ limitations under the License.
package project
import (
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+
orcv1alpha1 "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1"
"github.com/k-orc/openstack-resource-controller/v2/internal/controllers/generic/interfaces"
)
@@ -55,6 +57,14 @@ func (f adapterT) GetManagedOptions() *orcv1alpha1.ManagedOptions {
return f.Spec.ManagedOptions
}
+func (f adapterT) GetResyncPeriod() *metav1.Duration {
+ return f.Spec.ResyncPeriod
+}
+
+func (f adapterT) GetLastSyncTime() *metav1.Time {
+ return f.Status.LastSyncTime
+}
+
func (f adapterT) GetStatusID() *string {
return f.Status.ID
}
@@ -77,6 +87,10 @@ func (f adapterT) GetImportFilter() *filterT {
return f.Spec.Import.Filter
}
+func (f adapterT) IsImported() bool {
+ return f.GetImportID() != nil || f.GetImportFilter() != nil
+}
+
// getResourceName returns the name of the OpenStack resource we should use.
// This method is not implemented as part of APIObjectAdapter as it is intended
// to be used by resource actuators, which don't use the adapter.
diff --git a/internal/controllers/role/controller.go b/internal/controllers/role/controller.go
index faa40bfc0..d4a1b241e 100644
--- a/internal/controllers/role/controller.go
+++ b/internal/controllers/role/controller.go
@@ -19,6 +19,7 @@ package role
import (
"context"
"errors"
+ "time"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/builder"
@@ -40,17 +41,22 @@ const controllerName = "role"
// +kubebuilder:rbac:groups=openstack.k-orc.cloud,resources=roles/status,verbs=get;update;patch
type roleReconcilerConstructor struct {
- scopeFactory scope.Factory
+ scopeFactory scope.Factory
+ defaultResyncPeriod time.Duration
}
func New(scopeFactory scope.Factory) interfaces.Controller {
- return roleReconcilerConstructor{scopeFactory: scopeFactory}
+ return &roleReconcilerConstructor{scopeFactory: scopeFactory}
}
func (roleReconcilerConstructor) GetName() string {
return controllerName
}
+func (c *roleReconcilerConstructor) SetDefaultResyncPeriod(d time.Duration) {
+ c.defaultResyncPeriod = d
+}
+
var domainDependency = dependency.NewDeletionGuardDependency[*orcv1alpha1.RoleList, *orcv1alpha1.Domain](
"spec.resource.domainRef",
func(role *orcv1alpha1.Role) []string {
@@ -75,7 +81,7 @@ var domainImportDependency = dependency.NewDependency[*orcv1alpha1.RoleList, *or
)
// SetupWithManager sets up the controller with the Manager.
-func (c roleReconcilerConstructor) SetupWithManager(ctx context.Context, mgr ctrl.Manager, options controller.Options) error {
+func (c *roleReconcilerConstructor) SetupWithManager(ctx context.Context, mgr ctrl.Manager, options controller.Options) error {
log := ctrl.LoggerFrom(ctx)
k8sClient := mgr.GetClient()
@@ -109,6 +115,6 @@ func (c roleReconcilerConstructor) SetupWithManager(ctx context.Context, mgr ctr
return err
}
- r := reconciler.NewController(controllerName, mgr.GetClient(), c.scopeFactory, roleHelperFactory{}, roleStatusWriter{})
+ r := reconciler.NewController(controllerName, mgr.GetClient(), c.scopeFactory, roleHelperFactory{}, roleStatusWriter{}, c.defaultResyncPeriod)
return builder.Complete(&r)
}
diff --git a/internal/controllers/role/zz_generated.adapter.go b/internal/controllers/role/zz_generated.adapter.go
index 5587b85d4..023bd040d 100644
--- a/internal/controllers/role/zz_generated.adapter.go
+++ b/internal/controllers/role/zz_generated.adapter.go
@@ -18,6 +18,8 @@ limitations under the License.
package role
import (
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+
orcv1alpha1 "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1"
"github.com/k-orc/openstack-resource-controller/v2/internal/controllers/generic/interfaces"
)
@@ -55,6 +57,14 @@ func (f adapterT) GetManagedOptions() *orcv1alpha1.ManagedOptions {
return f.Spec.ManagedOptions
}
+func (f adapterT) GetResyncPeriod() *metav1.Duration {
+ return f.Spec.ResyncPeriod
+}
+
+func (f adapterT) GetLastSyncTime() *metav1.Time {
+ return f.Status.LastSyncTime
+}
+
func (f adapterT) GetStatusID() *string {
return f.Status.ID
}
@@ -77,6 +87,10 @@ func (f adapterT) GetImportFilter() *filterT {
return f.Spec.Import.Filter
}
+func (f adapterT) IsImported() bool {
+ return f.GetImportID() != nil || f.GetImportFilter() != nil
+}
+
// getResourceName returns the name of the OpenStack resource we should use.
// This method is not implemented as part of APIObjectAdapter as it is intended
// to be used by resource actuators, which don't use the adapter.
diff --git a/internal/controllers/router/controller.go b/internal/controllers/router/controller.go
index 3b11b3192..2509bd4de 100644
--- a/internal/controllers/router/controller.go
+++ b/internal/controllers/router/controller.go
@@ -19,6 +19,7 @@ package router
import (
"context"
"errors"
+ "time"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/builder"
@@ -38,17 +39,22 @@ import (
// +kubebuilder:rbac:groups=openstack.k-orc.cloud,resources=routers/status,verbs=get;update;patch
type routerReconcilerConstructor struct {
- scopeFactory scope.Factory
+ scopeFactory scope.Factory
+ defaultResyncPeriod time.Duration
}
func New(scopeFactory scope.Factory) interfaces.Controller {
- return routerReconcilerConstructor{scopeFactory: scopeFactory}
+ return &routerReconcilerConstructor{scopeFactory: scopeFactory}
}
func (routerReconcilerConstructor) GetName() string {
return controllerName
}
+func (c *routerReconcilerConstructor) SetDefaultResyncPeriod(d time.Duration) {
+ c.defaultResyncPeriod = d
+}
+
const controllerName = "router"
var (
@@ -95,7 +101,7 @@ var (
)
// SetupWithManager sets up the controller with the Manager.
-func (c routerReconcilerConstructor) SetupWithManager(ctx context.Context, mgr ctrl.Manager, options controller.Options) error {
+func (c *routerReconcilerConstructor) SetupWithManager(ctx context.Context, mgr ctrl.Manager, options controller.Options) error {
log := mgr.GetLogger().WithValues("controller", controllerName)
k8sClient := mgr.GetClient()
@@ -138,6 +144,6 @@ func (c routerReconcilerConstructor) SetupWithManager(ctx context.Context, mgr c
return err
}
- r := reconciler.NewController(controllerName, k8sClient, c.scopeFactory, routerHelperFactory{}, routerStatusWriter{})
+ r := reconciler.NewController(controllerName, k8sClient, c.scopeFactory, routerHelperFactory{}, routerStatusWriter{}, c.defaultResyncPeriod)
return builder.Complete(&r)
}
diff --git a/internal/controllers/router/zz_generated.adapter.go b/internal/controllers/router/zz_generated.adapter.go
index ccab08587..444dc2389 100644
--- a/internal/controllers/router/zz_generated.adapter.go
+++ b/internal/controllers/router/zz_generated.adapter.go
@@ -18,6 +18,8 @@ limitations under the License.
package router
import (
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+
orcv1alpha1 "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1"
"github.com/k-orc/openstack-resource-controller/v2/internal/controllers/generic/interfaces"
)
@@ -55,6 +57,14 @@ func (f adapterT) GetManagedOptions() *orcv1alpha1.ManagedOptions {
return f.Spec.ManagedOptions
}
+func (f adapterT) GetResyncPeriod() *metav1.Duration {
+ return f.Spec.ResyncPeriod
+}
+
+func (f adapterT) GetLastSyncTime() *metav1.Time {
+ return f.Status.LastSyncTime
+}
+
func (f adapterT) GetStatusID() *string {
return f.Status.ID
}
@@ -77,6 +87,10 @@ func (f adapterT) GetImportFilter() *filterT {
return f.Spec.Import.Filter
}
+func (f adapterT) IsImported() bool {
+ return f.GetImportID() != nil || f.GetImportFilter() != nil
+}
+
// getResourceName returns the name of the OpenStack resource we should use.
// This method is not implemented as part of APIObjectAdapter as it is intended
// to be used by resource actuators, which don't use the adapter.
diff --git a/internal/controllers/securitygroup/controller.go b/internal/controllers/securitygroup/controller.go
index 2e5d525e5..d52103ce5 100644
--- a/internal/controllers/securitygroup/controller.go
+++ b/internal/controllers/securitygroup/controller.go
@@ -19,6 +19,7 @@ package securitygroup
import (
"context"
"errors"
+ "time"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/builder"
@@ -65,11 +66,12 @@ var (
)
type securitygroupReconcilerConstructor struct {
- scopeFactory scope.Factory
+ scopeFactory scope.Factory
+ defaultResyncPeriod time.Duration
}
func New(scopeFactory scope.Factory) interfaces.Controller {
- return securitygroupReconcilerConstructor{
+ return &securitygroupReconcilerConstructor{
scopeFactory: scopeFactory,
}
}
@@ -78,8 +80,12 @@ func (securitygroupReconcilerConstructor) GetName() string {
return controllerName
}
+func (c *securitygroupReconcilerConstructor) SetDefaultResyncPeriod(d time.Duration) {
+ c.defaultResyncPeriod = d
+}
+
// SetupWithManager sets up the controller with the Manager.
-func (c securitygroupReconcilerConstructor) SetupWithManager(ctx context.Context, mgr ctrl.Manager, options controller.Options) error {
+func (c *securitygroupReconcilerConstructor) SetupWithManager(ctx context.Context, mgr ctrl.Manager, options controller.Options) error {
log := ctrl.LoggerFrom(ctx)
k8sClient := mgr.GetClient()
@@ -113,7 +119,7 @@ func (c securitygroupReconcilerConstructor) SetupWithManager(ctx context.Context
return err
}
- r := reconciler.NewController(controllerName, mgr.GetClient(), c.scopeFactory, securityGroupHelperFactory{}, securityGroupStatusWriter{})
+ r := reconciler.NewController(controllerName, mgr.GetClient(), c.scopeFactory, securityGroupHelperFactory{}, securityGroupStatusWriter{}, c.defaultResyncPeriod)
return builder.Complete(&r)
}
diff --git a/internal/controllers/securitygroup/zz_generated.adapter.go b/internal/controllers/securitygroup/zz_generated.adapter.go
index 1b055740c..2fa815a5f 100644
--- a/internal/controllers/securitygroup/zz_generated.adapter.go
+++ b/internal/controllers/securitygroup/zz_generated.adapter.go
@@ -18,6 +18,8 @@ limitations under the License.
package securitygroup
import (
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+
orcv1alpha1 "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1"
"github.com/k-orc/openstack-resource-controller/v2/internal/controllers/generic/interfaces"
)
@@ -55,6 +57,14 @@ func (f adapterT) GetManagedOptions() *orcv1alpha1.ManagedOptions {
return f.Spec.ManagedOptions
}
+func (f adapterT) GetResyncPeriod() *metav1.Duration {
+ return f.Spec.ResyncPeriod
+}
+
+func (f adapterT) GetLastSyncTime() *metav1.Time {
+ return f.Status.LastSyncTime
+}
+
func (f adapterT) GetStatusID() *string {
return f.Status.ID
}
@@ -77,6 +87,10 @@ func (f adapterT) GetImportFilter() *filterT {
return f.Spec.Import.Filter
}
+func (f adapterT) IsImported() bool {
+ return f.GetImportID() != nil || f.GetImportFilter() != nil
+}
+
// getResourceName returns the name of the OpenStack resource we should use.
// This method is not implemented as part of APIObjectAdapter as it is intended
// to be used by resource actuators, which don't use the adapter.
diff --git a/internal/controllers/server/controller.go b/internal/controllers/server/controller.go
index c83381a9a..5e5cd23b9 100644
--- a/internal/controllers/server/controller.go
+++ b/internal/controllers/server/controller.go
@@ -19,6 +19,7 @@ package server
import (
"context"
"errors"
+ "time"
corev1 "k8s.io/api/core/v1"
ctrl "sigs.k8s.io/controller-runtime"
@@ -38,17 +39,22 @@ import (
// +kubebuilder:rbac:groups=openstack.k-orc.cloud,resources=servers/status,verbs=get;update;patch
type serverReconcilerConstructor struct {
- scopeFactory scope.Factory
+ scopeFactory scope.Factory
+ defaultResyncPeriod time.Duration
}
func New(scopeFactory scope.Factory) interfaces.Controller {
- return serverReconcilerConstructor{scopeFactory: scopeFactory}
+ return &serverReconcilerConstructor{scopeFactory: scopeFactory}
}
func (serverReconcilerConstructor) GetName() string {
return controllerName
}
+func (c *serverReconcilerConstructor) SetDefaultResyncPeriod(d time.Duration) {
+ c.defaultResyncPeriod = d
+}
+
const controllerName = "server"
var (
@@ -182,7 +188,7 @@ var (
)
// SetupWithManager sets up the controller with the Manager.
-func (c serverReconcilerConstructor) SetupWithManager(ctx context.Context, mgr ctrl.Manager, options controller.Options) error {
+func (c *serverReconcilerConstructor) SetupWithManager(ctx context.Context, mgr ctrl.Manager, options controller.Options) error {
log := mgr.GetLogger().WithValues("controller", controllerName)
k8sClient := mgr.GetClient()
@@ -267,6 +273,6 @@ func (c serverReconcilerConstructor) SetupWithManager(ctx context.Context, mgr c
return err
}
- r := reconciler.NewController(controllerName, k8sClient, c.scopeFactory, serverHelperFactory{}, serverStatusWriter{})
+ r := reconciler.NewController(controllerName, k8sClient, c.scopeFactory, serverHelperFactory{}, serverStatusWriter{}, c.defaultResyncPeriod)
return builder.Complete(&r)
}
diff --git a/internal/controllers/server/zz_generated.adapter.go b/internal/controllers/server/zz_generated.adapter.go
index 1b51cde39..0d1535ded 100644
--- a/internal/controllers/server/zz_generated.adapter.go
+++ b/internal/controllers/server/zz_generated.adapter.go
@@ -18,6 +18,8 @@ limitations under the License.
package server
import (
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+
orcv1alpha1 "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1"
"github.com/k-orc/openstack-resource-controller/v2/internal/controllers/generic/interfaces"
)
@@ -55,6 +57,14 @@ func (f adapterT) GetManagedOptions() *orcv1alpha1.ManagedOptions {
return f.Spec.ManagedOptions
}
+func (f adapterT) GetResyncPeriod() *metav1.Duration {
+ return f.Spec.ResyncPeriod
+}
+
+func (f adapterT) GetLastSyncTime() *metav1.Time {
+ return f.Status.LastSyncTime
+}
+
func (f adapterT) GetStatusID() *string {
return f.Status.ID
}
@@ -77,6 +87,10 @@ func (f adapterT) GetImportFilter() *filterT {
return f.Spec.Import.Filter
}
+func (f adapterT) IsImported() bool {
+ return f.GetImportID() != nil || f.GetImportFilter() != nil
+}
+
// getResourceName returns the name of the OpenStack resource we should use.
// This method is not implemented as part of APIObjectAdapter as it is intended
// to be used by resource actuators, which don't use the adapter.
diff --git a/internal/controllers/servergroup/controller.go b/internal/controllers/servergroup/controller.go
index 98069dc81..fa63d245d 100644
--- a/internal/controllers/servergroup/controller.go
+++ b/internal/controllers/servergroup/controller.go
@@ -19,6 +19,7 @@ package servergroup
import (
"context"
"errors"
+ "time"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/controller"
@@ -37,19 +38,24 @@ const controllerName = "servergroup"
// +kubebuilder:rbac:groups=openstack.k-orc.cloud,resources=servergroups/status,verbs=get;update;patch
type servergroupReconcilerConstructor struct {
- scopeFactory scope.Factory
+ scopeFactory scope.Factory
+ defaultResyncPeriod time.Duration
}
func New(scopeFactory scope.Factory) interfaces.Controller {
- return servergroupReconcilerConstructor{scopeFactory: scopeFactory}
+ return &servergroupReconcilerConstructor{scopeFactory: scopeFactory}
}
func (servergroupReconcilerConstructor) GetName() string {
return controllerName
}
+func (c *servergroupReconcilerConstructor) SetDefaultResyncPeriod(d time.Duration) {
+ c.defaultResyncPeriod = d
+}
+
// SetupWithManager sets up the controller with the Manager.
-func (c servergroupReconcilerConstructor) SetupWithManager(ctx context.Context, mgr ctrl.Manager, options controller.Options) error {
+func (c *servergroupReconcilerConstructor) SetupWithManager(ctx context.Context, mgr ctrl.Manager, options controller.Options) error {
log := ctrl.LoggerFrom(ctx)
builder := ctrl.NewControllerManagedBy(mgr).
@@ -63,6 +69,6 @@ func (c servergroupReconcilerConstructor) SetupWithManager(ctx context.Context,
return err
}
- r := reconciler.NewController(controllerName, mgr.GetClient(), c.scopeFactory, servergroupHelperFactory{}, servergroupStatusWriter{})
+ r := reconciler.NewController(controllerName, mgr.GetClient(), c.scopeFactory, servergroupHelperFactory{}, servergroupStatusWriter{}, c.defaultResyncPeriod)
return builder.Complete(&r)
}
diff --git a/internal/controllers/servergroup/zz_generated.adapter.go b/internal/controllers/servergroup/zz_generated.adapter.go
index dc272f462..654d26c7d 100644
--- a/internal/controllers/servergroup/zz_generated.adapter.go
+++ b/internal/controllers/servergroup/zz_generated.adapter.go
@@ -18,6 +18,8 @@ limitations under the License.
package servergroup
import (
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+
orcv1alpha1 "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1"
"github.com/k-orc/openstack-resource-controller/v2/internal/controllers/generic/interfaces"
)
@@ -55,6 +57,14 @@ func (f adapterT) GetManagedOptions() *orcv1alpha1.ManagedOptions {
return f.Spec.ManagedOptions
}
+func (f adapterT) GetResyncPeriod() *metav1.Duration {
+ return f.Spec.ResyncPeriod
+}
+
+func (f adapterT) GetLastSyncTime() *metav1.Time {
+ return f.Status.LastSyncTime
+}
+
func (f adapterT) GetStatusID() *string {
return f.Status.ID
}
@@ -77,6 +87,10 @@ func (f adapterT) GetImportFilter() *filterT {
return f.Spec.Import.Filter
}
+func (f adapterT) IsImported() bool {
+ return f.GetImportID() != nil || f.GetImportFilter() != nil
+}
+
// getResourceName returns the name of the OpenStack resource we should use.
// This method is not implemented as part of APIObjectAdapter as it is intended
// to be used by resource actuators, which don't use the adapter.
diff --git a/internal/controllers/service/controller.go b/internal/controllers/service/controller.go
index 6e46a0dbd..195d4988d 100644
--- a/internal/controllers/service/controller.go
+++ b/internal/controllers/service/controller.go
@@ -19,6 +19,7 @@ package service
import (
"context"
"errors"
+ "time"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/controller"
@@ -37,19 +38,24 @@ const controllerName = "service"
// +kubebuilder:rbac:groups=openstack.k-orc.cloud,resources=services/status,verbs=get;update;patch
type serviceReconcilerConstructor struct {
- scopeFactory scope.Factory
+ scopeFactory scope.Factory
+ defaultResyncPeriod time.Duration
}
func New(scopeFactory scope.Factory) interfaces.Controller {
- return serviceReconcilerConstructor{scopeFactory: scopeFactory}
+ return &serviceReconcilerConstructor{scopeFactory: scopeFactory}
}
func (serviceReconcilerConstructor) GetName() string {
return controllerName
}
+func (c *serviceReconcilerConstructor) SetDefaultResyncPeriod(d time.Duration) {
+ c.defaultResyncPeriod = d
+}
+
// SetupWithManager sets up the controller with the Manager.
-func (c serviceReconcilerConstructor) SetupWithManager(ctx context.Context, mgr ctrl.Manager, options controller.Options) error {
+func (c *serviceReconcilerConstructor) SetupWithManager(ctx context.Context, mgr ctrl.Manager, options controller.Options) error {
log := ctrl.LoggerFrom(ctx)
builder := ctrl.NewControllerManagedBy(mgr).
@@ -63,6 +69,6 @@ func (c serviceReconcilerConstructor) SetupWithManager(ctx context.Context, mgr
return err
}
- r := reconciler.NewController(controllerName, mgr.GetClient(), c.scopeFactory, serviceHelperFactory{}, serviceStatusWriter{})
+ r := reconciler.NewController(controllerName, mgr.GetClient(), c.scopeFactory, serviceHelperFactory{}, serviceStatusWriter{}, c.defaultResyncPeriod)
return builder.Complete(&r)
}
diff --git a/internal/controllers/service/zz_generated.adapter.go b/internal/controllers/service/zz_generated.adapter.go
index f70ba04d9..ae823b299 100644
--- a/internal/controllers/service/zz_generated.adapter.go
+++ b/internal/controllers/service/zz_generated.adapter.go
@@ -18,6 +18,8 @@ limitations under the License.
package service
import (
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+
orcv1alpha1 "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1"
"github.com/k-orc/openstack-resource-controller/v2/internal/controllers/generic/interfaces"
)
@@ -55,6 +57,14 @@ func (f adapterT) GetManagedOptions() *orcv1alpha1.ManagedOptions {
return f.Spec.ManagedOptions
}
+func (f adapterT) GetResyncPeriod() *metav1.Duration {
+ return f.Spec.ResyncPeriod
+}
+
+func (f adapterT) GetLastSyncTime() *metav1.Time {
+ return f.Status.LastSyncTime
+}
+
func (f adapterT) GetStatusID() *string {
return f.Status.ID
}
@@ -77,6 +87,10 @@ func (f adapterT) GetImportFilter() *filterT {
return f.Spec.Import.Filter
}
+func (f adapterT) IsImported() bool {
+ return f.GetImportID() != nil || f.GetImportFilter() != nil
+}
+
// getResourceName returns the name of the OpenStack resource we should use.
// This method is not implemented as part of APIObjectAdapter as it is intended
// to be used by resource actuators, which don't use the adapter.
diff --git a/internal/controllers/subnet/controller.go b/internal/controllers/subnet/controller.go
index ea8eb33f0..b8d039dcf 100644
--- a/internal/controllers/subnet/controller.go
+++ b/internal/controllers/subnet/controller.go
@@ -20,6 +20,7 @@ import (
"context"
"errors"
"fmt"
+ "time"
"k8s.io/apimachinery/pkg/types"
ctrl "sigs.k8s.io/controller-runtime"
@@ -40,17 +41,22 @@ import (
)
type subnetReconcilerConstructor struct {
- scopeFactory scope.Factory
+ scopeFactory scope.Factory
+ defaultResyncPeriod time.Duration
}
func New(scopeFactory scope.Factory) interfaces.Controller {
- return subnetReconcilerConstructor{scopeFactory: scopeFactory}
+ return &subnetReconcilerConstructor{scopeFactory: scopeFactory}
}
func (subnetReconcilerConstructor) GetName() string {
return controllerName
}
+func (c *subnetReconcilerConstructor) SetDefaultResyncPeriod(d time.Duration) {
+ c.defaultResyncPeriod = d
+}
+
const controllerName = "subnet"
var (
@@ -114,7 +120,7 @@ var (
)
// SetupWithManager sets up the controller with the Manager.
-func (c subnetReconcilerConstructor) SetupWithManager(ctx context.Context, mgr ctrl.Manager, options controller.Options) error {
+func (c *subnetReconcilerConstructor) SetupWithManager(ctx context.Context, mgr ctrl.Manager, options controller.Options) error {
controllerName := c.GetName()
log := mgr.GetLogger().WithValues("controller", controllerName)
k8sClient := mgr.GetClient()
@@ -195,6 +201,6 @@ func (c subnetReconcilerConstructor) SetupWithManager(ctx context.Context, mgr c
return err
}
- r := reconciler.NewController(controllerName, k8sClient, c.scopeFactory, subnetHelperFactory{}, subnetStatusWriter{})
+ r := reconciler.NewController(controllerName, k8sClient, c.scopeFactory, subnetHelperFactory{}, subnetStatusWriter{}, c.defaultResyncPeriod)
return builder.Complete(&r)
}
diff --git a/internal/controllers/subnet/zz_generated.adapter.go b/internal/controllers/subnet/zz_generated.adapter.go
index 34c84d5b8..6debcd6fe 100644
--- a/internal/controllers/subnet/zz_generated.adapter.go
+++ b/internal/controllers/subnet/zz_generated.adapter.go
@@ -18,6 +18,8 @@ limitations under the License.
package subnet
import (
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+
orcv1alpha1 "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1"
"github.com/k-orc/openstack-resource-controller/v2/internal/controllers/generic/interfaces"
)
@@ -55,6 +57,14 @@ func (f adapterT) GetManagedOptions() *orcv1alpha1.ManagedOptions {
return f.Spec.ManagedOptions
}
+func (f adapterT) GetResyncPeriod() *metav1.Duration {
+ return f.Spec.ResyncPeriod
+}
+
+func (f adapterT) GetLastSyncTime() *metav1.Time {
+ return f.Status.LastSyncTime
+}
+
func (f adapterT) GetStatusID() *string {
return f.Status.ID
}
@@ -77,6 +87,10 @@ func (f adapterT) GetImportFilter() *filterT {
return f.Spec.Import.Filter
}
+func (f adapterT) IsImported() bool {
+ return f.GetImportID() != nil || f.GetImportFilter() != nil
+}
+
// getResourceName returns the name of the OpenStack resource we should use.
// This method is not implemented as part of APIObjectAdapter as it is intended
// to be used by resource actuators, which don't use the adapter.
diff --git a/internal/controllers/trunk/controller.go b/internal/controllers/trunk/controller.go
index ce8b13f2e..95b0c23a2 100644
--- a/internal/controllers/trunk/controller.go
+++ b/internal/controllers/trunk/controller.go
@@ -19,6 +19,7 @@ package trunk
import (
"context"
"errors"
+ "time"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/builder"
@@ -41,17 +42,22 @@ const controllerName = "trunk"
// +kubebuilder:rbac:groups=openstack.k-orc.cloud,resources=trunks/status,verbs=get;update;patch
type trunkReconcilerConstructor struct {
- scopeFactory scope.Factory
+ scopeFactory scope.Factory
+ defaultResyncPeriod time.Duration
}
func New(scopeFactory scope.Factory) interfaces.Controller {
- return trunkReconcilerConstructor{scopeFactory: scopeFactory}
+ return &trunkReconcilerConstructor{scopeFactory: scopeFactory}
}
func (trunkReconcilerConstructor) GetName() string {
return controllerName
}
+func (c *trunkReconcilerConstructor) SetDefaultResyncPeriod(d time.Duration) {
+ c.defaultResyncPeriod = d
+}
+
var portDependency = dependency.NewDeletionGuardDependency[*orcv1alpha1.TrunkList, *orcv1alpha1.Port](
"spec.resource.portRef",
func(trunk *orcv1alpha1.Trunk) []string {
@@ -119,7 +125,7 @@ var subportPortDependency = dependency.NewDeletionGuardDependency[*orcv1alpha1.T
)
// SetupWithManager sets up the controller with the Manager.
-func (c trunkReconcilerConstructor) SetupWithManager(ctx context.Context, mgr ctrl.Manager, options controller.Options) error {
+func (c *trunkReconcilerConstructor) SetupWithManager(ctx context.Context, mgr ctrl.Manager, options controller.Options) error {
log := ctrl.LoggerFrom(ctx)
k8sClient := mgr.GetClient()
@@ -182,6 +188,6 @@ func (c trunkReconcilerConstructor) SetupWithManager(ctx context.Context, mgr ct
return err
}
- r := reconciler.NewController(controllerName, mgr.GetClient(), c.scopeFactory, trunkHelperFactory{}, trunkStatusWriter{})
+ r := reconciler.NewController(controllerName, mgr.GetClient(), c.scopeFactory, trunkHelperFactory{}, trunkStatusWriter{}, c.defaultResyncPeriod)
return builder.Complete(&r)
}
diff --git a/internal/controllers/trunk/zz_generated.adapter.go b/internal/controllers/trunk/zz_generated.adapter.go
index ef7e54457..3028d4457 100644
--- a/internal/controllers/trunk/zz_generated.adapter.go
+++ b/internal/controllers/trunk/zz_generated.adapter.go
@@ -18,6 +18,8 @@ limitations under the License.
package trunk
import (
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+
orcv1alpha1 "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1"
"github.com/k-orc/openstack-resource-controller/v2/internal/controllers/generic/interfaces"
)
@@ -55,6 +57,14 @@ func (f adapterT) GetManagedOptions() *orcv1alpha1.ManagedOptions {
return f.Spec.ManagedOptions
}
+func (f adapterT) GetResyncPeriod() *metav1.Duration {
+ return f.Spec.ResyncPeriod
+}
+
+func (f adapterT) GetLastSyncTime() *metav1.Time {
+ return f.Status.LastSyncTime
+}
+
func (f adapterT) GetStatusID() *string {
return f.Status.ID
}
@@ -77,6 +87,10 @@ func (f adapterT) GetImportFilter() *filterT {
return f.Spec.Import.Filter
}
+func (f adapterT) IsImported() bool {
+ return f.GetImportID() != nil || f.GetImportFilter() != nil
+}
+
// getResourceName returns the name of the OpenStack resource we should use.
// This method is not implemented as part of APIObjectAdapter as it is intended
// to be used by resource actuators, which don't use the adapter.
diff --git a/internal/controllers/user/controller.go b/internal/controllers/user/controller.go
index e0f106927..86e34b4b1 100644
--- a/internal/controllers/user/controller.go
+++ b/internal/controllers/user/controller.go
@@ -19,6 +19,7 @@ package user
import (
"context"
"errors"
+ "time"
corev1 "k8s.io/api/core/v1"
ctrl "sigs.k8s.io/controller-runtime"
@@ -41,17 +42,22 @@ const controllerName = "user"
// +kubebuilder:rbac:groups=openstack.k-orc.cloud,resources=users/status,verbs=get;update;patch
type userReconcilerConstructor struct {
- scopeFactory scope.Factory
+ scopeFactory scope.Factory
+ defaultResyncPeriod time.Duration
}
func New(scopeFactory scope.Factory) interfaces.Controller {
- return userReconcilerConstructor{scopeFactory: scopeFactory}
+ return &userReconcilerConstructor{scopeFactory: scopeFactory}
}
func (userReconcilerConstructor) GetName() string {
return controllerName
}
+func (c *userReconcilerConstructor) SetDefaultResyncPeriod(d time.Duration) {
+ c.defaultResyncPeriod = d
+}
+
var domainDependency = dependency.NewDeletionGuardDependency[*orcv1alpha1.UserList, *orcv1alpha1.Domain](
"spec.resource.domainRef",
func(user *orcv1alpha1.User) []string {
@@ -99,7 +105,7 @@ var passwordDependency = dependency.NewDependency[*orcv1alpha1.UserList, *corev1
)
// SetupWithManager sets up the controller with the Manager.
-func (c userReconcilerConstructor) SetupWithManager(ctx context.Context, mgr ctrl.Manager, options controller.Options) error {
+func (c *userReconcilerConstructor) SetupWithManager(ctx context.Context, mgr ctrl.Manager, options controller.Options) error {
log := ctrl.LoggerFrom(ctx)
k8sClient := mgr.GetClient()
@@ -156,6 +162,6 @@ func (c userReconcilerConstructor) SetupWithManager(ctx context.Context, mgr ctr
return err
}
- r := reconciler.NewController(controllerName, mgr.GetClient(), c.scopeFactory, userHelperFactory{}, userStatusWriter{})
+ r := reconciler.NewController(controllerName, mgr.GetClient(), c.scopeFactory, userHelperFactory{}, userStatusWriter{}, c.defaultResyncPeriod)
return builder.Complete(&r)
}
diff --git a/internal/controllers/user/zz_generated.adapter.go b/internal/controllers/user/zz_generated.adapter.go
index 718a1ef46..5367e84f2 100644
--- a/internal/controllers/user/zz_generated.adapter.go
+++ b/internal/controllers/user/zz_generated.adapter.go
@@ -18,6 +18,8 @@ limitations under the License.
package user
import (
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+
orcv1alpha1 "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1"
"github.com/k-orc/openstack-resource-controller/v2/internal/controllers/generic/interfaces"
)
@@ -55,6 +57,14 @@ func (f adapterT) GetManagedOptions() *orcv1alpha1.ManagedOptions {
return f.Spec.ManagedOptions
}
+func (f adapterT) GetResyncPeriod() *metav1.Duration {
+ return f.Spec.ResyncPeriod
+}
+
+func (f adapterT) GetLastSyncTime() *metav1.Time {
+ return f.Status.LastSyncTime
+}
+
func (f adapterT) GetStatusID() *string {
return f.Status.ID
}
@@ -77,6 +87,10 @@ func (f adapterT) GetImportFilter() *filterT {
return f.Spec.Import.Filter
}
+func (f adapterT) IsImported() bool {
+ return f.GetImportID() != nil || f.GetImportFilter() != nil
+}
+
// getResourceName returns the name of the OpenStack resource we should use.
// This method is not implemented as part of APIObjectAdapter as it is intended
// to be used by resource actuators, which don't use the adapter.
diff --git a/internal/controllers/volume/controller.go b/internal/controllers/volume/controller.go
index fb64c2c75..36fd5438f 100644
--- a/internal/controllers/volume/controller.go
+++ b/internal/controllers/volume/controller.go
@@ -20,6 +20,7 @@ import (
"context"
"errors"
"fmt"
+ "time"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
@@ -51,17 +52,22 @@ const controllerName = "volume"
// +kubebuilder:rbac:groups=openstack.k-orc.cloud,resources=volumes/status,verbs=get;update;patch
type volumeReconcilerConstructor struct {
- scopeFactory scope.Factory
+ scopeFactory scope.Factory
+ defaultResyncPeriod time.Duration
}
func New(scopeFactory scope.Factory) interfaces.Controller {
- return volumeReconcilerConstructor{scopeFactory: scopeFactory}
+ return &volumeReconcilerConstructor{scopeFactory: scopeFactory}
}
func (volumeReconcilerConstructor) GetName() string {
return controllerName
}
+func (c *volumeReconcilerConstructor) SetDefaultResyncPeriod(d time.Duration) {
+ c.defaultResyncPeriod = d
+}
+
var volumetypeDependency = dependency.NewDeletionGuardDependency[*orcv1alpha1.VolumeList, *orcv1alpha1.VolumeType](
"spec.resource.volumeTypeRef",
func(volume *orcv1alpha1.Volume) []string {
@@ -213,7 +219,7 @@ func serverToVolumeMapFunc(ctx context.Context, k8sClient client.Client) handler
}
// SetupWithManager sets up the controller with the Manager.
-func (c volumeReconcilerConstructor) SetupWithManager(ctx context.Context, mgr ctrl.Manager, options controller.Options) error {
+func (c *volumeReconcilerConstructor) SetupWithManager(ctx context.Context, mgr ctrl.Manager, options controller.Options) error {
log := ctrl.LoggerFrom(ctx)
k8sClient := mgr.GetClient()
@@ -249,6 +255,6 @@ func (c volumeReconcilerConstructor) SetupWithManager(ctx context.Context, mgr c
return err
}
- r := reconciler.NewController(controllerName, mgr.GetClient(), c.scopeFactory, volumeHelperFactory{}, volumeStatusWriter{})
+ r := reconciler.NewController(controllerName, mgr.GetClient(), c.scopeFactory, volumeHelperFactory{}, volumeStatusWriter{}, c.defaultResyncPeriod)
return builder.Complete(&r)
}
diff --git a/internal/controllers/volume/zz_generated.adapter.go b/internal/controllers/volume/zz_generated.adapter.go
index 956b64693..6f9dcae13 100644
--- a/internal/controllers/volume/zz_generated.adapter.go
+++ b/internal/controllers/volume/zz_generated.adapter.go
@@ -18,6 +18,8 @@ limitations under the License.
package volume
import (
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+
orcv1alpha1 "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1"
"github.com/k-orc/openstack-resource-controller/v2/internal/controllers/generic/interfaces"
)
@@ -55,6 +57,14 @@ func (f adapterT) GetManagedOptions() *orcv1alpha1.ManagedOptions {
return f.Spec.ManagedOptions
}
+func (f adapterT) GetResyncPeriod() *metav1.Duration {
+ return f.Spec.ResyncPeriod
+}
+
+func (f adapterT) GetLastSyncTime() *metav1.Time {
+ return f.Status.LastSyncTime
+}
+
func (f adapterT) GetStatusID() *string {
return f.Status.ID
}
@@ -77,6 +87,10 @@ func (f adapterT) GetImportFilter() *filterT {
return f.Spec.Import.Filter
}
+func (f adapterT) IsImported() bool {
+ return f.GetImportID() != nil || f.GetImportFilter() != nil
+}
+
// getResourceName returns the name of the OpenStack resource we should use.
// This method is not implemented as part of APIObjectAdapter as it is intended
// to be used by resource actuators, which don't use the adapter.
diff --git a/internal/controllers/volumetype/controller.go b/internal/controllers/volumetype/controller.go
index 45707166a..a358a6d2d 100644
--- a/internal/controllers/volumetype/controller.go
+++ b/internal/controllers/volumetype/controller.go
@@ -19,6 +19,7 @@ package volumetype
import (
"context"
"errors"
+ "time"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/controller"
@@ -36,19 +37,24 @@ const controllerName = "volumetype"
// +kubebuilder:rbac:groups=openstack.k-orc.cloud,resources=volumetypes/status,verbs=get;update;patch
type volumetypeReconcilerConstructor struct {
- scopeFactory scope.Factory
+ scopeFactory scope.Factory
+ defaultResyncPeriod time.Duration
}
func New(scopeFactory scope.Factory) interfaces.Controller {
- return volumetypeReconcilerConstructor{scopeFactory: scopeFactory}
+ return &volumetypeReconcilerConstructor{scopeFactory: scopeFactory}
}
func (volumetypeReconcilerConstructor) GetName() string {
return controllerName
}
+func (c *volumetypeReconcilerConstructor) SetDefaultResyncPeriod(d time.Duration) {
+ c.defaultResyncPeriod = d
+}
+
// SetupWithManager sets up the controller with the Manager.
-func (c volumetypeReconcilerConstructor) SetupWithManager(ctx context.Context, mgr ctrl.Manager, options controller.Options) error {
+func (c *volumetypeReconcilerConstructor) SetupWithManager(ctx context.Context, mgr ctrl.Manager, options controller.Options) error {
log := ctrl.LoggerFrom(ctx)
builder := ctrl.NewControllerManagedBy(mgr).
@@ -62,6 +68,6 @@ func (c volumetypeReconcilerConstructor) SetupWithManager(ctx context.Context, m
return err
}
- r := reconciler.NewController(controllerName, mgr.GetClient(), c.scopeFactory, volumetypeHelperFactory{}, volumetypeStatusWriter{})
+ r := reconciler.NewController(controllerName, mgr.GetClient(), c.scopeFactory, volumetypeHelperFactory{}, volumetypeStatusWriter{}, c.defaultResyncPeriod)
return builder.Complete(&r)
}
diff --git a/internal/controllers/volumetype/zz_generated.adapter.go b/internal/controllers/volumetype/zz_generated.adapter.go
index 9f19fa751..71c3caab1 100644
--- a/internal/controllers/volumetype/zz_generated.adapter.go
+++ b/internal/controllers/volumetype/zz_generated.adapter.go
@@ -18,6 +18,8 @@ limitations under the License.
package volumetype
import (
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+
orcv1alpha1 "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1"
"github.com/k-orc/openstack-resource-controller/v2/internal/controllers/generic/interfaces"
)
@@ -55,6 +57,14 @@ func (f adapterT) GetManagedOptions() *orcv1alpha1.ManagedOptions {
return f.Spec.ManagedOptions
}
+func (f adapterT) GetResyncPeriod() *metav1.Duration {
+ return f.Spec.ResyncPeriod
+}
+
+func (f adapterT) GetLastSyncTime() *metav1.Time {
+ return f.Status.LastSyncTime
+}
+
func (f adapterT) GetStatusID() *string {
return f.Status.ID
}
@@ -77,6 +87,10 @@ func (f adapterT) GetImportFilter() *filterT {
return f.Spec.Import.Filter
}
+func (f adapterT) IsImported() bool {
+ return f.GetImportID() != nil || f.GetImportFilter() != nil
+}
+
// getResourceName returns the name of the OpenStack resource we should use.
// This method is not implemented as part of APIObjectAdapter as it is intended
// to be used by resource actuators, which don't use the adapter.
diff --git a/internal/manager/manager.go b/internal/manager/manager.go
index ea84eb77f..0965acc94 100644
--- a/internal/manager/manager.go
+++ b/internal/manager/manager.go
@@ -20,6 +20,7 @@ import (
"context"
"crypto/tls"
"fmt"
+ "time"
// Import all Kubernetes client auth plugins (e.g. Azure, GCP, OIDC, etc.)
// to ensure that exec-entrypoint and run can make use of them.
@@ -49,6 +50,7 @@ type Options struct {
TLSOpts []func(*tls.Config)
ScopeCacheMaxSize int
WatchNamespaces []string
+ DefaultResyncPeriod time.Duration
}
func Run(ctx context.Context, opts *Options, restConfig *rest.Config, scheme *runtime.Scheme, setupLog, log logr.Logger, controllers []interfaces.Controller) error {
@@ -142,6 +144,11 @@ func Run(ctx context.Context, opts *Options, restConfig *rest.Config, scheme *ru
}
for _, c := range controllers {
+ // If the controller supports a configurable default resync period, wire
+ // in the operator-level default before setup.
+ if rc, ok := c.(interfaces.ResyncConfigurable); ok {
+ rc.SetDefaultResyncPeriod(opts.DefaultResyncPeriod)
+ }
if err := c.SetupWithManager(ctx, mgr, controller.Options{}); err != nil {
return fmt.Errorf("unable to create %s controller: %w", c.GetName(), err)
}
diff --git a/pkg/clients/applyconfiguration/api/v1alpha1/addressscopespec.go b/pkg/clients/applyconfiguration/api/v1alpha1/addressscopespec.go
index 4a42ce57c..1ef5b5cee 100644
--- a/pkg/clients/applyconfiguration/api/v1alpha1/addressscopespec.go
+++ b/pkg/clients/applyconfiguration/api/v1alpha1/addressscopespec.go
@@ -20,6 +20,7 @@ package v1alpha1
import (
apiv1alpha1 "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
// AddressScopeSpecApplyConfiguration represents a declarative configuration of the AddressScopeSpec type for use
@@ -29,6 +30,7 @@ type AddressScopeSpecApplyConfiguration struct {
Resource *AddressScopeResourceSpecApplyConfiguration `json:"resource,omitempty"`
ManagementPolicy *apiv1alpha1.ManagementPolicy `json:"managementPolicy,omitempty"`
ManagedOptions *ManagedOptionsApplyConfiguration `json:"managedOptions,omitempty"`
+ ResyncPeriod *v1.Duration `json:"resyncPeriod,omitempty"`
CloudCredentialsRef *CloudCredentialsReferenceApplyConfiguration `json:"cloudCredentialsRef,omitempty"`
}
@@ -70,6 +72,14 @@ func (b *AddressScopeSpecApplyConfiguration) WithManagedOptions(value *ManagedOp
return b
}
+// WithResyncPeriod sets the ResyncPeriod field in the declarative configuration to the given value
+// and returns the receiver, so that objects can be built by chaining "With" function invocations.
+// If called multiple times, the ResyncPeriod field is set to the value of the last call.
+func (b *AddressScopeSpecApplyConfiguration) WithResyncPeriod(value v1.Duration) *AddressScopeSpecApplyConfiguration {
+ b.ResyncPeriod = &value
+ return b
+}
+
// WithCloudCredentialsRef sets the CloudCredentialsRef field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the CloudCredentialsRef field is set to the value of the last call.
diff --git a/pkg/clients/applyconfiguration/api/v1alpha1/addressscopestatus.go b/pkg/clients/applyconfiguration/api/v1alpha1/addressscopestatus.go
index c2d823af0..b7ecb594f 100644
--- a/pkg/clients/applyconfiguration/api/v1alpha1/addressscopestatus.go
+++ b/pkg/clients/applyconfiguration/api/v1alpha1/addressscopestatus.go
@@ -19,15 +19,17 @@ limitations under the License.
package v1alpha1
import (
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
v1 "k8s.io/client-go/applyconfigurations/meta/v1"
)
// AddressScopeStatusApplyConfiguration represents a declarative configuration of the AddressScopeStatus type for use
// with apply.
type AddressScopeStatusApplyConfiguration struct {
- Conditions []v1.ConditionApplyConfiguration `json:"conditions,omitempty"`
- ID *string `json:"id,omitempty"`
- Resource *AddressScopeResourceStatusApplyConfiguration `json:"resource,omitempty"`
+ Conditions []v1.ConditionApplyConfiguration `json:"conditions,omitempty"`
+ ID *string `json:"id,omitempty"`
+ Resource *AddressScopeResourceStatusApplyConfiguration `json:"resource,omitempty"`
+ LastSyncTime *metav1.Time `json:"lastSyncTime,omitempty"`
}
// AddressScopeStatusApplyConfiguration constructs a declarative configuration of the AddressScopeStatus type for use with
@@ -64,3 +66,11 @@ func (b *AddressScopeStatusApplyConfiguration) WithResource(value *AddressScopeR
b.Resource = value
return b
}
+
+// WithLastSyncTime sets the LastSyncTime field in the declarative configuration to the given value
+// and returns the receiver, so that objects can be built by chaining "With" function invocations.
+// If called multiple times, the LastSyncTime field is set to the value of the last call.
+func (b *AddressScopeStatusApplyConfiguration) WithLastSyncTime(value metav1.Time) *AddressScopeStatusApplyConfiguration {
+ b.LastSyncTime = &value
+ return b
+}
diff --git a/pkg/clients/applyconfiguration/api/v1alpha1/applicationcredentialspec.go b/pkg/clients/applyconfiguration/api/v1alpha1/applicationcredentialspec.go
index d73e0886b..09f1178b1 100644
--- a/pkg/clients/applyconfiguration/api/v1alpha1/applicationcredentialspec.go
+++ b/pkg/clients/applyconfiguration/api/v1alpha1/applicationcredentialspec.go
@@ -20,6 +20,7 @@ package v1alpha1
import (
apiv1alpha1 "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
// ApplicationCredentialSpecApplyConfiguration represents a declarative configuration of the ApplicationCredentialSpec type for use
@@ -29,6 +30,7 @@ type ApplicationCredentialSpecApplyConfiguration struct {
Resource *ApplicationCredentialResourceSpecApplyConfiguration `json:"resource,omitempty"`
ManagementPolicy *apiv1alpha1.ManagementPolicy `json:"managementPolicy,omitempty"`
ManagedOptions *ManagedOptionsApplyConfiguration `json:"managedOptions,omitempty"`
+ ResyncPeriod *v1.Duration `json:"resyncPeriod,omitempty"`
CloudCredentialsRef *CloudCredentialsReferenceApplyConfiguration `json:"cloudCredentialsRef,omitempty"`
}
@@ -70,6 +72,14 @@ func (b *ApplicationCredentialSpecApplyConfiguration) WithManagedOptions(value *
return b
}
+// WithResyncPeriod sets the ResyncPeriod field in the declarative configuration to the given value
+// and returns the receiver, so that objects can be built by chaining "With" function invocations.
+// If called multiple times, the ResyncPeriod field is set to the value of the last call.
+func (b *ApplicationCredentialSpecApplyConfiguration) WithResyncPeriod(value v1.Duration) *ApplicationCredentialSpecApplyConfiguration {
+ b.ResyncPeriod = &value
+ return b
+}
+
// WithCloudCredentialsRef sets the CloudCredentialsRef field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the CloudCredentialsRef field is set to the value of the last call.
diff --git a/pkg/clients/applyconfiguration/api/v1alpha1/applicationcredentialstatus.go b/pkg/clients/applyconfiguration/api/v1alpha1/applicationcredentialstatus.go
index 2dc54e77a..70e271a57 100644
--- a/pkg/clients/applyconfiguration/api/v1alpha1/applicationcredentialstatus.go
+++ b/pkg/clients/applyconfiguration/api/v1alpha1/applicationcredentialstatus.go
@@ -19,15 +19,17 @@ limitations under the License.
package v1alpha1
import (
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
v1 "k8s.io/client-go/applyconfigurations/meta/v1"
)
// ApplicationCredentialStatusApplyConfiguration represents a declarative configuration of the ApplicationCredentialStatus type for use
// with apply.
type ApplicationCredentialStatusApplyConfiguration struct {
- Conditions []v1.ConditionApplyConfiguration `json:"conditions,omitempty"`
- ID *string `json:"id,omitempty"`
- Resource *ApplicationCredentialResourceStatusApplyConfiguration `json:"resource,omitempty"`
+ Conditions []v1.ConditionApplyConfiguration `json:"conditions,omitempty"`
+ ID *string `json:"id,omitempty"`
+ Resource *ApplicationCredentialResourceStatusApplyConfiguration `json:"resource,omitempty"`
+ LastSyncTime *metav1.Time `json:"lastSyncTime,omitempty"`
}
// ApplicationCredentialStatusApplyConfiguration constructs a declarative configuration of the ApplicationCredentialStatus type for use with
@@ -64,3 +66,11 @@ func (b *ApplicationCredentialStatusApplyConfiguration) WithResource(value *Appl
b.Resource = value
return b
}
+
+// WithLastSyncTime sets the LastSyncTime field in the declarative configuration to the given value
+// and returns the receiver, so that objects can be built by chaining "With" function invocations.
+// If called multiple times, the LastSyncTime field is set to the value of the last call.
+func (b *ApplicationCredentialStatusApplyConfiguration) WithLastSyncTime(value metav1.Time) *ApplicationCredentialStatusApplyConfiguration {
+ b.LastSyncTime = &value
+ return b
+}
diff --git a/pkg/clients/applyconfiguration/api/v1alpha1/domainspec.go b/pkg/clients/applyconfiguration/api/v1alpha1/domainspec.go
index e5357a87e..dc2da0444 100644
--- a/pkg/clients/applyconfiguration/api/v1alpha1/domainspec.go
+++ b/pkg/clients/applyconfiguration/api/v1alpha1/domainspec.go
@@ -20,6 +20,7 @@ package v1alpha1
import (
apiv1alpha1 "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
// DomainSpecApplyConfiguration represents a declarative configuration of the DomainSpec type for use
@@ -29,6 +30,7 @@ type DomainSpecApplyConfiguration struct {
Resource *DomainResourceSpecApplyConfiguration `json:"resource,omitempty"`
ManagementPolicy *apiv1alpha1.ManagementPolicy `json:"managementPolicy,omitempty"`
ManagedOptions *ManagedOptionsApplyConfiguration `json:"managedOptions,omitempty"`
+ ResyncPeriod *v1.Duration `json:"resyncPeriod,omitempty"`
CloudCredentialsRef *CloudCredentialsReferenceApplyConfiguration `json:"cloudCredentialsRef,omitempty"`
}
@@ -70,6 +72,14 @@ func (b *DomainSpecApplyConfiguration) WithManagedOptions(value *ManagedOptionsA
return b
}
+// WithResyncPeriod sets the ResyncPeriod field in the declarative configuration to the given value
+// and returns the receiver, so that objects can be built by chaining "With" function invocations.
+// If called multiple times, the ResyncPeriod field is set to the value of the last call.
+func (b *DomainSpecApplyConfiguration) WithResyncPeriod(value v1.Duration) *DomainSpecApplyConfiguration {
+ b.ResyncPeriod = &value
+ return b
+}
+
// WithCloudCredentialsRef sets the CloudCredentialsRef field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the CloudCredentialsRef field is set to the value of the last call.
diff --git a/pkg/clients/applyconfiguration/api/v1alpha1/domainstatus.go b/pkg/clients/applyconfiguration/api/v1alpha1/domainstatus.go
index c7540a168..c87fc50e1 100644
--- a/pkg/clients/applyconfiguration/api/v1alpha1/domainstatus.go
+++ b/pkg/clients/applyconfiguration/api/v1alpha1/domainstatus.go
@@ -19,15 +19,17 @@ limitations under the License.
package v1alpha1
import (
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
v1 "k8s.io/client-go/applyconfigurations/meta/v1"
)
// DomainStatusApplyConfiguration represents a declarative configuration of the DomainStatus type for use
// with apply.
type DomainStatusApplyConfiguration struct {
- Conditions []v1.ConditionApplyConfiguration `json:"conditions,omitempty"`
- ID *string `json:"id,omitempty"`
- Resource *DomainResourceStatusApplyConfiguration `json:"resource,omitempty"`
+ Conditions []v1.ConditionApplyConfiguration `json:"conditions,omitempty"`
+ ID *string `json:"id,omitempty"`
+ Resource *DomainResourceStatusApplyConfiguration `json:"resource,omitempty"`
+ LastSyncTime *metav1.Time `json:"lastSyncTime,omitempty"`
}
// DomainStatusApplyConfiguration constructs a declarative configuration of the DomainStatus type for use with
@@ -64,3 +66,11 @@ func (b *DomainStatusApplyConfiguration) WithResource(value *DomainResourceStatu
b.Resource = value
return b
}
+
+// WithLastSyncTime sets the LastSyncTime field in the declarative configuration to the given value
+// and returns the receiver, so that objects can be built by chaining "With" function invocations.
+// If called multiple times, the LastSyncTime field is set to the value of the last call.
+func (b *DomainStatusApplyConfiguration) WithLastSyncTime(value metav1.Time) *DomainStatusApplyConfiguration {
+ b.LastSyncTime = &value
+ return b
+}
diff --git a/pkg/clients/applyconfiguration/api/v1alpha1/endpointspec.go b/pkg/clients/applyconfiguration/api/v1alpha1/endpointspec.go
index 198237c30..ddde864fe 100644
--- a/pkg/clients/applyconfiguration/api/v1alpha1/endpointspec.go
+++ b/pkg/clients/applyconfiguration/api/v1alpha1/endpointspec.go
@@ -20,6 +20,7 @@ package v1alpha1
import (
apiv1alpha1 "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
// EndpointSpecApplyConfiguration represents a declarative configuration of the EndpointSpec type for use
@@ -29,6 +30,7 @@ type EndpointSpecApplyConfiguration struct {
Resource *EndpointResourceSpecApplyConfiguration `json:"resource,omitempty"`
ManagementPolicy *apiv1alpha1.ManagementPolicy `json:"managementPolicy,omitempty"`
ManagedOptions *ManagedOptionsApplyConfiguration `json:"managedOptions,omitempty"`
+ ResyncPeriod *v1.Duration `json:"resyncPeriod,omitempty"`
CloudCredentialsRef *CloudCredentialsReferenceApplyConfiguration `json:"cloudCredentialsRef,omitempty"`
}
@@ -70,6 +72,14 @@ func (b *EndpointSpecApplyConfiguration) WithManagedOptions(value *ManagedOption
return b
}
+// WithResyncPeriod sets the ResyncPeriod field in the declarative configuration to the given value
+// and returns the receiver, so that objects can be built by chaining "With" function invocations.
+// If called multiple times, the ResyncPeriod field is set to the value of the last call.
+func (b *EndpointSpecApplyConfiguration) WithResyncPeriod(value v1.Duration) *EndpointSpecApplyConfiguration {
+ b.ResyncPeriod = &value
+ return b
+}
+
// WithCloudCredentialsRef sets the CloudCredentialsRef field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the CloudCredentialsRef field is set to the value of the last call.
diff --git a/pkg/clients/applyconfiguration/api/v1alpha1/endpointstatus.go b/pkg/clients/applyconfiguration/api/v1alpha1/endpointstatus.go
index d620075a5..63156d676 100644
--- a/pkg/clients/applyconfiguration/api/v1alpha1/endpointstatus.go
+++ b/pkg/clients/applyconfiguration/api/v1alpha1/endpointstatus.go
@@ -19,15 +19,17 @@ limitations under the License.
package v1alpha1
import (
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
v1 "k8s.io/client-go/applyconfigurations/meta/v1"
)
// EndpointStatusApplyConfiguration represents a declarative configuration of the EndpointStatus type for use
// with apply.
type EndpointStatusApplyConfiguration struct {
- Conditions []v1.ConditionApplyConfiguration `json:"conditions,omitempty"`
- ID *string `json:"id,omitempty"`
- Resource *EndpointResourceStatusApplyConfiguration `json:"resource,omitempty"`
+ Conditions []v1.ConditionApplyConfiguration `json:"conditions,omitempty"`
+ ID *string `json:"id,omitempty"`
+ Resource *EndpointResourceStatusApplyConfiguration `json:"resource,omitempty"`
+ LastSyncTime *metav1.Time `json:"lastSyncTime,omitempty"`
}
// EndpointStatusApplyConfiguration constructs a declarative configuration of the EndpointStatus type for use with
@@ -64,3 +66,11 @@ func (b *EndpointStatusApplyConfiguration) WithResource(value *EndpointResourceS
b.Resource = value
return b
}
+
+// WithLastSyncTime sets the LastSyncTime field in the declarative configuration to the given value
+// and returns the receiver, so that objects can be built by chaining "With" function invocations.
+// If called multiple times, the LastSyncTime field is set to the value of the last call.
+func (b *EndpointStatusApplyConfiguration) WithLastSyncTime(value metav1.Time) *EndpointStatusApplyConfiguration {
+ b.LastSyncTime = &value
+ return b
+}
diff --git a/pkg/clients/applyconfiguration/api/v1alpha1/flavorspec.go b/pkg/clients/applyconfiguration/api/v1alpha1/flavorspec.go
index abe7c0d07..28f5e9f50 100644
--- a/pkg/clients/applyconfiguration/api/v1alpha1/flavorspec.go
+++ b/pkg/clients/applyconfiguration/api/v1alpha1/flavorspec.go
@@ -20,6 +20,7 @@ package v1alpha1
import (
apiv1alpha1 "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
// FlavorSpecApplyConfiguration represents a declarative configuration of the FlavorSpec type for use
@@ -29,6 +30,7 @@ type FlavorSpecApplyConfiguration struct {
Resource *FlavorResourceSpecApplyConfiguration `json:"resource,omitempty"`
ManagementPolicy *apiv1alpha1.ManagementPolicy `json:"managementPolicy,omitempty"`
ManagedOptions *ManagedOptionsApplyConfiguration `json:"managedOptions,omitempty"`
+ ResyncPeriod *v1.Duration `json:"resyncPeriod,omitempty"`
CloudCredentialsRef *CloudCredentialsReferenceApplyConfiguration `json:"cloudCredentialsRef,omitempty"`
}
@@ -70,6 +72,14 @@ func (b *FlavorSpecApplyConfiguration) WithManagedOptions(value *ManagedOptionsA
return b
}
+// WithResyncPeriod sets the ResyncPeriod field in the declarative configuration to the given value
+// and returns the receiver, so that objects can be built by chaining "With" function invocations.
+// If called multiple times, the ResyncPeriod field is set to the value of the last call.
+func (b *FlavorSpecApplyConfiguration) WithResyncPeriod(value v1.Duration) *FlavorSpecApplyConfiguration {
+ b.ResyncPeriod = &value
+ return b
+}
+
// WithCloudCredentialsRef sets the CloudCredentialsRef field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the CloudCredentialsRef field is set to the value of the last call.
diff --git a/pkg/clients/applyconfiguration/api/v1alpha1/flavorstatus.go b/pkg/clients/applyconfiguration/api/v1alpha1/flavorstatus.go
index 928a60e26..dd370aa1b 100644
--- a/pkg/clients/applyconfiguration/api/v1alpha1/flavorstatus.go
+++ b/pkg/clients/applyconfiguration/api/v1alpha1/flavorstatus.go
@@ -19,15 +19,17 @@ limitations under the License.
package v1alpha1
import (
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
v1 "k8s.io/client-go/applyconfigurations/meta/v1"
)
// FlavorStatusApplyConfiguration represents a declarative configuration of the FlavorStatus type for use
// with apply.
type FlavorStatusApplyConfiguration struct {
- Conditions []v1.ConditionApplyConfiguration `json:"conditions,omitempty"`
- ID *string `json:"id,omitempty"`
- Resource *FlavorResourceStatusApplyConfiguration `json:"resource,omitempty"`
+ Conditions []v1.ConditionApplyConfiguration `json:"conditions,omitempty"`
+ ID *string `json:"id,omitempty"`
+ Resource *FlavorResourceStatusApplyConfiguration `json:"resource,omitempty"`
+ LastSyncTime *metav1.Time `json:"lastSyncTime,omitempty"`
}
// FlavorStatusApplyConfiguration constructs a declarative configuration of the FlavorStatus type for use with
@@ -64,3 +66,11 @@ func (b *FlavorStatusApplyConfiguration) WithResource(value *FlavorResourceStatu
b.Resource = value
return b
}
+
+// WithLastSyncTime sets the LastSyncTime field in the declarative configuration to the given value
+// and returns the receiver, so that objects can be built by chaining "With" function invocations.
+// If called multiple times, the LastSyncTime field is set to the value of the last call.
+func (b *FlavorStatusApplyConfiguration) WithLastSyncTime(value metav1.Time) *FlavorStatusApplyConfiguration {
+ b.LastSyncTime = &value
+ return b
+}
diff --git a/pkg/clients/applyconfiguration/api/v1alpha1/floatingipspec.go b/pkg/clients/applyconfiguration/api/v1alpha1/floatingipspec.go
index 8fe12ac3a..066b710b8 100644
--- a/pkg/clients/applyconfiguration/api/v1alpha1/floatingipspec.go
+++ b/pkg/clients/applyconfiguration/api/v1alpha1/floatingipspec.go
@@ -20,6 +20,7 @@ package v1alpha1
import (
apiv1alpha1 "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
// FloatingIPSpecApplyConfiguration represents a declarative configuration of the FloatingIPSpec type for use
@@ -29,6 +30,7 @@ type FloatingIPSpecApplyConfiguration struct {
Resource *FloatingIPResourceSpecApplyConfiguration `json:"resource,omitempty"`
ManagementPolicy *apiv1alpha1.ManagementPolicy `json:"managementPolicy,omitempty"`
ManagedOptions *ManagedOptionsApplyConfiguration `json:"managedOptions,omitempty"`
+ ResyncPeriod *v1.Duration `json:"resyncPeriod,omitempty"`
CloudCredentialsRef *CloudCredentialsReferenceApplyConfiguration `json:"cloudCredentialsRef,omitempty"`
}
@@ -70,6 +72,14 @@ func (b *FloatingIPSpecApplyConfiguration) WithManagedOptions(value *ManagedOpti
return b
}
+// WithResyncPeriod sets the ResyncPeriod field in the declarative configuration to the given value
+// and returns the receiver, so that objects can be built by chaining "With" function invocations.
+// If called multiple times, the ResyncPeriod field is set to the value of the last call.
+func (b *FloatingIPSpecApplyConfiguration) WithResyncPeriod(value v1.Duration) *FloatingIPSpecApplyConfiguration {
+ b.ResyncPeriod = &value
+ return b
+}
+
// WithCloudCredentialsRef sets the CloudCredentialsRef field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the CloudCredentialsRef field is set to the value of the last call.
diff --git a/pkg/clients/applyconfiguration/api/v1alpha1/floatingipstatus.go b/pkg/clients/applyconfiguration/api/v1alpha1/floatingipstatus.go
index 61291bdd7..eb856b839 100644
--- a/pkg/clients/applyconfiguration/api/v1alpha1/floatingipstatus.go
+++ b/pkg/clients/applyconfiguration/api/v1alpha1/floatingipstatus.go
@@ -19,15 +19,17 @@ limitations under the License.
package v1alpha1
import (
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
v1 "k8s.io/client-go/applyconfigurations/meta/v1"
)
// FloatingIPStatusApplyConfiguration represents a declarative configuration of the FloatingIPStatus type for use
// with apply.
type FloatingIPStatusApplyConfiguration struct {
- Conditions []v1.ConditionApplyConfiguration `json:"conditions,omitempty"`
- ID *string `json:"id,omitempty"`
- Resource *FloatingIPResourceStatusApplyConfiguration `json:"resource,omitempty"`
+ Conditions []v1.ConditionApplyConfiguration `json:"conditions,omitempty"`
+ ID *string `json:"id,omitempty"`
+ Resource *FloatingIPResourceStatusApplyConfiguration `json:"resource,omitempty"`
+ LastSyncTime *metav1.Time `json:"lastSyncTime,omitempty"`
}
// FloatingIPStatusApplyConfiguration constructs a declarative configuration of the FloatingIPStatus type for use with
@@ -64,3 +66,11 @@ func (b *FloatingIPStatusApplyConfiguration) WithResource(value *FloatingIPResou
b.Resource = value
return b
}
+
+// WithLastSyncTime sets the LastSyncTime field in the declarative configuration to the given value
+// and returns the receiver, so that objects can be built by chaining "With" function invocations.
+// If called multiple times, the LastSyncTime field is set to the value of the last call.
+func (b *FloatingIPStatusApplyConfiguration) WithLastSyncTime(value metav1.Time) *FloatingIPStatusApplyConfiguration {
+ b.LastSyncTime = &value
+ return b
+}
diff --git a/pkg/clients/applyconfiguration/api/v1alpha1/groupspec.go b/pkg/clients/applyconfiguration/api/v1alpha1/groupspec.go
index 59a744101..218db914f 100644
--- a/pkg/clients/applyconfiguration/api/v1alpha1/groupspec.go
+++ b/pkg/clients/applyconfiguration/api/v1alpha1/groupspec.go
@@ -20,6 +20,7 @@ package v1alpha1
import (
apiv1alpha1 "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
// GroupSpecApplyConfiguration represents a declarative configuration of the GroupSpec type for use
@@ -29,6 +30,7 @@ type GroupSpecApplyConfiguration struct {
Resource *GroupResourceSpecApplyConfiguration `json:"resource,omitempty"`
ManagementPolicy *apiv1alpha1.ManagementPolicy `json:"managementPolicy,omitempty"`
ManagedOptions *ManagedOptionsApplyConfiguration `json:"managedOptions,omitempty"`
+ ResyncPeriod *v1.Duration `json:"resyncPeriod,omitempty"`
CloudCredentialsRef *CloudCredentialsReferenceApplyConfiguration `json:"cloudCredentialsRef,omitempty"`
}
@@ -70,6 +72,14 @@ func (b *GroupSpecApplyConfiguration) WithManagedOptions(value *ManagedOptionsAp
return b
}
+// WithResyncPeriod sets the ResyncPeriod field in the declarative configuration to the given value
+// and returns the receiver, so that objects can be built by chaining "With" function invocations.
+// If called multiple times, the ResyncPeriod field is set to the value of the last call.
+func (b *GroupSpecApplyConfiguration) WithResyncPeriod(value v1.Duration) *GroupSpecApplyConfiguration {
+ b.ResyncPeriod = &value
+ return b
+}
+
// WithCloudCredentialsRef sets the CloudCredentialsRef field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the CloudCredentialsRef field is set to the value of the last call.
diff --git a/pkg/clients/applyconfiguration/api/v1alpha1/groupstatus.go b/pkg/clients/applyconfiguration/api/v1alpha1/groupstatus.go
index 564e9cdc4..c7f97fef2 100644
--- a/pkg/clients/applyconfiguration/api/v1alpha1/groupstatus.go
+++ b/pkg/clients/applyconfiguration/api/v1alpha1/groupstatus.go
@@ -19,15 +19,17 @@ limitations under the License.
package v1alpha1
import (
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
v1 "k8s.io/client-go/applyconfigurations/meta/v1"
)
// GroupStatusApplyConfiguration represents a declarative configuration of the GroupStatus type for use
// with apply.
type GroupStatusApplyConfiguration struct {
- Conditions []v1.ConditionApplyConfiguration `json:"conditions,omitempty"`
- ID *string `json:"id,omitempty"`
- Resource *GroupResourceStatusApplyConfiguration `json:"resource,omitempty"`
+ Conditions []v1.ConditionApplyConfiguration `json:"conditions,omitempty"`
+ ID *string `json:"id,omitempty"`
+ Resource *GroupResourceStatusApplyConfiguration `json:"resource,omitempty"`
+ LastSyncTime *metav1.Time `json:"lastSyncTime,omitempty"`
}
// GroupStatusApplyConfiguration constructs a declarative configuration of the GroupStatus type for use with
@@ -64,3 +66,11 @@ func (b *GroupStatusApplyConfiguration) WithResource(value *GroupResourceStatusA
b.Resource = value
return b
}
+
+// WithLastSyncTime sets the LastSyncTime field in the declarative configuration to the given value
+// and returns the receiver, so that objects can be built by chaining "With" function invocations.
+// If called multiple times, the LastSyncTime field is set to the value of the last call.
+func (b *GroupStatusApplyConfiguration) WithLastSyncTime(value metav1.Time) *GroupStatusApplyConfiguration {
+ b.LastSyncTime = &value
+ return b
+}
diff --git a/pkg/clients/applyconfiguration/api/v1alpha1/imagespec.go b/pkg/clients/applyconfiguration/api/v1alpha1/imagespec.go
index 7982dcda4..e63cfdbce 100644
--- a/pkg/clients/applyconfiguration/api/v1alpha1/imagespec.go
+++ b/pkg/clients/applyconfiguration/api/v1alpha1/imagespec.go
@@ -20,6 +20,7 @@ package v1alpha1
import (
apiv1alpha1 "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
// ImageSpecApplyConfiguration represents a declarative configuration of the ImageSpec type for use
@@ -29,6 +30,7 @@ type ImageSpecApplyConfiguration struct {
Resource *ImageResourceSpecApplyConfiguration `json:"resource,omitempty"`
ManagementPolicy *apiv1alpha1.ManagementPolicy `json:"managementPolicy,omitempty"`
ManagedOptions *ManagedOptionsApplyConfiguration `json:"managedOptions,omitempty"`
+ ResyncPeriod *v1.Duration `json:"resyncPeriod,omitempty"`
CloudCredentialsRef *CloudCredentialsReferenceApplyConfiguration `json:"cloudCredentialsRef,omitempty"`
}
@@ -70,6 +72,14 @@ func (b *ImageSpecApplyConfiguration) WithManagedOptions(value *ManagedOptionsAp
return b
}
+// WithResyncPeriod sets the ResyncPeriod field in the declarative configuration to the given value
+// and returns the receiver, so that objects can be built by chaining "With" function invocations.
+// If called multiple times, the ResyncPeriod field is set to the value of the last call.
+func (b *ImageSpecApplyConfiguration) WithResyncPeriod(value v1.Duration) *ImageSpecApplyConfiguration {
+ b.ResyncPeriod = &value
+ return b
+}
+
// WithCloudCredentialsRef sets the CloudCredentialsRef field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the CloudCredentialsRef field is set to the value of the last call.
diff --git a/pkg/clients/applyconfiguration/api/v1alpha1/imagestatus.go b/pkg/clients/applyconfiguration/api/v1alpha1/imagestatus.go
index 033e2cd30..0a4ba2519 100644
--- a/pkg/clients/applyconfiguration/api/v1alpha1/imagestatus.go
+++ b/pkg/clients/applyconfiguration/api/v1alpha1/imagestatus.go
@@ -19,6 +19,7 @@ limitations under the License.
package v1alpha1
import (
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
v1 "k8s.io/client-go/applyconfigurations/meta/v1"
)
@@ -28,6 +29,7 @@ type ImageStatusApplyConfiguration struct {
Conditions []v1.ConditionApplyConfiguration `json:"conditions,omitempty"`
ID *string `json:"id,omitempty"`
Resource *ImageResourceStatusApplyConfiguration `json:"resource,omitempty"`
+ LastSyncTime *metav1.Time `json:"lastSyncTime,omitempty"`
ImageStatusExtraApplyConfiguration `json:",inline"`
}
@@ -66,6 +68,14 @@ func (b *ImageStatusApplyConfiguration) WithResource(value *ImageResourceStatusA
return b
}
+// WithLastSyncTime sets the LastSyncTime field in the declarative configuration to the given value
+// and returns the receiver, so that objects can be built by chaining "With" function invocations.
+// If called multiple times, the LastSyncTime field is set to the value of the last call.
+func (b *ImageStatusApplyConfiguration) WithLastSyncTime(value metav1.Time) *ImageStatusApplyConfiguration {
+ b.LastSyncTime = &value
+ return b
+}
+
// WithDownloadAttempts sets the DownloadAttempts field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the DownloadAttempts field is set to the value of the last call.
diff --git a/pkg/clients/applyconfiguration/api/v1alpha1/keypairspec.go b/pkg/clients/applyconfiguration/api/v1alpha1/keypairspec.go
index 725c5278d..e8c3e5e21 100644
--- a/pkg/clients/applyconfiguration/api/v1alpha1/keypairspec.go
+++ b/pkg/clients/applyconfiguration/api/v1alpha1/keypairspec.go
@@ -20,6 +20,7 @@ package v1alpha1
import (
apiv1alpha1 "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
// KeyPairSpecApplyConfiguration represents a declarative configuration of the KeyPairSpec type for use
@@ -29,6 +30,7 @@ type KeyPairSpecApplyConfiguration struct {
Resource *KeyPairResourceSpecApplyConfiguration `json:"resource,omitempty"`
ManagementPolicy *apiv1alpha1.ManagementPolicy `json:"managementPolicy,omitempty"`
ManagedOptions *ManagedOptionsApplyConfiguration `json:"managedOptions,omitempty"`
+ ResyncPeriod *v1.Duration `json:"resyncPeriod,omitempty"`
CloudCredentialsRef *CloudCredentialsReferenceApplyConfiguration `json:"cloudCredentialsRef,omitempty"`
}
@@ -70,6 +72,14 @@ func (b *KeyPairSpecApplyConfiguration) WithManagedOptions(value *ManagedOptions
return b
}
+// WithResyncPeriod sets the ResyncPeriod field in the declarative configuration to the given value
+// and returns the receiver, so that objects can be built by chaining "With" function invocations.
+// If called multiple times, the ResyncPeriod field is set to the value of the last call.
+func (b *KeyPairSpecApplyConfiguration) WithResyncPeriod(value v1.Duration) *KeyPairSpecApplyConfiguration {
+ b.ResyncPeriod = &value
+ return b
+}
+
// WithCloudCredentialsRef sets the CloudCredentialsRef field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the CloudCredentialsRef field is set to the value of the last call.
diff --git a/pkg/clients/applyconfiguration/api/v1alpha1/keypairstatus.go b/pkg/clients/applyconfiguration/api/v1alpha1/keypairstatus.go
index fb316a629..591a9a77b 100644
--- a/pkg/clients/applyconfiguration/api/v1alpha1/keypairstatus.go
+++ b/pkg/clients/applyconfiguration/api/v1alpha1/keypairstatus.go
@@ -19,15 +19,17 @@ limitations under the License.
package v1alpha1
import (
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
v1 "k8s.io/client-go/applyconfigurations/meta/v1"
)
// KeyPairStatusApplyConfiguration represents a declarative configuration of the KeyPairStatus type for use
// with apply.
type KeyPairStatusApplyConfiguration struct {
- Conditions []v1.ConditionApplyConfiguration `json:"conditions,omitempty"`
- ID *string `json:"id,omitempty"`
- Resource *KeyPairResourceStatusApplyConfiguration `json:"resource,omitempty"`
+ Conditions []v1.ConditionApplyConfiguration `json:"conditions,omitempty"`
+ ID *string `json:"id,omitempty"`
+ Resource *KeyPairResourceStatusApplyConfiguration `json:"resource,omitempty"`
+ LastSyncTime *metav1.Time `json:"lastSyncTime,omitempty"`
}
// KeyPairStatusApplyConfiguration constructs a declarative configuration of the KeyPairStatus type for use with
@@ -64,3 +66,11 @@ func (b *KeyPairStatusApplyConfiguration) WithResource(value *KeyPairResourceSta
b.Resource = value
return b
}
+
+// WithLastSyncTime sets the LastSyncTime field in the declarative configuration to the given value
+// and returns the receiver, so that objects can be built by chaining "With" function invocations.
+// If called multiple times, the LastSyncTime field is set to the value of the last call.
+func (b *KeyPairStatusApplyConfiguration) WithLastSyncTime(value metav1.Time) *KeyPairStatusApplyConfiguration {
+ b.LastSyncTime = &value
+ return b
+}
diff --git a/pkg/clients/applyconfiguration/api/v1alpha1/networkspec.go b/pkg/clients/applyconfiguration/api/v1alpha1/networkspec.go
index a27a7b21c..682a2b264 100644
--- a/pkg/clients/applyconfiguration/api/v1alpha1/networkspec.go
+++ b/pkg/clients/applyconfiguration/api/v1alpha1/networkspec.go
@@ -20,6 +20,7 @@ package v1alpha1
import (
apiv1alpha1 "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
// NetworkSpecApplyConfiguration represents a declarative configuration of the NetworkSpec type for use
@@ -29,6 +30,7 @@ type NetworkSpecApplyConfiguration struct {
Resource *NetworkResourceSpecApplyConfiguration `json:"resource,omitempty"`
ManagementPolicy *apiv1alpha1.ManagementPolicy `json:"managementPolicy,omitempty"`
ManagedOptions *ManagedOptionsApplyConfiguration `json:"managedOptions,omitempty"`
+ ResyncPeriod *v1.Duration `json:"resyncPeriod,omitempty"`
CloudCredentialsRef *CloudCredentialsReferenceApplyConfiguration `json:"cloudCredentialsRef,omitempty"`
}
@@ -70,6 +72,14 @@ func (b *NetworkSpecApplyConfiguration) WithManagedOptions(value *ManagedOptions
return b
}
+// WithResyncPeriod sets the ResyncPeriod field in the declarative configuration to the given value
+// and returns the receiver, so that objects can be built by chaining "With" function invocations.
+// If called multiple times, the ResyncPeriod field is set to the value of the last call.
+func (b *NetworkSpecApplyConfiguration) WithResyncPeriod(value v1.Duration) *NetworkSpecApplyConfiguration {
+ b.ResyncPeriod = &value
+ return b
+}
+
// WithCloudCredentialsRef sets the CloudCredentialsRef field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the CloudCredentialsRef field is set to the value of the last call.
diff --git a/pkg/clients/applyconfiguration/api/v1alpha1/networkstatus.go b/pkg/clients/applyconfiguration/api/v1alpha1/networkstatus.go
index 1d671bd04..fa0fa85ec 100644
--- a/pkg/clients/applyconfiguration/api/v1alpha1/networkstatus.go
+++ b/pkg/clients/applyconfiguration/api/v1alpha1/networkstatus.go
@@ -19,15 +19,17 @@ limitations under the License.
package v1alpha1
import (
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
v1 "k8s.io/client-go/applyconfigurations/meta/v1"
)
// NetworkStatusApplyConfiguration represents a declarative configuration of the NetworkStatus type for use
// with apply.
type NetworkStatusApplyConfiguration struct {
- Conditions []v1.ConditionApplyConfiguration `json:"conditions,omitempty"`
- ID *string `json:"id,omitempty"`
- Resource *NetworkResourceStatusApplyConfiguration `json:"resource,omitempty"`
+ Conditions []v1.ConditionApplyConfiguration `json:"conditions,omitempty"`
+ ID *string `json:"id,omitempty"`
+ Resource *NetworkResourceStatusApplyConfiguration `json:"resource,omitempty"`
+ LastSyncTime *metav1.Time `json:"lastSyncTime,omitempty"`
}
// NetworkStatusApplyConfiguration constructs a declarative configuration of the NetworkStatus type for use with
@@ -64,3 +66,11 @@ func (b *NetworkStatusApplyConfiguration) WithResource(value *NetworkResourceSta
b.Resource = value
return b
}
+
+// WithLastSyncTime sets the LastSyncTime field in the declarative configuration to the given value
+// and returns the receiver, so that objects can be built by chaining "With" function invocations.
+// If called multiple times, the LastSyncTime field is set to the value of the last call.
+func (b *NetworkStatusApplyConfiguration) WithLastSyncTime(value metav1.Time) *NetworkStatusApplyConfiguration {
+ b.LastSyncTime = &value
+ return b
+}
diff --git a/pkg/clients/applyconfiguration/api/v1alpha1/portspec.go b/pkg/clients/applyconfiguration/api/v1alpha1/portspec.go
index f3a31f9d1..15f08e7b0 100644
--- a/pkg/clients/applyconfiguration/api/v1alpha1/portspec.go
+++ b/pkg/clients/applyconfiguration/api/v1alpha1/portspec.go
@@ -20,6 +20,7 @@ package v1alpha1
import (
apiv1alpha1 "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
// PortSpecApplyConfiguration represents a declarative configuration of the PortSpec type for use
@@ -29,6 +30,7 @@ type PortSpecApplyConfiguration struct {
Resource *PortResourceSpecApplyConfiguration `json:"resource,omitempty"`
ManagementPolicy *apiv1alpha1.ManagementPolicy `json:"managementPolicy,omitempty"`
ManagedOptions *ManagedOptionsApplyConfiguration `json:"managedOptions,omitempty"`
+ ResyncPeriod *v1.Duration `json:"resyncPeriod,omitempty"`
CloudCredentialsRef *CloudCredentialsReferenceApplyConfiguration `json:"cloudCredentialsRef,omitempty"`
}
@@ -70,6 +72,14 @@ func (b *PortSpecApplyConfiguration) WithManagedOptions(value *ManagedOptionsApp
return b
}
+// WithResyncPeriod sets the ResyncPeriod field in the declarative configuration to the given value
+// and returns the receiver, so that objects can be built by chaining "With" function invocations.
+// If called multiple times, the ResyncPeriod field is set to the value of the last call.
+func (b *PortSpecApplyConfiguration) WithResyncPeriod(value v1.Duration) *PortSpecApplyConfiguration {
+ b.ResyncPeriod = &value
+ return b
+}
+
// WithCloudCredentialsRef sets the CloudCredentialsRef field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the CloudCredentialsRef field is set to the value of the last call.
diff --git a/pkg/clients/applyconfiguration/api/v1alpha1/portstatus.go b/pkg/clients/applyconfiguration/api/v1alpha1/portstatus.go
index f902f1538..7fe027d83 100644
--- a/pkg/clients/applyconfiguration/api/v1alpha1/portstatus.go
+++ b/pkg/clients/applyconfiguration/api/v1alpha1/portstatus.go
@@ -19,15 +19,17 @@ limitations under the License.
package v1alpha1
import (
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
v1 "k8s.io/client-go/applyconfigurations/meta/v1"
)
// PortStatusApplyConfiguration represents a declarative configuration of the PortStatus type for use
// with apply.
type PortStatusApplyConfiguration struct {
- Conditions []v1.ConditionApplyConfiguration `json:"conditions,omitempty"`
- ID *string `json:"id,omitempty"`
- Resource *PortResourceStatusApplyConfiguration `json:"resource,omitempty"`
+ Conditions []v1.ConditionApplyConfiguration `json:"conditions,omitempty"`
+ ID *string `json:"id,omitempty"`
+ Resource *PortResourceStatusApplyConfiguration `json:"resource,omitempty"`
+ LastSyncTime *metav1.Time `json:"lastSyncTime,omitempty"`
}
// PortStatusApplyConfiguration constructs a declarative configuration of the PortStatus type for use with
@@ -64,3 +66,11 @@ func (b *PortStatusApplyConfiguration) WithResource(value *PortResourceStatusApp
b.Resource = value
return b
}
+
+// WithLastSyncTime sets the LastSyncTime field in the declarative configuration to the given value
+// and returns the receiver, so that objects can be built by chaining "With" function invocations.
+// If called multiple times, the LastSyncTime field is set to the value of the last call.
+func (b *PortStatusApplyConfiguration) WithLastSyncTime(value metav1.Time) *PortStatusApplyConfiguration {
+ b.LastSyncTime = &value
+ return b
+}
diff --git a/pkg/clients/applyconfiguration/api/v1alpha1/projectspec.go b/pkg/clients/applyconfiguration/api/v1alpha1/projectspec.go
index fe81e80ba..b9a681c7d 100644
--- a/pkg/clients/applyconfiguration/api/v1alpha1/projectspec.go
+++ b/pkg/clients/applyconfiguration/api/v1alpha1/projectspec.go
@@ -20,6 +20,7 @@ package v1alpha1
import (
apiv1alpha1 "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
// ProjectSpecApplyConfiguration represents a declarative configuration of the ProjectSpec type for use
@@ -29,6 +30,7 @@ type ProjectSpecApplyConfiguration struct {
Resource *ProjectResourceSpecApplyConfiguration `json:"resource,omitempty"`
ManagementPolicy *apiv1alpha1.ManagementPolicy `json:"managementPolicy,omitempty"`
ManagedOptions *ManagedOptionsApplyConfiguration `json:"managedOptions,omitempty"`
+ ResyncPeriod *v1.Duration `json:"resyncPeriod,omitempty"`
CloudCredentialsRef *CloudCredentialsReferenceApplyConfiguration `json:"cloudCredentialsRef,omitempty"`
}
@@ -70,6 +72,14 @@ func (b *ProjectSpecApplyConfiguration) WithManagedOptions(value *ManagedOptions
return b
}
+// WithResyncPeriod sets the ResyncPeriod field in the declarative configuration to the given value
+// and returns the receiver, so that objects can be built by chaining "With" function invocations.
+// If called multiple times, the ResyncPeriod field is set to the value of the last call.
+func (b *ProjectSpecApplyConfiguration) WithResyncPeriod(value v1.Duration) *ProjectSpecApplyConfiguration {
+ b.ResyncPeriod = &value
+ return b
+}
+
// WithCloudCredentialsRef sets the CloudCredentialsRef field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the CloudCredentialsRef field is set to the value of the last call.
diff --git a/pkg/clients/applyconfiguration/api/v1alpha1/projectstatus.go b/pkg/clients/applyconfiguration/api/v1alpha1/projectstatus.go
index 328980bcf..469f29ea4 100644
--- a/pkg/clients/applyconfiguration/api/v1alpha1/projectstatus.go
+++ b/pkg/clients/applyconfiguration/api/v1alpha1/projectstatus.go
@@ -19,15 +19,17 @@ limitations under the License.
package v1alpha1
import (
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
v1 "k8s.io/client-go/applyconfigurations/meta/v1"
)
// ProjectStatusApplyConfiguration represents a declarative configuration of the ProjectStatus type for use
// with apply.
type ProjectStatusApplyConfiguration struct {
- Conditions []v1.ConditionApplyConfiguration `json:"conditions,omitempty"`
- ID *string `json:"id,omitempty"`
- Resource *ProjectResourceStatusApplyConfiguration `json:"resource,omitempty"`
+ Conditions []v1.ConditionApplyConfiguration `json:"conditions,omitempty"`
+ ID *string `json:"id,omitempty"`
+ Resource *ProjectResourceStatusApplyConfiguration `json:"resource,omitempty"`
+ LastSyncTime *metav1.Time `json:"lastSyncTime,omitempty"`
}
// ProjectStatusApplyConfiguration constructs a declarative configuration of the ProjectStatus type for use with
@@ -64,3 +66,11 @@ func (b *ProjectStatusApplyConfiguration) WithResource(value *ProjectResourceSta
b.Resource = value
return b
}
+
+// WithLastSyncTime sets the LastSyncTime field in the declarative configuration to the given value
+// and returns the receiver, so that objects can be built by chaining "With" function invocations.
+// If called multiple times, the LastSyncTime field is set to the value of the last call.
+func (b *ProjectStatusApplyConfiguration) WithLastSyncTime(value metav1.Time) *ProjectStatusApplyConfiguration {
+ b.LastSyncTime = &value
+ return b
+}
diff --git a/pkg/clients/applyconfiguration/api/v1alpha1/rolespec.go b/pkg/clients/applyconfiguration/api/v1alpha1/rolespec.go
index 05205d08b..bc26455d9 100644
--- a/pkg/clients/applyconfiguration/api/v1alpha1/rolespec.go
+++ b/pkg/clients/applyconfiguration/api/v1alpha1/rolespec.go
@@ -20,6 +20,7 @@ package v1alpha1
import (
apiv1alpha1 "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
// RoleSpecApplyConfiguration represents a declarative configuration of the RoleSpec type for use
@@ -29,6 +30,7 @@ type RoleSpecApplyConfiguration struct {
Resource *RoleResourceSpecApplyConfiguration `json:"resource,omitempty"`
ManagementPolicy *apiv1alpha1.ManagementPolicy `json:"managementPolicy,omitempty"`
ManagedOptions *ManagedOptionsApplyConfiguration `json:"managedOptions,omitempty"`
+ ResyncPeriod *v1.Duration `json:"resyncPeriod,omitempty"`
CloudCredentialsRef *CloudCredentialsReferenceApplyConfiguration `json:"cloudCredentialsRef,omitempty"`
}
@@ -70,6 +72,14 @@ func (b *RoleSpecApplyConfiguration) WithManagedOptions(value *ManagedOptionsApp
return b
}
+// WithResyncPeriod sets the ResyncPeriod field in the declarative configuration to the given value
+// and returns the receiver, so that objects can be built by chaining "With" function invocations.
+// If called multiple times, the ResyncPeriod field is set to the value of the last call.
+func (b *RoleSpecApplyConfiguration) WithResyncPeriod(value v1.Duration) *RoleSpecApplyConfiguration {
+ b.ResyncPeriod = &value
+ return b
+}
+
// WithCloudCredentialsRef sets the CloudCredentialsRef field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the CloudCredentialsRef field is set to the value of the last call.
diff --git a/pkg/clients/applyconfiguration/api/v1alpha1/rolestatus.go b/pkg/clients/applyconfiguration/api/v1alpha1/rolestatus.go
index 8731d9e8b..8a2d976a6 100644
--- a/pkg/clients/applyconfiguration/api/v1alpha1/rolestatus.go
+++ b/pkg/clients/applyconfiguration/api/v1alpha1/rolestatus.go
@@ -19,15 +19,17 @@ limitations under the License.
package v1alpha1
import (
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
v1 "k8s.io/client-go/applyconfigurations/meta/v1"
)
// RoleStatusApplyConfiguration represents a declarative configuration of the RoleStatus type for use
// with apply.
type RoleStatusApplyConfiguration struct {
- Conditions []v1.ConditionApplyConfiguration `json:"conditions,omitempty"`
- ID *string `json:"id,omitempty"`
- Resource *RoleResourceStatusApplyConfiguration `json:"resource,omitempty"`
+ Conditions []v1.ConditionApplyConfiguration `json:"conditions,omitempty"`
+ ID *string `json:"id,omitempty"`
+ Resource *RoleResourceStatusApplyConfiguration `json:"resource,omitempty"`
+ LastSyncTime *metav1.Time `json:"lastSyncTime,omitempty"`
}
// RoleStatusApplyConfiguration constructs a declarative configuration of the RoleStatus type for use with
@@ -64,3 +66,11 @@ func (b *RoleStatusApplyConfiguration) WithResource(value *RoleResourceStatusApp
b.Resource = value
return b
}
+
+// WithLastSyncTime sets the LastSyncTime field in the declarative configuration to the given value
+// and returns the receiver, so that objects can be built by chaining "With" function invocations.
+// If called multiple times, the LastSyncTime field is set to the value of the last call.
+func (b *RoleStatusApplyConfiguration) WithLastSyncTime(value metav1.Time) *RoleStatusApplyConfiguration {
+ b.LastSyncTime = &value
+ return b
+}
diff --git a/pkg/clients/applyconfiguration/api/v1alpha1/routerspec.go b/pkg/clients/applyconfiguration/api/v1alpha1/routerspec.go
index fb3da1400..c1dde96b9 100644
--- a/pkg/clients/applyconfiguration/api/v1alpha1/routerspec.go
+++ b/pkg/clients/applyconfiguration/api/v1alpha1/routerspec.go
@@ -20,6 +20,7 @@ package v1alpha1
import (
apiv1alpha1 "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
// RouterSpecApplyConfiguration represents a declarative configuration of the RouterSpec type for use
@@ -29,6 +30,7 @@ type RouterSpecApplyConfiguration struct {
Resource *RouterResourceSpecApplyConfiguration `json:"resource,omitempty"`
ManagementPolicy *apiv1alpha1.ManagementPolicy `json:"managementPolicy,omitempty"`
ManagedOptions *ManagedOptionsApplyConfiguration `json:"managedOptions,omitempty"`
+ ResyncPeriod *v1.Duration `json:"resyncPeriod,omitempty"`
CloudCredentialsRef *CloudCredentialsReferenceApplyConfiguration `json:"cloudCredentialsRef,omitempty"`
}
@@ -70,6 +72,14 @@ func (b *RouterSpecApplyConfiguration) WithManagedOptions(value *ManagedOptionsA
return b
}
+// WithResyncPeriod sets the ResyncPeriod field in the declarative configuration to the given value
+// and returns the receiver, so that objects can be built by chaining "With" function invocations.
+// If called multiple times, the ResyncPeriod field is set to the value of the last call.
+func (b *RouterSpecApplyConfiguration) WithResyncPeriod(value v1.Duration) *RouterSpecApplyConfiguration {
+ b.ResyncPeriod = &value
+ return b
+}
+
// WithCloudCredentialsRef sets the CloudCredentialsRef field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the CloudCredentialsRef field is set to the value of the last call.
diff --git a/pkg/clients/applyconfiguration/api/v1alpha1/routerstatus.go b/pkg/clients/applyconfiguration/api/v1alpha1/routerstatus.go
index 2b42ab43e..4652956fd 100644
--- a/pkg/clients/applyconfiguration/api/v1alpha1/routerstatus.go
+++ b/pkg/clients/applyconfiguration/api/v1alpha1/routerstatus.go
@@ -19,15 +19,17 @@ limitations under the License.
package v1alpha1
import (
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
v1 "k8s.io/client-go/applyconfigurations/meta/v1"
)
// RouterStatusApplyConfiguration represents a declarative configuration of the RouterStatus type for use
// with apply.
type RouterStatusApplyConfiguration struct {
- Conditions []v1.ConditionApplyConfiguration `json:"conditions,omitempty"`
- ID *string `json:"id,omitempty"`
- Resource *RouterResourceStatusApplyConfiguration `json:"resource,omitempty"`
+ Conditions []v1.ConditionApplyConfiguration `json:"conditions,omitempty"`
+ ID *string `json:"id,omitempty"`
+ Resource *RouterResourceStatusApplyConfiguration `json:"resource,omitempty"`
+ LastSyncTime *metav1.Time `json:"lastSyncTime,omitempty"`
}
// RouterStatusApplyConfiguration constructs a declarative configuration of the RouterStatus type for use with
@@ -64,3 +66,11 @@ func (b *RouterStatusApplyConfiguration) WithResource(value *RouterResourceStatu
b.Resource = value
return b
}
+
+// WithLastSyncTime sets the LastSyncTime field in the declarative configuration to the given value
+// and returns the receiver, so that objects can be built by chaining "With" function invocations.
+// If called multiple times, the LastSyncTime field is set to the value of the last call.
+func (b *RouterStatusApplyConfiguration) WithLastSyncTime(value metav1.Time) *RouterStatusApplyConfiguration {
+ b.LastSyncTime = &value
+ return b
+}
diff --git a/pkg/clients/applyconfiguration/api/v1alpha1/securitygroupspec.go b/pkg/clients/applyconfiguration/api/v1alpha1/securitygroupspec.go
index aea02dbb7..51a5f5a1f 100644
--- a/pkg/clients/applyconfiguration/api/v1alpha1/securitygroupspec.go
+++ b/pkg/clients/applyconfiguration/api/v1alpha1/securitygroupspec.go
@@ -20,6 +20,7 @@ package v1alpha1
import (
apiv1alpha1 "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
// SecurityGroupSpecApplyConfiguration represents a declarative configuration of the SecurityGroupSpec type for use
@@ -29,6 +30,7 @@ type SecurityGroupSpecApplyConfiguration struct {
Resource *SecurityGroupResourceSpecApplyConfiguration `json:"resource,omitempty"`
ManagementPolicy *apiv1alpha1.ManagementPolicy `json:"managementPolicy,omitempty"`
ManagedOptions *ManagedOptionsApplyConfiguration `json:"managedOptions,omitempty"`
+ ResyncPeriod *v1.Duration `json:"resyncPeriod,omitempty"`
CloudCredentialsRef *CloudCredentialsReferenceApplyConfiguration `json:"cloudCredentialsRef,omitempty"`
}
@@ -70,6 +72,14 @@ func (b *SecurityGroupSpecApplyConfiguration) WithManagedOptions(value *ManagedO
return b
}
+// WithResyncPeriod sets the ResyncPeriod field in the declarative configuration to the given value
+// and returns the receiver, so that objects can be built by chaining "With" function invocations.
+// If called multiple times, the ResyncPeriod field is set to the value of the last call.
+func (b *SecurityGroupSpecApplyConfiguration) WithResyncPeriod(value v1.Duration) *SecurityGroupSpecApplyConfiguration {
+ b.ResyncPeriod = &value
+ return b
+}
+
// WithCloudCredentialsRef sets the CloudCredentialsRef field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the CloudCredentialsRef field is set to the value of the last call.
diff --git a/pkg/clients/applyconfiguration/api/v1alpha1/securitygroupstatus.go b/pkg/clients/applyconfiguration/api/v1alpha1/securitygroupstatus.go
index 8ff720652..9237c1699 100644
--- a/pkg/clients/applyconfiguration/api/v1alpha1/securitygroupstatus.go
+++ b/pkg/clients/applyconfiguration/api/v1alpha1/securitygroupstatus.go
@@ -19,15 +19,17 @@ limitations under the License.
package v1alpha1
import (
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
v1 "k8s.io/client-go/applyconfigurations/meta/v1"
)
// SecurityGroupStatusApplyConfiguration represents a declarative configuration of the SecurityGroupStatus type for use
// with apply.
type SecurityGroupStatusApplyConfiguration struct {
- Conditions []v1.ConditionApplyConfiguration `json:"conditions,omitempty"`
- ID *string `json:"id,omitempty"`
- Resource *SecurityGroupResourceStatusApplyConfiguration `json:"resource,omitempty"`
+ Conditions []v1.ConditionApplyConfiguration `json:"conditions,omitempty"`
+ ID *string `json:"id,omitempty"`
+ Resource *SecurityGroupResourceStatusApplyConfiguration `json:"resource,omitempty"`
+ LastSyncTime *metav1.Time `json:"lastSyncTime,omitempty"`
}
// SecurityGroupStatusApplyConfiguration constructs a declarative configuration of the SecurityGroupStatus type for use with
@@ -64,3 +66,11 @@ func (b *SecurityGroupStatusApplyConfiguration) WithResource(value *SecurityGrou
b.Resource = value
return b
}
+
+// WithLastSyncTime sets the LastSyncTime field in the declarative configuration to the given value
+// and returns the receiver, so that objects can be built by chaining "With" function invocations.
+// If called multiple times, the LastSyncTime field is set to the value of the last call.
+func (b *SecurityGroupStatusApplyConfiguration) WithLastSyncTime(value metav1.Time) *SecurityGroupStatusApplyConfiguration {
+ b.LastSyncTime = &value
+ return b
+}
diff --git a/pkg/clients/applyconfiguration/api/v1alpha1/servergroupspec.go b/pkg/clients/applyconfiguration/api/v1alpha1/servergroupspec.go
index 21efdd462..ed08d4bc3 100644
--- a/pkg/clients/applyconfiguration/api/v1alpha1/servergroupspec.go
+++ b/pkg/clients/applyconfiguration/api/v1alpha1/servergroupspec.go
@@ -20,6 +20,7 @@ package v1alpha1
import (
apiv1alpha1 "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
// ServerGroupSpecApplyConfiguration represents a declarative configuration of the ServerGroupSpec type for use
@@ -29,6 +30,7 @@ type ServerGroupSpecApplyConfiguration struct {
Resource *ServerGroupResourceSpecApplyConfiguration `json:"resource,omitempty"`
ManagementPolicy *apiv1alpha1.ManagementPolicy `json:"managementPolicy,omitempty"`
ManagedOptions *ManagedOptionsApplyConfiguration `json:"managedOptions,omitempty"`
+ ResyncPeriod *v1.Duration `json:"resyncPeriod,omitempty"`
CloudCredentialsRef *CloudCredentialsReferenceApplyConfiguration `json:"cloudCredentialsRef,omitempty"`
}
@@ -70,6 +72,14 @@ func (b *ServerGroupSpecApplyConfiguration) WithManagedOptions(value *ManagedOpt
return b
}
+// WithResyncPeriod sets the ResyncPeriod field in the declarative configuration to the given value
+// and returns the receiver, so that objects can be built by chaining "With" function invocations.
+// If called multiple times, the ResyncPeriod field is set to the value of the last call.
+func (b *ServerGroupSpecApplyConfiguration) WithResyncPeriod(value v1.Duration) *ServerGroupSpecApplyConfiguration {
+ b.ResyncPeriod = &value
+ return b
+}
+
// WithCloudCredentialsRef sets the CloudCredentialsRef field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the CloudCredentialsRef field is set to the value of the last call.
diff --git a/pkg/clients/applyconfiguration/api/v1alpha1/servergroupstatus.go b/pkg/clients/applyconfiguration/api/v1alpha1/servergroupstatus.go
index 8b7e8ce34..77ba8454b 100644
--- a/pkg/clients/applyconfiguration/api/v1alpha1/servergroupstatus.go
+++ b/pkg/clients/applyconfiguration/api/v1alpha1/servergroupstatus.go
@@ -19,15 +19,17 @@ limitations under the License.
package v1alpha1
import (
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
v1 "k8s.io/client-go/applyconfigurations/meta/v1"
)
// ServerGroupStatusApplyConfiguration represents a declarative configuration of the ServerGroupStatus type for use
// with apply.
type ServerGroupStatusApplyConfiguration struct {
- Conditions []v1.ConditionApplyConfiguration `json:"conditions,omitempty"`
- ID *string `json:"id,omitempty"`
- Resource *ServerGroupResourceStatusApplyConfiguration `json:"resource,omitempty"`
+ Conditions []v1.ConditionApplyConfiguration `json:"conditions,omitempty"`
+ ID *string `json:"id,omitempty"`
+ Resource *ServerGroupResourceStatusApplyConfiguration `json:"resource,omitempty"`
+ LastSyncTime *metav1.Time `json:"lastSyncTime,omitempty"`
}
// ServerGroupStatusApplyConfiguration constructs a declarative configuration of the ServerGroupStatus type for use with
@@ -64,3 +66,11 @@ func (b *ServerGroupStatusApplyConfiguration) WithResource(value *ServerGroupRes
b.Resource = value
return b
}
+
+// WithLastSyncTime sets the LastSyncTime field in the declarative configuration to the given value
+// and returns the receiver, so that objects can be built by chaining "With" function invocations.
+// If called multiple times, the LastSyncTime field is set to the value of the last call.
+func (b *ServerGroupStatusApplyConfiguration) WithLastSyncTime(value metav1.Time) *ServerGroupStatusApplyConfiguration {
+ b.LastSyncTime = &value
+ return b
+}
diff --git a/pkg/clients/applyconfiguration/api/v1alpha1/serverspec.go b/pkg/clients/applyconfiguration/api/v1alpha1/serverspec.go
index 2e284079c..95b7b111d 100644
--- a/pkg/clients/applyconfiguration/api/v1alpha1/serverspec.go
+++ b/pkg/clients/applyconfiguration/api/v1alpha1/serverspec.go
@@ -20,6 +20,7 @@ package v1alpha1
import (
apiv1alpha1 "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
// ServerSpecApplyConfiguration represents a declarative configuration of the ServerSpec type for use
@@ -29,6 +30,7 @@ type ServerSpecApplyConfiguration struct {
Resource *ServerResourceSpecApplyConfiguration `json:"resource,omitempty"`
ManagementPolicy *apiv1alpha1.ManagementPolicy `json:"managementPolicy,omitempty"`
ManagedOptions *ManagedOptionsApplyConfiguration `json:"managedOptions,omitempty"`
+ ResyncPeriod *v1.Duration `json:"resyncPeriod,omitempty"`
CloudCredentialsRef *CloudCredentialsReferenceApplyConfiguration `json:"cloudCredentialsRef,omitempty"`
}
@@ -70,6 +72,14 @@ func (b *ServerSpecApplyConfiguration) WithManagedOptions(value *ManagedOptionsA
return b
}
+// WithResyncPeriod sets the ResyncPeriod field in the declarative configuration to the given value
+// and returns the receiver, so that objects can be built by chaining "With" function invocations.
+// If called multiple times, the ResyncPeriod field is set to the value of the last call.
+func (b *ServerSpecApplyConfiguration) WithResyncPeriod(value v1.Duration) *ServerSpecApplyConfiguration {
+ b.ResyncPeriod = &value
+ return b
+}
+
// WithCloudCredentialsRef sets the CloudCredentialsRef field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the CloudCredentialsRef field is set to the value of the last call.
diff --git a/pkg/clients/applyconfiguration/api/v1alpha1/serverstatus.go b/pkg/clients/applyconfiguration/api/v1alpha1/serverstatus.go
index c433aafb2..43e471a4a 100644
--- a/pkg/clients/applyconfiguration/api/v1alpha1/serverstatus.go
+++ b/pkg/clients/applyconfiguration/api/v1alpha1/serverstatus.go
@@ -19,15 +19,17 @@ limitations under the License.
package v1alpha1
import (
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
v1 "k8s.io/client-go/applyconfigurations/meta/v1"
)
// ServerStatusApplyConfiguration represents a declarative configuration of the ServerStatus type for use
// with apply.
type ServerStatusApplyConfiguration struct {
- Conditions []v1.ConditionApplyConfiguration `json:"conditions,omitempty"`
- ID *string `json:"id,omitempty"`
- Resource *ServerResourceStatusApplyConfiguration `json:"resource,omitempty"`
+ Conditions []v1.ConditionApplyConfiguration `json:"conditions,omitempty"`
+ ID *string `json:"id,omitempty"`
+ Resource *ServerResourceStatusApplyConfiguration `json:"resource,omitempty"`
+ LastSyncTime *metav1.Time `json:"lastSyncTime,omitempty"`
}
// ServerStatusApplyConfiguration constructs a declarative configuration of the ServerStatus type for use with
@@ -64,3 +66,11 @@ func (b *ServerStatusApplyConfiguration) WithResource(value *ServerResourceStatu
b.Resource = value
return b
}
+
+// WithLastSyncTime sets the LastSyncTime field in the declarative configuration to the given value
+// and returns the receiver, so that objects can be built by chaining "With" function invocations.
+// If called multiple times, the LastSyncTime field is set to the value of the last call.
+func (b *ServerStatusApplyConfiguration) WithLastSyncTime(value metav1.Time) *ServerStatusApplyConfiguration {
+ b.LastSyncTime = &value
+ return b
+}
diff --git a/pkg/clients/applyconfiguration/api/v1alpha1/servicespec.go b/pkg/clients/applyconfiguration/api/v1alpha1/servicespec.go
index 1cc5b6645..ff6fe4241 100644
--- a/pkg/clients/applyconfiguration/api/v1alpha1/servicespec.go
+++ b/pkg/clients/applyconfiguration/api/v1alpha1/servicespec.go
@@ -20,6 +20,7 @@ package v1alpha1
import (
apiv1alpha1 "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
// ServiceSpecApplyConfiguration represents a declarative configuration of the ServiceSpec type for use
@@ -29,6 +30,7 @@ type ServiceSpecApplyConfiguration struct {
Resource *ServiceResourceSpecApplyConfiguration `json:"resource,omitempty"`
ManagementPolicy *apiv1alpha1.ManagementPolicy `json:"managementPolicy,omitempty"`
ManagedOptions *ManagedOptionsApplyConfiguration `json:"managedOptions,omitempty"`
+ ResyncPeriod *v1.Duration `json:"resyncPeriod,omitempty"`
CloudCredentialsRef *CloudCredentialsReferenceApplyConfiguration `json:"cloudCredentialsRef,omitempty"`
}
@@ -70,6 +72,14 @@ func (b *ServiceSpecApplyConfiguration) WithManagedOptions(value *ManagedOptions
return b
}
+// WithResyncPeriod sets the ResyncPeriod field in the declarative configuration to the given value
+// and returns the receiver, so that objects can be built by chaining "With" function invocations.
+// If called multiple times, the ResyncPeriod field is set to the value of the last call.
+func (b *ServiceSpecApplyConfiguration) WithResyncPeriod(value v1.Duration) *ServiceSpecApplyConfiguration {
+ b.ResyncPeriod = &value
+ return b
+}
+
// WithCloudCredentialsRef sets the CloudCredentialsRef field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the CloudCredentialsRef field is set to the value of the last call.
diff --git a/pkg/clients/applyconfiguration/api/v1alpha1/servicestatus.go b/pkg/clients/applyconfiguration/api/v1alpha1/servicestatus.go
index 89fa866d4..b7bc37269 100644
--- a/pkg/clients/applyconfiguration/api/v1alpha1/servicestatus.go
+++ b/pkg/clients/applyconfiguration/api/v1alpha1/servicestatus.go
@@ -19,15 +19,17 @@ limitations under the License.
package v1alpha1
import (
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
v1 "k8s.io/client-go/applyconfigurations/meta/v1"
)
// ServiceStatusApplyConfiguration represents a declarative configuration of the ServiceStatus type for use
// with apply.
type ServiceStatusApplyConfiguration struct {
- Conditions []v1.ConditionApplyConfiguration `json:"conditions,omitempty"`
- ID *string `json:"id,omitempty"`
- Resource *ServiceResourceStatusApplyConfiguration `json:"resource,omitempty"`
+ Conditions []v1.ConditionApplyConfiguration `json:"conditions,omitempty"`
+ ID *string `json:"id,omitempty"`
+ Resource *ServiceResourceStatusApplyConfiguration `json:"resource,omitempty"`
+ LastSyncTime *metav1.Time `json:"lastSyncTime,omitempty"`
}
// ServiceStatusApplyConfiguration constructs a declarative configuration of the ServiceStatus type for use with
@@ -64,3 +66,11 @@ func (b *ServiceStatusApplyConfiguration) WithResource(value *ServiceResourceSta
b.Resource = value
return b
}
+
+// WithLastSyncTime sets the LastSyncTime field in the declarative configuration to the given value
+// and returns the receiver, so that objects can be built by chaining "With" function invocations.
+// If called multiple times, the LastSyncTime field is set to the value of the last call.
+func (b *ServiceStatusApplyConfiguration) WithLastSyncTime(value metav1.Time) *ServiceStatusApplyConfiguration {
+ b.LastSyncTime = &value
+ return b
+}
diff --git a/pkg/clients/applyconfiguration/api/v1alpha1/subnetspec.go b/pkg/clients/applyconfiguration/api/v1alpha1/subnetspec.go
index 4c092dd01..c32747ef5 100644
--- a/pkg/clients/applyconfiguration/api/v1alpha1/subnetspec.go
+++ b/pkg/clients/applyconfiguration/api/v1alpha1/subnetspec.go
@@ -20,6 +20,7 @@ package v1alpha1
import (
apiv1alpha1 "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
// SubnetSpecApplyConfiguration represents a declarative configuration of the SubnetSpec type for use
@@ -29,6 +30,7 @@ type SubnetSpecApplyConfiguration struct {
Resource *SubnetResourceSpecApplyConfiguration `json:"resource,omitempty"`
ManagementPolicy *apiv1alpha1.ManagementPolicy `json:"managementPolicy,omitempty"`
ManagedOptions *ManagedOptionsApplyConfiguration `json:"managedOptions,omitempty"`
+ ResyncPeriod *v1.Duration `json:"resyncPeriod,omitempty"`
CloudCredentialsRef *CloudCredentialsReferenceApplyConfiguration `json:"cloudCredentialsRef,omitempty"`
}
@@ -70,6 +72,14 @@ func (b *SubnetSpecApplyConfiguration) WithManagedOptions(value *ManagedOptionsA
return b
}
+// WithResyncPeriod sets the ResyncPeriod field in the declarative configuration to the given value
+// and returns the receiver, so that objects can be built by chaining "With" function invocations.
+// If called multiple times, the ResyncPeriod field is set to the value of the last call.
+func (b *SubnetSpecApplyConfiguration) WithResyncPeriod(value v1.Duration) *SubnetSpecApplyConfiguration {
+ b.ResyncPeriod = &value
+ return b
+}
+
// WithCloudCredentialsRef sets the CloudCredentialsRef field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the CloudCredentialsRef field is set to the value of the last call.
diff --git a/pkg/clients/applyconfiguration/api/v1alpha1/subnetstatus.go b/pkg/clients/applyconfiguration/api/v1alpha1/subnetstatus.go
index e538e3724..fde0cef71 100644
--- a/pkg/clients/applyconfiguration/api/v1alpha1/subnetstatus.go
+++ b/pkg/clients/applyconfiguration/api/v1alpha1/subnetstatus.go
@@ -19,15 +19,17 @@ limitations under the License.
package v1alpha1
import (
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
v1 "k8s.io/client-go/applyconfigurations/meta/v1"
)
// SubnetStatusApplyConfiguration represents a declarative configuration of the SubnetStatus type for use
// with apply.
type SubnetStatusApplyConfiguration struct {
- Conditions []v1.ConditionApplyConfiguration `json:"conditions,omitempty"`
- ID *string `json:"id,omitempty"`
- Resource *SubnetResourceStatusApplyConfiguration `json:"resource,omitempty"`
+ Conditions []v1.ConditionApplyConfiguration `json:"conditions,omitempty"`
+ ID *string `json:"id,omitempty"`
+ Resource *SubnetResourceStatusApplyConfiguration `json:"resource,omitempty"`
+ LastSyncTime *metav1.Time `json:"lastSyncTime,omitempty"`
}
// SubnetStatusApplyConfiguration constructs a declarative configuration of the SubnetStatus type for use with
@@ -64,3 +66,11 @@ func (b *SubnetStatusApplyConfiguration) WithResource(value *SubnetResourceStatu
b.Resource = value
return b
}
+
+// WithLastSyncTime sets the LastSyncTime field in the declarative configuration to the given value
+// and returns the receiver, so that objects can be built by chaining "With" function invocations.
+// If called multiple times, the LastSyncTime field is set to the value of the last call.
+func (b *SubnetStatusApplyConfiguration) WithLastSyncTime(value metav1.Time) *SubnetStatusApplyConfiguration {
+ b.LastSyncTime = &value
+ return b
+}
diff --git a/pkg/clients/applyconfiguration/api/v1alpha1/trunkspec.go b/pkg/clients/applyconfiguration/api/v1alpha1/trunkspec.go
index c744fe03f..12f298757 100644
--- a/pkg/clients/applyconfiguration/api/v1alpha1/trunkspec.go
+++ b/pkg/clients/applyconfiguration/api/v1alpha1/trunkspec.go
@@ -20,6 +20,7 @@ package v1alpha1
import (
apiv1alpha1 "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
// TrunkSpecApplyConfiguration represents a declarative configuration of the TrunkSpec type for use
@@ -29,6 +30,7 @@ type TrunkSpecApplyConfiguration struct {
Resource *TrunkResourceSpecApplyConfiguration `json:"resource,omitempty"`
ManagementPolicy *apiv1alpha1.ManagementPolicy `json:"managementPolicy,omitempty"`
ManagedOptions *ManagedOptionsApplyConfiguration `json:"managedOptions,omitempty"`
+ ResyncPeriod *v1.Duration `json:"resyncPeriod,omitempty"`
CloudCredentialsRef *CloudCredentialsReferenceApplyConfiguration `json:"cloudCredentialsRef,omitempty"`
}
@@ -70,6 +72,14 @@ func (b *TrunkSpecApplyConfiguration) WithManagedOptions(value *ManagedOptionsAp
return b
}
+// WithResyncPeriod sets the ResyncPeriod field in the declarative configuration to the given value
+// and returns the receiver, so that objects can be built by chaining "With" function invocations.
+// If called multiple times, the ResyncPeriod field is set to the value of the last call.
+func (b *TrunkSpecApplyConfiguration) WithResyncPeriod(value v1.Duration) *TrunkSpecApplyConfiguration {
+ b.ResyncPeriod = &value
+ return b
+}
+
// WithCloudCredentialsRef sets the CloudCredentialsRef field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the CloudCredentialsRef field is set to the value of the last call.
diff --git a/pkg/clients/applyconfiguration/api/v1alpha1/trunkstatus.go b/pkg/clients/applyconfiguration/api/v1alpha1/trunkstatus.go
index ffd42aeb8..5e7b3d922 100644
--- a/pkg/clients/applyconfiguration/api/v1alpha1/trunkstatus.go
+++ b/pkg/clients/applyconfiguration/api/v1alpha1/trunkstatus.go
@@ -19,15 +19,17 @@ limitations under the License.
package v1alpha1
import (
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
v1 "k8s.io/client-go/applyconfigurations/meta/v1"
)
// TrunkStatusApplyConfiguration represents a declarative configuration of the TrunkStatus type for use
// with apply.
type TrunkStatusApplyConfiguration struct {
- Conditions []v1.ConditionApplyConfiguration `json:"conditions,omitempty"`
- ID *string `json:"id,omitempty"`
- Resource *TrunkResourceStatusApplyConfiguration `json:"resource,omitempty"`
+ Conditions []v1.ConditionApplyConfiguration `json:"conditions,omitempty"`
+ ID *string `json:"id,omitempty"`
+ Resource *TrunkResourceStatusApplyConfiguration `json:"resource,omitempty"`
+ LastSyncTime *metav1.Time `json:"lastSyncTime,omitempty"`
}
// TrunkStatusApplyConfiguration constructs a declarative configuration of the TrunkStatus type for use with
@@ -64,3 +66,11 @@ func (b *TrunkStatusApplyConfiguration) WithResource(value *TrunkResourceStatusA
b.Resource = value
return b
}
+
+// WithLastSyncTime sets the LastSyncTime field in the declarative configuration to the given value
+// and returns the receiver, so that objects can be built by chaining "With" function invocations.
+// If called multiple times, the LastSyncTime field is set to the value of the last call.
+func (b *TrunkStatusApplyConfiguration) WithLastSyncTime(value metav1.Time) *TrunkStatusApplyConfiguration {
+ b.LastSyncTime = &value
+ return b
+}
diff --git a/pkg/clients/applyconfiguration/api/v1alpha1/userspec.go b/pkg/clients/applyconfiguration/api/v1alpha1/userspec.go
index fadcb620b..8ce4fb751 100644
--- a/pkg/clients/applyconfiguration/api/v1alpha1/userspec.go
+++ b/pkg/clients/applyconfiguration/api/v1alpha1/userspec.go
@@ -20,6 +20,7 @@ package v1alpha1
import (
apiv1alpha1 "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
// UserSpecApplyConfiguration represents a declarative configuration of the UserSpec type for use
@@ -29,6 +30,7 @@ type UserSpecApplyConfiguration struct {
Resource *UserResourceSpecApplyConfiguration `json:"resource,omitempty"`
ManagementPolicy *apiv1alpha1.ManagementPolicy `json:"managementPolicy,omitempty"`
ManagedOptions *ManagedOptionsApplyConfiguration `json:"managedOptions,omitempty"`
+ ResyncPeriod *v1.Duration `json:"resyncPeriod,omitempty"`
CloudCredentialsRef *CloudCredentialsReferenceApplyConfiguration `json:"cloudCredentialsRef,omitempty"`
}
@@ -70,6 +72,14 @@ func (b *UserSpecApplyConfiguration) WithManagedOptions(value *ManagedOptionsApp
return b
}
+// WithResyncPeriod sets the ResyncPeriod field in the declarative configuration to the given value
+// and returns the receiver, so that objects can be built by chaining "With" function invocations.
+// If called multiple times, the ResyncPeriod field is set to the value of the last call.
+func (b *UserSpecApplyConfiguration) WithResyncPeriod(value v1.Duration) *UserSpecApplyConfiguration {
+ b.ResyncPeriod = &value
+ return b
+}
+
// WithCloudCredentialsRef sets the CloudCredentialsRef field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the CloudCredentialsRef field is set to the value of the last call.
diff --git a/pkg/clients/applyconfiguration/api/v1alpha1/userstatus.go b/pkg/clients/applyconfiguration/api/v1alpha1/userstatus.go
index 1aae09224..d2e1194bf 100644
--- a/pkg/clients/applyconfiguration/api/v1alpha1/userstatus.go
+++ b/pkg/clients/applyconfiguration/api/v1alpha1/userstatus.go
@@ -19,15 +19,17 @@ limitations under the License.
package v1alpha1
import (
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
v1 "k8s.io/client-go/applyconfigurations/meta/v1"
)
// UserStatusApplyConfiguration represents a declarative configuration of the UserStatus type for use
// with apply.
type UserStatusApplyConfiguration struct {
- Conditions []v1.ConditionApplyConfiguration `json:"conditions,omitempty"`
- ID *string `json:"id,omitempty"`
- Resource *UserResourceStatusApplyConfiguration `json:"resource,omitempty"`
+ Conditions []v1.ConditionApplyConfiguration `json:"conditions,omitempty"`
+ ID *string `json:"id,omitempty"`
+ Resource *UserResourceStatusApplyConfiguration `json:"resource,omitempty"`
+ LastSyncTime *metav1.Time `json:"lastSyncTime,omitempty"`
}
// UserStatusApplyConfiguration constructs a declarative configuration of the UserStatus type for use with
@@ -64,3 +66,11 @@ func (b *UserStatusApplyConfiguration) WithResource(value *UserResourceStatusApp
b.Resource = value
return b
}
+
+// WithLastSyncTime sets the LastSyncTime field in the declarative configuration to the given value
+// and returns the receiver, so that objects can be built by chaining "With" function invocations.
+// If called multiple times, the LastSyncTime field is set to the value of the last call.
+func (b *UserStatusApplyConfiguration) WithLastSyncTime(value metav1.Time) *UserStatusApplyConfiguration {
+ b.LastSyncTime = &value
+ return b
+}
diff --git a/pkg/clients/applyconfiguration/api/v1alpha1/volumespec.go b/pkg/clients/applyconfiguration/api/v1alpha1/volumespec.go
index e0ffdcbca..208243749 100644
--- a/pkg/clients/applyconfiguration/api/v1alpha1/volumespec.go
+++ b/pkg/clients/applyconfiguration/api/v1alpha1/volumespec.go
@@ -20,6 +20,7 @@ package v1alpha1
import (
apiv1alpha1 "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
// VolumeSpecApplyConfiguration represents a declarative configuration of the VolumeSpec type for use
@@ -29,6 +30,7 @@ type VolumeSpecApplyConfiguration struct {
Resource *VolumeResourceSpecApplyConfiguration `json:"resource,omitempty"`
ManagementPolicy *apiv1alpha1.ManagementPolicy `json:"managementPolicy,omitempty"`
ManagedOptions *ManagedOptionsApplyConfiguration `json:"managedOptions,omitempty"`
+ ResyncPeriod *v1.Duration `json:"resyncPeriod,omitempty"`
CloudCredentialsRef *CloudCredentialsReferenceApplyConfiguration `json:"cloudCredentialsRef,omitempty"`
}
@@ -70,6 +72,14 @@ func (b *VolumeSpecApplyConfiguration) WithManagedOptions(value *ManagedOptionsA
return b
}
+// WithResyncPeriod sets the ResyncPeriod field in the declarative configuration to the given value
+// and returns the receiver, so that objects can be built by chaining "With" function invocations.
+// If called multiple times, the ResyncPeriod field is set to the value of the last call.
+func (b *VolumeSpecApplyConfiguration) WithResyncPeriod(value v1.Duration) *VolumeSpecApplyConfiguration {
+ b.ResyncPeriod = &value
+ return b
+}
+
// WithCloudCredentialsRef sets the CloudCredentialsRef field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the CloudCredentialsRef field is set to the value of the last call.
diff --git a/pkg/clients/applyconfiguration/api/v1alpha1/volumestatus.go b/pkg/clients/applyconfiguration/api/v1alpha1/volumestatus.go
index 3e6be3743..fb12e4acf 100644
--- a/pkg/clients/applyconfiguration/api/v1alpha1/volumestatus.go
+++ b/pkg/clients/applyconfiguration/api/v1alpha1/volumestatus.go
@@ -19,15 +19,17 @@ limitations under the License.
package v1alpha1
import (
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
v1 "k8s.io/client-go/applyconfigurations/meta/v1"
)
// VolumeStatusApplyConfiguration represents a declarative configuration of the VolumeStatus type for use
// with apply.
type VolumeStatusApplyConfiguration struct {
- Conditions []v1.ConditionApplyConfiguration `json:"conditions,omitempty"`
- ID *string `json:"id,omitempty"`
- Resource *VolumeResourceStatusApplyConfiguration `json:"resource,omitempty"`
+ Conditions []v1.ConditionApplyConfiguration `json:"conditions,omitempty"`
+ ID *string `json:"id,omitempty"`
+ Resource *VolumeResourceStatusApplyConfiguration `json:"resource,omitempty"`
+ LastSyncTime *metav1.Time `json:"lastSyncTime,omitempty"`
}
// VolumeStatusApplyConfiguration constructs a declarative configuration of the VolumeStatus type for use with
@@ -64,3 +66,11 @@ func (b *VolumeStatusApplyConfiguration) WithResource(value *VolumeResourceStatu
b.Resource = value
return b
}
+
+// WithLastSyncTime sets the LastSyncTime field in the declarative configuration to the given value
+// and returns the receiver, so that objects can be built by chaining "With" function invocations.
+// If called multiple times, the LastSyncTime field is set to the value of the last call.
+func (b *VolumeStatusApplyConfiguration) WithLastSyncTime(value metav1.Time) *VolumeStatusApplyConfiguration {
+ b.LastSyncTime = &value
+ return b
+}
diff --git a/pkg/clients/applyconfiguration/api/v1alpha1/volumetypespec.go b/pkg/clients/applyconfiguration/api/v1alpha1/volumetypespec.go
index d4540dcfd..42f263428 100644
--- a/pkg/clients/applyconfiguration/api/v1alpha1/volumetypespec.go
+++ b/pkg/clients/applyconfiguration/api/v1alpha1/volumetypespec.go
@@ -20,6 +20,7 @@ package v1alpha1
import (
apiv1alpha1 "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
// VolumeTypeSpecApplyConfiguration represents a declarative configuration of the VolumeTypeSpec type for use
@@ -29,6 +30,7 @@ type VolumeTypeSpecApplyConfiguration struct {
Resource *VolumeTypeResourceSpecApplyConfiguration `json:"resource,omitempty"`
ManagementPolicy *apiv1alpha1.ManagementPolicy `json:"managementPolicy,omitempty"`
ManagedOptions *ManagedOptionsApplyConfiguration `json:"managedOptions,omitempty"`
+ ResyncPeriod *v1.Duration `json:"resyncPeriod,omitempty"`
CloudCredentialsRef *CloudCredentialsReferenceApplyConfiguration `json:"cloudCredentialsRef,omitempty"`
}
@@ -70,6 +72,14 @@ func (b *VolumeTypeSpecApplyConfiguration) WithManagedOptions(value *ManagedOpti
return b
}
+// WithResyncPeriod sets the ResyncPeriod field in the declarative configuration to the given value
+// and returns the receiver, so that objects can be built by chaining "With" function invocations.
+// If called multiple times, the ResyncPeriod field is set to the value of the last call.
+func (b *VolumeTypeSpecApplyConfiguration) WithResyncPeriod(value v1.Duration) *VolumeTypeSpecApplyConfiguration {
+ b.ResyncPeriod = &value
+ return b
+}
+
// WithCloudCredentialsRef sets the CloudCredentialsRef field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the CloudCredentialsRef field is set to the value of the last call.
diff --git a/pkg/clients/applyconfiguration/api/v1alpha1/volumetypestatus.go b/pkg/clients/applyconfiguration/api/v1alpha1/volumetypestatus.go
index 64a797263..b54ea49fc 100644
--- a/pkg/clients/applyconfiguration/api/v1alpha1/volumetypestatus.go
+++ b/pkg/clients/applyconfiguration/api/v1alpha1/volumetypestatus.go
@@ -19,15 +19,17 @@ limitations under the License.
package v1alpha1
import (
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
v1 "k8s.io/client-go/applyconfigurations/meta/v1"
)
// VolumeTypeStatusApplyConfiguration represents a declarative configuration of the VolumeTypeStatus type for use
// with apply.
type VolumeTypeStatusApplyConfiguration struct {
- Conditions []v1.ConditionApplyConfiguration `json:"conditions,omitempty"`
- ID *string `json:"id,omitempty"`
- Resource *VolumeTypeResourceStatusApplyConfiguration `json:"resource,omitempty"`
+ Conditions []v1.ConditionApplyConfiguration `json:"conditions,omitempty"`
+ ID *string `json:"id,omitempty"`
+ Resource *VolumeTypeResourceStatusApplyConfiguration `json:"resource,omitempty"`
+ LastSyncTime *metav1.Time `json:"lastSyncTime,omitempty"`
}
// VolumeTypeStatusApplyConfiguration constructs a declarative configuration of the VolumeTypeStatus type for use with
@@ -64,3 +66,11 @@ func (b *VolumeTypeStatusApplyConfiguration) WithResource(value *VolumeTypeResou
b.Resource = value
return b
}
+
+// WithLastSyncTime sets the LastSyncTime field in the declarative configuration to the given value
+// and returns the receiver, so that objects can be built by chaining "With" function invocations.
+// If called multiple times, the LastSyncTime field is set to the value of the last call.
+func (b *VolumeTypeStatusApplyConfiguration) WithLastSyncTime(value metav1.Time) *VolumeTypeStatusApplyConfiguration {
+ b.LastSyncTime = &value
+ return b
+}
diff --git a/pkg/clients/applyconfiguration/internal/internal.go b/pkg/clients/applyconfiguration/internal/internal.go
index 419e61894..7c4792104 100644
--- a/pkg/clients/applyconfiguration/internal/internal.go
+++ b/pkg/clients/applyconfiguration/internal/internal.go
@@ -143,6 +143,9 @@ var schemaYAML = typed.YAMLObject(`types:
- name: resource
type:
namedType: com.github.k-orc.openstack-resource-controller.v2.api.v1alpha1.AddressScopeResourceSpec
+ - name: resyncPeriod
+ type:
+ namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Duration
- name: com.github.k-orc.openstack-resource-controller.v2.api.v1alpha1.AddressScopeStatus
map:
fields:
@@ -157,6 +160,9 @@ var schemaYAML = typed.YAMLObject(`types:
- name: id
type:
scalar: string
+ - name: lastSyncTime
+ type:
+ namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time
- name: resource
type:
namedType: com.github.k-orc.openstack-resource-controller.v2.api.v1alpha1.AddressScopeResourceStatus
@@ -359,6 +365,9 @@ var schemaYAML = typed.YAMLObject(`types:
- name: resource
type:
namedType: com.github.k-orc.openstack-resource-controller.v2.api.v1alpha1.ApplicationCredentialResourceSpec
+ - name: resyncPeriod
+ type:
+ namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Duration
- name: com.github.k-orc.openstack-resource-controller.v2.api.v1alpha1.ApplicationCredentialStatus
map:
fields:
@@ -373,6 +382,9 @@ var schemaYAML = typed.YAMLObject(`types:
- name: id
type:
scalar: string
+ - name: lastSyncTime
+ type:
+ namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time
- name: resource
type:
namedType: com.github.k-orc.openstack-resource-controller.v2.api.v1alpha1.ApplicationCredentialResourceStatus
@@ -467,6 +479,9 @@ var schemaYAML = typed.YAMLObject(`types:
- name: resource
type:
namedType: com.github.k-orc.openstack-resource-controller.v2.api.v1alpha1.DomainResourceSpec
+ - name: resyncPeriod
+ type:
+ namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Duration
- name: com.github.k-orc.openstack-resource-controller.v2.api.v1alpha1.DomainStatus
map:
fields:
@@ -481,6 +496,9 @@ var schemaYAML = typed.YAMLObject(`types:
- name: id
type:
scalar: string
+ - name: lastSyncTime
+ type:
+ namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time
- name: resource
type:
namedType: com.github.k-orc.openstack-resource-controller.v2.api.v1alpha1.DomainResourceStatus
@@ -582,6 +600,9 @@ var schemaYAML = typed.YAMLObject(`types:
- name: resource
type:
namedType: com.github.k-orc.openstack-resource-controller.v2.api.v1alpha1.EndpointResourceSpec
+ - name: resyncPeriod
+ type:
+ namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Duration
- name: com.github.k-orc.openstack-resource-controller.v2.api.v1alpha1.EndpointStatus
map:
fields:
@@ -596,6 +617,9 @@ var schemaYAML = typed.YAMLObject(`types:
- name: id
type:
scalar: string
+ - name: lastSyncTime
+ type:
+ namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time
- name: resource
type:
namedType: com.github.k-orc.openstack-resource-controller.v2.api.v1alpha1.EndpointResourceStatus
@@ -739,6 +763,9 @@ var schemaYAML = typed.YAMLObject(`types:
- name: resource
type:
namedType: com.github.k-orc.openstack-resource-controller.v2.api.v1alpha1.FlavorResourceSpec
+ - name: resyncPeriod
+ type:
+ namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Duration
- name: com.github.k-orc.openstack-resource-controller.v2.api.v1alpha1.FlavorStatus
map:
fields:
@@ -753,6 +780,9 @@ var schemaYAML = typed.YAMLObject(`types:
- name: id
type:
scalar: string
+ - name: lastSyncTime
+ type:
+ namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time
- name: resource
type:
namedType: com.github.k-orc.openstack-resource-controller.v2.api.v1alpha1.FlavorResourceStatus
@@ -925,6 +955,9 @@ var schemaYAML = typed.YAMLObject(`types:
- name: resource
type:
namedType: com.github.k-orc.openstack-resource-controller.v2.api.v1alpha1.FloatingIPResourceSpec
+ - name: resyncPeriod
+ type:
+ namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Duration
- name: com.github.k-orc.openstack-resource-controller.v2.api.v1alpha1.FloatingIPStatus
map:
fields:
@@ -939,6 +972,9 @@ var schemaYAML = typed.YAMLObject(`types:
- name: id
type:
scalar: string
+ - name: lastSyncTime
+ type:
+ namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time
- name: resource
type:
namedType: com.github.k-orc.openstack-resource-controller.v2.api.v1alpha1.FloatingIPResourceStatus
@@ -1024,6 +1060,9 @@ var schemaYAML = typed.YAMLObject(`types:
- name: resource
type:
namedType: com.github.k-orc.openstack-resource-controller.v2.api.v1alpha1.GroupResourceSpec
+ - name: resyncPeriod
+ type:
+ namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Duration
- name: com.github.k-orc.openstack-resource-controller.v2.api.v1alpha1.GroupStatus
map:
fields:
@@ -1038,6 +1077,9 @@ var schemaYAML = typed.YAMLObject(`types:
- name: id
type:
scalar: string
+ - name: lastSyncTime
+ type:
+ namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time
- name: resource
type:
namedType: com.github.k-orc.openstack-resource-controller.v2.api.v1alpha1.GroupResourceStatus
@@ -1295,6 +1337,9 @@ var schemaYAML = typed.YAMLObject(`types:
- name: resource
type:
namedType: com.github.k-orc.openstack-resource-controller.v2.api.v1alpha1.ImageResourceSpec
+ - name: resyncPeriod
+ type:
+ namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Duration
- name: com.github.k-orc.openstack-resource-controller.v2.api.v1alpha1.ImageStatus
map:
fields:
@@ -1312,6 +1357,9 @@ var schemaYAML = typed.YAMLObject(`types:
- name: id
type:
scalar: string
+ - name: lastSyncTime
+ type:
+ namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time
- name: resource
type:
namedType: com.github.k-orc.openstack-resource-controller.v2.api.v1alpha1.ImageResourceStatus
@@ -1397,6 +1445,9 @@ var schemaYAML = typed.YAMLObject(`types:
- name: resource
type:
namedType: com.github.k-orc.openstack-resource-controller.v2.api.v1alpha1.KeyPairResourceSpec
+ - name: resyncPeriod
+ type:
+ namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Duration
- name: com.github.k-orc.openstack-resource-controller.v2.api.v1alpha1.KeyPairStatus
map:
fields:
@@ -1411,6 +1462,9 @@ var schemaYAML = typed.YAMLObject(`types:
- name: id
type:
scalar: string
+ - name: lastSyncTime
+ type:
+ namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time
- name: resource
type:
namedType: com.github.k-orc.openstack-resource-controller.v2.api.v1alpha1.KeyPairResourceStatus
@@ -1613,6 +1667,9 @@ var schemaYAML = typed.YAMLObject(`types:
- name: resource
type:
namedType: com.github.k-orc.openstack-resource-controller.v2.api.v1alpha1.NetworkResourceSpec
+ - name: resyncPeriod
+ type:
+ namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Duration
- name: com.github.k-orc.openstack-resource-controller.v2.api.v1alpha1.NetworkStatus
map:
fields:
@@ -1627,6 +1684,9 @@ var schemaYAML = typed.YAMLObject(`types:
- name: id
type:
scalar: string
+ - name: lastSyncTime
+ type:
+ namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time
- name: resource
type:
namedType: com.github.k-orc.openstack-resource-controller.v2.api.v1alpha1.NetworkResourceStatus
@@ -1876,6 +1936,9 @@ var schemaYAML = typed.YAMLObject(`types:
- name: resource
type:
namedType: com.github.k-orc.openstack-resource-controller.v2.api.v1alpha1.PortResourceSpec
+ - name: resyncPeriod
+ type:
+ namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Duration
- name: com.github.k-orc.openstack-resource-controller.v2.api.v1alpha1.PortStatus
map:
fields:
@@ -1890,6 +1953,9 @@ var schemaYAML = typed.YAMLObject(`types:
- name: id
type:
scalar: string
+ - name: lastSyncTime
+ type:
+ namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time
- name: resource
type:
namedType: com.github.k-orc.openstack-resource-controller.v2.api.v1alpha1.PortResourceStatus
@@ -2017,6 +2083,9 @@ var schemaYAML = typed.YAMLObject(`types:
- name: resource
type:
namedType: com.github.k-orc.openstack-resource-controller.v2.api.v1alpha1.ProjectResourceSpec
+ - name: resyncPeriod
+ type:
+ namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Duration
- name: com.github.k-orc.openstack-resource-controller.v2.api.v1alpha1.ProjectStatus
map:
fields:
@@ -2031,6 +2100,9 @@ var schemaYAML = typed.YAMLObject(`types:
- name: id
type:
scalar: string
+ - name: lastSyncTime
+ type:
+ namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time
- name: resource
type:
namedType: com.github.k-orc.openstack-resource-controller.v2.api.v1alpha1.ProjectResourceStatus
@@ -2128,6 +2200,9 @@ var schemaYAML = typed.YAMLObject(`types:
- name: resource
type:
namedType: com.github.k-orc.openstack-resource-controller.v2.api.v1alpha1.RoleResourceSpec
+ - name: resyncPeriod
+ type:
+ namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Duration
- name: com.github.k-orc.openstack-resource-controller.v2.api.v1alpha1.RoleStatus
map:
fields:
@@ -2142,6 +2217,9 @@ var schemaYAML = typed.YAMLObject(`types:
- name: id
type:
scalar: string
+ - name: lastSyncTime
+ type:
+ namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time
- name: resource
type:
namedType: com.github.k-orc.openstack-resource-controller.v2.api.v1alpha1.RoleResourceStatus
@@ -2349,6 +2427,9 @@ var schemaYAML = typed.YAMLObject(`types:
- name: resource
type:
namedType: com.github.k-orc.openstack-resource-controller.v2.api.v1alpha1.RouterResourceSpec
+ - name: resyncPeriod
+ type:
+ namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Duration
- name: com.github.k-orc.openstack-resource-controller.v2.api.v1alpha1.RouterStatus
map:
fields:
@@ -2363,6 +2444,9 @@ var schemaYAML = typed.YAMLObject(`types:
- name: id
type:
scalar: string
+ - name: lastSyncTime
+ type:
+ namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time
- name: resource
type:
namedType: com.github.k-orc.openstack-resource-controller.v2.api.v1alpha1.RouterResourceStatus
@@ -2562,6 +2646,9 @@ var schemaYAML = typed.YAMLObject(`types:
- name: resource
type:
namedType: com.github.k-orc.openstack-resource-controller.v2.api.v1alpha1.SecurityGroupResourceSpec
+ - name: resyncPeriod
+ type:
+ namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Duration
- name: com.github.k-orc.openstack-resource-controller.v2.api.v1alpha1.SecurityGroupStatus
map:
fields:
@@ -2576,6 +2663,9 @@ var schemaYAML = typed.YAMLObject(`types:
- name: id
type:
scalar: string
+ - name: lastSyncTime
+ type:
+ namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time
- name: resource
type:
namedType: com.github.k-orc.openstack-resource-controller.v2.api.v1alpha1.SecurityGroupResourceStatus
@@ -2739,6 +2829,9 @@ var schemaYAML = typed.YAMLObject(`types:
- name: resource
type:
namedType: com.github.k-orc.openstack-resource-controller.v2.api.v1alpha1.ServerGroupResourceSpec
+ - name: resyncPeriod
+ type:
+ namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Duration
- name: com.github.k-orc.openstack-resource-controller.v2.api.v1alpha1.ServerGroupStatus
map:
fields:
@@ -2753,6 +2846,9 @@ var schemaYAML = typed.YAMLObject(`types:
- name: id
type:
scalar: string
+ - name: lastSyncTime
+ type:
+ namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time
- name: resource
type:
namedType: com.github.k-orc.openstack-resource-controller.v2.api.v1alpha1.ServerGroupResourceStatus
@@ -2943,6 +3039,9 @@ var schemaYAML = typed.YAMLObject(`types:
- name: resource
type:
namedType: com.github.k-orc.openstack-resource-controller.v2.api.v1alpha1.ServerResourceSpec
+ - name: resyncPeriod
+ type:
+ namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Duration
- name: com.github.k-orc.openstack-resource-controller.v2.api.v1alpha1.ServerStatus
map:
fields:
@@ -2957,6 +3056,9 @@ var schemaYAML = typed.YAMLObject(`types:
- name: id
type:
scalar: string
+ - name: lastSyncTime
+ type:
+ namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time
- name: resource
type:
namedType: com.github.k-orc.openstack-resource-controller.v2.api.v1alpha1.ServerResourceStatus
@@ -3063,6 +3165,9 @@ var schemaYAML = typed.YAMLObject(`types:
- name: resource
type:
namedType: com.github.k-orc.openstack-resource-controller.v2.api.v1alpha1.ServiceResourceSpec
+ - name: resyncPeriod
+ type:
+ namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Duration
- name: com.github.k-orc.openstack-resource-controller.v2.api.v1alpha1.ServiceStatus
map:
fields:
@@ -3077,6 +3182,9 @@ var schemaYAML = typed.YAMLObject(`types:
- name: id
type:
scalar: string
+ - name: lastSyncTime
+ type:
+ namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time
- name: resource
type:
namedType: com.github.k-orc.openstack-resource-controller.v2.api.v1alpha1.ServiceResourceStatus
@@ -3323,6 +3431,9 @@ var schemaYAML = typed.YAMLObject(`types:
- name: resource
type:
namedType: com.github.k-orc.openstack-resource-controller.v2.api.v1alpha1.SubnetResourceSpec
+ - name: resyncPeriod
+ type:
+ namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Duration
- name: com.github.k-orc.openstack-resource-controller.v2.api.v1alpha1.SubnetStatus
map:
fields:
@@ -3337,6 +3448,9 @@ var schemaYAML = typed.YAMLObject(`types:
- name: id
type:
scalar: string
+ - name: lastSyncTime
+ type:
+ namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time
- name: resource
type:
namedType: com.github.k-orc.openstack-resource-controller.v2.api.v1alpha1.SubnetResourceStatus
@@ -3506,6 +3620,9 @@ var schemaYAML = typed.YAMLObject(`types:
- name: resource
type:
namedType: com.github.k-orc.openstack-resource-controller.v2.api.v1alpha1.TrunkResourceSpec
+ - name: resyncPeriod
+ type:
+ namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Duration
- name: com.github.k-orc.openstack-resource-controller.v2.api.v1alpha1.TrunkStatus
map:
fields:
@@ -3520,6 +3637,9 @@ var schemaYAML = typed.YAMLObject(`types:
- name: id
type:
scalar: string
+ - name: lastSyncTime
+ type:
+ namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time
- name: resource
type:
namedType: com.github.k-orc.openstack-resource-controller.v2.api.v1alpha1.TrunkResourceStatus
@@ -3656,6 +3776,9 @@ var schemaYAML = typed.YAMLObject(`types:
- name: resource
type:
namedType: com.github.k-orc.openstack-resource-controller.v2.api.v1alpha1.UserResourceSpec
+ - name: resyncPeriod
+ type:
+ namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Duration
- name: com.github.k-orc.openstack-resource-controller.v2.api.v1alpha1.UserStatus
map:
fields:
@@ -3670,6 +3793,9 @@ var schemaYAML = typed.YAMLObject(`types:
- name: id
type:
scalar: string
+ - name: lastSyncTime
+ type:
+ namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time
- name: resource
type:
namedType: com.github.k-orc.openstack-resource-controller.v2.api.v1alpha1.UserResourceStatus
@@ -3877,6 +4003,9 @@ var schemaYAML = typed.YAMLObject(`types:
- name: resource
type:
namedType: com.github.k-orc.openstack-resource-controller.v2.api.v1alpha1.VolumeResourceSpec
+ - name: resyncPeriod
+ type:
+ namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Duration
- name: com.github.k-orc.openstack-resource-controller.v2.api.v1alpha1.VolumeStatus
map:
fields:
@@ -3891,6 +4020,9 @@ var schemaYAML = typed.YAMLObject(`types:
- name: id
type:
scalar: string
+ - name: lastSyncTime
+ type:
+ namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time
- name: resource
type:
namedType: com.github.k-orc.openstack-resource-controller.v2.api.v1alpha1.VolumeResourceStatus
@@ -4011,6 +4143,9 @@ var schemaYAML = typed.YAMLObject(`types:
- name: resource
type:
namedType: com.github.k-orc.openstack-resource-controller.v2.api.v1alpha1.VolumeTypeResourceSpec
+ - name: resyncPeriod
+ type:
+ namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Duration
- name: com.github.k-orc.openstack-resource-controller.v2.api.v1alpha1.VolumeTypeStatus
map:
fields:
@@ -4025,6 +4160,9 @@ var schemaYAML = typed.YAMLObject(`types:
- name: id
type:
scalar: string
+ - name: lastSyncTime
+ type:
+ namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time
- name: resource
type:
namedType: com.github.k-orc.openstack-resource-controller.v2.api.v1alpha1.VolumeTypeResourceStatus
@@ -4053,6 +4191,8 @@ var schemaYAML = typed.YAMLObject(`types:
type:
scalar: string
default: ""
+- name: io.k8s.apimachinery.pkg.apis.meta.v1.Duration
+ scalar: string
- name: io.k8s.apimachinery.pkg.apis.meta.v1.FieldsV1
map:
elementType:
diff --git a/website/docs/crd-reference.md b/website/docs/crd-reference.md
index 12e26692e..c3d823f86 100644
--- a/website/docs/crd-reference.md
+++ b/website/docs/crd-reference.md
@@ -168,6 +168,7 @@ _Appears in:_
| `resource` _[AddressScopeResourceSpec](#addressscoperesourcespec)_ | resource specifies the desired state of the resource.
resource may not be specified if the management policy is `unmanaged`.
resource must be specified if the management policy is `managed`. | | Optional: \{\}
|
| `managementPolicy` _[ManagementPolicy](#managementpolicy)_ | managementPolicy defines how ORC will treat the object. Valid values are
`managed`: ORC will create, update, and delete the resource; `unmanaged`:
ORC will import an existing resource, and will not apply updates to it or
delete it. | managed | Enum: [managed unmanaged]
Optional: \{\}
|
| `managedOptions` _[ManagedOptions](#managedoptions)_ | managedOptions specifies options which may be applied to managed objects. | | Optional: \{\}
|
+| `resyncPeriod` _[Duration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#duration-v1-meta)_ | resyncPeriod defines how frequently the controller will re-reconcile
this resource even when no changes have been detected. This overrides
the global default resync period. The value must be a valid Go duration
string, e.g. "10m", "1h". Set to "0s" to disable periodic resync for
this resource. | | Optional: \{\}
|
| `cloudCredentialsRef` _[CloudCredentialsReference](#cloudcredentialsreference)_ | cloudCredentialsRef points to a secret containing OpenStack credentials | | Required: \{\}
|
@@ -187,6 +188,7 @@ _Appears in:_
| `conditions` _[Condition](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#condition-v1-meta) array_ | conditions represents the observed status of the object.
Known .status.conditions.type are: "Available", "Progressing"
Available represents the availability of the OpenStack resource. If it is
true then the resource is ready for use.
Progressing indicates whether the controller is still attempting to
reconcile the current state of the OpenStack resource to the desired
state. Progressing will be False either because the desired state has
been achieved, or because some terminal error prevents it from ever being
achieved and the controller is no longer attempting to reconcile. If
Progressing is True, an observer waiting on the resource should continue
to wait. | | MaxItems: 32
Optional: \{\}
|
| `id` _string_ | id is the unique identifier of the OpenStack resource. | | MaxLength: 1024
Optional: \{\}
|
| `resource` _[AddressScopeResourceStatus](#addressscoperesourcestatus)_ | resource contains the observed state of the OpenStack resource. | | Optional: \{\}
|
+| `lastSyncTime` _[Time](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#time-v1-meta)_ | lastSyncTime is the timestamp of the last successful reconciliation
that fetched state from OpenStack. It is updated each time the
controller successfully reads the resource state from the OpenStack
API. | | Optional: \{\}
|
#### AllocationPool
@@ -433,6 +435,7 @@ _Appears in:_
| `resource` _[ApplicationCredentialResourceSpec](#applicationcredentialresourcespec)_ | resource specifies the desired state of the resource.
resource may not be specified if the management policy is `unmanaged`.
resource must be specified if the management policy is `managed`. | | Optional: \{\}
|
| `managementPolicy` _[ManagementPolicy](#managementpolicy)_ | managementPolicy defines how ORC will treat the object. Valid values are
`managed`: ORC will create, update, and delete the resource; `unmanaged`:
ORC will import an existing resource, and will not apply updates to it or
delete it. | managed | Enum: [managed unmanaged]
Optional: \{\}
|
| `managedOptions` _[ManagedOptions](#managedoptions)_ | managedOptions specifies options which may be applied to managed objects. | | Optional: \{\}
|
+| `resyncPeriod` _[Duration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#duration-v1-meta)_ | resyncPeriod defines how frequently the controller will re-reconcile
this resource even when no changes have been detected. This overrides
the global default resync period. The value must be a valid Go duration
string, e.g. "10m", "1h". Set to "0s" to disable periodic resync for
this resource. | | Optional: \{\}
|
| `cloudCredentialsRef` _[CloudCredentialsReference](#cloudcredentialsreference)_ | cloudCredentialsRef points to a secret containing OpenStack credentials | | Required: \{\}
|
@@ -452,6 +455,7 @@ _Appears in:_
| `conditions` _[Condition](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#condition-v1-meta) array_ | conditions represents the observed status of the object.
Known .status.conditions.type are: "Available", "Progressing"
Available represents the availability of the OpenStack resource. If it is
true then the resource is ready for use.
Progressing indicates whether the controller is still attempting to
reconcile the current state of the OpenStack resource to the desired
state. Progressing will be False either because the desired state has
been achieved, or because some terminal error prevents it from ever being
achieved and the controller is no longer attempting to reconcile. If
Progressing is True, an observer waiting on the resource should continue
to wait. | | MaxItems: 32
Optional: \{\}
|
| `id` _string_ | id is the unique identifier of the OpenStack resource. | | MaxLength: 1024
Optional: \{\}
|
| `resource` _[ApplicationCredentialResourceStatus](#applicationcredentialresourcestatus)_ | resource contains the observed state of the OpenStack resource. | | Optional: \{\}
|
+| `lastSyncTime` _[Time](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#time-v1-meta)_ | lastSyncTime is the timestamp of the last successful reconciliation
that fetched state from OpenStack. It is updated each time the
controller successfully reads the resource state from the OpenStack
API. | | Optional: \{\}
|
#### AvailabilityZoneHint
@@ -530,6 +534,10 @@ _Appears in:_
| `cloudName` _string_ | cloudName specifies the name of the entry in the clouds.yaml file to use. | | MaxLength: 256
MinLength: 1
Required: \{\}
|
+
+
+
+
#### DNSDomain
_Underlying type:_ _string_
@@ -656,6 +664,7 @@ _Appears in:_
| `resource` _[DomainResourceSpec](#domainresourcespec)_ | resource specifies the desired state of the resource.
resource may not be specified if the management policy is `unmanaged`.
resource must be specified if the management policy is `managed`. | | Optional: \{\}
|
| `managementPolicy` _[ManagementPolicy](#managementpolicy)_ | managementPolicy defines how ORC will treat the object. Valid values are
`managed`: ORC will create, update, and delete the resource; `unmanaged`:
ORC will import an existing resource, and will not apply updates to it or
delete it. | managed | Enum: [managed unmanaged]
Optional: \{\}
|
| `managedOptions` _[ManagedOptions](#managedoptions)_ | managedOptions specifies options which may be applied to managed objects. | | Optional: \{\}
|
+| `resyncPeriod` _[Duration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#duration-v1-meta)_ | resyncPeriod defines how frequently the controller will re-reconcile
this resource even when no changes have been detected. This overrides
the global default resync period. The value must be a valid Go duration
string, e.g. "10m", "1h". Set to "0s" to disable periodic resync for
this resource. | | Optional: \{\}
|
| `cloudCredentialsRef` _[CloudCredentialsReference](#cloudcredentialsreference)_ | cloudCredentialsRef points to a secret containing OpenStack credentials | | Required: \{\}
|
@@ -675,6 +684,7 @@ _Appears in:_
| `conditions` _[Condition](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#condition-v1-meta) array_ | conditions represents the observed status of the object.
Known .status.conditions.type are: "Available", "Progressing"
Available represents the availability of the OpenStack resource. If it is
true then the resource is ready for use.
Progressing indicates whether the controller is still attempting to
reconcile the current state of the OpenStack resource to the desired
state. Progressing will be False either because the desired state has
been achieved, or because some terminal error prevents it from ever being
achieved and the controller is no longer attempting to reconcile. If
Progressing is True, an observer waiting on the resource should continue
to wait. | | MaxItems: 32
Optional: \{\}
|
| `id` _string_ | id is the unique identifier of the OpenStack resource. | | MaxLength: 1024
Optional: \{\}
|
| `resource` _[DomainResourceStatus](#domainresourcestatus)_ | resource contains the observed state of the OpenStack resource. | | Optional: \{\}
|
+| `lastSyncTime` _[Time](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#time-v1-meta)_ | lastSyncTime is the timestamp of the last successful reconciliation
that fetched state from OpenStack. It is updated each time the
controller successfully reads the resource state from the OpenStack
API. | | Optional: \{\}
|
#### Endpoint
@@ -792,6 +802,7 @@ _Appears in:_
| `resource` _[EndpointResourceSpec](#endpointresourcespec)_ | resource specifies the desired state of the resource.
resource may not be specified if the management policy is `unmanaged`.
resource must be specified if the management policy is `managed`. | | Optional: \{\}
|
| `managementPolicy` _[ManagementPolicy](#managementpolicy)_ | managementPolicy defines how ORC will treat the object. Valid values are
`managed`: ORC will create, update, and delete the resource; `unmanaged`:
ORC will import an existing resource, and will not apply updates to it or
delete it. | managed | Enum: [managed unmanaged]
Optional: \{\}
|
| `managedOptions` _[ManagedOptions](#managedoptions)_ | managedOptions specifies options which may be applied to managed objects. | | Optional: \{\}
|
+| `resyncPeriod` _[Duration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#duration-v1-meta)_ | resyncPeriod defines how frequently the controller will re-reconcile
this resource even when no changes have been detected. This overrides
the global default resync period. The value must be a valid Go duration
string, e.g. "10m", "1h". Set to "0s" to disable periodic resync for
this resource. | | Optional: \{\}
|
| `cloudCredentialsRef` _[CloudCredentialsReference](#cloudcredentialsreference)_ | cloudCredentialsRef points to a secret containing OpenStack credentials | | Required: \{\}
|
@@ -811,6 +822,7 @@ _Appears in:_
| `conditions` _[Condition](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#condition-v1-meta) array_ | conditions represents the observed status of the object.
Known .status.conditions.type are: "Available", "Progressing"
Available represents the availability of the OpenStack resource. If it is
true then the resource is ready for use.
Progressing indicates whether the controller is still attempting to
reconcile the current state of the OpenStack resource to the desired
state. Progressing will be False either because the desired state has
been achieved, or because some terminal error prevents it from ever being
achieved and the controller is no longer attempting to reconcile. If
Progressing is True, an observer waiting on the resource should continue
to wait. | | MaxItems: 32
Optional: \{\}
|
| `id` _string_ | id is the unique identifier of the OpenStack resource. | | MaxLength: 1024
Optional: \{\}
|
| `resource` _[EndpointResourceStatus](#endpointresourcestatus)_ | resource contains the observed state of the OpenStack resource. | | Optional: \{\}
|
+| `lastSyncTime` _[Time](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#time-v1-meta)_ | lastSyncTime is the timestamp of the last successful reconciliation
that fetched state from OpenStack. It is updated each time the
controller successfully reads the resource state from the OpenStack
API. | | Optional: \{\}
|
#### Ethertype
@@ -1065,6 +1077,7 @@ _Appears in:_
| `resource` _[FlavorResourceSpec](#flavorresourcespec)_ | resource specifies the desired state of the resource.
resource may not be specified if the management policy is `unmanaged`.
resource must be specified if the management policy is `managed`. | | Optional: \{\}
|
| `managementPolicy` _[ManagementPolicy](#managementpolicy)_ | managementPolicy defines how ORC will treat the object. Valid values are
`managed`: ORC will create, update, and delete the resource; `unmanaged`:
ORC will import an existing resource, and will not apply updates to it or
delete it. | managed | Enum: [managed unmanaged]
Optional: \{\}
|
| `managedOptions` _[ManagedOptions](#managedoptions)_ | managedOptions specifies options which may be applied to managed objects. | | Optional: \{\}
|
+| `resyncPeriod` _[Duration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#duration-v1-meta)_ | resyncPeriod defines how frequently the controller will re-reconcile
this resource even when no changes have been detected. This overrides
the global default resync period. The value must be a valid Go duration
string, e.g. "10m", "1h". Set to "0s" to disable periodic resync for
this resource. | | Optional: \{\}
|
| `cloudCredentialsRef` _[CloudCredentialsReference](#cloudcredentialsreference)_ | cloudCredentialsRef points to a secret containing OpenStack credentials | | Required: \{\}
|
@@ -1084,6 +1097,7 @@ _Appears in:_
| `conditions` _[Condition](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#condition-v1-meta) array_ | conditions represents the observed status of the object.
Known .status.conditions.type are: "Available", "Progressing"
Available represents the availability of the OpenStack resource. If it is
true then the resource is ready for use.
Progressing indicates whether the controller is still attempting to
reconcile the current state of the OpenStack resource to the desired
state. Progressing will be False either because the desired state has
been achieved, or because some terminal error prevents it from ever being
achieved and the controller is no longer attempting to reconcile. If
Progressing is True, an observer waiting on the resource should continue
to wait. | | MaxItems: 32
Optional: \{\}
|
| `id` _string_ | id is the unique identifier of the OpenStack resource. | | MaxLength: 1024
Optional: \{\}
|
| `resource` _[FlavorResourceStatus](#flavorresourcestatus)_ | resource contains the observed state of the OpenStack resource. | | Optional: \{\}
|
+| `lastSyncTime` _[Time](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#time-v1-meta)_ | lastSyncTime is the timestamp of the last successful reconciliation
that fetched state from OpenStack. It is updated each time the
controller successfully reads the resource state from the OpenStack
API. | | Optional: \{\}
|
#### FloatingIP
@@ -1219,6 +1233,7 @@ _Appears in:_
| `resource` _[FloatingIPResourceSpec](#floatingipresourcespec)_ | resource specifies the desired state of the resource.
resource may not be specified if the management policy is `unmanaged`.
resource must be specified if the management policy is `managed`. | | Optional: \{\}
|
| `managementPolicy` _[ManagementPolicy](#managementpolicy)_ | managementPolicy defines how ORC will treat the object. Valid values are
`managed`: ORC will create, update, and delete the resource; `unmanaged`:
ORC will import an existing resource, and will not apply updates to it or
delete it. | managed | Enum: [managed unmanaged]
Optional: \{\}
|
| `managedOptions` _[ManagedOptions](#managedoptions)_ | managedOptions specifies options which may be applied to managed objects. | | Optional: \{\}
|
+| `resyncPeriod` _[Duration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#duration-v1-meta)_ | resyncPeriod defines how frequently the controller will re-reconcile
this resource even when no changes have been detected. This overrides
the global default resync period. The value must be a valid Go duration
string, e.g. "10m", "1h". Set to "0s" to disable periodic resync for
this resource. | | Optional: \{\}
|
| `cloudCredentialsRef` _[CloudCredentialsReference](#cloudcredentialsreference)_ | cloudCredentialsRef points to a secret containing OpenStack credentials | | Required: \{\}
|
@@ -1238,6 +1253,7 @@ _Appears in:_
| `conditions` _[Condition](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#condition-v1-meta) array_ | conditions represents the observed status of the object.
Known .status.conditions.type are: "Available", "Progressing"
Available represents the availability of the OpenStack resource. If it is
true then the resource is ready for use.
Progressing indicates whether the controller is still attempting to
reconcile the current state of the OpenStack resource to the desired
state. Progressing will be False either because the desired state has
been achieved, or because some terminal error prevents it from ever being
achieved and the controller is no longer attempting to reconcile. If
Progressing is True, an observer waiting on the resource should continue
to wait. | | MaxItems: 32
Optional: \{\}
|
| `id` _string_ | id is the unique identifier of the OpenStack resource. | | MaxLength: 1024
Optional: \{\}
|
| `resource` _[FloatingIPResourceStatus](#floatingipresourcestatus)_ | resource contains the observed state of the OpenStack resource. | | Optional: \{\}
|
+| `lastSyncTime` _[Time](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#time-v1-meta)_ | lastSyncTime is the timestamp of the last successful reconciliation
that fetched state from OpenStack. It is updated each time the
controller successfully reads the resource state from the OpenStack
API. | | Optional: \{\}
|
#### Group
@@ -1350,6 +1366,7 @@ _Appears in:_
| `resource` _[GroupResourceSpec](#groupresourcespec)_ | resource specifies the desired state of the resource.
resource may not be specified if the management policy is `unmanaged`.
resource must be specified if the management policy is `managed`. | | Optional: \{\}
|
| `managementPolicy` _[ManagementPolicy](#managementpolicy)_ | managementPolicy defines how ORC will treat the object. Valid values are
`managed`: ORC will create, update, and delete the resource; `unmanaged`:
ORC will import an existing resource, and will not apply updates to it or
delete it. | managed | Enum: [managed unmanaged]
Optional: \{\}
|
| `managedOptions` _[ManagedOptions](#managedoptions)_ | managedOptions specifies options which may be applied to managed objects. | | Optional: \{\}
|
+| `resyncPeriod` _[Duration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#duration-v1-meta)_ | resyncPeriod defines how frequently the controller will re-reconcile
this resource even when no changes have been detected. This overrides
the global default resync period. The value must be a valid Go duration
string, e.g. "10m", "1h". Set to "0s" to disable periodic resync for
this resource. | | Optional: \{\}
|
| `cloudCredentialsRef` _[CloudCredentialsReference](#cloudcredentialsreference)_ | cloudCredentialsRef points to a secret containing OpenStack credentials | | Required: \{\}
|
@@ -1369,6 +1386,7 @@ _Appears in:_
| `conditions` _[Condition](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#condition-v1-meta) array_ | conditions represents the observed status of the object.
Known .status.conditions.type are: "Available", "Progressing"
Available represents the availability of the OpenStack resource. If it is
true then the resource is ready for use.
Progressing indicates whether the controller is still attempting to
reconcile the current state of the OpenStack resource to the desired
state. Progressing will be False either because the desired state has
been achieved, or because some terminal error prevents it from ever being
achieved and the controller is no longer attempting to reconcile. If
Progressing is True, an observer waiting on the resource should continue
to wait. | | MaxItems: 32
Optional: \{\}
|
| `id` _string_ | id is the unique identifier of the OpenStack resource. | | MaxLength: 1024
Optional: \{\}
|
| `resource` _[GroupResourceStatus](#groupresourcestatus)_ | resource contains the observed state of the OpenStack resource. | | Optional: \{\}
|
+| `lastSyncTime` _[Time](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#time-v1-meta)_ | lastSyncTime is the timestamp of the last successful reconciliation
that fetched state from OpenStack. It is updated each time the
controller successfully reads the resource state from the OpenStack
API. | | Optional: \{\}
|
#### HTTPMethod
@@ -1880,6 +1898,7 @@ _Appears in:_
| `resource` _[ImageResourceSpec](#imageresourcespec)_ | resource specifies the desired state of the resource.
resource may not be specified if the management policy is `unmanaged`.
resource must be specified if the management policy is `managed`. | | Optional: \{\}
|
| `managementPolicy` _[ManagementPolicy](#managementpolicy)_ | managementPolicy defines how ORC will treat the object. Valid values are
`managed`: ORC will create, update, and delete the resource; `unmanaged`:
ORC will import an existing resource, and will not apply updates to it or
delete it. | managed | Enum: [managed unmanaged]
Optional: \{\}
|
| `managedOptions` _[ManagedOptions](#managedoptions)_ | managedOptions specifies options which may be applied to managed objects. | | Optional: \{\}
|
+| `resyncPeriod` _[Duration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#duration-v1-meta)_ | resyncPeriod defines how frequently the controller will re-reconcile
this resource even when no changes have been detected. This overrides
the global default resync period. The value must be a valid Go duration
string, e.g. "10m", "1h". Set to "0s" to disable periodic resync for
this resource. | | Optional: \{\}
|
| `cloudCredentialsRef` _[CloudCredentialsReference](#cloudcredentialsreference)_ | cloudCredentialsRef points to a secret containing OpenStack credentials | | Required: \{\}
|
@@ -1899,6 +1918,7 @@ _Appears in:_
| `conditions` _[Condition](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#condition-v1-meta) array_ | conditions represents the observed status of the object.
Known .status.conditions.type are: "Available", "Progressing"
Available represents the availability of the OpenStack resource. If it is
true then the resource is ready for use.
Progressing indicates whether the controller is still attempting to
reconcile the current state of the OpenStack resource to the desired
state. Progressing will be False either because the desired state has
been achieved, or because some terminal error prevents it from ever being
achieved and the controller is no longer attempting to reconcile. If
Progressing is True, an observer waiting on the resource should continue
to wait. | | MaxItems: 32
Optional: \{\}
|
| `id` _string_ | id is the unique identifier of the OpenStack resource. | | MaxLength: 1024
Optional: \{\}
|
| `resource` _[ImageResourceStatus](#imageresourcestatus)_ | resource contains the observed state of the OpenStack resource. | | Optional: \{\}
|
+| `lastSyncTime` _[Time](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#time-v1-meta)_ | lastSyncTime is the timestamp of the last successful reconciliation
that fetched state from OpenStack. It is updated each time the
controller successfully reads the resource state from the OpenStack
API. | | Optional: \{\}
|
| `downloadAttempts` _integer_ | downloadAttempts is the number of times the controller has attempted to download the image contents | | Optional: \{\}
|
@@ -2065,6 +2085,7 @@ _Appears in:_
| `resource` _[KeyPairResourceSpec](#keypairresourcespec)_ | resource specifies the desired state of the resource.
resource may not be specified if the management policy is `unmanaged`.
resource must be specified if the management policy is `managed`. | | Optional: \{\}
|
| `managementPolicy` _[ManagementPolicy](#managementpolicy)_ | managementPolicy defines how ORC will treat the object. Valid values are
`managed`: ORC will create, update, and delete the resource; `unmanaged`:
ORC will import an existing resource, and will not apply updates to it or
delete it. | managed | Enum: [managed unmanaged]
Optional: \{\}
|
| `managedOptions` _[ManagedOptions](#managedoptions)_ | managedOptions specifies options which may be applied to managed objects. | | Optional: \{\}
|
+| `resyncPeriod` _[Duration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#duration-v1-meta)_ | resyncPeriod defines how frequently the controller will re-reconcile
this resource even when no changes have been detected. This overrides
the global default resync period. The value must be a valid Go duration
string, e.g. "10m", "1h". Set to "0s" to disable periodic resync for
this resource. | | Optional: \{\}
|
| `cloudCredentialsRef` _[CloudCredentialsReference](#cloudcredentialsreference)_ | cloudCredentialsRef points to a secret containing OpenStack credentials | | Required: \{\}
|
@@ -2084,6 +2105,7 @@ _Appears in:_
| `conditions` _[Condition](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#condition-v1-meta) array_ | conditions represents the observed status of the object.
Known .status.conditions.type are: "Available", "Progressing"
Available represents the availability of the OpenStack resource. If it is
true then the resource is ready for use.
Progressing indicates whether the controller is still attempting to
reconcile the current state of the OpenStack resource to the desired
state. Progressing will be False either because the desired state has
been achieved, or because some terminal error prevents it from ever being
achieved and the controller is no longer attempting to reconcile. If
Progressing is True, an observer waiting on the resource should continue
to wait. | | MaxItems: 32
Optional: \{\}
|
| `id` _string_ | id is the unique identifier of the OpenStack resource. | | MaxLength: 1024
Optional: \{\}
|
| `resource` _[KeyPairResourceStatus](#keypairresourcestatus)_ | resource contains the observed state of the OpenStack resource. | | Optional: \{\}
|
+| `lastSyncTime` _[Time](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#time-v1-meta)_ | lastSyncTime is the timestamp of the last successful reconciliation
that fetched state from OpenStack. It is updated each time the
controller successfully reads the resource state from the OpenStack
API. | | Optional: \{\}
|
#### KeystoneName
@@ -2425,6 +2447,7 @@ _Appears in:_
| `resource` _[NetworkResourceSpec](#networkresourcespec)_ | resource specifies the desired state of the resource.
resource may not be specified if the management policy is `unmanaged`.
resource must be specified if the management policy is `managed`. | | Optional: \{\}
|
| `managementPolicy` _[ManagementPolicy](#managementpolicy)_ | managementPolicy defines how ORC will treat the object. Valid values are
`managed`: ORC will create, update, and delete the resource; `unmanaged`:
ORC will import an existing resource, and will not apply updates to it or
delete it. | managed | Enum: [managed unmanaged]
Optional: \{\}
|
| `managedOptions` _[ManagedOptions](#managedoptions)_ | managedOptions specifies options which may be applied to managed objects. | | Optional: \{\}
|
+| `resyncPeriod` _[Duration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#duration-v1-meta)_ | resyncPeriod defines how frequently the controller will re-reconcile
this resource even when no changes have been detected. This overrides
the global default resync period. The value must be a valid Go duration
string, e.g. "10m", "1h". Set to "0s" to disable periodic resync for
this resource. | | Optional: \{\}
|
| `cloudCredentialsRef` _[CloudCredentialsReference](#cloudcredentialsreference)_ | cloudCredentialsRef points to a secret containing OpenStack credentials | | Required: \{\}
|
@@ -2444,6 +2467,7 @@ _Appears in:_
| `conditions` _[Condition](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#condition-v1-meta) array_ | conditions represents the observed status of the object.
Known .status.conditions.type are: "Available", "Progressing"
Available represents the availability of the OpenStack resource. If it is
true then the resource is ready for use.
Progressing indicates whether the controller is still attempting to
reconcile the current state of the OpenStack resource to the desired
state. Progressing will be False either because the desired state has
been achieved, or because some terminal error prevents it from ever being
achieved and the controller is no longer attempting to reconcile. If
Progressing is True, an observer waiting on the resource should continue
to wait. | | MaxItems: 32
Optional: \{\}
|
| `id` _string_ | id is the unique identifier of the OpenStack resource. | | MaxLength: 1024
Optional: \{\}
|
| `resource` _[NetworkResourceStatus](#networkresourcestatus)_ | resource contains the observed state of the OpenStack resource. | | Optional: \{\}
|
+| `lastSyncTime` _[Time](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#time-v1-meta)_ | lastSyncTime is the timestamp of the last successful reconciliation
that fetched state from OpenStack. It is updated each time the
controller successfully reads the resource state from the OpenStack
API. | | Optional: \{\}
|
#### NeutronDescription
@@ -2810,6 +2834,7 @@ _Appears in:_
| `resource` _[PortResourceSpec](#portresourcespec)_ | resource specifies the desired state of the resource.
resource may not be specified if the management policy is `unmanaged`.
resource must be specified if the management policy is `managed`. | | Optional: \{\}
|
| `managementPolicy` _[ManagementPolicy](#managementpolicy)_ | managementPolicy defines how ORC will treat the object. Valid values are
`managed`: ORC will create, update, and delete the resource; `unmanaged`:
ORC will import an existing resource, and will not apply updates to it or
delete it. | managed | Enum: [managed unmanaged]
Optional: \{\}
|
| `managedOptions` _[ManagedOptions](#managedoptions)_ | managedOptions specifies options which may be applied to managed objects. | | Optional: \{\}
|
+| `resyncPeriod` _[Duration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#duration-v1-meta)_ | resyncPeriod defines how frequently the controller will re-reconcile
this resource even when no changes have been detected. This overrides
the global default resync period. The value must be a valid Go duration
string, e.g. "10m", "1h". Set to "0s" to disable periodic resync for
this resource. | | Optional: \{\}
|
| `cloudCredentialsRef` _[CloudCredentialsReference](#cloudcredentialsreference)_ | cloudCredentialsRef points to a secret containing OpenStack credentials | | Required: \{\}
|
@@ -2829,6 +2854,7 @@ _Appears in:_
| `conditions` _[Condition](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#condition-v1-meta) array_ | conditions represents the observed status of the object.
Known .status.conditions.type are: "Available", "Progressing"
Available represents the availability of the OpenStack resource. If it is
true then the resource is ready for use.
Progressing indicates whether the controller is still attempting to
reconcile the current state of the OpenStack resource to the desired
state. Progressing will be False either because the desired state has
been achieved, or because some terminal error prevents it from ever being
achieved and the controller is no longer attempting to reconcile. If
Progressing is True, an observer waiting on the resource should continue
to wait. | | MaxItems: 32
Optional: \{\}
|
| `id` _string_ | id is the unique identifier of the OpenStack resource. | | MaxLength: 1024
Optional: \{\}
|
| `resource` _[PortResourceStatus](#portresourcestatus)_ | resource contains the observed state of the OpenStack resource. | | Optional: \{\}
|
+| `lastSyncTime` _[Time](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#time-v1-meta)_ | lastSyncTime is the timestamp of the last successful reconciliation
that fetched state from OpenStack. It is updated each time the
controller successfully reads the resource state from the OpenStack
API. | | Optional: \{\}
|
#### Project
@@ -2949,6 +2975,7 @@ _Appears in:_
| `resource` _[ProjectResourceSpec](#projectresourcespec)_ | resource specifies the desired state of the resource.
resource may not be specified if the management policy is `unmanaged`.
resource must be specified if the management policy is `managed`. | | Optional: \{\}
|
| `managementPolicy` _[ManagementPolicy](#managementpolicy)_ | managementPolicy defines how ORC will treat the object. Valid values are
`managed`: ORC will create, update, and delete the resource; `unmanaged`:
ORC will import an existing resource, and will not apply updates to it or
delete it. | managed | Enum: [managed unmanaged]
Optional: \{\}
|
| `managedOptions` _[ManagedOptions](#managedoptions)_ | managedOptions specifies options which may be applied to managed objects. | | Optional: \{\}
|
+| `resyncPeriod` _[Duration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#duration-v1-meta)_ | resyncPeriod defines how frequently the controller will re-reconcile
this resource even when no changes have been detected. This overrides
the global default resync period. The value must be a valid Go duration
string, e.g. "10m", "1h". Set to "0s" to disable periodic resync for
this resource. | | Optional: \{\}
|
| `cloudCredentialsRef` _[CloudCredentialsReference](#cloudcredentialsreference)_ | cloudCredentialsRef points to a secret containing OpenStack credentials | | Required: \{\}
|
@@ -2968,6 +2995,7 @@ _Appears in:_
| `conditions` _[Condition](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#condition-v1-meta) array_ | conditions represents the observed status of the object.
Known .status.conditions.type are: "Available", "Progressing"
Available represents the availability of the OpenStack resource. If it is
true then the resource is ready for use.
Progressing indicates whether the controller is still attempting to
reconcile the current state of the OpenStack resource to the desired
state. Progressing will be False either because the desired state has
been achieved, or because some terminal error prevents it from ever being
achieved and the controller is no longer attempting to reconcile. If
Progressing is True, an observer waiting on the resource should continue
to wait. | | MaxItems: 32
Optional: \{\}
|
| `id` _string_ | id is the unique identifier of the OpenStack resource. | | MaxLength: 1024
Optional: \{\}
|
| `resource` _[ProjectResourceStatus](#projectresourcestatus)_ | resource contains the observed state of the OpenStack resource. | | Optional: \{\}
|
+| `lastSyncTime` _[Time](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#time-v1-meta)_ | lastSyncTime is the timestamp of the last successful reconciliation
that fetched state from OpenStack. It is updated each time the
controller successfully reads the resource state from the OpenStack
API. | | Optional: \{\}
|
#### Protocol
@@ -3137,6 +3165,7 @@ _Appears in:_
| `resource` _[RoleResourceSpec](#roleresourcespec)_ | resource specifies the desired state of the resource.
resource may not be specified if the management policy is `unmanaged`.
resource must be specified if the management policy is `managed`. | | Optional: \{\}
|
| `managementPolicy` _[ManagementPolicy](#managementpolicy)_ | managementPolicy defines how ORC will treat the object. Valid values are
`managed`: ORC will create, update, and delete the resource; `unmanaged`:
ORC will import an existing resource, and will not apply updates to it or
delete it. | managed | Enum: [managed unmanaged]
Optional: \{\}
|
| `managedOptions` _[ManagedOptions](#managedoptions)_ | managedOptions specifies options which may be applied to managed objects. | | Optional: \{\}
|
+| `resyncPeriod` _[Duration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#duration-v1-meta)_ | resyncPeriod defines how frequently the controller will re-reconcile
this resource even when no changes have been detected. This overrides
the global default resync period. The value must be a valid Go duration
string, e.g. "10m", "1h". Set to "0s" to disable periodic resync for
this resource. | | Optional: \{\}
|
| `cloudCredentialsRef` _[CloudCredentialsReference](#cloudcredentialsreference)_ | cloudCredentialsRef points to a secret containing OpenStack credentials | | Required: \{\}
|
@@ -3156,6 +3185,7 @@ _Appears in:_
| `conditions` _[Condition](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#condition-v1-meta) array_ | conditions represents the observed status of the object.
Known .status.conditions.type are: "Available", "Progressing"
Available represents the availability of the OpenStack resource. If it is
true then the resource is ready for use.
Progressing indicates whether the controller is still attempting to
reconcile the current state of the OpenStack resource to the desired
state. Progressing will be False either because the desired state has
been achieved, or because some terminal error prevents it from ever being
achieved and the controller is no longer attempting to reconcile. If
Progressing is True, an observer waiting on the resource should continue
to wait. | | MaxItems: 32
Optional: \{\}
|
| `id` _string_ | id is the unique identifier of the OpenStack resource. | | MaxLength: 1024
Optional: \{\}
|
| `resource` _[RoleResourceStatus](#roleresourcestatus)_ | resource contains the observed state of the OpenStack resource. | | Optional: \{\}
|
+| `lastSyncTime` _[Time](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#time-v1-meta)_ | lastSyncTime is the timestamp of the last successful reconciliation
that fetched state from OpenStack. It is updated each time the
controller successfully reads the resource state from the OpenStack
API. | | Optional: \{\}
|
#### Router
@@ -3356,6 +3386,7 @@ _Appears in:_
| `resource` _[RouterResourceSpec](#routerresourcespec)_ | resource specifies the desired state of the resource.
resource may not be specified if the management policy is `unmanaged`.
resource must be specified if the management policy is `managed`. | | Optional: \{\}
|
| `managementPolicy` _[ManagementPolicy](#managementpolicy)_ | managementPolicy defines how ORC will treat the object. Valid values are
`managed`: ORC will create, update, and delete the resource; `unmanaged`:
ORC will import an existing resource, and will not apply updates to it or
delete it. | managed | Enum: [managed unmanaged]
Optional: \{\}
|
| `managedOptions` _[ManagedOptions](#managedoptions)_ | managedOptions specifies options which may be applied to managed objects. | | Optional: \{\}
|
+| `resyncPeriod` _[Duration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#duration-v1-meta)_ | resyncPeriod defines how frequently the controller will re-reconcile
this resource even when no changes have been detected. This overrides
the global default resync period. The value must be a valid Go duration
string, e.g. "10m", "1h". Set to "0s" to disable periodic resync for
this resource. | | Optional: \{\}
|
| `cloudCredentialsRef` _[CloudCredentialsReference](#cloudcredentialsreference)_ | cloudCredentialsRef points to a secret containing OpenStack credentials | | Required: \{\}
|
@@ -3375,6 +3406,7 @@ _Appears in:_
| `conditions` _[Condition](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#condition-v1-meta) array_ | conditions represents the observed status of the object.
Known .status.conditions.type are: "Available", "Progressing"
Available represents the availability of the OpenStack resource. If it is
true then the resource is ready for use.
Progressing indicates whether the controller is still attempting to
reconcile the current state of the OpenStack resource to the desired
state. Progressing will be False either because the desired state has
been achieved, or because some terminal error prevents it from ever being
achieved and the controller is no longer attempting to reconcile. If
Progressing is True, an observer waiting on the resource should continue
to wait. | | MaxItems: 32
Optional: \{\}
|
| `id` _string_ | id is the unique identifier of the OpenStack resource. | | MaxLength: 1024
Optional: \{\}
|
| `resource` _[RouterResourceStatus](#routerresourcestatus)_ | resource contains the observed state of the OpenStack resource. | | Optional: \{\}
|
+| `lastSyncTime` _[Time](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#time-v1-meta)_ | lastSyncTime is the timestamp of the last successful reconciliation
that fetched state from OpenStack. It is updated each time the
controller successfully reads the resource state from the OpenStack
API. | | Optional: \{\}
|
#### RuleDirection
@@ -3560,6 +3592,7 @@ _Appears in:_
| `resource` _[SecurityGroupResourceSpec](#securitygroupresourcespec)_ | resource specifies the desired state of the resource.
resource may not be specified if the management policy is `unmanaged`.
resource must be specified if the management policy is `managed`. | | Optional: \{\}
|
| `managementPolicy` _[ManagementPolicy](#managementpolicy)_ | managementPolicy defines how ORC will treat the object. Valid values are
`managed`: ORC will create, update, and delete the resource; `unmanaged`:
ORC will import an existing resource, and will not apply updates to it or
delete it. | managed | Enum: [managed unmanaged]
Optional: \{\}
|
| `managedOptions` _[ManagedOptions](#managedoptions)_ | managedOptions specifies options which may be applied to managed objects. | | Optional: \{\}
|
+| `resyncPeriod` _[Duration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#duration-v1-meta)_ | resyncPeriod defines how frequently the controller will re-reconcile
this resource even when no changes have been detected. This overrides
the global default resync period. The value must be a valid Go duration
string, e.g. "10m", "1h". Set to "0s" to disable periodic resync for
this resource. | | Optional: \{\}
|
| `cloudCredentialsRef` _[CloudCredentialsReference](#cloudcredentialsreference)_ | cloudCredentialsRef points to a secret containing OpenStack credentials | | Required: \{\}
|
@@ -3579,6 +3612,7 @@ _Appears in:_
| `conditions` _[Condition](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#condition-v1-meta) array_ | conditions represents the observed status of the object.
Known .status.conditions.type are: "Available", "Progressing"
Available represents the availability of the OpenStack resource. If it is
true then the resource is ready for use.
Progressing indicates whether the controller is still attempting to
reconcile the current state of the OpenStack resource to the desired
state. Progressing will be False either because the desired state has
been achieved, or because some terminal error prevents it from ever being
achieved and the controller is no longer attempting to reconcile. If
Progressing is True, an observer waiting on the resource should continue
to wait. | | MaxItems: 32
Optional: \{\}
|
| `id` _string_ | id is the unique identifier of the OpenStack resource. | | MaxLength: 1024
Optional: \{\}
|
| `resource` _[SecurityGroupResourceStatus](#securitygroupresourcestatus)_ | resource contains the observed state of the OpenStack resource. | | Optional: \{\}
|
+| `lastSyncTime` _[Time](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#time-v1-meta)_ | lastSyncTime is the timestamp of the last successful reconciliation
that fetched state from OpenStack. It is updated each time the
controller successfully reads the resource state from the OpenStack
API. | | Optional: \{\}
|
#### Server
@@ -3803,6 +3837,7 @@ _Appears in:_
| `resource` _[ServerGroupResourceSpec](#servergroupresourcespec)_ | resource specifies the desired state of the resource.
resource may not be specified if the management policy is `unmanaged`.
resource must be specified if the management policy is `managed`. | | Optional: \{\}
|
| `managementPolicy` _[ManagementPolicy](#managementpolicy)_ | managementPolicy defines how ORC will treat the object. Valid values are
`managed`: ORC will create, update, and delete the resource; `unmanaged`:
ORC will import an existing resource, and will not apply updates to it or
delete it. | managed | Enum: [managed unmanaged]
Optional: \{\}
|
| `managedOptions` _[ManagedOptions](#managedoptions)_ | managedOptions specifies options which may be applied to managed objects. | | Optional: \{\}
|
+| `resyncPeriod` _[Duration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#duration-v1-meta)_ | resyncPeriod defines how frequently the controller will re-reconcile
this resource even when no changes have been detected. This overrides
the global default resync period. The value must be a valid Go duration
string, e.g. "10m", "1h". Set to "0s" to disable periodic resync for
this resource. | | Optional: \{\}
|
| `cloudCredentialsRef` _[CloudCredentialsReference](#cloudcredentialsreference)_ | cloudCredentialsRef points to a secret containing OpenStack credentials | | Required: \{\}
|
@@ -3822,6 +3857,7 @@ _Appears in:_
| `conditions` _[Condition](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#condition-v1-meta) array_ | conditions represents the observed status of the object.
Known .status.conditions.type are: "Available", "Progressing"
Available represents the availability of the OpenStack resource. If it is
true then the resource is ready for use.
Progressing indicates whether the controller is still attempting to
reconcile the current state of the OpenStack resource to the desired
state. Progressing will be False either because the desired state has
been achieved, or because some terminal error prevents it from ever being
achieved and the controller is no longer attempting to reconcile. If
Progressing is True, an observer waiting on the resource should continue
to wait. | | MaxItems: 32
Optional: \{\}
|
| `id` _string_ | id is the unique identifier of the OpenStack resource. | | MaxLength: 1024
Optional: \{\}
|
| `resource` _[ServerGroupResourceStatus](#servergroupresourcestatus)_ | resource contains the observed state of the OpenStack resource. | | Optional: \{\}
|
+| `lastSyncTime` _[Time](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#time-v1-meta)_ | lastSyncTime is the timestamp of the last successful reconciliation
that fetched state from OpenStack. It is updated each time the
controller successfully reads the resource state from the OpenStack
API. | | Optional: \{\}
|
#### ServerImport
@@ -4004,6 +4040,7 @@ _Appears in:_
| `resource` _[ServerResourceSpec](#serverresourcespec)_ | resource specifies the desired state of the resource.
resource may not be specified if the management policy is `unmanaged`.
resource must be specified if the management policy is `managed`. | | Optional: \{\}
|
| `managementPolicy` _[ManagementPolicy](#managementpolicy)_ | managementPolicy defines how ORC will treat the object. Valid values are
`managed`: ORC will create, update, and delete the resource; `unmanaged`:
ORC will import an existing resource, and will not apply updates to it or
delete it. | managed | Enum: [managed unmanaged]
Optional: \{\}
|
| `managedOptions` _[ManagedOptions](#managedoptions)_ | managedOptions specifies options which may be applied to managed objects. | | Optional: \{\}
|
+| `resyncPeriod` _[Duration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#duration-v1-meta)_ | resyncPeriod defines how frequently the controller will re-reconcile
this resource even when no changes have been detected. This overrides
the global default resync period. The value must be a valid Go duration
string, e.g. "10m", "1h". Set to "0s" to disable periodic resync for
this resource. | | Optional: \{\}
|
| `cloudCredentialsRef` _[CloudCredentialsReference](#cloudcredentialsreference)_ | cloudCredentialsRef points to a secret containing OpenStack credentials | | Required: \{\}
|
@@ -4023,6 +4060,7 @@ _Appears in:_
| `conditions` _[Condition](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#condition-v1-meta) array_ | conditions represents the observed status of the object.
Known .status.conditions.type are: "Available", "Progressing"
Available represents the availability of the OpenStack resource. If it is
true then the resource is ready for use.
Progressing indicates whether the controller is still attempting to
reconcile the current state of the OpenStack resource to the desired
state. Progressing will be False either because the desired state has
been achieved, or because some terminal error prevents it from ever being
achieved and the controller is no longer attempting to reconcile. If
Progressing is True, an observer waiting on the resource should continue
to wait. | | MaxItems: 32
Optional: \{\}
|
| `id` _string_ | id is the unique identifier of the OpenStack resource. | | MaxLength: 1024
Optional: \{\}
|
| `resource` _[ServerResourceStatus](#serverresourcestatus)_ | resource contains the observed state of the OpenStack resource. | | Optional: \{\}
|
+| `lastSyncTime` _[Time](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#time-v1-meta)_ | lastSyncTime is the timestamp of the last successful reconciliation
that fetched state from OpenStack. It is updated each time the
controller successfully reads the resource state from the OpenStack
API. | | Optional: \{\}
|
#### ServerTag
@@ -4188,6 +4226,7 @@ _Appears in:_
| `resource` _[ServiceResourceSpec](#serviceresourcespec)_ | resource specifies the desired state of the resource.
resource may not be specified if the management policy is `unmanaged`.
resource must be specified if the management policy is `managed`. | | Optional: \{\}
|
| `managementPolicy` _[ManagementPolicy](#managementpolicy)_ | managementPolicy defines how ORC will treat the object. Valid values are
`managed`: ORC will create, update, and delete the resource; `unmanaged`:
ORC will import an existing resource, and will not apply updates to it or
delete it. | managed | Enum: [managed unmanaged]
Optional: \{\}
|
| `managedOptions` _[ManagedOptions](#managedoptions)_ | managedOptions specifies options which may be applied to managed objects. | | Optional: \{\}
|
+| `resyncPeriod` _[Duration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#duration-v1-meta)_ | resyncPeriod defines how frequently the controller will re-reconcile
this resource even when no changes have been detected. This overrides
the global default resync period. The value must be a valid Go duration
string, e.g. "10m", "1h". Set to "0s" to disable periodic resync for
this resource. | | Optional: \{\}
|
| `cloudCredentialsRef` _[CloudCredentialsReference](#cloudcredentialsreference)_ | cloudCredentialsRef points to a secret containing OpenStack credentials | | Required: \{\}
|
@@ -4207,6 +4246,7 @@ _Appears in:_
| `conditions` _[Condition](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#condition-v1-meta) array_ | conditions represents the observed status of the object.
Known .status.conditions.type are: "Available", "Progressing"
Available represents the availability of the OpenStack resource. If it is
true then the resource is ready for use.
Progressing indicates whether the controller is still attempting to
reconcile the current state of the OpenStack resource to the desired
state. Progressing will be False either because the desired state has
been achieved, or because some terminal error prevents it from ever being
achieved and the controller is no longer attempting to reconcile. If
Progressing is True, an observer waiting on the resource should continue
to wait. | | MaxItems: 32
Optional: \{\}
|
| `id` _string_ | id is the unique identifier of the OpenStack resource. | | MaxLength: 1024
Optional: \{\}
|
| `resource` _[ServiceResourceStatus](#serviceresourcestatus)_ | resource contains the observed state of the OpenStack resource. | | Optional: \{\}
|
+| `lastSyncTime` _[Time](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#time-v1-meta)_ | lastSyncTime is the timestamp of the last successful reconciliation
that fetched state from OpenStack. It is updated each time the
controller successfully reads the resource state from the OpenStack
API. | | Optional: \{\}
|
#### Subnet
@@ -4387,6 +4427,7 @@ _Appears in:_
| `resource` _[SubnetResourceSpec](#subnetresourcespec)_ | resource specifies the desired state of the resource.
resource may not be specified if the management policy is `unmanaged`.
resource must be specified if the management policy is `managed`. | | Optional: \{\}
|
| `managementPolicy` _[ManagementPolicy](#managementpolicy)_ | managementPolicy defines how ORC will treat the object. Valid values are
`managed`: ORC will create, update, and delete the resource; `unmanaged`:
ORC will import an existing resource, and will not apply updates to it or
delete it. | managed | Enum: [managed unmanaged]
Optional: \{\}
|
| `managedOptions` _[ManagedOptions](#managedoptions)_ | managedOptions specifies options which may be applied to managed objects. | | Optional: \{\}
|
+| `resyncPeriod` _[Duration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#duration-v1-meta)_ | resyncPeriod defines how frequently the controller will re-reconcile
this resource even when no changes have been detected. This overrides
the global default resync period. The value must be a valid Go duration
string, e.g. "10m", "1h". Set to "0s" to disable periodic resync for
this resource. | | Optional: \{\}
|
| `cloudCredentialsRef` _[CloudCredentialsReference](#cloudcredentialsreference)_ | cloudCredentialsRef points to a secret containing OpenStack credentials | | Required: \{\}
|
@@ -4406,6 +4447,7 @@ _Appears in:_
| `conditions` _[Condition](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#condition-v1-meta) array_ | conditions represents the observed status of the object.
Known .status.conditions.type are: "Available", "Progressing"
Available represents the availability of the OpenStack resource. If it is
true then the resource is ready for use.
Progressing indicates whether the controller is still attempting to
reconcile the current state of the OpenStack resource to the desired
state. Progressing will be False either because the desired state has
been achieved, or because some terminal error prevents it from ever being
achieved and the controller is no longer attempting to reconcile. If
Progressing is True, an observer waiting on the resource should continue
to wait. | | MaxItems: 32
Optional: \{\}
|
| `id` _string_ | id is the unique identifier of the OpenStack resource. | | MaxLength: 1024
Optional: \{\}
|
| `resource` _[SubnetResourceStatus](#subnetresourcestatus)_ | resource contains the observed state of the OpenStack resource. | | Optional: \{\}
|
+| `lastSyncTime` _[Time](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#time-v1-meta)_ | lastSyncTime is the timestamp of the last successful reconciliation
that fetched state from OpenStack. It is updated each time the
controller successfully reads the resource state from the OpenStack
API. | | Optional: \{\}
|
#### Trunk
@@ -4538,6 +4580,7 @@ _Appears in:_
| `resource` _[TrunkResourceSpec](#trunkresourcespec)_ | resource specifies the desired state of the resource.
resource may not be specified if the management policy is `unmanaged`.
resource must be specified if the management policy is `managed`. | | Optional: \{\}
|
| `managementPolicy` _[ManagementPolicy](#managementpolicy)_ | managementPolicy defines how ORC will treat the object. Valid values are
`managed`: ORC will create, update, and delete the resource; `unmanaged`:
ORC will import an existing resource, and will not apply updates to it or
delete it. | managed | Enum: [managed unmanaged]
Optional: \{\}
|
| `managedOptions` _[ManagedOptions](#managedoptions)_ | managedOptions specifies options which may be applied to managed objects. | | Optional: \{\}
|
+| `resyncPeriod` _[Duration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#duration-v1-meta)_ | resyncPeriod defines how frequently the controller will re-reconcile
this resource even when no changes have been detected. This overrides
the global default resync period. The value must be a valid Go duration
string, e.g. "10m", "1h". Set to "0s" to disable periodic resync for
this resource. | | Optional: \{\}
|
| `cloudCredentialsRef` _[CloudCredentialsReference](#cloudcredentialsreference)_ | cloudCredentialsRef points to a secret containing OpenStack credentials | | Required: \{\}
|
@@ -4557,6 +4600,7 @@ _Appears in:_
| `conditions` _[Condition](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#condition-v1-meta) array_ | conditions represents the observed status of the object.
Known .status.conditions.type are: "Available", "Progressing"
Available represents the availability of the OpenStack resource. If it is
true then the resource is ready for use.
Progressing indicates whether the controller is still attempting to
reconcile the current state of the OpenStack resource to the desired
state. Progressing will be False either because the desired state has
been achieved, or because some terminal error prevents it from ever being
achieved and the controller is no longer attempting to reconcile. If
Progressing is True, an observer waiting on the resource should continue
to wait. | | MaxItems: 32
Optional: \{\}
|
| `id` _string_ | id is the unique identifier of the OpenStack resource. | | MaxLength: 1024
Optional: \{\}
|
| `resource` _[TrunkResourceStatus](#trunkresourcestatus)_ | resource contains the observed state of the OpenStack resource. | | Optional: \{\}
|
+| `lastSyncTime` _[Time](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#time-v1-meta)_ | lastSyncTime is the timestamp of the last successful reconciliation
that fetched state from OpenStack. It is updated each time the
controller successfully reads the resource state from the OpenStack
API. | | Optional: \{\}
|
#### TrunkSubportSpec
@@ -4734,6 +4778,7 @@ _Appears in:_
| `resource` _[UserResourceSpec](#userresourcespec)_ | resource specifies the desired state of the resource.
resource may not be specified if the management policy is `unmanaged`.
resource must be specified if the management policy is `managed`. | | Optional: \{\}
|
| `managementPolicy` _[ManagementPolicy](#managementpolicy)_ | managementPolicy defines how ORC will treat the object. Valid values are
`managed`: ORC will create, update, and delete the resource; `unmanaged`:
ORC will import an existing resource, and will not apply updates to it or
delete it. | managed | Enum: [managed unmanaged]
Optional: \{\}
|
| `managedOptions` _[ManagedOptions](#managedoptions)_ | managedOptions specifies options which may be applied to managed objects. | | Optional: \{\}
|
+| `resyncPeriod` _[Duration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#duration-v1-meta)_ | resyncPeriod defines how frequently the controller will re-reconcile
this resource even when no changes have been detected. This overrides
the global default resync period. The value must be a valid Go duration
string, e.g. "10m", "1h". Set to "0s" to disable periodic resync for
this resource. | | Optional: \{\}
|
| `cloudCredentialsRef` _[CloudCredentialsReference](#cloudcredentialsreference)_ | cloudCredentialsRef points to a secret containing OpenStack credentials | | Required: \{\}
|
@@ -4753,6 +4798,7 @@ _Appears in:_
| `conditions` _[Condition](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#condition-v1-meta) array_ | conditions represents the observed status of the object.
Known .status.conditions.type are: "Available", "Progressing"
Available represents the availability of the OpenStack resource. If it is
true then the resource is ready for use.
Progressing indicates whether the controller is still attempting to
reconcile the current state of the OpenStack resource to the desired
state. Progressing will be False either because the desired state has
been achieved, or because some terminal error prevents it from ever being
achieved and the controller is no longer attempting to reconcile. If
Progressing is True, an observer waiting on the resource should continue
to wait. | | MaxItems: 32
Optional: \{\}
|
| `id` _string_ | id is the unique identifier of the OpenStack resource. | | MaxLength: 1024
Optional: \{\}
|
| `resource` _[UserResourceStatus](#userresourcestatus)_ | resource contains the observed state of the OpenStack resource. | | Optional: \{\}
|
+| `lastSyncTime` _[Time](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#time-v1-meta)_ | lastSyncTime is the timestamp of the last successful reconciliation
that fetched state from OpenStack. It is updated each time the
controller successfully reads the resource state from the OpenStack
API. | | Optional: \{\}
|
#### Volume
@@ -4943,6 +4989,7 @@ _Appears in:_
| `resource` _[VolumeResourceSpec](#volumeresourcespec)_ | resource specifies the desired state of the resource.
resource may not be specified if the management policy is `unmanaged`.
resource must be specified if the management policy is `managed`. | | Optional: \{\}
|
| `managementPolicy` _[ManagementPolicy](#managementpolicy)_ | managementPolicy defines how ORC will treat the object. Valid values are
`managed`: ORC will create, update, and delete the resource; `unmanaged`:
ORC will import an existing resource, and will not apply updates to it or
delete it. | managed | Enum: [managed unmanaged]
Optional: \{\}
|
| `managedOptions` _[ManagedOptions](#managedoptions)_ | managedOptions specifies options which may be applied to managed objects. | | Optional: \{\}
|
+| `resyncPeriod` _[Duration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#duration-v1-meta)_ | resyncPeriod defines how frequently the controller will re-reconcile
this resource even when no changes have been detected. This overrides
the global default resync period. The value must be a valid Go duration
string, e.g. "10m", "1h". Set to "0s" to disable periodic resync for
this resource. | | Optional: \{\}
|
| `cloudCredentialsRef` _[CloudCredentialsReference](#cloudcredentialsreference)_ | cloudCredentialsRef points to a secret containing OpenStack credentials | | Required: \{\}
|
@@ -4962,6 +5009,7 @@ _Appears in:_
| `conditions` _[Condition](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#condition-v1-meta) array_ | conditions represents the observed status of the object.
Known .status.conditions.type are: "Available", "Progressing"
Available represents the availability of the OpenStack resource. If it is
true then the resource is ready for use.
Progressing indicates whether the controller is still attempting to
reconcile the current state of the OpenStack resource to the desired
state. Progressing will be False either because the desired state has
been achieved, or because some terminal error prevents it from ever being
achieved and the controller is no longer attempting to reconcile. If
Progressing is True, an observer waiting on the resource should continue
to wait. | | MaxItems: 32
Optional: \{\}
|
| `id` _string_ | id is the unique identifier of the OpenStack resource. | | MaxLength: 1024
Optional: \{\}
|
| `resource` _[VolumeResourceStatus](#volumeresourcestatus)_ | resource contains the observed state of the OpenStack resource. | | Optional: \{\}
|
+| `lastSyncTime` _[Time](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#time-v1-meta)_ | lastSyncTime is the timestamp of the last successful reconciliation
that fetched state from OpenStack. It is updated each time the
controller successfully reads the resource state from the OpenStack
API. | | Optional: \{\}
|
#### VolumeType
@@ -5111,6 +5159,7 @@ _Appears in:_
| `resource` _[VolumeTypeResourceSpec](#volumetyperesourcespec)_ | resource specifies the desired state of the resource.
resource may not be specified if the management policy is `unmanaged`.
resource must be specified if the management policy is `managed`. | | Optional: \{\}
|
| `managementPolicy` _[ManagementPolicy](#managementpolicy)_ | managementPolicy defines how ORC will treat the object. Valid values are
`managed`: ORC will create, update, and delete the resource; `unmanaged`:
ORC will import an existing resource, and will not apply updates to it or
delete it. | managed | Enum: [managed unmanaged]
Optional: \{\}
|
| `managedOptions` _[ManagedOptions](#managedoptions)_ | managedOptions specifies options which may be applied to managed objects. | | Optional: \{\}
|
+| `resyncPeriod` _[Duration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#duration-v1-meta)_ | resyncPeriod defines how frequently the controller will re-reconcile
this resource even when no changes have been detected. This overrides
the global default resync period. The value must be a valid Go duration
string, e.g. "10m", "1h". Set to "0s" to disable periodic resync for
this resource. | | Optional: \{\}
|
| `cloudCredentialsRef` _[CloudCredentialsReference](#cloudcredentialsreference)_ | cloudCredentialsRef points to a secret containing OpenStack credentials | | Required: \{\}
|
@@ -5130,5 +5179,6 @@ _Appears in:_
| `conditions` _[Condition](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#condition-v1-meta) array_ | conditions represents the observed status of the object.
Known .status.conditions.type are: "Available", "Progressing"
Available represents the availability of the OpenStack resource. If it is
true then the resource is ready for use.
Progressing indicates whether the controller is still attempting to
reconcile the current state of the OpenStack resource to the desired
state. Progressing will be False either because the desired state has
been achieved, or because some terminal error prevents it from ever being
achieved and the controller is no longer attempting to reconcile. If
Progressing is True, an observer waiting on the resource should continue
to wait. | | MaxItems: 32
Optional: \{\}
|
| `id` _string_ | id is the unique identifier of the OpenStack resource. | | MaxLength: 1024
Optional: \{\}
|
| `resource` _[VolumeTypeResourceStatus](#volumetyperesourcestatus)_ | resource contains the observed state of the OpenStack resource. | | Optional: \{\}
|
+| `lastSyncTime` _[Time](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#time-v1-meta)_ | lastSyncTime is the timestamp of the last successful reconciliation
that fetched state from OpenStack. It is updated each time the
controller successfully reads the resource state from the OpenStack
API. | | Optional: \{\}
|
diff --git a/website/docs/development/godoc/generic-interfaces.md b/website/docs/development/godoc/generic-interfaces.md
index 2d0021572..85753dd6c 100644
--- a/website/docs/development/godoc/generic-interfaces.md
+++ b/website/docs/development/godoc/generic-interfaces.md
@@ -20,10 +20,11 @@ import "github.com/k-orc/openstack-resource-controller/v2/internal/controllers/g
- [type ResourceHelperFactory](<#ResourceHelperFactory>)
- [type ResourceReconciler](<#ResourceReconciler>)
- [type ResourceStatusWriter](<#ResourceStatusWriter>)
+- [type ResyncConfigurable](<#ResyncConfigurable>)
-## type [APIObjectAdapter]()
+## type [APIObjectAdapter]()
@@ -39,11 +40,20 @@ type APIObjectAdapter[orcObjectPT any, resourceSpecT any, filterT any] interface
GetManagementPolicy() orcv1alpha1.ManagementPolicy
GetManagedOptions() *orcv1alpha1.ManagedOptions
+ GetResyncPeriod() *metav1.Duration
+ GetLastSyncTime() *metav1.Time
GetStatusID() *string
GetResourceSpec() *resourceSpecT
GetImportID() *string
GetImportFilter() *filterT
+
+ // IsImported returns true if the resource was imported (rather than created
+ // by ORC). A resource is considered imported if it has a non-nil importID or
+ // a non-nil importFilter. This is used to decide how to handle external
+ // deletion: imported resources result in a terminal error, while ORC-created
+ // resources are recreated.
+ IsImported() bool
}
```
@@ -90,7 +100,7 @@ type BaseResourceActuator[
```
-## type [Controller]()
+## type [Controller]()
@@ -203,14 +213,15 @@ type ORCApplyConfig[objectApplyPT any, statusApplyPT ORCStatusApplyConfig[status
```
-## type [ORCStatusApplyConfig]()
+## type [ORCStatusApplyConfig]()
-ORCStatusApplyConfig is an interface implemented by the status of any apply configuration for an ORC API object. It has Conditions and an ID field.
+ORCStatusApplyConfig is an interface implemented by the status of any apply configuration for an ORC API object. It has Conditions, an ID field, and a LastSyncTime field.
```go
type ORCStatusApplyConfig[statusApplyPT any] interface {
WithConditions(...*applyconfigv1.ConditionApplyConfiguration) statusApplyPT
WithID(id string) statusApplyPT
+ WithLastSyncTime(metav1.Time) statusApplyPT
}
```
@@ -245,7 +256,7 @@ type ReconcileResourceActuator[orcObjectPT, osResourceT any] interface {
```
-## type [ResourceController]()
+## type [ResourceController]()
@@ -313,7 +324,7 @@ type ResourceReconciler[orcObjectPT, osResourceT any] func(ctx context.Context,
```
-## type [ResourceStatusWriter]()
+## type [ResourceStatusWriter]()
ResourceStatusWriter defines methods for writing an ORC object status
@@ -334,4 +345,15 @@ type ResourceStatusWriter[objectPT orcv1alpha1.ObjectWithConditions, osResourceP
}
```
+
+## type [ResyncConfigurable]()
+
+ResyncConfigurable is an optional interface that Controller implementations may satisfy to receive the operator\-level default resync period. The manager calls SetDefaultResyncPeriod before SetupWithManager so that the value is available when the controller is built.
+
+```go
+type ResyncConfigurable interface {
+ SetDefaultResyncPeriod(time.Duration)
+}
+```
+
Generated by [gomarkdoc]()
diff --git a/website/docs/user-guide/drift-detection.md b/website/docs/user-guide/drift-detection.md
new file mode 100644
index 000000000..1938931d1
--- /dev/null
+++ b/website/docs/user-guide/drift-detection.md
@@ -0,0 +1,189 @@
+# Drift Detection and External Deletion Handling
+
+ORC can periodically reconcile resources to detect and correct configuration drift — changes made to OpenStack resources outside of ORC's control. This feature also detects when managed resources have been deleted directly from OpenStack and recreates them automatically.
+
+## Enabling Drift Detection
+
+Drift detection is disabled by default. Enable it per-resource by setting `spec.resyncPeriod`:
+
+```yaml
+apiVersion: openstack.k-orc.cloud/v1alpha1
+kind: Network
+metadata:
+ name: critical-network
+spec:
+ cloudCredentialsRef:
+ secretName: openstack-clouds
+ cloudName: openstack
+ managementPolicy: managed
+ resyncPeriod: 1h # Re-check OpenStack every hour
+ resource:
+ description: Critical application network
+```
+
+The `resyncPeriod` field accepts any Go duration string: `10m`, `1h`, `24h`, etc.
+
+**Default:** `0` (disabled). When disabled, ORC only reconciles resources in response to spec changes or controller restarts.
+
+!!! note
+
+ Conservative resync periods (e.g., `1h` or `10h`) are recommended in production to avoid excessive OpenStack API calls.
+
+## How It Works
+
+After a resource reaches a stable state (`Progressing=False`), ORC schedules a reconciliation after the configured `resyncPeriod`. On each resync:
+
+1. ORC fetches the current state of the OpenStack resource.
+2. For **managed** resources: if drift is detected, ORC updates the resource to match the Kubernetes spec.
+3. For **unmanaged** resources: ORC refreshes `status.resource` to reflect the current OpenStack state, but makes no changes.
+4. The next resync is scheduled.
+
+A small random jitter ([0%, +20%]) is applied to `resyncPeriod` to spread reconciliations and avoid thundering-herd effects.
+
+!!! note
+
+ Resources in a terminal error state (`Progressing=False` with reason `InvalidConfiguration` or `UnrecoverableError`) are **not** periodically resynced. Terminal errors require manual intervention to resolve.
+
+## Tracking Sync Status
+
+Every ORC resource has a `status.lastSyncTime` field that records when ORC last successfully reconciled with OpenStack:
+
+```bash
+kubectl get network critical-network -o jsonpath='{.status.lastSyncTime}'
+# 2026-02-03T10:30:00Z
+```
+
+ORC persists this timestamp in the Kubernetes status. After a controller restart, it uses `lastSyncTime` to determine when the next resync should occur, preventing a thundering herd of reconciliations on startup.
+
+## External Deletion Handling
+
+When a resource is deleted directly from OpenStack (bypassing ORC), the behavior depends on how ORC originally obtained the resource.
+
+### ORC-Created Resources (Managed, Not Imported)
+
+If you created the resource through ORC's `spec.resource` field, ORC **recreates** it automatically:
+
+1. ORC detects the resource is missing from OpenStack (the ID stored in `status.id` no longer exists).
+2. ORC clears `status.id`.
+3. On the next reconcile, ORC creates a new OpenStack resource.
+4. The new resource ID is stored in `status.id`.
+
+The ORC object continues to exist and becomes `Available=True` again once the resource is recreated.
+
+```yaml
+# This type of resource will be recreated if deleted from OpenStack
+spec:
+ managementPolicy: managed
+ resyncPeriod: 10m # Enable resync to detect deletion quickly
+ resource: # Resource was created by ORC
+ description: My application network
+```
+
+!!! warning
+
+ Recreation produces a new OpenStack resource with a **new ID**. Any OpenStack resources (outside ORC) that referenced the old ID will need to be updated manually.
+
+### Imported Resources (Terminal Error)
+
+If you imported an existing resource using `spec.import`, ORC reports a **terminal error** when the resource is deleted from OpenStack:
+
+- `Available=False`
+- `Progressing=False`
+- Condition reason: `UnrecoverableError`
+- Message: `resource has been deleted from OpenStack`
+
+ORC does **not** recreate imported resources because it did not create them originally, and recreating a new empty resource would not restore what was lost.
+
+```yaml
+# This type of resource enters terminal error if deleted from OpenStack
+spec:
+ managementPolicy: managed
+ import:
+ id: "12345678-1234-1234-1234-123456789abc" # Was imported by ID
+```
+
+```yaml
+# This type also enters terminal error if deleted from OpenStack
+spec:
+ managementPolicy: unmanaged
+ import:
+ filter:
+ name: public # Was imported by filter
+```
+
+To recover: manually recreate the OpenStack resource and update the ORC object's `spec.import.id` to the new resource ID, or delete and recreate the ORC object.
+
+### Summary Table
+
+| Resource Type | How Obtained | External Deletion Behavior |
+|--------------|--------------|---------------------------|
+| Managed, ORC-created | `spec.resource` | **Recreated** automatically |
+| Managed, imported by ID | `spec.import.id` | **Terminal error** |
+| Managed, imported by filter | `spec.import.filter` | **Terminal error** |
+| Unmanaged | `spec.import.*` | **Terminal error** |
+
+## Verifying Recreation Occurred
+
+When an ORC-created resource is recreated after external deletion, `status.id` changes to reflect the new OpenStack resource ID. Monitor this to detect recreation events:
+
+```bash
+# Record the current ID
+ORIGINAL_ID=$(kubectl get network my-network -o jsonpath='{.status.id}')
+echo "Original ID: $ORIGINAL_ID"
+
+# ... some time later, check if it changed ...
+CURRENT_ID=$(kubectl get network my-network -o jsonpath='{.status.id}')
+if [ "$ORIGINAL_ID" != "$CURRENT_ID" ]; then
+ echo "Resource was recreated! New ID: $CURRENT_ID"
+fi
+```
+
+You can also watch the resource for status changes:
+
+```bash
+kubectl get network my-network -w
+```
+
+During recreation, you will observe:
+
+1. `Available=False`, `Progressing=True` — ORC is recreating the resource
+2. `Available=True`, `Progressing=False` — Recreation complete, `status.id` has new value
+
+## Implications for Dependent Resources
+
+OpenStack enforces referential integrity for most resource relationships (e.g., a Network cannot be deleted while Subnets exist). If an external deletion manages to bypass these constraints (e.g., direct database manipulation), the behavior of dependent ORC resources follows these rules:
+
+### If a Parent Resource Is Recreated
+
+When a parent resource (e.g., Network) is recreated by ORC, dependent resources that reference it (e.g., Subnets) detect the parent as available again but may encounter errors when OpenStack rejects operations referencing the old parent ID. **Manual intervention may be required** to recreate dependent resources against the new parent.
+
+### If a Parent Resource Enters Terminal Error
+
+When a parent resource enters terminal error:
+
+- **Dependent resources waiting on it** (e.g., a Subnet waiting for its Network): ORC will not proceed — it waits until the parent becomes available again. The dependent is not itself in an error state; it is just waiting.
+- **Dependent resources already created**: ORC continues managing them normally. If ORC attempts to update a dependent resource that references a deleted parent in OpenStack, the behavior depends on what OpenStack returns for that operation.
+
+!!! warning
+
+ If a parent resource is externally deleted in a way that bypasses OpenStack's referential integrity checks, the resulting state may require manual cleanup of both the parent and dependent resources. This is an unusual operational scenario and not specific to drift detection.
+
+## Interaction with `managementPolicy: unmanaged`
+
+Unmanaged resources are never modified by ORC. With `resyncPeriod` set, ORC will periodically refresh `status.resource` to reflect the current OpenStack state. However, if the OpenStack resource is deleted, ORC will report a terminal error — it does not recreate unmanaged resources under any circumstances.
+
+```yaml
+spec:
+ managementPolicy: unmanaged
+ resyncPeriod: 1h # Refresh status every hour, but never modify OpenStack
+ import:
+ id: "12345678-1234-1234-1234-123456789abc"
+```
+
+## Drift Detection Without Resync
+
+Even with `resyncPeriod: 0` (the default, disabled), ORC will still detect external deletion when another event triggers reconciliation — for example, when you make a spec change or the controller restarts. The recreation or terminal error behavior is the same; the difference is only in how quickly ORC detects the deletion.
+
+!!! tip
+
+ If you want rapid detection of external deletions for critical resources, set a short `resyncPeriod` (e.g., `10m`).
diff --git a/website/docs/user-guide/index.md b/website/docs/user-guide/index.md
index 4945fcdef..d30c84dd3 100644
--- a/website/docs/user-guide/index.md
+++ b/website/docs/user-guide/index.md
@@ -122,6 +122,15 @@ spec:
ipVersion: 4
```
+### Drift Detection and External Deletion
+
+ORC can periodically reconcile resources to detect configuration drift and recreate managed resources that are deleted directly from OpenStack. See [Drift Detection](drift-detection.md) for details on:
+
+- How to enable periodic resync with `spec.resyncPeriod`
+- How ORC handles externally deleted resources (recreation vs. terminal error)
+- How to verify that recreation occurred by checking `status.id`
+- Implications for dependent resources
+
### Understanding Status and Conditions
Every ORC resource reports its status through two conditions: `Available` (whether the resource is ready for use) and `Progressing` (whether ORC is still working on it). For detailed information about conditions and their meanings, see [Troubleshooting: Status Conditions Explained](../troubleshooting.md#status-conditions-explained).
diff --git a/website/mkdocs.yml b/website/mkdocs.yml
index e71fbe9e9..01f6d8815 100644
--- a/website/mkdocs.yml
+++ b/website/mkdocs.yml
@@ -7,7 +7,9 @@ nav:
- Getting Started:
- Installation: installation.md
- Quick Start: getting-started.md
- - User Guide: user-guide/index.md
+ - User Guide:
+ - Overview: user-guide/index.md
+ - Drift Detection: user-guide/drift-detection.md
- CRD Reference: crd-reference.md
- Troubleshooting: troubleshooting.md
- Contributing: