Compare commits
98 commits
v0.2.0-alp
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 6608d0aa8c | |||
|
|
29f2e2a2b9 | ||
|
|
0faeee703d | ||
|
|
e3a9fe7026 | ||
|
|
9ef4566cae | ||
|
|
e79a5c1d50 | ||
|
|
89fecd9dcd | ||
|
|
6fee10c737 | ||
|
|
642b3bbf92 | ||
|
|
1fceec374d | ||
|
|
d05df36868 | ||
|
|
5c703f310b | ||
|
|
86a0b0cf4f | ||
|
|
5a26614acf | ||
|
|
39003f006a | ||
|
|
c48bb50f2a | ||
|
|
54c6571ccd | ||
|
|
8d5c6b6738 | ||
|
|
48769587bb | ||
|
|
9aa2e297b9 | ||
|
|
4341b4869c | ||
|
|
8bda81d6cc | ||
|
|
004c03962f | ||
|
|
69a2c509a7 | ||
|
|
b8ff6d9e14 | ||
|
|
9028ef64b1 | ||
|
|
eeed5ae508 | ||
|
|
04d1042a4c | ||
|
|
102c430e1d | ||
|
|
7f647941f6 | ||
|
|
8cf0b0a56e | ||
|
|
f805123a85 | ||
|
|
6b49c21206 | ||
|
|
31ad45eeb6 | ||
|
|
b4113048bb | ||
|
|
118319c7c1 | ||
|
|
10dcbec954 | ||
|
|
b58bf4c895 | ||
|
|
8cc96dbcd1 | ||
|
|
eec158b32c | ||
|
|
a811d129d0 | ||
|
|
98a769b8d1 | ||
|
|
5a6ac12118 | ||
|
|
325bca4af3 | ||
|
|
b2dee1d844 | ||
|
|
9f2764f614 | ||
|
|
37eba0fed9 | ||
|
|
389a8538af | ||
|
|
f24a22d537 | ||
|
|
dfa9848999 | ||
|
|
3f51046279 | ||
|
|
256521ac38 | ||
|
|
e2169865a1 | ||
|
|
fd9a4d544a | ||
|
|
20a16d923c | ||
|
|
212f6fff42 | ||
|
|
2ee2fca8ae | ||
|
|
5915107446 | ||
|
|
e43acd5b65 | ||
|
|
f85fe3d63f | ||
|
|
8082e1a30e | ||
|
|
daf2a13e48 | ||
|
|
4ad7d8e856 | ||
|
|
22f655f48d | ||
|
|
158b35db06 | ||
|
|
eb07ed3774 | ||
|
|
0f4f98dd03 | ||
|
|
f6f22cb686 | ||
|
|
af1c090db5 | ||
|
|
be3026e87c | ||
|
|
5152bab1b8 | ||
|
|
3687c7fea4 | ||
|
|
1e8d0d79a6 | ||
|
|
97ef92706b | ||
|
|
53cdfd70a1 | ||
|
|
7817d20516 | ||
|
|
daadad682b | ||
|
|
f4892be193 | ||
|
|
e687565671 | ||
|
|
567c465ad7 | ||
|
|
f1fed3c462 | ||
|
|
80735ac2eb | ||
|
|
bb45324dcd | ||
|
|
a984782fd7 | ||
|
|
d26973da2a | ||
|
|
69779a0a7d | ||
|
|
c95252547e | ||
|
|
d17b168b4e | ||
|
|
a46c474640 | ||
|
|
65d6d1ae87 | ||
|
|
78547fefaa | ||
|
|
0cc51e48ef | ||
|
|
86b8ac9e94 | ||
|
|
f9b1b26f80 | ||
|
|
19e025c2be | ||
|
|
b23bca73bc | ||
|
|
20d4e68fd4 | ||
|
|
6ae3b25b4d |
504 changed files with 75483 additions and 8039 deletions
59
.github/workflows/build-and-push.yml
vendored
59
.github/workflows/build-and-push.yml
vendored
|
|
@ -1,17 +1,17 @@
|
|||
name: "Build GARM images"
|
||||
name: "Build and push GARM images"
|
||||
on:
|
||||
workflow_dispatch:
|
||||
workflow_call:
|
||||
inputs:
|
||||
push_to_project:
|
||||
description: "Project to build images for"
|
||||
required: true
|
||||
required: false
|
||||
type: string
|
||||
default: "ghcr.io/cloudbase"
|
||||
ref:
|
||||
description: "Ref to build"
|
||||
required: true
|
||||
required: false
|
||||
type: string
|
||||
default: "main"
|
||||
schedule:
|
||||
- cron: "0 2 * * *"
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
|
@ -24,7 +24,7 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: "Checkout"
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
path: src/github.com/cloudbase/garm
|
||||
fetch-depth: 0
|
||||
|
|
@ -39,35 +39,16 @@ jobs:
|
|||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Build and push
|
||||
- name: Build and push image
|
||||
env:
|
||||
IMAGE_REGISTRY: ${{ inputs.push_to_project }}
|
||||
GH_REF: ${{ inputs.ref }}
|
||||
working-directory: src/github.com/cloudbase/garm
|
||||
run: |
|
||||
set -x
|
||||
REGISTRY_INPUT="${{ github.event.inputs.push_to_project }}"
|
||||
REF_INPUT="${{ github.event.inputs.ref }}"
|
||||
|
||||
PUSH_TO_PROJECT="${REGISTRY_INPUT:-ghcr.io/cloudbase}"
|
||||
GH_REF="${REF_INPUT:-main}"
|
||||
cd src/github.com/cloudbase/garm && git checkout "${GH_REF}"
|
||||
|
||||
VERSION=$(git describe --tags --match='v[0-9]*' --always)
|
||||
AZURE_REF=v0.1.0
|
||||
OPENSTACK_REF=v0.1.0
|
||||
LXD_REF=v0.1.0
|
||||
INCUS_REF=v0.1.0
|
||||
AWS_REF=v0.1.0
|
||||
GCP_REF=v0.1.0
|
||||
EQUINIX_REF=v0.1.0
|
||||
K8S_REF=v0.3.2
|
||||
if [ "$GH_REF" == "main" ]; then
|
||||
AZURE_REF="main"
|
||||
OPENSTACK_REF="main"
|
||||
LXD_REF="main"
|
||||
INCUS_REF="main"
|
||||
AWS_REF="main"
|
||||
GCP_REF="main"
|
||||
EQUINIX_REF="main"
|
||||
K8S_REF="main"
|
||||
VERSION="nightly"
|
||||
IMAGE_TAG="nightly"
|
||||
else
|
||||
IMAGE_TAG=$(git describe --tags --match='v[0-9]*' --always ${GH_REF})
|
||||
fi
|
||||
docker buildx build \
|
||||
--provenance=false \
|
||||
|
|
@ -76,13 +57,5 @@ jobs:
|
|||
--label "org.opencontainers.image.description=GARM ${GH_REF}" \
|
||||
--label "org.opencontainers.image.licenses=Apache 2.0" \
|
||||
--build-arg="GARM_REF=${GH_REF}" \
|
||||
--build-arg="AZURE_REF=${AZURE_REF}" \
|
||||
--build-arg="OPENSTACK_REF=${OPENSTACK_REF}" \
|
||||
--build-arg="LXD_REF=${LXD_REF}" \
|
||||
--build-arg="INCUS_REF=${INCUS_REF}" \
|
||||
--build-arg="AWS_REF=${AWS_REF}" \
|
||||
--build-arg="GCP_REF=${GCP_REF}" \
|
||||
--build-arg="EQUINIX_REF=${EQUINIX_REF}" \
|
||||
--build-arg="K8S_REF=${K8S_REF}" \
|
||||
-t ${PUSH_TO_PROJECT}/garm:"${VERSION}" \
|
||||
-t ${IMAGE_REGISTRY}/garm:"${IMAGE_TAG}" \
|
||||
--push .
|
||||
|
|
|
|||
31
.github/workflows/go-tests.yml
vendored
31
.github/workflows/go-tests.yml
vendored
|
|
@ -28,10 +28,11 @@ jobs:
|
|||
sudo apt-get update
|
||||
sudo apt-get install -y libbtrfs-dev build-essential apg jq
|
||||
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: '^1.22.3'
|
||||
- uses: actions/checkout@v3
|
||||
go-version-file: go.mod
|
||||
|
||||
- name: make lint
|
||||
run: make golangci-lint && GOLANGCI_LINT_EXTRA_ARGS="--timeout=8m --build-tags=testing,integration" make lint
|
||||
- name: Verify go vendor, go modules and gofmt
|
||||
|
|
@ -43,15 +44,39 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
needs: [linters]
|
||||
steps:
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y libbtrfs-dev build-essential apg jq default-jre
|
||||
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '>=v24.5.0'
|
||||
|
||||
- name: Set up openapi-generator-cli
|
||||
run: |
|
||||
mkdir -p $HOME/openapi-generator
|
||||
cd $HOME/openapi-generator
|
||||
npm install @openapitools/openapi-generator-cli
|
||||
echo "$HOME/openapi-generator/node_modules/.bin" >> $GITHUB_PATH
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Setup Golang
|
||||
uses: actions/setup-go@v3
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version-file: go.mod
|
||||
|
||||
- run: go version
|
||||
|
||||
- name: Run go generate
|
||||
run: |
|
||||
GOTOOLCHAIN=go1.24.6 make generate
|
||||
|
||||
- name: Run GARM Go Tests
|
||||
run: make go-test
|
||||
|
||||
- name: Run web UI tests
|
||||
run: |
|
||||
make webui-test
|
||||
|
|
|
|||
19
.github/workflows/trigger-manual.yml
vendored
Normal file
19
.github/workflows/trigger-manual.yml
vendored
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
name: Manual build of GARM images
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
push_to_project:
|
||||
description: "Project to build images for"
|
||||
required: true
|
||||
default: "ghcr.io/cloudbase"
|
||||
ref:
|
||||
description: "Ref to build"
|
||||
required: true
|
||||
default: "main"
|
||||
|
||||
jobs:
|
||||
call-build-and-push:
|
||||
uses: ./.github/workflows/build-and-push.yml
|
||||
with:
|
||||
push_to_project: ${{ inputs.push_to_project }}
|
||||
ref: ${{ inputs.ref }}
|
||||
10
.github/workflows/trigger-nightly.yml
vendored
Normal file
10
.github/workflows/trigger-nightly.yml
vendored
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
name: Nightly build of GARM images
|
||||
on:
|
||||
schedule:
|
||||
- cron: "0 2 * * *"
|
||||
|
||||
jobs:
|
||||
call-build-and-push:
|
||||
uses: ./.github/workflows/build-and-push.yml
|
||||
with:
|
||||
ref: "main"
|
||||
6
.gitignore
vendored
6
.gitignore
vendored
|
|
@ -19,3 +19,9 @@ bin/
|
|||
cmd/temp
|
||||
build/
|
||||
release/
|
||||
node_modules/
|
||||
.svelte-kit/
|
||||
debug.html
|
||||
git_push.sh
|
||||
webapp/src/lib/api/generated/docs
|
||||
.env
|
||||
|
|
|
|||
27
.mockery.yaml
Normal file
27
.mockery.yaml
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
with-expecter: true
|
||||
dir: "mocks"
|
||||
mockname: "{{ .InterfaceName }}"
|
||||
outpkg: "mocks"
|
||||
filename: "{{ .InterfaceName }}.go"
|
||||
# V3 compatibility settings
|
||||
resolve-type-alias: false
|
||||
disable-version-string: true
|
||||
issue-845-fix: true
|
||||
packages:
|
||||
# Database store interfaces
|
||||
github.com/cloudbase/garm/database/common:
|
||||
interfaces:
|
||||
Store:
|
||||
config:
|
||||
dir: "{{ .InterfaceDir }}/mocks"
|
||||
# Runner interfaces
|
||||
github.com/cloudbase/garm/runner:
|
||||
interfaces:
|
||||
PoolManagerController:
|
||||
config:
|
||||
dir: "{{ .InterfaceDir }}/mocks"
|
||||
# Runner common interfaces (generate all interfaces in this package)
|
||||
github.com/cloudbase/garm/runner/common:
|
||||
config:
|
||||
dir: "{{ .InterfaceDir }}/mocks"
|
||||
all: true
|
||||
90
Dockerfile
90
Dockerfile
|
|
@ -1,49 +1,63 @@
|
|||
FROM docker.io/golang:alpine AS builder
|
||||
ARG GARM_REF
|
||||
ARG AZURE_REF=v0.1.0
|
||||
ARG OPENSTACK_REF=v0.1.0
|
||||
ARG LXD_REF=v0.1.0
|
||||
ARG INCUS_REF=v0.1.0
|
||||
ARG AWS_REF=v0.1.0
|
||||
ARG GCP_REF=v0.1.0
|
||||
ARG EQUINIX_REF=v0.1.0
|
||||
ARG K8S_REF=v0.3.2
|
||||
|
||||
LABEL stage=builder
|
||||
|
||||
RUN apk add musl-dev gcc libtool m4 autoconf g++ make libblkid util-linux-dev git linux-headers upx
|
||||
RUN git config --global --add safe.directory /build
|
||||
RUN apk add --no-cache musl-dev gcc libtool m4 autoconf g++ make libblkid util-linux-dev git linux-headers upx curl jq
|
||||
RUN git config --global --add safe.directory /build && git config --global --add advice.detachedHead false
|
||||
RUN echo ${GARM_REF}
|
||||
|
||||
ADD . /build/garm
|
||||
RUN cd /build/garm && git checkout ${GARM_REF}
|
||||
RUN git clone --depth 1 --branch ${AZURE_REF} https://github.com/cloudbase/garm-provider-azure /build/garm-provider-azure
|
||||
RUN git clone --depth 1 --branch ${OPENSTACK_REF} https://github.com/cloudbase/garm-provider-openstack /build/garm-provider-openstack
|
||||
RUN git clone --depth 1 --branch ${LXD_REF} https://github.com/cloudbase/garm-provider-lxd /build/garm-provider-lxd
|
||||
RUN git clone --depth 1 --branch ${INCUS_REF} https://github.com/cloudbase/garm-provider-incus /build/garm-provider-incus
|
||||
RUN git clone --depth 1 --branch ${AWS_REF} https://github.com/cloudbase/garm-provider-aws /build/garm-provider-aws
|
||||
RUN git clone --depth 1 --branch ${GCP_REF} https://github.com/cloudbase/garm-provider-gcp /build/garm-provider-gcp
|
||||
RUN git clone --depth 1 --branch ${EQUINIX_REF} https://github.com/cloudbase/garm-provider-equinix /build/garm-provider-equinix
|
||||
|
||||
RUN git clone --depth 1 --branch ${K8S_REF} https://github.com/mercedes-benz/garm-provider-k8s /build/garm-provider-k8s
|
||||
|
||||
RUN cd /build/garm && go build -o /bin/garm \
|
||||
-tags osusergo,netgo,sqlite_omit_load_extension \
|
||||
-ldflags "-linkmode external -extldflags '-static' -s -w -X github.com/cloudbase/garm/util/appdefaults.Version=$(git describe --tags --match='v[0-9]*' --dirty --always)" \
|
||||
/build/garm/cmd/garm && upx /bin/garm
|
||||
RUN cd /build/garm/cmd/garm-cli && go build -o /bin/garm-cli \
|
||||
-tags osusergo,netgo,sqlite_omit_load_extension \
|
||||
-ldflags "-linkmode external -extldflags '-static' -s -w -X github.com/cloudbase/garm/util/appdefaults.Version=$(git describe --tags --match='v[0-9]*' --dirty --always)" \
|
||||
. && upx /bin/garm-cli
|
||||
RUN mkdir -p /opt/garm/providers.d
|
||||
RUN cd /build/garm-provider-azure && go build -ldflags="-linkmode external -extldflags '-static' -s -w -X main.Version=$(git describe --tags --match='v[0-9]*' --dirty --always)" -o /opt/garm/providers.d/garm-provider-azure . && upx /opt/garm/providers.d/garm-provider-azure
|
||||
RUN cd /build/garm-provider-openstack && go build -ldflags="-linkmode external -extldflags '-static' -s -w -X main.Version=$(git describe --tags --match='v[0-9]*' --dirty --always)" -o /opt/garm/providers.d/garm-provider-openstack . && upx /opt/garm/providers.d/garm-provider-openstack
|
||||
RUN cd /build/garm-provider-lxd && go build -ldflags="-linkmode external -extldflags '-static' -s -w -X main.Version=$(git describe --tags --match='v[0-9]*' --dirty --always)" -o /opt/garm/providers.d/garm-provider-lxd . && upx /opt/garm/providers.d/garm-provider-lxd
|
||||
RUN cd /build/garm-provider-incus && go build -ldflags="-linkmode external -extldflags '-static' -s -w -X main.Version=$(git describe --tags --match='v[0-9]*' --dirty --always)" -o /opt/garm/providers.d/garm-provider-incus . && upx /opt/garm/providers.d/garm-provider-incus
|
||||
RUN cd /build/garm-provider-aws && go build -ldflags="-linkmode external -extldflags '-static' -s -w -X main.Version=$(git describe --tags --match='v[0-9]*' --dirty --always)" -o /opt/garm/providers.d/garm-provider-aws . && upx /opt/garm/providers.d/garm-provider-aws
|
||||
RUN cd /build/garm-provider-gcp && go build -ldflags="-linkmode external -extldflags '-static' -s -w -X main.Version=$(git describe --tags --match='v[0-9]*' --dirty --always)" -o /opt/garm/providers.d/garm-provider-gcp . && upx /opt/garm/providers.d/garm-provider-gcp
|
||||
RUN cd /build/garm-provider-equinix && go build -ldflags="-linkmode external -extldflags '-static' -s -w -X main.Version=$(git describe --tags --match='v[0-9]*' --dirty --always)" -o /opt/garm/providers.d/garm-provider-equinix . && upx /opt/garm/providers.d/garm-provider-equinix
|
||||
|
||||
RUN cd /build/garm-provider-k8s/cmd/garm-provider-k8s && go build -ldflags="-linkmode external -extldflags '-static' -s -w" -o /opt/garm/providers.d/garm-provider-k8s . && upx /opt/garm/providers.d/garm-provider-k8s
|
||||
RUN git -C /build/garm checkout ${GARM_REF}
|
||||
RUN cd /build/garm \
|
||||
&& go build -o /bin/garm \
|
||||
-tags osusergo,netgo,sqlite_omit_load_extension \
|
||||
-ldflags "-linkmode external -extldflags '-static' -s -w -X github.com/cloudbase/garm/util/appdefaults.Version=$(git describe --tags --match='v[0-9]*' --dirty --always)" \
|
||||
/build/garm/cmd/garm && upx /bin/garm
|
||||
RUN cd /build/garm/cmd/garm-cli \
|
||||
&& go build -o /bin/garm-cli \
|
||||
-tags osusergo,netgo,sqlite_omit_load_extension \
|
||||
-ldflags "-linkmode external -extldflags '-static' -s -w -X github.com/cloudbase/garm/util/appdefaults.Version=$(git describe --tags --match='v[0-9]*' --dirty --always)" \
|
||||
. && upx /bin/garm-cli
|
||||
RUN set -ex; \
|
||||
mkdir -p /opt/garm/providers.d; \
|
||||
for repo in \
|
||||
cloudbase/garm-provider-azure \
|
||||
cloudbase/garm-provider-openstack \
|
||||
cloudbase/garm-provider-lxd \
|
||||
cloudbase/garm-provider-incus \
|
||||
cloudbase/garm-provider-aws \
|
||||
cloudbase/garm-provider-gcp \
|
||||
cloudbase/garm-provider-equinix \
|
||||
flatcar/garm-provider-linode \
|
||||
mercedes-benz/garm-provider-k8s; \
|
||||
do \
|
||||
export PROVIDER_NAME="$(basename $repo)"; \
|
||||
export PROVIDER_SUBDIR=""; \
|
||||
if [ "$GARM_REF" == "main" ]; then \
|
||||
export PROVIDER_REF="main"; \
|
||||
else \
|
||||
export PROVIDER_REF="$(curl -s -L https://api.github.com/repos/$repo/releases/latest | jq -r '.tag_name')"; \
|
||||
fi; \
|
||||
git clone --branch "$PROVIDER_REF" "https://github.com/$repo" "/build/$PROVIDER_NAME"; \
|
||||
case $PROVIDER_NAME in \
|
||||
"garm-provider-k8s") \
|
||||
export PROVIDER_SUBDIR="cmd/garm-provider-k8s"; \
|
||||
export PROVIDER_LDFLAGS="-linkmode external -extldflags \"-static\" -s -w"; \
|
||||
;; \
|
||||
"garm-provider-linode") \
|
||||
export PROVIDER_LDFLAGS="-linkmode external -extldflags \"-static\" -s -w"; \
|
||||
;; \
|
||||
*) \
|
||||
export PROVIDER_VERSION=$(git -C /build/$PROVIDER_NAME describe --tags --match='v[0-9]*' --dirty --always); \
|
||||
export PROVIDER_LDFLAGS="-linkmode external -extldflags \"-static\" -s -w -X main.Version=$PROVIDER_VERSION"; \
|
||||
;; \
|
||||
esac; \
|
||||
cd "/build/$PROVIDER_NAME/$PROVIDER_SUBDIR" \
|
||||
&& go build -ldflags="$PROVIDER_LDFLAGS" -o /opt/garm/providers.d/$PROVIDER_NAME . \
|
||||
&& upx /opt/garm/providers.d/$PROVIDER_NAME; \
|
||||
done
|
||||
|
||||
FROM busybox
|
||||
|
||||
|
|
|
|||
29
Makefile
29
Makefile
|
|
@ -7,8 +7,9 @@ GEN_PASSWORD=$(shell (/usr/bin/apg -n1 -m32))
|
|||
IMAGE_TAG = garm-build
|
||||
|
||||
IMAGE_BUILDER=$(shell (which docker || which podman))
|
||||
USER_ID=$(shell (($(IMAGE_BUILDER) --version | grep -q podman) && echo "0" || id -u))
|
||||
USER_GROUP=$(shell (($(IMAGE_BUILDER) --version | grep -q podman) && echo "0" || id -g))
|
||||
IS_PODMAN=$(shell (($(IMAGE_BUILDER) --version | grep -q podman) && echo "yes" || echo "no"))
|
||||
USER_ID=$(if $(filter yes,$(IS_PODMAN)),0,$(shell id -u))
|
||||
USER_GROUP=$(if $(filter yes,$(IS_PODMAN)),0,$(shell id -g))
|
||||
ROOTDIR=$(dir $(abspath $(lastword $(MAKEFILE_LIST))))
|
||||
GOPATH ?= $(shell go env GOPATH)
|
||||
VERSION ?= $(shell git describe --tags --match='v[0-9]*' --dirty --always)
|
||||
|
|
@ -21,6 +22,11 @@ export CREDENTIALS_NAME ?= test-garm-creds
|
|||
export WORKFLOW_FILE_NAME ?= test.yml
|
||||
export GARM_ADMIN_USERNAME ?= admin
|
||||
|
||||
ifeq ($(IS_PODMAN),yes)
|
||||
EXTRA_ARGS := -v /etc/ssl/certs/ca-certificates.crt:/etc/ssl/certs/ca-certificates.crt
|
||||
endif
|
||||
|
||||
|
||||
.PHONY: help
|
||||
help: ## Display this help.
|
||||
@awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m<target>\033[0m\n"} /^[a-zA-Z_0-9-]+:.*?##/ { printf " \033[36m%-20s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST)
|
||||
|
|
@ -33,7 +39,7 @@ default: build
|
|||
.PHONY : build-static test install-lint-deps lint go-test fmt fmtcheck verify-vendor verify create-release-files release
|
||||
build-static: ## Build garm statically
|
||||
@echo Building garm
|
||||
$(IMAGE_BUILDER) build -v /etc/ssl/certs/ca-certificates.crt:/etc/ssl/certs/ca-certificates.crt --tag $(IMAGE_TAG) -f Dockerfile.build-static .
|
||||
$(IMAGE_BUILDER) build $(EXTRA_ARGS) --tag $(IMAGE_TAG) -f Dockerfile.build-static .
|
||||
mkdir -p build
|
||||
$(IMAGE_BUILDER) run --rm -e USER_ID=$(USER_ID) -e GARM_REF=$(GARM_REF) -e USER_GROUP=$(USER_GROUP) -v $(PWD)/build:/build/output:z $(IMAGE_TAG) /build-static.sh
|
||||
@echo Binaries are available in $(PWD)/build
|
||||
|
|
@ -49,6 +55,20 @@ build: ## Build garm
|
|||
@$(GO) build -ldflags "-s -w -X github.com/cloudbase/garm/util/appdefaults.Version=${VERSION}" -tags osusergo,netgo,sqlite_omit_load_extension -o bin/garm-cli ./cmd/garm-cli
|
||||
@echo Binaries are available in $(PWD)/bin
|
||||
|
||||
.PHONY: build-webui
|
||||
build-webui:
|
||||
@echo Building GARM web ui
|
||||
./build-webapp.sh
|
||||
rm -rf webapp/assets/_app
|
||||
cp -r webapp/build/* webapp/assets/
|
||||
|
||||
.PHONY: generate
|
||||
generate: ## Run go generate after checking required tools are in PATH
|
||||
@echo Checking required tools...
|
||||
@which openapi-generator-cli > /dev/null || (echo "Error: openapi-generator-cli not found in PATH" && exit 1)
|
||||
@echo Running go generate
|
||||
@$(GO) generate ./...
|
||||
|
||||
test: verify go-test ## Run tests
|
||||
|
||||
##@ Release
|
||||
|
|
@ -95,6 +115,9 @@ go-test: ## Run tests
|
|||
fmt: ## Run go fmt against code.
|
||||
@$(GO) fmt $$(go list ./...)
|
||||
|
||||
webui-test:
|
||||
(cd webapp && npm install)
|
||||
(cd webapp && npm run test:run)
|
||||
|
||||
##@ Build Dependencies
|
||||
|
||||
|
|
|
|||
18
README.md
18
README.md
|
|
@ -18,6 +18,7 @@
|
|||
- [Installing on Kubernetes](#installing-on-kubernetes)
|
||||
- [Configuring GARM for GHES](#configuring-garm-for-ghes)
|
||||
- [Configuring GARM for Gitea](#configuring-garm-for-gitea)
|
||||
- [Enabling the web UI](#enabling-the-web-ui)
|
||||
- [Using GARM](#using-garm)
|
||||
- [Supported providers](#supported-providers)
|
||||
- [Installing external providers](#installing-external-providers)
|
||||
|
|
@ -48,9 +49,11 @@ Here is a brief architectural diagram of how pools work and how GARM reacts to w
|
|||
|
||||
**Scale sets** work differently. While pools (as they are defined in GARM) rely on webhooks to know when a job was started and GARM needs to internally make the right decission in terms of which pool should handle that runner, scale sets have a lot of the scheduling and decission making logic done in GitHub itself.
|
||||
|
||||
:warning: **Important note**: The README and documentation in the `main` branch are relevant to the not yet released code that is present in `main`. Following the documentation from the `main` branch for a stable release of GARM, may lead to errors. To view the documentation for the latest stable release, please switch to the appropriate tag. For information about setting up `v0.1.5`, please refer to the [v0.1.5 tag](https://github.com/cloudbase/garm/tree/v0.1.5).
|
||||
> [!IMPORTANT]
|
||||
> The README and documentation in the `main` branch are relevant to the not yet released code that is present in `main`. Following the documentation from the `main` branch for a stable release of GARM, may lead to errors. To view the documentation for the latest stable release, please switch to the appropriate tag. For information about setting up `v0.1.6`, please refer to the [v0.1.6 tag](https://github.com/cloudbase/garm/tree/v0.1.6).
|
||||
|
||||
:warning: **Important note**: The `main` branch holds the latest code and is not guaranteed to be stable. If you are looking for a stable release, please check the releases page. If you plan to use the `main` branch, please do so on a new instance. Do not upgrade from a stable release to `main`.
|
||||
> [!CAUTION]
|
||||
> The `main` branch holds the latest code and is not guaranteed to be stable. If you are looking for a stable release, please check the releases page. If you plan to use the `main` branch, please do so on a new instance. Do not upgrade from a stable release to `main`.
|
||||
|
||||
## Join us on slack
|
||||
|
||||
|
|
@ -76,6 +79,17 @@ GARM supports creating pools and scale sets in either GitHub itself or in your o
|
|||
|
||||
GARM now has support for Gitea (>=1.24.0). For information on getting started with Gitea, see the [Gitea quickstart](/doc/gitea.md) document.
|
||||
|
||||
## Enabling the web UI
|
||||
|
||||
GARM now ships with a single page application. To enable it, add the following to your GARM config:
|
||||
|
||||
```toml
|
||||
[apiserver.webui]
|
||||
enable = true
|
||||
```
|
||||
|
||||
Check the [README.md](/webapp/README.md) file for details on the web UI.
|
||||
|
||||
## Using GARM
|
||||
|
||||
GARM is designed with simplicity in mind. At least we try to keep it as simple as possible. We're aware that adding a new tool in your workflow can be painful, especially when you already have to deal with so many. The cognitive load for OPS has reached a level where it feels overwhelming at times to even wrap your head around a new tool. As such, we believe that tools should be simple, should take no more than a few hours to understand and set up and if you absolutely need to interact with the tool, it should be as intuitive as possible. Although we try our best to make this happen, we're aware that GARM has some rough edges, especially for new users. If you encounter issues or feel like the setup process was too complicated, please let us know. We're always looking to improve the user experience.
|
||||
|
|
|
|||
|
|
@ -17,30 +17,57 @@ package controllers
|
|||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
gErrors "github.com/cloudbase/garm-provider-common/errors"
|
||||
"github.com/cloudbase/garm-provider-common/util"
|
||||
"github.com/cloudbase/garm/apiserver/events"
|
||||
"github.com/cloudbase/garm/apiserver/params"
|
||||
"github.com/cloudbase/garm/auth"
|
||||
"github.com/cloudbase/garm/config"
|
||||
"github.com/cloudbase/garm/metrics"
|
||||
runnerParams "github.com/cloudbase/garm/params"
|
||||
"github.com/cloudbase/garm/runner" //nolint:typecheck
|
||||
garmUtil "github.com/cloudbase/garm/util"
|
||||
wsWriter "github.com/cloudbase/garm/websocket"
|
||||
"github.com/cloudbase/garm/workers/websocket/events"
|
||||
)
|
||||
|
||||
func NewAPIController(r *runner.Runner, authenticator *auth.Authenticator, hub *wsWriter.Hub) (*APIController, error) {
|
||||
func NewAPIController(r *runner.Runner, authenticator *auth.Authenticator, hub *wsWriter.Hub, apiCfg config.APIServer) (*APIController, error) {
|
||||
controllerInfo, err := r.GetControllerInfo(auth.GetAdminContext(context.Background()))
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to get controller info")
|
||||
return nil, fmt.Errorf("failed to get controller info: %w", err)
|
||||
}
|
||||
var checkOrigin func(r *http.Request) bool
|
||||
if len(apiCfg.CORSOrigins) > 0 {
|
||||
checkOrigin = func(r *http.Request) bool {
|
||||
origin := r.Header["Origin"]
|
||||
if len(origin) == 0 {
|
||||
return true
|
||||
}
|
||||
u, err := url.Parse(origin[0])
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
for _, val := range apiCfg.CORSOrigins {
|
||||
corsVal, err := url.Parse(val)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
if garmUtil.ASCIIEqualFold(u.Host, corsVal.Host) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
return &APIController{
|
||||
r: r,
|
||||
|
|
@ -49,6 +76,7 @@ func NewAPIController(r *runner.Runner, authenticator *auth.Authenticator, hub *
|
|||
upgrader: websocket.Upgrader{
|
||||
ReadBufferSize: 1024,
|
||||
WriteBufferSize: 16384,
|
||||
CheckOrigin: checkOrigin,
|
||||
},
|
||||
controllerID: controllerInfo.ControllerID.String(),
|
||||
}, nil
|
||||
|
|
@ -64,24 +92,22 @@ type APIController struct {
|
|||
|
||||
func handleError(ctx context.Context, w http.ResponseWriter, err error) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
origErr := errors.Cause(err)
|
||||
apiErr := params.APIErrorResponse{
|
||||
Details: origErr.Error(),
|
||||
Details: err.Error(),
|
||||
}
|
||||
|
||||
switch origErr.(type) {
|
||||
case *gErrors.NotFoundError:
|
||||
switch {
|
||||
case errors.Is(err, gErrors.ErrNotFound):
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
apiErr.Error = "Not Found"
|
||||
case *gErrors.UnauthorizedError:
|
||||
case errors.Is(err, gErrors.ErrUnauthorized):
|
||||
w.WriteHeader(http.StatusUnauthorized)
|
||||
apiErr.Error = "Not Authorized"
|
||||
// Don't include details on 401 errors.
|
||||
apiErr.Details = ""
|
||||
case *gErrors.BadRequestError:
|
||||
case errors.Is(err, gErrors.ErrBadRequest):
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
apiErr.Error = "Bad Request"
|
||||
case *gErrors.DuplicateUserError, *gErrors.ConflictError:
|
||||
case errors.Is(err, gErrors.ErrDuplicateEntity), errors.Is(err, &gErrors.ConflictError{}):
|
||||
w.WriteHeader(http.StatusConflict)
|
||||
apiErr.Error = "Conflict"
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@
|
|||
|
||||
package params
|
||||
|
||||
// swagger:model APIErrorResponse
|
||||
// APIErrorResponse holds information about an error, returned by the API
|
||||
type APIErrorResponse struct {
|
||||
Error string `json:"error"`
|
||||
|
|
|
|||
|
|
@ -57,6 +57,8 @@ import (
|
|||
|
||||
"github.com/cloudbase/garm/apiserver/controllers"
|
||||
"github.com/cloudbase/garm/auth"
|
||||
"github.com/cloudbase/garm/config"
|
||||
spaAssets "github.com/cloudbase/garm/webapp/assets"
|
||||
)
|
||||
|
||||
func WithMetricsRouter(parentRouter *mux.Router, disableAuth bool, metricsMiddlerware auth.Middleware) *mux.Router {
|
||||
|
|
@ -82,6 +84,30 @@ func WithDebugServer(parentRouter *mux.Router) *mux.Router {
|
|||
return parentRouter
|
||||
}
|
||||
|
||||
func WithWebUI(parentRouter *mux.Router, apiConfig config.APIServer) *mux.Router {
|
||||
if parentRouter == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
if apiConfig.WebUI.EnableWebUI {
|
||||
slog.Info("WebUI is enabled, adding webapp routes")
|
||||
webappPath := apiConfig.WebUI.GetWebappPath()
|
||||
slog.Info("Using webapp path", "path", webappPath)
|
||||
// Accessing / should redirect to the UI
|
||||
parentRouter.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
||||
http.Redirect(w, r, webappPath, http.StatusMovedPermanently) // 301
|
||||
})
|
||||
// Serve the SPA with dynamic path
|
||||
parentRouter.PathPrefix(webappPath).HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
spaAssets.ServeSPAWithPath(w, r, webappPath)
|
||||
}).Methods("GET")
|
||||
} else {
|
||||
slog.Info("WebUI is disabled, skipping webapp routes")
|
||||
}
|
||||
|
||||
return parentRouter
|
||||
}
|
||||
|
||||
func requestLogger(h http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
// gathers metrics from the upstream handlers
|
||||
|
|
@ -505,7 +531,7 @@ func NewAPIRouter(han *controllers.APIController, authMiddleware, initMiddleware
|
|||
apiRouter.Handle("/ws/events/", http.HandlerFunc(han.EventsHandler)).Methods("GET")
|
||||
apiRouter.Handle("/ws/events", http.HandlerFunc(han.EventsHandler)).Methods("GET")
|
||||
|
||||
// NotFound handler
|
||||
// NotFound handler - this should be last
|
||||
apiRouter.PathPrefix("/").HandlerFunc(han.NotFoundHandler).Methods("GET", "POST", "PUT", "DELETE", "OPTIONS")
|
||||
return router
|
||||
}
|
||||
|
|
|
|||
17
auth/auth.go
17
auth/auth.go
|
|
@ -16,11 +16,12 @@ package auth
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
jwt "github.com/golang-jwt/jwt/v5"
|
||||
"github.com/nbutton23/zxcvbn-go"
|
||||
"github.com/pkg/errors"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
|
||||
runnerErrors "github.com/cloudbase/garm-provider-common/errors"
|
||||
|
|
@ -49,7 +50,7 @@ func (a *Authenticator) IsInitialized() bool {
|
|||
func (a *Authenticator) GetJWTToken(ctx context.Context) (string, error) {
|
||||
tokenID, err := util.GetRandomString(16)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "generating random string")
|
||||
return "", fmt.Errorf("error generating random string: %w", err)
|
||||
}
|
||||
expireToken := time.Now().Add(a.cfg.TimeToLive.Duration())
|
||||
expires := &jwt.NumericDate{
|
||||
|
|
@ -72,7 +73,7 @@ func (a *Authenticator) GetJWTToken(ctx context.Context) (string, error) {
|
|||
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
|
||||
tokenString, err := token.SignedString([]byte(a.cfg.Secret))
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "fetching token string")
|
||||
return "", fmt.Errorf("error fetching token string: %w", err)
|
||||
}
|
||||
|
||||
return tokenString, nil
|
||||
|
|
@ -87,7 +88,7 @@ func (a *Authenticator) GetJWTMetricsToken(ctx context.Context) (string, error)
|
|||
|
||||
tokenID, err := util.GetRandomString(16)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "generating random string")
|
||||
return "", fmt.Errorf("error generating random string: %w", err)
|
||||
}
|
||||
// nolint:golangci-lint,godox
|
||||
// TODO: currently this is the same TTL as the normal Token
|
||||
|
|
@ -111,7 +112,7 @@ func (a *Authenticator) GetJWTMetricsToken(ctx context.Context) (string, error)
|
|||
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
|
||||
tokenString, err := token.SignedString([]byte(a.cfg.Secret))
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "fetching token string")
|
||||
return "", fmt.Errorf("error fetching token string: %w", err)
|
||||
}
|
||||
|
||||
return tokenString, nil
|
||||
|
|
@ -121,7 +122,7 @@ func (a *Authenticator) InitController(ctx context.Context, param params.NewUser
|
|||
_, err := a.store.ControllerInfo()
|
||||
if err != nil {
|
||||
if !errors.Is(err, runnerErrors.ErrNotFound) {
|
||||
return params.User{}, errors.Wrap(err, "initializing controller")
|
||||
return params.User{}, fmt.Errorf("error initializing controller: %w", err)
|
||||
}
|
||||
}
|
||||
if a.store.HasAdminUser(ctx) {
|
||||
|
|
@ -151,7 +152,7 @@ func (a *Authenticator) InitController(ctx context.Context, param params.NewUser
|
|||
|
||||
hashed, err := util.PaswsordToBcrypt(param.Password)
|
||||
if err != nil {
|
||||
return params.User{}, errors.Wrap(err, "creating user")
|
||||
return params.User{}, fmt.Errorf("error creating user: %w", err)
|
||||
}
|
||||
|
||||
param.Password = hashed
|
||||
|
|
@ -169,7 +170,7 @@ func (a *Authenticator) AuthenticateUser(ctx context.Context, info params.Passwo
|
|||
if errors.Is(err, runnerErrors.ErrNotFound) {
|
||||
return ctx, runnerErrors.ErrUnauthorized
|
||||
}
|
||||
return ctx, errors.Wrap(err, "authenticating")
|
||||
return ctx, fmt.Errorf("error authenticating: %w", err)
|
||||
}
|
||||
|
||||
if !user.Enabled {
|
||||
|
|
|
|||
|
|
@ -38,8 +38,8 @@ type initRequired struct {
|
|||
func (i *initRequired) Middleware(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
ctrlInfo, err := i.store.ControllerInfo()
|
||||
if err != nil || ctrlInfo.ControllerID.String() == "" {
|
||||
|
||||
if !i.store.HasAdminUser(ctx) {
|
||||
w.Header().Add("Content-Type", "application/json")
|
||||
w.WriteHeader(http.StatusConflict)
|
||||
if err := json.NewEncoder(w).Encode(params.InitializationRequired); err != nil {
|
||||
|
|
|
|||
|
|
@ -24,7 +24,6 @@ import (
|
|||
"time"
|
||||
|
||||
jwt "github.com/golang-jwt/jwt/v5"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
runnerErrors "github.com/cloudbase/garm-provider-common/errors"
|
||||
commonParams "github.com/cloudbase/garm-provider-common/params"
|
||||
|
|
@ -91,7 +90,7 @@ func (i *instanceToken) NewInstanceJWTToken(instance params.Instance, entity par
|
|||
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
|
||||
tokenString, err := token.SignedString([]byte(i.jwtSecret))
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "signing token")
|
||||
return "", fmt.Errorf("error signing token: %w", err)
|
||||
}
|
||||
|
||||
return tokenString, nil
|
||||
|
|
@ -121,7 +120,7 @@ func (amw *instanceMiddleware) claimsToContext(ctx context.Context, claims *Inst
|
|||
return nil, runnerErrors.ErrUnauthorized
|
||||
}
|
||||
|
||||
instanceInfo, err := amw.store.GetInstanceByName(ctx, claims.Name)
|
||||
instanceInfo, err := amw.store.GetInstance(ctx, claims.Name)
|
||||
if err != nil {
|
||||
return ctx, runnerErrors.ErrUnauthorized
|
||||
}
|
||||
|
|
|
|||
31
auth/jwt.go
31
auth/jwt.go
|
|
@ -97,26 +97,37 @@ func invalidAuthResponse(ctx context.Context, w http.ResponseWriter) {
|
|||
}
|
||||
}
|
||||
|
||||
func (amw *jwtMiddleware) getTokenFromRequest(r *http.Request) (string, error) {
|
||||
authorizationHeader := r.Header.Get("authorization")
|
||||
if authorizationHeader == "" {
|
||||
cookie, err := r.Cookie("garm_token")
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to get cookie: %w", err)
|
||||
}
|
||||
return cookie.Value, nil
|
||||
}
|
||||
|
||||
bearerToken := strings.Split(authorizationHeader, " ")
|
||||
if len(bearerToken) != 2 {
|
||||
return "", fmt.Errorf("invalid auth header")
|
||||
}
|
||||
return bearerToken[1], nil
|
||||
}
|
||||
|
||||
// Middleware implements the middleware interface
|
||||
func (amw *jwtMiddleware) Middleware(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
// nolint:golangci-lint,godox
|
||||
// TODO: Log error details when authentication fails
|
||||
ctx := r.Context()
|
||||
authorizationHeader := r.Header.Get("authorization")
|
||||
if authorizationHeader == "" {
|
||||
authToken, err := amw.getTokenFromRequest(r)
|
||||
if err != nil {
|
||||
slog.ErrorContext(ctx, "failed to get auth token", "error", err)
|
||||
invalidAuthResponse(ctx, w)
|
||||
return
|
||||
}
|
||||
|
||||
bearerToken := strings.Split(authorizationHeader, " ")
|
||||
if len(bearerToken) != 2 {
|
||||
invalidAuthResponse(ctx, w)
|
||||
return
|
||||
}
|
||||
|
||||
claims := &JWTClaims{}
|
||||
token, err := jwt.ParseWithClaims(bearerToken[1], claims, func(token *jwt.Token) (interface{}, error) {
|
||||
token, err := jwt.ParseWithClaims(authToken, claims, func(token *jwt.Token) (interface{}, error) {
|
||||
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
|
||||
return nil, fmt.Errorf("invalid signing method")
|
||||
}
|
||||
|
|
|
|||
16
build-webapp.sh
Executable file
16
build-webapp.sh
Executable file
|
|
@ -0,0 +1,16 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
echo "Building GARM SPA (SvelteKit)..."
|
||||
|
||||
# Navigate to webapp directory
|
||||
cd webapp
|
||||
|
||||
# Install dependencies if node_modules doesn't exist
|
||||
npm install
|
||||
|
||||
# Build the SPA
|
||||
echo "Building SPA..."
|
||||
npm run build
|
||||
echo "SPA built successfully!"
|
||||
56
cache/entity_cache.go
vendored
56
cache/entity_cache.go
vendored
|
|
@ -15,6 +15,7 @@ package cache
|
|||
|
||||
import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/cloudbase/garm/params"
|
||||
)
|
||||
|
|
@ -28,10 +29,16 @@ func init() {
|
|||
entityCache = ghEntityCache
|
||||
}
|
||||
|
||||
type RunnerGroupEntry struct {
|
||||
RunnerGroupID int64
|
||||
time time.Time
|
||||
}
|
||||
|
||||
type EntityItem struct {
|
||||
Entity params.ForgeEntity
|
||||
Pools map[string]params.Pool
|
||||
ScaleSets map[uint]params.ScaleSet
|
||||
Entity params.ForgeEntity
|
||||
Pools map[string]params.Pool
|
||||
ScaleSets map[uint]params.ScaleSet
|
||||
RunnerGroups map[string]RunnerGroupEntry
|
||||
}
|
||||
|
||||
type EntityCache struct {
|
||||
|
|
@ -80,9 +87,10 @@ func (e *EntityCache) SetEntity(entity params.ForgeEntity) {
|
|||
cache, ok := e.entities[entity.ID]
|
||||
if !ok {
|
||||
e.entities[entity.ID] = EntityItem{
|
||||
Entity: entity,
|
||||
Pools: make(map[string]params.Pool),
|
||||
ScaleSets: make(map[uint]params.ScaleSet),
|
||||
Entity: entity,
|
||||
Pools: make(map[string]params.Pool),
|
||||
ScaleSets: make(map[uint]params.ScaleSet),
|
||||
RunnerGroups: make(map[string]RunnerGroupEntry),
|
||||
}
|
||||
return
|
||||
}
|
||||
|
|
@ -314,6 +322,42 @@ func (e *EntityCache) GetAllScaleSets() []params.ScaleSet {
|
|||
return scaleSets
|
||||
}
|
||||
|
||||
func (e *EntityCache) SetEntityRunnerGroup(entityID, runnerGroupName string, runnerGroupID int64) {
|
||||
e.mux.Lock()
|
||||
defer e.mux.Unlock()
|
||||
|
||||
if _, ok := e.entities[entityID]; ok {
|
||||
e.entities[entityID].RunnerGroups[runnerGroupName] = RunnerGroupEntry{
|
||||
RunnerGroupID: runnerGroupID,
|
||||
time: time.Now().UTC(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (e *EntityCache) GetEntityRunnerGroup(entityID, runnerGroupName string) (int64, bool) {
|
||||
e.mux.Lock()
|
||||
defer e.mux.Unlock()
|
||||
|
||||
if _, ok := e.entities[entityID]; ok {
|
||||
if runnerGroup, ok := e.entities[entityID].RunnerGroups[runnerGroupName]; ok {
|
||||
if time.Now().UTC().After(runnerGroup.time.Add(1 * time.Hour)) {
|
||||
delete(e.entities[entityID].RunnerGroups, runnerGroupName)
|
||||
return 0, false
|
||||
}
|
||||
return runnerGroup.RunnerGroupID, true
|
||||
}
|
||||
}
|
||||
return 0, false
|
||||
}
|
||||
|
||||
func SetEntityRunnerGroup(entityID, runnerGroupName string, runnerGroupID int64) {
|
||||
entityCache.SetEntityRunnerGroup(entityID, runnerGroupName, runnerGroupID)
|
||||
}
|
||||
|
||||
func GetEntityRunnerGroup(entityID, runnerGroupName string) (int64, bool) {
|
||||
return entityCache.GetEntityRunnerGroup(entityID, runnerGroupName)
|
||||
}
|
||||
|
||||
func GetEntity(entityID string) (params.ForgeEntity, bool) {
|
||||
return entityCache.GetEntity(entityID)
|
||||
}
|
||||
|
|
|
|||
20
cache/instance_cache.go
vendored
20
cache/instance_cache.go
vendored
|
|
@ -98,6 +98,22 @@ func (i *InstanceCache) GetInstancesForScaleSet(scaleSetID uint) []params.Instan
|
|||
return filteredInstances
|
||||
}
|
||||
|
||||
func (i *InstanceCache) GetEntityInstances(entityID string) []params.Instance {
|
||||
pools := GetEntityPools(entityID)
|
||||
poolsAsMap := map[string]bool{}
|
||||
for _, pool := range pools {
|
||||
poolsAsMap[pool.ID] = true
|
||||
}
|
||||
|
||||
ret := []params.Instance{}
|
||||
for _, val := range i.GetAllInstances() {
|
||||
if _, ok := poolsAsMap[val.PoolID]; ok {
|
||||
ret = append(ret, val)
|
||||
}
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func SetInstanceCache(instance params.Instance) {
|
||||
instanceCache.SetInstance(instance)
|
||||
}
|
||||
|
|
@ -121,3 +137,7 @@ func GetInstancesForPool(poolID string) []params.Instance {
|
|||
func GetInstancesForScaleSet(scaleSetID uint) []params.Instance {
|
||||
return instanceCache.GetInstancesForScaleSet(scaleSetID)
|
||||
}
|
||||
|
||||
func GetEntityInstances(entityID string) []params.Instance {
|
||||
return instanceCache.GetEntityInstances(entityID)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,7 +21,6 @@ import (
|
|||
|
||||
openapiRuntimeClient "github.com/go-openapi/runtime/client"
|
||||
"github.com/jedib0t/go-pretty/v6/table"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
apiClientController "github.com/cloudbase/garm/client/controller"
|
||||
|
|
@ -80,7 +79,7 @@ garm-cli init --name=dev --url=https://runner.example.com --username=admin --pas
|
|||
|
||||
response, err := apiCli.FirstRun.FirstRun(newUserReq, authToken)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "initializing manager")
|
||||
return fmt.Errorf("error initializing manager: %w", err)
|
||||
}
|
||||
|
||||
newLoginParamsReq := apiClientLogin.NewLoginParams()
|
||||
|
|
@ -91,7 +90,7 @@ garm-cli init --name=dev --url=https://runner.example.com --username=admin --pas
|
|||
|
||||
token, err := apiCli.Login.Login(newLoginParamsReq, authToken)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "authenticating")
|
||||
return fmt.Errorf("error authenticating: %w", err)
|
||||
}
|
||||
|
||||
cfg.Managers = append(cfg.Managers, config.Manager{
|
||||
|
|
@ -104,7 +103,7 @@ garm-cli init --name=dev --url=https://runner.example.com --username=admin --pas
|
|||
cfg.ActiveManager = loginProfileName
|
||||
|
||||
if err := cfg.SaveConfig(); err != nil {
|
||||
return errors.Wrap(err, "saving config")
|
||||
return fmt.Errorf("error saving config: %w", err)
|
||||
}
|
||||
|
||||
updateUrlsReq := apiClientController.NewUpdateControllerParams()
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ package cmd
|
|||
import (
|
||||
"context"
|
||||
"os/signal"
|
||||
"strings"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
|
|
@ -23,7 +24,12 @@ import (
|
|||
"github.com/cloudbase/garm/cmd/garm-cli/common"
|
||||
)
|
||||
|
||||
var eventsFilters string
|
||||
var (
|
||||
eventsFilters string
|
||||
logLevel string
|
||||
filters []string
|
||||
enableColor bool
|
||||
)
|
||||
|
||||
var logCmd = &cobra.Command{
|
||||
Use: "debug-log",
|
||||
|
|
@ -34,7 +40,19 @@ var logCmd = &cobra.Command{
|
|||
ctx, stop := signal.NotifyContext(context.Background(), signals...)
|
||||
defer stop()
|
||||
|
||||
reader, err := garmWs.NewReader(ctx, mgr.BaseURL, "/api/v1/ws/logs", mgr.Token, common.PrintWebsocketMessage)
|
||||
// Parse filters into map
|
||||
attributeFilters := make(map[string]string)
|
||||
for _, filter := range filters {
|
||||
parts := strings.SplitN(filter, "=", 2)
|
||||
if len(parts) == 2 {
|
||||
attributeFilters[parts[0]] = parts[1]
|
||||
}
|
||||
}
|
||||
|
||||
// Create log formatter with filters
|
||||
logFormatter := common.NewLogFormatter(logLevel, attributeFilters, enableColor)
|
||||
|
||||
reader, err := garmWs.NewReader(ctx, mgr.BaseURL, "/api/v1/ws/logs", mgr.Token, logFormatter.FormatWebsocketMessage)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -49,5 +67,9 @@ var logCmd = &cobra.Command{
|
|||
}
|
||||
|
||||
func init() {
|
||||
logCmd.Flags().StringVar(&logLevel, "log-level", "", "Minimum log level to display (DEBUG, INFO, WARN, ERROR)")
|
||||
logCmd.Flags().StringArrayVar(&filters, "filter", []string{}, "Filter logs by attribute (format: key=value) or message content (msg=text). You can specify this option multiple times. The filter will return true for any of the attributes you set.")
|
||||
logCmd.Flags().BoolVar(&enableColor, "enable-color", true, "Enable color logging (auto-detects terminal support)")
|
||||
|
||||
rootCmd.AddCommand(logCmd)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,7 +21,6 @@ import (
|
|||
"strings"
|
||||
|
||||
"github.com/jedib0t/go-pretty/v6/table"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
commonParams "github.com/cloudbase/garm-provider-common/params"
|
||||
|
|
@ -128,12 +127,9 @@ Example:
|
|||
listEnterprisePoolsReq := apiClientEnterprises.NewListEnterprisePoolsParams()
|
||||
listEnterprisePoolsReq.EnterpriseID = poolEnterprise
|
||||
response, err = apiCli.Enterprises.ListEnterprisePools(listEnterprisePoolsReq, authToken)
|
||||
} else if cmd.Flags().Changed("all") {
|
||||
} else {
|
||||
listPoolsReq := apiClientPools.NewListPoolsParams()
|
||||
response, err = apiCli.Pools.ListPools(listPoolsReq, authToken)
|
||||
} else {
|
||||
cmd.Help() //nolint
|
||||
os.Exit(0)
|
||||
}
|
||||
default:
|
||||
cmd.Help() //nolint
|
||||
|
|
@ -409,11 +405,12 @@ func init() {
|
|||
poolListCmd.Flags().StringVarP(&poolRepository, "repo", "r", "", "List all pools within this repository.")
|
||||
poolListCmd.Flags().StringVarP(&poolOrganization, "org", "o", "", "List all pools within this organization.")
|
||||
poolListCmd.Flags().StringVarP(&poolEnterprise, "enterprise", "e", "", "List all pools within this enterprise.")
|
||||
poolListCmd.Flags().BoolVarP(&poolAll, "all", "a", false, "List all pools, regardless of org or repo.")
|
||||
poolListCmd.Flags().BoolVarP(&poolAll, "all", "a", true, "List all pools, regardless of org or repo.")
|
||||
poolListCmd.Flags().BoolVarP(&long, "long", "l", false, "Include additional info.")
|
||||
poolListCmd.Flags().StringVar(&endpointName, "endpoint", "", "When using the name of an entity, the endpoint must be specified when multiple entities with the same name exist.")
|
||||
|
||||
poolListCmd.MarkFlagsMutuallyExclusive("repo", "org", "all", "enterprise")
|
||||
poolListCmd.Flags().MarkDeprecated("all", "all pools are listed by default in the absence of --repo, --org or --enterprise.")
|
||||
poolListCmd.MarkFlagsMutuallyExclusive("repo", "org", "enterprise", "all")
|
||||
|
||||
poolUpdateCmd.Flags().StringVar(&poolImage, "image", "", "The provider-specific image name to use for runners in this pool.")
|
||||
poolUpdateCmd.Flags().UintVar(&priority, "priority", 0, "When multiple pools match the same labels, priority dictates the order by which they are returned, in descending order.")
|
||||
|
|
@ -473,7 +470,7 @@ func init() {
|
|||
func extraSpecsFromFile(specsFile string) (json.RawMessage, error) {
|
||||
data, err := os.ReadFile(specsFile)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "opening specs file")
|
||||
return nil, fmt.Errorf("error opening specs file: %w", err)
|
||||
}
|
||||
return asRawMessage(data)
|
||||
}
|
||||
|
|
@ -483,14 +480,14 @@ func asRawMessage(data []byte) (json.RawMessage, error) {
|
|||
// have a valid json.
|
||||
var unmarshaled interface{}
|
||||
if err := json.Unmarshal(data, &unmarshaled); err != nil {
|
||||
return nil, errors.Wrap(err, "decoding extra specs")
|
||||
return nil, fmt.Errorf("error decoding extra specs: %w", err)
|
||||
}
|
||||
|
||||
var asRawJSON json.RawMessage
|
||||
var err error
|
||||
asRawJSON, err = json.Marshal(unmarshaled)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "marshaling json")
|
||||
return nil, fmt.Errorf("error marshaling json: %w", err)
|
||||
}
|
||||
return asRawJSON, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -104,23 +104,32 @@ Example:
|
|||
response, err = apiCli.Instances.ListPoolInstances(listPoolInstancesReq, authToken)
|
||||
case 0:
|
||||
if cmd.Flags().Changed("repo") {
|
||||
runnerRepo, resErr := resolveRepository(runnerRepository, endpointName)
|
||||
if resErr != nil {
|
||||
return resErr
|
||||
}
|
||||
listRepoInstancesReq := apiClientRepos.NewListRepoInstancesParams()
|
||||
listRepoInstancesReq.RepoID = runnerRepository
|
||||
listRepoInstancesReq.RepoID = runnerRepo
|
||||
response, err = apiCli.Repositories.ListRepoInstances(listRepoInstancesReq, authToken)
|
||||
} else if cmd.Flags().Changed("org") {
|
||||
runnerOrg, resErr := resolveOrganization(runnerOrganization, endpointName)
|
||||
if resErr != nil {
|
||||
return resErr
|
||||
}
|
||||
listOrgInstancesReq := apiClientOrgs.NewListOrgInstancesParams()
|
||||
listOrgInstancesReq.OrgID = runnerOrganization
|
||||
listOrgInstancesReq.OrgID = runnerOrg
|
||||
response, err = apiCli.Organizations.ListOrgInstances(listOrgInstancesReq, authToken)
|
||||
} else if cmd.Flags().Changed("enterprise") {
|
||||
runnerEnt, resErr := resolveEnterprise(runnerEnterprise, endpointName)
|
||||
if resErr != nil {
|
||||
return resErr
|
||||
}
|
||||
listEnterpriseInstancesReq := apiClientEnterprises.NewListEnterpriseInstancesParams()
|
||||
listEnterpriseInstancesReq.EnterpriseID = runnerEnterprise
|
||||
listEnterpriseInstancesReq.EnterpriseID = runnerEnt
|
||||
response, err = apiCli.Enterprises.ListEnterpriseInstances(listEnterpriseInstancesReq, authToken)
|
||||
} else if cmd.Flags().Changed("all") {
|
||||
} else {
|
||||
listInstancesReq := apiClientInstances.NewListInstancesParams()
|
||||
response, err = apiCli.Instances.ListInstances(listInstancesReq, authToken)
|
||||
} else {
|
||||
cmd.Help() //nolint
|
||||
os.Exit(0)
|
||||
}
|
||||
default:
|
||||
cmd.Help() //nolint
|
||||
|
|
@ -205,9 +214,12 @@ func init() {
|
|||
runnerListCmd.Flags().StringVarP(&runnerRepository, "repo", "r", "", "List all runners from all pools within this repository.")
|
||||
runnerListCmd.Flags().StringVarP(&runnerOrganization, "org", "o", "", "List all runners from all pools within this organization.")
|
||||
runnerListCmd.Flags().StringVarP(&runnerEnterprise, "enterprise", "e", "", "List all runners from all pools within this enterprise.")
|
||||
runnerListCmd.Flags().BoolVarP(&runnerAll, "all", "a", false, "List all runners, regardless of org or repo.")
|
||||
runnerListCmd.Flags().BoolVarP(&runnerAll, "all", "a", true, "List all runners, regardless of org or repo. (deprecated)")
|
||||
runnerListCmd.Flags().BoolVarP(&long, "long", "l", false, "Include additional info.")
|
||||
runnerListCmd.MarkFlagsMutuallyExclusive("repo", "org", "enterprise", "all")
|
||||
runnerListCmd.Flags().StringVar(&endpointName, "endpoint", "", "When using the name of an entity, the endpoint must be specified when multiple entities with the same name exist.")
|
||||
|
||||
runnerListCmd.Flags().MarkDeprecated("all", "all runners are listed by default in the absence of --repo, --org or --enterprise.")
|
||||
|
||||
runnerDeleteCmd.Flags().BoolVarP(&forceRemove, "force-remove-runner", "f", false, "Forcefully remove a runner. If set to true, GARM will ignore provider errors when removing the runner.")
|
||||
runnerDeleteCmd.Flags().BoolVarP(&bypassGHUnauthorized, "bypass-github-unauthorized", "b", false, "Ignore Unauthorized errors from GitHub and proceed with removing runner from provider and DB. This is useful when credentials are no longer valid and you want to remove your runners. Warning, this has the potential to leave orphaned runners in GitHub. You will need to update your credentials to properly consolidate.")
|
||||
|
|
|
|||
|
|
@ -47,7 +47,6 @@ var (
|
|||
scalesetEnterprise string
|
||||
scalesetExtraSpecsFile string
|
||||
scalesetExtraSpecs string
|
||||
scalesetAll bool
|
||||
scalesetGitHubRunnerGroup string
|
||||
)
|
||||
|
||||
|
|
@ -128,12 +127,9 @@ Example:
|
|||
listEnterpriseScaleSetsReq := apiClientEnterprises.NewListEnterpriseScaleSetsParams()
|
||||
listEnterpriseScaleSetsReq.EnterpriseID = scalesetEnterprise
|
||||
response, err = apiCli.Enterprises.ListEnterpriseScaleSets(listEnterpriseScaleSetsReq, authToken)
|
||||
} else if cmd.Flags().Changed("all") {
|
||||
} else {
|
||||
listScaleSetsReq := apiClientScaleSets.NewListScalesetsParams()
|
||||
response, err = apiCli.Scalesets.ListScalesets(listScaleSetsReq, authToken)
|
||||
} else {
|
||||
cmd.Help() //nolint
|
||||
os.Exit(0)
|
||||
}
|
||||
default:
|
||||
cmd.Help() //nolint
|
||||
|
|
@ -400,8 +396,7 @@ func init() {
|
|||
scalesetListCmd.Flags().StringVarP(&scalesetRepository, "repo", "r", "", "List all scale sets within this repository.")
|
||||
scalesetListCmd.Flags().StringVarP(&scalesetOrganization, "org", "o", "", "List all scale sets within this organization.")
|
||||
scalesetListCmd.Flags().StringVarP(&scalesetEnterprise, "enterprise", "e", "", "List all scale sets within this enterprise.")
|
||||
scalesetListCmd.Flags().BoolVarP(&scalesetAll, "all", "a", false, "List all scale sets, regardless of org or repo.")
|
||||
scalesetListCmd.MarkFlagsMutuallyExclusive("repo", "org", "all", "enterprise")
|
||||
scalesetListCmd.MarkFlagsMutuallyExclusive("repo", "org", "enterprise")
|
||||
scalesetListCmd.Flags().StringVar(&endpointName, "endpoint", "", "When using the name of an entity, the endpoint must be specified when multiple entities with the same name exist.")
|
||||
|
||||
scaleSetUpdateCmd.Flags().StringVar(&scalesetImage, "image", "", "The provider-specific image name to use for runners in this scale set.")
|
||||
|
|
|
|||
|
|
@ -15,8 +15,14 @@
|
|||
package common
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"runtime"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/manifoldco/promptui"
|
||||
"github.com/nbutton23/zxcvbn-go"
|
||||
|
|
@ -74,3 +80,246 @@ func PrintWebsocketMessage(_ int, msg []byte) error {
|
|||
fmt.Println(util.SanitizeLogEntry(string(msg)))
|
||||
return nil
|
||||
}
|
||||
|
||||
type LogFormatter struct {
|
||||
MinLevel string
|
||||
AttributeFilters map[string]string
|
||||
EnableColor bool
|
||||
}
|
||||
|
||||
type LogRecord struct {
|
||||
Time string `json:"time"`
|
||||
Level string `json:"level"`
|
||||
Msg string `json:"msg"`
|
||||
Attrs map[string]interface{} `json:",inline"`
|
||||
}
|
||||
|
||||
// Color codes for different log levels
|
||||
const (
|
||||
ColorReset = "\033[0m"
|
||||
ColorRed = "\033[31m"
|
||||
ColorYellow = "\033[33m"
|
||||
ColorBlue = "\033[34m"
|
||||
ColorMagenta = "\033[35m"
|
||||
ColorCyan = "\033[36m"
|
||||
ColorWhite = "\033[37m"
|
||||
ColorGray = "\033[90m"
|
||||
)
|
||||
|
||||
func (lf *LogFormatter) colorizeLevel(level string) string {
|
||||
if !lf.EnableColor {
|
||||
return level
|
||||
}
|
||||
|
||||
levelUpper := strings.TrimSpace(strings.ToUpper(level))
|
||||
switch levelUpper {
|
||||
case "ERROR":
|
||||
return ColorRed + level + ColorReset
|
||||
case "WARN", "WARNING":
|
||||
return ColorYellow + level + ColorReset
|
||||
case "INFO":
|
||||
return ColorBlue + level + ColorReset
|
||||
case "DEBUG":
|
||||
return ColorMagenta + level + ColorReset
|
||||
default:
|
||||
return level
|
||||
}
|
||||
}
|
||||
|
||||
func (lf *LogFormatter) shouldFilterLevel(level string) bool {
|
||||
if lf.MinLevel == "" {
|
||||
return false
|
||||
}
|
||||
|
||||
levelMap := map[string]int{
|
||||
"DEBUG": 0,
|
||||
"INFO": 1,
|
||||
"WARN": 2,
|
||||
"ERROR": 3,
|
||||
}
|
||||
|
||||
minLevelNum, exists := levelMap[strings.ToUpper(lf.MinLevel)]
|
||||
if !exists {
|
||||
return false
|
||||
}
|
||||
|
||||
currentLevelNum, exists := levelMap[strings.ToUpper(level)]
|
||||
if !exists {
|
||||
return false
|
||||
}
|
||||
|
||||
return currentLevelNum < minLevelNum
|
||||
}
|
||||
|
||||
func (lf *LogFormatter) matchesAttributeFilters(attrs map[string]interface{}, msg string) bool {
|
||||
if len(lf.AttributeFilters) == 0 {
|
||||
return true
|
||||
}
|
||||
|
||||
for key, expectedValue := range lf.AttributeFilters {
|
||||
// Special handling for message filtering
|
||||
if key == "msg" {
|
||||
if strings.Contains(msg, expectedValue) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
// Regular attribute filtering
|
||||
actualValue, exists := attrs[key]
|
||||
if exists {
|
||||
actualStr := fmt.Sprintf("%v", actualValue)
|
||||
if actualStr == expectedValue {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func (lf *LogFormatter) FormatWebsocketMessage(_ int, msg []byte) error {
|
||||
// Try to parse as JSON log record
|
||||
var logRecord LogRecord
|
||||
err := json.Unmarshal(msg, &logRecord)
|
||||
if err != nil {
|
||||
// If it's not JSON, print as-is (sanitized)
|
||||
_, err = fmt.Println(util.SanitizeLogEntry(string(msg)))
|
||||
return err
|
||||
}
|
||||
|
||||
// Apply level filtering
|
||||
if lf.shouldFilterLevel(logRecord.Level) {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Parse additional attributes from the JSON
|
||||
var fullRecord map[string]interface{}
|
||||
if err := json.Unmarshal(msg, &fullRecord); err == nil {
|
||||
// Remove standard fields and keep only attributes
|
||||
delete(fullRecord, "time")
|
||||
delete(fullRecord, "level")
|
||||
delete(fullRecord, "msg")
|
||||
logRecord.Attrs = fullRecord
|
||||
}
|
||||
|
||||
// Apply attribute filtering
|
||||
if !lf.matchesAttributeFilters(logRecord.Attrs, logRecord.Msg) {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Format timestamp to fixed width
|
||||
timeStr := logRecord.Time
|
||||
if t, err := time.Parse(time.RFC3339Nano, logRecord.Time); err == nil {
|
||||
timeStr = t.Format("2006-01-02 15:04:05.000")
|
||||
}
|
||||
|
||||
// Format log level to fixed width (5 characters)
|
||||
levelStr := lf.colorizeLevel(fmt.Sprintf("%-5s", strings.ToUpper(logRecord.Level)))
|
||||
|
||||
// Highlight message if it matches a msg filter
|
||||
msgStr := logRecord.Msg
|
||||
if msgFilter, hasMsgFilter := lf.AttributeFilters["msg"]; hasMsgFilter {
|
||||
if strings.Contains(msgStr, msgFilter) && lf.EnableColor {
|
||||
msgStr = ColorYellow + msgStr + ColorReset
|
||||
}
|
||||
}
|
||||
|
||||
output := fmt.Sprintf("%s [%s] %s", timeStr, levelStr, msgStr)
|
||||
|
||||
// Add attributes if any
|
||||
if len(logRecord.Attrs) > 0 {
|
||||
// Get sorted keys for consistent output
|
||||
var keys []string
|
||||
for k := range logRecord.Attrs {
|
||||
keys = append(keys, k)
|
||||
}
|
||||
sort.Strings(keys)
|
||||
|
||||
var attrPairs []string
|
||||
for _, k := range keys {
|
||||
v := logRecord.Attrs[k]
|
||||
attrStr := fmt.Sprintf("%s=%v", k, v)
|
||||
|
||||
// Highlight filtered attributes
|
||||
if filterValue, isFiltered := lf.AttributeFilters[k]; isFiltered && fmt.Sprintf("%v", v) == filterValue {
|
||||
if lf.EnableColor {
|
||||
attrStr = ColorYellow + attrStr + ColorGray
|
||||
}
|
||||
} else if lf.EnableColor {
|
||||
attrStr = ColorGray + attrStr
|
||||
}
|
||||
|
||||
attrPairs = append(attrPairs, attrStr)
|
||||
}
|
||||
if len(attrPairs) > 0 {
|
||||
if lf.EnableColor {
|
||||
output += " " + strings.Join(attrPairs, " ") + ColorReset
|
||||
} else {
|
||||
output += " " + strings.Join(attrPairs, " ")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Println(output)
|
||||
return nil
|
||||
}
|
||||
|
||||
// supportsColor checks if the current terminal/environment supports ANSI colors.
|
||||
// This is best effort. There is no reliable way to determine if a terminal supports
|
||||
// color. Set NO_COLOR=1 to disable color if your terminal doesn't support it, but this
|
||||
// function returns true.
|
||||
func supportsColor() bool {
|
||||
// Check NO_COLOR environment variable (universal standard)
|
||||
if os.Getenv("NO_COLOR") != "" {
|
||||
return false
|
||||
}
|
||||
|
||||
// Check FORCE_COLOR environment variable
|
||||
if os.Getenv("FORCE_COLOR") != "" {
|
||||
return true
|
||||
}
|
||||
|
||||
// On Windows, check for modern terminal support
|
||||
if runtime.GOOS == "windows" {
|
||||
// Check for Windows Terminal
|
||||
if os.Getenv("WT_SESSION") != "" {
|
||||
return true
|
||||
}
|
||||
// Check for ConEmu
|
||||
if os.Getenv("ConEmuANSI") == "ON" {
|
||||
return true
|
||||
}
|
||||
// Check for other modern terminals
|
||||
term := os.Getenv("TERM")
|
||||
if strings.Contains(term, "color") || term == "xterm-256color" || term == "screen-256color" {
|
||||
return true
|
||||
}
|
||||
// Modern PowerShell and cmd.exe with VT processing
|
||||
if os.Getenv("TERM_PROGRAM") != "" {
|
||||
return true
|
||||
}
|
||||
// Default to false for older Windows cmd.exe
|
||||
return false
|
||||
}
|
||||
|
||||
// On Unix-like systems, check TERM
|
||||
term := os.Getenv("TERM")
|
||||
if term == "" || term == "dumb" {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func NewLogFormatter(minLevel string, attributeFilters map[string]string, color bool) *LogFormatter {
|
||||
var enableColor bool
|
||||
if color && supportsColor() {
|
||||
enableColor = true
|
||||
}
|
||||
|
||||
return &LogFormatter{
|
||||
MinLevel: minLevel,
|
||||
AttributeFilters: attributeFilters,
|
||||
EnableColor: enableColor,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,13 +15,13 @@
|
|||
package config
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
|
||||
"github.com/BurntSushi/toml"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
runnerErrors "github.com/cloudbase/garm-provider-common/errors"
|
||||
)
|
||||
|
|
@ -34,11 +34,11 @@ const (
|
|||
func getConfigFilePath() (string, error) {
|
||||
configDir, err := getHomeDir()
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "fetching home folder")
|
||||
return "", fmt.Errorf("error fetching home folder: %w", err)
|
||||
}
|
||||
|
||||
if err := ensureHomeDir(configDir); err != nil {
|
||||
return "", errors.Wrap(err, "ensuring config dir")
|
||||
return "", fmt.Errorf("error ensuring config dir: %w", err)
|
||||
}
|
||||
|
||||
cfgFile := filepath.Join(configDir, DefaultConfigFileName)
|
||||
|
|
@ -48,7 +48,7 @@ func getConfigFilePath() (string, error) {
|
|||
func LoadConfig() (*Config, error) {
|
||||
cfgFile, err := getConfigFilePath()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "fetching config")
|
||||
return nil, fmt.Errorf("error fetching config: %w", err)
|
||||
}
|
||||
|
||||
if _, err := os.Stat(cfgFile); err != nil {
|
||||
|
|
@ -56,12 +56,12 @@ func LoadConfig() (*Config, error) {
|
|||
// return empty config
|
||||
return &Config{}, nil
|
||||
}
|
||||
return nil, errors.Wrap(err, "accessing config file")
|
||||
return nil, fmt.Errorf("error accessing config file: %w", err)
|
||||
}
|
||||
|
||||
var config Config
|
||||
if _, err := toml.DecodeFile(cfgFile, &config); err != nil {
|
||||
return nil, errors.Wrap(err, "decoding toml")
|
||||
return nil, fmt.Errorf("error decoding toml: %w", err)
|
||||
}
|
||||
|
||||
return &config, nil
|
||||
|
|
@ -157,17 +157,17 @@ func (c *Config) SaveConfig() error {
|
|||
cfgFile, err := getConfigFilePath()
|
||||
if err != nil {
|
||||
if !errors.Is(err, os.ErrNotExist) {
|
||||
return errors.Wrap(err, "getting config")
|
||||
return fmt.Errorf("error getting config: %w", err)
|
||||
}
|
||||
}
|
||||
cfgHandle, err := os.Create(cfgFile)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "getting file handle")
|
||||
return fmt.Errorf("error getting file handle: %w", err)
|
||||
}
|
||||
|
||||
encoder := toml.NewEncoder(cfgHandle)
|
||||
if err := encoder.Encode(c); err != nil {
|
||||
return errors.Wrap(err, "saving config")
|
||||
return fmt.Errorf("error saving config: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
|
|
|||
|
|
@ -15,19 +15,19 @@
|
|||
package config
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func ensureHomeDir(folder string) error {
|
||||
if _, err := os.Stat(folder); err != nil {
|
||||
if !errors.Is(err, os.ErrNotExist) {
|
||||
return errors.Wrap(err, "checking home dir")
|
||||
return fmt.Errorf("error checking home dir: %w", err)
|
||||
}
|
||||
|
||||
if err := os.MkdirAll(folder, 0o710); err != nil {
|
||||
return errors.Wrapf(err, "creating %s", folder)
|
||||
return fmt.Errorf("error creating %s: %w", folder, err)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -17,16 +17,15 @@
|
|||
package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func getHomeDir() (string, error) {
|
||||
home, err := os.UserHomeDir()
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "fetching home dir")
|
||||
return "", fmt.Errorf("error fetching home dir: %w", err)
|
||||
}
|
||||
|
||||
return filepath.Join(home, ".local", "share", DefaultAppFolder), nil
|
||||
|
|
|
|||
|
|
@ -18,7 +18,6 @@ import (
|
|||
"context"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"log/slog"
|
||||
"net"
|
||||
|
|
@ -31,7 +30,6 @@ import (
|
|||
|
||||
"github.com/gorilla/handlers"
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/pkg/errors"
|
||||
lumberjack "gopkg.in/natefinch/lumberjack.v2"
|
||||
|
||||
"github.com/cloudbase/garm-provider-common/util"
|
||||
|
|
@ -73,7 +71,7 @@ func maybeInitController(db common.Store) (params.ControllerInfo, error) {
|
|||
|
||||
info, err := db.InitController()
|
||||
if err != nil {
|
||||
return params.ControllerInfo{}, errors.Wrap(err, "initializing controller")
|
||||
return params.ControllerInfo{}, fmt.Errorf("error initializing controller: %w", err)
|
||||
}
|
||||
|
||||
return info, nil
|
||||
|
|
@ -105,16 +103,6 @@ func setupLogging(ctx context.Context, logCfg config.Logging, hub *websocket.Hub
|
|||
}
|
||||
}()
|
||||
|
||||
writers := []io.Writer{
|
||||
logWriter,
|
||||
}
|
||||
|
||||
if hub != nil {
|
||||
writers = append(writers, hub)
|
||||
}
|
||||
|
||||
wr := io.MultiWriter(writers...)
|
||||
|
||||
var logLevel slog.Level
|
||||
switch logCfg.LogLevel {
|
||||
case config.LevelDebug:
|
||||
|
|
@ -135,16 +123,25 @@ func setupLogging(ctx context.Context, logCfg config.Logging, hub *websocket.Hub
|
|||
Level: logLevel,
|
||||
}
|
||||
|
||||
var han slog.Handler
|
||||
var fileHan slog.Handler
|
||||
switch logCfg.LogFormat {
|
||||
case config.FormatJSON:
|
||||
han = slog.NewJSONHandler(wr, &opts)
|
||||
fileHan = slog.NewJSONHandler(logWriter, &opts)
|
||||
default:
|
||||
han = slog.NewTextHandler(wr, &opts)
|
||||
fileHan = slog.NewTextHandler(logWriter, &opts)
|
||||
}
|
||||
|
||||
wrapped := garmUtil.ContextHandler{
|
||||
Handler: han,
|
||||
handlers := []slog.Handler{
|
||||
fileHan,
|
||||
}
|
||||
|
||||
if hub != nil {
|
||||
wsHan := slog.NewJSONHandler(hub, &opts)
|
||||
handlers = append(handlers, wsHan)
|
||||
}
|
||||
|
||||
wrapped := &garmUtil.SlogMultiHandler{
|
||||
Handlers: handlers,
|
||||
}
|
||||
slog.SetDefault(slog.New(wrapped))
|
||||
}
|
||||
|
|
@ -152,7 +149,7 @@ func setupLogging(ctx context.Context, logCfg config.Logging, hub *websocket.Hub
|
|||
func maybeUpdateURLsFromConfig(cfg config.Config, store common.Store) error {
|
||||
info, err := store.ControllerInfo()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "fetching controller info")
|
||||
return fmt.Errorf("error fetching controller info: %w", err)
|
||||
}
|
||||
|
||||
var updateParams params.UpdateControllerParams
|
||||
|
|
@ -176,7 +173,7 @@ func maybeUpdateURLsFromConfig(cfg config.Config, store common.Store) error {
|
|||
|
||||
_, err = store.UpdateController(updateParams)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "updating controller info")
|
||||
return fmt.Errorf("error updating controller info: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
@ -283,7 +280,7 @@ func main() {
|
|||
}
|
||||
|
||||
authenticator := auth.NewAuthenticator(cfg.JWTAuth, db)
|
||||
controller, err := controllers.NewAPIController(runner, authenticator, hub)
|
||||
controller, err := controllers.NewAPIController(runner, authenticator, hub, cfg.APIServer)
|
||||
if err != nil {
|
||||
log.Fatalf("failed to create controller: %+v", err)
|
||||
}
|
||||
|
|
@ -315,6 +312,9 @@ func main() {
|
|||
|
||||
router := routers.NewAPIRouter(controller, jwtMiddleware, initMiddleware, urlsRequiredMiddleware, instanceMiddleware, cfg.Default.EnableWebhookManagement)
|
||||
|
||||
// Add WebUI routes
|
||||
router = routers.WithWebUI(router, cfg.APIServer)
|
||||
|
||||
// start the metrics collector
|
||||
if cfg.Metrics.Enable {
|
||||
slog.InfoContext(ctx, "setting up metric routes")
|
||||
|
|
@ -370,6 +370,13 @@ func main() {
|
|||
|
||||
<-ctx.Done()
|
||||
|
||||
slog.InfoContext(ctx, "shutting down http server")
|
||||
shutdownCtx, shutdownCancel := context.WithTimeout(context.Background(), 60*time.Second)
|
||||
defer shutdownCancel()
|
||||
if err := srv.Shutdown(shutdownCtx); err != nil {
|
||||
slog.With(slog.Any("error", err)).ErrorContext(ctx, "graceful api server shutdown failed")
|
||||
}
|
||||
|
||||
if err := cacheWorker.Stop(); err != nil {
|
||||
slog.With(slog.Any("error", err)).ErrorContext(ctx, "failed to stop credentials worker")
|
||||
}
|
||||
|
|
@ -384,13 +391,6 @@ func main() {
|
|||
slog.With(slog.Any("error", err)).ErrorContext(ctx, "failed to stop provider worker")
|
||||
}
|
||||
|
||||
slog.InfoContext(ctx, "shutting down http server")
|
||||
shutdownCtx, shutdownCancel := context.WithTimeout(context.Background(), 60*time.Second)
|
||||
defer shutdownCancel()
|
||||
if err := srv.Shutdown(shutdownCtx); err != nil {
|
||||
slog.With(slog.Any("error", err)).ErrorContext(ctx, "graceful api server shutdown failed")
|
||||
}
|
||||
|
||||
slog.With(slog.Any("error", err)).InfoContext(ctx, "waiting for runner to stop")
|
||||
if err := runner.Wait(); err != nil {
|
||||
slog.With(slog.Any("error", err)).ErrorContext(ctx, "failed to shutdown workers")
|
||||
|
|
|
|||
|
|
@ -31,7 +31,6 @@ import (
|
|||
"github.com/BurntSushi/toml"
|
||||
"github.com/bradleyfalzon/ghinstallation/v2"
|
||||
zxcvbn "github.com/nbutton23/zxcvbn-go"
|
||||
"github.com/pkg/errors"
|
||||
"golang.org/x/oauth2"
|
||||
|
||||
"github.com/cloudbase/garm/params"
|
||||
|
|
@ -84,10 +83,10 @@ const (
|
|||
func NewConfig(cfgFile string) (*Config, error) {
|
||||
var config Config
|
||||
if _, err := toml.DecodeFile(cfgFile, &config); err != nil {
|
||||
return nil, errors.Wrap(err, "decoding toml")
|
||||
return nil, fmt.Errorf("error decoding toml: %w", err)
|
||||
}
|
||||
if err := config.Validate(); err != nil {
|
||||
return nil, errors.Wrap(err, "validating config")
|
||||
return nil, fmt.Errorf("error validating config: %w", err)
|
||||
}
|
||||
return &config, nil
|
||||
}
|
||||
|
|
@ -496,19 +495,19 @@ type Database struct {
|
|||
// GormParams returns the database type and connection URI
|
||||
func (d *Database) GormParams() (dbType DBBackendType, uri string, err error) {
|
||||
if err := d.Validate(); err != nil {
|
||||
return "", "", errors.Wrap(err, "validating database config")
|
||||
return "", "", fmt.Errorf("error validating database config: %w", err)
|
||||
}
|
||||
dbType = d.DbBackend
|
||||
switch dbType {
|
||||
case MySQLBackend:
|
||||
uri, err = d.MySQL.ConnectionString()
|
||||
if err != nil {
|
||||
return "", "", errors.Wrap(err, "fetching mysql connection string")
|
||||
return "", "", fmt.Errorf("error fetching mysql connection string: %w", err)
|
||||
}
|
||||
case SQLiteBackend:
|
||||
uri, err = d.SQLite.ConnectionString()
|
||||
if err != nil {
|
||||
return "", "", errors.Wrap(err, "fetching sqlite3 connection string")
|
||||
return "", "", fmt.Errorf("error fetching sqlite3 connection string: %w", err)
|
||||
}
|
||||
default:
|
||||
return "", "", fmt.Errorf("invalid database backend: %s", dbType)
|
||||
|
|
@ -663,6 +662,21 @@ func (m *Metrics) Duration() time.Duration {
|
|||
return duration
|
||||
}
|
||||
|
||||
// WebUI holds configuration for the web UI
|
||||
type WebUI struct {
|
||||
EnableWebUI bool `toml:"enable" json:"enable"`
|
||||
}
|
||||
|
||||
// Validate validates the WebUI config
|
||||
func (w *WebUI) Validate() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetWebappPath returns the webapp path with proper formatting
|
||||
func (w *WebUI) GetWebappPath() string {
|
||||
return "/ui/"
|
||||
}
|
||||
|
||||
// APIServer holds configuration for the API server
|
||||
// worker
|
||||
type APIServer struct {
|
||||
|
|
@ -671,6 +685,7 @@ type APIServer struct {
|
|||
UseTLS bool `toml:"use_tls" json:"use-tls"`
|
||||
TLSConfig TLSConfig `toml:"tls" json:"tls"`
|
||||
CORSOrigins []string `toml:"cors_origins" json:"cors-origins"`
|
||||
WebUI WebUI `toml:"webui" json:"webui"`
|
||||
}
|
||||
|
||||
// BindAddress returns a host:port string.
|
||||
|
|
@ -696,6 +711,11 @@ func (a *APIServer) Validate() error {
|
|||
// when we try to bind to it.
|
||||
return fmt.Errorf("invalid IP address")
|
||||
}
|
||||
|
||||
if err := a.WebUI.Validate(); err != nil {
|
||||
return fmt.Errorf("invalid webui config: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -517,7 +517,6 @@ func TestJWTAuthConfig(t *testing.T) {
|
|||
|
||||
func TestTimeToLiveDuration(t *testing.T) {
|
||||
cfg := JWTAuth{
|
||||
Secret: EncryptionPassphrase,
|
||||
TimeToLive: "48h",
|
||||
}
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -75,7 +75,6 @@ type PoolStore interface {
|
|||
ListPoolInstances(ctx context.Context, poolID string) ([]params.Instance, error)
|
||||
|
||||
PoolInstanceCount(ctx context.Context, poolID string) (int64, error)
|
||||
GetPoolInstanceByName(ctx context.Context, poolID string, instanceName string) (params.Instance, error)
|
||||
FindPoolsMatchingAllTags(ctx context.Context, entityType params.ForgeEntityType, entityID string, tags []string) ([]params.Pool, error)
|
||||
}
|
||||
|
||||
|
|
@ -91,9 +90,9 @@ type UserStore interface {
|
|||
|
||||
type InstanceStore interface {
|
||||
CreateInstance(ctx context.Context, poolID string, param params.CreateInstanceParams) (params.Instance, error)
|
||||
DeleteInstance(ctx context.Context, poolID string, instanceName string) error
|
||||
DeleteInstance(ctx context.Context, poolID string, instanceNameOrID string) error
|
||||
DeleteInstanceByName(ctx context.Context, instanceName string) error
|
||||
UpdateInstance(ctx context.Context, instanceName string, param params.UpdateInstanceParams) (params.Instance, error)
|
||||
UpdateInstance(ctx context.Context, instanceNameOrID string, param params.UpdateInstanceParams) (params.Instance, error)
|
||||
|
||||
// Probably a bad idea without some king of filter or at least pagination
|
||||
//
|
||||
|
|
@ -101,8 +100,8 @@ type InstanceStore interface {
|
|||
// TODO: add filter/pagination
|
||||
ListAllInstances(ctx context.Context) ([]params.Instance, error)
|
||||
|
||||
GetInstanceByName(ctx context.Context, instanceName string) (params.Instance, error)
|
||||
AddInstanceEvent(ctx context.Context, instanceName string, event params.EventType, eventLevel params.EventLevel, eventMessage string) error
|
||||
GetInstance(ctx context.Context, instanceNameOrID string) (params.Instance, error)
|
||||
AddInstanceEvent(ctx context.Context, instanceNameOrID string, event params.EventType, eventLevel params.EventLevel, eventMessage string) error
|
||||
}
|
||||
|
||||
type JobsStore interface {
|
||||
|
|
@ -169,7 +168,7 @@ type GiteaCredentialsStore interface {
|
|||
DeleteGiteaCredentials(ctx context.Context, id uint) (err error)
|
||||
}
|
||||
|
||||
//go:generate mockery --name=Store
|
||||
//go:generate go run github.com/vektra/mockery/v2@latest
|
||||
type Store interface {
|
||||
RepoStore
|
||||
OrgStore
|
||||
|
|
|
|||
|
|
@ -15,10 +15,11 @@
|
|||
package sql
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/url"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/pkg/errors"
|
||||
"gorm.io/gorm"
|
||||
|
||||
runnerErrors "github.com/cloudbase/garm-provider-common/errors"
|
||||
|
|
@ -30,7 +31,7 @@ import (
|
|||
func dbControllerToCommonController(dbInfo ControllerInfo) (params.ControllerInfo, error) {
|
||||
url, err := url.JoinPath(dbInfo.WebhookBaseURL, dbInfo.ControllerID.String())
|
||||
if err != nil {
|
||||
return params.ControllerInfo{}, errors.Wrap(err, "joining webhook URL")
|
||||
return params.ControllerInfo{}, fmt.Errorf("error joining webhook URL: %w", err)
|
||||
}
|
||||
|
||||
return params.ControllerInfo{
|
||||
|
|
@ -49,14 +50,14 @@ func (s *sqlDatabase) ControllerInfo() (params.ControllerInfo, error) {
|
|||
q := s.conn.Model(&ControllerInfo{}).First(&info)
|
||||
if q.Error != nil {
|
||||
if errors.Is(q.Error, gorm.ErrRecordNotFound) {
|
||||
return params.ControllerInfo{}, errors.Wrap(runnerErrors.ErrNotFound, "fetching controller info")
|
||||
return params.ControllerInfo{}, fmt.Errorf("error fetching controller info: %w", runnerErrors.ErrNotFound)
|
||||
}
|
||||
return params.ControllerInfo{}, errors.Wrap(q.Error, "fetching controller info")
|
||||
return params.ControllerInfo{}, fmt.Errorf("error fetching controller info: %w", q.Error)
|
||||
}
|
||||
|
||||
paramInfo, err := dbControllerToCommonController(info)
|
||||
if err != nil {
|
||||
return params.ControllerInfo{}, errors.Wrap(err, "converting controller info")
|
||||
return params.ControllerInfo{}, fmt.Errorf("error converting controller info: %w", err)
|
||||
}
|
||||
|
||||
return paramInfo, nil
|
||||
|
|
@ -69,7 +70,7 @@ func (s *sqlDatabase) InitController() (params.ControllerInfo, error) {
|
|||
|
||||
newID, err := uuid.NewRandom()
|
||||
if err != nil {
|
||||
return params.ControllerInfo{}, errors.Wrap(err, "generating UUID")
|
||||
return params.ControllerInfo{}, fmt.Errorf("error generating UUID: %w", err)
|
||||
}
|
||||
|
||||
newInfo := ControllerInfo{
|
||||
|
|
@ -79,7 +80,7 @@ func (s *sqlDatabase) InitController() (params.ControllerInfo, error) {
|
|||
|
||||
q := s.conn.Save(&newInfo)
|
||||
if q.Error != nil {
|
||||
return params.ControllerInfo{}, errors.Wrap(q.Error, "saving controller info")
|
||||
return params.ControllerInfo{}, fmt.Errorf("error saving controller info: %w", q.Error)
|
||||
}
|
||||
|
||||
return params.ControllerInfo{
|
||||
|
|
@ -98,13 +99,13 @@ func (s *sqlDatabase) UpdateController(info params.UpdateControllerParams) (para
|
|||
q := tx.Model(&ControllerInfo{}).First(&dbInfo)
|
||||
if q.Error != nil {
|
||||
if errors.Is(q.Error, gorm.ErrRecordNotFound) {
|
||||
return errors.Wrap(runnerErrors.ErrNotFound, "fetching controller info")
|
||||
return fmt.Errorf("error fetching controller info: %w", runnerErrors.ErrNotFound)
|
||||
}
|
||||
return errors.Wrap(q.Error, "fetching controller info")
|
||||
return fmt.Errorf("error fetching controller info: %w", q.Error)
|
||||
}
|
||||
|
||||
if err := info.Validate(); err != nil {
|
||||
return errors.Wrap(err, "validating controller info")
|
||||
return fmt.Errorf("error validating controller info: %w", err)
|
||||
}
|
||||
|
||||
if info.MetadataURL != nil {
|
||||
|
|
@ -125,17 +126,17 @@ func (s *sqlDatabase) UpdateController(info params.UpdateControllerParams) (para
|
|||
|
||||
q = tx.Save(&dbInfo)
|
||||
if q.Error != nil {
|
||||
return errors.Wrap(q.Error, "saving controller info")
|
||||
return fmt.Errorf("error saving controller info: %w", q.Error)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return params.ControllerInfo{}, errors.Wrap(err, "updating controller info")
|
||||
return params.ControllerInfo{}, fmt.Errorf("error updating controller info: %w", err)
|
||||
}
|
||||
|
||||
paramInfo, err = dbControllerToCommonController(dbInfo)
|
||||
if err != nil {
|
||||
return params.ControllerInfo{}, errors.Wrap(err, "converting controller info")
|
||||
return params.ControllerInfo{}, fmt.Errorf("error converting controller info: %w", err)
|
||||
}
|
||||
return paramInfo, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,10 +16,11 @@ package sql
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/pkg/errors"
|
||||
"gorm.io/gorm"
|
||||
|
||||
runnerErrors "github.com/cloudbase/garm-provider-common/errors"
|
||||
|
|
@ -33,12 +34,12 @@ func (s *sqlDatabase) CreateEnterprise(ctx context.Context, name string, credent
|
|||
return params.Enterprise{}, errors.New("creating enterprise: missing secret")
|
||||
}
|
||||
if credentials.ForgeType != params.GithubEndpointType {
|
||||
return params.Enterprise{}, errors.Wrap(runnerErrors.ErrBadRequest, "enterprises are not supported on this forge type")
|
||||
return params.Enterprise{}, fmt.Errorf("enterprises are not supported on this forge type: %w", runnerErrors.ErrBadRequest)
|
||||
}
|
||||
|
||||
secret, err := util.Seal([]byte(webhookSecret), []byte(s.cfg.Passphrase))
|
||||
if err != nil {
|
||||
return params.Enterprise{}, errors.Wrap(err, "encoding secret")
|
||||
return params.Enterprise{}, fmt.Errorf("error encoding secret: %w", err)
|
||||
}
|
||||
|
||||
defer func() {
|
||||
|
|
@ -57,22 +58,22 @@ func (s *sqlDatabase) CreateEnterprise(ctx context.Context, name string, credent
|
|||
|
||||
q := tx.Create(&newEnterprise)
|
||||
if q.Error != nil {
|
||||
return errors.Wrap(q.Error, "creating enterprise")
|
||||
return fmt.Errorf("error creating enterprise: %w", q.Error)
|
||||
}
|
||||
|
||||
newEnterprise, err = s.getEnterpriseByID(ctx, tx, newEnterprise.ID.String(), "Pools", "Credentials", "Endpoint", "Credentials.Endpoint")
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "creating enterprise")
|
||||
return fmt.Errorf("error creating enterprise: %w", err)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return params.Enterprise{}, errors.Wrap(err, "creating enterprise")
|
||||
return params.Enterprise{}, fmt.Errorf("error creating enterprise: %w", err)
|
||||
}
|
||||
|
||||
ret, err := s.GetEnterpriseByID(ctx, newEnterprise.ID.String())
|
||||
if err != nil {
|
||||
return params.Enterprise{}, errors.Wrap(err, "creating enterprise")
|
||||
return params.Enterprise{}, fmt.Errorf("error creating enterprise: %w", err)
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
|
|
@ -81,12 +82,12 @@ func (s *sqlDatabase) CreateEnterprise(ctx context.Context, name string, credent
|
|||
func (s *sqlDatabase) GetEnterprise(ctx context.Context, name, endpointName string) (params.Enterprise, error) {
|
||||
enterprise, err := s.getEnterprise(ctx, name, endpointName)
|
||||
if err != nil {
|
||||
return params.Enterprise{}, errors.Wrap(err, "fetching enterprise")
|
||||
return params.Enterprise{}, fmt.Errorf("error fetching enterprise: %w", err)
|
||||
}
|
||||
|
||||
param, err := s.sqlToCommonEnterprise(enterprise, true)
|
||||
if err != nil {
|
||||
return params.Enterprise{}, errors.Wrap(err, "fetching enterprise")
|
||||
return params.Enterprise{}, fmt.Errorf("error fetching enterprise: %w", err)
|
||||
}
|
||||
return param, nil
|
||||
}
|
||||
|
|
@ -101,12 +102,12 @@ func (s *sqlDatabase) GetEnterpriseByID(ctx context.Context, enterpriseID string
|
|||
}
|
||||
enterprise, err := s.getEnterpriseByID(ctx, s.conn, enterpriseID, preloadList...)
|
||||
if err != nil {
|
||||
return params.Enterprise{}, errors.Wrap(err, "fetching enterprise")
|
||||
return params.Enterprise{}, fmt.Errorf("error fetching enterprise: %w", err)
|
||||
}
|
||||
|
||||
param, err := s.sqlToCommonEnterprise(enterprise, true)
|
||||
if err != nil {
|
||||
return params.Enterprise{}, errors.Wrap(err, "fetching enterprise")
|
||||
return params.Enterprise{}, fmt.Errorf("error fetching enterprise: %w", err)
|
||||
}
|
||||
return param, nil
|
||||
}
|
||||
|
|
@ -125,7 +126,7 @@ func (s *sqlDatabase) ListEnterprises(_ context.Context, filter params.Enterpris
|
|||
}
|
||||
q = q.Find(&enterprises)
|
||||
if q.Error != nil {
|
||||
return []params.Enterprise{}, errors.Wrap(q.Error, "fetching enterprises")
|
||||
return []params.Enterprise{}, fmt.Errorf("error fetching enterprises: %w", q.Error)
|
||||
}
|
||||
|
||||
ret := make([]params.Enterprise, len(enterprises))
|
||||
|
|
@ -133,7 +134,7 @@ func (s *sqlDatabase) ListEnterprises(_ context.Context, filter params.Enterpris
|
|||
var err error
|
||||
ret[idx], err = s.sqlToCommonEnterprise(val, true)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "fetching enterprises")
|
||||
return nil, fmt.Errorf("error fetching enterprises: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -143,7 +144,7 @@ func (s *sqlDatabase) ListEnterprises(_ context.Context, filter params.Enterpris
|
|||
func (s *sqlDatabase) DeleteEnterprise(ctx context.Context, enterpriseID string) error {
|
||||
enterprise, err := s.getEnterpriseByID(ctx, s.conn, enterpriseID, "Endpoint", "Credentials", "Credentials.Endpoint")
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "fetching enterprise")
|
||||
return fmt.Errorf("error fetching enterprise: %w", err)
|
||||
}
|
||||
|
||||
defer func(ent Enterprise) {
|
||||
|
|
@ -159,7 +160,7 @@ func (s *sqlDatabase) DeleteEnterprise(ctx context.Context, enterpriseID string)
|
|||
|
||||
q := s.conn.Unscoped().Delete(&enterprise)
|
||||
if q.Error != nil && !errors.Is(q.Error, gorm.ErrRecordNotFound) {
|
||||
return errors.Wrap(q.Error, "deleting enterprise")
|
||||
return fmt.Errorf("error deleting enterprise: %w", q.Error)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
|
@ -177,31 +178,31 @@ func (s *sqlDatabase) UpdateEnterprise(ctx context.Context, enterpriseID string,
|
|||
var err error
|
||||
enterprise, err = s.getEnterpriseByID(ctx, tx, enterpriseID)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "fetching enterprise")
|
||||
return fmt.Errorf("error fetching enterprise: %w", err)
|
||||
}
|
||||
|
||||
if enterprise.EndpointName == nil {
|
||||
return errors.Wrap(runnerErrors.ErrUnprocessable, "enterprise has no endpoint")
|
||||
return fmt.Errorf("error enterprise has no endpoint: %w", runnerErrors.ErrUnprocessable)
|
||||
}
|
||||
|
||||
if param.CredentialsName != "" {
|
||||
creds, err = s.getGithubCredentialsByName(ctx, tx, param.CredentialsName, false)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "fetching credentials")
|
||||
return fmt.Errorf("error fetching credentials: %w", err)
|
||||
}
|
||||
if creds.EndpointName == nil {
|
||||
return errors.Wrap(runnerErrors.ErrUnprocessable, "credentials have no endpoint")
|
||||
return fmt.Errorf("error credentials have no endpoint: %w", runnerErrors.ErrUnprocessable)
|
||||
}
|
||||
|
||||
if *creds.EndpointName != *enterprise.EndpointName {
|
||||
return errors.Wrap(runnerErrors.ErrBadRequest, "endpoint mismatch")
|
||||
return fmt.Errorf("error endpoint mismatch: %w", runnerErrors.ErrBadRequest)
|
||||
}
|
||||
enterprise.CredentialsID = &creds.ID
|
||||
}
|
||||
if param.WebhookSecret != "" {
|
||||
secret, err := util.Seal([]byte(param.WebhookSecret), []byte(s.cfg.Passphrase))
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "encoding secret")
|
||||
return fmt.Errorf("error encoding secret: %w", err)
|
||||
}
|
||||
enterprise.WebhookSecret = secret
|
||||
}
|
||||
|
|
@ -212,22 +213,22 @@ func (s *sqlDatabase) UpdateEnterprise(ctx context.Context, enterpriseID string,
|
|||
|
||||
q := tx.Save(&enterprise)
|
||||
if q.Error != nil {
|
||||
return errors.Wrap(q.Error, "saving enterprise")
|
||||
return fmt.Errorf("error saving enterprise: %w", q.Error)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return params.Enterprise{}, errors.Wrap(err, "updating enterprise")
|
||||
return params.Enterprise{}, fmt.Errorf("error updating enterprise: %w", err)
|
||||
}
|
||||
|
||||
enterprise, err = s.getEnterpriseByID(ctx, s.conn, enterpriseID, "Endpoint", "Credentials", "Credentials.Endpoint")
|
||||
if err != nil {
|
||||
return params.Enterprise{}, errors.Wrap(err, "updating enterprise")
|
||||
return params.Enterprise{}, fmt.Errorf("error updating enterprise: %w", err)
|
||||
}
|
||||
newParams, err = s.sqlToCommonEnterprise(enterprise, true)
|
||||
if err != nil {
|
||||
return params.Enterprise{}, errors.Wrap(err, "updating enterprise")
|
||||
return params.Enterprise{}, fmt.Errorf("error updating enterprise: %w", err)
|
||||
}
|
||||
return newParams, nil
|
||||
}
|
||||
|
|
@ -244,7 +245,7 @@ func (s *sqlDatabase) getEnterprise(_ context.Context, name, endpointName string
|
|||
if errors.Is(q.Error, gorm.ErrRecordNotFound) {
|
||||
return Enterprise{}, runnerErrors.ErrNotFound
|
||||
}
|
||||
return Enterprise{}, errors.Wrap(q.Error, "fetching enterprise from database")
|
||||
return Enterprise{}, fmt.Errorf("error fetching enterprise from database: %w", q.Error)
|
||||
}
|
||||
return enterprise, nil
|
||||
}
|
||||
|
|
@ -252,7 +253,7 @@ func (s *sqlDatabase) getEnterprise(_ context.Context, name, endpointName string
|
|||
func (s *sqlDatabase) getEnterpriseByID(_ context.Context, tx *gorm.DB, id string, preload ...string) (Enterprise, error) {
|
||||
u, err := uuid.Parse(id)
|
||||
if err != nil {
|
||||
return Enterprise{}, errors.Wrap(runnerErrors.ErrBadRequest, "parsing id")
|
||||
return Enterprise{}, fmt.Errorf("error parsing id: %w", runnerErrors.ErrBadRequest)
|
||||
}
|
||||
var enterprise Enterprise
|
||||
|
||||
|
|
@ -268,7 +269,7 @@ func (s *sqlDatabase) getEnterpriseByID(_ context.Context, tx *gorm.DB, id strin
|
|||
if errors.Is(q.Error, gorm.ErrRecordNotFound) {
|
||||
return Enterprise{}, runnerErrors.ErrNotFound
|
||||
}
|
||||
return Enterprise{}, errors.Wrap(q.Error, "fetching enterprise from database")
|
||||
return Enterprise{}, fmt.Errorf("error fetching enterprise from database: %w", q.Error)
|
||||
}
|
||||
return enterprise, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -218,7 +218,7 @@ func (s *EnterpriseTestSuite) TestCreateEnterpriseInvalidDBPassphrase() {
|
|||
params.PoolBalancerTypeRoundRobin)
|
||||
|
||||
s.Require().NotNil(err)
|
||||
s.Require().Equal("encoding secret: invalid passphrase length (expected length 32 characters)", err.Error())
|
||||
s.Require().Equal("error encoding secret: invalid passphrase length (expected length 32 characters)", err.Error())
|
||||
}
|
||||
|
||||
func (s *EnterpriseTestSuite) TestCreateEnterpriseDBCreateErr() {
|
||||
|
|
@ -236,7 +236,7 @@ func (s *EnterpriseTestSuite) TestCreateEnterpriseDBCreateErr() {
|
|||
params.PoolBalancerTypeRoundRobin)
|
||||
|
||||
s.Require().NotNil(err)
|
||||
s.Require().Equal("creating enterprise: creating enterprise: creating enterprise mock error", err.Error())
|
||||
s.Require().Equal("error creating enterprise: error creating enterprise: creating enterprise mock error", err.Error())
|
||||
s.assertSQLMockExpectations()
|
||||
}
|
||||
|
||||
|
|
@ -259,7 +259,7 @@ func (s *EnterpriseTestSuite) TestGetEnterpriseNotFound() {
|
|||
_, err := s.Store.GetEnterprise(s.adminCtx, "dummy-name", "github.com")
|
||||
|
||||
s.Require().NotNil(err)
|
||||
s.Require().Equal("fetching enterprise: not found", err.Error())
|
||||
s.Require().Equal("error fetching enterprise: not found", err.Error())
|
||||
}
|
||||
|
||||
func (s *EnterpriseTestSuite) TestGetEnterpriseDBDecryptingErr() {
|
||||
|
|
@ -271,7 +271,7 @@ func (s *EnterpriseTestSuite) TestGetEnterpriseDBDecryptingErr() {
|
|||
_, err := s.StoreSQLMocked.GetEnterprise(s.adminCtx, s.Fixtures.Enterprises[0].Name, s.Fixtures.Enterprises[0].Endpoint.Name)
|
||||
|
||||
s.Require().NotNil(err)
|
||||
s.Require().Equal("fetching enterprise: missing secret", err.Error())
|
||||
s.Require().Equal("error fetching enterprise: missing secret", err.Error())
|
||||
s.assertSQLMockExpectations()
|
||||
}
|
||||
|
||||
|
|
@ -341,7 +341,7 @@ func (s *EnterpriseTestSuite) TestListEnterprisesDBFetchErr() {
|
|||
|
||||
s.assertSQLMockExpectations()
|
||||
s.Require().NotNil(err)
|
||||
s.Require().Equal("fetching enterprises: fetching user from database mock error", err.Error())
|
||||
s.Require().Equal("error fetching enterprises: fetching user from database mock error", err.Error())
|
||||
}
|
||||
|
||||
func (s *EnterpriseTestSuite) TestDeleteEnterprise() {
|
||||
|
|
@ -350,14 +350,14 @@ func (s *EnterpriseTestSuite) TestDeleteEnterprise() {
|
|||
s.Require().Nil(err)
|
||||
_, err = s.Store.GetEnterpriseByID(s.adminCtx, s.Fixtures.Enterprises[0].ID)
|
||||
s.Require().NotNil(err)
|
||||
s.Require().Equal("fetching enterprise: not found", err.Error())
|
||||
s.Require().Equal("error fetching enterprise: not found", err.Error())
|
||||
}
|
||||
|
||||
func (s *EnterpriseTestSuite) TestDeleteEnterpriseInvalidEnterpriseID() {
|
||||
err := s.Store.DeleteEnterprise(s.adminCtx, "dummy-enterprise-id")
|
||||
|
||||
s.Require().NotNil(err)
|
||||
s.Require().Equal("fetching enterprise: parsing id: invalid request", err.Error())
|
||||
s.Require().Equal("error fetching enterprise: error parsing id: invalid request", err.Error())
|
||||
}
|
||||
|
||||
func (s *EnterpriseTestSuite) TestDeleteEnterpriseDBDeleteErr() {
|
||||
|
|
@ -375,7 +375,7 @@ func (s *EnterpriseTestSuite) TestDeleteEnterpriseDBDeleteErr() {
|
|||
err := s.StoreSQLMocked.DeleteEnterprise(s.adminCtx, s.Fixtures.Enterprises[0].ID)
|
||||
|
||||
s.Require().NotNil(err)
|
||||
s.Require().Equal("deleting enterprise: mocked delete enterprise error", err.Error())
|
||||
s.Require().Equal("error deleting enterprise: mocked delete enterprise error", err.Error())
|
||||
s.assertSQLMockExpectations()
|
||||
}
|
||||
|
||||
|
|
@ -391,7 +391,7 @@ func (s *EnterpriseTestSuite) TestUpdateEnterpriseInvalidEnterpriseID() {
|
|||
_, err := s.Store.UpdateEnterprise(s.adminCtx, "dummy-enterprise-id", s.Fixtures.UpdateRepoParams)
|
||||
|
||||
s.Require().NotNil(err)
|
||||
s.Require().Equal("updating enterprise: fetching enterprise: parsing id: invalid request", err.Error())
|
||||
s.Require().Equal("error updating enterprise: error fetching enterprise: error parsing id: invalid request", err.Error())
|
||||
}
|
||||
|
||||
func (s *EnterpriseTestSuite) TestUpdateEnterpriseDBEncryptErr() {
|
||||
|
|
@ -416,7 +416,7 @@ func (s *EnterpriseTestSuite) TestUpdateEnterpriseDBEncryptErr() {
|
|||
_, err := s.StoreSQLMocked.UpdateEnterprise(s.adminCtx, s.Fixtures.Enterprises[0].ID, s.Fixtures.UpdateRepoParams)
|
||||
|
||||
s.Require().NotNil(err)
|
||||
s.Require().Equal("updating enterprise: encoding secret: invalid passphrase length (expected length 32 characters)", err.Error())
|
||||
s.Require().Equal("error updating enterprise: error encoding secret: invalid passphrase length (expected length 32 characters)", err.Error())
|
||||
s.assertSQLMockExpectations()
|
||||
}
|
||||
|
||||
|
|
@ -444,7 +444,7 @@ func (s *EnterpriseTestSuite) TestUpdateEnterpriseDBSaveErr() {
|
|||
_, err := s.StoreSQLMocked.UpdateEnterprise(s.adminCtx, s.Fixtures.Enterprises[0].ID, s.Fixtures.UpdateRepoParams)
|
||||
|
||||
s.Require().NotNil(err)
|
||||
s.Require().Equal("updating enterprise: saving enterprise: saving enterprise mock error", err.Error())
|
||||
s.Require().Equal("error updating enterprise: error saving enterprise: saving enterprise mock error", err.Error())
|
||||
s.assertSQLMockExpectations()
|
||||
}
|
||||
|
||||
|
|
@ -472,7 +472,7 @@ func (s *EnterpriseTestSuite) TestUpdateEnterpriseDBDecryptingErr() {
|
|||
_, err := s.StoreSQLMocked.UpdateEnterprise(s.adminCtx, s.Fixtures.Enterprises[0].ID, s.Fixtures.UpdateRepoParams)
|
||||
|
||||
s.Require().NotNil(err)
|
||||
s.Require().Equal("updating enterprise: encoding secret: invalid passphrase length (expected length 32 characters)", err.Error())
|
||||
s.Require().Equal("error updating enterprise: error encoding secret: invalid passphrase length (expected length 32 characters)", err.Error())
|
||||
s.assertSQLMockExpectations()
|
||||
}
|
||||
|
||||
|
|
@ -487,7 +487,7 @@ func (s *EnterpriseTestSuite) TestGetEnterpriseByIDInvalidEnterpriseID() {
|
|||
_, err := s.Store.GetEnterpriseByID(s.adminCtx, "dummy-enterprise-id")
|
||||
|
||||
s.Require().NotNil(err)
|
||||
s.Require().Equal("fetching enterprise: parsing id: invalid request", err.Error())
|
||||
s.Require().Equal("error fetching enterprise: error parsing id: invalid request", err.Error())
|
||||
}
|
||||
|
||||
func (s *EnterpriseTestSuite) TestGetEnterpriseByIDDBDecryptingErr() {
|
||||
|
|
@ -508,7 +508,7 @@ func (s *EnterpriseTestSuite) TestGetEnterpriseByIDDBDecryptingErr() {
|
|||
|
||||
s.assertSQLMockExpectations()
|
||||
s.Require().NotNil(err)
|
||||
s.Require().Equal("fetching enterprise: missing secret", err.Error())
|
||||
s.Require().Equal("error fetching enterprise: missing secret", err.Error())
|
||||
}
|
||||
|
||||
func (s *EnterpriseTestSuite) TestCreateEnterprisePool() {
|
||||
|
|
@ -547,7 +547,7 @@ func (s *EnterpriseTestSuite) TestCreateEnterprisePoolInvalidEnterpriseID() {
|
|||
_, err := s.Store.CreateEntityPool(s.adminCtx, entity, s.Fixtures.CreatePoolParams)
|
||||
|
||||
s.Require().NotNil(err)
|
||||
s.Require().Equal("parsing id: invalid request", err.Error())
|
||||
s.Require().Equal("error parsing id: invalid request", err.Error())
|
||||
}
|
||||
|
||||
func (s *EnterpriseTestSuite) TestCreateEnterprisePoolDBFetchTagErr() {
|
||||
|
|
@ -565,7 +565,7 @@ func (s *EnterpriseTestSuite) TestCreateEnterprisePoolDBFetchTagErr() {
|
|||
_, err = s.StoreSQLMocked.CreateEntityPool(s.adminCtx, entity, s.Fixtures.CreatePoolParams)
|
||||
|
||||
s.Require().NotNil(err)
|
||||
s.Require().Equal("creating tag: fetching tag from database: mocked fetching tag error", err.Error())
|
||||
s.Require().Equal("error creating tag: error fetching tag from database: mocked fetching tag error", err.Error())
|
||||
s.assertSQLMockExpectations()
|
||||
}
|
||||
|
||||
|
|
@ -592,7 +592,7 @@ func (s *EnterpriseTestSuite) TestCreateEnterprisePoolDBAddingPoolErr() {
|
|||
_, err = s.StoreSQLMocked.CreateEntityPool(s.adminCtx, entity, s.Fixtures.CreatePoolParams)
|
||||
|
||||
s.Require().NotNil(err)
|
||||
s.Require().Equal("creating pool: mocked adding pool error", err.Error())
|
||||
s.Require().Equal("error creating pool: mocked adding pool error", err.Error())
|
||||
s.assertSQLMockExpectations()
|
||||
}
|
||||
|
||||
|
|
@ -623,7 +623,7 @@ func (s *EnterpriseTestSuite) TestCreateEnterprisePoolDBSaveTagErr() {
|
|||
_, err = s.StoreSQLMocked.CreateEntityPool(s.adminCtx, entity, s.Fixtures.CreatePoolParams)
|
||||
|
||||
s.Require().NotNil(err)
|
||||
s.Require().Equal("associating tags: mocked saving tag error", err.Error())
|
||||
s.Require().Equal("error associating tags: mocked saving tag error", err.Error())
|
||||
s.assertSQLMockExpectations()
|
||||
}
|
||||
|
||||
|
|
@ -663,7 +663,7 @@ func (s *EnterpriseTestSuite) TestCreateEnterprisePoolDBFetchPoolErr() {
|
|||
_, err = s.StoreSQLMocked.CreateEntityPool(s.adminCtx, entity, s.Fixtures.CreatePoolParams)
|
||||
|
||||
s.Require().NotNil(err)
|
||||
s.Require().Equal("fetching pool: not found", err.Error())
|
||||
s.Require().Equal("error fetching pool by ID: not found", err.Error())
|
||||
s.assertSQLMockExpectations()
|
||||
}
|
||||
|
||||
|
|
@ -694,7 +694,7 @@ func (s *EnterpriseTestSuite) TestListEnterprisePoolsInvalidEnterpriseID() {
|
|||
_, err := s.Store.ListEntityPools(s.adminCtx, entity)
|
||||
|
||||
s.Require().NotNil(err)
|
||||
s.Require().Equal("fetching pools: parsing id: invalid request", err.Error())
|
||||
s.Require().Equal("error fetching pools: error parsing id: invalid request", err.Error())
|
||||
}
|
||||
|
||||
func (s *EnterpriseTestSuite) TestGetEnterprisePool() {
|
||||
|
|
@ -719,7 +719,7 @@ func (s *EnterpriseTestSuite) TestGetEnterprisePoolInvalidEnterpriseID() {
|
|||
_, err := s.Store.GetEntityPool(s.adminCtx, entity, "dummy-pool-id")
|
||||
|
||||
s.Require().NotNil(err)
|
||||
s.Require().Equal("fetching pool: parsing id: invalid request", err.Error())
|
||||
s.Require().Equal("fetching pool: error parsing id: invalid request", err.Error())
|
||||
}
|
||||
|
||||
func (s *EnterpriseTestSuite) TestDeleteEnterprisePool() {
|
||||
|
|
@ -734,7 +734,7 @@ func (s *EnterpriseTestSuite) TestDeleteEnterprisePool() {
|
|||
|
||||
s.Require().Nil(err)
|
||||
_, err = s.Store.GetEntityPool(s.adminCtx, entity, pool.ID)
|
||||
s.Require().Equal("fetching pool: finding pool: not found", err.Error())
|
||||
s.Require().Equal("fetching pool: error finding pool: not found", err.Error())
|
||||
}
|
||||
|
||||
func (s *EnterpriseTestSuite) TestDeleteEnterprisePoolInvalidEnterpriseID() {
|
||||
|
|
@ -745,7 +745,7 @@ func (s *EnterpriseTestSuite) TestDeleteEnterprisePoolInvalidEnterpriseID() {
|
|||
err := s.Store.DeleteEntityPool(s.adminCtx, entity, "dummy-pool-id")
|
||||
|
||||
s.Require().NotNil(err)
|
||||
s.Require().Equal("parsing id: invalid request", err.Error())
|
||||
s.Require().Equal("error parsing id: invalid request", err.Error())
|
||||
}
|
||||
|
||||
func (s *EnterpriseTestSuite) TestDeleteEnterprisePoolDBDeleteErr() {
|
||||
|
|
@ -765,7 +765,7 @@ func (s *EnterpriseTestSuite) TestDeleteEnterprisePoolDBDeleteErr() {
|
|||
|
||||
err = s.StoreSQLMocked.DeleteEntityPool(s.adminCtx, entity, pool.ID)
|
||||
s.Require().NotNil(err)
|
||||
s.Require().Equal("removing pool: mocked deleting pool error", err.Error())
|
||||
s.Require().Equal("error removing pool: mocked deleting pool error", err.Error())
|
||||
s.assertSQLMockExpectations()
|
||||
}
|
||||
|
||||
|
|
@ -800,7 +800,7 @@ func (s *EnterpriseTestSuite) TestListEnterpriseInstancesInvalidEnterpriseID() {
|
|||
_, err := s.Store.ListEntityInstances(s.adminCtx, entity)
|
||||
|
||||
s.Require().NotNil(err)
|
||||
s.Require().Equal("fetching entity: parsing id: invalid request", err.Error())
|
||||
s.Require().Equal("error fetching entity: error parsing id: invalid request", err.Error())
|
||||
}
|
||||
|
||||
func (s *EnterpriseTestSuite) TestUpdateEnterprisePool() {
|
||||
|
|
@ -828,7 +828,7 @@ func (s *EnterpriseTestSuite) TestUpdateEnterprisePoolInvalidEnterpriseID() {
|
|||
_, err := s.Store.UpdateEntityPool(s.adminCtx, entity, "dummy-pool-id", s.Fixtures.UpdatePoolParams)
|
||||
|
||||
s.Require().NotNil(err)
|
||||
s.Require().Equal("fetching pool: parsing id: invalid request", err.Error())
|
||||
s.Require().Equal("error fetching pool: error parsing id: invalid request", err.Error())
|
||||
}
|
||||
|
||||
func (s *EnterpriseTestSuite) TestAddRepoEntityEvent() {
|
||||
|
|
|
|||
|
|
@ -16,9 +16,10 @@ package sql
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"gorm.io/gorm"
|
||||
|
||||
runnerErrors "github.com/cloudbase/garm-provider-common/errors"
|
||||
|
|
@ -36,7 +37,7 @@ func (s *sqlDatabase) CreateGiteaEndpoint(_ context.Context, param params.Create
|
|||
var endpoint GithubEndpoint
|
||||
err = s.conn.Transaction(func(tx *gorm.DB) error {
|
||||
if err := tx.Where("name = ?", param.Name).First(&endpoint).Error; err == nil {
|
||||
return errors.Wrap(runnerErrors.ErrDuplicateEntity, "gitea endpoint already exists")
|
||||
return fmt.Errorf("gitea endpoint already exists: %w", runnerErrors.ErrDuplicateEntity)
|
||||
}
|
||||
endpoint = GithubEndpoint{
|
||||
Name: param.Name,
|
||||
|
|
@ -48,16 +49,16 @@ func (s *sqlDatabase) CreateGiteaEndpoint(_ context.Context, param params.Create
|
|||
}
|
||||
|
||||
if err := tx.Create(&endpoint).Error; err != nil {
|
||||
return errors.Wrap(err, "creating gitea endpoint")
|
||||
return fmt.Errorf("error creating gitea endpoint: %w", err)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return params.ForgeEndpoint{}, errors.Wrap(err, "creating gitea endpoint")
|
||||
return params.ForgeEndpoint{}, fmt.Errorf("error creating gitea endpoint: %w", err)
|
||||
}
|
||||
ghEndpoint, err = s.sqlToCommonGithubEndpoint(endpoint)
|
||||
if err != nil {
|
||||
return params.ForgeEndpoint{}, errors.Wrap(err, "converting gitea endpoint")
|
||||
return params.ForgeEndpoint{}, fmt.Errorf("error converting gitea endpoint: %w", err)
|
||||
}
|
||||
return ghEndpoint, nil
|
||||
}
|
||||
|
|
@ -66,14 +67,14 @@ func (s *sqlDatabase) ListGiteaEndpoints(_ context.Context) ([]params.ForgeEndpo
|
|||
var endpoints []GithubEndpoint
|
||||
err := s.conn.Where("endpoint_type = ?", params.GiteaEndpointType).Find(&endpoints).Error
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "fetching gitea endpoints")
|
||||
return nil, fmt.Errorf("error fetching gitea endpoints: %w", err)
|
||||
}
|
||||
|
||||
var ret []params.ForgeEndpoint
|
||||
for _, ep := range endpoints {
|
||||
commonEp, err := s.sqlToCommonGithubEndpoint(ep)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "converting gitea endpoint")
|
||||
return nil, fmt.Errorf("error converting gitea endpoint: %w", err)
|
||||
}
|
||||
ret = append(ret, commonEp)
|
||||
}
|
||||
|
|
@ -90,19 +91,19 @@ func (s *sqlDatabase) UpdateGiteaEndpoint(_ context.Context, name string, param
|
|||
err = s.conn.Transaction(func(tx *gorm.DB) error {
|
||||
if err := tx.Where("name = ? and endpoint_type = ?", name, params.GiteaEndpointType).First(&endpoint).Error; err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return errors.Wrap(runnerErrors.ErrNotFound, "gitea endpoint not found")
|
||||
return runnerErrors.NewNotFoundError("gitea endpoint %q not found", name)
|
||||
}
|
||||
return errors.Wrap(err, "fetching gitea endpoint")
|
||||
return fmt.Errorf("error fetching gitea endpoint: %w", err)
|
||||
}
|
||||
|
||||
var credsCount int64
|
||||
if err := tx.Model(&GiteaCredentials{}).Where("endpoint_name = ?", endpoint.Name).Count(&credsCount).Error; err != nil {
|
||||
if !errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return errors.Wrap(err, "fetching gitea credentials")
|
||||
return fmt.Errorf("error fetching gitea credentials: %w", err)
|
||||
}
|
||||
}
|
||||
if credsCount > 0 && (param.APIBaseURL != nil || param.BaseURL != nil) {
|
||||
return errors.Wrap(runnerErrors.ErrBadRequest, "cannot update endpoint URLs with existing credentials")
|
||||
return runnerErrors.NewBadRequestError("cannot update endpoint URLs with existing credentials")
|
||||
}
|
||||
|
||||
if param.APIBaseURL != nil {
|
||||
|
|
@ -122,17 +123,17 @@ func (s *sqlDatabase) UpdateGiteaEndpoint(_ context.Context, name string, param
|
|||
}
|
||||
|
||||
if err := tx.Save(&endpoint).Error; err != nil {
|
||||
return errors.Wrap(err, "updating gitea endpoint")
|
||||
return fmt.Errorf("error updating gitea endpoint: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return params.ForgeEndpoint{}, errors.Wrap(err, "updating gitea endpoint")
|
||||
return params.ForgeEndpoint{}, fmt.Errorf("error updating gitea endpoint: %w", err)
|
||||
}
|
||||
ghEndpoint, err = s.sqlToCommonGithubEndpoint(endpoint)
|
||||
if err != nil {
|
||||
return params.ForgeEndpoint{}, errors.Wrap(err, "converting gitea endpoint")
|
||||
return params.ForgeEndpoint{}, fmt.Errorf("error converting gitea endpoint: %w", err)
|
||||
}
|
||||
return ghEndpoint, nil
|
||||
}
|
||||
|
|
@ -142,9 +143,9 @@ func (s *sqlDatabase) GetGiteaEndpoint(_ context.Context, name string) (params.F
|
|||
err := s.conn.Where("name = ? and endpoint_type = ?", name, params.GiteaEndpointType).First(&endpoint).Error
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return params.ForgeEndpoint{}, errors.Wrap(runnerErrors.ErrNotFound, "gitea endpoint not found")
|
||||
return params.ForgeEndpoint{}, runnerErrors.NewNotFoundError("gitea endpoint %q not found", name)
|
||||
}
|
||||
return params.ForgeEndpoint{}, errors.Wrap(err, "fetching gitea endpoint")
|
||||
return params.ForgeEndpoint{}, fmt.Errorf("error fetching gitea endpoint: %w", err)
|
||||
}
|
||||
|
||||
return s.sqlToCommonGithubEndpoint(endpoint)
|
||||
|
|
@ -162,41 +163,41 @@ func (s *sqlDatabase) DeleteGiteaEndpoint(_ context.Context, name string) (err e
|
|||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return nil
|
||||
}
|
||||
return errors.Wrap(err, "fetching gitea endpoint")
|
||||
return fmt.Errorf("error fetching gitea endpoint: %w", err)
|
||||
}
|
||||
|
||||
var credsCount int64
|
||||
if err := tx.Model(&GiteaCredentials{}).Where("endpoint_name = ?", endpoint.Name).Count(&credsCount).Error; err != nil {
|
||||
if !errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return errors.Wrap(err, "fetching gitea credentials")
|
||||
return fmt.Errorf("error fetching gitea credentials: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
var repoCnt int64
|
||||
if err := tx.Model(&Repository{}).Where("endpoint_name = ?", endpoint.Name).Count(&repoCnt).Error; err != nil {
|
||||
if !errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return errors.Wrap(err, "fetching gitea repositories")
|
||||
return fmt.Errorf("error fetching gitea repositories: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
var orgCnt int64
|
||||
if err := tx.Model(&Organization{}).Where("endpoint_name = ?", endpoint.Name).Count(&orgCnt).Error; err != nil {
|
||||
if !errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return errors.Wrap(err, "fetching gitea organizations")
|
||||
return fmt.Errorf("error fetching gitea organizations: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
if credsCount > 0 || repoCnt > 0 || orgCnt > 0 {
|
||||
return errors.Wrap(runnerErrors.ErrBadRequest, "cannot delete endpoint with associated entities")
|
||||
return runnerErrors.NewBadRequestError("cannot delete endpoint with associated entities")
|
||||
}
|
||||
|
||||
if err := tx.Unscoped().Delete(&endpoint).Error; err != nil {
|
||||
return errors.Wrap(err, "deleting gitea endpoint")
|
||||
return fmt.Errorf("error deleting gitea endpoint: %w", err)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "deleting gitea endpoint")
|
||||
return fmt.Errorf("error deleting gitea endpoint: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
@ -204,10 +205,10 @@ func (s *sqlDatabase) DeleteGiteaEndpoint(_ context.Context, name string) (err e
|
|||
func (s *sqlDatabase) CreateGiteaCredentials(ctx context.Context, param params.CreateGiteaCredentialsParams) (gtCreds params.ForgeCredentials, err error) {
|
||||
userID, err := getUIDFromContext(ctx)
|
||||
if err != nil {
|
||||
return params.ForgeCredentials{}, errors.Wrap(err, "creating gitea credentials")
|
||||
return params.ForgeCredentials{}, fmt.Errorf("error creating gitea credentials: %w", err)
|
||||
}
|
||||
if param.Endpoint == "" {
|
||||
return params.ForgeCredentials{}, errors.Wrap(runnerErrors.ErrBadRequest, "endpoint name is required")
|
||||
return params.ForgeCredentials{}, runnerErrors.NewBadRequestError("endpoint name is required")
|
||||
}
|
||||
|
||||
defer func() {
|
||||
|
|
@ -220,13 +221,13 @@ func (s *sqlDatabase) CreateGiteaCredentials(ctx context.Context, param params.C
|
|||
var endpoint GithubEndpoint
|
||||
if err := tx.Where("name = ? and endpoint_type = ?", param.Endpoint, params.GiteaEndpointType).First(&endpoint).Error; err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return errors.Wrap(runnerErrors.ErrNotFound, "gitea endpoint not found")
|
||||
return runnerErrors.NewNotFoundError("gitea endpoint %q not found", param.Endpoint)
|
||||
}
|
||||
return errors.Wrap(err, "fetching gitea endpoint")
|
||||
return fmt.Errorf("error fetching gitea endpoint: %w", err)
|
||||
}
|
||||
|
||||
if err := tx.Where("name = ? and user_id = ?", param.Name, userID).First(&creds).Error; err == nil {
|
||||
return errors.Wrap(runnerErrors.ErrDuplicateEntity, "gitea credentials already exists")
|
||||
return fmt.Errorf("gitea credentials already exists: %w", runnerErrors.ErrDuplicateEntity)
|
||||
}
|
||||
|
||||
var data []byte
|
||||
|
|
@ -235,10 +236,10 @@ func (s *sqlDatabase) CreateGiteaCredentials(ctx context.Context, param params.C
|
|||
case params.ForgeAuthTypePAT:
|
||||
data, err = s.marshalAndSeal(param.PAT)
|
||||
default:
|
||||
return errors.Wrap(runnerErrors.ErrBadRequest, "invalid auth type")
|
||||
return runnerErrors.NewBadRequestError("invalid auth type %q", param.AuthType)
|
||||
}
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "marshaling and sealing credentials")
|
||||
return fmt.Errorf("error marshaling and sealing credentials: %w", err)
|
||||
}
|
||||
|
||||
creds = GiteaCredentials{
|
||||
|
|
@ -251,7 +252,7 @@ func (s *sqlDatabase) CreateGiteaCredentials(ctx context.Context, param params.C
|
|||
}
|
||||
|
||||
if err := tx.Create(&creds).Error; err != nil {
|
||||
return errors.Wrap(err, "creating gitea credentials")
|
||||
return fmt.Errorf("error creating gitea credentials: %w", err)
|
||||
}
|
||||
// Skip making an extra query.
|
||||
creds.Endpoint = endpoint
|
||||
|
|
@ -259,11 +260,11 @@ func (s *sqlDatabase) CreateGiteaCredentials(ctx context.Context, param params.C
|
|||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return params.ForgeCredentials{}, errors.Wrap(err, "creating gitea credentials")
|
||||
return params.ForgeCredentials{}, fmt.Errorf("error creating gitea credentials: %w", err)
|
||||
}
|
||||
gtCreds, err = s.sqlGiteaToCommonForgeCredentials(creds)
|
||||
if err != nil {
|
||||
return params.ForgeCredentials{}, errors.Wrap(err, "converting gitea credentials")
|
||||
return params.ForgeCredentials{}, fmt.Errorf("error converting gitea credentials: %w", err)
|
||||
}
|
||||
return gtCreds, nil
|
||||
}
|
||||
|
|
@ -284,16 +285,16 @@ func (s *sqlDatabase) getGiteaCredentialsByName(ctx context.Context, tx *gorm.DB
|
|||
|
||||
userID, err := getUIDFromContext(ctx)
|
||||
if err != nil {
|
||||
return GiteaCredentials{}, errors.Wrap(err, "fetching gitea credentials")
|
||||
return GiteaCredentials{}, fmt.Errorf("error fetching gitea credentials: %w", err)
|
||||
}
|
||||
q = q.Where("user_id = ?", userID)
|
||||
|
||||
err = q.Where("name = ?", name).First(&creds).Error
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return GiteaCredentials{}, errors.Wrap(runnerErrors.ErrNotFound, "gitea credentials not found")
|
||||
return GiteaCredentials{}, runnerErrors.NewNotFoundError("gitea credentials %q not found", name)
|
||||
}
|
||||
return GiteaCredentials{}, errors.Wrap(err, "fetching gitea credentials")
|
||||
return GiteaCredentials{}, fmt.Errorf("error fetching gitea credentials: %w", err)
|
||||
}
|
||||
|
||||
return creds, nil
|
||||
|
|
@ -302,7 +303,7 @@ func (s *sqlDatabase) getGiteaCredentialsByName(ctx context.Context, tx *gorm.DB
|
|||
func (s *sqlDatabase) GetGiteaCredentialsByName(ctx context.Context, name string, detailed bool) (params.ForgeCredentials, error) {
|
||||
creds, err := s.getGiteaCredentialsByName(ctx, s.conn, name, detailed)
|
||||
if err != nil {
|
||||
return params.ForgeCredentials{}, errors.Wrap(err, "fetching gitea credentials")
|
||||
return params.ForgeCredentials{}, fmt.Errorf("error fetching gitea credentials: %w", err)
|
||||
}
|
||||
|
||||
return s.sqlGiteaToCommonForgeCredentials(creds)
|
||||
|
|
@ -325,7 +326,7 @@ func (s *sqlDatabase) GetGiteaCredentials(ctx context.Context, id uint, detailed
|
|||
if !auth.IsAdmin(ctx) {
|
||||
userID, err := getUIDFromContext(ctx)
|
||||
if err != nil {
|
||||
return params.ForgeCredentials{}, errors.Wrap(err, "fetching gitea credentials")
|
||||
return params.ForgeCredentials{}, fmt.Errorf("error fetching gitea credentials: %w", err)
|
||||
}
|
||||
q = q.Where("user_id = ?", userID)
|
||||
}
|
||||
|
|
@ -333,9 +334,9 @@ func (s *sqlDatabase) GetGiteaCredentials(ctx context.Context, id uint, detailed
|
|||
err := q.Where("id = ?", id).First(&creds).Error
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return params.ForgeCredentials{}, errors.Wrap(runnerErrors.ErrNotFound, "gitea credentials not found")
|
||||
return params.ForgeCredentials{}, runnerErrors.NewNotFoundError("gitea credentials not found")
|
||||
}
|
||||
return params.ForgeCredentials{}, errors.Wrap(err, "fetching gitea credentials")
|
||||
return params.ForgeCredentials{}, fmt.Errorf("error fetching gitea credentials: %w", err)
|
||||
}
|
||||
|
||||
return s.sqlGiteaToCommonForgeCredentials(creds)
|
||||
|
|
@ -346,7 +347,7 @@ func (s *sqlDatabase) ListGiteaCredentials(ctx context.Context) ([]params.ForgeC
|
|||
if !auth.IsAdmin(ctx) {
|
||||
userID, err := getUIDFromContext(ctx)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "fetching gitea credentials")
|
||||
return nil, fmt.Errorf("error fetching gitea credentials: %w", err)
|
||||
}
|
||||
q = q.Where("user_id = ?", userID)
|
||||
}
|
||||
|
|
@ -354,14 +355,14 @@ func (s *sqlDatabase) ListGiteaCredentials(ctx context.Context) ([]params.ForgeC
|
|||
var creds []GiteaCredentials
|
||||
err := q.Preload("Endpoint").Find(&creds).Error
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "fetching gitea credentials")
|
||||
return nil, fmt.Errorf("error fetching gitea credentials: %w", err)
|
||||
}
|
||||
|
||||
var ret []params.ForgeCredentials
|
||||
for _, c := range creds {
|
||||
commonCreds, err := s.sqlGiteaToCommonForgeCredentials(c)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "converting gitea credentials")
|
||||
return nil, fmt.Errorf("error converting gitea credentials: %w", err)
|
||||
}
|
||||
ret = append(ret, commonCreds)
|
||||
}
|
||||
|
|
@ -380,16 +381,16 @@ func (s *sqlDatabase) UpdateGiteaCredentials(ctx context.Context, id uint, param
|
|||
if !auth.IsAdmin(ctx) {
|
||||
userID, err := getUIDFromContext(ctx)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "updating gitea credentials")
|
||||
return fmt.Errorf("error updating gitea credentials: %w", err)
|
||||
}
|
||||
q = q.Where("user_id = ?", userID)
|
||||
}
|
||||
|
||||
if err := q.Where("id = ?", id).First(&creds).Error; err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return errors.Wrap(runnerErrors.ErrNotFound, "gitea credentials not found")
|
||||
return runnerErrors.NewNotFoundError("gitea credentials not found")
|
||||
}
|
||||
return errors.Wrap(err, "fetching gitea credentials")
|
||||
return fmt.Errorf("error fetching gitea credentials: %w", err)
|
||||
}
|
||||
|
||||
if param.Name != nil {
|
||||
|
|
@ -407,28 +408,28 @@ func (s *sqlDatabase) UpdateGiteaCredentials(ctx context.Context, id uint, param
|
|||
data, err = s.marshalAndSeal(param.PAT)
|
||||
}
|
||||
default:
|
||||
return errors.Wrap(runnerErrors.ErrBadRequest, "invalid auth type")
|
||||
return runnerErrors.NewBadRequestError("invalid auth type %q", creds.AuthType)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "marshaling and sealing credentials")
|
||||
return fmt.Errorf("error marshaling and sealing credentials: %w", err)
|
||||
}
|
||||
if len(data) > 0 {
|
||||
creds.Payload = data
|
||||
}
|
||||
|
||||
if err := tx.Save(&creds).Error; err != nil {
|
||||
return errors.Wrap(err, "updating gitea credentials")
|
||||
return fmt.Errorf("error updating gitea credentials: %w", err)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return params.ForgeCredentials{}, errors.Wrap(err, "updating gitea credentials")
|
||||
return params.ForgeCredentials{}, fmt.Errorf("error updating gitea credentials: %w", err)
|
||||
}
|
||||
|
||||
gtCreds, err = s.sqlGiteaToCommonForgeCredentials(creds)
|
||||
if err != nil {
|
||||
return params.ForgeCredentials{}, errors.Wrap(err, "converting gitea credentials")
|
||||
return params.ForgeCredentials{}, fmt.Errorf("error converting gitea credentials: %w", err)
|
||||
}
|
||||
return gtCreds, nil
|
||||
}
|
||||
|
|
@ -454,7 +455,7 @@ func (s *sqlDatabase) DeleteGiteaCredentials(ctx context.Context, id uint) (err
|
|||
if !auth.IsAdmin(ctx) {
|
||||
userID, err := getUIDFromContext(ctx)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "deleting gitea credentials")
|
||||
return fmt.Errorf("error deleting gitea credentials: %w", err)
|
||||
}
|
||||
q = q.Where("user_id = ?", userID)
|
||||
}
|
||||
|
|
@ -464,22 +465,22 @@ func (s *sqlDatabase) DeleteGiteaCredentials(ctx context.Context, id uint) (err
|
|||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return nil
|
||||
}
|
||||
return errors.Wrap(err, "fetching gitea credentials")
|
||||
return fmt.Errorf("error fetching gitea credentials: %w", err)
|
||||
}
|
||||
|
||||
if len(creds.Repositories) > 0 {
|
||||
return errors.Wrap(runnerErrors.ErrBadRequest, "cannot delete credentials with repositories")
|
||||
return runnerErrors.NewBadRequestError("cannot delete credentials with repositories")
|
||||
}
|
||||
if len(creds.Organizations) > 0 {
|
||||
return errors.Wrap(runnerErrors.ErrBadRequest, "cannot delete credentials with organizations")
|
||||
return runnerErrors.NewBadRequestError("cannot delete credentials with organizations")
|
||||
}
|
||||
if err := tx.Unscoped().Delete(&creds).Error; err != nil {
|
||||
return errors.Wrap(err, "deleting gitea credentials")
|
||||
return fmt.Errorf("error deleting gitea credentials: %w", err)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "deleting gitea credentials")
|
||||
return fmt.Errorf("error deleting gitea credentials: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -236,7 +236,7 @@ func (s *GiteaTestSuite) TestCreateCredentialsFailsWhenEndpointDoesNotExist() {
|
|||
_, err := s.db.CreateGiteaCredentials(ctx, params.CreateGiteaCredentialsParams{Endpoint: "non-existing"})
|
||||
s.Require().Error(err)
|
||||
s.Require().ErrorIs(err, runnerErrors.ErrNotFound)
|
||||
s.Require().Regexp("endpoint not found", err.Error())
|
||||
s.Require().Regexp("error creating gitea credentials: gitea endpoint \"non-existing\" not found", err.Error())
|
||||
}
|
||||
|
||||
func (s *GiteaTestSuite) TestCreateCredentialsFailsWhenAuthTypeIsInvalid() {
|
||||
|
|
@ -807,7 +807,7 @@ func (s *GiteaTestSuite) TestUpdateEndpointURLsFailsIfCredentialsAreAssociated()
|
|||
_, err = s.db.UpdateGiteaEndpoint(ctx, testEndpointName, updateEpParams)
|
||||
s.Require().Error(err)
|
||||
s.Require().ErrorIs(err, runnerErrors.ErrBadRequest)
|
||||
s.Require().EqualError(err, "updating gitea endpoint: cannot update endpoint URLs with existing credentials: invalid request")
|
||||
s.Require().EqualError(err, "error updating gitea endpoint: cannot update endpoint URLs with existing credentials")
|
||||
|
||||
updateEpParams = params.UpdateGiteaEndpointParams{
|
||||
APIBaseURL: &newAPIBaseURL,
|
||||
|
|
@ -815,7 +815,7 @@ func (s *GiteaTestSuite) TestUpdateEndpointURLsFailsIfCredentialsAreAssociated()
|
|||
_, err = s.db.UpdateGiteaEndpoint(ctx, testEndpointName, updateEpParams)
|
||||
s.Require().Error(err)
|
||||
s.Require().ErrorIs(err, runnerErrors.ErrBadRequest)
|
||||
s.Require().EqualError(err, "updating gitea endpoint: cannot update endpoint URLs with existing credentials: invalid request")
|
||||
s.Require().EqualError(err, "error updating gitea endpoint: cannot update endpoint URLs with existing credentials")
|
||||
|
||||
updateEpParams = params.UpdateGiteaEndpointParams{
|
||||
Description: &newDescription,
|
||||
|
|
|
|||
|
|
@ -16,8 +16,9 @@ package sql
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"gorm.io/gorm"
|
||||
|
||||
runnerErrors "github.com/cloudbase/garm-provider-common/errors"
|
||||
|
|
@ -35,7 +36,7 @@ func (s *sqlDatabase) CreateGithubEndpoint(_ context.Context, param params.Creat
|
|||
var endpoint GithubEndpoint
|
||||
err = s.conn.Transaction(func(tx *gorm.DB) error {
|
||||
if err := tx.Where("name = ?", param.Name).First(&endpoint).Error; err == nil {
|
||||
return errors.Wrap(runnerErrors.ErrDuplicateEntity, "github endpoint already exists")
|
||||
return fmt.Errorf("error github endpoint already exists: %w", runnerErrors.ErrDuplicateEntity)
|
||||
}
|
||||
endpoint = GithubEndpoint{
|
||||
Name: param.Name,
|
||||
|
|
@ -48,16 +49,16 @@ func (s *sqlDatabase) CreateGithubEndpoint(_ context.Context, param params.Creat
|
|||
}
|
||||
|
||||
if err := tx.Create(&endpoint).Error; err != nil {
|
||||
return errors.Wrap(err, "creating github endpoint")
|
||||
return fmt.Errorf("error creating github endpoint: %w", err)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return params.ForgeEndpoint{}, errors.Wrap(err, "creating github endpoint")
|
||||
return params.ForgeEndpoint{}, fmt.Errorf("error creating github endpoint: %w", err)
|
||||
}
|
||||
ghEndpoint, err = s.sqlToCommonGithubEndpoint(endpoint)
|
||||
if err != nil {
|
||||
return params.ForgeEndpoint{}, errors.Wrap(err, "converting github endpoint")
|
||||
return params.ForgeEndpoint{}, fmt.Errorf("error converting github endpoint: %w", err)
|
||||
}
|
||||
return ghEndpoint, nil
|
||||
}
|
||||
|
|
@ -66,14 +67,14 @@ func (s *sqlDatabase) ListGithubEndpoints(_ context.Context) ([]params.ForgeEndp
|
|||
var endpoints []GithubEndpoint
|
||||
err := s.conn.Where("endpoint_type = ?", params.GithubEndpointType).Find(&endpoints).Error
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "fetching github endpoints")
|
||||
return nil, fmt.Errorf("error fetching github endpoints: %w", err)
|
||||
}
|
||||
|
||||
var ret []params.ForgeEndpoint
|
||||
for _, ep := range endpoints {
|
||||
commonEp, err := s.sqlToCommonGithubEndpoint(ep)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "converting github endpoint")
|
||||
return nil, fmt.Errorf("error converting github endpoint: %w", err)
|
||||
}
|
||||
ret = append(ret, commonEp)
|
||||
}
|
||||
|
|
@ -90,19 +91,19 @@ func (s *sqlDatabase) UpdateGithubEndpoint(_ context.Context, name string, param
|
|||
err = s.conn.Transaction(func(tx *gorm.DB) error {
|
||||
if err := tx.Where("name = ? and endpoint_type = ?", name, params.GithubEndpointType).First(&endpoint).Error; err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return errors.Wrap(runnerErrors.ErrNotFound, "github endpoint not found")
|
||||
return fmt.Errorf("error github endpoint not found: %w", runnerErrors.ErrNotFound)
|
||||
}
|
||||
return errors.Wrap(err, "fetching github endpoint")
|
||||
return fmt.Errorf("error fetching github endpoint: %w", err)
|
||||
}
|
||||
|
||||
var credsCount int64
|
||||
if err := tx.Model(&GithubCredentials{}).Where("endpoint_name = ?", endpoint.Name).Count(&credsCount).Error; err != nil {
|
||||
if !errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return errors.Wrap(err, "fetching github credentials")
|
||||
return fmt.Errorf("error fetching github credentials: %w", err)
|
||||
}
|
||||
}
|
||||
if credsCount > 0 && (param.APIBaseURL != nil || param.BaseURL != nil || param.UploadBaseURL != nil) {
|
||||
return errors.Wrap(runnerErrors.ErrBadRequest, "cannot update endpoint URLs with existing credentials")
|
||||
return fmt.Errorf("cannot update endpoint URLs with existing credentials: %w", runnerErrors.ErrBadRequest)
|
||||
}
|
||||
|
||||
if param.APIBaseURL != nil {
|
||||
|
|
@ -126,17 +127,17 @@ func (s *sqlDatabase) UpdateGithubEndpoint(_ context.Context, name string, param
|
|||
}
|
||||
|
||||
if err := tx.Save(&endpoint).Error; err != nil {
|
||||
return errors.Wrap(err, "updating github endpoint")
|
||||
return fmt.Errorf("error updating github endpoint: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return params.ForgeEndpoint{}, errors.Wrap(err, "updating github endpoint")
|
||||
return params.ForgeEndpoint{}, fmt.Errorf("error updating github endpoint: %w", err)
|
||||
}
|
||||
ghEndpoint, err = s.sqlToCommonGithubEndpoint(endpoint)
|
||||
if err != nil {
|
||||
return params.ForgeEndpoint{}, errors.Wrap(err, "converting github endpoint")
|
||||
return params.ForgeEndpoint{}, fmt.Errorf("error converting github endpoint: %w", err)
|
||||
}
|
||||
return ghEndpoint, nil
|
||||
}
|
||||
|
|
@ -147,9 +148,9 @@ func (s *sqlDatabase) GetGithubEndpoint(_ context.Context, name string) (params.
|
|||
err := s.conn.Where("name = ? and endpoint_type = ?", name, params.GithubEndpointType).First(&endpoint).Error
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return params.ForgeEndpoint{}, errors.Wrap(runnerErrors.ErrNotFound, "github endpoint not found")
|
||||
return params.ForgeEndpoint{}, fmt.Errorf("github endpoint not found: %w", runnerErrors.ErrNotFound)
|
||||
}
|
||||
return params.ForgeEndpoint{}, errors.Wrap(err, "fetching github endpoint")
|
||||
return params.ForgeEndpoint{}, fmt.Errorf("error fetching github endpoint: %w", err)
|
||||
}
|
||||
|
||||
return s.sqlToCommonGithubEndpoint(endpoint)
|
||||
|
|
@ -167,48 +168,48 @@ func (s *sqlDatabase) DeleteGithubEndpoint(_ context.Context, name string) (err
|
|||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return nil
|
||||
}
|
||||
return errors.Wrap(err, "fetching github endpoint")
|
||||
return fmt.Errorf("error fetching github endpoint: %w", err)
|
||||
}
|
||||
|
||||
var credsCount int64
|
||||
if err := tx.Model(&GithubCredentials{}).Where("endpoint_name = ?", endpoint.Name).Count(&credsCount).Error; err != nil {
|
||||
if !errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return errors.Wrap(err, "fetching github credentials")
|
||||
return fmt.Errorf("error fetching github credentials: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
var repoCnt int64
|
||||
if err := tx.Model(&Repository{}).Where("endpoint_name = ?", endpoint.Name).Count(&repoCnt).Error; err != nil {
|
||||
if !errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return errors.Wrap(err, "fetching github repositories")
|
||||
return fmt.Errorf("error fetching github repositories: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
var orgCnt int64
|
||||
if err := tx.Model(&Organization{}).Where("endpoint_name = ?", endpoint.Name).Count(&orgCnt).Error; err != nil {
|
||||
if !errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return errors.Wrap(err, "fetching github organizations")
|
||||
return fmt.Errorf("error fetching github organizations: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
var entCnt int64
|
||||
if err := tx.Model(&Enterprise{}).Where("endpoint_name = ?", endpoint.Name).Count(&entCnt).Error; err != nil {
|
||||
if !errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return errors.Wrap(err, "fetching github enterprises")
|
||||
return fmt.Errorf("error fetching github enterprises: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
if credsCount > 0 || repoCnt > 0 || orgCnt > 0 || entCnt > 0 {
|
||||
return errors.Wrap(runnerErrors.ErrBadRequest, "cannot delete endpoint with associated entities")
|
||||
return fmt.Errorf("cannot delete endpoint with associated entities: %w", runnerErrors.ErrBadRequest)
|
||||
}
|
||||
|
||||
if err := tx.Unscoped().Delete(&endpoint).Error; err != nil {
|
||||
return errors.Wrap(err, "deleting github endpoint")
|
||||
return fmt.Errorf("error deleting github endpoint: %w", err)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "deleting github endpoint")
|
||||
return fmt.Errorf("error deleting github endpoint: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
@ -216,10 +217,10 @@ func (s *sqlDatabase) DeleteGithubEndpoint(_ context.Context, name string) (err
|
|||
func (s *sqlDatabase) CreateGithubCredentials(ctx context.Context, param params.CreateGithubCredentialsParams) (ghCreds params.ForgeCredentials, err error) {
|
||||
userID, err := getUIDFromContext(ctx)
|
||||
if err != nil {
|
||||
return params.ForgeCredentials{}, errors.Wrap(err, "creating github credentials")
|
||||
return params.ForgeCredentials{}, fmt.Errorf("error creating github credentials: %w", err)
|
||||
}
|
||||
if param.Endpoint == "" {
|
||||
return params.ForgeCredentials{}, errors.Wrap(runnerErrors.ErrBadRequest, "endpoint name is required")
|
||||
return params.ForgeCredentials{}, fmt.Errorf("endpoint name is required: %w", runnerErrors.ErrBadRequest)
|
||||
}
|
||||
|
||||
defer func() {
|
||||
|
|
@ -232,13 +233,13 @@ func (s *sqlDatabase) CreateGithubCredentials(ctx context.Context, param params.
|
|||
var endpoint GithubEndpoint
|
||||
if err := tx.Where("name = ? and endpoint_type = ?", param.Endpoint, params.GithubEndpointType).First(&endpoint).Error; err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return errors.Wrap(runnerErrors.ErrNotFound, "github endpoint not found")
|
||||
return fmt.Errorf("github endpoint not found: %w", runnerErrors.ErrNotFound)
|
||||
}
|
||||
return errors.Wrap(err, "fetching github endpoint")
|
||||
return fmt.Errorf("error fetching github endpoint: %w", err)
|
||||
}
|
||||
|
||||
if err := tx.Where("name = ? and user_id = ?", param.Name, userID).First(&creds).Error; err == nil {
|
||||
return errors.Wrap(runnerErrors.ErrDuplicateEntity, "github credentials already exists")
|
||||
return fmt.Errorf("github credentials already exists: %w", runnerErrors.ErrDuplicateEntity)
|
||||
}
|
||||
|
||||
var data []byte
|
||||
|
|
@ -249,10 +250,10 @@ func (s *sqlDatabase) CreateGithubCredentials(ctx context.Context, param params.
|
|||
case params.ForgeAuthTypeApp:
|
||||
data, err = s.marshalAndSeal(param.App)
|
||||
default:
|
||||
return errors.Wrap(runnerErrors.ErrBadRequest, "invalid auth type")
|
||||
return fmt.Errorf("invalid auth type: %w", runnerErrors.ErrBadRequest)
|
||||
}
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "marshaling and sealing credentials")
|
||||
return fmt.Errorf("error marshaling and sealing credentials: %w", err)
|
||||
}
|
||||
|
||||
creds = GithubCredentials{
|
||||
|
|
@ -265,7 +266,7 @@ func (s *sqlDatabase) CreateGithubCredentials(ctx context.Context, param params.
|
|||
}
|
||||
|
||||
if err := tx.Create(&creds).Error; err != nil {
|
||||
return errors.Wrap(err, "creating github credentials")
|
||||
return fmt.Errorf("error creating github credentials: %w", err)
|
||||
}
|
||||
// Skip making an extra query.
|
||||
creds.Endpoint = endpoint
|
||||
|
|
@ -273,11 +274,11 @@ func (s *sqlDatabase) CreateGithubCredentials(ctx context.Context, param params.
|
|||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return params.ForgeCredentials{}, errors.Wrap(err, "creating github credentials")
|
||||
return params.ForgeCredentials{}, fmt.Errorf("error creating github credentials: %w", err)
|
||||
}
|
||||
ghCreds, err = s.sqlToCommonForgeCredentials(creds)
|
||||
if err != nil {
|
||||
return params.ForgeCredentials{}, errors.Wrap(err, "converting github credentials")
|
||||
return params.ForgeCredentials{}, fmt.Errorf("error converting github credentials: %w", err)
|
||||
}
|
||||
return ghCreds, nil
|
||||
}
|
||||
|
|
@ -298,16 +299,16 @@ func (s *sqlDatabase) getGithubCredentialsByName(ctx context.Context, tx *gorm.D
|
|||
|
||||
userID, err := getUIDFromContext(ctx)
|
||||
if err != nil {
|
||||
return GithubCredentials{}, errors.Wrap(err, "fetching github credentials")
|
||||
return GithubCredentials{}, fmt.Errorf("error fetching github credentials: %w", err)
|
||||
}
|
||||
q = q.Where("user_id = ?", userID)
|
||||
|
||||
err = q.Where("name = ?", name).First(&creds).Error
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return GithubCredentials{}, errors.Wrap(runnerErrors.ErrNotFound, "github credentials not found")
|
||||
return GithubCredentials{}, fmt.Errorf("github credentials not found: %w", runnerErrors.ErrNotFound)
|
||||
}
|
||||
return GithubCredentials{}, errors.Wrap(err, "fetching github credentials")
|
||||
return GithubCredentials{}, fmt.Errorf("error fetching github credentials: %w", err)
|
||||
}
|
||||
|
||||
return creds, nil
|
||||
|
|
@ -316,7 +317,7 @@ func (s *sqlDatabase) getGithubCredentialsByName(ctx context.Context, tx *gorm.D
|
|||
func (s *sqlDatabase) GetGithubCredentialsByName(ctx context.Context, name string, detailed bool) (params.ForgeCredentials, error) {
|
||||
creds, err := s.getGithubCredentialsByName(ctx, s.conn, name, detailed)
|
||||
if err != nil {
|
||||
return params.ForgeCredentials{}, errors.Wrap(err, "fetching github credentials")
|
||||
return params.ForgeCredentials{}, fmt.Errorf("error fetching github credentials: %w", err)
|
||||
}
|
||||
return s.sqlToCommonForgeCredentials(creds)
|
||||
}
|
||||
|
|
@ -338,7 +339,7 @@ func (s *sqlDatabase) GetGithubCredentials(ctx context.Context, id uint, detaile
|
|||
if !auth.IsAdmin(ctx) {
|
||||
userID, err := getUIDFromContext(ctx)
|
||||
if err != nil {
|
||||
return params.ForgeCredentials{}, errors.Wrap(err, "fetching github credentials")
|
||||
return params.ForgeCredentials{}, fmt.Errorf("error fetching github credentials: %w", err)
|
||||
}
|
||||
q = q.Where("user_id = ?", userID)
|
||||
}
|
||||
|
|
@ -346,9 +347,9 @@ func (s *sqlDatabase) GetGithubCredentials(ctx context.Context, id uint, detaile
|
|||
err := q.Where("id = ?", id).First(&creds).Error
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return params.ForgeCredentials{}, errors.Wrap(runnerErrors.ErrNotFound, "github credentials not found")
|
||||
return params.ForgeCredentials{}, fmt.Errorf("github credentials not found: %w", runnerErrors.ErrNotFound)
|
||||
}
|
||||
return params.ForgeCredentials{}, errors.Wrap(err, "fetching github credentials")
|
||||
return params.ForgeCredentials{}, fmt.Errorf("error fetching github credentials: %w", err)
|
||||
}
|
||||
|
||||
return s.sqlToCommonForgeCredentials(creds)
|
||||
|
|
@ -359,7 +360,7 @@ func (s *sqlDatabase) ListGithubCredentials(ctx context.Context) ([]params.Forge
|
|||
if !auth.IsAdmin(ctx) {
|
||||
userID, err := getUIDFromContext(ctx)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "fetching github credentials")
|
||||
return nil, fmt.Errorf("error fetching github credentials: %w", err)
|
||||
}
|
||||
q = q.Where("user_id = ?", userID)
|
||||
}
|
||||
|
|
@ -367,14 +368,14 @@ func (s *sqlDatabase) ListGithubCredentials(ctx context.Context) ([]params.Forge
|
|||
var creds []GithubCredentials
|
||||
err := q.Preload("Endpoint").Find(&creds).Error
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "fetching github credentials")
|
||||
return nil, fmt.Errorf("error fetching github credentials: %w", err)
|
||||
}
|
||||
|
||||
var ret []params.ForgeCredentials
|
||||
for _, c := range creds {
|
||||
commonCreds, err := s.sqlToCommonForgeCredentials(c)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "converting github credentials")
|
||||
return nil, fmt.Errorf("error converting github credentials: %w", err)
|
||||
}
|
||||
ret = append(ret, commonCreds)
|
||||
}
|
||||
|
|
@ -393,16 +394,16 @@ func (s *sqlDatabase) UpdateGithubCredentials(ctx context.Context, id uint, para
|
|||
if !auth.IsAdmin(ctx) {
|
||||
userID, err := getUIDFromContext(ctx)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "updating github credentials")
|
||||
return fmt.Errorf("error updating github credentials: %w", err)
|
||||
}
|
||||
q = q.Where("user_id = ?", userID)
|
||||
}
|
||||
|
||||
if err := q.Where("id = ?", id).First(&creds).Error; err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return errors.Wrap(runnerErrors.ErrNotFound, "github credentials not found")
|
||||
return fmt.Errorf("github credentials not found: %w", runnerErrors.ErrNotFound)
|
||||
}
|
||||
return errors.Wrap(err, "fetching github credentials")
|
||||
return fmt.Errorf("error fetching github credentials: %w", err)
|
||||
}
|
||||
|
||||
if param.Name != nil {
|
||||
|
|
@ -421,7 +422,7 @@ func (s *sqlDatabase) UpdateGithubCredentials(ctx context.Context, id uint, para
|
|||
}
|
||||
|
||||
if param.App != nil {
|
||||
return errors.Wrap(runnerErrors.ErrBadRequest, "cannot update app credentials for PAT")
|
||||
return fmt.Errorf("cannot update app credentials for PAT: %w", runnerErrors.ErrBadRequest)
|
||||
}
|
||||
case params.ForgeAuthTypeApp:
|
||||
if param.App != nil {
|
||||
|
|
@ -429,33 +430,33 @@ func (s *sqlDatabase) UpdateGithubCredentials(ctx context.Context, id uint, para
|
|||
}
|
||||
|
||||
if param.PAT != nil {
|
||||
return errors.Wrap(runnerErrors.ErrBadRequest, "cannot update PAT credentials for app")
|
||||
return fmt.Errorf("cannot update PAT credentials for app: %w", runnerErrors.ErrBadRequest)
|
||||
}
|
||||
default:
|
||||
// This should never happen, unless there was a bug in the DB migration code,
|
||||
// or the DB was manually modified.
|
||||
return errors.Wrap(runnerErrors.ErrBadRequest, "invalid auth type")
|
||||
return fmt.Errorf("invalid auth type: %w", runnerErrors.ErrBadRequest)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "marshaling and sealing credentials")
|
||||
return fmt.Errorf("error marshaling and sealing credentials: %w", err)
|
||||
}
|
||||
if len(data) > 0 {
|
||||
creds.Payload = data
|
||||
}
|
||||
|
||||
if err := tx.Save(&creds).Error; err != nil {
|
||||
return errors.Wrap(err, "updating github credentials")
|
||||
return fmt.Errorf("error updating github credentials: %w", err)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return params.ForgeCredentials{}, errors.Wrap(err, "updating github credentials")
|
||||
return params.ForgeCredentials{}, fmt.Errorf("error updating github credentials: %w", err)
|
||||
}
|
||||
|
||||
ghCreds, err = s.sqlToCommonForgeCredentials(creds)
|
||||
if err != nil {
|
||||
return params.ForgeCredentials{}, errors.Wrap(err, "converting github credentials")
|
||||
return params.ForgeCredentials{}, fmt.Errorf("error converting github credentials: %w", err)
|
||||
}
|
||||
return ghCreds, nil
|
||||
}
|
||||
|
|
@ -475,7 +476,7 @@ func (s *sqlDatabase) DeleteGithubCredentials(ctx context.Context, id uint) (err
|
|||
if !auth.IsAdmin(ctx) {
|
||||
userID, err := getUIDFromContext(ctx)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "deleting github credentials")
|
||||
return fmt.Errorf("error deleting github credentials: %w", err)
|
||||
}
|
||||
q = q.Where("user_id = ?", userID)
|
||||
}
|
||||
|
|
@ -486,27 +487,27 @@ func (s *sqlDatabase) DeleteGithubCredentials(ctx context.Context, id uint) (err
|
|||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return nil
|
||||
}
|
||||
return errors.Wrap(err, "fetching github credentials")
|
||||
return fmt.Errorf("error fetching github credentials: %w", err)
|
||||
}
|
||||
name = creds.Name
|
||||
|
||||
if len(creds.Repositories) > 0 {
|
||||
return errors.Wrap(runnerErrors.ErrBadRequest, "cannot delete credentials with repositories")
|
||||
return fmt.Errorf("cannot delete credentials with repositories: %w", runnerErrors.ErrBadRequest)
|
||||
}
|
||||
if len(creds.Organizations) > 0 {
|
||||
return errors.Wrap(runnerErrors.ErrBadRequest, "cannot delete credentials with organizations")
|
||||
return fmt.Errorf("cannot delete credentials with organizations: %w", runnerErrors.ErrBadRequest)
|
||||
}
|
||||
if len(creds.Enterprises) > 0 {
|
||||
return errors.Wrap(runnerErrors.ErrBadRequest, "cannot delete credentials with enterprises")
|
||||
return fmt.Errorf("cannot delete credentials with enterprises: %w", runnerErrors.ErrBadRequest)
|
||||
}
|
||||
|
||||
if err := tx.Unscoped().Delete(&creds).Error; err != nil {
|
||||
return errors.Wrap(err, "deleting github credentials")
|
||||
return fmt.Errorf("error deleting github credentials: %w", err)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "deleting github credentials")
|
||||
return fmt.Errorf("error deleting github credentials: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -265,7 +265,7 @@ func (s *GithubTestSuite) TestUpdateEndpointURLsFailsIfCredentialsAreAssociated(
|
|||
_, err = s.db.UpdateGithubEndpoint(ctx, testEndpointName, updateEpParams)
|
||||
s.Require().Error(err)
|
||||
s.Require().ErrorIs(err, runnerErrors.ErrBadRequest)
|
||||
s.Require().EqualError(err, "updating github endpoint: cannot update endpoint URLs with existing credentials: invalid request")
|
||||
s.Require().EqualError(err, "error updating github endpoint: cannot update endpoint URLs with existing credentials: invalid request")
|
||||
|
||||
updateEpParams = params.UpdateGithubEndpointParams{
|
||||
UploadBaseURL: &newUploadBaseURL,
|
||||
|
|
@ -274,7 +274,7 @@ func (s *GithubTestSuite) TestUpdateEndpointURLsFailsIfCredentialsAreAssociated(
|
|||
_, err = s.db.UpdateGithubEndpoint(ctx, testEndpointName, updateEpParams)
|
||||
s.Require().Error(err)
|
||||
s.Require().ErrorIs(err, runnerErrors.ErrBadRequest)
|
||||
s.Require().EqualError(err, "updating github endpoint: cannot update endpoint URLs with existing credentials: invalid request")
|
||||
s.Require().EqualError(err, "error updating github endpoint: cannot update endpoint URLs with existing credentials: invalid request")
|
||||
|
||||
updateEpParams = params.UpdateGithubEndpointParams{
|
||||
APIBaseURL: &newAPIBaseURL,
|
||||
|
|
@ -282,7 +282,7 @@ func (s *GithubTestSuite) TestUpdateEndpointURLsFailsIfCredentialsAreAssociated(
|
|||
_, err = s.db.UpdateGithubEndpoint(ctx, testEndpointName, updateEpParams)
|
||||
s.Require().Error(err)
|
||||
s.Require().ErrorIs(err, runnerErrors.ErrBadRequest)
|
||||
s.Require().EqualError(err, "updating github endpoint: cannot update endpoint URLs with existing credentials: invalid request")
|
||||
s.Require().EqualError(err, "error updating github endpoint: cannot update endpoint URLs with existing credentials: invalid request")
|
||||
|
||||
updateEpParams = params.UpdateGithubEndpointParams{
|
||||
Description: &newDescription,
|
||||
|
|
@ -737,7 +737,7 @@ func (s *GithubTestSuite) TestUpdateGithubCredentialsFailIfWrongCredentialTypeIs
|
|||
_, err = s.db.UpdateGithubCredentials(ctx, creds.ID, updateCredParams)
|
||||
s.Require().Error(err)
|
||||
s.Require().ErrorIs(err, runnerErrors.ErrBadRequest)
|
||||
s.Require().EqualError(err, "updating github credentials: cannot update app credentials for PAT: invalid request")
|
||||
s.Require().EqualError(err, "error updating github credentials: cannot update app credentials for PAT: invalid request")
|
||||
|
||||
credParamsWithApp := params.CreateGithubCredentialsParams{
|
||||
Name: "test-credsApp",
|
||||
|
|
@ -764,7 +764,7 @@ func (s *GithubTestSuite) TestUpdateGithubCredentialsFailIfWrongCredentialTypeIs
|
|||
_, err = s.db.UpdateGithubCredentials(ctx, credsApp.ID, updateCredParams)
|
||||
s.Require().Error(err)
|
||||
s.Require().ErrorIs(err, runnerErrors.ErrBadRequest)
|
||||
s.Require().EqualError(err, "updating github credentials: cannot update PAT credentials for app: invalid request")
|
||||
s.Require().EqualError(err, "error updating github credentials: cannot update PAT credentials for app: invalid request")
|
||||
}
|
||||
|
||||
func (s *GithubTestSuite) TestUpdateCredentialsFailsForNonExistingCredentials() {
|
||||
|
|
|
|||
|
|
@ -17,10 +17,11 @@ package sql
|
|||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/pkg/errors"
|
||||
"gorm.io/datatypes"
|
||||
"gorm.io/gorm"
|
||||
"gorm.io/gorm/clause"
|
||||
|
|
@ -33,7 +34,7 @@ import (
|
|||
func (s *sqlDatabase) CreateInstance(_ context.Context, poolID string, param params.CreateInstanceParams) (instance params.Instance, err error) {
|
||||
pool, err := s.getPoolByID(s.conn, poolID)
|
||||
if err != nil {
|
||||
return params.Instance{}, errors.Wrap(err, "fetching pool")
|
||||
return params.Instance{}, fmt.Errorf("error fetching pool: %w", err)
|
||||
}
|
||||
|
||||
defer func() {
|
||||
|
|
@ -46,7 +47,7 @@ func (s *sqlDatabase) CreateInstance(_ context.Context, poolID string, param par
|
|||
if len(param.AditionalLabels) > 0 {
|
||||
labels, err = json.Marshal(param.AditionalLabels)
|
||||
if err != nil {
|
||||
return params.Instance{}, errors.Wrap(err, "marshalling labels")
|
||||
return params.Instance{}, fmt.Errorf("error marshalling labels: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -54,7 +55,7 @@ func (s *sqlDatabase) CreateInstance(_ context.Context, poolID string, param par
|
|||
if len(param.JitConfiguration) > 0 {
|
||||
secret, err = s.marshalAndSeal(param.JitConfiguration)
|
||||
if err != nil {
|
||||
return params.Instance{}, errors.Wrap(err, "marshalling jit config")
|
||||
return params.Instance{}, fmt.Errorf("error marshalling jit config: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -74,7 +75,7 @@ func (s *sqlDatabase) CreateInstance(_ context.Context, poolID string, param par
|
|||
}
|
||||
q := s.conn.Create(&newInstance)
|
||||
if q.Error != nil {
|
||||
return params.Instance{}, errors.Wrap(q.Error, "creating instance")
|
||||
return params.Instance{}, fmt.Errorf("error creating instance: %w", q.Error)
|
||||
}
|
||||
|
||||
return s.sqlToParamsInstance(newInstance)
|
||||
|
|
@ -83,7 +84,7 @@ func (s *sqlDatabase) CreateInstance(_ context.Context, poolID string, param par
|
|||
func (s *sqlDatabase) getPoolInstanceByName(poolID string, instanceName string) (Instance, error) {
|
||||
pool, err := s.getPoolByID(s.conn, poolID)
|
||||
if err != nil {
|
||||
return Instance{}, errors.Wrap(err, "fetching pool")
|
||||
return Instance{}, fmt.Errorf("error fetching pool: %w", err)
|
||||
}
|
||||
|
||||
var instance Instance
|
||||
|
|
@ -93,18 +94,25 @@ func (s *sqlDatabase) getPoolInstanceByName(poolID string, instanceName string)
|
|||
First(&instance)
|
||||
if q.Error != nil {
|
||||
if errors.Is(q.Error, gorm.ErrRecordNotFound) {
|
||||
return Instance{}, errors.Wrap(runnerErrors.ErrNotFound, "fetching pool instance by name")
|
||||
return Instance{}, fmt.Errorf("error fetching pool instance by name: %w", runnerErrors.ErrNotFound)
|
||||
}
|
||||
return Instance{}, errors.Wrap(q.Error, "fetching pool instance by name")
|
||||
return Instance{}, fmt.Errorf("error fetching pool instance by name: %w", q.Error)
|
||||
}
|
||||
|
||||
instance.Pool = pool
|
||||
return instance, nil
|
||||
}
|
||||
|
||||
func (s *sqlDatabase) getInstanceByName(_ context.Context, instanceName string, preload ...string) (Instance, error) {
|
||||
func (s *sqlDatabase) getInstance(_ context.Context, instanceNameOrID string, preload ...string) (Instance, error) {
|
||||
var instance Instance
|
||||
|
||||
var whereArg any = instanceNameOrID
|
||||
whereClause := "name = ?"
|
||||
id, err := uuid.Parse(instanceNameOrID)
|
||||
if err == nil {
|
||||
whereArg = id
|
||||
whereClause = "id = ?"
|
||||
}
|
||||
q := s.conn
|
||||
|
||||
if len(preload) > 0 {
|
||||
|
|
@ -115,30 +123,21 @@ func (s *sqlDatabase) getInstanceByName(_ context.Context, instanceName string,
|
|||
|
||||
q = q.Model(&Instance{}).
|
||||
Preload(clause.Associations).
|
||||
Where("name = ?", instanceName).
|
||||
Where(whereClause, whereArg).
|
||||
First(&instance)
|
||||
if q.Error != nil {
|
||||
if errors.Is(q.Error, gorm.ErrRecordNotFound) {
|
||||
return Instance{}, errors.Wrap(runnerErrors.ErrNotFound, "fetching instance by name")
|
||||
return Instance{}, fmt.Errorf("error fetching instance by name: %w", runnerErrors.ErrNotFound)
|
||||
}
|
||||
return Instance{}, errors.Wrap(q.Error, "fetching instance by name")
|
||||
return Instance{}, fmt.Errorf("error fetching instance by name: %w", q.Error)
|
||||
}
|
||||
return instance, nil
|
||||
}
|
||||
|
||||
func (s *sqlDatabase) GetPoolInstanceByName(_ context.Context, poolID string, instanceName string) (params.Instance, error) {
|
||||
instance, err := s.getPoolInstanceByName(poolID, instanceName)
|
||||
func (s *sqlDatabase) GetInstance(ctx context.Context, instanceName string) (params.Instance, error) {
|
||||
instance, err := s.getInstance(ctx, instanceName, "StatusMessages", "Pool", "ScaleSet")
|
||||
if err != nil {
|
||||
return params.Instance{}, errors.Wrap(err, "fetching instance")
|
||||
}
|
||||
|
||||
return s.sqlToParamsInstance(instance)
|
||||
}
|
||||
|
||||
func (s *sqlDatabase) GetInstanceByName(ctx context.Context, instanceName string) (params.Instance, error) {
|
||||
instance, err := s.getInstanceByName(ctx, instanceName, "StatusMessages", "Pool", "ScaleSet")
|
||||
if err != nil {
|
||||
return params.Instance{}, errors.Wrap(err, "fetching instance")
|
||||
return params.Instance{}, fmt.Errorf("error fetching instance: %w", err)
|
||||
}
|
||||
|
||||
return s.sqlToParamsInstance(instance)
|
||||
|
|
@ -150,7 +149,7 @@ func (s *sqlDatabase) DeleteInstance(_ context.Context, poolID string, instanceN
|
|||
if errors.Is(err, runnerErrors.ErrNotFound) {
|
||||
return nil
|
||||
}
|
||||
return errors.Wrap(err, "deleting instance")
|
||||
return fmt.Errorf("error deleting instance: %w", err)
|
||||
}
|
||||
|
||||
defer func() {
|
||||
|
|
@ -182,18 +181,18 @@ func (s *sqlDatabase) DeleteInstance(_ context.Context, poolID string, instanceN
|
|||
if errors.Is(q.Error, gorm.ErrRecordNotFound) {
|
||||
return nil
|
||||
}
|
||||
return errors.Wrap(q.Error, "deleting instance")
|
||||
return fmt.Errorf("error deleting instance: %w", q.Error)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *sqlDatabase) DeleteInstanceByName(ctx context.Context, instanceName string) error {
|
||||
instance, err := s.getInstanceByName(ctx, instanceName, "Pool", "ScaleSet")
|
||||
instance, err := s.getInstance(ctx, instanceName, "Pool", "ScaleSet")
|
||||
if err != nil {
|
||||
if errors.Is(err, runnerErrors.ErrNotFound) {
|
||||
return nil
|
||||
}
|
||||
return errors.Wrap(err, "deleting instance")
|
||||
return fmt.Errorf("error deleting instance: %w", err)
|
||||
}
|
||||
|
||||
defer func() {
|
||||
|
|
@ -224,15 +223,15 @@ func (s *sqlDatabase) DeleteInstanceByName(ctx context.Context, instanceName str
|
|||
if errors.Is(q.Error, gorm.ErrRecordNotFound) {
|
||||
return nil
|
||||
}
|
||||
return errors.Wrap(q.Error, "deleting instance")
|
||||
return fmt.Errorf("error deleting instance: %w", q.Error)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *sqlDatabase) AddInstanceEvent(ctx context.Context, instanceName string, event params.EventType, eventLevel params.EventLevel, statusMessage string) error {
|
||||
instance, err := s.getInstanceByName(ctx, instanceName)
|
||||
instance, err := s.getInstance(ctx, instanceName)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "updating instance")
|
||||
return fmt.Errorf("error updating instance: %w", err)
|
||||
}
|
||||
|
||||
msg := InstanceStatusUpdate{
|
||||
|
|
@ -242,15 +241,15 @@ func (s *sqlDatabase) AddInstanceEvent(ctx context.Context, instanceName string,
|
|||
}
|
||||
|
||||
if err := s.conn.Model(&instance).Association("StatusMessages").Append(&msg); err != nil {
|
||||
return errors.Wrap(err, "adding status message")
|
||||
return fmt.Errorf("error adding status message: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *sqlDatabase) UpdateInstance(ctx context.Context, instanceName string, param params.UpdateInstanceParams) (params.Instance, error) {
|
||||
instance, err := s.getInstanceByName(ctx, instanceName, "Pool", "ScaleSet")
|
||||
instance, err := s.getInstance(ctx, instanceName, "Pool", "ScaleSet")
|
||||
if err != nil {
|
||||
return params.Instance{}, errors.Wrap(err, "updating instance")
|
||||
return params.Instance{}, fmt.Errorf("error updating instance: %w", err)
|
||||
}
|
||||
|
||||
if param.AgentID != 0 {
|
||||
|
|
@ -287,7 +286,7 @@ func (s *sqlDatabase) UpdateInstance(ctx context.Context, instanceName string, p
|
|||
if param.JitConfiguration != nil {
|
||||
secret, err := s.marshalAndSeal(param.JitConfiguration)
|
||||
if err != nil {
|
||||
return params.Instance{}, errors.Wrap(err, "marshalling jit config")
|
||||
return params.Instance{}, fmt.Errorf("error marshalling jit config: %w", err)
|
||||
}
|
||||
instance.JitConfiguration = secret
|
||||
}
|
||||
|
|
@ -296,7 +295,7 @@ func (s *sqlDatabase) UpdateInstance(ctx context.Context, instanceName string, p
|
|||
|
||||
q := s.conn.Save(&instance)
|
||||
if q.Error != nil {
|
||||
return params.Instance{}, errors.Wrap(q.Error, "updating instance")
|
||||
return params.Instance{}, fmt.Errorf("error updating instance: %w", q.Error)
|
||||
}
|
||||
|
||||
if len(param.Addresses) > 0 {
|
||||
|
|
@ -308,12 +307,12 @@ func (s *sqlDatabase) UpdateInstance(ctx context.Context, instanceName string, p
|
|||
})
|
||||
}
|
||||
if err := s.conn.Model(&instance).Association("Addresses").Replace(addrs); err != nil {
|
||||
return params.Instance{}, errors.Wrap(err, "updating addresses")
|
||||
return params.Instance{}, fmt.Errorf("error updating addresses: %w", err)
|
||||
}
|
||||
}
|
||||
inst, err := s.sqlToParamsInstance(instance)
|
||||
if err != nil {
|
||||
return params.Instance{}, errors.Wrap(err, "converting instance")
|
||||
return params.Instance{}, fmt.Errorf("error converting instance: %w", err)
|
||||
}
|
||||
s.sendNotify(common.InstanceEntityType, common.UpdateOperation, inst)
|
||||
return inst, nil
|
||||
|
|
@ -322,21 +321,24 @@ func (s *sqlDatabase) UpdateInstance(ctx context.Context, instanceName string, p
|
|||
func (s *sqlDatabase) ListPoolInstances(_ context.Context, poolID string) ([]params.Instance, error) {
|
||||
u, err := uuid.Parse(poolID)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(runnerErrors.ErrBadRequest, "parsing id")
|
||||
return nil, fmt.Errorf("error parsing id: %w", runnerErrors.ErrBadRequest)
|
||||
}
|
||||
|
||||
var instances []Instance
|
||||
query := s.conn.Model(&Instance{}).Preload("Job").Where("pool_id = ?", u)
|
||||
query := s.conn.
|
||||
Preload("Pool").
|
||||
Preload("Job").
|
||||
Where("pool_id = ?", u)
|
||||
|
||||
if err := query.Find(&instances); err.Error != nil {
|
||||
return nil, errors.Wrap(err.Error, "fetching instances")
|
||||
return nil, fmt.Errorf("error fetching instances: %w", err.Error)
|
||||
}
|
||||
|
||||
ret := make([]params.Instance, len(instances))
|
||||
for idx, inst := range instances {
|
||||
ret[idx], err = s.sqlToParamsInstance(inst)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "converting instance")
|
||||
return nil, fmt.Errorf("error converting instance: %w", err)
|
||||
}
|
||||
}
|
||||
return ret, nil
|
||||
|
|
@ -345,16 +347,20 @@ func (s *sqlDatabase) ListPoolInstances(_ context.Context, poolID string) ([]par
|
|||
func (s *sqlDatabase) ListAllInstances(_ context.Context) ([]params.Instance, error) {
|
||||
var instances []Instance
|
||||
|
||||
q := s.conn.Model(&Instance{}).Preload("Job").Find(&instances)
|
||||
q := s.conn.
|
||||
Preload("Pool").
|
||||
Preload("ScaleSet").
|
||||
Preload("Job").
|
||||
Find(&instances)
|
||||
if q.Error != nil {
|
||||
return nil, errors.Wrap(q.Error, "fetching instances")
|
||||
return nil, fmt.Errorf("error fetching instances: %w", q.Error)
|
||||
}
|
||||
ret := make([]params.Instance, len(instances))
|
||||
var err error
|
||||
for idx, instance := range instances {
|
||||
ret[idx], err = s.sqlToParamsInstance(instance)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "converting instance")
|
||||
return nil, fmt.Errorf("error converting instance: %w", err)
|
||||
}
|
||||
}
|
||||
return ret, nil
|
||||
|
|
@ -363,13 +369,13 @@ func (s *sqlDatabase) ListAllInstances(_ context.Context) ([]params.Instance, er
|
|||
func (s *sqlDatabase) PoolInstanceCount(_ context.Context, poolID string) (int64, error) {
|
||||
pool, err := s.getPoolByID(s.conn, poolID)
|
||||
if err != nil {
|
||||
return 0, errors.Wrap(err, "fetching pool")
|
||||
return 0, fmt.Errorf("error fetching pool: %w", err)
|
||||
}
|
||||
|
||||
var cnt int64
|
||||
q := s.conn.Model(&Instance{}).Where("pool_id = ?", pool.ID).Count(&cnt)
|
||||
if q.Error != nil {
|
||||
return 0, errors.Wrap(q.Error, "fetching instance count")
|
||||
return 0, fmt.Errorf("error fetching instance count: %w", q.Error)
|
||||
}
|
||||
return cnt, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -196,7 +196,7 @@ func (s *InstancesTestSuite) TestCreateInstance() {
|
|||
|
||||
// assertions
|
||||
s.Require().Nil(err)
|
||||
storeInstance, err := s.Store.GetInstanceByName(s.adminCtx, s.Fixtures.CreateInstanceParams.Name)
|
||||
storeInstance, err := s.Store.GetInstance(s.adminCtx, s.Fixtures.CreateInstanceParams.Name)
|
||||
if err != nil {
|
||||
s.FailNow(fmt.Sprintf("failed to get instance: %v", err))
|
||||
}
|
||||
|
|
@ -210,7 +210,7 @@ func (s *InstancesTestSuite) TestCreateInstance() {
|
|||
func (s *InstancesTestSuite) TestCreateInstanceInvalidPoolID() {
|
||||
_, err := s.Store.CreateInstance(s.adminCtx, "dummy-pool-id", params.CreateInstanceParams{})
|
||||
|
||||
s.Require().Equal("fetching pool: parsing id: invalid request", err.Error())
|
||||
s.Require().Equal("error fetching pool: error parsing id: invalid request", err.Error())
|
||||
}
|
||||
|
||||
func (s *InstancesTestSuite) TestCreateInstanceDBCreateErr() {
|
||||
|
|
@ -233,32 +233,13 @@ func (s *InstancesTestSuite) TestCreateInstanceDBCreateErr() {
|
|||
|
||||
s.assertSQLMockExpectations()
|
||||
s.Require().NotNil(err)
|
||||
s.Require().Equal("creating instance: mocked insert instance error", err.Error())
|
||||
}
|
||||
|
||||
func (s *InstancesTestSuite) TestGetPoolInstanceByName() {
|
||||
storeInstance := s.Fixtures.Instances[0] // this is already created in `SetupTest()`
|
||||
|
||||
instance, err := s.Store.GetPoolInstanceByName(s.adminCtx, s.Fixtures.Pool.ID, storeInstance.Name)
|
||||
|
||||
s.Require().Nil(err)
|
||||
s.Require().Equal(storeInstance.Name, instance.Name)
|
||||
s.Require().Equal(storeInstance.PoolID, instance.PoolID)
|
||||
s.Require().Equal(storeInstance.OSArch, instance.OSArch)
|
||||
s.Require().Equal(storeInstance.OSType, instance.OSType)
|
||||
s.Require().Equal(storeInstance.CallbackURL, instance.CallbackURL)
|
||||
}
|
||||
|
||||
func (s *InstancesTestSuite) TestGetPoolInstanceByNameNotFound() {
|
||||
_, err := s.Store.GetPoolInstanceByName(s.adminCtx, s.Fixtures.Pool.ID, "not-existent-instance-name")
|
||||
|
||||
s.Require().Equal("fetching instance: fetching pool instance by name: not found", err.Error())
|
||||
s.Require().Equal("error creating instance: mocked insert instance error", err.Error())
|
||||
}
|
||||
|
||||
func (s *InstancesTestSuite) TestGetInstanceByName() {
|
||||
storeInstance := s.Fixtures.Instances[1]
|
||||
|
||||
instance, err := s.Store.GetInstanceByName(s.adminCtx, storeInstance.Name)
|
||||
instance, err := s.Store.GetInstance(s.adminCtx, storeInstance.Name)
|
||||
|
||||
s.Require().Nil(err)
|
||||
s.Require().Equal(storeInstance.Name, instance.Name)
|
||||
|
|
@ -269,9 +250,9 @@ func (s *InstancesTestSuite) TestGetInstanceByName() {
|
|||
}
|
||||
|
||||
func (s *InstancesTestSuite) TestGetInstanceByNameFetchInstanceFailed() {
|
||||
_, err := s.Store.GetInstanceByName(s.adminCtx, "not-existent-instance-name")
|
||||
_, err := s.Store.GetInstance(s.adminCtx, "not-existent-instance-name")
|
||||
|
||||
s.Require().Equal("fetching instance: fetching instance by name: not found", err.Error())
|
||||
s.Require().Equal("error fetching instance: error fetching instance by name: not found", err.Error())
|
||||
}
|
||||
|
||||
func (s *InstancesTestSuite) TestDeleteInstance() {
|
||||
|
|
@ -281,8 +262,8 @@ func (s *InstancesTestSuite) TestDeleteInstance() {
|
|||
|
||||
s.Require().Nil(err)
|
||||
|
||||
_, err = s.Store.GetPoolInstanceByName(s.adminCtx, s.Fixtures.Pool.ID, storeInstance.Name)
|
||||
s.Require().Equal("fetching instance: fetching pool instance by name: not found", err.Error())
|
||||
_, err = s.Store.GetInstance(s.adminCtx, storeInstance.Name)
|
||||
s.Require().Equal("error fetching instance: error fetching instance by name: not found", err.Error())
|
||||
|
||||
err = s.Store.DeleteInstance(s.adminCtx, s.Fixtures.Pool.ID, storeInstance.Name)
|
||||
s.Require().Nil(err)
|
||||
|
|
@ -295,8 +276,8 @@ func (s *InstancesTestSuite) TestDeleteInstanceByName() {
|
|||
|
||||
s.Require().Nil(err)
|
||||
|
||||
_, err = s.Store.GetPoolInstanceByName(s.adminCtx, s.Fixtures.Pool.ID, storeInstance.Name)
|
||||
s.Require().Equal("fetching instance: fetching pool instance by name: not found", err.Error())
|
||||
_, err = s.Store.GetInstance(s.adminCtx, storeInstance.Name)
|
||||
s.Require().Equal("error fetching instance: error fetching instance by name: not found", err.Error())
|
||||
|
||||
err = s.Store.DeleteInstanceByName(s.adminCtx, storeInstance.Name)
|
||||
s.Require().Nil(err)
|
||||
|
|
@ -305,7 +286,7 @@ func (s *InstancesTestSuite) TestDeleteInstanceByName() {
|
|||
func (s *InstancesTestSuite) TestDeleteInstanceInvalidPoolID() {
|
||||
err := s.Store.DeleteInstance(s.adminCtx, "dummy-pool-id", "dummy-instance-name")
|
||||
|
||||
s.Require().Equal("deleting instance: fetching pool: parsing id: invalid request", err.Error())
|
||||
s.Require().Equal("error deleting instance: error fetching pool: error parsing id: invalid request", err.Error())
|
||||
}
|
||||
|
||||
func (s *InstancesTestSuite) TestDeleteInstanceDBRecordNotFoundErr() {
|
||||
|
|
@ -380,7 +361,7 @@ func (s *InstancesTestSuite) TestDeleteInstanceDBDeleteErr() {
|
|||
|
||||
s.assertSQLMockExpectations()
|
||||
s.Require().NotNil(err)
|
||||
s.Require().Equal("deleting instance: mocked delete instance error", err.Error())
|
||||
s.Require().Equal("error deleting instance: mocked delete instance error", err.Error())
|
||||
}
|
||||
|
||||
func (s *InstancesTestSuite) TestAddInstanceEvent() {
|
||||
|
|
@ -390,7 +371,7 @@ func (s *InstancesTestSuite) TestAddInstanceEvent() {
|
|||
err := s.Store.AddInstanceEvent(s.adminCtx, storeInstance.Name, params.StatusEvent, params.EventInfo, statusMsg)
|
||||
|
||||
s.Require().Nil(err)
|
||||
instance, err := s.Store.GetInstanceByName(s.adminCtx, storeInstance.Name)
|
||||
instance, err := s.Store.GetInstance(s.adminCtx, storeInstance.Name)
|
||||
if err != nil {
|
||||
s.FailNow(fmt.Sprintf("failed to get db instance: %s", err))
|
||||
}
|
||||
|
|
@ -431,7 +412,7 @@ func (s *InstancesTestSuite) TestAddInstanceEventDBUpdateErr() {
|
|||
err := s.StoreSQLMocked.AddInstanceEvent(s.adminCtx, instance.Name, params.StatusEvent, params.EventInfo, statusMsg)
|
||||
|
||||
s.Require().NotNil(err)
|
||||
s.Require().Equal("adding status message: mocked add status message error", err.Error())
|
||||
s.Require().Equal("error adding status message: mocked add status message error", err.Error())
|
||||
s.assertSQLMockExpectations()
|
||||
}
|
||||
|
||||
|
|
@ -476,7 +457,7 @@ func (s *InstancesTestSuite) TestUpdateInstanceDBUpdateInstanceErr() {
|
|||
_, err := s.StoreSQLMocked.UpdateInstance(s.adminCtx, instance.Name, s.Fixtures.UpdateInstanceParams)
|
||||
|
||||
s.Require().NotNil(err)
|
||||
s.Require().Equal("updating instance: mocked update instance error", err.Error())
|
||||
s.Require().Equal("error updating instance: mocked update instance error", err.Error())
|
||||
s.assertSQLMockExpectations()
|
||||
}
|
||||
|
||||
|
|
@ -522,7 +503,7 @@ func (s *InstancesTestSuite) TestUpdateInstanceDBUpdateAddressErr() {
|
|||
_, err := s.StoreSQLMocked.UpdateInstance(s.adminCtx, instance.Name, s.Fixtures.UpdateInstanceParams)
|
||||
|
||||
s.Require().NotNil(err)
|
||||
s.Require().Equal("updating addresses: update addresses mock error", err.Error())
|
||||
s.Require().Equal("error updating addresses: update addresses mock error", err.Error())
|
||||
s.assertSQLMockExpectations()
|
||||
}
|
||||
|
||||
|
|
@ -536,7 +517,7 @@ func (s *InstancesTestSuite) TestListPoolInstances() {
|
|||
func (s *InstancesTestSuite) TestListPoolInstancesInvalidPoolID() {
|
||||
_, err := s.Store.ListPoolInstances(s.adminCtx, "dummy-pool-id")
|
||||
|
||||
s.Require().Equal("parsing id: invalid request", err.Error())
|
||||
s.Require().Equal("error parsing id: invalid request", err.Error())
|
||||
}
|
||||
|
||||
func (s *InstancesTestSuite) TestListAllInstances() {
|
||||
|
|
@ -555,7 +536,7 @@ func (s *InstancesTestSuite) TestListAllInstancesDBFetchErr() {
|
|||
|
||||
s.assertSQLMockExpectations()
|
||||
s.Require().NotNil(err)
|
||||
s.Require().Equal("fetching instances: fetch instances mock error", err.Error())
|
||||
s.Require().Equal("error fetching instances: fetch instances mock error", err.Error())
|
||||
}
|
||||
|
||||
func (s *InstancesTestSuite) TestPoolInstanceCount() {
|
||||
|
|
@ -568,7 +549,7 @@ func (s *InstancesTestSuite) TestPoolInstanceCount() {
|
|||
func (s *InstancesTestSuite) TestPoolInstanceCountInvalidPoolID() {
|
||||
_, err := s.Store.PoolInstanceCount(s.adminCtx, "dummy-pool-id")
|
||||
|
||||
s.Require().Equal("fetching pool: parsing id: invalid request", err.Error())
|
||||
s.Require().Equal("error fetching pool: error parsing id: invalid request", err.Error())
|
||||
}
|
||||
|
||||
func (s *InstancesTestSuite) TestPoolInstanceCountDBCountErr() {
|
||||
|
|
@ -587,7 +568,7 @@ func (s *InstancesTestSuite) TestPoolInstanceCountDBCountErr() {
|
|||
|
||||
s.assertSQLMockExpectations()
|
||||
s.Require().NotNil(err)
|
||||
s.Require().Equal("fetching instance count: count mock error", err.Error())
|
||||
s.Require().Equal("error fetching instance count: count mock error", err.Error())
|
||||
}
|
||||
|
||||
func TestInstTestSuite(t *testing.T) {
|
||||
|
|
|
|||
|
|
@ -17,10 +17,11 @@ package sql
|
|||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/pkg/errors"
|
||||
"gorm.io/gorm"
|
||||
"gorm.io/gorm/clause"
|
||||
|
||||
|
|
@ -35,12 +36,14 @@ func sqlWorkflowJobToParamsJob(job WorkflowJob) (params.Job, error) {
|
|||
labels := []string{}
|
||||
if job.Labels != nil {
|
||||
if err := json.Unmarshal(job.Labels, &labels); err != nil {
|
||||
return params.Job{}, errors.Wrap(err, "unmarshaling labels")
|
||||
return params.Job{}, fmt.Errorf("error unmarshaling labels: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
jobParam := params.Job{
|
||||
ID: job.ID,
|
||||
WorkflowJobID: job.WorkflowJobID,
|
||||
ScaleSetJobID: job.ScaleSetJobID,
|
||||
RunID: job.RunID,
|
||||
Action: job.Action,
|
||||
Status: job.Status,
|
||||
|
|
@ -71,11 +74,12 @@ func sqlWorkflowJobToParamsJob(job WorkflowJob) (params.Job, error) {
|
|||
func (s *sqlDatabase) paramsJobToWorkflowJob(ctx context.Context, job params.Job) (WorkflowJob, error) {
|
||||
asJSON, err := json.Marshal(job.Labels)
|
||||
if err != nil {
|
||||
return WorkflowJob{}, errors.Wrap(err, "marshaling labels")
|
||||
return WorkflowJob{}, fmt.Errorf("error marshaling labels: %w", err)
|
||||
}
|
||||
|
||||
workflofJob := WorkflowJob{
|
||||
ID: job.ID,
|
||||
ScaleSetJobID: job.ScaleSetJobID,
|
||||
WorkflowJobID: job.WorkflowJobID,
|
||||
RunID: job.RunID,
|
||||
Action: job.Action,
|
||||
Status: job.Status,
|
||||
|
|
@ -96,7 +100,7 @@ func (s *sqlDatabase) paramsJobToWorkflowJob(ctx context.Context, job params.Job
|
|||
}
|
||||
|
||||
if job.RunnerName != "" {
|
||||
instance, err := s.getInstanceByName(s.ctx, job.RunnerName)
|
||||
instance, err := s.getInstance(s.ctx, job.RunnerName)
|
||||
if err != nil {
|
||||
// This usually is very normal as not all jobs run on our runners.
|
||||
slog.DebugContext(ctx, "failed to get instance by name", "instance_name", job.RunnerName)
|
||||
|
|
@ -109,19 +113,32 @@ func (s *sqlDatabase) paramsJobToWorkflowJob(ctx context.Context, job params.Job
|
|||
}
|
||||
|
||||
func (s *sqlDatabase) DeleteJob(_ context.Context, jobID int64) (err error) {
|
||||
defer func() {
|
||||
if err == nil {
|
||||
if notifyErr := s.sendNotify(common.JobEntityType, common.DeleteOperation, params.Job{ID: jobID}); notifyErr != nil {
|
||||
slog.With(slog.Any("error", notifyErr)).Error("failed to send notify")
|
||||
}
|
||||
}
|
||||
}()
|
||||
q := s.conn.Delete(&WorkflowJob{}, jobID)
|
||||
var workflowJob WorkflowJob
|
||||
q := s.conn.Where("workflow_job_id = ?", jobID).Preload("Instance").First(&workflowJob)
|
||||
if q.Error != nil {
|
||||
if errors.Is(q.Error, gorm.ErrRecordNotFound) {
|
||||
return nil
|
||||
}
|
||||
return errors.Wrap(q.Error, "deleting job")
|
||||
return fmt.Errorf("error fetching job: %w", q.Error)
|
||||
}
|
||||
removedJob, err := sqlWorkflowJobToParamsJob(workflowJob)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error converting job: %w", err)
|
||||
}
|
||||
|
||||
defer func() {
|
||||
if err == nil {
|
||||
if notifyErr := s.sendNotify(common.JobEntityType, common.DeleteOperation, removedJob); notifyErr != nil {
|
||||
slog.With(slog.Any("error", notifyErr)).Error("failed to send notify")
|
||||
}
|
||||
}
|
||||
}()
|
||||
q = s.conn.Delete(&workflowJob)
|
||||
if q.Error != nil {
|
||||
if errors.Is(q.Error, gorm.ErrRecordNotFound) {
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("error deleting job: %w", q.Error)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
@ -129,16 +146,16 @@ func (s *sqlDatabase) DeleteJob(_ context.Context, jobID int64) (err error) {
|
|||
func (s *sqlDatabase) LockJob(_ context.Context, jobID int64, entityID string) error {
|
||||
entityUUID, err := uuid.Parse(entityID)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "parsing entity id")
|
||||
return fmt.Errorf("error parsing entity id: %w", err)
|
||||
}
|
||||
var workflowJob WorkflowJob
|
||||
q := s.conn.Clauses(clause.Locking{Strength: "UPDATE"}).Preload("Instance").Where("id = ?", jobID).First(&workflowJob)
|
||||
q := s.conn.Preload("Instance").Where("workflow_job_id = ?", jobID).First(&workflowJob)
|
||||
|
||||
if q.Error != nil {
|
||||
if errors.Is(q.Error, gorm.ErrRecordNotFound) {
|
||||
return runnerErrors.ErrNotFound
|
||||
}
|
||||
return errors.Wrap(q.Error, "fetching job")
|
||||
return fmt.Errorf("error fetching job: %w", q.Error)
|
||||
}
|
||||
|
||||
if workflowJob.LockedBy.String() == entityID {
|
||||
|
|
@ -153,12 +170,12 @@ func (s *sqlDatabase) LockJob(_ context.Context, jobID int64, entityID string) e
|
|||
workflowJob.LockedBy = entityUUID
|
||||
|
||||
if err := s.conn.Save(&workflowJob).Error; err != nil {
|
||||
return errors.Wrap(err, "saving job")
|
||||
return fmt.Errorf("error saving job: %w", err)
|
||||
}
|
||||
|
||||
asParams, err := sqlWorkflowJobToParamsJob(workflowJob)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "converting job")
|
||||
return fmt.Errorf("error converting job: %w", err)
|
||||
}
|
||||
s.sendNotify(common.JobEntityType, common.UpdateOperation, asParams)
|
||||
|
||||
|
|
@ -167,13 +184,13 @@ func (s *sqlDatabase) LockJob(_ context.Context, jobID int64, entityID string) e
|
|||
|
||||
func (s *sqlDatabase) BreakLockJobIsQueued(_ context.Context, jobID int64) (err error) {
|
||||
var workflowJob WorkflowJob
|
||||
q := s.conn.Clauses(clause.Locking{Strength: "UPDATE"}).Preload("Instance").Where("id = ? and status = ?", jobID, params.JobStatusQueued).First(&workflowJob)
|
||||
q := s.conn.Clauses(clause.Locking{Strength: "UPDATE"}).Preload("Instance").Where("workflow_job_id = ? and status = ?", jobID, params.JobStatusQueued).First(&workflowJob)
|
||||
|
||||
if q.Error != nil {
|
||||
if errors.Is(q.Error, gorm.ErrRecordNotFound) {
|
||||
return nil
|
||||
}
|
||||
return errors.Wrap(q.Error, "fetching job")
|
||||
return fmt.Errorf("error fetching job: %w", q.Error)
|
||||
}
|
||||
|
||||
if workflowJob.LockedBy == uuid.Nil {
|
||||
|
|
@ -183,11 +200,11 @@ func (s *sqlDatabase) BreakLockJobIsQueued(_ context.Context, jobID int64) (err
|
|||
|
||||
workflowJob.LockedBy = uuid.Nil
|
||||
if err := s.conn.Save(&workflowJob).Error; err != nil {
|
||||
return errors.Wrap(err, "saving job")
|
||||
return fmt.Errorf("error saving job: %w", err)
|
||||
}
|
||||
asParams, err := sqlWorkflowJobToParamsJob(workflowJob)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "converting job")
|
||||
return fmt.Errorf("error converting job: %w", err)
|
||||
}
|
||||
s.sendNotify(common.JobEntityType, common.UpdateOperation, asParams)
|
||||
return nil
|
||||
|
|
@ -195,13 +212,13 @@ func (s *sqlDatabase) BreakLockJobIsQueued(_ context.Context, jobID int64) (err
|
|||
|
||||
func (s *sqlDatabase) UnlockJob(_ context.Context, jobID int64, entityID string) error {
|
||||
var workflowJob WorkflowJob
|
||||
q := s.conn.Clauses(clause.Locking{Strength: "UPDATE"}).Where("id = ?", jobID).First(&workflowJob)
|
||||
q := s.conn.Clauses(clause.Locking{Strength: "UPDATE"}).Where("workflow_job_id = ?", jobID).First(&workflowJob)
|
||||
|
||||
if q.Error != nil {
|
||||
if errors.Is(q.Error, gorm.ErrRecordNotFound) {
|
||||
return runnerErrors.ErrNotFound
|
||||
}
|
||||
return errors.Wrap(q.Error, "fetching job")
|
||||
return fmt.Errorf("error fetching job: %w", q.Error)
|
||||
}
|
||||
|
||||
if workflowJob.LockedBy == uuid.Nil {
|
||||
|
|
@ -215,12 +232,12 @@ func (s *sqlDatabase) UnlockJob(_ context.Context, jobID int64, entityID string)
|
|||
|
||||
workflowJob.LockedBy = uuid.Nil
|
||||
if err := s.conn.Save(&workflowJob).Error; err != nil {
|
||||
return errors.Wrap(err, "saving job")
|
||||
return fmt.Errorf("error saving job: %w", err)
|
||||
}
|
||||
|
||||
asParams, err := sqlWorkflowJobToParamsJob(workflowJob)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "converting job")
|
||||
return fmt.Errorf("error converting job: %w", err)
|
||||
}
|
||||
s.sendNotify(common.JobEntityType, common.UpdateOperation, asParams)
|
||||
return nil
|
||||
|
|
@ -229,11 +246,18 @@ func (s *sqlDatabase) UnlockJob(_ context.Context, jobID int64, entityID string)
|
|||
func (s *sqlDatabase) CreateOrUpdateJob(ctx context.Context, job params.Job) (params.Job, error) {
|
||||
var workflowJob WorkflowJob
|
||||
var err error
|
||||
q := s.conn.Clauses(clause.Locking{Strength: "UPDATE"}).Preload("Instance").Where("id = ?", job.ID).First(&workflowJob)
|
||||
|
||||
searchField := "workflow_job_id = ?"
|
||||
var searchVal any = job.WorkflowJobID
|
||||
if job.ScaleSetJobID != "" {
|
||||
searchField = "scale_set_job_id = ?"
|
||||
searchVal = job.ScaleSetJobID
|
||||
}
|
||||
q := s.conn.Preload("Instance").Where(searchField, searchVal).First(&workflowJob)
|
||||
|
||||
if q.Error != nil {
|
||||
if !errors.Is(q.Error, gorm.ErrRecordNotFound) {
|
||||
return params.Job{}, errors.Wrap(q.Error, "fetching job")
|
||||
return params.Job{}, fmt.Errorf("error fetching job: %w", q.Error)
|
||||
}
|
||||
}
|
||||
var operation common.OperationType
|
||||
|
|
@ -249,13 +273,16 @@ func (s *sqlDatabase) CreateOrUpdateJob(ctx context.Context, job params.Job) (pa
|
|||
workflowJob.GithubRunnerID = job.GithubRunnerID
|
||||
workflowJob.RunnerGroupID = job.RunnerGroupID
|
||||
workflowJob.RunnerGroupName = job.RunnerGroupName
|
||||
if job.RunID != 0 && workflowJob.RunID == 0 {
|
||||
workflowJob.RunID = job.RunID
|
||||
}
|
||||
|
||||
if job.LockedBy != uuid.Nil {
|
||||
workflowJob.LockedBy = job.LockedBy
|
||||
}
|
||||
|
||||
if job.RunnerName != "" {
|
||||
instance, err := s.getInstanceByName(ctx, job.RunnerName)
|
||||
instance, err := s.getInstance(ctx, job.RunnerName)
|
||||
if err == nil {
|
||||
workflowJob.InstanceID = &instance.ID
|
||||
} else {
|
||||
|
|
@ -276,23 +303,23 @@ func (s *sqlDatabase) CreateOrUpdateJob(ctx context.Context, job params.Job) (pa
|
|||
workflowJob.EnterpriseID = job.EnterpriseID
|
||||
}
|
||||
if err := s.conn.Save(&workflowJob).Error; err != nil {
|
||||
return params.Job{}, errors.Wrap(err, "saving job")
|
||||
return params.Job{}, fmt.Errorf("error saving job: %w", err)
|
||||
}
|
||||
} else {
|
||||
operation = common.CreateOperation
|
||||
|
||||
workflowJob, err = s.paramsJobToWorkflowJob(ctx, job)
|
||||
if err != nil {
|
||||
return params.Job{}, errors.Wrap(err, "converting job")
|
||||
return params.Job{}, fmt.Errorf("error converting job: %w", err)
|
||||
}
|
||||
if err := s.conn.Create(&workflowJob).Error; err != nil {
|
||||
return params.Job{}, errors.Wrap(err, "creating job")
|
||||
return params.Job{}, fmt.Errorf("error creating job: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
asParams, err := sqlWorkflowJobToParamsJob(workflowJob)
|
||||
if err != nil {
|
||||
return params.Job{}, errors.Wrap(err, "converting job")
|
||||
return params.Job{}, fmt.Errorf("error converting job: %w", err)
|
||||
}
|
||||
s.sendNotify(common.JobEntityType, operation, asParams)
|
||||
|
||||
|
|
@ -312,7 +339,7 @@ func (s *sqlDatabase) ListJobsByStatus(_ context.Context, status params.JobStatu
|
|||
for idx, job := range jobs {
|
||||
jobParam, err := sqlWorkflowJobToParamsJob(job)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "converting job")
|
||||
return nil, fmt.Errorf("error converting job: %w", err)
|
||||
}
|
||||
ret[idx] = jobParam
|
||||
}
|
||||
|
|
@ -327,7 +354,11 @@ func (s *sqlDatabase) ListEntityJobsByStatus(_ context.Context, entityType param
|
|||
}
|
||||
|
||||
var jobs []WorkflowJob
|
||||
query := s.conn.Model(&WorkflowJob{}).Preload("Instance").Where("status = ?", status)
|
||||
query := s.conn.
|
||||
Model(&WorkflowJob{}).
|
||||
Preload("Instance").
|
||||
Where("status = ?", status).
|
||||
Where("workflow_job_id > 0")
|
||||
|
||||
switch entityType {
|
||||
case params.ForgeEntityTypeOrganization:
|
||||
|
|
@ -349,7 +380,7 @@ func (s *sqlDatabase) ListEntityJobsByStatus(_ context.Context, entityType param
|
|||
for idx, job := range jobs {
|
||||
jobParam, err := sqlWorkflowJobToParamsJob(job)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "converting job")
|
||||
return nil, fmt.Errorf("error converting job: %w", err)
|
||||
}
|
||||
ret[idx] = jobParam
|
||||
}
|
||||
|
|
@ -371,7 +402,7 @@ func (s *sqlDatabase) ListAllJobs(_ context.Context) ([]params.Job, error) {
|
|||
for idx, job := range jobs {
|
||||
jobParam, err := sqlWorkflowJobToParamsJob(job)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "converting job")
|
||||
return nil, fmt.Errorf("error converting job: %w", err)
|
||||
}
|
||||
ret[idx] = jobParam
|
||||
}
|
||||
|
|
@ -381,7 +412,7 @@ func (s *sqlDatabase) ListAllJobs(_ context.Context) ([]params.Job, error) {
|
|||
// GetJobByID gets a job by id.
|
||||
func (s *sqlDatabase) GetJobByID(_ context.Context, jobID int64) (params.Job, error) {
|
||||
var job WorkflowJob
|
||||
query := s.conn.Model(&WorkflowJob{}).Preload("Instance").Where("id = ?", jobID)
|
||||
query := s.conn.Model(&WorkflowJob{}).Preload("Instance").Where("workflow_job_id = ?", jobID)
|
||||
|
||||
if err := query.First(&job); err.Error != nil {
|
||||
if errors.Is(err.Error, gorm.ErrRecordNotFound) {
|
||||
|
|
|
|||
|
|
@ -15,10 +15,10 @@
|
|||
package sql
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/pkg/errors"
|
||||
"gorm.io/datatypes"
|
||||
"gorm.io/gorm"
|
||||
|
||||
|
|
@ -40,7 +40,7 @@ func (b *Base) BeforeCreate(_ *gorm.DB) error {
|
|||
}
|
||||
newID, err := uuid.NewRandom()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "generating id")
|
||||
return fmt.Errorf("error generating id: %w", err)
|
||||
}
|
||||
b.ID = newID
|
||||
return nil
|
||||
|
|
@ -319,6 +319,12 @@ type User struct {
|
|||
type WorkflowJob struct {
|
||||
// ID is the ID of the job.
|
||||
ID int64 `gorm:"index"`
|
||||
|
||||
// WorkflowJobID is the ID of the workflow job.
|
||||
WorkflowJobID int64 `gorm:"index:workflow_job_id_idx"`
|
||||
// ScaleSetJobID is the job ID for a scaleset job.
|
||||
ScaleSetJobID string `gorm:"index:scaleset_job_id_idx"`
|
||||
|
||||
// RunID is the ID of the workflow run. A run may have multiple jobs.
|
||||
RunID int64
|
||||
// Action is the specific activity that triggered the event.
|
||||
|
|
|
|||
|
|
@ -16,11 +16,11 @@ package sql
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/pkg/errors"
|
||||
"gorm.io/gorm"
|
||||
|
||||
runnerErrors "github.com/cloudbase/garm-provider-common/errors"
|
||||
|
|
@ -35,7 +35,7 @@ func (s *sqlDatabase) CreateOrganization(ctx context.Context, name string, crede
|
|||
}
|
||||
secret, err := util.Seal([]byte(webhookSecret), []byte(s.cfg.Passphrase))
|
||||
if err != nil {
|
||||
return params.Organization{}, errors.Wrap(err, "encoding secret")
|
||||
return params.Organization{}, fmt.Errorf("error encoding secret: %w", err)
|
||||
}
|
||||
|
||||
defer func() {
|
||||
|
|
@ -56,23 +56,23 @@ func (s *sqlDatabase) CreateOrganization(ctx context.Context, name string, crede
|
|||
case params.GiteaEndpointType:
|
||||
newOrg.GiteaCredentialsID = &credentials.ID
|
||||
default:
|
||||
return errors.Wrap(runnerErrors.ErrBadRequest, "unsupported credentials type")
|
||||
return fmt.Errorf("unsupported credentials type: %w", runnerErrors.ErrBadRequest)
|
||||
}
|
||||
|
||||
newOrg.EndpointName = &credentials.Endpoint.Name
|
||||
q := tx.Create(&newOrg)
|
||||
if q.Error != nil {
|
||||
return errors.Wrap(q.Error, "creating org")
|
||||
return fmt.Errorf("error creating org: %w", q.Error)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return params.Organization{}, errors.Wrap(err, "creating org")
|
||||
return params.Organization{}, fmt.Errorf("error creating org: %w", err)
|
||||
}
|
||||
|
||||
ret, err := s.GetOrganizationByID(ctx, newOrg.ID.String())
|
||||
if err != nil {
|
||||
return params.Organization{}, errors.Wrap(err, "creating org")
|
||||
return params.Organization{}, fmt.Errorf("error creating org: %w", err)
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
|
|
@ -81,12 +81,12 @@ func (s *sqlDatabase) CreateOrganization(ctx context.Context, name string, crede
|
|||
func (s *sqlDatabase) GetOrganization(ctx context.Context, name, endpointName string) (params.Organization, error) {
|
||||
org, err := s.getOrg(ctx, name, endpointName)
|
||||
if err != nil {
|
||||
return params.Organization{}, errors.Wrap(err, "fetching org")
|
||||
return params.Organization{}, fmt.Errorf("error fetching org: %w", err)
|
||||
}
|
||||
|
||||
param, err := s.sqlToCommonOrganization(org, true)
|
||||
if err != nil {
|
||||
return params.Organization{}, errors.Wrap(err, "fetching org")
|
||||
return params.Organization{}, fmt.Errorf("error fetching org: %w", err)
|
||||
}
|
||||
|
||||
return param, nil
|
||||
|
|
@ -110,7 +110,7 @@ func (s *sqlDatabase) ListOrganizations(_ context.Context, filter params.Organiz
|
|||
}
|
||||
q = q.Find(&orgs)
|
||||
if q.Error != nil {
|
||||
return []params.Organization{}, errors.Wrap(q.Error, "fetching org from database")
|
||||
return []params.Organization{}, fmt.Errorf("error fetching org from database: %w", q.Error)
|
||||
}
|
||||
|
||||
ret := make([]params.Organization, len(orgs))
|
||||
|
|
@ -118,7 +118,7 @@ func (s *sqlDatabase) ListOrganizations(_ context.Context, filter params.Organiz
|
|||
var err error
|
||||
ret[idx], err = s.sqlToCommonOrganization(val, true)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "fetching org")
|
||||
return nil, fmt.Errorf("error fetching org: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -128,7 +128,7 @@ func (s *sqlDatabase) ListOrganizations(_ context.Context, filter params.Organiz
|
|||
func (s *sqlDatabase) DeleteOrganization(ctx context.Context, orgID string) (err error) {
|
||||
org, err := s.getOrgByID(ctx, s.conn, orgID, "Endpoint", "Credentials", "Credentials.Endpoint", "GiteaCredentials", "GiteaCredentials.Endpoint")
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "fetching org")
|
||||
return fmt.Errorf("error fetching org: %w", err)
|
||||
}
|
||||
|
||||
defer func(org Organization) {
|
||||
|
|
@ -144,7 +144,7 @@ func (s *sqlDatabase) DeleteOrganization(ctx context.Context, orgID string) (err
|
|||
|
||||
q := s.conn.Unscoped().Delete(&org)
|
||||
if q.Error != nil && !errors.Is(q.Error, gorm.ErrRecordNotFound) {
|
||||
return errors.Wrap(q.Error, "deleting org")
|
||||
return fmt.Errorf("error deleting org: %w", q.Error)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
|
@ -162,23 +162,23 @@ func (s *sqlDatabase) UpdateOrganization(ctx context.Context, orgID string, para
|
|||
var err error
|
||||
org, err = s.getOrgByID(ctx, tx, orgID)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "fetching org")
|
||||
return fmt.Errorf("error fetching org: %w", err)
|
||||
}
|
||||
if org.EndpointName == nil {
|
||||
return errors.Wrap(runnerErrors.ErrUnprocessable, "org has no endpoint")
|
||||
return fmt.Errorf("error org has no endpoint: %w", runnerErrors.ErrUnprocessable)
|
||||
}
|
||||
|
||||
if param.CredentialsName != "" {
|
||||
creds, err = s.getGithubCredentialsByName(ctx, tx, param.CredentialsName, false)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "fetching credentials")
|
||||
return fmt.Errorf("error fetching credentials: %w", err)
|
||||
}
|
||||
if creds.EndpointName == nil {
|
||||
return errors.Wrap(runnerErrors.ErrUnprocessable, "credentials have no endpoint")
|
||||
return fmt.Errorf("error credentials have no endpoint: %w", runnerErrors.ErrUnprocessable)
|
||||
}
|
||||
|
||||
if *creds.EndpointName != *org.EndpointName {
|
||||
return errors.Wrap(runnerErrors.ErrBadRequest, "endpoint mismatch")
|
||||
return fmt.Errorf("error endpoint mismatch: %w", runnerErrors.ErrBadRequest)
|
||||
}
|
||||
org.CredentialsID = &creds.ID
|
||||
}
|
||||
|
|
@ -197,22 +197,22 @@ func (s *sqlDatabase) UpdateOrganization(ctx context.Context, orgID string, para
|
|||
|
||||
q := tx.Save(&org)
|
||||
if q.Error != nil {
|
||||
return errors.Wrap(q.Error, "saving org")
|
||||
return fmt.Errorf("error saving org: %w", q.Error)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return params.Organization{}, errors.Wrap(err, "saving org")
|
||||
return params.Organization{}, fmt.Errorf("error saving org: %w", err)
|
||||
}
|
||||
|
||||
org, err = s.getOrgByID(ctx, s.conn, orgID, "Endpoint", "Credentials", "Credentials.Endpoint", "GiteaCredentials", "GiteaCredentials.Endpoint")
|
||||
if err != nil {
|
||||
return params.Organization{}, errors.Wrap(err, "updating enterprise")
|
||||
return params.Organization{}, fmt.Errorf("error updating enterprise: %w", err)
|
||||
}
|
||||
paramOrg, err = s.sqlToCommonOrganization(org, true)
|
||||
if err != nil {
|
||||
return params.Organization{}, errors.Wrap(err, "saving org")
|
||||
return params.Organization{}, fmt.Errorf("error saving org: %w", err)
|
||||
}
|
||||
return paramOrg, nil
|
||||
}
|
||||
|
|
@ -229,12 +229,12 @@ func (s *sqlDatabase) GetOrganizationByID(ctx context.Context, orgID string) (pa
|
|||
}
|
||||
org, err := s.getOrgByID(ctx, s.conn, orgID, preloadList...)
|
||||
if err != nil {
|
||||
return params.Organization{}, errors.Wrap(err, "fetching org")
|
||||
return params.Organization{}, fmt.Errorf("error fetching org: %w", err)
|
||||
}
|
||||
|
||||
param, err := s.sqlToCommonOrganization(org, true)
|
||||
if err != nil {
|
||||
return params.Organization{}, errors.Wrap(err, "fetching org")
|
||||
return params.Organization{}, fmt.Errorf("error fetching org: %w", err)
|
||||
}
|
||||
return param, nil
|
||||
}
|
||||
|
|
@ -242,7 +242,7 @@ func (s *sqlDatabase) GetOrganizationByID(ctx context.Context, orgID string) (pa
|
|||
func (s *sqlDatabase) getOrgByID(_ context.Context, db *gorm.DB, id string, preload ...string) (Organization, error) {
|
||||
u, err := uuid.Parse(id)
|
||||
if err != nil {
|
||||
return Organization{}, errors.Wrap(runnerErrors.ErrBadRequest, "parsing id")
|
||||
return Organization{}, fmt.Errorf("error parsing id: %w", runnerErrors.ErrBadRequest)
|
||||
}
|
||||
var org Organization
|
||||
|
||||
|
|
@ -258,7 +258,7 @@ func (s *sqlDatabase) getOrgByID(_ context.Context, db *gorm.DB, id string, prel
|
|||
if errors.Is(q.Error, gorm.ErrRecordNotFound) {
|
||||
return Organization{}, runnerErrors.ErrNotFound
|
||||
}
|
||||
return Organization{}, errors.Wrap(q.Error, "fetching org from database")
|
||||
return Organization{}, fmt.Errorf("error fetching org from database: %w", q.Error)
|
||||
}
|
||||
return org, nil
|
||||
}
|
||||
|
|
@ -277,7 +277,7 @@ func (s *sqlDatabase) getOrg(_ context.Context, name, endpointName string) (Orga
|
|||
if errors.Is(q.Error, gorm.ErrRecordNotFound) {
|
||||
return Organization{}, runnerErrors.ErrNotFound
|
||||
}
|
||||
return Organization{}, errors.Wrap(q.Error, "fetching org from database")
|
||||
return Organization{}, fmt.Errorf("error fetching org from database: %w", q.Error)
|
||||
}
|
||||
return org, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -251,7 +251,7 @@ func (s *OrgTestSuite) TestCreateOrganizationInvalidForgeType() {
|
|||
s.Fixtures.CreateOrgParams.WebhookSecret,
|
||||
params.PoolBalancerTypeRoundRobin)
|
||||
s.Require().NotNil(err)
|
||||
s.Require().Equal("creating org: unsupported credentials type: invalid request", err.Error())
|
||||
s.Require().Equal("error creating org: unsupported credentials type: invalid request", err.Error())
|
||||
}
|
||||
|
||||
func (s *OrgTestSuite) TestCreateOrganizationInvalidDBPassphrase() {
|
||||
|
|
@ -275,7 +275,7 @@ func (s *OrgTestSuite) TestCreateOrganizationInvalidDBPassphrase() {
|
|||
params.PoolBalancerTypeRoundRobin)
|
||||
|
||||
s.Require().NotNil(err)
|
||||
s.Require().Equal("encoding secret: invalid passphrase length (expected length 32 characters)", err.Error())
|
||||
s.Require().Equal("error encoding secret: invalid passphrase length (expected length 32 characters)", err.Error())
|
||||
}
|
||||
|
||||
func (s *OrgTestSuite) TestCreateOrganizationDBCreateErr() {
|
||||
|
|
@ -293,7 +293,7 @@ func (s *OrgTestSuite) TestCreateOrganizationDBCreateErr() {
|
|||
params.PoolBalancerTypeRoundRobin)
|
||||
|
||||
s.Require().NotNil(err)
|
||||
s.Require().Equal("creating org: creating org: creating org mock error", err.Error())
|
||||
s.Require().Equal("error creating org: error creating org: creating org mock error", err.Error())
|
||||
s.assertSQLMockExpectations()
|
||||
}
|
||||
|
||||
|
|
@ -316,7 +316,7 @@ func (s *OrgTestSuite) TestGetOrganizationNotFound() {
|
|||
_, err := s.Store.GetOrganization(s.adminCtx, "dummy-name", "github.com")
|
||||
|
||||
s.Require().NotNil(err)
|
||||
s.Require().Equal("fetching org: not found", err.Error())
|
||||
s.Require().Equal("error fetching org: not found", err.Error())
|
||||
}
|
||||
|
||||
func (s *OrgTestSuite) TestGetOrganizationDBDecryptingErr() {
|
||||
|
|
@ -328,7 +328,7 @@ func (s *OrgTestSuite) TestGetOrganizationDBDecryptingErr() {
|
|||
_, err := s.StoreSQLMocked.GetOrganization(s.adminCtx, s.Fixtures.Orgs[0].Name, s.Fixtures.Orgs[0].Endpoint.Name)
|
||||
|
||||
s.Require().NotNil(err)
|
||||
s.Require().Equal("fetching org: missing secret", err.Error())
|
||||
s.Require().Equal("error fetching org: missing secret", err.Error())
|
||||
s.assertSQLMockExpectations()
|
||||
}
|
||||
|
||||
|
|
@ -404,7 +404,7 @@ func (s *OrgTestSuite) TestListOrganizationsDBFetchErr() {
|
|||
|
||||
s.assertSQLMockExpectations()
|
||||
s.Require().NotNil(err)
|
||||
s.Require().Equal("fetching org from database: fetching user from database mock error", err.Error())
|
||||
s.Require().Equal("error fetching org from database: fetching user from database mock error", err.Error())
|
||||
}
|
||||
|
||||
func (s *OrgTestSuite) TestDeleteOrganization() {
|
||||
|
|
@ -413,14 +413,14 @@ func (s *OrgTestSuite) TestDeleteOrganization() {
|
|||
s.Require().Nil(err)
|
||||
_, err = s.Store.GetOrganizationByID(s.adminCtx, s.Fixtures.Orgs[0].ID)
|
||||
s.Require().NotNil(err)
|
||||
s.Require().Equal("fetching org: not found", err.Error())
|
||||
s.Require().Equal("error fetching org: not found", err.Error())
|
||||
}
|
||||
|
||||
func (s *OrgTestSuite) TestDeleteOrganizationInvalidOrgID() {
|
||||
err := s.Store.DeleteOrganization(s.adminCtx, "dummy-org-id")
|
||||
|
||||
s.Require().NotNil(err)
|
||||
s.Require().Equal("fetching org: parsing id: invalid request", err.Error())
|
||||
s.Require().Equal("error fetching org: error parsing id: invalid request", err.Error())
|
||||
}
|
||||
|
||||
func (s *OrgTestSuite) TestDeleteOrganizationDBDeleteErr() {
|
||||
|
|
@ -439,7 +439,7 @@ func (s *OrgTestSuite) TestDeleteOrganizationDBDeleteErr() {
|
|||
|
||||
s.assertSQLMockExpectations()
|
||||
s.Require().NotNil(err)
|
||||
s.Require().Equal("deleting org: mocked delete org error", err.Error())
|
||||
s.Require().Equal("error deleting org: mocked delete org error", err.Error())
|
||||
}
|
||||
|
||||
func (s *OrgTestSuite) TestUpdateOrganization() {
|
||||
|
|
@ -454,7 +454,7 @@ func (s *OrgTestSuite) TestUpdateOrganizationInvalidOrgID() {
|
|||
_, err := s.Store.UpdateOrganization(s.adminCtx, "dummy-org-id", s.Fixtures.UpdateRepoParams)
|
||||
|
||||
s.Require().NotNil(err)
|
||||
s.Require().Equal("saving org: fetching org: parsing id: invalid request", err.Error())
|
||||
s.Require().Equal("error saving org: error fetching org: error parsing id: invalid request", err.Error())
|
||||
}
|
||||
|
||||
func (s *OrgTestSuite) TestUpdateOrganizationDBEncryptErr() {
|
||||
|
|
@ -479,7 +479,7 @@ func (s *OrgTestSuite) TestUpdateOrganizationDBEncryptErr() {
|
|||
_, err := s.StoreSQLMocked.UpdateOrganization(s.adminCtx, s.Fixtures.Orgs[0].ID, s.Fixtures.UpdateRepoParams)
|
||||
|
||||
s.Require().NotNil(err)
|
||||
s.Require().Equal("saving org: saving org: failed to encrypt string: invalid passphrase length (expected length 32 characters)", err.Error())
|
||||
s.Require().Equal("error saving org: saving org: failed to encrypt string: invalid passphrase length (expected length 32 characters)", err.Error())
|
||||
s.assertSQLMockExpectations()
|
||||
}
|
||||
|
||||
|
|
@ -507,7 +507,7 @@ func (s *OrgTestSuite) TestUpdateOrganizationDBSaveErr() {
|
|||
_, err := s.StoreSQLMocked.UpdateOrganization(s.adminCtx, s.Fixtures.Orgs[0].ID, s.Fixtures.UpdateRepoParams)
|
||||
|
||||
s.Require().NotNil(err)
|
||||
s.Require().Equal("saving org: saving org: saving org mock error", err.Error())
|
||||
s.Require().Equal("error saving org: error saving org: saving org mock error", err.Error())
|
||||
s.assertSQLMockExpectations()
|
||||
}
|
||||
|
||||
|
|
@ -535,7 +535,7 @@ func (s *OrgTestSuite) TestUpdateOrganizationDBDecryptingErr() {
|
|||
_, err := s.StoreSQLMocked.UpdateOrganization(s.adminCtx, s.Fixtures.Orgs[0].ID, s.Fixtures.UpdateRepoParams)
|
||||
|
||||
s.Require().NotNil(err)
|
||||
s.Require().Equal("saving org: saving org: failed to encrypt string: invalid passphrase length (expected length 32 characters)", err.Error())
|
||||
s.Require().Equal("error saving org: saving org: failed to encrypt string: invalid passphrase length (expected length 32 characters)", err.Error())
|
||||
s.assertSQLMockExpectations()
|
||||
}
|
||||
|
||||
|
|
@ -550,7 +550,7 @@ func (s *OrgTestSuite) TestGetOrganizationByIDInvalidOrgID() {
|
|||
_, err := s.Store.GetOrganizationByID(s.adminCtx, "dummy-org-id")
|
||||
|
||||
s.Require().NotNil(err)
|
||||
s.Require().Equal("fetching org: parsing id: invalid request", err.Error())
|
||||
s.Require().Equal("error fetching org: error parsing id: invalid request", err.Error())
|
||||
}
|
||||
|
||||
func (s *OrgTestSuite) TestGetOrganizationByIDDBDecryptingErr() {
|
||||
|
|
@ -571,7 +571,7 @@ func (s *OrgTestSuite) TestGetOrganizationByIDDBDecryptingErr() {
|
|||
|
||||
s.assertSQLMockExpectations()
|
||||
s.Require().NotNil(err)
|
||||
s.Require().Equal("fetching org: missing secret", err.Error())
|
||||
s.Require().Equal("error fetching org: missing secret", err.Error())
|
||||
}
|
||||
|
||||
func (s *OrgTestSuite) TestCreateOrganizationPool() {
|
||||
|
|
@ -610,7 +610,7 @@ func (s *OrgTestSuite) TestCreateOrganizationPoolInvalidOrgID() {
|
|||
_, err := s.Store.CreateEntityPool(s.adminCtx, entity, s.Fixtures.CreatePoolParams)
|
||||
|
||||
s.Require().NotNil(err)
|
||||
s.Require().Equal("parsing id: invalid request", err.Error())
|
||||
s.Require().Equal("error parsing id: invalid request", err.Error())
|
||||
}
|
||||
|
||||
func (s *OrgTestSuite) TestCreateOrganizationPoolDBFetchTagErr() {
|
||||
|
|
@ -628,7 +628,7 @@ func (s *OrgTestSuite) TestCreateOrganizationPoolDBFetchTagErr() {
|
|||
_, err = s.StoreSQLMocked.CreateEntityPool(s.adminCtx, entity, s.Fixtures.CreatePoolParams)
|
||||
|
||||
s.Require().NotNil(err)
|
||||
s.Require().Equal("creating tag: fetching tag from database: mocked fetching tag error", err.Error())
|
||||
s.Require().Equal("error creating tag: error fetching tag from database: mocked fetching tag error", err.Error())
|
||||
s.assertSQLMockExpectations()
|
||||
}
|
||||
|
||||
|
|
@ -656,7 +656,7 @@ func (s *OrgTestSuite) TestCreateOrganizationPoolDBAddingPoolErr() {
|
|||
_, err = s.StoreSQLMocked.CreateEntityPool(s.adminCtx, entity, s.Fixtures.CreatePoolParams)
|
||||
|
||||
s.Require().NotNil(err)
|
||||
s.Require().Equal("creating pool: mocked adding pool error", err.Error())
|
||||
s.Require().Equal("error creating pool: mocked adding pool error", err.Error())
|
||||
s.assertSQLMockExpectations()
|
||||
}
|
||||
|
||||
|
|
@ -687,7 +687,7 @@ func (s *OrgTestSuite) TestCreateOrganizationPoolDBSaveTagErr() {
|
|||
_, err = s.StoreSQLMocked.CreateEntityPool(s.adminCtx, entity, s.Fixtures.CreatePoolParams)
|
||||
|
||||
s.Require().NotNil(err)
|
||||
s.Require().Equal("associating tags: mocked saving tag error", err.Error())
|
||||
s.Require().Equal("error associating tags: mocked saving tag error", err.Error())
|
||||
s.assertSQLMockExpectations()
|
||||
}
|
||||
|
||||
|
|
@ -728,7 +728,7 @@ func (s *OrgTestSuite) TestCreateOrganizationPoolDBFetchPoolErr() {
|
|||
_, err = s.StoreSQLMocked.CreateEntityPool(s.adminCtx, entity, s.Fixtures.CreatePoolParams)
|
||||
|
||||
s.Require().NotNil(err)
|
||||
s.Require().Equal("fetching pool: not found", err.Error())
|
||||
s.Require().Equal("error fetching pool by ID: not found", err.Error())
|
||||
s.assertSQLMockExpectations()
|
||||
}
|
||||
|
||||
|
|
@ -758,7 +758,7 @@ func (s *OrgTestSuite) TestListOrgPoolsInvalidOrgID() {
|
|||
_, err := s.Store.ListEntityPools(s.adminCtx, entity)
|
||||
|
||||
s.Require().NotNil(err)
|
||||
s.Require().Equal("fetching pools: parsing id: invalid request", err.Error())
|
||||
s.Require().Equal("error fetching pools: error parsing id: invalid request", err.Error())
|
||||
}
|
||||
|
||||
func (s *OrgTestSuite) TestGetOrganizationPool() {
|
||||
|
|
@ -783,7 +783,7 @@ func (s *OrgTestSuite) TestGetOrganizationPoolInvalidOrgID() {
|
|||
_, err := s.Store.GetEntityPool(s.adminCtx, entity, "dummy-pool-id")
|
||||
|
||||
s.Require().NotNil(err)
|
||||
s.Require().Equal("fetching pool: parsing id: invalid request", err.Error())
|
||||
s.Require().Equal("fetching pool: error parsing id: invalid request", err.Error())
|
||||
}
|
||||
|
||||
func (s *OrgTestSuite) TestDeleteOrganizationPool() {
|
||||
|
|
@ -798,7 +798,7 @@ func (s *OrgTestSuite) TestDeleteOrganizationPool() {
|
|||
|
||||
s.Require().Nil(err)
|
||||
_, err = s.Store.GetEntityPool(s.adminCtx, entity, pool.ID)
|
||||
s.Require().Equal("fetching pool: finding pool: not found", err.Error())
|
||||
s.Require().Equal("fetching pool: error finding pool: not found", err.Error())
|
||||
}
|
||||
|
||||
func (s *OrgTestSuite) TestDeleteOrganizationPoolInvalidOrgID() {
|
||||
|
|
@ -809,7 +809,7 @@ func (s *OrgTestSuite) TestDeleteOrganizationPoolInvalidOrgID() {
|
|||
err := s.Store.DeleteEntityPool(s.adminCtx, entity, "dummy-pool-id")
|
||||
|
||||
s.Require().NotNil(err)
|
||||
s.Require().Equal("parsing id: invalid request", err.Error())
|
||||
s.Require().Equal("error parsing id: invalid request", err.Error())
|
||||
}
|
||||
|
||||
func (s *OrgTestSuite) TestDeleteOrganizationPoolDBDeleteErr() {
|
||||
|
|
@ -831,7 +831,7 @@ func (s *OrgTestSuite) TestDeleteOrganizationPoolDBDeleteErr() {
|
|||
err = s.StoreSQLMocked.DeleteEntityPool(s.adminCtx, entity, pool.ID)
|
||||
|
||||
s.Require().NotNil(err)
|
||||
s.Require().Equal("removing pool: mocked deleting pool error", err.Error())
|
||||
s.Require().Equal("error removing pool: mocked deleting pool error", err.Error())
|
||||
s.assertSQLMockExpectations()
|
||||
}
|
||||
|
||||
|
|
@ -866,7 +866,7 @@ func (s *OrgTestSuite) TestListOrgInstancesInvalidOrgID() {
|
|||
_, err := s.Store.ListEntityInstances(s.adminCtx, entity)
|
||||
|
||||
s.Require().NotNil(err)
|
||||
s.Require().Equal("fetching entity: parsing id: invalid request", err.Error())
|
||||
s.Require().Equal("error fetching entity: error parsing id: invalid request", err.Error())
|
||||
}
|
||||
|
||||
func (s *OrgTestSuite) TestUpdateOrganizationPool() {
|
||||
|
|
@ -916,7 +916,7 @@ func (s *OrgTestSuite) TestUpdateOrganizationPoolInvalidOrgID() {
|
|||
_, err := s.Store.UpdateEntityPool(s.adminCtx, entity, "dummy-pool-id", s.Fixtures.UpdatePoolParams)
|
||||
|
||||
s.Require().NotNil(err)
|
||||
s.Require().Equal("fetching pool: parsing id: invalid request", err.Error())
|
||||
s.Require().Equal("error fetching pool: error parsing id: invalid request", err.Error())
|
||||
}
|
||||
|
||||
func TestOrgTestSuite(t *testing.T) {
|
||||
|
|
|
|||
|
|
@ -16,10 +16,10 @@ package sql
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/pkg/errors"
|
||||
"gorm.io/datatypes"
|
||||
"gorm.io/gorm"
|
||||
|
||||
|
|
@ -37,7 +37,7 @@ const (
|
|||
func (s *sqlDatabase) ListAllPools(_ context.Context) ([]params.Pool, error) {
|
||||
var pools []Pool
|
||||
|
||||
q := s.conn.Model(&Pool{}).
|
||||
q := s.conn.
|
||||
Preload("Tags").
|
||||
Preload("Organization").
|
||||
Preload("Organization.Endpoint").
|
||||
|
|
@ -48,7 +48,7 @@ func (s *sqlDatabase) ListAllPools(_ context.Context) ([]params.Pool, error) {
|
|||
Omit("extra_specs").
|
||||
Find(&pools)
|
||||
if q.Error != nil {
|
||||
return nil, errors.Wrap(q.Error, "fetching all pools")
|
||||
return nil, fmt.Errorf("error fetching all pools: %w", q.Error)
|
||||
}
|
||||
|
||||
ret := make([]params.Pool, len(pools))
|
||||
|
|
@ -56,7 +56,7 @@ func (s *sqlDatabase) ListAllPools(_ context.Context) ([]params.Pool, error) {
|
|||
for idx, val := range pools {
|
||||
ret[idx], err = s.sqlToCommonPool(val)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "converting pool")
|
||||
return nil, fmt.Errorf("error converting pool: %w", err)
|
||||
}
|
||||
}
|
||||
return ret, nil
|
||||
|
|
@ -75,7 +75,7 @@ func (s *sqlDatabase) GetPoolByID(_ context.Context, poolID string) (params.Pool
|
|||
}
|
||||
pool, err := s.getPoolByID(s.conn, poolID, preloadList...)
|
||||
if err != nil {
|
||||
return params.Pool{}, errors.Wrap(err, "fetching pool by ID")
|
||||
return params.Pool{}, fmt.Errorf("error fetching pool by ID: %w", err)
|
||||
}
|
||||
return s.sqlToCommonPool(pool)
|
||||
}
|
||||
|
|
@ -83,7 +83,7 @@ func (s *sqlDatabase) GetPoolByID(_ context.Context, poolID string) (params.Pool
|
|||
func (s *sqlDatabase) DeletePoolByID(_ context.Context, poolID string) (err error) {
|
||||
pool, err := s.getPoolByID(s.conn, poolID)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "fetching pool by ID")
|
||||
return fmt.Errorf("error fetching pool by ID: %w", err)
|
||||
}
|
||||
|
||||
defer func() {
|
||||
|
|
@ -93,7 +93,7 @@ func (s *sqlDatabase) DeletePoolByID(_ context.Context, poolID string) (err erro
|
|||
}()
|
||||
|
||||
if q := s.conn.Unscoped().Delete(&pool); q.Error != nil {
|
||||
return errors.Wrap(q.Error, "removing pool")
|
||||
return fmt.Errorf("error removing pool: %w", q.Error)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
|
@ -101,12 +101,12 @@ func (s *sqlDatabase) DeletePoolByID(_ context.Context, poolID string) (err erro
|
|||
|
||||
func (s *sqlDatabase) getEntityPool(tx *gorm.DB, entityType params.ForgeEntityType, entityID, poolID string, preload ...string) (Pool, error) {
|
||||
if entityID == "" {
|
||||
return Pool{}, errors.Wrap(runnerErrors.ErrBadRequest, "missing entity id")
|
||||
return Pool{}, fmt.Errorf("error missing entity id: %w", runnerErrors.ErrBadRequest)
|
||||
}
|
||||
|
||||
u, err := uuid.Parse(poolID)
|
||||
if err != nil {
|
||||
return Pool{}, errors.Wrap(runnerErrors.ErrBadRequest, "parsing id")
|
||||
return Pool{}, fmt.Errorf("error parsing id: %w", runnerErrors.ErrBadRequest)
|
||||
}
|
||||
|
||||
var fieldName string
|
||||
|
|
@ -140,9 +140,9 @@ func (s *sqlDatabase) getEntityPool(tx *gorm.DB, entityType params.ForgeEntityTy
|
|||
First(&pool).Error
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return Pool{}, errors.Wrap(runnerErrors.ErrNotFound, "finding pool")
|
||||
return Pool{}, fmt.Errorf("error finding pool: %w", runnerErrors.ErrNotFound)
|
||||
}
|
||||
return Pool{}, errors.Wrap(err, "fetching pool")
|
||||
return Pool{}, fmt.Errorf("error fetching pool: %w", err)
|
||||
}
|
||||
|
||||
return pool, nil
|
||||
|
|
@ -150,11 +150,11 @@ func (s *sqlDatabase) getEntityPool(tx *gorm.DB, entityType params.ForgeEntityTy
|
|||
|
||||
func (s *sqlDatabase) listEntityPools(tx *gorm.DB, entityType params.ForgeEntityType, entityID string, preload ...string) ([]Pool, error) {
|
||||
if _, err := uuid.Parse(entityID); err != nil {
|
||||
return nil, errors.Wrap(runnerErrors.ErrBadRequest, "parsing id")
|
||||
return nil, fmt.Errorf("error parsing id: %w", runnerErrors.ErrBadRequest)
|
||||
}
|
||||
|
||||
if err := s.hasGithubEntity(tx, entityType, entityID); err != nil {
|
||||
return nil, errors.Wrap(err, "checking entity existence")
|
||||
return nil, fmt.Errorf("error checking entity existence: %w", err)
|
||||
}
|
||||
|
||||
var preloadEntity string
|
||||
|
|
@ -191,7 +191,7 @@ func (s *sqlDatabase) listEntityPools(tx *gorm.DB, entityType params.ForgeEntity
|
|||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return []Pool{}, nil
|
||||
}
|
||||
return nil, errors.Wrap(err, "fetching pool")
|
||||
return nil, fmt.Errorf("error fetching pool: %w", err)
|
||||
}
|
||||
|
||||
return pools, nil
|
||||
|
|
@ -203,7 +203,7 @@ func (s *sqlDatabase) findPoolByTags(id string, poolType params.ForgeEntityType,
|
|||
}
|
||||
u, err := uuid.Parse(id)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(runnerErrors.ErrBadRequest, "parsing id")
|
||||
return nil, fmt.Errorf("error parsing id: %w", runnerErrors.ErrBadRequest)
|
||||
}
|
||||
|
||||
var fieldName string
|
||||
|
|
@ -233,7 +233,7 @@ func (s *sqlDatabase) findPoolByTags(id string, poolType params.ForgeEntityType,
|
|||
if errors.Is(q.Error, gorm.ErrRecordNotFound) {
|
||||
return nil, runnerErrors.ErrNotFound
|
||||
}
|
||||
return nil, errors.Wrap(q.Error, "fetching pool")
|
||||
return nil, fmt.Errorf("error fetching pool: %w", q.Error)
|
||||
}
|
||||
|
||||
if len(pools) == 0 {
|
||||
|
|
@ -244,7 +244,7 @@ func (s *sqlDatabase) findPoolByTags(id string, poolType params.ForgeEntityType,
|
|||
for idx, val := range pools {
|
||||
ret[idx], err = s.sqlToCommonPool(val)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "converting pool")
|
||||
return nil, fmt.Errorf("error converting pool: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -261,13 +261,13 @@ func (s *sqlDatabase) FindPoolsMatchingAllTags(_ context.Context, entityType par
|
|||
if errors.Is(err, runnerErrors.ErrNotFound) {
|
||||
return []params.Pool{}, nil
|
||||
}
|
||||
return nil, errors.Wrap(err, "fetching pools")
|
||||
return nil, fmt.Errorf("error fetching pools: %w", err)
|
||||
}
|
||||
|
||||
return pools, nil
|
||||
}
|
||||
|
||||
func (s *sqlDatabase) CreateEntityPool(_ context.Context, entity params.ForgeEntity, param params.CreatePoolParams) (pool params.Pool, err error) {
|
||||
func (s *sqlDatabase) CreateEntityPool(ctx context.Context, entity params.ForgeEntity, param params.CreatePoolParams) (pool params.Pool, err error) {
|
||||
if len(param.Tags) == 0 {
|
||||
return params.Pool{}, runnerErrors.NewBadRequestError("no tags specified")
|
||||
}
|
||||
|
|
@ -298,7 +298,7 @@ func (s *sqlDatabase) CreateEntityPool(_ context.Context, entity params.ForgeEnt
|
|||
|
||||
entityID, err := uuid.Parse(entity.ID)
|
||||
if err != nil {
|
||||
return params.Pool{}, errors.Wrap(runnerErrors.ErrBadRequest, "parsing id")
|
||||
return params.Pool{}, fmt.Errorf("error parsing id: %w", runnerErrors.ErrBadRequest)
|
||||
}
|
||||
|
||||
switch entity.EntityType {
|
||||
|
|
@ -311,26 +311,26 @@ func (s *sqlDatabase) CreateEntityPool(_ context.Context, entity params.ForgeEnt
|
|||
}
|
||||
err = s.conn.Transaction(func(tx *gorm.DB) error {
|
||||
if err := s.hasGithubEntity(tx, entity.EntityType, entity.ID); err != nil {
|
||||
return errors.Wrap(err, "checking entity existence")
|
||||
return fmt.Errorf("error checking entity existence: %w", err)
|
||||
}
|
||||
|
||||
tags := []Tag{}
|
||||
for _, val := range param.Tags {
|
||||
t, err := s.getOrCreateTag(tx, val)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "creating tag")
|
||||
return fmt.Errorf("error creating tag: %w", err)
|
||||
}
|
||||
tags = append(tags, t)
|
||||
}
|
||||
|
||||
q := tx.Create(&newPool)
|
||||
if q.Error != nil {
|
||||
return errors.Wrap(q.Error, "creating pool")
|
||||
return fmt.Errorf("error creating pool: %w", q.Error)
|
||||
}
|
||||
|
||||
for i := range tags {
|
||||
if err := tx.Model(&newPool).Association("Tags").Append(&tags[i]); err != nil {
|
||||
return errors.Wrap(err, "associating tags")
|
||||
return fmt.Errorf("error associating tags: %w", err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
|
@ -339,16 +339,21 @@ func (s *sqlDatabase) CreateEntityPool(_ context.Context, entity params.ForgeEnt
|
|||
return params.Pool{}, err
|
||||
}
|
||||
|
||||
dbPool, err := s.getPoolByID(s.conn, newPool.ID.String(), "Tags", "Instances", "Enterprise", "Organization", "Repository")
|
||||
if err != nil {
|
||||
return params.Pool{}, errors.Wrap(err, "fetching pool")
|
||||
}
|
||||
|
||||
return s.sqlToCommonPool(dbPool)
|
||||
return s.GetPoolByID(ctx, newPool.ID.String())
|
||||
}
|
||||
|
||||
func (s *sqlDatabase) GetEntityPool(_ context.Context, entity params.ForgeEntity, poolID string) (params.Pool, error) {
|
||||
pool, err := s.getEntityPool(s.conn, entity.EntityType, entity.ID, poolID, "Tags", "Instances")
|
||||
preloadList := []string{
|
||||
"Tags",
|
||||
"Instances",
|
||||
"Enterprise",
|
||||
"Enterprise.Endpoint",
|
||||
"Organization",
|
||||
"Organization.Endpoint",
|
||||
"Repository",
|
||||
"Repository.Endpoint",
|
||||
}
|
||||
pool, err := s.getEntityPool(s.conn, entity.EntityType, entity.ID, poolID, preloadList...)
|
||||
if err != nil {
|
||||
return params.Pool{}, fmt.Errorf("fetching pool: %w", err)
|
||||
}
|
||||
|
|
@ -358,7 +363,7 @@ func (s *sqlDatabase) GetEntityPool(_ context.Context, entity params.ForgeEntity
|
|||
func (s *sqlDatabase) DeleteEntityPool(_ context.Context, entity params.ForgeEntity, poolID string) (err error) {
|
||||
entityID, err := uuid.Parse(entity.ID)
|
||||
if err != nil {
|
||||
return errors.Wrap(runnerErrors.ErrBadRequest, "parsing id")
|
||||
return fmt.Errorf("error parsing id: %w", runnerErrors.ErrBadRequest)
|
||||
}
|
||||
|
||||
defer func() {
|
||||
|
|
@ -372,7 +377,7 @@ func (s *sqlDatabase) DeleteEntityPool(_ context.Context, entity params.ForgeEnt
|
|||
|
||||
poolUUID, err := uuid.Parse(poolID)
|
||||
if err != nil {
|
||||
return errors.Wrap(runnerErrors.ErrBadRequest, "parsing pool id")
|
||||
return fmt.Errorf("error parsing pool id: %w", runnerErrors.ErrBadRequest)
|
||||
}
|
||||
var fieldName string
|
||||
switch entity.EntityType {
|
||||
|
|
@ -387,12 +392,12 @@ func (s *sqlDatabase) DeleteEntityPool(_ context.Context, entity params.ForgeEnt
|
|||
}
|
||||
condition := fmt.Sprintf("id = ? and %s = ?", fieldName)
|
||||
if err := s.conn.Unscoped().Where(condition, poolUUID, entityID).Delete(&Pool{}).Error; err != nil {
|
||||
return errors.Wrap(err, "removing pool")
|
||||
return fmt.Errorf("error removing pool: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *sqlDatabase) UpdateEntityPool(_ context.Context, entity params.ForgeEntity, poolID string, param params.UpdatePoolParams) (updatedPool params.Pool, err error) {
|
||||
func (s *sqlDatabase) UpdateEntityPool(ctx context.Context, entity params.ForgeEntity, poolID string, param params.UpdatePoolParams) (updatedPool params.Pool, err error) {
|
||||
defer func() {
|
||||
if err == nil {
|
||||
s.sendNotify(common.PoolEntityType, common.UpdateOperation, updatedPool)
|
||||
|
|
@ -401,32 +406,37 @@ func (s *sqlDatabase) UpdateEntityPool(_ context.Context, entity params.ForgeEnt
|
|||
err = s.conn.Transaction(func(tx *gorm.DB) error {
|
||||
pool, err := s.getEntityPool(tx, entity.EntityType, entity.ID, poolID, "Tags", "Instances")
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "fetching pool")
|
||||
return fmt.Errorf("error fetching pool: %w", err)
|
||||
}
|
||||
|
||||
updatedPool, err = s.updatePool(tx, pool, param)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "updating pool")
|
||||
return fmt.Errorf("error updating pool: %w", err)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return params.Pool{}, err
|
||||
}
|
||||
|
||||
updatedPool, err = s.GetPoolByID(ctx, poolID)
|
||||
if err != nil {
|
||||
return params.Pool{}, err
|
||||
}
|
||||
return updatedPool, nil
|
||||
}
|
||||
|
||||
func (s *sqlDatabase) ListEntityPools(_ context.Context, entity params.ForgeEntity) ([]params.Pool, error) {
|
||||
pools, err := s.listEntityPools(s.conn, entity.EntityType, entity.ID, "Tags")
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "fetching pools")
|
||||
return nil, fmt.Errorf("error fetching pools: %w", err)
|
||||
}
|
||||
|
||||
ret := make([]params.Pool, len(pools))
|
||||
for idx, pool := range pools {
|
||||
ret[idx], err = s.sqlToCommonPool(pool)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "fetching pool")
|
||||
return nil, fmt.Errorf("error fetching pool: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -436,7 +446,7 @@ func (s *sqlDatabase) ListEntityPools(_ context.Context, entity params.ForgeEnti
|
|||
func (s *sqlDatabase) ListEntityInstances(_ context.Context, entity params.ForgeEntity) ([]params.Instance, error) {
|
||||
pools, err := s.listEntityPools(s.conn, entity.EntityType, entity.ID, "Instances", "Instances.Job")
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "fetching entity")
|
||||
return nil, fmt.Errorf("error fetching entity: %w", err)
|
||||
}
|
||||
ret := []params.Instance{}
|
||||
for _, pool := range pools {
|
||||
|
|
@ -446,7 +456,7 @@ func (s *sqlDatabase) ListEntityInstances(_ context.Context, entity params.Forge
|
|||
instance.Pool = pool
|
||||
paramsInstance, err := s.sqlToParamsInstance(instance)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "fetching instance")
|
||||
return nil, fmt.Errorf("error fetching instance: %w", err)
|
||||
}
|
||||
ret = append(ret, paramsInstance)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -157,7 +157,7 @@ func (s *PoolsTestSuite) TestListAllPoolsDBFetchErr() {
|
|||
|
||||
s.assertSQLMockExpectations()
|
||||
s.Require().NotNil(err)
|
||||
s.Require().Equal("fetching all pools: mocked fetching all pools error", err.Error())
|
||||
s.Require().Equal("error fetching all pools: mocked fetching all pools error", err.Error())
|
||||
}
|
||||
|
||||
func (s *PoolsTestSuite) TestGetPoolByID() {
|
||||
|
|
@ -171,7 +171,7 @@ func (s *PoolsTestSuite) TestGetPoolByIDInvalidPoolID() {
|
|||
_, err := s.Store.GetPoolByID(s.adminCtx, "dummy-pool-id")
|
||||
|
||||
s.Require().NotNil(err)
|
||||
s.Require().Equal("fetching pool by ID: parsing id: invalid request", err.Error())
|
||||
s.Require().Equal("error fetching pool by ID: error parsing id: invalid request", err.Error())
|
||||
}
|
||||
|
||||
func (s *PoolsTestSuite) TestDeletePoolByID() {
|
||||
|
|
@ -179,14 +179,14 @@ func (s *PoolsTestSuite) TestDeletePoolByID() {
|
|||
|
||||
s.Require().Nil(err)
|
||||
_, err = s.Store.GetPoolByID(s.adminCtx, s.Fixtures.Pools[0].ID)
|
||||
s.Require().Equal("fetching pool by ID: not found", err.Error())
|
||||
s.Require().Equal("error fetching pool by ID: not found", err.Error())
|
||||
}
|
||||
|
||||
func (s *PoolsTestSuite) TestDeletePoolByIDInvalidPoolID() {
|
||||
err := s.Store.DeletePoolByID(s.adminCtx, "dummy-pool-id")
|
||||
|
||||
s.Require().NotNil(err)
|
||||
s.Require().Equal("fetching pool by ID: parsing id: invalid request", err.Error())
|
||||
s.Require().Equal("error fetching pool by ID: error parsing id: invalid request", err.Error())
|
||||
}
|
||||
|
||||
func (s *PoolsTestSuite) TestDeletePoolByIDDBRemoveErr() {
|
||||
|
|
@ -204,7 +204,7 @@ func (s *PoolsTestSuite) TestDeletePoolByIDDBRemoveErr() {
|
|||
|
||||
s.assertSQLMockExpectations()
|
||||
s.Require().NotNil(err)
|
||||
s.Require().Equal("removing pool: mocked removing pool error", err.Error())
|
||||
s.Require().Equal("error removing pool: mocked removing pool error", err.Error())
|
||||
}
|
||||
|
||||
func (s *PoolsTestSuite) TestEntityPoolOperations() {
|
||||
|
|
|
|||
|
|
@ -16,11 +16,11 @@ package sql
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/pkg/errors"
|
||||
"gorm.io/gorm"
|
||||
|
||||
runnerErrors "github.com/cloudbase/garm-provider-common/errors"
|
||||
|
|
@ -57,23 +57,23 @@ func (s *sqlDatabase) CreateRepository(ctx context.Context, owner, name string,
|
|||
case params.GiteaEndpointType:
|
||||
newRepo.GiteaCredentialsID = &credentials.ID
|
||||
default:
|
||||
return errors.Wrap(runnerErrors.ErrBadRequest, "unsupported credentials type")
|
||||
return runnerErrors.NewBadRequestError("unsupported credentials type")
|
||||
}
|
||||
|
||||
newRepo.EndpointName = &credentials.Endpoint.Name
|
||||
q := tx.Create(&newRepo)
|
||||
if q.Error != nil {
|
||||
return errors.Wrap(q.Error, "creating repository")
|
||||
return fmt.Errorf("error creating repository: %w", q.Error)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return params.Repository{}, errors.Wrap(err, "creating repository")
|
||||
return params.Repository{}, fmt.Errorf("error creating repository: %w", err)
|
||||
}
|
||||
|
||||
ret, err := s.GetRepositoryByID(ctx, newRepo.ID.String())
|
||||
if err != nil {
|
||||
return params.Repository{}, errors.Wrap(err, "creating repository")
|
||||
return params.Repository{}, fmt.Errorf("error creating repository: %w", err)
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
|
|
@ -82,12 +82,12 @@ func (s *sqlDatabase) CreateRepository(ctx context.Context, owner, name string,
|
|||
func (s *sqlDatabase) GetRepository(ctx context.Context, owner, name, endpointName string) (params.Repository, error) {
|
||||
repo, err := s.getRepo(ctx, owner, name, endpointName)
|
||||
if err != nil {
|
||||
return params.Repository{}, errors.Wrap(err, "fetching repo")
|
||||
return params.Repository{}, fmt.Errorf("error fetching repo: %w", err)
|
||||
}
|
||||
|
||||
param, err := s.sqlToCommonRepository(repo, true)
|
||||
if err != nil {
|
||||
return params.Repository{}, errors.Wrap(err, "fetching repo")
|
||||
return params.Repository{}, fmt.Errorf("error fetching repo: %w", err)
|
||||
}
|
||||
|
||||
return param, nil
|
||||
|
|
@ -112,7 +112,7 @@ func (s *sqlDatabase) ListRepositories(_ context.Context, filter params.Reposito
|
|||
}
|
||||
q = q.Find(&repos)
|
||||
if q.Error != nil {
|
||||
return []params.Repository{}, errors.Wrap(q.Error, "fetching user from database")
|
||||
return []params.Repository{}, fmt.Errorf("error fetching user from database: %w", q.Error)
|
||||
}
|
||||
|
||||
ret := make([]params.Repository, len(repos))
|
||||
|
|
@ -120,7 +120,7 @@ func (s *sqlDatabase) ListRepositories(_ context.Context, filter params.Reposito
|
|||
var err error
|
||||
ret[idx], err = s.sqlToCommonRepository(val, true)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "fetching repositories")
|
||||
return nil, fmt.Errorf("error fetching repositories: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -130,7 +130,7 @@ func (s *sqlDatabase) ListRepositories(_ context.Context, filter params.Reposito
|
|||
func (s *sqlDatabase) DeleteRepository(ctx context.Context, repoID string) (err error) {
|
||||
repo, err := s.getRepoByID(ctx, s.conn, repoID, "Endpoint", "Credentials", "Credentials.Endpoint", "GiteaCredentials", "GiteaCredentials.Endpoint")
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "fetching repo")
|
||||
return fmt.Errorf("error fetching repo: %w", err)
|
||||
}
|
||||
|
||||
defer func(repo Repository) {
|
||||
|
|
@ -146,7 +146,7 @@ func (s *sqlDatabase) DeleteRepository(ctx context.Context, repoID string) (err
|
|||
|
||||
q := s.conn.Unscoped().Delete(&repo)
|
||||
if q.Error != nil && !errors.Is(q.Error, gorm.ErrRecordNotFound) {
|
||||
return errors.Wrap(q.Error, "deleting repo")
|
||||
return fmt.Errorf("error deleting repo: %w", q.Error)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
|
@ -164,23 +164,23 @@ func (s *sqlDatabase) UpdateRepository(ctx context.Context, repoID string, param
|
|||
var err error
|
||||
repo, err = s.getRepoByID(ctx, tx, repoID)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "fetching repo")
|
||||
return fmt.Errorf("error fetching repo: %w", err)
|
||||
}
|
||||
if repo.EndpointName == nil {
|
||||
return errors.Wrap(runnerErrors.ErrUnprocessable, "repository has no endpoint")
|
||||
return runnerErrors.NewUnprocessableError("repository has no endpoint")
|
||||
}
|
||||
|
||||
if param.CredentialsName != "" {
|
||||
creds, err = s.getGithubCredentialsByName(ctx, tx, param.CredentialsName, false)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "fetching credentials")
|
||||
return fmt.Errorf("error fetching credentials: %w", err)
|
||||
}
|
||||
if creds.EndpointName == nil {
|
||||
return errors.Wrap(runnerErrors.ErrUnprocessable, "credentials have no endpoint")
|
||||
return runnerErrors.NewUnprocessableError("credentials have no endpoint")
|
||||
}
|
||||
|
||||
if *creds.EndpointName != *repo.EndpointName {
|
||||
return errors.Wrap(runnerErrors.ErrBadRequest, "endpoint mismatch")
|
||||
return runnerErrors.NewBadRequestError("endpoint mismatch")
|
||||
}
|
||||
repo.CredentialsID = &creds.ID
|
||||
}
|
||||
|
|
@ -199,23 +199,23 @@ func (s *sqlDatabase) UpdateRepository(ctx context.Context, repoID string, param
|
|||
|
||||
q := tx.Save(&repo)
|
||||
if q.Error != nil {
|
||||
return errors.Wrap(q.Error, "saving repo")
|
||||
return fmt.Errorf("error saving repo: %w", q.Error)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return params.Repository{}, errors.Wrap(err, "saving repo")
|
||||
return params.Repository{}, fmt.Errorf("error saving repo: %w", err)
|
||||
}
|
||||
|
||||
repo, err = s.getRepoByID(ctx, s.conn, repoID, "Endpoint", "Credentials", "Credentials.Endpoint", "GiteaCredentials", "GiteaCredentials.Endpoint")
|
||||
if err != nil {
|
||||
return params.Repository{}, errors.Wrap(err, "updating enterprise")
|
||||
return params.Repository{}, fmt.Errorf("error updating enterprise: %w", err)
|
||||
}
|
||||
|
||||
newParams, err = s.sqlToCommonRepository(repo, true)
|
||||
if err != nil {
|
||||
return params.Repository{}, errors.Wrap(err, "saving repo")
|
||||
return params.Repository{}, fmt.Errorf("error saving repo: %w", err)
|
||||
}
|
||||
return newParams, nil
|
||||
}
|
||||
|
|
@ -232,12 +232,12 @@ func (s *sqlDatabase) GetRepositoryByID(ctx context.Context, repoID string) (par
|
|||
}
|
||||
repo, err := s.getRepoByID(ctx, s.conn, repoID, preloadList...)
|
||||
if err != nil {
|
||||
return params.Repository{}, errors.Wrap(err, "fetching repo")
|
||||
return params.Repository{}, fmt.Errorf("error fetching repo: %w", err)
|
||||
}
|
||||
|
||||
param, err := s.sqlToCommonRepository(repo, true)
|
||||
if err != nil {
|
||||
return params.Repository{}, errors.Wrap(err, "fetching repo")
|
||||
return params.Repository{}, fmt.Errorf("error fetching repo: %w", err)
|
||||
}
|
||||
return param, nil
|
||||
}
|
||||
|
|
@ -259,7 +259,7 @@ func (s *sqlDatabase) getRepo(_ context.Context, owner, name, endpointName strin
|
|||
if errors.Is(q.Error, gorm.ErrRecordNotFound) {
|
||||
return Repository{}, runnerErrors.ErrNotFound
|
||||
}
|
||||
return Repository{}, errors.Wrap(q.Error, "fetching repository from database")
|
||||
return Repository{}, fmt.Errorf("error fetching repository from database: %w", q.Error)
|
||||
}
|
||||
return repo, nil
|
||||
}
|
||||
|
|
@ -267,7 +267,7 @@ func (s *sqlDatabase) getRepo(_ context.Context, owner, name, endpointName strin
|
|||
func (s *sqlDatabase) getRepoByID(_ context.Context, tx *gorm.DB, id string, preload ...string) (Repository, error) {
|
||||
u, err := uuid.Parse(id)
|
||||
if err != nil {
|
||||
return Repository{}, errors.Wrap(runnerErrors.ErrBadRequest, "parsing id")
|
||||
return Repository{}, runnerErrors.NewBadRequestError("error parsing id: %s", err)
|
||||
}
|
||||
var repo Repository
|
||||
|
||||
|
|
@ -283,7 +283,7 @@ func (s *sqlDatabase) getRepoByID(_ context.Context, tx *gorm.DB, id string, pre
|
|||
if errors.Is(q.Error, gorm.ErrRecordNotFound) {
|
||||
return Repository{}, runnerErrors.ErrNotFound
|
||||
}
|
||||
return Repository{}, errors.Wrap(q.Error, "fetching repository from database")
|
||||
return Repository{}, fmt.Errorf("error fetching repository from database: %w", q.Error)
|
||||
}
|
||||
return repo, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -284,7 +284,7 @@ func (s *RepoTestSuite) TestCreateRepositoryInvalidForgeType() {
|
|||
)
|
||||
|
||||
s.Require().NotNil(err)
|
||||
s.Require().Equal("creating repository: unsupported credentials type: invalid request", err.Error())
|
||||
s.Require().Equal("error creating repository: unsupported credentials type", err.Error())
|
||||
}
|
||||
|
||||
func (s *RepoTestSuite) TestCreateRepositoryInvalidDBPassphrase() {
|
||||
|
|
@ -330,7 +330,7 @@ func (s *RepoTestSuite) TestCreateRepositoryInvalidDBCreateErr() {
|
|||
)
|
||||
|
||||
s.Require().NotNil(err)
|
||||
s.Require().Equal("creating repository: creating repository: creating repo mock error", err.Error())
|
||||
s.Require().Equal("error creating repository: error creating repository: creating repo mock error", err.Error())
|
||||
s.assertSQLMockExpectations()
|
||||
}
|
||||
|
||||
|
|
@ -355,7 +355,7 @@ func (s *RepoTestSuite) TestGetRepositoryNotFound() {
|
|||
_, err := s.Store.GetRepository(s.adminCtx, "dummy-owner", "dummy-name", "github.com")
|
||||
|
||||
s.Require().NotNil(err)
|
||||
s.Require().Equal("fetching repo: not found", err.Error())
|
||||
s.Require().Equal("error fetching repo: not found", err.Error())
|
||||
}
|
||||
|
||||
func (s *RepoTestSuite) TestGetRepositoryDBDecryptingErr() {
|
||||
|
|
@ -371,7 +371,7 @@ func (s *RepoTestSuite) TestGetRepositoryDBDecryptingErr() {
|
|||
_, err := s.StoreSQLMocked.GetRepository(s.adminCtx, s.Fixtures.Repos[0].Owner, s.Fixtures.Repos[0].Name, s.Fixtures.Repos[0].Endpoint.Name)
|
||||
|
||||
s.Require().NotNil(err)
|
||||
s.Require().Equal("fetching repo: missing secret", err.Error())
|
||||
s.Require().Equal("error fetching repo: missing secret", err.Error())
|
||||
s.assertSQLMockExpectations()
|
||||
}
|
||||
|
||||
|
|
@ -471,7 +471,7 @@ func (s *RepoTestSuite) TestListRepositoriesDBFetchErr() {
|
|||
_, err := s.StoreSQLMocked.ListRepositories(s.adminCtx, params.RepositoryFilter{})
|
||||
|
||||
s.Require().NotNil(err)
|
||||
s.Require().Equal("fetching user from database: fetching user from database mock error", err.Error())
|
||||
s.Require().Equal("error fetching user from database: fetching user from database mock error", err.Error())
|
||||
s.assertSQLMockExpectations()
|
||||
}
|
||||
|
||||
|
|
@ -485,7 +485,7 @@ func (s *RepoTestSuite) TestListRepositoriesDBDecryptingErr() {
|
|||
_, err := s.StoreSQLMocked.ListRepositories(s.adminCtx, params.RepositoryFilter{})
|
||||
|
||||
s.Require().NotNil(err)
|
||||
s.Require().Equal("fetching repositories: decrypting secret: invalid passphrase length (expected length 32 characters)", err.Error())
|
||||
s.Require().Equal("error fetching repositories: error decrypting secret: invalid passphrase length (expected length 32 characters)", err.Error())
|
||||
s.assertSQLMockExpectations()
|
||||
}
|
||||
|
||||
|
|
@ -495,14 +495,14 @@ func (s *RepoTestSuite) TestDeleteRepository() {
|
|||
s.Require().Nil(err)
|
||||
_, err = s.Store.GetRepositoryByID(s.adminCtx, s.Fixtures.Repos[0].ID)
|
||||
s.Require().NotNil(err)
|
||||
s.Require().Equal("fetching repo: not found", err.Error())
|
||||
s.Require().Equal("error fetching repo: not found", err.Error())
|
||||
}
|
||||
|
||||
func (s *RepoTestSuite) TestDeleteRepositoryInvalidRepoID() {
|
||||
err := s.Store.DeleteRepository(s.adminCtx, "dummy-repo-id")
|
||||
|
||||
s.Require().NotNil(err)
|
||||
s.Require().Equal("fetching repo: parsing id: invalid request", err.Error())
|
||||
s.Require().Equal("error fetching repo: error parsing id: invalid UUID length: 13", err.Error())
|
||||
}
|
||||
|
||||
func (s *RepoTestSuite) TestDeleteRepositoryDBRemoveErr() {
|
||||
|
|
@ -520,7 +520,7 @@ func (s *RepoTestSuite) TestDeleteRepositoryDBRemoveErr() {
|
|||
err := s.StoreSQLMocked.DeleteRepository(s.adminCtx, s.Fixtures.Repos[0].ID)
|
||||
|
||||
s.Require().NotNil(err)
|
||||
s.Require().Equal("deleting repo: mocked deleting repo error", err.Error())
|
||||
s.Require().Equal("error deleting repo: mocked deleting repo error", err.Error())
|
||||
s.assertSQLMockExpectations()
|
||||
}
|
||||
|
||||
|
|
@ -536,7 +536,7 @@ func (s *RepoTestSuite) TestUpdateRepositoryInvalidRepoID() {
|
|||
_, err := s.Store.UpdateRepository(s.adminCtx, "dummy-repo-id", s.Fixtures.UpdateRepoParams)
|
||||
|
||||
s.Require().NotNil(err)
|
||||
s.Require().Equal("saving repo: fetching repo: parsing id: invalid request", err.Error())
|
||||
s.Require().Equal("error saving repo: error fetching repo: error parsing id: invalid UUID length: 13", err.Error())
|
||||
}
|
||||
|
||||
func (s *RepoTestSuite) TestUpdateRepositoryDBEncryptErr() {
|
||||
|
|
@ -561,7 +561,7 @@ func (s *RepoTestSuite) TestUpdateRepositoryDBEncryptErr() {
|
|||
_, err := s.StoreSQLMocked.UpdateRepository(s.adminCtx, s.Fixtures.Repos[0].ID, s.Fixtures.UpdateRepoParams)
|
||||
|
||||
s.Require().NotNil(err)
|
||||
s.Require().Equal("saving repo: saving repo: failed to encrypt string: invalid passphrase length (expected length 32 characters)", err.Error())
|
||||
s.Require().Equal("error saving repo: saving repo: failed to encrypt string: invalid passphrase length (expected length 32 characters)", err.Error())
|
||||
s.assertSQLMockExpectations()
|
||||
}
|
||||
|
||||
|
|
@ -589,7 +589,7 @@ func (s *RepoTestSuite) TestUpdateRepositoryDBSaveErr() {
|
|||
_, err := s.StoreSQLMocked.UpdateRepository(s.adminCtx, s.Fixtures.Repos[0].ID, s.Fixtures.UpdateRepoParams)
|
||||
|
||||
s.Require().NotNil(err)
|
||||
s.Require().Equal("saving repo: saving repo: saving repo mock error", err.Error())
|
||||
s.Require().Equal("error saving repo: error saving repo: saving repo mock error", err.Error())
|
||||
s.assertSQLMockExpectations()
|
||||
}
|
||||
|
||||
|
|
@ -616,7 +616,7 @@ func (s *RepoTestSuite) TestUpdateRepositoryDBDecryptingErr() {
|
|||
_, err := s.StoreSQLMocked.UpdateRepository(s.adminCtx, s.Fixtures.Repos[0].ID, s.Fixtures.UpdateRepoParams)
|
||||
|
||||
s.Require().NotNil(err)
|
||||
s.Require().Equal("saving repo: saving repo: failed to encrypt string: invalid passphrase length (expected length 32 characters)", err.Error())
|
||||
s.Require().Equal("error saving repo: saving repo: failed to encrypt string: invalid passphrase length (expected length 32 characters)", err.Error())
|
||||
s.assertSQLMockExpectations()
|
||||
}
|
||||
|
||||
|
|
@ -631,7 +631,7 @@ func (s *RepoTestSuite) TestGetRepositoryByIDInvalidRepoID() {
|
|||
_, err := s.Store.GetRepositoryByID(s.adminCtx, "dummy-repo-id")
|
||||
|
||||
s.Require().NotNil(err)
|
||||
s.Require().Equal("fetching repo: parsing id: invalid request", err.Error())
|
||||
s.Require().Equal("error fetching repo: error parsing id: invalid UUID length: 13", err.Error())
|
||||
}
|
||||
|
||||
func (s *RepoTestSuite) TestGetRepositoryByIDDBDecryptingErr() {
|
||||
|
|
@ -651,7 +651,7 @@ func (s *RepoTestSuite) TestGetRepositoryByIDDBDecryptingErr() {
|
|||
_, err := s.StoreSQLMocked.GetRepositoryByID(s.adminCtx, s.Fixtures.Repos[0].ID)
|
||||
|
||||
s.Require().NotNil(err)
|
||||
s.Require().Equal("fetching repo: missing secret", err.Error())
|
||||
s.Require().Equal("error fetching repo: missing secret", err.Error())
|
||||
s.assertSQLMockExpectations()
|
||||
}
|
||||
|
||||
|
|
@ -690,7 +690,7 @@ func (s *RepoTestSuite) TestCreateRepositoryPoolInvalidRepoID() {
|
|||
_, err := s.Store.CreateEntityPool(s.adminCtx, entity, s.Fixtures.CreatePoolParams)
|
||||
|
||||
s.Require().NotNil(err)
|
||||
s.Require().Equal("parsing id: invalid request", err.Error())
|
||||
s.Require().Equal("error parsing id: invalid request", err.Error())
|
||||
}
|
||||
|
||||
func (s *RepoTestSuite) TestCreateRepositoryPoolDBFetchTagErr() {
|
||||
|
|
@ -709,7 +709,7 @@ func (s *RepoTestSuite) TestCreateRepositoryPoolDBFetchTagErr() {
|
|||
_, err = s.StoreSQLMocked.CreateEntityPool(s.adminCtx, entity, s.Fixtures.CreatePoolParams)
|
||||
|
||||
s.Require().NotNil(err)
|
||||
s.Require().Equal("creating tag: fetching tag from database: mocked fetching tag error", err.Error())
|
||||
s.Require().Equal("error creating tag: error fetching tag from database: mocked fetching tag error", err.Error())
|
||||
s.assertSQLMockExpectations()
|
||||
}
|
||||
|
||||
|
|
@ -738,7 +738,7 @@ func (s *RepoTestSuite) TestCreateRepositoryPoolDBAddingPoolErr() {
|
|||
_, err = s.StoreSQLMocked.CreateEntityPool(s.adminCtx, entity, s.Fixtures.CreatePoolParams)
|
||||
|
||||
s.Require().NotNil(err)
|
||||
s.Require().Equal("creating pool: mocked adding pool error", err.Error())
|
||||
s.Require().Equal("error creating pool: mocked adding pool error", err.Error())
|
||||
s.assertSQLMockExpectations()
|
||||
}
|
||||
|
||||
|
|
@ -769,7 +769,7 @@ func (s *RepoTestSuite) TestCreateRepositoryPoolDBSaveTagErr() {
|
|||
|
||||
_, err = s.StoreSQLMocked.CreateEntityPool(s.adminCtx, entity, s.Fixtures.CreatePoolParams)
|
||||
s.Require().NotNil(err)
|
||||
s.Require().Equal("associating tags: mocked saving tag error", err.Error())
|
||||
s.Require().Equal("error associating tags: mocked saving tag error", err.Error())
|
||||
s.assertSQLMockExpectations()
|
||||
}
|
||||
|
||||
|
|
@ -810,7 +810,7 @@ func (s *RepoTestSuite) TestCreateRepositoryPoolDBFetchPoolErr() {
|
|||
_, err = s.StoreSQLMocked.CreateEntityPool(s.adminCtx, entity, s.Fixtures.CreatePoolParams)
|
||||
|
||||
s.Require().NotNil(err)
|
||||
s.Require().Equal("fetching pool: not found", err.Error())
|
||||
s.Require().Equal("error fetching pool by ID: not found", err.Error())
|
||||
s.assertSQLMockExpectations()
|
||||
}
|
||||
|
||||
|
|
@ -841,7 +841,7 @@ func (s *RepoTestSuite) TestListRepoPoolsInvalidRepoID() {
|
|||
_, err := s.Store.ListEntityPools(s.adminCtx, entity)
|
||||
|
||||
s.Require().NotNil(err)
|
||||
s.Require().Equal("fetching pools: parsing id: invalid request", err.Error())
|
||||
s.Require().Equal("error fetching pools: error parsing id: invalid request", err.Error())
|
||||
}
|
||||
|
||||
func (s *RepoTestSuite) TestGetRepositoryPool() {
|
||||
|
|
@ -866,7 +866,7 @@ func (s *RepoTestSuite) TestGetRepositoryPoolInvalidRepoID() {
|
|||
_, err := s.Store.GetEntityPool(s.adminCtx, entity, "dummy-pool-id")
|
||||
|
||||
s.Require().NotNil(err)
|
||||
s.Require().Equal("fetching pool: parsing id: invalid request", err.Error())
|
||||
s.Require().Equal("fetching pool: error parsing id: invalid request", err.Error())
|
||||
}
|
||||
|
||||
func (s *RepoTestSuite) TestDeleteRepositoryPool() {
|
||||
|
|
@ -881,7 +881,7 @@ func (s *RepoTestSuite) TestDeleteRepositoryPool() {
|
|||
|
||||
s.Require().Nil(err)
|
||||
_, err = s.Store.GetEntityPool(s.adminCtx, entity, pool.ID)
|
||||
s.Require().Equal("fetching pool: finding pool: not found", err.Error())
|
||||
s.Require().Equal("fetching pool: error finding pool: not found", err.Error())
|
||||
}
|
||||
|
||||
func (s *RepoTestSuite) TestDeleteRepositoryPoolInvalidRepoID() {
|
||||
|
|
@ -892,7 +892,7 @@ func (s *RepoTestSuite) TestDeleteRepositoryPoolInvalidRepoID() {
|
|||
err := s.Store.DeleteEntityPool(s.adminCtx, entity, "dummy-pool-id")
|
||||
|
||||
s.Require().NotNil(err)
|
||||
s.Require().Equal("parsing id: invalid request", err.Error())
|
||||
s.Require().Equal("error parsing id: invalid request", err.Error())
|
||||
}
|
||||
|
||||
func (s *RepoTestSuite) TestDeleteRepositoryPoolDBDeleteErr() {
|
||||
|
|
@ -913,7 +913,7 @@ func (s *RepoTestSuite) TestDeleteRepositoryPoolDBDeleteErr() {
|
|||
|
||||
err = s.StoreSQLMocked.DeleteEntityPool(s.adminCtx, entity, pool.ID)
|
||||
s.Require().NotNil(err)
|
||||
s.Require().Equal("removing pool: mocked deleting pool error", err.Error())
|
||||
s.Require().Equal("error removing pool: mocked deleting pool error", err.Error())
|
||||
s.assertSQLMockExpectations()
|
||||
}
|
||||
|
||||
|
|
@ -948,7 +948,7 @@ func (s *RepoTestSuite) TestListRepoInstancesInvalidRepoID() {
|
|||
_, err := s.Store.ListEntityInstances(s.adminCtx, entity)
|
||||
|
||||
s.Require().NotNil(err)
|
||||
s.Require().Equal("fetching entity: parsing id: invalid request", err.Error())
|
||||
s.Require().Equal("error fetching entity: error parsing id: invalid request", err.Error())
|
||||
}
|
||||
|
||||
func (s *RepoTestSuite) TestUpdateRepositoryPool() {
|
||||
|
|
@ -976,7 +976,7 @@ func (s *RepoTestSuite) TestUpdateRepositoryPoolInvalidRepoID() {
|
|||
_, err := s.Store.UpdateEntityPool(s.adminCtx, entity, "dummy-repo-id", s.Fixtures.UpdatePoolParams)
|
||||
|
||||
s.Require().NotNil(err)
|
||||
s.Require().Equal("fetching pool: parsing id: invalid request", err.Error())
|
||||
s.Require().Equal("error fetching pool: error parsing id: invalid request", err.Error())
|
||||
}
|
||||
|
||||
func (s *RepoTestSuite) TestAddRepoEntityEvent() {
|
||||
|
|
|
|||
|
|
@ -16,8 +16,7 @@ package sql
|
|||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/cloudbase/garm/database/common"
|
||||
"github.com/cloudbase/garm/params"
|
||||
|
|
@ -26,7 +25,7 @@ import (
|
|||
func (s *sqlDatabase) CreateScaleSetInstance(_ context.Context, scaleSetID uint, param params.CreateInstanceParams) (instance params.Instance, err error) {
|
||||
scaleSet, err := s.getScaleSetByID(s.conn, scaleSetID)
|
||||
if err != nil {
|
||||
return params.Instance{}, errors.Wrap(err, "fetching scale set")
|
||||
return params.Instance{}, fmt.Errorf("error fetching scale set: %w", err)
|
||||
}
|
||||
|
||||
defer func() {
|
||||
|
|
@ -39,7 +38,7 @@ func (s *sqlDatabase) CreateScaleSetInstance(_ context.Context, scaleSetID uint,
|
|||
if len(param.JitConfiguration) > 0 {
|
||||
secret, err = s.marshalAndSeal(param.JitConfiguration)
|
||||
if err != nil {
|
||||
return params.Instance{}, errors.Wrap(err, "marshalling jit config")
|
||||
return params.Instance{}, fmt.Errorf("error marshalling jit config: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -58,7 +57,7 @@ func (s *sqlDatabase) CreateScaleSetInstance(_ context.Context, scaleSetID uint,
|
|||
}
|
||||
q := s.conn.Create(&newInstance)
|
||||
if q.Error != nil {
|
||||
return params.Instance{}, errors.Wrap(q.Error, "creating instance")
|
||||
return params.Instance{}, fmt.Errorf("error creating instance: %w", q.Error)
|
||||
}
|
||||
|
||||
return s.sqlToParamsInstance(newInstance)
|
||||
|
|
@ -66,10 +65,13 @@ func (s *sqlDatabase) CreateScaleSetInstance(_ context.Context, scaleSetID uint,
|
|||
|
||||
func (s *sqlDatabase) ListScaleSetInstances(_ context.Context, scalesetID uint) ([]params.Instance, error) {
|
||||
var instances []Instance
|
||||
query := s.conn.Model(&Instance{}).Preload("Job").Where("scale_set_fk_id = ?", scalesetID)
|
||||
query := s.conn.
|
||||
Preload("ScaleSet").
|
||||
Preload("Job").
|
||||
Where("scale_set_fk_id = ?", scalesetID)
|
||||
|
||||
if err := query.Find(&instances); err.Error != nil {
|
||||
return nil, errors.Wrap(err.Error, "fetching instances")
|
||||
return nil, fmt.Errorf("error fetching instances: %w", err.Error)
|
||||
}
|
||||
|
||||
var err error
|
||||
|
|
@ -77,7 +79,7 @@ func (s *sqlDatabase) ListScaleSetInstances(_ context.Context, scalesetID uint)
|
|||
for idx, inst := range instances {
|
||||
ret[idx], err = s.sqlToParamsInstance(inst)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "converting instance")
|
||||
return nil, fmt.Errorf("error converting instance: %w", err)
|
||||
}
|
||||
}
|
||||
return ret, nil
|
||||
|
|
|
|||
|
|
@ -16,10 +16,10 @@ package sql
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/pkg/errors"
|
||||
"gorm.io/datatypes"
|
||||
"gorm.io/gorm"
|
||||
|
||||
|
|
@ -33,13 +33,16 @@ func (s *sqlDatabase) ListAllScaleSets(_ context.Context) ([]params.ScaleSet, er
|
|||
|
||||
q := s.conn.Model(&ScaleSet{}).
|
||||
Preload("Organization").
|
||||
Preload("Organization.Endpoint").
|
||||
Preload("Repository").
|
||||
Preload("Repository.Endpoint").
|
||||
Preload("Enterprise").
|
||||
Preload("Enterprise.Endpoint").
|
||||
Omit("extra_specs").
|
||||
Omit("status_messages").
|
||||
Find(&scaleSets)
|
||||
if q.Error != nil {
|
||||
return nil, errors.Wrap(q.Error, "fetching all scale sets")
|
||||
return nil, fmt.Errorf("error fetching all scale sets: %w", q.Error)
|
||||
}
|
||||
|
||||
ret := make([]params.ScaleSet, len(scaleSets))
|
||||
|
|
@ -47,7 +50,7 @@ func (s *sqlDatabase) ListAllScaleSets(_ context.Context) ([]params.ScaleSet, er
|
|||
for idx, val := range scaleSets {
|
||||
ret[idx], err = s.sqlToCommonScaleSet(val)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "converting scale sets")
|
||||
return nil, fmt.Errorf("error converting scale sets: %w", err)
|
||||
}
|
||||
}
|
||||
return ret, nil
|
||||
|
|
@ -88,7 +91,7 @@ func (s *sqlDatabase) CreateEntityScaleSet(_ context.Context, entity params.Forg
|
|||
|
||||
entityID, err := uuid.Parse(entity.ID)
|
||||
if err != nil {
|
||||
return params.ScaleSet{}, errors.Wrap(runnerErrors.ErrBadRequest, "parsing id")
|
||||
return params.ScaleSet{}, fmt.Errorf("error parsing id: %w", runnerErrors.ErrBadRequest)
|
||||
}
|
||||
|
||||
switch entity.EntityType {
|
||||
|
|
@ -101,12 +104,12 @@ func (s *sqlDatabase) CreateEntityScaleSet(_ context.Context, entity params.Forg
|
|||
}
|
||||
err = s.conn.Transaction(func(tx *gorm.DB) error {
|
||||
if err := s.hasGithubEntity(tx, entity.EntityType, entity.ID); err != nil {
|
||||
return errors.Wrap(err, "checking entity existence")
|
||||
return fmt.Errorf("error checking entity existence: %w", err)
|
||||
}
|
||||
|
||||
q := tx.Create(&newScaleSet)
|
||||
if q.Error != nil {
|
||||
return errors.Wrap(q.Error, "creating scale set")
|
||||
return fmt.Errorf("error creating scale set: %w", q.Error)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
|
@ -117,7 +120,7 @@ func (s *sqlDatabase) CreateEntityScaleSet(_ context.Context, entity params.Forg
|
|||
|
||||
dbScaleSet, err := s.getScaleSetByID(s.conn, newScaleSet.ID, "Instances", "Enterprise", "Organization", "Repository")
|
||||
if err != nil {
|
||||
return params.ScaleSet{}, errors.Wrap(err, "fetching scale set")
|
||||
return params.ScaleSet{}, fmt.Errorf("error fetching scale set: %w", err)
|
||||
}
|
||||
|
||||
return s.sqlToCommonScaleSet(dbScaleSet)
|
||||
|
|
@ -125,11 +128,11 @@ func (s *sqlDatabase) CreateEntityScaleSet(_ context.Context, entity params.Forg
|
|||
|
||||
func (s *sqlDatabase) listEntityScaleSets(tx *gorm.DB, entityType params.ForgeEntityType, entityID string, preload ...string) ([]ScaleSet, error) {
|
||||
if _, err := uuid.Parse(entityID); err != nil {
|
||||
return nil, errors.Wrap(runnerErrors.ErrBadRequest, "parsing id")
|
||||
return nil, fmt.Errorf("error parsing id: %w", runnerErrors.ErrBadRequest)
|
||||
}
|
||||
|
||||
if err := s.hasGithubEntity(tx, entityType, entityID); err != nil {
|
||||
return nil, errors.Wrap(err, "checking entity existence")
|
||||
return nil, fmt.Errorf("error checking entity existence: %w", err)
|
||||
}
|
||||
|
||||
var preloadEntity string
|
||||
|
|
@ -167,7 +170,7 @@ func (s *sqlDatabase) listEntityScaleSets(tx *gorm.DB, entityType params.ForgeEn
|
|||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return []ScaleSet{}, nil
|
||||
}
|
||||
return nil, errors.Wrap(err, "fetching scale sets")
|
||||
return nil, fmt.Errorf("error fetching scale sets: %w", err)
|
||||
}
|
||||
|
||||
return scaleSets, nil
|
||||
|
|
@ -176,21 +179,21 @@ func (s *sqlDatabase) listEntityScaleSets(tx *gorm.DB, entityType params.ForgeEn
|
|||
func (s *sqlDatabase) ListEntityScaleSets(_ context.Context, entity params.ForgeEntity) ([]params.ScaleSet, error) {
|
||||
scaleSets, err := s.listEntityScaleSets(s.conn, entity.EntityType, entity.ID)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "fetching scale sets")
|
||||
return nil, fmt.Errorf("error fetching scale sets: %w", err)
|
||||
}
|
||||
|
||||
ret := make([]params.ScaleSet, len(scaleSets))
|
||||
for idx, set := range scaleSets {
|
||||
ret[idx], err = s.sqlToCommonScaleSet(set)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "conbverting scale set")
|
||||
return nil, fmt.Errorf("error conbverting scale set: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (s *sqlDatabase) UpdateEntityScaleSet(_ context.Context, entity params.ForgeEntity, scaleSetID uint, param params.UpdateScaleSetParams, callback func(old, newSet params.ScaleSet) error) (updatedScaleSet params.ScaleSet, err error) {
|
||||
func (s *sqlDatabase) UpdateEntityScaleSet(ctx context.Context, entity params.ForgeEntity, scaleSetID uint, param params.UpdateScaleSetParams, callback func(old, newSet params.ScaleSet) error) (updatedScaleSet params.ScaleSet, err error) {
|
||||
defer func() {
|
||||
if err == nil {
|
||||
s.sendNotify(common.ScaleSetEntityType, common.UpdateOperation, updatedScaleSet)
|
||||
|
|
@ -199,22 +202,22 @@ func (s *sqlDatabase) UpdateEntityScaleSet(_ context.Context, entity params.Forg
|
|||
err = s.conn.Transaction(func(tx *gorm.DB) error {
|
||||
scaleSet, err := s.getEntityScaleSet(tx, entity.EntityType, entity.ID, scaleSetID, "Instances")
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "fetching scale set")
|
||||
return fmt.Errorf("error fetching scale set: %w", err)
|
||||
}
|
||||
|
||||
old, err := s.sqlToCommonScaleSet(scaleSet)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "converting scale set")
|
||||
return fmt.Errorf("error converting scale set: %w", err)
|
||||
}
|
||||
|
||||
updatedScaleSet, err = s.updateScaleSet(tx, scaleSet, param)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "updating scale set")
|
||||
return fmt.Errorf("error updating scale set: %w", err)
|
||||
}
|
||||
|
||||
if callback != nil {
|
||||
if err := callback(old, updatedScaleSet); err != nil {
|
||||
return errors.Wrap(err, "executing update callback")
|
||||
return fmt.Errorf("error executing update callback: %w", err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
|
@ -222,16 +225,21 @@ func (s *sqlDatabase) UpdateEntityScaleSet(_ context.Context, entity params.Forg
|
|||
if err != nil {
|
||||
return params.ScaleSet{}, err
|
||||
}
|
||||
|
||||
updatedScaleSet, err = s.GetScaleSetByID(ctx, scaleSetID)
|
||||
if err != nil {
|
||||
return params.ScaleSet{}, err
|
||||
}
|
||||
return updatedScaleSet, nil
|
||||
}
|
||||
|
||||
func (s *sqlDatabase) getEntityScaleSet(tx *gorm.DB, entityType params.ForgeEntityType, entityID string, scaleSetID uint, preload ...string) (ScaleSet, error) {
|
||||
if entityID == "" {
|
||||
return ScaleSet{}, errors.Wrap(runnerErrors.ErrBadRequest, "missing entity id")
|
||||
return ScaleSet{}, fmt.Errorf("error missing entity id: %w", runnerErrors.ErrBadRequest)
|
||||
}
|
||||
|
||||
if scaleSetID == 0 {
|
||||
return ScaleSet{}, errors.Wrap(runnerErrors.ErrBadRequest, "missing scaleset id")
|
||||
return ScaleSet{}, fmt.Errorf("error missing scaleset id: %w", runnerErrors.ErrBadRequest)
|
||||
}
|
||||
|
||||
var fieldName string
|
||||
|
|
@ -265,9 +273,9 @@ func (s *sqlDatabase) getEntityScaleSet(tx *gorm.DB, entityType params.ForgeEnti
|
|||
First(&scaleSet).Error
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return ScaleSet{}, errors.Wrap(runnerErrors.ErrNotFound, "finding scale set")
|
||||
return ScaleSet{}, fmt.Errorf("error finding scale set: %w", runnerErrors.ErrNotFound)
|
||||
}
|
||||
return ScaleSet{}, errors.Wrap(err, "fetching scale set")
|
||||
return ScaleSet{}, fmt.Errorf("error fetching scale set: %w", err)
|
||||
}
|
||||
|
||||
return scaleSet, nil
|
||||
|
|
@ -286,6 +294,10 @@ func (s *sqlDatabase) updateScaleSet(tx *gorm.DB, scaleSet ScaleSet, param param
|
|||
scaleSet.ExtendedState = *param.ExtendedState
|
||||
}
|
||||
|
||||
if param.ScaleSetID != 0 {
|
||||
scaleSet.ScaleSetID = param.ScaleSetID
|
||||
}
|
||||
|
||||
if param.Name != "" {
|
||||
scaleSet.Name = param.Name
|
||||
}
|
||||
|
|
@ -335,16 +347,26 @@ func (s *sqlDatabase) updateScaleSet(tx *gorm.DB, scaleSet ScaleSet, param param
|
|||
}
|
||||
|
||||
if q := tx.Save(&scaleSet); q.Error != nil {
|
||||
return params.ScaleSet{}, errors.Wrap(q.Error, "saving database entry")
|
||||
return params.ScaleSet{}, fmt.Errorf("error saving database entry: %w", q.Error)
|
||||
}
|
||||
|
||||
return s.sqlToCommonScaleSet(scaleSet)
|
||||
}
|
||||
|
||||
func (s *sqlDatabase) GetScaleSetByID(_ context.Context, scaleSet uint) (params.ScaleSet, error) {
|
||||
set, err := s.getScaleSetByID(s.conn, scaleSet, "Instances", "Enterprise", "Organization", "Repository")
|
||||
set, err := s.getScaleSetByID(
|
||||
s.conn,
|
||||
scaleSet,
|
||||
"Instances",
|
||||
"Enterprise",
|
||||
"Enterprise.Endpoint",
|
||||
"Organization",
|
||||
"Organization.Endpoint",
|
||||
"Repository",
|
||||
"Repository.Endpoint",
|
||||
)
|
||||
if err != nil {
|
||||
return params.ScaleSet{}, errors.Wrap(err, "fetching scale set by ID")
|
||||
return params.ScaleSet{}, fmt.Errorf("error fetching scale set by ID: %w", err)
|
||||
}
|
||||
return s.sqlToCommonScaleSet(set)
|
||||
}
|
||||
|
|
@ -359,7 +381,7 @@ func (s *sqlDatabase) DeleteScaleSetByID(_ context.Context, scaleSetID uint) (er
|
|||
err = s.conn.Transaction(func(tx *gorm.DB) error {
|
||||
dbSet, err := s.getScaleSetByID(tx, scaleSetID, "Instances", "Enterprise", "Organization", "Repository")
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "fetching scale set")
|
||||
return fmt.Errorf("error fetching scale set: %w", err)
|
||||
}
|
||||
|
||||
if len(dbSet.Instances) > 0 {
|
||||
|
|
@ -367,16 +389,16 @@ func (s *sqlDatabase) DeleteScaleSetByID(_ context.Context, scaleSetID uint) (er
|
|||
}
|
||||
scaleSet, err = s.sqlToCommonScaleSet(dbSet)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "converting scale set")
|
||||
return fmt.Errorf("error converting scale set: %w", err)
|
||||
}
|
||||
|
||||
if q := tx.Unscoped().Delete(&dbSet); q.Error != nil {
|
||||
return errors.Wrap(q.Error, "deleting scale set")
|
||||
return fmt.Errorf("error deleting scale set: %w", q.Error)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "removing scale set")
|
||||
return fmt.Errorf("error removing scale set: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
@ -389,21 +411,21 @@ func (s *sqlDatabase) SetScaleSetLastMessageID(_ context.Context, scaleSetID uin
|
|||
}
|
||||
}()
|
||||
if err := s.conn.Transaction(func(tx *gorm.DB) error {
|
||||
dbSet, err := s.getScaleSetByID(tx, scaleSetID)
|
||||
dbSet, err := s.getScaleSetByID(tx, scaleSetID, "Instances", "Enterprise", "Organization", "Repository")
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "fetching scale set")
|
||||
return fmt.Errorf("error fetching scale set: %w", err)
|
||||
}
|
||||
dbSet.LastMessageID = lastMessageID
|
||||
if err := tx.Save(&dbSet).Error; err != nil {
|
||||
return errors.Wrap(err, "saving database entry")
|
||||
return fmt.Errorf("error saving database entry: %w", err)
|
||||
}
|
||||
scaleSet, err = s.sqlToCommonScaleSet(dbSet)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "converting scale set")
|
||||
return fmt.Errorf("error converting scale set: %w", err)
|
||||
}
|
||||
return nil
|
||||
}); err != nil {
|
||||
return errors.Wrap(err, "setting last message ID")
|
||||
return fmt.Errorf("error setting last message ID: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
@ -416,21 +438,21 @@ func (s *sqlDatabase) SetScaleSetDesiredRunnerCount(_ context.Context, scaleSetI
|
|||
}
|
||||
}()
|
||||
if err := s.conn.Transaction(func(tx *gorm.DB) error {
|
||||
dbSet, err := s.getScaleSetByID(tx, scaleSetID)
|
||||
dbSet, err := s.getScaleSetByID(tx, scaleSetID, "Instances", "Enterprise", "Organization", "Repository")
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "fetching scale set")
|
||||
return fmt.Errorf("error fetching scale set: %w", err)
|
||||
}
|
||||
dbSet.DesiredRunnerCount = desiredRunnerCount
|
||||
if err := tx.Save(&dbSet).Error; err != nil {
|
||||
return errors.Wrap(err, "saving database entry")
|
||||
return fmt.Errorf("error saving database entry: %w", err)
|
||||
}
|
||||
scaleSet, err = s.sqlToCommonScaleSet(dbSet)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "converting scale set")
|
||||
return fmt.Errorf("error converting scale set: %w", err)
|
||||
}
|
||||
return nil
|
||||
}); err != nil {
|
||||
return errors.Wrap(err, "setting desired runner count")
|
||||
return fmt.Errorf("error setting desired runner count: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,12 +16,12 @@ package sql
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"gorm.io/driver/mysql"
|
||||
"gorm.io/driver/sqlite"
|
||||
"gorm.io/gorm"
|
||||
|
|
@ -46,7 +46,7 @@ const (
|
|||
func newDBConn(dbCfg config.Database) (conn *gorm.DB, err error) {
|
||||
dbType, connURI, err := dbCfg.GormParams()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "getting DB URI string")
|
||||
return nil, fmt.Errorf("error getting DB URI string: %w", err)
|
||||
}
|
||||
|
||||
gormConfig := &gorm.Config{}
|
||||
|
|
@ -61,7 +61,7 @@ func newDBConn(dbCfg config.Database) (conn *gorm.DB, err error) {
|
|||
conn, err = gorm.Open(sqlite.Open(connURI), gormConfig)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "connecting to database")
|
||||
return nil, fmt.Errorf("error connecting to database: %w", err)
|
||||
}
|
||||
|
||||
if dbCfg.Debug {
|
||||
|
|
@ -73,11 +73,11 @@ func newDBConn(dbCfg config.Database) (conn *gorm.DB, err error) {
|
|||
func NewSQLDatabase(ctx context.Context, cfg config.Database) (common.Store, error) {
|
||||
conn, err := newDBConn(cfg)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "creating DB connection")
|
||||
return nil, fmt.Errorf("error creating DB connection: %w", err)
|
||||
}
|
||||
producer, err := watcher.RegisterProducer(ctx, "sql")
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "registering producer")
|
||||
return nil, fmt.Errorf("error registering producer: %w", err)
|
||||
}
|
||||
db := &sqlDatabase{
|
||||
conn: conn,
|
||||
|
|
@ -87,7 +87,7 @@ func NewSQLDatabase(ctx context.Context, cfg config.Database) (common.Store, err
|
|||
}
|
||||
|
||||
if err := db.migrateDB(); err != nil {
|
||||
return nil, errors.Wrap(err, "migrating database")
|
||||
return nil, fmt.Errorf("error migrating database: %w", err)
|
||||
}
|
||||
return db, nil
|
||||
}
|
||||
|
|
@ -221,14 +221,14 @@ func (s *sqlDatabase) ensureGithubEndpoint() error {
|
|||
var epCount int64
|
||||
if err := s.conn.Model(&GithubEndpoint{}).Count(&epCount).Error; err != nil {
|
||||
if !errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return errors.Wrap(err, "counting github endpoints")
|
||||
return fmt.Errorf("error counting github endpoints: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
if epCount == 0 {
|
||||
if _, err := s.CreateGithubEndpoint(context.Background(), createEndpointParams); err != nil {
|
||||
if !errors.Is(err, runnerErrors.ErrDuplicateEntity) {
|
||||
return errors.Wrap(err, "creating default github endpoint")
|
||||
return fmt.Errorf("error creating default github endpoint: %w", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -246,7 +246,7 @@ func (s *sqlDatabase) migrateCredentialsToDB() (err error) {
|
|||
// Admin user doesn't exist. This is a new deploy. Nothing to migrate.
|
||||
return nil
|
||||
}
|
||||
return errors.Wrap(err, "getting admin user")
|
||||
return fmt.Errorf("error getting admin user: %w", err)
|
||||
}
|
||||
|
||||
// Impersonate the admin user. We're migrating from config credentials to
|
||||
|
|
@ -259,7 +259,7 @@ func (s *sqlDatabase) migrateCredentialsToDB() (err error) {
|
|||
slog.Info("migrating credentials to DB")
|
||||
slog.Info("creating github endpoints table")
|
||||
if err := s.conn.AutoMigrate(&GithubEndpoint{}); err != nil {
|
||||
return errors.Wrap(err, "migrating github endpoints")
|
||||
return fmt.Errorf("error migrating github endpoints: %w", err)
|
||||
}
|
||||
|
||||
defer func() {
|
||||
|
|
@ -271,7 +271,7 @@ func (s *sqlDatabase) migrateCredentialsToDB() (err error) {
|
|||
|
||||
slog.Info("creating github credentials table")
|
||||
if err := s.conn.AutoMigrate(&GithubCredentials{}); err != nil {
|
||||
return errors.Wrap(err, "migrating github credentials")
|
||||
return fmt.Errorf("error migrating github credentials: %w", err)
|
||||
}
|
||||
|
||||
defer func() {
|
||||
|
|
@ -291,12 +291,12 @@ func (s *sqlDatabase) migrateCredentialsToDB() (err error) {
|
|||
slog.Info("importing credential", "name", cred.Name)
|
||||
parsed, err := url.Parse(cred.BaseEndpoint())
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "parsing base URL")
|
||||
return fmt.Errorf("error parsing base URL: %w", err)
|
||||
}
|
||||
|
||||
certBundle, err := cred.CACertBundle()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "getting CA cert bundle")
|
||||
return fmt.Errorf("error getting CA cert bundle: %w", err)
|
||||
}
|
||||
hostname := parsed.Hostname()
|
||||
createParams := params.CreateGithubEndpointParams{
|
||||
|
|
@ -312,11 +312,11 @@ func (s *sqlDatabase) migrateCredentialsToDB() (err error) {
|
|||
endpoint, err = s.GetGithubEndpoint(adminCtx, hostname)
|
||||
if err != nil {
|
||||
if !errors.Is(err, runnerErrors.ErrNotFound) {
|
||||
return errors.Wrap(err, "getting github endpoint")
|
||||
return fmt.Errorf("error getting github endpoint: %w", err)
|
||||
}
|
||||
endpoint, err = s.CreateGithubEndpoint(adminCtx, createParams)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "creating default github endpoint")
|
||||
return fmt.Errorf("error creating default github endpoint: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -330,7 +330,7 @@ func (s *sqlDatabase) migrateCredentialsToDB() (err error) {
|
|||
case params.ForgeAuthTypeApp:
|
||||
keyBytes, err := cred.App.PrivateKeyBytes()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "getting private key bytes")
|
||||
return fmt.Errorf("error getting private key bytes: %w", err)
|
||||
}
|
||||
credParams.App = params.GithubApp{
|
||||
AppID: cred.App.AppID,
|
||||
|
|
@ -339,7 +339,7 @@ func (s *sqlDatabase) migrateCredentialsToDB() (err error) {
|
|||
}
|
||||
|
||||
if err := credParams.App.Validate(); err != nil {
|
||||
return errors.Wrap(err, "validating app credentials")
|
||||
return fmt.Errorf("error validating app credentials: %w", err)
|
||||
}
|
||||
case params.ForgeAuthTypePAT:
|
||||
token := cred.PAT.OAuth2Token
|
||||
|
|
@ -356,19 +356,35 @@ func (s *sqlDatabase) migrateCredentialsToDB() (err error) {
|
|||
|
||||
creds, err := s.CreateGithubCredentials(adminCtx, credParams)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "creating github credentials")
|
||||
return fmt.Errorf("error creating github credentials: %w", err)
|
||||
}
|
||||
|
||||
if err := s.conn.Exec("update repositories set credentials_id = ?,endpoint_name = ? where credentials_name = ?", creds.ID, creds.Endpoint.Name, creds.Name).Error; err != nil {
|
||||
return errors.Wrap(err, "updating repositories")
|
||||
return fmt.Errorf("error updating repositories: %w", err)
|
||||
}
|
||||
|
||||
if err := s.conn.Exec("update organizations set credentials_id = ?,endpoint_name = ? where credentials_name = ?", creds.ID, creds.Endpoint.Name, creds.Name).Error; err != nil {
|
||||
return errors.Wrap(err, "updating organizations")
|
||||
return fmt.Errorf("error updating organizations: %w", err)
|
||||
}
|
||||
|
||||
if err := s.conn.Exec("update enterprises set credentials_id = ?,endpoint_name = ? where credentials_name = ?", creds.ID, creds.Endpoint.Name, creds.Name).Error; err != nil {
|
||||
return errors.Wrap(err, "updating enterprises")
|
||||
return fmt.Errorf("error updating enterprises: %w", err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *sqlDatabase) migrateWorkflow() error {
|
||||
if s.conn.Migrator().HasTable(&WorkflowJob{}) {
|
||||
if s.conn.Migrator().HasColumn(&WorkflowJob{}, "runner_name") {
|
||||
// Remove jobs that are not in "queued" status. We really only care about queued jobs. Once they transition
|
||||
// to something else, we don't really consume them anyway.
|
||||
if err := s.conn.Exec("delete from workflow_jobs where status is not 'queued'").Error; err != nil {
|
||||
return fmt.Errorf("error updating workflow_jobs: %w", err)
|
||||
}
|
||||
if err := s.conn.Migrator().DropColumn(&WorkflowJob{}, "runner_name"); err != nil {
|
||||
return fmt.Errorf("error updating workflow_jobs: %w", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
|
@ -388,43 +404,34 @@ func (s *sqlDatabase) migrateDB() error {
|
|||
}
|
||||
|
||||
if err := s.cascadeMigration(); err != nil {
|
||||
return errors.Wrap(err, "running cascade migration")
|
||||
return fmt.Errorf("error running cascade migration: %w", err)
|
||||
}
|
||||
|
||||
if s.conn.Migrator().HasTable(&Pool{}) {
|
||||
if err := s.conn.Exec("update pools set repo_id=NULL where repo_id='00000000-0000-0000-0000-000000000000'").Error; err != nil {
|
||||
return errors.Wrap(err, "updating pools")
|
||||
return fmt.Errorf("error updating pools %w", err)
|
||||
}
|
||||
|
||||
if err := s.conn.Exec("update pools set org_id=NULL where org_id='00000000-0000-0000-0000-000000000000'").Error; err != nil {
|
||||
return errors.Wrap(err, "updating pools")
|
||||
return fmt.Errorf("error updating pools: %w", err)
|
||||
}
|
||||
|
||||
if err := s.conn.Exec("update pools set enterprise_id=NULL where enterprise_id='00000000-0000-0000-0000-000000000000'").Error; err != nil {
|
||||
return errors.Wrap(err, "updating pools")
|
||||
return fmt.Errorf("error updating pools: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
if s.conn.Migrator().HasTable(&WorkflowJob{}) {
|
||||
if s.conn.Migrator().HasColumn(&WorkflowJob{}, "runner_name") {
|
||||
// Remove jobs that are not in "queued" status. We really only care about queued jobs. Once they transition
|
||||
// to something else, we don't really consume them anyway.
|
||||
if err := s.conn.Exec("delete from workflow_jobs where status is not 'queued'").Error; err != nil {
|
||||
return errors.Wrap(err, "updating workflow_jobs")
|
||||
}
|
||||
if err := s.conn.Migrator().DropColumn(&WorkflowJob{}, "runner_name"); err != nil {
|
||||
return errors.Wrap(err, "updating workflow_jobs")
|
||||
}
|
||||
}
|
||||
if err := s.migrateWorkflow(); err != nil {
|
||||
return fmt.Errorf("error migrating workflows: %w", err)
|
||||
}
|
||||
|
||||
if s.conn.Migrator().HasTable(&GithubEndpoint{}) {
|
||||
if !s.conn.Migrator().HasColumn(&GithubEndpoint{}, "endpoint_type") {
|
||||
if err := s.conn.Migrator().AutoMigrate(&GithubEndpoint{}); err != nil {
|
||||
return errors.Wrap(err, "migrating github endpoints")
|
||||
return fmt.Errorf("error migrating github endpoints: %w", err)
|
||||
}
|
||||
if err := s.conn.Exec("update github_endpoints set endpoint_type = 'github' where endpoint_type is null").Error; err != nil {
|
||||
return errors.Wrap(err, "updating github endpoints")
|
||||
return fmt.Errorf("error updating github endpoints: %w", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -460,7 +467,7 @@ func (s *sqlDatabase) migrateDB() error {
|
|||
&WorkflowJob{},
|
||||
&ScaleSet{},
|
||||
); err != nil {
|
||||
return errors.Wrap(err, "running auto migrate")
|
||||
return fmt.Errorf("error running auto migrate: %w", err)
|
||||
}
|
||||
s.conn.Exec("PRAGMA foreign_keys = ON")
|
||||
|
||||
|
|
@ -468,23 +475,23 @@ func (s *sqlDatabase) migrateDB() error {
|
|||
var controller ControllerInfo
|
||||
if err := s.conn.First(&controller).Error; err != nil {
|
||||
if !errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return errors.Wrap(err, "updating controller info")
|
||||
return fmt.Errorf("error updating controller info: %w", err)
|
||||
}
|
||||
} else {
|
||||
controller.MinimumJobAgeBackoff = 30
|
||||
if err := s.conn.Save(&controller).Error; err != nil {
|
||||
return errors.Wrap(err, "updating controller info")
|
||||
return fmt.Errorf("error updating controller info: %w", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if err := s.ensureGithubEndpoint(); err != nil {
|
||||
return errors.Wrap(err, "ensuring github endpoint")
|
||||
return fmt.Errorf("error ensuring github endpoint: %w", err)
|
||||
}
|
||||
|
||||
if needsCredentialMigration {
|
||||
if err := s.migrateCredentialsToDB(); err != nil {
|
||||
return errors.Wrap(err, "migrating credentials")
|
||||
return fmt.Errorf("error migrating credentials: %w", err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
|
|
|||
|
|
@ -16,9 +16,9 @@ package sql
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"gorm.io/gorm"
|
||||
|
||||
runnerErrors "github.com/cloudbase/garm-provider-common/errors"
|
||||
|
|
@ -39,7 +39,7 @@ func (s *sqlDatabase) getUserByUsernameOrEmail(tx *gorm.DB, user string) (User,
|
|||
if errors.Is(q.Error, gorm.ErrRecordNotFound) {
|
||||
return User{}, runnerErrors.ErrNotFound
|
||||
}
|
||||
return User{}, errors.Wrap(q.Error, "fetching user")
|
||||
return User{}, fmt.Errorf("error fetching user: %w", q.Error)
|
||||
}
|
||||
return dbUser, nil
|
||||
}
|
||||
|
|
@ -51,7 +51,7 @@ func (s *sqlDatabase) getUserByID(tx *gorm.DB, userID string) (User, error) {
|
|||
if errors.Is(q.Error, gorm.ErrRecordNotFound) {
|
||||
return User{}, runnerErrors.ErrNotFound
|
||||
}
|
||||
return User{}, errors.Wrap(q.Error, "fetching user")
|
||||
return User{}, fmt.Errorf("error fetching user: %w", q.Error)
|
||||
}
|
||||
return dbUser, nil
|
||||
}
|
||||
|
|
@ -82,12 +82,12 @@ func (s *sqlDatabase) CreateUser(_ context.Context, user params.NewUserParams) (
|
|||
|
||||
q := tx.Save(&newUser)
|
||||
if q.Error != nil {
|
||||
return errors.Wrap(q.Error, "creating user")
|
||||
return fmt.Errorf("error creating user: %w", q.Error)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return params.User{}, errors.Wrap(err, "creating user")
|
||||
return params.User{}, fmt.Errorf("error creating user: %w", err)
|
||||
}
|
||||
return s.sqlToParamsUser(newUser), nil
|
||||
}
|
||||
|
|
@ -105,7 +105,7 @@ func (s *sqlDatabase) HasAdminUser(_ context.Context) bool {
|
|||
func (s *sqlDatabase) GetUser(_ context.Context, user string) (params.User, error) {
|
||||
dbUser, err := s.getUserByUsernameOrEmail(s.conn, user)
|
||||
if err != nil {
|
||||
return params.User{}, errors.Wrap(err, "fetching user")
|
||||
return params.User{}, fmt.Errorf("error fetching user: %w", err)
|
||||
}
|
||||
return s.sqlToParamsUser(dbUser), nil
|
||||
}
|
||||
|
|
@ -113,7 +113,7 @@ func (s *sqlDatabase) GetUser(_ context.Context, user string) (params.User, erro
|
|||
func (s *sqlDatabase) GetUserByID(_ context.Context, userID string) (params.User, error) {
|
||||
dbUser, err := s.getUserByID(s.conn, userID)
|
||||
if err != nil {
|
||||
return params.User{}, errors.Wrap(err, "fetching user")
|
||||
return params.User{}, fmt.Errorf("error fetching user: %w", err)
|
||||
}
|
||||
return s.sqlToParamsUser(dbUser), nil
|
||||
}
|
||||
|
|
@ -124,7 +124,7 @@ func (s *sqlDatabase) UpdateUser(_ context.Context, user string, param params.Up
|
|||
err = s.conn.Transaction(func(tx *gorm.DB) error {
|
||||
dbUser, err = s.getUserByUsernameOrEmail(tx, user)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "fetching user")
|
||||
return fmt.Errorf("error fetching user: %w", err)
|
||||
}
|
||||
|
||||
if param.FullName != "" {
|
||||
|
|
@ -141,12 +141,12 @@ func (s *sqlDatabase) UpdateUser(_ context.Context, user string, param params.Up
|
|||
}
|
||||
|
||||
if q := tx.Save(&dbUser); q.Error != nil {
|
||||
return errors.Wrap(q.Error, "saving user")
|
||||
return fmt.Errorf("error saving user: %w", q.Error)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return params.User{}, errors.Wrap(err, "updating user")
|
||||
return params.User{}, fmt.Errorf("error updating user: %w", err)
|
||||
}
|
||||
return s.sqlToParamsUser(dbUser), nil
|
||||
}
|
||||
|
|
@ -159,7 +159,7 @@ func (s *sqlDatabase) GetAdminUser(_ context.Context) (params.User, error) {
|
|||
if errors.Is(q.Error, gorm.ErrRecordNotFound) {
|
||||
return params.User{}, runnerErrors.ErrNotFound
|
||||
}
|
||||
return params.User{}, errors.Wrap(q.Error, "fetching admin user")
|
||||
return params.User{}, fmt.Errorf("error fetching admin user: %w", q.Error)
|
||||
}
|
||||
return s.sqlToParamsUser(user), nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -161,7 +161,7 @@ func (s *UserTestSuite) TestCreateUserUsernameAlreadyExist() {
|
|||
_, err := s.Store.CreateUser(context.Background(), s.Fixtures.NewUserParams)
|
||||
|
||||
s.Require().NotNil(err)
|
||||
s.Require().Equal(("creating user: username already exists"), err.Error())
|
||||
s.Require().Equal(("error creating user: username already exists"), err.Error())
|
||||
}
|
||||
|
||||
func (s *UserTestSuite) TestCreateUserEmailAlreadyExist() {
|
||||
|
|
@ -170,7 +170,7 @@ func (s *UserTestSuite) TestCreateUserEmailAlreadyExist() {
|
|||
_, err := s.Store.CreateUser(context.Background(), s.Fixtures.NewUserParams)
|
||||
|
||||
s.Require().NotNil(err)
|
||||
s.Require().Equal(("creating user: email already exists"), err.Error())
|
||||
s.Require().Equal(("error creating user: email already exists"), err.Error())
|
||||
}
|
||||
|
||||
func (s *UserTestSuite) TestCreateUserDBCreateErr() {
|
||||
|
|
@ -191,7 +191,7 @@ func (s *UserTestSuite) TestCreateUserDBCreateErr() {
|
|||
_, err := s.StoreSQLMocked.CreateUser(context.Background(), s.Fixtures.NewUserParams)
|
||||
|
||||
s.Require().NotNil(err)
|
||||
s.Require().Equal("creating user: creating user: creating user mock error", err.Error())
|
||||
s.Require().Equal("error creating user: error creating user: creating user mock error", err.Error())
|
||||
s.assertSQLMockExpectations()
|
||||
}
|
||||
|
||||
|
|
@ -230,7 +230,7 @@ func (s *UserTestSuite) TestGetUserNotFound() {
|
|||
_, err := s.Store.GetUser(context.Background(), "dummy-user")
|
||||
|
||||
s.Require().NotNil(err)
|
||||
s.Require().Equal("fetching user: not found", err.Error())
|
||||
s.Require().Equal("error fetching user: not found", err.Error())
|
||||
}
|
||||
|
||||
func (s *UserTestSuite) TestGetUserByID() {
|
||||
|
|
@ -244,7 +244,7 @@ func (s *UserTestSuite) TestGetUserByIDNotFound() {
|
|||
_, err := s.Store.GetUserByID(context.Background(), "dummy-user-id")
|
||||
|
||||
s.Require().NotNil(err)
|
||||
s.Require().Equal("fetching user: not found", err.Error())
|
||||
s.Require().Equal("error fetching user: not found", err.Error())
|
||||
}
|
||||
|
||||
func (s *UserTestSuite) TestUpdateUser() {
|
||||
|
|
@ -260,7 +260,7 @@ func (s *UserTestSuite) TestUpdateUserNotFound() {
|
|||
_, err := s.Store.UpdateUser(context.Background(), "dummy-user", s.Fixtures.UpdateUserParams)
|
||||
|
||||
s.Require().NotNil(err)
|
||||
s.Require().Equal("updating user: fetching user: not found", err.Error())
|
||||
s.Require().Equal("error updating user: error fetching user: not found", err.Error())
|
||||
}
|
||||
|
||||
func (s *UserTestSuite) TestUpdateUserDBSaveErr() {
|
||||
|
|
@ -278,7 +278,7 @@ func (s *UserTestSuite) TestUpdateUserDBSaveErr() {
|
|||
|
||||
s.assertSQLMockExpectations()
|
||||
s.Require().NotNil(err)
|
||||
s.Require().Equal("updating user: saving user: saving user mock error", err.Error())
|
||||
s.Require().Equal("error updating user: error saving user: saving user mock error", err.Error())
|
||||
}
|
||||
|
||||
func TestUserTestSuite(t *testing.T) {
|
||||
|
|
|
|||
|
|
@ -17,10 +17,10 @@ package sql
|
|||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/pkg/errors"
|
||||
"gorm.io/datatypes"
|
||||
"gorm.io/gorm"
|
||||
|
||||
|
|
@ -41,14 +41,14 @@ func (s *sqlDatabase) sqlToParamsInstance(instance Instance) (params.Instance, e
|
|||
var labels []string
|
||||
if len(instance.AditionalLabels) > 0 {
|
||||
if err := json.Unmarshal(instance.AditionalLabels, &labels); err != nil {
|
||||
return params.Instance{}, errors.Wrap(err, "unmarshalling labels")
|
||||
return params.Instance{}, fmt.Errorf("error unmarshalling labels: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
var jitConfig map[string]string
|
||||
if len(instance.JitConfiguration) > 0 {
|
||||
if err := s.unsealAndUnmarshal(instance.JitConfiguration, &jitConfig); err != nil {
|
||||
return params.Instance{}, errors.Wrap(err, "unmarshalling jit configuration")
|
||||
return params.Instance{}, fmt.Errorf("error unmarshalling jit configuration: %w", err)
|
||||
}
|
||||
}
|
||||
ret := params.Instance{
|
||||
|
|
@ -95,7 +95,7 @@ func (s *sqlDatabase) sqlToParamsInstance(instance Instance) (params.Instance, e
|
|||
if instance.Job != nil {
|
||||
paramJob, err := sqlWorkflowJobToParamsJob(*instance.Job)
|
||||
if err != nil {
|
||||
return params.Instance{}, errors.Wrap(err, "converting job")
|
||||
return params.Instance{}, fmt.Errorf("error converting job: %w", err)
|
||||
}
|
||||
ret.Job = ¶mJob
|
||||
}
|
||||
|
|
@ -132,12 +132,12 @@ func (s *sqlDatabase) sqlToCommonOrganization(org Organization, detailed bool) (
|
|||
}
|
||||
secret, err := util.Unseal(org.WebhookSecret, []byte(s.cfg.Passphrase))
|
||||
if err != nil {
|
||||
return params.Organization{}, errors.Wrap(err, "decrypting secret")
|
||||
return params.Organization{}, fmt.Errorf("error decrypting secret: %w", err)
|
||||
}
|
||||
|
||||
endpoint, err := s.sqlToCommonGithubEndpoint(org.Endpoint)
|
||||
if err != nil {
|
||||
return params.Organization{}, errors.Wrap(err, "converting endpoint")
|
||||
return params.Organization{}, fmt.Errorf("error converting endpoint: %w", err)
|
||||
}
|
||||
ret := params.Organization{
|
||||
ID: org.ID.String(),
|
||||
|
|
@ -163,7 +163,7 @@ func (s *sqlDatabase) sqlToCommonOrganization(org Organization, detailed bool) (
|
|||
}
|
||||
|
||||
if err != nil {
|
||||
return params.Organization{}, errors.Wrap(err, "converting credentials")
|
||||
return params.Organization{}, fmt.Errorf("error converting credentials: %w", err)
|
||||
}
|
||||
|
||||
if len(org.Events) > 0 {
|
||||
|
|
@ -191,7 +191,7 @@ func (s *sqlDatabase) sqlToCommonOrganization(org Organization, detailed bool) (
|
|||
for idx, pool := range org.Pools {
|
||||
ret.Pools[idx], err = s.sqlToCommonPool(pool)
|
||||
if err != nil {
|
||||
return params.Organization{}, errors.Wrap(err, "converting pool")
|
||||
return params.Organization{}, fmt.Errorf("error converting pool: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -204,12 +204,12 @@ func (s *sqlDatabase) sqlToCommonEnterprise(enterprise Enterprise, detailed bool
|
|||
}
|
||||
secret, err := util.Unseal(enterprise.WebhookSecret, []byte(s.cfg.Passphrase))
|
||||
if err != nil {
|
||||
return params.Enterprise{}, errors.Wrap(err, "decrypting secret")
|
||||
return params.Enterprise{}, fmt.Errorf("error decrypting secret: %w", err)
|
||||
}
|
||||
|
||||
endpoint, err := s.sqlToCommonGithubEndpoint(enterprise.Endpoint)
|
||||
if err != nil {
|
||||
return params.Enterprise{}, errors.Wrap(err, "converting endpoint")
|
||||
return params.Enterprise{}, fmt.Errorf("error converting endpoint: %w", err)
|
||||
}
|
||||
ret := params.Enterprise{
|
||||
ID: enterprise.ID.String(),
|
||||
|
|
@ -243,7 +243,7 @@ func (s *sqlDatabase) sqlToCommonEnterprise(enterprise Enterprise, detailed bool
|
|||
if detailed {
|
||||
creds, err := s.sqlToCommonForgeCredentials(enterprise.Credentials)
|
||||
if err != nil {
|
||||
return params.Enterprise{}, errors.Wrap(err, "converting credentials")
|
||||
return params.Enterprise{}, fmt.Errorf("error converting credentials: %w", err)
|
||||
}
|
||||
ret.Credentials = creds
|
||||
}
|
||||
|
|
@ -255,7 +255,7 @@ func (s *sqlDatabase) sqlToCommonEnterprise(enterprise Enterprise, detailed bool
|
|||
for idx, pool := range enterprise.Pools {
|
||||
ret.Pools[idx], err = s.sqlToCommonPool(pool)
|
||||
if err != nil {
|
||||
return params.Enterprise{}, errors.Wrap(err, "converting pool")
|
||||
return params.Enterprise{}, fmt.Errorf("error converting pool: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -309,7 +309,7 @@ func (s *sqlDatabase) sqlToCommonPool(pool Pool) (params.Pool, error) {
|
|||
|
||||
endpoint, err := s.sqlToCommonGithubEndpoint(ep)
|
||||
if err != nil {
|
||||
return params.Pool{}, errors.Wrap(err, "converting endpoint")
|
||||
return params.Pool{}, fmt.Errorf("error converting endpoint: %w", err)
|
||||
}
|
||||
ret.Endpoint = endpoint
|
||||
|
||||
|
|
@ -320,7 +320,7 @@ func (s *sqlDatabase) sqlToCommonPool(pool Pool) (params.Pool, error) {
|
|||
for idx, inst := range pool.Instances {
|
||||
ret.Instances[idx], err = s.sqlToParamsInstance(inst)
|
||||
if err != nil {
|
||||
return params.Pool{}, errors.Wrap(err, "converting instance")
|
||||
return params.Pool{}, fmt.Errorf("error converting instance: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -330,6 +330,8 @@ func (s *sqlDatabase) sqlToCommonPool(pool Pool) (params.Pool, error) {
|
|||
func (s *sqlDatabase) sqlToCommonScaleSet(scaleSet ScaleSet) (params.ScaleSet, error) {
|
||||
ret := params.ScaleSet{
|
||||
ID: scaleSet.ID,
|
||||
CreatedAt: scaleSet.CreatedAt,
|
||||
UpdatedAt: scaleSet.UpdatedAt,
|
||||
ScaleSetID: scaleSet.ScaleSetID,
|
||||
Name: scaleSet.Name,
|
||||
DisableUpdate: scaleSet.DisableUpdate,
|
||||
|
|
@ -355,28 +357,37 @@ func (s *sqlDatabase) sqlToCommonScaleSet(scaleSet ScaleSet) (params.ScaleSet, e
|
|||
DesiredRunnerCount: scaleSet.DesiredRunnerCount,
|
||||
}
|
||||
|
||||
var ep GithubEndpoint
|
||||
if scaleSet.RepoID != nil {
|
||||
ret.RepoID = scaleSet.RepoID.String()
|
||||
if scaleSet.Repository.Owner != "" && scaleSet.Repository.Name != "" {
|
||||
ret.RepoName = fmt.Sprintf("%s/%s", scaleSet.Repository.Owner, scaleSet.Repository.Name)
|
||||
}
|
||||
ep = scaleSet.Repository.Endpoint
|
||||
}
|
||||
|
||||
if scaleSet.OrgID != nil && scaleSet.Organization.Name != "" {
|
||||
if scaleSet.OrgID != nil {
|
||||
ret.OrgID = scaleSet.OrgID.String()
|
||||
ret.OrgName = scaleSet.Organization.Name
|
||||
ep = scaleSet.Organization.Endpoint
|
||||
}
|
||||
|
||||
if scaleSet.EnterpriseID != nil && scaleSet.Enterprise.Name != "" {
|
||||
if scaleSet.EnterpriseID != nil {
|
||||
ret.EnterpriseID = scaleSet.EnterpriseID.String()
|
||||
ret.EnterpriseName = scaleSet.Enterprise.Name
|
||||
ep = scaleSet.Enterprise.Endpoint
|
||||
}
|
||||
|
||||
var err error
|
||||
endpoint, err := s.sqlToCommonGithubEndpoint(ep)
|
||||
if err != nil {
|
||||
return params.ScaleSet{}, fmt.Errorf("error converting endpoint: %w", err)
|
||||
}
|
||||
ret.Endpoint = endpoint
|
||||
|
||||
for idx, inst := range scaleSet.Instances {
|
||||
ret.Instances[idx], err = s.sqlToParamsInstance(inst)
|
||||
if err != nil {
|
||||
return params.ScaleSet{}, errors.Wrap(err, "converting instance")
|
||||
return params.ScaleSet{}, fmt.Errorf("error converting instance: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -396,11 +407,11 @@ func (s *sqlDatabase) sqlToCommonRepository(repo Repository, detailed bool) (par
|
|||
}
|
||||
secret, err := util.Unseal(repo.WebhookSecret, []byte(s.cfg.Passphrase))
|
||||
if err != nil {
|
||||
return params.Repository{}, errors.Wrap(err, "decrypting secret")
|
||||
return params.Repository{}, fmt.Errorf("error decrypting secret: %w", err)
|
||||
}
|
||||
endpoint, err := s.sqlToCommonGithubEndpoint(repo.Endpoint)
|
||||
if err != nil {
|
||||
return params.Repository{}, errors.Wrap(err, "converting endpoint")
|
||||
return params.Repository{}, fmt.Errorf("error converting endpoint: %w", err)
|
||||
}
|
||||
ret := params.Repository{
|
||||
ID: repo.ID.String(),
|
||||
|
|
@ -431,7 +442,7 @@ func (s *sqlDatabase) sqlToCommonRepository(repo Repository, detailed bool) (par
|
|||
}
|
||||
|
||||
if err != nil {
|
||||
return params.Repository{}, errors.Wrap(err, "converting credentials")
|
||||
return params.Repository{}, fmt.Errorf("error converting credentials: %w", err)
|
||||
}
|
||||
|
||||
if len(repo.Events) > 0 {
|
||||
|
|
@ -459,7 +470,7 @@ func (s *sqlDatabase) sqlToCommonRepository(repo Repository, detailed bool) (par
|
|||
for idx, pool := range repo.Pools {
|
||||
ret.Pools[idx], err = s.sqlToCommonPool(pool)
|
||||
if err != nil {
|
||||
return params.Repository{}, errors.Wrap(err, "converting pool")
|
||||
return params.Repository{}, fmt.Errorf("error converting pool: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -488,14 +499,14 @@ func (s *sqlDatabase) getOrCreateTag(tx *gorm.DB, tagName string) (Tag, error) {
|
|||
return tag, nil
|
||||
}
|
||||
if !errors.Is(q.Error, gorm.ErrRecordNotFound) {
|
||||
return Tag{}, errors.Wrap(q.Error, "fetching tag from database")
|
||||
return Tag{}, fmt.Errorf("error fetching tag from database: %w", q.Error)
|
||||
}
|
||||
newTag := Tag{
|
||||
Name: tagName,
|
||||
}
|
||||
|
||||
if err := tx.Create(&newTag).Error; err != nil {
|
||||
return Tag{}, errors.Wrap(err, "creating tag")
|
||||
return Tag{}, fmt.Errorf("error creating tag: %w", err)
|
||||
}
|
||||
return newTag, nil
|
||||
}
|
||||
|
|
@ -550,7 +561,7 @@ func (s *sqlDatabase) updatePool(tx *gorm.DB, pool Pool, param params.UpdatePool
|
|||
}
|
||||
|
||||
if q := tx.Save(&pool); q.Error != nil {
|
||||
return params.Pool{}, errors.Wrap(q.Error, "saving database entry")
|
||||
return params.Pool{}, fmt.Errorf("error saving database entry: %w", q.Error)
|
||||
}
|
||||
|
||||
tags := []Tag{}
|
||||
|
|
@ -558,13 +569,13 @@ func (s *sqlDatabase) updatePool(tx *gorm.DB, pool Pool, param params.UpdatePool
|
|||
for _, val := range param.Tags {
|
||||
t, err := s.getOrCreateTag(tx, val)
|
||||
if err != nil {
|
||||
return params.Pool{}, errors.Wrap(err, "fetching tag")
|
||||
return params.Pool{}, fmt.Errorf("error fetching tag: %w", err)
|
||||
}
|
||||
tags = append(tags, t)
|
||||
}
|
||||
|
||||
if err := tx.Model(&pool).Association("Tags").Replace(&tags); err != nil {
|
||||
return params.Pool{}, errors.Wrap(err, "replacing tags")
|
||||
return params.Pool{}, fmt.Errorf("error replacing tags: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -574,7 +585,7 @@ func (s *sqlDatabase) updatePool(tx *gorm.DB, pool Pool, param params.UpdatePool
|
|||
func (s *sqlDatabase) getPoolByID(tx *gorm.DB, poolID string, preload ...string) (Pool, error) {
|
||||
u, err := uuid.Parse(poolID)
|
||||
if err != nil {
|
||||
return Pool{}, errors.Wrap(runnerErrors.ErrBadRequest, "parsing id")
|
||||
return Pool{}, fmt.Errorf("error parsing id: %w", runnerErrors.ErrBadRequest)
|
||||
}
|
||||
var pool Pool
|
||||
q := tx.Model(&Pool{})
|
||||
|
|
@ -590,7 +601,7 @@ func (s *sqlDatabase) getPoolByID(tx *gorm.DB, poolID string, preload ...string)
|
|||
if errors.Is(q.Error, gorm.ErrRecordNotFound) {
|
||||
return Pool{}, runnerErrors.ErrNotFound
|
||||
}
|
||||
return Pool{}, errors.Wrap(q.Error, "fetching org from database")
|
||||
return Pool{}, fmt.Errorf("error fetching org from database: %w", q.Error)
|
||||
}
|
||||
return pool, nil
|
||||
}
|
||||
|
|
@ -610,7 +621,7 @@ func (s *sqlDatabase) getScaleSetByID(tx *gorm.DB, scaleSetID uint, preload ...s
|
|||
if errors.Is(q.Error, gorm.ErrRecordNotFound) {
|
||||
return ScaleSet{}, runnerErrors.ErrNotFound
|
||||
}
|
||||
return ScaleSet{}, errors.Wrap(q.Error, "fetching scale set from database")
|
||||
return ScaleSet{}, fmt.Errorf("error fetching scale set from database: %w", q.Error)
|
||||
}
|
||||
return scaleSet, nil
|
||||
}
|
||||
|
|
@ -618,7 +629,7 @@ func (s *sqlDatabase) getScaleSetByID(tx *gorm.DB, scaleSetID uint, preload ...s
|
|||
func (s *sqlDatabase) hasGithubEntity(tx *gorm.DB, entityType params.ForgeEntityType, entityID string) error {
|
||||
u, err := uuid.Parse(entityID)
|
||||
if err != nil {
|
||||
return errors.Wrap(runnerErrors.ErrBadRequest, "parsing id")
|
||||
return fmt.Errorf("error parsing id: %w", runnerErrors.ErrBadRequest)
|
||||
}
|
||||
var q *gorm.DB
|
||||
switch entityType {
|
||||
|
|
@ -629,15 +640,15 @@ func (s *sqlDatabase) hasGithubEntity(tx *gorm.DB, entityType params.ForgeEntity
|
|||
case params.ForgeEntityTypeEnterprise:
|
||||
q = tx.Model(&Enterprise{}).Where("id = ?", u)
|
||||
default:
|
||||
return errors.Wrap(runnerErrors.ErrBadRequest, "invalid entity type")
|
||||
return fmt.Errorf("error invalid entity type: %w", runnerErrors.ErrBadRequest)
|
||||
}
|
||||
|
||||
var entity interface{}
|
||||
if err := q.First(entity).Error; err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return errors.Wrap(runnerErrors.ErrNotFound, "entity not found")
|
||||
return fmt.Errorf("error entity not found: %w", runnerErrors.ErrNotFound)
|
||||
}
|
||||
return errors.Wrap(err, "fetching entity from database")
|
||||
return fmt.Errorf("error fetching entity from database: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
@ -645,7 +656,7 @@ func (s *sqlDatabase) hasGithubEntity(tx *gorm.DB, entityType params.ForgeEntity
|
|||
func (s *sqlDatabase) marshalAndSeal(data interface{}) ([]byte, error) {
|
||||
enc, err := json.Marshal(data)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "marshalling data")
|
||||
return nil, fmt.Errorf("error marshalling data: %w", err)
|
||||
}
|
||||
return util.Seal(enc, []byte(s.cfg.Passphrase))
|
||||
}
|
||||
|
|
@ -653,10 +664,10 @@ func (s *sqlDatabase) marshalAndSeal(data interface{}) ([]byte, error) {
|
|||
func (s *sqlDatabase) unsealAndUnmarshal(data []byte, target interface{}) error {
|
||||
decrypted, err := util.Unseal(data, []byte(s.cfg.Passphrase))
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "decrypting data")
|
||||
return fmt.Errorf("error decrypting data: %w", err)
|
||||
}
|
||||
if err := json.Unmarshal(decrypted, target); err != nil {
|
||||
return errors.Wrap(err, "unmarshalling data")
|
||||
return fmt.Errorf("error unmarshalling data: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
@ -688,15 +699,15 @@ func (s *sqlDatabase) GetForgeEntity(_ context.Context, entityType params.ForgeE
|
|||
case params.ForgeEntityTypeRepository:
|
||||
ghEntity, err = s.GetRepositoryByID(s.ctx, entityID)
|
||||
default:
|
||||
return params.ForgeEntity{}, errors.Wrap(runnerErrors.ErrBadRequest, "invalid entity type")
|
||||
return params.ForgeEntity{}, fmt.Errorf("error invalid entity type: %w", runnerErrors.ErrBadRequest)
|
||||
}
|
||||
if err != nil {
|
||||
return params.ForgeEntity{}, errors.Wrap(err, "failed to get ")
|
||||
return params.ForgeEntity{}, fmt.Errorf("error failed to get entity from db: %w", err)
|
||||
}
|
||||
|
||||
entity, err := ghEntity.GetEntity()
|
||||
if err != nil {
|
||||
return params.ForgeEntity{}, errors.Wrap(err, "failed to get entity")
|
||||
return params.ForgeEntity{}, fmt.Errorf("error failed to get entity: %w", err)
|
||||
}
|
||||
return entity, nil
|
||||
}
|
||||
|
|
@ -704,7 +715,7 @@ func (s *sqlDatabase) GetForgeEntity(_ context.Context, entityType params.ForgeE
|
|||
func (s *sqlDatabase) addRepositoryEvent(ctx context.Context, repoID string, event params.EventType, eventLevel params.EventLevel, statusMessage string, maxEvents int) error {
|
||||
repo, err := s.getRepoByID(ctx, s.conn, repoID)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "updating instance")
|
||||
return fmt.Errorf("error updating instance: %w", err)
|
||||
}
|
||||
|
||||
msg := RepositoryEvent{
|
||||
|
|
@ -714,7 +725,7 @@ func (s *sqlDatabase) addRepositoryEvent(ctx context.Context, repoID string, eve
|
|||
}
|
||||
|
||||
if err := s.conn.Model(&repo).Association("Events").Append(&msg); err != nil {
|
||||
return errors.Wrap(err, "adding status message")
|
||||
return fmt.Errorf("error adding status message: %w", err)
|
||||
}
|
||||
|
||||
if maxEvents > 0 {
|
||||
|
|
@ -723,12 +734,12 @@ func (s *sqlDatabase) addRepositoryEvent(ctx context.Context, repoID string, eve
|
|||
Limit(maxEvents).Order("id desc").
|
||||
Where("repo_id = ?", repo.ID).Find(&latestEvents)
|
||||
if q.Error != nil {
|
||||
return errors.Wrap(q.Error, "fetching latest events")
|
||||
return fmt.Errorf("error fetching latest events: %w", q.Error)
|
||||
}
|
||||
if len(latestEvents) == maxEvents {
|
||||
lastInList := latestEvents[len(latestEvents)-1]
|
||||
if err := s.conn.Where("repo_id = ? and id < ?", repo.ID, lastInList.ID).Unscoped().Delete(&RepositoryEvent{}).Error; err != nil {
|
||||
return errors.Wrap(err, "deleting old events")
|
||||
return fmt.Errorf("error deleting old events: %w", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -738,7 +749,7 @@ func (s *sqlDatabase) addRepositoryEvent(ctx context.Context, repoID string, eve
|
|||
func (s *sqlDatabase) addOrgEvent(ctx context.Context, orgID string, event params.EventType, eventLevel params.EventLevel, statusMessage string, maxEvents int) error {
|
||||
org, err := s.getOrgByID(ctx, s.conn, orgID)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "updating instance")
|
||||
return fmt.Errorf("error updating instance: %w", err)
|
||||
}
|
||||
|
||||
msg := OrganizationEvent{
|
||||
|
|
@ -748,7 +759,7 @@ func (s *sqlDatabase) addOrgEvent(ctx context.Context, orgID string, event param
|
|||
}
|
||||
|
||||
if err := s.conn.Model(&org).Association("Events").Append(&msg); err != nil {
|
||||
return errors.Wrap(err, "adding status message")
|
||||
return fmt.Errorf("error adding status message: %w", err)
|
||||
}
|
||||
|
||||
if maxEvents > 0 {
|
||||
|
|
@ -757,12 +768,12 @@ func (s *sqlDatabase) addOrgEvent(ctx context.Context, orgID string, event param
|
|||
Limit(maxEvents).Order("id desc").
|
||||
Where("org_id = ?", org.ID).Find(&latestEvents)
|
||||
if q.Error != nil {
|
||||
return errors.Wrap(q.Error, "fetching latest events")
|
||||
return fmt.Errorf("error fetching latest events: %w", q.Error)
|
||||
}
|
||||
if len(latestEvents) == maxEvents {
|
||||
lastInList := latestEvents[len(latestEvents)-1]
|
||||
if err := s.conn.Where("org_id = ? and id < ?", org.ID, lastInList.ID).Unscoped().Delete(&OrganizationEvent{}).Error; err != nil {
|
||||
return errors.Wrap(err, "deleting old events")
|
||||
return fmt.Errorf("error deleting old events: %w", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -772,7 +783,7 @@ func (s *sqlDatabase) addOrgEvent(ctx context.Context, orgID string, event param
|
|||
func (s *sqlDatabase) addEnterpriseEvent(ctx context.Context, entID string, event params.EventType, eventLevel params.EventLevel, statusMessage string, maxEvents int) error {
|
||||
ent, err := s.getEnterpriseByID(ctx, s.conn, entID)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "updating instance")
|
||||
return fmt.Errorf("error updating instance: %w", err)
|
||||
}
|
||||
|
||||
msg := EnterpriseEvent{
|
||||
|
|
@ -782,7 +793,7 @@ func (s *sqlDatabase) addEnterpriseEvent(ctx context.Context, entID string, even
|
|||
}
|
||||
|
||||
if err := s.conn.Model(&ent).Association("Events").Append(&msg); err != nil {
|
||||
return errors.Wrap(err, "adding status message")
|
||||
return fmt.Errorf("error adding status message: %w", err)
|
||||
}
|
||||
|
||||
if maxEvents > 0 {
|
||||
|
|
@ -791,12 +802,12 @@ func (s *sqlDatabase) addEnterpriseEvent(ctx context.Context, entID string, even
|
|||
Limit(maxEvents).Order("id desc").
|
||||
Where("enterprise_id = ?", ent.ID).Find(&latestEvents)
|
||||
if q.Error != nil {
|
||||
return errors.Wrap(q.Error, "fetching latest events")
|
||||
return fmt.Errorf("error fetching latest events: %w", q.Error)
|
||||
}
|
||||
if len(latestEvents) == maxEvents {
|
||||
lastInList := latestEvents[len(latestEvents)-1]
|
||||
if err := s.conn.Where("enterprise_id = ? and id < ?", ent.ID, lastInList.ID).Unscoped().Delete(&EnterpriseEvent{}).Error; err != nil {
|
||||
return errors.Wrap(err, "deleting old events")
|
||||
return fmt.Errorf("error deleting old events: %w", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -806,7 +817,7 @@ func (s *sqlDatabase) addEnterpriseEvent(ctx context.Context, entID string, even
|
|||
|
||||
func (s *sqlDatabase) AddEntityEvent(ctx context.Context, entity params.ForgeEntity, event params.EventType, eventLevel params.EventLevel, statusMessage string, maxEvents int) error {
|
||||
if maxEvents == 0 {
|
||||
return errors.Wrap(runnerErrors.ErrBadRequest, "max events cannot be 0")
|
||||
return fmt.Errorf("max events cannot be 0: %w", runnerErrors.ErrBadRequest)
|
||||
}
|
||||
|
||||
switch entity.EntityType {
|
||||
|
|
@ -817,7 +828,7 @@ func (s *sqlDatabase) AddEntityEvent(ctx context.Context, entity params.ForgeEnt
|
|||
case params.ForgeEntityTypeEnterprise:
|
||||
return s.addEnterpriseEvent(ctx, entity.ID, event, eventLevel, statusMessage, maxEvents)
|
||||
default:
|
||||
return errors.Wrap(runnerErrors.ErrBadRequest, "invalid entity type")
|
||||
return fmt.Errorf("invalid entity type: %w", runnerErrors.ErrBadRequest)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -827,12 +838,12 @@ func (s *sqlDatabase) sqlToCommonForgeCredentials(creds GithubCredentials) (para
|
|||
}
|
||||
data, err := util.Unseal(creds.Payload, []byte(s.cfg.Passphrase))
|
||||
if err != nil {
|
||||
return params.ForgeCredentials{}, errors.Wrap(err, "unsealing credentials")
|
||||
return params.ForgeCredentials{}, fmt.Errorf("error unsealing credentials: %w", err)
|
||||
}
|
||||
|
||||
ep, err := s.sqlToCommonGithubEndpoint(creds.Endpoint)
|
||||
if err != nil {
|
||||
return params.ForgeCredentials{}, errors.Wrap(err, "converting github endpoint")
|
||||
return params.ForgeCredentials{}, fmt.Errorf("error converting github endpoint: %w", err)
|
||||
}
|
||||
|
||||
commonCreds := params.ForgeCredentials{
|
||||
|
|
@ -854,7 +865,7 @@ func (s *sqlDatabase) sqlToCommonForgeCredentials(creds GithubCredentials) (para
|
|||
for _, repo := range creds.Repositories {
|
||||
commonRepo, err := s.sqlToCommonRepository(repo, false)
|
||||
if err != nil {
|
||||
return params.ForgeCredentials{}, errors.Wrap(err, "converting github repository")
|
||||
return params.ForgeCredentials{}, fmt.Errorf("error converting github repository: %w", err)
|
||||
}
|
||||
commonCreds.Repositories = append(commonCreds.Repositories, commonRepo)
|
||||
}
|
||||
|
|
@ -862,7 +873,7 @@ func (s *sqlDatabase) sqlToCommonForgeCredentials(creds GithubCredentials) (para
|
|||
for _, org := range creds.Organizations {
|
||||
commonOrg, err := s.sqlToCommonOrganization(org, false)
|
||||
if err != nil {
|
||||
return params.ForgeCredentials{}, errors.Wrap(err, "converting github organization")
|
||||
return params.ForgeCredentials{}, fmt.Errorf("error converting github organization: %w", err)
|
||||
}
|
||||
commonCreds.Organizations = append(commonCreds.Organizations, commonOrg)
|
||||
}
|
||||
|
|
@ -870,7 +881,7 @@ func (s *sqlDatabase) sqlToCommonForgeCredentials(creds GithubCredentials) (para
|
|||
for _, ent := range creds.Enterprises {
|
||||
commonEnt, err := s.sqlToCommonEnterprise(ent, false)
|
||||
if err != nil {
|
||||
return params.ForgeCredentials{}, errors.Wrapf(err, "converting github enterprise: %s", ent.Name)
|
||||
return params.ForgeCredentials{}, fmt.Errorf("error converting github enterprise %s: %w", ent.Name, err)
|
||||
}
|
||||
commonCreds.Enterprises = append(commonCreds.Enterprises, commonEnt)
|
||||
}
|
||||
|
|
@ -884,12 +895,12 @@ func (s *sqlDatabase) sqlGiteaToCommonForgeCredentials(creds GiteaCredentials) (
|
|||
}
|
||||
data, err := util.Unseal(creds.Payload, []byte(s.cfg.Passphrase))
|
||||
if err != nil {
|
||||
return params.ForgeCredentials{}, errors.Wrap(err, "unsealing credentials")
|
||||
return params.ForgeCredentials{}, fmt.Errorf("error unsealing credentials: %w", err)
|
||||
}
|
||||
|
||||
ep, err := s.sqlToCommonGithubEndpoint(creds.Endpoint)
|
||||
if err != nil {
|
||||
return params.ForgeCredentials{}, errors.Wrap(err, "converting github endpoint")
|
||||
return params.ForgeCredentials{}, fmt.Errorf("error converting github endpoint: %w", err)
|
||||
}
|
||||
|
||||
commonCreds := params.ForgeCredentials{
|
||||
|
|
@ -910,7 +921,7 @@ func (s *sqlDatabase) sqlGiteaToCommonForgeCredentials(creds GiteaCredentials) (
|
|||
for _, repo := range creds.Repositories {
|
||||
commonRepo, err := s.sqlToCommonRepository(repo, false)
|
||||
if err != nil {
|
||||
return params.ForgeCredentials{}, errors.Wrap(err, "converting github repository")
|
||||
return params.ForgeCredentials{}, fmt.Errorf("error converting github repository: %w", err)
|
||||
}
|
||||
commonCreds.Repositories = append(commonCreds.Repositories, commonRepo)
|
||||
}
|
||||
|
|
@ -918,7 +929,7 @@ func (s *sqlDatabase) sqlGiteaToCommonForgeCredentials(creds GiteaCredentials) (
|
|||
for _, org := range creds.Organizations {
|
||||
commonOrg, err := s.sqlToCommonOrganization(org, false)
|
||||
if err != nil {
|
||||
return params.ForgeCredentials{}, errors.Wrap(err, "converting github organization")
|
||||
return params.ForgeCredentials{}, fmt.Errorf("error converting github organization: %w", err)
|
||||
}
|
||||
commonCreds.Organizations = append(commonCreds.Organizations, commonOrg)
|
||||
}
|
||||
|
|
@ -943,12 +954,12 @@ func (s *sqlDatabase) sqlToCommonGithubEndpoint(ep GithubEndpoint) (params.Forge
|
|||
func getUIDFromContext(ctx context.Context) (uuid.UUID, error) {
|
||||
userID := auth.UserID(ctx)
|
||||
if userID == "" {
|
||||
return uuid.Nil, errors.Wrap(runnerErrors.ErrUnauthorized, "getting UID from context")
|
||||
return uuid.Nil, fmt.Errorf("error getting UID from context: %w", runnerErrors.ErrUnauthorized)
|
||||
}
|
||||
|
||||
asUUID, err := uuid.Parse(userID)
|
||||
if err != nil {
|
||||
return uuid.Nil, errors.Wrap(runnerErrors.ErrUnauthorized, "parsing UID from context")
|
||||
return uuid.Nil, fmt.Errorf("error parsing UID from context: %w", runnerErrors.ErrUnauthorized)
|
||||
}
|
||||
return asUUID, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,11 +16,10 @@ package watcher
|
|||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"sync"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/cloudbase/garm/database/common"
|
||||
garmUtil "github.com/cloudbase/garm/util"
|
||||
)
|
||||
|
|
@ -83,7 +82,7 @@ func (w *watcher) RegisterProducer(ctx context.Context, id string) (common.Produ
|
|||
defer w.mux.Unlock()
|
||||
|
||||
if _, ok := w.producers[id]; ok {
|
||||
return nil, errors.Wrapf(common.ErrProducerAlreadyRegistered, "producer_id: %s", id)
|
||||
return nil, fmt.Errorf("producer_id %s: %w", id, common.ErrProducerAlreadyRegistered)
|
||||
}
|
||||
p := &producer{
|
||||
id: id,
|
||||
|
|
|
|||
|
|
@ -50,12 +50,12 @@ func (s *WatcherStoreTestSuite) TestJobWatcher() {
|
|||
consumeEvents(consumer)
|
||||
|
||||
jobParams := params.Job{
|
||||
ID: 1,
|
||||
RunID: 2,
|
||||
Action: "test-action",
|
||||
Conclusion: "started",
|
||||
Status: "in_progress",
|
||||
Name: "test-job",
|
||||
WorkflowJobID: 2,
|
||||
RunID: 2,
|
||||
Action: "test-action",
|
||||
Conclusion: "started",
|
||||
Status: "in_progress",
|
||||
Name: "test-job",
|
||||
}
|
||||
|
||||
job, err := s.store.CreateOrUpdateJob(s.ctx, jobParams)
|
||||
|
|
@ -76,8 +76,8 @@ func (s *WatcherStoreTestSuite) TestJobWatcher() {
|
|||
s.T().Fatal("expected payload not received")
|
||||
}
|
||||
|
||||
jobParams.Conclusion = "success"
|
||||
updatedJob, err := s.store.CreateOrUpdateJob(s.ctx, jobParams)
|
||||
job.Conclusion = "success"
|
||||
updatedJob, err := s.store.CreateOrUpdateJob(s.ctx, job)
|
||||
s.Require().NoError(err)
|
||||
|
||||
select {
|
||||
|
|
@ -94,7 +94,7 @@ func (s *WatcherStoreTestSuite) TestJobWatcher() {
|
|||
entityID, err := uuid.NewUUID()
|
||||
s.Require().NoError(err)
|
||||
|
||||
err = s.store.LockJob(s.ctx, updatedJob.ID, entityID.String())
|
||||
err = s.store.LockJob(s.ctx, updatedJob.WorkflowJobID, entityID.String())
|
||||
s.Require().NoError(err)
|
||||
|
||||
select {
|
||||
|
|
@ -110,7 +110,7 @@ func (s *WatcherStoreTestSuite) TestJobWatcher() {
|
|||
s.T().Fatal("expected payload not received")
|
||||
}
|
||||
|
||||
err = s.store.UnlockJob(s.ctx, updatedJob.ID, entityID.String())
|
||||
err = s.store.UnlockJob(s.ctx, updatedJob.WorkflowJobID, entityID.String())
|
||||
s.Require().NoError(err)
|
||||
|
||||
select {
|
||||
|
|
@ -134,7 +134,7 @@ func (s *WatcherStoreTestSuite) TestJobWatcher() {
|
|||
// We don't care about the update event here.
|
||||
consumeEvents(consumer)
|
||||
|
||||
err = s.store.BreakLockJobIsQueued(s.ctx, updatedJob.ID)
|
||||
err = s.store.BreakLockJobIsQueued(s.ctx, updatedJob.WorkflowJobID)
|
||||
s.Require().NoError(err)
|
||||
|
||||
select {
|
||||
|
|
@ -600,6 +600,11 @@ func (s *WatcherStoreTestSuite) TestScaleSetWatcher() {
|
|||
// We updated last message ID and desired runner count above.
|
||||
updatedScaleSet.DesiredRunnerCount = 5
|
||||
updatedScaleSet.LastMessageID = 99
|
||||
payloadFromEvent, ok := event.Payload.(params.ScaleSet)
|
||||
s.Require().True(ok)
|
||||
updatedScaleSet.UpdatedAt = payloadFromEvent.UpdatedAt
|
||||
updatedScaleSet.CreatedAt = payloadFromEvent.CreatedAt
|
||||
updatedScaleSet.Endpoint = params.ForgeEndpoint{}
|
||||
s.Require().Equal(common.ChangePayload{
|
||||
EntityType: common.ScaleSetEntityType,
|
||||
Operation: common.DeleteOperation,
|
||||
|
|
|
|||
|
|
@ -17,11 +17,11 @@ package watcher_test
|
|||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/stretchr/testify/suite"
|
||||
|
||||
commonParams "github.com/cloudbase/garm-provider-common/params"
|
||||
|
|
@ -310,7 +310,7 @@ func maybeInitController(db common.Store) error {
|
|||
}
|
||||
|
||||
if _, err := db.InitController(); err != nil {
|
||||
return errors.Wrap(err, "initializing controller")
|
||||
return fmt.Errorf("error initializing controller: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
|
|
|||
|
|
@ -6,12 +6,13 @@ First, clone the repository:
|
|||
|
||||
```bash
|
||||
git clone https://github.com/cloudbase/garm
|
||||
cd garm
|
||||
```
|
||||
|
||||
Then build garm:
|
||||
|
||||
```bash
|
||||
make
|
||||
make build
|
||||
```
|
||||
|
||||
You should now have both `garm` and `garm-cli` available in the `./bin` folder.
|
||||
|
|
@ -22,4 +23,65 @@ If you have docker/podman installed, you can also build a static binary against
|
|||
make build-static
|
||||
```
|
||||
|
||||
This command will also build for both AMD64 and ARM64. Resulting binaries will be in the `./bin` folder.
|
||||
This command will also build for both AMD64 and ARM64. Resulting binaries will be in the `./bin` folder.
|
||||
|
||||
## Hacking
|
||||
|
||||
If you're hacking on GARM and want to override the default version GARM injects, you can run the following command:
|
||||
|
||||
```bash
|
||||
VERSION=v1.0.0 make build
|
||||
```
|
||||
|
||||
> [!IMPORTANT]
|
||||
> This only works for `make build`. The `make build-static` command does not support version overrides.
|
||||
|
||||
## The Web UI SPA
|
||||
|
||||
GARM now ships with a single page application. The application is written in svelte and tailwind CSS. To rebuild it or hack on it, you will need a number of dependencies installed and placed in your `$PATH`.
|
||||
|
||||
### Prerequisites
|
||||
|
||||
- **Node.js 24+** and **npm**
|
||||
- **Go 1.21+** (for building the GARM backend)
|
||||
- **openapi-generator-cli** in your PATH (for API client generation)
|
||||
|
||||
### Installing openapi-generator-cli
|
||||
|
||||
**Option 1: NPM Global Install**
|
||||
```bash
|
||||
npm install -g @openapitools/openapi-generator-cli
|
||||
```
|
||||
|
||||
**Option 2: Manual Install**
|
||||
Download from [OpenAPI Generator releases](https://github.com/OpenAPITools/openapi-generator/releases) and add to your PATH.
|
||||
|
||||
**Verify Installation:**
|
||||
|
||||
```bash
|
||||
openapi-generator-cli version
|
||||
```
|
||||
|
||||
|
||||
|
||||
### Hacking on the Web UI
|
||||
|
||||
If you need to change something in the `webapp/src` folder, make sure to rebuild the webapp before rebuilding GARM:
|
||||
|
||||
```bash
|
||||
make build-webui
|
||||
make build
|
||||
```
|
||||
|
||||
> [!IMPORTANT]
|
||||
> The Web UI that GARM ships with has `go generate` stanzas that require `@openapitools/openapi-generator-cli` and `tailwindcss` to be installed. You will also have to make sure that if you change API models, the Web UI still works, as adding new fields or changing the json tags of old fields will change accessors in the client code.
|
||||
|
||||
### Changing API models
|
||||
|
||||
If you need to change the models in the `params/` package, you will also need to regenerate the client both for garm-cli and for the web application we ship with GARM. To do this, you can run:
|
||||
|
||||
```bash
|
||||
make generate
|
||||
```
|
||||
|
||||
You will also need to make sure that the web app still works.
|
||||
|
|
|
|||
|
|
@ -473,6 +473,8 @@ The config options are fairly straight forward.
|
|||
certificate = ""
|
||||
# The path on disk to the corresponding private key for the certificate.
|
||||
key = ""
|
||||
[apiserver.webui]
|
||||
enable = true
|
||||
```
|
||||
|
||||
The GARM API server has the option to enable TLS, but I suggest you use a reverse proxy and enable TLS termination in that reverse proxy. There is an `nginx` sample in this repository with TLS termination enabled.
|
||||
|
|
|
|||
|
|
@ -88,7 +88,9 @@ The filter is defined as a JSON that you write over the websocket connections. T
|
|||
"job",
|
||||
"controller",
|
||||
"github_credentials",
|
||||
"github_endpoint"
|
||||
"gitea_credentials",
|
||||
"github_endpoint",
|
||||
"scaleset"
|
||||
],
|
||||
"title": "entity type",
|
||||
"description": "The type of entity to filter on",
|
||||
|
|
|
|||
|
|
@ -346,7 +346,7 @@ garm-cli pool add \
|
|||
You should now see 1 runner being spun up in LXD. You can check the status of the pool by doing:
|
||||
|
||||
```bash
|
||||
garm-cli runner ls -a
|
||||
garm-cli runner ls
|
||||
```
|
||||
|
||||
To get more details about the runner, run:
|
||||
|
|
|
|||
|
|
@ -61,6 +61,9 @@ time_to_live = "8760h"
|
|||
bind = "0.0.0.0"
|
||||
port = 80
|
||||
use_tls = false
|
||||
[apiserver.webui]
|
||||
# Set this to false if you want to disable the Web UI.
|
||||
enable = true
|
||||
|
||||
[database]
|
||||
backend = "sqlite3"
|
||||
|
|
@ -133,7 +136,7 @@ docker run -d \
|
|||
-p 80:80 \
|
||||
-v /etc/garm:/etc/garm:rw \
|
||||
-v /var/snap/lxd/common/lxd/unix.socket:/var/snap/lxd/common/lxd/unix.socket:rw \
|
||||
ghcr.io/cloudbase/garm:v0.1.4
|
||||
ghcr.io/cloudbase/garm:v0.1.6
|
||||
```
|
||||
|
||||
You will notice that we also mounted the LXD unix socket from the host inside the container where the config you pasted expects to find it. If you plan to use an external provider that does not need to connect to LXD over a unix socket, feel free to remove that mount.
|
||||
|
|
@ -166,7 +169,7 @@ Adding the `garm` user to the LXD group will allow it to connect to the LXD unix
|
|||
Next, download the latest release from the [releases page](https://github.com/cloudbase/garm/releases).
|
||||
|
||||
```bash
|
||||
wget -q -O - https://github.com/cloudbase/garm/releases/download/v0.1.5/garm-linux-amd64.tgz | tar xzf - -C /usr/local/bin/
|
||||
wget -q -O - https://github.com/cloudbase/garm/releases/download/v0.1.6/garm-linux-amd64.tgz | tar xzf - -C /usr/local/bin/
|
||||
```
|
||||
|
||||
We'll be running under an unprivileged user. If we want to be able to listen on any port under `1024`, we'll have to set some capabilities on the binary:
|
||||
|
|
@ -199,7 +202,7 @@ Copy the sample `systemd` service file:
|
|||
|
||||
```bash
|
||||
wget -O /etc/systemd/system/garm.service \
|
||||
https://raw.githubusercontent.com/cloudbase/garm/v0.1.5/contrib/garm.service
|
||||
https://raw.githubusercontent.com/cloudbase/garm/v0.1.6/contrib/garm.service
|
||||
```
|
||||
|
||||
Reload the `systemd` daemon and start the service:
|
||||
|
|
@ -234,7 +237,7 @@ Before we can start using GARM, we need initialize it. This will create the `adm
|
|||
To initialize GARM, we'll use the `garm-cli` tool. You can download the latest release from the [releases page](https://github.com/cloudbase/garm/releases):
|
||||
|
||||
```bash
|
||||
wget -q -O - https://github.com/cloudbase/garm/releases/download/v0.1.5/garm-cli-linux-amd64.tgz | tar xzf - -C /usr/local/bin/
|
||||
wget -q -O - https://github.com/cloudbase/garm/releases/download/v0.1.6/garm-cli-linux-amd64.tgz | tar xzf - -C /usr/local/bin/
|
||||
```
|
||||
|
||||
Now we can initialize GARM:
|
||||
|
|
@ -502,7 +505,7 @@ gabriel@rossak:~$ garm-cli pool add \
|
|||
If we list the pool we should see it:
|
||||
|
||||
```bash
|
||||
gabriel@rock:~$ garm-cli pool ls -a
|
||||
gabriel@rock:~$ garm-cli pool ls
|
||||
+--------------------------------------+---------------------------+--------------+-----------------+------------------+-------+---------+---------------+----------+
|
||||
| ID | IMAGE | FLAVOR | TAGS | BELONGS TO | LEVEL | ENABLED | RUNNER PREFIX | PRIORITY |
|
||||
+--------------------------------------+---------------------------+--------------+-----------------+------------------+-------+---------+---------------+----------+
|
||||
|
|
@ -517,7 +520,7 @@ For the purposes of this guide, we'll increase it to 1 so we have a runner creat
|
|||
First, list current runners:
|
||||
|
||||
```bash
|
||||
gabriel@rossak:~$ garm-cli runner ls -a
|
||||
gabriel@rossak:~$ garm-cli runner ls
|
||||
+----+------+--------+---------------+---------+
|
||||
| NR | NAME | STATUS | RUNNER STATUS | POOL ID |
|
||||
+----+------+--------+---------------+---------+
|
||||
|
|
@ -554,7 +557,7 @@ gabriel@rossak:~$ garm-cli pool update 344e4a72-2035-4a18-a3d5-87bd3874b56c --mi
|
|||
Now if we list the runners:
|
||||
|
||||
```bash
|
||||
gabriel@rossak:~$ garm-cli runner ls -a
|
||||
gabriel@rossak:~$ garm-cli runner ls
|
||||
+----+-------------------+----------------+---------------+--------------------------------------+
|
||||
| NR | NAME | STATUS | RUNNER STATUS | POOL ID |
|
||||
+----+-------------------+----------------+---------------+--------------------------------------+
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ garm-cli controller show
|
|||
| Webhook Base URL | https://garm.example.com/webhooks |
|
||||
| Controller Webhook URL | https://garm.example.com/webhooks/a4dd5f41-8e1e-42a7-af53-c0ba5ff6b0b3 |
|
||||
| Minimum Job Age Backoff | 30 |
|
||||
| Version | v0.1.5 |
|
||||
| Version | v0.1.6 |
|
||||
+-------------------------+----------------------------------------------------------------------------+
|
||||
```
|
||||
|
||||
|
|
@ -567,10 +567,10 @@ ubuntu@garm:~$ garm-cli pool list --repo=be3a0673-56af-4395-9ebf-4521fea67567
|
|||
|
||||
If you want to list pools for an organization or enterprise, you can use the `--org` or `--enterprise` options respectively.
|
||||
|
||||
You can also list **all** pools from all configureg github entities by using the `--all` option.
|
||||
In the absence or the `--repo`, `--org` or `--enterprise` options, the command will list all pools in GARM, regardless of the entity they belong to.
|
||||
|
||||
```bash
|
||||
ubuntu@garm:~/garm$ garm-cli pool list --all
|
||||
ubuntu@garm:~/garm$ garm-cli pool list
|
||||
+--------------------------------------+---------------------------+--------------+-----------------------------------------+------------------+-------+---------+---------------+----------+
|
||||
| ID | IMAGE | FLAVOR | TAGS | BELONGS TO | LEVEL | ENABLED | RUNNER PREFIX | PRIORITY |
|
||||
+--------------------------------------+---------------------------+--------------+-----------------------------------------+------------------+-------+---------+---------------+----------+
|
||||
|
|
@ -705,7 +705,7 @@ Awesome! This runner will be able to pick up jobs that match the labels we've se
|
|||
You can list runners for a pool, for a repository, organization or enterprise, or for all of them. To list all runners, you can run:
|
||||
|
||||
```bash
|
||||
ubuntu@garm:~$ garm-cli runner list --all
|
||||
ubuntu@garm:~$ garm-cli runner list
|
||||
+----+---------------------+---------+---------------+--------------------------------------+
|
||||
| NR | NAME | STATUS | RUNNER STATUS | POOL ID |
|
||||
+----+---------------------+---------+---------------+--------------------------------------+
|
||||
|
|
|
|||
45
go.mod
45
go.mod
|
|
@ -1,43 +1,38 @@
|
|||
module github.com/cloudbase/garm
|
||||
|
||||
go 1.23.0
|
||||
|
||||
toolchain go1.23.6
|
||||
go 1.24.6
|
||||
|
||||
require (
|
||||
github.com/BurntSushi/toml v1.5.0
|
||||
github.com/bradleyfalzon/ghinstallation/v2 v2.16.0
|
||||
github.com/cloudbase/garm-provider-common v0.1.5
|
||||
github.com/cloudbase/garm-provider-common v0.1.7
|
||||
github.com/felixge/httpsnoop v1.0.4
|
||||
github.com/go-openapi/errors v0.22.1
|
||||
github.com/go-openapi/errors v0.22.2
|
||||
github.com/go-openapi/runtime v0.28.0
|
||||
github.com/go-openapi/strfmt v0.23.0
|
||||
github.com/go-openapi/swag v0.23.1
|
||||
github.com/golang-jwt/jwt/v5 v5.2.2
|
||||
github.com/golang-jwt/jwt/v5 v5.3.0
|
||||
github.com/google/go-github/v72 v72.0.0
|
||||
github.com/google/uuid v1.6.0
|
||||
github.com/gorilla/handlers v1.5.2
|
||||
github.com/gorilla/mux v1.8.1
|
||||
github.com/gorilla/websocket v1.5.4-0.20240702125206-a62d9d2a8413
|
||||
github.com/jedib0t/go-pretty/v6 v6.6.7
|
||||
github.com/juju/clock v1.1.1
|
||||
github.com/juju/retry v1.0.1
|
||||
github.com/jedib0t/go-pretty/v6 v6.6.8
|
||||
github.com/manifoldco/promptui v0.9.0
|
||||
github.com/nbutton23/zxcvbn-go v0.0.0-20210217022336-fa2cb2858354
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/prometheus/client_golang v1.22.0
|
||||
github.com/prometheus/client_golang v1.23.0
|
||||
github.com/spf13/cobra v1.9.1
|
||||
github.com/stretchr/testify v1.10.0
|
||||
golang.org/x/crypto v0.39.0
|
||||
golang.org/x/mod v0.25.0
|
||||
github.com/stretchr/testify v1.11.0
|
||||
golang.org/x/crypto v0.41.0
|
||||
golang.org/x/mod v0.27.0
|
||||
golang.org/x/oauth2 v0.30.0
|
||||
golang.org/x/sync v0.15.0
|
||||
golang.org/x/sync v0.16.0
|
||||
gopkg.in/DATA-DOG/go-sqlmock.v1 v1.3.0
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.2.1
|
||||
gorm.io/datatypes v1.2.6
|
||||
gorm.io/driver/mysql v1.6.0
|
||||
gorm.io/driver/sqlite v1.6.0
|
||||
gorm.io/gorm v1.30.0
|
||||
gorm.io/gorm v1.30.1
|
||||
)
|
||||
|
||||
require (
|
||||
|
|
@ -50,7 +45,7 @@ require (
|
|||
github.com/go-logr/logr v1.4.3 // indirect
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/go-openapi/analysis v0.23.0 // indirect
|
||||
github.com/go-openapi/jsonpointer v0.21.1 // indirect
|
||||
github.com/go-openapi/jsonpointer v0.21.2 // indirect
|
||||
github.com/go-openapi/jsonreference v0.21.0 // indirect
|
||||
github.com/go-openapi/loads v0.22.0 // indirect
|
||||
github.com/go-openapi/spec v0.21.0 // indirect
|
||||
|
|
@ -62,24 +57,22 @@ require (
|
|||
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||
github.com/jinzhu/now v1.1.5 // indirect
|
||||
github.com/josharian/intern v1.0.0 // indirect
|
||||
github.com/juju/errors v1.0.0 // indirect
|
||||
github.com/juju/loggo v1.0.0 // indirect
|
||||
github.com/juju/testing v1.0.2 // indirect
|
||||
github.com/mailru/easyjson v0.9.0 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.16 // indirect
|
||||
github.com/mattn/go-sqlite3 v1.14.28 // indirect
|
||||
github.com/mattn/go-sqlite3 v1.14.31 // indirect
|
||||
github.com/minio/sio v0.4.1 // indirect
|
||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||
github.com/oklog/ulid v1.3.1 // indirect
|
||||
github.com/opentracing/opentracing-go v1.2.0 // 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_model v0.6.2 // indirect
|
||||
github.com/prometheus/common v0.64.0 // indirect
|
||||
github.com/prometheus/common v0.65.0 // indirect
|
||||
github.com/prometheus/procfs v0.16.1 // indirect
|
||||
github.com/rivo/uniseg v0.4.7 // indirect
|
||||
github.com/spf13/pflag v1.0.6 // indirect
|
||||
github.com/spf13/pflag v1.0.7 // indirect
|
||||
github.com/stretchr/objx v0.5.2 // indirect
|
||||
github.com/teris-io/shortid v0.0.0-20220617161101-71ec9f2aa569 // indirect
|
||||
go.mongodb.org/mongo-driver v1.17.4 // indirect
|
||||
|
|
@ -87,9 +80,9 @@ require (
|
|||
go.opentelemetry.io/otel v1.36.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.36.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.36.0 // indirect
|
||||
golang.org/x/net v0.41.0 // indirect
|
||||
golang.org/x/sys v0.33.0 // indirect
|
||||
golang.org/x/text v0.26.0 // indirect
|
||||
golang.org/x/net v0.42.0 // indirect
|
||||
golang.org/x/sys v0.35.0 // indirect
|
||||
golang.org/x/text v0.28.0 // indirect
|
||||
google.golang.org/protobuf v1.36.6 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
|
|
|||
88
go.sum
88
go.sum
|
|
@ -19,8 +19,8 @@ github.com/chzyer/readline v1.5.1/go.mod h1:Eh+b79XXUwfKfcPLepksvw2tcLE/Ct21YObk
|
|||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||
github.com/chzyer/test v1.0.0 h1:p3BQDXSxOhOG0P9z6/hGnII4LGiEPOYBhs8asl/fC04=
|
||||
github.com/chzyer/test v1.0.0/go.mod h1:2JlltgoNkt4TW/z9V/IzDdFaMTM2JPIi26O1pF38GC8=
|
||||
github.com/cloudbase/garm-provider-common v0.1.5 h1:aJL646l+VnZceQ2grbDYhWfxYpaQR2/QsUSD76kSZVs=
|
||||
github.com/cloudbase/garm-provider-common v0.1.5/go.mod h1:2O51WbcfqRx5fDHyyJgIFq7KdTZZnefsM+aoOchyleU=
|
||||
github.com/cloudbase/garm-provider-common v0.1.7 h1:V0upTejFRDiyFBO4hhkMWmPtmRTguyOt/4i1u9/rfbg=
|
||||
github.com/cloudbase/garm-provider-common v0.1.7/go.mod h1:2O51WbcfqRx5fDHyyJgIFq7KdTZZnefsM+aoOchyleU=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
|
|
@ -34,10 +34,10 @@ github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
|||
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
||||
github.com/go-openapi/analysis v0.23.0 h1:aGday7OWupfMs+LbmLZG4k0MYXIANxcuBTYUC03zFCU=
|
||||
github.com/go-openapi/analysis v0.23.0/go.mod h1:9mz9ZWaSlV8TvjQHLl2mUW2PbZtemkE8yA5v22ohupo=
|
||||
github.com/go-openapi/errors v0.22.1 h1:kslMRRnK7NCb/CvR1q1VWuEQCEIsBGn5GgKD9e+HYhU=
|
||||
github.com/go-openapi/errors v0.22.1/go.mod h1:+n/5UdIqdVnLIJ6Q9Se8HNGUXYaY6CN8ImWzfi/Gzp0=
|
||||
github.com/go-openapi/jsonpointer v0.21.1 h1:whnzv/pNXtK2FbX/W9yJfRmE2gsmkfahjMKB0fZvcic=
|
||||
github.com/go-openapi/jsonpointer v0.21.1/go.mod h1:50I1STOfbY1ycR8jGz8DaMeLCdXiI6aDteEdRNNzpdk=
|
||||
github.com/go-openapi/errors v0.22.2 h1:rdxhzcBUazEcGccKqbY1Y7NS8FDcMyIRr0934jrYnZg=
|
||||
github.com/go-openapi/errors v0.22.2/go.mod h1:+n/5UdIqdVnLIJ6Q9Se8HNGUXYaY6CN8ImWzfi/Gzp0=
|
||||
github.com/go-openapi/jsonpointer v0.21.2 h1:AqQaNADVwq/VnkCmQg6ogE+M3FOsKTytwges0JdwVuA=
|
||||
github.com/go-openapi/jsonpointer v0.21.2/go.mod h1:50I1STOfbY1ycR8jGz8DaMeLCdXiI6aDteEdRNNzpdk=
|
||||
github.com/go-openapi/jsonreference v0.21.0 h1:Rs+Y7hSXT83Jacb7kFyjn4ijOuVGSvOdF2+tg1TRrwQ=
|
||||
github.com/go-openapi/jsonreference v0.21.0/go.mod h1:LmZmgsrTkVg9LG4EaHeY8cBDslNPMo06cago5JNLkm4=
|
||||
github.com/go-openapi/loads v0.22.0 h1:ECPGd4jX1U6NApCGG1We+uEozOAvXvJSF4nnwHZ8Aco=
|
||||
|
|
@ -56,8 +56,8 @@ github.com/go-sql-driver/mysql v1.9.3 h1:U/N249h2WzJ3Ukj8SowVFjdtZKfu9vlLZxjPXV1
|
|||
github.com/go-sql-driver/mysql v1.9.3/go.mod h1:qn46aNg1333BRMNU69Lq93t8du/dwxI64Gl8i5p1WMU=
|
||||
github.com/golang-jwt/jwt/v4 v4.5.2 h1:YtQM7lnr8iZ+j5q71MGKkNw9Mn7AjHM68uc9g5fXeUI=
|
||||
github.com/golang-jwt/jwt/v4 v4.5.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
|
||||
github.com/golang-jwt/jwt/v5 v5.2.2 h1:Rl4B7itRWVtYIHFrSNd7vhTiz9UpLdi6gZhZ3wEeDy8=
|
||||
github.com/golang-jwt/jwt/v5 v5.2.2/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
|
||||
github.com/golang-jwt/jwt/v5 v5.3.0 h1:pv4AsKCKKZuqlgs5sUmn4x8UlGa0kEVt/puTpKx9vvo=
|
||||
github.com/golang-jwt/jwt/v5 v5.3.0/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE=
|
||||
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 h1:au07oEsX2xN0ktxqI+Sida1w446QrXBRJ0nee3SNZlA=
|
||||
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
|
||||
github.com/golang-sql/sqlexp v0.1.0 h1:ZCD6MBpcuOVfGVqsEmY5/4FtYiKz6tSyUv9LPEDei6A=
|
||||
|
|
@ -87,27 +87,14 @@ github.com/jackc/pgx/v5 v5.5.5 h1:amBjrZVmksIdNjxGW/IiIMzxMKZFelXbUoPNb+8sjQw=
|
|||
github.com/jackc/pgx/v5 v5.5.5/go.mod h1:ez9gk+OAat140fv9ErkZDYFWmXLfV+++K0uAOiwgm1A=
|
||||
github.com/jackc/puddle/v2 v2.2.1 h1:RhxXJtFG022u4ibrCSMSiu5aOq1i77R3OHKNJj77OAk=
|
||||
github.com/jackc/puddle/v2 v2.2.1/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
|
||||
github.com/jedib0t/go-pretty/v6 v6.6.7 h1:m+LbHpm0aIAPLzLbMfn8dc3Ht8MW7lsSO4MPItz/Uuo=
|
||||
github.com/jedib0t/go-pretty/v6 v6.6.7/go.mod h1:YwC5CE4fJ1HFUDeivSV1r//AmANFHyqczZk+U6BDALU=
|
||||
github.com/jedib0t/go-pretty/v6 v6.6.8 h1:JnnzQeRz2bACBobIaa/r+nqjvws4yEhcmaZ4n1QzsEc=
|
||||
github.com/jedib0t/go-pretty/v6 v6.6.8/go.mod h1:YwC5CE4fJ1HFUDeivSV1r//AmANFHyqczZk+U6BDALU=
|
||||
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
|
||||
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
|
||||
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
|
||||
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
||||
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
|
||||
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
|
||||
github.com/juju/ansiterm v0.0.0-20180109212912-720a0952cc2a/go.mod h1:UJSiEoRfvx3hP73CvoARgeLjaIOjybY9vj8PUPPFGeU=
|
||||
github.com/juju/clock v1.1.1 h1:NvgHG9DQmOpBevgt6gzkyimdWBooLXDy1cQn89qJzBI=
|
||||
github.com/juju/clock v1.1.1/go.mod h1:HIBvJ8kiV/n7UHwKuCkdYL4l/MDECztHR2sAvWDxxf0=
|
||||
github.com/juju/errors v1.0.0 h1:yiq7kjCLll1BiaRuNY53MGI0+EQ3rF6GB+wvboZDefM=
|
||||
github.com/juju/errors v1.0.0/go.mod h1:B5x9thDqx0wIMH3+aLIMP9HjItInYWObRovoCFM5Qe8=
|
||||
github.com/juju/loggo v1.0.0 h1:Y6ZMQOGR9Aj3BGkiWx7HBbIx6zNwNkxhVNOHU2i1bl0=
|
||||
github.com/juju/loggo v1.0.0/go.mod h1:NIXFioti1SmKAlKNuUwbMenNdef59IF52+ZzuOmHYkg=
|
||||
github.com/juju/retry v1.0.1 h1:EVwOPq273wO1o0BCU7Ay7XE/bNb+bTNYsCK6y+BboAk=
|
||||
github.com/juju/retry v1.0.1/go.mod h1:SssN1eYeK3A2qjnFGTiVMbdzGJ2BfluaJblJXvuvgqA=
|
||||
github.com/juju/testing v1.0.2 h1:OR90RqCd9CJONxXamZAjLknpZdtqDyxqW8IwCbgw3i4=
|
||||
github.com/juju/testing v1.0.2/go.mod h1:h3Vd2rzB57KrdsBEy6R7bmSKPzP76BnNavt7i8PerwQ=
|
||||
github.com/juju/utils/v3 v3.0.0 h1:Gg3n63mGPbBuoXCo+EPJuMi44hGZfloI8nlCIebHu2Q=
|
||||
github.com/juju/utils/v3 v3.0.0/go.mod h1:8csUcj1VRkfjNIRzBFWzLFCMLwLqsRWvkmhfVAUwbC4=
|
||||
github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
|
||||
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
|
|
@ -116,19 +103,16 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
|||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
|
||||
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
|
||||
github.com/lunixbochs/vtclean v0.0.0-20160125035106-4fbf7632a2c6/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI=
|
||||
github.com/mailru/easyjson v0.9.0 h1:PrnmzHw7262yW8sTBwxi1PdJA3Iw/EKBa8psRf7d9a4=
|
||||
github.com/mailru/easyjson v0.9.0/go.mod h1:1+xMtQp2MRNVL/V1bOzuP3aP8VNwRW55fQUto+XFtTU=
|
||||
github.com/manifoldco/promptui v0.9.0 h1:3V4HzJk1TtXW1MTZMP7mdlwbBpIinw3HztaIlYthEiA=
|
||||
github.com/manifoldco/promptui v0.9.0/go.mod h1:ka04sppxSGFAtxX0qhlYQjISsg9mR4GWtQEhdbn6Pgg=
|
||||
github.com/mattn/go-colorable v0.0.6/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
||||
github.com/mattn/go-isatty v0.0.0-20160806122752-66b8e73f3f5c/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
|
||||
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||
github.com/mattn/go-sqlite3 v1.14.28 h1:ThEiQrnbtumT+QMknw63Befp/ce/nUPgBPMlRFEum7A=
|
||||
github.com/mattn/go-sqlite3 v1.14.28/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
|
||||
github.com/mattn/go-sqlite3 v1.14.31 h1:ldt6ghyPJsokUIlksH63gWZkG6qVGeEAu4zLeS4aVZM=
|
||||
github.com/mattn/go-sqlite3 v1.14.31/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
|
||||
github.com/microsoft/go-mssqldb v1.7.2 h1:CHkFJiObW7ItKTJfHo1QX7QBBD1iV+mn1eOyRP3b/PA=
|
||||
github.com/microsoft/go-mssqldb v1.7.2/go.mod h1:kOvZKUdrhhFQmxLZqbwUV0rHkNkZpthMITIb2Ko1IoA=
|
||||
github.com/minio/sio v0.4.1 h1:EMe3YBC1nf+sRQia65Rutxi+Z554XPV0dt8BIBA+a/0=
|
||||
|
|
@ -148,12 +132,12 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
|
|||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/prometheus/client_golang v1.22.0 h1:rb93p9lokFEsctTys46VnV1kLCDpVZ0a/Y92Vm0Zc6Q=
|
||||
github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0=
|
||||
github.com/prometheus/client_golang v1.23.0 h1:ust4zpdl9r4trLY/gSjlm07PuiBq2ynaXXlptpfy8Uc=
|
||||
github.com/prometheus/client_golang v1.23.0/go.mod h1:i/o0R9ByOnHX0McrTMTyhYvKE4haaf2mW08I+jGAjEE=
|
||||
github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
|
||||
github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
|
||||
github.com/prometheus/common v0.64.0 h1:pdZeA+g617P7oGv1CzdTzyeShxAGrTBsolKNOLQPGO4=
|
||||
github.com/prometheus/common v0.64.0/go.mod h1:0gZns+BLRQ3V6NdaerOhMbwwRbNh9hkGINtQAsP5GS8=
|
||||
github.com/prometheus/common v0.65.0 h1:QDwzd+G1twt//Kwj/Ww6E9FQq1iVMmODnILtW1t2VzE=
|
||||
github.com/prometheus/common v0.65.0/go.mod h1:0gZns+BLRQ3V6NdaerOhMbwwRbNh9hkGINtQAsP5GS8=
|
||||
github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg=
|
||||
github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is=
|
||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
|
|
@ -164,15 +148,16 @@ github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWN
|
|||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo=
|
||||
github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0=
|
||||
github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o=
|
||||
github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/spf13/pflag v1.0.7 h1:vN6T9TfwStFPFM5XzjsvmzZkLuaLX+HS+0SeFLRgU6M=
|
||||
github.com/spf13/pflag v1.0.7/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
|
||||
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
||||
github.com/stretchr/testify v1.1.4/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
||||
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/stretchr/testify v1.11.0 h1:ib4sjIrwZKxE5u/Japgo/7SJV3PvgjGiRNAvTVGqQl8=
|
||||
github.com/stretchr/testify v1.11.0/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
||||
github.com/teris-io/shortid v0.0.0-20220617161101-71ec9f2aa569 h1:xzABM9let0HLLqFypcxvLmlvEciCHL7+Lv+4vwZqecI=
|
||||
github.com/teris-io/shortid v0.0.0-20220617161101-71ec9f2aa569/go.mod h1:2Ly+NIftZN4de9zRmENdYbvPQeaVIYKWpLFStLFEBgI=
|
||||
go.mongodb.org/mongo-driver v1.17.4 h1:jUorfmVzljjr0FLzYQsGP8cgN/qzzxlY9Vh0C9KFXVw=
|
||||
|
|
@ -187,36 +172,35 @@ go.opentelemetry.io/otel/sdk v1.24.0 h1:YMPPDNymmQN3ZgczicBY3B6sf9n62Dlj9pWD3ucg
|
|||
go.opentelemetry.io/otel/sdk v1.24.0/go.mod h1:KVrIYw6tEubO9E96HQpcmpTKDVn9gdv35HoYiQWGDFg=
|
||||
go.opentelemetry.io/otel/trace v1.36.0 h1:ahxWNuqZjpdiFAyrIoQ4GIiAIhxAunQR6MUoKrsNd4w=
|
||||
go.opentelemetry.io/otel/trace v1.36.0/go.mod h1:gQ+OnDZzrybY4k4seLzPAWNwVBBVlF2szhehOBB/tGA=
|
||||
golang.org/x/crypto v0.39.0 h1:SHs+kF4LP+f+p14esP5jAoDpHU8Gu/v9lFRK6IT5imM=
|
||||
golang.org/x/crypto v0.39.0/go.mod h1:L+Xg3Wf6HoL4Bn4238Z6ft6KfEpN0tJGo53AAPC632U=
|
||||
golang.org/x/mod v0.25.0 h1:n7a+ZbQKQA/Ysbyb0/6IbB1H/X41mKgbhfv7AfG/44w=
|
||||
golang.org/x/mod v0.25.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww=
|
||||
golang.org/x/net v0.41.0 h1:vBTly1HeNPEn3wtREYfy4GZ/NECgw2Cnl+nK6Nz3uvw=
|
||||
golang.org/x/net v0.41.0/go.mod h1:B/K4NNqkfmg07DQYrbwvSluqCJOOXwUjeb/5lOisjbA=
|
||||
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
||||
golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4=
|
||||
golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc=
|
||||
golang.org/x/mod v0.27.0 h1:kb+q2PyFnEADO2IEF935ehFUXlWiNjJWtRNgBLSfbxQ=
|
||||
golang.org/x/mod v0.27.0/go.mod h1:rWI627Fq0DEoudcK+MBkNkCe0EetEaDSwJJkCcjpazc=
|
||||
golang.org/x/net v0.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs=
|
||||
golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8=
|
||||
golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI=
|
||||
golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU=
|
||||
golang.org/x/sync v0.15.0 h1:KWH3jNZsfyT6xfAfKiz6MRNmd46ByHDYaZ7KSkCtdW8=
|
||||
golang.org/x/sync v0.15.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||
golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw=
|
||||
golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||
golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
|
||||
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/text v0.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M=
|
||||
golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA=
|
||||
golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI=
|
||||
golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng=
|
||||
golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
|
||||
google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
|
||||
gopkg.in/DATA-DOG/go-sqlmock.v1 v1.3.0 h1:FVCohIoYO7IJoDDVpV2pdq7SgrMH6wHnuTyrdrxJNoY=
|
||||
gopkg.in/DATA-DOG/go-sqlmock.v1 v1.3.0/go.mod h1:OdE7CF6DbADk7lN8LIKRzRJTTZXIjtWgA5THM5lhBAw=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20160105164936-4f90aeace3a2/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc=
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc=
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gorm.io/datatypes v1.2.6 h1:KafLdXvFUhzNeL2ncm03Gl3eTLONQfNKZ+wJ+9Y4Nck=
|
||||
|
|
@ -229,5 +213,5 @@ gorm.io/driver/sqlite v1.6.0 h1:WHRRrIiulaPiPFmDcod6prc4l2VGVWHz80KspNsxSfQ=
|
|||
gorm.io/driver/sqlite v1.6.0/go.mod h1:AO9V1qIQddBESngQUKWL9yoH93HIeA1X6V633rBwyT8=
|
||||
gorm.io/driver/sqlserver v1.6.0 h1:VZOBQVsVhkHU/NzNhRJKoANt5pZGQAS1Bwc6m6dgfnc=
|
||||
gorm.io/driver/sqlserver v1.6.0/go.mod h1:WQzt4IJo/WHKnckU9jXBLMJIVNMVeTu25dnOzehntWw=
|
||||
gorm.io/gorm v1.30.0 h1:qbT5aPv1UH8gI99OsRlvDToLxW5zR7FzS9acZDOZcgs=
|
||||
gorm.io/gorm v1.30.0/go.mod h1:8Z33v652h4//uMA76KjeDH8mJXPm1QNCYrMeatR0DOE=
|
||||
gorm.io/gorm v1.30.1 h1:lSHg33jJTBxs2mgJRfRZeLDG+WZaHYCk3Wtfl6Ngzo4=
|
||||
gorm.io/gorm v1.30.1/go.mod h1:8Z33v652h4//uMA76KjeDH8mJXPm1QNCYrMeatR0DOE=
|
||||
|
|
|
|||
|
|
@ -19,13 +19,13 @@ package testing
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"testing"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
runnerErrors "github.com/cloudbase/garm-provider-common/errors"
|
||||
|
|
|
|||
|
|
@ -420,7 +420,6 @@ func (r RunnerScaleSetMessage) GetJobsFromBody() ([]ScaleSetJobMessage, error) {
|
|||
if r.Body == "" {
|
||||
return nil, fmt.Errorf("no body specified")
|
||||
}
|
||||
|
||||
if err := json.Unmarshal([]byte(r.Body), &body); err != nil {
|
||||
return nil, fmt.Errorf("failed to unmarshal body: %w", err)
|
||||
}
|
||||
|
|
@ -428,21 +427,21 @@ func (r RunnerScaleSetMessage) GetJobsFromBody() ([]ScaleSetJobMessage, error) {
|
|||
}
|
||||
|
||||
type RunnerReference struct {
|
||||
ID int64 `json:"id"`
|
||||
Name string `json:"name"`
|
||||
OS string `json:"os"`
|
||||
RunnerScaleSetID int `json:"runnerScaleSetId"`
|
||||
CreatedOn interface{} `json:"createdOn"`
|
||||
RunnerGroupID uint64 `json:"runnerGroupId"`
|
||||
RunnerGroupName string `json:"runnerGroupName"`
|
||||
Version string `json:"version"`
|
||||
Enabled bool `json:"enabled"`
|
||||
Ephemeral bool `json:"ephemeral"`
|
||||
Status interface{} `json:"status"`
|
||||
DisableUpdate bool `json:"disableUpdate"`
|
||||
ProvisioningState string `json:"provisioningState"`
|
||||
Busy bool `json:"busy"`
|
||||
Labels []Label `json:"labels,omitempty"`
|
||||
ID int64 `json:"id"`
|
||||
Name string `json:"name"`
|
||||
OS string `json:"os"`
|
||||
RunnerScaleSetID int `json:"runnerScaleSetId"`
|
||||
CreatedOn any `json:"createdOn"`
|
||||
RunnerGroupID uint64 `json:"runnerGroupId"`
|
||||
RunnerGroupName string `json:"runnerGroupName"`
|
||||
Version string `json:"version"`
|
||||
Enabled bool `json:"enabled"`
|
||||
Ephemeral bool `json:"ephemeral"`
|
||||
Status any `json:"status"`
|
||||
DisableUpdate bool `json:"disableUpdate"`
|
||||
ProvisioningState string `json:"provisioningState"`
|
||||
Busy bool `json:"busy"`
|
||||
Labels []Label `json:"labels,omitempty"`
|
||||
}
|
||||
|
||||
func (r RunnerReference) GetStatus() RunnerStatus {
|
||||
|
|
@ -519,6 +518,7 @@ type RunnerGroupList struct {
|
|||
|
||||
type ScaleSetJobMessage struct {
|
||||
MessageType string `json:"messageType,omitempty"`
|
||||
JobID string `json:"jobId,omitempty"`
|
||||
RunnerRequestID int64 `json:"runnerRequestId,omitempty"`
|
||||
RepositoryName string `json:"repositoryName,omitempty"`
|
||||
OwnerName string `json:"ownerName,omitempty"`
|
||||
|
|
@ -552,7 +552,7 @@ func (s ScaleSetJobMessage) MessageTypeToStatus() JobStatus {
|
|||
|
||||
func (s ScaleSetJobMessage) ToJob() Job {
|
||||
return Job{
|
||||
ID: s.RunnerRequestID,
|
||||
ScaleSetJobID: s.JobID,
|
||||
Action: s.EventName,
|
||||
RunID: s.WorkflowRunID,
|
||||
Status: string(s.MessageTypeToStatus()),
|
||||
|
|
|
|||
|
|
@ -172,6 +172,7 @@ const (
|
|||
MessageTypeJobAvailable = "JobAvailable"
|
||||
)
|
||||
|
||||
// swagger:model StatusMessage
|
||||
type StatusMessage struct {
|
||||
CreatedAt time.Time `json:"created_at,omitempty"`
|
||||
Message string `json:"message,omitempty"`
|
||||
|
|
@ -179,6 +180,7 @@ type StatusMessage struct {
|
|||
EventLevel EventLevel `json:"event_level,omitempty"`
|
||||
}
|
||||
|
||||
// swagger:model EntityEvent
|
||||
type EntityEvent struct {
|
||||
ID uint `json:"id,omitempty"`
|
||||
CreatedAt time.Time `json:"created_at,omitempty"`
|
||||
|
|
@ -188,6 +190,7 @@ type EntityEvent struct {
|
|||
Message string `json:"message,omitempty"`
|
||||
}
|
||||
|
||||
// swagger:model Instance
|
||||
type Instance struct {
|
||||
// ID is the database ID of this instance.
|
||||
ID string `json:"id,omitempty"`
|
||||
|
|
@ -282,6 +285,7 @@ func (i Instance) GetID() string {
|
|||
}
|
||||
|
||||
// used by swagger client generated code
|
||||
// swagger:model Instances
|
||||
type Instances []Instance
|
||||
|
||||
type BootstrapInstance struct {
|
||||
|
|
@ -352,6 +356,7 @@ type Tag struct {
|
|||
Name string `json:"name,omitempty"`
|
||||
}
|
||||
|
||||
// swagger:model Pool
|
||||
type Pool struct {
|
||||
RunnerPrefix
|
||||
|
||||
|
|
@ -376,7 +381,7 @@ type Pool struct {
|
|||
EnterpriseID string `json:"enterprise_id,omitempty"`
|
||||
EnterpriseName string `json:"enterprise_name,omitempty"`
|
||||
|
||||
Endpoint ForgeEndpoint `json:"forge_type,omitempty"`
|
||||
Endpoint ForgeEndpoint `json:"endpoint,omitempty"`
|
||||
|
||||
RunnerBootstrapTimeout uint `json:"runner_bootstrap_timeout,omitempty"`
|
||||
CreatedAt time.Time `json:"created_at,omitempty"`
|
||||
|
|
@ -487,11 +492,16 @@ func (p *Pool) HasRequiredLabels(set []string) bool {
|
|||
}
|
||||
|
||||
// used by swagger client generated code
|
||||
// swagger:model Pools
|
||||
type Pools []Pool
|
||||
|
||||
// swagger:model ScaleSet
|
||||
type ScaleSet struct {
|
||||
RunnerPrefix
|
||||
|
||||
CreatedAt time.Time `json:"created_at,omitempty"`
|
||||
UpdatedAt time.Time `json:"updated_at,omitempty"`
|
||||
|
||||
ID uint `json:"id,omitempty"`
|
||||
ScaleSetID int `json:"scale_set_id,omitempty"`
|
||||
Name string `json:"name,omitempty"`
|
||||
|
|
@ -511,6 +521,8 @@ type ScaleSet struct {
|
|||
Instances []Instance `json:"instances,omitempty"`
|
||||
DesiredRunnerCount int `json:"desired_runner_count,omitempty"`
|
||||
|
||||
Endpoint ForgeEndpoint `json:"endpoint,omitempty"`
|
||||
|
||||
RunnerBootstrapTimeout uint `json:"runner_bootstrap_timeout,omitempty"`
|
||||
// ExtraSpecs is an opaque raw json that gets sent to the provider
|
||||
// as part of the bootstrap params for instances. It can contain
|
||||
|
|
@ -570,7 +582,7 @@ func (p ScaleSet) GetEntity() (ForgeEntity, error) {
|
|||
EntityType: ForgeEntityTypeEnterprise,
|
||||
}, nil
|
||||
}
|
||||
return ForgeEntity{}, fmt.Errorf("pool has no associated entity")
|
||||
return ForgeEntity{}, fmt.Errorf("scale set has no associated entity")
|
||||
}
|
||||
|
||||
func (p *ScaleSet) ScaleSetType() ForgeEntityType {
|
||||
|
|
@ -593,8 +605,10 @@ func (p *ScaleSet) RunnerTimeout() uint {
|
|||
}
|
||||
|
||||
// used by swagger client generated code
|
||||
// swagger:model ScaleSets
|
||||
type ScaleSets []ScaleSet
|
||||
|
||||
// swagger:model Repository
|
||||
type Repository struct {
|
||||
ID string `json:"id,omitempty"`
|
||||
Owner string `json:"owner,omitempty"`
|
||||
|
|
@ -666,8 +680,10 @@ func (r Repository) String() string {
|
|||
}
|
||||
|
||||
// used by swagger client generated code
|
||||
// swagger:model Repositories
|
||||
type Repositories []Repository
|
||||
|
||||
// swagger:model Organization
|
||||
type Organization struct {
|
||||
ID string `json:"id,omitempty"`
|
||||
Name string `json:"name,omitempty"`
|
||||
|
|
@ -724,8 +740,10 @@ func (o Organization) GetBalancerType() PoolBalancerType {
|
|||
}
|
||||
|
||||
// used by swagger client generated code
|
||||
// swagger:model Organizations
|
||||
type Organizations []Organization
|
||||
|
||||
// swagger:model Enterprise
|
||||
type Enterprise struct {
|
||||
ID string `json:"id,omitempty"`
|
||||
Name string `json:"name,omitempty"`
|
||||
|
|
@ -782,9 +800,11 @@ func (e Enterprise) GetBalancerType() PoolBalancerType {
|
|||
}
|
||||
|
||||
// used by swagger client generated code
|
||||
// swagger:model Enterprises
|
||||
type Enterprises []Enterprise
|
||||
|
||||
// Users holds information about a particular user
|
||||
// swagger:model User
|
||||
type User struct {
|
||||
ID string `json:"id,omitempty"`
|
||||
CreatedAt time.Time `json:"created_at,omitempty"`
|
||||
|
|
@ -801,10 +821,12 @@ type User struct {
|
|||
|
||||
// JWTResponse holds the JWT token returned as a result of a
|
||||
// successful auth
|
||||
// swagger:model JWTResponse
|
||||
type JWTResponse struct {
|
||||
Token string `json:"token,omitempty"`
|
||||
}
|
||||
|
||||
// swagger:model ControllerInfo
|
||||
type ControllerInfo struct {
|
||||
// ControllerID is the unique ID of this controller. This ID gets generated
|
||||
// automatically on controller init.
|
||||
|
|
@ -857,6 +879,7 @@ func (c *ControllerInfo) JobBackoff() time.Duration {
|
|||
return time.Duration(int64(c.MinimumJobAgeBackoff))
|
||||
}
|
||||
|
||||
// swagger:model GithubRateLimit
|
||||
type GithubRateLimit struct {
|
||||
Limit int `json:"limit,omitempty"`
|
||||
Used int `json:"used,omitempty"`
|
||||
|
|
@ -875,6 +898,7 @@ func (g GithubRateLimit) ResetAt() time.Time {
|
|||
return time.Unix(g.Reset, 0)
|
||||
}
|
||||
|
||||
// swagger:model ForgeCredentials
|
||||
type ForgeCredentials struct {
|
||||
ID uint `json:"id,omitempty"`
|
||||
Name string `json:"name,omitempty"`
|
||||
|
|
@ -1000,8 +1024,10 @@ func (g ForgeCredentials) RootCertificateBundle() (CertificateBundle, error) {
|
|||
}
|
||||
|
||||
// used by swagger client generated code
|
||||
// swagger:model Credentials
|
||||
type Credentials []ForgeCredentials
|
||||
|
||||
// swagger:model Provider
|
||||
type Provider struct {
|
||||
Name string `json:"name,omitempty"`
|
||||
ProviderType ProviderType `json:"type,omitempty"`
|
||||
|
|
@ -1009,8 +1035,10 @@ type Provider struct {
|
|||
}
|
||||
|
||||
// used by swagger client generated code
|
||||
// swagger:model Providers
|
||||
type Providers []Provider
|
||||
|
||||
// swagger:model PoolManagerStatus
|
||||
type PoolManagerStatus struct {
|
||||
IsRunning bool `json:"running,omitempty"`
|
||||
FailureReason string `json:"failure_reason,omitempty"`
|
||||
|
|
@ -1032,9 +1060,14 @@ func (p RunnerPrefix) GetRunnerPrefix() string {
|
|||
return p.Prefix
|
||||
}
|
||||
|
||||
// swagger:model Job
|
||||
type Job struct {
|
||||
// ID is the ID of the job.
|
||||
ID int64 `json:"id,omitempty"`
|
||||
|
||||
WorkflowJobID int64 `json:"workflow_job_id,omitempty"`
|
||||
// ScaleSetJobID is the job ID when generated for a scale set.
|
||||
ScaleSetJobID string `json:"scaleset_job_id,omitempty"`
|
||||
// RunID is the ID of the workflow run. A run may have multiple jobs.
|
||||
RunID int64 `json:"run_id,omitempty"`
|
||||
// Action is the specific activity that triggered the event.
|
||||
|
|
@ -1082,14 +1115,17 @@ type Job struct {
|
|||
UpdatedAt time.Time `json:"updated_at,omitempty"`
|
||||
}
|
||||
|
||||
// swagger:model Jobs
|
||||
// used by swagger client generated code
|
||||
type Jobs []Job
|
||||
|
||||
// swagger:model InstallWebhookParams
|
||||
type InstallWebhookParams struct {
|
||||
WebhookEndpointType WebhookEndpointType `json:"webhook_endpoint_type,omitempty"`
|
||||
InsecureSSL bool `json:"insecure_ssl,omitempty"`
|
||||
}
|
||||
|
||||
// swagger:model HookInfo
|
||||
type HookInfo struct {
|
||||
ID int64 `json:"id,omitempty"`
|
||||
URL string `json:"url,omitempty"`
|
||||
|
|
@ -1102,6 +1138,7 @@ type CertificateBundle struct {
|
|||
RootCertificates map[string][]byte `json:"root_certificates,omitempty"`
|
||||
}
|
||||
|
||||
// swagger:model ForgeEntity
|
||||
type UpdateSystemInfoParams struct {
|
||||
OSName string `json:"os_name,omitempty"`
|
||||
OSVersion string `json:"os_version,omitempty"`
|
||||
|
|
@ -1133,18 +1170,13 @@ func (g ForgeEntity) GetForgeType() (EndpointType, error) {
|
|||
}
|
||||
|
||||
func (g ForgeEntity) ForgeURL() string {
|
||||
switch g.Credentials.ForgeType {
|
||||
case GiteaEndpointType:
|
||||
return g.Credentials.Endpoint.APIBaseURL
|
||||
default:
|
||||
switch g.EntityType {
|
||||
case ForgeEntityTypeRepository:
|
||||
return fmt.Sprintf("%s/%s/%s", g.Credentials.BaseURL, g.Owner, g.Name)
|
||||
case ForgeEntityTypeOrganization:
|
||||
return fmt.Sprintf("%s/%s", g.Credentials.BaseURL, g.Owner)
|
||||
case ForgeEntityTypeEnterprise:
|
||||
return fmt.Sprintf("%s/enterprises/%s", g.Credentials.BaseURL, g.Owner)
|
||||
}
|
||||
switch g.EntityType {
|
||||
case ForgeEntityTypeRepository:
|
||||
return fmt.Sprintf("%s/%s/%s", g.Credentials.BaseURL, g.Owner, g.Name)
|
||||
case ForgeEntityTypeOrganization:
|
||||
return fmt.Sprintf("%s/%s", g.Credentials.BaseURL, g.Owner)
|
||||
case ForgeEntityTypeEnterprise:
|
||||
return fmt.Sprintf("%s/enterprises/%s", g.Credentials.BaseURL, g.Owner)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
|
@ -1190,8 +1222,10 @@ func (g ForgeEntity) GetIDAsUUID() (uuid.UUID, error) {
|
|||
}
|
||||
|
||||
// used by swagger client generated code
|
||||
// swagger:model ForgeEndpoints
|
||||
type ForgeEndpoints []ForgeEndpoint
|
||||
|
||||
// swagger:model ForgeEndpoint
|
||||
type ForgeEndpoint struct {
|
||||
Name string `json:"name,omitempty"`
|
||||
Description string `json:"description,omitempty"`
|
||||
|
|
|
|||
|
|
@ -21,8 +21,6 @@ import (
|
|||
"fmt"
|
||||
"net/url"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
runnerErrors "github.com/cloudbase/garm-provider-common/errors"
|
||||
commonParams "github.com/cloudbase/garm-provider-common/params"
|
||||
)
|
||||
|
|
@ -39,6 +37,7 @@ type InstanceRequest struct {
|
|||
OSVersion string `json:"os_version"`
|
||||
}
|
||||
|
||||
// swagger:model CreateRepoParams
|
||||
type CreateRepoParams struct {
|
||||
Owner string `json:"owner,omitempty"`
|
||||
Name string `json:"name,omitempty"`
|
||||
|
|
@ -80,6 +79,7 @@ func (c *CreateRepoParams) Validate() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// swagger:model CreateOrgParams
|
||||
type CreateOrgParams struct {
|
||||
Name string `json:"name,omitempty"`
|
||||
CredentialsName string `json:"credentials_name,omitempty"`
|
||||
|
|
@ -115,6 +115,7 @@ func (c *CreateOrgParams) Validate() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// swagger:model CreateEnterpriseParams
|
||||
type CreateEnterpriseParams struct {
|
||||
Name string `json:"name,omitempty"`
|
||||
CredentialsName string `json:"credentials_name,omitempty"`
|
||||
|
|
@ -143,6 +144,7 @@ func (c *CreateEnterpriseParams) Validate() error {
|
|||
|
||||
// NewUserParams holds the needed information to create
|
||||
// a new user
|
||||
// swagger:model NewUserParams
|
||||
type NewUserParams struct {
|
||||
Email string `json:"email,omitempty"`
|
||||
Username string `json:"username,omitempty"`
|
||||
|
|
@ -152,6 +154,7 @@ type NewUserParams struct {
|
|||
Enabled bool `json:"-"`
|
||||
}
|
||||
|
||||
// swagger:model UpdatePoolParams
|
||||
type UpdatePoolParams struct {
|
||||
RunnerPrefix
|
||||
|
||||
|
|
@ -189,6 +192,7 @@ type CreateInstanceParams struct {
|
|||
JitConfiguration map[string]string `json:"jit_configuration,omitempty"`
|
||||
}
|
||||
|
||||
// swagger:model CreatePoolParams
|
||||
type CreatePoolParams struct {
|
||||
RunnerPrefix
|
||||
|
||||
|
|
@ -263,6 +267,7 @@ type UpdateUserParams struct {
|
|||
Enabled *bool `json:"enabled,omitempty"`
|
||||
}
|
||||
|
||||
// swagger:model PasswordLoginParams
|
||||
// PasswordLoginParams holds information used during
|
||||
// password authentication, that will be passed to a
|
||||
// password login function
|
||||
|
|
@ -279,6 +284,7 @@ func (p PasswordLoginParams) Validate() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// swagger:model UpdateEntityParams
|
||||
type UpdateEntityParams struct {
|
||||
CredentialsName string `json:"credentials_name,omitempty"`
|
||||
WebhookSecret string `json:"webhook_secret,omitempty"`
|
||||
|
|
@ -291,6 +297,7 @@ type InstanceUpdateMessage struct {
|
|||
AgentID *int64 `json:"agent_id,omitempty"`
|
||||
}
|
||||
|
||||
// swagger:model CreateGithubEndpointParams
|
||||
type CreateGithubEndpointParams struct {
|
||||
Name string `json:"name,omitempty"`
|
||||
Description string `json:"description,omitempty"`
|
||||
|
|
@ -358,6 +365,7 @@ func (c CreateGithubEndpointParams) Validate() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// swagger:model UpdateGithubEndpointParams
|
||||
type UpdateGithubEndpointParams struct {
|
||||
Description *string `json:"description,omitempty"`
|
||||
APIBaseURL *string `json:"api_base_url,omitempty"`
|
||||
|
|
@ -416,10 +424,12 @@ func (u UpdateGithubEndpointParams) Validate() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// swagger:model GithubPAT
|
||||
type GithubPAT struct {
|
||||
OAuth2Token string `json:"oauth2_token,omitempty"`
|
||||
}
|
||||
|
||||
// swagger:model GithubApp
|
||||
type GithubApp struct {
|
||||
AppID int64 `json:"app_id,omitempty"`
|
||||
InstallationID int64 `json:"installation_id,omitempty"`
|
||||
|
|
@ -452,6 +462,7 @@ func (g GithubApp) Validate() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// swagger:model CreateGithubCredentialsParams
|
||||
type CreateGithubCredentialsParams struct {
|
||||
Name string `json:"name,omitempty"`
|
||||
Description string `json:"description,omitempty"`
|
||||
|
|
@ -484,13 +495,14 @@ func (c CreateGithubCredentialsParams) Validate() error {
|
|||
|
||||
if c.AuthType == ForgeAuthTypeApp {
|
||||
if err := c.App.Validate(); err != nil {
|
||||
return errors.Wrap(err, "invalid app")
|
||||
return fmt.Errorf("invalid app: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// swagger:model UpdateGithubCredentialsParams
|
||||
type UpdateGithubCredentialsParams struct {
|
||||
Name *string `json:"name,omitempty"`
|
||||
Description *string `json:"description,omitempty"`
|
||||
|
|
@ -511,13 +523,14 @@ func (u UpdateGithubCredentialsParams) Validate() error {
|
|||
|
||||
if u.App != nil {
|
||||
if err := u.App.Validate(); err != nil {
|
||||
return errors.Wrap(err, "invalid app")
|
||||
return fmt.Errorf("invalid app: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// swagger:model UpdateControllerParams
|
||||
type UpdateControllerParams struct {
|
||||
MetadataURL *string `json:"metadata_url,omitempty"`
|
||||
CallbackURL *string `json:"callback_url,omitempty"`
|
||||
|
|
@ -550,6 +563,7 @@ func (u UpdateControllerParams) Validate() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// swagger:model CreateScaleSetParams
|
||||
type CreateScaleSetParams struct {
|
||||
RunnerPrefix
|
||||
|
||||
|
|
@ -602,6 +616,7 @@ func (s *CreateScaleSetParams) Validate() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// swagger:model UpdateScaleSetParams
|
||||
type UpdateScaleSetParams struct {
|
||||
RunnerPrefix
|
||||
|
||||
|
|
@ -621,8 +636,10 @@ type UpdateScaleSetParams struct {
|
|||
GitHubRunnerGroup *string `json:"runner_group,omitempty"`
|
||||
State *ScaleSetState `json:"state"`
|
||||
ExtendedState *string `json:"extended_state"`
|
||||
ScaleSetID int `json:"-"`
|
||||
}
|
||||
|
||||
// swagger:model CreateGiteaEndpointParams
|
||||
type CreateGiteaEndpointParams struct {
|
||||
Name string `json:"name,omitempty"`
|
||||
Description string `json:"description,omitempty"`
|
||||
|
|
@ -674,6 +691,7 @@ func (c CreateGiteaEndpointParams) Validate() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// swagger:model UpdateGiteaEndpointParams
|
||||
type UpdateGiteaEndpointParams struct {
|
||||
Description *string `json:"description,omitempty"`
|
||||
APIBaseURL *string `json:"api_base_url,omitempty"`
|
||||
|
|
@ -719,6 +737,7 @@ func (u UpdateGiteaEndpointParams) Validate() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// swagger:model CreateGiteaCredentialsParams
|
||||
type CreateGiteaCredentialsParams struct {
|
||||
Name string `json:"name,omitempty"`
|
||||
Description string `json:"description,omitempty"`
|
||||
|
|
@ -752,6 +771,7 @@ func (c CreateGiteaCredentialsParams) Validate() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// swagger:model UpdateGiteaCredentialsParams
|
||||
type UpdateGiteaCredentialsParams struct {
|
||||
Name *string `json:"name,omitempty"`
|
||||
Description *string `json:"description,omitempty"`
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@ package runner
|
|||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
runnerErrors "github.com/cloudbase/garm-provider-common/errors"
|
||||
"github.com/cloudbase/garm/params"
|
||||
|
|
@ -12,11 +12,11 @@ import (
|
|||
func (r *Runner) ResolveForgeCredentialByName(ctx context.Context, credentialsName string) (params.ForgeCredentials, error) {
|
||||
githubCred, err := r.store.GetGithubCredentialsByName(ctx, credentialsName, false)
|
||||
if err != nil && !errors.Is(err, runnerErrors.ErrNotFound) {
|
||||
return params.ForgeCredentials{}, errors.Wrap(err, "fetching github credentials")
|
||||
return params.ForgeCredentials{}, fmt.Errorf("error fetching github credentials: %w", err)
|
||||
}
|
||||
giteaCred, err := r.store.GetGiteaCredentialsByName(ctx, credentialsName, false)
|
||||
if err != nil && !errors.Is(err, runnerErrors.ErrNotFound) {
|
||||
return params.ForgeCredentials{}, errors.Wrap(err, "fetching gitea credentials")
|
||||
return params.ForgeCredentials{}, fmt.Errorf("error fetching gitea credentials: %w", err)
|
||||
}
|
||||
if githubCred.ID != 0 && giteaCred.ID != 0 {
|
||||
return params.ForgeCredentials{}, runnerErrors.NewBadRequestError("credentials %s are defined for both GitHub and Gitea, please specify the forge type", credentialsName)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// Code generated by mockery v2.53.3. DO NOT EDIT.
|
||||
// Code generated by mockery. DO NOT EDIT.
|
||||
|
||||
package mocks
|
||||
|
||||
|
|
@ -18,6 +18,14 @@ type GithubClient struct {
|
|||
mock.Mock
|
||||
}
|
||||
|
||||
type GithubClient_Expecter struct {
|
||||
mock *mock.Mock
|
||||
}
|
||||
|
||||
func (_m *GithubClient) EXPECT() *GithubClient_Expecter {
|
||||
return &GithubClient_Expecter{mock: &_m.Mock}
|
||||
}
|
||||
|
||||
// CreateEntityHook provides a mock function with given fields: ctx, hook
|
||||
func (_m *GithubClient) CreateEntityHook(ctx context.Context, hook *github.Hook) (*github.Hook, error) {
|
||||
ret := _m.Called(ctx, hook)
|
||||
|
|
@ -48,6 +56,35 @@ func (_m *GithubClient) CreateEntityHook(ctx context.Context, hook *github.Hook)
|
|||
return r0, r1
|
||||
}
|
||||
|
||||
// GithubClient_CreateEntityHook_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CreateEntityHook'
|
||||
type GithubClient_CreateEntityHook_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// CreateEntityHook is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
// - hook *github.Hook
|
||||
func (_e *GithubClient_Expecter) CreateEntityHook(ctx interface{}, hook interface{}) *GithubClient_CreateEntityHook_Call {
|
||||
return &GithubClient_CreateEntityHook_Call{Call: _e.mock.On("CreateEntityHook", ctx, hook)}
|
||||
}
|
||||
|
||||
func (_c *GithubClient_CreateEntityHook_Call) Run(run func(ctx context.Context, hook *github.Hook)) *GithubClient_CreateEntityHook_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(context.Context), args[1].(*github.Hook))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *GithubClient_CreateEntityHook_Call) Return(ret *github.Hook, err error) *GithubClient_CreateEntityHook_Call {
|
||||
_c.Call.Return(ret, err)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *GithubClient_CreateEntityHook_Call) RunAndReturn(run func(context.Context, *github.Hook) (*github.Hook, error)) *GithubClient_CreateEntityHook_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// CreateEntityRegistrationToken provides a mock function with given fields: ctx
|
||||
func (_m *GithubClient) CreateEntityRegistrationToken(ctx context.Context) (*github.RegistrationToken, *github.Response, error) {
|
||||
ret := _m.Called(ctx)
|
||||
|
|
@ -87,6 +124,34 @@ func (_m *GithubClient) CreateEntityRegistrationToken(ctx context.Context) (*git
|
|||
return r0, r1, r2
|
||||
}
|
||||
|
||||
// GithubClient_CreateEntityRegistrationToken_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CreateEntityRegistrationToken'
|
||||
type GithubClient_CreateEntityRegistrationToken_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// CreateEntityRegistrationToken is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
func (_e *GithubClient_Expecter) CreateEntityRegistrationToken(ctx interface{}) *GithubClient_CreateEntityRegistrationToken_Call {
|
||||
return &GithubClient_CreateEntityRegistrationToken_Call{Call: _e.mock.On("CreateEntityRegistrationToken", ctx)}
|
||||
}
|
||||
|
||||
func (_c *GithubClient_CreateEntityRegistrationToken_Call) Run(run func(ctx context.Context)) *GithubClient_CreateEntityRegistrationToken_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(context.Context))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *GithubClient_CreateEntityRegistrationToken_Call) Return(_a0 *github.RegistrationToken, _a1 *github.Response, _a2 error) *GithubClient_CreateEntityRegistrationToken_Call {
|
||||
_c.Call.Return(_a0, _a1, _a2)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *GithubClient_CreateEntityRegistrationToken_Call) RunAndReturn(run func(context.Context) (*github.RegistrationToken, *github.Response, error)) *GithubClient_CreateEntityRegistrationToken_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// DeleteEntityHook provides a mock function with given fields: ctx, id
|
||||
func (_m *GithubClient) DeleteEntityHook(ctx context.Context, id int64) (*github.Response, error) {
|
||||
ret := _m.Called(ctx, id)
|
||||
|
|
@ -117,6 +182,35 @@ func (_m *GithubClient) DeleteEntityHook(ctx context.Context, id int64) (*github
|
|||
return r0, r1
|
||||
}
|
||||
|
||||
// GithubClient_DeleteEntityHook_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'DeleteEntityHook'
|
||||
type GithubClient_DeleteEntityHook_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// DeleteEntityHook is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
// - id int64
|
||||
func (_e *GithubClient_Expecter) DeleteEntityHook(ctx interface{}, id interface{}) *GithubClient_DeleteEntityHook_Call {
|
||||
return &GithubClient_DeleteEntityHook_Call{Call: _e.mock.On("DeleteEntityHook", ctx, id)}
|
||||
}
|
||||
|
||||
func (_c *GithubClient_DeleteEntityHook_Call) Run(run func(ctx context.Context, id int64)) *GithubClient_DeleteEntityHook_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(context.Context), args[1].(int64))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *GithubClient_DeleteEntityHook_Call) Return(ret *github.Response, err error) *GithubClient_DeleteEntityHook_Call {
|
||||
_c.Call.Return(ret, err)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *GithubClient_DeleteEntityHook_Call) RunAndReturn(run func(context.Context, int64) (*github.Response, error)) *GithubClient_DeleteEntityHook_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// GetEntity provides a mock function with no fields
|
||||
func (_m *GithubClient) GetEntity() params.ForgeEntity {
|
||||
ret := _m.Called()
|
||||
|
|
@ -135,6 +229,33 @@ func (_m *GithubClient) GetEntity() params.ForgeEntity {
|
|||
return r0
|
||||
}
|
||||
|
||||
// GithubClient_GetEntity_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetEntity'
|
||||
type GithubClient_GetEntity_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// GetEntity is a helper method to define mock.On call
|
||||
func (_e *GithubClient_Expecter) GetEntity() *GithubClient_GetEntity_Call {
|
||||
return &GithubClient_GetEntity_Call{Call: _e.mock.On("GetEntity")}
|
||||
}
|
||||
|
||||
func (_c *GithubClient_GetEntity_Call) Run(run func()) *GithubClient_GetEntity_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run()
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *GithubClient_GetEntity_Call) Return(_a0 params.ForgeEntity) *GithubClient_GetEntity_Call {
|
||||
_c.Call.Return(_a0)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *GithubClient_GetEntity_Call) RunAndReturn(run func() params.ForgeEntity) *GithubClient_GetEntity_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// GetEntityHook provides a mock function with given fields: ctx, id
|
||||
func (_m *GithubClient) GetEntityHook(ctx context.Context, id int64) (*github.Hook, error) {
|
||||
ret := _m.Called(ctx, id)
|
||||
|
|
@ -165,6 +286,35 @@ func (_m *GithubClient) GetEntityHook(ctx context.Context, id int64) (*github.Ho
|
|||
return r0, r1
|
||||
}
|
||||
|
||||
// GithubClient_GetEntityHook_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetEntityHook'
|
||||
type GithubClient_GetEntityHook_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// GetEntityHook is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
// - id int64
|
||||
func (_e *GithubClient_Expecter) GetEntityHook(ctx interface{}, id interface{}) *GithubClient_GetEntityHook_Call {
|
||||
return &GithubClient_GetEntityHook_Call{Call: _e.mock.On("GetEntityHook", ctx, id)}
|
||||
}
|
||||
|
||||
func (_c *GithubClient_GetEntityHook_Call) Run(run func(ctx context.Context, id int64)) *GithubClient_GetEntityHook_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(context.Context), args[1].(int64))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *GithubClient_GetEntityHook_Call) Return(ret *github.Hook, err error) *GithubClient_GetEntityHook_Call {
|
||||
_c.Call.Return(ret, err)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *GithubClient_GetEntityHook_Call) RunAndReturn(run func(context.Context, int64) (*github.Hook, error)) *GithubClient_GetEntityHook_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// GetEntityJITConfig provides a mock function with given fields: ctx, instance, pool, labels
|
||||
func (_m *GithubClient) GetEntityJITConfig(ctx context.Context, instance string, pool params.Pool, labels []string) (map[string]string, *github.Runner, error) {
|
||||
ret := _m.Called(ctx, instance, pool, labels)
|
||||
|
|
@ -204,6 +354,94 @@ func (_m *GithubClient) GetEntityJITConfig(ctx context.Context, instance string,
|
|||
return r0, r1, r2
|
||||
}
|
||||
|
||||
// GithubClient_GetEntityJITConfig_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetEntityJITConfig'
|
||||
type GithubClient_GetEntityJITConfig_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// GetEntityJITConfig is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
// - instance string
|
||||
// - pool params.Pool
|
||||
// - labels []string
|
||||
func (_e *GithubClient_Expecter) GetEntityJITConfig(ctx interface{}, instance interface{}, pool interface{}, labels interface{}) *GithubClient_GetEntityJITConfig_Call {
|
||||
return &GithubClient_GetEntityJITConfig_Call{Call: _e.mock.On("GetEntityJITConfig", ctx, instance, pool, labels)}
|
||||
}
|
||||
|
||||
func (_c *GithubClient_GetEntityJITConfig_Call) Run(run func(ctx context.Context, instance string, pool params.Pool, labels []string)) *GithubClient_GetEntityJITConfig_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(context.Context), args[1].(string), args[2].(params.Pool), args[3].([]string))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *GithubClient_GetEntityJITConfig_Call) Return(jitConfigMap map[string]string, runner *github.Runner, err error) *GithubClient_GetEntityJITConfig_Call {
|
||||
_c.Call.Return(jitConfigMap, runner, err)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *GithubClient_GetEntityJITConfig_Call) RunAndReturn(run func(context.Context, string, params.Pool, []string) (map[string]string, *github.Runner, error)) *GithubClient_GetEntityJITConfig_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// GetEntityRunnerGroupIDByName provides a mock function with given fields: ctx, runnerGroupName
|
||||
func (_m *GithubClient) GetEntityRunnerGroupIDByName(ctx context.Context, runnerGroupName string) (int64, error) {
|
||||
ret := _m.Called(ctx, runnerGroupName)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for GetEntityRunnerGroupIDByName")
|
||||
}
|
||||
|
||||
var r0 int64
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string) (int64, error)); ok {
|
||||
return rf(ctx, runnerGroupName)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string) int64); ok {
|
||||
r0 = rf(ctx, runnerGroupName)
|
||||
} else {
|
||||
r0 = ret.Get(0).(int64)
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, string) error); ok {
|
||||
r1 = rf(ctx, runnerGroupName)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// GithubClient_GetEntityRunnerGroupIDByName_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetEntityRunnerGroupIDByName'
|
||||
type GithubClient_GetEntityRunnerGroupIDByName_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// GetEntityRunnerGroupIDByName is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
// - runnerGroupName string
|
||||
func (_e *GithubClient_Expecter) GetEntityRunnerGroupIDByName(ctx interface{}, runnerGroupName interface{}) *GithubClient_GetEntityRunnerGroupIDByName_Call {
|
||||
return &GithubClient_GetEntityRunnerGroupIDByName_Call{Call: _e.mock.On("GetEntityRunnerGroupIDByName", ctx, runnerGroupName)}
|
||||
}
|
||||
|
||||
func (_c *GithubClient_GetEntityRunnerGroupIDByName_Call) Run(run func(ctx context.Context, runnerGroupName string)) *GithubClient_GetEntityRunnerGroupIDByName_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(context.Context), args[1].(string))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *GithubClient_GetEntityRunnerGroupIDByName_Call) Return(_a0 int64, _a1 error) *GithubClient_GetEntityRunnerGroupIDByName_Call {
|
||||
_c.Call.Return(_a0, _a1)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *GithubClient_GetEntityRunnerGroupIDByName_Call) RunAndReturn(run func(context.Context, string) (int64, error)) *GithubClient_GetEntityRunnerGroupIDByName_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// GetWorkflowJobByID provides a mock function with given fields: ctx, owner, repo, jobID
|
||||
func (_m *GithubClient) GetWorkflowJobByID(ctx context.Context, owner string, repo string, jobID int64) (*github.WorkflowJob, *github.Response, error) {
|
||||
ret := _m.Called(ctx, owner, repo, jobID)
|
||||
|
|
@ -243,6 +481,37 @@ func (_m *GithubClient) GetWorkflowJobByID(ctx context.Context, owner string, re
|
|||
return r0, r1, r2
|
||||
}
|
||||
|
||||
// GithubClient_GetWorkflowJobByID_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetWorkflowJobByID'
|
||||
type GithubClient_GetWorkflowJobByID_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// GetWorkflowJobByID is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
// - owner string
|
||||
// - repo string
|
||||
// - jobID int64
|
||||
func (_e *GithubClient_Expecter) GetWorkflowJobByID(ctx interface{}, owner interface{}, repo interface{}, jobID interface{}) *GithubClient_GetWorkflowJobByID_Call {
|
||||
return &GithubClient_GetWorkflowJobByID_Call{Call: _e.mock.On("GetWorkflowJobByID", ctx, owner, repo, jobID)}
|
||||
}
|
||||
|
||||
func (_c *GithubClient_GetWorkflowJobByID_Call) Run(run func(ctx context.Context, owner string, repo string, jobID int64)) *GithubClient_GetWorkflowJobByID_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(context.Context), args[1].(string), args[2].(string), args[3].(int64))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *GithubClient_GetWorkflowJobByID_Call) Return(_a0 *github.WorkflowJob, _a1 *github.Response, _a2 error) *GithubClient_GetWorkflowJobByID_Call {
|
||||
_c.Call.Return(_a0, _a1, _a2)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *GithubClient_GetWorkflowJobByID_Call) RunAndReturn(run func(context.Context, string, string, int64) (*github.WorkflowJob, *github.Response, error)) *GithubClient_GetWorkflowJobByID_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// GithubBaseURL provides a mock function with no fields
|
||||
func (_m *GithubClient) GithubBaseURL() *url.URL {
|
||||
ret := _m.Called()
|
||||
|
|
@ -263,6 +532,33 @@ func (_m *GithubClient) GithubBaseURL() *url.URL {
|
|||
return r0
|
||||
}
|
||||
|
||||
// GithubClient_GithubBaseURL_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GithubBaseURL'
|
||||
type GithubClient_GithubBaseURL_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// GithubBaseURL is a helper method to define mock.On call
|
||||
func (_e *GithubClient_Expecter) GithubBaseURL() *GithubClient_GithubBaseURL_Call {
|
||||
return &GithubClient_GithubBaseURL_Call{Call: _e.mock.On("GithubBaseURL")}
|
||||
}
|
||||
|
||||
func (_c *GithubClient_GithubBaseURL_Call) Run(run func()) *GithubClient_GithubBaseURL_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run()
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *GithubClient_GithubBaseURL_Call) Return(_a0 *url.URL) *GithubClient_GithubBaseURL_Call {
|
||||
_c.Call.Return(_a0)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *GithubClient_GithubBaseURL_Call) RunAndReturn(run func() *url.URL) *GithubClient_GithubBaseURL_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// ListEntityHooks provides a mock function with given fields: ctx, opts
|
||||
func (_m *GithubClient) ListEntityHooks(ctx context.Context, opts *github.ListOptions) ([]*github.Hook, *github.Response, error) {
|
||||
ret := _m.Called(ctx, opts)
|
||||
|
|
@ -302,6 +598,35 @@ func (_m *GithubClient) ListEntityHooks(ctx context.Context, opts *github.ListOp
|
|||
return r0, r1, r2
|
||||
}
|
||||
|
||||
// GithubClient_ListEntityHooks_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ListEntityHooks'
|
||||
type GithubClient_ListEntityHooks_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// ListEntityHooks is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
// - opts *github.ListOptions
|
||||
func (_e *GithubClient_Expecter) ListEntityHooks(ctx interface{}, opts interface{}) *GithubClient_ListEntityHooks_Call {
|
||||
return &GithubClient_ListEntityHooks_Call{Call: _e.mock.On("ListEntityHooks", ctx, opts)}
|
||||
}
|
||||
|
||||
func (_c *GithubClient_ListEntityHooks_Call) Run(run func(ctx context.Context, opts *github.ListOptions)) *GithubClient_ListEntityHooks_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(context.Context), args[1].(*github.ListOptions))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *GithubClient_ListEntityHooks_Call) Return(ret []*github.Hook, response *github.Response, err error) *GithubClient_ListEntityHooks_Call {
|
||||
_c.Call.Return(ret, response, err)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *GithubClient_ListEntityHooks_Call) RunAndReturn(run func(context.Context, *github.ListOptions) ([]*github.Hook, *github.Response, error)) *GithubClient_ListEntityHooks_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// ListEntityRunnerApplicationDownloads provides a mock function with given fields: ctx
|
||||
func (_m *GithubClient) ListEntityRunnerApplicationDownloads(ctx context.Context) ([]*github.RunnerApplicationDownload, *github.Response, error) {
|
||||
ret := _m.Called(ctx)
|
||||
|
|
@ -341,6 +666,34 @@ func (_m *GithubClient) ListEntityRunnerApplicationDownloads(ctx context.Context
|
|||
return r0, r1, r2
|
||||
}
|
||||
|
||||
// GithubClient_ListEntityRunnerApplicationDownloads_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ListEntityRunnerApplicationDownloads'
|
||||
type GithubClient_ListEntityRunnerApplicationDownloads_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// ListEntityRunnerApplicationDownloads is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
func (_e *GithubClient_Expecter) ListEntityRunnerApplicationDownloads(ctx interface{}) *GithubClient_ListEntityRunnerApplicationDownloads_Call {
|
||||
return &GithubClient_ListEntityRunnerApplicationDownloads_Call{Call: _e.mock.On("ListEntityRunnerApplicationDownloads", ctx)}
|
||||
}
|
||||
|
||||
func (_c *GithubClient_ListEntityRunnerApplicationDownloads_Call) Run(run func(ctx context.Context)) *GithubClient_ListEntityRunnerApplicationDownloads_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(context.Context))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *GithubClient_ListEntityRunnerApplicationDownloads_Call) Return(_a0 []*github.RunnerApplicationDownload, _a1 *github.Response, _a2 error) *GithubClient_ListEntityRunnerApplicationDownloads_Call {
|
||||
_c.Call.Return(_a0, _a1, _a2)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *GithubClient_ListEntityRunnerApplicationDownloads_Call) RunAndReturn(run func(context.Context) ([]*github.RunnerApplicationDownload, *github.Response, error)) *GithubClient_ListEntityRunnerApplicationDownloads_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// ListEntityRunners provides a mock function with given fields: ctx, opts
|
||||
func (_m *GithubClient) ListEntityRunners(ctx context.Context, opts *github.ListRunnersOptions) (*github.Runners, *github.Response, error) {
|
||||
ret := _m.Called(ctx, opts)
|
||||
|
|
@ -380,6 +733,35 @@ func (_m *GithubClient) ListEntityRunners(ctx context.Context, opts *github.List
|
|||
return r0, r1, r2
|
||||
}
|
||||
|
||||
// GithubClient_ListEntityRunners_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ListEntityRunners'
|
||||
type GithubClient_ListEntityRunners_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// ListEntityRunners is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
// - opts *github.ListRunnersOptions
|
||||
func (_e *GithubClient_Expecter) ListEntityRunners(ctx interface{}, opts interface{}) *GithubClient_ListEntityRunners_Call {
|
||||
return &GithubClient_ListEntityRunners_Call{Call: _e.mock.On("ListEntityRunners", ctx, opts)}
|
||||
}
|
||||
|
||||
func (_c *GithubClient_ListEntityRunners_Call) Run(run func(ctx context.Context, opts *github.ListRunnersOptions)) *GithubClient_ListEntityRunners_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(context.Context), args[1].(*github.ListRunnersOptions))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *GithubClient_ListEntityRunners_Call) Return(_a0 *github.Runners, _a1 *github.Response, _a2 error) *GithubClient_ListEntityRunners_Call {
|
||||
_c.Call.Return(_a0, _a1, _a2)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *GithubClient_ListEntityRunners_Call) RunAndReturn(run func(context.Context, *github.ListRunnersOptions) (*github.Runners, *github.Response, error)) *GithubClient_ListEntityRunners_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// PingEntityHook provides a mock function with given fields: ctx, id
|
||||
func (_m *GithubClient) PingEntityHook(ctx context.Context, id int64) (*github.Response, error) {
|
||||
ret := _m.Called(ctx, id)
|
||||
|
|
@ -410,6 +792,35 @@ func (_m *GithubClient) PingEntityHook(ctx context.Context, id int64) (*github.R
|
|||
return r0, r1
|
||||
}
|
||||
|
||||
// GithubClient_PingEntityHook_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'PingEntityHook'
|
||||
type GithubClient_PingEntityHook_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// PingEntityHook is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
// - id int64
|
||||
func (_e *GithubClient_Expecter) PingEntityHook(ctx interface{}, id interface{}) *GithubClient_PingEntityHook_Call {
|
||||
return &GithubClient_PingEntityHook_Call{Call: _e.mock.On("PingEntityHook", ctx, id)}
|
||||
}
|
||||
|
||||
func (_c *GithubClient_PingEntityHook_Call) Run(run func(ctx context.Context, id int64)) *GithubClient_PingEntityHook_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(context.Context), args[1].(int64))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *GithubClient_PingEntityHook_Call) Return(ret *github.Response, err error) *GithubClient_PingEntityHook_Call {
|
||||
_c.Call.Return(ret, err)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *GithubClient_PingEntityHook_Call) RunAndReturn(run func(context.Context, int64) (*github.Response, error)) *GithubClient_PingEntityHook_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// RateLimit provides a mock function with given fields: ctx
|
||||
func (_m *GithubClient) RateLimit(ctx context.Context) (*github.RateLimits, error) {
|
||||
ret := _m.Called(ctx)
|
||||
|
|
@ -440,6 +851,34 @@ func (_m *GithubClient) RateLimit(ctx context.Context) (*github.RateLimits, erro
|
|||
return r0, r1
|
||||
}
|
||||
|
||||
// GithubClient_RateLimit_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'RateLimit'
|
||||
type GithubClient_RateLimit_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// RateLimit is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
func (_e *GithubClient_Expecter) RateLimit(ctx interface{}) *GithubClient_RateLimit_Call {
|
||||
return &GithubClient_RateLimit_Call{Call: _e.mock.On("RateLimit", ctx)}
|
||||
}
|
||||
|
||||
func (_c *GithubClient_RateLimit_Call) Run(run func(ctx context.Context)) *GithubClient_RateLimit_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(context.Context))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *GithubClient_RateLimit_Call) Return(_a0 *github.RateLimits, _a1 error) *GithubClient_RateLimit_Call {
|
||||
_c.Call.Return(_a0, _a1)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *GithubClient_RateLimit_Call) RunAndReturn(run func(context.Context) (*github.RateLimits, error)) *GithubClient_RateLimit_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// RemoveEntityRunner provides a mock function with given fields: ctx, runnerID
|
||||
func (_m *GithubClient) RemoveEntityRunner(ctx context.Context, runnerID int64) error {
|
||||
ret := _m.Called(ctx, runnerID)
|
||||
|
|
@ -458,6 +897,35 @@ func (_m *GithubClient) RemoveEntityRunner(ctx context.Context, runnerID int64)
|
|||
return r0
|
||||
}
|
||||
|
||||
// GithubClient_RemoveEntityRunner_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'RemoveEntityRunner'
|
||||
type GithubClient_RemoveEntityRunner_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// RemoveEntityRunner is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
// - runnerID int64
|
||||
func (_e *GithubClient_Expecter) RemoveEntityRunner(ctx interface{}, runnerID interface{}) *GithubClient_RemoveEntityRunner_Call {
|
||||
return &GithubClient_RemoveEntityRunner_Call{Call: _e.mock.On("RemoveEntityRunner", ctx, runnerID)}
|
||||
}
|
||||
|
||||
func (_c *GithubClient_RemoveEntityRunner_Call) Run(run func(ctx context.Context, runnerID int64)) *GithubClient_RemoveEntityRunner_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(context.Context), args[1].(int64))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *GithubClient_RemoveEntityRunner_Call) Return(_a0 error) *GithubClient_RemoveEntityRunner_Call {
|
||||
_c.Call.Return(_a0)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *GithubClient_RemoveEntityRunner_Call) RunAndReturn(run func(context.Context, int64) error) *GithubClient_RemoveEntityRunner_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// NewGithubClient creates a new instance of GithubClient. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
|
||||
// The first argument is typically a *testing.T value.
|
||||
func NewGithubClient(t interface {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// Code generated by mockery v2.53.3. DO NOT EDIT.
|
||||
// Code generated by mockery. DO NOT EDIT.
|
||||
|
||||
package mocks
|
||||
|
||||
|
|
@ -18,6 +18,14 @@ type GithubEntityOperations struct {
|
|||
mock.Mock
|
||||
}
|
||||
|
||||
type GithubEntityOperations_Expecter struct {
|
||||
mock *mock.Mock
|
||||
}
|
||||
|
||||
func (_m *GithubEntityOperations) EXPECT() *GithubEntityOperations_Expecter {
|
||||
return &GithubEntityOperations_Expecter{mock: &_m.Mock}
|
||||
}
|
||||
|
||||
// CreateEntityHook provides a mock function with given fields: ctx, hook
|
||||
func (_m *GithubEntityOperations) CreateEntityHook(ctx context.Context, hook *github.Hook) (*github.Hook, error) {
|
||||
ret := _m.Called(ctx, hook)
|
||||
|
|
@ -48,6 +56,35 @@ func (_m *GithubEntityOperations) CreateEntityHook(ctx context.Context, hook *gi
|
|||
return r0, r1
|
||||
}
|
||||
|
||||
// GithubEntityOperations_CreateEntityHook_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CreateEntityHook'
|
||||
type GithubEntityOperations_CreateEntityHook_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// CreateEntityHook is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
// - hook *github.Hook
|
||||
func (_e *GithubEntityOperations_Expecter) CreateEntityHook(ctx interface{}, hook interface{}) *GithubEntityOperations_CreateEntityHook_Call {
|
||||
return &GithubEntityOperations_CreateEntityHook_Call{Call: _e.mock.On("CreateEntityHook", ctx, hook)}
|
||||
}
|
||||
|
||||
func (_c *GithubEntityOperations_CreateEntityHook_Call) Run(run func(ctx context.Context, hook *github.Hook)) *GithubEntityOperations_CreateEntityHook_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(context.Context), args[1].(*github.Hook))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *GithubEntityOperations_CreateEntityHook_Call) Return(ret *github.Hook, err error) *GithubEntityOperations_CreateEntityHook_Call {
|
||||
_c.Call.Return(ret, err)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *GithubEntityOperations_CreateEntityHook_Call) RunAndReturn(run func(context.Context, *github.Hook) (*github.Hook, error)) *GithubEntityOperations_CreateEntityHook_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// CreateEntityRegistrationToken provides a mock function with given fields: ctx
|
||||
func (_m *GithubEntityOperations) CreateEntityRegistrationToken(ctx context.Context) (*github.RegistrationToken, *github.Response, error) {
|
||||
ret := _m.Called(ctx)
|
||||
|
|
@ -87,6 +124,34 @@ func (_m *GithubEntityOperations) CreateEntityRegistrationToken(ctx context.Cont
|
|||
return r0, r1, r2
|
||||
}
|
||||
|
||||
// GithubEntityOperations_CreateEntityRegistrationToken_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CreateEntityRegistrationToken'
|
||||
type GithubEntityOperations_CreateEntityRegistrationToken_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// CreateEntityRegistrationToken is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
func (_e *GithubEntityOperations_Expecter) CreateEntityRegistrationToken(ctx interface{}) *GithubEntityOperations_CreateEntityRegistrationToken_Call {
|
||||
return &GithubEntityOperations_CreateEntityRegistrationToken_Call{Call: _e.mock.On("CreateEntityRegistrationToken", ctx)}
|
||||
}
|
||||
|
||||
func (_c *GithubEntityOperations_CreateEntityRegistrationToken_Call) Run(run func(ctx context.Context)) *GithubEntityOperations_CreateEntityRegistrationToken_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(context.Context))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *GithubEntityOperations_CreateEntityRegistrationToken_Call) Return(_a0 *github.RegistrationToken, _a1 *github.Response, _a2 error) *GithubEntityOperations_CreateEntityRegistrationToken_Call {
|
||||
_c.Call.Return(_a0, _a1, _a2)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *GithubEntityOperations_CreateEntityRegistrationToken_Call) RunAndReturn(run func(context.Context) (*github.RegistrationToken, *github.Response, error)) *GithubEntityOperations_CreateEntityRegistrationToken_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// DeleteEntityHook provides a mock function with given fields: ctx, id
|
||||
func (_m *GithubEntityOperations) DeleteEntityHook(ctx context.Context, id int64) (*github.Response, error) {
|
||||
ret := _m.Called(ctx, id)
|
||||
|
|
@ -117,6 +182,35 @@ func (_m *GithubEntityOperations) DeleteEntityHook(ctx context.Context, id int64
|
|||
return r0, r1
|
||||
}
|
||||
|
||||
// GithubEntityOperations_DeleteEntityHook_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'DeleteEntityHook'
|
||||
type GithubEntityOperations_DeleteEntityHook_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// DeleteEntityHook is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
// - id int64
|
||||
func (_e *GithubEntityOperations_Expecter) DeleteEntityHook(ctx interface{}, id interface{}) *GithubEntityOperations_DeleteEntityHook_Call {
|
||||
return &GithubEntityOperations_DeleteEntityHook_Call{Call: _e.mock.On("DeleteEntityHook", ctx, id)}
|
||||
}
|
||||
|
||||
func (_c *GithubEntityOperations_DeleteEntityHook_Call) Run(run func(ctx context.Context, id int64)) *GithubEntityOperations_DeleteEntityHook_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(context.Context), args[1].(int64))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *GithubEntityOperations_DeleteEntityHook_Call) Return(ret *github.Response, err error) *GithubEntityOperations_DeleteEntityHook_Call {
|
||||
_c.Call.Return(ret, err)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *GithubEntityOperations_DeleteEntityHook_Call) RunAndReturn(run func(context.Context, int64) (*github.Response, error)) *GithubEntityOperations_DeleteEntityHook_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// GetEntity provides a mock function with no fields
|
||||
func (_m *GithubEntityOperations) GetEntity() params.ForgeEntity {
|
||||
ret := _m.Called()
|
||||
|
|
@ -135,6 +229,33 @@ func (_m *GithubEntityOperations) GetEntity() params.ForgeEntity {
|
|||
return r0
|
||||
}
|
||||
|
||||
// GithubEntityOperations_GetEntity_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetEntity'
|
||||
type GithubEntityOperations_GetEntity_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// GetEntity is a helper method to define mock.On call
|
||||
func (_e *GithubEntityOperations_Expecter) GetEntity() *GithubEntityOperations_GetEntity_Call {
|
||||
return &GithubEntityOperations_GetEntity_Call{Call: _e.mock.On("GetEntity")}
|
||||
}
|
||||
|
||||
func (_c *GithubEntityOperations_GetEntity_Call) Run(run func()) *GithubEntityOperations_GetEntity_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run()
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *GithubEntityOperations_GetEntity_Call) Return(_a0 params.ForgeEntity) *GithubEntityOperations_GetEntity_Call {
|
||||
_c.Call.Return(_a0)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *GithubEntityOperations_GetEntity_Call) RunAndReturn(run func() params.ForgeEntity) *GithubEntityOperations_GetEntity_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// GetEntityHook provides a mock function with given fields: ctx, id
|
||||
func (_m *GithubEntityOperations) GetEntityHook(ctx context.Context, id int64) (*github.Hook, error) {
|
||||
ret := _m.Called(ctx, id)
|
||||
|
|
@ -165,6 +286,35 @@ func (_m *GithubEntityOperations) GetEntityHook(ctx context.Context, id int64) (
|
|||
return r0, r1
|
||||
}
|
||||
|
||||
// GithubEntityOperations_GetEntityHook_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetEntityHook'
|
||||
type GithubEntityOperations_GetEntityHook_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// GetEntityHook is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
// - id int64
|
||||
func (_e *GithubEntityOperations_Expecter) GetEntityHook(ctx interface{}, id interface{}) *GithubEntityOperations_GetEntityHook_Call {
|
||||
return &GithubEntityOperations_GetEntityHook_Call{Call: _e.mock.On("GetEntityHook", ctx, id)}
|
||||
}
|
||||
|
||||
func (_c *GithubEntityOperations_GetEntityHook_Call) Run(run func(ctx context.Context, id int64)) *GithubEntityOperations_GetEntityHook_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(context.Context), args[1].(int64))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *GithubEntityOperations_GetEntityHook_Call) Return(ret *github.Hook, err error) *GithubEntityOperations_GetEntityHook_Call {
|
||||
_c.Call.Return(ret, err)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *GithubEntityOperations_GetEntityHook_Call) RunAndReturn(run func(context.Context, int64) (*github.Hook, error)) *GithubEntityOperations_GetEntityHook_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// GetEntityJITConfig provides a mock function with given fields: ctx, instance, pool, labels
|
||||
func (_m *GithubEntityOperations) GetEntityJITConfig(ctx context.Context, instance string, pool params.Pool, labels []string) (map[string]string, *github.Runner, error) {
|
||||
ret := _m.Called(ctx, instance, pool, labels)
|
||||
|
|
@ -204,6 +354,94 @@ func (_m *GithubEntityOperations) GetEntityJITConfig(ctx context.Context, instan
|
|||
return r0, r1, r2
|
||||
}
|
||||
|
||||
// GithubEntityOperations_GetEntityJITConfig_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetEntityJITConfig'
|
||||
type GithubEntityOperations_GetEntityJITConfig_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// GetEntityJITConfig is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
// - instance string
|
||||
// - pool params.Pool
|
||||
// - labels []string
|
||||
func (_e *GithubEntityOperations_Expecter) GetEntityJITConfig(ctx interface{}, instance interface{}, pool interface{}, labels interface{}) *GithubEntityOperations_GetEntityJITConfig_Call {
|
||||
return &GithubEntityOperations_GetEntityJITConfig_Call{Call: _e.mock.On("GetEntityJITConfig", ctx, instance, pool, labels)}
|
||||
}
|
||||
|
||||
func (_c *GithubEntityOperations_GetEntityJITConfig_Call) Run(run func(ctx context.Context, instance string, pool params.Pool, labels []string)) *GithubEntityOperations_GetEntityJITConfig_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(context.Context), args[1].(string), args[2].(params.Pool), args[3].([]string))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *GithubEntityOperations_GetEntityJITConfig_Call) Return(jitConfigMap map[string]string, runner *github.Runner, err error) *GithubEntityOperations_GetEntityJITConfig_Call {
|
||||
_c.Call.Return(jitConfigMap, runner, err)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *GithubEntityOperations_GetEntityJITConfig_Call) RunAndReturn(run func(context.Context, string, params.Pool, []string) (map[string]string, *github.Runner, error)) *GithubEntityOperations_GetEntityJITConfig_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// GetEntityRunnerGroupIDByName provides a mock function with given fields: ctx, runnerGroupName
|
||||
func (_m *GithubEntityOperations) GetEntityRunnerGroupIDByName(ctx context.Context, runnerGroupName string) (int64, error) {
|
||||
ret := _m.Called(ctx, runnerGroupName)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for GetEntityRunnerGroupIDByName")
|
||||
}
|
||||
|
||||
var r0 int64
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string) (int64, error)); ok {
|
||||
return rf(ctx, runnerGroupName)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string) int64); ok {
|
||||
r0 = rf(ctx, runnerGroupName)
|
||||
} else {
|
||||
r0 = ret.Get(0).(int64)
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, string) error); ok {
|
||||
r1 = rf(ctx, runnerGroupName)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// GithubEntityOperations_GetEntityRunnerGroupIDByName_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetEntityRunnerGroupIDByName'
|
||||
type GithubEntityOperations_GetEntityRunnerGroupIDByName_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// GetEntityRunnerGroupIDByName is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
// - runnerGroupName string
|
||||
func (_e *GithubEntityOperations_Expecter) GetEntityRunnerGroupIDByName(ctx interface{}, runnerGroupName interface{}) *GithubEntityOperations_GetEntityRunnerGroupIDByName_Call {
|
||||
return &GithubEntityOperations_GetEntityRunnerGroupIDByName_Call{Call: _e.mock.On("GetEntityRunnerGroupIDByName", ctx, runnerGroupName)}
|
||||
}
|
||||
|
||||
func (_c *GithubEntityOperations_GetEntityRunnerGroupIDByName_Call) Run(run func(ctx context.Context, runnerGroupName string)) *GithubEntityOperations_GetEntityRunnerGroupIDByName_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(context.Context), args[1].(string))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *GithubEntityOperations_GetEntityRunnerGroupIDByName_Call) Return(_a0 int64, _a1 error) *GithubEntityOperations_GetEntityRunnerGroupIDByName_Call {
|
||||
_c.Call.Return(_a0, _a1)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *GithubEntityOperations_GetEntityRunnerGroupIDByName_Call) RunAndReturn(run func(context.Context, string) (int64, error)) *GithubEntityOperations_GetEntityRunnerGroupIDByName_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// GithubBaseURL provides a mock function with no fields
|
||||
func (_m *GithubEntityOperations) GithubBaseURL() *url.URL {
|
||||
ret := _m.Called()
|
||||
|
|
@ -224,6 +462,33 @@ func (_m *GithubEntityOperations) GithubBaseURL() *url.URL {
|
|||
return r0
|
||||
}
|
||||
|
||||
// GithubEntityOperations_GithubBaseURL_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GithubBaseURL'
|
||||
type GithubEntityOperations_GithubBaseURL_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// GithubBaseURL is a helper method to define mock.On call
|
||||
func (_e *GithubEntityOperations_Expecter) GithubBaseURL() *GithubEntityOperations_GithubBaseURL_Call {
|
||||
return &GithubEntityOperations_GithubBaseURL_Call{Call: _e.mock.On("GithubBaseURL")}
|
||||
}
|
||||
|
||||
func (_c *GithubEntityOperations_GithubBaseURL_Call) Run(run func()) *GithubEntityOperations_GithubBaseURL_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run()
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *GithubEntityOperations_GithubBaseURL_Call) Return(_a0 *url.URL) *GithubEntityOperations_GithubBaseURL_Call {
|
||||
_c.Call.Return(_a0)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *GithubEntityOperations_GithubBaseURL_Call) RunAndReturn(run func() *url.URL) *GithubEntityOperations_GithubBaseURL_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// ListEntityHooks provides a mock function with given fields: ctx, opts
|
||||
func (_m *GithubEntityOperations) ListEntityHooks(ctx context.Context, opts *github.ListOptions) ([]*github.Hook, *github.Response, error) {
|
||||
ret := _m.Called(ctx, opts)
|
||||
|
|
@ -263,6 +528,35 @@ func (_m *GithubEntityOperations) ListEntityHooks(ctx context.Context, opts *git
|
|||
return r0, r1, r2
|
||||
}
|
||||
|
||||
// GithubEntityOperations_ListEntityHooks_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ListEntityHooks'
|
||||
type GithubEntityOperations_ListEntityHooks_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// ListEntityHooks is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
// - opts *github.ListOptions
|
||||
func (_e *GithubEntityOperations_Expecter) ListEntityHooks(ctx interface{}, opts interface{}) *GithubEntityOperations_ListEntityHooks_Call {
|
||||
return &GithubEntityOperations_ListEntityHooks_Call{Call: _e.mock.On("ListEntityHooks", ctx, opts)}
|
||||
}
|
||||
|
||||
func (_c *GithubEntityOperations_ListEntityHooks_Call) Run(run func(ctx context.Context, opts *github.ListOptions)) *GithubEntityOperations_ListEntityHooks_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(context.Context), args[1].(*github.ListOptions))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *GithubEntityOperations_ListEntityHooks_Call) Return(ret []*github.Hook, response *github.Response, err error) *GithubEntityOperations_ListEntityHooks_Call {
|
||||
_c.Call.Return(ret, response, err)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *GithubEntityOperations_ListEntityHooks_Call) RunAndReturn(run func(context.Context, *github.ListOptions) ([]*github.Hook, *github.Response, error)) *GithubEntityOperations_ListEntityHooks_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// ListEntityRunnerApplicationDownloads provides a mock function with given fields: ctx
|
||||
func (_m *GithubEntityOperations) ListEntityRunnerApplicationDownloads(ctx context.Context) ([]*github.RunnerApplicationDownload, *github.Response, error) {
|
||||
ret := _m.Called(ctx)
|
||||
|
|
@ -302,6 +596,34 @@ func (_m *GithubEntityOperations) ListEntityRunnerApplicationDownloads(ctx conte
|
|||
return r0, r1, r2
|
||||
}
|
||||
|
||||
// GithubEntityOperations_ListEntityRunnerApplicationDownloads_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ListEntityRunnerApplicationDownloads'
|
||||
type GithubEntityOperations_ListEntityRunnerApplicationDownloads_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// ListEntityRunnerApplicationDownloads is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
func (_e *GithubEntityOperations_Expecter) ListEntityRunnerApplicationDownloads(ctx interface{}) *GithubEntityOperations_ListEntityRunnerApplicationDownloads_Call {
|
||||
return &GithubEntityOperations_ListEntityRunnerApplicationDownloads_Call{Call: _e.mock.On("ListEntityRunnerApplicationDownloads", ctx)}
|
||||
}
|
||||
|
||||
func (_c *GithubEntityOperations_ListEntityRunnerApplicationDownloads_Call) Run(run func(ctx context.Context)) *GithubEntityOperations_ListEntityRunnerApplicationDownloads_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(context.Context))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *GithubEntityOperations_ListEntityRunnerApplicationDownloads_Call) Return(_a0 []*github.RunnerApplicationDownload, _a1 *github.Response, _a2 error) *GithubEntityOperations_ListEntityRunnerApplicationDownloads_Call {
|
||||
_c.Call.Return(_a0, _a1, _a2)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *GithubEntityOperations_ListEntityRunnerApplicationDownloads_Call) RunAndReturn(run func(context.Context) ([]*github.RunnerApplicationDownload, *github.Response, error)) *GithubEntityOperations_ListEntityRunnerApplicationDownloads_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// ListEntityRunners provides a mock function with given fields: ctx, opts
|
||||
func (_m *GithubEntityOperations) ListEntityRunners(ctx context.Context, opts *github.ListRunnersOptions) (*github.Runners, *github.Response, error) {
|
||||
ret := _m.Called(ctx, opts)
|
||||
|
|
@ -341,6 +663,35 @@ func (_m *GithubEntityOperations) ListEntityRunners(ctx context.Context, opts *g
|
|||
return r0, r1, r2
|
||||
}
|
||||
|
||||
// GithubEntityOperations_ListEntityRunners_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ListEntityRunners'
|
||||
type GithubEntityOperations_ListEntityRunners_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// ListEntityRunners is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
// - opts *github.ListRunnersOptions
|
||||
func (_e *GithubEntityOperations_Expecter) ListEntityRunners(ctx interface{}, opts interface{}) *GithubEntityOperations_ListEntityRunners_Call {
|
||||
return &GithubEntityOperations_ListEntityRunners_Call{Call: _e.mock.On("ListEntityRunners", ctx, opts)}
|
||||
}
|
||||
|
||||
func (_c *GithubEntityOperations_ListEntityRunners_Call) Run(run func(ctx context.Context, opts *github.ListRunnersOptions)) *GithubEntityOperations_ListEntityRunners_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(context.Context), args[1].(*github.ListRunnersOptions))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *GithubEntityOperations_ListEntityRunners_Call) Return(_a0 *github.Runners, _a1 *github.Response, _a2 error) *GithubEntityOperations_ListEntityRunners_Call {
|
||||
_c.Call.Return(_a0, _a1, _a2)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *GithubEntityOperations_ListEntityRunners_Call) RunAndReturn(run func(context.Context, *github.ListRunnersOptions) (*github.Runners, *github.Response, error)) *GithubEntityOperations_ListEntityRunners_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// PingEntityHook provides a mock function with given fields: ctx, id
|
||||
func (_m *GithubEntityOperations) PingEntityHook(ctx context.Context, id int64) (*github.Response, error) {
|
||||
ret := _m.Called(ctx, id)
|
||||
|
|
@ -371,6 +722,35 @@ func (_m *GithubEntityOperations) PingEntityHook(ctx context.Context, id int64)
|
|||
return r0, r1
|
||||
}
|
||||
|
||||
// GithubEntityOperations_PingEntityHook_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'PingEntityHook'
|
||||
type GithubEntityOperations_PingEntityHook_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// PingEntityHook is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
// - id int64
|
||||
func (_e *GithubEntityOperations_Expecter) PingEntityHook(ctx interface{}, id interface{}) *GithubEntityOperations_PingEntityHook_Call {
|
||||
return &GithubEntityOperations_PingEntityHook_Call{Call: _e.mock.On("PingEntityHook", ctx, id)}
|
||||
}
|
||||
|
||||
func (_c *GithubEntityOperations_PingEntityHook_Call) Run(run func(ctx context.Context, id int64)) *GithubEntityOperations_PingEntityHook_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(context.Context), args[1].(int64))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *GithubEntityOperations_PingEntityHook_Call) Return(ret *github.Response, err error) *GithubEntityOperations_PingEntityHook_Call {
|
||||
_c.Call.Return(ret, err)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *GithubEntityOperations_PingEntityHook_Call) RunAndReturn(run func(context.Context, int64) (*github.Response, error)) *GithubEntityOperations_PingEntityHook_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// RateLimit provides a mock function with given fields: ctx
|
||||
func (_m *GithubEntityOperations) RateLimit(ctx context.Context) (*github.RateLimits, error) {
|
||||
ret := _m.Called(ctx)
|
||||
|
|
@ -401,6 +781,34 @@ func (_m *GithubEntityOperations) RateLimit(ctx context.Context) (*github.RateLi
|
|||
return r0, r1
|
||||
}
|
||||
|
||||
// GithubEntityOperations_RateLimit_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'RateLimit'
|
||||
type GithubEntityOperations_RateLimit_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// RateLimit is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
func (_e *GithubEntityOperations_Expecter) RateLimit(ctx interface{}) *GithubEntityOperations_RateLimit_Call {
|
||||
return &GithubEntityOperations_RateLimit_Call{Call: _e.mock.On("RateLimit", ctx)}
|
||||
}
|
||||
|
||||
func (_c *GithubEntityOperations_RateLimit_Call) Run(run func(ctx context.Context)) *GithubEntityOperations_RateLimit_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(context.Context))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *GithubEntityOperations_RateLimit_Call) Return(_a0 *github.RateLimits, _a1 error) *GithubEntityOperations_RateLimit_Call {
|
||||
_c.Call.Return(_a0, _a1)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *GithubEntityOperations_RateLimit_Call) RunAndReturn(run func(context.Context) (*github.RateLimits, error)) *GithubEntityOperations_RateLimit_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// RemoveEntityRunner provides a mock function with given fields: ctx, runnerID
|
||||
func (_m *GithubEntityOperations) RemoveEntityRunner(ctx context.Context, runnerID int64) error {
|
||||
ret := _m.Called(ctx, runnerID)
|
||||
|
|
@ -419,6 +827,35 @@ func (_m *GithubEntityOperations) RemoveEntityRunner(ctx context.Context, runner
|
|||
return r0
|
||||
}
|
||||
|
||||
// GithubEntityOperations_RemoveEntityRunner_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'RemoveEntityRunner'
|
||||
type GithubEntityOperations_RemoveEntityRunner_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// RemoveEntityRunner is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
// - runnerID int64
|
||||
func (_e *GithubEntityOperations_Expecter) RemoveEntityRunner(ctx interface{}, runnerID interface{}) *GithubEntityOperations_RemoveEntityRunner_Call {
|
||||
return &GithubEntityOperations_RemoveEntityRunner_Call{Call: _e.mock.On("RemoveEntityRunner", ctx, runnerID)}
|
||||
}
|
||||
|
||||
func (_c *GithubEntityOperations_RemoveEntityRunner_Call) Run(run func(ctx context.Context, runnerID int64)) *GithubEntityOperations_RemoveEntityRunner_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(context.Context), args[1].(int64))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *GithubEntityOperations_RemoveEntityRunner_Call) Return(_a0 error) *GithubEntityOperations_RemoveEntityRunner_Call {
|
||||
_c.Call.Return(_a0)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *GithubEntityOperations_RemoveEntityRunner_Call) RunAndReturn(run func(context.Context, int64) error) *GithubEntityOperations_RemoveEntityRunner_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// NewGithubEntityOperations creates a new instance of GithubEntityOperations. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
|
||||
// The first argument is typically a *testing.T value.
|
||||
func NewGithubEntityOperations(t interface {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// Code generated by mockery v2.53.3. DO NOT EDIT.
|
||||
// Code generated by mockery. DO NOT EDIT.
|
||||
|
||||
package mocks
|
||||
|
||||
|
|
@ -14,6 +14,14 @@ type PoolManager struct {
|
|||
mock.Mock
|
||||
}
|
||||
|
||||
type PoolManager_Expecter struct {
|
||||
mock *mock.Mock
|
||||
}
|
||||
|
||||
func (_m *PoolManager) EXPECT() *PoolManager_Expecter {
|
||||
return &PoolManager_Expecter{mock: &_m.Mock}
|
||||
}
|
||||
|
||||
// GetWebhookInfo provides a mock function with given fields: ctx
|
||||
func (_m *PoolManager) GetWebhookInfo(ctx context.Context) (params.HookInfo, error) {
|
||||
ret := _m.Called(ctx)
|
||||
|
|
@ -42,6 +50,34 @@ func (_m *PoolManager) GetWebhookInfo(ctx context.Context) (params.HookInfo, err
|
|||
return r0, r1
|
||||
}
|
||||
|
||||
// PoolManager_GetWebhookInfo_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetWebhookInfo'
|
||||
type PoolManager_GetWebhookInfo_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// GetWebhookInfo is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
func (_e *PoolManager_Expecter) GetWebhookInfo(ctx interface{}) *PoolManager_GetWebhookInfo_Call {
|
||||
return &PoolManager_GetWebhookInfo_Call{Call: _e.mock.On("GetWebhookInfo", ctx)}
|
||||
}
|
||||
|
||||
func (_c *PoolManager_GetWebhookInfo_Call) Run(run func(ctx context.Context)) *PoolManager_GetWebhookInfo_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(context.Context))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *PoolManager_GetWebhookInfo_Call) Return(_a0 params.HookInfo, _a1 error) *PoolManager_GetWebhookInfo_Call {
|
||||
_c.Call.Return(_a0, _a1)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *PoolManager_GetWebhookInfo_Call) RunAndReturn(run func(context.Context) (params.HookInfo, error)) *PoolManager_GetWebhookInfo_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// GithubRunnerRegistrationToken provides a mock function with no fields
|
||||
func (_m *PoolManager) GithubRunnerRegistrationToken() (string, error) {
|
||||
ret := _m.Called()
|
||||
|
|
@ -70,6 +106,33 @@ func (_m *PoolManager) GithubRunnerRegistrationToken() (string, error) {
|
|||
return r0, r1
|
||||
}
|
||||
|
||||
// PoolManager_GithubRunnerRegistrationToken_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GithubRunnerRegistrationToken'
|
||||
type PoolManager_GithubRunnerRegistrationToken_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// GithubRunnerRegistrationToken is a helper method to define mock.On call
|
||||
func (_e *PoolManager_Expecter) GithubRunnerRegistrationToken() *PoolManager_GithubRunnerRegistrationToken_Call {
|
||||
return &PoolManager_GithubRunnerRegistrationToken_Call{Call: _e.mock.On("GithubRunnerRegistrationToken")}
|
||||
}
|
||||
|
||||
func (_c *PoolManager_GithubRunnerRegistrationToken_Call) Run(run func()) *PoolManager_GithubRunnerRegistrationToken_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run()
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *PoolManager_GithubRunnerRegistrationToken_Call) Return(_a0 string, _a1 error) *PoolManager_GithubRunnerRegistrationToken_Call {
|
||||
_c.Call.Return(_a0, _a1)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *PoolManager_GithubRunnerRegistrationToken_Call) RunAndReturn(run func() (string, error)) *PoolManager_GithubRunnerRegistrationToken_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// HandleWorkflowJob provides a mock function with given fields: job
|
||||
func (_m *PoolManager) HandleWorkflowJob(job params.WorkflowJob) error {
|
||||
ret := _m.Called(job)
|
||||
|
|
@ -88,6 +151,34 @@ func (_m *PoolManager) HandleWorkflowJob(job params.WorkflowJob) error {
|
|||
return r0
|
||||
}
|
||||
|
||||
// PoolManager_HandleWorkflowJob_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'HandleWorkflowJob'
|
||||
type PoolManager_HandleWorkflowJob_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// HandleWorkflowJob is a helper method to define mock.On call
|
||||
// - job params.WorkflowJob
|
||||
func (_e *PoolManager_Expecter) HandleWorkflowJob(job interface{}) *PoolManager_HandleWorkflowJob_Call {
|
||||
return &PoolManager_HandleWorkflowJob_Call{Call: _e.mock.On("HandleWorkflowJob", job)}
|
||||
}
|
||||
|
||||
func (_c *PoolManager_HandleWorkflowJob_Call) Run(run func(job params.WorkflowJob)) *PoolManager_HandleWorkflowJob_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(params.WorkflowJob))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *PoolManager_HandleWorkflowJob_Call) Return(_a0 error) *PoolManager_HandleWorkflowJob_Call {
|
||||
_c.Call.Return(_a0)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *PoolManager_HandleWorkflowJob_Call) RunAndReturn(run func(params.WorkflowJob) error) *PoolManager_HandleWorkflowJob_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// ID provides a mock function with no fields
|
||||
func (_m *PoolManager) ID() string {
|
||||
ret := _m.Called()
|
||||
|
|
@ -106,6 +197,33 @@ func (_m *PoolManager) ID() string {
|
|||
return r0
|
||||
}
|
||||
|
||||
// PoolManager_ID_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ID'
|
||||
type PoolManager_ID_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// ID is a helper method to define mock.On call
|
||||
func (_e *PoolManager_Expecter) ID() *PoolManager_ID_Call {
|
||||
return &PoolManager_ID_Call{Call: _e.mock.On("ID")}
|
||||
}
|
||||
|
||||
func (_c *PoolManager_ID_Call) Run(run func()) *PoolManager_ID_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run()
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *PoolManager_ID_Call) Return(_a0 string) *PoolManager_ID_Call {
|
||||
_c.Call.Return(_a0)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *PoolManager_ID_Call) RunAndReturn(run func() string) *PoolManager_ID_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// InstallWebhook provides a mock function with given fields: ctx, param
|
||||
func (_m *PoolManager) InstallWebhook(ctx context.Context, param params.InstallWebhookParams) (params.HookInfo, error) {
|
||||
ret := _m.Called(ctx, param)
|
||||
|
|
@ -134,6 +252,35 @@ func (_m *PoolManager) InstallWebhook(ctx context.Context, param params.InstallW
|
|||
return r0, r1
|
||||
}
|
||||
|
||||
// PoolManager_InstallWebhook_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'InstallWebhook'
|
||||
type PoolManager_InstallWebhook_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// InstallWebhook is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
// - param params.InstallWebhookParams
|
||||
func (_e *PoolManager_Expecter) InstallWebhook(ctx interface{}, param interface{}) *PoolManager_InstallWebhook_Call {
|
||||
return &PoolManager_InstallWebhook_Call{Call: _e.mock.On("InstallWebhook", ctx, param)}
|
||||
}
|
||||
|
||||
func (_c *PoolManager_InstallWebhook_Call) Run(run func(ctx context.Context, param params.InstallWebhookParams)) *PoolManager_InstallWebhook_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(context.Context), args[1].(params.InstallWebhookParams))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *PoolManager_InstallWebhook_Call) Return(_a0 params.HookInfo, _a1 error) *PoolManager_InstallWebhook_Call {
|
||||
_c.Call.Return(_a0, _a1)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *PoolManager_InstallWebhook_Call) RunAndReturn(run func(context.Context, params.InstallWebhookParams) (params.HookInfo, error)) *PoolManager_InstallWebhook_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// RootCABundle provides a mock function with no fields
|
||||
func (_m *PoolManager) RootCABundle() (params.CertificateBundle, error) {
|
||||
ret := _m.Called()
|
||||
|
|
@ -162,11 +309,67 @@ func (_m *PoolManager) RootCABundle() (params.CertificateBundle, error) {
|
|||
return r0, r1
|
||||
}
|
||||
|
||||
// PoolManager_RootCABundle_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'RootCABundle'
|
||||
type PoolManager_RootCABundle_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// RootCABundle is a helper method to define mock.On call
|
||||
func (_e *PoolManager_Expecter) RootCABundle() *PoolManager_RootCABundle_Call {
|
||||
return &PoolManager_RootCABundle_Call{Call: _e.mock.On("RootCABundle")}
|
||||
}
|
||||
|
||||
func (_c *PoolManager_RootCABundle_Call) Run(run func()) *PoolManager_RootCABundle_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run()
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *PoolManager_RootCABundle_Call) Return(_a0 params.CertificateBundle, _a1 error) *PoolManager_RootCABundle_Call {
|
||||
_c.Call.Return(_a0, _a1)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *PoolManager_RootCABundle_Call) RunAndReturn(run func() (params.CertificateBundle, error)) *PoolManager_RootCABundle_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// SetPoolRunningState provides a mock function with given fields: isRunning, failureReason
|
||||
func (_m *PoolManager) SetPoolRunningState(isRunning bool, failureReason string) {
|
||||
_m.Called(isRunning, failureReason)
|
||||
}
|
||||
|
||||
// PoolManager_SetPoolRunningState_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SetPoolRunningState'
|
||||
type PoolManager_SetPoolRunningState_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// SetPoolRunningState is a helper method to define mock.On call
|
||||
// - isRunning bool
|
||||
// - failureReason string
|
||||
func (_e *PoolManager_Expecter) SetPoolRunningState(isRunning interface{}, failureReason interface{}) *PoolManager_SetPoolRunningState_Call {
|
||||
return &PoolManager_SetPoolRunningState_Call{Call: _e.mock.On("SetPoolRunningState", isRunning, failureReason)}
|
||||
}
|
||||
|
||||
func (_c *PoolManager_SetPoolRunningState_Call) Run(run func(isRunning bool, failureReason string)) *PoolManager_SetPoolRunningState_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(bool), args[1].(string))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *PoolManager_SetPoolRunningState_Call) Return() *PoolManager_SetPoolRunningState_Call {
|
||||
_c.Call.Return()
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *PoolManager_SetPoolRunningState_Call) RunAndReturn(run func(bool, string)) *PoolManager_SetPoolRunningState_Call {
|
||||
_c.Run(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// Start provides a mock function with no fields
|
||||
func (_m *PoolManager) Start() error {
|
||||
ret := _m.Called()
|
||||
|
|
@ -185,6 +388,33 @@ func (_m *PoolManager) Start() error {
|
|||
return r0
|
||||
}
|
||||
|
||||
// PoolManager_Start_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Start'
|
||||
type PoolManager_Start_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// Start is a helper method to define mock.On call
|
||||
func (_e *PoolManager_Expecter) Start() *PoolManager_Start_Call {
|
||||
return &PoolManager_Start_Call{Call: _e.mock.On("Start")}
|
||||
}
|
||||
|
||||
func (_c *PoolManager_Start_Call) Run(run func()) *PoolManager_Start_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run()
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *PoolManager_Start_Call) Return(_a0 error) *PoolManager_Start_Call {
|
||||
_c.Call.Return(_a0)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *PoolManager_Start_Call) RunAndReturn(run func() error) *PoolManager_Start_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// Status provides a mock function with no fields
|
||||
func (_m *PoolManager) Status() params.PoolManagerStatus {
|
||||
ret := _m.Called()
|
||||
|
|
@ -203,6 +433,33 @@ func (_m *PoolManager) Status() params.PoolManagerStatus {
|
|||
return r0
|
||||
}
|
||||
|
||||
// PoolManager_Status_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Status'
|
||||
type PoolManager_Status_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// Status is a helper method to define mock.On call
|
||||
func (_e *PoolManager_Expecter) Status() *PoolManager_Status_Call {
|
||||
return &PoolManager_Status_Call{Call: _e.mock.On("Status")}
|
||||
}
|
||||
|
||||
func (_c *PoolManager_Status_Call) Run(run func()) *PoolManager_Status_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run()
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *PoolManager_Status_Call) Return(_a0 params.PoolManagerStatus) *PoolManager_Status_Call {
|
||||
_c.Call.Return(_a0)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *PoolManager_Status_Call) RunAndReturn(run func() params.PoolManagerStatus) *PoolManager_Status_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// Stop provides a mock function with no fields
|
||||
func (_m *PoolManager) Stop() error {
|
||||
ret := _m.Called()
|
||||
|
|
@ -221,6 +478,33 @@ func (_m *PoolManager) Stop() error {
|
|||
return r0
|
||||
}
|
||||
|
||||
// PoolManager_Stop_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Stop'
|
||||
type PoolManager_Stop_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// Stop is a helper method to define mock.On call
|
||||
func (_e *PoolManager_Expecter) Stop() *PoolManager_Stop_Call {
|
||||
return &PoolManager_Stop_Call{Call: _e.mock.On("Stop")}
|
||||
}
|
||||
|
||||
func (_c *PoolManager_Stop_Call) Run(run func()) *PoolManager_Stop_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run()
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *PoolManager_Stop_Call) Return(_a0 error) *PoolManager_Stop_Call {
|
||||
_c.Call.Return(_a0)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *PoolManager_Stop_Call) RunAndReturn(run func() error) *PoolManager_Stop_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// UninstallWebhook provides a mock function with given fields: ctx
|
||||
func (_m *PoolManager) UninstallWebhook(ctx context.Context) error {
|
||||
ret := _m.Called(ctx)
|
||||
|
|
@ -239,6 +523,34 @@ func (_m *PoolManager) UninstallWebhook(ctx context.Context) error {
|
|||
return r0
|
||||
}
|
||||
|
||||
// PoolManager_UninstallWebhook_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'UninstallWebhook'
|
||||
type PoolManager_UninstallWebhook_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// UninstallWebhook is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
func (_e *PoolManager_Expecter) UninstallWebhook(ctx interface{}) *PoolManager_UninstallWebhook_Call {
|
||||
return &PoolManager_UninstallWebhook_Call{Call: _e.mock.On("UninstallWebhook", ctx)}
|
||||
}
|
||||
|
||||
func (_c *PoolManager_UninstallWebhook_Call) Run(run func(ctx context.Context)) *PoolManager_UninstallWebhook_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(context.Context))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *PoolManager_UninstallWebhook_Call) Return(_a0 error) *PoolManager_UninstallWebhook_Call {
|
||||
_c.Call.Return(_a0)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *PoolManager_UninstallWebhook_Call) RunAndReturn(run func(context.Context) error) *PoolManager_UninstallWebhook_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// Wait provides a mock function with no fields
|
||||
func (_m *PoolManager) Wait() error {
|
||||
ret := _m.Called()
|
||||
|
|
@ -257,6 +569,33 @@ func (_m *PoolManager) Wait() error {
|
|||
return r0
|
||||
}
|
||||
|
||||
// PoolManager_Wait_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Wait'
|
||||
type PoolManager_Wait_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// Wait is a helper method to define mock.On call
|
||||
func (_e *PoolManager_Expecter) Wait() *PoolManager_Wait_Call {
|
||||
return &PoolManager_Wait_Call{Call: _e.mock.On("Wait")}
|
||||
}
|
||||
|
||||
func (_c *PoolManager_Wait_Call) Run(run func()) *PoolManager_Wait_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run()
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *PoolManager_Wait_Call) Return(_a0 error) *PoolManager_Wait_Call {
|
||||
_c.Call.Return(_a0)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *PoolManager_Wait_Call) RunAndReturn(run func() error) *PoolManager_Wait_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// WebhookSecret provides a mock function with no fields
|
||||
func (_m *PoolManager) WebhookSecret() string {
|
||||
ret := _m.Called()
|
||||
|
|
@ -275,6 +614,33 @@ func (_m *PoolManager) WebhookSecret() string {
|
|||
return r0
|
||||
}
|
||||
|
||||
// PoolManager_WebhookSecret_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'WebhookSecret'
|
||||
type PoolManager_WebhookSecret_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// WebhookSecret is a helper method to define mock.On call
|
||||
func (_e *PoolManager_Expecter) WebhookSecret() *PoolManager_WebhookSecret_Call {
|
||||
return &PoolManager_WebhookSecret_Call{Call: _e.mock.On("WebhookSecret")}
|
||||
}
|
||||
|
||||
func (_c *PoolManager_WebhookSecret_Call) Run(run func()) *PoolManager_WebhookSecret_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run()
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *PoolManager_WebhookSecret_Call) Return(_a0 string) *PoolManager_WebhookSecret_Call {
|
||||
_c.Call.Return(_a0)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *PoolManager_WebhookSecret_Call) RunAndReturn(run func() string) *PoolManager_WebhookSecret_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// NewPoolManager creates a new instance of PoolManager. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
|
||||
// The first argument is typically a *testing.T value.
|
||||
func NewPoolManager(t interface {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// Code generated by mockery v2.53.3. DO NOT EDIT.
|
||||
// Code generated by mockery. DO NOT EDIT.
|
||||
|
||||
package mocks
|
||||
|
||||
|
|
@ -19,6 +19,14 @@ type Provider struct {
|
|||
mock.Mock
|
||||
}
|
||||
|
||||
type Provider_Expecter struct {
|
||||
mock *mock.Mock
|
||||
}
|
||||
|
||||
func (_m *Provider) EXPECT() *Provider_Expecter {
|
||||
return &Provider_Expecter{mock: &_m.Mock}
|
||||
}
|
||||
|
||||
// AsParams provides a mock function with no fields
|
||||
func (_m *Provider) AsParams() params.Provider {
|
||||
ret := _m.Called()
|
||||
|
|
@ -37,6 +45,33 @@ func (_m *Provider) AsParams() params.Provider {
|
|||
return r0
|
||||
}
|
||||
|
||||
// Provider_AsParams_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'AsParams'
|
||||
type Provider_AsParams_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// AsParams is a helper method to define mock.On call
|
||||
func (_e *Provider_Expecter) AsParams() *Provider_AsParams_Call {
|
||||
return &Provider_AsParams_Call{Call: _e.mock.On("AsParams")}
|
||||
}
|
||||
|
||||
func (_c *Provider_AsParams_Call) Run(run func()) *Provider_AsParams_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run()
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *Provider_AsParams_Call) Return(_a0 params.Provider) *Provider_AsParams_Call {
|
||||
_c.Call.Return(_a0)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *Provider_AsParams_Call) RunAndReturn(run func() params.Provider) *Provider_AsParams_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// CreateInstance provides a mock function with given fields: ctx, bootstrapParams, createInstanceParams
|
||||
func (_m *Provider) CreateInstance(ctx context.Context, bootstrapParams garm_provider_commonparams.BootstrapInstance, createInstanceParams common.CreateInstanceParams) (garm_provider_commonparams.ProviderInstance, error) {
|
||||
ret := _m.Called(ctx, bootstrapParams, createInstanceParams)
|
||||
|
|
@ -65,6 +100,36 @@ func (_m *Provider) CreateInstance(ctx context.Context, bootstrapParams garm_pro
|
|||
return r0, r1
|
||||
}
|
||||
|
||||
// Provider_CreateInstance_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CreateInstance'
|
||||
type Provider_CreateInstance_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// CreateInstance is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
// - bootstrapParams garm_provider_commonparams.BootstrapInstance
|
||||
// - createInstanceParams common.CreateInstanceParams
|
||||
func (_e *Provider_Expecter) CreateInstance(ctx interface{}, bootstrapParams interface{}, createInstanceParams interface{}) *Provider_CreateInstance_Call {
|
||||
return &Provider_CreateInstance_Call{Call: _e.mock.On("CreateInstance", ctx, bootstrapParams, createInstanceParams)}
|
||||
}
|
||||
|
||||
func (_c *Provider_CreateInstance_Call) Run(run func(ctx context.Context, bootstrapParams garm_provider_commonparams.BootstrapInstance, createInstanceParams common.CreateInstanceParams)) *Provider_CreateInstance_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(context.Context), args[1].(garm_provider_commonparams.BootstrapInstance), args[2].(common.CreateInstanceParams))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *Provider_CreateInstance_Call) Return(_a0 garm_provider_commonparams.ProviderInstance, _a1 error) *Provider_CreateInstance_Call {
|
||||
_c.Call.Return(_a0, _a1)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *Provider_CreateInstance_Call) RunAndReturn(run func(context.Context, garm_provider_commonparams.BootstrapInstance, common.CreateInstanceParams) (garm_provider_commonparams.ProviderInstance, error)) *Provider_CreateInstance_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// DeleteInstance provides a mock function with given fields: ctx, instance, deleteInstanceParams
|
||||
func (_m *Provider) DeleteInstance(ctx context.Context, instance string, deleteInstanceParams common.DeleteInstanceParams) error {
|
||||
ret := _m.Called(ctx, instance, deleteInstanceParams)
|
||||
|
|
@ -83,6 +148,36 @@ func (_m *Provider) DeleteInstance(ctx context.Context, instance string, deleteI
|
|||
return r0
|
||||
}
|
||||
|
||||
// Provider_DeleteInstance_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'DeleteInstance'
|
||||
type Provider_DeleteInstance_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// DeleteInstance is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
// - instance string
|
||||
// - deleteInstanceParams common.DeleteInstanceParams
|
||||
func (_e *Provider_Expecter) DeleteInstance(ctx interface{}, instance interface{}, deleteInstanceParams interface{}) *Provider_DeleteInstance_Call {
|
||||
return &Provider_DeleteInstance_Call{Call: _e.mock.On("DeleteInstance", ctx, instance, deleteInstanceParams)}
|
||||
}
|
||||
|
||||
func (_c *Provider_DeleteInstance_Call) Run(run func(ctx context.Context, instance string, deleteInstanceParams common.DeleteInstanceParams)) *Provider_DeleteInstance_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(context.Context), args[1].(string), args[2].(common.DeleteInstanceParams))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *Provider_DeleteInstance_Call) Return(_a0 error) *Provider_DeleteInstance_Call {
|
||||
_c.Call.Return(_a0)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *Provider_DeleteInstance_Call) RunAndReturn(run func(context.Context, string, common.DeleteInstanceParams) error) *Provider_DeleteInstance_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// DisableJITConfig provides a mock function with no fields
|
||||
func (_m *Provider) DisableJITConfig() bool {
|
||||
ret := _m.Called()
|
||||
|
|
@ -101,6 +196,33 @@ func (_m *Provider) DisableJITConfig() bool {
|
|||
return r0
|
||||
}
|
||||
|
||||
// Provider_DisableJITConfig_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'DisableJITConfig'
|
||||
type Provider_DisableJITConfig_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// DisableJITConfig is a helper method to define mock.On call
|
||||
func (_e *Provider_Expecter) DisableJITConfig() *Provider_DisableJITConfig_Call {
|
||||
return &Provider_DisableJITConfig_Call{Call: _e.mock.On("DisableJITConfig")}
|
||||
}
|
||||
|
||||
func (_c *Provider_DisableJITConfig_Call) Run(run func()) *Provider_DisableJITConfig_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run()
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *Provider_DisableJITConfig_Call) Return(_a0 bool) *Provider_DisableJITConfig_Call {
|
||||
_c.Call.Return(_a0)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *Provider_DisableJITConfig_Call) RunAndReturn(run func() bool) *Provider_DisableJITConfig_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// GetInstance provides a mock function with given fields: ctx, instance, getInstanceParams
|
||||
func (_m *Provider) GetInstance(ctx context.Context, instance string, getInstanceParams common.GetInstanceParams) (garm_provider_commonparams.ProviderInstance, error) {
|
||||
ret := _m.Called(ctx, instance, getInstanceParams)
|
||||
|
|
@ -129,6 +251,36 @@ func (_m *Provider) GetInstance(ctx context.Context, instance string, getInstanc
|
|||
return r0, r1
|
||||
}
|
||||
|
||||
// Provider_GetInstance_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetInstance'
|
||||
type Provider_GetInstance_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// GetInstance is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
// - instance string
|
||||
// - getInstanceParams common.GetInstanceParams
|
||||
func (_e *Provider_Expecter) GetInstance(ctx interface{}, instance interface{}, getInstanceParams interface{}) *Provider_GetInstance_Call {
|
||||
return &Provider_GetInstance_Call{Call: _e.mock.On("GetInstance", ctx, instance, getInstanceParams)}
|
||||
}
|
||||
|
||||
func (_c *Provider_GetInstance_Call) Run(run func(ctx context.Context, instance string, getInstanceParams common.GetInstanceParams)) *Provider_GetInstance_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(context.Context), args[1].(string), args[2].(common.GetInstanceParams))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *Provider_GetInstance_Call) Return(_a0 garm_provider_commonparams.ProviderInstance, _a1 error) *Provider_GetInstance_Call {
|
||||
_c.Call.Return(_a0, _a1)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *Provider_GetInstance_Call) RunAndReturn(run func(context.Context, string, common.GetInstanceParams) (garm_provider_commonparams.ProviderInstance, error)) *Provider_GetInstance_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// ListInstances provides a mock function with given fields: ctx, poolID, listInstancesParams
|
||||
func (_m *Provider) ListInstances(ctx context.Context, poolID string, listInstancesParams common.ListInstancesParams) ([]garm_provider_commonparams.ProviderInstance, error) {
|
||||
ret := _m.Called(ctx, poolID, listInstancesParams)
|
||||
|
|
@ -159,6 +311,36 @@ func (_m *Provider) ListInstances(ctx context.Context, poolID string, listInstan
|
|||
return r0, r1
|
||||
}
|
||||
|
||||
// Provider_ListInstances_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ListInstances'
|
||||
type Provider_ListInstances_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// ListInstances is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
// - poolID string
|
||||
// - listInstancesParams common.ListInstancesParams
|
||||
func (_e *Provider_Expecter) ListInstances(ctx interface{}, poolID interface{}, listInstancesParams interface{}) *Provider_ListInstances_Call {
|
||||
return &Provider_ListInstances_Call{Call: _e.mock.On("ListInstances", ctx, poolID, listInstancesParams)}
|
||||
}
|
||||
|
||||
func (_c *Provider_ListInstances_Call) Run(run func(ctx context.Context, poolID string, listInstancesParams common.ListInstancesParams)) *Provider_ListInstances_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(context.Context), args[1].(string), args[2].(common.ListInstancesParams))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *Provider_ListInstances_Call) Return(_a0 []garm_provider_commonparams.ProviderInstance, _a1 error) *Provider_ListInstances_Call {
|
||||
_c.Call.Return(_a0, _a1)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *Provider_ListInstances_Call) RunAndReturn(run func(context.Context, string, common.ListInstancesParams) ([]garm_provider_commonparams.ProviderInstance, error)) *Provider_ListInstances_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// RemoveAllInstances provides a mock function with given fields: ctx, removeAllInstancesParams
|
||||
func (_m *Provider) RemoveAllInstances(ctx context.Context, removeAllInstancesParams common.RemoveAllInstancesParams) error {
|
||||
ret := _m.Called(ctx, removeAllInstancesParams)
|
||||
|
|
@ -177,6 +359,35 @@ func (_m *Provider) RemoveAllInstances(ctx context.Context, removeAllInstancesPa
|
|||
return r0
|
||||
}
|
||||
|
||||
// Provider_RemoveAllInstances_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'RemoveAllInstances'
|
||||
type Provider_RemoveAllInstances_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// RemoveAllInstances is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
// - removeAllInstancesParams common.RemoveAllInstancesParams
|
||||
func (_e *Provider_Expecter) RemoveAllInstances(ctx interface{}, removeAllInstancesParams interface{}) *Provider_RemoveAllInstances_Call {
|
||||
return &Provider_RemoveAllInstances_Call{Call: _e.mock.On("RemoveAllInstances", ctx, removeAllInstancesParams)}
|
||||
}
|
||||
|
||||
func (_c *Provider_RemoveAllInstances_Call) Run(run func(ctx context.Context, removeAllInstancesParams common.RemoveAllInstancesParams)) *Provider_RemoveAllInstances_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(context.Context), args[1].(common.RemoveAllInstancesParams))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *Provider_RemoveAllInstances_Call) Return(_a0 error) *Provider_RemoveAllInstances_Call {
|
||||
_c.Call.Return(_a0)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *Provider_RemoveAllInstances_Call) RunAndReturn(run func(context.Context, common.RemoveAllInstancesParams) error) *Provider_RemoveAllInstances_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// Start provides a mock function with given fields: ctx, instance, startParams
|
||||
func (_m *Provider) Start(ctx context.Context, instance string, startParams common.StartParams) error {
|
||||
ret := _m.Called(ctx, instance, startParams)
|
||||
|
|
@ -195,6 +406,36 @@ func (_m *Provider) Start(ctx context.Context, instance string, startParams comm
|
|||
return r0
|
||||
}
|
||||
|
||||
// Provider_Start_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Start'
|
||||
type Provider_Start_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// Start is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
// - instance string
|
||||
// - startParams common.StartParams
|
||||
func (_e *Provider_Expecter) Start(ctx interface{}, instance interface{}, startParams interface{}) *Provider_Start_Call {
|
||||
return &Provider_Start_Call{Call: _e.mock.On("Start", ctx, instance, startParams)}
|
||||
}
|
||||
|
||||
func (_c *Provider_Start_Call) Run(run func(ctx context.Context, instance string, startParams common.StartParams)) *Provider_Start_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(context.Context), args[1].(string), args[2].(common.StartParams))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *Provider_Start_Call) Return(_a0 error) *Provider_Start_Call {
|
||||
_c.Call.Return(_a0)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *Provider_Start_Call) RunAndReturn(run func(context.Context, string, common.StartParams) error) *Provider_Start_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// Stop provides a mock function with given fields: ctx, instance, stopParams
|
||||
func (_m *Provider) Stop(ctx context.Context, instance string, stopParams common.StopParams) error {
|
||||
ret := _m.Called(ctx, instance, stopParams)
|
||||
|
|
@ -213,6 +454,36 @@ func (_m *Provider) Stop(ctx context.Context, instance string, stopParams common
|
|||
return r0
|
||||
}
|
||||
|
||||
// Provider_Stop_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Stop'
|
||||
type Provider_Stop_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// Stop is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
// - instance string
|
||||
// - stopParams common.StopParams
|
||||
func (_e *Provider_Expecter) Stop(ctx interface{}, instance interface{}, stopParams interface{}) *Provider_Stop_Call {
|
||||
return &Provider_Stop_Call{Call: _e.mock.On("Stop", ctx, instance, stopParams)}
|
||||
}
|
||||
|
||||
func (_c *Provider_Stop_Call) Run(run func(ctx context.Context, instance string, stopParams common.StopParams)) *Provider_Stop_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(context.Context), args[1].(string), args[2].(common.StopParams))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *Provider_Stop_Call) Return(_a0 error) *Provider_Stop_Call {
|
||||
_c.Call.Return(_a0)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *Provider_Stop_Call) RunAndReturn(run func(context.Context, string, common.StopParams) error) *Provider_Stop_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// NewProvider creates a new instance of Provider. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
|
||||
// The first argument is typically a *testing.T value.
|
||||
func NewProvider(t interface {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// Code generated by mockery v2.53.3. DO NOT EDIT.
|
||||
// Code generated by mockery. DO NOT EDIT.
|
||||
|
||||
package mocks
|
||||
|
||||
|
|
@ -14,6 +14,14 @@ type RateLimitClient struct {
|
|||
mock.Mock
|
||||
}
|
||||
|
||||
type RateLimitClient_Expecter struct {
|
||||
mock *mock.Mock
|
||||
}
|
||||
|
||||
func (_m *RateLimitClient) EXPECT() *RateLimitClient_Expecter {
|
||||
return &RateLimitClient_Expecter{mock: &_m.Mock}
|
||||
}
|
||||
|
||||
// RateLimit provides a mock function with given fields: ctx
|
||||
func (_m *RateLimitClient) RateLimit(ctx context.Context) (*github.RateLimits, error) {
|
||||
ret := _m.Called(ctx)
|
||||
|
|
@ -44,6 +52,34 @@ func (_m *RateLimitClient) RateLimit(ctx context.Context) (*github.RateLimits, e
|
|||
return r0, r1
|
||||
}
|
||||
|
||||
// RateLimitClient_RateLimit_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'RateLimit'
|
||||
type RateLimitClient_RateLimit_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// RateLimit is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
func (_e *RateLimitClient_Expecter) RateLimit(ctx interface{}) *RateLimitClient_RateLimit_Call {
|
||||
return &RateLimitClient_RateLimit_Call{Call: _e.mock.On("RateLimit", ctx)}
|
||||
}
|
||||
|
||||
func (_c *RateLimitClient_RateLimit_Call) Run(run func(ctx context.Context)) *RateLimitClient_RateLimit_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(context.Context))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *RateLimitClient_RateLimit_Call) Return(_a0 *github.RateLimits, _a1 error) *RateLimitClient_RateLimit_Call {
|
||||
_c.Call.Return(_a0, _a1)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *RateLimitClient_RateLimit_Call) RunAndReturn(run func(context.Context) (*github.RateLimits, error)) *RateLimitClient_RateLimit_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// NewRateLimitClient creates a new instance of RateLimitClient. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
|
||||
// The first argument is typically a *testing.T value.
|
||||
func NewRateLimitClient(t interface {
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ const (
|
|||
BackoffTimer = 1 * time.Minute
|
||||
)
|
||||
|
||||
//go:generate mockery --all
|
||||
//go:generate go run github.com/vektra/mockery/v2@latest
|
||||
type PoolManager interface {
|
||||
// ID returns the ID of the entity (repo, org, enterprise)
|
||||
ID() string
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ import (
|
|||
"github.com/cloudbase/garm/params"
|
||||
)
|
||||
|
||||
//go:generate mockery --all
|
||||
//go:generate go run github.com/vektra/mockery/v2@latest
|
||||
type Provider interface {
|
||||
// CreateInstance creates a new compute instance in the provider.
|
||||
CreateInstance(ctx context.Context, bootstrapParams commonParams.BootstrapInstance, createInstanceParams CreateInstanceParams) (commonParams.ProviderInstance, error)
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ type GithubEntityOperations interface {
|
|||
RateLimit(ctx context.Context) (*github.RateLimits, error)
|
||||
CreateEntityRegistrationToken(ctx context.Context) (*github.RegistrationToken, *github.Response, error)
|
||||
GetEntityJITConfig(ctx context.Context, instance string, pool params.Pool, labels []string) (jitConfigMap map[string]string, runner *github.Runner, err error)
|
||||
GetEntityRunnerGroupIDByName(ctx context.Context, runnerGroupName string) (int64, error)
|
||||
|
||||
// GetEntity returns the GitHub entity for which the github client was instanciated.
|
||||
GetEntity() params.ForgeEntity
|
||||
|
|
@ -49,7 +50,7 @@ type RateLimitClient interface {
|
|||
// GithubClient that describes the minimum list of functions we need to interact with github.
|
||||
// Allows for easier testing.
|
||||
//
|
||||
//go:generate mockery --all
|
||||
//go:generate go run github.com/vektra/mockery/v2@latest
|
||||
type GithubClient interface {
|
||||
GithubEntityOperations
|
||||
|
||||
|
|
|
|||
|
|
@ -16,12 +16,11 @@ package runner
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"strings"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
runnerErrors "github.com/cloudbase/garm-provider-common/errors"
|
||||
"github.com/cloudbase/garm/auth"
|
||||
"github.com/cloudbase/garm/params"
|
||||
|
|
@ -36,7 +35,7 @@ func (r *Runner) CreateEnterprise(ctx context.Context, param params.CreateEnterp
|
|||
|
||||
err = param.Validate()
|
||||
if err != nil {
|
||||
return params.Enterprise{}, errors.Wrap(err, "validating params")
|
||||
return params.Enterprise{}, fmt.Errorf("error validating params: %w", err)
|
||||
}
|
||||
|
||||
creds, err := r.store.GetGithubCredentialsByName(ctx, param.CredentialsName, true)
|
||||
|
|
@ -47,7 +46,7 @@ func (r *Runner) CreateEnterprise(ctx context.Context, param params.CreateEnterp
|
|||
_, err = r.store.GetEnterprise(ctx, param.Name, creds.Endpoint.Name)
|
||||
if err != nil {
|
||||
if !errors.Is(err, runnerErrors.ErrNotFound) {
|
||||
return params.Enterprise{}, errors.Wrap(err, "fetching enterprise")
|
||||
return params.Enterprise{}, fmt.Errorf("error fetching enterprise: %w", err)
|
||||
}
|
||||
} else {
|
||||
return params.Enterprise{}, runnerErrors.NewConflictError("enterprise %s already exists", param.Name)
|
||||
|
|
@ -55,7 +54,7 @@ func (r *Runner) CreateEnterprise(ctx context.Context, param params.CreateEnterp
|
|||
|
||||
enterprise, err = r.store.CreateEnterprise(ctx, param.Name, creds, param.WebhookSecret, param.PoolBalancerType)
|
||||
if err != nil {
|
||||
return params.Enterprise{}, errors.Wrap(err, "creating enterprise")
|
||||
return params.Enterprise{}, fmt.Errorf("error creating enterprise: %w", err)
|
||||
}
|
||||
|
||||
defer func() {
|
||||
|
|
@ -73,7 +72,7 @@ func (r *Runner) CreateEnterprise(ctx context.Context, param params.CreateEnterp
|
|||
var poolMgr common.PoolManager
|
||||
poolMgr, err = r.poolManagerCtrl.CreateEnterprisePoolManager(r.ctx, enterprise, r.providers, r.store)
|
||||
if err != nil {
|
||||
return params.Enterprise{}, errors.Wrap(err, "creating enterprise pool manager")
|
||||
return params.Enterprise{}, fmt.Errorf("error creating enterprise pool manager: %w", err)
|
||||
}
|
||||
if err := poolMgr.Start(); err != nil {
|
||||
if deleteErr := r.poolManagerCtrl.DeleteEnterprisePoolManager(enterprise); deleteErr != nil {
|
||||
|
|
@ -81,7 +80,7 @@ func (r *Runner) CreateEnterprise(ctx context.Context, param params.CreateEnterp
|
|||
ctx, "failed to cleanup pool manager for enterprise",
|
||||
"enterprise_id", enterprise.ID)
|
||||
}
|
||||
return params.Enterprise{}, errors.Wrap(err, "starting enterprise pool manager")
|
||||
return params.Enterprise{}, fmt.Errorf("error starting enterprise pool manager: %w", err)
|
||||
}
|
||||
return enterprise, nil
|
||||
}
|
||||
|
|
@ -93,7 +92,7 @@ func (r *Runner) ListEnterprises(ctx context.Context, filter params.EnterpriseFi
|
|||
|
||||
enterprises, err := r.store.ListEnterprises(ctx, filter)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "listing enterprises")
|
||||
return nil, fmt.Errorf("error listing enterprises: %w", err)
|
||||
}
|
||||
|
||||
var allEnterprises []params.Enterprise
|
||||
|
|
@ -119,7 +118,7 @@ func (r *Runner) GetEnterpriseByID(ctx context.Context, enterpriseID string) (pa
|
|||
|
||||
enterprise, err := r.store.GetEnterpriseByID(ctx, enterpriseID)
|
||||
if err != nil {
|
||||
return params.Enterprise{}, errors.Wrap(err, "fetching enterprise")
|
||||
return params.Enterprise{}, fmt.Errorf("error fetching enterprise: %w", err)
|
||||
}
|
||||
poolMgr, err := r.poolManagerCtrl.GetEnterprisePoolManager(enterprise)
|
||||
if err != nil {
|
||||
|
|
@ -137,17 +136,17 @@ func (r *Runner) DeleteEnterprise(ctx context.Context, enterpriseID string) erro
|
|||
|
||||
enterprise, err := r.store.GetEnterpriseByID(ctx, enterpriseID)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "fetching enterprise")
|
||||
return fmt.Errorf("error fetching enterprise: %w", err)
|
||||
}
|
||||
|
||||
entity, err := enterprise.GetEntity()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "getting entity")
|
||||
return fmt.Errorf("error getting entity: %w", err)
|
||||
}
|
||||
|
||||
pools, err := r.store.ListEntityPools(ctx, entity)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "fetching enterprise pools")
|
||||
return fmt.Errorf("error fetching enterprise pools: %w", err)
|
||||
}
|
||||
|
||||
if len(pools) > 0 {
|
||||
|
|
@ -161,7 +160,7 @@ func (r *Runner) DeleteEnterprise(ctx context.Context, enterpriseID string) erro
|
|||
|
||||
scaleSets, err := r.store.ListEntityScaleSets(ctx, entity)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "fetching enterprise scale sets")
|
||||
return fmt.Errorf("error fetching enterprise scale sets: %w", err)
|
||||
}
|
||||
|
||||
if len(scaleSets) > 0 {
|
||||
|
|
@ -169,11 +168,11 @@ func (r *Runner) DeleteEnterprise(ctx context.Context, enterpriseID string) erro
|
|||
}
|
||||
|
||||
if err := r.poolManagerCtrl.DeleteEnterprisePoolManager(enterprise); err != nil {
|
||||
return errors.Wrap(err, "deleting enterprise pool manager")
|
||||
return fmt.Errorf("error deleting enterprise pool manager: %w", err)
|
||||
}
|
||||
|
||||
if err := r.store.DeleteEnterprise(ctx, enterpriseID); err != nil {
|
||||
return errors.Wrapf(err, "removing enterprise %s", enterpriseID)
|
||||
return fmt.Errorf("error removing enterprise %s: %w", enterpriseID, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
@ -194,7 +193,7 @@ func (r *Runner) UpdateEnterprise(ctx context.Context, enterpriseID string, para
|
|||
|
||||
enterprise, err := r.store.UpdateEnterprise(ctx, enterpriseID, param)
|
||||
if err != nil {
|
||||
return params.Enterprise{}, errors.Wrap(err, "updating enterprise")
|
||||
return params.Enterprise{}, fmt.Errorf("error updating enterprise: %w", err)
|
||||
}
|
||||
|
||||
poolMgr, err := r.poolManagerCtrl.GetEnterprisePoolManager(enterprise)
|
||||
|
|
@ -243,7 +242,7 @@ func (r *Runner) GetEnterprisePoolByID(ctx context.Context, enterpriseID, poolID
|
|||
}
|
||||
pool, err := r.store.GetEntityPool(ctx, entity, poolID)
|
||||
if err != nil {
|
||||
return params.Pool{}, errors.Wrap(err, "fetching pool")
|
||||
return params.Pool{}, fmt.Errorf("error fetching pool: %w", err)
|
||||
}
|
||||
return pool, nil
|
||||
}
|
||||
|
|
@ -260,7 +259,7 @@ func (r *Runner) DeleteEnterprisePool(ctx context.Context, enterpriseID, poolID
|
|||
|
||||
pool, err := r.store.GetEntityPool(ctx, entity, poolID)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "fetching pool")
|
||||
return fmt.Errorf("error fetching pool: %w", err)
|
||||
}
|
||||
|
||||
// nolint:golangci-lint,godox
|
||||
|
|
@ -274,7 +273,7 @@ func (r *Runner) DeleteEnterprisePool(ctx context.Context, enterpriseID, poolID
|
|||
}
|
||||
|
||||
if err := r.store.DeleteEntityPool(ctx, entity, poolID); err != nil {
|
||||
return errors.Wrap(err, "deleting pool")
|
||||
return fmt.Errorf("error deleting pool: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
@ -290,7 +289,7 @@ func (r *Runner) ListEnterprisePools(ctx context.Context, enterpriseID string) (
|
|||
}
|
||||
pools, err := r.store.ListEntityPools(ctx, entity)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "fetching pools")
|
||||
return nil, fmt.Errorf("error fetching pools: %w", err)
|
||||
}
|
||||
return pools, nil
|
||||
}
|
||||
|
|
@ -306,7 +305,7 @@ func (r *Runner) UpdateEnterprisePool(ctx context.Context, enterpriseID, poolID
|
|||
}
|
||||
pool, err := r.store.GetEntityPool(ctx, entity, poolID)
|
||||
if err != nil {
|
||||
return params.Pool{}, errors.Wrap(err, "fetching pool")
|
||||
return params.Pool{}, fmt.Errorf("error fetching pool: %w", err)
|
||||
}
|
||||
|
||||
maxRunners := pool.MaxRunners
|
||||
|
|
@ -325,7 +324,7 @@ func (r *Runner) UpdateEnterprisePool(ctx context.Context, enterpriseID, poolID
|
|||
|
||||
newPool, err := r.store.UpdateEntityPool(ctx, entity, poolID, param)
|
||||
if err != nil {
|
||||
return params.Pool{}, errors.Wrap(err, "updating pool")
|
||||
return params.Pool{}, fmt.Errorf("error updating pool: %w", err)
|
||||
}
|
||||
return newPool, nil
|
||||
}
|
||||
|
|
@ -340,7 +339,7 @@ func (r *Runner) ListEnterpriseInstances(ctx context.Context, enterpriseID strin
|
|||
}
|
||||
instances, err := r.store.ListEntityInstances(ctx, entity)
|
||||
if err != nil {
|
||||
return []params.Instance{}, errors.Wrap(err, "fetching instances")
|
||||
return []params.Instance{}, fmt.Errorf("error fetching instances: %w", err)
|
||||
}
|
||||
return instances, nil
|
||||
}
|
||||
|
|
@ -351,12 +350,12 @@ func (r *Runner) findEnterprisePoolManager(name, endpointName string) (common.Po
|
|||
|
||||
enterprise, err := r.store.GetEnterprise(r.ctx, name, endpointName)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "fetching enterprise")
|
||||
return nil, fmt.Errorf("error fetching enterprise: %w", err)
|
||||
}
|
||||
|
||||
poolManager, err := r.poolManagerCtrl.GetEnterprisePoolManager(enterprise)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "fetching pool manager for enterprise")
|
||||
return nil, fmt.Errorf("error fetching pool manager for enterprise: %w", err)
|
||||
}
|
||||
return poolManager, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,10 +16,10 @@ package runner
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/stretchr/testify/mock"
|
||||
"github.com/stretchr/testify/suite"
|
||||
|
||||
|
|
@ -210,7 +210,7 @@ func (s *EnterpriseTestSuite) TestCreateEnterprisePoolMgrFailed() {
|
|||
|
||||
s.Fixtures.PoolMgrMock.AssertExpectations(s.T())
|
||||
s.Fixtures.PoolMgrCtrlMock.AssertExpectations(s.T())
|
||||
s.Require().Equal(fmt.Sprintf("creating enterprise pool manager: %s", s.Fixtures.ErrMock.Error()), err.Error())
|
||||
s.Require().Equal(fmt.Sprintf("error creating enterprise pool manager: %s", s.Fixtures.ErrMock.Error()), err.Error())
|
||||
}
|
||||
|
||||
func (s *EnterpriseTestSuite) TestCreateEnterpriseStartPoolMgrFailed() {
|
||||
|
|
@ -222,7 +222,7 @@ func (s *EnterpriseTestSuite) TestCreateEnterpriseStartPoolMgrFailed() {
|
|||
|
||||
s.Fixtures.PoolMgrMock.AssertExpectations(s.T())
|
||||
s.Fixtures.PoolMgrCtrlMock.AssertExpectations(s.T())
|
||||
s.Require().Equal(fmt.Sprintf("starting enterprise pool manager: %s", s.Fixtures.ErrMock.Error()), err.Error())
|
||||
s.Require().Equal(fmt.Sprintf("error starting enterprise pool manager: %s", s.Fixtures.ErrMock.Error()), err.Error())
|
||||
}
|
||||
|
||||
func (s *EnterpriseTestSuite) TestListEnterprises() {
|
||||
|
|
@ -324,7 +324,7 @@ func (s *EnterpriseTestSuite) TestDeleteEnterprise() {
|
|||
s.Require().Nil(err)
|
||||
|
||||
_, err = s.Fixtures.Store.GetEnterpriseByID(s.Fixtures.AdminContext, s.Fixtures.StoreEnterprises["test-enterprise-3"].ID)
|
||||
s.Require().Equal("fetching enterprise: not found", err.Error())
|
||||
s.Require().Equal("error fetching enterprise: not found", err.Error())
|
||||
}
|
||||
|
||||
func (s *EnterpriseTestSuite) TestDeleteEnterpriseErrUnauthorized() {
|
||||
|
|
@ -354,7 +354,7 @@ func (s *EnterpriseTestSuite) TestDeleteEnterprisePoolMgrFailed() {
|
|||
err := s.Runner.DeleteEnterprise(s.Fixtures.AdminContext, s.Fixtures.StoreEnterprises["test-enterprise-1"].ID)
|
||||
|
||||
s.Fixtures.PoolMgrCtrlMock.AssertExpectations(s.T())
|
||||
s.Require().Equal(fmt.Sprintf("deleting enterprise pool manager: %s", s.Fixtures.ErrMock.Error()), err.Error())
|
||||
s.Require().Equal(fmt.Sprintf("error deleting enterprise pool manager: %s", s.Fixtures.ErrMock.Error()), err.Error())
|
||||
}
|
||||
|
||||
func (s *EnterpriseTestSuite) TestUpdateEnterprise() {
|
||||
|
|
@ -477,7 +477,7 @@ func (s *EnterpriseTestSuite) TestDeleteEnterprisePool() {
|
|||
s.Require().Nil(err)
|
||||
|
||||
_, err = s.Fixtures.Store.GetEntityPool(s.Fixtures.AdminContext, entity, pool.ID)
|
||||
s.Require().Equal("fetching pool: finding pool: not found", err.Error())
|
||||
s.Require().Equal("fetching pool: error finding pool: not found", err.Error())
|
||||
}
|
||||
|
||||
func (s *EnterpriseTestSuite) TestDeleteEnterprisePoolErrUnauthorized() {
|
||||
|
|
|
|||
|
|
@ -16,8 +16,7 @@ package runner
|
|||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"fmt"
|
||||
|
||||
runnerErrors "github.com/cloudbase/garm-provider-common/errors"
|
||||
"github.com/cloudbase/garm/auth"
|
||||
|
|
@ -35,7 +34,7 @@ func (r *Runner) ListGiteaCredentials(ctx context.Context) ([]params.ForgeCreden
|
|||
// there is a posibillity that not all creds will be in the cache.
|
||||
creds, err := r.store.ListGiteaCredentials(ctx)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "fetching gitea credentials")
|
||||
return nil, fmt.Errorf("error fetching gitea credentials: %w", err)
|
||||
}
|
||||
return creds, nil
|
||||
}
|
||||
|
|
@ -46,12 +45,12 @@ func (r *Runner) CreateGiteaCredentials(ctx context.Context, param params.Create
|
|||
}
|
||||
|
||||
if err := param.Validate(); err != nil {
|
||||
return params.ForgeCredentials{}, errors.Wrap(err, "failed to validate gitea credentials params")
|
||||
return params.ForgeCredentials{}, fmt.Errorf("error failed to validate gitea credentials params: %w", err)
|
||||
}
|
||||
|
||||
creds, err := r.store.CreateGiteaCredentials(ctx, param)
|
||||
if err != nil {
|
||||
return params.ForgeCredentials{}, errors.Wrap(err, "failed to create gitea credentials")
|
||||
return params.ForgeCredentials{}, fmt.Errorf("error failed to create gitea credentials: %w", err)
|
||||
}
|
||||
|
||||
return creds, nil
|
||||
|
|
@ -64,7 +63,7 @@ func (r *Runner) GetGiteaCredentials(ctx context.Context, id uint) (params.Forge
|
|||
|
||||
creds, err := r.store.GetGiteaCredentials(ctx, id, true)
|
||||
if err != nil {
|
||||
return params.ForgeCredentials{}, errors.Wrap(err, "failed to get gitea credentials")
|
||||
return params.ForgeCredentials{}, fmt.Errorf("error failed to get gitea credentials: %w", err)
|
||||
}
|
||||
|
||||
return creds, nil
|
||||
|
|
@ -76,7 +75,7 @@ func (r *Runner) DeleteGiteaCredentials(ctx context.Context, id uint) error {
|
|||
}
|
||||
|
||||
if err := r.store.DeleteGiteaCredentials(ctx, id); err != nil {
|
||||
return errors.Wrap(err, "failed to delete gitea credentials")
|
||||
return fmt.Errorf("error failed to delete gitea credentials: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
|
@ -88,12 +87,12 @@ func (r *Runner) UpdateGiteaCredentials(ctx context.Context, id uint, param para
|
|||
}
|
||||
|
||||
if err := param.Validate(); err != nil {
|
||||
return params.ForgeCredentials{}, errors.Wrap(err, "failed to validate gitea credentials params")
|
||||
return params.ForgeCredentials{}, fmt.Errorf("error failed to validate gitea credentials params: %w", err)
|
||||
}
|
||||
|
||||
newCreds, err := r.store.UpdateGiteaCredentials(ctx, id, param)
|
||||
if err != nil {
|
||||
return params.ForgeCredentials{}, errors.Wrap(err, "failed to update gitea credentials")
|
||||
return params.ForgeCredentials{}, fmt.Errorf("error failed to update gitea credentials: %w", err)
|
||||
}
|
||||
|
||||
return newCreds, nil
|
||||
|
|
|
|||
|
|
@ -16,8 +16,7 @@ package runner
|
|||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"fmt"
|
||||
|
||||
runnerErrors "github.com/cloudbase/garm-provider-common/errors"
|
||||
"github.com/cloudbase/garm/auth"
|
||||
|
|
@ -30,12 +29,12 @@ func (r *Runner) CreateGiteaEndpoint(ctx context.Context, param params.CreateGit
|
|||
}
|
||||
|
||||
if err := param.Validate(); err != nil {
|
||||
return params.ForgeEndpoint{}, errors.Wrap(err, "failed to validate gitea endpoint params")
|
||||
return params.ForgeEndpoint{}, fmt.Errorf("failed to validate gitea endpoint params: %w", err)
|
||||
}
|
||||
|
||||
ep, err := r.store.CreateGiteaEndpoint(ctx, param)
|
||||
if err != nil {
|
||||
return params.ForgeEndpoint{}, errors.Wrap(err, "failed to create gitea endpoint")
|
||||
return params.ForgeEndpoint{}, fmt.Errorf("failed to create gitea endpoint: %w", err)
|
||||
}
|
||||
|
||||
return ep, nil
|
||||
|
|
@ -47,7 +46,7 @@ func (r *Runner) GetGiteaEndpoint(ctx context.Context, name string) (params.Forg
|
|||
}
|
||||
endpoint, err := r.store.GetGiteaEndpoint(ctx, name)
|
||||
if err != nil {
|
||||
return params.ForgeEndpoint{}, errors.Wrap(err, "failed to get gitea endpoint")
|
||||
return params.ForgeEndpoint{}, fmt.Errorf("failed to get gitea endpoint: %w", err)
|
||||
}
|
||||
|
||||
return endpoint, nil
|
||||
|
|
@ -60,7 +59,7 @@ func (r *Runner) DeleteGiteaEndpoint(ctx context.Context, name string) error {
|
|||
|
||||
err := r.store.DeleteGiteaEndpoint(ctx, name)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to delete gitea endpoint")
|
||||
return fmt.Errorf("failed to delete gitea endpoint: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
|
@ -72,12 +71,12 @@ func (r *Runner) UpdateGiteaEndpoint(ctx context.Context, name string, param par
|
|||
}
|
||||
|
||||
if err := param.Validate(); err != nil {
|
||||
return params.ForgeEndpoint{}, errors.Wrap(err, "failed to validate gitea endpoint params")
|
||||
return params.ForgeEndpoint{}, fmt.Errorf("failed to validate gitea endpoint params: %w", err)
|
||||
}
|
||||
|
||||
newEp, err := r.store.UpdateGiteaEndpoint(ctx, name, param)
|
||||
if err != nil {
|
||||
return params.ForgeEndpoint{}, errors.Wrap(err, "failed to update gitea endpoint")
|
||||
return params.ForgeEndpoint{}, fmt.Errorf("failed to update gitea endpoint: %w", err)
|
||||
}
|
||||
return newEp, nil
|
||||
}
|
||||
|
|
@ -89,7 +88,7 @@ func (r *Runner) ListGiteaEndpoints(ctx context.Context) ([]params.ForgeEndpoint
|
|||
|
||||
endpoints, err := r.store.ListGiteaEndpoints(ctx)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to list gitea endpoints")
|
||||
return nil, fmt.Errorf("failed to list gitea endpoints: %w", err)
|
||||
}
|
||||
|
||||
return endpoints, nil
|
||||
|
|
|
|||
|
|
@ -16,8 +16,7 @@ package runner
|
|||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"fmt"
|
||||
|
||||
runnerErrors "github.com/cloudbase/garm-provider-common/errors"
|
||||
"github.com/cloudbase/garm/auth"
|
||||
|
|
@ -36,7 +35,7 @@ func (r *Runner) ListCredentials(ctx context.Context) ([]params.ForgeCredentials
|
|||
// there is a posibillity that not all creds will be in the cache.
|
||||
creds, err := r.store.ListGithubCredentials(ctx)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "fetching github credentials")
|
||||
return nil, fmt.Errorf("error fetching github credentials: %w", err)
|
||||
}
|
||||
|
||||
// If we do have cache, update the rate limit for each credential. The rate limits are queried
|
||||
|
|
@ -57,12 +56,12 @@ func (r *Runner) CreateGithubCredentials(ctx context.Context, param params.Creat
|
|||
}
|
||||
|
||||
if err := param.Validate(); err != nil {
|
||||
return params.ForgeCredentials{}, errors.Wrap(err, "failed to validate github credentials params")
|
||||
return params.ForgeCredentials{}, fmt.Errorf("failed to validate github credentials params: %w", err)
|
||||
}
|
||||
|
||||
creds, err := r.store.CreateGithubCredentials(ctx, param)
|
||||
if err != nil {
|
||||
return params.ForgeCredentials{}, errors.Wrap(err, "failed to create github credentials")
|
||||
return params.ForgeCredentials{}, fmt.Errorf("failed to create github credentials: %w", err)
|
||||
}
|
||||
|
||||
return creds, nil
|
||||
|
|
@ -75,7 +74,7 @@ func (r *Runner) GetGithubCredentials(ctx context.Context, id uint) (params.Forg
|
|||
|
||||
creds, err := r.store.GetGithubCredentials(ctx, id, true)
|
||||
if err != nil {
|
||||
return params.ForgeCredentials{}, errors.Wrap(err, "failed to get github credentials")
|
||||
return params.ForgeCredentials{}, fmt.Errorf("failed to get github credentials: %w", err)
|
||||
}
|
||||
|
||||
cached, ok := cache.GetGithubCredentials((creds.ID))
|
||||
|
|
@ -92,7 +91,7 @@ func (r *Runner) DeleteGithubCredentials(ctx context.Context, id uint) error {
|
|||
}
|
||||
|
||||
if err := r.store.DeleteGithubCredentials(ctx, id); err != nil {
|
||||
return errors.Wrap(err, "failed to delete github credentials")
|
||||
return fmt.Errorf("failed to delete github credentials: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
|
@ -104,12 +103,12 @@ func (r *Runner) UpdateGithubCredentials(ctx context.Context, id uint, param par
|
|||
}
|
||||
|
||||
if err := param.Validate(); err != nil {
|
||||
return params.ForgeCredentials{}, errors.Wrap(err, "failed to validate github credentials params")
|
||||
return params.ForgeCredentials{}, fmt.Errorf("failed to validate github credentials params: %w", err)
|
||||
}
|
||||
|
||||
newCreds, err := r.store.UpdateGithubCredentials(ctx, id, param)
|
||||
if err != nil {
|
||||
return params.ForgeCredentials{}, errors.Wrap(err, "failed to update github credentials")
|
||||
return params.ForgeCredentials{}, fmt.Errorf("failed to update github credentials: %w", err)
|
||||
}
|
||||
|
||||
return newCreds, nil
|
||||
|
|
|
|||
|
|
@ -16,8 +16,7 @@ package runner
|
|||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"fmt"
|
||||
|
||||
runnerErrors "github.com/cloudbase/garm-provider-common/errors"
|
||||
"github.com/cloudbase/garm/auth"
|
||||
|
|
@ -30,12 +29,12 @@ func (r *Runner) CreateGithubEndpoint(ctx context.Context, param params.CreateGi
|
|||
}
|
||||
|
||||
if err := param.Validate(); err != nil {
|
||||
return params.ForgeEndpoint{}, errors.Wrap(err, "failed to validate github endpoint params")
|
||||
return params.ForgeEndpoint{}, fmt.Errorf("error failed to validate github endpoint params: %w", err)
|
||||
}
|
||||
|
||||
ep, err := r.store.CreateGithubEndpoint(ctx, param)
|
||||
if err != nil {
|
||||
return params.ForgeEndpoint{}, errors.Wrap(err, "failed to create github endpoint")
|
||||
return params.ForgeEndpoint{}, fmt.Errorf("failed to create github endpoint: %w", err)
|
||||
}
|
||||
|
||||
return ep, nil
|
||||
|
|
@ -47,7 +46,7 @@ func (r *Runner) GetGithubEndpoint(ctx context.Context, name string) (params.For
|
|||
}
|
||||
endpoint, err := r.store.GetGithubEndpoint(ctx, name)
|
||||
if err != nil {
|
||||
return params.ForgeEndpoint{}, errors.Wrap(err, "failed to get github endpoint")
|
||||
return params.ForgeEndpoint{}, fmt.Errorf("failed to get github endpoint: %w", err)
|
||||
}
|
||||
|
||||
return endpoint, nil
|
||||
|
|
@ -60,7 +59,7 @@ func (r *Runner) DeleteGithubEndpoint(ctx context.Context, name string) error {
|
|||
|
||||
err := r.store.DeleteGithubEndpoint(ctx, name)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to delete github endpoint")
|
||||
return fmt.Errorf("failed to delete github endpoint: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
|
@ -72,12 +71,12 @@ func (r *Runner) UpdateGithubEndpoint(ctx context.Context, name string, param pa
|
|||
}
|
||||
|
||||
if err := param.Validate(); err != nil {
|
||||
return params.ForgeEndpoint{}, errors.Wrap(err, "failed to validate github endpoint params")
|
||||
return params.ForgeEndpoint{}, fmt.Errorf("failed to validate github endpoint params: %w", err)
|
||||
}
|
||||
|
||||
newEp, err := r.store.UpdateGithubEndpoint(ctx, name, param)
|
||||
if err != nil {
|
||||
return params.ForgeEndpoint{}, errors.Wrap(err, "failed to update github endpoint")
|
||||
return params.ForgeEndpoint{}, fmt.Errorf("failed to update github endpoint: %w", err)
|
||||
}
|
||||
return newEp, nil
|
||||
}
|
||||
|
|
@ -89,7 +88,7 @@ func (r *Runner) ListGithubEndpoints(ctx context.Context) ([]params.ForgeEndpoin
|
|||
|
||||
endpoints, err := r.store.ListGithubEndpoints(ctx)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to list github endpoints")
|
||||
return nil, fmt.Errorf("failed to list github endpoints: %w", err)
|
||||
}
|
||||
|
||||
return endpoints, nil
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ type EnterprisePoolManager interface {
|
|||
GetEnterprisePoolManagers() (map[string]common.PoolManager, error)
|
||||
}
|
||||
|
||||
//go:generate mockery --name=PoolManagerController
|
||||
//go:generate go run github.com/vektra/mockery/v2@latest
|
||||
|
||||
type PoolManagerController interface {
|
||||
RepoPoolManager
|
||||
|
|
|
|||
|
|
@ -18,12 +18,11 @@ import (
|
|||
"bytes"
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
"fmt"
|
||||
"html/template"
|
||||
"log/slog"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/cloudbase/garm-provider-common/defaults"
|
||||
runnerErrors "github.com/cloudbase/garm-provider-common/errors"
|
||||
"github.com/cloudbase/garm/auth"
|
||||
|
|
@ -92,7 +91,7 @@ func (r *Runner) getForgeEntityFromInstance(ctx context.Context, instance params
|
|||
slog.With(slog.Any("error", err)).ErrorContext(
|
||||
ctx, "failed to get entity getter",
|
||||
"instance", instance.Name)
|
||||
return params.ForgeEntity{}, errors.Wrap(err, "fetching entity getter")
|
||||
return params.ForgeEntity{}, fmt.Errorf("error fetching entity getter: %w", err)
|
||||
}
|
||||
|
||||
poolEntity, err := entityGetter.GetEntity()
|
||||
|
|
@ -100,7 +99,7 @@ func (r *Runner) getForgeEntityFromInstance(ctx context.Context, instance params
|
|||
slog.With(slog.Any("error", err)).ErrorContext(
|
||||
ctx, "failed to get entity",
|
||||
"instance", instance.Name)
|
||||
return params.ForgeEntity{}, errors.Wrap(err, "fetching entity")
|
||||
return params.ForgeEntity{}, fmt.Errorf("error fetching entity: %w", err)
|
||||
}
|
||||
|
||||
entity, err := r.store.GetForgeEntity(r.ctx, poolEntity.EntityType, poolEntity.ID)
|
||||
|
|
@ -108,7 +107,7 @@ func (r *Runner) getForgeEntityFromInstance(ctx context.Context, instance params
|
|||
slog.With(slog.Any("error", err)).ErrorContext(
|
||||
ctx, "failed to get entity",
|
||||
"instance", instance.Name)
|
||||
return params.ForgeEntity{}, errors.Wrap(err, "fetching entity")
|
||||
return params.ForgeEntity{}, fmt.Errorf("error fetching entity: %w", err)
|
||||
}
|
||||
return entity, nil
|
||||
}
|
||||
|
|
@ -136,13 +135,13 @@ func (r *Runner) GetRunnerServiceName(ctx context.Context) (string, error) {
|
|||
entity, err := r.getForgeEntityFromInstance(ctx, instance)
|
||||
if err != nil {
|
||||
slog.ErrorContext(r.ctx, "failed to get entity", "error", err)
|
||||
return "", errors.Wrap(err, "fetching entity")
|
||||
return "", fmt.Errorf("error fetching entity: %w", err)
|
||||
}
|
||||
|
||||
serviceName, err := r.getServiceNameForEntity(entity)
|
||||
if err != nil {
|
||||
slog.ErrorContext(r.ctx, "failed to get service name", "error", err)
|
||||
return "", errors.Wrap(err, "fetching service name")
|
||||
return "", fmt.Errorf("error fetching service name: %w", err)
|
||||
}
|
||||
return serviceName, nil
|
||||
}
|
||||
|
|
@ -157,13 +156,13 @@ func (r *Runner) GenerateSystemdUnitFile(ctx context.Context, runAsUser string)
|
|||
entity, err := r.getForgeEntityFromInstance(ctx, instance)
|
||||
if err != nil {
|
||||
slog.ErrorContext(r.ctx, "failed to get entity", "error", err)
|
||||
return nil, errors.Wrap(err, "fetching entity")
|
||||
return nil, fmt.Errorf("error fetching entity: %w", err)
|
||||
}
|
||||
|
||||
serviceName, err := r.getServiceNameForEntity(entity)
|
||||
if err != nil {
|
||||
slog.ErrorContext(r.ctx, "failed to get service name", "error", err)
|
||||
return nil, errors.Wrap(err, "fetching service name")
|
||||
return nil, fmt.Errorf("error fetching service name: %w", err)
|
||||
}
|
||||
|
||||
var unitTemplate *template.Template
|
||||
|
|
@ -178,7 +177,7 @@ func (r *Runner) GenerateSystemdUnitFile(ctx context.Context, runAsUser string)
|
|||
}
|
||||
if err != nil {
|
||||
slog.ErrorContext(r.ctx, "failed to parse template", "error", err)
|
||||
return nil, errors.Wrap(err, "parsing template")
|
||||
return nil, fmt.Errorf("error parsing template: %w", err)
|
||||
}
|
||||
|
||||
if runAsUser == "" {
|
||||
|
|
@ -196,14 +195,14 @@ func (r *Runner) GenerateSystemdUnitFile(ctx context.Context, runAsUser string)
|
|||
var unitFile bytes.Buffer
|
||||
if err := unitTemplate.Execute(&unitFile, data); err != nil {
|
||||
slog.ErrorContext(r.ctx, "failed to execute template", "error", err)
|
||||
return nil, errors.Wrap(err, "executing template")
|
||||
return nil, fmt.Errorf("error executing template: %w", err)
|
||||
}
|
||||
return unitFile.Bytes(), nil
|
||||
}
|
||||
|
||||
func (r *Runner) GetJITConfigFile(ctx context.Context, file string) ([]byte, error) {
|
||||
if !auth.InstanceHasJITConfig(ctx) {
|
||||
return nil, fmt.Errorf("instance not configured for JIT: %w", runnerErrors.ErrNotFound)
|
||||
return nil, runnerErrors.NewNotFoundError("instance not configured for JIT")
|
||||
}
|
||||
|
||||
instance, err := validateInstanceState(ctx)
|
||||
|
|
@ -215,12 +214,12 @@ func (r *Runner) GetJITConfigFile(ctx context.Context, file string) ([]byte, err
|
|||
jitConfig := instance.JitConfiguration
|
||||
contents, ok := jitConfig[file]
|
||||
if !ok {
|
||||
return nil, errors.Wrap(runnerErrors.ErrNotFound, "retrieving file")
|
||||
return nil, runnerErrors.NewNotFoundError("could not find file %q", file)
|
||||
}
|
||||
|
||||
decoded, err := base64.StdEncoding.DecodeString(contents)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "decoding file contents")
|
||||
return nil, fmt.Errorf("error decoding file contents: %w", err)
|
||||
}
|
||||
|
||||
return decoded, nil
|
||||
|
|
@ -249,12 +248,12 @@ func (r *Runner) GetInstanceGithubRegistrationToken(ctx context.Context) (string
|
|||
|
||||
poolMgr, err := r.getPoolManagerFromInstance(ctx, instance)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "fetching pool manager for instance")
|
||||
return "", fmt.Errorf("error fetching pool manager for instance: %w", err)
|
||||
}
|
||||
|
||||
token, err := poolMgr.GithubRunnerRegistrationToken()
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "fetching runner token")
|
||||
return "", fmt.Errorf("error fetching runner token: %w", err)
|
||||
}
|
||||
|
||||
tokenFetched := true
|
||||
|
|
@ -263,11 +262,11 @@ func (r *Runner) GetInstanceGithubRegistrationToken(ctx context.Context) (string
|
|||
}
|
||||
|
||||
if _, err := r.store.UpdateInstance(r.ctx, instance.Name, updateParams); err != nil {
|
||||
return "", errors.Wrap(err, "setting token_fetched for instance")
|
||||
return "", fmt.Errorf("error setting token_fetched for instance: %w", err)
|
||||
}
|
||||
|
||||
if err := r.store.AddInstanceEvent(ctx, instance.Name, params.FetchTokenEvent, params.EventInfo, "runner registration token was retrieved"); err != nil {
|
||||
return "", errors.Wrap(err, "recording event")
|
||||
return "", fmt.Errorf("error recording event: %w", err)
|
||||
}
|
||||
|
||||
return token, nil
|
||||
|
|
@ -283,7 +282,7 @@ func (r *Runner) GetRootCertificateBundle(ctx context.Context) (params.Certifica
|
|||
|
||||
poolMgr, err := r.getPoolManagerFromInstance(ctx, instance)
|
||||
if err != nil {
|
||||
return params.CertificateBundle{}, errors.Wrap(err, "fetching pool manager for instance")
|
||||
return params.CertificateBundle{}, fmt.Errorf("error fetching pool manager for instance: %w", err)
|
||||
}
|
||||
|
||||
bundle, err := poolMgr.RootCABundle()
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// Code generated by mockery v2.53.3. DO NOT EDIT.
|
||||
// Code generated by mockery. DO NOT EDIT.
|
||||
|
||||
package mocks
|
||||
|
||||
|
|
@ -19,6 +19,14 @@ type PoolManagerController struct {
|
|||
mock.Mock
|
||||
}
|
||||
|
||||
type PoolManagerController_Expecter struct {
|
||||
mock *mock.Mock
|
||||
}
|
||||
|
||||
func (_m *PoolManagerController) EXPECT() *PoolManagerController_Expecter {
|
||||
return &PoolManagerController_Expecter{mock: &_m.Mock}
|
||||
}
|
||||
|
||||
// CreateEnterprisePoolManager provides a mock function with given fields: ctx, enterprise, providers, store
|
||||
func (_m *PoolManagerController) CreateEnterprisePoolManager(ctx context.Context, enterprise params.Enterprise, providers map[string]common.Provider, store databasecommon.Store) (common.PoolManager, error) {
|
||||
ret := _m.Called(ctx, enterprise, providers, store)
|
||||
|
|
@ -49,6 +57,37 @@ func (_m *PoolManagerController) CreateEnterprisePoolManager(ctx context.Context
|
|||
return r0, r1
|
||||
}
|
||||
|
||||
// PoolManagerController_CreateEnterprisePoolManager_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CreateEnterprisePoolManager'
|
||||
type PoolManagerController_CreateEnterprisePoolManager_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// CreateEnterprisePoolManager is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
// - enterprise params.Enterprise
|
||||
// - providers map[string]common.Provider
|
||||
// - store databasecommon.Store
|
||||
func (_e *PoolManagerController_Expecter) CreateEnterprisePoolManager(ctx interface{}, enterprise interface{}, providers interface{}, store interface{}) *PoolManagerController_CreateEnterprisePoolManager_Call {
|
||||
return &PoolManagerController_CreateEnterprisePoolManager_Call{Call: _e.mock.On("CreateEnterprisePoolManager", ctx, enterprise, providers, store)}
|
||||
}
|
||||
|
||||
func (_c *PoolManagerController_CreateEnterprisePoolManager_Call) Run(run func(ctx context.Context, enterprise params.Enterprise, providers map[string]common.Provider, store databasecommon.Store)) *PoolManagerController_CreateEnterprisePoolManager_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(context.Context), args[1].(params.Enterprise), args[2].(map[string]common.Provider), args[3].(databasecommon.Store))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *PoolManagerController_CreateEnterprisePoolManager_Call) Return(_a0 common.PoolManager, _a1 error) *PoolManagerController_CreateEnterprisePoolManager_Call {
|
||||
_c.Call.Return(_a0, _a1)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *PoolManagerController_CreateEnterprisePoolManager_Call) RunAndReturn(run func(context.Context, params.Enterprise, map[string]common.Provider, databasecommon.Store) (common.PoolManager, error)) *PoolManagerController_CreateEnterprisePoolManager_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// CreateOrgPoolManager provides a mock function with given fields: ctx, org, providers, store
|
||||
func (_m *PoolManagerController) CreateOrgPoolManager(ctx context.Context, org params.Organization, providers map[string]common.Provider, store databasecommon.Store) (common.PoolManager, error) {
|
||||
ret := _m.Called(ctx, org, providers, store)
|
||||
|
|
@ -79,6 +118,37 @@ func (_m *PoolManagerController) CreateOrgPoolManager(ctx context.Context, org p
|
|||
return r0, r1
|
||||
}
|
||||
|
||||
// PoolManagerController_CreateOrgPoolManager_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CreateOrgPoolManager'
|
||||
type PoolManagerController_CreateOrgPoolManager_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// CreateOrgPoolManager is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
// - org params.Organization
|
||||
// - providers map[string]common.Provider
|
||||
// - store databasecommon.Store
|
||||
func (_e *PoolManagerController_Expecter) CreateOrgPoolManager(ctx interface{}, org interface{}, providers interface{}, store interface{}) *PoolManagerController_CreateOrgPoolManager_Call {
|
||||
return &PoolManagerController_CreateOrgPoolManager_Call{Call: _e.mock.On("CreateOrgPoolManager", ctx, org, providers, store)}
|
||||
}
|
||||
|
||||
func (_c *PoolManagerController_CreateOrgPoolManager_Call) Run(run func(ctx context.Context, org params.Organization, providers map[string]common.Provider, store databasecommon.Store)) *PoolManagerController_CreateOrgPoolManager_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(context.Context), args[1].(params.Organization), args[2].(map[string]common.Provider), args[3].(databasecommon.Store))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *PoolManagerController_CreateOrgPoolManager_Call) Return(_a0 common.PoolManager, _a1 error) *PoolManagerController_CreateOrgPoolManager_Call {
|
||||
_c.Call.Return(_a0, _a1)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *PoolManagerController_CreateOrgPoolManager_Call) RunAndReturn(run func(context.Context, params.Organization, map[string]common.Provider, databasecommon.Store) (common.PoolManager, error)) *PoolManagerController_CreateOrgPoolManager_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// CreateRepoPoolManager provides a mock function with given fields: ctx, repo, providers, store
|
||||
func (_m *PoolManagerController) CreateRepoPoolManager(ctx context.Context, repo params.Repository, providers map[string]common.Provider, store databasecommon.Store) (common.PoolManager, error) {
|
||||
ret := _m.Called(ctx, repo, providers, store)
|
||||
|
|
@ -109,6 +179,37 @@ func (_m *PoolManagerController) CreateRepoPoolManager(ctx context.Context, repo
|
|||
return r0, r1
|
||||
}
|
||||
|
||||
// PoolManagerController_CreateRepoPoolManager_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CreateRepoPoolManager'
|
||||
type PoolManagerController_CreateRepoPoolManager_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// CreateRepoPoolManager is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
// - repo params.Repository
|
||||
// - providers map[string]common.Provider
|
||||
// - store databasecommon.Store
|
||||
func (_e *PoolManagerController_Expecter) CreateRepoPoolManager(ctx interface{}, repo interface{}, providers interface{}, store interface{}) *PoolManagerController_CreateRepoPoolManager_Call {
|
||||
return &PoolManagerController_CreateRepoPoolManager_Call{Call: _e.mock.On("CreateRepoPoolManager", ctx, repo, providers, store)}
|
||||
}
|
||||
|
||||
func (_c *PoolManagerController_CreateRepoPoolManager_Call) Run(run func(ctx context.Context, repo params.Repository, providers map[string]common.Provider, store databasecommon.Store)) *PoolManagerController_CreateRepoPoolManager_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(context.Context), args[1].(params.Repository), args[2].(map[string]common.Provider), args[3].(databasecommon.Store))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *PoolManagerController_CreateRepoPoolManager_Call) Return(_a0 common.PoolManager, _a1 error) *PoolManagerController_CreateRepoPoolManager_Call {
|
||||
_c.Call.Return(_a0, _a1)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *PoolManagerController_CreateRepoPoolManager_Call) RunAndReturn(run func(context.Context, params.Repository, map[string]common.Provider, databasecommon.Store) (common.PoolManager, error)) *PoolManagerController_CreateRepoPoolManager_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// DeleteEnterprisePoolManager provides a mock function with given fields: enterprise
|
||||
func (_m *PoolManagerController) DeleteEnterprisePoolManager(enterprise params.Enterprise) error {
|
||||
ret := _m.Called(enterprise)
|
||||
|
|
@ -127,6 +228,34 @@ func (_m *PoolManagerController) DeleteEnterprisePoolManager(enterprise params.E
|
|||
return r0
|
||||
}
|
||||
|
||||
// PoolManagerController_DeleteEnterprisePoolManager_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'DeleteEnterprisePoolManager'
|
||||
type PoolManagerController_DeleteEnterprisePoolManager_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// DeleteEnterprisePoolManager is a helper method to define mock.On call
|
||||
// - enterprise params.Enterprise
|
||||
func (_e *PoolManagerController_Expecter) DeleteEnterprisePoolManager(enterprise interface{}) *PoolManagerController_DeleteEnterprisePoolManager_Call {
|
||||
return &PoolManagerController_DeleteEnterprisePoolManager_Call{Call: _e.mock.On("DeleteEnterprisePoolManager", enterprise)}
|
||||
}
|
||||
|
||||
func (_c *PoolManagerController_DeleteEnterprisePoolManager_Call) Run(run func(enterprise params.Enterprise)) *PoolManagerController_DeleteEnterprisePoolManager_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(params.Enterprise))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *PoolManagerController_DeleteEnterprisePoolManager_Call) Return(_a0 error) *PoolManagerController_DeleteEnterprisePoolManager_Call {
|
||||
_c.Call.Return(_a0)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *PoolManagerController_DeleteEnterprisePoolManager_Call) RunAndReturn(run func(params.Enterprise) error) *PoolManagerController_DeleteEnterprisePoolManager_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// DeleteOrgPoolManager provides a mock function with given fields: org
|
||||
func (_m *PoolManagerController) DeleteOrgPoolManager(org params.Organization) error {
|
||||
ret := _m.Called(org)
|
||||
|
|
@ -145,6 +274,34 @@ func (_m *PoolManagerController) DeleteOrgPoolManager(org params.Organization) e
|
|||
return r0
|
||||
}
|
||||
|
||||
// PoolManagerController_DeleteOrgPoolManager_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'DeleteOrgPoolManager'
|
||||
type PoolManagerController_DeleteOrgPoolManager_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// DeleteOrgPoolManager is a helper method to define mock.On call
|
||||
// - org params.Organization
|
||||
func (_e *PoolManagerController_Expecter) DeleteOrgPoolManager(org interface{}) *PoolManagerController_DeleteOrgPoolManager_Call {
|
||||
return &PoolManagerController_DeleteOrgPoolManager_Call{Call: _e.mock.On("DeleteOrgPoolManager", org)}
|
||||
}
|
||||
|
||||
func (_c *PoolManagerController_DeleteOrgPoolManager_Call) Run(run func(org params.Organization)) *PoolManagerController_DeleteOrgPoolManager_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(params.Organization))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *PoolManagerController_DeleteOrgPoolManager_Call) Return(_a0 error) *PoolManagerController_DeleteOrgPoolManager_Call {
|
||||
_c.Call.Return(_a0)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *PoolManagerController_DeleteOrgPoolManager_Call) RunAndReturn(run func(params.Organization) error) *PoolManagerController_DeleteOrgPoolManager_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// DeleteRepoPoolManager provides a mock function with given fields: repo
|
||||
func (_m *PoolManagerController) DeleteRepoPoolManager(repo params.Repository) error {
|
||||
ret := _m.Called(repo)
|
||||
|
|
@ -163,6 +320,34 @@ func (_m *PoolManagerController) DeleteRepoPoolManager(repo params.Repository) e
|
|||
return r0
|
||||
}
|
||||
|
||||
// PoolManagerController_DeleteRepoPoolManager_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'DeleteRepoPoolManager'
|
||||
type PoolManagerController_DeleteRepoPoolManager_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// DeleteRepoPoolManager is a helper method to define mock.On call
|
||||
// - repo params.Repository
|
||||
func (_e *PoolManagerController_Expecter) DeleteRepoPoolManager(repo interface{}) *PoolManagerController_DeleteRepoPoolManager_Call {
|
||||
return &PoolManagerController_DeleteRepoPoolManager_Call{Call: _e.mock.On("DeleteRepoPoolManager", repo)}
|
||||
}
|
||||
|
||||
func (_c *PoolManagerController_DeleteRepoPoolManager_Call) Run(run func(repo params.Repository)) *PoolManagerController_DeleteRepoPoolManager_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(params.Repository))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *PoolManagerController_DeleteRepoPoolManager_Call) Return(_a0 error) *PoolManagerController_DeleteRepoPoolManager_Call {
|
||||
_c.Call.Return(_a0)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *PoolManagerController_DeleteRepoPoolManager_Call) RunAndReturn(run func(params.Repository) error) *PoolManagerController_DeleteRepoPoolManager_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// GetEnterprisePoolManager provides a mock function with given fields: enterprise
|
||||
func (_m *PoolManagerController) GetEnterprisePoolManager(enterprise params.Enterprise) (common.PoolManager, error) {
|
||||
ret := _m.Called(enterprise)
|
||||
|
|
@ -193,6 +378,34 @@ func (_m *PoolManagerController) GetEnterprisePoolManager(enterprise params.Ente
|
|||
return r0, r1
|
||||
}
|
||||
|
||||
// PoolManagerController_GetEnterprisePoolManager_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetEnterprisePoolManager'
|
||||
type PoolManagerController_GetEnterprisePoolManager_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// GetEnterprisePoolManager is a helper method to define mock.On call
|
||||
// - enterprise params.Enterprise
|
||||
func (_e *PoolManagerController_Expecter) GetEnterprisePoolManager(enterprise interface{}) *PoolManagerController_GetEnterprisePoolManager_Call {
|
||||
return &PoolManagerController_GetEnterprisePoolManager_Call{Call: _e.mock.On("GetEnterprisePoolManager", enterprise)}
|
||||
}
|
||||
|
||||
func (_c *PoolManagerController_GetEnterprisePoolManager_Call) Run(run func(enterprise params.Enterprise)) *PoolManagerController_GetEnterprisePoolManager_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(params.Enterprise))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *PoolManagerController_GetEnterprisePoolManager_Call) Return(_a0 common.PoolManager, _a1 error) *PoolManagerController_GetEnterprisePoolManager_Call {
|
||||
_c.Call.Return(_a0, _a1)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *PoolManagerController_GetEnterprisePoolManager_Call) RunAndReturn(run func(params.Enterprise) (common.PoolManager, error)) *PoolManagerController_GetEnterprisePoolManager_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// GetEnterprisePoolManagers provides a mock function with no fields
|
||||
func (_m *PoolManagerController) GetEnterprisePoolManagers() (map[string]common.PoolManager, error) {
|
||||
ret := _m.Called()
|
||||
|
|
@ -223,6 +436,33 @@ func (_m *PoolManagerController) GetEnterprisePoolManagers() (map[string]common.
|
|||
return r0, r1
|
||||
}
|
||||
|
||||
// PoolManagerController_GetEnterprisePoolManagers_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetEnterprisePoolManagers'
|
||||
type PoolManagerController_GetEnterprisePoolManagers_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// GetEnterprisePoolManagers is a helper method to define mock.On call
|
||||
func (_e *PoolManagerController_Expecter) GetEnterprisePoolManagers() *PoolManagerController_GetEnterprisePoolManagers_Call {
|
||||
return &PoolManagerController_GetEnterprisePoolManagers_Call{Call: _e.mock.On("GetEnterprisePoolManagers")}
|
||||
}
|
||||
|
||||
func (_c *PoolManagerController_GetEnterprisePoolManagers_Call) Run(run func()) *PoolManagerController_GetEnterprisePoolManagers_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run()
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *PoolManagerController_GetEnterprisePoolManagers_Call) Return(_a0 map[string]common.PoolManager, _a1 error) *PoolManagerController_GetEnterprisePoolManagers_Call {
|
||||
_c.Call.Return(_a0, _a1)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *PoolManagerController_GetEnterprisePoolManagers_Call) RunAndReturn(run func() (map[string]common.PoolManager, error)) *PoolManagerController_GetEnterprisePoolManagers_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// GetOrgPoolManager provides a mock function with given fields: org
|
||||
func (_m *PoolManagerController) GetOrgPoolManager(org params.Organization) (common.PoolManager, error) {
|
||||
ret := _m.Called(org)
|
||||
|
|
@ -253,6 +493,34 @@ func (_m *PoolManagerController) GetOrgPoolManager(org params.Organization) (com
|
|||
return r0, r1
|
||||
}
|
||||
|
||||
// PoolManagerController_GetOrgPoolManager_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetOrgPoolManager'
|
||||
type PoolManagerController_GetOrgPoolManager_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// GetOrgPoolManager is a helper method to define mock.On call
|
||||
// - org params.Organization
|
||||
func (_e *PoolManagerController_Expecter) GetOrgPoolManager(org interface{}) *PoolManagerController_GetOrgPoolManager_Call {
|
||||
return &PoolManagerController_GetOrgPoolManager_Call{Call: _e.mock.On("GetOrgPoolManager", org)}
|
||||
}
|
||||
|
||||
func (_c *PoolManagerController_GetOrgPoolManager_Call) Run(run func(org params.Organization)) *PoolManagerController_GetOrgPoolManager_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(params.Organization))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *PoolManagerController_GetOrgPoolManager_Call) Return(_a0 common.PoolManager, _a1 error) *PoolManagerController_GetOrgPoolManager_Call {
|
||||
_c.Call.Return(_a0, _a1)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *PoolManagerController_GetOrgPoolManager_Call) RunAndReturn(run func(params.Organization) (common.PoolManager, error)) *PoolManagerController_GetOrgPoolManager_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// GetOrgPoolManagers provides a mock function with no fields
|
||||
func (_m *PoolManagerController) GetOrgPoolManagers() (map[string]common.PoolManager, error) {
|
||||
ret := _m.Called()
|
||||
|
|
@ -283,6 +551,33 @@ func (_m *PoolManagerController) GetOrgPoolManagers() (map[string]common.PoolMan
|
|||
return r0, r1
|
||||
}
|
||||
|
||||
// PoolManagerController_GetOrgPoolManagers_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetOrgPoolManagers'
|
||||
type PoolManagerController_GetOrgPoolManagers_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// GetOrgPoolManagers is a helper method to define mock.On call
|
||||
func (_e *PoolManagerController_Expecter) GetOrgPoolManagers() *PoolManagerController_GetOrgPoolManagers_Call {
|
||||
return &PoolManagerController_GetOrgPoolManagers_Call{Call: _e.mock.On("GetOrgPoolManagers")}
|
||||
}
|
||||
|
||||
func (_c *PoolManagerController_GetOrgPoolManagers_Call) Run(run func()) *PoolManagerController_GetOrgPoolManagers_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run()
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *PoolManagerController_GetOrgPoolManagers_Call) Return(_a0 map[string]common.PoolManager, _a1 error) *PoolManagerController_GetOrgPoolManagers_Call {
|
||||
_c.Call.Return(_a0, _a1)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *PoolManagerController_GetOrgPoolManagers_Call) RunAndReturn(run func() (map[string]common.PoolManager, error)) *PoolManagerController_GetOrgPoolManagers_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// GetRepoPoolManager provides a mock function with given fields: repo
|
||||
func (_m *PoolManagerController) GetRepoPoolManager(repo params.Repository) (common.PoolManager, error) {
|
||||
ret := _m.Called(repo)
|
||||
|
|
@ -313,6 +608,34 @@ func (_m *PoolManagerController) GetRepoPoolManager(repo params.Repository) (com
|
|||
return r0, r1
|
||||
}
|
||||
|
||||
// PoolManagerController_GetRepoPoolManager_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetRepoPoolManager'
|
||||
type PoolManagerController_GetRepoPoolManager_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// GetRepoPoolManager is a helper method to define mock.On call
|
||||
// - repo params.Repository
|
||||
func (_e *PoolManagerController_Expecter) GetRepoPoolManager(repo interface{}) *PoolManagerController_GetRepoPoolManager_Call {
|
||||
return &PoolManagerController_GetRepoPoolManager_Call{Call: _e.mock.On("GetRepoPoolManager", repo)}
|
||||
}
|
||||
|
||||
func (_c *PoolManagerController_GetRepoPoolManager_Call) Run(run func(repo params.Repository)) *PoolManagerController_GetRepoPoolManager_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(params.Repository))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *PoolManagerController_GetRepoPoolManager_Call) Return(_a0 common.PoolManager, _a1 error) *PoolManagerController_GetRepoPoolManager_Call {
|
||||
_c.Call.Return(_a0, _a1)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *PoolManagerController_GetRepoPoolManager_Call) RunAndReturn(run func(params.Repository) (common.PoolManager, error)) *PoolManagerController_GetRepoPoolManager_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// GetRepoPoolManagers provides a mock function with no fields
|
||||
func (_m *PoolManagerController) GetRepoPoolManagers() (map[string]common.PoolManager, error) {
|
||||
ret := _m.Called()
|
||||
|
|
@ -343,6 +666,33 @@ func (_m *PoolManagerController) GetRepoPoolManagers() (map[string]common.PoolMa
|
|||
return r0, r1
|
||||
}
|
||||
|
||||
// PoolManagerController_GetRepoPoolManagers_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetRepoPoolManagers'
|
||||
type PoolManagerController_GetRepoPoolManagers_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// GetRepoPoolManagers is a helper method to define mock.On call
|
||||
func (_e *PoolManagerController_Expecter) GetRepoPoolManagers() *PoolManagerController_GetRepoPoolManagers_Call {
|
||||
return &PoolManagerController_GetRepoPoolManagers_Call{Call: _e.mock.On("GetRepoPoolManagers")}
|
||||
}
|
||||
|
||||
func (_c *PoolManagerController_GetRepoPoolManagers_Call) Run(run func()) *PoolManagerController_GetRepoPoolManagers_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run()
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *PoolManagerController_GetRepoPoolManagers_Call) Return(_a0 map[string]common.PoolManager, _a1 error) *PoolManagerController_GetRepoPoolManagers_Call {
|
||||
_c.Call.Return(_a0, _a1)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *PoolManagerController_GetRepoPoolManagers_Call) RunAndReturn(run func() (map[string]common.PoolManager, error)) *PoolManagerController_GetRepoPoolManagers_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// NewPoolManagerController creates a new instance of PoolManagerController. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
|
||||
// The first argument is typically a *testing.T value.
|
||||
func NewPoolManagerController(t interface {
|
||||
|
|
|
|||
|
|
@ -16,12 +16,11 @@ package runner
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"strings"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
runnerErrors "github.com/cloudbase/garm-provider-common/errors"
|
||||
"github.com/cloudbase/garm/auth"
|
||||
"github.com/cloudbase/garm/params"
|
||||
|
|
@ -35,7 +34,7 @@ func (r *Runner) CreateOrganization(ctx context.Context, param params.CreateOrgP
|
|||
}
|
||||
|
||||
if err := param.Validate(); err != nil {
|
||||
return params.Organization{}, errors.Wrap(err, "validating params")
|
||||
return params.Organization{}, fmt.Errorf("error validating params: %w", err)
|
||||
}
|
||||
|
||||
var creds params.ForgeCredentials
|
||||
|
|
@ -57,7 +56,7 @@ func (r *Runner) CreateOrganization(ctx context.Context, param params.CreateOrgP
|
|||
_, err = r.store.GetOrganization(ctx, param.Name, creds.Endpoint.Name)
|
||||
if err != nil {
|
||||
if !errors.Is(err, runnerErrors.ErrNotFound) {
|
||||
return params.Organization{}, errors.Wrap(err, "fetching org")
|
||||
return params.Organization{}, fmt.Errorf("error fetching org: %w", err)
|
||||
}
|
||||
} else {
|
||||
return params.Organization{}, runnerErrors.NewConflictError("organization %s already exists", param.Name)
|
||||
|
|
@ -65,7 +64,7 @@ func (r *Runner) CreateOrganization(ctx context.Context, param params.CreateOrgP
|
|||
|
||||
org, err = r.store.CreateOrganization(ctx, param.Name, creds, param.WebhookSecret, param.PoolBalancerType)
|
||||
if err != nil {
|
||||
return params.Organization{}, errors.Wrap(err, "creating organization")
|
||||
return params.Organization{}, fmt.Errorf("error creating organization: %w", err)
|
||||
}
|
||||
|
||||
defer func() {
|
||||
|
|
@ -82,7 +81,7 @@ func (r *Runner) CreateOrganization(ctx context.Context, param params.CreateOrgP
|
|||
// updating the store.
|
||||
poolMgr, err := r.poolManagerCtrl.CreateOrgPoolManager(r.ctx, org, r.providers, r.store)
|
||||
if err != nil {
|
||||
return params.Organization{}, errors.Wrap(err, "creating org pool manager")
|
||||
return params.Organization{}, fmt.Errorf("error creating org pool manager: %w", err)
|
||||
}
|
||||
if err := poolMgr.Start(); err != nil {
|
||||
if deleteErr := r.poolManagerCtrl.DeleteOrgPoolManager(org); deleteErr != nil {
|
||||
|
|
@ -90,7 +89,7 @@ func (r *Runner) CreateOrganization(ctx context.Context, param params.CreateOrgP
|
|||
ctx, "failed to cleanup pool manager for org",
|
||||
"org_id", org.ID)
|
||||
}
|
||||
return params.Organization{}, errors.Wrap(err, "starting org pool manager")
|
||||
return params.Organization{}, fmt.Errorf("error starting org pool manager: %w", err)
|
||||
}
|
||||
return org, nil
|
||||
}
|
||||
|
|
@ -102,7 +101,7 @@ func (r *Runner) ListOrganizations(ctx context.Context, filter params.Organizati
|
|||
|
||||
orgs, err := r.store.ListOrganizations(ctx, filter)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "listing organizations")
|
||||
return nil, fmt.Errorf("error listing organizations: %w", err)
|
||||
}
|
||||
|
||||
var allOrgs []params.Organization
|
||||
|
|
@ -129,7 +128,7 @@ func (r *Runner) GetOrganizationByID(ctx context.Context, orgID string) (params.
|
|||
|
||||
org, err := r.store.GetOrganizationByID(ctx, orgID)
|
||||
if err != nil {
|
||||
return params.Organization{}, errors.Wrap(err, "fetching organization")
|
||||
return params.Organization{}, fmt.Errorf("error fetching organization: %w", err)
|
||||
}
|
||||
|
||||
poolMgr, err := r.poolManagerCtrl.GetOrgPoolManager(org)
|
||||
|
|
@ -148,17 +147,17 @@ func (r *Runner) DeleteOrganization(ctx context.Context, orgID string, keepWebho
|
|||
|
||||
org, err := r.store.GetOrganizationByID(ctx, orgID)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "fetching org")
|
||||
return fmt.Errorf("error fetching org: %w", err)
|
||||
}
|
||||
|
||||
entity, err := org.GetEntity()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "getting entity")
|
||||
return fmt.Errorf("error getting entity: %w", err)
|
||||
}
|
||||
|
||||
pools, err := r.store.ListEntityPools(ctx, entity)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "fetching org pools")
|
||||
return fmt.Errorf("error fetching org pools: %w", err)
|
||||
}
|
||||
|
||||
if len(pools) > 0 {
|
||||
|
|
@ -172,7 +171,7 @@ func (r *Runner) DeleteOrganization(ctx context.Context, orgID string, keepWebho
|
|||
|
||||
scaleSets, err := r.store.ListEntityScaleSets(ctx, entity)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "fetching organization scale sets")
|
||||
return fmt.Errorf("error fetching organization scale sets: %w", err)
|
||||
}
|
||||
|
||||
if len(scaleSets) > 0 {
|
||||
|
|
@ -182,7 +181,7 @@ func (r *Runner) DeleteOrganization(ctx context.Context, orgID string, keepWebho
|
|||
if !keepWebhook && r.config.Default.EnableWebhookManagement {
|
||||
poolMgr, err := r.poolManagerCtrl.GetOrgPoolManager(org)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "fetching pool manager")
|
||||
return fmt.Errorf("error fetching pool manager: %w", err)
|
||||
}
|
||||
|
||||
if err := poolMgr.UninstallWebhook(ctx); err != nil {
|
||||
|
|
@ -195,11 +194,11 @@ func (r *Runner) DeleteOrganization(ctx context.Context, orgID string, keepWebho
|
|||
}
|
||||
|
||||
if err := r.poolManagerCtrl.DeleteOrgPoolManager(org); err != nil {
|
||||
return errors.Wrap(err, "deleting org pool manager")
|
||||
return fmt.Errorf("error deleting org pool manager: %w", err)
|
||||
}
|
||||
|
||||
if err := r.store.DeleteOrganization(ctx, orgID); err != nil {
|
||||
return errors.Wrapf(err, "removing organization %s", orgID)
|
||||
return fmt.Errorf("error removing organization %s: %w", orgID, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
@ -220,7 +219,7 @@ func (r *Runner) UpdateOrganization(ctx context.Context, orgID string, param par
|
|||
|
||||
org, err := r.store.UpdateOrganization(ctx, orgID, param)
|
||||
if err != nil {
|
||||
return params.Organization{}, errors.Wrap(err, "updating org")
|
||||
return params.Organization{}, fmt.Errorf("error updating org: %w", err)
|
||||
}
|
||||
|
||||
poolMgr, err := r.poolManagerCtrl.GetOrgPoolManager(org)
|
||||
|
|
@ -239,7 +238,7 @@ func (r *Runner) CreateOrgPool(ctx context.Context, orgID string, param params.C
|
|||
|
||||
createPoolParams, err := r.appendTagsToCreatePoolParams(param)
|
||||
if err != nil {
|
||||
return params.Pool{}, errors.Wrap(err, "fetching pool params")
|
||||
return params.Pool{}, fmt.Errorf("error fetching pool params: %w", err)
|
||||
}
|
||||
|
||||
if param.RunnerBootstrapTimeout == 0 {
|
||||
|
|
@ -253,7 +252,7 @@ func (r *Runner) CreateOrgPool(ctx context.Context, orgID string, param params.C
|
|||
|
||||
pool, err := r.store.CreateEntityPool(ctx, entity, createPoolParams)
|
||||
if err != nil {
|
||||
return params.Pool{}, errors.Wrap(err, "creating pool")
|
||||
return params.Pool{}, fmt.Errorf("error creating pool: %w", err)
|
||||
}
|
||||
|
||||
return pool, nil
|
||||
|
|
@ -271,7 +270,7 @@ func (r *Runner) GetOrgPoolByID(ctx context.Context, orgID, poolID string) (para
|
|||
|
||||
pool, err := r.store.GetEntityPool(ctx, entity, poolID)
|
||||
if err != nil {
|
||||
return params.Pool{}, errors.Wrap(err, "fetching pool")
|
||||
return params.Pool{}, fmt.Errorf("error fetching pool: %w", err)
|
||||
}
|
||||
|
||||
return pool, nil
|
||||
|
|
@ -290,7 +289,7 @@ func (r *Runner) DeleteOrgPool(ctx context.Context, orgID, poolID string) error
|
|||
pool, err := r.store.GetEntityPool(ctx, entity, poolID)
|
||||
if err != nil {
|
||||
if !errors.Is(err, runnerErrors.ErrNotFound) {
|
||||
return errors.Wrap(err, "fetching pool")
|
||||
return fmt.Errorf("error fetching pool: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
@ -306,7 +305,7 @@ func (r *Runner) DeleteOrgPool(ctx context.Context, orgID, poolID string) error
|
|||
}
|
||||
|
||||
if err := r.store.DeleteEntityPool(ctx, entity, poolID); err != nil {
|
||||
return errors.Wrap(err, "deleting pool")
|
||||
return fmt.Errorf("error deleting pool: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
@ -321,7 +320,7 @@ func (r *Runner) ListOrgPools(ctx context.Context, orgID string) ([]params.Pool,
|
|||
}
|
||||
pools, err := r.store.ListEntityPools(ctx, entity)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "fetching pools")
|
||||
return nil, fmt.Errorf("error fetching pools: %w", err)
|
||||
}
|
||||
return pools, nil
|
||||
}
|
||||
|
|
@ -338,7 +337,7 @@ func (r *Runner) UpdateOrgPool(ctx context.Context, orgID, poolID string, param
|
|||
|
||||
pool, err := r.store.GetEntityPool(ctx, entity, poolID)
|
||||
if err != nil {
|
||||
return params.Pool{}, errors.Wrap(err, "fetching pool")
|
||||
return params.Pool{}, fmt.Errorf("error fetching pool: %w", err)
|
||||
}
|
||||
|
||||
maxRunners := pool.MaxRunners
|
||||
|
|
@ -357,7 +356,7 @@ func (r *Runner) UpdateOrgPool(ctx context.Context, orgID, poolID string, param
|
|||
|
||||
newPool, err := r.store.UpdateEntityPool(ctx, entity, poolID, param)
|
||||
if err != nil {
|
||||
return params.Pool{}, errors.Wrap(err, "updating pool")
|
||||
return params.Pool{}, fmt.Errorf("error updating pool: %w", err)
|
||||
}
|
||||
return newPool, nil
|
||||
}
|
||||
|
|
@ -374,7 +373,7 @@ func (r *Runner) ListOrgInstances(ctx context.Context, orgID string) ([]params.I
|
|||
|
||||
instances, err := r.store.ListEntityInstances(ctx, entity)
|
||||
if err != nil {
|
||||
return []params.Instance{}, errors.Wrap(err, "fetching instances")
|
||||
return []params.Instance{}, fmt.Errorf("error fetching instances: %w", err)
|
||||
}
|
||||
return instances, nil
|
||||
}
|
||||
|
|
@ -385,12 +384,12 @@ func (r *Runner) findOrgPoolManager(name, endpointName string) (common.PoolManag
|
|||
|
||||
org, err := r.store.GetOrganization(r.ctx, name, endpointName)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "fetching org")
|
||||
return nil, fmt.Errorf("error fetching org: %w", err)
|
||||
}
|
||||
|
||||
poolManager, err := r.poolManagerCtrl.GetOrgPoolManager(org)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "fetching pool manager for org")
|
||||
return nil, fmt.Errorf("error fetching pool manager for org: %w", err)
|
||||
}
|
||||
return poolManager, nil
|
||||
}
|
||||
|
|
@ -402,17 +401,17 @@ func (r *Runner) InstallOrgWebhook(ctx context.Context, orgID string, param para
|
|||
|
||||
org, err := r.store.GetOrganizationByID(ctx, orgID)
|
||||
if err != nil {
|
||||
return params.HookInfo{}, errors.Wrap(err, "fetching org")
|
||||
return params.HookInfo{}, fmt.Errorf("error fetching org: %w", err)
|
||||
}
|
||||
|
||||
poolMgr, err := r.poolManagerCtrl.GetOrgPoolManager(org)
|
||||
if err != nil {
|
||||
return params.HookInfo{}, errors.Wrap(err, "fetching pool manager for org")
|
||||
return params.HookInfo{}, fmt.Errorf("error fetching pool manager for org: %w", err)
|
||||
}
|
||||
|
||||
info, err := poolMgr.InstallWebhook(ctx, param)
|
||||
if err != nil {
|
||||
return params.HookInfo{}, errors.Wrap(err, "installing webhook")
|
||||
return params.HookInfo{}, fmt.Errorf("error installing webhook: %w", err)
|
||||
}
|
||||
return info, nil
|
||||
}
|
||||
|
|
@ -424,16 +423,16 @@ func (r *Runner) UninstallOrgWebhook(ctx context.Context, orgID string) error {
|
|||
|
||||
org, err := r.store.GetOrganizationByID(ctx, orgID)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "fetching org")
|
||||
return fmt.Errorf("error fetching org: %w", err)
|
||||
}
|
||||
|
||||
poolMgr, err := r.poolManagerCtrl.GetOrgPoolManager(org)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "fetching pool manager for org")
|
||||
return fmt.Errorf("error fetching pool manager for org: %w", err)
|
||||
}
|
||||
|
||||
if err := poolMgr.UninstallWebhook(ctx); err != nil {
|
||||
return errors.Wrap(err, "uninstalling webhook")
|
||||
return fmt.Errorf("error uninstalling webhook: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
@ -445,17 +444,17 @@ func (r *Runner) GetOrgWebhookInfo(ctx context.Context, orgID string) (params.Ho
|
|||
|
||||
org, err := r.store.GetOrganizationByID(ctx, orgID)
|
||||
if err != nil {
|
||||
return params.HookInfo{}, errors.Wrap(err, "fetching org")
|
||||
return params.HookInfo{}, fmt.Errorf("error fetching org: %w", err)
|
||||
}
|
||||
|
||||
poolMgr, err := r.poolManagerCtrl.GetOrgPoolManager(org)
|
||||
if err != nil {
|
||||
return params.HookInfo{}, errors.Wrap(err, "fetching pool manager for org")
|
||||
return params.HookInfo{}, fmt.Errorf("error fetching pool manager for org: %w", err)
|
||||
}
|
||||
|
||||
info, err := poolMgr.GetWebhookInfo(ctx)
|
||||
if err != nil {
|
||||
return params.HookInfo{}, errors.Wrap(err, "fetching webhook info")
|
||||
return params.HookInfo{}, fmt.Errorf("error fetching webhook info: %w", err)
|
||||
}
|
||||
return info, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,10 +16,10 @@ package runner
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/stretchr/testify/mock"
|
||||
"github.com/stretchr/testify/suite"
|
||||
|
||||
|
|
@ -224,7 +224,7 @@ func (s *OrgTestSuite) TestCreateOrganizationPoolMgrFailed() {
|
|||
|
||||
s.Fixtures.PoolMgrMock.AssertExpectations(s.T())
|
||||
s.Fixtures.PoolMgrCtrlMock.AssertExpectations(s.T())
|
||||
s.Require().Equal(fmt.Sprintf("creating org pool manager: %s", s.Fixtures.ErrMock.Error()), err.Error())
|
||||
s.Require().Equal(fmt.Sprintf("error creating org pool manager: %s", s.Fixtures.ErrMock.Error()), err.Error())
|
||||
}
|
||||
|
||||
func (s *OrgTestSuite) TestCreateOrganizationStartPoolMgrFailed() {
|
||||
|
|
@ -236,7 +236,7 @@ func (s *OrgTestSuite) TestCreateOrganizationStartPoolMgrFailed() {
|
|||
|
||||
s.Fixtures.PoolMgrMock.AssertExpectations(s.T())
|
||||
s.Fixtures.PoolMgrCtrlMock.AssertExpectations(s.T())
|
||||
s.Require().Equal(fmt.Sprintf("starting org pool manager: %s", s.Fixtures.ErrMock.Error()), err.Error())
|
||||
s.Require().Equal(fmt.Sprintf("error starting org pool manager: %s", s.Fixtures.ErrMock.Error()), err.Error())
|
||||
}
|
||||
|
||||
func (s *OrgTestSuite) TestListOrganizations() {
|
||||
|
|
@ -338,7 +338,7 @@ func (s *OrgTestSuite) TestDeleteOrganization() {
|
|||
s.Require().Nil(err)
|
||||
|
||||
_, err = s.Fixtures.Store.GetOrganizationByID(s.Fixtures.AdminContext, s.Fixtures.StoreOrgs["test-org-3"].ID)
|
||||
s.Require().Equal("fetching org: not found", err.Error())
|
||||
s.Require().Equal("error fetching org: not found", err.Error())
|
||||
}
|
||||
|
||||
func (s *OrgTestSuite) TestDeleteOrganizationErrUnauthorized() {
|
||||
|
|
@ -368,7 +368,7 @@ func (s *OrgTestSuite) TestDeleteOrganizationPoolMgrFailed() {
|
|||
err := s.Runner.DeleteOrganization(s.Fixtures.AdminContext, s.Fixtures.StoreOrgs["test-org-1"].ID, true)
|
||||
|
||||
s.Fixtures.PoolMgrCtrlMock.AssertExpectations(s.T())
|
||||
s.Require().Equal(fmt.Sprintf("deleting org pool manager: %s", s.Fixtures.ErrMock.Error()), err.Error())
|
||||
s.Require().Equal(fmt.Sprintf("error deleting org pool manager: %s", s.Fixtures.ErrMock.Error()), err.Error())
|
||||
}
|
||||
|
||||
func (s *OrgTestSuite) TestUpdateOrganization() {
|
||||
|
|
@ -502,7 +502,7 @@ func (s *OrgTestSuite) TestDeleteOrgPool() {
|
|||
s.Require().Nil(err)
|
||||
|
||||
_, err = s.Fixtures.Store.GetEntityPool(s.Fixtures.AdminContext, entity, pool.ID)
|
||||
s.Require().Equal("fetching pool: finding pool: not found", err.Error())
|
||||
s.Require().Equal("fetching pool: error finding pool: not found", err.Error())
|
||||
}
|
||||
|
||||
func (s *OrgTestSuite) TestDeleteOrgPoolErrUnauthorized() {
|
||||
|
|
|
|||
75
runner/pool/cache.go
Normal file
75
runner/pool/cache.go
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
package pool
|
||||
|
||||
import (
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
|
||||
runnerErrors "github.com/cloudbase/garm-provider-common/errors"
|
||||
"github.com/cloudbase/garm/params"
|
||||
)
|
||||
|
||||
type poolCacheStore interface {
|
||||
Next() (params.Pool, error)
|
||||
Reset()
|
||||
Len() int
|
||||
}
|
||||
|
||||
type poolRoundRobin struct {
|
||||
pools []params.Pool
|
||||
next uint32
|
||||
}
|
||||
|
||||
func (p *poolRoundRobin) Next() (params.Pool, error) {
|
||||
if len(p.pools) == 0 {
|
||||
return params.Pool{}, runnerErrors.ErrNoPoolsAvailable
|
||||
}
|
||||
|
||||
n := atomic.AddUint32(&p.next, 1)
|
||||
return p.pools[(int(n)-1)%len(p.pools)], nil
|
||||
}
|
||||
|
||||
func (p *poolRoundRobin) Len() int {
|
||||
return len(p.pools)
|
||||
}
|
||||
|
||||
func (p *poolRoundRobin) Reset() {
|
||||
atomic.StoreUint32(&p.next, 0)
|
||||
}
|
||||
|
||||
type poolsForTags struct {
|
||||
pools sync.Map
|
||||
poolCacheType params.PoolBalancerType
|
||||
}
|
||||
|
||||
func (p *poolsForTags) Get(tags []string) (poolCacheStore, bool) {
|
||||
sort.Strings(tags)
|
||||
key := strings.Join(tags, "^")
|
||||
|
||||
v, ok := p.pools.Load(key)
|
||||
if !ok {
|
||||
return nil, false
|
||||
}
|
||||
poolCache := v.(*poolRoundRobin)
|
||||
if p.poolCacheType == params.PoolBalancerTypePack {
|
||||
// When we service a list of jobs, we want to try each pool in turn
|
||||
// for each job. Pools are sorted by priority so we always start from the
|
||||
// highest priority pool and move on to the next if the first one is full.
|
||||
poolCache.Reset()
|
||||
}
|
||||
return poolCache, true
|
||||
}
|
||||
|
||||
func (p *poolsForTags) Add(tags []string, pools []params.Pool) poolCacheStore {
|
||||
sort.Slice(pools, func(i, j int) bool {
|
||||
return pools[i].Priority > pools[j].Priority
|
||||
})
|
||||
|
||||
sort.Strings(tags)
|
||||
key := strings.Join(tags, "^")
|
||||
|
||||
poolRR := &poolRoundRobin{pools: pools}
|
||||
v, _ := p.pools.LoadOrStore(key, poolRR)
|
||||
return v.(*poolRoundRobin)
|
||||
}
|
||||
|
|
@ -14,79 +14,15 @@
|
|||
|
||||
package pool
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"github.com/google/go-github/v72/github"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
runnerErrors "github.com/cloudbase/garm-provider-common/errors"
|
||||
"github.com/cloudbase/garm/params"
|
||||
)
|
||||
|
||||
func validateHookRequest(controllerID, baseURL string, allHooks []*github.Hook, req *github.Hook) error {
|
||||
parsed, err := url.Parse(baseURL)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "parsing webhook url")
|
||||
}
|
||||
|
||||
partialMatches := []string{}
|
||||
for _, hook := range allHooks {
|
||||
hookURL := strings.ToLower(hook.Config.GetURL())
|
||||
if hookURL == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
if hook.Config.GetURL() == req.Config.GetURL() {
|
||||
return runnerErrors.NewConflictError("hook already installed")
|
||||
} else if strings.Contains(hookURL, controllerID) || strings.Contains(hookURL, parsed.Hostname()) {
|
||||
partialMatches = append(partialMatches, hook.Config.GetURL())
|
||||
}
|
||||
}
|
||||
|
||||
if len(partialMatches) > 0 {
|
||||
return runnerErrors.NewConflictError("a webhook containing the controller ID or hostname of this contreoller is already installed on this repository")
|
||||
}
|
||||
|
||||
return nil
|
||||
type RunnerLabels struct {
|
||||
ID int64 `json:"id,omitempty"`
|
||||
Name string `json:"name,omitempty"`
|
||||
Type string `json:"type,omitempty"`
|
||||
}
|
||||
|
||||
func hookToParamsHookInfo(hook *github.Hook) params.HookInfo {
|
||||
hookURL := hook.Config.GetURL()
|
||||
|
||||
insecureSSLConfig := hook.Config.GetInsecureSSL()
|
||||
insecureSSL := insecureSSLConfig == "1"
|
||||
|
||||
return params.HookInfo{
|
||||
ID: *hook.ID,
|
||||
URL: hookURL,
|
||||
Events: hook.Events,
|
||||
Active: *hook.Active,
|
||||
InsecureSSL: insecureSSL,
|
||||
}
|
||||
}
|
||||
|
||||
func (r *basePoolManager) listHooks(ctx context.Context) ([]*github.Hook, error) {
|
||||
opts := github.ListOptions{
|
||||
PerPage: 100,
|
||||
}
|
||||
var allHooks []*github.Hook
|
||||
for {
|
||||
hooks, ghResp, err := r.ghcli.ListEntityHooks(ctx, &opts)
|
||||
if err != nil {
|
||||
if ghResp != nil && ghResp.StatusCode == http.StatusNotFound {
|
||||
return nil, runnerErrors.NewBadRequestError("repository not found or your PAT does not have access to manage webhooks")
|
||||
}
|
||||
return nil, errors.Wrap(err, "fetching hooks")
|
||||
}
|
||||
allHooks = append(allHooks, hooks...)
|
||||
if ghResp.NextPage == 0 {
|
||||
break
|
||||
}
|
||||
opts.Page = ghResp.NextPage
|
||||
}
|
||||
return allHooks, nil
|
||||
type forgeRunner struct {
|
||||
ID int64 `json:"id,omitempty"`
|
||||
Name string `json:"name,omitempty"`
|
||||
Status string `json:"status,omitempty"`
|
||||
Labels []RunnerLabels `json:"labels,omitempty"`
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ package pool
|
|||
import (
|
||||
"context"
|
||||
"crypto/rand"
|
||||
"errors"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"math"
|
||||
|
|
@ -29,7 +30,6 @@ import (
|
|||
|
||||
"github.com/google/go-github/v72/github"
|
||||
"github.com/google/uuid"
|
||||
"github.com/pkg/errors"
|
||||
"golang.org/x/sync/errgroup"
|
||||
|
||||
runnerErrors "github.com/cloudbase/garm-provider-common/errors"
|
||||
|
|
@ -44,6 +44,7 @@ import (
|
|||
"github.com/cloudbase/garm/runner/common"
|
||||
garmUtil "github.com/cloudbase/garm/util"
|
||||
ghClient "github.com/cloudbase/garm/util/github"
|
||||
"github.com/cloudbase/garm/util/github/scalesets"
|
||||
)
|
||||
|
||||
var (
|
||||
|
|
@ -68,19 +69,24 @@ const (
|
|||
)
|
||||
|
||||
func NewEntityPoolManager(ctx context.Context, entity params.ForgeEntity, instanceTokenGetter auth.InstanceTokenGetter, providers map[string]common.Provider, store dbCommon.Store) (common.PoolManager, error) {
|
||||
ctx = garmUtil.WithSlogContext(ctx, slog.Any("pool_mgr", entity.String()), slog.Any("pool_type", entity.EntityType))
|
||||
ctx = garmUtil.WithSlogContext(
|
||||
ctx,
|
||||
slog.Any("pool_mgr", entity.String()),
|
||||
slog.Any("endpoint", entity.Credentials.Endpoint.Name),
|
||||
slog.Any("pool_type", entity.EntityType),
|
||||
)
|
||||
ghc, err := ghClient.Client(ctx, entity)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "getting github client")
|
||||
return nil, fmt.Errorf("error getting github client: %w", err)
|
||||
}
|
||||
|
||||
if entity.WebhookSecret == "" {
|
||||
return nil, errors.New("webhook secret is empty")
|
||||
return nil, fmt.Errorf("webhook secret is empty")
|
||||
}
|
||||
|
||||
controllerInfo, err := store.ControllerInfo()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "getting controller info")
|
||||
return nil, fmt.Errorf("error getting controller info: %w", err)
|
||||
}
|
||||
|
||||
consumerID := fmt.Sprintf("pool-manager-%s-%s", entity.String(), entity.Credentials.Endpoint.Name)
|
||||
|
|
@ -90,20 +96,28 @@ func NewEntityPoolManager(ctx context.Context, entity params.ForgeEntity, instan
|
|||
composeWatcherFilters(entity),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "registering consumer")
|
||||
return nil, fmt.Errorf("error registering consumer: %w", err)
|
||||
}
|
||||
|
||||
wg := &sync.WaitGroup{}
|
||||
backoff, err := locking.NewInstanceDeleteBackoff(ctx)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "creating backoff")
|
||||
return nil, fmt.Errorf("error creating backoff: %w", err)
|
||||
}
|
||||
|
||||
var scaleSetCli *scalesets.ScaleSetClient
|
||||
if entity.Credentials.ForgeType == params.GithubEndpointType {
|
||||
scaleSetCli, err = scalesets.NewClient(ghc)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get scalesets client: %w", err)
|
||||
}
|
||||
}
|
||||
repo := &basePoolManager{
|
||||
ctx: ctx,
|
||||
consumerID: consumerID,
|
||||
entity: entity,
|
||||
ghcli: ghc,
|
||||
scaleSetClient: scaleSetCli,
|
||||
controllerInfo: controllerInfo,
|
||||
instanceTokenGetter: instanceTokenGetter,
|
||||
|
||||
|
|
@ -122,6 +136,7 @@ type basePoolManager struct {
|
|||
consumerID string
|
||||
entity params.ForgeEntity
|
||||
ghcli common.GithubClient
|
||||
scaleSetClient *scalesets.ScaleSetClient
|
||||
controllerInfo params.ControllerInfo
|
||||
instanceTokenGetter auth.InstanceTokenGetter
|
||||
consumer dbCommon.Consumer
|
||||
|
|
@ -153,7 +168,7 @@ func (r *basePoolManager) getProviderBaseParams(pool params.Pool) common.Provide
|
|||
func (r *basePoolManager) HandleWorkflowJob(job params.WorkflowJob) error {
|
||||
if err := r.ValidateOwner(job); err != nil {
|
||||
slog.ErrorContext(r.ctx, "failed to validate owner", "error", err)
|
||||
return errors.Wrap(err, "validating owner")
|
||||
return fmt.Errorf("error validating owner: %w", err)
|
||||
}
|
||||
|
||||
// we see events where the lables seem to be missing. We should ignore these
|
||||
|
|
@ -166,24 +181,24 @@ func (r *basePoolManager) HandleWorkflowJob(job params.WorkflowJob) error {
|
|||
jobParams, err := r.paramsWorkflowJobToParamsJob(job)
|
||||
if err != nil {
|
||||
slog.ErrorContext(r.ctx, "failed to convert job to params", "error", err)
|
||||
return errors.Wrap(err, "converting job to params")
|
||||
return fmt.Errorf("error converting job to params: %w", err)
|
||||
}
|
||||
|
||||
var triggeredBy int64
|
||||
defer func() {
|
||||
if jobParams.ID == 0 {
|
||||
if jobParams.WorkflowJobID == 0 {
|
||||
return
|
||||
}
|
||||
// we're updating the job in the database, regardless of whether it was successful or not.
|
||||
// or if it was meant for this pool or not. Github will send the same job data to all hierarchies
|
||||
// that have been configured to work with garm. Updating the job at all levels should yield the same
|
||||
// outcome in the db.
|
||||
_, err := r.store.GetJobByID(r.ctx, jobParams.ID)
|
||||
_, err := r.store.GetJobByID(r.ctx, jobParams.WorkflowJobID)
|
||||
if err != nil {
|
||||
if !errors.Is(err, runnerErrors.ErrNotFound) {
|
||||
slog.With(slog.Any("error", err)).ErrorContext(
|
||||
r.ctx, "failed to get job",
|
||||
"job_id", jobParams.ID)
|
||||
"job_id", jobParams.WorkflowJobID)
|
||||
return
|
||||
}
|
||||
// This job is new to us. Check if we have a pool that can handle it.
|
||||
|
|
@ -198,10 +213,10 @@ func (r *basePoolManager) HandleWorkflowJob(job params.WorkflowJob) error {
|
|||
|
||||
if _, jobErr := r.store.CreateOrUpdateJob(r.ctx, jobParams); jobErr != nil {
|
||||
slog.With(slog.Any("error", jobErr)).ErrorContext(
|
||||
r.ctx, "failed to update job", "job_id", jobParams.ID)
|
||||
r.ctx, "failed to update job", "job_id", jobParams.WorkflowJobID)
|
||||
}
|
||||
|
||||
if triggeredBy != 0 && jobParams.ID != triggeredBy {
|
||||
if triggeredBy != 0 && jobParams.WorkflowJobID != triggeredBy {
|
||||
// The triggeredBy value is only set by the "in_progress" webhook. The runner that
|
||||
// transitioned to in_progress was created as a result of a different queued job. If that job is
|
||||
// still queued and we don't remove the lock, it will linger until the lock timeout is reached.
|
||||
|
|
@ -244,7 +259,7 @@ func (r *basePoolManager) HandleWorkflowJob(job params.WorkflowJob) error {
|
|||
slog.With(slog.Any("error", err)).ErrorContext(
|
||||
r.ctx, "failed to update runner status",
|
||||
"runner_name", util.SanitizeLogEntry(jobParams.RunnerName))
|
||||
return errors.Wrap(err, "updating runner")
|
||||
return fmt.Errorf("error updating runner: %w", err)
|
||||
}
|
||||
slog.DebugContext(
|
||||
r.ctx, "marking instance as pending_delete",
|
||||
|
|
@ -256,7 +271,7 @@ func (r *basePoolManager) HandleWorkflowJob(job params.WorkflowJob) error {
|
|||
slog.With(slog.Any("error", err)).ErrorContext(
|
||||
r.ctx, "failed to update runner status",
|
||||
"runner_name", util.SanitizeLogEntry(jobParams.RunnerName))
|
||||
return errors.Wrap(err, "updating runner")
|
||||
return fmt.Errorf("error updating runner: %w", err)
|
||||
}
|
||||
case "in_progress":
|
||||
fromCache, ok := cache.GetInstanceCache(jobParams.RunnerName)
|
||||
|
|
@ -279,7 +294,7 @@ func (r *basePoolManager) HandleWorkflowJob(job params.WorkflowJob) error {
|
|||
slog.With(slog.Any("error", err)).ErrorContext(
|
||||
r.ctx, "failed to update runner status",
|
||||
"runner_name", util.SanitizeLogEntry(jobParams.RunnerName))
|
||||
return errors.Wrap(err, "updating runner")
|
||||
return fmt.Errorf("error updating runner: %w", err)
|
||||
}
|
||||
// Set triggeredBy here so we break the lock on any potential queued job.
|
||||
triggeredBy = jobIDFromLabels(instance.AditionalLabels)
|
||||
|
|
@ -388,10 +403,10 @@ func (r *basePoolManager) updateTools() error {
|
|||
// happens, github will remove the ephemeral worker and send a webhook our way.
|
||||
// If we were offline and did not process the webhook, the instance will linger.
|
||||
// We need to remove it from the provider and database.
|
||||
func (r *basePoolManager) cleanupOrphanedProviderRunners(runners []*github.Runner) error {
|
||||
func (r *basePoolManager) cleanupOrphanedProviderRunners(runners []forgeRunner) error {
|
||||
dbInstances, err := r.store.ListEntityInstances(r.ctx, r.entity)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "fetching instances from db")
|
||||
return fmt.Errorf("error fetching instances from db: %w", err)
|
||||
}
|
||||
|
||||
runnerNames := map[string]bool{}
|
||||
|
|
@ -399,10 +414,10 @@ func (r *basePoolManager) cleanupOrphanedProviderRunners(runners []*github.Runne
|
|||
if !isManagedRunner(labelsFromRunner(run), r.controllerInfo.ControllerID.String()) {
|
||||
slog.DebugContext(
|
||||
r.ctx, "runner is not managed by a pool we manage",
|
||||
"runner_name", run.GetName())
|
||||
"runner_name", run.Name)
|
||||
continue
|
||||
}
|
||||
runnerNames[*run.Name] = true
|
||||
runnerNames[run.Name] = true
|
||||
}
|
||||
|
||||
for _, instance := range dbInstances {
|
||||
|
|
@ -430,7 +445,7 @@ func (r *basePoolManager) cleanupOrphanedProviderRunners(runners []*github.Runne
|
|||
}
|
||||
pool, err := r.store.GetEntityPool(r.ctx, r.entity, instance.PoolID)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "fetching instance pool info")
|
||||
return fmt.Errorf("error fetching instance pool info: %w", err)
|
||||
}
|
||||
|
||||
switch instance.RunnerStatus {
|
||||
|
|
@ -458,7 +473,7 @@ func (r *basePoolManager) cleanupOrphanedProviderRunners(runners []*github.Runne
|
|||
slog.With(slog.Any("error", err)).ErrorContext(
|
||||
r.ctx, "failed to update runner",
|
||||
"runner_name", instance.Name)
|
||||
return errors.Wrap(err, "updating runner")
|
||||
return fmt.Errorf("error updating runner: %w", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -468,21 +483,21 @@ func (r *basePoolManager) cleanupOrphanedProviderRunners(runners []*github.Runne
|
|||
// reapTimedOutRunners will mark as pending_delete any runner that has a status
|
||||
// of "running" in the provider, but that has not registered with Github, and has
|
||||
// received no new updates in the configured timeout interval.
|
||||
func (r *basePoolManager) reapTimedOutRunners(runners []*github.Runner) error {
|
||||
func (r *basePoolManager) reapTimedOutRunners(runners []forgeRunner) error {
|
||||
dbInstances, err := r.store.ListEntityInstances(r.ctx, r.entity)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "fetching instances from db")
|
||||
return fmt.Errorf("error fetching instances from db: %w", err)
|
||||
}
|
||||
|
||||
runnersByName := map[string]*github.Runner{}
|
||||
runnersByName := map[string]forgeRunner{}
|
||||
for _, run := range runners {
|
||||
if !isManagedRunner(labelsFromRunner(run), r.controllerInfo.ControllerID.String()) {
|
||||
slog.DebugContext(
|
||||
r.ctx, "runner is not managed by a pool we manage",
|
||||
"runner_name", run.GetName())
|
||||
"runner_name", run.Name)
|
||||
continue
|
||||
}
|
||||
runnersByName[*run.Name] = run
|
||||
runnersByName[run.Name] = run
|
||||
}
|
||||
|
||||
for _, instance := range dbInstances {
|
||||
|
|
@ -505,7 +520,7 @@ func (r *basePoolManager) reapTimedOutRunners(runners []*github.Runner) error {
|
|||
|
||||
pool, err := r.store.GetEntityPool(r.ctx, r.entity, instance.PoolID)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "fetching instance pool info")
|
||||
return fmt.Errorf("error fetching instance pool info: %w", err)
|
||||
}
|
||||
if time.Since(instance.UpdatedAt).Minutes() < float64(pool.RunnerTimeout()) {
|
||||
continue
|
||||
|
|
@ -516,7 +531,7 @@ func (r *basePoolManager) reapTimedOutRunners(runners []*github.Runner) error {
|
|||
// * The runner managed to join github, but the setup process failed later and the runner
|
||||
// never started on the instance.
|
||||
// * A JIT config was created, but the runner never joined github.
|
||||
if runner, ok := runnersByName[instance.Name]; !ok || runner.GetStatus() == "offline" {
|
||||
if runner, ok := runnersByName[instance.Name]; !ok || runner.Status == "offline" {
|
||||
slog.InfoContext(
|
||||
r.ctx, "reaping timed-out/failed runner",
|
||||
"runner_name", instance.Name)
|
||||
|
|
@ -524,7 +539,7 @@ func (r *basePoolManager) reapTimedOutRunners(runners []*github.Runner) error {
|
|||
slog.With(slog.Any("error", err)).ErrorContext(
|
||||
r.ctx, "failed to update runner status",
|
||||
"runner_name", instance.Name)
|
||||
return errors.Wrap(err, "updating runner")
|
||||
return fmt.Errorf("error updating runner: %w", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -535,39 +550,39 @@ func (r *basePoolManager) reapTimedOutRunners(runners []*github.Runner) error {
|
|||
// as offline and for which we no longer have a local instance.
|
||||
// This may happen if someone manually deletes the instance in the provider. We need to
|
||||
// first remove the instance from github, and then from our database.
|
||||
func (r *basePoolManager) cleanupOrphanedGithubRunners(runners []*github.Runner) error {
|
||||
func (r *basePoolManager) cleanupOrphanedGithubRunners(runners []forgeRunner) error {
|
||||
poolInstanceCache := map[string][]commonParams.ProviderInstance{}
|
||||
g, ctx := errgroup.WithContext(r.ctx)
|
||||
for _, runner := range runners {
|
||||
if !isManagedRunner(labelsFromRunner(runner), r.controllerInfo.ControllerID.String()) {
|
||||
slog.DebugContext(
|
||||
r.ctx, "runner is not managed by a pool we manage",
|
||||
"runner_name", runner.GetName())
|
||||
"runner_name", runner.Name)
|
||||
continue
|
||||
}
|
||||
|
||||
status := runner.GetStatus()
|
||||
status := runner.Status
|
||||
if status != "offline" {
|
||||
// Runner is online. Ignore it.
|
||||
continue
|
||||
}
|
||||
|
||||
dbInstance, err := r.store.GetInstanceByName(r.ctx, *runner.Name)
|
||||
dbInstance, err := r.store.GetInstance(r.ctx, runner.Name)
|
||||
if err != nil {
|
||||
if !errors.Is(err, runnerErrors.ErrNotFound) {
|
||||
return errors.Wrap(err, "fetching instance from DB")
|
||||
return fmt.Errorf("error fetching instance from DB: %w", err)
|
||||
}
|
||||
// We no longer have a DB entry for this instance, and the runner appears offline in github.
|
||||
// Previous forceful removal may have failed?
|
||||
slog.InfoContext(
|
||||
r.ctx, "Runner has no database entry in garm, removing from github",
|
||||
"runner_name", runner.GetName())
|
||||
if err := r.ghcli.RemoveEntityRunner(r.ctx, runner.GetID()); err != nil {
|
||||
"runner_name", runner.Name)
|
||||
if err := r.ghcli.RemoveEntityRunner(r.ctx, runner.ID); err != nil {
|
||||
// Removed in the meantime?
|
||||
if errors.Is(err, runnerErrors.ErrNotFound) {
|
||||
continue
|
||||
}
|
||||
return errors.Wrap(err, "removing runner")
|
||||
return fmt.Errorf("error removing runner: %w", err)
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
|
@ -601,7 +616,7 @@ func (r *basePoolManager) cleanupOrphanedGithubRunners(runners []*github.Runner)
|
|||
|
||||
pool, err := r.store.GetEntityPool(r.ctx, r.entity, dbInstance.PoolID)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "fetching pool")
|
||||
return fmt.Errorf("error fetching pool: %w", err)
|
||||
}
|
||||
|
||||
// check if the provider still has the instance.
|
||||
|
|
@ -623,7 +638,7 @@ func (r *basePoolManager) cleanupOrphanedGithubRunners(runners []*github.Runner)
|
|||
}
|
||||
poolInstances, err = provider.ListInstances(r.ctx, pool.ID, listInstancesParams)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "fetching instances for pool %s", dbInstance.PoolID)
|
||||
return fmt.Errorf("error fetching instances for pool %s: %w", dbInstance.PoolID, err)
|
||||
}
|
||||
poolInstanceCache[dbInstance.PoolID] = poolInstances
|
||||
}
|
||||
|
|
@ -650,14 +665,14 @@ func (r *basePoolManager) cleanupOrphanedGithubRunners(runners []*github.Runner)
|
|||
slog.InfoContext(
|
||||
r.ctx, "Runner instance is no longer on the provider, removing from github",
|
||||
"runner_name", dbInstance.Name)
|
||||
if err := r.ghcli.RemoveEntityRunner(r.ctx, runner.GetID()); err != nil {
|
||||
if err := r.ghcli.RemoveEntityRunner(r.ctx, runner.ID); err != nil {
|
||||
// Removed in the meantime?
|
||||
if errors.Is(err, runnerErrors.ErrNotFound) {
|
||||
slog.DebugContext(
|
||||
r.ctx, "runner disappeared from github",
|
||||
"runner_name", dbInstance.Name)
|
||||
} else {
|
||||
return errors.Wrap(err, "removing runner from github")
|
||||
return fmt.Errorf("error removing runner from github: %w", err)
|
||||
}
|
||||
}
|
||||
// Remove the database entry for the runner.
|
||||
|
|
@ -665,7 +680,7 @@ func (r *basePoolManager) cleanupOrphanedGithubRunners(runners []*github.Runner)
|
|||
r.ctx, "Removing from database",
|
||||
"runner_name", dbInstance.Name)
|
||||
if err := r.store.DeleteInstance(ctx, dbInstance.PoolID, dbInstance.Name); err != nil {
|
||||
return errors.Wrap(err, "removing runner from database")
|
||||
return fmt.Errorf("error removing runner from database: %w", err)
|
||||
}
|
||||
deleteMux = true
|
||||
return nil
|
||||
|
|
@ -691,13 +706,13 @@ func (r *basePoolManager) cleanupOrphanedGithubRunners(runners []*github.Runner)
|
|||
},
|
||||
}
|
||||
if err := provider.Start(r.ctx, dbInstance.ProviderID, startParams); err != nil {
|
||||
return errors.Wrapf(err, "starting instance %s", dbInstance.ProviderID)
|
||||
return fmt.Errorf("error starting instance %s: %w", dbInstance.ProviderID, err)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
if err := r.waitForErrorGroupOrContextCancelled(g); err != nil {
|
||||
return errors.Wrap(err, "removing orphaned github runners")
|
||||
return fmt.Errorf("error removing orphaned github runners: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
@ -727,7 +742,7 @@ func (r *basePoolManager) setInstanceRunnerStatus(runnerName string, status para
|
|||
}
|
||||
instance, err := r.store.UpdateInstance(r.ctx, runnerName, updateParams)
|
||||
if err != nil {
|
||||
return params.Instance{}, errors.Wrap(err, "updating runner state")
|
||||
return params.Instance{}, fmt.Errorf("error updating runner state: %w", err)
|
||||
}
|
||||
return instance, nil
|
||||
}
|
||||
|
|
@ -740,7 +755,7 @@ func (r *basePoolManager) setInstanceStatus(runnerName string, status commonPara
|
|||
|
||||
instance, err := r.store.UpdateInstance(r.ctx, runnerName, updateParams)
|
||||
if err != nil {
|
||||
return params.Instance{}, errors.Wrap(err, "updating runner state")
|
||||
return params.Instance{}, fmt.Errorf("error updating runner state: %w", err)
|
||||
}
|
||||
return instance, nil
|
||||
}
|
||||
|
|
@ -748,7 +763,7 @@ func (r *basePoolManager) setInstanceStatus(runnerName string, status commonPara
|
|||
func (r *basePoolManager) AddRunner(ctx context.Context, poolID string, aditionalLabels []string) (err error) {
|
||||
pool, err := r.store.GetEntityPool(r.ctx, r.entity, poolID)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "fetching pool")
|
||||
return fmt.Errorf("error fetching pool: %w", err)
|
||||
}
|
||||
|
||||
provider, ok := r.providers[pool.ProviderName]
|
||||
|
|
@ -762,12 +777,10 @@ func (r *basePoolManager) AddRunner(ctx context.Context, poolID string, aditiona
|
|||
jitConfig := make(map[string]string)
|
||||
var runner *github.Runner
|
||||
|
||||
if !provider.DisableJITConfig() {
|
||||
// Attempt to create JIT config
|
||||
if !provider.DisableJITConfig() && r.entity.Credentials.ForgeType != params.GiteaEndpointType {
|
||||
jitConfig, runner, err = r.ghcli.GetEntityJITConfig(ctx, name, pool, labels)
|
||||
if err != nil {
|
||||
slog.With(slog.Any("error", err)).ErrorContext(
|
||||
ctx, "failed to get JIT config, falling back to registration token")
|
||||
return fmt.Errorf("failed to generate JIT config: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -791,7 +804,7 @@ func (r *basePoolManager) AddRunner(ctx context.Context, poolID string, aditiona
|
|||
|
||||
instance, err := r.store.CreateInstance(r.ctx, poolID, createParams)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "creating instance")
|
||||
return fmt.Errorf("error creating instance: %w", err)
|
||||
}
|
||||
|
||||
defer func() {
|
||||
|
|
@ -859,7 +872,7 @@ func (r *basePoolManager) getLabelsForInstance(pool params.Pool) []string {
|
|||
func (r *basePoolManager) addInstanceToProvider(instance params.Instance) error {
|
||||
pool, err := r.store.GetEntityPool(r.ctx, r.entity, instance.PoolID)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "fetching pool")
|
||||
return fmt.Errorf("error fetching pool: %w", err)
|
||||
}
|
||||
|
||||
provider, ok := r.providers[pool.ProviderName]
|
||||
|
|
@ -871,7 +884,7 @@ func (r *basePoolManager) addInstanceToProvider(instance params.Instance) error
|
|||
|
||||
jwtToken, err := r.instanceTokenGetter.NewInstanceJWTToken(instance, r.entity, pool.PoolType(), jwtValidity)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "fetching instance jwt token")
|
||||
return fmt.Errorf("error fetching instance jwt token: %w", err)
|
||||
}
|
||||
|
||||
hasJITConfig := len(instance.JitConfiguration) > 0
|
||||
|
|
@ -928,7 +941,7 @@ func (r *basePoolManager) addInstanceToProvider(instance params.Instance) error
|
|||
providerInstance, err := provider.CreateInstance(r.ctx, bootstrapArgs, createInstanceParams)
|
||||
if err != nil {
|
||||
instanceIDToDelete = instance.Name
|
||||
return errors.Wrap(err, "creating instance")
|
||||
return fmt.Errorf("error creating instance: %w", err)
|
||||
}
|
||||
|
||||
if providerInstance.Status == commonParams.InstanceError {
|
||||
|
|
@ -940,7 +953,7 @@ func (r *basePoolManager) addInstanceToProvider(instance params.Instance) error
|
|||
|
||||
updateInstanceArgs := r.updateArgsFromProviderInstance(providerInstance)
|
||||
if _, err := r.store.UpdateInstance(r.ctx, instance.Name, updateInstanceArgs); err != nil {
|
||||
return errors.Wrap(err, "updating instance")
|
||||
return fmt.Errorf("error updating instance: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
@ -961,11 +974,11 @@ func (r *basePoolManager) addInstanceToProvider(instance params.Instance) error
|
|||
func (r *basePoolManager) paramsWorkflowJobToParamsJob(job params.WorkflowJob) (params.Job, error) {
|
||||
asUUID, err := uuid.Parse(r.ID())
|
||||
if err != nil {
|
||||
return params.Job{}, errors.Wrap(err, "parsing pool ID as UUID")
|
||||
return params.Job{}, fmt.Errorf("error parsing pool ID as UUID: %w", err)
|
||||
}
|
||||
|
||||
jobParams := params.Job{
|
||||
ID: job.WorkflowJob.ID,
|
||||
WorkflowJobID: job.WorkflowJob.ID,
|
||||
Action: job.Action,
|
||||
RunID: job.WorkflowJob.RunID,
|
||||
Status: job.WorkflowJob.Status,
|
||||
|
|
@ -990,7 +1003,7 @@ func (r *basePoolManager) paramsWorkflowJobToParamsJob(job params.WorkflowJob) (
|
|||
case params.ForgeEntityTypeOrganization:
|
||||
jobParams.OrgID = &asUUID
|
||||
default:
|
||||
return jobParams, errors.Errorf("unknown pool type: %s", r.entity.EntityType)
|
||||
return jobParams, fmt.Errorf("unknown pool type: %s", r.entity.EntityType)
|
||||
}
|
||||
|
||||
return jobParams, nil
|
||||
|
|
@ -1096,15 +1109,15 @@ func (r *basePoolManager) scaleDownOnePool(ctx context.Context, pool params.Pool
|
|||
// instead of returning a bunch of results and filtering manually.
|
||||
queued, err := r.store.ListEntityJobsByStatus(r.ctx, r.entity.EntityType, r.entity.ID, params.JobStatusQueued)
|
||||
if err != nil && !errors.Is(err, runnerErrors.ErrNotFound) {
|
||||
return errors.Wrap(err, "listing queued jobs")
|
||||
return fmt.Errorf("error listing queued jobs: %w", err)
|
||||
}
|
||||
|
||||
for _, job := range queued {
|
||||
if time.Since(job.CreatedAt).Minutes() > 10 && pool.HasRequiredLabels(job.Labels) {
|
||||
if err := r.store.DeleteJob(ctx, job.ID); err != nil && !errors.Is(err, runnerErrors.ErrNotFound) {
|
||||
if err := r.store.DeleteJob(ctx, job.WorkflowJobID); err != nil && !errors.Is(err, runnerErrors.ErrNotFound) {
|
||||
slog.With(slog.Any("error", err)).ErrorContext(
|
||||
ctx, "failed to delete job",
|
||||
"job_id", job.ID)
|
||||
"job_id", job.WorkflowJobID)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1336,7 +1349,7 @@ func (r *basePoolManager) ensureMinIdleRunners() error {
|
|||
func (r *basePoolManager) deleteInstanceFromProvider(ctx context.Context, instance params.Instance) error {
|
||||
pool, err := r.store.GetEntityPool(r.ctx, r.entity, instance.PoolID)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "fetching pool")
|
||||
return fmt.Errorf("error fetching pool: %w", err)
|
||||
}
|
||||
|
||||
provider, ok := r.providers[instance.ProviderName]
|
||||
|
|
@ -1362,13 +1375,16 @@ func (r *basePoolManager) deleteInstanceFromProvider(ctx context.Context, instan
|
|||
},
|
||||
}
|
||||
if err := provider.DeleteInstance(ctx, identifier, deleteInstanceParams); err != nil {
|
||||
return errors.Wrap(err, "removing instance")
|
||||
return fmt.Errorf("error removing instance: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *basePoolManager) sleepWithCancel(sleepTime time.Duration) (canceled bool) {
|
||||
if sleepTime == 0 {
|
||||
return false
|
||||
}
|
||||
ticker := time.NewTicker(sleepTime)
|
||||
defer ticker.Stop()
|
||||
|
||||
|
|
@ -1575,7 +1591,7 @@ func (r *basePoolManager) Wait() error {
|
|||
select {
|
||||
case <-done:
|
||||
case <-timer.C:
|
||||
return errors.Wrap(runnerErrors.ErrTimeout, "waiting for pool to stop")
|
||||
return runnerErrors.NewTimeoutError("waiting for pool to stop")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
@ -1599,13 +1615,13 @@ func (r *basePoolManager) runnerCleanup() (err error) {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (r *basePoolManager) cleanupOrphanedRunners(runners []*github.Runner) error {
|
||||
func (r *basePoolManager) cleanupOrphanedRunners(runners []forgeRunner) error {
|
||||
if err := r.cleanupOrphanedProviderRunners(runners); err != nil {
|
||||
return errors.Wrap(err, "cleaning orphaned instances")
|
||||
return fmt.Errorf("error cleaning orphaned instances: %w", err)
|
||||
}
|
||||
|
||||
if err := r.cleanupOrphanedGithubRunners(runners); err != nil {
|
||||
return errors.Wrap(err, "cleaning orphaned github runners")
|
||||
return fmt.Errorf("error cleaning orphaned github runners: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
|
@ -1685,10 +1701,10 @@ func (r *basePoolManager) DeleteRunner(runner params.Instance, forceRemove, bypa
|
|||
if bypassGHUnauthorizedError {
|
||||
slog.Info("bypass github unauthorized error is set, marking runner for deletion")
|
||||
} else {
|
||||
return errors.Wrap(err, "removing runner")
|
||||
return fmt.Errorf("error removing runner: %w", err)
|
||||
}
|
||||
} else {
|
||||
return errors.Wrap(err, "removing runner")
|
||||
return fmt.Errorf("error removing runner: %w", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1706,7 +1722,7 @@ func (r *basePoolManager) DeleteRunner(runner params.Instance, forceRemove, bypa
|
|||
slog.With(slog.Any("error", err)).ErrorContext(
|
||||
r.ctx, "failed to update runner",
|
||||
"runner_name", runner.Name)
|
||||
return errors.Wrap(err, "updating runner")
|
||||
return fmt.Errorf("error updating runner: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
@ -1737,7 +1753,7 @@ func (r *basePoolManager) DeleteRunner(runner params.Instance, forceRemove, bypa
|
|||
func (r *basePoolManager) consumeQueuedJobs() error {
|
||||
queued, err := r.store.ListEntityJobsByStatus(r.ctx, r.entity.EntityType, r.entity.ID, params.JobStatusQueued)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "listing queued jobs")
|
||||
return fmt.Errorf("error listing queued jobs: %w", err)
|
||||
}
|
||||
|
||||
poolsCache := poolsForTags{
|
||||
|
|
@ -1752,7 +1768,7 @@ func (r *basePoolManager) consumeQueuedJobs() error {
|
|||
// Job was handled by us or another entity.
|
||||
slog.DebugContext(
|
||||
r.ctx, "job is locked",
|
||||
"job_id", job.ID,
|
||||
"job_id", job.WorkflowJobID,
|
||||
"locking_entity", job.LockedBy.String())
|
||||
continue
|
||||
}
|
||||
|
|
@ -1761,7 +1777,7 @@ func (r *basePoolManager) consumeQueuedJobs() error {
|
|||
// give the idle runners a chance to pick up the job.
|
||||
slog.DebugContext(
|
||||
r.ctx, "job backoff not reached", "backoff_interval", r.controllerInfo.MinimumJobAgeBackoff,
|
||||
"job_id", job.ID)
|
||||
"job_id", job.WorkflowJobID)
|
||||
continue
|
||||
}
|
||||
|
||||
|
|
@ -1769,12 +1785,12 @@ func (r *basePoolManager) consumeQueuedJobs() error {
|
|||
// Job is still queued in our db, 10 minutes after a matching runner
|
||||
// was spawned. Unlock it and try again. A different job may have picked up
|
||||
// the runner.
|
||||
if err := r.store.UnlockJob(r.ctx, job.ID, r.ID()); err != nil {
|
||||
if err := r.store.UnlockJob(r.ctx, job.WorkflowJobID, r.ID()); err != nil {
|
||||
// nolint:golangci-lint,godox
|
||||
// TODO: Implament a cache? Should we return here?
|
||||
slog.With(slog.Any("error", err)).ErrorContext(
|
||||
r.ctx, "failed to unlock job",
|
||||
"job_id", job.ID)
|
||||
"job_id", job.WorkflowJobID)
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
|
@ -1787,7 +1803,7 @@ func (r *basePoolManager) consumeQueuedJobs() error {
|
|||
// runner.
|
||||
slog.DebugContext(
|
||||
r.ctx, "job is locked by us",
|
||||
"job_id", job.ID)
|
||||
"job_id", job.WorkflowJobID)
|
||||
continue
|
||||
}
|
||||
|
||||
|
|
@ -1808,29 +1824,29 @@ func (r *basePoolManager) consumeQueuedJobs() error {
|
|||
}
|
||||
|
||||
runnerCreated := false
|
||||
if err := r.store.LockJob(r.ctx, job.ID, r.ID()); err != nil {
|
||||
if err := r.store.LockJob(r.ctx, job.WorkflowJobID, r.ID()); err != nil {
|
||||
slog.With(slog.Any("error", err)).ErrorContext(
|
||||
r.ctx, "could not lock job",
|
||||
"job_id", job.ID)
|
||||
"job_id", job.WorkflowJobID)
|
||||
continue
|
||||
}
|
||||
|
||||
jobLabels := []string{
|
||||
fmt.Sprintf("%s=%d", jobLabelPrefix, job.ID),
|
||||
fmt.Sprintf("%s=%d", jobLabelPrefix, job.WorkflowJobID),
|
||||
}
|
||||
for i := 0; i < poolRR.Len(); i++ {
|
||||
pool, err := poolRR.Next()
|
||||
if err != nil {
|
||||
slog.With(slog.Any("error", err)).ErrorContext(
|
||||
r.ctx, "could not find a pool to create a runner for job",
|
||||
"job_id", job.ID)
|
||||
"job_id", job.WorkflowJobID)
|
||||
break
|
||||
}
|
||||
|
||||
slog.InfoContext(
|
||||
r.ctx, "attempting to create a runner in pool",
|
||||
"pool_id", pool.ID,
|
||||
"job_id", job.ID)
|
||||
"job_id", job.WorkflowJobID)
|
||||
if err := r.addRunnerToPool(pool, jobLabels); err != nil {
|
||||
slog.With(slog.Any("error", err)).ErrorContext(
|
||||
r.ctx, "could not add runner to pool",
|
||||
|
|
@ -1839,7 +1855,7 @@ func (r *basePoolManager) consumeQueuedJobs() error {
|
|||
}
|
||||
slog.DebugContext(r.ctx, "a new runner was added as a response to queued job",
|
||||
"pool_id", pool.ID,
|
||||
"job_id", job.ID)
|
||||
"job_id", job.WorkflowJobID)
|
||||
runnerCreated = true
|
||||
break
|
||||
}
|
||||
|
|
@ -1847,12 +1863,12 @@ func (r *basePoolManager) consumeQueuedJobs() error {
|
|||
if !runnerCreated {
|
||||
slog.WarnContext(
|
||||
r.ctx, "could not create a runner for job; unlocking",
|
||||
"job_id", job.ID)
|
||||
if err := r.store.UnlockJob(r.ctx, job.ID, r.ID()); err != nil {
|
||||
"job_id", job.WorkflowJobID)
|
||||
if err := r.store.UnlockJob(r.ctx, job.WorkflowJobID, r.ID()); err != nil {
|
||||
slog.With(slog.Any("error", err)).ErrorContext(
|
||||
r.ctx, "failed to unlock job",
|
||||
"job_id", job.ID)
|
||||
return errors.Wrap(err, "unlocking job")
|
||||
"job_id", job.WorkflowJobID)
|
||||
return fmt.Errorf("error unlocking job: %w", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1866,12 +1882,12 @@ func (r *basePoolManager) consumeQueuedJobs() error {
|
|||
|
||||
func (r *basePoolManager) UninstallWebhook(ctx context.Context) error {
|
||||
if r.controllerInfo.ControllerWebhookURL == "" {
|
||||
return errors.Wrap(runnerErrors.ErrBadRequest, "controller webhook url is empty")
|
||||
return runnerErrors.NewBadRequestError("controller webhook url is empty")
|
||||
}
|
||||
|
||||
allHooks, err := r.listHooks(ctx)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "listing hooks")
|
||||
return fmt.Errorf("error listing hooks: %w", err)
|
||||
}
|
||||
|
||||
var controllerHookID int64
|
||||
|
|
@ -1909,16 +1925,16 @@ func (r *basePoolManager) UninstallWebhook(ctx context.Context) error {
|
|||
func (r *basePoolManager) InstallHook(ctx context.Context, req *github.Hook) (params.HookInfo, error) {
|
||||
allHooks, err := r.listHooks(ctx)
|
||||
if err != nil {
|
||||
return params.HookInfo{}, errors.Wrap(err, "listing hooks")
|
||||
return params.HookInfo{}, fmt.Errorf("error listing hooks: %w", err)
|
||||
}
|
||||
|
||||
if err := validateHookRequest(r.controllerInfo.ControllerID.String(), r.controllerInfo.WebhookURL, allHooks, req); err != nil {
|
||||
return params.HookInfo{}, errors.Wrap(err, "validating hook request")
|
||||
return params.HookInfo{}, fmt.Errorf("error validating hook request: %w", err)
|
||||
}
|
||||
|
||||
hook, err := r.ghcli.CreateEntityHook(ctx, req)
|
||||
if err != nil {
|
||||
return params.HookInfo{}, errors.Wrap(err, "creating entity hook")
|
||||
return params.HookInfo{}, fmt.Errorf("error creating entity hook: %w", err)
|
||||
}
|
||||
|
||||
if _, err := r.ghcli.PingEntityHook(ctx, hook.GetID()); err != nil {
|
||||
|
|
@ -1933,7 +1949,7 @@ func (r *basePoolManager) InstallHook(ctx context.Context, req *github.Hook) (pa
|
|||
|
||||
func (r *basePoolManager) InstallWebhook(ctx context.Context, param params.InstallWebhookParams) (params.HookInfo, error) {
|
||||
if r.controllerInfo.ControllerWebhookURL == "" {
|
||||
return params.HookInfo{}, errors.Wrap(runnerErrors.ErrBadRequest, "controller webhook url is empty")
|
||||
return params.HookInfo{}, runnerErrors.NewBadRequestError("controller webhook url is empty")
|
||||
}
|
||||
|
||||
insecureSSL := "0"
|
||||
|
|
@ -1981,9 +1997,9 @@ func (r *basePoolManager) GithubRunnerRegistrationToken() (string, error) {
|
|||
tk, ghResp, err := r.ghcli.CreateEntityRegistrationToken(r.ctx)
|
||||
if err != nil {
|
||||
if ghResp != nil && ghResp.StatusCode == http.StatusUnauthorized {
|
||||
return "", errors.Wrap(runnerErrors.ErrUnauthorized, "fetching token")
|
||||
return "", runnerErrors.NewUnauthorizedError("error fetching token")
|
||||
}
|
||||
return "", errors.Wrap(err, "creating runner token")
|
||||
return "", fmt.Errorf("error creating runner token: %w", err)
|
||||
}
|
||||
return *tk.Token, nil
|
||||
}
|
||||
|
|
@ -1992,9 +2008,9 @@ func (r *basePoolManager) FetchTools() ([]commonParams.RunnerApplicationDownload
|
|||
tools, ghResp, err := r.ghcli.ListEntityRunnerApplicationDownloads(r.ctx)
|
||||
if err != nil {
|
||||
if ghResp != nil && ghResp.StatusCode == http.StatusUnauthorized {
|
||||
return nil, errors.Wrap(runnerErrors.ErrUnauthorized, "fetching tools")
|
||||
return nil, runnerErrors.NewUnauthorizedError("error fetching tools")
|
||||
}
|
||||
return nil, errors.Wrap(err, "fetching runner tools")
|
||||
return nil, fmt.Errorf("error fetching runner tools: %w", err)
|
||||
}
|
||||
|
||||
ret := []commonParams.RunnerApplicationDownload{}
|
||||
|
|
@ -2007,36 +2023,10 @@ func (r *basePoolManager) FetchTools() ([]commonParams.RunnerApplicationDownload
|
|||
return ret, nil
|
||||
}
|
||||
|
||||
func (r *basePoolManager) GetGithubRunners() ([]*github.Runner, error) {
|
||||
opts := github.ListRunnersOptions{
|
||||
ListOptions: github.ListOptions{
|
||||
PerPage: 100,
|
||||
},
|
||||
}
|
||||
var allRunners []*github.Runner
|
||||
|
||||
for {
|
||||
runners, ghResp, err := r.ghcli.ListEntityRunners(r.ctx, &opts)
|
||||
if err != nil {
|
||||
if ghResp != nil && ghResp.StatusCode == http.StatusUnauthorized {
|
||||
return nil, errors.Wrap(runnerErrors.ErrUnauthorized, "fetching runners")
|
||||
}
|
||||
return nil, errors.Wrap(err, "fetching runners")
|
||||
}
|
||||
allRunners = append(allRunners, runners.Runners...)
|
||||
if ghResp.NextPage == 0 {
|
||||
break
|
||||
}
|
||||
opts.Page = ghResp.NextPage
|
||||
}
|
||||
|
||||
return allRunners, nil
|
||||
}
|
||||
|
||||
func (r *basePoolManager) GetWebhookInfo(ctx context.Context) (params.HookInfo, error) {
|
||||
allHooks, err := r.listHooks(ctx)
|
||||
if err != nil {
|
||||
return params.HookInfo{}, errors.Wrap(err, "listing hooks")
|
||||
return params.HookInfo{}, fmt.Errorf("error listing hooks: %w", err)
|
||||
}
|
||||
trimmedBase := strings.TrimRight(r.controllerInfo.WebhookURL, "/")
|
||||
trimmedController := strings.TrimRight(r.controllerInfo.ControllerWebhookURL, "/")
|
||||
|
|
|
|||
|
|
@ -82,3 +82,7 @@ func (s *stubGithubClient) GithubBaseURL() *url.URL {
|
|||
func (s *stubGithubClient) RateLimit(_ context.Context) (*github.RateLimits, error) {
|
||||
return nil, s.err
|
||||
}
|
||||
|
||||
func (s *stubGithubClient) GetEntityRunnerGroupIDByName(_ context.Context, _ string) (int64, error) {
|
||||
return 0, s.err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,10 +15,12 @@
|
|||
package pool
|
||||
|
||||
import (
|
||||
"sort"
|
||||
"context"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/google/go-github/v72/github"
|
||||
|
|
@ -31,70 +33,6 @@ import (
|
|||
"github.com/cloudbase/garm/params"
|
||||
)
|
||||
|
||||
type poolCacheStore interface {
|
||||
Next() (params.Pool, error)
|
||||
Reset()
|
||||
Len() int
|
||||
}
|
||||
|
||||
type poolRoundRobin struct {
|
||||
pools []params.Pool
|
||||
next uint32
|
||||
}
|
||||
|
||||
func (p *poolRoundRobin) Next() (params.Pool, error) {
|
||||
if len(p.pools) == 0 {
|
||||
return params.Pool{}, runnerErrors.ErrNoPoolsAvailable
|
||||
}
|
||||
|
||||
n := atomic.AddUint32(&p.next, 1)
|
||||
return p.pools[(int(n)-1)%len(p.pools)], nil
|
||||
}
|
||||
|
||||
func (p *poolRoundRobin) Len() int {
|
||||
return len(p.pools)
|
||||
}
|
||||
|
||||
func (p *poolRoundRobin) Reset() {
|
||||
atomic.StoreUint32(&p.next, 0)
|
||||
}
|
||||
|
||||
type poolsForTags struct {
|
||||
pools sync.Map
|
||||
poolCacheType params.PoolBalancerType
|
||||
}
|
||||
|
||||
func (p *poolsForTags) Get(tags []string) (poolCacheStore, bool) {
|
||||
sort.Strings(tags)
|
||||
key := strings.Join(tags, "^")
|
||||
|
||||
v, ok := p.pools.Load(key)
|
||||
if !ok {
|
||||
return nil, false
|
||||
}
|
||||
poolCache := v.(*poolRoundRobin)
|
||||
if p.poolCacheType == params.PoolBalancerTypePack {
|
||||
// When we service a list of jobs, we want to try each pool in turn
|
||||
// for each job. Pools are sorted by priority so we always start from the
|
||||
// highest priority pool and move on to the next if the first one is full.
|
||||
poolCache.Reset()
|
||||
}
|
||||
return poolCache, true
|
||||
}
|
||||
|
||||
func (p *poolsForTags) Add(tags []string, pools []params.Pool) poolCacheStore {
|
||||
sort.Slice(pools, func(i, j int) bool {
|
||||
return pools[i].Priority > pools[j].Priority
|
||||
})
|
||||
|
||||
sort.Strings(tags)
|
||||
key := strings.Join(tags, "^")
|
||||
|
||||
poolRR := &poolRoundRobin{pools: pools}
|
||||
v, _ := p.pools.LoadOrStore(key, poolRR)
|
||||
return v.(*poolRoundRobin)
|
||||
}
|
||||
|
||||
func instanceInList(instanceName string, instances []commonParams.ProviderInstance) (commonParams.ProviderInstance, bool) {
|
||||
for _, val := range instances {
|
||||
if val.Name == instanceName {
|
||||
|
|
@ -114,17 +52,14 @@ func controllerIDFromLabels(labels []string) string {
|
|||
return ""
|
||||
}
|
||||
|
||||
func labelsFromRunner(runner *github.Runner) []string {
|
||||
if runner == nil || runner.Labels == nil {
|
||||
func labelsFromRunner(runner forgeRunner) []string {
|
||||
if runner.Labels == nil {
|
||||
return []string{}
|
||||
}
|
||||
|
||||
var labels []string
|
||||
for _, val := range runner.Labels {
|
||||
if val == nil {
|
||||
continue
|
||||
}
|
||||
labels = append(labels, val.GetName())
|
||||
labels = append(labels, val.Name)
|
||||
}
|
||||
return labels
|
||||
}
|
||||
|
|
@ -167,3 +102,172 @@ func (r *basePoolManager) waitForToolsOrCancel() (hasTools, stopped bool) {
|
|||
return false, true
|
||||
}
|
||||
}
|
||||
|
||||
func validateHookRequest(controllerID, baseURL string, allHooks []*github.Hook, req *github.Hook) error {
|
||||
parsed, err := url.Parse(baseURL)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error parsing webhook url: %w", err)
|
||||
}
|
||||
|
||||
partialMatches := []string{}
|
||||
for _, hook := range allHooks {
|
||||
hookURL := strings.ToLower(hook.Config.GetURL())
|
||||
if hookURL == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
if hook.Config.GetURL() == req.Config.GetURL() {
|
||||
return runnerErrors.NewConflictError("hook already installed")
|
||||
} else if strings.Contains(hookURL, controllerID) || strings.Contains(hookURL, parsed.Hostname()) {
|
||||
partialMatches = append(partialMatches, hook.Config.GetURL())
|
||||
}
|
||||
}
|
||||
|
||||
if len(partialMatches) > 0 {
|
||||
return runnerErrors.NewConflictError("a webhook containing the controller ID or hostname of this contreoller is already installed on this repository")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func hookToParamsHookInfo(hook *github.Hook) params.HookInfo {
|
||||
hookURL := hook.Config.GetURL()
|
||||
|
||||
insecureSSLConfig := hook.Config.GetInsecureSSL()
|
||||
insecureSSL := insecureSSLConfig == "1"
|
||||
|
||||
return params.HookInfo{
|
||||
ID: *hook.ID,
|
||||
URL: hookURL,
|
||||
Events: hook.Events,
|
||||
Active: *hook.Active,
|
||||
InsecureSSL: insecureSSL,
|
||||
}
|
||||
}
|
||||
|
||||
func (r *basePoolManager) listHooks(ctx context.Context) ([]*github.Hook, error) {
|
||||
opts := github.ListOptions{
|
||||
PerPage: 100,
|
||||
}
|
||||
var allHooks []*github.Hook
|
||||
for {
|
||||
hooks, ghResp, err := r.ghcli.ListEntityHooks(ctx, &opts)
|
||||
if err != nil {
|
||||
if ghResp != nil && ghResp.StatusCode == http.StatusNotFound {
|
||||
return nil, runnerErrors.NewBadRequestError("repository not found or your PAT does not have access to manage webhooks")
|
||||
}
|
||||
return nil, fmt.Errorf("error fetching hooks: %w", err)
|
||||
}
|
||||
allHooks = append(allHooks, hooks...)
|
||||
if ghResp.NextPage == 0 {
|
||||
break
|
||||
}
|
||||
opts.Page = ghResp.NextPage
|
||||
}
|
||||
return allHooks, nil
|
||||
}
|
||||
|
||||
func (r *basePoolManager) listRunnersWithPagination() ([]forgeRunner, error) {
|
||||
opts := github.ListRunnersOptions{
|
||||
ListOptions: github.ListOptions{
|
||||
PerPage: 100,
|
||||
},
|
||||
}
|
||||
var allRunners []*github.Runner
|
||||
|
||||
// Paginating like this can lead to a situation where if we have many pages of runners,
|
||||
// while we paginate, a particular runner can move from page n to page n-1 while we move
|
||||
// from page n-1 to page n. In situations such as that, we end up with a list of runners
|
||||
// that does not contain the runner that swapped pages while we were paginating.
|
||||
// Sadly, the GitHub API does not allow listing more than 100 runners per page.
|
||||
for {
|
||||
runners, ghResp, err := r.ghcli.ListEntityRunners(r.ctx, &opts)
|
||||
if err != nil {
|
||||
if ghResp != nil && ghResp.StatusCode == http.StatusUnauthorized {
|
||||
return nil, runnerErrors.NewUnauthorizedError("error fetching runners")
|
||||
}
|
||||
return nil, fmt.Errorf("error fetching runners: %w", err)
|
||||
}
|
||||
allRunners = append(allRunners, runners.Runners...)
|
||||
if ghResp.NextPage == 0 {
|
||||
break
|
||||
}
|
||||
opts.Page = ghResp.NextPage
|
||||
}
|
||||
|
||||
ret := make([]forgeRunner, len(allRunners))
|
||||
for idx, val := range allRunners {
|
||||
ret[idx] = forgeRunner{
|
||||
ID: val.GetID(),
|
||||
Name: val.GetName(),
|
||||
Status: val.GetStatus(),
|
||||
Labels: make([]RunnerLabels, len(val.Labels)),
|
||||
}
|
||||
for labelIdx, label := range val.Labels {
|
||||
ret[idx].Labels[labelIdx] = RunnerLabels{
|
||||
Name: label.GetName(),
|
||||
Type: label.GetType(),
|
||||
ID: label.GetID(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (r *basePoolManager) listRunnersWithScaleSetAPI() ([]forgeRunner, error) {
|
||||
if r.scaleSetClient == nil {
|
||||
return nil, fmt.Errorf("scaleset client not initialized")
|
||||
}
|
||||
|
||||
runners, err := r.scaleSetClient.ListAllRunners(r.ctx)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to list runners through scaleset API: %w", err)
|
||||
}
|
||||
|
||||
ret := []forgeRunner{}
|
||||
for _, runner := range runners.RunnerReferences {
|
||||
if runner.RunnerScaleSetID != 0 {
|
||||
// skip scale set runners.
|
||||
continue
|
||||
}
|
||||
run := forgeRunner{
|
||||
Name: runner.Name,
|
||||
ID: runner.ID,
|
||||
Status: string(runner.GetStatus()),
|
||||
Labels: make([]RunnerLabels, len(runner.Labels)),
|
||||
}
|
||||
for labelIDX, label := range runner.Labels {
|
||||
run.Labels[labelIDX] = RunnerLabels{
|
||||
Name: label.Name,
|
||||
Type: label.Type,
|
||||
}
|
||||
}
|
||||
ret = append(ret, run)
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (r *basePoolManager) GetGithubRunners() ([]forgeRunner, error) {
|
||||
// Gitea has no scale sets API
|
||||
if r.scaleSetClient == nil {
|
||||
return r.listRunnersWithPagination()
|
||||
}
|
||||
|
||||
// try the scale sets API for github
|
||||
runners, err := r.listRunnersWithScaleSetAPI()
|
||||
if err != nil {
|
||||
slog.WarnContext(r.ctx, "failed to list runners via scaleset API; falling back to pagination", "error", err)
|
||||
return r.listRunnersWithPagination()
|
||||
}
|
||||
|
||||
entityInstances := cache.GetEntityInstances(r.entity.ID)
|
||||
if len(entityInstances) > 0 && len(runners) == 0 {
|
||||
// I have trust issues in the undocumented API. We seem to have runners for this
|
||||
// entity, but the scaleset API returned nothing and no error. Fall back to pagination.
|
||||
slog.DebugContext(r.ctx, "the scaleset api returned nothing, but we seem to have runners in the db; falling back to paginated API runner list")
|
||||
return r.listRunnersWithPagination()
|
||||
}
|
||||
slog.DebugContext(r.ctx, "Scaleset API runner list succeeded", "runners", runners)
|
||||
return runners, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,8 +17,6 @@ package pool
|
|||
import (
|
||||
"log/slog"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
runnerErrors "github.com/cloudbase/garm-provider-common/errors"
|
||||
"github.com/cloudbase/garm/database/common"
|
||||
"github.com/cloudbase/garm/params"
|
||||
|
|
@ -46,7 +44,7 @@ func (r *basePoolManager) getClientOrStub() runnerCommon.GithubClient {
|
|||
if err != nil {
|
||||
slog.WarnContext(r.ctx, "failed to create github client", "error", err)
|
||||
ghc = &stubGithubClient{
|
||||
err: errors.Wrapf(runnerErrors.ErrUnauthorized, "failed to create github client; please update credentials: %v", err),
|
||||
err: runnerErrors.NewUnauthorizedError("failed to create github client; please update credentials"),
|
||||
}
|
||||
}
|
||||
return ghc
|
||||
|
|
|
|||
|
|
@ -16,8 +16,8 @@ package runner
|
|||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
runnerErrors "github.com/cloudbase/garm-provider-common/errors"
|
||||
"github.com/cloudbase/garm/auth"
|
||||
|
|
@ -31,7 +31,7 @@ func (r *Runner) ListAllPools(ctx context.Context) ([]params.Pool, error) {
|
|||
|
||||
pools, err := r.store.ListAllPools(ctx)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "fetching pools")
|
||||
return nil, fmt.Errorf("error fetching pools: %w", err)
|
||||
}
|
||||
return pools, nil
|
||||
}
|
||||
|
|
@ -43,7 +43,7 @@ func (r *Runner) GetPoolByID(ctx context.Context, poolID string) (params.Pool, e
|
|||
|
||||
pool, err := r.store.GetPoolByID(ctx, poolID)
|
||||
if err != nil {
|
||||
return params.Pool{}, errors.Wrap(err, "fetching pool")
|
||||
return params.Pool{}, fmt.Errorf("error fetching pool: %w", err)
|
||||
}
|
||||
return pool, nil
|
||||
}
|
||||
|
|
@ -56,7 +56,7 @@ func (r *Runner) DeletePoolByID(ctx context.Context, poolID string) error {
|
|||
pool, err := r.store.GetPoolByID(ctx, poolID)
|
||||
if err != nil {
|
||||
if !errors.Is(err, runnerErrors.ErrNotFound) {
|
||||
return errors.Wrap(err, "fetching pool")
|
||||
return fmt.Errorf("error fetching pool: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
@ -66,7 +66,7 @@ func (r *Runner) DeletePoolByID(ctx context.Context, poolID string) error {
|
|||
}
|
||||
|
||||
if err := r.store.DeletePoolByID(ctx, poolID); err != nil {
|
||||
return errors.Wrap(err, "deleting pool")
|
||||
return fmt.Errorf("error deleting pool: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
@ -78,7 +78,7 @@ func (r *Runner) UpdatePoolByID(ctx context.Context, poolID string, param params
|
|||
|
||||
pool, err := r.store.GetPoolByID(ctx, poolID)
|
||||
if err != nil {
|
||||
return params.Pool{}, errors.Wrap(err, "fetching pool")
|
||||
return params.Pool{}, fmt.Errorf("error fetching pool: %w", err)
|
||||
}
|
||||
|
||||
maxRunners := pool.MaxRunners
|
||||
|
|
@ -101,12 +101,12 @@ func (r *Runner) UpdatePoolByID(ctx context.Context, poolID string, param params
|
|||
|
||||
entity, err := pool.GetEntity()
|
||||
if err != nil {
|
||||
return params.Pool{}, errors.Wrap(err, "getting entity")
|
||||
return params.Pool{}, fmt.Errorf("error getting entity: %w", err)
|
||||
}
|
||||
|
||||
newPool, err := r.store.UpdateEntityPool(ctx, entity, poolID, param)
|
||||
if err != nil {
|
||||
return params.Pool{}, errors.Wrap(err, "updating pool")
|
||||
return params.Pool{}, fmt.Errorf("error updating pool: %w", err)
|
||||
}
|
||||
return newPool, nil
|
||||
}
|
||||
|
|
@ -118,7 +118,7 @@ func (r *Runner) ListAllJobs(ctx context.Context) ([]params.Job, error) {
|
|||
|
||||
jobs, err := r.store.ListAllJobs(ctx)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "fetching jobs")
|
||||
return nil, fmt.Errorf("error fetching jobs: %w", err)
|
||||
}
|
||||
return jobs, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -169,7 +169,7 @@ func (s *PoolTestSuite) TestGetPoolByIDNotFound() {
|
|||
s.Require().Nil(err)
|
||||
_, err = s.Runner.GetPoolByID(s.Fixtures.AdminContext, s.Fixtures.Pools[0].ID)
|
||||
s.Require().NotNil(err)
|
||||
s.Require().Equal("fetching pool: fetching pool by ID: not found", err.Error())
|
||||
s.Require().Equal("error fetching pool: error fetching pool by ID: not found", err.Error())
|
||||
}
|
||||
|
||||
func (s *PoolTestSuite) TestDeletePoolByID() {
|
||||
|
|
@ -178,7 +178,7 @@ func (s *PoolTestSuite) TestDeletePoolByID() {
|
|||
s.Require().Nil(err)
|
||||
_, err = s.Fixtures.Store.GetPoolByID(s.Fixtures.AdminContext, s.Fixtures.Pools[0].ID)
|
||||
s.Require().NotNil(err)
|
||||
s.Require().Equal("fetching pool by ID: not found", err.Error())
|
||||
s.Require().Equal("error fetching pool by ID: not found", err.Error())
|
||||
}
|
||||
|
||||
func (s *PoolTestSuite) TestDeletePoolByIDErrUnauthorized() {
|
||||
|
|
@ -220,7 +220,7 @@ func (s *PoolTestSuite) TestTestUpdatePoolByIDInvalidPoolID() {
|
|||
_, err := s.Runner.UpdatePoolByID(s.Fixtures.AdminContext, "dummy-pool-id", s.Fixtures.UpdatePoolParams)
|
||||
|
||||
s.Require().NotNil(err)
|
||||
s.Require().Equal("fetching pool: fetching pool by ID: parsing id: invalid request", err.Error())
|
||||
s.Require().Equal("error fetching pool: error fetching pool by ID: error parsing id: invalid request", err.Error())
|
||||
}
|
||||
|
||||
func (s *PoolTestSuite) TestTestUpdatePoolByIDRunnerBootstrapTimeoutFailed() {
|
||||
|
|
|
|||
|
|
@ -16,10 +16,9 @@ package providers
|
|||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/cloudbase/garm/config"
|
||||
"github.com/cloudbase/garm/params"
|
||||
"github.com/cloudbase/garm/runner/common"
|
||||
|
|
@ -39,11 +38,11 @@ func LoadProvidersFromConfig(ctx context.Context, cfg config.Config, controllerI
|
|||
conf := providerCfg
|
||||
provider, err := external.NewProvider(ctx, &conf, controllerID)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "creating provider")
|
||||
return nil, fmt.Errorf("error creating provider: %w", err)
|
||||
}
|
||||
providers[providerCfg.Name] = provider
|
||||
default:
|
||||
return nil, errors.Errorf("unknown provider type %s", providerCfg.ProviderType)
|
||||
return nil, fmt.Errorf("unknown provider type %s", providerCfg.ProviderType)
|
||||
}
|
||||
}
|
||||
return providers, nil
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue