mirror of
https://github.com/k8sgpt-ai/k8sgpt.git
synced 2026-03-19 11:33:08 +00:00
Compare commits
24 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
391c3fa7a8 | ||
|
|
8e99076497 | ||
|
|
c2b8732a5c | ||
|
|
3ed545f33f | ||
|
|
975813d328 | ||
|
|
9aa0e8960e | ||
|
|
0a124484a2 | ||
|
|
30faf84254 | ||
|
|
9ebb7de3c0 | ||
|
|
9e9cd7083d | ||
|
|
a8bf45134f | ||
|
|
4d5449f97a | ||
|
|
25f8dc390c | ||
|
|
32ddf6691c | ||
|
|
6e17c9e285 | ||
|
|
9f0cb6240e | ||
|
|
26db0f6941 | ||
|
|
2acab541bc | ||
|
|
53a19bb04d | ||
|
|
c8f3c946b0 | ||
|
|
b061566404 | ||
|
|
be061da5b6 | ||
|
|
5f548421c7 | ||
|
|
0afd52844b |
@@ -1 +1 @@
|
||||
{".":"0.1.3"}
|
||||
{".":"0.1.5"}
|
||||
41
CHANGELOG.md
41
CHANGELOG.md
@@ -1,5 +1,46 @@
|
||||
# Changelog
|
||||
|
||||
## [0.1.5](https://github.com/k8sgpt-ai/k8sgpt/compare/v0.1.4...v0.1.5) (2023-03-31)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* add & remove default filter(s) to analyze. ([32ddf66](https://github.com/k8sgpt-ai/k8sgpt/commit/32ddf6691ce083fd4283a1d5ac4b9f02e90df867))
|
||||
* add filter command add "list" subcommand ([#159](https://github.com/k8sgpt-ai/k8sgpt/issues/159)) ([6e17c9e](https://github.com/k8sgpt-ai/k8sgpt/commit/6e17c9e285e3871bb8f694b734a8cd6fd02e60f0))
|
||||
* check if filters does not empty on add & remove ([975813d](https://github.com/k8sgpt-ai/k8sgpt/commit/975813d3284719c877630ad20f90c6fe163283da))
|
||||
* remove filter prefix on subcommand ([30faf84](https://github.com/k8sgpt-ai/k8sgpt/commit/30faf842541c0be6b6483f71f6cf04d5cafecef5))
|
||||
* rework filters ([3ed545f](https://github.com/k8sgpt-ai/k8sgpt/commit/3ed545f33fb3ecb3827c03e8c89027c61386c44f))
|
||||
* update filters add & remove to be more consistent ([9aa0e89](https://github.com/k8sgpt-ai/k8sgpt/commit/9aa0e8960ee340208b4749954c99867842ba58b9))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* kubecontext flag has no effect ([a8bf451](https://github.com/k8sgpt-ai/k8sgpt/commit/a8bf45134ff3a72dc3e531d720f119790faff9d4))
|
||||
* spelling on dupplicateFilters ([0a12448](https://github.com/k8sgpt-ai/k8sgpt/commit/0a124484a23789376258413e73628c7b1d7abded))
|
||||
|
||||
|
||||
### Other
|
||||
|
||||
* renamed filter list file ([25f8dc3](https://github.com/k8sgpt-ai/k8sgpt/commit/25f8dc390cccd66965993f464351e671af11f8ac))
|
||||
|
||||
## [0.1.4](https://github.com/k8sgpt-ai/k8sgpt/compare/v0.1.3...v0.1.4) (2023-03-30)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* add Ingress class validation ([#154](https://github.com/k8sgpt-ai/k8sgpt/issues/154)) ([b061566](https://github.com/k8sgpt-ai/k8sgpt/commit/b061566404ef80288ca29add2d401574109d44c0))
|
||||
* output selected backend ([#153](https://github.com/k8sgpt-ai/k8sgpt/issues/153)) ([be061da](https://github.com/k8sgpt-ai/k8sgpt/commit/be061da5b65045938acd70ad2eb2d21b87d2d6bf))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* now supports different kubeconfig and kubectx ([c8f3c94](https://github.com/k8sgpt-ai/k8sgpt/commit/c8f3c946b00c00cd185961a4fa777806da94014e))
|
||||
|
||||
|
||||
### Refactoring
|
||||
|
||||
* removed sample flag ([0afd528](https://github.com/k8sgpt-ai/k8sgpt/commit/0afd52844b96579391f77698bf0555145b6d2be8))
|
||||
|
||||
## [0.1.3](https://github.com/k8sgpt-ai/k8sgpt/compare/v0.1.2...v0.1.3) (2023-03-30)
|
||||
|
||||
|
||||
|
||||
32
README.md
32
README.md
@@ -47,6 +47,7 @@ If you install gcc as suggested, the problem will persist. Therefore, you need t
|
||||
* Currently the default AI provider is OpenAI, you will need to generate an API key from [OpenAI](https://openai.com)
|
||||
* You can do this by running `k8sgpt generate` to open a browser link to generate it
|
||||
* Run `k8sgpt auth` to set it in k8sgpt.
|
||||
* Run `k8sgpt filters` to manage the active filters used by the analyzer. By default, all filters are executed during analysis.
|
||||
* Run `k8sgpt analyze` to run a scan.
|
||||
* And use `k8sgpt analyze --explain` to get a more detailed explanation of the issues.
|
||||
|
||||
@@ -76,6 +77,7 @@ Available Commands:
|
||||
analyze This command will find problems within your Kubernetes cluster
|
||||
auth Authenticate with your chosen backend
|
||||
completion Generate the autocompletion script for the specified shell
|
||||
filters Manage filters for analyzing Kubernetes resources
|
||||
generate Generate Key for your chosen backend (opens browser)
|
||||
help Help about any command
|
||||
version Print the version number of k8sgpt
|
||||
@@ -90,6 +92,36 @@ Flags:
|
||||
Use "k8sgpt [command] --help" for more information about a command.
|
||||
```
|
||||
|
||||
_Manage filters_
|
||||
|
||||
_List filters_
|
||||
|
||||
```
|
||||
k8sgpt filters list
|
||||
```
|
||||
|
||||
_Add default filters_
|
||||
|
||||
```
|
||||
k8sgpt filters add [filter(s)]
|
||||
```
|
||||
|
||||
### Examples :
|
||||
|
||||
- Simple filter : `k8sgpt filters add Service`
|
||||
- Multiple filters : `k8sgpt filters add Ingress,Pod`
|
||||
|
||||
_Add default filters_
|
||||
|
||||
```
|
||||
k8sgpt filters remove [filter(s)]
|
||||
```
|
||||
|
||||
### Examples :
|
||||
|
||||
- Simple filter : `k8sgpt filters remove Service`
|
||||
- Multiple filters : `k8sgpt filters remove Ingress,Pod`
|
||||
|
||||
_Run a scan with the default analyzers_
|
||||
|
||||
```
|
||||
|
||||
@@ -35,6 +35,7 @@ var AuthCmd = &cobra.Command{
|
||||
// override the default backend if a flag is provided
|
||||
if backend != "" {
|
||||
backendType = backend
|
||||
color.Green("Using %s as backend AI provider", backendType)
|
||||
}
|
||||
|
||||
fmt.Printf("Enter %s Key: ", backendType)
|
||||
|
||||
71
cmd/filters/add.go
Normal file
71
cmd/filters/add.go
Normal file
@@ -0,0 +1,71 @@
|
||||
package filters
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/fatih/color"
|
||||
"github.com/k8sgpt-ai/k8sgpt/pkg/analyzer"
|
||||
"github.com/k8sgpt-ai/k8sgpt/pkg/util"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
var addCmd = &cobra.Command{
|
||||
Use: "add [filter(s)]",
|
||||
Short: "Adds one or more new filters.",
|
||||
Long: `The add command adds one or more new filters to the default set of filters used by the analyze.`,
|
||||
Args: cobra.ExactArgs(1),
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
inputFilters := strings.Split(args[0], ",")
|
||||
availableFilters := analyzer.ListFilters()
|
||||
|
||||
// Verify filter exist
|
||||
invalidFilters := []string{}
|
||||
for _, f := range inputFilters {
|
||||
if f == "" {
|
||||
color.Red("Filter cannot be empty. Please use correct syntax.")
|
||||
os.Exit(1)
|
||||
}
|
||||
foundFilter := false
|
||||
for _, filter := range availableFilters {
|
||||
if filter == f {
|
||||
foundFilter = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !foundFilter {
|
||||
invalidFilters = append(invalidFilters, f)
|
||||
}
|
||||
}
|
||||
|
||||
if len(invalidFilters) != 0 {
|
||||
color.Red("Filter %s does not exist. Please use k8sgpt filters list", strings.Join(invalidFilters, ", "))
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Get defined active_filters
|
||||
activeFilters := viper.GetStringSlice("active_filters")
|
||||
if len(activeFilters) == 0 {
|
||||
activeFilters = availableFilters
|
||||
}
|
||||
|
||||
mergedFilters := append(activeFilters, inputFilters...)
|
||||
|
||||
uniqueFilters, dupplicatedFilters := util.RemoveDuplicates(mergedFilters)
|
||||
|
||||
// Verify dupplicate
|
||||
if len(dupplicatedFilters) != 0 {
|
||||
color.Red("Duplicate filters found: %s", strings.Join(dupplicatedFilters, ", "))
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
viper.Set("active_filters", uniqueFilters)
|
||||
|
||||
if err := viper.WriteConfig(); err != nil {
|
||||
color.Red("Error writing config file: %s", err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
color.Green("Filter %s added", strings.Join(inputFilters, ", "))
|
||||
},
|
||||
}
|
||||
25
cmd/filters/filters.go
Normal file
25
cmd/filters/filters.go
Normal file
@@ -0,0 +1,25 @@
|
||||
package filters
|
||||
|
||||
import (
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var FiltersCmd = &cobra.Command{
|
||||
Use: "filters",
|
||||
Aliases: []string{"filters"},
|
||||
Short: "Manage filters for analyzing Kubernetes resources",
|
||||
Long: `The filters command allows you to manage filters that are used to analyze Kubernetes resources.
|
||||
You can list available filters to analyze resources.`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
if len(args) == 0 {
|
||||
cmd.Help()
|
||||
return
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
FiltersCmd.AddCommand(listCmd)
|
||||
FiltersCmd.AddCommand(addCmd)
|
||||
FiltersCmd.AddCommand(removeCmd)
|
||||
}
|
||||
39
cmd/filters/list.go
Normal file
39
cmd/filters/list.go
Normal file
@@ -0,0 +1,39 @@
|
||||
package filters
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/fatih/color"
|
||||
"github.com/k8sgpt-ai/k8sgpt/pkg/analyzer"
|
||||
"github.com/k8sgpt-ai/k8sgpt/pkg/util"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
var listCmd = &cobra.Command{
|
||||
Use: "list",
|
||||
Short: "List available filters",
|
||||
Long: `The list command displays a list of available filters that can be used to analyze Kubernetes resources.`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
activeFilters := viper.GetStringSlice("active_filters")
|
||||
availableFilters := analyzer.ListFilters()
|
||||
|
||||
if len(activeFilters) == 0 {
|
||||
activeFilters = availableFilters
|
||||
}
|
||||
|
||||
inactiveFilters := util.SliceDiff(availableFilters, activeFilters)
|
||||
fmt.Printf(color.YellowString("Active: \n"))
|
||||
for _, filter := range activeFilters {
|
||||
fmt.Printf("> %s\n", color.GreenString(filter))
|
||||
}
|
||||
// display inactive filters
|
||||
if len(inactiveFilters) != 0 {
|
||||
fmt.Printf(color.YellowString("Unused: \n"))
|
||||
for _, filter := range inactiveFilters {
|
||||
fmt.Printf("> %s\n", color.RedString(filter))
|
||||
}
|
||||
}
|
||||
|
||||
},
|
||||
}
|
||||
72
cmd/filters/remove.go
Normal file
72
cmd/filters/remove.go
Normal file
@@ -0,0 +1,72 @@
|
||||
package filters
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/fatih/color"
|
||||
"github.com/k8sgpt-ai/k8sgpt/pkg/analyzer"
|
||||
"github.com/k8sgpt-ai/k8sgpt/pkg/util"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
var removeCmd = &cobra.Command{
|
||||
Use: "remove [filter(s)]",
|
||||
Short: "Remove one or more filters.",
|
||||
Long: `The add command remove one or more filters to the default set of filters used by the analyze.`,
|
||||
Args: cobra.ExactArgs(1),
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
inputFilters := strings.Split(args[0], ",")
|
||||
|
||||
// Get defined active_filters
|
||||
activeFilters := viper.GetStringSlice("active_filters")
|
||||
if len(activeFilters) == 0 {
|
||||
activeFilters = analyzer.ListFilters()
|
||||
}
|
||||
|
||||
// Check if input input filters is not empty
|
||||
for _, f := range inputFilters {
|
||||
if f == "" {
|
||||
color.Red("Filter cannot be empty. Please use correct syntax.")
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
// verify dupplicate filters example: k8sgpt filters remove Pod Pod
|
||||
uniqueFilters, dupplicatedFilters := util.RemoveDuplicates(inputFilters)
|
||||
if len(dupplicatedFilters) != 0 {
|
||||
color.Red("Duplicate filters found: %s", strings.Join(dupplicatedFilters, ", "))
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Verify if filter exist in config file and update default_filter
|
||||
filterNotFound := []string{}
|
||||
for _, filter := range uniqueFilters {
|
||||
foundFilter := false
|
||||
for i, f := range activeFilters {
|
||||
if f == filter {
|
||||
foundFilter = true
|
||||
activeFilters = append(activeFilters[:i], activeFilters[i+1:]...)
|
||||
break
|
||||
}
|
||||
}
|
||||
if !foundFilter {
|
||||
filterNotFound = append(filterNotFound, filter)
|
||||
}
|
||||
}
|
||||
|
||||
if len(filterNotFound) != 0 {
|
||||
color.Red("Filter(s) %s does not exist in configuration file. Please use k8sgpt filters add.", strings.Join(filterNotFound, ", "))
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
viper.Set("active_filters", activeFilters)
|
||||
|
||||
if err := viper.WriteConfig(); err != nil {
|
||||
color.Red("Error writing config file: %s", err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
color.Green("Filter(s) %s removed", strings.Join(inputFilters, ", "))
|
||||
},
|
||||
}
|
||||
45
cmd/root.go
45
cmd/root.go
@@ -1,8 +1,12 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"github.com/k8sgpt-ai/k8sgpt/cmd/generate"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/k8sgpt-ai/k8sgpt/cmd/filters"
|
||||
"github.com/k8sgpt-ai/k8sgpt/cmd/generate"
|
||||
"k8s.io/client-go/util/homedir"
|
||||
|
||||
"github.com/fatih/color"
|
||||
"github.com/k8sgpt-ai/k8sgpt/cmd/analyze"
|
||||
@@ -13,10 +17,10 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
cfgFile string
|
||||
masterURL string
|
||||
kubeconfig string
|
||||
version string
|
||||
cfgFile string
|
||||
kubecontext string
|
||||
kubeconfig string
|
||||
version string
|
||||
)
|
||||
|
||||
// rootCmd represents the base command when called without any subcommands
|
||||
@@ -42,26 +46,20 @@ func Execute(v string) {
|
||||
func init() {
|
||||
cobra.OnInitialize(initConfig)
|
||||
|
||||
// Here you will define your flags and configuration settings.
|
||||
// Cobra supports persistent flags, which, if defined here,
|
||||
// will be global for your application.
|
||||
var kubeconfigPath string
|
||||
if home := homedir.HomeDir(); home != "" {
|
||||
kubeconfigPath = filepath.Join(home, ".kube", "config")
|
||||
}
|
||||
rootCmd.AddCommand(auth.AuthCmd)
|
||||
rootCmd.AddCommand(analyze.AnalyzeCmd)
|
||||
rootCmd.AddCommand(filters.FiltersCmd)
|
||||
rootCmd.AddCommand(generate.GenerateCmd)
|
||||
rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.k8sgpt.yaml)")
|
||||
rootCmd.PersistentFlags().StringVar(&masterURL, "master", "", "The address of the Kubernetes API server. Overrides any value in kubeconfig. Only required if out-of-cluster.")
|
||||
rootCmd.PersistentFlags().StringVar(&kubeconfig, "kubeconfig", "", "Path to a kubeconfig. Only required if out-of-cluster.")
|
||||
rootCmd.PersistentFlags().StringVar(&kubecontext, "kubecontext", "", "Kubernetes context to use. Only required if out-of-cluster.")
|
||||
rootCmd.PersistentFlags().StringVar(&kubeconfig, "kubeconfig", kubeconfigPath, "Path to a kubeconfig. Only required if out-of-cluster.")
|
||||
// Cobra also supports local flags, which will only run
|
||||
// when this action is called directly.
|
||||
rootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
|
||||
|
||||
//Initialise the kubeconfig
|
||||
kubernetesClient, err := kubernetes.NewClient(masterURL, kubeconfig)
|
||||
if err != nil {
|
||||
color.Red("Error initialising kubernetes client: %v", err)
|
||||
}
|
||||
|
||||
viper.Set("kubernetesClient", kubernetesClient)
|
||||
// rootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
|
||||
|
||||
}
|
||||
|
||||
@@ -83,6 +81,15 @@ func initConfig() {
|
||||
viper.SafeWriteConfig()
|
||||
}
|
||||
|
||||
//Initialise the kubeconfig
|
||||
kubernetesClient, err := kubernetes.NewClient(kubecontext, kubeconfig)
|
||||
if err != nil {
|
||||
color.Red("Error initialising kubernetes client: %v", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
viper.Set("kubernetesClient", kubernetesClient)
|
||||
|
||||
viper.AutomaticEnv() // read in environment variables that match
|
||||
|
||||
// If a config file is found, read it in.
|
||||
|
||||
@@ -24,8 +24,10 @@ func RunAnalysis(ctx context.Context, filters []string, config *AnalysisConfigur
|
||||
client *kubernetes.Client,
|
||||
aiClient ai.IAI, analysisResults *[]Analysis) error {
|
||||
|
||||
// if there are no filters selected then run all of them
|
||||
if len(filters) == 0 {
|
||||
activeFilters := viper.GetStringSlice("active_filters")
|
||||
|
||||
// if there are no filters selected and no active_filters then run all of them
|
||||
if len(filters) == 0 && len(activeFilters) == 0 {
|
||||
for _, analyzer := range analyzerMap {
|
||||
if err := analyzer(ctx, config, client, aiClient, analysisResults); err != nil {
|
||||
return err
|
||||
@@ -34,7 +36,20 @@ func RunAnalysis(ctx context.Context, filters []string, config *AnalysisConfigur
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, filter := range filters {
|
||||
// if the filters flag is specified
|
||||
if len(filters) != 0 {
|
||||
for _, filter := range filters {
|
||||
if analyzer, ok := analyzerMap[filter]; ok {
|
||||
if err := analyzer(ctx, config, client, aiClient, analysisResults); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// use active_filters
|
||||
for _, filter := range activeFilters {
|
||||
if analyzer, ok := analyzerMap[filter]; ok {
|
||||
if err := analyzer(ctx, config, client, aiClient, analysisResults); err != nil {
|
||||
return err
|
||||
@@ -81,3 +96,11 @@ func ParseViaAI(ctx context.Context, config *AnalysisConfiguration,
|
||||
}
|
||||
return response, nil
|
||||
}
|
||||
|
||||
func ListFilters() []string {
|
||||
keys := make([]string, 0, len(analyzerMap))
|
||||
for k := range analyzerMap {
|
||||
keys = append(keys, k)
|
||||
}
|
||||
return keys
|
||||
}
|
||||
|
||||
@@ -22,6 +22,26 @@ func AnalyzeIngress(ctx context.Context, config *AnalysisConfiguration, client *
|
||||
|
||||
for _, ing := range list.Items {
|
||||
var failures []string
|
||||
|
||||
// get ingressClassName
|
||||
ingressClassName := ing.Spec.IngressClassName
|
||||
if ingressClassName == nil {
|
||||
ingClassValue := ing.Annotations["kubernetes.io/ingress.class"]
|
||||
if ingClassValue == "" {
|
||||
failures = append(failures, fmt.Sprintf("Ingress %s/%s does not specify an Ingress class.", ing.Namespace, ing.Name))
|
||||
} else {
|
||||
ingressClassName = &ingClassValue
|
||||
}
|
||||
}
|
||||
|
||||
// check if ingressclass exist
|
||||
if ingressClassName != nil {
|
||||
_, err := client.GetClient().NetworkingV1().IngressClasses().Get(ctx, *ingressClassName, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
failures = append(failures, fmt.Sprintf("Ingress uses the ingress class %s which does not exist.", *ingressClassName))
|
||||
}
|
||||
}
|
||||
|
||||
// loop over rules
|
||||
for _, rule := range ing.Spec.Rules {
|
||||
// loop over paths
|
||||
|
||||
@@ -2,7 +2,6 @@ package kubernetes
|
||||
|
||||
import (
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/rest"
|
||||
"k8s.io/client-go/tools/clientcmd"
|
||||
)
|
||||
|
||||
@@ -14,21 +13,23 @@ func (c *Client) GetClient() *kubernetes.Clientset {
|
||||
return c.client
|
||||
}
|
||||
|
||||
func NewClient(masterURL string, kubeconfig string) (*Client, error) {
|
||||
func NewClient(kubecontext string, kubeconfig string) (*Client, error) {
|
||||
|
||||
config, err := rest.InClusterConfig()
|
||||
if err != nil {
|
||||
kubeconfig :=
|
||||
clientcmd.NewDefaultClientConfigLoadingRules().GetDefaultFilename()
|
||||
config, err = clientcmd.BuildConfigFromFlags(masterURL, kubeconfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
clientSet, err := kubernetes.NewForConfig(config)
|
||||
config := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(
|
||||
&clientcmd.ClientConfigLoadingRules{ExplicitPath: kubeconfig},
|
||||
&clientcmd.ConfigOverrides{
|
||||
CurrentContext: kubecontext,
|
||||
})
|
||||
// create the clientset
|
||||
c, err := config.ClientConfig()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
clientSet, err := kubernetes.NewForConfig(c)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &Client{
|
||||
client: clientSet,
|
||||
}, nil
|
||||
|
||||
@@ -65,3 +65,34 @@ func GetParent(client *kubernetes.Client, meta metav1.ObjectMeta) (string, bool)
|
||||
}
|
||||
return meta.Name, false
|
||||
}
|
||||
|
||||
func RemoveDuplicates(slice []string) ([]string, []string) {
|
||||
set := make(map[string]bool)
|
||||
duplicates := []string{}
|
||||
for _, val := range slice {
|
||||
if _, ok := set[val]; !ok {
|
||||
set[val] = true
|
||||
} else {
|
||||
duplicates = append(duplicates, val)
|
||||
}
|
||||
}
|
||||
uniqueSlice := make([]string, 0, len(set))
|
||||
for val := range set {
|
||||
uniqueSlice = append(uniqueSlice, val)
|
||||
}
|
||||
return uniqueSlice, duplicates
|
||||
}
|
||||
|
||||
func SliceDiff(source, dest []string) []string {
|
||||
mb := make(map[string]struct{}, len(dest))
|
||||
for _, x := range dest {
|
||||
mb[x] = struct{}{}
|
||||
}
|
||||
var diff []string
|
||||
for _, x := range source {
|
||||
if _, found := mb[x]; !found {
|
||||
diff = append(diff, x)
|
||||
}
|
||||
}
|
||||
return diff
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user