Signed-off-by: Alex Jones <alexsimonjones@gmail.com>
This commit is contained in:
Alex Jones 2023-04-11 12:30:57 +01:00
parent 80ac51c804
commit 4984840de1
22 changed files with 170 additions and 85 deletions

View File

@ -4,7 +4,6 @@ import (
"github.com/fatih/color" "github.com/fatih/color"
"github.com/k8sgpt-ai/k8sgpt/pkg/integration" "github.com/k8sgpt-ai/k8sgpt/pkg/integration"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/spf13/viper"
) )
// activateCmd represents the activate command // activateCmd represents the activate command
@ -16,7 +15,7 @@ var activateCmd = &cobra.Command{
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
intName := args[0] intName := args[0]
integration := viper.Get("integration").(*integration.Integration) integration := integration.NewIntegration()
// Check if the integation exists // Check if the integation exists
err := integration.Activate(intName, namespace) err := integration.Activate(intName, namespace)
if err != nil { if err != nil {
@ -26,7 +25,7 @@ var activateCmd = &cobra.Command{
color.Yellow("Activating analyzer for integration %s", intName) color.Yellow("Activating analyzer for integration %s", intName)
// TODO: // Write the integration to the config file
color.Green("Activate integration %s", intName) color.Green("Activate integration %s", intName)
}, },

View File

@ -7,7 +7,6 @@ import (
"github.com/fatih/color" "github.com/fatih/color"
"github.com/k8sgpt-ai/k8sgpt/pkg/integration" "github.com/k8sgpt-ai/k8sgpt/pkg/integration"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/spf13/viper"
) )
// deactivateCmd represents the deactivate command // deactivateCmd represents the deactivate command
@ -19,8 +18,7 @@ var deactivateCmd = &cobra.Command{
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
intName := args[0] intName := args[0]
// Check if the integation exists integration := integration.NewIntegration()
integration := viper.Get("integration").(*integration.Integration)
if err := integration.Deactivate(intName, namespace); err != nil { if err := integration.Deactivate(intName, namespace); err != nil {
color.Red("Error: %v", err) color.Red("Error: %v", err)

View File

@ -6,7 +6,6 @@ import (
var ( var (
namespace string namespace string
name string
) )
// IntegrationCmd represents the integrate command // IntegrationCmd represents the integrate command
@ -14,7 +13,8 @@ var IntegrationCmd = &cobra.Command{
Use: "integration", Use: "integration",
Short: "Intergrate another tool into K8sGPT", Short: "Intergrate another tool into K8sGPT",
Long: `Intergrate another tool into K8sGPT. For example: Long: `Intergrate another tool into K8sGPT. For example:
k8sgpt integration add trivy
k8sgpt integration activate trivy
This would allow you to deploy trivy into your cluster and use a K8sGPT analyzer to parse trivy results.`, This would allow you to deploy trivy into your cluster and use a K8sGPT analyzer to parse trivy results.`,
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
@ -23,6 +23,5 @@ var IntegrationCmd = &cobra.Command{
} }
func init() { func init() {
IntegrationCmd.PersistentFlags().StringVarP(&name, "name", "a", "", "The name of the integration")
IntegrationCmd.PersistentFlags().StringVarP(&namespace, "namespace", "n", "default", "The namespace to use for the integration") IntegrationCmd.PersistentFlags().StringVarP(&namespace, "namespace", "n", "default", "The namespace to use for the integration")
} }

View File

@ -2,11 +2,11 @@ package integration
import ( import (
"fmt" "fmt"
"os"
"github.com/fatih/color" "github.com/fatih/color"
"github.com/k8sgpt-ai/k8sgpt/pkg/integration" "github.com/k8sgpt-ai/k8sgpt/pkg/integration"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/spf13/viper"
) )
// listCmd represents the list command // listCmd represents the list command
@ -15,12 +15,31 @@ var listCmd = &cobra.Command{
Short: "Lists built-in integrations", Short: "Lists built-in integrations",
Long: ``, Long: ``,
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
integration := integration.NewIntegration()
integration := viper.Get("integration").(*integration.Integration)
integrations := integration.List() integrations := integration.List()
for _, integration := range integrations { fmt.Println(color.YellowString("Active:"))
fmt.Printf("> %s\n", color.GreenString(integration)) for _, i := range integrations {
b, err := integration.IsActivate(i)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
if b {
fmt.Printf("> %s\n", color.GreenString(i))
}
}
fmt.Println(color.YellowString("Unused: "))
for _, i := range integrations {
b, err := integration.IsActivate(i)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
if !b {
fmt.Printf("> %s\n", color.GreenString(i))
}
} }
}, },
} }

View File

@ -10,7 +10,6 @@ import (
"github.com/k8sgpt-ai/k8sgpt/cmd/filters" "github.com/k8sgpt-ai/k8sgpt/cmd/filters"
"github.com/k8sgpt-ai/k8sgpt/cmd/generate" "github.com/k8sgpt-ai/k8sgpt/cmd/generate"
"github.com/k8sgpt-ai/k8sgpt/cmd/integration" "github.com/k8sgpt-ai/k8sgpt/cmd/integration"
in "github.com/k8sgpt-ai/k8sgpt/pkg/integration"
"github.com/k8sgpt-ai/k8sgpt/pkg/kubernetes" "github.com/k8sgpt-ai/k8sgpt/pkg/kubernetes"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/spf13/viper" "github.com/spf13/viper"
@ -59,10 +58,6 @@ func init() {
rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.k8sgpt.yaml)") rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.k8sgpt.yaml)")
rootCmd.PersistentFlags().StringVar(&kubecontext, "kubecontext", "", "Kubernetes context to use. 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.") rootCmd.PersistentFlags().StringVar(&kubeconfig, "kubeconfig", kubeconfigPath, "Path to a kubeconfig. Only required if out-of-cluster.")
// Integration start up
integration := in.NewIntegration()
viper.Set("integration", integration)
} }
// initConfig reads in config file and ENV variables if set. // initConfig reads in config file and ENV variables if set.

2
go.mod
View File

@ -17,6 +17,7 @@ require (
k8s.io/api v0.26.3 k8s.io/api v0.26.3
k8s.io/apimachinery v0.26.3 k8s.io/apimachinery v0.26.3
k8s.io/client-go v0.26.3 k8s.io/client-go v0.26.3
k8s.io/kubectl v0.26.3
) )
require ( require (
@ -154,7 +155,6 @@ require (
k8s.io/component-base v0.26.3 // indirect k8s.io/component-base v0.26.3 // indirect
k8s.io/klog/v2 v2.90.1 // indirect k8s.io/klog/v2 v2.90.1 // indirect
k8s.io/kube-openapi v0.0.0-20230327201221-f5883ff37f0c // indirect k8s.io/kube-openapi v0.0.0-20230327201221-f5883ff37f0c // indirect
k8s.io/kubectl v0.26.3 // indirect
k8s.io/utils v0.0.0-20230313181309-38a27ef9d749 // indirect k8s.io/utils v0.0.0-20230313181309-38a27ef9d749 // indirect
oras.land/oras-go v1.2.2 // indirect oras.land/oras-go v1.2.2 // indirect
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect

View File

@ -10,6 +10,7 @@ import (
"github.com/fatih/color" "github.com/fatih/color"
"github.com/k8sgpt-ai/k8sgpt/pkg/ai" "github.com/k8sgpt-ai/k8sgpt/pkg/ai"
"github.com/k8sgpt-ai/k8sgpt/pkg/analyzer" "github.com/k8sgpt-ai/k8sgpt/pkg/analyzer"
"github.com/k8sgpt-ai/k8sgpt/pkg/common"
"github.com/k8sgpt-ai/k8sgpt/pkg/kubernetes" "github.com/k8sgpt-ai/k8sgpt/pkg/kubernetes"
"github.com/schollz/progressbar/v3" "github.com/schollz/progressbar/v3"
"github.com/spf13/viper" "github.com/spf13/viper"
@ -20,7 +21,7 @@ type Analysis struct {
Filters []string Filters []string
Client *kubernetes.Client Client *kubernetes.Client
AIClient ai.IAI AIClient ai.IAI
Results []analyzer.Result Results []common.Result
Namespace string Namespace string
NoCache bool NoCache bool
Explain bool Explain bool
@ -36,7 +37,7 @@ const (
type JsonOutput struct { type JsonOutput struct {
Status AnalysisStatus `json:"status"` Status AnalysisStatus `json:"status"`
Problems int `json:"problems"` Problems int `json:"problems"`
Results []analyzer.Result `json:"results"` Results []common.Result `json:"results"`
} }
func (a *Analysis) RunAnalysis() error { func (a *Analysis) RunAnalysis() error {
@ -45,7 +46,7 @@ func (a *Analysis) RunAnalysis() error {
analyzerMap := analyzer.GetAnalyzerMap() analyzerMap := analyzer.GetAnalyzerMap()
analyzerConfig := analyzer.Analyzer{ analyzerConfig := common.Analyzer{
Client: a.Client, Client: a.Client,
Context: a.Context, Context: a.Context,
Namespace: a.Namespace, Namespace: a.Namespace,

View File

@ -3,22 +3,23 @@ package analysis
import ( import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"github.com/k8sgpt-ai/k8sgpt/pkg/analyzer"
"github.com/stretchr/testify/require"
"testing" "testing"
"github.com/k8sgpt-ai/k8sgpt/pkg/common"
"github.com/stretchr/testify/require"
) )
func TestAnalysis_NoProblemJsonOutput(t *testing.T) { func TestAnalysis_NoProblemJsonOutput(t *testing.T) {
analysis := Analysis{ analysis := Analysis{
Results: []analyzer.Result{}, Results: []common.Result{},
Namespace: "default", Namespace: "default",
} }
expected := JsonOutput{ expected := JsonOutput{
Status: StateOK, Status: StateOK,
Problems: 0, Problems: 0,
Results: []analyzer.Result{}, Results: []common.Result{},
} }
gotJson, err := analysis.JsonOutput() gotJson, err := analysis.JsonOutput()
@ -40,7 +41,7 @@ func TestAnalysis_NoProblemJsonOutput(t *testing.T) {
func TestAnalysis_ProblemJsonOutput(t *testing.T) { func TestAnalysis_ProblemJsonOutput(t *testing.T) {
analysis := Analysis{ analysis := Analysis{
Results: []analyzer.Result{ Results: []common.Result{
{ {
"Deployment", "Deployment",
"test-deployment", "test-deployment",
@ -54,7 +55,7 @@ func TestAnalysis_ProblemJsonOutput(t *testing.T) {
expected := JsonOutput{ expected := JsonOutput{
Status: StateProblemDetected, Status: StateProblemDetected,
Problems: 1, Problems: 1,
Results: []analyzer.Result{ Results: []common.Result{
{"Deployment", {"Deployment",
"test-deployment", "test-deployment",
[]string{"test-problem"}, []string{"test-problem"},
@ -82,7 +83,7 @@ func TestAnalysis_ProblemJsonOutput(t *testing.T) {
func TestAnalysis_MultipleProblemJsonOutput(t *testing.T) { func TestAnalysis_MultipleProblemJsonOutput(t *testing.T) {
analysis := Analysis{ analysis := Analysis{
Results: []analyzer.Result{ Results: []common.Result{
{ {
"Deployment", "Deployment",
"test-deployment", "test-deployment",
@ -96,7 +97,7 @@ func TestAnalysis_MultipleProblemJsonOutput(t *testing.T) {
expected := JsonOutput{ expected := JsonOutput{
Status: StateProblemDetected, Status: StateProblemDetected,
Problems: 2, Problems: 2,
Results: []analyzer.Result{ Results: []common.Result{
{"Deployment", {"Deployment",
"test-deployment", "test-deployment",
[]string{"test-problem", "another-test-problem"}, []string{"test-problem", "another-test-problem"},

View File

@ -1,10 +1,15 @@
package analyzer package analyzer
type IAnalyzer interface { import (
Analyze(analysis Analyzer) ([]Result, error) "fmt"
} "os"
var coreAnalyzerMap = map[string]IAnalyzer{ "github.com/fatih/color"
"github.com/k8sgpt-ai/k8sgpt/pkg/common"
"github.com/k8sgpt-ai/k8sgpt/pkg/integration"
)
var coreAnalyzerMap = map[string]common.IAnalyzer{
"Pod": PodAnalyzer{}, "Pod": PodAnalyzer{},
"ReplicaSet": ReplicaSetAnalyzer{}, "ReplicaSet": ReplicaSetAnalyzer{},
"PersistentVolumeClaim": PvcAnalyzer{}, "PersistentVolumeClaim": PvcAnalyzer{},
@ -13,7 +18,7 @@ var coreAnalyzerMap = map[string]IAnalyzer{
"StatefulSet": StatefulSetAnalyzer{}, "StatefulSet": StatefulSetAnalyzer{},
} }
var additionalAnalyzerMap = map[string]IAnalyzer{ var additionalAnalyzerMap = map[string]common.IAnalyzer{
"HorizontalPodAutoScaler": HpaAnalyzer{}, "HorizontalPodAutoScaler": HpaAnalyzer{},
"PodDisruptionBudget": PdbAnalyzer{}, "PodDisruptionBudget": PdbAnalyzer{},
} }
@ -31,9 +36,9 @@ func ListFilters() ([]string, []string) {
return coreKeys, additionalKeys return coreKeys, additionalKeys
} }
func GetAnalyzerMap() map[string]IAnalyzer { func GetAnalyzerMap() map[string]common.IAnalyzer {
mergedMap := make(map[string]IAnalyzer) mergedMap := make(map[string]common.IAnalyzer)
// add core analyzer // add core analyzer
for key, value := range coreAnalyzerMap { for key, value := range coreAnalyzerMap {
@ -45,5 +50,23 @@ func GetAnalyzerMap() map[string]IAnalyzer {
mergedMap[key] = value mergedMap[key] = value
} }
integrationProvider := integration.NewIntegration()
for _, i := range integrationProvider.List() {
b, err := integrationProvider.IsActivate(i)
if err != nil {
fmt.Println(color.RedString(err.Error()))
os.Exit(1)
}
if b {
in, err := integrationProvider.Get(i)
if err != nil {
fmt.Println(color.RedString(err.Error()))
os.Exit(1)
}
in.AddAnalyzer(&mergedMap)
}
}
return mergedMap return mergedMap
} }

View File

@ -2,6 +2,7 @@ package analyzer
import ( import (
"context" "context"
"github.com/k8sgpt-ai/k8sgpt/pkg/kubernetes" "github.com/k8sgpt-ai/k8sgpt/pkg/kubernetes"
v1 "k8s.io/api/core/v1" v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

View File

@ -2,20 +2,22 @@ package analyzer
import ( import (
"fmt" "fmt"
"github.com/k8sgpt-ai/k8sgpt/pkg/common"
"github.com/k8sgpt-ai/k8sgpt/pkg/util" "github.com/k8sgpt-ai/k8sgpt/pkg/util"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
) )
type HpaAnalyzer struct{} type HpaAnalyzer struct{}
func (HpaAnalyzer) Analyze(a Analyzer) ([]Result, error) { func (HpaAnalyzer) Analyze(a common.Analyzer) ([]common.Result, error) {
list, err := a.Client.GetClient().AutoscalingV1().HorizontalPodAutoscalers(a.Namespace).List(a.Context, metav1.ListOptions{}) list, err := a.Client.GetClient().AutoscalingV1().HorizontalPodAutoscalers(a.Namespace).List(a.Context, metav1.ListOptions{})
if err != nil { if err != nil {
return nil, err return nil, err
} }
var preAnalysis = map[string]PreAnalysis{} var preAnalysis = map[string]common.PreAnalysis{}
for _, hpa := range list.Items { for _, hpa := range list.Items {
var failures []string var failures []string
@ -54,7 +56,7 @@ func (HpaAnalyzer) Analyze(a Analyzer) ([]Result, error) {
} }
if len(failures) > 0 { if len(failures) > 0 {
preAnalysis[fmt.Sprintf("%s/%s", hpa.Namespace, hpa.Name)] = PreAnalysis{ preAnalysis[fmt.Sprintf("%s/%s", hpa.Namespace, hpa.Name)] = common.PreAnalysis{
HorizontalPodAutoscalers: hpa, HorizontalPodAutoscalers: hpa,
FailureDetails: failures, FailureDetails: failures,
} }
@ -63,7 +65,7 @@ func (HpaAnalyzer) Analyze(a Analyzer) ([]Result, error) {
} }
for key, value := range preAnalysis { for key, value := range preAnalysis {
var currentAnalysis = Result{ var currentAnalysis = common.Result{
Kind: "HorizontalPodAutoscaler", Kind: "HorizontalPodAutoscaler",
Name: key, Name: key,
Error: value.FailureDetails, Error: value.FailureDetails,

View File

@ -2,20 +2,22 @@ package analyzer
import ( import (
"fmt" "fmt"
"github.com/k8sgpt-ai/k8sgpt/pkg/common"
"github.com/k8sgpt-ai/k8sgpt/pkg/util" "github.com/k8sgpt-ai/k8sgpt/pkg/util"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
) )
type IngressAnalyzer struct{} type IngressAnalyzer struct{}
func (IngressAnalyzer) Analyze(a Analyzer) ([]Result, error) { func (IngressAnalyzer) Analyze(a common.Analyzer) ([]common.Result, error) {
list, err := a.Client.GetClient().NetworkingV1().Ingresses(a.Namespace).List(a.Context, metav1.ListOptions{}) list, err := a.Client.GetClient().NetworkingV1().Ingresses(a.Namespace).List(a.Context, metav1.ListOptions{})
if err != nil { if err != nil {
return nil, err return nil, err
} }
var preAnalysis = map[string]PreAnalysis{} var preAnalysis = map[string]common.PreAnalysis{}
for _, ing := range list.Items { for _, ing := range list.Items {
var failures []string var failures []string
@ -57,7 +59,7 @@ func (IngressAnalyzer) Analyze(a Analyzer) ([]Result, error) {
} }
} }
if len(failures) > 0 { if len(failures) > 0 {
preAnalysis[fmt.Sprintf("%s/%s", ing.Namespace, ing.Name)] = PreAnalysis{ preAnalysis[fmt.Sprintf("%s/%s", ing.Namespace, ing.Name)] = common.PreAnalysis{
Ingress: ing, Ingress: ing,
FailureDetails: failures, FailureDetails: failures,
} }
@ -66,7 +68,7 @@ func (IngressAnalyzer) Analyze(a Analyzer) ([]Result, error) {
} }
for key, value := range preAnalysis { for key, value := range preAnalysis {
var currentAnalysis = Result{ var currentAnalysis = common.Result{
Kind: "Ingress", Kind: "Ingress",
Name: key, Name: key,
Error: value.FailureDetails, Error: value.FailureDetails,

View File

@ -2,20 +2,22 @@ package analyzer
import ( import (
"fmt" "fmt"
"github.com/k8sgpt-ai/k8sgpt/pkg/common"
"github.com/k8sgpt-ai/k8sgpt/pkg/util" "github.com/k8sgpt-ai/k8sgpt/pkg/util"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
) )
type PdbAnalyzer struct{} type PdbAnalyzer struct{}
func (PdbAnalyzer) Analyze(a Analyzer) ([]Result, error) { func (PdbAnalyzer) Analyze(a common.Analyzer) ([]common.Result, error) {
list, err := a.Client.GetClient().PolicyV1().PodDisruptionBudgets(a.Namespace).List(a.Context, metav1.ListOptions{}) list, err := a.Client.GetClient().PolicyV1().PodDisruptionBudgets(a.Namespace).List(a.Context, metav1.ListOptions{})
if err != nil { if err != nil {
return nil, err return nil, err
} }
var preAnalysis = map[string]PreAnalysis{} var preAnalysis = map[string]common.PreAnalysis{}
for _, pdb := range list.Items { for _, pdb := range list.Items {
var failures []string var failures []string
@ -39,7 +41,7 @@ func (PdbAnalyzer) Analyze(a Analyzer) ([]Result, error) {
} }
if len(failures) > 0 { if len(failures) > 0 {
preAnalysis[fmt.Sprintf("%s/%s", pdb.Namespace, pdb.Name)] = PreAnalysis{ preAnalysis[fmt.Sprintf("%s/%s", pdb.Namespace, pdb.Name)] = common.PreAnalysis{
PodDisruptionBudget: pdb, PodDisruptionBudget: pdb,
FailureDetails: failures, FailureDetails: failures,
} }
@ -47,7 +49,7 @@ func (PdbAnalyzer) Analyze(a Analyzer) ([]Result, error) {
} }
for key, value := range preAnalysis { for key, value := range preAnalysis {
var currentAnalysis = Result{ var currentAnalysis = common.Result{
Kind: "PodDisruptionBudget", Kind: "PodDisruptionBudget",
Name: key, Name: key,
Error: value.FailureDetails, Error: value.FailureDetails,

View File

@ -2,6 +2,8 @@ package analyzer
import ( import (
"fmt" "fmt"
"github.com/k8sgpt-ai/k8sgpt/pkg/common"
"github.com/k8sgpt-ai/k8sgpt/pkg/util" "github.com/k8sgpt-ai/k8sgpt/pkg/util"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
) )
@ -9,13 +11,13 @@ import (
type PodAnalyzer struct { type PodAnalyzer struct {
} }
func (PodAnalyzer) Analyze(a Analyzer) ([]Result, error) { func (PodAnalyzer) Analyze(a common.Analyzer) ([]common.Result, error) {
// search all namespaces for pods that are not running // search all namespaces for pods that are not running
list, err := a.Client.GetClient().CoreV1().Pods(a.Namespace).List(a.Context, metav1.ListOptions{}) list, err := a.Client.GetClient().CoreV1().Pods(a.Namespace).List(a.Context, metav1.ListOptions{})
if err != nil { if err != nil {
return nil, err return nil, err
} }
var preAnalysis = map[string]PreAnalysis{} var preAnalysis = map[string]common.PreAnalysis{}
for _, pod := range list.Items { for _, pod := range list.Items {
var failures []string var failures []string
@ -55,7 +57,7 @@ func (PodAnalyzer) Analyze(a Analyzer) ([]Result, error) {
} }
} }
if len(failures) > 0 { if len(failures) > 0 {
preAnalysis[fmt.Sprintf("%s/%s", pod.Namespace, pod.Name)] = PreAnalysis{ preAnalysis[fmt.Sprintf("%s/%s", pod.Namespace, pod.Name)] = common.PreAnalysis{
Pod: pod, Pod: pod,
FailureDetails: failures, FailureDetails: failures,
} }
@ -63,7 +65,7 @@ func (PodAnalyzer) Analyze(a Analyzer) ([]Result, error) {
} }
for key, value := range preAnalysis { for key, value := range preAnalysis {
var currentAnalysis = Result{ var currentAnalysis = common.Result{
Kind: "Pod", Kind: "Pod",
Name: key, Name: key,
Error: value.FailureDetails, Error: value.FailureDetails,

View File

@ -2,13 +2,15 @@ package analyzer
import ( import (
"fmt" "fmt"
"github.com/k8sgpt-ai/k8sgpt/pkg/common"
"github.com/k8sgpt-ai/k8sgpt/pkg/util" "github.com/k8sgpt-ai/k8sgpt/pkg/util"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
) )
type PvcAnalyzer struct{} type PvcAnalyzer struct{}
func (PvcAnalyzer) Analyze(a Analyzer) ([]Result, error) { func (PvcAnalyzer) Analyze(a common.Analyzer) ([]common.Result, error) {
// search all namespaces for pods that are not running // search all namespaces for pods that are not running
list, err := a.Client.GetClient().CoreV1().PersistentVolumeClaims(a.Namespace).List(a.Context, metav1.ListOptions{}) list, err := a.Client.GetClient().CoreV1().PersistentVolumeClaims(a.Namespace).List(a.Context, metav1.ListOptions{})
@ -16,7 +18,7 @@ func (PvcAnalyzer) Analyze(a Analyzer) ([]Result, error) {
return nil, err return nil, err
} }
var preAnalysis = map[string]PreAnalysis{} var preAnalysis = map[string]common.PreAnalysis{}
for _, pvc := range list.Items { for _, pvc := range list.Items {
var failures []string var failures []string
@ -34,7 +36,7 @@ func (PvcAnalyzer) Analyze(a Analyzer) ([]Result, error) {
} }
} }
if len(failures) > 0 { if len(failures) > 0 {
preAnalysis[fmt.Sprintf("%s/%s", pvc.Namespace, pvc.Name)] = PreAnalysis{ preAnalysis[fmt.Sprintf("%s/%s", pvc.Namespace, pvc.Name)] = common.PreAnalysis{
PersistentVolumeClaim: pvc, PersistentVolumeClaim: pvc,
FailureDetails: failures, FailureDetails: failures,
} }
@ -42,7 +44,7 @@ func (PvcAnalyzer) Analyze(a Analyzer) ([]Result, error) {
} }
for key, value := range preAnalysis { for key, value := range preAnalysis {
var currentAnalysis = Result{ var currentAnalysis = common.Result{
Kind: "PersistentVolumeClaim", Kind: "PersistentVolumeClaim",
Name: key, Name: key,
Error: value.FailureDetails, Error: value.FailureDetails,

View File

@ -2,13 +2,15 @@ package analyzer
import ( import (
"fmt" "fmt"
"github.com/k8sgpt-ai/k8sgpt/pkg/common"
"github.com/k8sgpt-ai/k8sgpt/pkg/util" "github.com/k8sgpt-ai/k8sgpt/pkg/util"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
) )
type ReplicaSetAnalyzer struct{} type ReplicaSetAnalyzer struct{}
func (ReplicaSetAnalyzer) Analyze(a Analyzer) ([]Result, error) { func (ReplicaSetAnalyzer) Analyze(a common.Analyzer) ([]common.Result, error) {
// search all namespaces for pods that are not running // search all namespaces for pods that are not running
list, err := a.Client.GetClient().AppsV1().ReplicaSets(a.Namespace).List(a.Context, metav1.ListOptions{}) list, err := a.Client.GetClient().AppsV1().ReplicaSets(a.Namespace).List(a.Context, metav1.ListOptions{})
@ -16,7 +18,7 @@ func (ReplicaSetAnalyzer) Analyze(a Analyzer) ([]Result, error) {
return nil, err return nil, err
} }
var preAnalysis = map[string]PreAnalysis{} var preAnalysis = map[string]common.PreAnalysis{}
for _, rs := range list.Items { for _, rs := range list.Items {
var failures []string var failures []string
@ -32,7 +34,7 @@ func (ReplicaSetAnalyzer) Analyze(a Analyzer) ([]Result, error) {
} }
} }
if len(failures) > 0 { if len(failures) > 0 {
preAnalysis[fmt.Sprintf("%s/%s", rs.Namespace, rs.Name)] = PreAnalysis{ preAnalysis[fmt.Sprintf("%s/%s", rs.Namespace, rs.Name)] = common.PreAnalysis{
ReplicaSet: rs, ReplicaSet: rs,
FailureDetails: failures, FailureDetails: failures,
} }
@ -40,7 +42,7 @@ func (ReplicaSetAnalyzer) Analyze(a Analyzer) ([]Result, error) {
} }
for key, value := range preAnalysis { for key, value := range preAnalysis {
var currentAnalysis = Result{ var currentAnalysis = common.Result{
Kind: "ReplicaSet", Kind: "ReplicaSet",
Name: key, Name: key,
Error: value.FailureDetails, Error: value.FailureDetails,

View File

@ -2,14 +2,16 @@ package analyzer
import ( import (
"fmt" "fmt"
"github.com/fatih/color" "github.com/fatih/color"
"github.com/k8sgpt-ai/k8sgpt/pkg/common"
"github.com/k8sgpt-ai/k8sgpt/pkg/util" "github.com/k8sgpt-ai/k8sgpt/pkg/util"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
) )
type ServiceAnalyzer struct{} type ServiceAnalyzer struct{}
func (ServiceAnalyzer) Analyze(a Analyzer) ([]Result, error) { func (ServiceAnalyzer) Analyze(a common.Analyzer) ([]common.Result, error) {
// search all namespaces for pods that are not running // search all namespaces for pods that are not running
list, err := a.Client.GetClient().CoreV1().Endpoints(a.Namespace).List(a.Context, metav1.ListOptions{}) list, err := a.Client.GetClient().CoreV1().Endpoints(a.Namespace).List(a.Context, metav1.ListOptions{})
@ -17,7 +19,7 @@ func (ServiceAnalyzer) Analyze(a Analyzer) ([]Result, error) {
return nil, err return nil, err
} }
var preAnalysis = map[string]PreAnalysis{} var preAnalysis = map[string]common.PreAnalysis{}
for _, ep := range list.Items { for _, ep := range list.Items {
var failures []string var failures []string
@ -50,7 +52,7 @@ func (ServiceAnalyzer) Analyze(a Analyzer) ([]Result, error) {
} }
if len(failures) > 0 { if len(failures) > 0 {
preAnalysis[fmt.Sprintf("%s/%s", ep.Namespace, ep.Name)] = PreAnalysis{ preAnalysis[fmt.Sprintf("%s/%s", ep.Namespace, ep.Name)] = common.PreAnalysis{
Endpoint: ep, Endpoint: ep,
FailureDetails: failures, FailureDetails: failures,
} }
@ -58,7 +60,7 @@ func (ServiceAnalyzer) Analyze(a Analyzer) ([]Result, error) {
} }
for key, value := range preAnalysis { for key, value := range preAnalysis {
var currentAnalysis = Result{ var currentAnalysis = common.Result{
Kind: "Service", Kind: "Service",
Name: key, Name: key,
Error: value.FailureDetails, Error: value.FailureDetails,

View File

@ -3,18 +3,19 @@ package analyzer
import ( import (
"fmt" "fmt"
"github.com/k8sgpt-ai/k8sgpt/pkg/common"
"github.com/k8sgpt-ai/k8sgpt/pkg/util" "github.com/k8sgpt-ai/k8sgpt/pkg/util"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
) )
type StatefulSetAnalyzer struct{} type StatefulSetAnalyzer struct{}
func (StatefulSetAnalyzer) Analyze(a Analyzer) ([]Result, error) { func (StatefulSetAnalyzer) Analyze(a common.Analyzer) ([]common.Result, error) {
list, err := a.Client.GetClient().AppsV1().StatefulSets(a.Namespace).List(a.Context, metav1.ListOptions{}) list, err := a.Client.GetClient().AppsV1().StatefulSets(a.Namespace).List(a.Context, metav1.ListOptions{})
if err != nil { if err != nil {
return nil, err return nil, err
} }
var preAnalysis = map[string]PreAnalysis{} var preAnalysis = map[string]common.PreAnalysis{}
for _, sts := range list.Items { for _, sts := range list.Items {
var failures []string var failures []string
@ -36,7 +37,7 @@ func (StatefulSetAnalyzer) Analyze(a Analyzer) ([]Result, error) {
} }
} }
if len(failures) > 0 { if len(failures) > 0 {
preAnalysis[fmt.Sprintf("%s/%s", sts.Namespace, sts.Name)] = PreAnalysis{ preAnalysis[fmt.Sprintf("%s/%s", sts.Namespace, sts.Name)] = common.PreAnalysis{
StatefulSet: sts, StatefulSet: sts,
FailureDetails: failures, FailureDetails: failures,
} }
@ -44,7 +45,7 @@ func (StatefulSetAnalyzer) Analyze(a Analyzer) ([]Result, error) {
} }
for key, value := range preAnalysis { for key, value := range preAnalysis {
var currentAnalysis = Result{ var currentAnalysis = common.Result{
Kind: "StatefulSet", Kind: "StatefulSet",
Name: key, Name: key,
Error: value.FailureDetails, Error: value.FailureDetails,

View File

@ -1,4 +1,4 @@
package analyzer package common
import ( import (
"context" "context"
@ -13,6 +13,10 @@ import (
policyv1 "k8s.io/api/policy/v1" policyv1 "k8s.io/api/policy/v1"
) )
type IAnalyzer interface {
Analyze(analysis Analyzer) ([]Result, error)
}
type Analyzer struct { type Analyzer struct {
Client *kubernetes.Client Client *kubernetes.Client
Context context.Context Context context.Context

View File

@ -3,7 +3,7 @@ package integration
import ( import (
"errors" "errors"
"github.com/k8sgpt-ai/k8sgpt/pkg/analyzer" "github.com/k8sgpt-ai/k8sgpt/pkg/common"
"github.com/k8sgpt-ai/k8sgpt/pkg/integration/trivy" "github.com/k8sgpt-ai/k8sgpt/pkg/integration/trivy"
) )
@ -13,7 +13,7 @@ type IIntegration interface {
// Remove removes an integration from the cluster // Remove removes an integration from the cluster
UnDeploy(namespace string) error UnDeploy(namespace string) error
// //
AddAnalyzer() (string, analyzer.IAnalyzer, error) AddAnalyzer(*map[string]common.IAnalyzer)
// RemoveAnalyzer removes an analyzer from the cluster // RemoveAnalyzer removes an analyzer from the cluster
RemoveAnalyzer() error RemoveAnalyzer() error
@ -23,6 +23,10 @@ type IIntegration interface {
type Integration struct { type Integration struct {
} }
type IntegrationProvider struct {
Active []string `mapstructure:"active"`
}
var integrations = map[string]IIntegration{ var integrations = map[string]IIntegration{
"trivy": trivy.NewTrivy(), "trivy": trivy.NewTrivy(),
} }
@ -39,16 +43,40 @@ func (*Integration) List() []string {
return keys return keys
} }
func (*Integration) Get(name string) (IIntegration, error) {
if _, ok := integrations[name]; !ok {
return nil, errors.New("integration not found")
}
return integrations[name], nil
}
func (*Integration) Activate(name string, namespace string) error { func (*Integration) Activate(name string, namespace string) error {
if _, ok := integrations[name]; !ok { if _, ok := integrations[name]; !ok {
return errors.New("integration not found") return errors.New("integration not found")
} }
return integrations[name].Deploy(namespace)
if err := integrations[name].Deploy(namespace); err != nil {
return err
}
return nil
} }
func (*Integration) Deactivate(name string, namespace string) error { func (*Integration) Deactivate(name string, namespace string) error {
if _, ok := integrations[name]; !ok { if _, ok := integrations[name]; !ok {
return errors.New("integration not found") return errors.New("integration not found")
} }
return integrations[name].UnDeploy(namespace)
if err := integrations[name].UnDeploy(namespace); err != nil {
return err
}
return nil
}
func (*Integration) IsActivate(name string) (bool, error) {
if _, ok := integrations[name]; !ok {
return false, errors.New("integration not found")
}
return integrations[name].IsActivate(), nil
} }

View File

@ -4,14 +4,14 @@ import (
"fmt" "fmt"
"github.com/aquasecurity/trivy-operator/pkg/apis/aquasecurity/v1alpha1" "github.com/aquasecurity/trivy-operator/pkg/apis/aquasecurity/v1alpha1"
"github.com/k8sgpt-ai/k8sgpt/pkg/analyzer" "github.com/k8sgpt-ai/k8sgpt/pkg/common"
"github.com/k8sgpt-ai/k8sgpt/pkg/util" "github.com/k8sgpt-ai/k8sgpt/pkg/util"
) )
type TrivyAnalyzer struct { type TrivyAnalyzer struct {
} }
func (TrivyAnalyzer) Analyze(a analyzer.Analyzer) ([]analyzer.Result, error) { func (TrivyAnalyzer) Analyze(a common.Analyzer) ([]common.Result, error) {
// Get all trivy VulnerabilityReports // Get all trivy VulnerabilityReports
result := &v1alpha1.VulnerabilityReportList{} result := &v1alpha1.VulnerabilityReportList{}
@ -22,7 +22,7 @@ func (TrivyAnalyzer) Analyze(a analyzer.Analyzer) ([]analyzer.Result, error) {
} }
// Find criticals and get CVE // Find criticals and get CVE
var preAnalysis = map[string]analyzer.PreAnalysis{} var preAnalysis = map[string]common.PreAnalysis{}
for _, report := range result.Items { for _, report := range result.Items {
@ -37,7 +37,7 @@ func (TrivyAnalyzer) Analyze(a analyzer.Analyzer) ([]analyzer.Result, error) {
} }
if len(failures) > 0 { if len(failures) > 0 {
preAnalysis[fmt.Sprintf("%s/%s", report.Labels["trivy-operator.resource.namespace"], preAnalysis[fmt.Sprintf("%s/%s", report.Labels["trivy-operator.resource.namespace"],
report.Labels["trivy-operator.resource.name"])] = analyzer.PreAnalysis{ report.Labels["trivy-operator.resource.name"])] = common.PreAnalysis{
TrivyVulnerabilityReport: report, TrivyVulnerabilityReport: report,
FailureDetails: failures, FailureDetails: failures,
} }
@ -45,7 +45,7 @@ func (TrivyAnalyzer) Analyze(a analyzer.Analyzer) ([]analyzer.Result, error) {
} }
for key, value := range preAnalysis { for key, value := range preAnalysis {
var currentAnalysis = analyzer.Result{ var currentAnalysis = common.Result{
Kind: "VulnerabilityReport", Kind: "VulnerabilityReport",
Name: key, Name: key,
Error: value.FailureDetails, Error: value.FailureDetails,

View File

@ -4,7 +4,7 @@ import (
"context" "context"
"fmt" "fmt"
"github.com/k8sgpt-ai/k8sgpt/pkg/analyzer" "github.com/k8sgpt-ai/k8sgpt/pkg/common"
helmclient "github.com/mittwald/go-helm-client" helmclient "github.com/mittwald/go-helm-client"
"helm.sh/helm/v3/pkg/repo" "helm.sh/helm/v3/pkg/repo"
) )
@ -88,8 +88,10 @@ func (t *Trivy) IsActivate() bool {
return true return true
} }
func (t *Trivy) AddAnalyzer() (string, analyzer.IAnalyzer, error) { func (t *Trivy) AddAnalyzer(mergedMap *map[string]common.IAnalyzer) {
return "trivy", TrivyAnalyzer{}, nil
(*mergedMap)["trivy"] = &TrivyAnalyzer{}
} }
func (t *Trivy) RemoveAnalyzer() error { func (t *Trivy) RemoveAnalyzer() error {