Skip to content

Commit

Permalink
feat(app): impl part of app controller (#322)
Browse files Browse the repository at this point in the history
  • Loading branch information
maslow authored Sep 17, 2022
1 parent f105553 commit 00e434d
Show file tree
Hide file tree
Showing 6 changed files with 172 additions and 79 deletions.
24 changes: 12 additions & 12 deletions controllers/application/api/v1/application_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ limitations under the License.
package v1

import (
v1 "github.com/labring/laf/controllers/runtime/api/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
runtimev1 "laf/controllers/runtime/api/v1"
)

// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN!
Expand All @@ -41,6 +41,12 @@ type ApplicationSpec struct {
// INSERT ADDITIONAL SPEC FIELDS - desired state of cluster
// Important: Run "make" to regenerate code after modifying this file

// AppId
//+kubebuilder:validation:MinLength=3
//+kubebuilder:validation:MaxLength=24
//+kubebuilder:validation:Required
AppId string `json:"appid"`

// State of the application
//+kubebuilder:validation:Enum=Running;Stopped;
//+kubebuilder:validation:Required
Expand All @@ -61,20 +67,14 @@ type ApplicationStatus struct {
// INSERT ADDITIONAL STATUS FIELD - define observed state of cluster
// Important: Run "make" to regenerate code after modifying this file

// AppId
//+kubebuilder:validation:MinLength=3
//+kubebuilder:validation:MaxLength=24
//+kubebuilder:validation:Required
AppId string `json:"appid"`

// State of the application
Phase ApplicationState `json:"state,omitempty"`

// Bundle of the application
Bundle BundleSpec `json:"bundle,omitempty"`
Bundle Bundle `json:"bundle,omitempty"`

// Runtime of the application
Runtime v1.RuntimeSpec `json:"runtime,omitempty"`
Runtime runtimev1.Runtime `json:"runtime,omitempty"`

// State of the application
Phase ApplicationState `json:"state,omitempty"`

// Conditions:
// - type: DatabaseCreated
Expand Down
124 changes: 122 additions & 2 deletions controllers/application/controllers/application_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,16 @@ package controllers

import (
"context"
runtimev1 "laf/controllers/runtime/api/v1"
"laf/pkg/common"
"laf/pkg/util"

"k8s.io/apimachinery/pkg/runtime"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/log"

applicationv1 "github.com/labring/laf/controllers/application/api/v1"
applicationv1 "laf/controllers/application/api/v1"
)

const ApplicationFinalizer = "application.finalizers.laf.dev"
Expand All @@ -51,7 +54,124 @@ type ApplicationReconciler struct {
func (r *ApplicationReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
_ = log.FromContext(ctx)

// TODO(user): your logic here
// get the application
application := &applicationv1.Application{}
err := r.Get(ctx, req.NamespacedName, application)
if err != nil {
return ctrl.Result{}, client.IgnoreNotFound(err)
}

// deal with the deletion
if !application.ObjectMeta.DeletionTimestamp.IsZero() {
return r.delete(ctx, application)
}

return r.apply(ctx, application)
}

// apply is called when the application is created or updated
func (r *ApplicationReconciler) apply(ctx context.Context, application *applicationv1.Application) (ctrl.Result, error) {
_log := log.FromContext(ctx)

// check if the finalizer is present
if !util.ContainsString(application.ObjectMeta.Finalizers, ApplicationFinalizer) {
application.ObjectMeta.Finalizers = append(application.ObjectMeta.Finalizers, ApplicationFinalizer)
err := r.Update(ctx, application)
if err != nil {
return ctrl.Result{}, err
}

_log.Info("finalizer added")
}

// reconcile runtime
if application.Status.Runtime.Name != application.Spec.RuntimeName {
err := r.reconcileRuntime(ctx, application)
if err != nil {
return ctrl.Result{}, err
}
_log.Info("runtime reconciled")
return ctrl.Result{}, nil
}

// reconcile bundle
if application.Status.Bundle.Name != application.Spec.BundleName {
if err := r.reconcileBundle(ctx, application); err != nil {
return ctrl.Result{}, err
}
_log.Info("bundle reconciled")
return ctrl.Result{}, nil
}

// reconcile phase of application
if application.Status.Phase != application.Spec.State {
if err := r.reconcilePhase(ctx, application); err != nil {
return ctrl.Result{}, err
}
_log.Info("phase reconciled")
return ctrl.Result{}, nil
}

return ctrl.Result{}, nil
}

// reconcilePhase reconciles the phase of the application
func (r *ApplicationReconciler) reconcilePhase(ctx context.Context, application *applicationv1.Application) error {
// TODO

return nil
}

// reconcileRuntime reconciles the runtime of the application
func (r *ApplicationReconciler) reconcileRuntime(ctx context.Context, application *applicationv1.Application) error {
// get runtime by name
rt := &runtimev1.Runtime{}
err := r.Get(ctx, client.ObjectKey{
Namespace: common.GetSystemNamespace(),
Name: application.Spec.RuntimeName,
}, rt)
if err != nil {
return err
}

// update the status
application.Status.Runtime = *rt
err = r.Status().Update(ctx, application)
return err
}

// reconcileBundle reconciles the bundle of the application
func (r *ApplicationReconciler) reconcileBundle(ctx context.Context, application *applicationv1.Application) error {
// get bundle by name
bundle := &applicationv1.Bundle{}
err := r.Get(ctx, client.ObjectKey{
Namespace: common.GetSystemNamespace(),
Name: application.Spec.BundleName,
}, bundle)
if err != nil {
return err
}

// update the status
application.Status.Bundle = *bundle
err = r.Status().Update(ctx, application)
return err
}

// delete is called when the application is deleted
func (r *ApplicationReconciler) delete(ctx context.Context, application *applicationv1.Application) (ctrl.Result, error) {

// TODO: delete the application
if true {
return ctrl.Result{}, nil
}

// remove the finalizer
application.ObjectMeta.Finalizers = util.RemoveString(application.ObjectMeta.Finalizers, ApplicationFinalizer)
err := r.Update(ctx, application)
if err != nil {
return ctrl.Result{}, err
}

return ctrl.Result{}, nil
}
Expand Down
51 changes: 13 additions & 38 deletions controllers/application/controllers/creationform_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,13 @@ package controllers
import (
"context"
applicationv1 "github.com/labring/laf/controllers/application/api/v1"
gonanoid "github.com/matoous/go-nanoid/v2"
v1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/runtime"
"laf/pkg/common"
"laf/pkg/util"
"os"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/log"
"strconv"
)

const creationFormFinalizer = "creationform.finalizers.laf.dev"
Expand Down Expand Up @@ -70,7 +68,7 @@ func (r *CreationFormReconciler) Reconcile(ctx context.Context, req ctrl.Request

// apply the form
func (r *CreationFormReconciler) apply(ctx context.Context, form *applicationv1.CreationForm) (ctrl.Result, error) {
log := log.FromContext(ctx)
_log := log.FromContext(ctx)

// add finalizer if not present
if !util.ContainsString(form.ObjectMeta.Finalizers, creationFormFinalizer) {
Expand All @@ -79,21 +77,22 @@ func (r *CreationFormReconciler) apply(ctx context.Context, form *applicationv1.
return ctrl.Result{}, err
}

log.Info("Added finalizer to form")
_log.Info("Added finalizer to form")
return ctrl.Result{}, nil
}

// TODO: validate the form spec: bundle, runtime

// reconcile the namespace
if form.Status.Namespace == "" {
appid, err := GenerateAppId()
appid, err := common.GenerateAppId()
if err != nil {
return ctrl.Result{}, err
}

// create the namespace
var namespace v1.Namespace
namespace.Name = GetAppNamespacePrefix() + appid
namespace.Name = common.GetApplicationNamespace(appid)
namespace.Labels = map[string]string{
"laf.dev/appid": appid,
"laf.dev/namespace.type": "app",
Expand All @@ -103,7 +102,7 @@ func (r *CreationFormReconciler) apply(ctx context.Context, form *applicationv1.
return ctrl.Result{}, err
}

log.Info("Created namespace for app")
_log.Info("Created namespace for app")

form.Status.AppId = appid
form.Status.Namespace = namespace.Name
Expand All @@ -112,7 +111,7 @@ func (r *CreationFormReconciler) apply(ctx context.Context, form *applicationv1.
return ctrl.Result{}, err
}

log.Info("Updated form status: fill the namespace")
_log.Info("Updated form status: fill the namespace")
return ctrl.Result{}, nil
}

Expand All @@ -128,6 +127,8 @@ func (r *CreationFormReconciler) apply(ctx context.Context, form *applicationv1.
app.Annotations = map[string]string{
"laf.dev/name": form.Spec.DisplayName,
}

app.Spec.AppId = form.Status.AppId
app.Spec.State = applicationv1.ApplicationStateRunning
app.Spec.BundleName = form.Spec.BundleName
app.Spec.RuntimeName = form.Spec.RuntimeName
Expand All @@ -136,21 +137,21 @@ func (r *CreationFormReconciler) apply(ctx context.Context, form *applicationv1.
return ctrl.Result{}, err
}

log.Info("Created app")
_log.Info("Created app")

form.Status.Created = true
if err := r.Status().Update(ctx, form); err != nil {
return ctrl.Result{}, err
}

log.Info("Updated form status")
_log.Info("Updated form status")
} else {
// delete the form
if err := r.Delete(ctx, form); err != nil {
return ctrl.Result{}, err
}

log.Info("Deleted form")
_log.Info("Deleted form")
}

return ctrl.Result{}, nil
Expand All @@ -176,29 +177,3 @@ func (r *CreationFormReconciler) SetupWithManager(mgr ctrl.Manager) error {
For(&applicationv1.CreationForm{}).
Complete(r)
}

// GetAppNamespacePrefix returns the app namespace prefix
func GetAppNamespacePrefix() string {
prefix := ""
if prefixStr := os.Getenv("APP_NAMESPACE_PREFIX"); prefixStr != "" {
prefix = prefixStr
}
return prefix
}

// GenerateAppId generates app id
func GenerateAppId() (string, error) {
const alphabet = "23456789abcdefghijklmnopqrstuvwxyz"
size := 6

// get size from env
if sizeStr := os.Getenv("APPID_LENGTH"); sizeStr != "" {
int64, err := strconv.ParseInt(sizeStr, 10, 64)
if err == nil {
size = int(int64)
}
}

appid, err := gonanoid.Generate(alphabet, size)
return appid, err
}
Loading

0 comments on commit 00e434d

Please sign in to comment.