From 9dbbb1727a20e3b2898f845df299e1cd0c89dc83 Mon Sep 17 00:00:00 2001 From: user1 Date: Tue, 17 Oct 2023 18:31:31 +0300 Subject: [PATCH 01/11] fix: metric labels --- checks/common.go | 3 -- pkg/metrics/metrics.go | 72 ++++++++++++++++++++++++------------------ 2 files changed, 42 insertions(+), 33 deletions(-) diff --git a/checks/common.go b/checks/common.go index e39879348..3d6cc782f 100644 --- a/checks/common.go +++ b/checks/common.go @@ -115,9 +115,6 @@ func transform(ctx *context.Context, in *pkg.CheckResult) ([]*pkg.CheckResult, e } return results, nil } else if len(transformed) == 1 && t.Name == "" { - if ctx.IsTrace() { - ctx.Tracef("merging %v into %v", t, in) - } in.Metrics = append(in.Metrics, t.Metrics...) if t.Start != nil { in.Start = *t.Start diff --git a/pkg/metrics/metrics.go b/pkg/metrics/metrics.go index 0f215091f..982b935c5 100644 --- a/pkg/metrics/metrics.go +++ b/pkg/metrics/metrics.go @@ -7,7 +7,6 @@ import ( v1 "github.com/flanksource/canary-checker/api/v1" "github.com/flanksource/canary-checker/pkg" "github.com/flanksource/canary-checker/pkg/runner" - "github.com/flanksource/canary-checker/pkg/utils" "github.com/flanksource/commons/logger" cmap "github.com/orcaman/concurrent-map" "github.com/prometheus/client_golang/prometheus" @@ -142,6 +141,12 @@ func GetMetrics(key string) (uptime pkg.Uptime, latency pkg.Latency) { } func Record(canary v1.Canary, result *pkg.CheckResult) (_uptime pkg.Uptime, _latency pkg.Latency) { + defer func() { + e := recover() + if e != nil { + logger.Errorf("panic recording metrics for %s/%s/%s ==> %s", canary.Namespace, canary.Name, result, e) + } + }() if result == nil || result.Check == nil { logger.Warnf("%s/%s returned a nil result", canary.Namespace, canary.Name) return _uptime, _latency @@ -240,60 +245,67 @@ func Record(canary v1.Canary, result *pkg.CheckResult) (_uptime pkg.Uptime, _lat return _uptime, _latency } -func getOrCreateGauge(m pkg.Metric) (e any) { - defer func() { - e = recover() - }() - +func getOrCreateGauge(m pkg.Metric) error { var gauge *prometheus.GaugeVec var ok bool - if gauge, ok = CustomGauges[m.Name]; !ok { + if gauge, ok = CustomGauges[m.ID()]; !ok { gauge = prometheus.V2.NewGaugeVec(prometheus.GaugeVecOpts{ + VariableLabels: prometheus.UnconstrainedLabels(m.LabelNames()), GaugeOpts: prometheus.GaugeOpts{ Name: m.Name, }, }) - CustomGauges[m.Name] = gauge + CustomGauges[m.ID()] = gauge } - gauge.With(m.Labels).Set(m.Value) - return nil + if metric, err := gauge.GetMetricWith(m.Labels); err != nil { + return err + } else { + metric.Set(m.Value) + return nil + } } -func getOrCreateCounter(m pkg.Metric) (e any) { - defer func() { - e = recover() - }() +func getOrCreateCounter(m pkg.Metric) error { var counter *prometheus.CounterVec var ok bool - if counter, ok = CustomCounters[m.Name]; !ok { - counter = prometheus.NewCounterVec( - prometheus.CounterOpts{Name: m.Name}, - utils.MapKeys(m.Labels), - ) - CustomCounters[m.Name] = counter + if counter, ok = CustomCounters[m.ID()]; !ok { + counter = prometheus.V2.NewCounterVec(prometheus.CounterVecOpts{ + VariableLabels: prometheus.UnconstrainedLabels(m.LabelNames()), + CounterOpts: prometheus.CounterOpts{ + Name: m.Name, + }, + }) + CustomCounters[m.ID()] = counter + } + + if metric, err := counter.GetMetricWith(m.Labels); err != nil { + return err + } else { + metric.Add(m.Value) + return nil } - counter.With(m.Labels).Add(m.Value) - return nil } -func getOrCreateHistogram(m pkg.Metric) (e any) { - defer func() { - e = recover() - }() +func getOrCreateHistogram(m pkg.Metric) error { var histogram *prometheus.HistogramVec var ok bool - if histogram, ok = CustomHistograms[m.Name]; !ok { + if histogram, ok = CustomHistograms[m.ID()]; !ok { histogram = prometheus.V2.NewHistogramVec(prometheus.HistogramVecOpts{ + VariableLabels: prometheus.UnconstrainedLabels(m.LabelNames()), HistogramOpts: prometheus.HistogramOpts{ Name: m.Name, }, }) - CustomHistograms[m.Name] = histogram + CustomHistograms[m.ID()] = histogram + } + if metric, err := histogram.GetMetricWith(m.Labels); err != nil { + return err + } else { + metric.Observe(m.Value) + return nil } - histogram.With(m.Labels).Observe(m.Value) - return nil } func FillLatencies(checkKey string, duration string, latency *pkg.Latency) error { From 6bc390d744a4fdca44f62485589208e22e9f0bcc Mon Sep 17 00:00:00 2001 From: user1 Date: Tue, 17 Oct 2023 18:32:54 +0300 Subject: [PATCH 02/11] fix: including namespaces,canaries,types --- checks/runchecks.go | 6 ++++++ cmd/operator.go | 27 +++++++++---------------- cmd/root.go | 6 ++++-- pkg/api.go | 14 +++++++++++++ pkg/controllers/canary_controller.go | 30 +++++++++------------------- pkg/db/canary.go | 8 ++++---- pkg/jobs/canary/canary_jobs.go | 17 +++++++++++----- pkg/runner/runner.go | 26 +++++++++++++++++++++++- 8 files changed, 83 insertions(+), 51 deletions(-) diff --git a/checks/runchecks.go b/checks/runchecks.go index 3c0523c32..7ebf954ef 100644 --- a/checks/runchecks.go +++ b/checks/runchecks.go @@ -16,6 +16,8 @@ import ( var checksCache = cache.New(5*time.Minute, 5*time.Minute) +var DisabledChecks []string + func getDisabledChecks(ctx *context.Context) (map[string]struct{}, error) { if val, ok := checksCache.Get("disabledChecks"); ok { return val.(map[string]struct{}), nil @@ -41,6 +43,10 @@ func getDisabledChecks(ctx *context.Context) (map[string]struct{}, error) { result[strings.TrimPrefix(name, "check.disabled.")] = struct{}{} } + for _, check := range DisabledChecks { + result[check] = struct{}{} + } + if rows.Err() != nil { return nil, rows.Err() } diff --git a/cmd/operator.go b/cmd/operator.go index 2d2b7d6a3..6c9c473c8 100644 --- a/cmd/operator.go +++ b/cmd/operator.go @@ -2,7 +2,6 @@ package cmd import ( "os" - "strings" "time" "github.com/flanksource/canary-checker/pkg/cache" @@ -31,7 +30,6 @@ import ( var webhookPort int var enableLeaderElection bool -var operatorNamespace string var operatorExecutor bool var disablePostgrest bool var Operator = &cobra.Command{ @@ -42,7 +40,7 @@ var Operator = &cobra.Command{ func init() { ServerFlags(Operator.Flags()) - Operator.Flags().StringVarP(&operatorNamespace, "namespace", "n", "", "Watch only specified namespaces, otherwise watch all") + Operator.Flags().StringVarP(&runner.WatchNamespace, "namespace", "n", "", "Watch only specified namespaces, otherwise watch all") Operator.Flags().BoolVar(&operatorExecutor, "executor", true, "If false, only serve the UI and sync the configs") Operator.Flags().IntVar(&webhookPort, "webhookPort", 8082, "Port for webhooks ") Operator.Flags().BoolVar(&enableLeaderElection, "enable-leader-election", false, "Enabling this will ensure there is only one active controller manager") @@ -88,7 +86,7 @@ func run(cmd *cobra.Command, args []string) { mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{ Scheme: scheme, LeaderElection: enableLeaderElection, - LeaderElectionNamespace: operatorNamespace, + LeaderElectionNamespace: runner.WatchNamespace, Metrics: ctrlMetrics.Options{ BindAddress: ":0", }, @@ -106,23 +104,16 @@ func run(cmd *cobra.Command, args []string) { } loggr.Sugar().Infof("Using runner name: %s", runner.RunnerName) - includeNamespaces := []string{} - if operatorNamespace != "" { - includeNamespaces = strings.Split(operatorNamespace, ",") - canaryJobs.CanaryNamespaces = includeNamespaces - } runner.RunnerLabels = labels.LoadFromFile("/etc/podinfo/labels") canaryReconciler := &controllers.CanaryReconciler{ - IncludeCheck: includeCheck, - IncludeNamespaces: includeNamespaces, - Client: mgr.GetClient(), - LogPass: logPass, - LogFail: logFail, - Log: ctrl.Log.WithName("controllers").WithName("canary"), - Scheme: mgr.GetScheme(), - RunnerName: runner.RunnerName, - CanaryCache: gocache.New(7*24*time.Hour, 1*time.Hour), + Client: mgr.GetClient(), + LogPass: logPass, + LogFail: logFail, + Log: ctrl.Log.WithName("controllers").WithName("canary"), + Scheme: mgr.GetScheme(), + RunnerName: runner.RunnerName, + CanaryCache: gocache.New(7*24*time.Hour, 1*time.Hour), } systemReconciler := &controllers.TopologyReconciler{ diff --git a/cmd/root.go b/cmd/root.go index 1f89b922e..08c4b24e7 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -31,7 +31,7 @@ var Root = &cobra.Command{ var httpPort = 8080 var publicEndpoint = "http://localhost:8080" -var includeCheck, prometheusURL string +var prometheusURL string var pushServers, pullServers []string var sharedLibrary []string var exposeEnv bool @@ -49,7 +49,9 @@ func ServerFlags(flags *pflag.FlagSet) { _ = flags.MarkDeprecated("dev", "") flags.StringVar(&publicEndpoint, "public-endpoint", publicEndpoint, "Host on which the health dashboard is exposed. Could be used for generting-links, redirects etc.") - flags.StringVar(&includeCheck, "include-check", "", "Run matching canaries - useful for debugging") + flags.StringSliceVar(&runner.IncludeCanaries, "include-check", []string{}, "Run matching canaries - useful for debugging") + flags.StringSliceVar(&runner.IncludeTypes, "include-type", []string{}, "Check type to disable") + flags.StringSliceVar(&runner.IncludeNamespaces, "include-namespace", []string{}, "Check type to disable") flags.IntVar(&cache.DefaultCacheCount, "maxStatusCheckCount", 5, "Maximum number of past checks in the in memory cache") flags.StringSliceVar(&pushServers, "push-servers", []string{}, "push check results to multiple canary servers") flags.StringSliceVar(&pullServers, "pull-servers", []string{}, "push check results to multiple canary servers") diff --git a/pkg/api.go b/pkg/api.go index 766ea3dac..4560b616f 100644 --- a/pkg/api.go +++ b/pkg/api.go @@ -2,6 +2,7 @@ package pkg import ( "fmt" + "sort" "strings" "time" @@ -525,6 +526,19 @@ type Metric struct { Value float64 `json:"value,omitempty"` } +func (m Metric) ID() string { + return fmt.Sprintf("%s-%s", m.Name, strings.Join(m.LabelNames(), "-")) +} + +func (m Metric) LabelNames() []string { + var names []string + for k := range m.Labels { + names = append(names, k) + } + sort.Strings(names) + return names +} + func (m Metric) String() string { labels := "" if len(m.Labels) > 0 { diff --git a/pkg/controllers/canary_controller.go b/pkg/controllers/canary_controller.go index 1dd374505..98686bb52 100644 --- a/pkg/controllers/canary_controller.go +++ b/pkg/controllers/canary_controller.go @@ -27,6 +27,7 @@ import ( v1 "github.com/flanksource/canary-checker/api/v1" "github.com/flanksource/canary-checker/pkg" canaryJobs "github.com/flanksource/canary-checker/pkg/jobs/canary" + "github.com/flanksource/canary-checker/pkg/runner" "github.com/flanksource/kommons" "github.com/go-logr/logr" jsontime "github.com/liamylian/jsontime/v2/v2" @@ -46,9 +47,7 @@ var json = jsontime.ConfigWithCustomTimeFormat // CanaryReconciler reconciles a Canary object type CanaryReconciler struct { - IncludeCheck string - IncludeNamespaces []string - LogPass, LogFail bool + LogPass, LogFail bool client.Client Kubernetes kubernetes.Interface Kommons *kommons.Client @@ -68,21 +67,19 @@ const FinalizerName = "canary.canaries.flanksource.com" // +kubebuilder:rbac:groups="",resources=pods/exec,verbs=* // +kubebuilder:rbac:groups="",resources=pods/logs,verbs=* func (r *CanaryReconciler) Reconcile(ctx gocontext.Context, req ctrl.Request) (ctrl.Result, error) { - if len(r.IncludeNamespaces) > 0 && !r.includeNamespace(req.Namespace) { - r.Log.V(2).Info("namespace not included, skipping") - return ctrl.Result{}, nil - } - if r.IncludeCheck != "" && r.IncludeCheck != req.Name { - r.Log.V(2).Info("check not included, skipping") - return ctrl.Result{}, nil - } - logger := r.Log.WithValues("canary", req.NamespacedName) canary := &v1.Canary{} err := r.Get(ctx, req.NamespacedName, canary) if errors.IsNotFound(err) { return ctrl.Result{}, nil + } else if err != nil { + return ctrl.Result{RequeueAfter: 10 * time.Minute}, corev1.ErrUnexpectedEndOfGroupGenerated } + + if runner.IsCanaryIgnored(&canary.ObjectMeta) { + return ctrl.Result{}, nil + } + canary.SetRunnerName(r.RunnerName) // Add finalizer first if not exist to avoid the race condition between init and delete if !controllerutil.ContainsFinalizer(canary, FinalizerName) { @@ -219,12 +216,3 @@ func (r *CanaryReconciler) Report() { } } } - -func (r *CanaryReconciler) includeNamespace(namespace string) bool { - for _, n := range r.IncludeNamespaces { - if n == namespace { - return true - } - } - return false -} diff --git a/pkg/db/canary.go b/pkg/db/canary.go index 2f6cdd0cf..fa21d4ddc 100644 --- a/pkg/db/canary.go +++ b/pkg/db/canary.go @@ -23,7 +23,7 @@ import ( "gorm.io/gorm/clause" ) -func GetAllCanariesForSync(namespaces ...string) ([]pkg.Canary, error) { +func GetAllCanariesForSync(namespace string) ([]pkg.Canary, error) { query := ` SELECT json_agg( jsonb_set_lax(to_jsonb(canaries),'{checks}', ( @@ -44,9 +44,9 @@ func GetAllCanariesForSync(namespaces ...string) ([]pkg.Canary, error) { args := make(pgx.NamedArgs) - if namespaces != nil { - query += " AND namespace = ANY(@namespaces)" - args["namespaces"] = namespaces + if namespace != "" { + query += " AND namespace = @namespace" + args["namespace"] = namespace } rows, err := Pool.Query(context.Background(), query, args) diff --git a/pkg/jobs/canary/canary_jobs.go b/pkg/jobs/canary/canary_jobs.go index 17d7b96fa..5fb8fd60a 100644 --- a/pkg/jobs/canary/canary_jobs.go +++ b/pkg/jobs/canary/canary_jobs.go @@ -14,6 +14,7 @@ import ( "github.com/flanksource/canary-checker/pkg/db" "github.com/flanksource/canary-checker/pkg/metrics" "github.com/flanksource/canary-checker/pkg/push" + "github.com/flanksource/canary-checker/pkg/runner" "github.com/flanksource/canary-checker/pkg/utils" "github.com/flanksource/commons/logger" "github.com/flanksource/duty/models" @@ -30,10 +31,6 @@ var DataFile string var Executor bool var LogPass, LogFail bool -// CanaryNamespaces is a list of namespaces whose canary specs should be synced. -// If empty, all namespaces will be synced -var CanaryNamespaces []string - var Kommons *kommons.Client var Kubernetes kubernetes.Interface var FuncScheduler = cron.New() @@ -69,6 +66,9 @@ var minimumTimeBetweenCanaryRuns = 10 * time.Second var canaryLastRuntimes = sync.Map{} func (job CanaryJob) Run() { + if runner.IsCanaryIgnored(&job.Canary.ObjectMeta) { + return + } canaryID := job.DBCanary.ID.String() val, _ := concurrentJobLocks.LoadOrStore(canaryID, &sync.Mutex{}) lock, ok := val.(*sync.Mutex) @@ -279,6 +279,9 @@ func ScanCanaryConfigs() { } for _, canary := range configs { + if runner.IsCanaryIgnored(&canary.ObjectMeta) { + continue + } _, err := db.PersistCanary(canary, path.Base(configfile)) if err != nil { logger.Errorf("could not persist %s: %v", canary.Name, err) @@ -303,6 +306,10 @@ func SyncCanaryJob(dbCanary pkg.Canary) error { return nil } + if runner.IsCanaryIgnored(&canary.ObjectMeta) { + return nil + } + if Kommons == nil { var err error Kommons, Kubernetes, err = pkg.NewKommonsClient() @@ -350,7 +357,7 @@ func SyncCanaryJob(dbCanary pkg.Canary) error { func SyncCanaryJobs() { logger.Debugf("Syncing canary jobs") - canaries, err := db.GetAllCanariesForSync(CanaryNamespaces...) + canaries, err := db.GetAllCanariesForSync(runner.WatchNamespace) if err != nil { logger.Errorf("Failed to get canaries: %v", err) diff --git a/pkg/runner/runner.go b/pkg/runner/runner.go index a1793d8a6..d24d34f30 100644 --- a/pkg/runner/runner.go +++ b/pkg/runner/runner.go @@ -1,6 +1,10 @@ package runner -import "github.com/flanksource/canary-checker/pkg/prometheus" +import ( + "github.com/flanksource/canary-checker/pkg/prometheus" + "github.com/flanksource/commons/collections" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) var RunnerName string @@ -9,3 +13,23 @@ var Version string var RunnerLabels map[string]string = make(map[string]string) var Prometheus *prometheus.PrometheusClient + +var IncludeNamespaces []string + +var WatchNamespace string + +var IncludeCanaries []string + +var IncludeTypes []string + +func IsCanaryIgnored(canary *metav1.ObjectMeta) bool { + if !collections.MatchItems(canary.Namespace, IncludeNamespaces...) { + return true + } + + if !collections.MatchItems(canary.Name, IncludeCanaries...) { + return true + } + + return canary.Annotations != nil && canary.Annotations["suspend"] == "true" +} From 0173bdb7b14fbd62cad82c96f9f5e979d6264ced Mon Sep 17 00:00:00 2001 From: user1 Date: Tue, 17 Oct 2023 18:33:17 +0300 Subject: [PATCH 03/11] chore: disable db-metrics by default --- cmd/root.go | 1 + pkg/db/init.go | 25 ++++++++++++++----------- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/cmd/root.go b/cmd/root.go index 08c4b24e7..b2bc0a3d7 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -84,6 +84,7 @@ func init() { Root.PersistentFlags().StringVar(&db.ConnectionString, "db", "DB_URL", "Connection string for the postgres database") Root.PersistentFlags().BoolVar(&db.RunMigrations, "db-migrations", false, "Run database migrations") + Root.PersistentFlags().BoolVar(&db.DbMetrics, "db-metrics", false, "Expose db metrics") Root.PersistentFlags().BoolVar(&logFail, "log-fail", true, "Log every failing check") Root.PersistentFlags().BoolVar(&logPass, "log-pass", false, "Log every passing check") Root.PersistentFlags().StringArrayVar(&sharedLibrary, "shared-library", []string{}, "Add javascript files to be shared by all javascript templates") diff --git a/pkg/db/init.go b/pkg/db/init.go index 0ea2e128e..21accfd3e 100644 --- a/pkg/db/init.go +++ b/pkg/db/init.go @@ -22,6 +22,7 @@ var Gorm *gorm.DB var ConnectionString string var DefaultExpiryDays int var RunMigrations bool +var DbMetrics bool var PostgresServer *embeddedpostgres.EmbeddedPostgres var HTTPEndpoint = "http://localhost:8080/db" @@ -101,17 +102,19 @@ func Init() error { return err } - go func() { - if err := Gorm.Use(prometheus.New(prometheus.Config{ - DBName: Pool.Config().ConnConfig.Database, - StartServer: false, - MetricsCollector: []prometheus.MetricsCollector{ - &prometheus.Postgres{}, - }, - })); err != nil { - logger.Warnf("Failed to register prometheus metrics: %v", err) - } - }() + if DbMetrics { + go func() { + if err := Gorm.Use(prometheus.New(prometheus.Config{ + DBName: Pool.Config().ConnConfig.Database, + StartServer: false, + MetricsCollector: []prometheus.MetricsCollector{ + &prometheus.Postgres{}, + }, + })); err != nil { + logger.Warnf("Failed to register prometheus metrics: %v", err) + } + }() + } if RunMigrations { opts := &migrate.MigrateOptions{IgnoreFiles: []string{"007_events.sql", "012_changelog.sql"}} From d27239fdee0522a07c421973b9c5fa37b57ad413 Mon Sep 17 00:00:00 2001 From: user1 Date: Tue, 17 Oct 2023 18:43:22 +0300 Subject: [PATCH 04/11] fix: test failure --- pkg/jobs/canary/canary_jobs_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/jobs/canary/canary_jobs_test.go b/pkg/jobs/canary/canary_jobs_test.go index 8b46e8bb1..d32f1fbfd 100644 --- a/pkg/jobs/canary/canary_jobs_test.go +++ b/pkg/jobs/canary/canary_jobs_test.go @@ -42,7 +42,7 @@ var _ = ginkgo.Describe("Test Sync Canary Job", ginkgo.Ordered, func() { err = db.Gorm.Create(canaryM).Error Expect(err).To(BeNil()) - response, err := db.GetAllCanariesForSync() + response, err := db.GetAllCanariesForSync("") Expect(err).To(BeNil()) Expect(len(response)).To(Equal(1)) }) From d589b1caded54b067397206c5cf7be8c03ae025b Mon Sep 17 00:00:00 2001 From: user1 Date: Tue, 17 Oct 2023 18:47:07 +0300 Subject: [PATCH 05/11] chore: fix lint error --- cmd/root.go | 2 +- pkg/db/init.go | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cmd/root.go b/cmd/root.go index b2bc0a3d7..9cc55d6d9 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -84,7 +84,7 @@ func init() { Root.PersistentFlags().StringVar(&db.ConnectionString, "db", "DB_URL", "Connection string for the postgres database") Root.PersistentFlags().BoolVar(&db.RunMigrations, "db-migrations", false, "Run database migrations") - Root.PersistentFlags().BoolVar(&db.DbMetrics, "db-metrics", false, "Expose db metrics") + Root.PersistentFlags().BoolVar(&db.DBMetrics, "db-metrics", false, "Expose db metrics") Root.PersistentFlags().BoolVar(&logFail, "log-fail", true, "Log every failing check") Root.PersistentFlags().BoolVar(&logPass, "log-pass", false, "Log every passing check") Root.PersistentFlags().StringArrayVar(&sharedLibrary, "shared-library", []string{}, "Add javascript files to be shared by all javascript templates") diff --git a/pkg/db/init.go b/pkg/db/init.go index 21accfd3e..cb96d75fd 100644 --- a/pkg/db/init.go +++ b/pkg/db/init.go @@ -22,7 +22,7 @@ var Gorm *gorm.DB var ConnectionString string var DefaultExpiryDays int var RunMigrations bool -var DbMetrics bool +var DBMetrics bool var PostgresServer *embeddedpostgres.EmbeddedPostgres var HTTPEndpoint = "http://localhost:8080/db" @@ -102,7 +102,7 @@ func Init() error { return err } - if DbMetrics { + if DBMetrics { go func() { if err := Gorm.Use(prometheus.New(prometheus.Config{ DBName: Pool.Config().ConnConfig.Database, From 32f8f19f703468b0563bb20c7eb67e2d5b62d1b1 Mon Sep 17 00:00:00 2001 From: Moshe Immerman Date: Wed, 18 Oct 2023 00:33:10 +0300 Subject: [PATCH 06/11] chore: bump images, mergestat and install robot --- .github/workflows/build.yml | 8 ++- .github/workflows/test.yml | 2 +- Makefile | 9 ++- build/full/Dockerfile | 74 ++++++++++++---------- build/minimal/Dockerfile | 38 +++++++---- checks/github.go | 25 +++----- fixtures/git/_setup.sh | 22 +++---- fixtures/git/git_check_pass.yaml | 4 +- fixtures/git/git_test_expression_pass.yaml | 2 +- 9 files changed, 100 insertions(+), 84 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 1f7228191..f147b6909 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -5,10 +5,16 @@ permissions: read-all jobs: build: runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + target: + - docker-full + - docker-minimal steps: - name: Checkout code uses: actions/checkout@ee0669bd1cc54295c223e0bb666b733df41de1c5 # v2.7.0 - name: Build Container - run: make docker + run: make ${{matrix.target}} env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 362759c38..d44740a30 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -46,7 +46,7 @@ jobs: - { name: k8s, on: ubuntu-latest } - { name: datasources, on: ubuntu-latest } - { name: opensearch, on: ubuntu-latest } - - { name: elasticsearch, on: ubuntu-latest } + # - { name: elasticsearch, on: ubuntu-latest } - { name: git, on: ubuntu-latest } # - restic runs-on: ${{ matrix.suite.on }} diff --git a/Makefile b/Makefile index 0352dda17..0e834f885 100644 --- a/Makefile +++ b/Makefile @@ -82,15 +82,18 @@ generate: .bin/controller-gen .bin/controller-gen object:headerFile="hack/boilerplate.go.txt" paths="./api/..." # Build the docker image -docker: - docker build . -f build/full/Dockerfile -t ${IMG_F} +docker: docker-minimal docker-full + +docker-full: + docker build . -f build/full/Dockerfile -t ${IMG} + +docker-minimal: docker build . -f build/minimal/Dockerfile -t ${IMG} # Build the docker image docker-dev: linux docker build ./ -f build/dev/Dockerfile -t ${IMG} - docker-push-%: docker build . -f build/full/Dockerfile -t ${IMG_F} docker build . -f build/minimal/Dockerfile -t ${IMG} diff --git a/build/full/Dockerfile b/build/full/Dockerfile index e6081edb9..07258e4b8 100644 --- a/build/full/Dockerfile +++ b/build/full/Dockerfile @@ -1,4 +1,4 @@ -FROM golang:1.20@sha256:690e4135bf2a4571a572bfd5ddfa806b1cb9c3dea0446ebadaf32bc2ea09d4f9 AS builder +FROM golang:1.20-bookworm@sha256:077ff85b374b23916b4b41835e242e5a3ddad9fc537ea7e980f230431747d245 AS builder WORKDIR /app ARG NAME @@ -12,27 +12,37 @@ RUN go mod download COPY ./ ./ RUN make build -FROM eclipse-temurin:11.0.18_10-jdk-focal@sha256:509043cc38d37a5bd44720b471c38bef40fb34de67c03baaa67a5a9d8cda52a0 +FROM eclipse-temurin:11.0.20.1_1-jdk-jammy@sha256:1584fd589b45a67b6f56b0c702776ca3d5640d1001f7848f5bcd19cb10545eaa WORKDIR /app +ENV DEBIAN_FRONTEND=noninteractive RUN apt-get update && \ - apt-get install -y curl unzip ca-certificates jq wget gnupg2 bzip2 --no-install-recommends && \ + apt-get install -y curl unzip ca-certificates jq tzdata wget gnupg2 bzip2 apt-transport-https lsb-release python3 python3-pip --no-install-recommends && \ rm -Rf /var/lib/apt/lists/* && \ rm -Rf /usr/share/doc && rm -Rf /usr/share/man && \ apt-get clean -RUN wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - && \ - echo "deb http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list && \ - apt-get update && apt-get install -y \ - google-chrome-stable \ - fontconfig \ - fonts-ipafont-gothic \ - fonts-wqy-zenhei \ - fonts-thai-tlwg \ - fonts-kacst \ - fonts-symbola \ - fonts-noto \ - fonts-freefont-ttf \ - --no-install-recommends +RUN pip3 install pip pyyaml lxml requests robotframework \ + robotframework \ + robotframework-jsonlibrary \ + robotframework-jsonschemalibrary \ + robotframework-requests \ + robotframework-restlibrary \ + robotframework-seleniumlibrary \ + robotframework-excellib \ + robotframework-crypto \ + robotframework-databaselibrary \ + psycopg2-binary \ + PyMySQL + +RUN mkdir -p /etc/apt/keyrings && \ + curl -sLS https://packages.microsoft.com/keys/microsoft.asc | \ + gpg --dearmor | tee /etc/apt/keyrings/microsoft.gpg > /dev/null && \ + chmod go+r /etc/apt/keyrings/microsoft.gpg && \ + echo "deb [arch=`dpkg --print-architecture` signed-by=/etc/apt/keyrings/microsoft.gpg] https://packages.microsoft.com/repos/azure-cli/ $(lsb_release -cs) main" | tee /etc/apt/sources.list.d/azure-cli.list && \ + cat /etc/apt/sources.list.d/azure-cli.list && \ + apt-get update && \ + apt-get install -y azure-cli && \ + apt-get clean RUN apt-get update && apt-get upgrade -y && \ rm -Rf /var/lib/apt/lists/* && \ @@ -45,42 +55,37 @@ RUN curl -L https://github.com/restic/restic/releases/download/v${RESTIC_VERSION mv /app/restic /usr/local/bin/ && \ rm -rf /app/restic.bz2 -ENV JMETER_VERSION=5.5 +ENV JMETER_VERSION=5.6.2 RUN curl -L https://dlcdn.apache.org//jmeter/binaries/apache-jmeter-${JMETER_VERSION}.zip -o apache-jmeter-${JMETER_VERSION}.zip && \ - unzip apache-jmeter-${JMETER_VERSION}.zip -d /opt && \ + unzip -q apache-jmeter-${JMETER_VERSION}.zip -d /opt && \ rm apache-jmeter-${JMETER_VERSION}.zip ENV PATH /opt/apache-jmeter-${JMETER_VERSION}/bin/:$PATH -RUN curl -L https://github.com/flanksource/askgit/releases/download/v0.4.8-flanksource/askgit-linux-amd64.tar.gz -o askgit.tar.gz && \ - tar xf askgit.tar.gz && \ - mv askgit /usr/local/bin/askgit && \ - rm askgit.tar.gz && \ - wget http://mirrors.kernel.org/ubuntu/pool/main/o/openssl/openssl_1.1.1f-1ubuntu2.19_amd64.deb && \ - dpkg -i openssl_1.1.1f-1ubuntu2.19_amd64.deb && \ - rm openssl_1.1.1f-1ubuntu2.19_amd64.deb + +RUN curl -L https://github.com/mergestat/mergestat-lite/releases/download/v0.6.1/mergestat-linux-amd64.tar.gz -o mergestat.tar.gz && \ + tar zxf mergestat.tar.gz -C /usr/local/bin/ && \ + rm mergestat.tar.gz # The best developer experience for load testing -ENV K6_VERSION=v0.44.0 +ENV K6_VERSION=v0.47.0 RUN curl -L https://github.com/grafana/k6/releases/download/${K6_VERSION}/k6-${K6_VERSION}-linux-amd64.tar.gz -o k6.tar.gz && \ tar xvf k6.tar.gz && \ mv k6-${K6_VERSION}-linux-amd64/k6 /usr/local/bin/k6 && \ rm k6.tar.gz # Benthos is a high performance and resilient stream processor -RUN curl -Lsf https://sh.benthos.dev | bash -s -- 4.15.0 +RUN curl -Lsf https://sh.benthos.dev | bash -s -- 4.22.0 # Commandline tool for running SQL queries against JSON, CSV, Excel, Parquet, and more RUN curl -L https://github.com/multiprocessio/dsq/releases/download/v0.23.0/dsq-linux-x64-v0.23.0.zip -o dsq.zip && \ - unzip dsq.zip && \ + unzip -q dsq.zip && \ mv dsq /usr/local/bin/dsq && \ rm dsq.zip # Install alexellis/arkade as root RUN curl -sLS https://get.arkade.dev | sh -# Install Azure CLI (need to install as root) -RUN curl -sL https://aka.ms/InstallAzureCLIDeb | bash RUN mkdir /opt/database && groupadd --gid 1000 canary && \ useradd canary --uid 1000 -g canary -m -d /var/lib/canary && \ @@ -95,14 +100,15 @@ ENV PATH="${PATH}:/var/lib/canary/bin/" # Install AWS CLI RUN curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" && \ - unzip awscliv2.zip && ./aws/install -i ${HOME}/aws -b ${HOME}/bin/ && \ + unzip -q awscliv2.zip && ./aws/install -i ${HOME}/aws -b ${HOME}/bin/ && \ rm awscliv2.zip # Install GCP CLI -RUN curl -sL -O https://dl.google.com/dl/cloudsdk/channels/rapid/downloads/google-cloud-cli-441.0.0-linux-x86_64.tar.gz && \ - tar -xf google-cloud-cli-441.0.0-linux-x86_64.tar.gz && \ +ENV GCLOUD_VERSION=441.0.0 +RUN curl -sL -O https://dl.google.com/dl/cloudsdk/channels/rapid/downloads/google-cloud-cli-${GCLOUD_VERSION}-linux-x86_64.tar.gz && \ + tar -xf google-cloud-cli-${GCLOUD_VERSION}-linux-x86_64.tar.gz && \ ln -sf /app/google-cloud-sdk/bin/gcloud ${HOME}/bin/gcloud && \ - rm google-cloud-cli-441.0.0-linux-x86_64.tar.gz + rm google-cloud-cli-${GCLOUD_VERSION}-linux-x86_64.tar.gz COPY --from=builder /app/.bin/canary-checker /app diff --git a/build/minimal/Dockerfile b/build/minimal/Dockerfile index fa6628729..277e332b5 100644 --- a/build/minimal/Dockerfile +++ b/build/minimal/Dockerfile @@ -1,4 +1,4 @@ -FROM golang:1.20@sha256:690e4135bf2a4571a572bfd5ddfa806b1cb9c3dea0446ebadaf32bc2ea09d4f9 AS builder +FROM golang:1.20-bookworm@sha256:077ff85b374b23916b4b41835e242e5a3ddad9fc537ea7e980f230431747d245 AS builder WORKDIR /app ARG NAME @@ -12,22 +12,30 @@ RUN go mod download COPY ./ ./ RUN make build -FROM ubuntu +FROM ubuntu:jammy-20231004@sha256:2b7412e6465c3c7fc5bb21d3e6f1917c167358449fecac8176c6e496e5c1f05f WORKDIR /app +ENV DEBIAN_FRONTEND=noninteractive RUN apt-get update && \ - apt-get install -y curl unzip ca-certificates jq wget gnupg2 bzip2 --no-install-recommends && \ - rm -Rf /var/lib/apt/lists/* && \ - rm -Rf /usr/share/doc && rm -Rf /usr/share/man && \ + apt-get install -y curl unzip ca-certificates jq tzdata wget gnupg2 bzip2 apt-transport-https lsb-release --no-install-recommends && \ apt-get clean -COPY --from=builder /app/.bin/canary-checker /app +RUN mkdir -p /etc/apt/keyrings && \ + curl -sLS https://packages.microsoft.com/keys/microsoft.asc | \ + gpg --dearmor | tee /etc/apt/keyrings/microsoft.gpg > /dev/null && \ + chmod go+r /etc/apt/keyrings/microsoft.gpg && \ + echo "deb [arch=`dpkg --print-architecture` signed-by=/etc/apt/keyrings/microsoft.gpg] https://packages.microsoft.com/repos/azure-cli/ $(lsb_release -cs) main" | tee /etc/apt/sources.list.d/azure-cli.list && \ + cat /etc/apt/sources.list.d/azure-cli.list && \ + apt-get update && \ + apt-get install -y azure-cli && \ + apt-get clean + +RUN apt-get update && apt-get upgrade -y && \ + rm -Rf /var/lib/apt/lists/* && \ + apt-get clean # Install alexellis/arkade as root RUN curl -sLS https://get.arkade.dev | sh -# Install Azure CLI (need to install as root) -RUN curl -sL https://aka.ms/InstallAzureCLIDeb | bash - RUN mkdir /opt/database && groupadd --gid 1000 canary && \ useradd canary --uid 1000 -g canary -m -d /var/lib/canary && \ chown -R 1000:1000 /opt/database && chown -R 1000:1000 /app @@ -41,15 +49,17 @@ ENV PATH="${PATH}:/var/lib/canary/bin/" # Install AWS CLI RUN curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" && \ - unzip awscliv2.zip && ./aws/install -i ${HOME}/aws -b ${HOME}/bin/ && \ + unzip -q awscliv2.zip && ./aws/install -i ${HOME}/aws -b ${HOME}/bin/ && \ rm awscliv2.zip # Install GCP CLI -RUN curl -sL -O https://dl.google.com/dl/cloudsdk/channels/rapid/downloads/google-cloud-cli-441.0.0-linux-x86_64.tar.gz && \ - tar -xf google-cloud-cli-441.0.0-linux-x86_64.tar.gz && \ +ENV GCLOUD_VERSION=441.0.0 +RUN curl -sL -O https://dl.google.com/dl/cloudsdk/channels/rapid/downloads/google-cloud-cli-${GCLOUD_VERSION}-linux-x86_64.tar.gz && \ + tar -xf google-cloud-cli-${GCLOUD_VERSION}-linux-x86_64.tar.gz && \ ln -sf /app/google-cloud-sdk/bin/gcloud ${HOME}/bin/gcloud && \ - rm google-cloud-cli-441.0.0-linux-x86_64.tar.gz + rm google-cloud-cli-${GCLOUD_VERSION}-linux-x86_64.tar.gz -RUN /app/canary-checker go-offline +COPY --from=builder /app/.bin/canary-checker /app +RUN /app/canary-checker go-offline ENTRYPOINT ["/app/canary-checker"] diff --git a/checks/github.go b/checks/github.go index 983df0834..9518d7a05 100644 --- a/checks/github.go +++ b/checks/github.go @@ -4,7 +4,6 @@ import ( "encoding/json" "fmt" osExec "os/exec" - "strings" "github.com/flanksource/canary-checker/api/context" "github.com/flanksource/canary-checker/api/external" @@ -49,27 +48,23 @@ func (c *GitHubChecker) Check(ctx *context.Context, extConfig external.Check) pk } } - askGitCmd := fmt.Sprintf("GITHUB_TOKEN=%v askgit \"%v\" --format json", githubToken, check.Query) + askGitCmd := fmt.Sprintf("mergestat \"%v\" --format json", check.Query) + if ctx.IsTrace() { + ctx.Tracef("Executing askgit command: %v", askGitCmd) + } cmd := osExec.Command("bash", "-c", askGitCmd) + cmd.Env = append(cmd.Env, "GITHUB_TOKEN="+githubToken) output, err := cmd.CombinedOutput() if err != nil { return results.Failf("error executing askgit command. output=%q: %v", output, err) } - rows := string(output) - var rowResults = make([]map[string]string, 0) - for _, row := range strings.Split(rows, "\n") { - if row == "" { - continue - } - var rowResult map[string]string - err := json.Unmarshal([]byte(row), &rowResult) - if err != nil { - return results.Failf("error parsing askgit result: %v", err) - } - - rowResults = append(rowResults, rowResult) + var rowResults = make([]map[string]any, 0) + err = json.Unmarshal(output, &rowResults) + if err != nil { + return results.Failf("error parsing mergestat result: %v", err) } + result.AddDetails(rowResults) return results } diff --git a/fixtures/git/_setup.sh b/fixtures/git/_setup.sh index 6ba43a463..4232e2b2e 100755 --- a/fixtures/git/_setup.sh +++ b/fixtures/git/_setup.sh @@ -2,21 +2,15 @@ set -e -# Install askgit -curl -L https://github.com/flanksource/askgit/releases/download/v0.4.8-flanksource/askgit-linux-amd64.tar.gz -o askgit.tar.gz -tar xf askgit.tar.gz -sudo mv askgit /usr/bin/askgit -sudo chmod +x /usr/bin/askgit -rm askgit.tar.gz +if ! which mergestat > /dev/null; then + if $(uname -a | grep -q Darwin); then + curl -L https://github.com/mergestat/mergestat-lite/releases/download/v0.6.1/mergestat-macos-amd64.tar.gz -o mergestat.tar.gz + sudo tar xf mergestat.tar.gz -C /usr/local/bin/ -wget -O libssl.deb http://nz2.archive.ubuntu.com/ubuntu/pool/main/o/openssl/libssl1.1_1.1.1f-1ubuntu2_amd64.deb -sudo dpkg -i libssl.deb - -#verification -which askgit -if ! askgit --help > /dev/null; then - printf "`askgit --help` failed. Check the binary?" - exit 1; + else + curl -L https://github.com/mergestat/mergestat-lite/releases/download/v0.6.1/mergestat-linux-amd64.tar.gz -o mergestat.tar.gz + sudo tar xf mergestat.tar.gz -C /usr/local/bin/ + fi fi # creating a GITHUB_TOKEN Secret diff --git a/fixtures/git/git_check_pass.yaml b/fixtures/git/git_check_pass.yaml index 13c4eb1b2..dfda47e4f 100644 --- a/fixtures/git/git_check_pass.yaml +++ b/fixtures/git/git_check_pass.yaml @@ -2,10 +2,12 @@ apiVersion: canaries.flanksource.com/v1 kind: Canary metadata: name: github-pass + annotations: + trace: "true" spec: interval: 30 github: - - query: "SELECT * FROM github_repo_checks('flanksource/duty') where branch='main'" + - query: "SELECT * FROM commits('https://github.com/flanksource/commons')" name: github-check test: expr: size(results) > 0 diff --git a/fixtures/git/git_test_expression_pass.yaml b/fixtures/git/git_test_expression_pass.yaml index 5d2517094..a1c6dc37e 100644 --- a/fixtures/git/git_test_expression_pass.yaml +++ b/fixtures/git/git_test_expression_pass.yaml @@ -13,4 +13,4 @@ spec: valueFrom: secretKeyRef: name: github-token - key: GITHUB_TOKEN \ No newline at end of file + key: GITHUB_TOKEN From edf1a29985a0b92f4c2533c430b47ad16114ee15 Mon Sep 17 00:00:00 2001 From: Moshe Immerman Date: Wed, 18 Oct 2023 00:41:35 +0300 Subject: [PATCH 07/11] chore: fix git build --- fixtures/git/_setup.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fixtures/git/_setup.sh b/fixtures/git/_setup.sh index 4232e2b2e..de8b4b1c2 100755 --- a/fixtures/git/_setup.sh +++ b/fixtures/git/_setup.sh @@ -4,11 +4,11 @@ set -e if ! which mergestat > /dev/null; then if $(uname -a | grep -q Darwin); then - curl -L https://github.com/mergestat/mergestat-lite/releases/download/v0.6.1/mergestat-macos-amd64.tar.gz -o mergestat.tar.gz + curl -L https://github.com/flanksource/askgit/releases/download/v0.61.0-flanksource.1/mergestat-macos-amd64.tar.gz -o mergestat.tar.gz sudo tar xf mergestat.tar.gz -C /usr/local/bin/ else - curl -L https://github.com/mergestat/mergestat-lite/releases/download/v0.6.1/mergestat-linux-amd64.tar.gz -o mergestat.tar.gz + curl -L https://github.com/flanksource/askgit/releases/download/v0.61.0-flanksource.1/mergestat-linux-amd64.tar.gz -o mergestat.tar.gz sudo tar xf mergestat.tar.gz -C /usr/local/bin/ fi fi From e118613e1c27a8ea65987d1d1cbe3a00081843d6 Mon Sep 17 00:00:00 2001 From: Moshe Immerman Date: Wed, 18 Oct 2023 14:00:57 +0300 Subject: [PATCH 08/11] feat: add http pretty printing + fix auth bug --- checks/http.go | 11 ++++++++--- fixtures/minimal/http_no_auth_pass.yaml | 12 ++++++++++++ fixtures/minimal/http_pass_single.yaml | 5 +++++ go.mod | 2 +- go.sum | 4 ++-- main.go | 4 +++- 6 files changed, 31 insertions(+), 7 deletions(-) create mode 100644 fixtures/minimal/http_no_auth_pass.yaml diff --git a/checks/http.go b/checks/http.go index 45606ea63..e37253d22 100644 --- a/checks/http.go +++ b/checks/http.go @@ -19,6 +19,7 @@ import ( v1 "github.com/flanksource/canary-checker/api/v1" "github.com/flanksource/canary-checker/pkg" "github.com/flanksource/canary-checker/pkg/metrics" + "github.com/flanksource/canary-checker/pkg/runner" "github.com/flanksource/canary-checker/pkg/utils" ) @@ -63,7 +64,7 @@ func (c *HTTPChecker) Run(ctx *context.Context) pkg.Results { } func (c *HTTPChecker) generateHTTPRequest(ctx *context.Context, check v1.HTTPCheck, connection *models.Connection) (*http.Request, error) { - client := http.NewClient() + client := http.NewClient().UserAgent("canary-checker/" + runner.Version) for _, header := range check.Headers { value, err := ctx.GetEnvValueFromCache(header) @@ -91,7 +92,11 @@ func (c *HTTPChecker) generateHTTPRequest(ctx *context.Context, check v1.HTTPChe // TODO: Add finer controls over tracing to the canary if ctx.IsTrace() { - client.Trace(http.TraceConfig{MaxBodyLength: 512, Body: true, Headers: true, ResponseHeaders: true}) + client.TraceToStdout(http.TraceAll) + client.Trace(http.TraceAll) + } else if ctx.IsDebug() { + client.TraceToStdout(http.TraceHeaders) + client.Trace(http.TraceHeaders) } return client.R(ctx), nil @@ -199,7 +204,7 @@ func (c *HTTPChecker) Check(ctx *context.Context, extConfig external.Check) pkg. data := map[string]interface{}{ "code": status, - "headers": response.Header, + "headers": response.GetHeaders(), "elapsed": time.Since(start), "sslAge": utils.Deref(age), "json": make(map[string]any), diff --git a/fixtures/minimal/http_no_auth_pass.yaml b/fixtures/minimal/http_no_auth_pass.yaml new file mode 100644 index 000000000..8d4ec6c09 --- /dev/null +++ b/fixtures/minimal/http_no_auth_pass.yaml @@ -0,0 +1,12 @@ +apiVersion: canaries.flanksource.com/v1 +kind: Canary +metadata: + name: http-no-auth + annotations: + trace: "true" +spec: + http: + - name: http-no-auth + url: https://httpbin.demo.aws.flanksource.com/headers + test: + expr: "! ('Authorization' in json.headers.keys())" diff --git a/fixtures/minimal/http_pass_single.yaml b/fixtures/minimal/http_pass_single.yaml index 7a6f2ebcc..dab245877 100644 --- a/fixtures/minimal/http_pass_single.yaml +++ b/fixtures/minimal/http_pass_single.yaml @@ -33,3 +33,8 @@ spec: expr: "code in [200,201,301] && sslAge > Duration('7d')" display: template: "code={{.code}}, age={{.sslAge}}" + + - name: http-headers + url: https://httpbin.demo.aws.flanksource.com/headers + test: + expr: json.headers["User-Agent"].startsWith("canary-checker/") diff --git a/go.mod b/go.mod index 4598e39e3..f2e1c0c4a 100644 --- a/go.mod +++ b/go.mod @@ -21,7 +21,7 @@ require ( github.com/eko/gocache/store/bigcache/v4 v4.2.1 github.com/elastic/go-elasticsearch/v8 v8.10.0 github.com/fergusstrange/embedded-postgres v1.24.0 - github.com/flanksource/commons v1.15.0 + github.com/flanksource/commons v1.16.0 github.com/flanksource/duty v1.0.191 github.com/flanksource/gomplate/v3 v3.20.18 github.com/flanksource/is-healthy v0.0.0-20231003215854-76c51e3a3ff7 diff --git a/go.sum b/go.sum index a41ee9728..b5c489da8 100644 --- a/go.sum +++ b/go.sum @@ -819,8 +819,8 @@ github.com/evanphx/json-patch/v5 v5.7.0/go.mod h1:VNkHZ/282BpEyt/tObQO8s5CMPmYYq github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fergusstrange/embedded-postgres v1.24.0 h1:WqXbmYrBeT5JfNWQ8Qa+yHa5YJO/0sBIgL9k5rn3dFk= github.com/fergusstrange/embedded-postgres v1.24.0/go.mod h1:wL562t1V+iuFwq0UcgMi2e9rp8CROY9wxWZEfP8Y874= -github.com/flanksource/commons v1.15.0 h1:p74hrKzIz0r3H8YN3CuB8ePJOjzPFO0BRLVmpXmeqvY= -github.com/flanksource/commons v1.15.0/go.mod h1:FMZFLcQr98JwBKuKLs44DvCQ2JNoHz5maRIzVufQ9Cs= +github.com/flanksource/commons v1.16.0 h1:8kxeP9gPAuCKHNxLosi1uk+qIrZFs62YIzfkkneazTg= +github.com/flanksource/commons v1.16.0/go.mod h1:RDdQI0/QYC4GzicbDaXIvBPjWuQWKLzX8/rFBbFjG5U= github.com/flanksource/duty v1.0.191 h1:acnvyTeQlfqmtyXxWprNFGK/vBTUlqkYwxEPLtXSPrk= github.com/flanksource/duty v1.0.191/go.mod h1:ikyl/TcRy6Cc0R5b0wEHT7CecV7gyJvrDGq/4oIZHoc= github.com/flanksource/gomplate/v3 v3.20.4/go.mod h1:27BNWhzzSjDed1z8YShO6W+z6G9oZXuxfNFGd/iGSdc= diff --git a/main.go b/main.go index 9d8364e34..473988a4f 100644 --- a/main.go +++ b/main.go @@ -19,6 +19,9 @@ var ( func main() { if len(commit) > 8 { version = fmt.Sprintf("%v, commit %v, built at %v", version, commit[0:8], date) + runner.Version = fmt.Sprintf("%v (%v)", version, commit[0:8]) + } else { + runner.Version = version } cmd.Root.AddCommand(&cobra.Command{ @@ -30,7 +33,6 @@ func main() { }, }) - runner.Version = version cmd.Root.SetUsageTemplate(cmd.Root.UsageTemplate() + fmt.Sprintf("\nversion: %s\n ", version)) defer func() { err := db.StopServer() From ae25a35322e6cc873024ac0a18534e22b416a77e Mon Sep 17 00:00:00 2001 From: Moshe Immerman Date: Wed, 18 Oct 2023 14:54:01 +0300 Subject: [PATCH 09/11] fix: json array responses --- api/v1/checks.go | 2 +- checks/http.go | 54 +++++++++++++----------------------------------- 2 files changed, 15 insertions(+), 41 deletions(-) diff --git a/api/v1/checks.go b/api/v1/checks.go index 5e4db0a0c..923281603 100644 --- a/api/v1/checks.go +++ b/api/v1/checks.go @@ -74,7 +74,7 @@ type HTTPCheck struct { ResponseCodes []int `yaml:"responseCodes,omitempty" json:"responseCodes,omitempty"` // Exact response content expected to be returned by the endpoint. ResponseContent string `yaml:"responseContent,omitempty" json:"responseContent,omitempty"` - // Path and value to of expect JSON response by the endpoint + // Deprecated, use expr and jsonpath function ResponseJSONContent *JSONCheck `yaml:"responseJSONContent,omitempty" json:"responseJSONContent,omitempty"` // Maximum number of days until the SSL Certificate expires. MaxSSLExpiry int `yaml:"maxSSLExpiry,omitempty" json:"maxSSLExpiry,omitempty"` diff --git a/checks/http.go b/checks/http.go index e37253d22..38cb887b8 100644 --- a/checks/http.go +++ b/checks/http.go @@ -1,13 +1,13 @@ package checks import ( + "encoding/json" "fmt" "net/url" "strconv" "strings" "time" - "github.com/PaesslerAG/jsonpath" "github.com/flanksource/canary-checker/api/context" "github.com/flanksource/commons/http" "github.com/flanksource/duty/models" @@ -210,29 +210,29 @@ func (c *HTTPChecker) Check(ctx *context.Context, extConfig external.Check) pkg. "json": make(map[string]any), } + responseBody, err := response.AsString() + if err != nil { + return results.ErrorMessage(err) + } + data["content"] = responseBody + if response.IsJSON() { - json, err := response.AsJSON() - data["json"] = json - if err == nil { - data["json"] = json - if check.ResponseJSONContent != nil && check.ResponseJSONContent.Path != "" { - err := checkJSONContent(json, check.ResponseJSONContent) - if err != nil { - return results.ErrorMessage(err) - } - } + var jsonContent interface{} + if err := json.Unmarshal([]byte(responseBody), &jsonContent); err == nil { + data["json"] = jsonContent } else if check.Test.IsEmpty() { return results.Failf("invalid json response: %v", err) } else { ctx.Tracef("ignoring invalid json response %v", err) } - } else { - responseBody, _ := response.AsString() - data["content"] = responseBody } result.AddData(data) + if check.ResponseJSONContent != nil { + ctx.Tracef("jsonContent is deprecated") + } + if ok := response.IsOK(check.ResponseCodes...); !ok { return results.Failf("response code invalid %d != %v", status, check.ResponseCodes) } @@ -272,29 +272,3 @@ func statusCodeToClass(statusCode int) string { return "unknown" } } - -func checkJSONContent(jsonContent map[string]any, jsonCheck *v1.JSONCheck) error { - if jsonCheck == nil { - return nil - } - - jsonResult, err := jsonpath.Get(jsonCheck.Path, jsonContent) - if err != nil { - return fmt.Errorf("error getting jsonPath: %w", err) - } - - switch s := jsonResult.(type) { - case string: - if s != jsonCheck.Value { - return fmt.Errorf("%v not equal to %v", s, jsonCheck.Value) - } - case fmt.Stringer: - if s.String() != jsonCheck.Value { - return fmt.Errorf("%v not equal to %v", s.String(), jsonCheck.Value) - } - default: - return fmt.Errorf("json response could not be parsed back to string") - } - - return nil -} From 3486268237aacd40058710ce0015240c9bbe02bd Mon Sep 17 00:00:00 2001 From: Moshe Immerman Date: Wed, 18 Oct 2023 14:59:10 +0300 Subject: [PATCH 10/11] chore: update manifests [ckip ci] --- config/deploy/crd.yaml | 2 +- config/deploy/manifests.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/config/deploy/crd.yaml b/config/deploy/crd.yaml index 8211b31c5..f80c8d552 100644 --- a/config/deploy/crd.yaml +++ b/config/deploy/crd.yaml @@ -3208,7 +3208,7 @@ spec: description: Exact response content expected to be returned by the endpoint. type: string responseJSONContent: - description: Path and value to of expect JSON response by the endpoint + description: Deprecated, use expr and jsonpath function properties: path: type: string diff --git a/config/deploy/manifests.yaml b/config/deploy/manifests.yaml index 228a51f38..690074867 100644 --- a/config/deploy/manifests.yaml +++ b/config/deploy/manifests.yaml @@ -3208,7 +3208,7 @@ spec: description: Exact response content expected to be returned by the endpoint. type: string responseJSONContent: - description: Path and value to of expect JSON response by the endpoint + description: Deprecated, use expr and jsonpath function properties: path: type: string From fa1d75c1e1ed258bb8915e3e93f32096914e7e2c Mon Sep 17 00:00:00 2001 From: Moshe Immerman Date: Wed, 18 Oct 2023 15:28:46 +0300 Subject: [PATCH 11/11] chore: enable http insecure tls by default --- checks/http.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/checks/http.go b/checks/http.go index 38cb887b8..79e177943 100644 --- a/checks/http.go +++ b/checks/http.go @@ -64,7 +64,7 @@ func (c *HTTPChecker) Run(ctx *context.Context) pkg.Results { } func (c *HTTPChecker) generateHTTPRequest(ctx *context.Context, check v1.HTTPCheck, connection *models.Connection) (*http.Request, error) { - client := http.NewClient().UserAgent("canary-checker/" + runner.Version) + client := http.NewClient().UserAgent("canary-checker/" + runner.Version).InsecureSkipVerify(true) for _, header := range check.Headers { value, err := ctx.GetEnvValueFromCache(header)