Skip to content
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
20 changes: 14 additions & 6 deletions pkg/reconciler/route/domains/domains.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,11 @@ const HTTPScheme string = "http"

var ErrDomainName = errors.New("domain name error")

type Domains struct {
Primary string
Expanded sets.Set[string]
}

// GetAllDomainsAndTags returns all of the domains and tags(including subdomains) associated with a Route
func GetAllDomainsAndTags(ctx context.Context, r *v1.Route, names []string, visibility map[string]netv1alpha1.IngressVisibility) (map[string]string, error) {
domainTagMap := make(map[string]string)
Expand All @@ -69,10 +74,11 @@ func GetAllDomainsAndTags(ctx context.Context, r *v1.Route, names []string, visi
}

// GetDomainsForVisibility return all domains for the specified visibility.
func GetDomainsForVisibility(ctx context.Context, targetName string, r *v1.Route, visibility netv1alpha1.IngressVisibility) (sets.Set[string], error) {
func GetDomainsForVisibility(ctx context.Context, targetName string, r *v1.Route, visibility netv1alpha1.IngressVisibility) (Domains, error) {
domains := Domains{}
hostname, err := HostnameFromTemplate(ctx, r.Name, targetName)
if err != nil {
return nil, err
return domains, err
}

meta := r.ObjectMeta.DeepCopy()
Expand All @@ -81,13 +87,15 @@ func GetDomainsForVisibility(ctx context.Context, targetName string, r *v1.Route

domain, err := DomainNameFromTemplate(ctx, *meta, hostname)
if err != nil {
return nil, err
return domains, err
}
domains := []string{domain}

domains.Primary = domain
domains.Expanded = sets.New(domain)
if isClusterLocal {
domains = sets.List(ingress.ExpandedHosts(sets.New(domains...)))
domains.Expanded = ingress.ExpandedHosts(domains.Expanded)
}
return sets.New(domains...), err
return domains, err
}

// DomainNameFromTemplate generates domain name base on the template specified in the `config-network` ConfigMap.
Expand Down
16 changes: 15 additions & 1 deletion pkg/reconciler/route/domains/domains_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,7 @@ func TestGetDomainsForVisibility(t *testing.T) {
visibility v1alpha1.IngressVisibility
domainTemplate string
tagTemplate string
primary string
want sets.Set[string]
}{
{
Expand All @@ -289,6 +290,7 @@ func TestGetDomainsForVisibility(t *testing.T) {
visibility: v1alpha1.IngressVisibilityClusterLocal,
domainTemplate: "{{.Name}}.{{.Namespace}}.{{.Domain}}",
tagTemplate: "{{.Name}}-{{.Tag}}",
primary: "myroute.default.svc.cluster.local",
want: sets.New(
"myroute.default",
"myroute.default.svc",
Expand All @@ -300,6 +302,7 @@ func TestGetDomainsForVisibility(t *testing.T) {
visibility: v1alpha1.IngressVisibilityExternalIP,
domainTemplate: "{{.Name}}.{{.Namespace}}.{{.Domain}}",
tagTemplate: "{{.Name}}-{{.Tag}}",
primary: "myroute.default.example.com",
want: sets.New(
"myroute.default.example.com",
),
Expand All @@ -309,6 +312,7 @@ func TestGetDomainsForVisibility(t *testing.T) {
visibility: v1alpha1.IngressVisibilityClusterLocal,
domainTemplate: "{{.Name}}.{{.Namespace}}.{{.Domain}}",
tagTemplate: "{{.Name}}-{{.Tag}}",
primary: "myroute-test.default.svc.cluster.local",
want: sets.New(
"myroute-test.default",
"myroute-test.default.svc",
Expand All @@ -320,6 +324,7 @@ func TestGetDomainsForVisibility(t *testing.T) {
visibility: v1alpha1.IngressVisibilityExternalIP,
domainTemplate: "{{.Name}}.{{.Namespace}}.{{.Domain}}",
tagTemplate: "{{.Name}}-{{.Tag}}",
primary: "myroute-test.default.example.com",
want: sets.New(
"myroute-test.default.example.com",
),
Expand All @@ -329,6 +334,7 @@ func TestGetDomainsForVisibility(t *testing.T) {
visibility: v1alpha1.IngressVisibilityClusterLocal,
domainTemplate: "{{.Name}}.{{.Namespace}}.{{.Domain}}",
tagTemplate: "{{.Tag}}-{{.Name}}",
primary: "myroute.default.svc.cluster.local",
want: sets.New(
"myroute.default",
"myroute.default.svc",
Expand All @@ -340,6 +346,7 @@ func TestGetDomainsForVisibility(t *testing.T) {
visibility: v1alpha1.IngressVisibilityExternalIP,
domainTemplate: "{{.Name}}.{{.Namespace}}.{{.Domain}}",
tagTemplate: "{{.Tag}}-{{.Name}}",
primary: "myroute.default.example.com",
want: sets.New(
"myroute.default.example.com",
),
Expand All @@ -349,6 +356,7 @@ func TestGetDomainsForVisibility(t *testing.T) {
visibility: v1alpha1.IngressVisibilityClusterLocal,
domainTemplate: "{{.Name}}.{{.Namespace}}.{{.Domain}}",
tagTemplate: "{{.Tag}}-{{.Name}}",
primary: "test-myroute.default.svc.cluster.local",
want: sets.New(
"test-myroute.default",
"test-myroute.default.svc",
Expand All @@ -360,6 +368,7 @@ func TestGetDomainsForVisibility(t *testing.T) {
visibility: v1alpha1.IngressVisibilityExternalIP,
domainTemplate: "{{.Name}}.{{.Namespace}}.{{.Domain}}",
tagTemplate: "{{.Tag}}-{{.Name}}",
primary: "test-myroute.default.example.com",
want: sets.New(
"test-myroute.default.example.com",
),
Expand All @@ -384,11 +393,16 @@ func TestGetDomainsForVisibility(t *testing.T) {
cfg.Network.TagTemplate = tt.tagTemplate
ctx = config.ToContext(ctx, cfg)

want := Domains{
Primary: tt.primary,
Expanded: tt.want,
}

got, err := GetDomainsForVisibility(ctx, tt.tag, route, tt.visibility)
if err != nil {
t.Errorf("failed calling GetDomainsForVisibility: %v", err)
}
if diff := cmp.Diff(tt.want, got); diff != "" {
if diff := cmp.Diff(want, got); diff != "" {
t.Error("GetDomainsForVisibility() diff (-want +got):", diff)
}
})
Expand Down
44 changes: 35 additions & 9 deletions pkg/reconciler/route/resources/ingress.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,11 +79,12 @@ func MakeIngressWithRollout(
ingressClass string,
acmeChallenges ...netv1alpha1.HTTP01Challenge,
) (*netv1alpha1.Ingress, error) {
spec, err := makeIngressSpec(ctx, r, tls, tc, ro, acmeChallenges...)
spec, tagToHost, err := makeIngressSpec(ctx, r, tls, tc, ro, acmeChallenges...)
if err != nil {
return nil, err
}
return &netv1alpha1.Ingress{

ing := &netv1alpha1.Ingress{
ObjectMeta: metav1.ObjectMeta{
Name: names.Ingress(r),
Namespace: r.Namespace,
Expand All @@ -98,7 +99,24 @@ func MakeIngressWithRollout(
OwnerReferences: []metav1.OwnerReference{*kmeta.NewControllerRef(r)},
},
Spec: spec,
}, nil
}

if len(tagToHost) > 0 {
ing.Annotations[networking.TagToHostAnnotationKey] = serializeTagToHostMap(ctx, tagToHost)
}

return ing, nil
}

func serializeTagToHostMap(ctx context.Context, mapping map[string][]string) string {
sr, err := json.Marshal(mapping)
if err != nil {
// This must never happen in the normal course of things.
logging.FromContext(ctx).Warnw("Error serializing tag to host mapping: "+spew.Sprint(mapping),
zap.Error(err))
return ""
}
return string(sr)
}

func serializeRollout(ctx context.Context, r *traffic.Rollout) string {
Expand All @@ -120,7 +138,9 @@ func makeIngressSpec(
tc *traffic.Config,
ro *traffic.Rollout,
acmeChallenges ...netv1alpha1.HTTP01Challenge,
) (netv1alpha1.IngressSpec, error) {
) (netv1alpha1.IngressSpec, map[string][]string, error) {
tagToHost := make(map[string][]string)

// Domain should have been specified in route status
// before calling this func.
names := make([]string, 0, len(tc.Targets))
Expand Down Expand Up @@ -152,9 +172,9 @@ func makeIngressSpec(
for _, visibility := range visibilities {
domains, err := domains.GetDomainsForVisibility(ctx, name, r, visibility)
if err != nil {
return netv1alpha1.IngressSpec{}, err
return netv1alpha1.IngressSpec{}, nil, err
}
domainRules := makeIngressRules(domains, r.Namespace,
domainRules := makeIngressRules(domains.Expanded, r.Namespace,
visibility, tc.Targets[name], ro.RolloutsByTag(name), networkConfig.SystemInternalTLSEnabled())

// Apply tag header routing and ACME merging to each rule
Expand Down Expand Up @@ -205,19 +225,25 @@ func makeIngressSpec(
}

rules = append(rules, domainRules...)

if name != traffic.DefaultTarget {
tagToHost[name] = append(tagToHost[name], domains.Primary)
}
}
}

httpOption, err := servingnetworking.GetHTTPOption(ctx, config.FromContext(ctx).Network, r.GetAnnotations())
if err != nil {
return netv1alpha1.IngressSpec{}, err
return netv1alpha1.IngressSpec{}, nil, err
}

return netv1alpha1.IngressSpec{
spec := netv1alpha1.IngressSpec{
Rules: rules,
TLS: tls,
HTTPOption: httpOption,
}, nil
}

return spec, tagToHost, nil
}

// MakeACMEIngressPath converts an ACME challenge into an HTTPIngressPath.
Expand Down
14 changes: 8 additions & 6 deletions pkg/reconciler/route/resources/ingress_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ func TestMakeIngressWithTaggedRollout(t *testing.T) {
networking.IngressClassAnnotationKey: ingressClass,
networking.RolloutAnnotationKey: `{"configurations":[{"configurationName":"valhalla","percent":100,"revisions":[{"revisionName":"valhalla-01982","percent":100}],"stepParams":{}},{"configurationName":"thor","tag":"tagged","percent":100,"revisions":[{"revisionName":"thor-02020","percent":100}],"stepParams":{}}]}`,
"test-annotation": "bar",
networking.TagToHostAnnotationKey: `{"tagged":["tagged-test-route.test-ns.svc.cluster.local","tagged-test-route.test-ns.example.com"]}`,
},
OwnerReferences: []metav1.OwnerReference{*kmeta.NewControllerRef(r)},
}
Expand Down Expand Up @@ -245,6 +246,7 @@ func TestMakeIngressWithActualRollout(t *testing.T) {
Annotations: map[string]string{
networking.IngressClassAnnotationKey: ingressClass,
networking.RolloutAnnotationKey: serializeRollout(context.Background(), ro),
networking.TagToHostAnnotationKey: `{"hammer":["hammer-test-route.test-ns.svc.cluster.local","hammer-test-route.test-ns.example.com"]}`,
},
OwnerReferences: []metav1.OwnerReference{*kmeta.NewControllerRef(r)},
}
Expand Down Expand Up @@ -587,7 +589,7 @@ func TestMakeIngressSpecCorrectRules(t *testing.T) {

tc := &traffic.Config{Targets: targets}
ro := tc.BuildRollout()
ci, err := makeIngressSpec(testContext(), r, nil /*tls*/, tc, ro)
ci, _, err := makeIngressSpec(testContext(), r, nil /*tls*/, tc, ro)
if err != nil {
t.Error("Unexpected error", err)
}
Expand Down Expand Up @@ -662,7 +664,7 @@ func TestMakeIngressSpecCorrectRuleVisibility(t *testing.T) {
Visibility: c.serviceVisibility,
}
ro := tc.BuildRollout()
ci, err := makeIngressSpec(testContext(), c.route, nil /*tls*/, tc, ro)
ci, _, err := makeIngressSpec(testContext(), c.route, nil /*tls*/, tc, ro)
if err != nil {
t.Error("Unexpected error", err)
}
Expand Down Expand Up @@ -842,7 +844,7 @@ func TestMakeIngressSpecCorrectRulesWithTagBasedRouting(t *testing.T) {

tc := &traffic.Config{Targets: targets}
ro := tc.BuildRollout()
ci, err := makeIngressSpec(ctx, r, nil /*tls*/, tc, ro)
ci, _, err := makeIngressSpec(ctx, r, nil /*tls*/, tc, ro)
if err != nil {
t.Error("Unexpected error", err)
}
Expand Down Expand Up @@ -1221,7 +1223,7 @@ func TestMakeIngressWithActivatorCA(t *testing.T) {

tc := &traffic.Config{Targets: targets}
ro := tc.BuildRollout()
ci, err := makeIngressSpec(testContextWithActivatorCA(), r, nil /*tls*/, tc, ro)
ci, _, err := makeIngressSpec(testContextWithActivatorCA(), r, nil /*tls*/, tc, ro)
if err != nil {
t.Error("Unexpected error", err)
}
Expand Down Expand Up @@ -1352,7 +1354,7 @@ func TestMakeIngressACMEChallenges(t *testing.T) {
}
ro := tc.BuildRollout()

ci, err := makeIngressSpec(testContext(), r, nil /*tls*/, tc, ro, acmeChallenge)
ci, _, err := makeIngressSpec(testContext(), r, nil /*tls*/, tc, ro, acmeChallenge)
if err != nil {
t.Error("Unexpected error", err)
}
Expand Down Expand Up @@ -1442,7 +1444,7 @@ func TestMakeIngressACMEChallengesWithTrafficTags(t *testing.T) {
}
ro := tc.BuildRollout()

ci, err := makeIngressSpec(testContext(), r, nil /*tls*/, tc, ro, acmeChallenges...)
ci, _, err := makeIngressSpec(testContext(), r, nil /*tls*/, tc, ro, acmeChallenges...)
if err != nil {
t.Fatal("Unexpected error", err)
}
Expand Down
8 changes: 4 additions & 4 deletions pkg/reconciler/route/route.go
Original file line number Diff line number Diff line change
Expand Up @@ -326,7 +326,7 @@ func (c *Reconciler) clusterLocalDomainTLS(ctx context.Context, r *v1.Route, tc
return nil, err
}

desiredCert := resources.MakeClusterLocalCertificate(r, name, localDomains, certClass(ctx, r))
desiredCert := resources.MakeClusterLocalCertificate(r, name, localDomains.Expanded, certClass(ctx, r))
cert, err := networkaccessor.ReconcileCertificate(ctx, r, desiredCert, c)
if err != nil {
if kaccessor.IsNotOwned(err) {
Expand All @@ -342,19 +342,19 @@ func (c *Reconciler) clusterLocalDomainTLS(ctx context.Context, r *v1.Route, tc

// r.Status.URL contains the major domain,
// so only change if the cert is for the major domain
if localDomains.Has(r.Status.URL.Host) {
if localDomains.Expanded.Has(r.Status.URL.Host) {
r.Status.URL.Scheme = "https"
}

r.Status.MarkCertificateReady(cert.Name)
tls = append(tls, resources.MakeIngressTLS(cert, sets.List(localDomains)))
tls = append(tls, resources.MakeIngressTLS(cert, sets.List(localDomains.Expanded)))
} else if cert.IsFailed() {
r.Status.MarkCertificateProvisionFailed(cert)
} else {
r.Status.MarkCertificateNotReady(cert)
}

for s := range localDomains {
for s := range localDomains.Expanded {
usedDomains[s] = s
}
}
Expand Down
Loading