Skip to content

Commit

Permalink
Merge pull request #269 from vshn/nextcloud/multi_fqdn
Browse files Browse the repository at this point in the history
Use an array instead of a string for the FQDN parameter
  • Loading branch information
TheBigLee authored Nov 26, 2024
2 parents b1ec9ef + 3ac924e commit 33a1df9
Show file tree
Hide file tree
Showing 15 changed files with 542 additions and 123 deletions.
5 changes: 3 additions & 2 deletions apis/vshn/v1/vshn_nextcloud.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,11 +91,12 @@ type VSHNNextcloudServiceSpec struct {
// Collabora contains settings to control the Collabora integration.
Collabora CollaboraSpec `json:"collabora,omitempty"`
// +kubebuilder:validation:Required
// +kubebuilder:validation:MinItems=1

// FQDN contains the FQDN which will be used for the ingress.
// FQDN contains the FQDNs array, which will be used for the ingress.
// If it's not set, no ingress will be deployed.
// This also enables strict hostname checking for this FQDN.
FQDN string `json:"fqdn"`
FQDN []string `json:"fqdn"`

// RelativePath on which Nextcloud will listen.
// +kubebuilder:default="/"
Expand Down
5 changes: 5 additions & 0 deletions apis/vshn/v1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 5 additions & 2 deletions crds/vshn.appcat.vshn.io_vshnnextclouds.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4866,10 +4866,13 @@ spec:
type: object
fqdn:
description: |-
FQDN contains the FQDN which will be used for the ingress.
FQDN contains the FQDNs array, which will be used for the ingress.
If it's not set, no ingress will be deployed.
This also enables strict hostname checking for this FQDN.
type: string
items:
type: string
minItems: 1
type: array
postgreSQLParameters:
description: |-
PostgreSQLParameters can be used to set any supported setting in the
Expand Down
7 changes: 5 additions & 2 deletions crds/vshn.appcat.vshn.io_xvshnnextclouds.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5595,10 +5595,13 @@ spec:
type: object
fqdn:
description: |-
FQDN contains the FQDN which will be used for the ingress.
FQDN contains the FQDNs array, which will be used for the ingress.
If it's not set, no ingress will be deployed.
This also enables strict hostname checking for this FQDN.
type: string
items:
type: string
minItems: 1
type: array
postgreSQLParameters:
description: |-
PostgreSQLParameters can be used to set any supported setting in the
Expand Down
5 changes: 0 additions & 5 deletions pkg/comp-functions/functions/vshnnextcloud/collabora.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import (
"encoding/pem"
"fmt"

valid "github.com/asaskevich/govalidator"
cmv1 "github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1"
certmgrv1 "github.com/cert-manager/cert-manager/pkg/apis/meta/v1"
xfnproto "github.com/crossplane/function-sdk-go/proto/v1beta1"
Expand Down Expand Up @@ -53,10 +52,6 @@ func DeployCollabora(ctx context.Context, comp *vshnv1.VSHNNextcloud, svc *runti
return runtime.NewNormalResult("Collabora not enabled")
}

if !valid.IsDNSName(comp.Spec.Parameters.Service.Collabora.FQDN) {
return runtime.NewWarningResult("Collabora FQDN is not a valid DNS name: " + comp.Spec.Parameters.Service.Collabora.FQDN)
}

rules := []rbacv1.PolicyRule{
{
APIGroups: []string{""},
Expand Down
7 changes: 0 additions & 7 deletions pkg/comp-functions/functions/vshnnextcloud/collabora_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,4 @@ func Test_addCollabora(t *testing.T) {
res = DeployCollabora(ctx, comp, svc)

assert.True(t, res.Severity == v1beta1.Severity_SEVERITY_NORMAL && res.Message == "Collabora not enabled")

comp.Spec.Parameters.Service.Collabora.Enabled = true
comp.Spec.Parameters.Service.Collabora.FQDN = ""
res = DeployCollabora(ctx, comp, svc)

assert.True(t, res.Severity == v1beta1.Severity_SEVERITY_WARNING && res.Message == "Collabora FQDN is not a valid DNS name: "+comp.Spec.Parameters.Service.Collabora.FQDN)

}
18 changes: 17 additions & 1 deletion pkg/comp-functions/functions/vshnnextcloud/deploy.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"strings"
"time"

valid "github.com/asaskevich/govalidator"
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"
Expand Down Expand Up @@ -256,10 +257,16 @@ func newValues(ctx context.Context, svc *runtime.ServiceRuntime, comp *vshnv1.VS
}
}

trustedDomain := []string{
comp.GetName() + "." + comp.GetInstanceNamespace() + ".svc.cluster.local",
}
trustedDomain = append(trustedDomain, comp.Spec.Parameters.Service.FQDN...)

updatedNextcloudConfig := setBackgroundJobMaintenance(comp.Spec.Parameters.Maintenance.GetMaintenanceTimeOfDay(), nextcloudConfig)
values = map[string]any{
"nextcloud": map[string]any{
"host": comp.Spec.Parameters.Service.FQDN,
"host": comp.Spec.Parameters.Service.FQDN[0],
"trustedDomains": trustedDomain,
"existingSecret": map[string]any{
"enabled": true,
"secretName": adminSecret,
Expand Down Expand Up @@ -428,3 +435,12 @@ func setBackgroundJobMaintenance(t vshnv1.TimeOfDay, nextcloudConfig string) str
backgroundJobHour := t.GetTime().Add(40 * time.Minute).Add(time.Hour).Hour()
return strings.Replace(nextcloudConfig, "%maintenance_value%", strconv.Itoa(backgroundJobHour), 1)
}

func validateFQDNs(fqdns []string) error {
for _, fqdn := range fqdns {
if !valid.IsDNSName(fqdn) {
return fmt.Errorf("FQDN %s is not a valid DNS name", fqdn)
}
}
return nil
}
108 changes: 55 additions & 53 deletions pkg/comp-functions/functions/vshnnextcloud/ingress.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,16 @@ package vshnnextcloud

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

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/runtime"
"gopkg.in/yaml.v2"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
netv1 "k8s.io/api/networking/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/utils/ptr"
)

// AddIngress adds an inrgess to the Nextcloud instance.
Expand All @@ -22,69 +22,71 @@ func AddIngress(_ context.Context, comp *vshnv1.VSHNNextcloud, svc *runtime.Serv
return runtime.NewFatalResult(fmt.Errorf("cannot get composite: %w", err))
}

if comp.Spec.Parameters.Service.FQDN == "" {
return nil
if len(comp.Spec.Parameters.Service.FQDN) == 0 {
return runtime.NewFatalResult(fmt.Errorf("FQDN array is empty, but requires at least one entry, %w", errors.New("empty fqdn")))
}

values, err := common.GetDesiredReleaseValues(svc, comp.GetName()+"-release")
if err != nil {
return runtime.NewWarningResult(fmt.Sprintf("cannot get desired release values: %s", err))
}

svc.Log.Info("Enable ingress for release")
enableIngresValues(svc, comp, values)

release := &xhelmv1.Release{}
err = svc.GetDesiredComposedResourceByName(release, comp.GetName()+"-release")
if err != nil {
return runtime.NewWarningResult(fmt.Sprintf("cannot get desired release: %s", err))
annotations := map[string]string{}
if svc.Config.Data["ingress_annotations"] != "" {
err := yaml.Unmarshal([]byte(svc.Config.Data["ingress_annotations"]), annotations)
if err != nil {
svc.Log.Error(err, "cannot unmarshal ingress annotations from input")
svc.AddResult(runtime.NewWarningResult(fmt.Sprintf("cannot unmarshal ingress annotations from input: %s", err)))
}
}

vb, err := json.Marshal(values)
if err != nil {
return runtime.NewWarningResult(fmt.Sprintf("cannot marhal values: %s", err))
ingress := &netv1.Ingress{
ObjectMeta: metav1.ObjectMeta{
Name: comp.GetName(),
Namespace: comp.GetInstanceNamespace(),
Annotations: annotations,
},
Spec: netv1.IngressSpec{
Rules: createIngressRule(comp),
TLS: []netv1.IngressTLS{
{
Hosts: comp.Spec.Parameters.Service.FQDN,
SecretName: "nextcloud-ingress-cert",
},
},
},
}

release.Spec.ForProvider.Values.Raw = vb

err = svc.SetDesiredComposedResourceWithName(release, comp.GetName()+"-release")
err = svc.SetDesiredKubeObject(ingress, comp.GetName()+"-ingress")
if err != nil {
return runtime.NewWarningResult(fmt.Sprintf("cannot set desired release: %s", err))
return runtime.NewWarningResult(fmt.Sprintf("cannot set create ingress: %s", err))
}

return nil
}

func enableIngresValues(svc *runtime.ServiceRuntime, comp *vshnv1.VSHNNextcloud, values map[string]any) {
fqdn := comp.Spec.Parameters.Service.FQDN

values["ingress"] = map[string]any{
"enabled": true,
"servicePort": "http",
"path": comp.Spec.Parameters.Service.RelativePath,
"tls": []map[string]any{
{
"hosts": []string{
fqdn,
func createIngressRule(comp *vshnv1.VSHNNextcloud) []netv1.IngressRule {

ingressRules := []netv1.IngressRule{}

for _, fqdn := range comp.Spec.Parameters.Service.FQDN {
rule := netv1.IngressRule{
Host: fqdn,
IngressRuleValue: netv1.IngressRuleValue{
HTTP: &netv1.HTTPIngressRuleValue{
Paths: []netv1.HTTPIngressPath{
{
Path: "/",
PathType: ptr.To(netv1.PathType("Prefix")),
Backend: netv1.IngressBackend{
Service: &netv1.IngressServiceBackend{
Name: comp.GetName(),
Port: netv1.ServiceBackendPort{
Number: 8080,
},
},
},
},
},
},
"secretName": "nextcloud-ingress-cert",
},
},
}

if svc.Config.Data["ingress_annotations"] != "" {
annotations := map[string]any{}

err := yaml.Unmarshal([]byte(svc.Config.Data["ingress_annotations"]), annotations)
if err != nil {
svc.Log.Error(err, "cannot unmarshal ingress annotations from input")
svc.AddResult(runtime.NewWarningResult(fmt.Sprintf("cannot unmarshal ingress annotations from input: %s", err)))
}

err = unstructured.SetNestedMap(values, annotations, "ingress", "annotations")
if err != nil {
svc.Log.Error(err, "cannot set ingress annotations")
svc.AddResult(runtime.NewWarningResult(fmt.Sprintf("cannot set ingress annotations: %s", err)))
}
ingressRules = append(ingressRules, rule)
}
return ingressRules
}
Loading

0 comments on commit 33a1df9

Please sign in to comment.