Skip to content

Commit

Permalink
Merge pull request #124 from orange-cloudfoundry/use-nats-instead-of-…
Browse files Browse the repository at this point in the history
…gorouter

use nats instead of gorouters to manage a routing table
  • Loading branch information
mdimiceli authored May 22, 2024
2 parents 9fe101f + 3a3e9f4 commit 625fbc9
Show file tree
Hide file tree
Showing 223 changed files with 39,919 additions and 295 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/goreleaser.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ jobs:
- name: set up go
uses: actions/setup-go@v5
with:
go-version: "1.21"
go-version: "1.22"

- name: cache go modules
uses: actions/cache@v4
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/unit-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:
- name: set up go
uses: actions/setup-go@v5
with:
go-version: "1.21"
go-version: "1.22"

- name: cache go modules
uses: actions/cache@v4
Expand Down
4 changes: 1 addition & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,13 +73,11 @@ This is useful for authentication purpose, for example:

### How does it work?

Promfetcher only needs [gorouter] and will read route table from it.
Promfetcher only needs [NATS](https://nats.io/) an infrastructure that allows data exchange, segmented in the form of messages (We call this a "message oriented middleware"). Promfetcher subscribes to NATS in order to receive messages about routes and then manages its own routing table in memory.

When asking metrics for an App, Promfetcher will asynchronously call all App instances
(provided by the gorouter routing table) metrics endpoint and merge them together with new labels.

[gorouter]: https://github.com/cloudfoundry/gorouter

Example, given an App with metrics from instance 0:

```
Expand Down
119 changes: 82 additions & 37 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,26 @@ import (
"github.com/orange-cloudfoundry/promfetcher/models"
)

type GorouterConfig struct {
Host string `yaml:"host"`
Port uint16 `yaml:"port"`
User string `yaml:"user"`
Pass string `yaml:"pass"`
type NatsConfig struct {
Hosts []NatsHost `yaml:"hosts"`
User string `yaml:"user"`
Pass string `yaml:"pass"`
TLSEnabled bool `yaml:"tls_enabled"`
CACerts string `yaml:"ca_certs"`
CAPool *x509.CertPool `yaml:"-"`
ClientAuthCertificate tls.Certificate `yaml:"-"`
TLSPem `yaml:",inline"` // embed to get cert_chain and private_key for client authentication
}

type NatsHost struct {
Hostname string
Port uint16
}

var defaultNatsConfig = NatsConfig{
Hosts: []NatsHost{{Hostname: "localhost", Port: 4222}},
User: "",
Pass: "",
}

type BackendConfig struct {
Expand All @@ -34,15 +49,6 @@ type BackendConfig struct {
TLSPem `yaml:",inline"` // embed to get cert_chain and private_key for client authentication
}

var defaultGoroutersConfig = []GorouterConfig{
{
Host: "localhost",
Port: 8080,
User: "",
Pass: "",
},
}

type BrokerConfig struct {
BrokerServiceID string `yaml:"broker_service_id"`
BrokerPlanID string `yaml:"broker_plan_id"`
Expand Down Expand Up @@ -92,16 +98,22 @@ type TLSPem struct {
}

type Config struct {
Gorouters []GorouterConfig `yaml:"gorouters,omitempty"`
Logging Log `yaml:"logging,omitempty"`
Port uint16 `yaml:"port,omitempty"`
HealthCheckPort uint16 `yaml:"health_check_port,omitempty"`
EnableSSL bool `yaml:"enable_ssl,omitempty"`
SSLCertificate tls.Certificate `yaml:"-"`
TLSPEM TLSPem `yaml:"tls_pem,omitempty"`
CACerts string `yaml:"ca_certs,omitempty"`
CAPool *x509.CertPool `yaml:"-"`
SkipSSLValidation bool `yaml:"skip_ssl_validation,omitempty"`
Nats NatsConfig `yaml:"nats,omitempty"`
NatsClientPingInterval time.Duration `yaml:"nats_client_ping_interval,omitempty"`
NatsClientMessageBufferSize int `yaml:"-"`
EnableHTTP2 bool `yaml:"enable_http2"`
DropletStaleThreshold time.Duration `yaml:"droplet_stale_threshold,omitempty"`
StartResponseDelayInterval time.Duration `yaml:"start_response_delay_interval,omitempty"`
Index uint `yaml:"index,omitempty"`
Logging Log `yaml:"logging,omitempty"`
Port uint16 `yaml:"port,omitempty"`
HealthCheckPort uint16 `yaml:"health_check_port,omitempty"`
EnableSSL bool `yaml:"enable_ssl,omitempty"`
SSLCertificate tls.Certificate `yaml:"-"`
TLSPEM TLSPem `yaml:"tls_pem,omitempty"`
CACerts string `yaml:"ca_certs,omitempty"`
CAPool *x509.CertPool `yaml:"-"`
SkipSSLValidation bool `yaml:"skip_ssl_validation,omitempty"`

Backends BackendConfig `yaml:"backends,omitempty"`

Expand All @@ -124,18 +136,23 @@ type Config struct {
}

var defaultConfig = Config{
Gorouters: defaultGoroutersConfig,
Logging: Log{},
Port: 8085,
HealthCheckPort: 8080,
DisableKeepAlives: true,
MaxIdleConns: 100,
MaxIdleConnsPerHost: 2,
SQLCnxMaxIdle: 5,
SQLCnxMaxOpen: 10,
SQLCnxMaxLife: "1h",
Broker: defaultBrokerConfig,
BaseURL: "http://localhost:8085",
Nats: defaultNatsConfig,
NatsClientPingInterval: time.Duration(20 * float64(time.Second)),
DropletStaleThreshold: 120 * time.Second,
StartResponseDelayInterval: 5 * time.Second,
EnableHTTP2: true,
Index: 0,
Logging: Log{},
Port: 8085,
HealthCheckPort: 8080,
DisableKeepAlives: true,
MaxIdleConns: 100,
MaxIdleConnsPerHost: 2,
SQLCnxMaxIdle: 5,
SQLCnxMaxOpen: 10,
SQLCnxMaxLife: "1h",
Broker: defaultBrokerConfig,
BaseURL: "http://localhost:8085",
}

func DefaultConfig() (*Config, error) {
Expand All @@ -154,6 +171,21 @@ func (c *Config) Process() error {
c.Backends.ClientAuthCertificate = certificate
}

if c.Nats.TLSEnabled {
certificate, err := tls.X509KeyPair([]byte(c.Nats.CertChain), []byte(c.Nats.PrivateKey))
if err != nil {
errMsg := fmt.Sprintf("Error loading NATS key pair: %s", err.Error())
return fmt.Errorf(errMsg)
}
c.Nats.ClientAuthCertificate = certificate

certPool := x509.NewCertPool()
if ok := certPool.AppendCertsFromPEM([]byte(c.Nats.CACerts)); !ok {
return fmt.Errorf("Error while adding CACerts to gorouter's routing-api cert pool: \n%s\n", c.Nats.CACerts)
}
c.Nats.CAPool = certPool
}

if c.EnableSSL {
if c.TLSPEM.PrivateKey == "" || c.TLSPEM.CertChain == "" {
return fmt.Errorf("Error parsing PEM blocks of router.tls_pem, missing cert or key.")
Expand Down Expand Up @@ -245,7 +277,6 @@ func (c *Config) buildCertPool() error {
}

func (c *Config) Initialize(configYAML []byte) error {
c.Gorouters = make([]GorouterConfig, 0)
return yaml.Unmarshal(configYAML, &c)
}

Expand All @@ -272,3 +303,17 @@ func InitConfigFromFile(file *os.File) (*Config, error) {

return c, nil
}

func (c *Config) NatsServers() []string {
var natsServers []string
for _, host := range c.Nats.Hosts {
uri := url.URL{
Scheme: "nats",
User: url.UserPassword(c.Nats.User, c.Nats.Pass),
Host: fmt.Sprintf("%s:%d", host.Hostname, host.Port),
}
natsServers = append(natsServers, uri.String())
}

return natsServers
}
69 changes: 59 additions & 10 deletions fetchers/fetchersfakes/fake_routes_fetch.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 625fbc9

Please sign in to comment.