mirror of
https://github.com/k8sgpt-ai/k8sgpt.git
synced 2026-03-19 19:42:38 +00:00
Compare commits
78 Commits
AlexsJones
...
v0.4.2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a75ec50789 | ||
|
|
e5817f9e55 | ||
|
|
f5eaf817f0 | ||
|
|
eb381b8087 | ||
|
|
288ca862b3 | ||
|
|
81d4aaf402 | ||
|
|
fdf8e7a95a | ||
|
|
5a48bae667 | ||
|
|
7540e0084e | ||
|
|
eb7b36aa27 | ||
|
|
d6d2e3bc42 | ||
|
|
4e39cb65b3 | ||
|
|
db5e517dbb | ||
|
|
aa1e237ebb | ||
|
|
f2fdfd8dca | ||
|
|
e14c3dad55 | ||
|
|
093975e50d | ||
|
|
4f4f4f13a0 | ||
|
|
2a6f48500c | ||
|
|
f2e3b9a8a7 | ||
|
|
d1b2227ff9 | ||
|
|
1f953585c9 | ||
|
|
9dcb21e160 | ||
|
|
d956f32e1e | ||
|
|
7dadea2570 | ||
|
|
3b85f09348 | ||
|
|
06b8f78150 | ||
|
|
076ca2f148 | ||
|
|
fcc8563e4e | ||
|
|
5de4f7704a | ||
|
|
83672fa768 | ||
|
|
990d723909 | ||
|
|
c506a4b441 | ||
|
|
2918556793 | ||
|
|
19abbef9a3 | ||
|
|
939e0672aa | ||
|
|
8cd3b2985e | ||
|
|
1827c43696 | ||
|
|
1363219b1b | ||
|
|
c3f448693d | ||
|
|
5514ebb53b | ||
|
|
c21ba86237 | ||
|
|
d6d80ee860 | ||
|
|
a841568a9c | ||
|
|
4d7eb0f622 | ||
|
|
a12aa07b1a | ||
|
|
ec5e42b8f4 | ||
|
|
69c67bd1d9 | ||
|
|
b3f60b2d20 | ||
|
|
cb1e1ffede | ||
|
|
f37d923918 | ||
|
|
a50375c960 | ||
|
|
da266b3c82 | ||
|
|
896a53be83 | ||
|
|
2da057360b | ||
|
|
69fd7c7696 | ||
|
|
ad86e7aa39 | ||
|
|
1ae70e806e | ||
|
|
2ce8450e03 | ||
|
|
b6b3d0c856 | ||
|
|
5f7d9de46a | ||
|
|
7dcdfc83d2 | ||
|
|
44f4f7437f | ||
|
|
783cd1cfc6 | ||
|
|
62ba6d84a4 | ||
|
|
cc9b3ea657 | ||
|
|
8ad288152f | ||
|
|
004d9efc55 | ||
|
|
2f62c7b3e0 | ||
|
|
a6b19a81b0 | ||
|
|
32e8bc3253 | ||
|
|
5f01cc685f | ||
|
|
c67add30c6 | ||
|
|
2f759865b6 | ||
|
|
9d68c47040 | ||
|
|
14e0f19b12 | ||
|
|
c1a38c2b35 | ||
|
|
458fcfe8d3 |
18
.github/workflows/build_container.yaml
vendored
18
.github/workflows/build_container.yaml
vendored
@@ -22,7 +22,7 @@ defaults:
|
||||
jobs:
|
||||
prepare_ci_run:
|
||||
name: Prepare CI Run
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
GIT_SHA: ${{ steps.extract_branch.outputs.GIT_SHA }}
|
||||
BRANCH: ${{ steps.extract_branch.outputs.BRANCH }}
|
||||
@@ -61,7 +61,7 @@ jobs:
|
||||
build_image:
|
||||
name: Build Container Image
|
||||
needs: prepare_ci_run
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
BRANCH: ${{ needs.prepare_ci_run.outputs.BRANCH }}
|
||||
DATETIME: ${{ needs.prepare_ci_run.outputs.DATETIME }}
|
||||
@@ -74,10 +74,10 @@ jobs:
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
id: buildx
|
||||
uses: docker/setup-buildx-action@c47758b77c9736f4b2ef4073d4d51994fabfe349 # v3
|
||||
uses: docker/setup-buildx-action@6524bf65af31da8d45b59e8c27de4bd072b392f5 # v3
|
||||
|
||||
- name: Build Docker Image
|
||||
uses: docker/build-push-action@ca052bb54ab0790a636c9b5f226502c73d547a25 # v5
|
||||
uses: docker/build-push-action@471d1dc4e07e5cdedd4c2171150001c434f0b7a4 # v6
|
||||
with:
|
||||
context: .
|
||||
platforms: linux/amd64
|
||||
@@ -96,7 +96,7 @@ jobs:
|
||||
outputs: type=docker,dest=/tmp/${{ env.IMAGE_NAME }}-image.tar
|
||||
|
||||
- name: Upload image as artifact
|
||||
uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4
|
||||
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
|
||||
with:
|
||||
name: ${{ env.IMAGE_NAME }}-image.tar
|
||||
path: /tmp/${{ env.IMAGE_NAME }}-image.tar
|
||||
@@ -105,7 +105,7 @@ jobs:
|
||||
name: Upload images to ghcr registry
|
||||
needs: [ prepare_ci_run, build_image ]
|
||||
if: github.event_name == 'push' && needs.prepare_ci_run.outputs.NON_FORKED_AND_NON_ROBOT_RUN == 'true' # only run on push to main/maintenance branches
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
DATETIME: ${{ needs.prepare_ci_run.outputs.DATETIME }}
|
||||
BUILD_TIME: ${{ needs.prepare_ci_run.outputs.BUILD_TIME }}
|
||||
@@ -118,7 +118,7 @@ jobs:
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
||||
|
||||
- name: Login to GitHub Container Registry
|
||||
uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # v3
|
||||
uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3
|
||||
with:
|
||||
registry: "ghcr.io"
|
||||
username: ${{ github.actor }}
|
||||
@@ -126,10 +126,10 @@ jobs:
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
id: buildx
|
||||
uses: docker/setup-buildx-action@c47758b77c9736f4b2ef4073d4d51994fabfe349 # v3
|
||||
uses: docker/setup-buildx-action@6524bf65af31da8d45b59e8c27de4bd072b392f5 # v3
|
||||
|
||||
- name: Build Docker Image
|
||||
uses: docker/build-push-action@ca052bb54ab0790a636c9b5f226502c73d547a25 # v5
|
||||
uses: docker/build-push-action@471d1dc4e07e5cdedd4c2171150001c434f0b7a4 # v6
|
||||
with:
|
||||
context: .
|
||||
file: ./container/Dockerfile
|
||||
|
||||
34
.github/workflows/release.yaml
vendored
34
.github/workflows/release.yaml
vendored
@@ -40,18 +40,32 @@ jobs:
|
||||
- release-please
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Free Disk Space (Ubuntu)
|
||||
uses: jlumbroso/free-disk-space@main
|
||||
with:
|
||||
# this might remove tools that are actually needed,
|
||||
# if set to "true" but frees about 6 GB
|
||||
tool-cache: false
|
||||
# all of these default to true, but feel free to set to
|
||||
# "false" if necessary for your workflow
|
||||
android: false
|
||||
dotnet: false
|
||||
haskell: false
|
||||
large-packages: true
|
||||
docker-images: true
|
||||
swap-storage: true
|
||||
- name: Checkout
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5
|
||||
uses: actions/setup-go@0aaccfd150d50ccaeb58ebd88d36e91967a5f35b # v5
|
||||
with:
|
||||
go-version: '1.22'
|
||||
- name: Download Syft
|
||||
uses: anchore/sbom-action/download-syft@251a468eed47e5082b105c3ba6ee500c0e65a764 # v0.17.6
|
||||
uses: anchore/sbom-action/download-syft@55dc4ee22412511ee8c3142cbea40418e6cec693 # v0.17.8
|
||||
- name: Run GoReleaser
|
||||
uses: goreleaser/goreleaser-action@286f3b13b1b49da4ac219696163fb8c1c93e1200 # v6
|
||||
uses: goreleaser/goreleaser-action@90a3faa9d0182683851fbfa97ca1a2cb983bfca3 # v6
|
||||
with:
|
||||
# either 'goreleaser' (default) or 'goreleaser-pro'
|
||||
distribution: goreleaser
|
||||
@@ -60,13 +74,13 @@ jobs:
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.K8SGPT_BOT_SECRET }}
|
||||
- name: Update new version in krew-index
|
||||
uses: rajatjindal/krew-release-bot@df3eb197549e3568be8b4767eec31c5e8e8e6ad8 # v0.0.46
|
||||
uses: rajatjindal/krew-release-bot@3d9faef30a82761d610544f62afddca00993eef9 # v0.0.47
|
||||
|
||||
build-container:
|
||||
if: needs.release-please.outputs.releases_created == 'true'
|
||||
needs:
|
||||
- release-please
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write
|
||||
packages: write
|
||||
@@ -82,17 +96,17 @@ jobs:
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
id: buildx
|
||||
uses: docker/setup-buildx-action@c47758b77c9736f4b2ef4073d4d51994fabfe349 # v3
|
||||
uses: docker/setup-buildx-action@6524bf65af31da8d45b59e8c27de4bd072b392f5 # v3
|
||||
|
||||
- name: Login to GitHub Container Registry
|
||||
uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # v3
|
||||
uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3
|
||||
with:
|
||||
registry: "ghcr.io"
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Build Docker Image
|
||||
uses: docker/build-push-action@ca052bb54ab0790a636c9b5f226502c73d547a25 # v5
|
||||
uses: docker/build-push-action@471d1dc4e07e5cdedd4c2171150001c434f0b7a4 # v6
|
||||
with:
|
||||
context: .
|
||||
file: ./container/Dockerfile
|
||||
@@ -106,14 +120,14 @@ jobs:
|
||||
cache-to: type=gha,scope=${{ github.ref_name }}-${{ env.IMAGE_TAG }}
|
||||
|
||||
- name: Generate SBOM
|
||||
uses: anchore/sbom-action@251a468eed47e5082b105c3ba6ee500c0e65a764 # v0.17.6
|
||||
uses: anchore/sbom-action@55dc4ee22412511ee8c3142cbea40418e6cec693 # v0.17.8
|
||||
with:
|
||||
image: ${{ env.IMAGE_TAG }}
|
||||
artifact-name: sbom-${{ env.IMAGE_NAME }}
|
||||
output-file: ./sbom-${{ env.IMAGE_NAME }}.spdx.json
|
||||
|
||||
- name: Attach SBOM to release
|
||||
uses: softprops/action-gh-release@de2c0eb89ae2a093876385947365aca7b0e5f844 # v1
|
||||
uses: softprops/action-gh-release@c95fe1489396fe8a9eb87c0abf8aa5b2ef267fda # v2
|
||||
with:
|
||||
tag_name: ${{ needs.release-please.outputs.tag_name }}
|
||||
files: ./sbom-${{ env.IMAGE_NAME }}.spdx.json
|
||||
|
||||
2
.github/workflows/semantic_pr.yaml
vendored
2
.github/workflows/semantic_pr.yaml
vendored
@@ -10,7 +10,7 @@ defaults:
|
||||
shell: bash
|
||||
jobs:
|
||||
validate:
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read # Needed for checking out the repository
|
||||
pull-requests: read # Needed for reading prs
|
||||
|
||||
4
.github/workflows/test.yaml
vendored
4
.github/workflows/test.yaml
vendored
@@ -18,13 +18,13 @@ jobs:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
||||
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5
|
||||
uses: actions/setup-go@0aaccfd150d50ccaeb58ebd88d36e91967a5f35b # v5
|
||||
with:
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
|
||||
- name: Run test
|
||||
run: go test ./... -coverprofile=coverage.txt
|
||||
- name: Upload coverage to Codecov
|
||||
uses: codecov/codecov-action@ab904c41d6ece82784817410c45d8b8c02684457 # v3
|
||||
uses: codecov/codecov-action@0565863a31f2c772f9f0395002a31e3f06189574 # v5
|
||||
env:
|
||||
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
||||
|
||||
@@ -1 +1 @@
|
||||
{".":"0.3.41"}
|
||||
{".":"0.4.2"}
|
||||
217
CHANGELOG.md
217
CHANGELOG.md
@@ -1,5 +1,222 @@
|
||||
# Changelog
|
||||
|
||||
## [0.4.2](https://github.com/k8sgpt-ai/k8sgpt/compare/v0.4.1...v0.4.2) (2025-03-28)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* old sonnet ([#1408](https://github.com/k8sgpt-ai/k8sgpt/issues/1408)) ([e5817f9](https://github.com/k8sgpt-ai/k8sgpt/commit/e5817f9e557f4f97b016a0a7b7674342c3a1773e))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **deps:** update k8s.io/utils digest to 1f6e0b7 ([#1405](https://github.com/k8sgpt-ai/k8sgpt/issues/1405)) ([f5eaf81](https://github.com/k8sgpt-ai/k8sgpt/commit/f5eaf817f0cf2b732013e67e94c758a225c35ba6))
|
||||
|
||||
|
||||
### Other
|
||||
|
||||
* **deps:** update actions/setup-go digest to 0aaccfd ([#1401](https://github.com/k8sgpt-ai/k8sgpt/issues/1401)) ([81d4aaf](https://github.com/k8sgpt-ai/k8sgpt/commit/81d4aaf402647bf4bcbc618fd82f9518cf3a5b4d))
|
||||
* **deps:** update actions/upload-artifact digest to ea165f8 ([#1402](https://github.com/k8sgpt-ai/k8sgpt/issues/1402)) ([eb381b8](https://github.com/k8sgpt-ai/k8sgpt/commit/eb381b8087bbb3216d9bcdcc88a71fbad9e31e41))
|
||||
* **deps:** update docker/login-action digest to 74a5d14 ([#1397](https://github.com/k8sgpt-ai/k8sgpt/issues/1397)) ([fdf8e7a](https://github.com/k8sgpt-ai/k8sgpt/commit/fdf8e7a95a6667b782e1e347a3b1d2fb0f2aafde))
|
||||
* fix error ([#1403](https://github.com/k8sgpt-ai/k8sgpt/issues/1403)) ([288ca86](https://github.com/k8sgpt-ai/k8sgpt/commit/288ca862b3aaf942e58aa0dad0e15e2fda84780f))
|
||||
|
||||
## [0.4.1](https://github.com/k8sgpt-ai/k8sgpt/compare/v0.4.0...v0.4.1) (2025-03-17)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* add amazon bedrock nova pro and nova lite models ([#1383](https://github.com/k8sgpt-ai/k8sgpt/issues/1383)) ([aa1e237](https://github.com/k8sgpt-ai/k8sgpt/commit/aa1e237ebb8c816383561c9b3e6a1ca0ddea8f78))
|
||||
* add custom restful backend for complex scenarios (e.g, rag) ([#1228](https://github.com/k8sgpt-ai/k8sgpt/issues/1228)) ([7540e00](https://github.com/k8sgpt-ai/k8sgpt/commit/7540e0084e0c0c44fc52ed9a906b76f9f2e6a981))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **deps:** update default model to gpt-4o for improved performance and cost efficiency ([#1332](https://github.com/k8sgpt-ai/k8sgpt/issues/1332)) ([4e39cb6](https://github.com/k8sgpt-ai/k8sgpt/commit/4e39cb65b3a7fc0d1c057c647794346e072d3fd0))
|
||||
* **deps:** update module golang.org/x/net to v0.36.0 [security] ([#1395](https://github.com/k8sgpt-ai/k8sgpt/issues/1395)) ([eb7b36a](https://github.com/k8sgpt-ai/k8sgpt/commit/eb7b36aa2764bc460ffc29a0aee18abe3631c2ed))
|
||||
|
||||
|
||||
### Other
|
||||
|
||||
* **deps:** update actions/setup-go digest to f111f33 ([#1364](https://github.com/k8sgpt-ai/k8sgpt/issues/1364)) ([f2fdfd8](https://github.com/k8sgpt-ai/k8sgpt/commit/f2fdfd8dcaae6f57378d50396c4746d738d38bf2))
|
||||
* **deps:** update goreleaser/goreleaser-action digest to 90a3faa ([#1308](https://github.com/k8sgpt-ai/k8sgpt/issues/1308)) ([d6d2e3b](https://github.com/k8sgpt-ai/k8sgpt/commit/d6d2e3bc4254877c8af61aba7386706e942e3fe9))
|
||||
* **deps:** update softprops/action-gh-release digest to c95fe14 ([#1359](https://github.com/k8sgpt-ai/k8sgpt/issues/1359)) ([db5e517](https://github.com/k8sgpt-ai/k8sgpt/commit/db5e517dbb23a4cb0f203427744f4007d6e9faa8))
|
||||
|
||||
## [0.4.0](https://github.com/k8sgpt-ai/k8sgpt/compare/v0.3.50...v0.4.0) (2025-03-06)
|
||||
|
||||
|
||||
### ⚠ BREAKING CHANGES
|
||||
|
||||
* Removal of Trivy ([#1386](https://github.com/k8sgpt-ai/k8sgpt/issues/1386))
|
||||
|
||||
### Features
|
||||
|
||||
* Removal of Trivy ([#1386](https://github.com/k8sgpt-ai/k8sgpt/issues/1386)) ([d1b2227](https://github.com/k8sgpt-ai/k8sgpt/commit/d1b2227ff9a8ef42bf63c83e289fbd801706821e))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* [Bug] Filter PolicyReport ignores namespace flag ([#1355](https://github.com/k8sgpt-ai/k8sgpt/issues/1355)) ([9dcb21e](https://github.com/k8sgpt-ai/k8sgpt/commit/9dcb21e160233eb120ccf50f9b9b80c145d0e01a))
|
||||
|
||||
|
||||
### Other
|
||||
|
||||
* Adding region ([#1388](https://github.com/k8sgpt-ai/k8sgpt/issues/1388)) ([4f4f4f1](https://github.com/k8sgpt-ai/k8sgpt/commit/4f4f4f13a065ca7add283088c93777f78dcea228))
|
||||
* **deps:** update actions/upload-artifact digest to 4cec3d8 ([#1378](https://github.com/k8sgpt-ai/k8sgpt/issues/1378)) ([093975e](https://github.com/k8sgpt-ai/k8sgpt/commit/093975e50ddadeab70a7c4f544df8351ac9758a2))
|
||||
* **deps:** update codecov/codecov-action digest to 0565863 ([#1387](https://github.com/k8sgpt-ai/k8sgpt/issues/1387)) ([2a6f485](https://github.com/k8sgpt-ai/k8sgpt/commit/2a6f48500c4567519453fc51ea070f5e407d3cfb))
|
||||
* **deps:** update docker/build-push-action digest to 471d1dc ([#1358](https://github.com/k8sgpt-ai/k8sgpt/issues/1358)) ([f2e3b9a](https://github.com/k8sgpt-ai/k8sgpt/commit/f2e3b9a8a72c4df32713197e50756e37e1302ff9))
|
||||
* remediating security issue ([#1381](https://github.com/k8sgpt-ai/k8sgpt/issues/1381)) ([1f95358](https://github.com/k8sgpt-ai/k8sgpt/commit/1f953585c91f8a208db3b37440e4d458b8d821eb))
|
||||
|
||||
## [0.3.50](https://github.com/k8sgpt-ai/k8sgpt/compare/v0.3.49...v0.3.50) (2025-02-24)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* rework to how bedrock data models are structured and accessed ([#1369](https://github.com/k8sgpt-ai/k8sgpt/issues/1369)) ([7dadea2](https://github.com/k8sgpt-ai/k8sgpt/commit/7dadea257007df64148f1e47f7960d1d30df67b2))
|
||||
|
||||
## [0.3.49](https://github.com/k8sgpt-ai/k8sgpt/compare/v0.3.48...v0.3.49) (2025-02-20)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **deps:** update all non-major dependencies ([#1335](https://github.com/k8sgpt-ai/k8sgpt/issues/1335)) ([8cd3b29](https://github.com/k8sgpt-ai/k8sgpt/commit/8cd3b2985e4cd61711497fb0436e72b6b8aa3162))
|
||||
* **deps:** update k8s.io/utils digest to 24370be ([#1344](https://github.com/k8sgpt-ai/k8sgpt/issues/1344)) ([fcc8563](https://github.com/k8sgpt-ai/k8sgpt/commit/fcc8563e4eba9bf45d49901b7287d311b93372c2))
|
||||
* **deps:** update module golang.org/x/net to v0.33.0 [security] ([#1354](https://github.com/k8sgpt-ai/k8sgpt/issues/1354)) ([5de4f77](https://github.com/k8sgpt-ai/k8sgpt/commit/5de4f7704a856fd7db7b2f800bda40c5beb9333b))
|
||||
* **deps:** update module gopkg.in/yaml.v2 to v3 ([#1336](https://github.com/k8sgpt-ai/k8sgpt/issues/1336)) ([19abbef](https://github.com/k8sgpt-ai/k8sgpt/commit/19abbef9a3112ceb060ac3fd772e2e4f62f19f84))
|
||||
* prevent npe by handling checking error in NewAnalysis call ([#1365](https://github.com/k8sgpt-ai/k8sgpt/issues/1365)) ([83672fa](https://github.com/k8sgpt-ai/k8sgpt/commit/83672fa768887dd1c6f4dc12a92c3444f100c4f6))
|
||||
|
||||
|
||||
### Other
|
||||
|
||||
* **deps:** update actions/setup-go digest to 3041bf5 ([#1347](https://github.com/k8sgpt-ai/k8sgpt/issues/1347)) ([939e067](https://github.com/k8sgpt-ai/k8sgpt/commit/939e0672aaaa5538cd58bb171f1e5d1c07831651))
|
||||
* **deps:** update actions/upload-artifact digest to 65c4c4a ([#1350](https://github.com/k8sgpt-ai/k8sgpt/issues/1350)) ([c506a4b](https://github.com/k8sgpt-ai/k8sgpt/commit/c506a4b441e24052398c00c93d96806cec1b9f75))
|
||||
* **deps:** update codecov/codecov-action digest to 13ce06b ([#1342](https://github.com/k8sgpt-ai/k8sgpt/issues/1342)) ([990d723](https://github.com/k8sgpt-ai/k8sgpt/commit/990d7239091b368178e06af60e4dc0e897fc8236))
|
||||
* **deps:** update docker/setup-buildx-action digest to 6524bf6 ([#1349](https://github.com/k8sgpt-ai/k8sgpt/issues/1349)) ([2918556](https://github.com/k8sgpt-ai/k8sgpt/commit/2918556793316ea4f5a319c9aa51c1fec12ede85))
|
||||
* fix typo in "completion" ([#1362](https://github.com/k8sgpt-ai/k8sgpt/issues/1362)) ([06b8f78](https://github.com/k8sgpt-ai/k8sgpt/commit/06b8f78150308c1f6023747fa34826e038d6bc3a))
|
||||
|
||||
|
||||
### Docs
|
||||
|
||||
* fix broken schema link in README.md ([#1373](https://github.com/k8sgpt-ai/k8sgpt/issues/1373)) ([076ca2f](https://github.com/k8sgpt-ai/k8sgpt/commit/076ca2f14832cf83e43c465c377ef21825218b2f))
|
||||
|
||||
## [0.3.48](https://github.com/k8sgpt-ai/k8sgpt/compare/v0.3.47...v0.3.48) (2024-12-04)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* fixed missing cache params ([#1340](https://github.com/k8sgpt-ai/k8sgpt/issues/1340)) ([1363219](https://github.com/k8sgpt-ai/k8sgpt/commit/1363219b1b94e157ef03c53eba8838b7cef559b4))
|
||||
|
||||
## [0.3.47](https://github.com/k8sgpt-ai/k8sgpt/compare/v0.3.46...v0.3.47) (2024-12-02)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* add new AWS Bedrock model ids ([#1330](https://github.com/k8sgpt-ai/k8sgpt/issues/1330)) ([a12aa07](https://github.com/k8sgpt-ai/k8sgpt/commit/a12aa07b1a2e34c5106b7b930b29b0c97b172dc4))
|
||||
* adds interplex as a caching provider ([#1328](https://github.com/k8sgpt-ai/k8sgpt/issues/1328)) ([d6d80ee](https://github.com/k8sgpt-ai/k8sgpt/commit/d6d80ee86083643d9b91457791bfc77ef475e82e))
|
||||
* dump ([#1322](https://github.com/k8sgpt-ai/k8sgpt/issues/1322)) ([da266b3](https://github.com/k8sgpt-ai/k8sgpt/commit/da266b3c82ca8b3e96461be688a9f30e408568fe))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* add maxTokens to serve mode ([#1280](https://github.com/k8sgpt-ai/k8sgpt/issues/1280)) ([a50375c](https://github.com/k8sgpt-ai/k8sgpt/commit/a50375c9605a87546a0fcbcacabe5482fdfa1c2c))
|
||||
* **deps:** update all non-major dependencies ([#1323](https://github.com/k8sgpt-ai/k8sgpt/issues/1323)) ([b3f60b2](https://github.com/k8sgpt-ai/k8sgpt/commit/b3f60b2d2018d4bede3918adcb3547ef2acf6688))
|
||||
* **deps:** update module gopkg.in/yaml.v2 to v3 ([#1303](https://github.com/k8sgpt-ai/k8sgpt/issues/1303)) ([2da0573](https://github.com/k8sgpt-ai/k8sgpt/commit/2da057360b378d34126e1480ade0686f104e3ace))
|
||||
* **deps:** update module gopkg.in/yaml.v2 to v3 ([#1321](https://github.com/k8sgpt-ai/k8sgpt/issues/1321)) ([69c67bd](https://github.com/k8sgpt-ai/k8sgpt/commit/69c67bd1d9d4404816a8b7a00c98499729f2185f))
|
||||
* **deps:** update module gopkg.in/yaml.v2 to v3 ([#1326](https://github.com/k8sgpt-ai/k8sgpt/issues/1326)) ([5514ebb](https://github.com/k8sgpt-ai/k8sgpt/commit/5514ebb53b79b5bac0fc861ffdebc9399fe87b62))
|
||||
* update OpenAI API key generation URL to reflect new platform link ([#1331](https://github.com/k8sgpt-ai/k8sgpt/issues/1331)) ([ec5e42b](https://github.com/k8sgpt-ai/k8sgpt/commit/ec5e42b8f43e90632bb62dd89cc6aa3665e0f60d))
|
||||
|
||||
|
||||
### Other
|
||||
|
||||
* **deps:** update all non-major dependencies ([#1327](https://github.com/k8sgpt-ai/k8sgpt/issues/1327)) ([a841568](https://github.com/k8sgpt-ai/k8sgpt/commit/a841568a9c4c0012291cf8f4248250192b72a383))
|
||||
* **deps:** update codecov/codecov-action action to v5 ([#1324](https://github.com/k8sgpt-ai/k8sgpt/issues/1324)) ([cb1e1ff](https://github.com/k8sgpt-ai/k8sgpt/commit/cb1e1ffede1d3086d54157142c6803341e560ca8))
|
||||
* **deps:** update codecov/codecov-action digest to 015f24e ([#1325](https://github.com/k8sgpt-ai/k8sgpt/issues/1325)) ([4d7eb0f](https://github.com/k8sgpt-ai/k8sgpt/commit/4d7eb0f6226fc50f58b5c2fff7534dd16e2ca378))
|
||||
* **deps:** update docker/build-push-action action to v6 ([#1294](https://github.com/k8sgpt-ai/k8sgpt/issues/1294)) ([f37d923](https://github.com/k8sgpt-ai/k8sgpt/commit/f37d92391877819c6d26a993ab58bc0c49fb3b66))
|
||||
* **deps:** update docker/build-push-action digest to 48aba3b ([#1333](https://github.com/k8sgpt-ai/k8sgpt/issues/1333)) ([c21ba86](https://github.com/k8sgpt-ai/k8sgpt/commit/c21ba86237db651086c0a37abc3454db513e505b))
|
||||
* **deps:** update rajatjindal/krew-release-bot action to v0.0.47 ([#1317](https://github.com/k8sgpt-ai/k8sgpt/issues/1317)) ([896a53b](https://github.com/k8sgpt-ai/k8sgpt/commit/896a53be8394c490e2d34f151de44c3663dddf5b))
|
||||
|
||||
## [0.3.46](https://github.com/k8sgpt-ai/k8sgpt/compare/v0.3.45...v0.3.46) (2024-11-10)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* reverting the cncf runners ([#1319](https://github.com/k8sgpt-ai/k8sgpt/issues/1319)) ([ad86e7a](https://github.com/k8sgpt-ai/k8sgpt/commit/ad86e7aa39995c492437627dbd9f89f152f11f2c))
|
||||
* switching to higher spec runners ([#1312](https://github.com/k8sgpt-ai/k8sgpt/issues/1312)) ([5f7d9de](https://github.com/k8sgpt-ai/k8sgpt/commit/5f7d9de46a521463cedc901b729fe27f8d86f381))
|
||||
* testupdate ([#1315](https://github.com/k8sgpt-ai/k8sgpt/issues/1315)) ([7dcdfc8](https://github.com/k8sgpt-ai/k8sgpt/commit/7dcdfc83d2461e4342ded5fa80493936b70f64a1))
|
||||
* updated runners to enterprise ([#1318](https://github.com/k8sgpt-ai/k8sgpt/issues/1318)) ([1ae70e8](https://github.com/k8sgpt-ai/k8sgpt/commit/1ae70e806e2609c8fb964f0a577304d07b365cae))
|
||||
|
||||
|
||||
### Other
|
||||
|
||||
* **deps:** update actions/setup-go digest to 41dfa10 ([#1284](https://github.com/k8sgpt-ai/k8sgpt/issues/1284)) ([2ce8450](https://github.com/k8sgpt-ai/k8sgpt/commit/2ce8450e03986904a7ffe7afac4b5ba777c67c57))
|
||||
* **deps:** update softprops/action-gh-release action to v2 ([#1295](https://github.com/k8sgpt-ai/k8sgpt/issues/1295)) ([b6b3d0c](https://github.com/k8sgpt-ai/k8sgpt/commit/b6b3d0c8566b0dbd9cb0e5f59c8493e4343e0106))
|
||||
|
||||
## [0.3.45](https://github.com/k8sgpt-ai/k8sgpt/compare/v0.3.44...v0.3.45) (2024-11-10)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* free disk ([#1313](https://github.com/k8sgpt-ai/k8sgpt/issues/1313)) ([783cd1c](https://github.com/k8sgpt-ai/k8sgpt/commit/783cd1cfc66f8e4489e5006529745d8caf38cfd4))
|
||||
|
||||
## [0.3.44](https://github.com/k8sgpt-ai/k8sgpt/compare/v0.3.43...v0.3.44) (2024-11-09)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* test revert runner on release job ([#1310](https://github.com/k8sgpt-ai/k8sgpt/issues/1310)) ([cc9b3ea](https://github.com/k8sgpt-ai/k8sgpt/commit/cc9b3ea6579c6190629e0fac48e37e0eba650158))
|
||||
|
||||
## [0.3.43](https://github.com/k8sgpt-ai/k8sgpt/compare/v0.3.42...v0.3.43) (2024-11-05)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **deps:** update module gopkg.in/yaml.v2 to v3 ([#1296](https://github.com/k8sgpt-ai/k8sgpt/issues/1296)) ([2f75986](https://github.com/k8sgpt-ai/k8sgpt/commit/2f759865b6fc5ae143c8f5e89a306abc89d4de27))
|
||||
|
||||
|
||||
### Other
|
||||
|
||||
* **deps:** update dependency ubuntu to v24 ([#1293](https://github.com/k8sgpt-ai/k8sgpt/issues/1293)) ([c67add3](https://github.com/k8sgpt-ai/k8sgpt/commit/c67add30c64257ac6258dec93193e3201ba8c4ab))
|
||||
|
||||
## [0.3.42](https://github.com/k8sgpt-ai/k8sgpt/compare/v0.3.41...v0.3.42) (2024-11-04)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* add stats option to analyze command for performance insights ([#1237](https://github.com/k8sgpt-ai/k8sgpt/issues/1237)) ([3eec9bb](https://github.com/k8sgpt-ai/k8sgpt/commit/3eec9bbb05b2f0717437cc4a2ec786594ece1cc3))
|
||||
* error from events for STS analyzer ([#1256](https://github.com/k8sgpt-ai/k8sgpt/issues/1256)) ([d8fad95](https://github.com/k8sgpt-ai/k8sgpt/commit/d8fad956f45a4dd668647379bb0295e169faeac6))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* [Bug] Make lint command is not working ([#1282](https://github.com/k8sgpt-ai/k8sgpt/issues/1282)) ([87565a0](https://github.com/k8sgpt-ai/k8sgpt/commit/87565a0bcce7087114798c3a32877894c8a9dcee))
|
||||
* add providerId to serve mode ([#1260](https://github.com/k8sgpt-ai/k8sgpt/issues/1260)) ([da0764d](https://github.com/k8sgpt-ai/k8sgpt/commit/da0764d951ca76cb7007c412f8efa794619c20ba))
|
||||
* **deps:** update all non-major dependencies ([#1291](https://github.com/k8sgpt-ai/k8sgpt/issues/1291)) ([14e0f19](https://github.com/k8sgpt-ai/k8sgpt/commit/14e0f19b12189052b03d551e409b407fd0b6bd30))
|
||||
* **deps:** update k8s.io/utils digest to 49e7df5 ([#1259](https://github.com/k8sgpt-ai/k8sgpt/issues/1259)) ([7785dd1](https://github.com/k8sgpt-ai/k8sgpt/commit/7785dd12a0245a33af25dedd2fbb5f4178b5cda9))
|
||||
* **deps:** update module buf.build/gen/go/k8sgpt-ai/k8sgpt/protocolbuffers/go to v1.35.1-20240920204244-7a91c8620515.1 ([#1274](https://github.com/k8sgpt-ai/k8sgpt/issues/1274)) ([9f39abf](https://github.com/k8sgpt-ai/k8sgpt/commit/9f39abf89e4e92009f5e138d9b01d11c60ac135c))
|
||||
* **deps:** update module cloud.google.com/go/storage to v1.44.0 ([#1265](https://github.com/k8sgpt-ai/k8sgpt/issues/1265)) ([4143e9f](https://github.com/k8sgpt-ai/k8sgpt/commit/4143e9fd524bed3179524d949b7b0f92c02ecd11))
|
||||
* **deps:** update module github.com/adrg/xdg to v0.5.0 ([#1262](https://github.com/k8sgpt-ai/k8sgpt/issues/1262)) ([98237b6](https://github.com/k8sgpt-ai/k8sgpt/commit/98237b6408521ee7afc05fcaed2f78ba79e77144))
|
||||
* **deps:** update module github.com/aquasecurity/trivy-operator to v0.22.0 ([#1034](https://github.com/k8sgpt-ai/k8sgpt/issues/1034)) ([037e745](https://github.com/k8sgpt-ai/k8sgpt/commit/037e745c6f667830f0e1d531ce4bbd07083ef972))
|
||||
* **deps:** update module github.com/aws/aws-sdk-go to v1.55.5 ([#1263](https://github.com/k8sgpt-ai/k8sgpt/issues/1263)) ([0148a5b](https://github.com/k8sgpt-ai/k8sgpt/commit/0148a5b3549cbdb6c6e5832dc01aab044b90ddc9))
|
||||
* **deps:** update module github.com/azure/azure-sdk-for-go/sdk/azidentity to v1.8.0 ([#1264](https://github.com/k8sgpt-ai/k8sgpt/issues/1264)) ([3613585](https://github.com/k8sgpt-ai/k8sgpt/commit/36135857ac55e126b3a6c4533a000cb0b7f32c6b))
|
||||
* **deps:** update module github.com/azure/azure-sdk-for-go/sdk/storage/azblob to v1.4.1 ([#1275](https://github.com/k8sgpt-ai/k8sgpt/issues/1275)) ([c9b11b6](https://github.com/k8sgpt-ai/k8sgpt/commit/c9b11b6eee00d0269a4d48ad2e4be5458436b51d))
|
||||
* **deps:** update module github.com/cohere-ai/cohere-go/v2 to v2.12.0 ([#1276](https://github.com/k8sgpt-ai/k8sgpt/issues/1276)) ([7a3fb3c](https://github.com/k8sgpt-ai/k8sgpt/commit/7a3fb3cf6777d5b0babf00455c3833a47bb1bfdb))
|
||||
* **deps:** update module github.com/google/generative-ai-go to v0.18.0 ([#1278](https://github.com/k8sgpt-ai/k8sgpt/issues/1278)) ([ad349ae](https://github.com/k8sgpt-ai/k8sgpt/commit/ad349ae263f226e300f60dd092729c5a3bf61dbe))
|
||||
* rename watsonxai to ibmwatsonxai ([#1234](https://github.com/k8sgpt-ai/k8sgpt/issues/1234)) ([5ff6dc9](https://github.com/k8sgpt-ai/k8sgpt/commit/5ff6dc9be5218e47839c4ac5e8f3458b40eb9c88))
|
||||
|
||||
|
||||
### Other
|
||||
|
||||
* **deps:** update actions/checkout digest to 11bd719 ([#1283](https://github.com/k8sgpt-ai/k8sgpt/issues/1283)) ([0cfecbd](https://github.com/k8sgpt-ai/k8sgpt/commit/0cfecbdd87586fd138cc63c4e7a26d54e7ed83a8))
|
||||
* **deps:** update actions/checkout digest to eef6144 ([#1270](https://github.com/k8sgpt-ai/k8sgpt/issues/1270)) ([72eb815](https://github.com/k8sgpt-ai/k8sgpt/commit/72eb8159fb4a2284cf43eb6a5f3de7bed10c6224))
|
||||
* **deps:** update actions/upload-artifact digest to b4b15b8 ([#1272](https://github.com/k8sgpt-ai/k8sgpt/issues/1272)) ([911d578](https://github.com/k8sgpt-ai/k8sgpt/commit/911d578bf006253d10fe21d96888ddf34a8b4691))
|
||||
* **deps:** update anchore/sbom-action action to v0.17.2 ([#1248](https://github.com/k8sgpt-ai/k8sgpt/issues/1248)) ([04582d8](https://github.com/k8sgpt-ai/k8sgpt/commit/04582d85160055da30e4e00fd3c6ca69d1decd1a))
|
||||
* **deps:** update anchore/sbom-action action to v0.17.4 ([#1273](https://github.com/k8sgpt-ai/k8sgpt/issues/1273)) ([c128bf7](https://github.com/k8sgpt-ai/k8sgpt/commit/c128bf7942e380fcab5e9771f405471198e388fe))
|
||||
* **deps:** update anchore/sbom-action action to v0.17.6 ([#1285](https://github.com/k8sgpt-ai/k8sgpt/issues/1285)) ([173e4dc](https://github.com/k8sgpt-ai/k8sgpt/commit/173e4dc5ac6265af4a3538556220d3a43ab721f7))
|
||||
* **deps:** update codecov/codecov-action action to v4 ([#1292](https://github.com/k8sgpt-ai/k8sgpt/issues/1292)) ([c1a38c2](https://github.com/k8sgpt-ai/k8sgpt/commit/c1a38c2b35a0bfa772b88f15843c9354b0345284))
|
||||
* **deps:** update docker/setup-buildx-action digest to c47758b ([#1213](https://github.com/k8sgpt-ai/k8sgpt/issues/1213)) ([161bc11](https://github.com/k8sgpt-ai/k8sgpt/commit/161bc11294d5094533068cf7af9880795a61536e))
|
||||
* **deps:** update golang docker tag to v1.23 ([#1254](https://github.com/k8sgpt-ai/k8sgpt/issues/1254)) ([b62b7db](https://github.com/k8sgpt-ai/k8sgpt/commit/b62b7dbe3c9cd02b81f6a0111bca939034c5cc9f))
|
||||
* **deps:** update module github.com/docker/docker to v27.3.1+incompatible ([#1225](https://github.com/k8sgpt-ai/k8sgpt/issues/1225)) ([9c1927b](https://github.com/k8sgpt-ai/k8sgpt/commit/9c1927b4975fa8132fbc24dd96a5737819855544))
|
||||
* renovate.json ([#1290](https://github.com/k8sgpt-ai/k8sgpt/issues/1290)) ([458fcfe](https://github.com/k8sgpt-ai/k8sgpt/commit/458fcfe8d330523781d32af680febc2a0c0525a2))
|
||||
|
||||
## [0.3.41](https://github.com/k8sgpt-ai/k8sgpt/compare/v0.3.40...v0.3.41) (2024-09-22)
|
||||
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
We're happy that you want to contribute to this project. Please read the sections to make the process as smooth as possible.
|
||||
|
||||
## Requirements
|
||||
- Golang `1.20`
|
||||
- Golang `1.23`
|
||||
- An OpenAI API key
|
||||
* OpenAI API keys can be obtained from [OpenAI](https://platform.openai.com/account/api-keys)
|
||||
* You can set the API key for k8sgpt using `./k8sgpt auth key`
|
||||
|
||||
23
README.md
23
README.md
@@ -49,7 +49,7 @@ brew install k8sgpt
|
||||
<!---x-release-please-start-version-->
|
||||
|
||||
```
|
||||
sudo rpm -ivh https://github.com/k8sgpt-ai/k8sgpt/releases/download/v0.3.41/k8sgpt_386.rpm
|
||||
sudo rpm -ivh https://github.com/k8sgpt-ai/k8sgpt/releases/download/v0.4.2/k8sgpt_386.rpm
|
||||
```
|
||||
<!---x-release-please-end-->
|
||||
|
||||
@@ -57,7 +57,7 @@ brew install k8sgpt
|
||||
|
||||
<!---x-release-please-start-version-->
|
||||
```
|
||||
sudo rpm -ivh https://github.com/k8sgpt-ai/k8sgpt/releases/download/v0.3.41/k8sgpt_amd64.rpm
|
||||
sudo rpm -ivh https://github.com/k8sgpt-ai/k8sgpt/releases/download/v0.4.2/k8sgpt_amd64.rpm
|
||||
```
|
||||
<!---x-release-please-end-->
|
||||
</details>
|
||||
@@ -70,7 +70,7 @@ brew install k8sgpt
|
||||
<!---x-release-please-start-version-->
|
||||
|
||||
```
|
||||
curl -LO https://github.com/k8sgpt-ai/k8sgpt/releases/download/v0.3.41/k8sgpt_386.deb
|
||||
curl -LO https://github.com/k8sgpt-ai/k8sgpt/releases/download/v0.4.2/k8sgpt_386.deb
|
||||
sudo dpkg -i k8sgpt_386.deb
|
||||
```
|
||||
|
||||
@@ -81,7 +81,7 @@ sudo dpkg -i k8sgpt_386.deb
|
||||
<!---x-release-please-start-version-->
|
||||
|
||||
```
|
||||
curl -LO https://github.com/k8sgpt-ai/k8sgpt/releases/download/v0.3.41/k8sgpt_amd64.deb
|
||||
curl -LO https://github.com/k8sgpt-ai/k8sgpt/releases/download/v0.4.2/k8sgpt_amd64.deb
|
||||
sudo dpkg -i k8sgpt_amd64.deb
|
||||
```
|
||||
|
||||
@@ -96,7 +96,7 @@ sudo dpkg -i k8sgpt_amd64.deb
|
||||
|
||||
<!---x-release-please-start-version-->
|
||||
```
|
||||
wget https://github.com/k8sgpt-ai/k8sgpt/releases/download/v0.3.41/k8sgpt_386.apk
|
||||
wget https://github.com/k8sgpt-ai/k8sgpt/releases/download/v0.4.2/k8sgpt_386.apk
|
||||
apk add --allow-untrusted k8sgpt_386.apk
|
||||
```
|
||||
<!---x-release-please-end-->
|
||||
@@ -105,7 +105,7 @@ sudo dpkg -i k8sgpt_amd64.deb
|
||||
|
||||
<!---x-release-please-start-version-->
|
||||
```
|
||||
wget https://github.com/k8sgpt-ai/k8sgpt/releases/download/v0.3.41/k8sgpt_amd64.apk
|
||||
wget https://github.com/k8sgpt-ai/k8sgpt/releases/download/v0.4.2/k8sgpt_amd64.apk
|
||||
apk add --allow-untrusted k8sgpt_amd64.apk
|
||||
```
|
||||
<!---x-release-please-end-->
|
||||
@@ -335,6 +335,13 @@ The stats mode allows for debugging and understanding the time taken by an analy
|
||||
- Analyzer Service took 38.583359166s
|
||||
```
|
||||
|
||||
_Diagnostic information_
|
||||
|
||||
To collect diagnostic information use the following command to create a `dump_<timestamp>_json` in your local directory.
|
||||
```
|
||||
k8sgpt dump
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
## LLM AI Backends
|
||||
@@ -359,6 +366,8 @@ Unused:
|
||||
> huggingface
|
||||
> noopai
|
||||
> googlevertexai
|
||||
> watsonxai
|
||||
> customrest
|
||||
> ibmwatsonxai
|
||||
```
|
||||
|
||||
@@ -522,7 +531,7 @@ k8sgpt cache remove
|
||||
<summary> Custom Analyzers</summary>
|
||||
|
||||
There may be scenarios where you wish to write your own analyzer in a language of your choice.
|
||||
K8sGPT now supports the ability to do so by abiding by the [schema](https://github.com/k8sgpt-ai/schemas/blob/main/protobuf/schema/v1/analyzer.proto) and serving the analyzer for consumption.
|
||||
K8sGPT now supports the ability to do so by abiding by the [schema](https://github.com/k8sgpt-ai/schemas/blob/main/protobuf/schema/v1/custom_analyzer.proto) and serving the analyzer for consumption.
|
||||
To do so, define the analyzer within the K8sGPT configuration and it will add it into the scanning process.
|
||||
In addition to this you will need to enable the following flag on analysis:
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ import (
|
||||
|
||||
const (
|
||||
defaultBackend = "openai"
|
||||
defaultModel = "gpt-3.5-turbo"
|
||||
defaultModel = "gpt-4o"
|
||||
)
|
||||
|
||||
var addCmd = &cobra.Command{
|
||||
|
||||
10
cmd/cache/add.go
vendored
10
cmd/cache/add.go
vendored
@@ -17,6 +17,7 @@ package cache
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/fatih/color"
|
||||
"github.com/k8sgpt-ai/k8sgpt/pkg/cache"
|
||||
@@ -40,9 +41,10 @@ var addCmd = &cobra.Command{
|
||||
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`,
|
||||
- Azure Blob storage (e.g., k8sgpt cache add azure)
|
||||
- Google Cloud storage (e.g., k8sgpt cache add gcs)
|
||||
- S3 (e.g., k8sgpt cache add s3)
|
||||
- Interplex (e.g., k8sgpt cache add interplex)`,
|
||||
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")
|
||||
@@ -50,7 +52,7 @@ var addCmd = &cobra.Command{
|
||||
}
|
||||
fmt.Println(color.YellowString("Adding remote based cache"))
|
||||
cacheType := args[0]
|
||||
remoteCache, err := cache.NewCacheProvider(cacheType, bucketName, region, endpoint, storageAccount, containerName, projectId, insecure)
|
||||
remoteCache, err := cache.NewCacheProvider(strings.ToLower(cacheType), bucketName, region, endpoint, storageAccount, containerName, projectId, insecure)
|
||||
if err != nil {
|
||||
color.Red("Error: %v", err)
|
||||
os.Exit(1)
|
||||
|
||||
45
cmd/cache/get.go
vendored
Normal file
45
cmd/cache/get.go
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
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"
|
||||
"github.com/fatih/color"
|
||||
"github.com/k8sgpt-ai/k8sgpt/pkg/cache"
|
||||
"github.com/spf13/cobra"
|
||||
"os"
|
||||
)
|
||||
|
||||
// listCmd represents the list command
|
||||
var getCmd = &cobra.Command{
|
||||
Use: "get",
|
||||
Short: "Get the current cache",
|
||||
Long: `Returns the current remote cache being used`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
|
||||
// load remote cache if it is configured
|
||||
c, err := cache.GetCacheConfiguration()
|
||||
if err != nil {
|
||||
color.Red("Error: %v", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
fmt.Printf("Current remote cache is: %s", c.GetName())
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
CacheCmd.AddCommand(getCmd)
|
||||
|
||||
}
|
||||
113
cmd/dump/dump.go
Normal file
113
cmd/dump/dump.go
Normal file
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
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 dump
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/fatih/color"
|
||||
"github.com/k8sgpt-ai/k8sgpt/pkg/ai"
|
||||
"github.com/k8sgpt-ai/k8sgpt/pkg/kubernetes"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
"k8s.io/apimachinery/pkg/version"
|
||||
)
|
||||
|
||||
type K8sGPTInfo struct {
|
||||
Version string
|
||||
Commit string
|
||||
Date string
|
||||
}
|
||||
type DumpOut struct {
|
||||
AIConfiguration ai.AIConfiguration
|
||||
ActiveFilters []string
|
||||
KubenetesServerVersion *version.Info
|
||||
K8sGPTInfo K8sGPTInfo
|
||||
}
|
||||
|
||||
var DumpCmd = &cobra.Command{
|
||||
Use: "dump",
|
||||
Short: "Creates a dumpfile for debugging issues with K8sGPT",
|
||||
Long: `The dump command will create a dump.*.json which will contain K8sGPT non-sensitive configuration information.`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
|
||||
// Fetch the configuration object(s)
|
||||
// get ai configuration
|
||||
var configAI ai.AIConfiguration
|
||||
err := viper.UnmarshalKey("ai", &configAI)
|
||||
if err != nil {
|
||||
color.Red("Error: %v", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
var newProvider []ai.AIProvider
|
||||
for _, config := range configAI.Providers {
|
||||
// we blank out the custom headers for data protection reasons
|
||||
config.CustomHeaders = make([]http.Header, 0)
|
||||
// blank out the password
|
||||
if len(config.Password) > 4 {
|
||||
config.Password = config.Password[:4] + "***"
|
||||
} else {
|
||||
// If the password is shorter than 4 characters
|
||||
config.Password = "***"
|
||||
}
|
||||
newProvider = append(newProvider, config)
|
||||
}
|
||||
configAI.Providers = newProvider
|
||||
activeFilters := viper.GetStringSlice("active_filters")
|
||||
kubecontext := viper.GetString("kubecontext")
|
||||
kubeconfig := viper.GetString("kubeconfig")
|
||||
client, err := kubernetes.NewClient(kubecontext, kubeconfig)
|
||||
if err != nil {
|
||||
color.Red("Error: %v", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
v, err := client.Client.Discovery().ServerVersion()
|
||||
if err != nil {
|
||||
color.Yellow("Could not find kubernetes server version")
|
||||
}
|
||||
var dumpOut DumpOut = DumpOut{
|
||||
AIConfiguration: configAI,
|
||||
ActiveFilters: activeFilters,
|
||||
KubenetesServerVersion: v,
|
||||
K8sGPTInfo: K8sGPTInfo{
|
||||
Version: viper.GetString("Version"),
|
||||
Commit: viper.GetString("Commit"),
|
||||
Date: viper.GetString("Date"),
|
||||
},
|
||||
}
|
||||
// Serialize dumpOut to JSON
|
||||
jsonData, err := json.MarshalIndent(dumpOut, "", " ")
|
||||
if err != nil {
|
||||
color.Red("Error: %v", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
// Write JSON data to file
|
||||
f := fmt.Sprintf("dump_%s.json", time.Now().Format("20060102150405"))
|
||||
err = os.WriteFile(f, jsonData, 0644)
|
||||
if err != nil {
|
||||
color.Red("Error: %v", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
color.Green("Dump created successfully: %s", f)
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
|
||||
}
|
||||
@@ -45,7 +45,7 @@ var GenerateCmd = &cobra.Command{
|
||||
backendType = backend
|
||||
}
|
||||
fmt.Println("")
|
||||
openbrowser("https://beta.openai.com/account/api-keys")
|
||||
openbrowser("https://platform.openai.com/api-keys")
|
||||
},
|
||||
}
|
||||
|
||||
@@ -81,10 +81,10 @@ func openbrowser(url string) {
|
||||
func printInstructions(isGui bool, backendType string) {
|
||||
fmt.Println("")
|
||||
if isGui {
|
||||
color.Green("Opening: https://beta.openai.com/account/api-keys to generate a key for %s", backendType)
|
||||
color.Green("Opening: https://platform.openai.com/api-keys to generate a key for %s", backendType)
|
||||
fmt.Println("")
|
||||
} else {
|
||||
color.Green("Please open: https://beta.openai.com/account/api-keys to generate a key for %s", backendType)
|
||||
color.Green("Please open: https://platform.openai.com/api-keys to generate a key for %s", backendType)
|
||||
fmt.Println("")
|
||||
}
|
||||
color.Green("Please copy the generated key and run `k8sgpt auth add` to add it to your config file")
|
||||
|
||||
@@ -24,7 +24,7 @@ var deactivateCmd = &cobra.Command{
|
||||
Use: "deactivate [integration]",
|
||||
Short: "Deactivate an integration",
|
||||
Args: cobra.ExactArgs(1),
|
||||
Long: `For example e.g. k8sgpt integration deactivate trivy`,
|
||||
Long: `For example e.g. k8sgpt integration deactivate prometheus`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
integrationName := args[0]
|
||||
|
||||
|
||||
@@ -28,9 +28,9 @@ var IntegrationCmd = &cobra.Command{
|
||||
Short: "Integrate another tool into K8sGPT",
|
||||
Long: `Integrate another tool into K8sGPT. For example:
|
||||
|
||||
k8sgpt integration activate trivy
|
||||
k8sgpt integration activate prometheus
|
||||
|
||||
This would allow you to deploy trivy into your cluster and use a K8sGPT analyzer to parse trivy results.`,
|
||||
This would allow you to connect to prometheus running with your cluster.`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
_ = cmd.Help()
|
||||
},
|
||||
|
||||
@@ -23,6 +23,7 @@ import (
|
||||
"github.com/k8sgpt-ai/k8sgpt/cmd/auth"
|
||||
"github.com/k8sgpt-ai/k8sgpt/cmd/cache"
|
||||
customanalyzer "github.com/k8sgpt-ai/k8sgpt/cmd/customAnalyzer"
|
||||
"github.com/k8sgpt-ai/k8sgpt/cmd/dump"
|
||||
"github.com/k8sgpt-ai/k8sgpt/cmd/filters"
|
||||
"github.com/k8sgpt-ai/k8sgpt/cmd/generate"
|
||||
"github.com/k8sgpt-ai/k8sgpt/cmd/integration"
|
||||
@@ -57,6 +58,9 @@ func Execute(v string, c string, d string) {
|
||||
Version = v
|
||||
Commit = c
|
||||
Date = d
|
||||
viper.Set("Version", Version)
|
||||
viper.Set("Commit", Commit)
|
||||
viper.Set("Date", Date)
|
||||
err := rootCmd.Execute()
|
||||
if err != nil {
|
||||
os.Exit(1)
|
||||
@@ -70,6 +74,7 @@ func init() {
|
||||
|
||||
rootCmd.AddCommand(auth.AuthCmd)
|
||||
rootCmd.AddCommand(analyze.AnalyzeCmd)
|
||||
rootCmd.AddCommand(dump.DumpCmd)
|
||||
rootCmd.AddCommand(filters.FiltersCmd)
|
||||
rootCmd.AddCommand(generate.GenerateCmd)
|
||||
rootCmd.AddCommand(integration.IntegrationCmd)
|
||||
|
||||
@@ -30,6 +30,7 @@ const (
|
||||
defaultTemperature float32 = 0.7
|
||||
defaultTopP float32 = 1.0
|
||||
defaultTopK int32 = 50
|
||||
defaultMaxTokens int = 2048
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -102,6 +103,18 @@ var ServeCmd = &cobra.Command{
|
||||
}
|
||||
return int32(topK)
|
||||
}
|
||||
maxTokens := func() int {
|
||||
env := os.Getenv("K8SGPT_MAX_TOKENS")
|
||||
if env == "" {
|
||||
return defaultMaxTokens
|
||||
}
|
||||
maxTokens, err := strconv.ParseInt(env, 10, 32)
|
||||
if err != nil {
|
||||
color.Red("Unable to convert maxTokens value: %v", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
return int(maxTokens)
|
||||
}
|
||||
// Check for env injection
|
||||
backend = os.Getenv("K8SGPT_BACKEND")
|
||||
password := os.Getenv("K8SGPT_PASSWORD")
|
||||
@@ -125,6 +138,7 @@ var ServeCmd = &cobra.Command{
|
||||
Temperature: temperature(),
|
||||
TopP: topP(),
|
||||
TopK: topK(),
|
||||
MaxTokens: maxTokens(),
|
||||
}
|
||||
|
||||
configAI.Providers = append(configAI.Providers, *aiProvider)
|
||||
|
||||
271
go.mod
271
go.mod
@@ -1,56 +1,55 @@
|
||||
module github.com/k8sgpt-ai/k8sgpt
|
||||
|
||||
go 1.22.3
|
||||
|
||||
toolchain go1.23.2
|
||||
go 1.23.3
|
||||
|
||||
require (
|
||||
github.com/aquasecurity/trivy-operator v0.22.0
|
||||
github.com/fatih/color v1.17.0
|
||||
github.com/kedacore/keda/v2 v2.11.2
|
||||
github.com/magiconair/properties v1.8.7
|
||||
github.com/mittwald/go-helm-client v0.12.13
|
||||
github.com/ollama/ollama v0.1.48
|
||||
github.com/sashabaranov/go-openai v1.23.0
|
||||
github.com/schollz/progressbar/v3 v3.15.0
|
||||
github.com/fatih/color v1.18.0
|
||||
github.com/kedacore/keda/v2 v2.16.0
|
||||
github.com/magiconair/properties v1.8.9
|
||||
github.com/mittwald/go-helm-client v0.12.14
|
||||
github.com/ollama/ollama v0.5.1
|
||||
github.com/sashabaranov/go-openai v1.36.0
|
||||
github.com/schollz/progressbar/v3 v3.17.1
|
||||
github.com/spf13/cobra v1.8.1
|
||||
github.com/spf13/viper v1.19.0
|
||||
github.com/stretchr/testify v1.9.0
|
||||
golang.org/x/term v0.24.0
|
||||
helm.sh/helm/v3 v3.15.4
|
||||
k8s.io/api v0.30.3
|
||||
k8s.io/apimachinery v0.30.3
|
||||
k8s.io/client-go v0.30.3
|
||||
k8s.io/kubectl v0.30.3 // indirect
|
||||
github.com/stretchr/testify v1.10.0
|
||||
golang.org/x/term v0.29.0
|
||||
helm.sh/helm/v3 v3.16.3
|
||||
k8s.io/api v0.31.3
|
||||
k8s.io/apimachinery v0.31.3
|
||||
k8s.io/client-go v0.31.3
|
||||
k8s.io/kubectl v0.31.1 // indirect
|
||||
|
||||
)
|
||||
|
||||
require github.com/adrg/xdg v0.5.0
|
||||
require github.com/adrg/xdg v0.5.3
|
||||
|
||||
require (
|
||||
buf.build/gen/go/k8sgpt-ai/k8sgpt/grpc-ecosystem/gateway/v2 v2.22.0-20240920204244-7a91c8620515.1
|
||||
buf.build/gen/go/k8sgpt-ai/k8sgpt/grpc/go v1.5.1-20240920204244-7a91c8620515.1
|
||||
buf.build/gen/go/k8sgpt-ai/k8sgpt/protocolbuffers/go v1.35.1-20240920204244-7a91c8620515.1
|
||||
cloud.google.com/go/storage v1.44.0
|
||||
cloud.google.com/go/vertexai v0.7.1
|
||||
buf.build/gen/go/interplex-ai/schemas/grpc/go v1.5.1-20241117203254-a91193b62179.1
|
||||
buf.build/gen/go/interplex-ai/schemas/protocolbuffers/go v1.35.2-20241117203254-a91193b62179.1
|
||||
buf.build/gen/go/k8sgpt-ai/k8sgpt/grpc-ecosystem/gateway/v2 v2.24.0-20241118152629-1379a5a1889d.1
|
||||
buf.build/gen/go/k8sgpt-ai/k8sgpt/grpc/go v1.5.1-20241118152629-1379a5a1889d.1
|
||||
buf.build/gen/go/k8sgpt-ai/k8sgpt/protocolbuffers/go v1.35.2-20241118152629-1379a5a1889d.1
|
||||
cloud.google.com/go/storage v1.48.0
|
||||
cloud.google.com/go/vertexai v0.13.2
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.0
|
||||
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.4.1
|
||||
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.5.0
|
||||
github.com/IBM/watsonx-go v1.0.1
|
||||
github.com/aws/aws-sdk-go v1.55.5
|
||||
github.com/cohere-ai/cohere-go/v2 v2.12.0
|
||||
github.com/cohere-ai/cohere-go/v2 v2.12.2
|
||||
github.com/go-logr/zapr v1.3.0
|
||||
github.com/google/generative-ai-go v0.18.0
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0
|
||||
github.com/google/generative-ai-go v0.19.0
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.24.0
|
||||
github.com/hupe1980/go-huggingface v0.0.15
|
||||
github.com/kyverno/policy-reporter-kyverno-plugin v1.6.3
|
||||
github.com/kyverno/policy-reporter-kyverno-plugin v1.6.4
|
||||
github.com/olekukonko/tablewriter v0.0.5
|
||||
github.com/oracle/oci-go-sdk/v65 v65.65.1
|
||||
github.com/prometheus/prometheus v0.53.1
|
||||
github.com/pterm/pterm v0.12.79
|
||||
google.golang.org/api v0.197.0
|
||||
github.com/oracle/oci-go-sdk/v65 v65.79.0
|
||||
github.com/prometheus/prometheus v0.300.1
|
||||
github.com/pterm/pterm v0.12.80
|
||||
google.golang.org/api v0.210.0
|
||||
gopkg.in/yaml.v2 v2.4.0
|
||||
sigs.k8s.io/controller-runtime v0.18.4
|
||||
sigs.k8s.io/gateway-api v1.0.0
|
||||
sigs.k8s.io/controller-runtime v0.19.3
|
||||
sigs.k8s.io/gateway-api v1.2.1
|
||||
)
|
||||
|
||||
require (
|
||||
@@ -58,139 +57,86 @@ require (
|
||||
atomicgo.dev/keyboard v0.2.9 // indirect
|
||||
atomicgo.dev/schedule v0.1.0 // indirect
|
||||
cel.dev/expr v0.16.1 // indirect
|
||||
cloud.google.com/go v0.115.1 // indirect
|
||||
cloud.google.com/go v0.116.0 // indirect
|
||||
cloud.google.com/go/ai v0.8.0 // indirect
|
||||
cloud.google.com/go/aiplatform v1.68.0 // indirect
|
||||
cloud.google.com/go/auth v0.9.3 // indirect
|
||||
cloud.google.com/go/auth/oauth2adapt v0.2.4 // indirect
|
||||
cloud.google.com/go/compute/metadata v0.5.1 // indirect
|
||||
cloud.google.com/go/iam v1.2.1 // indirect
|
||||
cloud.google.com/go/longrunning v0.6.1 // indirect
|
||||
cloud.google.com/go/monitoring v1.21.0 // indirect
|
||||
dario.cat/mergo v1.0.0 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.14.0 // indirect
|
||||
cloud.google.com/go/aiplatform v1.69.0 // indirect
|
||||
cloud.google.com/go/auth v0.11.0 // indirect
|
||||
cloud.google.com/go/auth/oauth2adapt v0.2.6 // indirect
|
||||
cloud.google.com/go/compute/metadata v0.5.2 // indirect
|
||||
cloud.google.com/go/iam v1.2.2 // indirect
|
||||
cloud.google.com/go/longrunning v0.6.2 // indirect
|
||||
cloud.google.com/go/monitoring v1.21.2 // indirect
|
||||
dario.cat/mergo v1.0.1 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.16.0 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 // indirect
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 // indirect
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v1.2.3 // indirect
|
||||
github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.24.1 // indirect
|
||||
github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.48.1 // indirect
|
||||
github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.48.1 // indirect
|
||||
github.com/Microsoft/go-winio v0.6.2 // indirect
|
||||
github.com/Microsoft/hcsshim v0.12.4 // indirect
|
||||
github.com/OneOfOne/xxhash v1.2.8 // indirect
|
||||
github.com/ProtonMail/go-crypto v1.1.0-alpha.2 // indirect
|
||||
github.com/agext/levenshtein v1.2.3 // indirect
|
||||
github.com/agnivade/levenshtein v1.1.1 // indirect
|
||||
github.com/alecthomas/chroma v0.10.0 // indirect
|
||||
github.com/alecthomas/units v0.0.0-20231202071711-9a357b53e9c9 // indirect
|
||||
github.com/apparentlymart/go-cidr v1.1.0 // indirect
|
||||
github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect
|
||||
github.com/aquasecurity/go-version v0.0.0-20240603093900-cf8a8d29271d // indirect
|
||||
github.com/aquasecurity/trivy-checks v0.13.0 // indirect
|
||||
github.com/aws/aws-sdk-go-v2 v1.30.3 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/s3 v1.55.1 // indirect
|
||||
github.com/aws/smithy-go v1.20.3 // indirect
|
||||
github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect
|
||||
github.com/alecthomas/units v0.0.0-20240626203959-61d1e3462e30 // indirect
|
||||
github.com/aws/aws-sdk-go-v2 v1.32.3 // indirect
|
||||
github.com/aws/smithy-go v1.22.0 // indirect
|
||||
github.com/blang/semver/v4 v4.0.0 // indirect
|
||||
github.com/bmatcuk/doublestar/v4 v4.6.1 // indirect
|
||||
github.com/census-instrumentation/opencensus-proto v0.4.1 // indirect
|
||||
github.com/cloudflare/circl v1.3.7 // indirect
|
||||
github.com/cncf/xds/go v0.0.0-20240905190251-b4127c9b8d78 // indirect
|
||||
github.com/containerd/console v1.0.4 // indirect
|
||||
github.com/containerd/errdefs v0.1.0 // indirect
|
||||
github.com/containerd/continuity v0.4.3 // indirect
|
||||
github.com/containerd/errdefs v0.3.0 // indirect
|
||||
github.com/containerd/log v0.1.0 // indirect
|
||||
github.com/containerd/typeurl/v2 v2.1.1 // indirect
|
||||
github.com/containerd/platforms v0.2.1 // indirect
|
||||
github.com/creack/pty v1.1.21 // indirect
|
||||
github.com/distribution/reference v0.6.0 // indirect
|
||||
github.com/dlclark/regexp2 v1.10.0 // indirect
|
||||
github.com/docker/go-units v0.5.0 // indirect
|
||||
github.com/emirpasic/gods v1.18.1 // indirect
|
||||
github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7 // indirect
|
||||
github.com/envoyproxy/go-control-plane v0.13.0 // indirect
|
||||
github.com/envoyproxy/protoc-gen-validate v1.1.0 // indirect
|
||||
github.com/evanphx/json-patch/v5 v5.9.0 // indirect
|
||||
github.com/expr-lang/expr v1.16.9 // indirect
|
||||
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
|
||||
github.com/go-git/go-billy/v5 v5.5.0 // indirect
|
||||
github.com/go-git/go-git/v5 v5.12.0 // indirect
|
||||
github.com/go-ini/ini v1.67.0 // indirect
|
||||
github.com/go-kit/log v0.2.1 // indirect
|
||||
github.com/go-logfmt/logfmt v0.6.0 // indirect
|
||||
github.com/fxamacker/cbor/v2 v2.7.0 // indirect
|
||||
github.com/gofrs/flock v0.12.1 // indirect
|
||||
github.com/golang-jwt/jwt/v5 v5.2.1 // 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.8 // indirect
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.4 // indirect
|
||||
github.com/googleapis/gax-go/v2 v2.13.0 // indirect
|
||||
github.com/googleapis/gax-go/v2 v2.14.0 // indirect
|
||||
github.com/gookit/color v1.5.4 // indirect
|
||||
github.com/gorilla/websocket v1.5.2 // indirect
|
||||
github.com/gorilla/websocket v1.5.1 // indirect
|
||||
github.com/grafana/regexp v0.0.0-20240518133315-a468a5bfb3bc // indirect
|
||||
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
|
||||
github.com/hashicorp/go-getter v1.7.5 // indirect
|
||||
github.com/hashicorp/go-safetemp v1.0.0 // indirect
|
||||
github.com/hashicorp/go-uuid v1.0.3 // indirect
|
||||
github.com/hashicorp/go-version v1.7.0 // indirect
|
||||
github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
|
||||
github.com/hashicorp/hcl/v2 v2.20.1 // indirect
|
||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
|
||||
github.com/jmespath/go-jmespath v0.4.0 // indirect
|
||||
github.com/jpillora/backoff v1.0.0 // indirect
|
||||
github.com/kevinburke/ssh_config v1.2.0 // indirect
|
||||
github.com/kylelemons/godebug v1.1.0 // indirect
|
||||
github.com/liamg/iamgo v0.0.9 // indirect
|
||||
github.com/liamg/jfather v0.0.7 // indirect
|
||||
github.com/liamg/memoryfs v1.6.0 // indirect
|
||||
github.com/lithammer/fuzzysearch v1.1.8 // indirect
|
||||
github.com/lunixbochs/struc v0.0.0-20200707160740-784aaebc1d40 // indirect
|
||||
github.com/masahiro331/go-disk v0.0.0-20220919035250-c8da316f91ac // indirect
|
||||
github.com/masahiro331/go-ext4-filesystem v0.0.0-20231208112839-4339555a0cd4 // indirect
|
||||
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
||||
github.com/mitchellh/go-testing-interface v1.14.1 // indirect
|
||||
github.com/moby/buildkit v0.13.2 // indirect
|
||||
github.com/moby/docker-image-spec v1.3.1 // indirect
|
||||
github.com/moby/sys/userns v0.1.0 // indirect
|
||||
github.com/moby/sys/mountinfo v0.7.1 // indirect
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f // indirect
|
||||
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect
|
||||
github.com/open-policy-agent/opa v0.65.0 // indirect
|
||||
github.com/owenrumney/squealer v1.2.2 // indirect
|
||||
github.com/package-url/packageurl-go v0.1.3 // indirect
|
||||
github.com/pjbgf/sha1cd v0.3.0 // indirect
|
||||
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect
|
||||
github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 // indirect
|
||||
github.com/prometheus/common/sigv4 v0.1.0 // indirect
|
||||
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect
|
||||
github.com/sagikazarmark/locafero v0.4.0 // indirect
|
||||
github.com/sagikazarmark/locafero v0.6.0 // indirect
|
||||
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
|
||||
github.com/segmentio/fasthash v1.0.3 // indirect
|
||||
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 // indirect
|
||||
github.com/skeema/knownhosts v1.2.2 // indirect
|
||||
github.com/sony/gobreaker v0.5.0 // indirect
|
||||
github.com/sourcegraph/conc v0.3.0 // indirect
|
||||
github.com/stretchr/objx v0.5.2 // indirect
|
||||
github.com/tchap/go-patricia/v2 v2.3.1 // indirect
|
||||
github.com/ulikunitz/xz v0.5.11 // indirect
|
||||
github.com/xanzy/ssh-agent v0.3.3 // indirect
|
||||
github.com/x448/float16 v0.8.4 // indirect
|
||||
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
|
||||
github.com/yashtewari/glob-intersection v0.2.0 // indirect
|
||||
github.com/zclconf/go-cty v1.14.4 // indirect
|
||||
github.com/zclconf/go-cty-yaml v1.0.3 // indirect
|
||||
go.opencensus.io v0.24.0 // indirect
|
||||
go.opentelemetry.io/contrib/detectors/gcp v1.29.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.54.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.29.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk v1.29.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk/metric v1.29.0 // indirect
|
||||
golang.org/x/mod v0.20.0 // indirect
|
||||
golang.org/x/tools v0.24.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.56.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.31.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk v1.31.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk/metric v1.31.0 // indirect
|
||||
gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect
|
||||
google.golang.org/genproto v0.0.0-20240903143218-8af14fe29dc1 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240903143218-8af14fe29dc1 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect
|
||||
google.golang.org/genproto v0.0.0-20241118233622-e639e219e697 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20241118233622-e639e219e697 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20241118233622-e639e219e697 // indirect
|
||||
google.golang.org/grpc/stats/opentelemetry v0.0.0-20240907200651-3ffb98b2c93a // indirect
|
||||
gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect
|
||||
gopkg.in/warnings.v0 v0.1.2 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
knative.dev/pkg v0.0.0-20230616134650-eb63a40adfb0 // indirect
|
||||
mvdan.cc/sh/v3 v3.8.0 // indirect
|
||||
knative.dev/pkg v0.0.0-20241026180704-25f6002b00f3 // indirect
|
||||
)
|
||||
|
||||
require (
|
||||
@@ -199,23 +145,19 @@ require (
|
||||
github.com/BurntSushi/toml v1.4.1-0.20240526193622-a339e1f7089c // indirect
|
||||
github.com/MakeNowJust/heredoc v1.0.0 // indirect
|
||||
github.com/Masterminds/goutils v1.1.1 // indirect
|
||||
github.com/Masterminds/semver/v3 v3.2.1 // indirect
|
||||
github.com/Masterminds/sprig/v3 v3.2.3 // indirect
|
||||
github.com/Masterminds/semver/v3 v3.3.0 // indirect
|
||||
github.com/Masterminds/sprig/v3 v3.3.0 // indirect
|
||||
github.com/Masterminds/squirrel v1.5.4 // indirect
|
||||
github.com/aquasecurity/table v1.8.0 // indirect
|
||||
github.com/aquasecurity/tml v0.6.1 // indirect
|
||||
github.com/aquasecurity/trivy v0.53.0 // indirect
|
||||
github.com/aquasecurity/trivy-db v0.0.0-20231020043206-3770774790ce // 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.3.0 // indirect
|
||||
github.com/chai2010/gettext-go v1.0.3 // indirect
|
||||
github.com/containerd/containerd v1.7.18 // indirect
|
||||
github.com/cyphar/filepath-securejoin v0.2.5 // indirect
|
||||
github.com/containerd/containerd v1.7.23 // indirect
|
||||
github.com/cyphar/filepath-securejoin v0.3.4 // indirect
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
||||
github.com/docker/cli v26.1.4+incompatible // indirect
|
||||
github.com/docker/distribution v2.8.3+incompatible // indirect
|
||||
github.com/docker/docker v27.1.1+incompatible // indirect
|
||||
github.com/docker/docker v27.3.1+incompatible // indirect
|
||||
github.com/docker/docker-credential-helpers v0.8.2 // indirect
|
||||
github.com/docker/go-connections v0.5.0 // indirect
|
||||
github.com/docker/go-metrics v0.0.1 // indirect
|
||||
@@ -236,7 +178,6 @@ require (
|
||||
github.com/google/btree v1.1.2 // indirect
|
||||
github.com/google/gnostic v0.7.0
|
||||
github.com/google/go-cmp v0.6.0 // indirect
|
||||
github.com/google/go-containerregistry v0.19.2 // indirect
|
||||
github.com/google/gofuzz v1.2.0 // indirect
|
||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
|
||||
github.com/google/uuid v1.6.0 // indirect
|
||||
@@ -252,23 +193,22 @@ require (
|
||||
github.com/jmoiron/sqlx v1.4.0 // indirect
|
||||
github.com/josharian/intern v1.0.0 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/klauspost/compress v1.17.9 // indirect
|
||||
github.com/klauspost/compress v1.17.10 // indirect
|
||||
github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 // indirect
|
||||
github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 // indirect
|
||||
github.com/lib/pq v1.10.9 // indirect
|
||||
github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect
|
||||
github.com/mailru/easyjson v0.7.7 // indirect
|
||||
github.com/masahiro331/go-xfs-filesystem v0.0.0-20230608043311-a335f4599b70 // indirect
|
||||
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.15 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.16 // 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
|
||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||
github.com/mitchellh/reflectwalk v1.0.2 // indirect
|
||||
github.com/moby/locker v1.0.1 // indirect
|
||||
github.com/moby/spdystream v0.2.0 // indirect
|
||||
github.com/moby/spdystream v0.4.0 // indirect
|
||||
github.com/moby/term v0.5.0 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
@@ -276,58 +216,55 @@ require (
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||
github.com/opencontainers/go-digest v1.0.0 // indirect
|
||||
github.com/opencontainers/image-spec v1.1.0 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.2.2 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.2.3 // indirect
|
||||
github.com/peterbourgon/diskv v2.0.1+incompatible // indirect
|
||||
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.19.1
|
||||
github.com/prometheus/client_golang v1.20.5
|
||||
github.com/prometheus/client_model v0.6.1 // indirect
|
||||
github.com/prometheus/common v0.54.0 // indirect
|
||||
github.com/prometheus/common v0.60.1 // indirect
|
||||
github.com/prometheus/procfs v0.15.1 // indirect
|
||||
github.com/rivo/uniseg v0.4.7 // indirect
|
||||
github.com/robfig/cron/v3 v3.0.1
|
||||
github.com/rubenv/sql-migrate v1.6.1 // indirect
|
||||
github.com/rubenv/sql-migrate v1.7.0 // indirect
|
||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||
github.com/samber/lo v1.39.0 // indirect
|
||||
github.com/shopspring/decimal v1.4.0 // indirect
|
||||
github.com/sirupsen/logrus v1.9.3 // indirect
|
||||
github.com/spf13/afero v1.11.0 // indirect
|
||||
github.com/spf13/cast v1.6.0 // indirect
|
||||
github.com/spf13/cast v1.7.0 // indirect
|
||||
github.com/spf13/pflag v1.0.5 // indirect
|
||||
github.com/subosito/gotenv v1.6.0 // indirect
|
||||
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
|
||||
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
|
||||
github.com/xeipuuv/gojsonschema v1.2.0 // indirect
|
||||
github.com/xlab/treeprint v1.2.0 // indirect
|
||||
go.opentelemetry.io/otel v1.29.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.29.0 // indirect
|
||||
go.starlark.net v0.0.0-20240520160348-046347dcd104 // indirect
|
||||
go.opentelemetry.io/otel v1.31.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.31.0 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
go.uber.org/zap v1.27.0
|
||||
golang.org/x/crypto v0.27.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20240604190554-fc45aab8b7f8 // indirect
|
||||
golang.org/x/net v0.29.0
|
||||
golang.org/x/oauth2 v0.23.0 // indirect
|
||||
golang.org/x/sync v0.8.0 // indirect
|
||||
golang.org/x/sys v0.25.0 // indirect
|
||||
golang.org/x/text v0.18.0 // indirect
|
||||
golang.org/x/time v0.6.0 // indirect
|
||||
golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect
|
||||
google.golang.org/grpc v1.66.2
|
||||
google.golang.org/protobuf v1.35.1 // indirect
|
||||
golang.org/x/crypto v0.35.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20240823005443-9b4947da3948 // indirect
|
||||
golang.org/x/net v0.36.0
|
||||
golang.org/x/oauth2 v0.24.0 // indirect
|
||||
golang.org/x/sync v0.11.0 // indirect
|
||||
golang.org/x/sys v0.30.0 // indirect
|
||||
golang.org/x/text v0.22.0 // indirect
|
||||
golang.org/x/time v0.8.0 // indirect
|
||||
google.golang.org/grpc v1.68.1
|
||||
google.golang.org/protobuf v1.35.2 // indirect
|
||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||
k8s.io/apiextensions-apiserver v0.30.3
|
||||
k8s.io/apiserver v0.30.3 // indirect
|
||||
k8s.io/cli-runtime v0.30.3 // indirect
|
||||
k8s.io/component-base v0.30.3 // indirect
|
||||
k8s.io/klog/v2 v2.120.1 // indirect
|
||||
k8s.io/kube-openapi v0.0.0-20240521193020-835d969ad83a // indirect
|
||||
k8s.io/utils v0.0.0-20240921022957-49e7df575cb6
|
||||
k8s.io/apiextensions-apiserver v0.31.3
|
||||
k8s.io/apiserver v0.31.3 // indirect
|
||||
k8s.io/cli-runtime v0.31.1 // indirect
|
||||
k8s.io/component-base v0.31.3 // indirect
|
||||
k8s.io/klog/v2 v2.130.1 // indirect
|
||||
k8s.io/kube-openapi v0.0.0-20241009091222-67ed5848f094 // indirect
|
||||
k8s.io/utils v0.0.0-20250321185631-1f6e0b77f77e
|
||||
oras.land/oras-go v1.2.5 // indirect
|
||||
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
|
||||
sigs.k8s.io/kustomize/api v0.17.2 // indirect
|
||||
sigs.k8s.io/kustomize/kyaml v0.17.1 // indirect
|
||||
sigs.k8s.io/kustomize/api v0.18.0 // indirect
|
||||
sigs.k8s.io/kustomize/kyaml v0.18.1 // indirect
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect
|
||||
sigs.k8s.io/yaml v1.4.0 // indirect
|
||||
)
|
||||
@@ -335,4 +272,6 @@ require (
|
||||
// v1.2.0 is taken from github.com/open-policy-agent/opa v0.42.0
|
||||
// v1.2.0 incompatible with github.com/docker/docker v23.0.0-rc.1+incompatible
|
||||
//replace oras.land/oras-go => oras.land/oras-go v1.2.4
|
||||
replace github.com/docker/docker => github.com/docker/docker v27.3.1+incompatible
|
||||
replace github.com/docker/docker => github.com/docker/docker v27.4.0+incompatible
|
||||
|
||||
replace dario.cat/mergo => github.com/imdario/mergo v1.0.1
|
||||
|
||||
@@ -2,10 +2,12 @@ package ai
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"errors"
|
||||
"github.com/aws/aws-sdk-go/service/bedrockruntime/bedrockruntimeiface"
|
||||
"os"
|
||||
|
||||
"github.com/k8sgpt-ai/k8sgpt/pkg/ai/bedrock_support"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/aws/session"
|
||||
"github.com/aws/aws-sdk-go/service/bedrockruntime"
|
||||
@@ -13,18 +15,18 @@ import (
|
||||
|
||||
const amazonbedrockAIClientName = "amazonbedrock"
|
||||
|
||||
// AmazonBedRockClient represents the client for interacting with the Amazon Bedrock service.
|
||||
// AmazonBedRockClient represents the client for interacting with the AmazonCompletion Bedrock service.
|
||||
type AmazonBedRockClient struct {
|
||||
nopCloser
|
||||
|
||||
client *bedrockruntime.BedrockRuntime
|
||||
model string
|
||||
client bedrockruntimeiface.BedrockRuntimeAPI
|
||||
model *bedrock_support.BedrockModel
|
||||
temperature float32
|
||||
topP float32
|
||||
maxTokens int
|
||||
topP float32
|
||||
maxTokens int
|
||||
}
|
||||
|
||||
// Amazon BedRock support region list US East (N. Virginia),US West (Oregon),Asia Pacific (Singapore),Asia Pacific (Tokyo),Europe (Frankfurt)
|
||||
// AmazonCompletion BedRock support region list US East (N. Virginia),US West (Oregon),Asia Pacific (Singapore),Asia Pacific (Tokyo),Europe (Frankfurt)
|
||||
// https://docs.aws.amazon.com/bedrock/latest/userguide/what-is-bedrock.html#bedrock-regions
|
||||
const BEDROCK_DEFAULT_REGION = "us-east-1" // default use us-east-1 region
|
||||
|
||||
@@ -34,6 +36,7 @@ const (
|
||||
AP_Southeast_1 = "ap-southeast-1"
|
||||
AP_Northeast_1 = "ap-northeast-1"
|
||||
EU_Central_1 = "eu-central-1"
|
||||
AP_South_1 = "ap-south-1"
|
||||
)
|
||||
|
||||
var BEDROCKER_SUPPORTED_REGION = []string{
|
||||
@@ -42,41 +45,184 @@ var BEDROCKER_SUPPORTED_REGION = []string{
|
||||
AP_Southeast_1,
|
||||
AP_Northeast_1,
|
||||
EU_Central_1,
|
||||
AP_South_1,
|
||||
}
|
||||
|
||||
const (
|
||||
ModelAnthropicClaudeV2 = "anthropic.claude-v2"
|
||||
ModelAnthropicClaudeV1 = "anthropic.claude-v1"
|
||||
ModelAnthropicClaudeInstantV1 = "anthropic.claude-instant-v1"
|
||||
ModelA21J2UltraV1 = "ai21.j2-ultra-v1"
|
||||
ModelA21J2JumboInstruct = "ai21.j2-jumbo-instruct"
|
||||
ModelAmazonTitanExpressV1 = "amazon.titan-text-express-v1"
|
||||
)
|
||||
|
||||
var BEDROCK_MODELS = []string{
|
||||
ModelAnthropicClaudeV2,
|
||||
ModelAnthropicClaudeV1,
|
||||
ModelAnthropicClaudeInstantV1,
|
||||
ModelA21J2UltraV1,
|
||||
ModelA21J2JumboInstruct,
|
||||
ModelAmazonTitanExpressV1,
|
||||
}
|
||||
|
||||
//const TOPP = 0.9 moved to config
|
||||
|
||||
// GetModelOrDefault check config model
|
||||
func GetModelOrDefault(model string) string {
|
||||
|
||||
// Check if the provided model is in the list
|
||||
for _, m := range BEDROCK_MODELS {
|
||||
if m == model {
|
||||
return model // Return the provided model
|
||||
}
|
||||
var (
|
||||
models = []bedrock_support.BedrockModel{
|
||||
{
|
||||
Name: "anthropic.claude-3-5-sonnet-20240620-v1:0",
|
||||
Completion: &bedrock_support.CohereMessagesCompletion{},
|
||||
Response: &bedrock_support.CohereMessagesResponse{},
|
||||
Config: bedrock_support.BedrockModelConfig{
|
||||
// sensible defaults
|
||||
MaxTokens: 100,
|
||||
Temperature: 0.5,
|
||||
TopP: 0.9,
|
||||
ModelName: "anthropic.claude-3-5-sonnet-20240620-v1:0",
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "us.anthropic.claude-3-5-sonnet-20241022-v2:0",
|
||||
Completion: &bedrock_support.CohereCompletion{},
|
||||
Response: &bedrock_support.CohereResponse{},
|
||||
Config: bedrock_support.BedrockModelConfig{
|
||||
// sensible defaults
|
||||
MaxTokens: 100,
|
||||
Temperature: 0.5,
|
||||
TopP: 0.9,
|
||||
ModelName: "us.anthropic.claude-3-5-sonnet-20241022-v2:0",
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "anthropic.claude-v2",
|
||||
Completion: &bedrock_support.CohereCompletion{},
|
||||
Response: &bedrock_support.CohereResponse{},
|
||||
Config: bedrock_support.BedrockModelConfig{
|
||||
// sensible defaults
|
||||
MaxTokens: 100,
|
||||
Temperature: 0.5,
|
||||
TopP: 0.9,
|
||||
ModelName: "anthropic.claude-v2",
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "anthropic.claude-v1",
|
||||
Completion: &bedrock_support.CohereCompletion{},
|
||||
Response: &bedrock_support.CohereResponse{},
|
||||
Config: bedrock_support.BedrockModelConfig{
|
||||
// sensible defaults
|
||||
MaxTokens: 100,
|
||||
Temperature: 0.5,
|
||||
TopP: 0.9,
|
||||
ModelName: "anthropic.claude-v1",
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "anthropic.claude-instant-v1",
|
||||
Completion: &bedrock_support.CohereCompletion{},
|
||||
Response: &bedrock_support.CohereResponse{},
|
||||
Config: bedrock_support.BedrockModelConfig{
|
||||
// sensible defaults
|
||||
MaxTokens: 100,
|
||||
Temperature: 0.5,
|
||||
TopP: 0.9,
|
||||
ModelName: "anthropic.claude-instant-v1",
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "ai21.j2-ultra-v1",
|
||||
Completion: &bedrock_support.AI21{},
|
||||
Response: &bedrock_support.AI21Response{},
|
||||
Config: bedrock_support.BedrockModelConfig{
|
||||
// sensible defaults
|
||||
MaxTokens: 100,
|
||||
Temperature: 0.5,
|
||||
TopP: 0.9,
|
||||
ModelName: "ai21.j2-ultra-v1",
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "ai21.j2-jumbo-instruct",
|
||||
Completion: &bedrock_support.AI21{},
|
||||
Response: &bedrock_support.AI21Response{},
|
||||
Config: bedrock_support.BedrockModelConfig{
|
||||
// sensible defaults
|
||||
MaxTokens: 100,
|
||||
Temperature: 0.5,
|
||||
TopP: 0.9,
|
||||
ModelName: "ai21.j2-jumbo-instruct",
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "amazon.titan-text-express-v1",
|
||||
Completion: &bedrock_support.AmazonCompletion{},
|
||||
Response: &bedrock_support.AmazonResponse{},
|
||||
Config: bedrock_support.BedrockModelConfig{
|
||||
// sensible defaults
|
||||
MaxTokens: 100,
|
||||
Temperature: 0.5,
|
||||
TopP: 0.9,
|
||||
ModelName: "amazon.titan-text-express-v1",
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "amazon.nova-pro-v1:0",
|
||||
Completion: &bedrock_support.AmazonCompletion{},
|
||||
Response: &bedrock_support.NovaResponse{},
|
||||
Config: bedrock_support.BedrockModelConfig{
|
||||
// sensible defaults
|
||||
// https://docs.aws.amazon.com/nova/latest/userguide/getting-started-api.html
|
||||
MaxTokens: 100, // max of 300k tokens
|
||||
Temperature: 0.5,
|
||||
TopP: 0.9,
|
||||
ModelName: "amazon.nova-pro-v1:0",
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "eu.amazon.nova-pro-v1:0",
|
||||
Completion: &bedrock_support.AmazonCompletion{},
|
||||
Response: &bedrock_support.NovaResponse{},
|
||||
Config: bedrock_support.BedrockModelConfig{
|
||||
// sensible defaults
|
||||
// https://docs.aws.amazon.com/nova/latest/userguide/getting-started-api.html
|
||||
MaxTokens: 100, // max of 300k tokens
|
||||
Temperature: 0.5,
|
||||
TopP: 0.9,
|
||||
ModelName: "eu.wamazon.nova-pro-v1:0",
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "us.amazon.nova-pro-v1:0",
|
||||
Completion: &bedrock_support.AmazonCompletion{},
|
||||
Response: &bedrock_support.NovaResponse{},
|
||||
Config: bedrock_support.BedrockModelConfig{
|
||||
// sensible defaults
|
||||
// https://docs.aws.amazon.com/nova/latest/userguide/getting-started-api.html
|
||||
MaxTokens: 100, // max of 300k tokens
|
||||
Temperature: 0.5,
|
||||
TopP: 0.9,
|
||||
ModelName: "us.amazon.nova-pro-v1:0",
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "amazon.nova-lite-v1:0",
|
||||
Completion: &bedrock_support.AmazonCompletion{},
|
||||
Response: &bedrock_support.NovaResponse{},
|
||||
Config: bedrock_support.BedrockModelConfig{
|
||||
// sensible defaults
|
||||
MaxTokens: 100, // max of 300k tokens
|
||||
Temperature: 0.5,
|
||||
TopP: 0.9,
|
||||
ModelName: "amazon.nova-lite-v1:0",
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "eu.amazon.nova-lite-v1:0",
|
||||
Completion: &bedrock_support.AmazonCompletion{},
|
||||
Response: &bedrock_support.NovaResponse{},
|
||||
Config: bedrock_support.BedrockModelConfig{
|
||||
// sensible defaults
|
||||
MaxTokens: 100, // max of 300k tokens
|
||||
Temperature: 0.5,
|
||||
TopP: 0.9,
|
||||
ModelName: "eu.amazon.nova-lite-v1:0",
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "us.amazon.nova-lite-v1:0",
|
||||
Completion: &bedrock_support.AmazonCompletion{},
|
||||
Response: &bedrock_support.NovaResponse{},
|
||||
Config: bedrock_support.BedrockModelConfig{
|
||||
// sensible defaults
|
||||
MaxTokens: 100, // max of 300k tokens
|
||||
Temperature: 0.5,
|
||||
TopP: 0.9,
|
||||
ModelName: "us.amazon.nova-lite-v1:0",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
// Return the default model if the provided model is not in the list
|
||||
return BEDROCK_MODELS[0]
|
||||
}
|
||||
)
|
||||
|
||||
// GetModelOrDefault check config region
|
||||
func GetRegionOrDefault(region string) string {
|
||||
@@ -95,6 +241,16 @@ func GetRegionOrDefault(region string) string {
|
||||
return BEDROCK_DEFAULT_REGION
|
||||
}
|
||||
|
||||
// Get model from string
|
||||
func (a *AmazonBedRockClient) getModelFromString(model string) (*bedrock_support.BedrockModel, error) {
|
||||
for _, m := range models {
|
||||
if model == m.Name {
|
||||
return &m, nil
|
||||
}
|
||||
}
|
||||
return nil, errors.New("model not found")
|
||||
}
|
||||
|
||||
// Configure configures the AmazonBedRockClient with the provided configuration.
|
||||
func (a *AmazonBedRockClient) Configure(config IAIConfig) error {
|
||||
|
||||
@@ -109,9 +265,16 @@ func (a *AmazonBedRockClient) Configure(config IAIConfig) error {
|
||||
return err
|
||||
}
|
||||
|
||||
foundModel, err := a.getModelFromString(config.GetModel())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// TODO: Override the completion config somehow
|
||||
|
||||
// Create a new BedrockRuntime client
|
||||
a.client = bedrockruntime.New(sess)
|
||||
a.model = GetModelOrDefault(config.GetModel())
|
||||
a.model = foundModel
|
||||
a.model.Config.ModelName = foundModel.Name
|
||||
a.temperature = config.GetTemperature()
|
||||
a.topP = config.GetTopP()
|
||||
a.maxTokens = config.GetMaxTokens()
|
||||
@@ -122,46 +285,19 @@ func (a *AmazonBedRockClient) Configure(config IAIConfig) error {
|
||||
// GetCompletion sends a request to the model for generating completion based on the provided prompt.
|
||||
func (a *AmazonBedRockClient) GetCompletion(ctx context.Context, prompt string) (string, error) {
|
||||
|
||||
// Prepare the input data for the model invocation based on the model & the Response Body per model as well.
|
||||
var request map[string]interface{}
|
||||
switch a.model {
|
||||
case ModelAnthropicClaudeV2, ModelAnthropicClaudeV1, ModelAnthropicClaudeInstantV1:
|
||||
request = map[string]interface{}{
|
||||
"prompt": fmt.Sprintf("\n\nHuman: %s \n\nAssistant:", prompt),
|
||||
"max_tokens_to_sample": a.maxTokens,
|
||||
"temperature": a.temperature,
|
||||
"top_p": a.topP,
|
||||
}
|
||||
case ModelA21J2UltraV1, ModelA21J2JumboInstruct:
|
||||
request = map[string]interface{}{
|
||||
"prompt": prompt,
|
||||
"maxTokens": a.maxTokens,
|
||||
"temperature": a.temperature,
|
||||
"topP": a.topP,
|
||||
}
|
||||
case ModelAmazonTitanExpressV1:
|
||||
request = map[string]interface{}{
|
||||
"inputText": fmt.Sprintf("\n\nUser: %s", prompt),
|
||||
"textGenerationConfig": map[string]interface{}{
|
||||
"maxTokenCount": a.maxTokens,
|
||||
"temperature": a.temperature,
|
||||
"topP": a.topP,
|
||||
},
|
||||
}
|
||||
default:
|
||||
return "", fmt.Errorf("model %s not supported", a.model)
|
||||
}
|
||||
// override config defaults
|
||||
a.model.Config.MaxTokens = a.maxTokens
|
||||
a.model.Config.Temperature = a.temperature
|
||||
a.model.Config.TopP = a.topP
|
||||
|
||||
|
||||
body, err := json.Marshal(request)
|
||||
body, err := a.model.Completion.GetCompletion(ctx, prompt, a.model.Config)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
// Build the parameters for the model invocation
|
||||
params := &bedrockruntime.InvokeModelInput{
|
||||
Body: body,
|
||||
ModelId: aws.String(a.model),
|
||||
ModelId: aws.String(a.model.Name),
|
||||
ContentType: aws.String("application/json"),
|
||||
Accept: aws.String("application/json"),
|
||||
}
|
||||
@@ -171,56 +307,12 @@ func (a *AmazonBedRockClient) GetCompletion(ctx context.Context, prompt string)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
// Response type changes as per model
|
||||
switch a.model {
|
||||
case ModelAnthropicClaudeV2, ModelAnthropicClaudeV1, ModelAnthropicClaudeInstantV1:
|
||||
type InvokeModelResponseBody struct {
|
||||
Completion string `json:"completion"`
|
||||
Stop_reason string `json:"stop_reason"`
|
||||
}
|
||||
output := &InvokeModelResponseBody{}
|
||||
err = json.Unmarshal(resp.Body, output)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return output.Completion, nil
|
||||
case ModelA21J2UltraV1, ModelA21J2JumboInstruct:
|
||||
type Data struct {
|
||||
Text string `json:"text"`
|
||||
}
|
||||
type Completion struct {
|
||||
Data Data `json:"data"`
|
||||
}
|
||||
type InvokeModelResponseBody struct {
|
||||
Completions []Completion `json:"completions"`
|
||||
}
|
||||
output := &InvokeModelResponseBody{}
|
||||
err = json.Unmarshal(resp.Body, output)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return output.Completions[0].Data.Text, nil
|
||||
case ModelAmazonTitanExpressV1:
|
||||
type Result struct {
|
||||
TokenCount int `json:"tokenCount"`
|
||||
OutputText string `json:"outputText"`
|
||||
CompletionReason string `json:"completionReason"`
|
||||
}
|
||||
type InvokeModelResponseBody struct {
|
||||
InputTextTokenCount int `json:"inputTextTokenCount"`
|
||||
Results []Result `json:"results"`
|
||||
}
|
||||
output := &InvokeModelResponseBody{}
|
||||
err = json.Unmarshal(resp.Body, output)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return output.Results[0].OutputText, nil
|
||||
default:
|
||||
return "", fmt.Errorf("model %s not supported", a.model)
|
||||
}
|
||||
|
||||
// Parse the response
|
||||
return a.model.Response.ParseResponse(resp.Body)
|
||||
|
||||
}
|
||||
|
||||
// GetName returns the name of the AmazonBedRockClient.
|
||||
func (a *AmazonBedRockClient) GetName() string {
|
||||
return amazonbedrockAIClientName
|
||||
|
||||
@@ -14,9 +14,9 @@ const azureAIClientName = "azureopenai"
|
||||
type AzureAIClient struct {
|
||||
nopCloser
|
||||
|
||||
client *openai.Client
|
||||
model string
|
||||
temperature float32
|
||||
client *openai.Client
|
||||
model string
|
||||
temperature float32
|
||||
// organizationId string
|
||||
}
|
||||
|
||||
|
||||
152
pkg/ai/bedrock_support/completions.go
Normal file
152
pkg/ai/bedrock_support/completions.go
Normal file
@@ -0,0 +1,152 @@
|
||||
package bedrock_support
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var SUPPPORTED_BEDROCK_MODELS = []string{
|
||||
"anthropic.claude-3-5-sonnet-20240620-v1:0",
|
||||
"us.anthropic.claude-3-5-sonnet-20241022-v2:0",
|
||||
"anthropic.claude-v2",
|
||||
"anthropic.claude-v1",
|
||||
"anthropic.claude-instant-v1",
|
||||
"ai21.j2-ultra-v1",
|
||||
"ai21.j2-jumbo-instruct",
|
||||
"amazon.titan-text-express-v1",
|
||||
"amazon.nova-pro-v1:0",
|
||||
"eu.amazon.nova-lite-v1:0",
|
||||
}
|
||||
|
||||
type ICompletion interface {
|
||||
GetCompletion(ctx context.Context, prompt string, modelConfig BedrockModelConfig) ([]byte, error)
|
||||
}
|
||||
|
||||
type CohereCompletion struct {
|
||||
completion ICompletion
|
||||
}
|
||||
|
||||
func (a *CohereCompletion) GetCompletion(ctx context.Context, prompt string, modelConfig BedrockModelConfig) ([]byte, error) {
|
||||
request := map[string]interface{}{
|
||||
"prompt": fmt.Sprintf("\n\nHuman: %s \n\nAssistant:", prompt),
|
||||
"max_tokens_to_sample": modelConfig.MaxTokens,
|
||||
"temperature": modelConfig.Temperature,
|
||||
"top_p": modelConfig.TopP,
|
||||
}
|
||||
body, err := json.Marshal(request)
|
||||
if err != nil {
|
||||
return []byte{}, err
|
||||
}
|
||||
return body, nil
|
||||
}
|
||||
|
||||
type CohereMessagesCompletion struct {
|
||||
completion ICompletion
|
||||
}
|
||||
|
||||
func (a *CohereMessagesCompletion) GetCompletion(ctx context.Context, prompt string, modelConfig BedrockModelConfig) ([]byte, error) {
|
||||
request := map[string]interface{}{
|
||||
"max_tokens": modelConfig.MaxTokens,
|
||||
"temperature": modelConfig.Temperature,
|
||||
"top_p": modelConfig.TopP,
|
||||
"anthropic_version": "bedrock-2023-05-31", // Or another valid version
|
||||
"messages": []map[string]interface{}{
|
||||
{
|
||||
"role": "user",
|
||||
"content": prompt,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
body, err := json.Marshal(request)
|
||||
if err != nil {
|
||||
return []byte{}, err
|
||||
}
|
||||
return body, nil
|
||||
}
|
||||
|
||||
type AI21 struct {
|
||||
completion ICompletion
|
||||
}
|
||||
|
||||
func (a *AI21) GetCompletion(ctx context.Context, prompt string, modelConfig BedrockModelConfig) ([]byte, error) {
|
||||
request := map[string]interface{}{
|
||||
"prompt": prompt,
|
||||
"maxTokens": modelConfig.MaxTokens,
|
||||
"temperature": modelConfig.Temperature,
|
||||
"topP": modelConfig.TopP,
|
||||
}
|
||||
body, err := json.Marshal(request)
|
||||
if err != nil {
|
||||
return []byte{}, err
|
||||
}
|
||||
return body, nil
|
||||
}
|
||||
|
||||
type AmazonCompletion struct {
|
||||
completion ICompletion
|
||||
}
|
||||
|
||||
func isModelSupported(modelName string) bool {
|
||||
for _, supportedModel := range SUPPPORTED_BEDROCK_MODELS {
|
||||
if modelName == supportedModel {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (a *AmazonCompletion) GetCompletion(ctx context.Context, prompt string, modelConfig BedrockModelConfig) ([]byte, error) {
|
||||
if !isModelSupported(modelConfig.ModelName) {
|
||||
return nil, fmt.Errorf("model %s is not supported", modelConfig.ModelName)
|
||||
}
|
||||
if strings.Contains(modelConfig.ModelName, "nova") {
|
||||
return a.GetNovaCompletion(ctx, prompt, modelConfig)
|
||||
} else {
|
||||
return a.GetDefaultCompletion(ctx, prompt, modelConfig)
|
||||
}
|
||||
}
|
||||
|
||||
func (a *AmazonCompletion) GetDefaultCompletion(ctx context.Context, prompt string, modelConfig BedrockModelConfig) ([]byte, error) {
|
||||
request := map[string]interface{}{
|
||||
"inputText": fmt.Sprintf("\n\nUser: %s", prompt),
|
||||
"textGenerationConfig": map[string]interface{}{
|
||||
"maxTokenCount": modelConfig.MaxTokens,
|
||||
"temperature": modelConfig.Temperature,
|
||||
"topP": modelConfig.TopP,
|
||||
},
|
||||
}
|
||||
body, err := json.Marshal(request)
|
||||
if err != nil {
|
||||
return []byte{}, err
|
||||
}
|
||||
return body, nil
|
||||
|
||||
}
|
||||
|
||||
func (a *AmazonCompletion) GetNovaCompletion(ctx context.Context, prompt string, modelConfig BedrockModelConfig) ([]byte, error) {
|
||||
request := map[string]interface{}{
|
||||
"inferenceConfig": map[string]interface{}{
|
||||
"max_new_tokens": modelConfig.MaxTokens,
|
||||
"temperature": modelConfig.Temperature,
|
||||
"topP": modelConfig.TopP,
|
||||
},
|
||||
"messages": []map[string]interface{}{
|
||||
{
|
||||
"role": "user",
|
||||
"content": []map[string]interface{}{
|
||||
{
|
||||
"text": prompt,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
body, err := json.Marshal(request)
|
||||
if err != nil {
|
||||
return []byte{}, err
|
||||
}
|
||||
return body, nil
|
||||
}
|
||||
179
pkg/ai/bedrock_support/completions_test.go
Normal file
179
pkg/ai/bedrock_support/completions_test.go
Normal file
@@ -0,0 +1,179 @@
|
||||
package bedrock_support
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestCohereCompletion_GetCompletion(t *testing.T) {
|
||||
completion := &CohereCompletion{}
|
||||
modelConfig := BedrockModelConfig{
|
||||
MaxTokens: 100,
|
||||
Temperature: 0.7,
|
||||
TopP: 0.9,
|
||||
}
|
||||
prompt := "Test prompt"
|
||||
|
||||
body, err := completion.GetCompletion(context.Background(), prompt, modelConfig)
|
||||
assert.NoError(t, err)
|
||||
|
||||
var request map[string]interface{}
|
||||
err = json.Unmarshal(body, &request)
|
||||
assert.NoError(t, err)
|
||||
|
||||
assert.Equal(t, "\n\nHuman: Test prompt \n\nAssistant:", request["prompt"])
|
||||
assert.Equal(t, 100, int(request["max_tokens_to_sample"].(float64)))
|
||||
assert.Equal(t, 0.7, request["temperature"])
|
||||
assert.Equal(t, 0.9, request["top_p"])
|
||||
}
|
||||
|
||||
func TestAI21_GetCompletion(t *testing.T) {
|
||||
completion := &AI21{}
|
||||
modelConfig := BedrockModelConfig{
|
||||
MaxTokens: 150,
|
||||
Temperature: 0.6,
|
||||
TopP: 0.8,
|
||||
}
|
||||
prompt := "Another test prompt"
|
||||
|
||||
body, err := completion.GetCompletion(context.Background(), prompt, modelConfig)
|
||||
assert.NoError(t, err)
|
||||
|
||||
var request map[string]interface{}
|
||||
err = json.Unmarshal(body, &request)
|
||||
assert.NoError(t, err)
|
||||
|
||||
assert.Equal(t, "Another test prompt", request["prompt"])
|
||||
assert.Equal(t, 150, int(request["maxTokens"].(float64)))
|
||||
assert.Equal(t, 0.6, request["temperature"])
|
||||
assert.Equal(t, 0.8, request["topP"])
|
||||
}
|
||||
|
||||
func TestAmazonCompletion_GetDefaultCompletion(t *testing.T) {
|
||||
completion := &AmazonCompletion{}
|
||||
modelConfig := BedrockModelConfig{
|
||||
MaxTokens: 200,
|
||||
Temperature: 0.5,
|
||||
TopP: 0.7,
|
||||
ModelName: "amazon.titan-text-express-v1",
|
||||
}
|
||||
prompt := "Default test prompt"
|
||||
|
||||
body, err := completion.GetDefaultCompletion(context.Background(), prompt, modelConfig)
|
||||
assert.NoError(t, err)
|
||||
|
||||
var request map[string]interface{}
|
||||
err = json.Unmarshal(body, &request)
|
||||
assert.NoError(t, err)
|
||||
|
||||
assert.Equal(t, "\n\nUser: Default test prompt", request["inputText"])
|
||||
textConfig := request["textGenerationConfig"].(map[string]interface{})
|
||||
assert.Equal(t, 200, int(textConfig["maxTokenCount"].(float64)))
|
||||
assert.Equal(t, 0.5, textConfig["temperature"])
|
||||
assert.Equal(t, 0.7, textConfig["topP"])
|
||||
}
|
||||
|
||||
func TestAmazonCompletion_GetNovaCompletion(t *testing.T) {
|
||||
completion := &AmazonCompletion{}
|
||||
modelConfig := BedrockModelConfig{
|
||||
MaxTokens: 250,
|
||||
Temperature: 0.4,
|
||||
TopP: 0.6,
|
||||
ModelName: "amazon.nova-pro-v1:0",
|
||||
}
|
||||
prompt := "Nova test prompt"
|
||||
|
||||
body, err := completion.GetNovaCompletion(context.Background(), prompt, modelConfig)
|
||||
assert.NoError(t, err)
|
||||
|
||||
var request map[string]interface{}
|
||||
err = json.Unmarshal(body, &request)
|
||||
assert.NoError(t, err)
|
||||
|
||||
inferenceConfig := request["inferenceConfig"].(map[string]interface{})
|
||||
assert.Equal(t, 250, int(inferenceConfig["max_new_tokens"].(float64)))
|
||||
assert.Equal(t, 0.4, inferenceConfig["temperature"])
|
||||
assert.Equal(t, 0.6, inferenceConfig["topP"])
|
||||
|
||||
messages := request["messages"].([]interface{})
|
||||
message := messages[0].(map[string]interface{})
|
||||
content := message["content"].([]interface{})
|
||||
contentMap := content[0].(map[string]interface{})
|
||||
assert.Equal(t, "Nova test prompt", contentMap["text"])
|
||||
}
|
||||
|
||||
func TestAmazonCompletion_GetCompletion_Nova(t *testing.T) {
|
||||
completion := &AmazonCompletion{}
|
||||
modelConfig := BedrockModelConfig{
|
||||
MaxTokens: 250,
|
||||
Temperature: 0.4,
|
||||
TopP: 0.6,
|
||||
ModelName: "amazon.nova-pro-v1:0",
|
||||
}
|
||||
prompt := "Nova test prompt"
|
||||
|
||||
body, err := completion.GetCompletion(context.Background(), prompt, modelConfig)
|
||||
assert.NoError(t, err)
|
||||
|
||||
var request map[string]interface{}
|
||||
err = json.Unmarshal(body, &request)
|
||||
assert.NoError(t, err)
|
||||
|
||||
inferenceConfig := request["inferenceConfig"].(map[string]interface{})
|
||||
assert.Equal(t, 250, int(inferenceConfig["max_new_tokens"].(float64)))
|
||||
assert.Equal(t, 0.4, inferenceConfig["temperature"])
|
||||
assert.Equal(t, 0.6, inferenceConfig["topP"])
|
||||
|
||||
messages := request["messages"].([]interface{})
|
||||
message := messages[0].(map[string]interface{})
|
||||
content := message["content"].([]interface{})
|
||||
contentMap := content[0].(map[string]interface{})
|
||||
assert.Equal(t, "Nova test prompt", contentMap["text"])
|
||||
}
|
||||
|
||||
func TestAmazonCompletion_GetCompletion_Default(t *testing.T) {
|
||||
completion := &AmazonCompletion{}
|
||||
modelConfig := BedrockModelConfig{
|
||||
MaxTokens: 200,
|
||||
Temperature: 0.5,
|
||||
TopP: 0.7,
|
||||
ModelName: "amazon.titan-text-express-v1",
|
||||
}
|
||||
prompt := "Default test prompt"
|
||||
|
||||
body, err := completion.GetCompletion(context.Background(), prompt, modelConfig)
|
||||
assert.NoError(t, err)
|
||||
|
||||
var request map[string]interface{}
|
||||
err = json.Unmarshal(body, &request)
|
||||
assert.NoError(t, err)
|
||||
|
||||
assert.Equal(t, "\n\nUser: Default test prompt", request["inputText"])
|
||||
textConfig := request["textGenerationConfig"].(map[string]interface{})
|
||||
assert.Equal(t, 200, int(textConfig["maxTokenCount"].(float64)))
|
||||
assert.Equal(t, 0.5, textConfig["temperature"])
|
||||
assert.Equal(t, 0.7, textConfig["topP"])
|
||||
}
|
||||
|
||||
func TestAmazonCompletion_GetCompletion_UnsupportedModel(t *testing.T) {
|
||||
completion := &AmazonCompletion{}
|
||||
modelConfig := BedrockModelConfig{
|
||||
MaxTokens: 200,
|
||||
Temperature: 0.5,
|
||||
TopP: 0.7,
|
||||
ModelName: "unsupported-model",
|
||||
}
|
||||
prompt := "Test prompt"
|
||||
|
||||
_, err := completion.GetCompletion(context.Background(), prompt, modelConfig)
|
||||
assert.Error(t, err)
|
||||
assert.Contains(t, err.Error(), "model unsupported-model is not supported")
|
||||
}
|
||||
|
||||
func Test_isModelSupported(t *testing.T) {
|
||||
assert.True(t, isModelSupported("anthropic.claude-v2"))
|
||||
assert.False(t, isModelSupported("unsupported-model"))
|
||||
}
|
||||
14
pkg/ai/bedrock_support/model.go
Normal file
14
pkg/ai/bedrock_support/model.go
Normal file
@@ -0,0 +1,14 @@
|
||||
package bedrock_support
|
||||
|
||||
type BedrockModelConfig struct {
|
||||
MaxTokens int
|
||||
Temperature float32
|
||||
TopP float32
|
||||
ModelName string
|
||||
}
|
||||
type BedrockModel struct {
|
||||
Name string
|
||||
Completion ICompletion
|
||||
Response IResponse
|
||||
Config BedrockModelConfig
|
||||
}
|
||||
59
pkg/ai/bedrock_support/model_test.go
Normal file
59
pkg/ai/bedrock_support/model_test.go
Normal file
@@ -0,0 +1,59 @@
|
||||
package bedrock_support
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestBedrockModelConfig(t *testing.T) {
|
||||
config := BedrockModelConfig{
|
||||
MaxTokens: 100,
|
||||
Temperature: 0.7,
|
||||
TopP: 0.9,
|
||||
ModelName: "test-model",
|
||||
}
|
||||
|
||||
assert.Equal(t, 100, config.MaxTokens)
|
||||
assert.Equal(t, float32(0.7), config.Temperature)
|
||||
assert.Equal(t, float32(0.9), config.TopP)
|
||||
assert.Equal(t, "test-model", config.ModelName)
|
||||
}
|
||||
|
||||
func TestBedrockModel(t *testing.T) {
|
||||
completion := &MockCompletion{}
|
||||
response := &MockResponse{}
|
||||
config := BedrockModelConfig{
|
||||
MaxTokens: 100,
|
||||
Temperature: 0.7,
|
||||
TopP: 0.9,
|
||||
ModelName: "test-model",
|
||||
}
|
||||
|
||||
model := BedrockModel{
|
||||
Name: "Test Model",
|
||||
Completion: completion,
|
||||
Response: response,
|
||||
Config: config,
|
||||
}
|
||||
|
||||
assert.Equal(t, "Test Model", model.Name)
|
||||
assert.Equal(t, completion, model.Completion)
|
||||
assert.Equal(t, response, model.Response)
|
||||
assert.Equal(t, config, model.Config)
|
||||
}
|
||||
|
||||
// MockCompletion is a mock implementation of the ICompletion interface
|
||||
type MockCompletion struct{}
|
||||
|
||||
func (m *MockCompletion) GetCompletion(ctx context.Context, prompt string, config BedrockModelConfig) ([]byte, error) {
|
||||
return []byte(`{"prompt": "mock prompt"}`), nil
|
||||
}
|
||||
|
||||
// MockResponse is a mock implementation of the IResponse interface
|
||||
type MockResponse struct{}
|
||||
|
||||
func (m *MockResponse) ParseResponse(body []byte) (string, error) {
|
||||
return "mock response", nil
|
||||
}
|
||||
155
pkg/ai/bedrock_support/responses.go
Normal file
155
pkg/ai/bedrock_support/responses.go
Normal file
@@ -0,0 +1,155 @@
|
||||
package bedrock_support
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
)
|
||||
|
||||
type IResponse interface {
|
||||
ParseResponse(rawResponse []byte) (string, error)
|
||||
}
|
||||
|
||||
type CohereMessagesResponse struct {
|
||||
response IResponse
|
||||
}
|
||||
|
||||
func (a *CohereMessagesResponse) ParseResponse(rawResponse []byte) (string, error) {
|
||||
type InvokeModelResponseBody struct {
|
||||
ID string `json:"id"`
|
||||
Type string `json:"type"`
|
||||
Role string `json:"role"`
|
||||
Model string `json:"model"`
|
||||
Content []struct {
|
||||
Type string `json:"type"`
|
||||
Text string `json:"text"`
|
||||
} `json:"content"`
|
||||
StopReason string `json:"stop_reason"`
|
||||
StopSequence interface{} `json:"stop_sequence"` // Could be null
|
||||
Usage struct {
|
||||
InputTokens int `json:"input_tokens"`
|
||||
OutputTokens int `json:"output_tokens"`
|
||||
} `json:"usage"`
|
||||
}
|
||||
|
||||
output := &InvokeModelResponseBody{}
|
||||
err := json.Unmarshal(rawResponse, output)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
// Extract the text content from the Content array
|
||||
var resultText string
|
||||
for _, content := range output.Content {
|
||||
if content.Type == "text" {
|
||||
resultText += content.Text
|
||||
}
|
||||
}
|
||||
|
||||
return resultText, nil
|
||||
}
|
||||
|
||||
type CohereResponse struct {
|
||||
response IResponse
|
||||
}
|
||||
|
||||
func (a *CohereResponse) ParseResponse(rawResponse []byte) (string, error) {
|
||||
type InvokeModelResponseBody struct {
|
||||
Completion string `json:"completion"`
|
||||
Stop_reason string `json:"stop_reason"`
|
||||
}
|
||||
output := &InvokeModelResponseBody{}
|
||||
err := json.Unmarshal(rawResponse, output)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return output.Completion, nil
|
||||
}
|
||||
|
||||
type AI21Response struct {
|
||||
response IResponse
|
||||
}
|
||||
|
||||
func (a *AI21Response) ParseResponse(rawResponse []byte) (string, error) {
|
||||
type Data struct {
|
||||
Text string `json:"text"`
|
||||
}
|
||||
type Completion struct {
|
||||
Data Data `json:"data"`
|
||||
}
|
||||
type InvokeModelResponseBody struct {
|
||||
Completions []Completion `json:"completions"`
|
||||
}
|
||||
output := &InvokeModelResponseBody{}
|
||||
err := json.Unmarshal(rawResponse, output)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return output.Completions[0].Data.Text, nil
|
||||
}
|
||||
|
||||
type AmazonResponse struct {
|
||||
response IResponse
|
||||
}
|
||||
|
||||
type NovaResponse struct {
|
||||
response NResponse
|
||||
}
|
||||
type NResponse interface {
|
||||
ParseResponse(rawResponse []byte) (string, error)
|
||||
}
|
||||
|
||||
func (a *AmazonResponse) ParseResponse(rawResponse []byte) (string, error) {
|
||||
type Result struct {
|
||||
TokenCount int `json:"tokenCount"`
|
||||
OutputText string `json:"outputText"`
|
||||
CompletionReason string `json:"completionReason"`
|
||||
}
|
||||
type InvokeModelResponseBody struct {
|
||||
InputTextTokenCount int `json:"inputTextTokenCount"`
|
||||
Results []Result `json:"results"`
|
||||
}
|
||||
output := &InvokeModelResponseBody{}
|
||||
err := json.Unmarshal(rawResponse, output)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return output.Results[0].OutputText, nil
|
||||
}
|
||||
|
||||
func (a *NovaResponse) ParseResponse(rawResponse []byte) (string, error) {
|
||||
type Content struct {
|
||||
Text string `json:"text"`
|
||||
}
|
||||
|
||||
type Message struct {
|
||||
Role string `json:"role"`
|
||||
Content []Content `json:"content"`
|
||||
}
|
||||
|
||||
type UsageDetails struct {
|
||||
InputTokens int `json:"inputTokens"`
|
||||
OutputTokens int `json:"outputTokens"`
|
||||
TotalTokens int `json:"totalTokens"`
|
||||
CacheReadInputTokenCount int `json:"cacheReadInputTokenCount"`
|
||||
CacheWriteInputTokenCount int `json:"cacheWriteInputTokenCount,omitempty"`
|
||||
}
|
||||
|
||||
type AmazonNovaResponse struct {
|
||||
Output struct {
|
||||
Message Message `json:"message"`
|
||||
} `json:"output"`
|
||||
StopReason string `json:"stopReason"`
|
||||
Usage UsageDetails `json:"usage"`
|
||||
}
|
||||
|
||||
response := &AmazonNovaResponse{}
|
||||
err := json.Unmarshal(rawResponse, response)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if len(response.Output.Message.Content) > 0 {
|
||||
return response.Output.Message.Content[0].Text, nil
|
||||
}
|
||||
|
||||
return "", nil
|
||||
}
|
||||
65
pkg/ai/bedrock_support/responses_test.go
Normal file
65
pkg/ai/bedrock_support/responses_test.go
Normal file
@@ -0,0 +1,65 @@
|
||||
package bedrock_support
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestCohereResponse_ParseResponse(t *testing.T) {
|
||||
response := &CohereResponse{}
|
||||
rawResponse := []byte(`{"completion": "Test completion", "stop_reason": "max_tokens"}`)
|
||||
|
||||
result, err := response.ParseResponse(rawResponse)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "Test completion", result)
|
||||
|
||||
invalidResponse := []byte(`{"completion": "Test completion", "invalid_json":]`)
|
||||
_, err = response.ParseResponse(invalidResponse)
|
||||
assert.Error(t, err)
|
||||
}
|
||||
|
||||
func TestAI21Response_ParseResponse(t *testing.T) {
|
||||
response := &AI21Response{}
|
||||
rawResponse := []byte(`{"completions": [{"data": {"text": "AI21 test"}}], "id": "123"}`)
|
||||
|
||||
result, err := response.ParseResponse(rawResponse)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "AI21 test", result)
|
||||
|
||||
invalidResponse := []byte(`{"completions": [{"data": {"text": "AI21 test"}}, "invalid_json":]`)
|
||||
_, err = response.ParseResponse(invalidResponse)
|
||||
assert.Error(t, err)
|
||||
}
|
||||
|
||||
func TestAmazonResponse_ParseResponse(t *testing.T) {
|
||||
response := &AmazonResponse{}
|
||||
rawResponse := []byte(`{"inputTextTokenCount": 10, "results": [{"tokenCount": 20, "outputText": "Amazon test", "completionReason": "stop"}]}`)
|
||||
|
||||
result, err := response.ParseResponse(rawResponse)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "Amazon test", result)
|
||||
|
||||
invalidResponse := []byte(`{"inputTextTokenCount": 10, "results": [{"tokenCount": 20, "outputText": "Amazon test", "invalid_json":]`)
|
||||
_, err = response.ParseResponse(invalidResponse)
|
||||
assert.Error(t, err)
|
||||
}
|
||||
|
||||
func TestNovaResponse_ParseResponse(t *testing.T) {
|
||||
response := &NovaResponse{}
|
||||
rawResponse := []byte(`{"output": {"message": {"content": [{"text": "Nova test"}]}}, "stopReason": "stop", "usage": {"inputTokens": 10, "outputTokens": 20, "totalTokens": 30, "cacheReadInputTokenCount": 5}}`)
|
||||
|
||||
result, err := response.ParseResponse(rawResponse)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "Nova test", result)
|
||||
|
||||
rawResponseEmptyContent := []byte(`{"output": {"message": {"content": []}}, "stopReason": "stop", "usage": {"inputTokens": 10, "outputTokens": 20, "totalTokens": 30, "cacheReadInputTokenCount": 5}}`)
|
||||
|
||||
resultEmptyContent, errEmptyContent := response.ParseResponse(rawResponseEmptyContent)
|
||||
assert.NoError(t, errEmptyContent)
|
||||
assert.Equal(t, "", resultEmptyContent)
|
||||
|
||||
invalidResponse := []byte(`{"output": {"message": {"content": [{"text": "Nova test"}}, "invalid_json":]`)
|
||||
_, err = response.ParseResponse(invalidResponse)
|
||||
assert.Error(t, err)
|
||||
}
|
||||
147
pkg/ai/customrest.go
Normal file
147
pkg/ai/customrest.go
Normal file
@@ -0,0 +1,147 @@
|
||||
package ai
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
const CustomRestClientName = "customrest"
|
||||
|
||||
type CustomRestClient struct {
|
||||
nopCloser
|
||||
client *http.Client
|
||||
base *url.URL
|
||||
token string
|
||||
model string
|
||||
temperature float32
|
||||
topP float32
|
||||
topK int32
|
||||
}
|
||||
|
||||
type CustomRestRequest struct {
|
||||
Model string `json:"model"`
|
||||
|
||||
// Prompt is the textual prompt to send to the model.
|
||||
Prompt string `json:"prompt"`
|
||||
|
||||
// Options lists model-specific options. For example, temperature can be
|
||||
// set through this field, if the model supports it.
|
||||
Options map[string]interface{} `json:"options"`
|
||||
}
|
||||
|
||||
type CustomRestResponse struct {
|
||||
// Model is the model name that generated the response.
|
||||
Model string `json:"model"`
|
||||
|
||||
// CreatedAt is the timestamp of the response.
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
|
||||
// Response is the textual response itself.
|
||||
Response string `json:"response"`
|
||||
}
|
||||
|
||||
func (c *CustomRestClient) Configure(config IAIConfig) error {
|
||||
baseURL := config.GetBaseURL()
|
||||
if baseURL == "" {
|
||||
baseURL = defaultBaseURL
|
||||
}
|
||||
c.token = config.GetPassword()
|
||||
baseClientURL, err := url.Parse(baseURL)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
c.base = baseClientURL
|
||||
|
||||
proxyEndpoint := config.GetProxyEndpoint()
|
||||
c.client = http.DefaultClient
|
||||
if proxyEndpoint != "" {
|
||||
proxyUrl, err := url.Parse(proxyEndpoint)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
transport := &http.Transport{
|
||||
Proxy: http.ProxyURL(proxyUrl),
|
||||
}
|
||||
|
||||
c.client = &http.Client{
|
||||
Transport: transport,
|
||||
}
|
||||
}
|
||||
|
||||
c.model = config.GetModel()
|
||||
if c.model == "" {
|
||||
c.model = defaultModel
|
||||
}
|
||||
c.temperature = config.GetTemperature()
|
||||
c.topP = config.GetTopP()
|
||||
c.topK = config.GetTopK()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *CustomRestClient) GetCompletion(ctx context.Context, prompt string) (string, error) {
|
||||
var promptDetail struct {
|
||||
Language string `json:"language,omitempty"`
|
||||
Message string `json:"message"`
|
||||
Prompt string `json:"prompt,omitempty"`
|
||||
}
|
||||
prompt = strings.NewReplacer("\n", "\\n", "\t", "\\t").Replace(prompt)
|
||||
if err := json.Unmarshal([]byte(prompt), &promptDetail); err != nil {
|
||||
return "", err
|
||||
}
|
||||
generateRequest := &CustomRestRequest{
|
||||
Model: c.model,
|
||||
Prompt: promptDetail.Prompt,
|
||||
Options: map[string]interface{}{
|
||||
"temperature": c.temperature,
|
||||
"top_p": c.topP,
|
||||
"top_k": c.topK,
|
||||
"message": promptDetail.Message,
|
||||
"language": promptDetail.Language,
|
||||
},
|
||||
}
|
||||
requestBody, err := json.Marshal(generateRequest)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
request, err := http.NewRequestWithContext(ctx, http.MethodPost, c.base.String(), bytes.NewBuffer(requestBody))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if c.token != "" {
|
||||
request.Header.Set("Authorization", "Bearer "+c.token)
|
||||
}
|
||||
request.Header.Set("Content-Type", "application/json")
|
||||
request.Header.Set("Accept", "application/x-ndjson")
|
||||
|
||||
response, err := c.client.Do(request)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer response.Body.Close()
|
||||
|
||||
responseBody, err := io.ReadAll(response.Body)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("could not read response body: %w", err)
|
||||
}
|
||||
|
||||
if response.StatusCode >= http.StatusBadRequest {
|
||||
return "", fmt.Errorf("Request Error, StatusCode: %d, ErrorMessage: %s", response.StatusCode, responseBody)
|
||||
}
|
||||
|
||||
var result CustomRestResponse
|
||||
if err := json.Unmarshal(responseBody, &result); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return result.Response, nil
|
||||
}
|
||||
|
||||
func (c *CustomRestClient) GetName() string {
|
||||
return CustomRestClientName
|
||||
}
|
||||
@@ -80,10 +80,10 @@ func (c *GoogleGenAIClient) GetCompletion(ctx context.Context, prompt string) (s
|
||||
if !r.Blocked {
|
||||
continue
|
||||
}
|
||||
return "", fmt.Errorf("complection blocked due to %v with probability %v", r.Category.String(), r.Probability.String())
|
||||
return "", fmt.Errorf("completion blocked due to %v with probability %v", r.Category.String(), r.Probability.String())
|
||||
}
|
||||
}
|
||||
return "", errors.New("no complection returned; unknown reason")
|
||||
return "", errors.New("no completion returned; unknown reason")
|
||||
}
|
||||
|
||||
// Format output.
|
||||
|
||||
@@ -123,7 +123,7 @@ func (g *GoogleVertexAIClient) GetCompletion(ctx context.Context, prompt string)
|
||||
model := g.client.GenerativeModel(g.model)
|
||||
model.SetTemperature(g.temperature)
|
||||
model.SetTopP(g.topP)
|
||||
model.SetTopK(float32(g.topK))
|
||||
model.SetTopK(g.topK)
|
||||
model.SetMaxOutputTokens(int32(g.maxTokens))
|
||||
|
||||
// Google AI SDK is capable of different inputs than just text, for now set explicit text prompt type.
|
||||
@@ -139,10 +139,10 @@ func (g *GoogleVertexAIClient) GetCompletion(ctx context.Context, prompt string)
|
||||
if !r.Blocked {
|
||||
continue
|
||||
}
|
||||
return "", fmt.Errorf("complection blocked due to %v with probability %v", r.Category.String(), r.Probability.String())
|
||||
return "", fmt.Errorf("completion blocked due to %v with probability %v", r.Category.String(), r.Probability.String())
|
||||
}
|
||||
}
|
||||
return "", errors.New("no complection returned; unknown reason")
|
||||
return "", errors.New("no completion returned; unknown reason")
|
||||
}
|
||||
|
||||
// Format output.
|
||||
|
||||
@@ -32,6 +32,7 @@ var (
|
||||
&HuggingfaceClient{},
|
||||
&GoogleVertexAIClient{},
|
||||
&OCIGenAIClient{},
|
||||
&CustomRestClient{},
|
||||
&IBMWatsonxAIClient{},
|
||||
}
|
||||
Backends = []string{
|
||||
@@ -47,6 +48,7 @@ var (
|
||||
huggingfaceAIClientName,
|
||||
googleVertexAIClientName,
|
||||
ociClientName,
|
||||
CustomRestClientName,
|
||||
ibmWatsonxAIClientName,
|
||||
}
|
||||
)
|
||||
@@ -181,7 +183,7 @@ func (p *AIProvider) GetCustomHeaders() []http.Header {
|
||||
return p.CustomHeaders
|
||||
}
|
||||
|
||||
var passwordlessProviders = []string{"localai", "ollama", "amazonsagemaker", "amazonbedrock", "googlevertexai", "oci"}
|
||||
var passwordlessProviders = []string{"localai", "ollama", "amazonsagemaker", "amazonbedrock", "googlevertexai", "oci", "customrest"}
|
||||
|
||||
func NeedPassword(backend string) bool {
|
||||
for _, b := range passwordlessProviders {
|
||||
|
||||
@@ -27,10 +27,10 @@ const openAIClientName = "openai"
|
||||
type OpenAIClient struct {
|
||||
nopCloser
|
||||
|
||||
client *openai.Client
|
||||
model string
|
||||
temperature float32
|
||||
topP float32
|
||||
client *openai.Client
|
||||
model string
|
||||
temperature float32
|
||||
topP float32
|
||||
// organizationId string
|
||||
}
|
||||
|
||||
|
||||
@@ -6,8 +6,6 @@ const (
|
||||
Error: {Explain error here}
|
||||
Solution: {Step by step solution here}
|
||||
`
|
||||
trivy_vuln_prompt = "Explain the following trivy scan result and the detail risk or root cause of the CVE ID, then provide a solution. Response in %s: %s"
|
||||
trivy_conf_prompt = "Explain the following trivy scan result and the detail risk or root cause of the security check, then provide a solution."
|
||||
|
||||
prom_conf_prompt = `Simplify the following Prometheus error message delimited by triple dashes written in --- %s --- language; --- %s ---.
|
||||
This error came when validating the Prometheus configuration file.
|
||||
@@ -58,12 +56,12 @@ const (
|
||||
|
||||
Solution: {kubectl command}
|
||||
`
|
||||
raw_promt = `{"language": "%s","message": "%s","prompt": "%s"}`
|
||||
)
|
||||
|
||||
var PromptMap = map[string]string{
|
||||
"raw": raw_promt,
|
||||
"default": default_prompt,
|
||||
"VulnerabilityReport": trivy_vuln_prompt, // for Trivy integration, the key should match `Result.Kind` in pkg/common/types.go
|
||||
"ConfigAuditReport": trivy_conf_prompt,
|
||||
"PrometheusConfigValidate": prom_conf_prompt,
|
||||
"PrometheusConfigRelabelReport": prom_relabel_prompt,
|
||||
"PolicyReport": kyverno_prompt,
|
||||
|
||||
@@ -295,7 +295,9 @@ func (a *Analysis) executeAnalyzer(analyzer common.IAnalyzer, filter string, ana
|
||||
|
||||
// Run the analyzer
|
||||
results, err := analyzer.Analyze(analyzerConfig)
|
||||
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
// Measure the time taken
|
||||
if a.WithStats {
|
||||
elapsedTime = time.Since(startTime)
|
||||
@@ -405,6 +407,9 @@ func (a *Analysis) getAIResultForSanitizedFailures(texts []string, promptTmpl st
|
||||
|
||||
// Process template.
|
||||
prompt := fmt.Sprintf(strings.TrimSpace(promptTmpl), a.Language, inputKey)
|
||||
if a.AIClient.GetName() == ai.CustomRestClientName {
|
||||
prompt = fmt.Sprintf(ai.PromptMap["raw"], a.Language, inputKey, prompt)
|
||||
}
|
||||
response, err := a.AIClient.GetCompletion(a.Context, prompt)
|
||||
if err != nil {
|
||||
return "", err
|
||||
|
||||
@@ -53,7 +53,6 @@ func (HpaAnalyzer) Analyze(a common.Analyzer) ([]common.Result, error) {
|
||||
for _, hpa := range list.Items {
|
||||
var failures []common.Failure
|
||||
|
||||
|
||||
//check the error from status field
|
||||
conditions := hpa.Status.Conditions
|
||||
for _, condition := range conditions {
|
||||
|
||||
@@ -566,7 +566,6 @@ func TestHPAAnalyzerLabelSelectorFiltering(t *testing.T) {
|
||||
assert.Equal(t, len(analysisResults), 1)
|
||||
}
|
||||
|
||||
|
||||
func TestHPAAnalyzerStatusFieldAbleToScale(t *testing.T) {
|
||||
clientset := fake.NewSimpleClientset(
|
||||
&autoscalingv2.HorizontalPodAutoscaler{
|
||||
@@ -584,8 +583,8 @@ func TestHPAAnalyzerStatusFieldAbleToScale(t *testing.T) {
|
||||
Status: autoscalingv2.HorizontalPodAutoscalerStatus{
|
||||
Conditions: []autoscalingv2.HorizontalPodAutoscalerCondition{
|
||||
{
|
||||
Type: "AbleToScale",
|
||||
Status: "False",
|
||||
Type: "AbleToScale",
|
||||
Status: "False",
|
||||
Message: "test reason",
|
||||
},
|
||||
},
|
||||
@@ -607,7 +606,6 @@ func TestHPAAnalyzerStatusFieldAbleToScale(t *testing.T) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
func TestHPAAnalyzerStatusFieldScalingActive(t *testing.T) {
|
||||
clientset := fake.NewSimpleClientset(
|
||||
&autoscalingv2.HorizontalPodAutoscaler{
|
||||
@@ -625,8 +623,8 @@ func TestHPAAnalyzerStatusFieldScalingActive(t *testing.T) {
|
||||
Status: autoscalingv2.HorizontalPodAutoscalerStatus{
|
||||
Conditions: []autoscalingv2.HorizontalPodAutoscalerCondition{
|
||||
{
|
||||
Type: autoscalingv2.ScalingActive,
|
||||
Status: "False",
|
||||
Type: autoscalingv2.ScalingActive,
|
||||
Status: "False",
|
||||
Message: "test reason",
|
||||
},
|
||||
},
|
||||
@@ -648,8 +646,6 @@ func TestHPAAnalyzerStatusFieldScalingActive(t *testing.T) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
func TestHPAAnalyzerStatusFieldScalingLimited(t *testing.T) {
|
||||
clientset := fake.NewSimpleClientset(
|
||||
&autoscalingv2.HorizontalPodAutoscaler{
|
||||
@@ -667,8 +663,8 @@ func TestHPAAnalyzerStatusFieldScalingLimited(t *testing.T) {
|
||||
Status: autoscalingv2.HorizontalPodAutoscalerStatus{
|
||||
Conditions: []autoscalingv2.HorizontalPodAutoscalerCondition{
|
||||
{
|
||||
Type: autoscalingv2.ScalingLimited,
|
||||
Status: "False",
|
||||
Type: autoscalingv2.ScalingLimited,
|
||||
Status: "False",
|
||||
Message: "test reason",
|
||||
},
|
||||
},
|
||||
@@ -690,7 +686,6 @@ func TestHPAAnalyzerStatusFieldScalingLimited(t *testing.T) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
func TestHPAAnalyzerStatusField(t *testing.T) {
|
||||
clientset := fake.NewSimpleClientset(
|
||||
&autoscalingv2.HorizontalPodAutoscaler{
|
||||
@@ -708,18 +703,18 @@ func TestHPAAnalyzerStatusField(t *testing.T) {
|
||||
Status: autoscalingv2.HorizontalPodAutoscalerStatus{
|
||||
Conditions: []autoscalingv2.HorizontalPodAutoscalerCondition{
|
||||
{
|
||||
Type: autoscalingv2.AbleToScale,
|
||||
Status: "True",
|
||||
Type: autoscalingv2.AbleToScale,
|
||||
Status: "True",
|
||||
Message: "recommended size matches current size",
|
||||
},
|
||||
{
|
||||
Type: autoscalingv2.ScalingActive,
|
||||
Status: "True",
|
||||
Type: autoscalingv2.ScalingActive,
|
||||
Status: "True",
|
||||
Message: "the HPA was able to successfully calculate a replica count",
|
||||
},
|
||||
{
|
||||
Type: autoscalingv2.ScalingLimited,
|
||||
Status: "True",
|
||||
Type: autoscalingv2.ScalingLimited,
|
||||
Status: "True",
|
||||
Message: "the desired replica count is less than the minimum replica count",
|
||||
},
|
||||
},
|
||||
@@ -739,4 +734,4 @@ func TestHPAAnalyzerStatusField(t *testing.T) {
|
||||
}
|
||||
assert.Equal(t, len(analysisResults), 1)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -384,7 +384,7 @@ func TestStatefulSetAnalyzerUnavailableReplicaWithPodInitialized(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
|
||||
var errorFound bool
|
||||
want := "Statefulset pod example-1 in the namespace default is not in running state."
|
||||
|
||||
|
||||
18
pkg/cache/cache.go
vendored
18
pkg/cache/cache.go
vendored
@@ -14,6 +14,7 @@ var (
|
||||
&FileBasedCache{},
|
||||
&GCSCache{},
|
||||
&S3Cache{},
|
||||
&InterplexCache{},
|
||||
}
|
||||
)
|
||||
|
||||
@@ -54,15 +55,21 @@ func NewCacheProvider(cacheType, bucketname, region, endpoint, storageAccount, c
|
||||
case cacheType == "azure":
|
||||
cProvider.Azure.ContainerName = containerName
|
||||
cProvider.Azure.StorageAccount = storageAccount
|
||||
cProvider.CurrentCacheType = "azure"
|
||||
case cacheType == "gcs":
|
||||
cProvider.GCS.BucketName = bucketname
|
||||
cProvider.GCS.ProjectId = projectId
|
||||
cProvider.GCS.Region = region
|
||||
cProvider.CurrentCacheType = "gcs"
|
||||
case cacheType == "s3":
|
||||
cProvider.S3.BucketName = bucketname
|
||||
cProvider.S3.Region = region
|
||||
cProvider.S3.Endpoint = endpoint
|
||||
cProvider.S3.InsecureSkipVerify = insecure
|
||||
cProvider.CurrentCacheType = "s3"
|
||||
case cacheType == "interplex":
|
||||
cProvider.Interplex.ConnectionString = endpoint
|
||||
cProvider.CurrentCacheType = "interplex"
|
||||
default:
|
||||
return CacheProvider{}, status.Error(codes.Internal, fmt.Sprintf("%s is not a valid option", cacheType))
|
||||
}
|
||||
@@ -83,20 +90,19 @@ func GetCacheConfiguration() (ICache, error) {
|
||||
}
|
||||
|
||||
var cache ICache
|
||||
|
||||
switch {
|
||||
case cacheInfo.GCS != GCSCacheConfiguration{}:
|
||||
case cacheInfo.CurrentCacheType == "gcs":
|
||||
cache = &GCSCache{}
|
||||
case cacheInfo.Azure != AzureCacheConfiguration{}:
|
||||
case cacheInfo.CurrentCacheType == "azure":
|
||||
cache = &AzureCache{}
|
||||
case cacheInfo.S3 != S3CacheConfiguration{}:
|
||||
case cacheInfo.CurrentCacheType == "s3":
|
||||
cache = &S3Cache{}
|
||||
case cacheInfo.CurrentCacheType == "interplex":
|
||||
cache = &InterplexCache{}
|
||||
default:
|
||||
cache = &FileBasedCache{}
|
||||
}
|
||||
|
||||
err_config := cache.Configure(cacheInfo)
|
||||
|
||||
return cache, err_config
|
||||
}
|
||||
|
||||
|
||||
108
pkg/cache/interplex_based.go
vendored
Normal file
108
pkg/cache/interplex_based.go
vendored
Normal file
@@ -0,0 +1,108 @@
|
||||
package cache
|
||||
|
||||
import (
|
||||
rpc "buf.build/gen/go/interplex-ai/schemas/grpc/go/protobuf/schema/v1/schemav1grpc"
|
||||
schemav1 "buf.build/gen/go/interplex-ai/schemas/protocolbuffers/go/protobuf/schema/v1"
|
||||
"context"
|
||||
"errors"
|
||||
"google.golang.org/grpc"
|
||||
"os"
|
||||
)
|
||||
|
||||
var _ ICache = (*InterplexCache)(nil)
|
||||
|
||||
type InterplexCache struct {
|
||||
configuration InterplexCacheConfiguration
|
||||
client InterplexClient
|
||||
cacheServiceClient rpc.CacheServiceClient
|
||||
noCache bool
|
||||
}
|
||||
|
||||
type InterplexCacheConfiguration struct {
|
||||
ConnectionString string `mapstructure:"connectionString" yaml:"connectionString,omitempty"`
|
||||
}
|
||||
|
||||
type InterplexClient struct {
|
||||
}
|
||||
|
||||
func (c *InterplexCache) Configure(cacheInfo CacheProvider) error {
|
||||
|
||||
if cacheInfo.Interplex.ConnectionString == "" {
|
||||
return errors.New("connection string is required")
|
||||
}
|
||||
c.configuration.ConnectionString = cacheInfo.Interplex.ConnectionString
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *InterplexCache) Store(key string, data string) error {
|
||||
|
||||
if os.Getenv("INTERPLEX_LOCAL_MODE") != "" {
|
||||
c.configuration.ConnectionString = "localhost:8084"
|
||||
}
|
||||
|
||||
conn, err := grpc.NewClient(c.configuration.ConnectionString, grpc.WithInsecure(), grpc.WithBlock())
|
||||
defer conn.Close()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
serviceClient := rpc.NewCacheServiceClient(conn)
|
||||
c.cacheServiceClient = serviceClient
|
||||
req := schemav1.SetRequest{
|
||||
Key: key,
|
||||
Value: data,
|
||||
}
|
||||
_, err = c.cacheServiceClient.Set(context.Background(), &req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *InterplexCache) Load(key string) (string, error) {
|
||||
conn, err := grpc.NewClient(c.configuration.ConnectionString, grpc.WithInsecure(), grpc.WithBlock())
|
||||
defer conn.Close()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
serviceClient := rpc.NewCacheServiceClient(conn)
|
||||
c.cacheServiceClient = serviceClient
|
||||
req := schemav1.GetRequest{
|
||||
Key: key,
|
||||
}
|
||||
resp, err := c.cacheServiceClient.Get(context.Background(), &req)
|
||||
// check if response is cache error not found
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return resp.Value, nil
|
||||
}
|
||||
|
||||
func (InterplexCache) List() ([]CacheObjectDetails, error) {
|
||||
//TODO implement me
|
||||
return nil, errors.New("not implemented")
|
||||
}
|
||||
|
||||
func (InterplexCache) Remove(key string) error {
|
||||
|
||||
return errors.New("not implemented")
|
||||
}
|
||||
|
||||
func (c *InterplexCache) Exists(key string) bool {
|
||||
if _, err := c.Load(key); err != nil {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (c *InterplexCache) IsCacheDisabled() bool {
|
||||
return c.noCache
|
||||
}
|
||||
|
||||
func (InterplexCache) GetName() string {
|
||||
//TODO implement me
|
||||
return "interplex"
|
||||
}
|
||||
|
||||
func (c *InterplexCache) DisableCache() {
|
||||
c.noCache = true
|
||||
}
|
||||
77
pkg/cache/interplex_based_test.go
vendored
Normal file
77
pkg/cache/interplex_based_test.go
vendored
Normal file
@@ -0,0 +1,77 @@
|
||||
package cache
|
||||
|
||||
import (
|
||||
rpc "buf.build/gen/go/interplex-ai/schemas/grpc/go/protobuf/schema/v1/schemav1grpc"
|
||||
schemav1 "buf.build/gen/go/interplex-ai/schemas/protocolbuffers/go/protobuf/schema/v1"
|
||||
"context"
|
||||
"errors"
|
||||
"google.golang.org/grpc"
|
||||
"net"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestInterplexCache(t *testing.T) {
|
||||
cache := &InterplexCache{
|
||||
configuration: InterplexCacheConfiguration{
|
||||
ConnectionString: "localhost:50051",
|
||||
},
|
||||
}
|
||||
|
||||
// Mock GRPC server setup
|
||||
go func() {
|
||||
lis, err := net.Listen("tcp", ":50051")
|
||||
if err != nil {
|
||||
t.Fatalf("failed to listen: %v", err)
|
||||
}
|
||||
s := grpc.NewServer()
|
||||
rpc.RegisterCacheServiceServer(s, &mockCacheService{})
|
||||
if err := s.Serve(lis); err != nil {
|
||||
t.Fatalf("failed to serve: %v", err)
|
||||
}
|
||||
}()
|
||||
|
||||
t.Run("TestStore", func(t *testing.T) {
|
||||
err := cache.Store("key1", "value1")
|
||||
if err != nil {
|
||||
t.Errorf("Error storing value: %v", err)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("TestLoad", func(t *testing.T) {
|
||||
value, err := cache.Load("key1")
|
||||
if err != nil {
|
||||
t.Errorf("Error loading value: %v", err)
|
||||
}
|
||||
if value != "value1" {
|
||||
t.Errorf("Expected value1, got %v", value)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("TestExists", func(t *testing.T) {
|
||||
exists := cache.Exists("key1")
|
||||
if !exists {
|
||||
t.Errorf("Expected key1 to exist")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
type mockCacheService struct {
|
||||
rpc.UnimplementedCacheServiceServer
|
||||
data map[string]string
|
||||
}
|
||||
|
||||
func (m *mockCacheService) Set(ctx context.Context, req *schemav1.SetRequest) (*schemav1.SetResponse, error) {
|
||||
if m.data == nil {
|
||||
m.data = make(map[string]string)
|
||||
}
|
||||
m.data[req.Key] = req.Value
|
||||
return &schemav1.SetResponse{}, nil
|
||||
}
|
||||
|
||||
func (m *mockCacheService) Get(ctx context.Context, req *schemav1.GetRequest) (*schemav1.GetResponse, error) {
|
||||
value, exists := m.data[req.Key]
|
||||
if !exists {
|
||||
return nil, errors.New("key not found")
|
||||
}
|
||||
return &schemav1.GetResponse{Value: value}, nil
|
||||
}
|
||||
8
pkg/cache/types.go
vendored
8
pkg/cache/types.go
vendored
@@ -3,9 +3,11 @@ 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"`
|
||||
CurrentCacheType string `mapstructure:"currentCacheType" yaml:"currentCacheType"`
|
||||
GCS GCSCacheConfiguration `mapstructure:"gcs" yaml:"gcs,omitempty"`
|
||||
Azure AzureCacheConfiguration `mapstructure:"azure" yaml:"azure,omitempty"`
|
||||
S3 S3CacheConfiguration `mapstructure:"s3" yaml:"s3,omitempty"`
|
||||
Interplex InterplexCacheConfiguration `mapstructure:"interplex" yaml:"interplex,omitempty"`
|
||||
}
|
||||
|
||||
type CacheObjectDetails struct {
|
||||
|
||||
@@ -17,7 +17,6 @@ import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
trivy "github.com/aquasecurity/trivy-operator/pkg/apis/aquasecurity/v1alpha1"
|
||||
openapi_v2 "github.com/google/gnostic/openapiv2"
|
||||
"github.com/k8sgpt-ai/k8sgpt/pkg/ai"
|
||||
"github.com/k8sgpt-ai/k8sgpt/pkg/kubernetes"
|
||||
@@ -67,8 +66,6 @@ type PreAnalysis struct {
|
||||
HTTPRoute gtwapi.HTTPRoute
|
||||
// Integrations
|
||||
ScaledObject keda.ScaledObject
|
||||
TrivyVulnerabilityReport trivy.VulnerabilityReport
|
||||
TrivyConfigAuditReport trivy.ConfigAuditReport
|
||||
KyvernoPolicyReport kyverno.PolicyReport
|
||||
KyvernoClusterPolicyReport kyverno.ClusterPolicyReport
|
||||
}
|
||||
|
||||
@@ -23,7 +23,6 @@ import (
|
||||
"github.com/k8sgpt-ai/k8sgpt/pkg/common"
|
||||
"github.com/k8sgpt-ai/k8sgpt/pkg/integration/keda"
|
||||
"github.com/k8sgpt-ai/k8sgpt/pkg/integration/prometheus"
|
||||
"github.com/k8sgpt-ai/k8sgpt/pkg/integration/trivy"
|
||||
"github.com/k8sgpt-ai/k8sgpt/pkg/util"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
@@ -49,7 +48,6 @@ type Integration struct {
|
||||
}
|
||||
|
||||
var integrations = map[string]IIntegration{
|
||||
"trivy": trivy.NewTrivy(),
|
||||
"prometheus": prometheus.NewPrometheus(),
|
||||
"aws": aws.NewAWS(),
|
||||
"keda": keda.NewKeda(),
|
||||
|
||||
@@ -43,14 +43,6 @@ func TestAnalyzerByIntegration(t *testing.T) {
|
||||
name: "PrometheusConfigRelabelReport",
|
||||
expectedName: "prometheus",
|
||||
},
|
||||
{
|
||||
name: "VulnerabilityReport",
|
||||
expectedName: "trivy",
|
||||
},
|
||||
{
|
||||
name: "ConfigAuditReport",
|
||||
expectedName: "trivy",
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
tt := tt
|
||||
@@ -106,12 +98,6 @@ func TestActivate(t *testing.T) {
|
||||
skipInstall: true,
|
||||
expectedIsActivate: true,
|
||||
},
|
||||
{
|
||||
name: "trivy",
|
||||
skipInstall: false,
|
||||
expectedActivationErr: "failed to deploy trivy integration:",
|
||||
expectedDeactivationErr: "failed to undeploy trivy integration:",
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
tt := tt
|
||||
|
||||
@@ -39,7 +39,7 @@ func (KyvernoAnalyzer) analyzePolicyReports(a common.Analyzer) ([]common.Result,
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := client.List(a.Context, result, &ctrl.ListOptions{}); err != nil {
|
||||
if err := client.List(a.Context, result, &ctrl.ListOptions{Namespace: a.Namespace}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
||||
117
pkg/integration/kyverno/analyzer_test.go
Normal file
117
pkg/integration/kyverno/analyzer_test.go
Normal file
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
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 kyverno
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/k8sgpt-ai/k8sgpt/pkg/common"
|
||||
"github.com/k8sgpt-ai/k8sgpt/pkg/kubernetes"
|
||||
"github.com/kyverno/policy-reporter-kyverno-plugin/pkg/crd/api/policyreport/v1alpha2"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client/fake"
|
||||
)
|
||||
|
||||
func buildFakeClient(t *testing.T) client.Client {
|
||||
objects := []client.Object{
|
||||
&v1alpha2.PolicyReport{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "policy-1",
|
||||
Namespace: "test-ns",
|
||||
},
|
||||
Results: []v1alpha2.PolicyReportResult{
|
||||
{
|
||||
Category: "Other",
|
||||
Message: "validation failure: Images built more than 6 months ago are prohibited.",
|
||||
Policy: "block-stale-images",
|
||||
Result: "fail",
|
||||
},
|
||||
},
|
||||
},
|
||||
&v1alpha2.PolicyReport{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "policy-2",
|
||||
Namespace: "other-ns",
|
||||
},
|
||||
Results: []v1alpha2.PolicyReportResult{
|
||||
{
|
||||
Category: "Other",
|
||||
Message: "validation failure: Images built more than 6 months ago are prohibited.",
|
||||
Policy: "block-stale-images",
|
||||
Result: "fail",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
scheme := runtime.NewScheme()
|
||||
err := v1alpha2.AddToScheme(scheme)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
return fake.NewClientBuilder().WithScheme(scheme).WithObjects(objects...).Build()
|
||||
}
|
||||
|
||||
func TestAnalyzerNamespaceFiltering(t *testing.T) {
|
||||
|
||||
config := common.Analyzer{
|
||||
Client: &kubernetes.Client{
|
||||
CtrlClient: buildFakeClient(t),
|
||||
},
|
||||
Context: context.Background(),
|
||||
Namespace: "test-ns",
|
||||
}
|
||||
|
||||
// Create and run analyzer
|
||||
analyzer := KyvernoAnalyzer{
|
||||
policyReportAnalysis: true,
|
||||
}
|
||||
results, err := analyzer.Analyze(config)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
// Verify results
|
||||
assert.Equal(t, len(results), 1)
|
||||
assert.Equal(t, results[0].Kind, "PolicyReport")
|
||||
assert.Equal(t, results[0].Name, "test-ns/policy-1")
|
||||
}
|
||||
|
||||
func TestAnalyzerAllNamespace(t *testing.T) {
|
||||
|
||||
config := common.Analyzer{
|
||||
Client: &kubernetes.Client{
|
||||
CtrlClient: buildFakeClient(t),
|
||||
},
|
||||
Context: context.Background(),
|
||||
}
|
||||
|
||||
// Create and run analyzer
|
||||
analyzer := KyvernoAnalyzer{
|
||||
policyReportAnalysis: true,
|
||||
}
|
||||
results, err := analyzer.Analyze(config)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
// Verify results
|
||||
assert.Equal(t, len(results), 2)
|
||||
|
||||
}
|
||||
@@ -1,175 +0,0 @@
|
||||
/*
|
||||
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 trivy
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
ctrl "sigs.k8s.io/controller-runtime/pkg/client"
|
||||
|
||||
"github.com/aquasecurity/trivy-operator/pkg/apis/aquasecurity/v1alpha1"
|
||||
"github.com/k8sgpt-ai/k8sgpt/pkg/common"
|
||||
"github.com/k8sgpt-ai/k8sgpt/pkg/util"
|
||||
)
|
||||
|
||||
type TrivyAnalyzer struct {
|
||||
vulernabilityReportAnalysis bool
|
||||
configAuditReportAnalysis bool
|
||||
}
|
||||
|
||||
func (TrivyAnalyzer) analyzeVulnerabilityReports(a common.Analyzer) ([]common.Result, error) {
|
||||
// Get all trivy VulnerabilityReports
|
||||
result := &v1alpha1.VulnerabilityReportList{}
|
||||
|
||||
client := a.Client.CtrlClient
|
||||
err := v1alpha1.AddToScheme(client.Scheme())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := client.List(a.Context, result, &ctrl.ListOptions{}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Find criticals and get CVE
|
||||
var preAnalysis = map[string]common.PreAnalysis{}
|
||||
|
||||
for _, report := range result.Items {
|
||||
|
||||
// For each pod there may be multiple vulnerabilities
|
||||
var failures []common.Failure
|
||||
distinctFailures := make(map[string]common.Failure)
|
||||
for _, vuln := range report.Report.Vulnerabilities {
|
||||
if vuln.Severity == "CRITICAL" {
|
||||
// get the vulnerability ID
|
||||
// get the vulnerability description
|
||||
text := fmt.Sprintf("critical Vulnerability found ID: %s (learn more at: %s)", vuln.VulnerabilityID, vuln.PrimaryLink)
|
||||
distinctFailures[text] = common.Failure{
|
||||
Text: text,
|
||||
Sensitive: []common.Sensitive{},
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, v := range distinctFailures {
|
||||
failures = append(failures, v)
|
||||
}
|
||||
if len(failures) > 0 {
|
||||
preAnalysis[fmt.Sprintf("%s/%s", report.Namespace,
|
||||
report.Name)] = common.PreAnalysis{
|
||||
TrivyVulnerabilityReport: report,
|
||||
FailureDetails: failures,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for key, value := range preAnalysis {
|
||||
var currentAnalysis = common.Result{
|
||||
Kind: "VulnerabilityReport",
|
||||
Name: key,
|
||||
Error: value.FailureDetails,
|
||||
}
|
||||
|
||||
parent, _ := util.GetParent(a.Client, value.TrivyVulnerabilityReport.ObjectMeta)
|
||||
currentAnalysis.ParentObject = parent
|
||||
a.Results = append(a.Results, currentAnalysis)
|
||||
}
|
||||
|
||||
return a.Results, nil
|
||||
|
||||
}
|
||||
|
||||
func (t TrivyAnalyzer) analyzeConfigAuditReports(a common.Analyzer) ([]common.Result, error) {
|
||||
// Get all trivy ConfigAuditReports
|
||||
result := &v1alpha1.ConfigAuditReportList{}
|
||||
|
||||
client := a.Client.CtrlClient
|
||||
err := v1alpha1.AddToScheme(client.Scheme())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := client.List(a.Context, result, &ctrl.ListOptions{}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Find criticals and get CVE
|
||||
var preAnalysis = map[string]common.PreAnalysis{}
|
||||
|
||||
for _, report := range result.Items {
|
||||
|
||||
// For each k8s resources there may be multiple checks
|
||||
var failures []common.Failure
|
||||
for _, check := range report.Report.Checks {
|
||||
if check.Severity == "MEDIUM" || check.Severity == "HIGH" || check.Severity == "CRITICAL" {
|
||||
failures = append(failures, common.Failure{
|
||||
Text: fmt.Sprintf("Config issue with severity \"%s\" found: %s", check.Severity, strings.Join(check.Messages, "")),
|
||||
Sensitive: []common.Sensitive{
|
||||
{
|
||||
Unmasked: report.Labels["trivy-operator.resource.name"],
|
||||
Masked: util.MaskString(report.Labels["trivy-operator.resource.name"]),
|
||||
},
|
||||
{
|
||||
Unmasked: report.Labels["trivy-operator.resource.namespace"],
|
||||
Masked: util.MaskString(report.Labels["trivy-operator.resource.namespace"]),
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
if len(failures) > 0 {
|
||||
preAnalysis[fmt.Sprintf("%s/%s", report.Namespace,
|
||||
report.Name)] = common.PreAnalysis{
|
||||
TrivyConfigAuditReport: report,
|
||||
FailureDetails: failures,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for key, value := range preAnalysis {
|
||||
var currentAnalysis = common.Result{
|
||||
Kind: "ConfigAuditReport",
|
||||
Name: key,
|
||||
Error: value.FailureDetails,
|
||||
}
|
||||
|
||||
parent, _ := util.GetParent(a.Client, value.TrivyConfigAuditReport.ObjectMeta)
|
||||
currentAnalysis.ParentObject = parent
|
||||
a.Results = append(a.Results, currentAnalysis)
|
||||
}
|
||||
|
||||
return a.Results, nil
|
||||
}
|
||||
|
||||
func (t TrivyAnalyzer) Analyze(a common.Analyzer) ([]common.Result, error) {
|
||||
|
||||
if t.vulernabilityReportAnalysis {
|
||||
common := make([]common.Result, 0)
|
||||
vresult, err := t.analyzeVulnerabilityReports(a)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
common = append(common, vresult...)
|
||||
return common, nil
|
||||
}
|
||||
if t.configAuditReportAnalysis {
|
||||
common := make([]common.Result, 0)
|
||||
cresult, err := t.analyzeConfigAuditReports(a)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
common = append(common, cresult...)
|
||||
return common, nil
|
||||
}
|
||||
return make([]common.Result, 0), nil
|
||||
}
|
||||
@@ -1,199 +0,0 @@
|
||||
/*
|
||||
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 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"
|
||||
)
|
||||
|
||||
var (
|
||||
Repo = getEnv("TRIVY_REPO", "https://aquasecurity.github.io/helm-charts/")
|
||||
Version = getEnv("TRIVY_VERSION", "0.13.0")
|
||||
ChartName = getEnv("TRIVY_CHART_NAME", "trivy-operator")
|
||||
RepoShortName = getEnv("TRIVY_REPO_SHORT_NAME", "aqua")
|
||||
ReleaseName = getEnv("TRIVY_RELEASE_NAME", "trivy-operator-k8sgpt")
|
||||
)
|
||||
|
||||
type Trivy struct {
|
||||
helm helmclient.Client
|
||||
}
|
||||
|
||||
func getEnv(key, defaultValue string) string {
|
||||
value := os.Getenv(key)
|
||||
if value == "" {
|
||||
return defaultValue
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
func NewTrivy() *Trivy {
|
||||
helmClient, err := helmclient.New(&helmclient.Options{})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return &Trivy{
|
||||
helm: helmClient,
|
||||
}
|
||||
}
|
||||
|
||||
func (t *Trivy) GetAnalyzerName() []string {
|
||||
return []string{
|
||||
"VulnerabilityReport",
|
||||
"ConfigAuditReport",
|
||||
}
|
||||
}
|
||||
|
||||
// This doesnt work
|
||||
func (t *Trivy) GetNamespace() (string, error) {
|
||||
releases, err := t.helm.ListDeployedReleases()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
for _, rel := range releases {
|
||||
if rel.Name == ReleaseName {
|
||||
return rel.Namespace, nil
|
||||
}
|
||||
}
|
||||
return "", status.Error(codes.NotFound, "trivy release not found")
|
||||
}
|
||||
|
||||
func (t *Trivy) OwnsAnalyzer(analyzer string) bool {
|
||||
|
||||
for _, a := range t.GetAnalyzerName() {
|
||||
if analyzer == a {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
func (t *Trivy) Deploy(namespace string) error {
|
||||
|
||||
// Add the repository
|
||||
chartRepo := repo.Entry{
|
||||
Name: RepoShortName,
|
||||
URL: Repo,
|
||||
}
|
||||
// Add a chart-repository to the client.
|
||||
if err := t.helm.AddOrUpdateChartRepo(chartRepo); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
chartSpec := helmclient.ChartSpec{
|
||||
ReleaseName: ReleaseName,
|
||||
ChartName: fmt.Sprintf("%s/%s", RepoShortName, ChartName),
|
||||
Namespace: namespace,
|
||||
|
||||
//TODO: All of this should be configurable
|
||||
UpgradeCRDs: true,
|
||||
Wait: false,
|
||||
Timeout: 300,
|
||||
CreateNamespace: true,
|
||||
}
|
||||
|
||||
// Install a chart release.
|
||||
// Note that helmclient.Options.Namespace should ideally match the namespace in chartSpec.Namespace.
|
||||
if _, err := t.helm.InstallOrUpgradeChart(context.Background(), &chartSpec, nil); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *Trivy) UnDeploy(namespace string) error {
|
||||
chartSpec := helmclient.ChartSpec{
|
||||
ReleaseName: ReleaseName,
|
||||
ChartName: fmt.Sprintf("%s/%s", RepoShortName, ChartName),
|
||||
Namespace: namespace,
|
||||
UpgradeCRDs: true,
|
||||
Wait: false,
|
||||
Timeout: 300,
|
||||
}
|
||||
// Uninstall the chart release.
|
||||
// Note that helmclient.Options.Namespace should ideally match the namespace in chartSpec.Namespace.
|
||||
if err := t.helm.UninstallRelease(&chartSpec); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
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) {
|
||||
|
||||
(*mergedMap)["VulnerabilityReport"] = &TrivyAnalyzer{
|
||||
vulernabilityReportAnalysis: true,
|
||||
}
|
||||
(*mergedMap)["ConfigAuditReport"] = &TrivyAnalyzer{
|
||||
configAuditReportAnalysis: true,
|
||||
}
|
||||
|
||||
}
|
||||
@@ -19,12 +19,12 @@ grpcurl -plaintext -d '{"namespace": "k8sgpt", "explain" : "true"}' localhost:80
|
||||
grpcurl -plaintext localhost:8080 schema.v1.ServiceConfigService/ListIntegrations
|
||||
{
|
||||
"integrations": [
|
||||
"trivy"
|
||||
"prometheus"
|
||||
]
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
```
|
||||
grpcurl -plaintext -d '{"integrations":{"trivy":{"enabled":"true","namespace":"default","skipInstall":"false"}}}' localhost:8080 schema.v1.ServiceConfigService/AddConfig
|
||||
grpcurl -plaintext -d '{"integrations":{"prometheus":{"enabled":"true","namespace":"default","skipInstall":"false"}}}' localhost:8080 schema.v1.ServiceConfigService/AddConfig
|
||||
```
|
||||
|
||||
@@ -34,10 +34,10 @@ func (h *Handler) Analyze(ctx context.Context, i *schemav1.AnalyzeRequest) (
|
||||
[]string{}, //TODO: add custom http headers in server mode
|
||||
false, // with stats disable
|
||||
)
|
||||
config.Context = ctx // Replace context for correct timeouts.
|
||||
if err != nil {
|
||||
return &schemav1.AnalyzeResponse{}, err
|
||||
}
|
||||
config.Context = ctx // Replace context for correct timeouts.
|
||||
defer config.Close()
|
||||
|
||||
if config.CustomAnalyzersAreAvailable() {
|
||||
|
||||
@@ -71,6 +71,8 @@ func (h *Handler) AddConfig(ctx context.Context, i *schemav1.AddConfigRequest) (
|
||||
remoteCache, err = cache.NewCacheProvider("s3", i.Cache.GetS3Cache().BucketName, i.Cache.GetS3Cache().Region, i.Cache.GetS3Cache().Endpoint, notUsedStorageAcc, notUsedContainerName, notUsedProjectId, i.Cache.GetS3Cache().Insecure)
|
||||
case *schemav1.Cache_GcsCache:
|
||||
remoteCache, err = cache.NewCacheProvider("gcs", i.Cache.GetGcsCache().BucketName, i.Cache.GetGcsCache().Region, notUsedEndpoint, notUsedStorageAcc, notUsedContainerName, i.Cache.GetGcsCache().GetProjectId(), notUsedInsecure)
|
||||
case *schemav1.Cache_InterplexCache:
|
||||
remoteCache, err = cache.NewCacheProvider("interplex", notUsedBucket, notUsedRegion, i.Cache.GetInterplexCache().Endpoint, notUsedStorageAcc, notUsedContainerName, notUsedProjectId, notUsedInsecure)
|
||||
default:
|
||||
return resp, status.Error(codes.InvalidArgument, "Invalid cache configuration")
|
||||
}
|
||||
|
||||
@@ -4,16 +4,14 @@ import (
|
||||
schemav1 "buf.build/gen/go/k8sgpt-ai/k8sgpt/protocolbuffers/go/schema/v1"
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/k8sgpt-ai/k8sgpt/pkg/analyzer"
|
||||
"github.com/k8sgpt-ai/k8sgpt/pkg/integration"
|
||||
"github.com/spf13/viper"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
const (
|
||||
trivyName = "trivy"
|
||||
)
|
||||
//const (
|
||||
// trivyName = "trivy"
|
||||
//)
|
||||
|
||||
// syncIntegration is aware of the following events
|
||||
// A new integration added
|
||||
@@ -21,6 +19,9 @@ const (
|
||||
func (h *Handler) syncIntegration(ctx context.Context,
|
||||
i *schemav1.AddConfigRequest) (*schemav1.AddConfigResponse, error,
|
||||
) {
|
||||
|
||||
fmt.Println("WARNING: syncIntegration is deprecated.")
|
||||
|
||||
response := &schemav1.AddConfigResponse{}
|
||||
integrationProvider := integration.NewIntegration()
|
||||
if i.Integrations == nil {
|
||||
@@ -31,98 +32,106 @@ func (h *Handler) syncIntegration(ctx context.Context,
|
||||
}
|
||||
return response, nil
|
||||
}
|
||||
coreFilters, _, _ := analyzer.ListFilters()
|
||||
// Update filters
|
||||
activeFilters := viper.GetStringSlice("active_filters")
|
||||
if len(activeFilters) == 0 {
|
||||
activeFilters = coreFilters
|
||||
}
|
||||
var err error = status.Error(codes.OK, "")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
deactivateFunc := func(integrationRef integration.IIntegration) error {
|
||||
namespace, err := integrationRef.GetNamespace()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = integrationProvider.Deactivate(trivyName, namespace)
|
||||
if err != nil {
|
||||
return status.Error(codes.NotFound, "integration already deactivated")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
integrationRef, err := integrationProvider.Get(trivyName)
|
||||
if err != nil {
|
||||
return response, status.Error(codes.NotFound, "provider get failure")
|
||||
}
|
||||
if i.Integrations.Trivy != nil {
|
||||
switch i.Integrations.Trivy.Enabled {
|
||||
case true:
|
||||
if b, err := integrationProvider.IsActivate(trivyName); err != nil {
|
||||
return response, status.Error(codes.Internal, "integration activation error")
|
||||
} else {
|
||||
if !b {
|
||||
err := integrationProvider.Activate(trivyName, i.Integrations.Trivy.Namespace,
|
||||
activeFilters, i.Integrations.Trivy.SkipInstall)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
return response, status.Error(codes.AlreadyExists, "integration already active")
|
||||
}
|
||||
}
|
||||
case false:
|
||||
err = deactivateFunc(integrationRef)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// This break is included purely for static analysis to pass
|
||||
}
|
||||
} else {
|
||||
// If Trivy has been removed, disable it
|
||||
err = deactivateFunc(integrationRef)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return response, err
|
||||
// Warning: This code is an example of an integration modifying the active filter list
|
||||
// This integration is no longer part of K8sGPT due to compatibility issues
|
||||
|
||||
//coreFilters, _, _ := analyzer.ListFilters()
|
||||
// Update filters
|
||||
//activeFilters := viper.GetStringSlice("active_filters")
|
||||
//if len(activeFilters) == 0 {
|
||||
// activeFilters = coreFilters
|
||||
//}
|
||||
//var err error = status.Error(codes.OK, "")
|
||||
//if err != nil {
|
||||
// fmt.Println(err)
|
||||
//}
|
||||
//deactivateFunc := func(integrationRef integration.IIntegration) error {
|
||||
// namespace, err := integrationRef.GetNamespace()
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
// err = integrationProvider.Deactivate(trivyName, namespace)
|
||||
// if err != nil {
|
||||
// return status.Error(codes.NotFound, "integration already deactivated")
|
||||
// }
|
||||
// return nil
|
||||
//}
|
||||
//integrationRef, err := integrationProvider.Get(trivyName)
|
||||
//if err != nil {
|
||||
// return response, status.Error(codes.NotFound, "provider get failure")
|
||||
//}
|
||||
//if i.Integrations.Trivy != nil {
|
||||
// switch i.Integrations.Trivy.Enabled {
|
||||
// case true:
|
||||
// if b, err := integrationProvider.IsActivate(trivyName); err != nil {
|
||||
// return response, status.Error(codes.Internal, "integration activation error")
|
||||
// } else {
|
||||
// if !b {
|
||||
// err := integrationProvider.Activate(trivyName, i.Integrations.Trivy.Namespace,
|
||||
// activeFilters, i.Integrations.Trivy.SkipInstall)
|
||||
// if err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
// } else {
|
||||
// return response, status.Error(codes.AlreadyExists, "integration already active")
|
||||
// }
|
||||
// }
|
||||
// case false:
|
||||
// err = deactivateFunc(integrationRef)
|
||||
// if err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
// // This break is included purely for static analysis to pass
|
||||
// }
|
||||
//} else {
|
||||
// // If Trivy has been removed, disable it
|
||||
// err = deactivateFunc(integrationRef)
|
||||
// if err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
//}
|
||||
|
||||
return response, nil
|
||||
}
|
||||
|
||||
func (*Handler) ListIntegrations(ctx context.Context, req *schemav1.ListIntegrationsRequest) (*schemav1.ListIntegrationsResponse, error) {
|
||||
func (h *Handler) ListIntegrations(ctx context.Context, req *schemav1.ListIntegrationsRequest) (*schemav1.ListIntegrationsResponse, error) {
|
||||
|
||||
integrationProvider := integration.NewIntegration()
|
||||
fmt.Println("WARNING: ListIntegrations is deprecated.")
|
||||
|
||||
//integrationProvider := integration.NewIntegration()
|
||||
// Update the requester with the status of Trivy
|
||||
trivy, err := integrationProvider.Get(trivyName)
|
||||
active := trivy.IsActivate()
|
||||
var skipInstall bool
|
||||
var namespace string = ""
|
||||
if active {
|
||||
namespace, err = trivy.GetNamespace()
|
||||
if err != nil {
|
||||
return nil, status.Error(codes.NotFound, "namespace not found")
|
||||
}
|
||||
if namespace == "" {
|
||||
skipInstall = true
|
||||
}
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return nil, status.Error(codes.NotFound, "trivy integration")
|
||||
}
|
||||
//trivy, err := integrationProvider.Get(trivyName)
|
||||
//active := trivy.IsActivate()
|
||||
//var skipInstall bool
|
||||
//var namespace string = ""
|
||||
//if active {
|
||||
// namespace, err = trivy.GetNamespace()
|
||||
// if err != nil {
|
||||
// return nil, status.Error(codes.NotFound, "namespace not found")
|
||||
// }
|
||||
// if namespace == "" {
|
||||
// skipInstall = true
|
||||
// }
|
||||
//}
|
||||
//
|
||||
//if err != nil {
|
||||
// return nil, status.Error(codes.NotFound, "trivy integration")
|
||||
//}
|
||||
resp := &schemav1.ListIntegrationsResponse{
|
||||
Trivy: &schemav1.Trivy{
|
||||
Enabled: active,
|
||||
Namespace: namespace,
|
||||
SkipInstall: skipInstall,
|
||||
},
|
||||
//Trivy: &schemav1.Trivy{
|
||||
// Enabled: active,
|
||||
// Namespace: namespace,
|
||||
// SkipInstall: skipInstall,
|
||||
//},
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func (*Handler) deactivateAllIntegrations(integrationProvider *integration.Integration) error {
|
||||
|
||||
fmt.Println("WARNING: deactivateIntegrations is deprecated.")
|
||||
integrations := integrationProvider.List()
|
||||
for _, i := range integrations {
|
||||
b, _ := integrationProvider.IsActivate(i)
|
||||
|
||||
@@ -1,38 +1,65 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"os"
|
||||
"context"
|
||||
"net"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/fatih/color"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"go.uber.org/zap"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/reflection/grpc_reflection_v1alpha"
|
||||
)
|
||||
|
||||
func TestServerInit(t *testing.T) {
|
||||
logger, err := zap.NewDevelopment()
|
||||
if err != nil {
|
||||
color.Red("failed to create logger: %v", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
//nolint:all
|
||||
func TestServe(t *testing.T) {
|
||||
logger, _ := zap.NewDevelopment()
|
||||
defer logger.Sync()
|
||||
server_config := Config{
|
||||
Backend: "openai",
|
||||
Port: "0",
|
||||
MetricsPort: "0",
|
||||
Token: "none",
|
||||
Logger: logger,
|
||||
|
||||
s := &Config{
|
||||
Port: "50059",
|
||||
Logger: logger,
|
||||
EnableHttp: false,
|
||||
}
|
||||
|
||||
go func() {
|
||||
err := server_config.Serve()
|
||||
if err != nil {
|
||||
assert.Fail(t, "serve: %s", err.Error())
|
||||
}
|
||||
err = server_config.Shutdown()
|
||||
if err != nil {
|
||||
assert.Fail(t, "shutdown: %s", err.Error())
|
||||
}
|
||||
err := s.Serve()
|
||||
time.Sleep(time.Second * 2)
|
||||
assert.NoError(t, err, "Serve should not return an error")
|
||||
}()
|
||||
|
||||
// Wait until the server is ready to accept connections
|
||||
err := waitForPort("localhost:50059", 10*time.Second)
|
||||
assert.NoError(t, err, "Server should start without error")
|
||||
|
||||
conn, err := grpc.Dial("localhost:50059", grpc.WithInsecure())
|
||||
assert.NoError(t, err, "Should be able to dial the server")
|
||||
defer conn.Close()
|
||||
|
||||
// Test a simple gRPC reflection request
|
||||
cli := grpc_reflection_v1alpha.NewServerReflectionClient(conn)
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
defer cancel()
|
||||
resp, err := cli.ServerReflectionInfo(ctx)
|
||||
assert.NoError(t, err, "Should be able to get server reflection info")
|
||||
assert.NotNil(t, resp, "Response should not be nil")
|
||||
|
||||
// Cleanup
|
||||
err = s.Shutdown()
|
||||
assert.NoError(t, err, "Shutdown should not return an error")
|
||||
}
|
||||
|
||||
func waitForPort(address string, timeout time.Duration) error {
|
||||
start := time.Now()
|
||||
for {
|
||||
conn, err := net.Dial("tcp", address)
|
||||
if err == nil {
|
||||
conn.Close()
|
||||
return nil
|
||||
}
|
||||
if time.Since(start) > timeout {
|
||||
return err
|
||||
}
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"config:base",
|
||||
"helpers:pinGitHubActionDigests",
|
||||
":gitSignOff",
|
||||
"group:allNonMajor",
|
||||
"group:allNonMajor"
|
||||
],
|
||||
"addLabels": ["dependencies"],
|
||||
"postUpdateOptions": [
|
||||
|
||||
Reference in New Issue
Block a user