blob: e811f5fba363789896d7ac1f8fc5e895b6077bd3 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 generator
import (
"context"
)
import (
"github.com/pkg/errors"
)
import (
core_mesh "github.com/apache/dubbo-kubernetes/pkg/core/resources/apis/mesh"
"github.com/apache/dubbo-kubernetes/pkg/core/validators"
core_xds "github.com/apache/dubbo-kubernetes/pkg/core/xds"
"github.com/apache/dubbo-kubernetes/pkg/util/net"
xds_context "github.com/apache/dubbo-kubernetes/pkg/xds/context"
envoy_common "github.com/apache/dubbo-kubernetes/pkg/xds/envoy"
envoy_clusters "github.com/apache/dubbo-kubernetes/pkg/xds/envoy/clusters"
envoy_listeners "github.com/apache/dubbo-kubernetes/pkg/xds/envoy/listeners"
envoy_names "github.com/apache/dubbo-kubernetes/pkg/xds/envoy/names"
)
const OriginInbound = "inbound"
type InboundProxyGenerator struct{}
func (g InboundProxyGenerator) Generator(ctx context.Context, _ *core_xds.ResourceSet, xdsCtx xds_context.Context, proxy *core_xds.Proxy) (*core_xds.ResourceSet, error) {
resources := core_xds.NewResourceSet()
for i, endpoint := range proxy.Dataplane.Spec.Networking.GetInboundInterfaces() {
// we do not create inbounds for serviceless
if endpoint.IsServiceLess() {
continue
}
iface := proxy.Dataplane.Spec.Networking.Inbound[i]
protocol := core_mesh.ParseProtocol(iface.GetProtocol())
// generate CDS resource
localClusterName := envoy_names.GetLocalClusterName(endpoint.WorkloadPort)
clusterBuilder := envoy_clusters.NewClusterBuilder(proxy.APIVersion, localClusterName).
Configure(envoy_clusters.ProvidedEndpointCluster(false, core_xds.Endpoint{Target: endpoint.WorkloadIP, Port: endpoint.DataplanePort}))
// localhost traffic is routed dirrectly to the application, in case of other interface we are going to set source address to
// 127.0.0.6 to avoid redirections and thanks to first iptables rule just return fast
if endpoint.WorkloadIP != core_mesh.IPv4Loopback.String() && endpoint.WorkloadIP != core_mesh.IPv6Loopback.String() {
switch net.IsAddressIPv6(endpoint.WorkloadIP) {
case true:
clusterBuilder.Configure(envoy_clusters.UpstreamBindConfig(InPassThroughIPv6, 0))
case false:
clusterBuilder.Configure(envoy_clusters.UpstreamBindConfig(InPassThroughIPv4, 0))
}
}
switch protocol {
case core_mesh.ProtocolHTTP:
clusterBuilder.Configure(envoy_clusters.Http())
case core_mesh.ProtocolHTTP2, core_mesh.ProtocolGRPC:
clusterBuilder.Configure(envoy_clusters.Http2())
}
envoyCluster, err := clusterBuilder.Build()
if err != nil {
return nil, errors.Wrapf(err, "%s: could not generate cluster %s", validators.RootedAt("dataplane").Field("networking").Field("inbound").Index(i), localClusterName)
}
resources.Add(&core_xds.Resource{
Name: localClusterName,
Resource: envoyCluster,
Origin: OriginInbound,
})
cluster := envoy_common.NewCluster(envoy_common.WithService(localClusterName))
routes := envoy_common.Routes{}
// Add the default fall-back route
routes = append(routes, envoy_common.NewRoute(envoy_common.WithCluster(cluster)))
// generate LDS resource
service := iface.GetService()
inboundListenerName := envoy_names.GetInboundListenerName(endpoint.DataplaneIP, endpoint.DataplanePort)
filterChainBuilder := func(serverSideMTLS bool) *envoy_listeners.FilterChainBuilder {
filterChainBuilder := envoy_listeners.NewFilterChainBuilder(proxy.APIVersion, envoy_common.AnonymousResource)
switch protocol {
case core_mesh.ProtocolTriple:
// TODO: implement the logic of Triple
// currently, we use the tcp proxy for the triple protocol
filterChainBuilder.
Configure(envoy_listeners.TripleConnectionManager()).
Configure(envoy_listeners.TcpProxyDeprecated(localClusterName, envoy_common.NewCluster(envoy_common.WithService(localClusterName))))
// configuration for HTTP case
case core_mesh.ProtocolHTTP, core_mesh.ProtocolHTTP2:
filterChainBuilder.
Configure(envoy_listeners.HttpConnectionManager(localClusterName, true)).
Configure(envoy_listeners.HttpInboundRoutes(service, routes))
case core_mesh.ProtocolGRPC:
filterChainBuilder.
Configure(envoy_listeners.HttpConnectionManager(localClusterName, true)).
Configure(envoy_listeners.GrpcStats()).
Configure(envoy_listeners.HttpInboundRoutes(service, routes))
case core_mesh.ProtocolKafka:
filterChainBuilder.
Configure(envoy_listeners.Kafka(localClusterName)).
Configure(envoy_listeners.TcpProxyDeprecated(localClusterName, envoy_common.NewCluster(envoy_common.WithService(localClusterName))))
case core_mesh.ProtocolTCP:
fallthrough
default:
// configuration for non-HTTP cases
filterChainBuilder.Configure(envoy_listeners.TcpProxyDeprecated(localClusterName, envoy_common.NewCluster(envoy_common.WithService(localClusterName))))
}
return filterChainBuilder
}
listenerBuilder := envoy_listeners.NewInboundListenerBuilder(proxy.APIVersion, endpoint.DataplaneIP, endpoint.DataplanePort, core_xds.SocketAddressProtocolTCP).
Configure(envoy_listeners.TagsMetadata(iface.GetTags()))
listenerBuilder.Configure(envoy_listeners.FilterChain(filterChainBuilder(false)))
inboundListener, err := listenerBuilder.Build()
if err != nil {
return nil, errors.Wrapf(err, "%s: could not generate listener %s", validators.RootedAt("dataplane").Field("networking").Field("inbound").Index(i), inboundListenerName)
}
resources.Add(&core_xds.Resource{
Name: inboundListenerName,
Resource: inboundListener,
Origin: OriginInbound,
})
}
return resources, nil
}