How to write an extendable Kubernetes operator

My company have won an open source project that involves creation of a Kubernetes operator to manage user workspaces for a web platform. We have an existing operator for another project that does the job, but it contains some project IP. I have been tasked to refactor out the generic functionality into a core package, and structure the module so that it is extendable. We are using Kubebuilder framework to create the operator. It’s also worth mentioning that, although I am an experienced software engineer, I am new to Go.

I have scaffolded the core project using Kubebuilder. I added the workspace API and everything works as expected. The functionality just now is minimal, when a workspace resource is created the API will create a namespace with the same name as the workspace resource. Key excerpts below:

# steps to scaffold project
kubebuilder init --domain my.domain --owner "My Org"
kubebuilder create api --group core --kind Workspace --version v1alpha1
// (core) api/v1alpha1/workspace_types.go
...
type WorkspaceSpec struct {}  // no functionality required yet

type WorkspaceStatus struct {
    // The name of the namespace for the workspace
    Namespace string `json:"namespace,omitempty"`
} // added namespace field to status

type Workspace struct {
    metav1.TypeMeta   `json:",inline"`
    metav1.ObjectMeta `json:"metadata,omitempty"`

    Spec   WorkspaceSpec   `json:"spec,omitempty"`
    Status WorkspaceStatus `json:"status,omitempty"`
} // boilerplate, unchanged from scaffolding

type WorkspaceList struct {
    metav1.TypeMeta `json:",inline"`
    metav1.ListMeta `json:"metadata,omitempty"`
    Items           []Workspace `json:"items"`
} // boilerplate, unchanged from scaffolding
// (core) controller/workspace_controller.go
...
type WorkspaceReconciler struct {
    client.Client
    Scheme *runtime.Scheme
}

func (r *WorkspaceReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
    // Get a reference to the workspace that has been updated
    workspace := &corev1alpha1.Workspace{}
    if err := r.Get(ctx, req.NamespacedName, workspace); err != nil {
        return ctrl.Result{}, client.IgnoreNotFound(err)
    }

    // my reconciliation logic

    return ctrl.Result{}, nil
}

Note that I removed the workspace_controller module from the internal directory created during the scaffolding as I want to make it importable in isolation by the extending project.

Now, my design is to allow a user to scaffold their own Kubebuilder project and reuse and extend the functionality provided by the core module.

Project is scaffolded similarly to above, but with different domain and group. I embedded the structs that define the API in the newly scaffolded API.

// (extension) api/v1alpha1/workspace_types.go
...
import (
    ...
    corev1alpha1 "github.com/MyOrg/workspace-controller/api/v1alpha1"
)
...
type WorkspaceSpec struct {
    corev1alpha1.WorkspaceSpec `json:",inline"`
} // embedded core spec

type WorkspaceStatus struct {
    corev1alpha1.WorkspaceStatus `json:",inline"`
} // embedded core status

type Workspace struct {
    metav1.TypeMeta   `json:",inline"`
    metav1.ObjectMeta `json:"metadata,omitempty"`

    Spec   WorkspaceSpec   `json:"spec,omitempty"`
    Status WorkspaceStatus `json:"status,omitempty"`
} // unmodified, so there is no link between core Workspace struct and ext Workspace struct

type WorkspaceList struct {
    metav1.TypeMeta `json:",inline"`
    metav1.ListMeta `json:"metadata,omitempty"`
    Items           []Workspace `json:"items"`
} // unmodified

So far so good, I can generate the CRDs with make manifests and the code runs. The issue I have is reusing the reconciliation logic in the core. In the controller/workspace_controller.go above, the type in the Reconcile method is hardcoded, and will differ from the extension type. When I try and call the core Reconcile from the extension Reconcile then it does not find any resources, which I understand since I hardcoded the core Workspace struct type.

// (extension) controller/workspace_controller.go
import (
    ...
    corecontroller "github.com/MyOrg/workspace-controller/controller"
)
...
type WorkspaceReconciler struct {
    corecontroller.WorkspaceReconciler
}

func (r *WorkspaceReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
    // Get a reference to the workspace that has been updated
    workspace := &corev1alpha1.Workspace{}
    if err := r.Get(ctx, req.NamespacedName, workspace); err != nil {
        return ctrl.Result{}, client.IgnoreNotFound(err)
    }  // this call finds the extension resource

    // call embedded core Reconciler
    r.WorkspaceReconciler.Reconcile(ctx, req)  // becomes a no-op because workspace resource not found, which is understandable

    return ctrl.Result{}, nil
}

So, my question is, how do other extendable Kubebuilder APIs deal with this issue? Is there something I have missed? Or can I use any features of Go that I haven’t thought of, such as reflection, to infer the type of resource I am looking for from the Reconciler or any other available variables so that when using the core module I get core.Workspace and when using the extension module I get extension.Workspace?

Is anyone aware of any extendable Kubebuilder API open source projects that I can reference to see how they do it?

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật