Skip to content

Commit

Permalink
Update VirtualClusterInstance status
Browse files Browse the repository at this point in the history
Signed-off-by: Xiaodong Ye <yeahdongcn@gmail.com>
  • Loading branch information
yeahdongcn committed Nov 28, 2023
1 parent 213659a commit b31ac8f
Show file tree
Hide file tree
Showing 9 changed files with 226 additions and 8 deletions.
2 changes: 2 additions & 0 deletions api/v1/clusterdomain_types.go
Expand Up @@ -32,6 +32,8 @@ type ClusterDomainStatus struct {
//+kubebuilder:object:root=true
//+kubebuilder:subresource:status
//+kubebuilder:resource:scope=Cluster
//+kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp"
//+kubebuilder:printcolumn:name="Domain",type=string,JSONPath=`.spec.domain`

// ClusterDomain is the Schema for the clusterdomains API
type ClusterDomain struct {
Expand Down
72 changes: 72 additions & 0 deletions api/v1/condition_types.go
@@ -0,0 +1,72 @@
package v1

import (
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

// ConditionType is a valid value for Condition.Type.
type ConditionType string

const (
// InitializedCondition defines the helm chart initialized condition type that defines if the helm chart was initialized correctly.
InitializedCondition ConditionType = "Initialized"

// DeployedCondition defines the helm chart deployed condition type that defines if the helm chart was deployed correctly.
DeployedCondition ConditionType = "Deployed"
)

// ConditionSeverity expresses the severity of a Condition Type failing.
type ConditionSeverity string

const (
// ConditionSeverityError specifies that a condition with `Status=False` is an error.
ConditionSeverityError ConditionSeverity = "Error"

// ConditionSeverityWarning specifies that a condition with `Status=False` is a warning.
ConditionSeverityWarning ConditionSeverity = "Warning"

// ConditionSeverityInfo specifies that a condition with `Status=False` is informative.
ConditionSeverityInfo ConditionSeverity = "Info"

// ConditionSeverityNone should apply only to conditions with `Status=True`.
ConditionSeverityNone ConditionSeverity = ""
)

// Conditions is an array of conditions
type Conditions []Condition

type Condition struct {
// Type of condition in CamelCase or in foo.example.com/CamelCase.
// Many .condition.type values are consistent across resources like Available, but because arbitrary conditions
// can be useful (see .node.status.conditions), the ability to deconflict is important.
// +required
Type ConditionType `json:"type"`

// Status of the condition, one of True, False, Unknown.
// +required
Status corev1.ConditionStatus `json:"status"`

// Severity provides an explicit classification of Reason code, so the users or machines can immediately
// understand the current situation and act accordingly.
// The Severity field MUST be set only when Status=False.
// +optional
Severity ConditionSeverity `json:"severity,omitempty"`

// Last time the condition transitioned from one status to another.
// This should be when the underlying condition changed. If that is not known, then using the time when
// the API field changed is acceptable.
// +required
LastTransitionTime metav1.Time `json:"lastTransitionTime,omitempty"`

// The reason for the condition's last transition in CamelCase.
// The specific API may choose whether this field is considered a guaranteed API.
// This field may not be empty.
// +optional
Reason string `json:"reason,omitempty"`

// A human readable message indicating details about the transition.
// This field may be empty.
// +optional
Message string `json:"message,omitempty"`
}
3 changes: 3 additions & 0 deletions api/v1/virtualcluster_types.go
Expand Up @@ -35,6 +35,9 @@ type VirtualClusterSpec struct {

// VirtualClusterStatus defines the observed state of VirtualCluster
type VirtualClusterStatus struct {
// Conditions holds several conditions the vcluster might be in
// +optional
Conditions Conditions `json:"conditions,omitempty"`
}

//+kubebuilder:object:root=true
Expand Down
46 changes: 45 additions & 1 deletion api/v1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 8 additions & 1 deletion config/crd/bases/storage.openloft.cn_clusterdomains.yaml
Expand Up @@ -15,7 +15,14 @@ spec:
singular: clusterdomain
scope: Cluster
versions:
- name: v1
- additionalPrinterColumns:
- jsonPath: .metadata.creationTimestamp
name: Age
type: date
- jsonPath: .spec.domain
name: Domain
type: string
name: v1
schema:
openAPIV3Schema:
description: ClusterDomain is the Schema for the clusterdomains API
Expand Down
43 changes: 43 additions & 0 deletions config/crd/bases/storage.openloft.cn_virtualclusters.yaml
Expand Up @@ -1190,6 +1190,49 @@ spec:
type: object
status:
description: VirtualClusterStatus defines the observed state of VirtualCluster
properties:
conditions:
description: Conditions holds several conditions the vcluster might
be in
items:
properties:
lastTransitionTime:
description: Last time the condition transitioned from one status
to another. This should be when the underlying condition changed.
If that is not known, then using the time when the API field
changed is acceptable.
format: date-time
type: string
message:
description: A human readable message indicating details about
the transition. This field may be empty.
type: string
reason:
description: The reason for the condition's last transition
in CamelCase. The specific API may choose whether this field
is considered a guaranteed API. This field may not be empty.
type: string
severity:
description: Severity provides an explicit classification of
Reason code, so the users or machines can immediately understand
the current situation and act accordingly. The Severity field
MUST be set only when Status=False.
type: string
status:
description: Status of the condition, one of True, False, Unknown.
type: string
type:
description: Type of condition in CamelCase or in foo.example.com/CamelCase.
Many .condition.type values are consistent across resources
like Available, but because arbitrary conditions can be useful
(see .node.status.conditions), the ability to deconflict is
important.
type: string
required:
- status
- type
type: object
type: array
type: object
type: object
served: true
Expand Down
8 changes: 4 additions & 4 deletions controllers/clusterdomain/controller.go
Expand Up @@ -28,8 +28,8 @@ import (
openloftv1 "github.com/openloft/openloft/api/v1"
)

// ClusterDomainReconciler reconciles a ClusterDomain object
type ClusterDomainReconciler struct {
// Reconciler reconciles a ClusterDomain object
type Reconciler struct {
client.Client
Scheme *runtime.Scheme
Log logr.Logger
Expand All @@ -40,14 +40,14 @@ type ClusterDomainReconciler struct {
//+kubebuilder:rbac:groups=storage.openloft.cn,resources=clusterdomains/status,verbs=get;update;patch
//+kubebuilder:rbac:groups=storage.openloft.cn,resources=clusterdomains/finalizers,verbs=update

func (r *ClusterDomainReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
r.Log.Info("Reconciling VirtualClusterTemplateReconciler", "req.NamespacedName", req.NamespacedName)

return ctrl.Result{}, nil
}

// SetupWithManager sets up the controller with the Manager.
func (r *ClusterDomainReconciler) SetupWithManager(mgr ctrl.Manager) error {
func (r *Reconciler) SetupWithManager(mgr ctrl.Manager) error {
return ctrl.NewControllerManagedBy(mgr).
For(&openloftv1.ClusterDomain{}).
Complete(r)
Expand Down
49 changes: 48 additions & 1 deletion controllers/virtualclusterinstance/controller.go
Expand Up @@ -75,7 +75,7 @@ func normalizedNamespace(vci *loftv1.VirtualClusterInstance) string {
//+kubebuilder:rbac:groups=networking.k8s.io,resources=ingressclasses,verbs=get;list;watch
//+kubebuilder:rbac:groups=core,resources=events,verbs=create;patch

func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (_ ctrl.Result, reterr error) {
r.Log.Info("Reconciling VirtualClusterInstance", "req.NamespacedName", req.NamespacedName)

vci := &loftv1.VirtualClusterInstance{}
Expand Down Expand Up @@ -108,9 +108,56 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Resu
return result, err
}

defer func() {
// Always reconcile the Status.Phase field.
r.reconcilePhase(ctx, req)
}()

return ctrl.Result{}, nil
}

func (r *Reconciler) reconcilePhase(ctx context.Context, req ctrl.Request) {
vci := &loftv1.VirtualClusterInstance{}
err := r.Get(ctx, req.NamespacedName, vci)
if err != nil {
r.Log.Error(err, "Failed to get VirtualClusterInstance")
return
}

vc := &openloftv1.VirtualCluster{}
err = r.Get(ctx, types.NamespacedName{Name: normalizedName(vci), Namespace: normalizedNamespace(vci)}, vc)
if err != nil {
r.Log.Error(err, "Failed to get VirtualCluster")
return
}

if vci.Status.Phase != loftv1.InstancePending {
vci.Status.Phase = loftv1.InstancePending
}

// set failed if a condition is errored
vci.Status.Reason = ""
vci.Status.Message = ""

for _, c := range vc.Status.Conditions {
if c.Status == corev1.ConditionTrue && c.Type == openloftv1.DeployedCondition {
vci.Status.Phase = loftv1.InstanceReady
break
}
if c.Status == corev1.ConditionFalse && c.Severity == openloftv1.ConditionSeverityError {
vci.Status.Phase = loftv1.InstanceFailed
vci.Status.Reason = c.Reason
vci.Status.Message = c.Message
break
}
}

r.Log.Info("Updating VirtualClusterInstance status", "VirtualClusterInstance.Name", vci.Name)
if err := r.Update(ctx, vci); err != nil {
r.Log.Error(err, "Failed to update VirtualClusterInstance status")
}
}

// SetupWithManager sets up the controller with the Manager.
func (r *Reconciler) SetupWithManager(mgr ctrl.Manager) error {
return ctrl.NewControllerManagedBy(mgr).
Expand Down
2 changes: 1 addition & 1 deletion main.go
Expand Up @@ -111,7 +111,7 @@ func main() {
setupLog.Error(err, "unable to create controller", "controller", "VirtualClusterTemplate")
os.Exit(1)
}
if err = (&clusterdomain.ClusterDomainReconciler{
if err = (&clusterdomain.Reconciler{
Client: mgr.GetClient(),
Scheme: mgr.GetScheme(),
Log: ctrlLog.WithName("ClusterDomain"),
Expand Down

0 comments on commit b31ac8f

Please sign in to comment.