Skip to content

Commit

Permalink
Merge pull request #15 from embik/object-status-phases
Browse files Browse the repository at this point in the history
✨ Add phase and owner references to RootShards
  • Loading branch information
kcp-ci-bot authored Jan 13, 2025
2 parents 16cdaf5 + bd92432 commit 6ffdca9
Show file tree
Hide file tree
Showing 7 changed files with 88 additions and 76 deletions.
2 changes: 1 addition & 1 deletion api/v1alpha1/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ type ImageSpec struct {

type RootShardConfig struct {
// Reference references a local RootShard object.
Reference *corev1.ObjectReference `json:"ref,omitempty"`
Reference *corev1.LocalObjectReference `json:"ref,omitempty"`
}

type EtcdConfig struct {
Expand Down
20 changes: 18 additions & 2 deletions api/v1alpha1/rootshard_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,12 +84,28 @@ type OIDCConfiguration struct {

// RootShardStatus defines the observed state of RootShard
type RootShardStatus struct {
// INSERT ADDITIONAL STATUS FIELD - define observed state of cluster
// Important: Run "make" to regenerate code after modifying this file
Phase RootShardPhase `json:"phase,omitempty"`
}

type RootShardPhase string

const (
RootShardPhaseProvisioning RootShardPhase = "Provisioning"
RootShardPhaseRunning RootShardPhase = "Running"
RootShardPhaseDeleting RootShardPhase = "Deleting"
)

type RootShardConditionType string

const (
RootShardConditionTypeAvailable RootShardConditionType = "Available"
)

// +kubebuilder:object:root=true
// +kubebuilder:subresource:status
// +kubebuilder:printcolumn:JSONPath=".spec.external.hostname",name="Hostname",type="string"
// +kubebuilder:printcolumn:JSONPath=".status.phase",name="Phase",type="string"
// +kubebuilder:printcolumn:JSONPath=".metadata.creationTimestamp",name="Age",type="date"

// RootShard is the Schema for the kcpinstances API
type RootShard struct {
Expand Down
2 changes: 1 addition & 1 deletion api/v1alpha1/zz_generated.deepcopy.go

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

37 changes: 4 additions & 33 deletions config/crd/bases/operator.kcp.io_frontproxies.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -98,44 +98,15 @@ spec:
ref:
description: Reference references a local RootShard object.
properties:
apiVersion:
description: API version of the referent.
type: string
fieldPath:
description: |-
If referring to a piece of an object instead of an entire object, this string
should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2].
For example, if the object reference is to a container within a pod, this would take on a value like:
"spec.containers{name}" (where "name" refers to the name of the container that triggered
the event) or if no container name is specified "spec.containers[2]" (container with
index 2 in this pod). This syntax is chosen only to have some well-defined way of
referencing a part of an object.
type: string
kind:
description: |-
Kind of the referent.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
type: string
name:
default: ""
description: |-
Name of the referent.
This field is effectively required, but due to backwards compatibility is
allowed to be empty. Instances of this type with an empty value here are
almost certainly wrong.
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
type: string
namespace:
description: |-
Namespace of the referent.
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/
type: string
resourceVersion:
description: |-
Specific resourceVersion to which this reference is made, if any.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency
type: string
uid:
description: |-
UID of the referent.
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids
type: string
type: object
x-kubernetes-map-type: atomic
type: object
Expand Down
15 changes: 14 additions & 1 deletion config/crd/bases/operator.kcp.io_rootshards.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,17 @@ spec:
singular: rootshard
scope: Namespaced
versions:
- name: v1alpha1
- additionalPrinterColumns:
- jsonPath: .spec.external.hostname
name: Hostname
type: string
- jsonPath: .status.phase
name: Phase
type: string
- jsonPath: .metadata.creationTimestamp
name: Age
type: date
name: v1alpha1
schema:
openAPIV3Schema:
description: RootShard is the Schema for the kcpinstances API
Expand Down Expand Up @@ -188,6 +198,9 @@ spec:
type: object
status:
description: RootShardStatus defines the observed state of RootShard
properties:
phase:
type: string
type: object
type: object
served: true
Expand Down
37 changes: 4 additions & 33 deletions config/crd/bases/operator.kcp.io_shards.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -120,44 +120,15 @@ spec:
ref:
description: Reference references a local RootShard object.
properties:
apiVersion:
description: API version of the referent.
type: string
fieldPath:
description: |-
If referring to a piece of an object instead of an entire object, this string
should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2].
For example, if the object reference is to a container within a pod, this would take on a value like:
"spec.containers{name}" (where "name" refers to the name of the container that triggered
the event) or if no container name is specified "spec.containers[2]" (container with
index 2 in this pod). This syntax is chosen only to have some well-defined way of
referencing a part of an object.
type: string
kind:
description: |-
Kind of the referent.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
type: string
name:
default: ""
description: |-
Name of the referent.
This field is effectively required, but due to backwards compatibility is
allowed to be empty. Instances of this type with an empty value here are
almost certainly wrong.
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
type: string
namespace:
description: |-
Namespace of the referent.
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/
type: string
resourceVersion:
description: |-
Specific resourceVersion to which this reference is made, if any.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency
type: string
uid:
description: |-
UID of the referent.
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids
type: string
type: object
x-kubernetes-map-type: atomic
type: object
Expand Down
51 changes: 46 additions & 5 deletions internal/controller/rootshard_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,11 @@ import (

k8creconciling "k8c.io/reconciler/pkg/reconciling"

appsv1 "k8s.io/api/apps/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/types"
"k8s.io/utils/ptr"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/log"
Expand Down Expand Up @@ -62,9 +66,30 @@ func (r *RootShardReconciler) Reconcile(ctx context.Context, req ctrl.Request) (

var rootShard v1alpha1.RootShard
if err := r.Client.Get(ctx, req.NamespacedName, &rootShard); err != nil {
return ctrl.Result{}, fmt.Errorf("failed to find %s/%s: %w", req.Namespace, req.Name, err)
if client.IgnoreNotFound(err) != nil {
return ctrl.Result{}, fmt.Errorf("failed to find %s/%s: %w", req.Namespace, req.Name, err)
}

// Object has apparently been deleted already.
return ctrl.Result{}, nil
}

if rootShard.DeletionTimestamp != nil {
rootShard.Status.Phase = operatorkcpiov1alpha1.RootShardPhaseDeleting
if err := r.Client.Status().Update(ctx, &rootShard); err != nil {
return ctrl.Result{}, err
}
}

if rootShard.Status.Phase == "" {
rootShard.Status.Phase = operatorkcpiov1alpha1.RootShardPhaseProvisioning
if err := r.Client.Status().Update(ctx, &rootShard); err != nil {
return ctrl.Result{}, err
}
}

ownerRefWrapper := k8creconciling.OwnerRefWrapper(*metav1.NewControllerRef(&rootShard, operatorkcpiov1alpha1.GroupVersion.WithKind("RootShard")))

// Intermediate CAs that we need to generate a certificate and an issuer for.
intermediateCAs := []v1alpha1.CA{
v1alpha1.ServerCA,
Expand All @@ -91,32 +116,48 @@ func (r *RootShardReconciler) Reconcile(ctx context.Context, req ctrl.Request) (
certReconcilers = append(certReconcilers, rootshard.RootCACertificateReconciler(&rootShard))
}

if err := reconciling.ReconcileCertificates(ctx, certReconcilers, req.Namespace, r.Client); err != nil {
if err := reconciling.ReconcileCertificates(ctx, certReconcilers, req.Namespace, r.Client, ownerRefWrapper); err != nil {
return ctrl.Result{}, err
}

if err := reconciling.ReconcileIssuers(ctx, issuerReconcilers, req.Namespace, r.Client); err != nil {
if err := reconciling.ReconcileIssuers(ctx, issuerReconcilers, req.Namespace, r.Client, ownerRefWrapper); err != nil {
return ctrl.Result{}, err
}

if err := k8creconciling.ReconcileDeployments(ctx, []k8creconciling.NamedDeploymentReconcilerFactory{
rootshard.DeploymentReconciler(&rootShard),
}, req.Namespace, r.Client); err != nil {
}, req.Namespace, r.Client, ownerRefWrapper); err != nil {
return ctrl.Result{}, err
}

if err := k8creconciling.ReconcileServices(ctx, []k8creconciling.NamedServiceReconcilerFactory{
rootshard.ServiceReconciler(&rootShard),
}, req.Namespace, r.Client); err != nil {
}, req.Namespace, r.Client, ownerRefWrapper); err != nil {
return ctrl.Result{}, err
}

// check for Deployment health and update the rootShard phase if necessary.
var dep appsv1.Deployment
err := r.Client.Get(ctx, types.NamespacedName{Namespace: req.Namespace, Name: fmt.Sprintf("%s-kcp", rootShard.Name)}, &dep)
if client.IgnoreNotFound(err) != nil {
return ctrl.Result{}, err
}
if err == nil {
if rootShard.Status.Phase == operatorkcpiov1alpha1.RootShardPhaseProvisioning && dep.Status.ReadyReplicas == ptr.Deref(dep.Spec.Replicas, 0) {
rootShard.Status.Phase = operatorkcpiov1alpha1.RootShardPhaseRunning
if err := r.Client.Status().Update(ctx, &rootShard); err != nil {
return ctrl.Result{}, err
}
}
}

return ctrl.Result{}, nil
}

// SetupWithManager sets up the controller with the Manager.
func (r *RootShardReconciler) SetupWithManager(mgr ctrl.Manager) error {
return ctrl.NewControllerManagedBy(mgr).
For(&operatorkcpiov1alpha1.RootShard{}).
Owns(&appsv1.Deployment{}).
Complete(r)
}

0 comments on commit 6ffdca9

Please sign in to comment.