Skip to content
Commits on Source (2)
......@@ -12,6 +12,8 @@ type NextcloudSpec struct {
Domain string `json:"domain,omitempty"`
//+optional
Suspend bool `json:"suspend,omitempty"`
//+required
Version string `json:"version,omitempty"`
//+optional
DefaultApps []string `json:"enabledApps,omitempty"`
//+optional
......@@ -22,6 +24,8 @@ type NextcloudSpec struct {
type NextcloudStatus struct {
//+optional
Conditions []metav1.Condition `json:"conditions,omitempty"`
//+optional
InstalledVersion string `json:"installedVersion,omitempty"`
}
// +kubebuilder:object:root=true
......
......@@ -55,6 +55,8 @@ spec:
type: array
suspend:
type: boolean
version:
type: string
type: object
status:
description: NextcloudStatus defines the observed state of Nextcloud
......@@ -127,6 +129,8 @@ spec:
- type
type: object
type: array
installedVersion:
type: string
type: object
type: object
served: true
......
......@@ -4,3 +4,4 @@ metadata:
name: nextcloud-sample
spec:
domain: nuage.dev.local
version: v230.7.2
......@@ -5,6 +5,7 @@ import (
"fmt"
"time"
semver "github.com/Masterminds/semver/v3"
certmanager "github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1"
"github.com/fluxcd/pkg/apis/meta"
"github.com/fluxcd/pkg/runtime/conditions"
......@@ -169,18 +170,18 @@ func (r *NextcloudReconciler) Reconcile(ctx context.Context, req ctrl.Request) (
_, err = ctrl.CreateOrUpdate(ctx, r.Client, &samlClient, func() error {
// samlClient.Spec.Realm = "realm-sample"
samlClient.Spec.Suspend = nextcloud.Spec.Suspend
samlClient.Spec.ClientID = fmt.Sprintf("%s/apps/user_saml/saml/metadata", nextcloud.Spec.Domain)
samlClient.Spec.ClientID = fmt.Sprintf("http://%s/apps/user_saml/saml/metadata", nextcloud.Spec.Domain)
// samlClient.Spec.Enabled =
samlClient.Spec.RedirectURIs = []string{fmt.Sprintf("%s/apps/user_saml/saml/acs", nextcloud.Spec.Domain)}
samlClient.Spec.RedirectURIs = []string{fmt.Sprintf("http://%s/apps/user_saml/saml/acs", nextcloud.Spec.Domain)}
samlClient.Spec.SigningCertificateSecretName = samlCertificate.Spec.SecretName
samlClient.Spec.AssertionSignature = true
samlClient.Spec.SingleLogoutServiceURLRedirect = fmt.Sprintf("%s/apps/user_saml/saml/sls", nextcloud.Spec.Domain)
samlClient.Spec.SingleLogoutServiceURLRedirect = fmt.Sprintf("http://%s/apps/user_saml/saml/sls", nextcloud.Spec.Domain)
samlClient.Spec.SignatureAlgorithm = "RSA_SHA256"
samlClient.Spec.ClientSignature = true
samlClient.Spec.AuthnStatement = true
samlClient.Spec.AssertionConsumerURLPost = fmt.Sprintf("%s/apps/user_saml/saml/acs", nextcloud.Spec.Domain)
samlClient.Spec.AssertionConsumerURLPost = fmt.Sprintf("http://%s/apps/user_saml/saml/acs", nextcloud.Spec.Domain)
// TODO
samlClient.Spec.SingleLogoutServiceURLPost = fmt.Sprintf("https://%s", nextcloud.Spec.Domain)
samlClient.Spec.SingleLogoutServiceURLPost = fmt.Sprintf("http://%s", nextcloud.Spec.Domain)
samlClient.Spec.NameIDFormat = "username"
samlClient.Spec.ServerSignature = true
samlClient.Spec.ServerSignatureKeyInfoExt = false
......@@ -306,6 +307,7 @@ func (r *NextcloudReconciler) Reconcile(ctx context.Context, req ctrl.Request) (
"SAML_IDP_URL": "https://id.indie.host",
"SAML_DISPLAY_NAME": "LiiibreSSO",
"OVERWRITEPROTOCOL": "http",
// "CHAT_URL": "https://${CHAT_SUBDOMAIN}.${DOMAIN}",
}
cm.Data = data
......@@ -322,35 +324,42 @@ func (r *NextcloudReconciler) Reconcile(ctx context.Context, req ctrl.Request) (
return
}
var job batchv1.Job
job.SetName(fmt.Sprintf("%s-install", nextcloud.Name))
job.SetNamespace(nextcloud.Namespace)
err = r.Get(ctx, client.ObjectKeyFromObject(&job), &job)
if err != nil {
if !errors.IsNotFound(err) {
return
}
err = r.mutateJob(&nextcloud, &job)
if nextcloud.Status.InstalledVersion == "" {
var job batchv1.Job
job.SetName(fmt.Sprintf("%s-install", nextcloud.Name))
job.SetNamespace(nextcloud.Namespace)
err = r.Get(ctx, client.ObjectKeyFromObject(&job), &job)
if err != nil {
if !errors.IsNotFound(err) {
return
}
err = r.mutateJob(&nextcloud, &job)
if err != nil {
return
}
err = r.Create(ctx, &job)
if err != nil {
return
}
}
if r.isJobConditionTrue(&job.Status, batchv1.JobFailed) {
conditions.MarkTrue(&nextcloud, "NotInstalled", "JobFailed", "Failed to installl")
conditions.MarkStalled(&nextcloud, "InstallJobFailed", "Failed to install")
return
} else if stalled := conditions.Get(&nextcloud, meta.StalledCondition); stalled != nil && stalled.Reason == "InstallJobFailed" {
conditions.Delete(&nextcloud, meta.StalledCondition)
}
err = r.Create(ctx, &job)
if err != nil {
if job.Status.CompletionTime == nil {
conditions.MarkTrue(&nextcloud, "NotInstalled", "JobNotCompleted", "Waiting for install job to complete")
return
} else {
conditions.Delete(&nextcloud, "NotInstalled")
}
nextcloud.Status.InstalledVersion = nextcloud.Spec.Version
}
if r.isJobConditionTrue(&job.Status, batchv1.JobFailed) {
conditions.MarkTrue(&nextcloud, "NotInstalled", "JobFailed", "Failed to installl")
conditions.MarkStalled(&nextcloud, "InstallJobFailed", "Failed to install")
return
} else if stalled := conditions.Get(&nextcloud, meta.StalledCondition); stalled != nil && stalled.Reason == "InstallJobFailed" {
conditions.Delete(&nextcloud, meta.StalledCondition)
}
if job.Status.CompletionTime == nil {
conditions.MarkTrue(&nextcloud, "NotInstalled", "JobNotCompleted", "Waiting for install job to complete")
return
} else {
conditions.Delete(&nextcloud, "NotInstalled")
if nextcloudShouldUpgrade(&nextcloud) {
}
var deployment appsv1.Deployment
......@@ -375,7 +384,7 @@ func (r *NextcloudReconciler) Reconcile(ctx context.Context, req ctrl.Request) (
}
appContainer := corev1.Container{
Image: NextcloudImage,
Image: getNextcloudImage(&nextcloud),
Name: "app",
Ports: []corev1.ContainerPort{
{
......@@ -446,7 +455,7 @@ func (r *NextcloudReconciler) Reconcile(ctx context.Context, req ctrl.Request) (
appContainer.Env = envVars
webContainer := corev1.Container{
Image: NextcloudWebImage,
Image: getNextcloudWebImage(&nextcloud),
Name: "web",
Ports: []corev1.ContainerPort{
{
......@@ -844,7 +853,7 @@ func (r *NextcloudReconciler) getEnvVars(nextcloud *appsv1alpha1.Nextcloud) []co
ValueFrom: &corev1.EnvVarSource{
SecretKeyRef: &corev1.SecretKeySelector{
LocalObjectReference: corev1.LocalObjectReference{
Name: samlclientCert,
Name: samlclient,
},
Key: "tls.crt",
},
......@@ -871,7 +880,7 @@ func (r *NextcloudReconciler) getEnvVars(nextcloud *appsv1alpha1.Nextcloud) []co
},
{
Name: "VERSION",
Value: NextcloudFullVersion,
Value: getNextcloudFullversion(nextcloud),
},
}
}
......@@ -890,7 +899,7 @@ func (r *NextcloudReconciler) isJobConditionTrue(status *batchv1.JobStatus, cond
func (r *NextcloudReconciler) mutateJob(nextcloud *appsv1alpha1.Nextcloud, job *batchv1.Job) error {
container := corev1.Container{
Image: NextcloudImage,
Image: getNextcloudImage(nextcloud),
Command: []string{"/install.sh"},
Name: "install",
......@@ -925,3 +934,29 @@ func (r *NextcloudReconciler) mutateJob(nextcloud *appsv1alpha1.Nextcloud, job *
return controllerutil.SetControllerReference(nextcloud, job, r.Scheme)
}
func getNextcloudImage(nextcloud *appsv1alpha1.Nextcloud) string {
return fmt.Sprintf("hougo13/nextcloud:%s", nextcloud.Spec.Version)
}
func getNextcloudWebImage(nextcloud *appsv1alpha1.Nextcloud) string {
return fmt.Sprintf("hougo13/nextcloud-web:%s", nextcloud.Spec.Version)
}
func getNextcloudFullversion(nextcloud *appsv1alpha1.Nextcloud) string {
version := nextcloud.Status.InstalledVersion
if version == "" {
version = nextcloud.Spec.Version
}
v, _ := semver.NewVersion(version)
return fmt.Sprintf("%d.%d.%d.%d", v.Major()/10, v.Major()%10, v.Minor(), v.Patch())
}
func nextcloudShouldUpgrade(nextcloud *appsv1alpha1.Nextcloud) bool {
if nextcloud.Status.InstalledVersion == "" || nextcloud.Spec.Version == "" {
return false
}
installedV, _ := semver.NewVersion(nextcloud.Status.InstalledVersion)
v, _ := semver.NewVersion(nextcloud.Spec.Version)
return v.GreaterThan(installedV)
}
......@@ -3,6 +3,7 @@ module libre.sh/controller
go 1.18
require (
github.com/Masterminds/semver/v3 v3.1.1
github.com/Nerzal/gocloak/v11 v11.2.0
github.com/cert-manager/cert-manager v1.9.1
github.com/fluxcd/pkg/apis/meta v0.14.2
......