Skip to content

Commit

Permalink
Merge branch 'main' into enable-shallow-cloning
Browse files Browse the repository at this point in the history
Signed-off-by: Mmadu Manasseh <manasseh.mmadu@zapier.com>
  • Loading branch information
MeNsaaH authored Feb 24, 2025
2 parents 012a083 + 7a476ba commit a0cb272
Show file tree
Hide file tree
Showing 16 changed files with 174 additions and 74 deletions.
2 changes: 1 addition & 1 deletion charts/kubechecks/Chart.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
apiVersion: v2
name: kubechecks
description: A Helm chart for kubechecks
version: 0.5.3
version: 0.5.4
type: application
maintainers:
- name: zapier
1 change: 1 addition & 0 deletions charts/kubechecks/templates/deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ metadata:
{{- end}}
labels: {{- include "kubechecks.labels" . | nindent 4 }}
spec:
revisionHistoryLimit: {{ .Values.deployment.revisionHistoryLimit }}
replicas: {{ .Values.deployment.replicaCount }}
selector:
matchLabels:
Expand Down
3 changes: 3 additions & 0 deletions charts/kubechecks/values.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,9 @@
"readinessProbe": {
"type": "object"
},
"revisionHistoryLimit": {
"type": "integer"
},
"replicaCount": {
"type": "integer"
},
Expand Down
1 change: 1 addition & 0 deletions charts/kubechecks/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ deployment:
memory: 256Mi
cpu: 200m

revisionHistoryLimit: 10
replicaCount: 1

image:
Expand Down
3 changes: 3 additions & 0 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,9 @@ func init() {
boolFlag(flags, "repo-shallow-clone", "Enable shallow cloning for all git repos.",
newBoolOpts().
withDefault(false))
stringFlag(flags, "identifier", "Identifier for the kubechecks instance. Used to differentiate between multiple kubechecks instances.",
newStringOpts().
withDefault(""))

panicIfError(viper.BindPFlags(flags))
setupLogOutput()
Expand Down
1 change: 1 addition & 0 deletions docs/usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ The full list of supported environment variables is described below:
|`KUBECHECKS_GITHUB_APP_ID`|Github App ID.|`0`|
|`KUBECHECKS_GITHUB_INSTALLATION_ID`|Github Installation ID.|`0`|
|`KUBECHECKS_GITHUB_PRIVATE_KEY`|Github App Private Key.||
|`KUBECHECKS_IDENTIFIER`|Identifier for the kubechecks instance. Used to differentiate between multiple kubechecks instances.||
|`KUBECHECKS_KUBERNETES_CLUSTERID`|Kubernetes Cluster ID, must be specified if kubernetes-type is eks.||
|`KUBECHECKS_KUBERNETES_CONFIG`|Path to your kubernetes config file, used to monitor applications.||
|`KUBECHECKS_KUBERNETES_TYPE`|Kubernetes Type One of eks, or local.|`local`|
Expand Down
1 change: 1 addition & 0 deletions localdev/kubechecks/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ configMap:
KUBECHECKS_TIDY_OUTDATED_COMMENTS_MODE: "delete"
KUBECHECKS_ENABLE_CONFTEST: "false"
KUBECHECKS_REPO_SHALLOW_CLONE: "true"
KUBECHECKS_IDENTIFIER: "test"

deployment:
annotations:
Expand Down
1 change: 1 addition & 0 deletions pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ type ServerConfig struct {
MaxQueueSize int64 `mapstructure:"max-queue-size"`
MaxConcurrenctChecks int `mapstructure:"max-concurrenct-checks"`
ReplanCommentMessage string `mapstructure:"replan-comment-msg"`
Identifier string `mapstructure:"identifier"`
}

func New() (ServerConfig, error) {
Expand Down
11 changes: 8 additions & 3 deletions pkg/events/check.go
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,10 @@ func (ce *CheckEvent) Process(ctx context.Context) error {

if len(ce.affectedItems.Applications) <= 0 && len(ce.affectedItems.ApplicationSets) <= 0 {
ce.logger.Info().Msg("No affected apps or appsets, skipping")
if _, err := ce.ctr.VcsClient.PostMessage(ctx, ce.pullRequest, "No changes"); err != nil {
if _, err := ce.ctr.VcsClient.PostMessage(ctx, ce.pullRequest, fmt.Sprintf(`
## Kubechecks %s Report
No changes
`, ce.ctr.Config.Identifier)); err != nil {
return errors.Wrap(err, "failed to post changes")
}
return nil
Expand Down Expand Up @@ -325,7 +328,7 @@ func (ce *CheckEvent) Process(ctx context.Context) error {

ce.logger.Info().Msg("Finished")

comment := ce.vcsNote.BuildComment(ctx, start, ce.pullRequest.SHA, ce.ctr.Config.LabelFilter, ce.ctr.Config.ShowDebugInfo)
comment := ce.vcsNote.BuildComment(ctx, start, ce.pullRequest.SHA, ce.ctr.Config.LabelFilter, ce.ctr.Config.ShowDebugInfo, ce.ctr.Config.Identifier)

if err = ce.ctr.VcsClient.UpdateMessage(ctx, ce.vcsNote, comment); err != nil {
return errors.Wrap(err, "failed to push comment")
Expand Down Expand Up @@ -403,5 +406,7 @@ func (ce *CheckEvent) createNote(ctx context.Context) (*msg.Message, error) {

ce.logger.Info().Msgf("Creating note")

return ce.ctr.VcsClient.PostMessage(ctx, ce.pullRequest, ":hourglass: kubechecks running ... ")
return ce.ctr.VcsClient.PostMessage(ctx, ce.pullRequest, fmt.Sprintf(`
## Kubechecks %s Report
:hourglass: kubechecks running ... `, ce.ctr.Config.Identifier))
}
41 changes: 34 additions & 7 deletions pkg/kustomize/process.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,25 +8,49 @@ import (
"strings"

"github.com/pkg/errors"
"github.com/rs/zerolog/log"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/kustomize/kyaml/yaml"
)

// ProcessKustomizationFile processes a kustomization file and returns all the files and directories it references.
func ProcessKustomizationFile(sourceFS fs.FS, relKustomizationPath string) (files []string, dirs []string, err error) {
func ProcessKustomizationFile(sourceFS fs.FS, relKustomizationPath string) (files, dirs []string, err error) {
dirName := filepath.Dir(relKustomizationPath)
return processDir(sourceFS, dirName)

proc := processor{
visitedDirs: make(map[string]struct{}),
}

files, dirs, err = proc.processDir(sourceFS, dirName)
if err != nil {
return nil, nil, errors.Wrapf(err, "failed to process kustomize file %q", relKustomizationPath)
}

return files, dirs, nil
}

type processor struct {
visitedDirs map[string]struct{}
}

func processDir(sourceFS fs.FS, relBase string) (files []string, dirs []string, err error) {
func (p processor) processDir(sourceFS fs.FS, relBase string) (files, dirs []string, err error) {
if _, ok := p.visitedDirs[relBase]; ok {
log.Warn().Msgf("directory %q already processed", relBase)
return nil, nil, nil
}

log.Info().Msgf("processing directory %q", relBase)
p.visitedDirs[relBase] = struct{}{}

absKustPath := filepath.Join(relBase, "kustomization.yaml")

// Parse using official Kustomization type
file, err := sourceFS.Open(absKustPath)
if err != nil {
if os.IsNotExist(err) {
return nil, nil, nil // No kustomization.yaml in this directory
return nil, []string{relBase}, nil // No kustomization.yaml in this directory, the dir is the important thing
}

return nil, nil, errors.Wrapf(err, "failed to open file %q", absKustPath)
}

Expand All @@ -53,6 +77,10 @@ func processDir(sourceFS fs.FS, relBase string) (files []string, dirs []string,
files = append(files, kust.Crds...)
files = append(files, kust.Transformers...)

for _, helm := range kust.HelmCharts {
files = append(files, helm.ValuesFile)
}

for _, patch := range kust.Patches {
if patch.Path != "" {
files = append(files, patch.Path)
Expand Down Expand Up @@ -93,13 +121,12 @@ func processDir(sourceFS fs.FS, relBase string) (files []string, dirs []string,
}
}

// We now know this directory has a kustomization.yaml, so add it to "dirs".
allDirs := append([]string(nil), relBase)
allFiles := append([]string(nil), files...)
var allDirs []string

// process directories and add them
for _, relResource := range directories {
subFiles, subDirs, err := processDir(sourceFS, relResource)
subFiles, subDirs, err := p.processDir(sourceFS, relResource)
if err != nil {
return nil, nil, errors.Wrapf(err, "failed to process %q", relResource)
}
Expand Down
96 changes: 77 additions & 19 deletions pkg/kustomize/process_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,10 @@ func (d dummyFileInfo) Sys() interface{} { return nil }
func TestProcessDir(t *testing.T) {
t.Run("NoKustomization", func(t *testing.T) {
sourceFS := fstest.MapFS{}
files, dirs, err := processDir(sourceFS, "testdir")
files, dirs, err := ProcessKustomizationFile(sourceFS, filepath.Join("testdir", "kustomization.yaml"))
assert.NoError(t, err)
assert.Empty(t, files)
assert.Empty(t, dirs)
assert.Equal(t, []string{"testdir"}, dirs)
})

t.Run("OpenError", func(t *testing.T) {
Expand All @@ -70,7 +70,7 @@ func TestProcessDir(t *testing.T) {
return nil, fs.ErrNotExist
},
}
_, _, err := processDir(mfs, "testdir")
_, _, err := ProcessKustomizationFile(mfs, filepath.Join("testdir", "kustomation.yaml"))
require.Error(t, err)
assert.Contains(t, err.Error(), "failed to open file")
})
Expand All @@ -84,24 +84,26 @@ func TestProcessDir(t *testing.T) {
return nil, fs.ErrNotExist
},
}
_, _, err := processDir(mfs, "testdir")
_, _, err := ProcessKustomizationFile(mfs, filepath.Join("testdir", "kustomization.yaml"))
require.Error(t, err)
assert.Contains(t, err.Error(), "failed to read file")
})

t.Run("ValidKustomization", func(t *testing.T) {
kustContent := `
resources:
- resource.yaml
- resource.yaml
- ../rootdir
bases:
- base
- base
components:
- components
- components
`
sourceFS := fstest.MapFS{
"testdir/kustomization.yaml": &fstest.MapFile{
Data: []byte(kustContent),
},
"rootdir/file.yaml": &fstest.MapFile{},
"testdir/resource.yaml": &fstest.MapFile{},
"testdir/base/kustomization.yaml": &fstest.MapFile{
Data: []byte(`resources: ["base_resource.yaml"]`),
Expand All @@ -112,7 +114,7 @@ components:
},
}

files, dir, err := processDir(sourceFS, "testdir")
files, dirs, err := ProcessKustomizationFile(sourceFS, filepath.Join("testdir", "kustomization.yaml"))
require.NoError(t, err)

expectedFiles := []string{
Expand All @@ -122,18 +124,44 @@ components:
"testdir/base/base_resource.yaml",
"testdir/components/kustomization.yaml",
}
expectedDirs := []string{
"rootdir",
}
sort.Strings(files)
sort.Strings(expectedFiles)
assert.Equal(t, expectedFiles, files)
assert.Equal(t, expectedDirs, dirs)
})

expectedDirs := []string{
"testdir",
"testdir/base",
"testdir/components",
t.Run("relative components", func(t *testing.T) {
sourceFS := fstest.MapFS{
"apps/app1/overlays/env1/kustomization.yaml": &fstest.MapFile{
Data: []byte(`
components:
- ../../components/component1
- ../../components/component2
`),
},
"apps/app1/components/component1/kustomization.yaml": &fstest.MapFile{
Data: []byte(`
resources:
- resource1.yaml`),
},
"apps/app1/components/component1/resource1.yaml": &fstest.MapFile{},
"apps/app1/components/component2/resource1.yaml": &fstest.MapFile{},
"apps/app1/components/component2/resource2.yaml": &fstest.MapFile{},
}
sort.Strings(dir)
sort.Strings(expectedDirs)
assert.Equal(t, expectedDirs, dir)

files, dirs, err := ProcessKustomizationFile(sourceFS, filepath.Join("apps", "app1", "overlays", "env1", "kustomization.yaml"))
require.NoError(t, err)
assert.Equal(t, []string{
"apps/app1/overlays/env1/kustomization.yaml",
"apps/app1/components/component1/kustomization.yaml",
"apps/app1/components/component1/resource1.yaml",
}, files)
assert.Equal(t, []string{
"apps/app1/components/component2",
}, dirs)
})

t.Run("StrategicMergePatch", func(t *testing.T) {
Expand All @@ -149,7 +177,7 @@ patchesStrategicMerge:
},
}

files, _, err := processDir(sourceFS, "testdir")
files, _, err := ProcessKustomizationFile(sourceFS, filepath.Join("testdir", "kustomization.yaml"))
assert.NoError(t, err)
assert.Equal(t, []string{"testdir/kustomization.yaml"}, files)
})
Expand All @@ -166,7 +194,7 @@ patches:
"testdir/patch.yaml": &fstest.MapFile{},
}

files, _, err := processDir(sourceFS, "testdir")
files, _, err := ProcessKustomizationFile(sourceFS, filepath.Join("testdir", "kustomization.yaml"))
require.NoError(t, err)
assert.Contains(t, files, "testdir/patch.yaml")
})
Expand All @@ -183,7 +211,7 @@ patchesJson6902:
"testdir/patch.yaml": &fstest.MapFile{},
}

files, _, err := processDir(sourceFS, "testdir")
files, _, err := ProcessKustomizationFile(sourceFS, filepath.Join("testdir", "kustomization.yaml"))
require.NoError(t, err)
assert.Contains(t, files, "testdir/patch.yaml")
})
Expand All @@ -199,8 +227,38 @@ resources:
},
}

_, _, err := processDir(sourceFS, "testdir")
_, _, err := ProcessKustomizationFile(sourceFS, filepath.Join("testdir", "kustomization.yaml"))
assert.Error(t, err)
assert.Contains(t, err.Error(), "failed to stat testdir/missing-resource.yaml")
})

t.Run("helmChart", func(t *testing.T) {
kustContent := `
helmCharts:
- name: dummy
repo: https://dummy.local/repo
version: 1.2.3
releaseName: dummy
namespace: dummy
includeCRDs: true
valuesFile: values-dummy.yaml
`
valueContent := `
dummy:
labels:
release: dummy
`
sourceFS := fstest.MapFS{
"testdir/kustomization.yaml": &fstest.MapFile{
Data: []byte(kustContent),
},
"testdir/values-dummy.yaml": &fstest.MapFile{
Data: []byte(valueContent),
},
}

files, _, err := ProcessKustomizationFile(sourceFS, filepath.Join("testdir", "kustomization.yaml"))
assert.NoError(t, err)
assert.Contains(t, files, "testdir/values-dummy.yaml")
})
}
4 changes: 2 additions & 2 deletions pkg/msg/message.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,14 +142,14 @@ func (m *Message) buildFooter(start time.Time, commitSHA, labelFilter string, sh
}

// BuildComment iterates the map of all apps in this message, building a final comment from their current state
func (m *Message) BuildComment(ctx context.Context, start time.Time, commitSHA, labelFilter string, showDebugInfo bool) string {
func (m *Message) BuildComment(ctx context.Context, start time.Time, commitSHA, labelFilter string, showDebugInfo bool, identifier string) string {
_, span := tracer.Start(ctx, "buildComment")
defer span.End()

names := getSortedKeys(m.apps)

var sb strings.Builder
sb.WriteString("# Kubechecks Report\n")
sb.WriteString(fmt.Sprintf("# Kubechecks %s Report\n", identifier))

updateWritten := false
for _, appName := range names {
Expand Down
Loading

0 comments on commit a0cb272

Please sign in to comment.