cmd

package
v1.0.259 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 10, 2024 License: Apache-2.0 Imports: 64 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var AddCanary = &cobra.Command{
	Use:   "canary <system.yaml>",
	Short: "Add a new canary spec",
	Run: func(cmd *cobra.Command, configFiles []string) {

		if ctx, err := InitContext(); err != nil {
			logger.Fatalf("error connecting with postgres %v", err)
		} else {
			if err := configSync.SyncCanary(ctx, dataFile, configFiles...); err != nil {
				logger.Fatalf("Could not sync canaries: %v", err)
			}
		}
	},
}
View Source
var AddTopology = &cobra.Command{
	Use:   "topology <system.yaml>",
	Short: "Add a new topology spec",
	Run: func(cmd *cobra.Command, configFiles []string) {
		if err := configSync.SyncTopology(apicontext.DefaultContext, dataFile, configFiles...); err != nil {
			logger.Fatalf("Could not sync topology: %v", err)
		}
	},
}
View Source
var Docs = &cobra.Command{
	Use:    "docs",
	Short:  "Generate docs ",
	Hidden: true,
	Args:   cobra.MinimumNArgs(0),
	Run: func(cmd *cobra.Command, args []string) {
		printAPIDocs(args)
	},
}
View Source
var GoOffline = &cobra.Command{
	Use:  "go-offline",
	Long: "Download all dependencies.",
	Run: func(cmd *cobra.Command, args []string) {
		if err := db.GoOffline(); err != nil {
			logger.Fatalf("Failed to go offline: %+v", err)
		}

		databaseDir := "temp-database-dir"
		if err := os.Mkdir(databaseDir, 0755); err != nil {
			logger.Fatalf("Failed to create database directory[%s]: %+v", err)
		}
		defer os.RemoveAll(databaseDir)

		db.ConnectionString = "embedded://" + databaseDir
		if _, err := db.Connect(); err != nil {
			logger.Fatalf("Failed to run in embedded mode: %+v", err)
		}
		if err := db.PostgresServer.Stop(); err != nil {
			logger.Fatalf("Failed to stop embedded postgres: %+v", err)
		}

		os.Exit(0)
	},
}
View Source
var Operator = &cobra.Command{
	Use:   "operator",
	Short: "Start the kubernetes operator",
	Run:   run,
}
View Source
var QueryTopology = &cobra.Command{
	Use:   "query",
	Short: "Query the topology",
	Args:  cobra.MinimumNArgs(0),
	Run: func(cmd *cobra.Command, args []string) {
		if !db.IsConfigured() {
			logger.Fatalf("Must specify --db or DB_URL env")
		}

		results, err := topology.Query(apicontext.DefaultContext, queryParams)
		if err != nil {
			logger.Fatalf("Failed to query topology: %v", err)
		}
		data, _ := json.MarshalIndent(results, "", "  ")
		fmt.Println(string(data))
	},
}
View Source
var Root = &cobra.Command{
	Use: "canary-checker",
	PersistentPostRun: func(cmd *cobra.Command, args []string) {
		runner.Shutdown()
	},
	PersistentPreRun: func(cmd *cobra.Command, args []string) {
		logger.UseZap()

		canary.LogFail = logFail || logger.IsLevelEnabled(3)
		canary.LogPass = logPass || logger.IsLevelEnabled(4)

		db.ConnectionString = readFromEnv(db.ConnectionString)
		if db.ConnectionString == "DB_URL" {
			db.ConnectionString = ""
		}

		if canary.UpstreamConf.Valid() {
			logger.Infof("Pushing checks %s", canary.UpstreamConf)
		} else if canary.UpstreamConf.IsPartiallyFilled() {
			logger.Debugf("Upstream not fully configured: %s", canary.UpstreamConf)
		}

		if otelcollectorURL != "" {
			logger.Infof("Sending traces to %s", otelcollectorURL)

			runner.AddShutdownHook(telemetry.InitTracer(otelServiceName, otelcollectorURL, true))
		}
		if prometheus.PrometheusURL != "" {
			logger.Infof("Setting default prometheus: %s", prometheus.PrometheusURL)
			runner.Prometheus, _ = prometheus.NewPrometheusAPI(prometheus.PrometheusURL)
		}

		go func() {
			quit := make(chan os.Signal, 1)
			signal.Notify(quit, os.Interrupt)
			<-quit
			logger.Infof("Caught Ctrl+C")

			runner.Shutdown()
		}()
	},
}
View Source
var Run = &cobra.Command{
	Use:   "run <canary.yaml>",
	Short: "Execute checks and return",
	Run: func(cmd *cobra.Command, configFiles []string) {
		timer := timer.NewTimer()
		if len(configFiles) == 0 {
			log.Fatalln("Must specify at least one canary")
		}

		apicontext.DefaultContext, _ = InitContext()

		var results = []*pkg.CheckResult{}

		wg := sync.WaitGroup{}
		queue := make(chan []*pkg.CheckResult, 1)

		for _, configfile := range configFiles {
			configs, err := pkg.ParseConfig(configfile, dataFile)
			if err != nil {
				logger.Errorf("Could not parse %s: %v", configfile, err)
				continue
			}
			logger.Infof("Checking %s, %d checks found", configfile, len(configs))
			for _, config := range configs {
				if runNamespace != "" {
					config.Namespace = runNamespace
				}
				if config.Name == "" {
					config.Name = CleanupFilename(configfile)
				}
				log := logger.StandardLogger().Named(config.Name)
				wg.Add(1)
				_config := config
				go func() {
					defer wg.Done()

					res, err := checks.RunChecks(apicontext.New(apicontext.DefaultContext.WithName(_config.Name), _config))
					if err != nil {
						log.Errorf("error running checks: %v", err)
						return
					}

					queue <- res
				}()
			}
		}
		failed := 0
		passed := 0

		go func() {
			wg.Wait()
			close(queue)
		}()

		for item := range queue {
			for _, result := range item {
				if !result.Pass {
					failed++
				} else {
					passed++
				}
				logPass := result.Canary.IsDebug() || result.Canary.IsTrace() || logPass
				logFail := result.Canary.IsDebug() || result.Canary.IsTrace() || logFail

				if logPass && result.Pass || logFail && !result.Pass {
					logger.StandardLogger().Named(result.Canary.Name).Named(result.Name).Infof(result.String())
				}
				results = append(results, result)
			}
		}

		if junit {
			report := output.GetJunitReport(results)
			if err := output.HandleOutput(report, outputFile); err != nil {
				logger.Errorf("error writing output file: %v", err)
				os.Exit(1)
			}
		}
		if csv {
			report, err := output.GetCSVReport(results)
			if err != nil {
				logger.Errorf("error generating CSV file: %v", err)
				os.Exit(1)
			}
			if err := output.HandleOutput(report, outputFile); err != nil {
				logger.Errorf("error writing output file: %v", err)
				os.Exit(1)

			}
		}
		if jsonExport {
			for _, result := range results {
				result.Name = def(result.Name, result.Check.GetName(), result.Canary.Name)
				result.Description = def(result.Description, result.Check.GetDescription())
				result.Labels = merge(result.Check.GetLabels(), result.Labels)
			}

			data, err := json.Marshal(results)
			if err != nil {
				logger.Errorf("Failed to marshall json: %s", err)
				os.Exit(1)

			}
			_ = output.HandleOutput(string(data), outputFile)
		}

		logger.Infof("%d passed, %d failed in %s", passed, failed, timer)

		if failed > 0 {
			os.Exit(1)
		}
	},
}
View Source
var RunTopology = &cobra.Command{
	Use:   "run <system.yaml>",
	Short: "Execute topology and return",
	Run: func(cmd *cobra.Command, configFiles []string) {
		timer := timer.NewTimer()
		if len(configFiles) == 0 {
			logger.Errorf("Must specify at least one topology definition")
			os.Exit(1)
		}

		defer runner.Shutdown()
		var err error
		if apicontext.DefaultContext, err = InitContext(); err != nil {
			logger.Errorf(err.Error())
			return
		}

		var results = []*pkg.Component{}

		wg := sync.WaitGroup{}

		for _, configfile := range configFiles {
			_configfile := configfile
			configs, err := pkg.ParseTopology(configfile, dataFile)
			if err != nil {
				logger.Errorf("Could not parse %s: %v", configfile, err)
				continue
			}
			logger.Infof("Checking %s, %d topologies found", configfile, len(configs))
			for _, config := range configs {
				_config := config
				if _config.ID == uuid.Nil {
					_config.ID = uuid.MustParse(StaticTemplatedID)
					if _, err := db.PersistTopology(apicontext.DefaultContext, _config); err != nil {
						logger.Errorf(err.Error())
						continue
					}
				}
				wg.Add(1)
				go func() {
					ctx, span := apicontext.DefaultContext.StartSpan("Topology")
					defer span.End()
					components, _, err := topology.Run(ctx, *_config)
					if err != nil {
						logger.Errorf("[%s] error running %v", _configfile, err)
					}
					if db.IsConnected() {
						if err := db.PersistComponents(ctx, components); err != nil {
							logger.Errorf("error persisting results: %v", err)
						}
					}
					results = append(results, components...)
					wg.Done()
				}()
			}
		}
		wg.Wait()

		logger.Infof("Checked %d systems in %v", len(results), timer)

		if topologyOutput != "" {
			data, _ := json.Marshal(results)
			logger.Infof("Writing results to %s", topologyOutput)
			if err := os.WriteFile(topologyOutput, data, 0644); err != nil {
				log.Fatalln(err)
			}
		}
	},
}
View Source
var Serve = &cobra.Command{
	Use:   "serve config.yaml",
	Short: "Start a server to execute checks",
	Run: func(cmd *cobra.Command, configFiles []string) {
		defer runner.Shutdown()
		canaryJobs.StartScanCanaryConfigs(setup(), dataFile, configFiles)
		if executor {
			jobs.Start()
		}
		serve()
	},
}
View Source
var StaticTemplatedID string = "cf38821d-434f-4496-9bbd-c0c633bb2699"

StaticTemplatedID for topologies created by CLI, to ensure that components are updated rather than duplicated

View Source
var Sync = &cobra.Command{
	Use: "sync",
}
View Source
var Topology = &cobra.Command{
	Use: "topology",
}

Functions

func CleanupFilename added in v0.33.0

func CleanupFilename(fileName string) string

func InitContext added in v1.0.152

func InitContext() (context.Context, error)

func ParseDocumentationFrom

func ParseDocumentationFrom(srcs []string) map[string]*Struct

ParseDocumentationFrom gets all types' documentation and returns them as an array. Each type is again represented as an array (we have to use arrays as we need to be sure for the order of the fields). This function returns fields and struct definitions that have no documentation as {name, ""}.

func ServerFlags added in v0.38.4

func ServerFlags(flags *pflag.FlagSet)

Types

type Struct

type Struct struct {
	Name, Doc  string
	StructType *ast.StructType
	DocType    *doc.Type
	Fields     StructFields
}

func (Struct) Print added in v0.38.32

func (strukt Struct) Print(structs map[string]*Struct) string

type StructField

type StructField struct {
	Name, Doc, Type, ID string
	Mandatory           bool
	Markdown            string
}

func NewStructField

func NewStructField(field *ast.Field) StructField

func (StructField) MarkdownRow added in v0.38.32

func (f StructField) MarkdownRow(structs map[string]*Struct) string

type StructFields added in v0.38.32

type StructFields []StructField

func (StructFields) GetAllFields added in v0.38.32

func (s StructFields) GetAllFields(structs map[string]*Struct) StructFields

func (StructFields) Len added in v0.38.32

func (s StructFields) Len() int

func (StructFields) Less added in v0.38.32

func (s StructFields) Less(i, j int) bool

func (StructFields) Swap added in v0.38.32

func (s StructFields) Swap(i, j int)

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL