Skip to content

Commit

Permalink
Merge branch 'main' into feature/235/use-xdg-config-home
Browse files Browse the repository at this point in the history
Signed-off-by: Alex Jones <alexsimonjones@gmail.com>
  • Loading branch information
AlexsJones authored Apr 16, 2023
2 parents dee4355 + 6e7c583 commit a7cff48
Show file tree
Hide file tree
Showing 33 changed files with 403 additions and 111 deletions.
16 changes: 16 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
.PHONY: docker-build
IMG ?= ghcr.io/k8sgpt-ai/k8sgpt:latest

deploy:
ifndef SECRET
$(error SECRET environment variable is not set)
endif
kubectl create ns k8sgpt || true
kubectl create secret generic ai-backend-secret --from-literal=secret-key=$(SECRET) --namespace=k8sgpt || true
kubectl apply -f container/manifests
undeploy:
kubectl delete secret ai-backend-secret --namespace=k8sgpt
kubectl delete -f container/manifests
kubectl delete ns k8sgpt
docker-build:
docker buildx build --build-arg=VERSION="$$(git describe --tags --abbrev=0)" --build-arg=COMMIT="$$(git rev-parse --short HEAD)" --build-arg DATE="$$(date +%FT%TZ)" --platform="linux/amd64,linux/arm64" -t ${IMG} -f container/Dockerfile . --push
15 changes: 5 additions & 10 deletions cmd/analyze/analyze.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,17 +51,12 @@ var AnalyzeCmd = &cobra.Command{
}

// print results
switch output {
case "json":
output, err := config.JsonOutput()
if err != nil {
color.Red("Error: %v", err)
os.Exit(1)
}
fmt.Println(string(output))
default:
config.PrintOutput()
output, err := config.PrintOutput(output)
if err != nil {
color.Red("Error: %v", err)
os.Exit(1)
}
fmt.Println(string(output))
},
}

Expand Down
3 changes: 1 addition & 2 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,10 @@ import (
"fmt"
"os"
"path/filepath"

"github.com/adrg/xdg"
"github.com/fatih/color"
"github.com/k8sgpt-ai/k8sgpt/cmd/serve"
"github.com/k8sgpt-ai/k8sgpt/pkg/util"

"github.com/k8sgpt-ai/k8sgpt/cmd/analyze"
"github.com/k8sgpt-ai/k8sgpt/cmd/auth"
"github.com/k8sgpt-ai/k8sgpt/cmd/filters"
Expand Down Expand Up @@ -86,6 +84,7 @@ func initConfig() {
viper.Set("kubecontext", kubecontext)
viper.Set("kubeconfig", kubeconfig)

viper.SetEnvPrefix("K8SGPT")
viper.AutomaticEnv() // read in environment variables that match

// If a config file is found, read it in.
Expand Down
40 changes: 31 additions & 9 deletions cmd/serve/serve.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,17 +28,39 @@ var ServeCmd = &cobra.Command{
color.Red("Error: %v", err)
os.Exit(1)
}

var aiProvider *ai.AIProvider
if len(configAI.Providers) == 0 {
color.Red("Error: AI provider not specified in configuration. Please run k8sgpt auth")
os.Exit(1)
}
// Check for env injection
backend = os.Getenv("K8SGPT_BACKEND")
password := os.Getenv("K8SGPT_PASSWORD")
model := os.Getenv("K8SGPT_MODEL")
// If the envs are set, alocate in place to the aiProvider
// else exit with error
if backend != "" || password != "" || model != "" {
aiProvider = &ai.AIProvider{
Name: backend,
Password: password,
Model: model,
}

var aiProvider ai.AIProvider
for _, provider := range configAI.Providers {
if backend == provider.Name {
aiProvider = provider
break
configAI.Providers = append(configAI.Providers, *aiProvider)

viper.Set("ai", configAI)
if err := viper.WriteConfig(); err != nil {
color.Red("Error writing config file: %s", err.Error())
os.Exit(1)
}
} else {
color.Red("Error: AI provider not specified in configuration. Please run k8sgpt auth")
os.Exit(1)
}
}
if aiProvider == nil {
for _, provider := range configAI.Providers {
if backend == provider.Name {
aiProvider = &provider
break
}
}
}

Expand Down
42 changes: 42 additions & 0 deletions container/manifests/deployment.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: k8sgpt-deployment
namespace: k8sgpt
labels:
app: k8sgpt
spec:
replicas: 1
selector:
matchLabels:
app: k8sgpt
template:
metadata:
labels:
app: k8sgpt
spec:
serviceAccountName: k8sgpt
containers:
- name: k8sgpt-container
imagePullPolicy: Always
image: ghcr.io/k8sgpt-ai/k8sgpt:v0.2.2 #x-release-please-version
ports:
- containerPort: 8080
args: ["serve"]
resources:
limits:
cpu: "1"
memory: "512Mi"
requests:
cpu: "0.5"
memory: "256Mi"
env:
- name: K8SGPT_MODEL
value: "gpt-3.5-turbo"
- name: K8SGPT_BACKEND
value: "openai"
- name: K8SGPT_PASSWORD
valueFrom:
secretKeyRef:
name: ai-backend-secret
key: secret-key
13 changes: 13 additions & 0 deletions container/manifests/role.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: k8sgpt-cluster-role-all
rules:
- apiGroups:
- '*'
resources:
- '*'
verbs:
- get
- list
- watch
13 changes: 13 additions & 0 deletions container/manifests/rolebinding.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: k8sgpt-rolebinding
namespace: k8sgpt
subjects:
- kind: ServiceAccount
name: k8sgpt
namespace: k8sgpt
roleRef:
kind: ClusterRole
name: k8sgpt-cluster-role-all
apiGroup: rbac.authorization.k8s.io
5 changes: 5 additions & 0 deletions container/manifests/sa.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
apiVersion: v1
kind: ServiceAccount
metadata:
name: k8sgpt
namespace: k8sgpt
13 changes: 13 additions & 0 deletions container/manifests/service.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
apiVersion: v1
kind: Service
metadata:
name: k8sgpt-service
namespace: k8sgpt
spec:
selector:
app: k8sgpt
ports:
- name: http
port: 8080
targetPort: 8080
type: ClusterIP
11 changes: 11 additions & 0 deletions demo
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
. demo-magic.sh
clear

pe "k8sgpt filter list"
pe "k8sgpt analyze --filter=Pod --explain -o json | jq ."
pe "k8sgpt integration list"
pe "k8sgpt integration activate trivy"
pe "k8sgpt filter list"
pe "k8sgpt analyze --filter=VulnerabilityReport"
pe "./k8sgpt analyze --filter=Node --explain"

Binary file added images/demo5.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/nodes.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
40 changes: 0 additions & 40 deletions pkg/analysis/analysis.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package analysis

import (
"context"
"encoding/json"
"errors"
"fmt"
"os"
Expand Down Expand Up @@ -149,45 +148,6 @@ func (a *Analysis) RunAnalysis() error {
return nil
}

func (a *Analysis) JsonOutput() ([]byte, error) {
var problems int
var status AnalysisStatus
for _, result := range a.Results {
problems += len(result.Error)
}
if problems > 0 {
status = StateProblemDetected
} else {
status = StateOK
}

result := JsonOutput{
Problems: problems,
Results: a.Results,
Status: status,
}
output, err := json.MarshalIndent(result, "", " ")
if err != nil {
return nil, fmt.Errorf("error marshalling json: %v", err)
}
return output, nil
}

func (a *Analysis) PrintOutput() {
fmt.Println("")
if len(a.Results) == 0 {
fmt.Println(color.GreenString("No problems detected"))
}
for n, result := range a.Results {
fmt.Printf("%s %s(%s)\n", color.CyanString("%d", n),
color.YellowString(result.Name), color.CyanString(result.ParentObject))
for _, err := range result.Error {
fmt.Printf("- %s %s\n", color.RedString("Error:"), color.RedString(err.Text))
}
fmt.Println(color.GreenString(result.Details + "\n"))
}
}

func (a *Analysis) GetAIResults(output string, anonymize bool) error {
if len(a.Results) == 0 {
return nil
Expand Down
6 changes: 3 additions & 3 deletions pkg/analysis/analysis_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ func TestAnalysis_NoProblemJsonOutput(t *testing.T) {
Results: []common.Result{},
}

gotJson, err := analysis.JsonOutput()
gotJson, err := analysis.PrintOutput("json")
if err != nil {
t.Error(err)
}
Expand Down Expand Up @@ -75,7 +75,7 @@ func TestAnalysis_ProblemJsonOutput(t *testing.T) {
},
}

gotJson, err := analysis.JsonOutput()
gotJson, err := analysis.PrintOutput("json")
if err != nil {
t.Error(err)
}
Expand Down Expand Up @@ -136,7 +136,7 @@ func TestAnalysis_MultipleProblemJsonOutput(t *testing.T) {
},
}

gotJson, err := analysis.JsonOutput()
gotJson, err := analysis.PrintOutput("json")
if err != nil {
t.Error(err)
}
Expand Down
72 changes: 72 additions & 0 deletions pkg/analysis/output.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package analysis

import (
"encoding/json"
"fmt"
"strings"

"github.com/fatih/color"
)

var outputFormats = map[string]func(*Analysis) ([]byte, error){
"json": (*Analysis).jsonOutput,
"text": (*Analysis).textOutput,
}

func getOutputFormats() []string {
formats := make([]string, 0, len(outputFormats))
for format := range outputFormats {
formats = append(formats, format)
}
return formats
}

func (a *Analysis) PrintOutput(format string) ([]byte, error) {
outputFunc, ok := outputFormats[format]
if !ok {
return nil, fmt.Errorf("unsupported output format: %s. Available format %s", format, strings.Join(getOutputFormats(), ","))
}
return outputFunc(a)
}

func (a *Analysis) jsonOutput() ([]byte, error) {
var problems int
var status AnalysisStatus
for _, result := range a.Results {
problems += len(result.Error)
}
if problems > 0 {
status = StateProblemDetected
} else {
status = StateOK
}

result := JsonOutput{
Problems: problems,
Results: a.Results,
Status: status,
}
output, err := json.MarshalIndent(result, "", " ")
if err != nil {
return nil, fmt.Errorf("error marshalling json: %v", err)
}
return output, nil
}

func (a *Analysis) textOutput() ([]byte, error) {
var output strings.Builder
output.WriteString("\n")
if len(a.Results) == 0 {
output.WriteString(color.GreenString("No problems detected\n"))
return []byte(output.String()), nil
}
for n, result := range a.Results {
output.WriteString(fmt.Sprintf("%s %s(%s)\n", color.CyanString("%d", n),
color.YellowString(result.Name), color.CyanString(result.ParentObject)))
for _, err := range result.Error {
output.WriteString(fmt.Sprintf("- %s %s\n", color.RedString("Error:"), color.RedString(err.Text)))
}
output.WriteString(color.GreenString(result.Details + "\n"))
}
return []byte(output.String()), nil
}
9 changes: 9 additions & 0 deletions pkg/analyzer/analyzer.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,15 @@ import (
"github.com/fatih/color"
"github.com/k8sgpt-ai/k8sgpt/pkg/common"
"github.com/k8sgpt-ai/k8sgpt/pkg/integration"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
)

var (
AnalyzerErrorsMetric = promauto.NewGaugeVec(prometheus.GaugeOpts{
Name: "analyzer_errors",
Help: "Number of errors detected by analyzer",
}, []string{"analyzer_name", "object_name", "namespace"})
)

var coreAnalyzerMap = map[string]common.IAnalyzer{
Expand Down
Loading

0 comments on commit a7cff48

Please sign in to comment.