Skip to content

Commit

Permalink
Merge pull request #311 from istio-ecosystem/upstream-refresh-0810
Browse files Browse the repository at this point in the history
Upstream refresh 0810
  • Loading branch information
shriramsharma authored Aug 9, 2024
2 parents b335f01 + fd4da91 commit eae41b7
Show file tree
Hide file tree
Showing 53 changed files with 3,049 additions and 680 deletions.
13 changes: 9 additions & 4 deletions admiral/cmd/admiral/cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,8 @@ func GetRootCmd(args []string) *cobra.Command {
err error
remoteRegistry *clusters.RemoteRegistry
)
if params.HAMode == common.HAController {
remoteRegistry, err = clusters.InitAdmiralHA(ctx, params)
if params.AdmiralOperatorMode {
remoteRegistry, err = clusters.InitAdmiralOperator(ctx, params)
} else {
remoteRegistry, err = clusters.InitAdmiral(ctx, params)
}
Expand Down Expand Up @@ -209,8 +209,6 @@ func GetRootCmd(args []string) *cobra.Command {
rootCmd.PersistentFlags().IntVar(&params.ExportToMaxNamespaces, "exportto_max_namespaces", 35, "Max number of namespaces to write in ExportTo field before just replacing with *")

// Admiral HA flags
rootCmd.PersistentFlags().StringVar(&params.HAMode, "ha_mode", "",
"HA Mode changes the functionality of admiral. Valid options are: "+common.HAController)
rootCmd.PersistentFlags().IntVar(&params.DNSRetries, "dns_retries", 3, "number of retries for dns resolution")
rootCmd.PersistentFlags().IntVar(&params.DNSTimeoutMs, "dns_timeout_ms", 1000, "ttl for dns resolution timeout")
rootCmd.PersistentFlags().StringVar(&params.DnsConfigFile, "dns_config_file", "/etc/resolv.conf", "the dns config file to use")
Expand Down Expand Up @@ -242,6 +240,13 @@ func GetRootCmd(args []string) *cobra.Command {
rootCmd.PersistentFlags().BoolVar(&params.EnableSyncIstioResourcesToSourceClusters, "enable_sync_istio_resources_to_source_clusters", true, "Enable/Disable Sync of Istio Resources to Source Clusters")
rootCmd.PersistentFlags().BoolVar(&params.AdmiralStateSyncerMode, "admiral_state_syncer_mode", false, "Enable/Disable admiral to run as state syncer only")
rootCmd.PersistentFlags().Int64Var(&params.DefaultWarmupDurationSecs, "default_warmup_duration_in_seconds", 45, "The default value for the warmupDurationSecs to be used on Destination Rules created by admiral")

rootCmd.PersistentFlags().BoolVar(&params.EnableGenerationCheck, "enable_generation_check", true, "Enable/Disable Generation Check")

//Admiral 2.0 flags
rootCmd.PersistentFlags().BoolVar(&params.AdmiralOperatorMode, "admiral_operator_mode", false, "Enable/Disable admiral operator functionality")
rootCmd.PersistentFlags().StringVar(&params.OperatorSyncNamespace, "operator_sync_namespace", "admiral-operator-sync",
"Namespace in which Admiral Operator will put its generated configurations")
return rootCmd
}

Expand Down
4 changes: 4 additions & 0 deletions admiral/pkg/client/loader/client_loader.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package loader

import (
argo "github.com/argoproj/argo-rollouts/pkg/client/clientset/versioned"
admiralapi "github.com/istio-ecosystem/admiral-api/pkg/client/clientset/versioned"
admiral "github.com/istio-ecosystem/admiral/admiral/pkg/client/clientset/versioned"
istio "istio.io/client-go/pkg/clientset/versioned"
"k8s.io/client-go/kubernetes"
Expand All @@ -14,6 +15,9 @@ type ClientLoader interface {
LoadAdmiralClientFromPath(path string) (admiral.Interface, error)
LoadAdmiralClientFromConfig(config *rest.Config) (admiral.Interface, error)

LoadAdmiralApiClientFromPath(path string) (admiralapi.Interface, error)
LoadAdmiralApiClientFromConfig(config *rest.Config) (admiralapi.Interface, error)

LoadIstioClientFromPath(path string) (istio.Interface, error)
LoadIstioClientFromConfig(config *rest.Config) (istio.Interface, error)

Expand Down
17 changes: 17 additions & 0 deletions admiral/pkg/client/loader/fake_loader.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package loader
import (
argo "github.com/argoproj/argo-rollouts/pkg/client/clientset/versioned"
argofake "github.com/argoproj/argo-rollouts/pkg/client/clientset/versioned/fake"
admiralapi "github.com/istio-ecosystem/admiral-api/pkg/client/clientset/versioned"
admiralapifake "github.com/istio-ecosystem/admiral-api/pkg/client/clientset/versioned/fake"
admiral "github.com/istio-ecosystem/admiral/admiral/pkg/client/clientset/versioned"
admiralfake "github.com/istio-ecosystem/admiral/admiral/pkg/client/clientset/versioned/fake"
istio "istio.io/client-go/pkg/clientset/versioned"
Expand All @@ -16,12 +18,14 @@ const FakePrefix = "fake"

// fake clients for the Admiral cluster
var FakeAdmiralClient admiral.Interface = admiralfake.NewSimpleClientset()
var FakeAdmiralApiClient admiralapi.Interface = admiralapifake.NewSimpleClientset()
var FakeIstioClient istio.Interface = istiofake.NewSimpleClientset()
var FakeKubeClient kubernetes.Interface = kubefake.NewSimpleClientset()
var FakeArgoClient argo.Interface = argofake.NewSimpleClientset()

// fake clients for dependent clusters
var FakeAdmiralClientMap map[string]admiral.Interface = make(map[string]admiral.Interface)
var FakeAdmiralApiClientMap map[string]admiralapi.Interface = make(map[string]admiralapi.Interface)
var FakeIstioClientMap map[string]istio.Interface = make(map[string]istio.Interface)
var FakeKubeClientMap map[string]kubernetes.Interface = make(map[string]kubernetes.Interface)
var FakeArgoClientMap map[string]argo.Interface = make(map[string]argo.Interface)
Expand All @@ -48,6 +52,19 @@ func (*FakeClientLoader) LoadAdmiralClientFromConfig(config *rest.Config) (admir
return admiralClient, nil
}

func (loader *FakeClientLoader) LoadAdmiralApiClientFromPath(path string) (admiralapi.Interface, error) {
return FakeAdmiralApiClient, nil
}

func (loader *FakeClientLoader) LoadAdmiralApiClientFromConfig(config *rest.Config) (admiralapi.Interface, error) {
admiralApiClient, ok := FakeAdmiralApiClientMap[config.Host]
if !ok {
admiralApiClient = admiralapifake.NewSimpleClientset()
FakeAdmiralApiClientMap[config.Host] = admiralApiClient
}
return admiralApiClient, nil
}

func (loader *FakeClientLoader) LoadIstioClientFromPath(path string) (istio.Interface, error) {
return FakeIstioClient, nil
}
Expand Down
14 changes: 13 additions & 1 deletion admiral/pkg/client/loader/kube_loader.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ package loader

import (
"fmt"

argo "github.com/argoproj/argo-rollouts/pkg/client/clientset/versioned"
admiralapi "github.com/istio-ecosystem/admiral-api/pkg/client/clientset/versioned"
admiral "github.com/istio-ecosystem/admiral/admiral/pkg/client/clientset/versioned"
log "github.com/sirupsen/logrus"
istio "istio.io/client-go/pkg/clientset/versioned"
Expand Down Expand Up @@ -34,6 +34,18 @@ func (*KubeClientLoader) LoadAdmiralClientFromConfig(config *rest.Config) (admir
return admiral.NewForConfig(config)
}

func (loader *KubeClientLoader) LoadAdmiralApiClientFromPath(kubeConfigPath string) (admiralapi.Interface, error) {
config, err := getConfig(kubeConfigPath)
if err != nil || config == nil {
return nil, err
}
return loader.LoadAdmiralApiClientFromConfig(config)
}

func (loader *KubeClientLoader) LoadAdmiralApiClientFromConfig(config *rest.Config) (admiralapi.Interface, error) {
return admiralapi.NewForConfig(config)
}

func (loader *KubeClientLoader) LoadIstioClientFromPath(kubeConfigPath string) (istio.Interface, error) {
config, err := getConfig(kubeConfigPath)
if err != nil || config == nil {
Expand Down
186 changes: 186 additions & 0 deletions admiral/pkg/clusters/configwriter.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
package clusters

import (
"errors"
"github.com/istio-ecosystem/admiral/admiral/pkg/controller/admiral"
"github.com/istio-ecosystem/admiral/admiral/pkg/controller/common"
"github.com/istio-ecosystem/admiral/admiral/pkg/registry"
"github.com/istio-ecosystem/admiral/admiral/pkg/util"
"github.com/sirupsen/logrus"
networkingV1Alpha3 "istio.io/api/networking/v1alpha3"
"sort"
"strconv"
"strings"
)

// IstioSEBuilder is an interface to construct Service Entry objects
// from IdentityConfig objects. It can construct multiple Service Entries
// from an IdentityConfig or construct just one given a IdentityConfigEnvironment.
type IstioSEBuilder interface {
BuildServiceEntriesFromIdentityConfig(ctxLogger *logrus.Entry, event admiral.EventType, identityConfig registry.IdentityConfig) ([]*networkingV1Alpha3.ServiceEntry, error)
}

type ServiceEntryBuilder struct {
RemoteRegistry *RemoteRegistry
ClientCluster string
}

// BuildServiceEntriesFromIdentityConfig builds service entries to write to the client cluster
// by looping through the IdentityConfig clusters and environments to get spec information. It
// builds one SE per environment per cluster the identity is deployed in.
func (b *ServiceEntryBuilder) BuildServiceEntriesFromIdentityConfig(ctxLogger *logrus.Entry, identityConfig registry.IdentityConfig) ([]*networkingV1Alpha3.ServiceEntry, error) {
var (
identity = identityConfig.IdentityName
seMap = map[string]*networkingV1Alpha3.ServiceEntry{}
serviceEntries = []*networkingV1Alpha3.ServiceEntry{}
err error
)
ctxLogger.Infof(common.CtxLogFormat, "buildServiceEntry", identity, common.GetSyncNamespace(), b.ClientCluster, "Beginning to build the SE spec")
ingressEndpoints, err := getIngressEndpoints(identityConfig.Clusters)
if err != nil {
return serviceEntries, err
}
_, isServerOnClientCluster := ingressEndpoints[b.ClientCluster]
dependentNamespaces, err := getExportTo(ctxLogger, b.RemoteRegistry.RegistryClient, b.ClientCluster, isServerOnClientCluster, identityConfig.ClientAssets)
if err != nil {
return serviceEntries, err
}
for _, identityConfigCluster := range identityConfig.Clusters {
serverCluster := identityConfigCluster.Name
for _, identityConfigEnvironment := range identityConfigCluster.Environment {
env := identityConfigEnvironment.Name
var tmpSe *networkingV1Alpha3.ServiceEntry
ep, err := getServiceEntryEndpoint(ctxLogger, b.ClientCluster, serverCluster, ingressEndpoints, identityConfigEnvironment)
if err != nil {
return serviceEntries, err
}
ports, err := getServiceEntryPorts(identityConfigEnvironment)
if err != nil {
return serviceEntries, err
}
if se, ok := seMap[env]; !ok {
tmpSe = &networkingV1Alpha3.ServiceEntry{
Hosts: []string{common.GetCnameVal([]string{env, strings.ToLower(identity), common.GetHostnameSuffix()})},
Ports: ports,
Location: networkingV1Alpha3.ServiceEntry_MESH_INTERNAL,
Resolution: networkingV1Alpha3.ServiceEntry_DNS,
SubjectAltNames: []string{common.SpiffePrefix + common.GetSANPrefix() + common.Slash + identity},
Endpoints: []*networkingV1Alpha3.WorkloadEntry{ep},
ExportTo: dependentNamespaces,
}
} else {
tmpSe = se
tmpSe.Endpoints = append(tmpSe.Endpoints, ep)
}
serviceEntries = append(serviceEntries, tmpSe)
}
}
return serviceEntries, err
}

// getIngressEndpoints constructs the endpoint of the ingress gateway/remote endpoint for an identity
// by reading the information directly from the IdentityConfigCluster.
func getIngressEndpoints(clusters []registry.IdentityConfigCluster) (map[string]*networkingV1Alpha3.WorkloadEntry, error) {
ingressEndpoints := map[string]*networkingV1Alpha3.WorkloadEntry{}
var err error
for _, cluster := range clusters {
portNumber, err := strconv.ParseInt(cluster.IngressPort, 10, 64)
if err != nil {
return ingressEndpoints, err
}
ingressEndpoint := &networkingV1Alpha3.WorkloadEntry{
Address: cluster.IngressEndpoint,
Locality: cluster.Locality,
Ports: map[string]uint32{cluster.IngressPortName: uint32(portNumber)},
Labels: map[string]string{"security.istio.io/tlsMode": "istio"},
}
ingressEndpoints[cluster.Name] = ingressEndpoint
}
return ingressEndpoints, err
}

// getServiceEntryPorts constructs the ServicePorts of the service entry that should be built
// for the given identityConfigEnvironment.
func getServiceEntryPorts(identityConfigEnvironment registry.IdentityConfigEnvironment) ([]*networkingV1Alpha3.ServicePort, error) {
port := &networkingV1Alpha3.ServicePort{Number: uint32(common.DefaultServiceEntryPort), Name: util.Http, Protocol: util.Http}
var err error
if len(identityConfigEnvironment.Ports) == 0 {
err = errors.New("identityConfigEnvironment had no ports for: " + identityConfigEnvironment.Name)
}
for _, servicePort := range identityConfigEnvironment.Ports {
//TODO: 8090 is supposed to be set as the common.SidecarEnabledPorts (includeInboundPorts) which we check that in the rollout, but we don't have that information here so assume it is 8090
if servicePort.TargetPort.IntValue() == 8090 {
protocol := util.GetPortProtocol(servicePort.Name)
port.Name = protocol
port.Protocol = protocol
}
}
ports := []*networkingV1Alpha3.ServicePort{port}
return ports, err
}

// getServiceEntryEndpoint constructs the remote or local endpoints of the service entry that
// should be built for the given identityConfigEnvironment.
func getServiceEntryEndpoint(ctxLogger *logrus.Entry, clientCluster string, serverCluster string, ingressEndpoints map[string]*networkingV1Alpha3.WorkloadEntry, identityConfigEnvironment registry.IdentityConfigEnvironment) (*networkingV1Alpha3.WorkloadEntry, error) {
//TODO: Verify Local and Remote Endpoints are constructed correctly
var err error
endpoint := ingressEndpoints[serverCluster]
tmpEp := endpoint.DeepCopy()
tmpEp.Labels["type"] = identityConfigEnvironment.Type
if clientCluster == serverCluster {
//Local Endpoint Address if the identity is deployed on the same cluster as it's client and the endpoint is the remote endpoint for the cluster
tmpEp.Address = identityConfigEnvironment.ServiceName + common.Sep + identityConfigEnvironment.Namespace + common.GetLocalDomainSuffix()
for _, servicePort := range identityConfigEnvironment.Ports {
//There should only be one mesh port here (http-service-mesh), but we are preserving ability to have multiple ports
protocol := util.GetPortProtocol(servicePort.Name)
if _, ok := tmpEp.Ports[protocol]; ok {
tmpEp.Ports[protocol] = uint32(servicePort.Port)
ctxLogger.Infof(common.CtxLogFormat, "LocalMeshPort", servicePort.Port, "", serverCluster, "Protocol: "+protocol)
} else {
err = errors.New("failed to get Port for protocol: " + protocol)
}
}
}
return tmpEp, err
}

// getExportTo constructs a sorted list of unique namespaces for a given cluster, client assets,
// and cname, where each namespace is where a client asset of the cname is deployed on the cluster. If the cname
// is also deployed on the cluster then the istio-system namespace is also in the list.
func getExportTo(ctxLogger *logrus.Entry, registryClient registry.IdentityConfiguration, clientCluster string, isServerOnClientCluster bool, clientAssets []map[string]string) ([]string, error) {
clientNamespaces := []string{}
var err error
var clientIdentityConfig registry.IdentityConfig
for _, clientAsset := range clientAssets {
// For each client asset of cname, we fetch its identityConfig
clientIdentityConfig, err = registryClient.GetIdentityConfigByIdentityName(clientAsset["name"], ctxLogger)
if err != nil {
ctxLogger.Infof(common.CtxLogFormat, "buildServiceEntry", clientAsset["name"], common.GetSyncNamespace(), "", "could not fetch IdentityConfig: "+err.Error())
continue
}
for _, clientIdentityConfigCluster := range clientIdentityConfig.Clusters {
// For each cluster the client asset is deployed on, we check if that cluster is the client cluster we are writing to
if clientCluster == clientIdentityConfigCluster.Name {
for _, clientIdentityConfigEnvironment := range clientIdentityConfigCluster.Environment {
// For each environment of the client asset on the client cluster, we add the namespace to our list
//Do we need to check if ENV matches here for exportTo? Currently we don't, but we could
clientNamespaces = append(clientNamespaces, clientIdentityConfigEnvironment.Namespace)
}
}
}
}
if isServerOnClientCluster {
clientNamespaces = append(clientNamespaces, common.NamespaceIstioSystem)
}
if len(clientNamespaces) > common.GetExportToMaxNamespaces() {
clientNamespaces = []string{"*"}
}
sort.Strings(clientNamespaces)
var dedupClientNamespaces []string
for i := 0; i < len(clientNamespaces); i++ {
if i == 0 || clientNamespaces[i] != clientNamespaces[i-1] {
dedupClientNamespaces = append(dedupClientNamespaces, clientNamespaces[i])
}
}
return clientNamespaces, err
}
Loading

0 comments on commit eae41b7

Please sign in to comment.