Skip to content

Commit 5d6d52d

Browse files
committed
feat: add DRPC controller for ProtectedApplicationView generation
Implements controller to automatically create/update ProtectedApplicationView resources from DRPlacementControl, discovering application types (ApplicationSet/ Subscription/Discovered) and aggregating placement and DR status. - Add DRPCReconciler with app discovery logic via Placement reverse mapping - Support ApplicationSet (ClusterDecisionResource matchLabels) and Subscription (PlacementRef + parent Application lookup) - Include secondary watches for Placement/PlacementDecision cluster changes - Register required schemes (argoproj.io, cluster.open-cluster-management.io, apps.open-cluster-management.io) in manager - Add RBAC permissions for drplacementcontrols, applicationsets, subscriptions, applications, placements, and protectedapplicationviews Signed-off-by: vbadrina <[email protected]>
1 parent 53db812 commit 5d6d52d

File tree

4 files changed

+691
-0
lines changed

4 files changed

+691
-0
lines changed
Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
package v1alpha1
2+
3+
import (
4+
ramenv1alpha1 "github.com/ramendr/ramen/api/v1alpha1"
5+
corev1 "k8s.io/api/core/v1"
6+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
7+
)
8+
9+
type ApplicationType string
10+
11+
const (
12+
// ApplicationSetType represents an ArgoCD ApplicationSet application
13+
ApplicationSetType ApplicationType = "ApplicationSet"
14+
15+
// SubscriptionType represents an OpenShift Subscription application
16+
SubscriptionType ApplicationType = "Subscription"
17+
18+
// DiscoveredType represents a discovered application (neither ApplicationSet nor Subscription)
19+
DiscoveredType ApplicationType = "Discovered"
20+
)
21+
22+
// ProtectedApplicationViewSpec defines the desired state of ProtectedApplicationView
23+
type ProtectedApplicationViewSpec struct {
24+
25+
// DRPCRef references the DRPlacementControl protecting this application
26+
// +kubebuilder:validation:Required
27+
DRPCRef corev1.ObjectReference `json:"drpcRef"`
28+
29+
// ApplicationRef references the source application resource
30+
// +kubebuilder:validation:Required
31+
ApplicationRef corev1.ObjectReference `json:"applicationRef"`
32+
}
33+
34+
// PlacementInfo contains information about application placement
35+
type PlacementInfo struct {
36+
// Name of the Placement resource
37+
// +kubebuilder:validation:Required
38+
Name string `json:"name"`
39+
40+
// Namespace of the Placement resource
41+
// +kubebuilder:validation:Required
42+
Namespace string `json:"namespace"`
43+
44+
// Kind of placement (Placement or PlacementRule)
45+
// +kubebuilder:validation:Required
46+
// +kubebuilder:validation:Enum=Placement;PlacementRule
47+
Kind string `json:"kind"`
48+
49+
// SelectedClusters is the list of clusters where application is placed
50+
// +optional
51+
SelectedClusters []string `json:"selectedClusters,omitempty"`
52+
}
53+
54+
// DRInfo contains disaster recovery configuration information
55+
type DRInfo struct {
56+
// DRPolicyRef references the DRPolicy used for protection
57+
// +kubebuilder:validation:Required
58+
DRPolicyRef corev1.ObjectReference `json:"drpolicyRef"`
59+
60+
// DRClusters is the list of clusters in the DR relationship
61+
// +optional
62+
DRClusters []string `json:"drClusters,omitempty"`
63+
64+
// PrimaryCluster is the current primary/active cluster
65+
// +optional
66+
PrimaryCluster string `json:"primaryCluster,omitempty"`
67+
68+
// ProtectedNamespaces contains list of namespaces protected by this DRPC
69+
// +optional
70+
ProtectedNamespaces []string `json:"protectedNamespaces,omitempty"`
71+
72+
// Status contains current DR status information
73+
// +optional
74+
Status DRStatusInfo `json:"status,omitempty"`
75+
}
76+
77+
// DRStatusInfo contains disaster recovery status
78+
type DRStatusInfo struct {
79+
// Phase represents current DR phase (Relocated, FailingOver, etc.)
80+
// +optional
81+
Phase ramenv1alpha1.DRState `json:"phase,omitempty"`
82+
83+
LastGroupSyncTime *metav1.Time `json:"lastGroupSyncTime,omitempty"`
84+
85+
// Conditions represent the latest available observations of the DR state
86+
// +optional
87+
// +listType=map
88+
// +listMapKey=type
89+
Conditions []metav1.Condition `json:"conditions,omitempty"`
90+
}
91+
92+
type ApplicationInfo struct {
93+
// Type of application (ApplicationSet, Subscription, or Discovered)
94+
// +kubebuilder:validation:Required
95+
// +kubebuilder:validation:Enum=ApplicationSet;Subscription;Discovered
96+
Type ApplicationType `json:"type"`
97+
98+
// SubscriptionInfo contains Subscription-specific information
99+
// +optional
100+
SubscriptionInfo *SubscriptionInfo `json:"subscriptionInfo,omitempty"`
101+
}
102+
103+
// SubscriptionInfo contains Subscription-specific information
104+
type SubscriptionInfo struct {
105+
// SubscriptionRefs lists Subscription resources in this DRPC group
106+
// +optional
107+
SubscriptionRefs []corev1.ObjectReference `json:"subscriptionRefs,omitempty"`
108+
}
109+
110+
// ProtectedApplicationViewStatus defines the observed state of ProtectedApplicationView
111+
type ProtectedApplicationViewStatus struct {
112+
ApplicationInfo ApplicationInfo `json:"applicationInfo,omitempty"`
113+
114+
// Placements contains placement information for this application
115+
// +optional
116+
// +kubebuilder:validation:MaxItems=10
117+
PlacementInfo []PlacementInfo `json:"placementInfo,omitempty"`
118+
119+
// DRInfo contains disaster recovery configuration
120+
// +kubebuilder:validation:Required
121+
DRInfo DRInfo `json:"drInfo"`
122+
123+
// ObservedGeneration is the generation most recently observed
124+
// +optional
125+
ObservedGeneration int64 `json:"observedGeneration,omitempty"`
126+
127+
// LastSyncTime is the last time the view was synchronized
128+
// +optional
129+
LastSyncTime *metav1.Time `json:"lastSyncTime,omitempty"`
130+
131+
// Conditions represent the latest available observations of the application state
132+
// +optional
133+
// +listType=map
134+
// +listMapKey=type
135+
Conditions []metav1.Condition `json:"conditions,omitempty"`
136+
}
137+
138+
// +kubebuilder:object:root=true
139+
// +kubebuilder:subresource:status
140+
// +kubebuilder:resource:scope=Namespaced,shortName=pav
141+
// +kubebuilder:printcolumn:name="Type",type=string,JSONPath=`.status.applicationInfo.type`
142+
// +kubebuilder:printcolumn:name="App",type=string,JSONPath=`.spec.applicationRef.name`
143+
// +kubebuilder:printcolumn:name="DRPolicy",type=string,JSONPath=`.status.drInfo.drPolicyRef.name`
144+
// +kubebuilder:printcolumn:name="Status",type=string,JSONPath=`.status.drInfo.status.phase`
145+
// +kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp`
146+
147+
// ProtectedApplicationView represents an aggregated view of a protected application
148+
type ProtectedApplicationView struct {
149+
metav1.TypeMeta `json:",inline"`
150+
metav1.ObjectMeta `json:"metadata,omitempty"`
151+
152+
Spec ProtectedApplicationViewSpec `json:"spec,omitempty"`
153+
Status ProtectedApplicationViewStatus `json:"status,omitempty"`
154+
}
155+
156+
// +kubebuilder:object:root=true
157+
158+
// ProtectedApplicationViewList contains a list of ProtectedApplicationView
159+
type ProtectedApplicationViewList struct {
160+
metav1.TypeMeta `json:",inline"`
161+
metav1.ListMeta `json:"metadata,omitempty"`
162+
Items []ProtectedApplicationView `json:"items"`
163+
}
164+
165+
func init() {
166+
SchemeBuilder.Register(&ProtectedApplicationView{}, &ProtectedApplicationViewList{})
167+
}

0 commit comments

Comments
 (0)