Skip to content

Commit

Permalink
Merge pull request cloudbase#243 from gabriel-samfira/use-db-for-gh-c…
Browse files Browse the repository at this point in the history
…reds

Move github credentials to the database
  • Loading branch information
gabriel-samfira authored May 9, 2024
2 parents 834c3bb + b3e2c58 commit 76d45ad
Show file tree
Hide file tree
Showing 78 changed files with 9,200 additions and 877 deletions.
10 changes: 7 additions & 3 deletions .github/workflows/integration-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4

- name: Setup Golang
uses: actions/setup-go@v3
Expand All @@ -20,7 +20,9 @@ jobs:
uses: canonical/setup-lxd@v0.1.1

- name: Install dependencies
run: sudo apt-get -qq update && sudo apt-get -qq install -y apg coreutils make
run: |
sudo rm -f /etc/apt/sources.list.d/microsoft-prod.list
sudo apt-get -qq update && sudo apt-get -qq install -y apg coreutils make
- name: Set up ngrok
id: ngrok
Expand All @@ -43,6 +45,7 @@ jobs:
echo "GARM_PASSWORD=$GARM_PASSWORD" >> $GITHUB_ENV
echo "REPO_WEBHOOK_SECRET=$REPO_WEBHOOK_SECRET" >> $GITHUB_ENV
echo "ORG_WEBHOOK_SECRET=$ORG_WEBHOOK_SECRET" >> $GITHUB_ENV
echo "GARM_CHECKOUT_DIR=$GITHUB_WORKSPACE" >> $GITHUB_ENV
- name: Create logs directory
if: always()
Expand All @@ -52,7 +55,7 @@ jobs:
run: |
set -o pipefail
set -o errexit
make integration 2>&1 | tee /artifacts-logs/e2e.log
make integration 2>&1
env:
GARM_BASE_URL: ${{ steps.ngrok.outputs.tunnel-url }}
ORG_NAME: gsamfira
Expand All @@ -66,6 +69,7 @@ jobs:
run: |
sudo systemctl status garm@runner || true
sudo journalctl --no-pager 2>&1 > /artifacts-logs/system.log
sudo journalctl -u garm@runner --no-pager 2>&1 > /artifacts-logs/garm.log
- name: Upload GARM and e2e logs
if: always()
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ export SHELLOPTS:=$(if $(SHELLOPTS),$(SHELLOPTS):)pipefail:errexit

.ONESHELL:

GEN_PASSWORD=$(shell (apg -n1 -m32))
GEN_PASSWORD=$(shell (/usr/bin/apg -n1 -m32))
IMAGE_TAG = garm-build

USER_ID=$(shell ((docker --version | grep -q podman) && echo "0" || id -u))
Expand Down
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ The ```GARM``` configuration is a simple ```toml```. The sample config file in [
* [The default section](/doc/config_default.md)
* [Logging](/doc/config_logging.md)
* [Database](/doc/database.md)
* [Github credentials](/doc/github_credentials.md)
* [Providers](/doc/providers.md)
* [Metrics](/doc/config_metrics.md)
* [JWT authentication](/doc/config_jwt_auth.md)
Expand Down
21 changes: 0 additions & 21 deletions apiserver/controllers/controllers.go
Original file line number Diff line number Diff line change
Expand Up @@ -329,27 +329,6 @@ func (a *APIController) FirstRunHandler(w http.ResponseWriter, r *http.Request)
}
}

// swagger:route GET /credentials credentials ListCredentials
//
// List all credentials.
//
// Responses:
// 200: Credentials
// 400: APIErrorResponse
func (a *APIController) ListCredentials(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
creds, err := a.r.ListCredentials(ctx)
if err != nil {
handleError(ctx, w, err)
return
}

w.Header().Set("Content-Type", "application/json")
if err := json.NewEncoder(w).Encode(creds); err != nil {
slog.With(slog.Any("error", err)).ErrorContext(ctx, "failed to encode response")
}
}

// swagger:route GET /providers providers ListProviders
//
// List all providers.
Expand Down
229 changes: 229 additions & 0 deletions apiserver/controllers/credentials.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,229 @@
package controllers

import (
"encoding/json"
"log/slog"
"math"
"net/http"
"strconv"

"github.com/gorilla/mux"

gErrors "github.com/cloudbase/garm-provider-common/errors"
"github.com/cloudbase/garm/params"
)

// swagger:route GET /credentials credentials ListCredentials
// swagger:route GET /github/credentials credentials ListCredentials
//
// List all credentials.
//
// Responses:
// 200: Credentials
// 400: APIErrorResponse
func (a *APIController) ListCredentials(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
creds, err := a.r.ListCredentials(ctx)
if err != nil {
handleError(ctx, w, err)
return
}

w.Header().Set("Content-Type", "application/json")
if err := json.NewEncoder(w).Encode(creds); err != nil {
slog.With(slog.Any("error", err)).ErrorContext(ctx, "failed to encode response")
}
}

// swagger:route POST /github/credentials credentials CreateCredentials
//
// Create a GitHub credential.
//
// Parameters:
// + name: Body
// description: Parameters used when creating a GitHub credential.
// type: CreateGithubCredentialsParams
// in: body
// required: true
//
// Responses:
// 200: GithubCredentials
// 400: APIErrorResponse
func (a *APIController) CreateGithubCredential(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()

var params params.CreateGithubCredentialsParams
if err := json.NewDecoder(r.Body).Decode(&params); err != nil {
slog.With(slog.Any("error", err)).ErrorContext(ctx, "failed to decode request")
handleError(ctx, w, gErrors.ErrBadRequest)
return
}

cred, err := a.r.CreateGithubCredentials(ctx, params)
if err != nil {
slog.With(slog.Any("error", err)).ErrorContext(ctx, "failed to create GitHub credential")
handleError(ctx, w, err)
return
}
w.Header().Set("Content-Type", "application/json")
if err := json.NewEncoder(w).Encode(cred); err != nil {
slog.With(slog.Any("error", err)).ErrorContext(ctx, "failed to encode response")
}
}

// swagger:route GET /github/credentials/{id} credentials GetCredentials
//
// Get a GitHub credential.
//
// Parameters:
// + name: id
// description: ID of the GitHub credential.
// type: integer
// in: path
// required: true
//
// Responses:
// 200: GithubCredentials
// 400: APIErrorResponse
func (a *APIController) GetGithubCredential(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
vars := mux.Vars(r)
idParam, ok := vars["id"]
if !ok {
slog.ErrorContext(ctx, "missing id in request")
handleError(ctx, w, gErrors.ErrBadRequest)
return
}

id, err := strconv.ParseUint(idParam, 10, 64)
if err != nil {
slog.With(slog.Any("error", err)).ErrorContext(ctx, "failed to parse id")
handleError(ctx, w, gErrors.ErrBadRequest)
return
}

if id > math.MaxUint {
slog.With(slog.Any("error", err)).ErrorContext(ctx, "id is too large")
handleError(ctx, w, gErrors.ErrBadRequest)
return
}

cred, err := a.r.GetGithubCredentials(ctx, uint(id))
if err != nil {
slog.With(slog.Any("error", err)).ErrorContext(ctx, "failed to get GitHub credential")
handleError(ctx, w, err)
return
}

w.Header().Set("Content-Type", "application/json")
if err := json.NewEncoder(w).Encode(cred); err != nil {
slog.With(slog.Any("error", err)).ErrorContext(ctx, "failed to encode response")
}
}

// swagger:route DELETE /github/credentials/{id} credentials DeleteCredentials
//
// Delete a GitHub credential.
//
// Parameters:
// + name: id
// description: ID of the GitHub credential.
// type: integer
// in: path
// required: true
//
// Responses:
// default: APIErrorResponse
func (a *APIController) DeleteGithubCredential(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
vars := mux.Vars(r)
idParam, ok := vars["id"]
if !ok {
slog.ErrorContext(ctx, "missing id in request")
handleError(ctx, w, gErrors.ErrBadRequest)
return
}

id, err := strconv.ParseUint(idParam, 10, 64)
if err != nil {
slog.With(slog.Any("error", err)).ErrorContext(ctx, "failed to parse id")
handleError(ctx, w, gErrors.ErrBadRequest)
return
}

if id > math.MaxUint {
slog.With(slog.Any("error", err)).ErrorContext(ctx, "id is too large")
handleError(ctx, w, gErrors.ErrBadRequest)
return
}

if err := a.r.DeleteGithubCredentials(ctx, uint(id)); err != nil {
slog.With(slog.Any("error", err)).ErrorContext(ctx, "failed to delete GitHub credential")
handleError(ctx, w, err)
return
}

w.WriteHeader(http.StatusNoContent)
}

// swagger:route PUT /github/credentials/{id} credentials UpdateCredentials
//
// Update a GitHub credential.
//
// Parameters:
// + name: id
// description: ID of the GitHub credential.
// type: integer
// in: path
// required: true
// + name: Body
// description: Parameters used when updating a GitHub credential.
// type: UpdateGithubCredentialsParams
// in: body
// required: true
//
// Responses:
// 200: GithubCredentials
// 400: APIErrorResponse
func (a *APIController) UpdateGithubCredential(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
vars := mux.Vars(r)
idParam, ok := vars["id"]
if !ok {
slog.ErrorContext(ctx, "missing id in request")
handleError(ctx, w, gErrors.ErrBadRequest)
return
}

id, err := strconv.ParseUint(idParam, 10, 64)
if err != nil {
slog.With(slog.Any("error", err)).ErrorContext(ctx, "failed to parse id")
handleError(ctx, w, gErrors.ErrBadRequest)
return
}

if id > math.MaxUint {
slog.With(slog.Any("error", err)).ErrorContext(ctx, "id is too large")
handleError(ctx, w, gErrors.ErrBadRequest)
return
}

var params params.UpdateGithubCredentialsParams
if err := json.NewDecoder(r.Body).Decode(&params); err != nil {
slog.With(slog.Any("error", err)).ErrorContext(ctx, "failed to decode request")
handleError(ctx, w, gErrors.ErrBadRequest)
return
}

cred, err := a.r.UpdateGithubCredentials(ctx, uint(id), params)
if err != nil {
slog.With(slog.Any("error", err)).ErrorContext(ctx, "failed to update GitHub credential")
handleError(ctx, w, err)
return
}

w.Header().Set("Content-Type", "application/json")
if err := json.NewEncoder(w).Encode(cred); err != nil {
slog.With(slog.Any("error", err)).ErrorContext(ctx, "failed to encode response")
}
}
Loading

0 comments on commit 76d45ad

Please sign in to comment.