Skip to content

Commit

Permalink
feat: serve/integration capability (#645)
Browse files Browse the repository at this point in the history
* chore: updated schema for integrations support (#616)

Signed-off-by: Alex Jones <alexsimonjones@gmail.com>

wip: enabling integration activation

Signed-off-by: Alex Jones <alexsimonjones@gmail.com>

wip: enabling integration activation

Signed-off-by: Alex Jones <alexsimonjones@gmail.com>

* wip

Signed-off-by: Alex Jones <alexsimonjones@gmail.com>

* feat: skipinstall fixed

Signed-off-by: Alex Jones <alexsimonjones@gmail.com>

* feat: fixed filters for integrations but its ugly

Signed-off-by: Alex Jones <alexsimonjones@gmail.com>

* chore: updated library

Signed-off-by: Alex Jones <alexsimonjones@gmail.com>

* chore: updated go mod

Signed-off-by: Alex Jones <alexsimonjones@gmail.com>

* chore: updated go mod

Signed-off-by: Alex Jones <alexsimonjones@gmail.com>

---------

Signed-off-by: Alex Jones <alexsimonjones@gmail.com>
  • Loading branch information
AlexsJones committed Sep 16, 2023
1 parent 6481590 commit ab064b9
Show file tree
Hide file tree
Showing 8 changed files with 100 additions and 31 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
__debug*
.DS_Store
k8sgpt*
!charts/k8sgpt
Expand Down
11 changes: 9 additions & 2 deletions cmd/filters/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (

"github.com/fatih/color"
"github.com/k8sgpt-ai/k8sgpt/pkg/analyzer"
"github.com/k8sgpt-ai/k8sgpt/pkg/integration"
"github.com/k8sgpt-ai/k8sgpt/pkg/util"
"github.com/spf13/cobra"
"github.com/spf13/viper"
Expand All @@ -30,7 +31,7 @@ var listCmd = &cobra.Command{
Run: func(cmd *cobra.Command, args []string) {
activeFilters := viper.GetStringSlice("active_filters")
coreFilters, additionalFilters, integrationFilters := analyzer.ListFilters()

integration := integration.NewIntegration()
availableFilters := append(append(coreFilters, additionalFilters...), integrationFilters...)

if len(activeFilters) == 0 {
Expand All @@ -41,10 +42,16 @@ var listCmd = &cobra.Command{
for _, filter := range activeFilters {

// if the filter is an integration, mark this differently
// but if the integration is inactive, remove
if util.SliceContainsString(integrationFilters, filter) {
fmt.Printf("> %s\n", color.BlueString("%s (integration)", filter))
} else {
fmt.Printf("> %s\n", color.GreenString(filter))
// This strange bit of logic will loop through every integration via
// OwnsAnalyzer subcommand to check the filter and as the integrationFilters...
// was no match, we know this isn't part of an active integration
if _, err := integration.AnalyzerByIntegration(filter); err != nil {
fmt.Printf("> %s\n", color.GreenString(filter))
}
}
}

Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ buf.build/gen/go/k8sgpt-ai/k8sgpt/grpc/go v1.3.0-20230620082254-6f80f9533908.1/g
buf.build/gen/go/k8sgpt-ai/k8sgpt/protocolbuffers/go v1.28.1-20230620082254-6f80f9533908.4/go.mod h1:i/s4ALHwKvjA1oGNKpoHg0FpEOTbufoOm/NdTE6YQAE=
buf.build/gen/go/k8sgpt-ai/k8sgpt/protocolbuffers/go v1.31.0-20230828112343-a9fd9ad20848.1 h1:fScSW5Gzu1OzUYylwpvQwgXX5J9YPKkOQpbkc5c8Q+8=
buf.build/gen/go/k8sgpt-ai/k8sgpt/protocolbuffers/go v1.31.0-20230828112343-a9fd9ad20848.1/go.mod h1:gtnk2yAUexdY5nTuUg0SH5WCCGvpKzr7pd3Xbi7MWjE=
buf.build/gen/go/k8sgpt-ai/k8sgpt/protocolbuffers/go v1.31.0-20230830164712-dc062a152c20.1 h1:oD5YCdsVnQgVLSHxium66FFfuxjjvn5u65mnQo6vAyc=
buf.build/gen/go/k8sgpt-ai/k8sgpt/protocolbuffers/go v1.31.0-20230830164712-dc062a152c20.1/go.mod h1:gtnk2yAUexdY5nTuUg0SH5WCCGvpKzr7pd3Xbi7MWjE=
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
Expand Down
47 changes: 26 additions & 21 deletions pkg/integration/integration.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,8 @@ package integration

import (
"errors"
"os"
"strings"
"fmt"

"github.com/fatih/color"
"github.com/k8sgpt-ai/k8sgpt/pkg/common"
"github.com/k8sgpt-ai/k8sgpt/pkg/integration/trivy"
"github.com/k8sgpt-ai/k8sgpt/pkg/util"
Expand All @@ -35,6 +33,8 @@ type IIntegration interface {

GetAnalyzerName() []string

OwnsAnalyzer(string) bool

IsActivate() bool
}

Expand Down Expand Up @@ -64,34 +64,38 @@ func (*Integration) Get(name string) (IIntegration, error) {
return integrations[name], nil
}

func (i *Integration) AnalyzerByIntegration(input string) (string, error) {

for _, name := range i.List() {
if integ, err := i.Get(name); err == nil {
if integ.OwnsAnalyzer(input) {
return name, nil
}
}
}
return "", errors.New("analyzerbyintegration: no matches found")
}

func (*Integration) Activate(name string, namespace string, activeFilters []string, skipInstall bool) error {
if _, ok := integrations[name]; !ok {
return errors.New("integration not found")
}

mergedFilters := activeFilters

mergedFilters = append(mergedFilters, integrations[name].GetAnalyzerName()...)

uniqueFilters, dupplicatedFilters := util.RemoveDuplicates(mergedFilters)

// Verify dupplicate
if len(dupplicatedFilters) != 0 {
color.Red("Integration already activated : %s", strings.Join(dupplicatedFilters, ", "))
os.Exit(1)
}

viper.Set("active_filters", uniqueFilters)

if !skipInstall {
if err := integrations[name].Deploy(namespace); err != nil {
return err
}
}

mergedFilters := activeFilters
mergedFilters = append(mergedFilters, integrations[name].GetAnalyzerName()...)
uniqueFilters, _ := util.RemoveDuplicates(mergedFilters)

viper.Set("active_filters", uniqueFilters)

if err := viper.WriteConfig(); err != nil {
color.Red("Error writing config file: %s", err.Error())
os.Exit(1)
return fmt.Errorf("error writing config file: %s", err.Error())

}

return nil
Expand All @@ -111,6 +115,7 @@ func (*Integration) Deactivate(name string, namespace string) error {
activeFilters = append(activeFilters[:x], activeFilters[x+1:]...)
}
}

}

if err := integrations[name].UnDeploy(namespace); err != nil {
Expand All @@ -120,8 +125,8 @@ func (*Integration) Deactivate(name string, namespace string) error {
viper.Set("active_filters", activeFilters)

if err := viper.WriteConfig(); err != nil {
color.Red("Error writing config file: %s", err.Error())
os.Exit(1)
return fmt.Errorf("error writing config file: %s", err.Error())

}

return nil
Expand Down
9 changes: 9 additions & 0 deletions pkg/integration/trivy/trivy.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,15 @@ func (t *Trivy) GetAnalyzerName() []string {
}
}

func (t *Trivy) OwnsAnalyzer(analyzer string) bool {

for _, a := range t.GetAnalyzerName() {
if analyzer == a {
return true
}
}
return false
}
func (t *Trivy) Deploy(namespace string) error {

// Add the repository
Expand Down
17 changes: 17 additions & 0 deletions pkg/server/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# serve

The serve commands allow you to run k8sgpt in a grpc server mode.
This would be enabled typically through `k8sgpt serve` and is how the in-cluster k8sgpt deployment functions when managed by the [k8sgpt-operator](https://github.com/k8sgpt-ai/k8sgpt-operator)

The grpc interface that is served is hosted on [buf](https://buf.build/k8sgpt-ai/schemas) and the repository for this is [here](https://github.com/k8sgpt-ai/schemas)

## grpcurl

A fantastic tool for local debugging and development is `grpcurl`
It allows you to form curl like requests that are http2
e.g.

```
grpcurl -plaintext -d '{"namespace": "k8sgpt", "explain" : "true"}' localhost:8080 schema.v1.ServerService/Analyze
```

42 changes: 35 additions & 7 deletions pkg/server/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,46 @@ import (
"errors"

schemav1 "buf.build/gen/go/k8sgpt-ai/k8sgpt/protocolbuffers/go/schema/v1"
"github.com/k8sgpt-ai/k8sgpt/pkg/analyzer"
"github.com/k8sgpt-ai/k8sgpt/pkg/cache"
"github.com/k8sgpt-ai/k8sgpt/pkg/integration"
"github.com/spf13/viper"
)

func (h *handler) AddConfig(ctx context.Context, i *schemav1.AddConfigRequest) (*schemav1.AddConfigResponse, error,
) {
if i.Cache.BucketName == "" || i.Cache.Region == "" {
return nil, errors.New("BucketName & Region are required")
}

err := cache.AddRemoteCache(i.Cache.BucketName, i.Cache.Region)
if err != nil {
return &schemav1.AddConfigResponse{}, err
if i.Integrations != nil {
coreFilters, _, _ := analyzer.ListFilters()
// Update filters
activeFilters := viper.GetStringSlice("active_filters")
if len(activeFilters) == 0 {
activeFilters = coreFilters
}
integration := integration.NewIntegration()

if i.Integrations.Trivy != nil {
// Enable/Disable Trivy
var err = integration.Activate("trivy", i.Integrations.Trivy.Namespace,

Check failure on line 28 in pkg/server/config.go

View workflow job for this annotation

GitHub Actions / build

i.Integrations.Trivy.Namespace undefined (type *schemav1.Trivy has no field or method Namespace)
activeFilters, i.Integrations.Trivy.SkipInstall)

Check failure on line 29 in pkg/server/config.go

View workflow job for this annotation

GitHub Actions / build

i.Integrations.Trivy.SkipInstall undefined (type *schemav1.Trivy has no field or method SkipInstall)
return &schemav1.AddConfigResponse{
Status: "",
}, err
}
}
if i.Cache != nil {
// Remote cache
if i.Cache.BucketName == "" || i.Cache.Region == "" {
return &schemav1.AddConfigResponse{}, errors.New("BucketName & Region are required")
}

err := cache.AddRemoteCache(i.Cache.BucketName, i.Cache.Region)
if err != nil {
return &schemav1.AddConfigResponse{
Status: err.Error(),
}, err
}
}
return &schemav1.AddConfigResponse{
Status: "Configuration updated.",
}, nil
Expand All @@ -28,7 +54,9 @@ func (h *handler) RemoveConfig(ctx context.Context, i *schemav1.RemoveConfigRequ
) {
err := cache.RemoveRemoteCache(i.Cache.BucketName)
if err != nil {
return &schemav1.RemoveConfigResponse{}, err
return &schemav1.RemoveConfigResponse{
Status: err.Error(),
}, err
}

return &schemav1.RemoveConfigResponse{
Expand Down
2 changes: 1 addition & 1 deletion pkg/util/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@ package util

import (
"context"
"crypto/rand"
"crypto/sha256"
"encoding/base64"
"encoding/hex"
"errors"
"fmt"
"math/rand"
"os"
"regexp"

Expand Down

0 comments on commit ab064b9

Please sign in to comment.