Skip to content

Commit

Permalink
Merge pull request #56 from xmidt-org/feature/coreconfig
Browse files Browse the repository at this point in the history
refactored into a much simpler DI model
  • Loading branch information
johnabass authored Jan 16, 2025
2 parents 9a64383 + f70d694 commit c8752a5
Show file tree
Hide file tree
Showing 11 changed files with 470 additions and 421 deletions.
119 changes: 119 additions & 0 deletions config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
// SPDX-FileCopyrightText: 2025 Comcast Cable Communications Management, LLC
// SPDX-License-Identifier: Apache-2.0

package praetor

import (
"time"

"github.com/hashicorp/consul/api"
)

// BasicAuthConfig holds the HTTP basic authorization credentials for Consul.
type BasicAuthConfig struct {
// UserName is the HTTP basic auth user name.
UserName string `json:"userName" yaml:"userName" mapstructure:"userName"`

// Password is the HTTP basic auth user name.
Password string `json:"password" yaml:"password" mapstructure:"password"`
}

// TLSConfig holds the TLS options supported by praetor.
type TLSConfig struct {
// Address is the optional address of the consul server. If set, this field's value
// is used as the TLS ServerName.
Address string `json:"address" yaml:"address" mapstructure:"address"`

// CAFile is the system path to a CA certificate bundle used for Consul communication.
// Defaults to the system bundle if not specified.
CAFile string `json:"caFile" yaml:"caFile" mapstructure:"caFile"`

// CAPath is the system directory of CA certificates used for Consul communication.
// Defaults to the system bundle if not specified.
CAPath string `json:"caPath" yaml:"caPath" mapstructure:"caPath"`

// CertificateFile is the system file for the certificate used in Consul communication.
// If this is set, KeyFile must also be set.
CertificateFile string `json:"certificateFile" yaml:"certificateFile" mapstructure:"certificateFile"`

// KeyFile is the system file for the key used in Consul communication.
// If this is set, CertificateFile must also be set.
KeyFile string `json:"keyFile" yaml:"keyFile" mapstructure:"keyFile"`

// InsecureSkipVerify controls whether TLS host verification is disabled.
InsecureSkipVerify bool `json:"insecureSkipVerify" yaml:"insecureSkipVerify" mapstructure:"insecureSkipVerify"`
}

// Config is an easily unmarshalable configuration that praetor uses to create
// a consul api.Config. Fields in this struct mirror those of api.Config.
//
// An application can just unmarshal an api.Config directly, rather than using this type.
// This type provides struct tags to standardize fields across various libraries.
type Config struct {
// Scheme is the URI scheme of the consul server.
Scheme string `json:"scheme" yaml:"scheme" mapstructure:"scheme"`

// Address is the address of the consul server, including port.
Address string `json:"address" yaml:"address" mapstructure:"address"`

// PathPrefix is the URI path prefix to use when consul is behind an API gateway.
PathPrefix string `json:"pathPrefix" yaml:"pathPrefix" mapstructure:"pathPrefix"`

// Datacenter is the optional datacenter to use when interacting with the agent.
// If unset, the datacenter of the agent is used.
Datacenter string `json:"datacenter" yaml:"datacenter" mapstructure:"datacenter"`

// WaitTime specifies the time that watches will block. If unset, the agent's
// default will be used.
WaitTime time.Duration `json:"waitTime" yaml:"waitTime" mapstructure:"waitTime"`

// Token is a per request ACL token. If unset, the agent's token is used.
Token string `json:"token" yaml:"token" mapstructure:"token"`

// TokenFile is a file containing the per request ACL token.
TokenFile string `json:"tokenFile" yaml:"tokenFile" mapstructure:"tokenFile"`

// Namespace is the namespace to send to the agent in requests where no namespace is set.
Namespace string `json:"namespace" yaml:"namespace" mapstructure:"namespace"`

// Partition is the partition to send to the agent in requests where no namespace is set.
Partition string `json:"partition" yaml:"partition" mapstructure:"partition"`

// BasicAuth defines the HTTP basic credentials for interacting with the agent.
BasicAuth BasicAuthConfig `json:"basicAuth" yaml:"basicAuth" mapstructure:"basicAuth"`

// TLS defines the TLS configuration to use for the consul server.
TLS TLSConfig `json:"tls" yaml:"tls" mapstructure:"tls"`
}

// NewAPIConfig constructs a consul client api.Config from a praetor configuration.
func NewAPIConfig(src Config) (dst api.Config, err error) {
dst = api.Config{
Scheme: src.Scheme,
Address: src.Address,
PathPrefix: src.PathPrefix,
Datacenter: src.Datacenter,
WaitTime: src.WaitTime,
Token: src.Token,
TokenFile: src.TokenFile,
Namespace: src.Namespace,
Partition: src.Partition,
TLSConfig: api.TLSConfig{
Address: src.TLS.Address,
CAFile: src.TLS.CAFile,
CAPath: src.TLS.CAPath,
CertFile: src.TLS.CertificateFile,
KeyFile: src.TLS.KeyFile,
InsecureSkipVerify: src.TLS.InsecureSkipVerify,
},
}

if len(src.BasicAuth.UserName) > 0 {
dst.HttpAuth = &api.HttpBasicAuth{
Username: src.BasicAuth.UserName,
Password: src.BasicAuth.Password,
}
}

return
}
118 changes: 118 additions & 0 deletions config_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
// SPDX-FileCopyrightText: 2025 Comcast Cable Communications Management, LLC
// SPDX-License-Identifier: Apache-2.0

package praetor

import (
"testing"
"time"

"github.com/hashicorp/consul/api"
"github.com/stretchr/testify/suite"
)

type ConfigTestSuite struct {
suite.Suite
}

func (suite *ConfigTestSuite) newAPIConfig(src Config) api.Config {
dst, err := NewAPIConfig(src)
suite.Require().NoError(err)
return dst
}

// newSimpleConfig creates a praetor Config with the simple fields set.
func (suite *ConfigTestSuite) newSimpleConfig() Config {
return Config{
Scheme: "ftp",
Address: "foobar:8080",
PathPrefix: "/prefix",
Datacenter: "abc",
WaitTime: 5 * time.Minute,
Token: "xyz",
TokenFile: "/etc/app/token",
Namespace: "namespace",
Partition: "partition",
}
}

// assertSimpleFields asserts that the given consul api.Config's simple fields
// matches what is set by newSimpleConfig.
func (suite *ConfigTestSuite) assertSimpleFields(cfg api.Config) {
suite.Equal("ftp", cfg.Scheme)
suite.Equal("foobar:8080", cfg.Address)
suite.Equal("/prefix", cfg.PathPrefix)
suite.Equal("abc", cfg.Datacenter)
suite.Equal(5*time.Minute, cfg.WaitTime)
suite.Equal("xyz", cfg.Token)
suite.Equal("/etc/app/token", cfg.TokenFile)
suite.Equal("namespace", cfg.Namespace)
suite.Equal("partition", cfg.Partition)
suite.Nil(cfg.HttpClient)
suite.Nil(cfg.Transport)
}

func (suite *ConfigTestSuite) testNewAPIConfigSimple() {
cfg := suite.newAPIConfig(
suite.newSimpleConfig(),
)

suite.assertSimpleFields(cfg)
suite.Nil(cfg.HttpAuth)
suite.Equal(api.TLSConfig{}, cfg.TLSConfig)
}

func (suite *ConfigTestSuite) testNewAPIConfigHttpAuth() {
src := suite.newSimpleConfig()
src.BasicAuth.UserName = "user"
src.BasicAuth.Password = "password"

cfg := suite.newAPIConfig(src)

suite.assertSimpleFields(cfg)
suite.Equal(api.TLSConfig{}, cfg.TLSConfig)
suite.Require().NotNil(cfg.HttpAuth)
suite.Equal(
api.HttpBasicAuth{
Username: "user",
Password: "password",
},
*cfg.HttpAuth,
)
}

func (suite *ConfigTestSuite) testNewAPIConfigTLS() {
src := suite.newSimpleConfig()
src.TLS.Address = "foobar:9090"
src.TLS.CAFile = "/etc/app/cafile"
src.TLS.CAPath = "/etc/app/capath"
src.TLS.CertificateFile = "/etc/app/certificateFile"
src.TLS.KeyFile = "/etc/app/keyFile"
src.TLS.InsecureSkipVerify = true

cfg := suite.newAPIConfig(src)

suite.assertSimpleFields(cfg)
suite.Nil(cfg.HttpAuth)
suite.Equal(
api.TLSConfig{
Address: "foobar:9090",
CAFile: "/etc/app/cafile",
CAPath: "/etc/app/capath",
CertFile: "/etc/app/certificateFile",
KeyFile: "/etc/app/keyFile",
InsecureSkipVerify: true,
},
cfg.TLSConfig,
)
}

func (suite *ConfigTestSuite) TestNewAPIConfig() {
suite.Run("Simple", suite.testNewAPIConfigSimple)
suite.Run("HttpAuth", suite.testNewAPIConfigHttpAuth)
suite.Run("TLS", suite.testNewAPIConfigTLS)
}

func TestConfig(t *testing.T) {
suite.Run(t, new(ConfigTestSuite))
}
9 changes: 0 additions & 9 deletions constants_test.go

This file was deleted.

2 changes: 1 addition & 1 deletion doc.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: 2023 Comcast Cable Communications Management, LLC
// SPDX-FileCopyrightText: 2025 Comcast Cable Communications Management, LLC
// SPDX-License-Identifier: Apache-2.0

/*
Expand Down
18 changes: 9 additions & 9 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,36 +1,36 @@
module github.com/xmidt-org/praetor

go 1.21
go 1.22.0

toolchain go1.23.4

require (
github.com/hashicorp/consul/api v1.31.0
github.com/stretchr/testify v1.10.0
go.uber.org/fx v1.23.0
go.uber.org/multierr v1.11.0
)

require (
github.com/armon/go-metrics v0.4.1 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/fatih/color v1.16.0 // indirect
github.com/fatih/color v1.18.0 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
github.com/hashicorp/go-hclog v1.5.0 // indirect
github.com/hashicorp/go-hclog v1.6.3 // indirect
github.com/hashicorp/go-immutable-radix v1.3.1 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect
github.com/hashicorp/go-rootcerts v1.0.2 // indirect
github.com/hashicorp/golang-lru v1.0.2 // indirect
github.com/hashicorp/serf v0.10.1 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-colorable v0.1.14 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mitchellh/go-homedir v1.1.0 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
go.uber.org/dig v1.18.0 // indirect
go.uber.org/multierr v1.10.0 // indirect
go.uber.org/zap v1.26.0 // indirect
golang.org/x/exp v0.0.0-20231006140011-7918f672742d // indirect
golang.org/x/sys v0.19.0 // indirect
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect
golang.org/x/exp v0.0.0-20250106191152-7588d65b2ba8 // indirect
golang.org/x/sys v0.29.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
Loading

0 comments on commit c8752a5

Please sign in to comment.