Skip to content

Commit

Permalink
migration #3
Browse files Browse the repository at this point in the history
  • Loading branch information
m00g3n committed Mar 23, 2020
1 parent 0efa6fd commit 82f76fc
Show file tree
Hide file tree
Showing 7 changed files with 417 additions and 38 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -93,20 +93,22 @@ func (fn Function) ConditionReasonUpdateServiceSucceeded(msg string) *FunctionSt
return &FunctionStatus{
Phase: FunctionPhaseDeploying,
ObservedGeneration: fn.GetGeneration(),
ImageTag: fn.Status.ImageTag,
Conditions: append(fn.Status.Conditions, condition),
}
}

//TODO fix this
func (fn Function) FunctionPhaseDeploying(reason ConditionReason, msg string) *FunctionStatus {
condition := Condition{
Type: ConditionTypeError,
Type: ConditionTypeDeploying,
Reason: reason,
Message: msg,
}
return &FunctionStatus{
Phase: FunctionPhaseDeploying,
ObservedGeneration: fn.GetGeneration(),
ImageTag: fn.Status.ImageTag,
Conditions: append(fn.Status.Conditions, condition),
}
}
Expand Down Expand Up @@ -144,6 +146,7 @@ func (fn Function) ConditionReasonBuildSucceede() *FunctionStatus {
return &FunctionStatus{
Phase: FunctionPhaseDeploying,
ObservedGeneration: fn.GetGeneration(),
ImageTag: fn.Status.ImageTag,
Conditions: append(fn.Status.Conditions, condition),
}
}
Expand All @@ -152,18 +155,19 @@ func (fn Function) ConditionReasonBuildRunning() *FunctionStatus {
return &FunctionStatus{
Phase: FunctionPhaseBuilding,
ObservedGeneration: fn.GetGeneration(),
ImageTag: fn.Status.ImageTag,
Conditions: fn.Status.Conditions,
}
}

func (fn Function) ConditionReasonUpdateRuntimeConfig(imageTag string) *FunctionStatus {
func (fn Function) ConditionReasonUpdateRuntimeConfig() *FunctionStatus {
condition := Condition{
Type: ConditionTypeInitialized,
Reason: ConditionReasonUpdateRuntimeConfig,
}
return &FunctionStatus{
Phase: FunctionPhaseBuilding,
ImageTag: imageTag,
ImageTag: fn.Status.ImageTag,
ObservedGeneration: fn.GetGeneration(),
Conditions: append(fn.Status.Conditions, condition),
}
Expand Down
48 changes: 33 additions & 15 deletions components/function-controller/pkg/controllers/function/function.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ var (
Value: tektonDockerVolume,
},
}
containerName = "lambda"
)

// Add creates a new Function Controller and adds it to the Manager with default RBAC. The Manager will set fields on the Controller
Expand Down Expand Up @@ -302,7 +303,7 @@ func (r *ReconcileFunction) handleInitializingUpdateFunction(
// the changes do not have impact on docker image;
// the lambda must be redeployed but the tusk run may
// still be building;
return fn.ConditionReasonUpdateRuntimeConfig(imageTag)
return fn.ConditionReasonUpdateRuntimeConfig()
}

// update function config map
Expand Down Expand Up @@ -409,29 +410,35 @@ func (r *ReconcileFunction) handleDeploying(
ctx context.Context,
fn *serverless.Function) *serverless.FunctionStatus {

var svc *servingv1.Service
err := r.svcHelper.Fetch(ctx, fn.LabelSelector(), svc)

svc, err := r.svcHelper.Fetch(ctx, fn.LabelSelector())
if err != nil {
return fn.FunctionPhaseFailed(
serverless.ConditionReasonDeployFailed,
err.Error())
return fn.FunctionPhaseFailed(serverless.ConditionReasonDeployFailed, err.Error())
}

// create new knative serving
if svc == nil {
imgName := r.regHelper.ServiceImageName(
fn.Name, fn.Namespace,
fn.Status.ImageTag)
imgName := r.regHelper.ServiceImageName(fn.Name, fn.Namespace, fn.Status.ImageTag)
//TODO unit test image name creation
return r.handleDeployingNewService(ctx, fn, imgName)
}

// check if image tag matches function image tag
shoudlUpdateServing, err := shouldUpdateServing(svc, fn.Spec.Env, fn.Status.ImageTag)
if err != nil {
return fn.FunctionPhaseFailed(serverless.ConditionReasonDeployFailed, err.Error())
}

if shoudlUpdateServing {
//TODO update serving
}

if isServiceRunning(svc) {
return r.handleDeployingUpdateService(ctx, fn, svc)
}

// service failed -
return fn.FunctionPhaseDeploying(serverless.ConditionReasonDeployFailed, "failed to deploy knative service")
return fn.FunctionPhaseDeploying(
serverless.ConditionReasonDeployFailed,
"failed to deploy knative service")
}

type createSvc = func(context.Context, *servingv1.Service) error
Expand All @@ -447,14 +454,25 @@ func (r *ReconcileFunction) handleDeployingNewService(
r.rtHelper.ServiceAccount(),
fn.Spec.Env...,
)
svc := newService(fn.Name, fn.Namespace, podSpec, fn.Labels)

if err := r.svcHelper.Create(ctx, svc); err != nil {
return fn.FunctionPhaseFailed(
//TODO refactor this later on consider investigating labels package
labels := make(map[string]string, len(fn.Labels)+2)
for k, v := range fn.Labels {
labels[k] = v
}
labels["fnUUID"] = string(fn.UID)
labels["imageTag"] = fn.Status.ImageTag

svc := newService(fn.Name, fn.Namespace, podSpec, labels)

err := r.svcHelper.Create(ctx, svc)
if err != nil {
fn.FunctionPhaseFailed(
serverless.ConditionReasonDeployFailed,
err.Error(),
)
}

return fn.FunctionPhaseDeploying(
serverless.ConditionReasonCreateServiceSucceeded,
"",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
"k8s.io/client-go/kubernetes/scheme"
"k8s.io/client-go/rest"
"knative.dev/pkg/apis"
servingv1 "knative.dev/serving/pkg/apis/serving/v1"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/cache"
"sigs.k8s.io/controller-runtime/pkg/client"
Expand All @@ -26,16 +27,15 @@ import (
type add2Schme = func(*runtime.Scheme) error

func startAsync(mgr manager.Manager, stop chan struct{}) {
go func() {
mgr.Start(stop)
}()
go mgr.Start(stop)
}

func addToScheme() error {
// prepare scheme
for _, addToScheme := range []add2Schme{
serverless.AddToScheme,
tektonv1alpha1.AddToScheme,
servingv1.AddToScheme,
} {
err := addToScheme(scheme.Scheme)
if err != nil {
Expand Down Expand Up @@ -128,6 +128,31 @@ func TestReconcile(t *testing.T) {
// changes do not require image rebuild
fn.Spec.Timeout = 123

err = mgr.GetClient().Update(ctx, &fn)
g.Expect(err).ToNot(HaveOccurred())

_, err = reconciler.Reconcile(req)
g.Expect(err).ShouldNot(HaveOccurred())

err = mgr.GetClient().Get(ctx, req.NamespacedName, &fn)
g.Expect(err).ShouldNot(HaveOccurred())

g.Expect(fn.Status.Phase).To(Equal(serverless.FunctionPhaseInitializing))

_, err = reconciler.Reconcile(req)
g.Expect(err).ShouldNot(HaveOccurred())

err = mgr.GetClient().Get(ctx, req.NamespacedName, &fn)
g.Expect(err).ShouldNot(HaveOccurred())

g.Expect(fn.Status.Phase).To(Equal(serverless.FunctionPhaseBuilding))

g.Expect(mgr.GetClient().List(ctx, &tr, &client.ListOptions{
LabelSelector: fn.ImgLabelSelector(),
})).ShouldNot(gomega.HaveOccurred())

g.Expect(len(tr.Items)).To(gomega.Equal(1))

// changes require image rebuild
fn.Spec.Function = "function"

Expand All @@ -140,6 +165,8 @@ func TestReconcile(t *testing.T) {
err = mgr.GetClient().Get(ctx, req.NamespacedName, &fn)
g.Expect(err).ShouldNot(HaveOccurred())

g.Expect(fn.Status.Phase).To(Equal(serverless.FunctionPhaseInitializing))

_, err = reconciler.Reconcile(req)
g.Expect(err).ShouldNot(HaveOccurred())

Expand All @@ -154,9 +181,20 @@ func TestReconcile(t *testing.T) {

g.Expect(len(tr.Items)).To(gomega.Equal(1))

// fake task run continue running
_, err = reconciler.Reconcile(req)
g.Expect(err).ShouldNot(HaveOccurred())

err = mgr.GetClient().Get(ctx, req.NamespacedName, &fn)
g.Expect(err).ShouldNot(HaveOccurred())

g.Expect(fn.Status.Phase).To(Equal(serverless.FunctionPhaseBuilding))

// fake task run is finish
tr.Items[0].Status.Conditions = append(tr.Items[0].Status.Conditions, apis.Condition{
Type: apis.ConditionSucceeded,
})

err = mgr.GetClient().Status().Update(ctx, &tr.Items[0])
g.Expect(err).ShouldNot(gomega.HaveOccurred())

Expand All @@ -165,4 +203,54 @@ func TestReconcile(t *testing.T) {

err = mgr.GetClient().Get(ctx, req.NamespacedName, &fn)
g.Expect(err).ShouldNot(HaveOccurred())

// check if function is in the deploy phase
g.Expect(fn.Status.Phase).To(Equal(serverless.FunctionPhaseDeploying))

// check image tag
g.Expect(fn.Status.ImageTag).ShouldNot(BeEmpty())

// function should enter deploying phase
_, err = reconciler.Reconcile(req)
g.Expect(err).ShouldNot(HaveOccurred())

err = mgr.GetClient().Get(ctx, req.NamespacedName, &fn)
g.Expect(err).ShouldNot(HaveOccurred())

// check if function is in the deploy phase
g.Expect(fn.Status.Phase).To(Equal(serverless.FunctionPhaseDeploying))

// check image tag
g.Expect(fn.Status.ImageTag).ShouldNot(BeEmpty())

//TODO give one more round later on

var svcl servingv1.ServiceList
err = mgr.GetClient().List(ctx, &svcl, &client.ListOptions{
LabelSelector: fn.LabelSelector(),
})
g.Expect(err).ShouldNot(HaveOccurred())
g.Expect(svcl.Items).Should(HaveLen(1))

// check image label
g.Expect(svcl.Items[0].Labels).Should(HaveKey("imageTag"))
g.Expect(svcl.Items[0].Labels["imageTag"]).ShouldNot(BeEmpty())

// fake update serving to trigger deployment finish
svcl.Items[0].Status.Conditions = append(svcl.Items[0].Status.Conditions, apis.Condition{
Type: apis.ConditionSucceeded,
})
err = mgr.GetClient().Status().Update(ctx, &svcl.Items[0])
g.Expect(err).ShouldNot(HaveOccurred())

_, err = reconciler.Reconcile(req)
g.Expect(err).ShouldNot(HaveOccurred())

err = mgr.GetClient().Get(ctx, req.NamespacedName, &fn)
g.Expect(err).ShouldNot(HaveOccurred())

// check image tag
g.Expect(fn.Status.ImageTag).ShouldNot(BeEmpty())

g.Expect(fn.Status.Phase).Should(Equal(serverless.FunctionPhaseRunning))
}
Loading

0 comments on commit 82f76fc

Please sign in to comment.