Skip to content
Open
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
90 changes: 90 additions & 0 deletions pkg/obc/obc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -159,3 +159,93 @@ var _ = Describe("OBC referenced BucketClass", func() {
})
})
})

var _ = Describe("getExternalDNSDetails", func() {
noobaaWithExternalDNS := func(s3URLs, vectorsURLs []string) *nbv1.NooBaa {
return &nbv1.NooBaa{
Status: nbv1.NooBaaStatus{
Services: &nbv1.ServicesStatus{
ServiceS3: nbv1.ServiceStatus{ExternalDNS: s3URLs},
ServiceVectors: nbv1.ServiceStatus{ExternalDNS: vectorsURLs},
},
},
}
}

It("returns host and port from the first S3 ExternalDNS entry", func() {
host, port, err := getExternalDNSDetails(
noobaaWithExternalDNS([]string{"https://s3.route.example.com:443"}, nil),
externalDNSServiceS3,
)
Expect(err).NotTo(HaveOccurred())
Expect(host).To(Equal("s3.route.example.com"))
Expect(port).To(Equal(443))
})

It("returns host and port from the first Vectors ExternalDNS entry", func() {
host, port, err := getExternalDNSDetails(
noobaaWithExternalDNS(nil, []string{"https://vectors.apps.example.com:8443"}),
externalDNSServiceVectors,
)
Expect(err).NotTo(HaveOccurred())
Expect(host).To(Equal("vectors.apps.example.com"))
Expect(port).To(Equal(8443))
})

It("uses the first URL when S3 ExternalDNS lists multiple entries", func() {
host, port, err := getExternalDNSDetails(
noobaaWithExternalDNS([]string{"https://first.route.test:443", "https://second.route.test:443"}, nil),
externalDNSServiceS3,
)
Expect(err).NotTo(HaveOccurred())
Expect(host).To(Equal("first.route.test"))
Expect(port).To(Equal(443))
})

It("returns an error when the selected service has no ExternalDNS", func() {
_, _, err := getExternalDNSDetails(
noobaaWithExternalDNS(nil, []string{"https://vectors-only:443"}),
externalDNSServiceS3,
)
Expect(err).To(HaveOccurred())
Expect(err.Error()).To(ContainSubstring("no external"))
Expect(err.Error()).To(ContainSubstring("s3"))
})

It("returns an error for an unknown externalDNSService value", func() {
_, _, err := getExternalDNSDetails(
noobaaWithExternalDNS([]string{"https://x:443"}, nil),
externalDNSService("other"),
)
Expect(err).To(HaveOccurred())
Expect(err.Error()).To(ContainSubstring("unknown external DNS service"))
})

It("returns a parse error when the primary URL is invalid", func() {
_, _, err := getExternalDNSDetails(
noobaaWithExternalDNS([]string{"not-a-valid-request-uri"}, nil),
externalDNSServiceS3,
)
Expect(err).To(HaveOccurred())
})

It("returns an error when the URL omits a numeric port", func() {
_, _, err := getExternalDNSDetails(
noobaaWithExternalDNS([]string{"https://s3.example.com"}, nil),
externalDNSServiceS3,
)
Expect(err).To(HaveOccurred())
Expect(err.Error()).To(ContainSubstring("failed to parse external DNS"))
})

It("getExternalDNSDetails returns an error when NooBaa Status.Services is nil", func() {
for _, nb := range []*nbv1.NooBaa{
{},
{Status: nbv1.NooBaaStatus{Services: nil}},
} {
_, _, err := getExternalDNSDetails(nb, externalDNSServiceS3)
Expect(err).To(HaveOccurred())
Expect(err.Error()).To(ContainSubstring("no services found"))
}
})
})
55 changes: 54 additions & 1 deletion pkg/obc/provisioner.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"errors"
"fmt"
"net/http"
"net/url"
"strconv"
"time"

Expand All @@ -31,8 +32,12 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client"
)

type externalDNSService string

const (
allNamespaces = ""
allNamespaces = ""
externalDNSServiceS3 externalDNSService = "s3"
externalDNSServiceVectors externalDNSService = "vectors"
)

var excludeBucketTaggingLabelKeysSet = map[string]struct{}{
Expand Down Expand Up @@ -404,6 +409,20 @@ func NewBucketRequest(
endpointHostname = vectorsHostname
endpointPort = vectorsPort
}
if util.IsRemoteObcAnnotation(r.OBC.Annotations) {
extSvc := externalDNSServiceS3
if r.BucketClass.Spec.VectorPolicy != nil {
extSvc = externalDNSServiceVectors
}
extHost, extPort, externalErr := getExternalDNSDetails(sysClient.NooBaa, extSvc)
if externalErr != nil {
p.recorder.Event(r.OBC, "Warning", "RemoteOBCExternalDNSUnavailable",
fmt.Sprintf("using internal DNS details: %v", externalErr))
} else {
endpointHostname = extHost
endpointPort = extPort
}
}

additionalConfig := r.OBC.Spec.AdditionalConfig
if additionalConfig == nil {
Expand Down Expand Up @@ -936,3 +955,37 @@ func getBucketClass(

return bucketClass, false
}

// getExternalDNSDetails returns hostname and port for the ObjectBucket ConfigMap from NooBaa status ExternalDNS
func getExternalDNSDetails(nb *nbv1.NooBaa, svc externalDNSService) (string, int, error) {
if nb == nil || nb.Status.Services == nil {
return "", 0, fmt.Errorf("no services found in status")
}
var externalDNS []string
switch svc {
case externalDNSServiceS3:
externalDNS = nb.Status.Services.ServiceS3.ExternalDNS
case externalDNSServiceVectors:
externalDNS = nb.Status.Services.ServiceVectors.ExternalDNS
default:
return "", 0, fmt.Errorf("unknown external DNS service %q", svc)
}
if len(externalDNS) == 0 {
return "", 0, fmt.Errorf("no external %q service endpoint in status (Route or LoadBalancer)", svc)
}
// ExternalDNS order is defined in CheckServiceStatus:
// append Route URL when route.Spec.Host is set, then append each LoadBalancer ingress hostname.
// For status produced by that code, when both exist index 0 is always the Route URL;
primaryExternalDNS := externalDNS[0]
uri, err := url.ParseRequestURI(primaryExternalDNS)
if err != nil {
return "", 0, err
}
hostname := uri.Hostname()
portStr := uri.Port()
port, err := strconv.Atoi(portStr)
if err != nil {
return "", 0, fmt.Errorf("failed to parse external DNS in %q service: port %q. got error: %v", svc, portStr, err)
}
return hostname, port, nil
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Loading