Skip to content

Commit 233ae4c

Browse files
committed
Added support for istio gateways for OpenShift deployments.
1 parent 0ac1e8d commit 233ae4c

5 files changed

Lines changed: 339 additions & 12 deletions

File tree

cbdcconfig/config.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -67,10 +67,11 @@ type Config_Docker struct {
6767
}
6868

6969
type Config_K8s struct {
70-
Enabled StringBool `yaml:"enabled"`
71-
CaoTools string `yaml:"cao-tools"`
72-
KubeConfig string `yaml:"kubeconfig"`
73-
Context string `yaml:"context"`
70+
Enabled StringBool `yaml:"enabled"`
71+
CaoTools string `yaml:"cao-tools"`
72+
KubeConfig string `yaml:"kubeconfig"`
73+
Context string `yaml:"context"`
74+
SharedGateway string `yaml:"shared-gateway"`
7475
}
7576

7677
type Config_GitHub struct {

cmd/cmdhelper.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -178,8 +178,9 @@ func (h *CmdHelper) getCaoDeployer(ctx context.Context) (*caodeploy.Deployer, er
178178
}
179179

180180
deployer, err := caodeploy.NewDeployer(&caodeploy.NewDeployerOptions{
181-
Logger: logger,
182-
Client: caoCtrl,
181+
Logger: logger,
182+
Client: caoCtrl,
183+
SharedGateway: config.K8s.SharedGateway,
183184
})
184185
if err != nil {
185186
return nil, errors.Wrap(err, "failed to initializer deployer")

cmd/init.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -558,6 +558,7 @@ var initCmd = &cobra.Command{
558558
fmt.Printf(" CaoTools: %s\n", curConfig.K8s.CaoTools)
559559
fmt.Printf(" KubeConfig: %s\n", curConfig.K8s.KubeConfig)
560560
fmt.Printf(" Context: %s\n", curConfig.K8s.Context)
561+
fmt.Printf(" SharedGateway: %s\n", curConfig.K8s.SharedGateway)
561562
}
562563
{
563564
fmt.Printf("-- K8s Configuration\n")
@@ -572,6 +573,7 @@ var initCmd = &cobra.Command{
572573
k8sCaoTools := curConfig.K8s.CaoTools
573574
k8sKubeConfig := curConfig.K8s.KubeConfig
574575
k8sKubeContext := curConfig.K8s.Context
576+
k8sSharedGateway := curConfig.K8s.SharedGateway
575577

576578
for {
577579
if flagDisableK8s {
@@ -759,13 +761,40 @@ var initCmd = &cobra.Command{
759761
}
760762
}
761763

764+
// Check for a shared Istio Gateway in cbdc-shared namespace
765+
fmt.Printf("Checking for shared Istio gateway in cbdc-shared namespace...\n")
766+
gateways, err := caoCtrl.ListIstioGateways(ctx, "cbdc-shared")
767+
if err != nil {
768+
fmt.Printf("No shared gateway found in cbdc-shared namespace, will use OpenShift Routes for ingress\n")
769+
} else if len(gateways) == 0 {
770+
fmt.Printf("No shared gateway found in cbdc-shared namespace, will use OpenShift Routes for ingress\n")
771+
} else {
772+
gw := gateways[0]
773+
gwName := gw.GetName()
774+
namespacedName := fmt.Sprintf("cbdc-shared/%s", gwName)
775+
776+
annotations := gw.GetAnnotations()
777+
baseDomain := ""
778+
if annotations != nil {
779+
baseDomain = annotations["cbdc.couchbase.com/base-domain"]
780+
}
781+
782+
if baseDomain == "" {
783+
fmt.Printf("WARNING: Shared gateway %s found but missing cbdc.couchbase.com/base-domain annotation\n", namespacedName)
784+
} else {
785+
fmt.Printf("Found shared gateway: %s (base-domain: %s)\n", namespacedName, baseDomain)
786+
k8sSharedGateway = namespacedName
787+
}
788+
}
789+
762790
break
763791
}
764792

765793
curConfig.K8s.Enabled.Set(k8sEnabled)
766794
curConfig.K8s.CaoTools = k8sCaoTools
767795
curConfig.K8s.KubeConfig = k8sKubeConfig
768796
curConfig.K8s.Context = k8sKubeContext
797+
curConfig.K8s.SharedGateway = k8sSharedGateway
769798
saveConfig()
770799
}
771800

deployment/caodeploy/deployer.go

Lines changed: 160 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -48,21 +48,24 @@ func withMgmtx[T any](d *Deployer, ctx context.Context, clusterID string, fn fun
4848
}
4949

5050
type Deployer struct {
51-
logger *zap.Logger
52-
client *caocontrol.Controller
51+
logger *zap.Logger
52+
client *caocontrol.Controller
53+
sharedGateway string
5354
}
5455

5556
var _ deployment.Deployer = (*Deployer)(nil)
5657

5758
type NewDeployerOptions struct {
58-
Logger *zap.Logger
59-
Client *caocontrol.Controller
59+
Logger *zap.Logger
60+
Client *caocontrol.Controller
61+
SharedGateway string
6062
}
6163

6264
func NewDeployer(opts *NewDeployerOptions) (*Deployer, error) {
6365
return &Deployer{
64-
logger: opts.Logger,
65-
client: opts.Client,
66+
logger: opts.Logger,
67+
client: opts.Client,
68+
sharedGateway: opts.SharedGateway,
6669
}, nil
6770
}
6871

@@ -553,6 +556,104 @@ func (d *Deployer) RemoveAll(ctx context.Context) error {
553556
return nil
554557
}
555558

559+
func (d *Deployer) getSharedGatewayBaseDomain(ctx context.Context) (string, error) {
560+
baseDomain, err := d.client.GetIstioGatewayAnnotation(ctx, d.sharedGateway, "cbdc.couchbase.com/base-domain")
561+
if err != nil {
562+
return "", errors.Wrap(err, "failed to get shared gateway base domain")
563+
}
564+
if baseDomain == "" {
565+
return "", errors.New("shared gateway is missing cbdc.couchbase.com/base-domain annotation")
566+
}
567+
return baseDomain, nil
568+
}
569+
570+
func (d *Deployer) enableIngressesViaVirtualService(ctx context.Context, clusterID string, namespace string) error {
571+
baseDomain, err := d.getSharedGatewayBaseDomain(ctx)
572+
if err != nil {
573+
return err
574+
}
575+
576+
cngHost := fmt.Sprintf("cng-%s.%s", clusterID, baseDomain)
577+
578+
_, err = d.client.GetService(ctx, namespace, CngServiceName)
579+
if err != nil {
580+
d.logger.Info("no cng service detected, skipping cng virtual service")
581+
} else {
582+
d.logger.Info("creating cng virtual service", zap.String("host", cngHost))
583+
584+
err = d.client.CreateVirtualService(ctx, namespace, "cng", map[string]interface{}{
585+
"hosts": []interface{}{cngHost},
586+
"gateways": []interface{}{d.sharedGateway},
587+
"http": []interface{}{
588+
map[string]interface{}{
589+
"route": []interface{}{
590+
map[string]interface{}{
591+
"destination": map[string]interface{}{
592+
"host": CngServiceName,
593+
"port": map[string]interface{}{
594+
"number": 443,
595+
},
596+
},
597+
},
598+
},
599+
},
600+
},
601+
})
602+
if err != nil {
603+
return errors.Wrap(err, "failed to create cng virtual service")
604+
}
605+
606+
// CNG expects TLS connections, but the gateway terminates TLS.
607+
// Create a DestinationRule to originate TLS to CNG.
608+
d.logger.Info("creating cng destination rule for TLS origination")
609+
610+
err = d.client.CreateDestinationRule(ctx, namespace, "cng-tls", map[string]interface{}{
611+
"host": CngServiceName,
612+
"trafficPolicy": map[string]interface{}{
613+
"connectionPool": map[string]interface{}{
614+
"http": map[string]interface{}{
615+
"useClientProtocol": true,
616+
},
617+
},
618+
"tls": map[string]interface{}{
619+
"mode": "SIMPLE",
620+
"insecureSkipVerify": true,
621+
},
622+
},
623+
})
624+
if err != nil {
625+
return errors.Wrap(err, "failed to create cng destination rule")
626+
}
627+
}
628+
629+
uiHost := fmt.Sprintf("ui-%s.%s", clusterID, baseDomain)
630+
d.logger.Info("creating ui virtual service", zap.String("host", uiHost))
631+
632+
err = d.client.CreateVirtualService(ctx, namespace, "ui", map[string]interface{}{
633+
"hosts": []interface{}{uiHost},
634+
"gateways": []interface{}{d.sharedGateway},
635+
"http": []interface{}{
636+
map[string]interface{}{
637+
"route": []interface{}{
638+
map[string]interface{}{
639+
"destination": map[string]interface{}{
640+
"host": UiServiceName,
641+
"port": map[string]interface{}{
642+
"number": 8091,
643+
},
644+
},
645+
},
646+
},
647+
},
648+
},
649+
})
650+
if err != nil {
651+
return errors.Wrap(err, "failed to create ui virtual service")
652+
}
653+
654+
return nil
655+
}
656+
556657
func (d *Deployer) EnableIngresses(ctx context.Context, clusterID string) error {
557658
isOpenShift, err := d.client.IsOpenShift(ctx)
558659
if err != nil {
@@ -568,6 +669,10 @@ func (d *Deployer) EnableIngresses(ctx context.Context, clusterID string) error
568669
return err
569670
}
570671

672+
if d.sharedGateway != "" {
673+
return d.enableIngressesViaVirtualService(ctx, clusterID, namespace)
674+
}
675+
571676
_, err = d.client.GetRouteHost(ctx, namespace, "ui")
572677
if err != nil {
573678
d.logger.Info("creating ui route")
@@ -630,6 +735,37 @@ func (d *Deployer) DisableIngresses(ctx context.Context, clusterID string) error
630735
return err
631736
}
632737

738+
if d.sharedGateway != "" {
739+
allDeletesFailed := true
740+
741+
err = d.client.DeleteVirtualService(ctx, namespace, "cng")
742+
if err != nil {
743+
d.logger.Debug("failed to delete cng virtual service", zap.Error(err))
744+
} else {
745+
allDeletesFailed = false
746+
}
747+
748+
err = d.client.DeleteVirtualService(ctx, namespace, "ui")
749+
if err != nil {
750+
d.logger.Debug("failed to delete ui virtual service", zap.Error(err))
751+
} else {
752+
allDeletesFailed = false
753+
}
754+
755+
err = d.client.DeleteDestinationRule(ctx, namespace, "cng-tls")
756+
if err != nil {
757+
d.logger.Debug("failed to delete cng destination rule", zap.Error(err))
758+
} else {
759+
allDeletesFailed = false
760+
}
761+
762+
if allDeletesFailed {
763+
return errors.New("virtual service deletions failed")
764+
}
765+
766+
return nil
767+
}
768+
633769
allDeletesFailed := true
634770

635771
err = d.client.DeleteRoute(ctx, namespace, "ui")
@@ -742,6 +878,24 @@ func (d *Deployer) GetConnectInfo(ctx context.Context, clusterID string) (*deplo
742878
}
743879

744880
func (d *Deployer) GetIngressConnectInfo(ctx context.Context, clusterID string) (*deployment.ConnectInfo, error) {
881+
if d.sharedGateway != "" {
882+
baseDomain, err := d.getSharedGatewayBaseDomain(ctx)
883+
if err != nil {
884+
return nil, err
885+
}
886+
887+
cngHost := fmt.Sprintf("cng-%s.%s", clusterID, baseDomain)
888+
uiHost := fmt.Sprintf("ui-%s.%s", clusterID, baseDomain)
889+
890+
return &deployment.ConnectInfo{
891+
ConnStr: "",
892+
ConnStrTls: "",
893+
ConnStrCb2: fmt.Sprintf("couchbase2://%s:443", cngHost),
894+
Mgmt: "",
895+
MgmtTls: fmt.Sprintf("https://%s:443", uiHost),
896+
}, nil
897+
}
898+
745899
namespaceName, err := d.getClusterNamespace(ctx, clusterID)
746900
if err != nil {
747901
return nil, err

0 commit comments

Comments
 (0)