Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 26 additions & 59 deletions cmd/detect.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,79 +4,46 @@ Copyright © 2023 Henry Whitaker <henrywhitaker3@outlook.com>
package cmd

import (
"github.com/henrywhitaker3/argo-zombies/internal/config"
"github.com/henrywhitaker3/argo-zombies/internal/dashboard"
"github.com/henrywhitaker3/argo-zombies/internal/app"
"github.com/henrywhitaker3/argo-zombies/internal/detector"
"github.com/henrywhitaker3/argo-zombies/internal/k8s"
"github.com/henrywhitaker3/argo-zombies/internal/views/detect"
"github.com/spf13/cobra"
)

// detectCmd represents the detect command
var detectCmd = &cobra.Command{
Use: "detect",
Short: "Detect and list any resources not managed by ArgoCD",
RunE: func(cmd *cobra.Command, args []string) error {
client, err := k8s.NewClient(cmd.Flag("kubeconfig").Value.String())
if err != nil {
return err
}
dynClient, err := k8s.NewDynamicClient(cmd.Flag("kubeconfig").Value.String())
if err != nil {
return err
}
func NewDetectCommand(app *app.App) *cobra.Command {
return &cobra.Command{
Use: "detect",
Short: "Detect and list any resources not managed by ArgoCD",
RunE: func(cmd *cobra.Command, args []string) error {
client, err := k8s.NewClient(cmd.Flag("kubeconfig").Value.String())
if err != nil {
return err
}
dynClient, err := k8s.NewDynamicClient(cmd.Flag("kubeconfig").Value.String())
if err != nil {
return err
}

d := detector.NewDetector(client, dynClient)
d := detector.NewDetector(client, dynClient, app.Config)

c, err := d.Detect(cmd.Context())
if err != nil {
return err
}
c, err := d.Detect(cmd.Context())
if err != nil {
return err
}

tbl := detect.NewTable(c)
tbl.Print()
tbl := detect.NewTable(c)
tbl.Print()

if dashboardEnabled(config.Cfg) {
iB, err := detect.NewMarkdown(c)
if err != nil {
return err
}

if config.Cfg.Dashboards.Github.Enabled {
gh := dashboard.NewGithub(cmd.Context(), config.Cfg.Dashboards.Github.Repo, config.Cfg.Dashboards.Github.Token)
if err := gh.CreateOrUpdateDashboard(iB); err != nil {
panic(err)
}
}
if config.Cfg.Dashboards.Gitlab.Enabled {
gl, err := dashboard.NewGitlab(cmd.Context(), config.Cfg.Dashboards.Gitlab.Repo, config.Cfg.Dashboards.Gitlab.Token)
if err != nil {
panic(err)
}
if err := gl.CreateOrUpdateDashboard(iB); err != nil {
panic(err)
}
for _, tracker := range app.Trackers {
tracker.CreateOrUpdateDashboard(cmd.Context(), iB)
}
}

return nil
},
}

func init() {
rootCmd.AddCommand(detectCmd)

// Here you will define your flags and configuration settings.

// Cobra supports Persistent Flags which will work for this command
// and all subcommands, e.g.:
// detectCmd.PersistentFlags().String("foo", "", "A help for foo")

// Cobra supports local flags which will only run when this command
// is called directly, e.g.:
// detectCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
}

func dashboardEnabled(cfg *config.Config) bool {
return config.Cfg.Dashboards.Github.Enabled || config.Cfg.Dashboards.Gitlab.Enabled
return nil
},
}
}
38 changes: 10 additions & 28 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,39 +4,21 @@ Copyright © 2023 Henry Whitaker <henrywhitaker3@outlook.com>
package cmd

import (
"os"

"github.com/henrywhitaker3/argo-zombies/internal/app"
"github.com/spf13/cobra"
)

// rootCmd represents the base command when called without any subcommands
var rootCmd = &cobra.Command{
Use: "argo-zombies",
Short: "Find kubernetes resources which are not managed by ArgoCD",
Version: "0.1.12",
// Uncomment the following line if your bare application
// has an action associated with it:
// Run: func(cmd *cobra.Command, args []string) { },
}

// Execute adds all child commands to the root command and sets flags appropriately.
// This is called by main.main(). It only needs to happen once to the rootCmd.
func Execute() {
err := rootCmd.Execute()
if err != nil {
os.Exit(1)
func NewRootCommand(app *app.App) *cobra.Command {
cmd := &cobra.Command{
Use: "argo-zombies",
Short: "Find kubernetes resources which are not managed by ArgoCD",
Version: app.Version,
}
}

func init() {
// Here you will define your flags and configuration settings.
// Cobra supports persistent flags, which, if defined here,
// will be global for your application.
cmd.PersistentFlags().String("config", ".argo-zombies.yaml", "Path to the argo-zombies config file")
cmd.PersistentFlags().String("kubeconfig", "~/.kube/config", "Path to the kubeconfig file")

// rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.argo-zombies.yaml)")
cmd.AddCommand(NewDetectCommand(app))

// Cobra also supports local flags, which will only run
// when this action is called directly.
rootCmd.PersistentFlags().String("config", ".argo-zombies.yaml", "Path to the argo-zombies config file")
rootCmd.PersistentFlags().String("kubeconfig", "~/.kube/config", "Path to the kubeconfig file")
return cmd
}
5 changes: 4 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
module github.com/henrywhitaker3/argo-zombies

go 1.22.0
go 1.22.2

toolchain go1.22.5

require (
github.com/fatih/color v1.17.0
github.com/fatih/structs v1.1.0
github.com/google/go-github v17.0.0+incompatible
github.com/henrywhitaker3/ctxgen v1.0.1
github.com/rodaine/table v1.2.0
github.com/spf13/cobra v1.8.1
github.com/stretchr/testify v1.9.0
github.com/xanzy/go-gitlab v0.90.0
go.uber.org/zap v1.27.0
golang.org/x/oauth2 v0.21.0
gopkg.in/yaml.v3 v3.0.1
k8s.io/apimachinery v0.30.2
Expand Down Expand Up @@ -46,6 +48,7 @@ require (
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
go.uber.org/multierr v1.10.0 // indirect
golang.org/x/net v0.23.0 // indirect
golang.org/x/sys v0.18.0 // indirect
golang.org/x/term v0.18.0 // indirect
Expand Down
8 changes: 8 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ github.com/hashicorp/go-hclog v0.9.2 h1:CG6TE5H9/JXsFWJCfoIVpKFIkFe6ysEuHirp4DxC
github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ=
github.com/hashicorp/go-retryablehttp v0.7.2 h1:AcYqCvkpalPnPF2pn0KamgwamS42TqUDDYFRKq/RAd0=
github.com/hashicorp/go-retryablehttp v0.7.2/go.mod h1:Jy/gPYAdjqffZ/yFGCFV2doI5wjtH1ewM9u8iYVjtX8=
github.com/henrywhitaker3/ctxgen v1.0.1 h1:T1tsyUKS4ymBkqP9KBrVDh5fskzkdm2zTfLH0pw8dJ0=
github.com/henrywhitaker3/ctxgen v1.0.1/go.mod h1:Q9fBma6LqFfEqJbltrc1Icdp9YUA5M3UVcz7tqGfPLc=
github.com/imdario/mergo v0.3.6 h1:xTNEAn+kxVO7dTZGu0CegyqKZmoWFI0rF8UxjlB2d28=
github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
Expand Down Expand Up @@ -112,6 +114,12 @@ github.com/xanzy/go-gitlab v0.90.0 h1:j8ZUHfLfXdnC+B8njeNaW/kM44c1zw8fiuNj7D+qQN
github.com/xanzy/go-gitlab v0.90.0/go.mod h1:5ryv+MnpZStBH8I/77HuQBsMbBGANtVpLWC15qOjWAw=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ=
go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
Expand Down
36 changes: 36 additions & 0 deletions internal/app/app.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package app

import (
"context"

"github.com/henrywhitaker3/argo-zombies/internal/config"
"github.com/henrywhitaker3/argo-zombies/internal/dashboard"
"github.com/henrywhitaker3/argo-zombies/internal/detector"
)

type App struct {
Version string
Config *config.Config

Detector *detector.Detector
Trackers []Tracker
}

func New(cfg *config.Config) (*App, error) {
app := &App{Config: cfg}
if cfg.Dashboards.Github.Enabled {
app.Trackers = append(app.Trackers, dashboard.NewGithub(cfg.Dashboards.Github.Repo, cfg.Dashboards.Github.Token))
}
if cfg.Dashboards.Gitlab.Enabled {
t, err := dashboard.NewGitlab(cfg.Dashboards.Gitlab.Repo, cfg.Dashboards.Gitlab.Token)
if err != nil {
return nil, err
}
app.Trackers = append(app.Trackers, t)
}
return app, nil
}

type Tracker interface {
CreateOrUpdateDashboard(ctx context.Context, body string) error
}
40 changes: 27 additions & 13 deletions internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,42 +8,56 @@ import (
"github.com/henrywhitaker3/argo-zombies/internal/dashboard"
"github.com/henrywhitaker3/argo-zombies/internal/exclusions"
"github.com/henrywhitaker3/argo-zombies/internal/exclusions/bundles"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
"gopkg.in/yaml.v3"
)

var (
Cfg *Config
)
type LogLevel string

func (l LogLevel) Level() zap.AtomicLevel {
switch l {
case "info":
return zap.NewAtomicLevelAt(zapcore.InfoLevel)
case "debug":
return zap.NewAtomicLevelAt(zapcore.DebugLevel)
case "error":
fallthrough
default:
return zap.NewAtomicLevelAt(zapcore.ErrorLevel)
}
}

type Config struct {
LogLevel LogLevel `yaml:"logLevel"`
Exclusions exclusions.Exclusions `yaml:"exclusions"`
Dashboards struct {
Github dashboard.GithubDashboard `yaml:"github"`
Gitlab dashboard.GitlabDashboard `yaml:"gitlab"`
} `yaml:"dashboards"`
}

func LoadConfig(path string) error {
Cfg = &Config{}
Cfg.setDefaults()
func LoadConfig(path string) (*Config, error) {
c := &Config{}
c.setDefaults()

file, err := os.ReadFile(path)
if err != nil {
if errors.Is(err, os.ErrNotExist) {
return nil
return c, nil
}

return err
return nil, err
}

if err := yaml.Unmarshal(file, Cfg); err != nil {
return err
if err := yaml.Unmarshal(file, c); err != nil {
return nil, err
}

Cfg.addBundles()
Cfg.loadEnvVars()
c.addBundles()
c.loadEnvVars()

return nil
return c, nil
}

func (c *Config) setDefaults() {
Expand Down
21 changes: 12 additions & 9 deletions internal/config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,28 +8,31 @@ import (
)

func TestItReturnsAnEmptyConfigWhenNoFileProvided(t *testing.T) {
if err := LoadConfig("bongo"); err != nil {
cfg, err := LoadConfig("bongo")
if err != nil {
t.Error(err)
}

assert.Equal(t, []string{}, Cfg.Exclusions.Namespaces)
assert.Equal(t, []string{}, Cfg.Exclusions.Bundles)
assert.Equal(t, []exclusions.ExcludedGroupVersionResource{}, Cfg.Exclusions.GroupVersionResources)
assert.Equal(t, []exclusions.ExcludedMetadata{}, Cfg.Exclusions.Selectors)
assert.Equal(t, []string{}, cfg.Exclusions.Namespaces)
assert.Equal(t, []string{}, cfg.Exclusions.Bundles)
assert.Equal(t, []exclusions.ExcludedGroupVersionResource{}, cfg.Exclusions.GroupVersionResources)
assert.Equal(t, []exclusions.ExcludedMetadata{}, cfg.Exclusions.Selectors)
}

func TestItSetsGithubDashboardAsDisabledByDefault(t *testing.T) {
if err := LoadConfig("bongo"); err != nil {
cfg, err := LoadConfig("bongo")
if err != nil {
t.Error(err)
}

assert.Equal(t, false, Cfg.Dashboards.Github.Enabled)
assert.Equal(t, false, cfg.Dashboards.Github.Enabled)
}

func TestItSetsGitlabDashboardAsDisabledByDefault(t *testing.T) {
if err := LoadConfig("bongo"); err != nil {
cfg, err := LoadConfig("bongo")
if err != nil {
t.Error(err)
}

assert.Equal(t, false, Cfg.Dashboards.Gitlab.Enabled)
assert.Equal(t, false, cfg.Dashboards.Gitlab.Enabled)
}
Loading