Skip to content

Commit

Permalink
support multiple locations for schemas and policies
Browse files Browse the repository at this point in the history
also check and enforce linting
  • Loading branch information
djeebus committed Oct 11, 2023
1 parent a73f95f commit 35d1953
Show file tree
Hide file tree
Showing 235 changed files with 226 additions and 51,550 deletions.
10 changes: 10 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[*.go]
ij_any_blank_lines_after_imports = 1
ij_go_add_parentheses_for_single_import = true
ij_go_GROUP_CURRENT_PROJECT_IMPORTS = true
ij_go_group_stdlib_imports = true
ij_go_import_sorting = gofmt
ij_go_move_all_imports_in_one_declaration = true
ij_go_move_all_stdlib_imports_in_one_group = true
ij_go_remove_redundant_import_aliases = true
ij_go_use_back_quotes_for_imports = false
14 changes: 1 addition & 13 deletions .github/workflows/on_pull-request_docs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,4 @@ jobs:
--GOLANG_VERSION="${{ env.GOLANG_TOOL_VERSION }}"
- name: verify that the checked in file has not changed
run: |
#!/usr/bin/env bash
exitCode=0
# Log the actual diff for debugging purposes
git diff --name-only | cat
if ! git diff --exit-code --quiet; then
echo "Please run 'earthly +rebuild-docs' and commit the results to this PR"
exitCode=1
fi
exit $exitCode
run: ./hacks/exit-on-changed-files.sh "Please run 'earthly +rebuild-docs' and commit the results to this PR"
15 changes: 11 additions & 4 deletions Earthfile
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ test:
BUILD +ci-helm

ci-golang:
BUILD +fmt-golang
BUILD +lint-golang
BUILD +validate-golang
BUILD +test-golang
Expand Down Expand Up @@ -105,10 +106,7 @@ docker:

WORKDIR /app

COPY ./policy ./policy
VOLUME /app/policy

COPY ./schemas ./schemas
VOLUME /app/policies
VOLUME /app/schemas

COPY (+build-binary/kubechecks --GOARCH=amd64 --VARIANT=$TARGETVARIANT) .
Expand Down Expand Up @@ -148,6 +146,15 @@ docker-debug:

SAVE IMAGE --push $CI_REGISTRY_IMAGE

fmt-golang:
FROM +go-deps

WORKDIR /src
COPY . /src

RUN go fmt \
&& ./hacks/exit-on-changed-files.sh

lint-golang:
ARG STATICCHECK_VERSION="2023.1.3"

Expand Down
8 changes: 8 additions & 0 deletions cmd/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,18 @@ func newStringOpts() DocOpt[string] {
return DocOpt[string]{}
}

func newStringSliceOpts() DocOpt[[]string] {
return DocOpt[[]string]{}
}

func stringFlag(flags *pflag.FlagSet, name, usage string, opts ...DocOpt[string]) {
addFlag(name, usage, opts, flags.String, flags.StringP)
}

func stringSliceFlag(flags *pflag.FlagSet, name, usage string, opts ...DocOpt[[]string]) {
addFlag(name, usage, opts, flags.StringArray, flags.StringArrayP)
}

func addFlag[D any](
name, usage string,
opts []DocOpt[D],
Expand Down
12 changes: 8 additions & 4 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"github.com/spf13/viper"

"github.com/zapier/kubechecks/telemetry"
)

Expand Down Expand Up @@ -79,14 +80,17 @@ func init() {
withChoices("hide", "delete").
withDefault("hide"),
)
stringFlag(flags, "schemas-location", "Sets the schema location. Can be local path or git repository.",
newStringOpts().
withDefault("./schemas"))
stringSliceFlag(flags, "schemas-location", "Sets a schema location to be used for every check request. Can be a common path inside the repo being checked or a git url in either git or http(s) format.",
newStringSliceOpts().
withDefault([]string{"./schemas"}))

stringSliceFlag(flags, "policies-location", "Sets a policies location to be used for every check request. Can be a common path inside the repo being checked or a git url in either git or http(s) format.",
newStringSliceOpts().
withDefault([]string{"./policies"}))

panicIfError(viper.BindPFlags(flags))

setupLogOutput()

}

func initTelemetry(ctx context.Context) (*telemetry.OperatorTelemetry, error) {
Expand Down
15 changes: 15 additions & 0 deletions hacks/exit-on-changed-files.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#!/usr/bin/env bash

set -e

exitCode=0
message=$1

# Log the actual diff for debugging purposes
git diff --name-only | cat
if ! git diff --exit-code --quiet; then
echo "$message"
exitCode=1
fi

exit $exitCode
6 changes: 3 additions & 3 deletions pkg/affected_apps/best_effort.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,9 +115,9 @@ func isKustomizeApp(file string) bool {

func isKustomizeBaseComponentsChange(file string) bool {
return strings.Contains(file, "base/") ||
strings.Contains(file, "bases/") ||
strings.Contains(file, "components/") ||
strings.Contains(file, "resources/")
strings.Contains(file, "bases/") ||
strings.Contains(file, "components/") ||
strings.Contains(file, "resources/")
}

func overlaysDir(file string) string {
Expand Down
27 changes: 22 additions & 5 deletions pkg/conftest/conftest.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,13 @@ import (
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
"github.com/olekukonko/tablewriter"
"github.com/open-policy-agent/conftest/output"
"github.com/open-policy-agent/conftest/runner"
"github.com/rs/zerolog/log"
"github.com/zapier/kubechecks/pkg"
"github.com/zapier/kubechecks/telemetry"
"github.com/spf13/viper"
"go.opentelemetry.io/otel"

"github.com/open-policy-agent/conftest/runner"
"github.com/zapier/kubechecks/pkg"
"github.com/zapier/kubechecks/telemetry"
)

var gitLabCommentFormat = `
Expand All @@ -32,6 +33,8 @@ var gitLabCommentFormat = `

const passedMessage = "\nPassed all policy checks."

var reposCache = pkg.NewReposDirectory()

// Conftest runs the conftest validation against an application in a given repository
// path. It generates a summary string with the results, which can later be posted
// as a GitLab comment. The validation checks resources against Zapier policies and
Expand All @@ -45,12 +48,26 @@ func Conftest(ctx context.Context, app *v1alpha1.Application, repoPath string) (

log.Debug().Str("dir", confTestDir).Str("app", app.Name).Msg("running conftest in dir for application")

var r = runner.TestRunner{}
policiesLocations := viper.GetStringSlice("policies-location")
var locations []string
for _, policiesLocation := range policiesLocations {
log.Debug().Str("schemas-location", policiesLocation).Msg("viper")
schemaPath := reposCache.EnsurePath(ctx, repoPath, policiesLocation)
if schemaPath != "" {
locations = append(locations, schemaPath)
}
}

if len(locations) == 0 {
return "no policies locations configured", nil
}

var r runner.TestRunner

r.NoColor = true
r.AllNamespaces = true
// PATH To Rego Polices
r.Policy = []string{"./policy"}
r.Policy = locations
r.SuppressExceptions = false
r.Trace = false

Expand Down
6 changes: 3 additions & 3 deletions pkg/events/check.go
Original file line number Diff line number Diff line change
Expand Up @@ -344,7 +344,7 @@ func (ce *CheckEvent) processApp(ctx context.Context, app, dir string) error {
grp, grpCtx := errgroup.WithContext(ctx)
wrap := ce.createWrapper(span, grpCtx, app)

grp.Go(wrap("validating app against schema", ce.validateSchemas(grpCtx, app, k8sVersion, formattedManifests)))
grp.Go(wrap("validating app against schema", ce.validateSchemas(grpCtx, app, k8sVersion, ce.TempWorkingDir, formattedManifests)))
grp.Go(wrap("generating diff for app", ce.generateDiff(grpCtx, app, manifests)))

if viper.GetBool("enable-conftest") {
Expand Down Expand Up @@ -431,9 +431,9 @@ func (ce *CheckEvent) generateDiff(ctx context.Context, app string, manifests []
}
}

func (ce *CheckEvent) validateSchemas(ctx context.Context, app string, k8sVersion string, formattedManifests []string) func() (string, error) {
func (ce *CheckEvent) validateSchemas(ctx context.Context, app, k8sVersion, tempRepoPath string, formattedManifests []string) func() (string, error) {
return func() (string, error) {
s, err := validate.ArgoCdAppValidate(ctx, app, k8sVersion, formattedManifests)
s, err := validate.ArgoCdAppValidate(ctx, app, k8sVersion, tempRepoPath, formattedManifests)
if err != nil {
return "", err
}
Expand Down
94 changes: 94 additions & 0 deletions pkg/gitRepos.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
package pkg

import (
"context"
"os"
"os/exec"
"path/filepath"
"strings"
"sync"

"github.com/rs/zerolog/log"

"github.com/zapier/kubechecks/pkg/repo"
)

type ReposDirectory struct {
paths map[string]string

mutex sync.Mutex
}

func NewReposDirectory() *ReposDirectory {
rd := &ReposDirectory{
paths: make(map[string]string),
}

return rd
}

func (rd *ReposDirectory) EnsurePath(ctx context.Context, tempRepoPath, location string) string {
if location == "" {
return ""
}

if strings.HasPrefix(location, "https://") || strings.HasPrefix(location, "http://") || strings.HasPrefix(location, "git@") {
log.Debug().Str("location", location).Msg("registering remote repository")
localPath := rd.Register(ctx, location)
return localPath
}

schemaPath := filepath.Join(tempRepoPath, location)
if stat, err := os.Stat(schemaPath); err == nil && stat.IsDir() {
log.Debug().Str("location", location).Msg("registering in-repo path")
return schemaPath
} else {
log.Warn().Str("location", location).Err(err).Msg("failed to find in-repo path")
}

return ""
}

func (rd *ReposDirectory) Register(ctx context.Context, cloneUrl string) string {
var (
ok bool
repoDir string
)

rd.mutex.Lock()
defer rd.mutex.Unlock()

repoDir, ok = rd.paths[cloneUrl]
if ok {
rd.fetchLatest()
return repoDir
}

return rd.clone(ctx, cloneUrl)
}

func (rd *ReposDirectory) fetchLatest() {
cmd := exec.Command("git", "pull")
err := cmd.Run()
if err != nil {
log.Err(err).Msg("failed to pull latest")
}
}

func (rd *ReposDirectory) clone(ctx context.Context, cloneUrl string) string {
repoDir, err := os.MkdirTemp("/tmp", "schemas")
if err != nil {
log.Err(err).Msg("failed to make temp dir")
return ""
}

r := repo.Repo{CloneURL: cloneUrl}
err = r.CloneRepoLocal(ctx, repoDir)
if err != nil {
log.Err(err).Str("clone-url", cloneUrl).Msg("failed to clone repository")
return ""
}

rd.paths[cloneUrl] = repoDir
return repoDir
}
1 change: 0 additions & 1 deletion pkg/gitlab_client/pipeline.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package gitlab_client

import (

"github.com/rs/zerolog/log"
"github.com/xanzy/go-gitlab"
)
Expand Down
Loading

0 comments on commit 35d1953

Please sign in to comment.