Skip to content

Commit

Permalink
Merge pull request #210 from vshn/add/nextcloud_backups
Browse files Browse the repository at this point in the history
Add backups for nextcloud
  • Loading branch information
Kidswiss authored Aug 5, 2024
2 parents fabdc9c + d358573 commit 0c9e131
Show file tree
Hide file tree
Showing 8 changed files with 131 additions and 51 deletions.
17 changes: 17 additions & 0 deletions pkg/comp-functions/functions/common/backup/backup.go
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,7 @@ func AddPodAnnotationToValues(valueMap map[string]any, scriptName, fileExt strin

// AddBackupCMToValues adds the volume mount for the given configMap to the helm values.
// volumePath and mountPath specify the value path within the values map.
// It will mount the configmap under /scripts in the pod.
func AddBackupCMToValues(values map[string]any, volumePath []string, mountPath []string) error {
volumes := []interface{}{
corev1.Volume{
Expand Down Expand Up @@ -248,3 +249,19 @@ func AddBackupCMToValues(values map[string]any, volumePath []string, mountPath [

return nil
}

// AddBackupScriptCM will add a configmap containing the given script.
// This can then be used to mount into the resulting pod by whatever means applicable (helm values, pod-definition, etc)
func AddBackupScriptCM(svc *runtime.ServiceRuntime, comp common.Composite, script string) error {
cm := &corev1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Name: "backup-script",
Namespace: comp.GetInstanceNamespace(),
},
Data: map[string]string{
"backup.sh": script,
},
}

return svc.SetDesiredKubeObject(cm, comp.GetName()+"-backup-script")
}
4 changes: 3 additions & 1 deletion pkg/comp-functions/functions/common/postgresql.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
package common

import (
"dario.cat/mergo"
"encoding/json"

"dario.cat/mergo"
xpv1 "github.com/crossplane/crossplane-runtime/apis/common/v1"
sgv1 "github.com/vshn/appcat/v4/apis/stackgres/v1"
vshnv1 "github.com/vshn/appcat/v4/apis/vshn/v1"
Expand Down Expand Up @@ -76,6 +77,7 @@ func (a *PostgreSQLDependencyBuilder) CreateDependency() error {
Retention: retention,
DeletionProtection: ptr.To(true),
DeletionRetention: 7,
Schedule: a.comp.GetBackupSchedule(),
},
Service: vshnv1.VSHNPostgreSQLServiceSpec{
PgBouncerSettings: &sgv1.SGPoolingConfigSpecPgBouncerPgbouncerIni{
Expand Down
18 changes: 1 addition & 17 deletions pkg/comp-functions/functions/vshnmariadb/backup.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@ import (
"github.com/vshn/appcat/v4/pkg/comp-functions/functions/common"
"github.com/vshn/appcat/v4/pkg/comp-functions/functions/common/backup"
"github.com/vshn/appcat/v4/pkg/comp-functions/runtime"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
controllerruntime "sigs.k8s.io/controller-runtime"
)

Expand Down Expand Up @@ -43,7 +41,7 @@ func AddBackupMariadb(ctx context.Context, svc *runtime.ServiceRuntime) *xfnprot
}

l.Info("Adding backup script config map")
err = addBackupScriptCM(svc, comp)
err = backup.AddBackupScriptCM(svc, comp, mariadbBackupScript)
if err != nil {
return runtime.NewWarningResult(fmt.Sprintf("cannot create backup script configMap: %s", err.Error()))
}
Expand All @@ -57,20 +55,6 @@ func AddBackupMariadb(ctx context.Context, svc *runtime.ServiceRuntime) *xfnprot
return nil
}

func addBackupScriptCM(svc *runtime.ServiceRuntime, comp *vshnv1.VSHNMariaDB) error {
cm := &corev1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Name: "backup-script",
Namespace: comp.GetInstanceNamespace(),
},
Data: map[string]string{
"backup.sh": mariadbBackupScript,
},
}

return svc.SetDesiredKubeObject(cm, comp.GetName()+"-backup-script")
}

func updateRelease(ctx context.Context, svc *runtime.ServiceRuntime, comp *vshnv1.VSHNMariaDB) error {
l := controllerruntime.LoggerFrom(ctx)

Expand Down
81 changes: 81 additions & 0 deletions pkg/comp-functions/functions/vshnnextcloud/backup.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package vshnnextcloud

import (
"context"
"encoding/json"
"fmt"

_ "embed"

xfnproto "github.com/crossplane/function-sdk-go/proto/v1beta1"
xhelmv1 "github.com/vshn/appcat/v4/apis/helm/release/v1beta1"
vshnv1 "github.com/vshn/appcat/v4/apis/vshn/v1"
"github.com/vshn/appcat/v4/pkg/comp-functions/functions/common"
"github.com/vshn/appcat/v4/pkg/comp-functions/functions/common/backup"
"github.com/vshn/appcat/v4/pkg/comp-functions/runtime"
)

//go:embed files/backup.sh
var nextcloudBackupScript string

func AddBackup(ctx context.Context, svc *runtime.ServiceRuntime) *xfnproto.Result {
comp := &vshnv1.VSHNNextcloud{}
err := svc.GetDesiredComposite(comp)
if err != nil {
return runtime.NewFatalResult(fmt.Errorf("can't get composite: %w", err))
}

err = backup.AddK8upBackup(ctx, svc, comp)
if err != nil {
return runtime.NewFatalResult(fmt.Errorf("cannot add k8s backup to the desired state: %w", err))
}

err = backup.AddBackupScriptCM(svc, comp, nextcloudBackupScript)
if err != nil {
return runtime.NewFatalResult(err)
}

err = updateRelease(svc, comp)
if err != nil {
return runtime.NewWarningResult(fmt.Sprintf("cannot update release with backup configuration: %s", err))
}

return nil
}

func updateRelease(svc *runtime.ServiceRuntime, comp *vshnv1.VSHNNextcloud) error {
release := &xhelmv1.Release{}

err := svc.GetDesiredComposedResourceByName(release, comp.GetName()+"-release")
if err != nil {
return err
}

values, err := common.GetReleaseValues(release)
if err != nil {
return err
}

err = backup.AddPVCAnnotationToValues(values, "persistence", "annotations")
if err != nil {
return fmt.Errorf("cannot add pvc annotations to values: %w", err)
}

err = backup.AddPodAnnotationToValues(values, "/scripts/backup.sh", ".tar", "podAnnotations")
if err != nil {
return fmt.Errorf("cannot add pod annotations to values: %w", err)
}

err = backup.AddBackupCMToValues(values, []string{"nextcloud", "extraVolumes"}, []string{"nextcloud", "extraVolumeMounts"})
if err != nil {
return fmt.Errorf("cannot add backup cm to values: %w", err)
}

byteValues, err := json.Marshal(values)
if err != nil {
return err
}
release.Spec.ForProvider.Values.Raw = byteValues

return svc.SetDesiredComposedResourceWithName(release, comp.GetName()+"-release")
}
36 changes: 3 additions & 33 deletions pkg/comp-functions/functions/vshnnextcloud/deploy_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,46 +4,16 @@ import (
"context"
_ "embed"
"encoding/json"
"strings"
"testing"

"github.com/stretchr/testify/assert"
xhelmv1 "github.com/vshn/appcat/v4/apis/helm/release/v1beta1"
vshnv1 "github.com/vshn/appcat/v4/apis/vshn/v1"
"github.com/vshn/appcat/v4/pkg/comp-functions/functions/commontest"
"github.com/vshn/appcat/v4/pkg/comp-functions/runtime"
"k8s.io/utils/ptr"
"strings"
"testing"
)

func Test_addPostgreSQL(t *testing.T) {

svc := commontest.LoadRuntimeFromFile(t, "vshn-postgres/empty.yaml")

comp := &vshnv1.VSHNNextcloud{}

assert.NoError(t, addPostgreSQL(svc, comp))

pg := &vshnv1.XVSHNPostgreSQL{}

assert.NoError(t, svc.GetDesiredComposedResourceByName(pg, comp.GetName()+pgInstanceNameSuffix))

// Assert default values
assert.True(t, *pg.Spec.Parameters.Backup.DeletionProtection)
assert.Equal(t, 6, pg.Spec.Parameters.Backup.Retention)

// Assert default overrides
comp.Spec.Parameters.Service.PostgreSQLParameters = &vshnv1.VSHNPostgreSQLParameters{
Backup: vshnv1.VSHNPostgreSQLBackup{
DeletionProtection: ptr.To(false),
Retention: 1,
},
}

assert.NoError(t, addPostgreSQL(svc, comp))
assert.NoError(t, svc.GetDesiredComposedResourceByName(pg, comp.GetName()+pgInstanceNameSuffix))
assert.False(t, *pg.Spec.Parameters.Backup.DeletionProtection)
assert.Equal(t, 1, pg.Spec.Parameters.Backup.Retention)
}

func Test_addNextcloud(t *testing.T) {
svc, comp := getNextcloudComp(t, "vshnnextcloud/01_default.yaml")

Expand Down
17 changes: 17 additions & 0 deletions pkg/comp-functions/functions/vshnnextcloud/files/backup.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#!/bin/bash

set -e

# We need to run the occ command as the www-data user, but there's no sudo by default
apt update 1>&2 && apt install sudo -y 1>&2

function disableMaintenance {
>&2 echo "Disabling maintenance"
sudo -u www-data /var/www/html/occ maintenance:mode --off 1>&2
}

trap disableMaintenance EXIT

sudo -u www-data /var/www/html/occ maintenance:mode --on 1>&2

tar -cf - /var/www
5 changes: 5 additions & 0 deletions pkg/comp-functions/functions/vshnnextcloud/maintenance.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ func AddMaintenanceJob(ctx context.Context, svc *runtime.ServiceRuntime) *xfnpro
instanceNamespace := comp.GetInstanceNamespace()
schedule := comp.GetFullMaintenanceSchedule()

err = svc.SetDesiredCompositeStatus(comp)
if err != nil {
return runtime.NewFatalResult(fmt.Errorf("cannot update composite status: %w", err))
}

return maintenance.New(comp, svc, schedule, instanceNamespace, comp.GetServiceName()).
WithHelmBasedService().
Run(ctx)
Expand Down
4 changes: 4 additions & 0 deletions pkg/comp-functions/functions/vshnnextcloud/register.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ func init() {
Name: "maintenance",
Execute: AddMaintenanceJob,
},
{
Name: "backup",
Execute: AddBackup,
},
},
})
}

0 comments on commit 0c9e131

Please sign in to comment.