Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

install nginx out of band #83

Merged
merged 2 commits into from
Nov 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,5 @@ idpbuilder
bin/*
.DS_Store
cover.out
__debug*
.vscode
1 change: 1 addition & 0 deletions api/v1alpha1/localbuild_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ type LocalbuildStatus struct {

GitServerAvailable bool `json:"gitServerAvailable,omitempty"`
ArgoAvailable bool `json:"argoAvailable,omitempty"`
NginxAvailable bool `json:"nginxAvailable,omitempty"`
ArgoAppsCreated bool `json:"argoAppsCreated,omitempty"`
}

Expand Down
3 changes: 0 additions & 3 deletions pkg/apps/resources.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,6 @@ var (
}, {
Name: "crossplane",
Path: "crossplane",
}, {
Name: "nginx-ingress",
Path: "nginx-ingress",
}}
)

Expand Down
1 change: 1 addition & 0 deletions pkg/controllers/localbuild/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ func (r *LocalbuildReconciler) Reconcile(ctx context.Context, req ctrl.Request)
subReconcilers := []subReconciler{
r.ReconcileProjectNamespace,
r.ReconcileArgo,
r.ReconcileNginx,
r.ReconcileEmbeddedGitServer,
r.ReconcileArgoApps,
}
Expand Down
135 changes: 135 additions & 0 deletions pkg/controllers/localbuild/nginx.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
package localbuild
nimakaviani marked this conversation as resolved.
Show resolved Hide resolved

import (
"context"
"embed"
"errors"
"time"

"github.com/cnoe-io/idpbuilder/api/v1alpha1"
"github.com/cnoe-io/idpbuilder/pkg/k8s"
"github.com/cnoe-io/idpbuilder/pkg/util"
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/types"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
"sigs.k8s.io/controller-runtime/pkg/log"
)

const (
nginxNamespace string = "ingress-nginx"
nginxDeployment string = "ingress-nginx-controller"
)

//go:embed resources/nginx/k8s/*
var installNginxFS embed.FS
var timeout = time.After(3 * time.Minute)

func RawNginxInstallResources() ([][]byte, error) {
return util.ConvertFSToBytes(installNginxFS, "resources/nginx/k8s")
}

func NginxInstallResources(scheme *runtime.Scheme) ([]client.Object, error) {
rawResources, err := RawNginxInstallResources()
if err != nil {
return nil, err
}

return k8s.ConvertRawResourcesToObjects(scheme, rawResources)
}

func newNginxNamespace() *corev1.Namespace {
return &corev1.Namespace{
ObjectMeta: metav1.ObjectMeta{
Name: nginxNamespace,
},
}
}

func (r LocalbuildReconciler) ReconcileNginx(ctx context.Context, req ctrl.Request, resource *v1alpha1.Localbuild) (ctrl.Result, error) {
log := log.FromContext(ctx)

nginxNSClient := client.NewNamespacedClient(r.Client, nginxNamespace)
installObjs, err := NginxInstallResources(r.Scheme)
if err != nil {
return ctrl.Result{}, err
}

// Ensure namespace exists
nginxNewNS := newNginxNamespace()
if err = r.Client.Get(ctx, types.NamespacedName{Name: nginxNamespace}, nginxNewNS); err != nil {
// We got an error so try creating the NS
if err = r.Client.Create(ctx, nginxNewNS); err != nil {
return ctrl.Result{}, err
}
}

log.Info("Installing/Reconciling Nginx resources")
for _, obj := range installObjs {
if obj.GetObjectKind().GroupVersionKind().Kind == "Deployment" {
switch obj.GetName() {
case nginxDeployment:
gotObj := appsv1.Deployment{}
if err := r.Client.Get(ctx, types.NamespacedName{Namespace: obj.GetNamespace(), Name: obj.GetName()}, &gotObj); err != nil {
if err = controllerutil.SetControllerReference(resource, obj, r.Scheme); err != nil {
log.Error(err, "Setting controller reference for Nginx deployment", "deployment", obj)
return ctrl.Result{}, err
}
}
}
}

// Create object
if err = k8s.EnsureObject(ctx, nginxNSClient, obj, nginxNamespace); err != nil {
return ctrl.Result{}, err
}
}

// Wait for Nginx to become available
ready := make(chan error)
go func([]client.Object) {
for {
for _, obj := range installObjs {
if obj.GetObjectKind().GroupVersionKind().Kind == "Deployment" {
switch obj.GetName() {
case nginxDeployment:
gotObj := appsv1.Deployment{}
if err := r.Client.Get(ctx, types.NamespacedName{Namespace: obj.GetNamespace(), Name: obj.GetName()}, &gotObj); err != nil {
ready <- err
return
}

if gotObj.Status.AvailableReplicas >= 1 {
close(ready)
return
}
}
}
}
log.Info("Waiting for Nginx to become ready")
time.Sleep(30 * time.Second)
}
}(installObjs)

select {
case <-timeout:
nimakaviani marked this conversation as resolved.
Show resolved Hide resolved
err := errors.New("Timeout")
log.Error(err, "Didn't reconcile Nginx on time.")
return ctrl.Result{}, err
case err, errOccurred := <-ready:
if !errOccurred {
log.Info("Nginx is ready!")
resource.Status.NginxAvailable = true
} else {
log.Error(err, "failed to reconcile the Nginx resources")
resource.Status.NginxAvailable = false
return ctrl.Result{}, err
}
}

return ctrl.Result{}, nil
}
2 changes: 2 additions & 0 deletions pkg/controllers/resources/idpbuilder.cnoe.io_localbuilds.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ spec:
type: boolean
gitServerAvailable:
type: boolean
nginxAvailable:
type: boolean
observedGeneration:
description: ObservedGeneration is the 'Generation' of the Service
that was last processed by the controller.
Expand Down
3 changes: 3 additions & 0 deletions pkg/k8s/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,5 +36,8 @@ func EnsureObject(ctx context.Context, kubeClient client.Client, obj client.Obje
if err != nil {
return err
}

// hacky way to restore the GVK for the object after create corrupts it. didnt dig. not sure why?
nimakaviani marked this conversation as resolved.
Show resolved Hide resolved
obj.GetObjectKind().SetGroupVersionKind(curObj.GroupVersionKind())
return nil
}