blob: fd4ea78b411393e7abe068780887eec00b72838b [file] [log] [blame]
// Copyright Istio Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package util
import (
"strings"
)
import (
"istio.io/api/annotation"
"istio.io/api/networking/v1alpha3"
corev1 "k8s.io/api/core/v1"
)
import (
"github.com/apache/dubbo-go-pixiu/pkg/config/analysis"
"github.com/apache/dubbo-go-pixiu/pkg/config/resource"
"github.com/apache/dubbo-go-pixiu/pkg/config/schema/collections"
)
func InitServiceEntryHostMap(ctx analysis.Context) map[ScopedFqdn]*v1alpha3.ServiceEntry {
result := make(map[ScopedFqdn]*v1alpha3.ServiceEntry)
ctx.ForEach(collections.IstioNetworkingV1Alpha3Serviceentries.Name(), func(r *resource.Instance) bool {
s := r.Message.(*v1alpha3.ServiceEntry)
hostsNamespaceScope := string(r.Metadata.FullName.Namespace)
if IsExportToAllNamespaces(s.ExportTo) {
hostsNamespaceScope = ExportToAllNamespaces
}
for _, h := range s.GetHosts() {
result[NewScopedFqdn(hostsNamespaceScope, r.Metadata.FullName.Namespace, h)] = s
}
return true
})
// converts k8s service to serviceEntry since destinationHost
// validation is performed against serviceEntry
ctx.ForEach(collections.K8SCoreV1Services.Name(), func(r *resource.Instance) bool {
s := r.Message.(*corev1.ServiceSpec)
var se *v1alpha3.ServiceEntry
hostsNamespaceScope, ok := r.Metadata.Annotations[annotation.NetworkingExportTo.Name]
if !ok {
hostsNamespaceScope = ExportToAllNamespaces
}
var ports []*v1alpha3.Port
for _, p := range s.Ports {
ports = append(ports, &v1alpha3.Port{
Number: uint32(p.Port),
Name: p.Name,
Protocol: string(p.Protocol),
})
}
host := ConvertHostToFQDN(r.Metadata.FullName.Namespace, r.Metadata.FullName.Name.String())
se = &v1alpha3.ServiceEntry{
Hosts: []string{host},
Ports: ports,
}
result[NewScopedFqdn(hostsNamespaceScope, r.Metadata.FullName.Namespace, r.Metadata.FullName.Name.String())] = se
return true
})
return result
}
func GetDestinationHost(sourceNs resource.Namespace, host string, serviceEntryHosts map[ScopedFqdn]*v1alpha3.ServiceEntry) *v1alpha3.ServiceEntry {
// Check explicitly defined ServiceEntries as well as services discovered from the platform
// ServiceEntries can be either namespace scoped or exposed to all namespaces
nsScopedFqdn := NewScopedFqdn(string(sourceNs), sourceNs, host)
if s, ok := serviceEntryHosts[nsScopedFqdn]; ok {
return s
}
// Check ServiceEntries which are exposed to all namespaces
allNsScopedFqdn := NewScopedFqdn(ExportToAllNamespaces, sourceNs, host)
if s, ok := serviceEntryHosts[allNsScopedFqdn]; ok {
return s
}
// Now check wildcard matches, namespace scoped or all namespaces
// (This more expensive checking left for last)
// Assumes the wildcard entries are correctly formatted ("*<dns suffix>")
for seHostScopedFqdn, s := range serviceEntryHosts {
scope, seHost := seHostScopedFqdn.GetScopeAndFqdn()
// Skip over non-wildcard entries
if !strings.HasPrefix(seHost, Wildcard) {
continue
}
// Skip over entries not visible to the current virtual service namespace
if scope != ExportToAllNamespaces && scope != string(sourceNs) {
continue
}
seHostWithoutWildcard := strings.TrimPrefix(seHost, Wildcard)
hostWithoutWildCard := strings.TrimPrefix(host, Wildcard)
if strings.HasSuffix(hostWithoutWildCard, seHostWithoutWildcard) {
return s
}
}
return nil
}