Skip to content
Open
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
26 changes: 22 additions & 4 deletions cmd/all_in_one.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package cmd
import (
"context"
"fmt"
"net"
"net/url"
"os"
"strings"
Expand Down Expand Up @@ -218,7 +219,7 @@ func (s *allCmdParam) run(ctx context.Context) error {

eg, ctx := errgroup.WithContext(ctx)
cfgCtl := util.NewRestartOnChange[*config.Config]()
runner, err := pomerium_ctrl.NewPomeriumRunner(s.cfg, cfgCtl.OnConfigUpdated)
runner, err := pomerium_ctrl.NewPomeriumRunner(s.cfg, cfgCtl.OnConfigUpdated, s.syncAPIURL)
if err != nil {
return fmt.Errorf("preparing to run pomerium: %w", err)
}
Expand Down Expand Up @@ -339,7 +340,13 @@ func (s *allCmdParam) buildController(ctx context.Context, cfg *config.Config) (
client := databroker.NewDataBrokerServiceClient(conn)
var reconciler pomerium.Reconciler
if s.syncAPIURL != "" {
reconciler = pomerium.NewAPIReconciler(s.syncAPIURL, s.syncAPIToken, s.cfg.Options)
_, port, err := net.SplitHostPort(s.cfg.Options.Addr)
if err != nil {
return nil, fmt.Errorf("couldn't get server address port: %w", err)
}
dialAddressOverride := net.JoinHostPort("localhost", port)
reconciler = pomerium.NewAPIReconciler(
s.syncAPIURL, s.syncAPIToken, s.cfg.Options, dialAddressOverride)
} else {
reconciler = pomerium.NewDataBrokerReconciler(client, s.dumpConfigDiff)
}
Expand All @@ -365,9 +372,14 @@ func (s *allCmdParam) buildController(ctx context.Context, cfg *config.Config) (
return c, nil
}

type bootstrapReconciler interface {
pomerium.ConfigReconciler
pomerium.IngressReconciler
}

// runBootstrapConfigController runs a controller that only listens to changes in SettingsCRD
// related to pomerium bootstrap parameters
func (s *allCmdParam) runBootstrapConfigController(ctx context.Context, reconciler pomerium.ConfigReconciler) error {
func (s *allCmdParam) runBootstrapConfigController(ctx context.Context, reconciler bootstrapReconciler) error {
scheme, err := getScheme()
if err != nil {
return err
Expand All @@ -389,10 +401,16 @@ func (s *allCmdParam) runBootstrapConfigController(ctx context.Context, reconcil
if host, err := os.Hostname(); err == nil {
name = fmt.Sprintf("%s pod/%s", name, host)
}
// TODO: do we need to disable the bootstrap config controller when syncing via the API?
if err := settings.NewSettingsController(mgr, reconciler, s.settings, name, false, health_ctrl.SettingsBootstrapReconciler); err != nil {
return fmt.Errorf("settings controller: %w", err)
}
if s.syncAPIURL != "" {
// When using the sync API in all-in-one mode, also register a bootstrap
// ingress controller, in case we need a route to the sync API itself.
if err := ingress.NewIngressController(mgr, reconciler); err != nil {
return fmt.Errorf("ingress controller: %w", err)
}
}
return mgr.Start(ctx)
}

Expand Down
2 changes: 1 addition & 1 deletion cmd/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ func (s *controllerCmd) buildController(ctx context.Context) (*controllers.Contr

if s.SyncAPIURL != "" {
c.Reconciler = pomerium.NewAPIReconciler(
s.SyncAPIURL, s.SyncAPIToken, pomerium_config.NewDefaultOptions())
s.SyncAPIURL, s.SyncAPIToken, pomerium_config.NewDefaultOptions(), "")
c.MgrOpts.LeaderElection = true
c.MgrOpts.LeaderElectionID = s.leaderElectionID
c.MgrOpts.LeaderElectionNamespace = s.leaderElectionNamespace
Expand Down
104 changes: 103 additions & 1 deletion pomerium/ctrl/bootstrap.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,12 @@ import (
"k8s.io/apimachinery/pkg/types"
"sigs.k8s.io/controller-runtime/pkg/log"

"github.com/pomerium/pomerium/config"
configpb "github.com/pomerium/pomerium/pkg/grpc/config"

"github.com/pomerium/ingress-controller/internal/filemgr"
"github.com/pomerium/ingress-controller/model"
"github.com/pomerium/pomerium/config"
"github.com/pomerium/ingress-controller/pomerium"
)

// Apply prepares a minimal bootstrap configuration for Pomerium
Expand Down Expand Up @@ -211,3 +214,102 @@ func applySecrets(_ context.Context, dst *config.Options, src *model.Config) err

return nil
}

// ApplyAdditional propagates additional core bootstrap settings, needed when
// running all-in-one mode together with Enterprise API sync.
func ApplyAdditional(ctx context.Context, dst *config.Options, src *model.Config) error {
var pbConfig configpb.Config
if err := pomerium.ApplyConfig(ctx, &pbConfig, src); err != nil {
return err
}
dst.ApplySettings(ctx, nil, pbConfig.Settings)
return nil
}

// bootstrapIngressManager tracks Ingress resources matching a particular host.
type bootstrapIngressManager struct {
host string
routes map[types.NamespacedName][]config.Policy
updateFn func(context.Context)
}

func newBootstrapIngressManager(host string, updateFn func(context.Context)) *bootstrapIngressManager {
return &bootstrapIngressManager{
host: host,
routes: make(map[types.NamespacedName][]config.Policy),
updateFn: updateFn,
}
}

func (m *bootstrapIngressManager) addRoutesToConfig(cfg *config.Config) {
if m == nil {
return
}
for _, routes := range m.routes {
cfg.Options.Routes = append(cfg.Options.Routes, routes...)
}
}

func (m *bootstrapIngressManager) matchesHost(ic *model.IngressConfig) bool {
for _, rule := range ic.Spec.Rules {
if rule.Host == m.host {
return true
}
}
return false
}

func (m *bootstrapIngressManager) deleteRoutes(ctx context.Context, name types.NamespacedName) (changes bool) {
changes = len(m.routes[name]) > 0
delete(m.routes, name)
if changes {
m.updateFn(ctx)
}
return changes
}

func (m *bootstrapIngressManager) addRoutes(ctx context.Context, ics ...*model.IngressConfig) (changes bool, err error) {
for _, ic := range ics {
if !m.matchesHost(ic) {
continue
}
routes, err := pomerium.IngressToRoutes(ctx, ic)
if err != nil {
return changes, err
}
m.routes[ic.GetIngressNamespacedName()] = routes
changes = true
}
if changes {
m.updateFn(ctx)
}
return changes, nil
}

func (m *bootstrapIngressManager) Upsert(ctx context.Context, ic *model.IngressConfig) (changes bool, err error) {
// If this Ingress no longer matches the specific host, remove any
// previous matching routes.
if !m.matchesHost(ic) {
changes = m.deleteRoutes(ctx, ic.GetIngressNamespacedName())
return changes, nil
}
return m.addRoutes(ctx, ic)
}

// Set adds bootstrap routes for any ingresses matching the sync API URL.
func (m *bootstrapIngressManager) Set(ctx context.Context, ics []*model.IngressConfig) (changes bool, err error) {
if len(m.routes) > 0 {
changes = true
}
clear(m.routes)

added, err := m.addRoutes(ctx, ics...)
changes = changes || added
return changes, err
}

// Delete removes any bootstrap routes corresponding to the given ingress name.
func (m *bootstrapIngressManager) Delete(ctx context.Context, namespacedName types.NamespacedName) (changes bool, err error) {
changes = m.deleteRoutes(ctx, namespacedName)
return changes, nil
}
Loading
Loading