-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
14 changed files
with
1,021 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
# kdiscover | ||
|
||
A cli application used for discovering all EKS clusters that it can and exporting there kube-config's | ||
|
||
|
||
## ToDo | ||
|
||
- [x] allow for templated alias for the cluster name (give access to region, partition, cluster name, cluster arn) | ||
- [x] investigate maybe it is worth parsing the kubeconfig instead of executing another command | ||
- [ ] CleanUp comments. print statements | ||
- [ ] prepare a ci pipeline and maybe a cd one | ||
- [ ] prepare packages for brew to distribute this project (and maybe others) | ||
- [ ] add documentation to the readme | ||
- [ ] refactor modules (move from cmd to internals and add a better structure to internals) | ||
- [ ] add documentation to modules | ||
- [ ] add tests for important parts and expecially some integration tests |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
package cmd | ||
|
||
import ( | ||
"fmt" | ||
|
||
"github.com/jedib0t/go-pretty/table" | ||
"github.com/jedib0t/go-pretty/text" | ||
"github.com/mateimicu/kdiscover/internal" | ||
log "github.com/sirupsen/logrus" | ||
"github.com/spf13/cobra" | ||
) | ||
|
||
func newListCommand() *cobra.Command { | ||
listCommand := &cobra.Command{ | ||
Use: "list", | ||
Short: "List all EKS Clusters", | ||
Run: func(cmd *cobra.Command, args []string) { | ||
remoteEKSClusters := internal.GetEKSClusters(awsRegions) | ||
log.Info(remoteEKSClusters) | ||
|
||
tw := table.NewWriter() | ||
tw.AppendHeader(table.Row{"Cluster Name", "Region", "Status", "Exported Locally"}) | ||
rows := []table.Row{} | ||
for _, cls := range remoteEKSClusters { | ||
rows = append(rows, table.Row{cls.Name, cls.Region, cls.Status, getExportedString(&cls, kubeconfigPath)}) | ||
} | ||
tw.AppendRows(rows) | ||
|
||
tw.AppendFooter(table.Row{"", "Number of clusters", len(remoteEKSClusters)}) | ||
|
||
tw.SetAutoIndex(true) | ||
tw.SortBy([]table.SortBy{{Name: "Region", Mode: table.Dsc}}) | ||
|
||
tw.SetStyle(table.StyleLight) | ||
tw.Style().Format.Header = text.FormatLower | ||
tw.Style().Format.Footer = text.FormatLower | ||
tw.Style().Options.SeparateColumns = false | ||
tw.SetColumnConfigs([]table.ColumnConfig{ | ||
{ | ||
Name: "Exported Locally", | ||
Align: text.AlignCenter, | ||
AlignHeader: text.AlignCenter, | ||
}, | ||
}) | ||
// render it | ||
fmt.Println(tw.Render()) | ||
}, | ||
} | ||
|
||
return listCommand | ||
} | ||
|
||
func getExportedString(cls *internal.Cluster, kubeconfigPath string) string { | ||
if cls.IsExported(kubeconfigPath) { | ||
return "Yes" | ||
} | ||
return "No" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
package cmd | ||
|
||
import ( | ||
"fmt" | ||
"io/ioutil" | ||
"os" | ||
|
||
"github.com/mateimicu/kdiscover/internal" | ||
"github.com/spf13/cobra" | ||
|
||
log "github.com/sirupsen/logrus" | ||
) | ||
|
||
var ( | ||
awsPartitions []string | ||
awsRegions []string | ||
kubeconfigPath string | ||
debug bool | ||
rootCmd = &cobra.Command{ | ||
Use: "kdiscover", | ||
Short: "Discover all EKS clusters on an account.", | ||
Long: `kdiscover is a simple utility that can search | ||
all regions on an AWS account and try to find all EKS clsuters. | ||
It will try to upgrade the kube-config for each cluster.`, | ||
|
||
PersistentPreRun: func(cmd *cobra.Command, args []string) { | ||
if debug { | ||
log.SetLevel(log.DebugLevel) | ||
} else { | ||
log.SetOutput(ioutil.Discard) | ||
} | ||
|
||
log.WithFields(log.Fields{ | ||
"partitions": awsPartitions, | ||
}).Debug("Search regions for partitions") | ||
|
||
awsRegions = internal.GetRegions(awsPartitions) | ||
|
||
if len(awsRegions) == 0 { | ||
log.WithFields(log.Fields{ | ||
"partitions": awsPartitions, | ||
}).Error("Can't find regions for partitions") | ||
os.Exit(1) | ||
} | ||
|
||
log.WithFields(log.Fields{ | ||
"regions": awsRegions, | ||
}).Info("Founds regions") | ||
}, | ||
|
||
Run: func(cmd *cobra.Command, args []string) { | ||
cmd.HelpFunc()(cmd, args) | ||
}, | ||
} | ||
) | ||
|
||
func init() { | ||
rootCmd.PersistentFlags().BoolVar(&debug, "debug", false, "set log level to debug") | ||
|
||
rootCmd.PersistentFlags().StringSliceVar( | ||
&awsPartitions, | ||
"aws-partitions", | ||
[]string{"aws"}, | ||
fmt.Sprintf("In what partitions to search for clusters. Supported %v", internal.AllowedParitions())) | ||
|
||
rootCmd.PersistentFlags().StringVar(&kubeconfigPath, "kubeconfig-path", internal.GetDefaultKubeconfigPath(), "Path to the kubeconfig to work with") | ||
} | ||
|
||
// Execute will create the tree of commands and will start parsing and execution | ||
func Execute() { | ||
|
||
rootCmd.AddCommand(newListCommand()) | ||
rootCmd.AddCommand(newUpdateCommand()) | ||
|
||
if err := rootCmd.Execute(); err != nil { | ||
fmt.Println(err) | ||
os.Exit(1) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,140 @@ | ||
package cmd | ||
|
||
import ( | ||
"bytes" | ||
"fmt" | ||
"html/template" | ||
"io" | ||
"os" | ||
"path" | ||
|
||
"github.com/mateimicu/kdiscover/internal" | ||
log "github.com/sirupsen/logrus" | ||
"github.com/spf13/cobra" | ||
) | ||
|
||
var ( | ||
backupKubeconfig bool | ||
alias string | ||
) | ||
|
||
func newUpdateCommand() *cobra.Command { | ||
updateCommand := &cobra.Command{ | ||
Use: "update", | ||
Short: "Update all EKS Clusters", | ||
Run: func(cmd *cobra.Command, args []string) { | ||
fmt.Println(cmd.Short) | ||
remoteEKSClusters := internal.GetEKSClusters(awsRegions) | ||
log.Info(remoteEKSClusters) | ||
fmt.Printf("Found %v clusters remote\n", len(remoteEKSClusters)) | ||
if backupKubeconfig && fileExists(kubeconfigPath) { | ||
bName, err := generateBackupName(kubeconfigPath) | ||
if err != nil { | ||
log.WithFields(log.Fields{ | ||
"kubeconfig-path": kubeconfigPath, | ||
}).Info("Can't generate backup file name ") | ||
} | ||
fmt.Printf("Backup kubeconfig to %v\n", bName) | ||
copy(kubeconfigPath, bName) | ||
} | ||
internal.UpdateKubeconfig(remoteEKSClusters, kubeconfigPath, contextName{templateValue: alias}) | ||
}, | ||
} | ||
updateCommand.Flags().BoolVar(&backupKubeconfig, "backup-kubeconfig", true, "Backup cubeconfig before update") | ||
updateCommand.Flags().StringVar(&alias, "context-name-alias", "{{.Name}}", "Template for the context name. Has acces to Cluster type") | ||
|
||
return updateCommand | ||
} | ||
|
||
type contextName struct { | ||
templateValue string | ||
} | ||
|
||
func (c contextName) GetContextName(cls internal.Cluster) (string, error) { | ||
tmpl, err := template.New("context-name").Parse(c.templateValue) | ||
if err != nil { | ||
return "", err | ||
} | ||
var tpl bytes.Buffer | ||
err = tmpl.Execute(&tpl, cls) | ||
if err != nil { | ||
return "", err | ||
} | ||
return tpl.String(), nil | ||
} | ||
|
||
func copy(src, dst string) error { | ||
sourceFileStat, err := os.Stat(src) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
if !sourceFileStat.Mode().IsRegular() { | ||
return fmt.Errorf("%s is not a regular file", src) | ||
} | ||
|
||
source, err := os.Open(src) | ||
if err != nil { | ||
return err | ||
} | ||
defer source.Close() | ||
|
||
_, err = os.Stat(dst) | ||
if err == nil { | ||
return fmt.Errorf("file %s already exists", dst) | ||
} | ||
|
||
destination, err := os.Create(dst) | ||
if err != nil { | ||
return err | ||
} | ||
defer destination.Close() | ||
|
||
if err != nil { | ||
panic(err) | ||
} | ||
|
||
buf := make([]byte, 1000000) | ||
for { | ||
n, err := source.Read(buf) | ||
if err != nil && err != io.EOF { | ||
return err | ||
} | ||
if n == 0 { | ||
break | ||
} | ||
|
||
if _, err := destination.Write(buf[:n]); err != nil { | ||
return err | ||
} | ||
} | ||
return err | ||
} | ||
|
||
func generateBackupName(origin string) (string, error) { | ||
fi, err := os.Stat(origin) | ||
if err != nil { | ||
return "", err | ||
} | ||
if !fi.Mode().IsRegular() { | ||
return "", fmt.Errorf("%s is not a regular file", origin) | ||
} | ||
oName := path.Base(origin) | ||
oDir := path.Dir(origin) | ||
for { | ||
if fileExists(path.Join(oDir, oName)) { | ||
oName = oName + ".bak" | ||
} else { | ||
break | ||
} | ||
} | ||
return path.Join(oDir, oName), nil | ||
} | ||
|
||
func fileExists(filename string) bool { | ||
info, err := os.Stat(filename) | ||
if os.IsNotExist(err) { | ||
return false | ||
} | ||
return !info.IsDir() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
module github.com/mateimicu/kdiscover | ||
|
||
go 1.13 | ||
|
||
require ( | ||
github.com/Masterminds/semver v1.5.0 | ||
github.com/aws/aws-sdk-go v1.29.29 | ||
github.com/google/martian v2.1.0+incompatible | ||
github.com/jedib0t/go-pretty v4.3.0+incompatible | ||
github.com/mateimicu/eks-discover v0.0.0-20200419024348-4eb34377d311 | ||
github.com/mitchellh/go-homedir v1.1.0 | ||
github.com/sirupsen/logrus v1.2.0 | ||
github.com/spf13/cobra v0.0.6 | ||
github.com/spf13/viper v1.4.0 | ||
google.golang.org/appengine v1.5.0 | ||
gopkg.in/yaml.v2 v2.2.8 | ||
k8s.io/client-go v0.18.2 | ||
k8s.io/utils v0.0.0-20200414100711-2df71ebbae66 | ||
) |
Oops, something went wrong.