Skip to content

Commit

Permalink
Merge pull request #316 from flanksource/connections
Browse files Browse the repository at this point in the history
Connections
  • Loading branch information
moshloop authored Sep 5, 2021
2 parents 8bf3559 + 5071d3e commit f5900b9
Show file tree
Hide file tree
Showing 21 changed files with 708 additions and 516 deletions.
30 changes: 4 additions & 26 deletions api/v1/checks.go
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,7 @@ func (c ResticCheck) GetType() string {
}

type JmeterCheck struct {
Description `yaml:",inline" json:",inline"`
// Jmx defines tge ConfigMap or Secret reference to get the JMX test plan
Jmx kommons.EnvVar `yaml:"jmx" json:"jmx"`
// Host is the server against which test plan needs to be executed
Expand All @@ -199,7 +200,6 @@ type JmeterCheck struct {
Properties []string `yaml:"properties,omitempty" json:"properties,omitempty"`
// SystemProperties defines the java system property
SystemProperties []string `yaml:"systemProperties,omitempty" json:"systemProperties,omitempty"`
Description `yaml:",inline" json:",inline"`
// ResponseDuration under which the all the test should pass
ResponseDuration string `yaml:"responseDuration,omitempty" json:"responseDuration,omitempty"`
}
Expand Down Expand Up @@ -290,21 +290,12 @@ func (c RedisCheck) GetEndpoint() string {

type SQLCheck struct {
Description `yaml:",inline" json:",inline"`
Templatable `yaml:",inline" json:",inline"`
Connection `yaml:",inline" json:",inline"`
driver string `yaml:"-" json:"-"`
Connection string `yaml:"connection" json:"connection,omitempty" template:"true"`
Query string `yaml:"query" json:"query,omitempty" template:"true"`
// Number rows to check for
Result int `yaml:"results" json:"results,omitempty"`
// ResultsFunction tests query output for pass/fail (must return boolean)
// Example: '[[ if index .results 0 "surname" | eq "khandelwal" ]]true[[else]]false[[end]]'
ResultsFunction string `yaml:"resultsFunction,omitempty" json:"resultsFunction,omitempty"`
// DisplayTemplate displays query results in text (overrides default bar format for UI)
// Example: '[[index .results 0]]'
DisplayTemplate string `yaml:"displayTemplate,omitempty" json:"displayTemplate,omitempty"`
}

func (c SQLCheck) GetDisplayTemplate() string {
return c.DisplayTemplate
}

func (c *SQLCheck) GetQuery() string {
Expand All @@ -314,10 +305,6 @@ func (c *SQLCheck) GetQuery() string {
return c.Query
}

func (c *SQLCheck) GetConnection() string {
return c.Connection
}

func (c SQLCheck) GetDriver() string {
return c.driver
}
Expand All @@ -326,10 +313,6 @@ func (c *SQLCheck) SetDriver(driver string) {
c.driver = driver
}

func (c SQLCheck) GetEndpoint() string {
return sanitizeEndpoints(c.Connection)
}

func (c SQLCheck) GetType() string {
return c.GetDriver()
}
Expand Down Expand Up @@ -561,12 +544,7 @@ func (c PrometheusCheck) GetEndpoint() string {
type MongoDBCheck struct {
Description `yaml:",inline" json:",inline"`
// Monogodb connection string, e.g. mongodb://:27017/?authSource=admin, See https://docs.mongodb.com/manual/reference/connection-string/
Connection string `yaml:"connection" json:"connection,omitempty" template:"true"`
*Authentication `yaml:",inline" json:",inline"`
}

func (c MongoDBCheck) GetEndpoint() string {
return sanitizeEndpoints(c.Connection)
Connection `yaml:",inline" json:",inline"`
}

func (c MongoDBCheck) GetType() string {
Expand Down
34 changes: 31 additions & 3 deletions api/v1/common.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package v1

import (
"net/url"
"os"
"regexp"
"strings"
Expand Down Expand Up @@ -161,6 +162,10 @@ type Authentication struct {
Password kommons.EnvVar `yaml:"password" json:"password"`
}

func (auth Authentication) IsEmpty() bool {
return auth.Username.IsEmpty() && auth.Password.IsEmpty()
}

func (auth Authentication) GetUsername() string {
return auth.Username.Value
}
Expand Down Expand Up @@ -245,14 +250,37 @@ func (d Description) GetIcon() string {
return d.Icon
}

type Connection struct {
Connection string `yaml:"connection" json:"connection" template:"true"`
Authentication Authentication `yaml:"auth,omitempty" json:"auth,omitempty"`
}

// +k8s:deepcopy-gen=false
type Connectable interface {
GetConnection() string
}

func (c Connection) GetConnection() string {
return c.Connection
}

func (c Connection) GetEndpoint() string {
return sanitizeEndpoints(c.Connection)
}

// Obfuscate passwords of the form ' password=xxxxx ' from connectionString since
// connectionStrings are used as metric labels and we don't want to leak passwords
// Returns the Connection string with the password replaced by '###'

func sanitizeEndpoints(connection string) string {
if _url, err := url.Parse(connection); err == nil {
if _url.User != nil {
_url.User = nil
connection = _url.String()
}
}
//looking for a substring that starts with a space,
//'password=', then any non-whitespace characters,
//until an ending space
re := regexp.MustCompile(`\spassword=\S*\s`)
return re.ReplaceAllString(connection, " password=### ")
re := regexp.MustCompile(`password=([^;]*)`)
return re.ReplaceAllString(connection, "password=###")
}
42 changes: 30 additions & 12 deletions api/v1/zz_generated.deepcopy.go

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

47 changes: 47 additions & 0 deletions checks/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,59 @@ import (
"os"
"time"

"github.com/flanksource/canary-checker/api/context"
v1 "github.com/flanksource/canary-checker/api/v1"
"github.com/flanksource/canary-checker/pkg/utils"
"github.com/flanksource/kommons"
"github.com/flanksource/kommons/ktemplate"
"github.com/robfig/cron/v3"
)

func GetConnection(ctx *context.Context, conn *v1.Connection, namespace string) (string, error) {
// TODO: this function should not be necessary, each check should be templated out individual
// however, the walk method only support high level values, not values from siblings.

if conn.Authentication.IsEmpty() {
return conn.Connection, nil
}
client, err := ctx.Kommons.GetClientset()
if err != nil {
return "", err
}

auth, err := GetAuthValues(&conn.Authentication, ctx.Kommons, namespace)
if err != nil {
return "", err
}

clone := conn.DeepCopy()

data := map[string]string{
"name": ctx.Canary.Name,
"namespace": namespace,
"username": auth.GetUsername(),
"password": auth.GetPassword(),
"domain": auth.GetDomain(),
}
templater := ktemplate.StructTemplater{
Clientset: client,
Values: data,
// access go values in template requires prefix everything with .
// to support $(username) instead of $(.username) we add a function for each var
ValueFunctions: true,
DelimSets: []ktemplate.Delims{
{Left: "{{", Right: "}}"},
{Left: "$(", Right: ")"},
},
RequiredTag: "template",
}
if err := templater.Walk(clone); err != nil {
return "", err
}

return clone.Connection, nil
}

func GetAuthValues(auth *v1.Authentication, client *kommons.Client, namespace string) (*v1.Authentication, error) {
authentication := &v1.Authentication{
Username: kommons.EnvVar{
Expand Down
47 changes: 22 additions & 25 deletions checks/mongodb.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
package checks

import (
gocontext "context"
"time"

"github.com/flanksource/canary-checker/api/context"
"github.com/flanksource/canary-checker/api/external"

"time"

v1 "github.com/flanksource/canary-checker/api/v1"
"github.com/flanksource/canary-checker/pkg"
"go.mongodb.org/mongo-driver/mongo"
Expand All @@ -32,34 +33,30 @@ func (c *MongoDBChecker) Run(ctx *context.Context) []*pkg.CheckResult {
}

func (c *MongoDBChecker) Check(ctx *context.Context, extConfig external.Check) *pkg.CheckResult {
start := time.Now()
check := extConfig.(v1.MongoDBCheck)
var client *mongo.Client
result := pkg.Success(check)
var err error
if check.Authentication != nil {
auth, err := GetAuthValues(check.Authentication, ctx.Kommons, ctx.Canary.Namespace)
if err != nil {
return pkg.Fail(check).ErrorMessage(err).StartTime(start)
}
credential := options.Credential{
Username: auth.Username.Value,
Password: auth.Password.Value,
}
client, err = mongo.Connect(ctx, options.Client().ApplyURI(check.Connection).SetAuth(credential))
if err != nil {
return pkg.Fail(check).ErrorMessage(err).StartTime(start)
}
} else {
client, err = mongo.Connect(ctx, options.Client().ApplyURI(check.Connection))
if err != nil {
return pkg.Fail(check).ErrorMessage(err).StartTime(start)
}

connection, err := GetConnection(ctx, &check.Connection, ctx.Namespace)
if err != nil {
return result.ErrorMessage(err)
}

opts := options.Client().
ApplyURI(connection).
SetConnectTimeout(3 * time.Second).
SetSocketTimeout(3 * time.Second)

_ctx, cancel := gocontext.WithTimeout(ctx, 5*time.Second)
defer cancel()
client, err := mongo.Connect(_ctx, opts)
if err != nil {
return result.ErrorMessage(err)
}
defer client.Disconnect(ctx) //nolint: errcheck
err = client.Ping(ctx, readpref.Primary())
err = client.Ping(_ctx, readpref.Primary())
if err != nil {
return pkg.Fail(check).ErrorMessage(err).StartTime(start)
return result.ErrorMessage(err)
}
return pkg.Success(check).StartTime(start)
return result
}
2 changes: 1 addition & 1 deletion checks/mssql.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,5 +34,5 @@ func (c *MssqlChecker) Run(ctx *context.Context) []*pkg.CheckResult {
// driver and connection string
// Returns check result and metrics
func (c *MssqlChecker) Check(ctx *context.Context, extConfig external.Check) *pkg.CheckResult {
return CheckSQL(extConfig.(v1.MssqlCheck).SQLCheck)
return CheckSQL(ctx, extConfig.(v1.MssqlCheck).SQLCheck)
}
2 changes: 1 addition & 1 deletion checks/postgres.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,5 @@ func (c *PostgresChecker) Run(ctx *context.Context) []*pkg.CheckResult {
}

func (c *PostgresChecker) Check(ctx *context.Context, extConfig external.Check) *pkg.CheckResult {
return CheckSQL(extConfig.(v1.PostgresCheck).SQLCheck)
return CheckSQL(ctx, extConfig.(v1.PostgresCheck).SQLCheck)
}
Loading

0 comments on commit f5900b9

Please sign in to comment.