Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/main' into linting
Browse files Browse the repository at this point in the history
  • Loading branch information
djeebus committed Mar 21, 2024
2 parents 82a481c + b9d12cc commit ea5bd73
Show file tree
Hide file tree
Showing 66 changed files with 2,179 additions and 1,414 deletions.
24 changes: 16 additions & 8 deletions cmd/container.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,20 @@ import (
"github.com/zapier/kubechecks/pkg/argo_client"
"github.com/zapier/kubechecks/pkg/config"
"github.com/zapier/kubechecks/pkg/container"
"github.com/zapier/kubechecks/pkg/git"
"github.com/zapier/kubechecks/pkg/vcs/github_client"
"github.com/zapier/kubechecks/pkg/vcs/gitlab_client"
)

func newContainer(ctx context.Context, cfg config.ServerConfig) (container.Container, error) {
func newContainer(ctx context.Context, cfg config.ServerConfig, watchApps bool) (container.Container, error) {
var err error

var ctr = container.Container{
Config: cfg,
Config: cfg,
RepoManager: git.NewRepoManager(cfg),
}

// create vcs client
switch cfg.VcsType {
case "gitlab":
ctr.VcsClient, err = gitlab_client.CreateGitlabClient(cfg)
Expand All @@ -34,24 +37,29 @@ func newContainer(ctx context.Context, cfg config.ServerConfig) (container.Conta
return ctr, errors.Wrap(err, "failed to create vcs client")
}

// create argo client
if ctr.ArgoClient, err = argo_client.NewArgoClient(cfg); err != nil {
return ctr, errors.Wrap(err, "failed to create argo client")
}

vcsToArgoMap := appdir.NewVcsToArgoMap()
// create vcs to argo map
vcsToArgoMap := appdir.NewVcsToArgoMap(ctr.VcsClient.Username())
ctr.VcsToArgoMap = vcsToArgoMap

// watch app modifications, if necessary
if cfg.MonitorAllApplications {
if err = buildAppsMap(ctx, ctr.ArgoClient, ctr.VcsToArgoMap); err != nil {
return ctr, errors.Wrap(err, "failed to build apps map")
}

ctr.ApplicationWatcher, err = app_watcher.NewApplicationWatcher(vcsToArgoMap)
if err != nil {
return ctr, errors.Wrap(err, "failed to create watch applications")
}
if watchApps {
ctr.ApplicationWatcher, err = app_watcher.NewApplicationWatcher(vcsToArgoMap, cfg)
if err != nil {
return ctr, errors.Wrap(err, "failed to create watch applications")
}

go ctr.ApplicationWatcher.Run(ctx, 1)
go ctr.ApplicationWatcher.Run(ctx, 1)
}
}

return ctr, nil
Expand Down
37 changes: 25 additions & 12 deletions cmd/controller_cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,12 @@ import (
"github.com/spf13/viper"

"github.com/zapier/kubechecks/pkg"
"github.com/zapier/kubechecks/pkg/checks"
"github.com/zapier/kubechecks/pkg/config"
"github.com/zapier/kubechecks/pkg/container"
"github.com/zapier/kubechecks/pkg/events"
"github.com/zapier/kubechecks/pkg/git"
"github.com/zapier/kubechecks/pkg/server"
"github.com/zapier/kubechecks/pkg/vcs"
"github.com/zapier/kubechecks/telemetry"
)

Expand All @@ -40,24 +41,36 @@ var ControllerCmd = &cobra.Command{
log.Fatal().Err(err).Msg("failed to parse configuration")
}

ctr, err := newContainer(ctx, cfg)
ctr, err := newContainer(ctx, cfg, true)
if err != nil {
log.Fatal().Err(err).Msg("failed to create container")
}

log.Info().Msg("initializing git settings")
if err = initializeGit(ctr); err != nil {
log.Fatal().Err(err).Msg("failed to initialize git settings")
}

if err = processLocations(ctx, ctr, cfg.PoliciesLocation); err != nil {
log.Fatal().Err(err).Msg("failed to process policy locations")
}
if err = processLocations(ctx, ctr, cfg.SchemasLocations); err != nil {
log.Fatal().Err(err).Msg("failed to process schema locations")
}

processors, err := getProcessors(ctr)
if err != nil {
log.Fatal().Err(err).Msg("failed to create processors")
}

t, err := initTelemetry(ctx, cfg)
if err != nil {
log.Panic().Err(err).Msg("Failed to initialize telemetry")
}
defer t.Shutdown()

log.Info().Msg("initializing git settings")
if err = initializeGit(ctr); err != nil {
log.Fatal().Err(err).Msg("failed to initialize git settings")
}

log.Info().Msgf("starting web server")
startWebserver(ctx, ctr)
startWebserver(ctx, ctr, processors)

log.Info().Msgf("listening for requests")
waitForShutdown()
Expand All @@ -74,13 +87,13 @@ func initTelemetry(ctx context.Context, cfg config.ServerConfig) (*telemetry.Ope
)
}

func startWebserver(ctx context.Context, ctr container.Container) {
srv := server.NewServer(ctr)
func startWebserver(ctx context.Context, ctr container.Container, processors []checks.ProcessorEntry) {
srv := server.NewServer(ctr, processors)
go srv.Start(ctx)
}

func initializeGit(ctr container.Container) error {
if err := vcs.InitializeGitSettings(ctr.Config, ctr.VcsClient); err != nil {
if err := git.SetCredentials(ctr.Config, ctr.VcsClient); err != nil {
return err
}

Expand Down Expand Up @@ -123,7 +136,7 @@ func init() {
stringFlag(flags, "fallback-k8s-version", "Fallback target Kubernetes version for schema / upgrade checks (KUBECHECKS_FALLBACK_K8S_VERSION).",
newStringOpts().withDefault("1.23.0"))
boolFlag(flags, "show-debug-info", "Set to true to print debug info to the footer of MR comments (KUBECHECKS_SHOW_DEBUG_INFO).")
boolFlag(flags, "enable-conftest", "Set to true to enable conftest policy checking of manifests (KUBECHECKS_ENABLE_CONFTEST).")

stringFlag(flags, "label-filter", `(Optional) If set, The label that must be set on an MR (as "kubechecks:<value>") for kubechecks to process the merge request webhook (KUBECHECKS_LABEL_FILTER).`)
stringFlag(flags, "openai-api-token", "OpenAI API Token.")
stringFlag(flags, "webhook-url-base", "The endpoint to listen on for incoming PR/MR event webhooks. For example, 'https://checker.mycompany.com'.")
Expand Down
4 changes: 4 additions & 0 deletions cmd/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ func boolFlag(flags *pflag.FlagSet, name, usage string, opts ...DocOpt[bool]) {
addFlag(name, usage, opts, flags.Bool, flags.BoolP)
}

func newBoolOpts() DocOpt[bool] {
return DocOpt[bool]{}
}

func newStringOpts() DocOpt[string] {
return DocOpt[string]{}
}
Expand Down
82 changes: 82 additions & 0 deletions cmd/locations.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package cmd

import (
"context"
"path/filepath"
"strings"
"time"

"github.com/docker/docker/builder/remotecontext/urlutil"
"github.com/pkg/errors"
"github.com/rs/zerolog/log"

"github.com/zapier/kubechecks/pkg"
"github.com/zapier/kubechecks/pkg/container"
"github.com/zapier/kubechecks/pkg/git"
)

func processLocations(ctx context.Context, ctr container.Container, locations []string) error {
for index, location := range locations {
if newLocation, err := maybeCloneGitUrl(ctx, ctr.RepoManager, location, ctr.VcsClient.Username()); err != nil {
return errors.Wrapf(err, "failed to clone %q", location)
} else if newLocation != "" {
locations[index] = newLocation
}
}

return nil
}

type cloner interface {
Clone(ctx context.Context, cloneUrl, branchName string) (*git.Repo, error)
}

var ErrCannotUseQueryWithFilePath = errors.New("relative and absolute file paths cannot have query parameters")

func maybeCloneGitUrl(ctx context.Context, repoManager cloner, location, vcsUsername string) (string, error) {
result := strings.SplitN(location, "?", 2)
if !urlutil.IsGitURL(result[0]) {
if len(result) > 1 {
return "", ErrCannotUseQueryWithFilePath
}
return result[0], nil
}

repoUrl, query, err := pkg.NormalizeRepoUrl(location)
if err != nil {
return "", errors.Wrapf(err, "invalid git url: %q", location)
}
cloneUrl := repoUrl.CloneURL(vcsUsername)

repo, err := repoManager.Clone(ctx, cloneUrl, query.Get("branch"))
if err != nil {
return "", errors.Wrap(err, "failed to clone")
}

go func() {
tick := time.Tick(time.Minute * 5)
for {
select {
case <-ctx.Done():
return
case <-tick:
}

if err := repo.Update(ctx); err != nil {
log.Warn().
Err(err).
Str("path", repo.Directory).
Str("url", repo.CloneURL).
Msg("failed to update repo")
}
}
}()

path := repo.Directory
subdir := query.Get("subdir")
if subdir != "" {
path = filepath.Join(path, subdir)
}

return path, nil
}
Loading

0 comments on commit ea5bd73

Please sign in to comment.