mirror of
https://github.com/k8sgpt-ai/k8sgpt.git
synced 2026-03-19 03:23:47 +00:00
Compare commits
22 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
eb32a0f2bc | ||
|
|
ec08cac214 | ||
|
|
dca5b4710d | ||
|
|
b1c791a396 | ||
|
|
b780105807 | ||
|
|
16469c01c9 | ||
|
|
cf1e243708 | ||
|
|
b5853de8a6 | ||
|
|
58d182e94f | ||
|
|
5b27c3e352 | ||
|
|
3e3f6a903a | ||
|
|
12146bf356 | ||
|
|
beaa53251c | ||
|
|
e2bb567d2f | ||
|
|
24132c2d87 | ||
|
|
11e568c6c2 | ||
|
|
9971699fcf | ||
|
|
531fa79ed6 | ||
|
|
2aa31bc66d | ||
|
|
84df3640bc | ||
|
|
73682717ed | ||
|
|
45312788c3 |
4
.github/workflows/build_container.yaml
vendored
4
.github/workflows/build_container.yaml
vendored
@@ -77,7 +77,7 @@ jobs:
|
||||
uses: docker/setup-buildx-action@f95db51fddba0c2d1ec667646a06c2ce06100226 # v3
|
||||
|
||||
- name: Build Docker Image
|
||||
uses: docker/build-push-action@0565240e2d4ab88bba5387d719585280857ece09 # v5
|
||||
uses: docker/build-push-action@4a13e500e55cf31b7a5d59a38ab2040ab0f42f56 # v5
|
||||
with:
|
||||
context: .
|
||||
platforms: linux/amd64
|
||||
@@ -129,7 +129,7 @@ jobs:
|
||||
uses: docker/setup-buildx-action@f95db51fddba0c2d1ec667646a06c2ce06100226 # v3
|
||||
|
||||
- name: Build Docker Image
|
||||
uses: docker/build-push-action@0565240e2d4ab88bba5387d719585280857ece09 # v5
|
||||
uses: docker/build-push-action@4a13e500e55cf31b7a5d59a38ab2040ab0f42f56 # v5
|
||||
with:
|
||||
context: .
|
||||
file: ./container/Dockerfile
|
||||
|
||||
6
.github/workflows/release.yaml
vendored
6
.github/workflows/release.yaml
vendored
@@ -49,7 +49,7 @@ jobs:
|
||||
with:
|
||||
go-version: '1.20'
|
||||
- name: Download Syft
|
||||
uses: anchore/sbom-action/download-syft@78fc58e266e87a38d4194b2137a3d4e9bcaf7ca1 # v0.14.3
|
||||
uses: anchore/sbom-action/download-syft@fd74a6fb98a204a1ad35bbfae0122c1a302ff88b # v0.15.0
|
||||
- name: Run GoReleaser
|
||||
uses: goreleaser/goreleaser-action@7ec5c2b0c6cdda6e8bbb49444bc797dd33d74dd8 # v5
|
||||
with:
|
||||
@@ -90,7 +90,7 @@ jobs:
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Build Docker Image
|
||||
uses: docker/build-push-action@0565240e2d4ab88bba5387d719585280857ece09 # v5
|
||||
uses: docker/build-push-action@4a13e500e55cf31b7a5d59a38ab2040ab0f42f56 # v5
|
||||
with:
|
||||
context: .
|
||||
file: ./container/Dockerfile
|
||||
@@ -104,7 +104,7 @@ jobs:
|
||||
cache-to: type=gha,scope=${{ github.ref_name }}-${{ env.IMAGE_TAG }}
|
||||
|
||||
- name: Generate SBOM
|
||||
uses: anchore/sbom-action@78fc58e266e87a38d4194b2137a3d4e9bcaf7ca1 # v0.14.3
|
||||
uses: anchore/sbom-action@fd74a6fb98a204a1ad35bbfae0122c1a302ff88b # v0.15.0
|
||||
with:
|
||||
image: ${{ env.IMAGE_TAG }}
|
||||
artifact-name: sbom-${{ env.IMAGE_NAME }}
|
||||
|
||||
@@ -1 +1 @@
|
||||
{".":"0.3.21"}
|
||||
{".":"0.3.23"}
|
||||
43
CHANGELOG.md
43
CHANGELOG.md
@@ -1,5 +1,48 @@
|
||||
# Changelog
|
||||
|
||||
## [0.3.23](https://github.com/k8sgpt-ai/k8sgpt/compare/v0.3.22...v0.3.23) (2023-11-24)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* add Gateway analysers ([#764](https://github.com/k8sgpt-ai/k8sgpt/issues/764)) ([ec08cac](https://github.com/k8sgpt-ai/k8sgpt/commit/ec08cac21496b34b123b75b06d9283eb6539e890))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **deps:** update module github.com/aws/aws-sdk-go to v1.48.3 ([#768](https://github.com/k8sgpt-ai/k8sgpt/issues/768)) ([b1c791a](https://github.com/k8sgpt-ai/k8sgpt/commit/b1c791a396b7287ef916e8f8d382a0e14ba39949))
|
||||
* **deps:** update module github.com/mittwald/go-helm-client to v0.12.4 ([#767](https://github.com/k8sgpt-ai/k8sgpt/issues/767)) ([dca5b47](https://github.com/k8sgpt-ai/k8sgpt/commit/dca5b4710d1bb35dfc3346219d3bddb7c726300e))
|
||||
|
||||
## [0.3.22](https://github.com/k8sgpt-ai/k8sgpt/compare/v0.3.21...v0.3.22) (2023-11-21)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* rework cache package - add gcs cache - add cache purge command ([#750](https://github.com/k8sgpt-ai/k8sgpt/issues/750)) ([12146bf](https://github.com/k8sgpt-ai/k8sgpt/commit/12146bf356a3b26176c47e3a013a713fd14f346d))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* cover more error reason messages ([#759](https://github.com/k8sgpt-ai/k8sgpt/issues/759)) ([5b27c3e](https://github.com/k8sgpt-ai/k8sgpt/commit/5b27c3e352701819f1d0449df9acf706040f1f13))
|
||||
* **deps:** update kubernetes packages to v0.28.4 ([#756](https://github.com/k8sgpt-ai/k8sgpt/issues/756)) ([24132c2](https://github.com/k8sgpt-ai/k8sgpt/commit/24132c2d87024157009589cf2bd410bac2a26241))
|
||||
* **deps:** update module cloud.google.com/go/storage to v1.35.1 ([#762](https://github.com/k8sgpt-ai/k8sgpt/issues/762)) ([58d182e](https://github.com/k8sgpt-ai/k8sgpt/commit/58d182e94f75f9b035a9e45159fa87ce8a57de38))
|
||||
* **deps:** update module github.com/aquasecurity/trivy-operator to v0.16.4 ([#676](https://github.com/k8sgpt-ai/k8sgpt/issues/676)) ([4531278](https://github.com/k8sgpt-ai/k8sgpt/commit/45312788c3c15e141027c3fc8e428cfaa71d3ace))
|
||||
* **deps:** update module github.com/aws/aws-sdk-go to v1.47.10 ([#751](https://github.com/k8sgpt-ai/k8sgpt/issues/751)) ([2aa31bc](https://github.com/k8sgpt-ai/k8sgpt/commit/2aa31bc66d239906b1047f53bcaa58b0c30a2856))
|
||||
* **deps:** update module github.com/aws/aws-sdk-go to v1.47.11 ([#752](https://github.com/k8sgpt-ai/k8sgpt/issues/752)) ([531fa79](https://github.com/k8sgpt-ai/k8sgpt/commit/531fa79ed640846b177c516559dc82f088fa940f))
|
||||
* **deps:** update module github.com/aws/aws-sdk-go to v1.48.0 ([#754](https://github.com/k8sgpt-ai/k8sgpt/issues/754)) ([e2bb567](https://github.com/k8sgpt-ai/k8sgpt/commit/e2bb567d2f8d59a904583309c2774d4174eb367f))
|
||||
* **deps:** update module github.com/aws/aws-sdk-go to v1.48.1 ([#766](https://github.com/k8sgpt-ai/k8sgpt/issues/766)) ([16469c0](https://github.com/k8sgpt-ai/k8sgpt/commit/16469c01c962fd5bfa4ad11dd88a41f3e00e4a0d))
|
||||
* **deps:** update module github.com/sashabaranov/go-openai to v1.17.6 ([#749](https://github.com/k8sgpt-ai/k8sgpt/issues/749)) ([84df364](https://github.com/k8sgpt-ai/k8sgpt/commit/84df3640bc114bb2c768f158d3575732103ff799))
|
||||
* **deps:** update module github.com/sashabaranov/go-openai to v1.17.7 ([#753](https://github.com/k8sgpt-ai/k8sgpt/issues/753)) ([9971699](https://github.com/k8sgpt-ai/k8sgpt/commit/9971699fcf42b3309449d81875d45180f723de8d))
|
||||
* **deps:** update module github.com/sashabaranov/go-openai to v1.17.8 ([#761](https://github.com/k8sgpt-ai/k8sgpt/issues/761)) ([beaa532](https://github.com/k8sgpt-ai/k8sgpt/commit/beaa53251c8201028db83d60f208e2b0658c93d8))
|
||||
* **deps:** update module google.golang.org/api to v0.151.0 ([#763](https://github.com/k8sgpt-ai/k8sgpt/issues/763)) ([3e3f6a9](https://github.com/k8sgpt-ai/k8sgpt/commit/3e3f6a903a81d9622660f5adf9cae7d22a5c99f4))
|
||||
* show trivy as active when activated with --no-install flag ([#675](https://github.com/k8sgpt-ai/k8sgpt/issues/675)) ([7368271](https://github.com/k8sgpt-ai/k8sgpt/commit/73682717eda4fa2e0cbc6311d5c97e01e0f2673c))
|
||||
|
||||
|
||||
### Other
|
||||
|
||||
* **deps:** update anchore/sbom-action action to v0.15.0 ([#765](https://github.com/k8sgpt-ai/k8sgpt/issues/765)) ([cf1e243](https://github.com/k8sgpt-ai/k8sgpt/commit/cf1e243708ab406f070da3f96be1fc60b7ce2ea4))
|
||||
* **deps:** update docker/build-push-action digest to 4a13e50 ([#760](https://github.com/k8sgpt-ai/k8sgpt/issues/760)) ([b5853de](https://github.com/k8sgpt-ai/k8sgpt/commit/b5853de8a6fcd17b1c1a4c53dbe3ffc82b83f72f))
|
||||
|
||||
## [0.3.21](https://github.com/k8sgpt-ai/k8sgpt/compare/v0.3.20...v0.3.21) (2023-11-12)
|
||||
|
||||
|
||||
|
||||
33
README.md
33
README.md
@@ -36,7 +36,7 @@ brew install k8sgpt
|
||||
**32 bit:**
|
||||
<!---x-release-please-start-version-->
|
||||
```
|
||||
curl -LO https://github.com/k8sgpt-ai/k8sgpt/releases/download/v0.3.21/k8sgpt_386.rpm
|
||||
curl -LO https://github.com/k8sgpt-ai/k8sgpt/releases/download/v0.3.23/k8sgpt_386.rpm
|
||||
sudo rpm -ivh k8sgpt_386.rpm
|
||||
```
|
||||
<!---x-release-please-end-->
|
||||
@@ -45,7 +45,7 @@ brew install k8sgpt
|
||||
|
||||
<!---x-release-please-start-version-->
|
||||
```
|
||||
curl -LO https://github.com/k8sgpt-ai/k8sgpt/releases/download/v0.3.21/k8sgpt_amd64.rpm
|
||||
curl -LO https://github.com/k8sgpt-ai/k8sgpt/releases/download/v0.3.23/k8sgpt_amd64.rpm
|
||||
sudo rpm -ivh -i k8sgpt_amd64.rpm
|
||||
```
|
||||
<!---x-release-please-end-->
|
||||
@@ -57,7 +57,7 @@ brew install k8sgpt
|
||||
**32 bit:**
|
||||
<!---x-release-please-start-version-->
|
||||
```
|
||||
curl -LO https://github.com/k8sgpt-ai/k8sgpt/releases/download/v0.3.21/k8sgpt_386.deb
|
||||
curl -LO https://github.com/k8sgpt-ai/k8sgpt/releases/download/v0.3.23/k8sgpt_386.deb
|
||||
sudo dpkg -i k8sgpt_386.deb
|
||||
```
|
||||
<!---x-release-please-end-->
|
||||
@@ -65,7 +65,7 @@ brew install k8sgpt
|
||||
|
||||
<!---x-release-please-start-version-->
|
||||
```
|
||||
curl -LO https://github.com/k8sgpt-ai/k8sgpt/releases/download/v0.3.21/k8sgpt_amd64.deb
|
||||
curl -LO https://github.com/k8sgpt-ai/k8sgpt/releases/download/v0.3.23/k8sgpt_amd64.deb
|
||||
sudo dpkg -i k8sgpt_amd64.deb
|
||||
```
|
||||
<!---x-release-please-end-->
|
||||
@@ -78,14 +78,14 @@ brew install k8sgpt
|
||||
**32 bit:**
|
||||
<!---x-release-please-start-version-->
|
||||
```
|
||||
curl -LO https://github.com/k8sgpt-ai/k8sgpt/releases/download/v0.3.21/k8sgpt_386.apk
|
||||
curl -LO https://github.com/k8sgpt-ai/k8sgpt/releases/download/v0.3.23/k8sgpt_386.apk
|
||||
apk add k8sgpt_386.apk
|
||||
```
|
||||
<!---x-release-please-end-->
|
||||
**64 bit:**
|
||||
<!---x-release-please-start-version-->
|
||||
```
|
||||
curl -LO https://github.com/k8sgpt-ai/k8sgpt/releases/download/v0.3.21/k8sgpt_amd64.apk
|
||||
curl -LO https://github.com/k8sgpt-ai/k8sgpt/releases/download/v0.3.23/k8sgpt_amd64.apk
|
||||
apk add k8sgpt_amd64.apk
|
||||
```
|
||||
<!---x-release-please-end-->x
|
||||
@@ -159,6 +159,9 @@ you will be able to write your own analyzers.
|
||||
- [x] hpaAnalyzer
|
||||
- [x] pdbAnalyzer
|
||||
- [x] networkPolicyAnalyzer
|
||||
- [x] gatewayClass
|
||||
- [x] gateway
|
||||
- [x] httproute
|
||||
|
||||
## Examples
|
||||
|
||||
@@ -595,19 +598,29 @@ _Adding a remote cache_
|
||||
|
||||
* AWS S3
|
||||
* _As a prerequisite `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` are required as environmental variables._
|
||||
* Configuration, ``` k8sgpt cache add --region <aws region> --bucket <name> ```
|
||||
* Configuration, ``` k8sgpt cache add s3 --region <aws region> --bucket <name> ```
|
||||
* K8sGPT will create the bucket if it does not exist
|
||||
* Azure Storage
|
||||
* We support a number of [techniques](https://learn.microsoft.com/en-us/azure/developer/go/azure-sdk-authentication?tabs=bash#2-authenticate-with-azure) to authenticate against Azure
|
||||
* Configuration, ``` k8sgpt cache add --storageacc <storage account name> --container <container name> ```
|
||||
* Configuration, ``` k8sgpt cache add azure --storageacc <storage account name> --container <container name> ```
|
||||
* K8sGPT assumes that the storage account already exist and it will create the container if it does not exist
|
||||
* It's **users'** responsibility have to grant specific permissions to their identity in order to be able to upload blob files and create SA containers (e.g Storage Blob Data Contributor)
|
||||
* It is the **user** responsibility have to grant specific permissions to their identity in order to be able to upload blob files and create SA containers (e.g Storage Blob Data Contributor)
|
||||
* Google Cloud Storage
|
||||
* _As a prerequisite `GOOGLE_APPLICATION_CREDENTIALS` are required as environmental variables._
|
||||
* Configuration, ``` k8sgpt cache add gcs --region <gcp region> --bucket <name> --projectid <project id>```
|
||||
* K8sGPT will create the bucket if it does not exist
|
||||
|
||||
_Listing cache items_
|
||||
```
|
||||
k8sgpt cache list
|
||||
```
|
||||
|
||||
_Purging an object from the cache_
|
||||
Note: purging an object using this command will delete upstream files, so it requires appropriate permissions.
|
||||
```
|
||||
k8sgpt cache purge $OBJECT_NAME
|
||||
```
|
||||
|
||||
_Removing the remote cache_
|
||||
Note: this will not delete the upstream S3 bucket or Azure storage container
|
||||
```
|
||||
@@ -625,7 +638,7 @@ Find our official documentation available [here](https://docs.k8sgpt.ai)
|
||||
|
||||
Please read our [contributing guide](./CONTRIBUTING.md).
|
||||
## Community
|
||||
Find us on [Slack](https://join.slack.com/t/k8sgpt/shared_invite/zt-1rwe5fpzq-VNtJK8DmYbbm~iWL1H34nw)
|
||||
Find us on [Slack](https://join.slack.com/t/k8sgpt/shared_invite/zt-276pa9uyq-pxAUr4TCVHubFxEvLZuT1Q)
|
||||
|
||||
<a href="https://github.com/k8sgpt-ai/k8sgpt/graphs/contributors">
|
||||
<img src="https://contrib.rocks/image?repo=k8sgpt-ai/k8sgpt" />
|
||||
|
||||
22
cmd/cache/add.go
vendored
22
cmd/cache/add.go
vendored
@@ -28,20 +28,31 @@ var (
|
||||
bucketName string
|
||||
storageAccount string
|
||||
containerName string
|
||||
projectId string
|
||||
)
|
||||
|
||||
// addCmd represents the add command
|
||||
var addCmd = &cobra.Command{
|
||||
Use: "add",
|
||||
Use: "add [cache type]",
|
||||
Short: "Add a remote cache",
|
||||
Long: `This command allows you to add a remote cache to store the results of an analysis.
|
||||
The supported cache types are:
|
||||
- Azure Blob storage
|
||||
- Google Cloud storage
|
||||
- S3`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
if len(args) == 0 {
|
||||
color.Red("Error: Please provide a value for cache types. Run k8sgpt cache add --help")
|
||||
os.Exit(1)
|
||||
}
|
||||
fmt.Println(color.YellowString("Adding remote based cache"))
|
||||
remoteCache := cache.NewCacheProvider(bucketname, region, storageAccount, containerName)
|
||||
err := cache.AddRemoteCache(remoteCache)
|
||||
cacheType := args[0]
|
||||
remoteCache, err := cache.NewCacheProvider(cacheType, bucketname, region, storageAccount, containerName, projectId)
|
||||
if err != nil {
|
||||
color.Red("Error: %v", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
err = cache.AddRemoteCache(remoteCache)
|
||||
if err != nil {
|
||||
color.Red("Error: %v", err)
|
||||
os.Exit(1)
|
||||
@@ -51,9 +62,10 @@ var addCmd = &cobra.Command{
|
||||
|
||||
func init() {
|
||||
CacheCmd.AddCommand(addCmd)
|
||||
addCmd.Flags().StringVarP(®ion, "region", "r", "", "The region to use for the AWS S3 cache")
|
||||
addCmd.Flags().StringVarP(®ion, "region", "r", "", "The region to use for the AWS S3 or GCS cache")
|
||||
addCmd.Flags().StringVarP(&bucketname, "bucket", "b", "", "The name of the AWS S3 bucket to use for the cache")
|
||||
addCmd.MarkFlagsRequiredTogether("region", "bucket")
|
||||
addCmd.Flags().StringVarP(&projectId, "projectid", "p", "", "The GCP project ID")
|
||||
addCmd.Flags().StringVarP(&storageAccount, "storageacc", "s", "", "The Azure storage account name of the container")
|
||||
addCmd.Flags().StringVarP(&containerName, "container", "c", "", "The Azure container name to use for the cache")
|
||||
addCmd.MarkFlagsRequiredTogether("storageacc", "container")
|
||||
@@ -62,4 +74,6 @@ func init() {
|
||||
addCmd.MarkFlagsMutuallyExclusive("region", "container")
|
||||
addCmd.MarkFlagsMutuallyExclusive("bucket", "storageacc")
|
||||
addCmd.MarkFlagsMutuallyExclusive("bucket", "container")
|
||||
addCmd.MarkFlagsMutuallyExclusive("projectid", "storageacc")
|
||||
addCmd.MarkFlagsMutuallyExclusive("projectid", "container")
|
||||
}
|
||||
|
||||
22
cmd/cache/list.go
vendored
22
cmd/cache/list.go
vendored
@@ -16,9 +16,11 @@ package cache
|
||||
|
||||
import (
|
||||
"os"
|
||||
"reflect"
|
||||
|
||||
"github.com/fatih/color"
|
||||
"github.com/k8sgpt-ai/k8sgpt/pkg/cache"
|
||||
"github.com/olekukonko/tablewriter"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
@@ -30,22 +32,32 @@ var listCmd = &cobra.Command{
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
|
||||
// load remote cache if it is configured
|
||||
remoteCacheEnabled, err := cache.RemoteCacheEnabled()
|
||||
c, err := cache.GetCacheConfiguration()
|
||||
if err != nil {
|
||||
color.Red("Error: %v", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
c := cache.New(false, remoteCacheEnabled)
|
||||
// list the contents of the cache
|
||||
names, err := c.List()
|
||||
if err != nil {
|
||||
color.Red("Error: %v", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
for _, name := range names {
|
||||
println(name)
|
||||
var headers []string
|
||||
obj := cache.CacheObjectDetails{}
|
||||
objType := reflect.TypeOf(obj)
|
||||
for i := 0; i < objType.NumField(); i++ {
|
||||
field := objType.Field(i)
|
||||
headers = append(headers, field.Name)
|
||||
}
|
||||
|
||||
table := tablewriter.NewWriter(os.Stdout)
|
||||
table.SetHeader(headers)
|
||||
|
||||
for _, v := range names {
|
||||
table.Append([]string{v.Name, v.UpdatedAt.String()})
|
||||
}
|
||||
table.Render()
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
54
cmd/cache/purge.go
vendored
Normal file
54
cmd/cache/purge.go
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
Copyright 2023 The K8sGPT Authors.
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
package cache
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/fatih/color"
|
||||
"github.com/k8sgpt-ai/k8sgpt/pkg/cache"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var purgeCmd = &cobra.Command{
|
||||
Use: "purge [object name]",
|
||||
Short: "Purge a remote cache",
|
||||
Long: "This command allows you to delete/purge one object from the cache",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
if len(args) == 0 {
|
||||
color.Red("Error: Please provide a value for object name. Run k8sgpt cache purge --help")
|
||||
os.Exit(1)
|
||||
}
|
||||
objectKey := args[0]
|
||||
fmt.Println(color.YellowString("Purging a remote cache."))
|
||||
c, err := cache.GetCacheConfiguration()
|
||||
if err != nil {
|
||||
color.Red("Error: %v", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
err = c.Remove(objectKey)
|
||||
if err != nil {
|
||||
color.Red("Error: %v", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
fmt.Println(color.GreenString("Object deleted."))
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
CacheCmd.AddCommand(purgeCmd)
|
||||
}
|
||||
97
go.mod
97
go.mod
@@ -3,36 +3,45 @@ module github.com/k8sgpt-ai/k8sgpt
|
||||
go 1.20
|
||||
|
||||
require (
|
||||
github.com/aquasecurity/trivy-operator v0.15.1
|
||||
github.com/aquasecurity/trivy-operator v0.16.4
|
||||
github.com/fatih/color v1.16.0
|
||||
github.com/magiconair/properties v1.8.7
|
||||
github.com/mittwald/go-helm-client v0.12.3
|
||||
github.com/sashabaranov/go-openai v1.17.5
|
||||
github.com/mittwald/go-helm-client v0.12.4
|
||||
github.com/sashabaranov/go-openai v1.17.8
|
||||
github.com/schollz/progressbar/v3 v3.14.1
|
||||
github.com/spf13/cobra v1.8.0
|
||||
github.com/spf13/viper v1.17.0
|
||||
github.com/stretchr/testify v1.8.4
|
||||
golang.org/x/term v0.14.0
|
||||
helm.sh/helm/v3 v3.13.2
|
||||
k8s.io/api v0.28.3
|
||||
k8s.io/apimachinery v0.28.3
|
||||
k8s.io/client-go v0.28.3
|
||||
k8s.io/kubectl v0.28.3
|
||||
k8s.io/api v0.28.4
|
||||
k8s.io/apimachinery v0.28.4
|
||||
k8s.io/client-go v0.28.4
|
||||
k8s.io/kubectl v0.28.4
|
||||
|
||||
)
|
||||
|
||||
require github.com/adrg/xdg v0.4.0
|
||||
|
||||
require (
|
||||
buf.build/gen/go/k8sgpt-ai/k8sgpt/grpc/go v1.3.0-20231002095256-194bc640518b.1
|
||||
buf.build/gen/go/k8sgpt-ai/k8sgpt/protocolbuffers/go v1.31.0-20231002095256-194bc640518b.1
|
||||
buf.build/gen/go/k8sgpt-ai/k8sgpt/grpc/go v1.3.0-20231116211251-9f5041346631.2
|
||||
buf.build/gen/go/k8sgpt-ai/k8sgpt/protocolbuffers/go v1.28.1-20231116211251-9f5041346631.4
|
||||
cloud.google.com/go/storage v1.35.1
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.4.0
|
||||
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.2.0
|
||||
github.com/aws/aws-sdk-go v1.47.9
|
||||
github.com/aws/aws-sdk-go v1.48.3
|
||||
github.com/cohere-ai/cohere-go v0.2.0
|
||||
github.com/olekukonko/tablewriter v0.0.5
|
||||
sigs.k8s.io/controller-runtime v0.16.3
|
||||
sigs.k8s.io/gateway-api v1.0.0
|
||||
google.golang.org/api v0.151.0
|
||||
)
|
||||
|
||||
require (
|
||||
cloud.google.com/go v0.110.8 // indirect
|
||||
cloud.google.com/go/compute v1.23.1 // indirect
|
||||
cloud.google.com/go/compute/metadata v0.2.3 // indirect
|
||||
cloud.google.com/go/iam v1.1.3 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.8.0 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 // indirect
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v1.1.1 // indirect
|
||||
@@ -40,15 +49,24 @@ require (
|
||||
github.com/anchore/go-struct-converter v0.0.0-20221118182256-c68fdcfa2092 // indirect
|
||||
github.com/cohere-ai/tokenizer v1.1.1 // indirect
|
||||
github.com/dlclark/regexp2 v1.4.0 // indirect
|
||||
github.com/evanphx/json-patch/v5 v5.7.0 // indirect
|
||||
github.com/golang-jwt/jwt/v5 v5.0.0 // indirect
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||
github.com/google/gnostic-models v0.6.9-0.20230804172637-c7be7c783f49 // indirect
|
||||
github.com/google/s2a-go v0.1.7 // indirect
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect
|
||||
github.com/googleapis/gax-go/v2 v2.12.0 // indirect
|
||||
github.com/jmespath/go-jmespath v0.4.0 // indirect
|
||||
github.com/kylelemons/godebug v1.1.0 // indirect
|
||||
github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 // indirect
|
||||
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 // indirect
|
||||
github.com/sagikazarmark/locafero v0.3.0 // indirect
|
||||
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
|
||||
github.com/sourcegraph/conc v0.3.0 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20230920204549-e6e6cdab5c13 // indirect
|
||||
go.opencensus.io v0.24.0 // indirect
|
||||
google.golang.org/genproto v0.0.0-20231016165738-49dd2c1f3d0b // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20231016165738-49dd2c1f3d0b // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20231030173426-d783a09b4405 // indirect
|
||||
)
|
||||
|
||||
require (
|
||||
@@ -60,12 +78,12 @@ require (
|
||||
github.com/Masterminds/semver/v3 v3.2.1 // indirect
|
||||
github.com/Masterminds/sprig/v3 v3.2.3 // indirect
|
||||
github.com/Masterminds/squirrel v1.5.4 // indirect
|
||||
github.com/aquasecurity/defsec v0.89.0 // indirect
|
||||
github.com/aquasecurity/go-dep-parser v0.0.0-20230605080024-b71d9356a6c6 // indirect
|
||||
github.com/aquasecurity/defsec v0.93.1 // indirect
|
||||
github.com/aquasecurity/go-dep-parser v0.0.0-20230830122616-841bc0f812c7 // indirect
|
||||
github.com/aquasecurity/table v1.8.0 // indirect
|
||||
github.com/aquasecurity/tml v0.6.1 // indirect
|
||||
github.com/aquasecurity/trivy v0.42.1 // indirect
|
||||
github.com/aquasecurity/trivy-db v0.0.0-20230515061101-378ab9ed302c // indirect
|
||||
github.com/aquasecurity/trivy v0.45.1 // indirect
|
||||
github.com/aquasecurity/trivy-db v0.0.0-20230831170347-f732860d4917 // indirect
|
||||
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.2.0 // indirect
|
||||
@@ -80,27 +98,27 @@ require (
|
||||
github.com/docker/go-connections v0.4.0 // indirect
|
||||
github.com/docker/go-metrics v0.0.1 // indirect
|
||||
github.com/docker/go-units v0.5.0 // indirect
|
||||
github.com/emicklei/go-restful/v3 v3.10.2 // indirect
|
||||
github.com/evanphx/json-patch v5.6.0+incompatible // indirect
|
||||
github.com/emicklei/go-restful/v3 v3.11.0 // indirect
|
||||
github.com/evanphx/json-patch v5.7.0+incompatible // indirect
|
||||
github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f // indirect
|
||||
github.com/fsnotify/fsnotify v1.6.0 // indirect
|
||||
github.com/fsnotify/fsnotify v1.7.0 // indirect
|
||||
github.com/go-errors/errors v1.4.2 // indirect
|
||||
github.com/go-gorp/gorp/v3 v3.1.0 // indirect
|
||||
github.com/go-logr/logr v1.2.4 // indirect
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/go-openapi/jsonpointer v0.19.6 // indirect
|
||||
github.com/go-openapi/jsonpointer v0.20.0 // indirect
|
||||
github.com/go-openapi/jsonreference v0.20.2 // indirect
|
||||
github.com/go-openapi/swag v0.22.3 // indirect
|
||||
github.com/go-openapi/swag v0.22.4 // indirect
|
||||
github.com/gobwas/glob v0.2.3 // indirect
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/golang/protobuf v1.5.3 // indirect
|
||||
github.com/google/btree v1.1.2 // indirect
|
||||
github.com/google/gnostic v0.7.0
|
||||
github.com/google/go-cmp v0.5.9 // indirect
|
||||
github.com/google/go-containerregistry v0.15.2 // indirect
|
||||
github.com/google/go-cmp v0.6.0 // indirect
|
||||
github.com/google/go-containerregistry v0.16.1 // indirect
|
||||
github.com/google/gofuzz v1.2.0 // indirect
|
||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
|
||||
github.com/google/uuid v1.3.1 // indirect
|
||||
github.com/google/uuid v1.4.0 // indirect
|
||||
github.com/gorilla/mux v1.8.0 // indirect
|
||||
github.com/gosuri/uitable v0.0.4 // indirect
|
||||
github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 // indirect
|
||||
@@ -108,7 +126,7 @@ require (
|
||||
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||
github.com/huandu/xstrings v1.4.0 // indirect
|
||||
github.com/imdario/mergo v0.3.15 // indirect
|
||||
github.com/imdario/mergo v0.3.16 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||
github.com/jmoiron/sqlx v1.3.5 // indirect
|
||||
github.com/josharian/intern v1.0.0 // indirect
|
||||
@@ -123,7 +141,6 @@ require (
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.14 // indirect
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
|
||||
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db // indirect
|
||||
github.com/mitchellh/copystructure v1.2.0 // indirect
|
||||
github.com/mitchellh/go-wordwrap v1.0.1 // indirect
|
||||
@@ -144,9 +161,9 @@ require (
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||
github.com/prometheus/client_golang v1.17.0
|
||||
github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16 // indirect
|
||||
github.com/prometheus/common v0.44.0 // indirect
|
||||
github.com/prometheus/procfs v0.11.1 // indirect
|
||||
github.com/prometheus/client_model v0.5.0 // indirect
|
||||
github.com/prometheus/common v0.45.0 // indirect
|
||||
github.com/prometheus/procfs v0.12.0 // indirect
|
||||
github.com/rivo/uniseg v0.4.4 // indirect
|
||||
github.com/robfig/cron/v3 v3.0.1
|
||||
github.com/rubenv/sql-migrate v1.5.2 // indirect
|
||||
@@ -169,34 +186,34 @@ require (
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
go.uber.org/zap v1.26.0
|
||||
golang.org/x/crypto v0.14.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect
|
||||
golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa // indirect
|
||||
golang.org/x/net v0.17.0 // indirect
|
||||
golang.org/x/oauth2 v0.12.0 // indirect
|
||||
golang.org/x/sync v0.3.0 // indirect
|
||||
golang.org/x/oauth2 v0.13.0 // indirect
|
||||
golang.org/x/sync v0.5.0 // indirect
|
||||
golang.org/x/sys v0.14.0 // indirect
|
||||
golang.org/x/text v0.13.0 // indirect
|
||||
golang.org/x/time v0.3.0 // indirect
|
||||
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
|
||||
google.golang.org/appengine v1.6.7 // indirect
|
||||
google.golang.org/appengine v1.6.8 // indirect
|
||||
google.golang.org/grpc v1.59.0
|
||||
google.golang.org/protobuf v1.31.0 // indirect
|
||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
k8s.io/apiextensions-apiserver v0.28.2 // indirect
|
||||
k8s.io/apiserver v0.28.2 // indirect
|
||||
k8s.io/cli-runtime v0.28.3 // indirect
|
||||
k8s.io/component-base v0.28.3 // indirect
|
||||
k8s.io/apiextensions-apiserver v0.28.3 // indirect
|
||||
k8s.io/apiserver v0.28.3 // indirect
|
||||
k8s.io/cli-runtime v0.28.4 // indirect
|
||||
k8s.io/component-base v0.28.4 // indirect
|
||||
k8s.io/klog/v2 v2.100.1 // indirect
|
||||
k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9 // indirect
|
||||
k8s.io/utils v0.0.0-20230406110748-d93618cff8a2 // indirect
|
||||
k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 // indirect
|
||||
k8s.io/utils v0.0.0-20230726121419-3b25d923346b // indirect
|
||||
oras.land/oras-go v1.2.4 // indirect
|
||||
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
|
||||
sigs.k8s.io/kustomize/api v0.13.5-0.20230601165947-6ce0bf390ce3 // indirect
|
||||
sigs.k8s.io/kustomize/kyaml v0.14.3-0.20230601165947-6ce0bf390ce3 // indirect
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect
|
||||
sigs.k8s.io/yaml v1.3.0 // indirect
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.3.0 // indirect
|
||||
sigs.k8s.io/yaml v1.4.0 // indirect
|
||||
)
|
||||
|
||||
// v1.2.0 is taken from github.com/open-policy-agent/opa v0.42.0
|
||||
|
||||
211
go.sum
211
go.sum
@@ -1,8 +1,7 @@
|
||||
buf.build/gen/go/k8sgpt-ai/k8sgpt/grpc/go v1.3.0-20231002095256-194bc640518b.1 h1:xYEAhcdWh89HNtbM5Uv4b2xu+4/MkNffR9JNrnnEjXU=
|
||||
buf.build/gen/go/k8sgpt-ai/k8sgpt/grpc/go v1.3.0-20231002095256-194bc640518b.1/go.mod h1:j2QJ3L7VTtI+VeK6t03h9X934FolVTb3FwXUc76bQMQ=
|
||||
buf.build/gen/go/k8sgpt-ai/k8sgpt/protocolbuffers/go v1.28.1-20231002095256-194bc640518b.4/go.mod h1:i/s4ALHwKvjA1oGNKpoHg0FpEOTbufoOm/NdTE6YQAE=
|
||||
buf.build/gen/go/k8sgpt-ai/k8sgpt/protocolbuffers/go v1.31.0-20231002095256-194bc640518b.1 h1:Bt8mnCodD/BqChxt/r3xYayGLoOAn334qC1tN7VqUTE=
|
||||
buf.build/gen/go/k8sgpt-ai/k8sgpt/protocolbuffers/go v1.31.0-20231002095256-194bc640518b.1/go.mod h1:gtnk2yAUexdY5nTuUg0SH5WCCGvpKzr7pd3Xbi7MWjE=
|
||||
buf.build/gen/go/k8sgpt-ai/k8sgpt/grpc/go v1.3.0-20231116211251-9f5041346631.2 h1:lr4kHFzPIzoWIHF6s/B+0Wb/WknraHrbqNguavOzP70=
|
||||
buf.build/gen/go/k8sgpt-ai/k8sgpt/grpc/go v1.3.0-20231116211251-9f5041346631.2/go.mod h1:g/UdFu0wAAS44ncCfX3zjna7WC1gp6BENVL6LPJ9tow=
|
||||
buf.build/gen/go/k8sgpt-ai/k8sgpt/protocolbuffers/go v1.28.1-20231116211251-9f5041346631.4 h1:f7e94G/tYVs+QDTvjU9sFolC5tuJxlOjzUBJ84XMwkg=
|
||||
buf.build/gen/go/k8sgpt-ai/k8sgpt/protocolbuffers/go v1.28.1-20231116211251-9f5041346631.4/go.mod h1:i/s4ALHwKvjA1oGNKpoHg0FpEOTbufoOm/NdTE6YQAE=
|
||||
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=
|
||||
@@ -41,6 +40,8 @@ cloud.google.com/go v0.104.0/go.mod h1:OO6xxXdJyvuJPcEPBLN9BJPD+jep5G1+2U5B5gkRY
|
||||
cloud.google.com/go v0.105.0/go.mod h1:PrLgOJNe5nfE9UMxKxgXj4mD3voiP+YQ6gdt6KMFOKM=
|
||||
cloud.google.com/go v0.107.0/go.mod h1:wpc2eNrD7hXUTy8EKS10jkxpZBjASrORK7goS+3YX2I=
|
||||
cloud.google.com/go v0.110.0/go.mod h1:SJnCLqQ0FCFGSZMUNUf84MV3Aia54kn7pi8st7tMzaY=
|
||||
cloud.google.com/go v0.110.8 h1:tyNdfIxjzaWctIiLYOTalaLKZ17SI44SKFW26QbOhME=
|
||||
cloud.google.com/go v0.110.8/go.mod h1:Iz8AkXJf1qmxC3Oxoep8R1T36w8B92yU29PcBhHO5fk=
|
||||
cloud.google.com/go/accessapproval v1.4.0/go.mod h1:zybIuC3KpDOvotz59lFe5qxRZx6C75OtwbisN56xYB4=
|
||||
cloud.google.com/go/accessapproval v1.5.0/go.mod h1:HFy3tuiGvMdcd/u+Cu5b9NkO1pEICJ46IR82PoUdplw=
|
||||
cloud.google.com/go/accessapproval v1.6.0/go.mod h1:R0EiYnwV5fsRFiKZkPHr6mwyk2wxUJ30nL4j2pcFY2E=
|
||||
@@ -176,9 +177,12 @@ cloud.google.com/go/compute v1.14.0/go.mod h1:YfLtxrj9sU4Yxv+sXzZkyPjEyPBZfXHUvj
|
||||
cloud.google.com/go/compute v1.15.1/go.mod h1:bjjoF/NtFUrkD/urWfdHaKuOPDR5nWIs63rR+SXhcpA=
|
||||
cloud.google.com/go/compute v1.18.0/go.mod h1:1X7yHxec2Ga+Ss6jPyjxRxpu2uu7PLgsOVXvgU0yacs=
|
||||
cloud.google.com/go/compute v1.19.0/go.mod h1:rikpw2y+UMidAe9tISo04EHNOIf42RLYF/q8Bs93scU=
|
||||
cloud.google.com/go/compute v1.23.1 h1:V97tBoDaZHb6leicZ1G6DLK2BAaZLJ/7+9BB/En3hR0=
|
||||
cloud.google.com/go/compute v1.23.1/go.mod h1:CqB3xpmPKKt3OJpW2ndFIXnA9A4xAy/F3Xp1ixncW78=
|
||||
cloud.google.com/go/compute/metadata v0.1.0/go.mod h1:Z1VN+bulIf6bt4P/C37K4DyZYZEXYonfTBHHFPO/4UU=
|
||||
cloud.google.com/go/compute/metadata v0.2.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k=
|
||||
cloud.google.com/go/compute/metadata v0.2.1/go.mod h1:jgHgmJd2RKBGzXqF5LR2EZMGxBkeanZ9wwa75XHJgOM=
|
||||
cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY=
|
||||
cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA=
|
||||
cloud.google.com/go/contactcenterinsights v1.3.0/go.mod h1:Eu2oemoePuEFc/xKFPjbTuPSj0fYJcPls9TFlPNnHHY=
|
||||
cloud.google.com/go/contactcenterinsights v1.4.0/go.mod h1:L2YzkGbPsv+vMQMCADxJoT9YiTTnSEd6fEvCeHTYVck=
|
||||
@@ -313,6 +317,8 @@ cloud.google.com/go/iam v0.8.0/go.mod h1:lga0/y3iH6CX7sYqypWJ33hf7kkfXJag67naqGE
|
||||
cloud.google.com/go/iam v0.11.0/go.mod h1:9PiLDanza5D+oWFZiH1uG+RnRCfEGKoyl6yo4cgWZGY=
|
||||
cloud.google.com/go/iam v0.12.0/go.mod h1:knyHGviacl11zrtZUoDuYpDgLjvr28sLQaG0YB2GYAY=
|
||||
cloud.google.com/go/iam v0.13.0/go.mod h1:ljOg+rcNfzZ5d6f1nAUJ8ZIxOaZUVoS14bKCtaLZ/D0=
|
||||
cloud.google.com/go/iam v1.1.3 h1:18tKG7DzydKWUnLjonWcJO6wjSCAtzh4GcRKlH/Hrzc=
|
||||
cloud.google.com/go/iam v1.1.3/go.mod h1:3khUlaBXfPKKe7huYgEpDn6FtgRyMEqbkvBxrQyY5SE=
|
||||
cloud.google.com/go/iap v1.4.0/go.mod h1:RGFwRJdihTINIe4wZ2iCP0zF/qu18ZwyKxrhMhygBEc=
|
||||
cloud.google.com/go/iap v1.5.0/go.mod h1:UH/CGgKd4KyohZL5Pt0jSKE4m3FR51qg6FKQ/z/Ix9A=
|
||||
cloud.google.com/go/iap v1.6.0/go.mod h1:NSuvI9C/j7UdjGjIde7t7HBz+QTwBcapPE07+sSRcLk=
|
||||
@@ -531,6 +537,8 @@ cloud.google.com/go/storage v1.23.0/go.mod h1:vOEEDNFnciUMhBeT6hsJIn3ieU5cFRmzeL
|
||||
cloud.google.com/go/storage v1.27.0/go.mod h1:x9DOL8TK/ygDUMieqwfhdpQryTeEkhGKMi80i/iqR2s=
|
||||
cloud.google.com/go/storage v1.28.1/go.mod h1:Qnisd4CqDdo6BGs2AD5LLnEsmSQ80wQ5ogcBBKhU86Y=
|
||||
cloud.google.com/go/storage v1.29.0/go.mod h1:4puEjyTKnku6gfKoTfNOU/W+a9JyuVNxjpS5GBrB8h4=
|
||||
cloud.google.com/go/storage v1.35.1 h1:B59ahL//eDfx2IIKFBeT5Atm9wnNmj3+8xG/W4WB//w=
|
||||
cloud.google.com/go/storage v1.35.1/go.mod h1:M6M/3V/D3KpzMTJyPOR/HU6n2Si5QdaXYEsng2xgOs8=
|
||||
cloud.google.com/go/storagetransfer v1.5.0/go.mod h1:dxNzUopWy7RQevYFHewchb29POFv3/AaBgnhqzqiK0w=
|
||||
cloud.google.com/go/storagetransfer v1.6.0/go.mod h1:y77xm4CQV/ZhFZH75PLEXY0ROiS7Gh6pSKrM8dJyg6I=
|
||||
cloud.google.com/go/storagetransfer v1.7.0/go.mod h1:8Giuj1QNb1kfLAiWM1bN6dHzfdlDAVC9rv9abHot2W4=
|
||||
@@ -619,7 +627,6 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03
|
||||
github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8=
|
||||
github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
|
||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||
github.com/CycloneDX/cyclonedx-go v0.7.1 h1:5w1SxjGm9MTMNTuRbEPyw21ObdbaagTWF/KfF0qHTRE=
|
||||
github.com/DATA-DOG/go-sqlmock v1.5.0 h1:Shsta01QNfFxHCfpW6YH2STWB0MudeXXEWMr20OEh60=
|
||||
github.com/JohnCGriffin/overflow v0.0.0-20211019200055-46fa312c352c/go.mod h1:X0CRv0ky0k6m906ixxpzmDRLvX58TFUKS2eePweuyxk=
|
||||
github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ=
|
||||
@@ -658,25 +665,25 @@ github.com/apache/arrow/go/v10 v10.0.1/go.mod h1:YvhnlEePVnBS4+0z3fhPfUy7W1Ikj0I
|
||||
github.com/apache/arrow/go/v11 v11.0.0/go.mod h1:Eg5OsL5H+e299f7u5ssuXsuHQVEGC4xei5aX110hRiI=
|
||||
github.com/apache/thrift v0.16.0/go.mod h1:PHK3hniurgQaNMZYaCLEqXKsYK8upmhPbmdP2FXSqgU=
|
||||
github.com/apparentlymart/go-textseg/v13 v13.0.0 h1:Y+KvPE1NYz0xl601PVImeQfFyEy6iT90AvPUL1NNfNw=
|
||||
github.com/aquasecurity/defsec v0.89.0 h1:5B0mJYraNa2n5zlYuShqOwRt5kqFXdVfGPRYiZJPDuw=
|
||||
github.com/aquasecurity/defsec v0.89.0/go.mod h1:te+KhIV8w1pDIjTsUQwlc6xRn8gC7f+TJUiFhLlcEHM=
|
||||
github.com/aquasecurity/go-dep-parser v0.0.0-20230605080024-b71d9356a6c6 h1:2iozdTN+LM7g2kbarphvy6L3N23+t0kCEonWQOGUXo8=
|
||||
github.com/aquasecurity/go-dep-parser v0.0.0-20230605080024-b71d9356a6c6/go.mod h1:2Yfi9sB8TSwxM/KQDTpy4xFM6zG4yBjc1jS966uMIP8=
|
||||
github.com/aquasecurity/defsec v0.93.1 h1:y4XgRknjs2M58XVLANBT1wulO7N6Rz1oyfwNuzID+h4=
|
||||
github.com/aquasecurity/defsec v0.93.1/go.mod h1:i80K4WRNbcIWDOQDWnTHkutBwplzw/uZD4laKbhu4sE=
|
||||
github.com/aquasecurity/go-dep-parser v0.0.0-20230830122616-841bc0f812c7 h1:FSfz2vfnL3EvTh04zDx4SYxKmgDbYSr8td6R8XbtbB8=
|
||||
github.com/aquasecurity/go-dep-parser v0.0.0-20230830122616-841bc0f812c7/go.mod h1:0+GvQF0gL4YEAAUPpNeLeGpFDxMvvIHLMd7vk9bpwko=
|
||||
github.com/aquasecurity/table v1.8.0 h1:9ntpSwrUfjrM6/YviArlx/ZBGd6ix8W+MtojQcM7tv0=
|
||||
github.com/aquasecurity/table v1.8.0/go.mod h1:eqOmvjjB7AhXFgFqpJUEE/ietg7RrMSJZXyTN8E/wZw=
|
||||
github.com/aquasecurity/tml v0.6.1 h1:y2ZlGSfrhnn7t4ZJ/0rotuH+v5Jgv6BDDO5jB6A9gwo=
|
||||
github.com/aquasecurity/tml v0.6.1/go.mod h1:OnYMWY5lvI9ejU7yH9LCberWaaTBW7hBFsITiIMY2yY=
|
||||
github.com/aquasecurity/trivy v0.42.1 h1:rBDGiilP1jdrc5/dyyZ41ESAVb9hOMwginHVn97ggJ0=
|
||||
github.com/aquasecurity/trivy v0.42.1/go.mod h1:mbwzUAyy3YdVGYvuqtd1E2ylhfz/k39lMNdJQlU2TZQ=
|
||||
github.com/aquasecurity/trivy-db v0.0.0-20230515061101-378ab9ed302c h1:mFMfHmb5GC6xrnUGk2mJcKNt5vBaFSzJx1MMW47uzB0=
|
||||
github.com/aquasecurity/trivy-db v0.0.0-20230515061101-378ab9ed302c/go.mod h1:s7x7CTxYeiFf6gPOakSsg4mCD93au4dbYplG4h0FGrs=
|
||||
github.com/aquasecurity/trivy-operator v0.15.1 h1:T/M2P+QX+vQTuDsoK+9GV3VK0AgAazrMIXhD5rSyiDA=
|
||||
github.com/aquasecurity/trivy-operator v0.15.1/go.mod h1:Qy1hd0sXX/1HOqn1cIuel23/PSNg25xfbS8V3pKKv0A=
|
||||
github.com/aquasecurity/trivy v0.45.1 h1:JjkrawgNpVUV6mxtFX635I3MhzDqmGkze46SnygkYN0=
|
||||
github.com/aquasecurity/trivy v0.45.1/go.mod h1:3cawI6q9o32pPGXhuGEIWWwUCSMAzRk/FhsEdA4eW1k=
|
||||
github.com/aquasecurity/trivy-db v0.0.0-20230831170347-f732860d4917 h1:MQd7h7yUyA8UlUzhjNMzpUX0NpD7jfxmRfSKwp/Ji3E=
|
||||
github.com/aquasecurity/trivy-db v0.0.0-20230831170347-f732860d4917/go.mod h1:WJ5Qnk5ZNGWvks07GOZe2IOsuXrPfSC5c8hYGOGfrsU=
|
||||
github.com/aquasecurity/trivy-operator v0.16.4 h1:iZqkmEz/ViwUTCqNts0qJsGIVEIVpw/MRoyOp6oTdBM=
|
||||
github.com/aquasecurity/trivy-operator v0.16.4/go.mod h1:zq+CnvZPz3u6db50UJ+ICf0LcbyrZoswFwDKkJj1Ujk=
|
||||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
|
||||
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so=
|
||||
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
|
||||
github.com/aws/aws-sdk-go v1.47.9 h1:rarTsos0mA16q+huicGx0e560aYRtOucV5z2Mw23JRY=
|
||||
github.com/aws/aws-sdk-go v1.47.9/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
|
||||
github.com/aws/aws-sdk-go v1.48.3 h1:btYjT+opVFxUbRz+qSCjJe07cdX82BHmMX/FXYmoL7g=
|
||||
github.com/aws/aws-sdk-go v1.48.3/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
|
||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||
@@ -753,8 +760,8 @@ github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDD
|
||||
github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7 h1:UhxFibDNY/bfvqU5CAUmr9zpesgbU6SWc8/B4mflAE4=
|
||||
github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE=
|
||||
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
github.com/emicklei/go-restful/v3 v3.10.2 h1:hIovbnmBTLjHXkqEBUz3HGpXZdM7ZrE9fJIZIqlJLqE=
|
||||
github.com/emicklei/go-restful/v3 v3.10.2/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
|
||||
github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g=
|
||||
github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
|
||||
github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=
|
||||
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
@@ -769,8 +776,10 @@ github.com/envoyproxy/go-control-plane v0.10.3/go.mod h1:fJJn/j26vwOu972OllsvAgJ
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.6.7/go.mod h1:dyJXwwfPK2VSqiB9Klm1J6romD608Ba7Hij42vrOBCo=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.9.1/go.mod h1:OKNgG7TCp5pF4d6XftA0++PMirau2/yoOwVac3AbF2w=
|
||||
github.com/evanphx/json-patch v5.6.0+incompatible h1:jBYDEEiFBPxA0v50tFdvOzQQTCvpL6mnFh5mB2/l16U=
|
||||
github.com/evanphx/json-patch v5.6.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
|
||||
github.com/evanphx/json-patch v5.7.0+incompatible h1:vgGkfT/9f8zE6tvSCe74nfpAVDQ2tG6yudJd8LBksgI=
|
||||
github.com/evanphx/json-patch v5.7.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
|
||||
github.com/evanphx/json-patch/v5 v5.7.0 h1:nJqP7uwL84RJInrohHfW0Fx3awjbm8qZeFv0nW9SYGc=
|
||||
github.com/evanphx/json-patch/v5 v5.7.0/go.mod h1:VNkHZ/282BpEyt/tObQO8s5CMPmYYq14uClGH4abBuQ=
|
||||
github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f h1:Wl78ApPPB2Wvf/TIe2xdyJxTlb6obmF18d8QdkxNDu4=
|
||||
github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f/go.mod h1:OSYXu++VVOHnXeitef/D8n/6y4QV8uLHSFXX4NeXMGc=
|
||||
github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
|
||||
@@ -781,8 +790,8 @@ github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/
|
||||
github.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k=
|
||||
github.com/foxcpp/go-mockdns v1.0.0 h1:7jBqxd3WDWwi/6WhDvacvH1XsN3rOLXyHM1uhvIx6FI=
|
||||
github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY=
|
||||
github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
|
||||
github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
|
||||
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
|
||||
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
|
||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA=
|
||||
github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og=
|
||||
@@ -810,12 +819,15 @@ github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ=
|
||||
github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
||||
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
||||
github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE=
|
||||
github.com/go-logr/zapr v1.2.4 h1:QHVo+6stLbfJmYGkQ7uGHUCu5hnAFAj6mDe6Ea0SeOo=
|
||||
github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs=
|
||||
github.com/go-openapi/jsonpointer v0.20.0 h1:ESKJdU9ASRfaPNOPRx12IUyA1vn3R9GiE3KYD14BXdQ=
|
||||
github.com/go-openapi/jsonpointer v0.20.0/go.mod h1:6PGzBjjIIumbLYysB73Klnms1mwnU4G3YHOECG3CedA=
|
||||
github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE=
|
||||
github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k=
|
||||
github.com/go-openapi/swag v0.22.3 h1:yMBqmnQ0gyZvEb/+KzuWZOXgllrXT4SADYbvDaXHv/g=
|
||||
github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=
|
||||
github.com/go-openapi/swag v0.22.4 h1:QLMzNJnMGPRNDCbySlcj1x01tzU8/9LTTL9hZZZogBU=
|
||||
github.com/go-openapi/swag v0.22.4/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=
|
||||
github.com/go-pdf/fpdf v0.5.0/go.mod h1:HzcnA+A23uwogo0tp9yU+l3V+KXhiESpt1PMayhOh5M=
|
||||
github.com/go-pdf/fpdf v0.6.0/go.mod h1:HzcnA+A23uwogo0tp9yU+l3V+KXhiESpt1PMayhOh5M=
|
||||
github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE=
|
||||
@@ -840,6 +852,7 @@ github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4er
|
||||
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
|
||||
@@ -894,18 +907,20 @@ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
|
||||
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
|
||||
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-containerregistry v0.15.2 h1:MMkSh+tjSdnmJZO7ljvEqV1DjfekB6VUEAZgy3a+TQE=
|
||||
github.com/google/go-containerregistry v0.15.2/go.mod h1:wWK+LnOv4jXMM23IT/F1wdYftGWGr47Is8CG+pmHK1Q=
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-containerregistry v0.16.1 h1:rUEt426sR6nyrL3gt+18ibRcvYpKYdpsa5ZW7MA08dQ=
|
||||
github.com/google/go-containerregistry v0.16.1/go.mod h1:u0qB2l7mvtWVR5kNcbFIhFY1hLbf8eeGapA+vbFDCtQ=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
|
||||
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/licenseclassifier/v2 v2.0.0 h1:1Y57HHILNf4m0ABuMVb6xk4vAJYEUO0gDxNpog0pyeA=
|
||||
github.com/google/martian v2.1.0+incompatible h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPgecwXBIDzw5no=
|
||||
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
||||
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
|
||||
github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
|
||||
github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk=
|
||||
github.com/google/martian/v3 v3.3.2 h1:IqNFLAmvJOgVlpdEBiQbDc2EwKW77amAycfTuWKdfvw=
|
||||
github.com/google/martian/v3 v3.3.2/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk=
|
||||
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||
@@ -924,18 +939,22 @@ github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLe
|
||||
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20220608213341-c488b8fa1db3 h1:mpL/HvfIgIejhVwAfxBQkwEjlhP5o0O9RAeTAjpwzxc=
|
||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||
github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o=
|
||||
github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw=
|
||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4=
|
||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ=
|
||||
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4=
|
||||
github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4=
|
||||
github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.0.0-20220520183353-fd19c99a87aa/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8=
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.1.0/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8=
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.2.0/go.mod h1:8C0jb7/mgJe/9KK8Lm7X9ctZC2t60YyIpYEI16jx0Qg=
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.2.1/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k=
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.2.3/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k=
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.2 h1:Vie5ybvEvT75RniqhfFxPRy3Bf7vr3h0cechB90XaQs=
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0=
|
||||
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
|
||||
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
|
||||
github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0=
|
||||
@@ -947,6 +966,8 @@ github.com/googleapis/gax-go/v2 v2.5.1/go.mod h1:h6B0KMMFNtI2ddbGJn3T3ZbwkeT6yqE
|
||||
github.com/googleapis/gax-go/v2 v2.6.0/go.mod h1:1mjbznJAPHFpesgE5ucqfYEscaz5kMdcIDwU/6+DDoY=
|
||||
github.com/googleapis/gax-go/v2 v2.7.0/go.mod h1:TEop28CZZQ2y+c0VxMUmu1lV+fQx57QpBWsYpwqHJx8=
|
||||
github.com/googleapis/gax-go/v2 v2.7.1/go.mod h1:4orTrqY6hXxxaUL4LHIPl6lGo8vAE38/qKbhSAKP6QI=
|
||||
github.com/googleapis/gax-go/v2 v2.12.0 h1:A+gCJKdRfqXkr+BIRGtZLibNXf0m1f9E4HG56etFpas=
|
||||
github.com/googleapis/gax-go/v2 v2.12.0/go.mod h1:y+aIqrI5eb1YGMVJfuV3185Ts/D7qKpsEkdD5+I6QGU=
|
||||
github.com/googleapis/go-type-adapters v1.0.0/go.mod h1:zHW75FOG2aur7gAO2B+MLby+cLsWGBF62rFAi7WjWO4=
|
||||
github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g=
|
||||
github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4=
|
||||
@@ -970,7 +991,7 @@ github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ
|
||||
github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc=
|
||||
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
|
||||
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||
github.com/hashicorp/hcl/v2 v2.14.1 h1:x0BpjfZ+CYdbiz+8yZTQ+gdLO7IXvOut7Da+XJayx34=
|
||||
github.com/hashicorp/hcl/v2 v2.17.0 h1:z1XvSUyXd1HP10U4lrLg5e0JMVz6CPaJvAgxM0KNZVY=
|
||||
github.com/huandu/xstrings v1.3.3/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
|
||||
github.com/huandu/xstrings v1.4.0 h1:D17IlohoQq4UcpqD7fDk80P7l+lwAmlFaBHgOipl2FU=
|
||||
github.com/huandu/xstrings v1.4.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
|
||||
@@ -978,8 +999,8 @@ github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
|
||||
github.com/imdario/mergo v0.3.15 h1:M8XP7IuFNsqUx6VPK2P9OSmsYsI/YFaGil0uD21V3dM=
|
||||
github.com/imdario/mergo v0.3.15/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY=
|
||||
github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4=
|
||||
github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY=
|
||||
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
||||
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=
|
||||
@@ -1011,7 +1032,6 @@ github.com/klauspost/compress v1.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHU
|
||||
github.com/klauspost/compress v1.17.0 h1:Rnbp4K9EjcDuVuHtd0dgA4qNuv9yKDYKK1ulpJwgrqM=
|
||||
github.com/klauspost/compress v1.17.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
|
||||
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||
github.com/knqyf263/go-rpm-version v0.0.0-20220614171824-631e686d1075 h1:aC6MEAs3PE3lWD7lqrJfDxHd6hcced9R4JTZu85cJwU=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
|
||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||
@@ -1054,14 +1074,15 @@ github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Ky
|
||||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||
github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU=
|
||||
github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||
github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
|
||||
github.com/mattn/go-sqlite3 v1.14.14/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
|
||||
github.com/mattn/go-sqlite3 v1.14.15 h1:vfoHhTN1af61xCRSWzFIWzx2YskyMTwHLrExkBOjvxI=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
|
||||
github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 h1:jWpvCLoY8Z/e3VKvlsiIGKtc+UG6U5vzxaoagmhXfyg=
|
||||
github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0/go.mod h1:QUyp042oQthUoa9bqDv0ER0wrtXnBruoNd7aNjkbP+k=
|
||||
github.com/miekg/dns v1.1.50 h1:DQUfb9uc6smULcREF09Uc+/Gd46YWqJd5DbpPE9xkcA=
|
||||
github.com/minio/asm2plan9s v0.0.0-20200509001527-cdd76441f9d8/go.mod h1:mC1jAcsrzbxHt8iiaC+zU4b1ylILSosueou12R++wfY=
|
||||
github.com/minio/c2goasm v0.0.0-20190812172519-36a3d3bbc4f3/go.mod h1:RagcQ7I8IeTMnF8JTXieKnO4Z6JCsikNEzj0DwauVzE=
|
||||
@@ -1072,14 +1093,13 @@ github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa1
|
||||
github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s=
|
||||
github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0=
|
||||
github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0=
|
||||
github.com/mitchellh/hashstructure/v2 v2.0.2 h1:vGKWl0YJqUNxE8d+h8f6NJLcCJrgbhC4NcD46KavDd4=
|
||||
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
|
||||
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
|
||||
github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ=
|
||||
github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
|
||||
github.com/mittwald/go-helm-client v0.12.3 h1:WlXhuMTT5HUdiYeiYMxlvi3XBxTKoGCNHcSsirLi8ug=
|
||||
github.com/mittwald/go-helm-client v0.12.3/go.mod h1:lC1Sn912rgRkGQZBUntJO7TOlqa1kK3Idwr3yo1Tco0=
|
||||
github.com/mittwald/go-helm-client v0.12.4 h1:fHI59uny/9vxGyBfxl8qSH5RD6mRvxNm9vi55Vw+dLY=
|
||||
github.com/mittwald/go-helm-client v0.12.4/go.mod h1:Cg65orz0i3B2/Uv/7nIK4SzyhMsIS+mDpK0tbw3Cy5Q=
|
||||
github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg=
|
||||
github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc=
|
||||
github.com/moby/spdystream v0.2.0 h1:cjW1zVyyoiM0T7b6UoySUFqzXMoqRckQtXwGPiBhOM8=
|
||||
@@ -1101,15 +1121,15 @@ github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7P
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
github.com/onsi/ginkgo/v2 v2.11.0 h1:WgqUCUt/lT6yXoQ8Wef0fsNn5cAuMK7+KT9UFRz2tcU=
|
||||
github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI=
|
||||
github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
|
||||
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
|
||||
github.com/onsi/ginkgo/v2 v2.13.0 h1:0jY9lJquiL8fcf3M4LAXN5aMlS/b2BV86HFFPCPMgE4=
|
||||
github.com/onsi/gomega v1.28.1 h1:MijcGUbfYuznzK/5R4CPNoUP/9Xvuo20sXfEm6XxoTA=
|
||||
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
|
||||
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
|
||||
github.com/opencontainers/image-spec v1.1.0-rc5 h1:Ygwkfw9bpDvs+c9E34SdgGOj41dX/cbdlwvlWt0pnFI=
|
||||
github.com/opencontainers/image-spec v1.1.0-rc5/go.mod h1:X4pATf0uXsnn3g5aiGIsVnJBR4mxhKzfwmvK/B2NTm8=
|
||||
github.com/owenrumney/go-sarif/v2 v2.2.0 h1:1DmZaijK0HBZCR1fgcDSGa7VzYkU9NDmbZ7qC2QfUjE=
|
||||
github.com/owenrumney/squealer v1.1.1 h1:e+fg29IxdNARSc4s7CbYnqVSepm9eOqErLNNNR5XbAs=
|
||||
github.com/package-url/packageurl-go v0.1.1-0.20220428063043-89078438f170 h1:DiLBVp4DAcZlBVBEtJpNWZpZVq0AEeCY7Hqk8URVs4o=
|
||||
github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4=
|
||||
github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc=
|
||||
github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI=
|
||||
@@ -1142,17 +1162,17 @@ github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:
|
||||
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16 h1:v7DLqVdK4VrYkVD5diGdl4sxJurKJEMnODWRJlxV9oM=
|
||||
github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU=
|
||||
github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw=
|
||||
github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI=
|
||||
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||
github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc=
|
||||
github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY=
|
||||
github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY=
|
||||
github.com/prometheus/common v0.45.0 h1:2BGz0eBc2hdMDLnO/8n0jeB3oPrt2D08CekT0lneoxM=
|
||||
github.com/prometheus/common v0.45.0/go.mod h1:YJmSTw9BoKxJplESWWxlbyttQR4uaEcGyv9MZjVOJsY=
|
||||
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||
github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ=
|
||||
github.com/prometheus/procfs v0.11.1 h1:xRC8Iq1yyca5ypa9n1EZnWZkt7dwcoRPQwX/5gwaUuI=
|
||||
github.com/prometheus/procfs v0.11.1/go.mod h1:eesXgaPo1q7lBpVMoMy0ZOFTth9hBn4W/y0/p/ScXhY=
|
||||
github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo=
|
||||
github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo=
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis=
|
||||
@@ -1176,8 +1196,8 @@ github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6g
|
||||
github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ=
|
||||
github.com/samber/lo v1.38.1 h1:j2XEAqXKb09Am4ebOg31SpvzUTTs6EN3VfgeLUhPdXM=
|
||||
github.com/samber/lo v1.38.1/go.mod h1:+m/ZKRl6ClXCE2Lgf3MsQlWfh4bn1bz6CXEOxnEXnEA=
|
||||
github.com/sashabaranov/go-openai v1.17.5 h1:ItBzlrrfTtkFWOFlgfOhk3y/xRBC4PJol4gdbiK7hgg=
|
||||
github.com/sashabaranov/go-openai v1.17.5/go.mod h1:lj5b/K+zjTSFxVLijLSTDZuP7adOgerWeFyZLUhAKRg=
|
||||
github.com/sashabaranov/go-openai v1.17.8 h1:snuE7l0XQ1KAmkY/cODAEgxu2fl+g/ybXK6cKQzli/E=
|
||||
github.com/sashabaranov/go-openai v1.17.8/go.mod h1:lj5b/K+zjTSFxVLijLSTDZuP7adOgerWeFyZLUhAKRg=
|
||||
github.com/schollz/progressbar/v3 v3.14.1 h1:VD+MJPCr4s3wdhTc7OEJ/Z3dAeBzJ7yKH/P4lC5yRTI=
|
||||
github.com/schollz/progressbar/v3 v3.14.1/go.mod h1:Zc9xXneTzWXF81TGoqL71u0sBPjULtEHYtj/WVgVy8E=
|
||||
github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ=
|
||||
@@ -1248,7 +1268,7 @@ github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5t
|
||||
github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43 h1:+lm10QQTNSBd8DVTNGHx7o/IKu9HYDvLMffDhbyLccI=
|
||||
github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50 h1:hlE8//ciYMztlGpl/VA+Zm1AcTPHYkHJPbHqE6WJUXE=
|
||||
github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f h1:ERexzlUfuTvpE74urLSbIQW0Z/6hF9t8U4NsJLaioAY=
|
||||
github.com/zclconf/go-cty v1.10.0 h1:mp9ZXQeIcN8kAwuqorjH+Q+njbJKjLrvB2yIh4q7U+0=
|
||||
github.com/zclconf/go-cty v1.13.0 h1:It5dfKTTZHe9aeppbNOda3mN7Ag7sg6QkBNm6TkyFa0=
|
||||
github.com/zeebo/assert v1.3.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0=
|
||||
github.com/zeebo/xxh3 v1.0.2/go.mod h1:5NWz9Sef7zIDm2JHfFlcQvNekmcEl9ekUZQQKCYaDcA=
|
||||
go.etcd.io/bbolt v1.3.7 h1:j+zJOnnEjF/kyHlDDgGnVL/AIqIJPq8UoB2GSNfkUfQ=
|
||||
@@ -1303,8 +1323,8 @@ golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u0
|
||||
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
|
||||
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
|
||||
golang.org/x/exp v0.0.0-20220827204233-334a2380cb91/go.mod h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE=
|
||||
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g=
|
||||
golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k=
|
||||
golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa h1:FRnLl4eNAQl8hwxVVC17teOw8kdjVDVAiFMtgUdTSRQ=
|
||||
golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa/go.mod h1:zk2irFbV9DP96SEBUUAy67IdHUaZuSnrz1n472HUCLE=
|
||||
golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs=
|
||||
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
@@ -1346,7 +1366,7 @@ golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc=
|
||||
golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
@@ -1436,8 +1456,8 @@ golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783/go.mod h1:h4gKUeWbJ4rQPri
|
||||
golang.org/x/oauth2 v0.4.0/go.mod h1:RznEsdpjGAINPTOF0UH/t+xJ75L18YO3Ho6Pyn+uRec=
|
||||
golang.org/x/oauth2 v0.5.0/go.mod h1:9/XBHVqLaWO3/BRHs5jbpYCnOZVjj5V0ndyaAM7KB4I=
|
||||
golang.org/x/oauth2 v0.6.0/go.mod h1:ycmewcwgD4Rpr3eZJLSB4Kyyljb3qDh40vJ8STE5HKw=
|
||||
golang.org/x/oauth2 v0.12.0 h1:smVPGxink+n1ZI5pkQa8y6fZT0RW0MgCO5bFpepy4B4=
|
||||
golang.org/x/oauth2 v0.12.0/go.mod h1:A74bZ3aGXgCY0qaIC9Ahg6Lglin4AMAco8cIv9baba4=
|
||||
golang.org/x/oauth2 v0.13.0 h1:jDDenyj+WgFtmV3zYVoi8aE2BwtXFLWOA67ZfNWftiY=
|
||||
golang.org/x/oauth2 v0.13.0/go.mod h1:/JMhi4ZRXAf4HG9LiNmxvk+45+96RUlVThiH8FzNBn0=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
@@ -1454,8 +1474,8 @@ golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJ
|
||||
golang.org/x/sync v0.0.0-20220819030929-7fc1605a5dde/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220929204114-8fcdb60fdcc0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
|
||||
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
|
||||
golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE=
|
||||
golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
@@ -1533,7 +1553,6 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220829200755-d48e67d00261/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
@@ -1635,7 +1654,7 @@ golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.3.0/go.mod h1:/rWhSS2+zyEVwoJf8YAX6L2f0ntZ7Kn/mGgAWcipA5k=
|
||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||
golang.org/x/tools v0.13.0 h1:Iey4qkscZuv0VvIt8E0neZjtPVQFSc870HQ448QgEmQ=
|
||||
golang.org/x/tools v0.15.0 h1:zdAyfUGbYmuVokhzVmghFl2ZJh5QhcfebBgmVPFYA+8=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
@@ -1645,6 +1664,7 @@ golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNq
|
||||
golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8=
|
||||
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk=
|
||||
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8=
|
||||
gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw=
|
||||
gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo=
|
||||
gonum.org/v1/gonum v0.8.2/go.mod h1:oe/vMfY3deqTw+1EZJhuvEW2iwGF1bW9wwu7XCu0+v0=
|
||||
gonum.org/v1/gonum v0.9.3/go.mod h1:TZumC3NeyVQskjXqmyWt4S3bINhy7B4eYwW69EbyX+0=
|
||||
@@ -1710,14 +1730,17 @@ google.golang.org/api v0.108.0/go.mod h1:2Ts0XTHNVWxypznxWOYUeI4g3WdP9Pk2Qk58+a/
|
||||
google.golang.org/api v0.110.0/go.mod h1:7FC4Vvx1Mooxh8C5HWjzZHcavuS2f6pmJpZx60ca7iI=
|
||||
google.golang.org/api v0.111.0/go.mod h1:qtFHvU9mhgTJegR31csQ+rwxyUTHOKFqCKWp1J0fdw0=
|
||||
google.golang.org/api v0.114.0/go.mod h1:ifYI2ZsFK6/uGddGfAD5BMxlnkBqCmqHSDUVi45N5Yg=
|
||||
google.golang.org/api v0.151.0 h1:FhfXLO/NFdJIzQtCqjpysWwqKk8AzGWBUhMIx67cVDU=
|
||||
google.golang.org/api v0.151.0/go.mod h1:ccy+MJ6nrYFgE3WgRx/AMXOxOmU8Q4hSa+jjibzhxcg=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
|
||||
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||
google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||
google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
|
||||
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||
google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM=
|
||||
google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds=
|
||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
@@ -1851,12 +1874,16 @@ google.golang.org/genproto v0.0.0-20230330154414-c0448cd141ea/go.mod h1:UUQDJDOl
|
||||
google.golang.org/genproto v0.0.0-20230331144136-dcfb400f0633/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak=
|
||||
google.golang.org/genproto v0.0.0-20230525234025-438c736192d0/go.mod h1:9ExIQyXL5hZrHzQceCwuSYwZZ5QZBazOcprJ5rgs3lY=
|
||||
google.golang.org/genproto v0.0.0-20230526161137-0005af68ea54/go.mod h1:zqTuNwFlFRsw5zIts5VnzLQxSRqh+CGOTVMlYbY0Eyk=
|
||||
google.golang.org/genproto v0.0.0-20231016165738-49dd2c1f3d0b h1:+YaDE2r2OG8t/z5qmsh7Y+XXwCbvadxxZ0YY6mTdrVA=
|
||||
google.golang.org/genproto v0.0.0-20231016165738-49dd2c1f3d0b/go.mod h1:CgAqfJo+Xmu0GwA0411Ht3OU3OntXwsGmrmjI8ioGXI=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20230525234020-1aefcd67740a/go.mod h1:ts19tUU+Z0ZShN1y3aPyq2+O3d5FUNNgT6FtOzmrNn8=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20230525234035-dd9d682886f9/go.mod h1:vHYtlOoi6TsQ3Uk2yxR7NI5z8uoV+3pZtR4jmHIkRig=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20231016165738-49dd2c1f3d0b h1:CIC2YMXmIhYw6evmhPxBKJ4fmLbOFtXQN/GV3XOZR8k=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20231016165738-49dd2c1f3d0b/go.mod h1:IBQ646DjkDkvUIsVq/cc03FUFQ9wbZu7yE396YcL870=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234015-3fc162c6f38a/go.mod h1:xURIpW9ES5+/GZhnV6beoEtxQrnkRGIfP5VQG2tCBLc=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234030-28d5490b6b19/go.mod h1:66JfowdXAEgad5O9NnYcsNPLCPZJD++2L9X0PCMODrA=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20230920204549-e6e6cdab5c13 h1:N3bU/SQDCDyD6R528GJ/PwW9KjYcJA3dgyH+MovAkIM=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20230920204549-e6e6cdab5c13/go.mod h1:KSqppvjFjtoCI+KGd4PELB0qLNxdJHRGqRI09mB6pQA=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20231030173426-d783a09b4405 h1:AB/lmRny7e2pLhFEYIbl5qkDAUt2h0ZRO4wGPhZf+ik=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20231030173426-d783a09b4405/go.mod h1:67X1fPuzjcrkymZzZV1vvkFeTn2Rvc6lYF9MYFGCcwE=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
||||
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
||||
@@ -1940,7 +1967,6 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=
|
||||
gotest.tools/v3 v3.4.0 h1:ZazjZUfuVeZGLAmlKKuyv3IKP5orXcwtOwDQH6YVr6o=
|
||||
helm.sh/helm/v3 v3.13.2 h1:IcO9NgmmpetJODLZhR3f3q+6zzyXVKlRizKFwbi7K8w=
|
||||
helm.sh/helm/v3 v3.13.2/go.mod h1:GIHDwZggaTGbedevTlrQ6DB++LBN6yuQdeGj0HNaDx0=
|
||||
@@ -1952,28 +1978,28 @@ honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt
|
||||
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||
honnef.co/go/tools v0.1.3/go.mod h1:NgwopIslSNH47DimFoV78dnkksY2EFtX0ajyb3K/las=
|
||||
k8s.io/api v0.28.3 h1:Gj1HtbSdB4P08C8rs9AR94MfSGpRhJgsS+GF9V26xMM=
|
||||
k8s.io/api v0.28.3/go.mod h1:MRCV/jr1dW87/qJnZ57U5Pak65LGmQVkKTzf3AtKFHc=
|
||||
k8s.io/apiextensions-apiserver v0.28.2 h1:J6/QRWIKV2/HwBhHRVITMLYoypCoPY1ftigDM0Kn+QU=
|
||||
k8s.io/apiextensions-apiserver v0.28.2/go.mod h1:5tnkxLGa9nefefYzWuAlWZ7RZYuN/765Au8cWLA6SRg=
|
||||
k8s.io/apimachinery v0.28.3 h1:B1wYx8txOaCQG0HmYF6nbpU8dg6HvA06x5tEffvOe7A=
|
||||
k8s.io/apimachinery v0.28.3/go.mod h1:uQTKmIqs+rAYaq+DFaoD2X7pcjLOqbQX2AOiO0nIpb8=
|
||||
k8s.io/apiserver v0.28.2 h1:rBeYkLvF94Nku9XfXyUIirsVzCzJBs6jMn3NWeHieyI=
|
||||
k8s.io/apiserver v0.28.2/go.mod h1:f7D5e8wH8MWcKD7azq6Csw9UN+CjdtXIVQUyUhrtb+E=
|
||||
k8s.io/cli-runtime v0.28.3 h1:lvuJYVkwCqHEvpS6KuTZsUVwPePFjBfSGvuaLl2SxzA=
|
||||
k8s.io/cli-runtime v0.28.3/go.mod h1:jeX37ZPjIcENVuXDDTskG3+FnVuZms5D9omDXS/2Jjc=
|
||||
k8s.io/client-go v0.28.3 h1:2OqNb72ZuTZPKCl+4gTKvqao0AMOl9f3o2ijbAj3LI4=
|
||||
k8s.io/client-go v0.28.3/go.mod h1:LTykbBp9gsA7SwqirlCXBWtK0guzfhpoW4qSm7i9dxo=
|
||||
k8s.io/component-base v0.28.3 h1:rDy68eHKxq/80RiMb2Ld/tbH8uAE75JdCqJyi6lXMzI=
|
||||
k8s.io/component-base v0.28.3/go.mod h1:fDJ6vpVNSk6cRo5wmDa6eKIG7UlIQkaFmZN2fYgIUD8=
|
||||
k8s.io/api v0.28.4 h1:8ZBrLjwosLl/NYgv1P7EQLqoO8MGQApnbgH8tu3BMzY=
|
||||
k8s.io/api v0.28.4/go.mod h1:axWTGrY88s/5YE+JSt4uUi6NMM+gur1en2REMR7IRj0=
|
||||
k8s.io/apiextensions-apiserver v0.28.3 h1:Od7DEnhXHnHPZG+W9I97/fSQkVpVPQx2diy+2EtmY08=
|
||||
k8s.io/apiextensions-apiserver v0.28.3/go.mod h1:NE1XJZ4On0hS11aWWJUTNkmVB03j9LM7gJSisbRt8Lc=
|
||||
k8s.io/apimachinery v0.28.4 h1:zOSJe1mc+GxuMnFzD4Z/U1wst50X28ZNsn5bhgIIao8=
|
||||
k8s.io/apimachinery v0.28.4/go.mod h1:wI37ncBvfAoswfq626yPTe6Bz1c22L7uaJ8dho83mgg=
|
||||
k8s.io/apiserver v0.28.3 h1:8Ov47O1cMyeDzTXz0rwcfIIGAP/dP7L8rWbEljRcg5w=
|
||||
k8s.io/apiserver v0.28.3/go.mod h1:YIpM+9wngNAv8Ctt0rHG4vQuX/I5rvkEMtZtsxW2rNM=
|
||||
k8s.io/cli-runtime v0.28.4 h1:IW3aqSNFXiGDllJF4KVYM90YX4cXPGxuCxCVqCD8X+Q=
|
||||
k8s.io/cli-runtime v0.28.4/go.mod h1:MLGRB7LWTIYyYR3d/DOgtUC8ihsAPA3P8K8FDNIqJ0k=
|
||||
k8s.io/client-go v0.28.4 h1:Np5ocjlZcTrkyRJ3+T3PkXDpe4UpatQxj85+xjaD2wY=
|
||||
k8s.io/client-go v0.28.4/go.mod h1:0VDZFpgoZfelyP5Wqu0/r/TRYcLYuJ2U1KEeoaPa1N4=
|
||||
k8s.io/component-base v0.28.4 h1:c/iQLWPdUgI90O+T9TeECg8o7N3YJTiuz2sKxILYcYo=
|
||||
k8s.io/component-base v0.28.4/go.mod h1:m9hR0uvqXDybiGL2nf/3Lf0MerAfQXzkfWhUY58JUbU=
|
||||
k8s.io/klog/v2 v2.100.1 h1:7WCHKK6K8fNhTqfBhISHQ97KrnJNFZMcQvKp7gP/tmg=
|
||||
k8s.io/klog/v2 v2.100.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0=
|
||||
k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9 h1:LyMgNKD2P8Wn1iAwQU5OhxCKlKJy0sHc+PcDwFB24dQ=
|
||||
k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9/go.mod h1:wZK2AVp1uHCp4VamDVgBP2COHZjqD1T68Rf0CM3YjSM=
|
||||
k8s.io/kubectl v0.28.3 h1:H1Peu1O3EbN9zHkJCcvhiJ4NUj6lb88sGPO5wrWIM6k=
|
||||
k8s.io/kubectl v0.28.3/go.mod h1:RDAudrth/2wQ3Sg46fbKKl4/g+XImzvbsSRZdP2RiyE=
|
||||
k8s.io/utils v0.0.0-20230406110748-d93618cff8a2 h1:qY1Ad8PODbnymg2pRbkyMT/ylpTrCM8P2RJ0yroCyIk=
|
||||
k8s.io/utils v0.0.0-20230406110748-d93618cff8a2/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
|
||||
k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 h1:aVUu9fTY98ivBPKR9Y5w/AuzbMm96cd3YHRTU83I780=
|
||||
k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00/go.mod h1:AsvuZPBlUDVuCdzJ87iajxtXuR9oktsTctW/R9wwouA=
|
||||
k8s.io/kubectl v0.28.4 h1:gWpUXW/T7aFne+rchYeHkyB8eVDl5UZce8G4X//kjUQ=
|
||||
k8s.io/kubectl v0.28.4/go.mod h1:CKOccVx3l+3MmDbkXtIUtibq93nN2hkDR99XDCn7c/c=
|
||||
k8s.io/utils v0.0.0-20230726121419-3b25d923346b h1:sgn3ZU783SCgtaSJjpcVVlRqd6GSnlTLKgpAAttJvpI=
|
||||
k8s.io/utils v0.0.0-20230726121419-3b25d923346b/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
|
||||
lukechampine.com/uint128 v1.1.1/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk=
|
||||
lukechampine.com/uint128 v1.2.0/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk=
|
||||
modernc.org/cc/v3 v3.36.0/go.mod h1:NFUHyPn4ekoC/JHeZFfZurN6ixxawE1BnVonP/oahEI=
|
||||
@@ -2014,13 +2040,18 @@ rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8
|
||||
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
|
||||
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
|
||||
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
|
||||
sigs.k8s.io/controller-runtime v0.16.3 h1:2TuvuokmfXvDUamSx1SuAOO3eTyye+47mJCigwG62c4=
|
||||
sigs.k8s.io/controller-runtime v0.16.3/go.mod h1:j7bialYoSn142nv9sCOJmQgDXQXxnroFU4VnX/brVJ0=
|
||||
sigs.k8s.io/gateway-api v1.0.0 h1:iPTStSv41+d9p0xFydll6d7f7MOBGuqXM6p2/zVYMAs=
|
||||
sigs.k8s.io/gateway-api v1.0.0/go.mod h1:4cUgr0Lnp5FZ0Cdq8FdRwCvpiWws7LVhLHGIudLlf4c=
|
||||
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo=
|
||||
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0=
|
||||
sigs.k8s.io/kustomize/api v0.13.5-0.20230601165947-6ce0bf390ce3 h1:XX3Ajgzov2RKUdc5jW3t5jwY7Bo7dcRm+tFxT+NfgY0=
|
||||
sigs.k8s.io/kustomize/api v0.13.5-0.20230601165947-6ce0bf390ce3/go.mod h1:9n16EZKMhXBNSiUC5kSdFQJkdH3zbxS/JoO619G1VAY=
|
||||
sigs.k8s.io/kustomize/kyaml v0.14.3-0.20230601165947-6ce0bf390ce3 h1:W6cLQc5pnqM7vh3b7HvGNfXrJ/xL6BDMS0v1V/HHg5U=
|
||||
sigs.k8s.io/kustomize/kyaml v0.14.3-0.20230601165947-6ce0bf390ce3/go.mod h1:JWP1Fj0VWGHyw3YUPjXSQnRnrwezrZSrApfX5S0nIag=
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.2.3 h1:PRbqxJClWWYMNV1dhaG4NsibJbArud9kFxnAMREiWFE=
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.2.3/go.mod h1:qjx8mGObPmV2aSZepjQjbmb2ihdVs8cGKBraizNC69E=
|
||||
sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo=
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.3.0 h1:UZbZAZfX0wV2zr7YZorDz6GXROfDFj6LvqCRm4VUVKk=
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.3.0/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08=
|
||||
sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8=
|
||||
sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E=
|
||||
sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=
|
||||
|
||||
@@ -115,18 +115,22 @@ func NewAnalysis(backend string, language string, filters []string, namespace st
|
||||
}
|
||||
|
||||
// load remote cache if it is configured
|
||||
remoteCacheEnabled, err := cache.RemoteCacheEnabled()
|
||||
cache, err := cache.GetCacheConfiguration()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if noCache {
|
||||
cache.DisableCache()
|
||||
}
|
||||
|
||||
return &Analysis{
|
||||
Context: ctx,
|
||||
Filters: filters,
|
||||
Client: client,
|
||||
AIClient: aiClient,
|
||||
Namespace: namespace,
|
||||
Cache: cache.New(noCache, remoteCacheEnabled),
|
||||
Cache: cache,
|
||||
Explain: explain,
|
||||
MaxConcurrency: maxConcurrency,
|
||||
AnalysisAIProvider: backend,
|
||||
|
||||
@@ -50,6 +50,9 @@ var additionalAnalyzerMap = map[string]common.IAnalyzer{
|
||||
"PodDisruptionBudget": PdbAnalyzer{},
|
||||
"NetworkPolicy": NetworkPolicyAnalyzer{},
|
||||
"Log": LogAnalyzer{},
|
||||
"GatewayClass": GatewayClassAnalyzer{},
|
||||
"Gateway": GatewayAnalyzer{},
|
||||
"HTTPRoute": HTTPRouteAnalyzer{},
|
||||
}
|
||||
|
||||
func ListFilters() ([]string, []string, []string) {
|
||||
|
||||
108
pkg/analyzer/gateway.go
Normal file
108
pkg/analyzer/gateway.go
Normal file
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
Copyright 2023 The K8sGPT Authors.
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package analyzer
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/k8sgpt-ai/k8sgpt/pkg/common"
|
||||
"github.com/k8sgpt-ai/k8sgpt/pkg/util"
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
ctrl "sigs.k8s.io/controller-runtime/pkg/client"
|
||||
gtwapi "sigs.k8s.io/gateway-api/apis/v1"
|
||||
)
|
||||
|
||||
type GatewayAnalyzer struct{}
|
||||
|
||||
// Gateway analyser will analyse all different Kinds and search for missing object dependencies
|
||||
func (GatewayAnalyzer) Analyze(a common.Analyzer) ([]common.Result, error) {
|
||||
|
||||
kind := "Gateway"
|
||||
AnalyzerErrorsMetric.DeletePartialMatch(map[string]string{
|
||||
"analyzer_name": kind,
|
||||
})
|
||||
|
||||
gtwList := >wapi.GatewayList{}
|
||||
gc := >wapi.GatewayClass{}
|
||||
client := a.Client.CtrlClient
|
||||
gtwapi.AddToScheme(client.Scheme())
|
||||
if err := client.List(a.Context, gtwList, &ctrl.ListOptions{}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var preAnalysis = map[string]common.PreAnalysis{}
|
||||
// Find all unhealthy gateway Classes
|
||||
|
||||
for _, gtw := range gtwList.Items {
|
||||
var failures []common.Failure
|
||||
|
||||
gtwName := gtw.GetName()
|
||||
gtwNamespace := gtw.GetNamespace()
|
||||
// Check if gatewayclass exists
|
||||
err := client.Get(a.Context, ctrl.ObjectKey{Namespace: gtwNamespace, Name: string(gtw.Spec.GatewayClassName)}, gc, &ctrl.GetOptions{})
|
||||
if errors.IsNotFound(err) {
|
||||
failures = append(failures, common.Failure{
|
||||
Text: fmt.Sprintf(
|
||||
"Gateway uses the GatewayClass %s which does not exist.",
|
||||
gtw.Spec.GatewayClassName,
|
||||
),
|
||||
Sensitive: []common.Sensitive{
|
||||
{
|
||||
Unmasked: string(gtw.Spec.GatewayClassName),
|
||||
Masked: util.MaskString(string(gtw.Spec.GatewayClassName)),
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// Check only the current conditions
|
||||
// TODO: maybe check other statuses Listeners, addresses?
|
||||
if gtw.Status.Conditions[0].Status != metav1.ConditionTrue {
|
||||
failures = append(failures, common.Failure{
|
||||
Text: fmt.Sprintf("Gateway '%s/%s' is not accepted. Message: '%s'.",
|
||||
gtwNamespace,
|
||||
gtwName,
|
||||
gtw.Status.Conditions[0].Message,
|
||||
),
|
||||
Sensitive: []common.Sensitive{
|
||||
{
|
||||
Unmasked: gtwNamespace,
|
||||
Masked: util.MaskString(gtwNamespace),
|
||||
},
|
||||
{
|
||||
Unmasked: gtwName,
|
||||
Masked: util.MaskString(gtwName),
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
if len(failures) > 0 {
|
||||
preAnalysis[fmt.Sprintf("%s/%s", gtwNamespace, gtwName)] = common.PreAnalysis{
|
||||
Gateway: gtw,
|
||||
FailureDetails: failures,
|
||||
}
|
||||
AnalyzerErrorsMetric.WithLabelValues(kind, gtwName, gtwNamespace).Set(float64(len(failures)))
|
||||
}
|
||||
}
|
||||
for key, value := range preAnalysis {
|
||||
var currentAnalysis = common.Result{
|
||||
Kind: kind,
|
||||
Name: key,
|
||||
Error: value.FailureDetails,
|
||||
}
|
||||
a.Results = append(a.Results, currentAnalysis)
|
||||
}
|
||||
return a.Results, nil
|
||||
}
|
||||
161
pkg/analyzer/gateway_test.go
Normal file
161
pkg/analyzer/gateway_test.go
Normal file
@@ -0,0 +1,161 @@
|
||||
package analyzer
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/k8sgpt-ai/k8sgpt/pkg/common"
|
||||
"github.com/k8sgpt-ai/k8sgpt/pkg/kubernetes"
|
||||
"github.com/magiconair/properties/assert"
|
||||
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/client-go/kubernetes/scheme"
|
||||
fakeclient "sigs.k8s.io/controller-runtime/pkg/client/fake"
|
||||
gtwapi "sigs.k8s.io/gateway-api/apis/v1"
|
||||
)
|
||||
|
||||
func BuildGatewayClass(name string) gtwapi.GatewayClass {
|
||||
GatewayClass := gtwapi.GatewayClass{}
|
||||
GatewayClass.Name = name
|
||||
// Namespace is not needed outside of this test, GatewayClass is cluster-scoped
|
||||
GatewayClass.Namespace = "default"
|
||||
GatewayClass.Spec.ControllerName = "gateway.fooproxy.io/gatewayclass-controller"
|
||||
|
||||
return GatewayClass
|
||||
}
|
||||
|
||||
func BuildGateway(className gtwapi.ObjectName, status metav1.ConditionStatus) gtwapi.Gateway {
|
||||
Gateway := gtwapi.Gateway{}
|
||||
Gateway.Name = "foobar"
|
||||
Gateway.Namespace = "default"
|
||||
Gateway.Spec.GatewayClassName = className
|
||||
Gateway.Spec.Listeners = []gtwapi.Listener{
|
||||
{
|
||||
Name: "proxy",
|
||||
Port: 80,
|
||||
Protocol: gtwapi.HTTPProtocolType,
|
||||
},
|
||||
}
|
||||
Condition := metav1.Condition{
|
||||
Type: "Accepted",
|
||||
Status: status,
|
||||
Message: "An expected message",
|
||||
Reason: "Test",
|
||||
}
|
||||
Gateway.Status.Conditions = []metav1.Condition{Condition}
|
||||
|
||||
return Gateway
|
||||
}
|
||||
|
||||
func TestGatewayAnalyzer(t *testing.T) {
|
||||
ClassName := gtwapi.ObjectName("exists")
|
||||
AcceptedStatus := metav1.ConditionTrue
|
||||
GatewayClass := BuildGatewayClass(string(ClassName))
|
||||
|
||||
Gateway := BuildGateway(ClassName, AcceptedStatus)
|
||||
// Create a Gateway Analyzer instance with the fake client
|
||||
scheme := scheme.Scheme
|
||||
gtwapi.Install(scheme)
|
||||
apiextensionsv1.AddToScheme(scheme)
|
||||
objects := []runtime.Object{
|
||||
&Gateway,
|
||||
&GatewayClass,
|
||||
}
|
||||
|
||||
fakeClient := fakeclient.NewClientBuilder().WithScheme(scheme).WithRuntimeObjects(objects...).Build()
|
||||
|
||||
analyzerInstance := GatewayAnalyzer{}
|
||||
config := common.Analyzer{
|
||||
Client: &kubernetes.Client{
|
||||
CtrlClient: fakeClient,
|
||||
},
|
||||
Context: context.Background(),
|
||||
Namespace: "default",
|
||||
}
|
||||
analysisResults, err := analyzerInstance.Analyze(config)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
assert.Equal(t, len(analysisResults), 0)
|
||||
|
||||
}
|
||||
|
||||
func TestMissingClassGatewayAnalyzer(t *testing.T) {
|
||||
ClassName := gtwapi.ObjectName("non-existed")
|
||||
AcceptedStatus := metav1.ConditionTrue
|
||||
Gateway := BuildGateway(ClassName, AcceptedStatus)
|
||||
|
||||
// Create a Gateway Analyzer instance with the fake client
|
||||
scheme := scheme.Scheme
|
||||
gtwapi.Install(scheme)
|
||||
apiextensionsv1.AddToScheme(scheme)
|
||||
objects := []runtime.Object{
|
||||
&Gateway,
|
||||
}
|
||||
|
||||
fakeClient := fakeclient.NewClientBuilder().WithScheme(scheme).WithRuntimeObjects(objects...).Build()
|
||||
|
||||
analyzerInstance := GatewayAnalyzer{}
|
||||
config := common.Analyzer{
|
||||
Client: &kubernetes.Client{
|
||||
CtrlClient: fakeClient,
|
||||
},
|
||||
Context: context.Background(),
|
||||
Namespace: "default",
|
||||
}
|
||||
analysisResults, err := analyzerInstance.Analyze(config)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
assert.Equal(t, len(analysisResults), 1)
|
||||
|
||||
}
|
||||
|
||||
func TestStatusGatewayAnalyzer(t *testing.T) {
|
||||
ClassName := gtwapi.ObjectName("exists")
|
||||
AcceptedStatus := metav1.ConditionUnknown
|
||||
GatewayClass := BuildGatewayClass(string(ClassName))
|
||||
|
||||
Gateway := BuildGateway(ClassName, AcceptedStatus)
|
||||
|
||||
// Create a Gateway Analyzer instance with the fake client
|
||||
scheme := scheme.Scheme
|
||||
gtwapi.Install(scheme)
|
||||
apiextensionsv1.AddToScheme(scheme)
|
||||
objects := []runtime.Object{
|
||||
&Gateway,
|
||||
&GatewayClass,
|
||||
}
|
||||
|
||||
fakeClient := fakeclient.NewClientBuilder().WithScheme(scheme).WithRuntimeObjects(objects...).Build()
|
||||
|
||||
analyzerInstance := GatewayAnalyzer{}
|
||||
config := common.Analyzer{
|
||||
Client: &kubernetes.Client{
|
||||
CtrlClient: fakeClient,
|
||||
},
|
||||
Context: context.Background(),
|
||||
Namespace: "default",
|
||||
}
|
||||
analysisResults, err := analyzerInstance.Analyze(config)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
var errorFound bool
|
||||
want := "Gateway 'default/foobar' is not accepted. Message: 'An expected message'."
|
||||
for _, analysis := range analysisResults {
|
||||
for _, got := range analysis.Error {
|
||||
if want == got.Text {
|
||||
errorFound = true
|
||||
}
|
||||
}
|
||||
if errorFound {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !errorFound {
|
||||
t.Errorf("Expected message, <%v> , not found in Gateway's analysis results", want)
|
||||
}
|
||||
}
|
||||
84
pkg/analyzer/gatewayclass.go
Normal file
84
pkg/analyzer/gatewayclass.go
Normal file
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
Copyright 2023 The K8sGPT Authors.
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package analyzer
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/k8sgpt-ai/k8sgpt/pkg/common"
|
||||
"github.com/k8sgpt-ai/k8sgpt/pkg/util"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
ctrl "sigs.k8s.io/controller-runtime/pkg/client"
|
||||
gtwapi "sigs.k8s.io/gateway-api/apis/v1"
|
||||
)
|
||||
|
||||
type GatewayClassAnalyzer struct{}
|
||||
|
||||
// Gateway analyser will analyse all different Kinds and search for missing object dependencies
|
||||
func (GatewayClassAnalyzer) Analyze(a common.Analyzer) ([]common.Result, error) {
|
||||
|
||||
kind := "GatewayClass"
|
||||
AnalyzerErrorsMetric.DeletePartialMatch(map[string]string{
|
||||
"analyzer_name": kind,
|
||||
})
|
||||
|
||||
gcList := >wapi.GatewayClassList{}
|
||||
client := a.Client.CtrlClient
|
||||
gtwapi.AddToScheme(client.Scheme())
|
||||
if err := client.List(a.Context, gcList, &ctrl.ListOptions{}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var preAnalysis = map[string]common.PreAnalysis{}
|
||||
|
||||
// Find all unhealthy gateway Classes
|
||||
|
||||
for _, gc := range gcList.Items {
|
||||
var failures []common.Failure
|
||||
|
||||
gcName := gc.GetName()
|
||||
// Check only the current condition
|
||||
if gc.Status.Conditions[0].Status != metav1.ConditionTrue {
|
||||
failures = append(failures, common.Failure{
|
||||
Text: fmt.Sprintf(
|
||||
"GatewayClass '%s' with a controller name '%s' is not accepted. Message: '%s'.",
|
||||
gcName,
|
||||
gc.Spec.ControllerName,
|
||||
gc.Status.Conditions[0].Message,
|
||||
),
|
||||
Sensitive: []common.Sensitive{
|
||||
{
|
||||
Unmasked: gcName,
|
||||
Masked: util.MaskString(gcName),
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
if len(failures) > 0 {
|
||||
preAnalysis[gcName] = common.PreAnalysis{
|
||||
GatewayClass: gc,
|
||||
FailureDetails: failures,
|
||||
}
|
||||
AnalyzerErrorsMetric.WithLabelValues(kind, gcName, "").Set(float64(len(failures)))
|
||||
}
|
||||
}
|
||||
for key, value := range preAnalysis {
|
||||
var currentAnalysis = common.Result{
|
||||
Kind: kind,
|
||||
Name: key,
|
||||
Error: value.FailureDetails,
|
||||
}
|
||||
a.Results = append(a.Results, currentAnalysis)
|
||||
}
|
||||
return a.Results, nil
|
||||
}
|
||||
51
pkg/analyzer/gatewayclass_test.go
Normal file
51
pkg/analyzer/gatewayclass_test.go
Normal file
@@ -0,0 +1,51 @@
|
||||
package analyzer
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/k8sgpt-ai/k8sgpt/pkg/common"
|
||||
"github.com/k8sgpt-ai/k8sgpt/pkg/kubernetes"
|
||||
"github.com/stretchr/testify/assert"
|
||||
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/client-go/kubernetes/scheme"
|
||||
fakeclient "sigs.k8s.io/controller-runtime/pkg/client/fake"
|
||||
gtwapi "sigs.k8s.io/gateway-api/apis/v1"
|
||||
)
|
||||
|
||||
// Testing with the fake dynamic client if GatewayClasses have an accepted status
|
||||
func TestGatewayClassAnalyzer(t *testing.T) {
|
||||
GatewayClass := >wapi.GatewayClass{}
|
||||
GatewayClass.Name = "foobar"
|
||||
GatewayClass.Spec.ControllerName = "gateway.fooproxy.io/gatewayclass-controller"
|
||||
// Initialize Conditions slice before setting properties
|
||||
BadCondition := metav1.Condition{
|
||||
Type: "Accepted",
|
||||
Status: "Uknown",
|
||||
Message: "Waiting for controller",
|
||||
Reason: "Pending",
|
||||
}
|
||||
GatewayClass.Status.Conditions = []metav1.Condition{BadCondition}
|
||||
// Create a GatewayClassAnalyzer instance with the fake client
|
||||
scheme := scheme.Scheme
|
||||
gtwapi.Install(scheme)
|
||||
apiextensionsv1.AddToScheme(scheme)
|
||||
|
||||
fakeClient := fakeclient.NewClientBuilder().WithScheme(scheme).WithRuntimeObjects(GatewayClass).Build()
|
||||
|
||||
analyzerInstance := GatewayClassAnalyzer{}
|
||||
config := common.Analyzer{
|
||||
Client: &kubernetes.Client{
|
||||
CtrlClient: fakeClient,
|
||||
},
|
||||
Context: context.Background(),
|
||||
Namespace: "default",
|
||||
}
|
||||
analysisResults, err := analyzerInstance.Analyze(config)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
assert.Equal(t, len(analysisResults), 1)
|
||||
|
||||
}
|
||||
228
pkg/analyzer/httroute.go
Normal file
228
pkg/analyzer/httroute.go
Normal file
@@ -0,0 +1,228 @@
|
||||
/*
|
||||
Copyright 2023 The K8sGPT Authors.
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package analyzer
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/k8sgpt-ai/k8sgpt/pkg/common"
|
||||
"github.com/k8sgpt-ai/k8sgpt/pkg/util"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
ctrl "sigs.k8s.io/controller-runtime/pkg/client"
|
||||
gtwapi "sigs.k8s.io/gateway-api/apis/v1"
|
||||
)
|
||||
|
||||
type HTTPRouteAnalyzer struct{}
|
||||
|
||||
// Gateway analyser will analyse all different Kinds and search for missing object dependencies
|
||||
func (HTTPRouteAnalyzer) Analyze(a common.Analyzer) ([]common.Result, error) {
|
||||
|
||||
kind := "HTTPRoute"
|
||||
AnalyzerErrorsMetric.DeletePartialMatch(map[string]string{
|
||||
"analyzer_name": kind,
|
||||
})
|
||||
|
||||
routeList := >wapi.HTTPRouteList{}
|
||||
gtw := >wapi.Gateway{}
|
||||
service := &corev1.Service{}
|
||||
client := a.Client.CtrlClient
|
||||
gtwapi.AddToScheme(client.Scheme())
|
||||
if err := client.List(a.Context, routeList, &ctrl.ListOptions{}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var preAnalysis = map[string]common.PreAnalysis{}
|
||||
|
||||
// Find all unhealthy gateway Classes
|
||||
|
||||
for _, route := range routeList.Items {
|
||||
var failures []common.Failure
|
||||
|
||||
// Check if Gateways exists in the same or designated namespace
|
||||
// TODO: when meshes and ClusterIp options are adopted we can add more checks
|
||||
// e.g Service Port matching
|
||||
for _, gtwref := range route.Spec.ParentRefs {
|
||||
namespace := route.Namespace
|
||||
if gtwref.Namespace != nil {
|
||||
namespace = string(*gtwref.Namespace)
|
||||
}
|
||||
err := client.Get(a.Context, ctrl.ObjectKey{Namespace: namespace, Name: string(gtwref.Name)}, gtw, &ctrl.GetOptions{})
|
||||
if errors.IsNotFound(err) {
|
||||
failures = append(failures, common.Failure{
|
||||
Text: fmt.Sprintf(
|
||||
"HTTPRoute uses the Gateway '%s/%s' which does not exist in the same namespace.",
|
||||
namespace,
|
||||
gtwref.Name,
|
||||
),
|
||||
Sensitive: []common.Sensitive{
|
||||
{
|
||||
Unmasked: gtw.Namespace,
|
||||
Masked: util.MaskString(gtw.Namespace),
|
||||
},
|
||||
{
|
||||
Unmasked: gtw.Name,
|
||||
Masked: util.MaskString(gtw.Name),
|
||||
},
|
||||
},
|
||||
})
|
||||
} else {
|
||||
// Check if the aforementioned Gateway allows the HTTPRoutes from the route's namespace
|
||||
for _, listener := range gtw.Spec.Listeners {
|
||||
if listener.AllowedRoutes.Namespaces != nil {
|
||||
switch allow := listener.AllowedRoutes.Namespaces.From; {
|
||||
case *allow == gtwapi.NamespacesFromSame:
|
||||
// check if Gateway is in the same namespace
|
||||
if route.Namespace != gtw.Namespace {
|
||||
failures = append(failures, common.Failure{
|
||||
Text: fmt.Sprintf("HTTPRoute '%s/%s' is deployed in a different namespace from Gateway '%s/%s' which only allows HTTPRoutes from its namespace.",
|
||||
route.Namespace,
|
||||
route.Name,
|
||||
gtw.Namespace,
|
||||
gtw.Name,
|
||||
),
|
||||
Sensitive: []common.Sensitive{
|
||||
{
|
||||
Unmasked: route.Namespace,
|
||||
Masked: util.MaskString(route.Namespace),
|
||||
},
|
||||
{
|
||||
Unmasked: route.Name,
|
||||
Masked: util.MaskString(route.Name),
|
||||
},
|
||||
{
|
||||
Unmasked: gtw.Namespace,
|
||||
Masked: util.MaskString(gtw.Namespace),
|
||||
},
|
||||
{
|
||||
Unmasked: gtw.Name,
|
||||
Masked: util.MaskString(gtw.Name),
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
case *allow == gtwapi.NamespacesFromSelector:
|
||||
// check if our route include the same selector Label
|
||||
if !util.LabelsIncludeAny(listener.AllowedRoutes.Namespaces.Selector.MatchLabels, route.Labels) {
|
||||
failures = append(failures, common.Failure{
|
||||
Text: fmt.Sprintf(
|
||||
"HTTPRoute '%s/%s' can't be attached on Gateway '%s/%s', selector labels do not match HTTProute's labels.",
|
||||
route.Namespace,
|
||||
route.Name,
|
||||
gtw.Namespace,
|
||||
gtw.Name,
|
||||
),
|
||||
Sensitive: []common.Sensitive{
|
||||
{
|
||||
Unmasked: route.Namespace,
|
||||
Masked: util.MaskString(route.Namespace),
|
||||
},
|
||||
{
|
||||
Unmasked: route.Name,
|
||||
Masked: util.MaskString(route.Name),
|
||||
},
|
||||
{
|
||||
Unmasked: gtw.Namespace,
|
||||
Masked: util.MaskString(gtw.Namespace),
|
||||
},
|
||||
{
|
||||
Unmasked: gtw.Name,
|
||||
Masked: util.MaskString(gtw.Name),
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
// Check if the Backends are valid services and ports are matching with services Ports
|
||||
for _, rule := range route.Spec.Rules {
|
||||
for _, backend := range rule.BackendRefs {
|
||||
err := client.Get(a.Context, ctrl.ObjectKey{Namespace: route.Namespace, Name: string(backend.Name)}, service, &ctrl.GetOptions{})
|
||||
if errors.IsNotFound(err) {
|
||||
failures = append(failures, common.Failure{
|
||||
Text: fmt.Sprintf(
|
||||
"HTTPRoute uses the Service '%s/%s' which does not exist.",
|
||||
route.Namespace,
|
||||
backend.Name,
|
||||
),
|
||||
Sensitive: []common.Sensitive{
|
||||
{
|
||||
Unmasked: service.Namespace,
|
||||
Masked: util.MaskString(service.Namespace),
|
||||
},
|
||||
{
|
||||
Unmasked: service.Name,
|
||||
Masked: util.MaskString(service.Name),
|
||||
},
|
||||
},
|
||||
})
|
||||
} else {
|
||||
portMatch := false
|
||||
for _, svcPort := range service.Spec.Ports {
|
||||
if int32(*backend.Port) == svcPort.Port {
|
||||
portMatch = true
|
||||
}
|
||||
}
|
||||
if !portMatch {
|
||||
failures = append(failures, common.Failure{
|
||||
Text: fmt.Sprintf(
|
||||
"HTTPRoute's backend service '%s' is using port '%d' but the corresponding K8s service '%s/%s' isn't configured with the same port.",
|
||||
backend.Name,
|
||||
int32(*backend.Port),
|
||||
service.Namespace,
|
||||
service.Name,
|
||||
),
|
||||
Sensitive: []common.Sensitive{
|
||||
{
|
||||
Unmasked: string(backend.Name),
|
||||
Masked: util.MaskString(string(backend.Name)),
|
||||
},
|
||||
{
|
||||
Unmasked: service.Name,
|
||||
Masked: util.MaskString(service.Name),
|
||||
},
|
||||
{
|
||||
Unmasked: service.Namespace,
|
||||
Masked: service.Namespace,
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(failures) > 0 {
|
||||
preAnalysis[fmt.Sprintf("%s/%s", route.Namespace, route.Name)] = common.PreAnalysis{
|
||||
HTTPRoute: route,
|
||||
FailureDetails: failures,
|
||||
}
|
||||
AnalyzerErrorsMetric.WithLabelValues(kind, route.Name, route.Namespace).Set(float64(len(failures)))
|
||||
}
|
||||
}
|
||||
for key, value := range preAnalysis {
|
||||
var currentAnalysis = common.Result{
|
||||
Kind: kind,
|
||||
Name: key,
|
||||
Error: value.FailureDetails,
|
||||
}
|
||||
a.Results = append(a.Results, currentAnalysis)
|
||||
}
|
||||
return a.Results, nil
|
||||
|
||||
}
|
||||
374
pkg/analyzer/httroute_test.go
Normal file
374
pkg/analyzer/httroute_test.go
Normal file
@@ -0,0 +1,374 @@
|
||||
package analyzer
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/k8sgpt-ai/k8sgpt/pkg/common"
|
||||
"github.com/k8sgpt-ai/k8sgpt/pkg/kubernetes"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/util/intstr"
|
||||
"k8s.io/client-go/kubernetes/scheme"
|
||||
fakeclient "sigs.k8s.io/controller-runtime/pkg/client/fake"
|
||||
gtwapi "sigs.k8s.io/gateway-api/apis/v1"
|
||||
)
|
||||
|
||||
func BuildRouteGateway(namespace, name, fromNamespaceref string) gtwapi.Gateway {
|
||||
routeNamespace := >wapi.RouteNamespaces{}
|
||||
switch fromNamespaceref {
|
||||
case "Same":
|
||||
fromSame := gtwapi.NamespacesFromSame
|
||||
routeNamespace.From = &fromSame
|
||||
case "Selector":
|
||||
fromSelector := gtwapi.NamespacesFromSelector
|
||||
routeNamespace.From = &fromSelector
|
||||
routeNamespace.Selector = &metav1.LabelSelector{}
|
||||
routeNamespace.Selector.MatchLabels = map[string]string{"foo": "bar"}
|
||||
|
||||
default:
|
||||
fromAll := gtwapi.NamespacesFromAll
|
||||
routeNamespace.From = &fromAll
|
||||
}
|
||||
Gateway := gtwapi.Gateway{}
|
||||
Gateway.Name = name
|
||||
Gateway.Namespace = namespace
|
||||
Gateway.Spec.GatewayClassName = "fooclassName"
|
||||
Gateway.Spec.Listeners = []gtwapi.Listener{
|
||||
{
|
||||
Name: "proxy",
|
||||
Port: 80,
|
||||
Protocol: gtwapi.HTTPProtocolType,
|
||||
AllowedRoutes: >wapi.AllowedRoutes{
|
||||
Namespaces: routeNamespace,
|
||||
},
|
||||
},
|
||||
}
|
||||
Condition := metav1.Condition{
|
||||
Type: "Accepted",
|
||||
Status: "True",
|
||||
Message: "An expected message",
|
||||
Reason: "Test",
|
||||
}
|
||||
Gateway.Status.Conditions = []metav1.Condition{Condition}
|
||||
|
||||
return Gateway
|
||||
}
|
||||
|
||||
func BuildHTTPRoute(backendName, gtwName gtwapi.ObjectName, gtwNamespace gtwapi.Namespace, svcPort *gtwapi.PortNumber, namespace string) gtwapi.HTTPRoute {
|
||||
HTTPRoute := gtwapi.HTTPRoute{}
|
||||
HTTPRoute.Name = "foohttproute"
|
||||
HTTPRoute.Namespace = namespace
|
||||
HTTPRoute.Spec.ParentRefs = []gtwapi.ParentReference{
|
||||
{
|
||||
Name: gtwName,
|
||||
Namespace: >wNamespace,
|
||||
},
|
||||
}
|
||||
HTTPRoute.Spec.Rules = []gtwapi.HTTPRouteRule{
|
||||
{
|
||||
BackendRefs: []gtwapi.HTTPBackendRef{
|
||||
{
|
||||
BackendRef: gtwapi.BackendRef{
|
||||
BackendObjectReference: gtwapi.BackendObjectReference{
|
||||
Name: backendName,
|
||||
Port: svcPort,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
return HTTPRoute
|
||||
}
|
||||
|
||||
/*
|
||||
Testing different cases
|
||||
|
||||
1. Gateway doesn't exist or at least doesn't exist in the same namespace
|
||||
2. Gateway exists in different namespace, is configured in httproute's spec
|
||||
and Gateway's configuration is allowing only from its same namespace
|
||||
3. Gateway exists in the same namespace but has selectors different from route's labels
|
||||
4. BackendRef is pointing to a non existent Service
|
||||
5. BackendRef's port and Service Port are different
|
||||
*/
|
||||
func TestGWMissiningHTTRouteAnalyzer(t *testing.T) {
|
||||
backendName := gtwapi.ObjectName("foobackend")
|
||||
gtwName := gtwapi.ObjectName("non-existent")
|
||||
gtwNamespace := gtwapi.Namespace("non-existent")
|
||||
svcPort := gtwapi.PortNumber(1027)
|
||||
httpRouteNamespace := "default"
|
||||
|
||||
HTTPRoute := BuildHTTPRoute(backendName, gtwName, gtwNamespace, &svcPort, httpRouteNamespace)
|
||||
// Create a Gateway Analyzer instance with the fake client
|
||||
scheme := scheme.Scheme
|
||||
gtwapi.Install(scheme)
|
||||
apiextensionsv1.AddToScheme(scheme)
|
||||
objects := []runtime.Object{
|
||||
&HTTPRoute,
|
||||
}
|
||||
|
||||
fakeClient := fakeclient.NewClientBuilder().WithScheme(scheme).WithRuntimeObjects(objects...).Build()
|
||||
|
||||
analyzerInstance := HTTPRouteAnalyzer{}
|
||||
config := common.Analyzer{
|
||||
Client: &kubernetes.Client{
|
||||
CtrlClient: fakeClient,
|
||||
},
|
||||
Context: context.Background(),
|
||||
Namespace: "default",
|
||||
}
|
||||
analysisResults, err := analyzerInstance.Analyze(config)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
var errorFound bool
|
||||
want := "HTTPRoute uses the Gateway 'non-existent/non-existent' which does not exist in the same namespace."
|
||||
for _, analysis := range analysisResults {
|
||||
for _, got := range analysis.Error {
|
||||
if want == got.Text {
|
||||
errorFound = true
|
||||
}
|
||||
}
|
||||
if errorFound {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !errorFound {
|
||||
t.Errorf("Expected message, <%s> , not found in HTTPRoute's analysis results", want)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestGWConfigSameHTTRouteAnalyzer(t *testing.T) {
|
||||
backendName := gtwapi.ObjectName("foobackend")
|
||||
gtwName := gtwapi.ObjectName("gatewayname")
|
||||
gtwNamespace := gtwapi.Namespace("differentnamespace")
|
||||
svcPort := gtwapi.PortNumber(1027)
|
||||
httpRouteNamespace := "default"
|
||||
|
||||
HTTPRoute := BuildHTTPRoute(backendName, gtwName, gtwNamespace, &svcPort, httpRouteNamespace)
|
||||
|
||||
Gateway := BuildRouteGateway("differentnamespace", "gatewayname", "Same")
|
||||
// Create a Gateway Analyzer instance with the fake client
|
||||
scheme := scheme.Scheme
|
||||
gtwapi.Install(scheme)
|
||||
apiextensionsv1.AddToScheme(scheme)
|
||||
objects := []runtime.Object{
|
||||
&HTTPRoute,
|
||||
&Gateway,
|
||||
}
|
||||
|
||||
fakeClient := fakeclient.NewClientBuilder().WithScheme(scheme).WithRuntimeObjects(objects...).Build()
|
||||
|
||||
analyzerInstance := HTTPRouteAnalyzer{}
|
||||
config := common.Analyzer{
|
||||
Client: &kubernetes.Client{
|
||||
CtrlClient: fakeClient,
|
||||
},
|
||||
Context: context.Background(),
|
||||
Namespace: "default",
|
||||
}
|
||||
analysisResults, err := analyzerInstance.Analyze(config)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
var errorFound bool
|
||||
want := "HTTPRoute 'default/foohttproute' is deployed in a different namespace from Gateway 'differentnamespace/gatewayname' which only allows HTTPRoutes from its namespace."
|
||||
for _, analysis := range analysisResults {
|
||||
for _, got := range analysis.Error {
|
||||
if want == got.Text {
|
||||
errorFound = true
|
||||
}
|
||||
}
|
||||
if errorFound {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !errorFound {
|
||||
t.Errorf("Expected message, <%s> , not found in HTTPRoute's analysis results", want)
|
||||
}
|
||||
}
|
||||
func TestGWConfigSelectorHTTRouteAnalyzer(t *testing.T) {
|
||||
backendName := gtwapi.ObjectName("foobackend")
|
||||
gtwName := gtwapi.ObjectName("gatewayname")
|
||||
gtwNamespace := gtwapi.Namespace("default")
|
||||
svcPort := gtwapi.PortNumber(1027)
|
||||
httpRouteNamespace := "default"
|
||||
|
||||
HTTPRoute := BuildHTTPRoute(backendName, gtwName, gtwNamespace, &svcPort, httpRouteNamespace)
|
||||
|
||||
Gateway := BuildRouteGateway("default", "gatewayname", "Selector")
|
||||
// Create a Gateway Analyzer instance with the fake client
|
||||
scheme := scheme.Scheme
|
||||
gtwapi.Install(scheme)
|
||||
apiextensionsv1.AddToScheme(scheme)
|
||||
objects := []runtime.Object{
|
||||
&HTTPRoute,
|
||||
&Gateway,
|
||||
}
|
||||
|
||||
fakeClient := fakeclient.NewClientBuilder().WithScheme(scheme).WithRuntimeObjects(objects...).Build()
|
||||
|
||||
analyzerInstance := HTTPRouteAnalyzer{}
|
||||
config := common.Analyzer{
|
||||
Client: &kubernetes.Client{
|
||||
CtrlClient: fakeClient,
|
||||
},
|
||||
Context: context.Background(),
|
||||
Namespace: "default",
|
||||
}
|
||||
analysisResults, err := analyzerInstance.Analyze(config)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
var errorFound bool
|
||||
want := "HTTPRoute 'default/foohttproute' can't be attached on Gateway 'default/gatewayname', selector labels do not match HTTProute's labels."
|
||||
for _, analysis := range analysisResults {
|
||||
for _, got := range analysis.Error {
|
||||
if want == got.Text {
|
||||
errorFound = true
|
||||
}
|
||||
}
|
||||
if errorFound {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !errorFound {
|
||||
t.Errorf("Expected message, <%s> , not found in HTTPRoute's analysis results", want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSvcMissingHTTRouteAnalyzer(t *testing.T) {
|
||||
backendName := gtwapi.ObjectName("foobackend")
|
||||
gtwName := gtwapi.ObjectName("gatewayname")
|
||||
gtwNamespace := gtwapi.Namespace("default")
|
||||
svcPort := gtwapi.PortNumber(1027)
|
||||
httpRouteNamespace := "default"
|
||||
|
||||
HTTPRoute := BuildHTTPRoute(backendName, gtwName, gtwNamespace, &svcPort, httpRouteNamespace)
|
||||
|
||||
Gateway := BuildRouteGateway("default", "gatewayname", "Same")
|
||||
// Create a Gateway Analyzer instance with the fake client
|
||||
scheme := scheme.Scheme
|
||||
gtwapi.Install(scheme)
|
||||
apiextensionsv1.AddToScheme(scheme)
|
||||
objects := []runtime.Object{
|
||||
&HTTPRoute,
|
||||
&Gateway,
|
||||
}
|
||||
|
||||
fakeClient := fakeclient.NewClientBuilder().WithScheme(scheme).WithRuntimeObjects(objects...).Build()
|
||||
|
||||
analyzerInstance := HTTPRouteAnalyzer{}
|
||||
config := common.Analyzer{
|
||||
Client: &kubernetes.Client{
|
||||
CtrlClient: fakeClient,
|
||||
},
|
||||
Context: context.Background(),
|
||||
Namespace: "default",
|
||||
}
|
||||
analysisResults, err := analyzerInstance.Analyze(config)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
var errorFound bool
|
||||
want := "HTTPRoute uses the Service 'default/foobackend' which does not exist."
|
||||
for _, analysis := range analysisResults {
|
||||
for _, got := range analysis.Error {
|
||||
if want == got.Text {
|
||||
errorFound = true
|
||||
}
|
||||
}
|
||||
if errorFound {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !errorFound {
|
||||
t.Errorf("Expected message, <%s> , not found in HTTPRoute's analysis results", want)
|
||||
}
|
||||
}
|
||||
func TestSvcDifferentPortHTTRouteAnalyzer(t *testing.T) {
|
||||
//Add a Service Object
|
||||
Service := corev1.Service{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "foobackend",
|
||||
Namespace: "default",
|
||||
},
|
||||
Spec: corev1.ServiceSpec{
|
||||
Selector: map[string]string{
|
||||
"app": "example-app",
|
||||
},
|
||||
Ports: []corev1.ServicePort{
|
||||
{
|
||||
Name: "http",
|
||||
Protocol: "TCP",
|
||||
Port: 80,
|
||||
TargetPort: intstr.FromInt(8080),
|
||||
},
|
||||
},
|
||||
Type: corev1.ServiceTypeClusterIP,
|
||||
},
|
||||
}
|
||||
backendName := gtwapi.ObjectName("foobackend")
|
||||
gtwName := gtwapi.ObjectName("gatewayname")
|
||||
gtwNamespace := gtwapi.Namespace("default")
|
||||
// different port
|
||||
svcPort := gtwapi.PortNumber(1027)
|
||||
httpRouteNamespace := "default"
|
||||
|
||||
HTTPRoute := BuildHTTPRoute(backendName, gtwName, gtwNamespace, &svcPort, httpRouteNamespace)
|
||||
|
||||
Gateway := BuildRouteGateway("default", "gatewayname", "Same")
|
||||
// Create a Gateway Analyzer instance with the fake client
|
||||
scheme := scheme.Scheme
|
||||
gtwapi.Install(scheme)
|
||||
apiextensionsv1.AddToScheme(scheme)
|
||||
objects := []runtime.Object{
|
||||
&HTTPRoute,
|
||||
&Gateway,
|
||||
&Service,
|
||||
}
|
||||
|
||||
fakeClient := fakeclient.NewClientBuilder().WithScheme(scheme).WithRuntimeObjects(objects...).Build()
|
||||
|
||||
analyzerInstance := HTTPRouteAnalyzer{}
|
||||
config := common.Analyzer{
|
||||
Client: &kubernetes.Client{
|
||||
CtrlClient: fakeClient,
|
||||
},
|
||||
Context: context.Background(),
|
||||
Namespace: "default",
|
||||
}
|
||||
analysisResults, err := analyzerInstance.Analyze(config)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
var errorFound bool
|
||||
want := "HTTPRoute's backend service 'foobackend' is using port '1027' but the corresponding K8s service 'default/foobackend' isn't configured with the same port."
|
||||
for _, analysis := range analysisResults {
|
||||
for _, got := range analysis.Error {
|
||||
if want == got.Text {
|
||||
errorFound = true
|
||||
}
|
||||
}
|
||||
if errorFound {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !errorFound {
|
||||
t.Errorf("Expected message, <%s> , not found in HTTPRoute's analysis results", want)
|
||||
}
|
||||
}
|
||||
@@ -59,15 +59,16 @@ func (PodAnalyzer) Analyze(a common.Analyzer) ([]common.Result, error) {
|
||||
|
||||
// Check through container status to check for crashes or unready
|
||||
for _, containerStatus := range pod.Status.ContainerStatuses {
|
||||
|
||||
if containerStatus.State.Waiting != nil {
|
||||
if containerStatus.State.Waiting.Reason == "CrashLoopBackOff" || containerStatus.State.Waiting.Reason == "ImagePullBackOff" || containerStatus.State.Waiting.Reason == "CreateContainerConfigError" {
|
||||
if containerStatus.State.Waiting.Message != "" {
|
||||
failures = append(failures, common.Failure{
|
||||
Text: containerStatus.State.Waiting.Message,
|
||||
Sensitive: []common.Sensitive{},
|
||||
})
|
||||
}
|
||||
|
||||
if isErrorReason(containerStatus.State.Waiting.Reason) && containerStatus.State.Waiting.Message != "" {
|
||||
failures = append(failures, common.Failure{
|
||||
Text: containerStatus.State.Waiting.Message,
|
||||
Sensitive: []common.Sensitive{},
|
||||
})
|
||||
}
|
||||
|
||||
// This represents a container that is still being created or blocked due to conditions such as OOMKilled
|
||||
if containerStatus.State.Waiting.Reason == "ContainerCreating" && pod.Status.Phase == "Pending" {
|
||||
|
||||
@@ -125,3 +126,16 @@ func (PodAnalyzer) Analyze(a common.Analyzer) ([]common.Result, error) {
|
||||
|
||||
return a.Results, nil
|
||||
}
|
||||
|
||||
func isErrorReason(reason string) bool {
|
||||
failureReasons := []string{
|
||||
"CrashLoopBackOff", "ImagePullBackOff", "CreateContainerConfigError", "PreCreateHookError", "CreateContainerError", "PreStartHookError", "RunContainerError", "ImageInspectError", "ErrImagePull", "ErrImageNeverPull", "InvalidImageName",
|
||||
}
|
||||
|
||||
for _, r := range failureReasons {
|
||||
if r == reason {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
109
pkg/cache/azuresa_based.go
vendored
109
pkg/cache/azuresa_based.go
vendored
@@ -9,7 +9,7 @@ import (
|
||||
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azidentity"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/storage/azblob"
|
||||
"github.com/spf13/viper"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/blob"
|
||||
)
|
||||
|
||||
// Generate ICache implementation
|
||||
@@ -20,6 +20,48 @@ type AzureCache struct {
|
||||
session *azblob.Client
|
||||
}
|
||||
|
||||
type AzureCacheConfiguration struct {
|
||||
StorageAccount string `mapstructure:"storageaccount" yaml:"storageaccount,omitempty"`
|
||||
ContainerName string `mapstructure:"container" yaml:"container,omitempty"`
|
||||
}
|
||||
|
||||
func (s *AzureCache) Configure(cacheInfo CacheProvider) error {
|
||||
s.ctx = context.Background()
|
||||
if cacheInfo.Azure.ContainerName == "" {
|
||||
log.Fatal("Azure Container name not configured")
|
||||
}
|
||||
if cacheInfo.Azure.StorageAccount == "" {
|
||||
log.Fatal("Azure Storage account not configured")
|
||||
}
|
||||
|
||||
// We assume that Storage account is already in place
|
||||
blobUrl := fmt.Sprintf("https://%s.blob.core.windows.net/", cacheInfo.Azure.StorageAccount)
|
||||
credential, err := azidentity.NewDefaultAzureCredential(nil)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
client, err := azblob.NewClient(blobUrl, credential, nil)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
// Try to create the blob container
|
||||
_, err = client.CreateContainer(s.ctx, cacheInfo.Azure.ContainerName, nil)
|
||||
if err != nil {
|
||||
// TODO: Maybe there is a better way to check this?
|
||||
// docs: https://pkg.go.dev/github.com/Azure/azure-storage-blob-go/azblob
|
||||
if strings.Contains(err.Error(), "ContainerAlreadyExists") {
|
||||
// do nothing
|
||||
} else {
|
||||
return err
|
||||
}
|
||||
}
|
||||
s.containerName = cacheInfo.Azure.ContainerName
|
||||
s.session = client
|
||||
|
||||
return nil
|
||||
|
||||
}
|
||||
|
||||
func (s *AzureCache) Store(key string, data string) error {
|
||||
// Store the object as a new file in the Azure blob storage with data as the content
|
||||
cacheData := []byte(data)
|
||||
@@ -45,9 +87,9 @@ func (s *AzureCache) Load(key string) (string, error) {
|
||||
return data.String(), nil
|
||||
}
|
||||
|
||||
func (s *AzureCache) List() ([]string, error) {
|
||||
func (s *AzureCache) List() ([]CacheObjectDetails, error) {
|
||||
// List the files in the blob containerName
|
||||
files := []string{}
|
||||
files := []CacheObjectDetails{}
|
||||
|
||||
pager := s.session.NewListBlobsFlatPager(s.containerName, &azblob.ListBlobsFlatOptions{
|
||||
Include: azblob.ListBlobsInclude{Snapshots: false, Versions: false},
|
||||
@@ -60,13 +102,24 @@ func (s *AzureCache) List() ([]string, error) {
|
||||
}
|
||||
|
||||
for _, blob := range resp.Segment.BlobItems {
|
||||
files = append(files, *blob.Name)
|
||||
files = append(files, CacheObjectDetails{
|
||||
Name: *blob.Name,
|
||||
UpdatedAt: *blob.Properties.LastModified,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return files, nil
|
||||
}
|
||||
|
||||
func (s *AzureCache) Remove(key string) error {
|
||||
_, err := s.session.DeleteBlob(s.ctx, s.containerName, key, &blob.DeleteOptions{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *AzureCache) Exists(key string) bool {
|
||||
// Check if the object exists in the blob storage
|
||||
pager := s.session.NewListBlobsFlatPager(s.containerName, &azblob.ListBlobsFlatOptions{
|
||||
@@ -93,46 +146,10 @@ func (s *AzureCache) IsCacheDisabled() bool {
|
||||
return s.noCache
|
||||
}
|
||||
|
||||
func NewAzureCache(nocache bool) ICache {
|
||||
ctx := context.Background()
|
||||
var cache CacheProvider
|
||||
err := viper.UnmarshalKey("cache", &cache)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if cache.ContainerName == "" {
|
||||
log.Fatal("Azure Container name not configured")
|
||||
}
|
||||
if cache.StorageAccount == "" {
|
||||
log.Fatal("Azure Storage account not configured")
|
||||
}
|
||||
|
||||
// We assume that Storage account is already in place
|
||||
blobUrl := fmt.Sprintf("https://%s.blob.core.windows.net/", cache.StorageAccount)
|
||||
credential, err := azidentity.NewDefaultAzureCredential(nil)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
client, err := azblob.NewClient(blobUrl, credential, nil)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
// Try to create the blob container
|
||||
_, err = client.CreateContainer(ctx, cache.ContainerName, nil)
|
||||
if err != nil {
|
||||
// TODO: Maybe there is a better way to check this?
|
||||
// docs: https://pkg.go.dev/github.com/Azure/azure-storage-blob-go/azblob
|
||||
if strings.Contains(err.Error(), "ContainerAlreadyExists") {
|
||||
// do nothing
|
||||
} else {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
return &AzureCache{
|
||||
ctx: ctx,
|
||||
noCache: nocache,
|
||||
containerName: cache.ContainerName,
|
||||
session: client,
|
||||
}
|
||||
func (s *AzureCache) GetName() string {
|
||||
return "azure"
|
||||
}
|
||||
|
||||
func (s *AzureCache) DisableCache() {
|
||||
s.noCache = true
|
||||
}
|
||||
|
||||
145
pkg/cache/cache.go
vendored
145
pkg/cache/cache.go
vendored
@@ -1,92 +1,108 @@
|
||||
package cache
|
||||
|
||||
import (
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
"fmt"
|
||||
|
||||
"github.com/spf13/viper"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
type CacheType string
|
||||
|
||||
const (
|
||||
Azure CacheType = "azure"
|
||||
S3 CacheType = "s3"
|
||||
FileBased CacheType = "file"
|
||||
var (
|
||||
types = []ICache{
|
||||
&AzureCache{},
|
||||
&FileBasedCache{},
|
||||
&GCSCache{},
|
||||
&S3Cache{},
|
||||
}
|
||||
)
|
||||
|
||||
type ICache interface {
|
||||
Configure(cacheInfo CacheProvider) error
|
||||
Store(key string, data string) error
|
||||
Load(key string) (string, error)
|
||||
List() ([]string, error)
|
||||
List() ([]CacheObjectDetails, error)
|
||||
Remove(key string) error
|
||||
Exists(key string) bool
|
||||
IsCacheDisabled() bool
|
||||
GetName() string
|
||||
DisableCache()
|
||||
}
|
||||
|
||||
func New(noCache bool, remoteCache CacheType) ICache {
|
||||
switch remoteCache {
|
||||
case S3:
|
||||
return NewS3Cache(noCache)
|
||||
case Azure:
|
||||
return NewAzureCache(noCache)
|
||||
case FileBased:
|
||||
return &FileBasedCache{
|
||||
noCache: noCache,
|
||||
}
|
||||
default:
|
||||
return &FileBasedCache{
|
||||
noCache: noCache,
|
||||
func New(cacheType string) ICache {
|
||||
for _, t := range types {
|
||||
if cacheType == t.GetName() {
|
||||
return t
|
||||
}
|
||||
}
|
||||
return &FileBasedCache{}
|
||||
}
|
||||
|
||||
// CacheProvider is the configuration for the cache provider when using a remote cache
|
||||
type CacheProvider struct {
|
||||
BucketName string `mapstructure:"bucketname" yaml:"bucketname,omitempty"`
|
||||
Region string `mapstructure:"region" yaml:"region,omitempty"`
|
||||
StorageAccount string `mapstructure:"storageaccount" yaml:"storageaccount,omitempty"`
|
||||
ContainerName string `mapstructure:"container" yaml:"container,omitempty"`
|
||||
}
|
||||
|
||||
// NewCacheProvider constructs a new cache struct
|
||||
func NewCacheProvider(bucketname, region, storageaccount, containername string) CacheProvider {
|
||||
return CacheProvider{
|
||||
BucketName: bucketname,
|
||||
Region: region,
|
||||
StorageAccount: storageaccount,
|
||||
ContainerName: containername,
|
||||
}
|
||||
}
|
||||
|
||||
// If we have set a remote cache, return the remote cache type
|
||||
func RemoteCacheEnabled() (CacheType, error) {
|
||||
// load remote cache if it is configured
|
||||
var cache CacheProvider
|
||||
err := viper.UnmarshalKey("cache", &cache)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if cache.BucketName != "" && cache.Region != "" {
|
||||
return S3, nil
|
||||
} else if cache.StorageAccount != "" && cache.ContainerName != "" {
|
||||
return Azure, nil
|
||||
}
|
||||
return FileBased, nil
|
||||
}
|
||||
|
||||
func AddRemoteCache(cache CacheProvider) error {
|
||||
func ParseCacheConfiguration() (CacheProvider, error) {
|
||||
var cacheInfo CacheProvider
|
||||
err := viper.UnmarshalKey("cache", &cacheInfo)
|
||||
if err != nil {
|
||||
return err
|
||||
return cacheInfo, err
|
||||
}
|
||||
return cacheInfo, nil
|
||||
}
|
||||
|
||||
func NewCacheProvider(cacheType, bucketname, region, storageAccount, containerName, projectId string) (CacheProvider, error) {
|
||||
cProvider := CacheProvider{}
|
||||
|
||||
switch {
|
||||
case cacheType == "azure":
|
||||
cProvider.Azure.ContainerName = containerName
|
||||
cProvider.Azure.StorageAccount = storageAccount
|
||||
case cacheType == "gcs":
|
||||
cProvider.GCS.BucketName = bucketname
|
||||
cProvider.GCS.ProjectId = projectId
|
||||
cProvider.GCS.Region = region
|
||||
case cacheType == "s3":
|
||||
cProvider.S3.BucketName = bucketname
|
||||
cProvider.S3.Region = region
|
||||
default:
|
||||
return CacheProvider{}, status.Error(codes.Internal, fmt.Sprintf("%s is not a valid option", cacheType))
|
||||
}
|
||||
|
||||
cacheInfo.BucketName = cache.BucketName
|
||||
cacheInfo.Region = cache.Region
|
||||
cacheInfo.StorageAccount = cache.StorageAccount
|
||||
cacheInfo.ContainerName = cache.ContainerName
|
||||
cache := New(cacheType)
|
||||
err := cache.Configure(cProvider)
|
||||
if err != nil {
|
||||
return CacheProvider{}, err
|
||||
}
|
||||
return cProvider, nil
|
||||
}
|
||||
|
||||
// If we have set a remote cache, return the remote cache configuration
|
||||
func GetCacheConfiguration() (ICache, error) {
|
||||
cacheInfo, err := ParseCacheConfiguration()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var cache ICache
|
||||
|
||||
switch {
|
||||
case cacheInfo.GCS != GCSCacheConfiguration{}:
|
||||
cache = &GCSCache{}
|
||||
case cacheInfo.Azure != AzureCacheConfiguration{}:
|
||||
cache = &AzureCache{}
|
||||
case cacheInfo.S3 != S3CacheConfiguration{}:
|
||||
cache = &S3Cache{}
|
||||
default:
|
||||
cache = &FileBasedCache{}
|
||||
}
|
||||
|
||||
cache.Configure(cacheInfo)
|
||||
|
||||
return cache, nil
|
||||
}
|
||||
|
||||
func AddRemoteCache(cacheInfo CacheProvider) error {
|
||||
|
||||
viper.Set("cache", cacheInfo)
|
||||
err = viper.WriteConfig()
|
||||
|
||||
err := viper.WriteConfig()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -99,9 +115,6 @@ func RemoveRemoteCache() error {
|
||||
if err != nil {
|
||||
return status.Error(codes.Internal, "cache unmarshal")
|
||||
}
|
||||
if cacheInfo.BucketName == "" && cacheInfo.ContainerName == "" && cacheInfo.StorageAccount == "" {
|
||||
return status.Error(codes.Internal, "no remote cache configured")
|
||||
}
|
||||
|
||||
cacheInfo = CacheProvider{}
|
||||
viper.Set("cache", cacheInfo)
|
||||
|
||||
39
pkg/cache/file_based.go
vendored
39
pkg/cache/file_based.go
vendored
@@ -15,11 +15,15 @@ type FileBasedCache struct {
|
||||
noCache bool
|
||||
}
|
||||
|
||||
func (f *FileBasedCache) Configure(cacheInfo CacheProvider) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *FileBasedCache) IsCacheDisabled() bool {
|
||||
return f.noCache
|
||||
}
|
||||
|
||||
func (*FileBasedCache) List() ([]string, error) {
|
||||
func (*FileBasedCache) List() ([]CacheObjectDetails, error) {
|
||||
path, err := xdg.CacheFile("k8sgpt")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -30,9 +34,16 @@ func (*FileBasedCache) List() ([]string, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var result []string
|
||||
var result []CacheObjectDetails
|
||||
for _, file := range files {
|
||||
result = append(result, file.Name())
|
||||
info, err := file.Info()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result = append(result, CacheObjectDetails{
|
||||
Name: file.Name(),
|
||||
UpdatedAt: info.ModTime(),
|
||||
})
|
||||
}
|
||||
|
||||
return result, nil
|
||||
@@ -72,6 +83,20 @@ func (*FileBasedCache) Load(key string) (string, error) {
|
||||
return string(data), nil
|
||||
}
|
||||
|
||||
func (*FileBasedCache) Remove(key string) error {
|
||||
path, err := xdg.CacheFile(filepath.Join("k8sgpt", key))
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := os.Remove(path); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (*FileBasedCache) Store(key string, data string) error {
|
||||
path, err := xdg.CacheFile(filepath.Join("k8sgpt", key))
|
||||
|
||||
@@ -81,3 +106,11 @@ func (*FileBasedCache) Store(key string, data string) error {
|
||||
|
||||
return os.WriteFile(path, []byte(data), 0600)
|
||||
}
|
||||
|
||||
func (s *FileBasedCache) GetName() string {
|
||||
return "file"
|
||||
}
|
||||
|
||||
func (s *FileBasedCache) DisableCache() {
|
||||
s.noCache = true
|
||||
}
|
||||
|
||||
133
pkg/cache/gcs_based.go
vendored
Normal file
133
pkg/cache/gcs_based.go
vendored
Normal file
@@ -0,0 +1,133 @@
|
||||
package cache
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"log"
|
||||
|
||||
"cloud.google.com/go/storage"
|
||||
"google.golang.org/api/iterator"
|
||||
)
|
||||
|
||||
type GCSCache struct {
|
||||
ctx context.Context
|
||||
noCache bool
|
||||
bucketName string
|
||||
projectId string
|
||||
region string
|
||||
session *storage.Client
|
||||
}
|
||||
|
||||
type GCSCacheConfiguration struct {
|
||||
ProjectId string `mapstructure:"projectid" yaml:"projectid,omitempty"`
|
||||
Region string `mapstructure:"region" yaml:"region,omitempty"`
|
||||
BucketName string `mapstructure:"bucketname" yaml:"bucketname,omitempty"`
|
||||
}
|
||||
|
||||
func (s *GCSCache) Configure(cacheInfo CacheProvider) error {
|
||||
s.ctx = context.Background()
|
||||
if cacheInfo.GCS.BucketName == "" {
|
||||
log.Fatal("Bucket name not configured")
|
||||
}
|
||||
if cacheInfo.GCS.Region == "" {
|
||||
log.Fatal("Region not configured")
|
||||
}
|
||||
if cacheInfo.GCS.ProjectId == "" {
|
||||
log.Fatal("ProjectID not configured")
|
||||
}
|
||||
s.bucketName = cacheInfo.GCS.BucketName
|
||||
s.projectId = cacheInfo.GCS.ProjectId
|
||||
s.region = cacheInfo.GCS.Region
|
||||
storageClient, err := storage.NewClient(s.ctx)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
_, err = storageClient.Bucket(s.bucketName).Attrs(s.ctx)
|
||||
if err == storage.ErrBucketNotExist {
|
||||
err = storageClient.Bucket(s.bucketName).Create(s.ctx, s.projectId, &storage.BucketAttrs{
|
||||
Location: s.region,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
s.session = storageClient
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *GCSCache) Store(key string, data string) error {
|
||||
wc := s.session.Bucket(s.bucketName).Object(key).NewWriter(s.ctx)
|
||||
|
||||
if _, err := wc.Write([]byte(data)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := wc.Close(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *GCSCache) Load(key string) (string, error) {
|
||||
reader, err := s.session.Bucket(s.bucketName).Object(key).NewReader(s.ctx)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer reader.Close()
|
||||
|
||||
data, err := io.ReadAll(reader)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return string(data), nil
|
||||
}
|
||||
|
||||
func (s *GCSCache) Remove(key string) error {
|
||||
bucketClient := s.session.Bucket(s.bucketName)
|
||||
obj := bucketClient.Object(key)
|
||||
if err := obj.Delete(s.ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *GCSCache) List() ([]CacheObjectDetails, error) {
|
||||
var files []CacheObjectDetails
|
||||
|
||||
items := s.session.Bucket(s.bucketName).Objects(s.ctx, nil)
|
||||
for {
|
||||
attrs, err := items.Next()
|
||||
if err == iterator.Done {
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
files = append(files, CacheObjectDetails{
|
||||
Name: attrs.Name,
|
||||
UpdatedAt: attrs.Updated,
|
||||
})
|
||||
}
|
||||
return files, nil
|
||||
}
|
||||
|
||||
func (s *GCSCache) Exists(key string) bool {
|
||||
obj := s.session.Bucket(s.bucketName).Object(key)
|
||||
_, err := obj.Attrs(s.ctx)
|
||||
return err == nil
|
||||
}
|
||||
|
||||
func (s *GCSCache) IsCacheDisabled() bool {
|
||||
return s.noCache
|
||||
}
|
||||
|
||||
func (s *GCSCache) GetName() string {
|
||||
return "gcs"
|
||||
}
|
||||
|
||||
func (s *GCSCache) DisableCache() {
|
||||
s.noCache = true
|
||||
}
|
||||
105
pkg/cache/s3_based.go
vendored
105
pkg/cache/s3_based.go
vendored
@@ -7,7 +7,6 @@ import (
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/aws/session"
|
||||
"github.com/aws/aws-sdk-go/service/s3"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
// Generate ICache implementation
|
||||
@@ -17,6 +16,45 @@ type S3Cache struct {
|
||||
session *s3.S3
|
||||
}
|
||||
|
||||
type S3CacheConfiguration struct {
|
||||
Region string `mapstructure:"region" yaml:"region,omitempty"`
|
||||
BucketName string `mapstructure:"bucketname" yaml:"bucketname,omitempty"`
|
||||
}
|
||||
|
||||
func (s *S3Cache) Configure(cacheInfo CacheProvider) error {
|
||||
if cacheInfo.S3.BucketName == "" {
|
||||
log.Fatal("Bucket name not configured")
|
||||
}
|
||||
if cacheInfo.S3.Region == "" {
|
||||
log.Fatal("Region not configured")
|
||||
}
|
||||
s.bucketName = cacheInfo.S3.BucketName
|
||||
|
||||
sess := session.Must(session.NewSessionWithOptions(session.Options{
|
||||
SharedConfigState: session.SharedConfigEnable,
|
||||
Config: aws.Config{
|
||||
Region: aws.String(cacheInfo.S3.Region),
|
||||
},
|
||||
}))
|
||||
|
||||
s3Client := s3.New(sess)
|
||||
|
||||
// Check if the bucket exists, if not create it
|
||||
_, err := s3Client.HeadBucket(&s3.HeadBucketInput{
|
||||
Bucket: aws.String(cacheInfo.S3.BucketName),
|
||||
})
|
||||
if err != nil {
|
||||
_, err = s3Client.CreateBucket(&s3.CreateBucketInput{
|
||||
Bucket: aws.String(cacheInfo.S3.BucketName),
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
s.session = s3Client
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *S3Cache) Store(key string, data string) error {
|
||||
// Store the object as a new file in the bucket with data as the content
|
||||
_, err := s.session.PutObject(&s3.PutObjectInput{
|
||||
@@ -28,6 +66,18 @@ func (s *S3Cache) Store(key string, data string) error {
|
||||
|
||||
}
|
||||
|
||||
func (s *S3Cache) Remove(key string) error {
|
||||
_, err := s.session.DeleteObject(&s3.DeleteObjectInput{
|
||||
Bucket: &s.bucketName,
|
||||
Key: aws.String(key),
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *S3Cache) Load(key string) (string, error) {
|
||||
|
||||
// Retrieve the object from the bucket and load it into a string
|
||||
@@ -45,7 +95,7 @@ func (s *S3Cache) Load(key string) (string, error) {
|
||||
return buf.String(), nil
|
||||
}
|
||||
|
||||
func (s *S3Cache) List() ([]string, error) {
|
||||
func (s *S3Cache) List() ([]CacheObjectDetails, error) {
|
||||
|
||||
// List the files in the bucket
|
||||
result, err := s.session.ListObjectsV2(&s3.ListObjectsV2Input{Bucket: aws.String(s.bucketName)})
|
||||
@@ -53,9 +103,12 @@ func (s *S3Cache) List() ([]string, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var keys []string
|
||||
var keys []CacheObjectDetails
|
||||
for _, item := range result.Contents {
|
||||
keys = append(keys, *item.Key)
|
||||
keys = append(keys, CacheObjectDetails{
|
||||
Name: *item.Key,
|
||||
UpdatedAt: *item.LastModified,
|
||||
})
|
||||
}
|
||||
|
||||
return keys, nil
|
||||
@@ -75,42 +128,10 @@ func (s *S3Cache) IsCacheDisabled() bool {
|
||||
return s.noCache
|
||||
}
|
||||
|
||||
func NewS3Cache(nocache bool) ICache {
|
||||
|
||||
var cache CacheProvider
|
||||
err := viper.UnmarshalKey("cache", &cache)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
if cache.BucketName == "" {
|
||||
log.Fatal("Bucket name not configured")
|
||||
}
|
||||
if cache.Region == "" {
|
||||
log.Fatal("Region not configured")
|
||||
}
|
||||
|
||||
sess := session.Must(session.NewSessionWithOptions(session.Options{
|
||||
SharedConfigState: session.SharedConfigEnable,
|
||||
Config: aws.Config{
|
||||
Region: aws.String(cache.Region),
|
||||
},
|
||||
}))
|
||||
|
||||
s := s3.New(sess)
|
||||
|
||||
// Check if the bucket exists, if not create it
|
||||
_, err = s.HeadBucket(&s3.HeadBucketInput{
|
||||
Bucket: aws.String(cache.BucketName),
|
||||
})
|
||||
if err != nil {
|
||||
_, _ = s.CreateBucket(&s3.CreateBucketInput{
|
||||
Bucket: aws.String(cache.BucketName),
|
||||
})
|
||||
}
|
||||
|
||||
return &S3Cache{
|
||||
noCache: nocache,
|
||||
session: s,
|
||||
bucketName: cache.BucketName,
|
||||
}
|
||||
func (s *S3Cache) GetName() string {
|
||||
return "s3"
|
||||
}
|
||||
|
||||
func (s *S3Cache) DisableCache() {
|
||||
s.noCache = true
|
||||
}
|
||||
|
||||
14
pkg/cache/types.go
vendored
Normal file
14
pkg/cache/types.go
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
package cache
|
||||
|
||||
import "time"
|
||||
|
||||
type CacheProvider struct {
|
||||
GCS GCSCacheConfiguration `mapstructucre:"gcs" yaml:"gcs,omitempty"`
|
||||
Azure AzureCacheConfiguration `mapstructucre:"azure" yaml:"azure,omitempty"`
|
||||
S3 S3CacheConfiguration `mapstructucre:"s3" yaml:"s3,omitempty"`
|
||||
}
|
||||
|
||||
type CacheObjectDetails struct {
|
||||
Name string
|
||||
UpdatedAt time.Time
|
||||
}
|
||||
@@ -26,6 +26,7 @@ import (
|
||||
v1 "k8s.io/api/core/v1"
|
||||
networkv1 "k8s.io/api/networking/v1"
|
||||
policyv1 "k8s.io/api/policy/v1"
|
||||
gtwapi "sigs.k8s.io/gateway-api/apis/v1"
|
||||
)
|
||||
|
||||
type IAnalyzer interface {
|
||||
@@ -57,6 +58,9 @@ type PreAnalysis struct {
|
||||
Node v1.Node
|
||||
ValidatingWebhook regv1.ValidatingWebhookConfiguration
|
||||
MutatingWebhook regv1.MutatingWebhookConfiguration
|
||||
GatewayClass gtwapi.GatewayClass
|
||||
Gateway gtwapi.Gateway
|
||||
HTTPRoute gtwapi.HTTPRoute
|
||||
// Integrations
|
||||
TrivyVulnerabilityReport trivy.VulnerabilityReport
|
||||
TrivyConfigAuditReport trivy.ConfigAuditReport
|
||||
|
||||
@@ -16,11 +16,15 @@ package trivy
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
|
||||
"github.com/fatih/color"
|
||||
"github.com/k8sgpt-ai/k8sgpt/pkg/common"
|
||||
"github.com/k8sgpt-ai/k8sgpt/pkg/kubernetes"
|
||||
helmclient "github.com/mittwald/go-helm-client"
|
||||
"github.com/spf13/viper"
|
||||
"helm.sh/helm/v3/pkg/repo"
|
||||
)
|
||||
|
||||
@@ -126,13 +130,52 @@ func (t *Trivy) UnDeploy(namespace string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *Trivy) IsActivate() bool {
|
||||
|
||||
if _, err := t.helm.GetRelease(ReleaseName); err != nil {
|
||||
return false
|
||||
func (t *Trivy) isDeployed() bool {
|
||||
// check if aquasec apigroup is available as a marker if trivy is installed on the cluster
|
||||
kubecontext := viper.GetString("kubecontext")
|
||||
kubeconfig := viper.GetString("kubeconfig")
|
||||
client, err := kubernetes.NewClient(kubecontext, kubeconfig)
|
||||
if err != nil {
|
||||
// TODO: better error handling
|
||||
color.Red("Error initialising kubernetes client: %v", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
groups, _, err := client.Client.Discovery().ServerGroupsAndResources()
|
||||
if err != nil {
|
||||
// TODO: better error handling
|
||||
color.Red("Error initialising discovery client: %v", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
return true
|
||||
for _, group := range groups {
|
||||
if group.Name == "aquasecurity.github.io" {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func (t *Trivy) isFilterActive() bool {
|
||||
activeFilters := viper.GetStringSlice("active_filters")
|
||||
|
||||
for _, filter := range t.GetAnalyzerName() {
|
||||
for _, af := range activeFilters {
|
||||
if af == filter {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func (t *Trivy) IsActivate() bool {
|
||||
if t.isFilterActive() && t.isDeployed() {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func (t *Trivy) AddAnalyzer(mergedMap *map[string]common.IAnalyzer) {
|
||||
|
||||
@@ -20,6 +20,7 @@ import (
|
||||
"k8s.io/client-go/rest"
|
||||
"k8s.io/client-go/tools/clientcmd"
|
||||
"k8s.io/kubectl/pkg/scheme"
|
||||
ctrl "sigs.k8s.io/controller-runtime/pkg/client"
|
||||
)
|
||||
|
||||
func (c *Client) GetConfig() *rest.Config {
|
||||
@@ -34,6 +35,10 @@ func (c *Client) GetRestClient() rest.Interface {
|
||||
return c.RestClient
|
||||
}
|
||||
|
||||
func (c *Client) GetCtrlClient() ctrl.Client {
|
||||
return c.CtrlClient
|
||||
}
|
||||
|
||||
func NewClient(kubecontext string, kubeconfig string) (*Client, error) {
|
||||
var config *rest.Config
|
||||
config, err := rest.InClusterConfig()
|
||||
@@ -68,6 +73,11 @@ func NewClient(kubecontext string, kubeconfig string) (*Client, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ctrlClient, err := ctrl.New(config, ctrl.Options{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
serverVersion, err := clientSet.ServerVersion()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -76,6 +86,7 @@ func NewClient(kubecontext string, kubeconfig string) (*Client, error) {
|
||||
return &Client{
|
||||
Client: clientSet,
|
||||
RestClient: restClient,
|
||||
CtrlClient: ctrlClient,
|
||||
Config: config,
|
||||
ServerVersion: serverVersion,
|
||||
}, nil
|
||||
|
||||
@@ -6,11 +6,13 @@ import (
|
||||
"k8s.io/apimachinery/pkg/version"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/rest"
|
||||
ctrl "sigs.k8s.io/controller-runtime/pkg/client"
|
||||
)
|
||||
|
||||
type Client struct {
|
||||
Client kubernetes.Interface
|
||||
RestClient rest.Interface
|
||||
CtrlClient ctrl.Client
|
||||
Config *rest.Config
|
||||
ServerVersion *version.Info
|
||||
}
|
||||
|
||||
@@ -18,17 +18,28 @@ func (h *handler) AddConfig(ctx context.Context, i *schemav1.AddConfigRequest) (
|
||||
}
|
||||
|
||||
if i.Cache != nil {
|
||||
// We check if we have a mixed cache configuration
|
||||
CacheConfigured := (i.Cache.Region == "" && i.Cache.BucketName == "") || (i.Cache.ContainerName == "" && i.Cache.StorageAccount == "")
|
||||
if !CacheConfigured {
|
||||
return resp, status.Error(codes.InvalidArgument, "mixed cache arguments")
|
||||
var err error
|
||||
var remoteCache cache.CacheProvider
|
||||
|
||||
switch i.Cache.GetCacheType().(type) {
|
||||
case *schemav1.Cache_AzureCache:
|
||||
remoteCache, err = cache.NewCacheProvider("azure", "", "", i.Cache.GetAzureCache().StorageAccount, i.Cache.GetAzureCache().ContainerName, "")
|
||||
case *schemav1.Cache_S3Cache:
|
||||
remoteCache, err = cache.NewCacheProvider("s3", i.Cache.GetS3Cache().BucketName, i.Cache.GetS3Cache().Region, "", "", "")
|
||||
case *schemav1.Cache_GcsCache:
|
||||
remoteCache, err = cache.NewCacheProvider("gcs", i.Cache.GetGcsCache().BucketName, i.Cache.GetGcsCache().Region, "", "", i.Cache.GetGcsCache().GetProjectId())
|
||||
default:
|
||||
return resp, status.Error(codes.InvalidArgument, "Invalid cache configuration")
|
||||
}
|
||||
|
||||
cacheProvider := cache.NewCacheProvider(i.Cache.BucketName, i.Cache.Region, i.Cache.StorageAccount, i.Cache.ContainerName)
|
||||
err := cache.AddRemoteCache(cacheProvider)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
}
|
||||
err = cache.AddRemoteCache(remoteCache)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
}
|
||||
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
@@ -219,3 +219,14 @@ func MapToString(m map[string]string) string {
|
||||
}
|
||||
return result[:len(result)-1]
|
||||
}
|
||||
|
||||
func LabelsIncludeAny(predefinedSelector, Labels map[string]string) bool {
|
||||
// Check if any label in the predefinedSelector exists in Labels
|
||||
for key := range predefinedSelector {
|
||||
if _, exists := Labels[key]; exists {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user