Switch to fmt.Errorf
Replace all instances of errors.Wrap() with fmt.Errorf. Signed-off-by: Gabriel Adrian Samfira <gsamfira@cloudbasesolutions.com>
This commit is contained in:
parent
10dcbec954
commit
118319c7c1
88 changed files with 1007 additions and 4467 deletions
|
|
@ -17,6 +17,8 @@ package controllers
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
@ -25,7 +27,6 @@ import (
|
||||||
|
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
"github.com/gorilla/websocket"
|
"github.com/gorilla/websocket"
|
||||||
"github.com/pkg/errors"
|
|
||||||
|
|
||||||
gErrors "github.com/cloudbase/garm-provider-common/errors"
|
gErrors "github.com/cloudbase/garm-provider-common/errors"
|
||||||
"github.com/cloudbase/garm-provider-common/util"
|
"github.com/cloudbase/garm-provider-common/util"
|
||||||
|
|
@ -43,7 +44,7 @@ import (
|
||||||
func NewAPIController(r *runner.Runner, authenticator *auth.Authenticator, hub *wsWriter.Hub, apiCfg config.APIServer) (*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()))
|
controllerInfo, err := r.GetControllerInfo(auth.GetAdminContext(context.Background()))
|
||||||
if err != nil {
|
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
|
var checkOrigin func(r *http.Request) bool
|
||||||
if len(apiCfg.CORSOrigins) > 0 {
|
if len(apiCfg.CORSOrigins) > 0 {
|
||||||
|
|
@ -91,24 +92,22 @@ type APIController struct {
|
||||||
|
|
||||||
func handleError(ctx context.Context, w http.ResponseWriter, err error) {
|
func handleError(ctx context.Context, w http.ResponseWriter, err error) {
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
origErr := errors.Cause(err)
|
|
||||||
apiErr := params.APIErrorResponse{
|
apiErr := params.APIErrorResponse{
|
||||||
Details: origErr.Error(),
|
Details: err.Error(),
|
||||||
}
|
}
|
||||||
|
switch {
|
||||||
switch origErr.(type) {
|
case errors.Is(err, gErrors.ErrNotFound):
|
||||||
case *gErrors.NotFoundError:
|
|
||||||
w.WriteHeader(http.StatusNotFound)
|
w.WriteHeader(http.StatusNotFound)
|
||||||
apiErr.Error = "Not Found"
|
apiErr.Error = "Not Found"
|
||||||
case *gErrors.UnauthorizedError:
|
case errors.Is(err, gErrors.ErrUnauthorized):
|
||||||
w.WriteHeader(http.StatusUnauthorized)
|
w.WriteHeader(http.StatusUnauthorized)
|
||||||
apiErr.Error = "Not Authorized"
|
apiErr.Error = "Not Authorized"
|
||||||
// Don't include details on 401 errors.
|
// Don't include details on 401 errors.
|
||||||
apiErr.Details = ""
|
apiErr.Details = ""
|
||||||
case *gErrors.BadRequestError:
|
case errors.Is(err, gErrors.ErrBadRequest):
|
||||||
w.WriteHeader(http.StatusBadRequest)
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
apiErr.Error = "Bad Request"
|
apiErr.Error = "Bad Request"
|
||||||
case *gErrors.DuplicateUserError, *gErrors.ConflictError:
|
case errors.Is(err, gErrors.ErrDuplicateEntity), errors.Is(err, &gErrors.ConflictError{}):
|
||||||
w.WriteHeader(http.StatusConflict)
|
w.WriteHeader(http.StatusConflict)
|
||||||
apiErr.Error = "Conflict"
|
apiErr.Error = "Conflict"
|
||||||
default:
|
default:
|
||||||
|
|
|
||||||
17
auth/auth.go
17
auth/auth.go
|
|
@ -16,11 +16,12 @@ package auth
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
jwt "github.com/golang-jwt/jwt/v5"
|
jwt "github.com/golang-jwt/jwt/v5"
|
||||||
"github.com/nbutton23/zxcvbn-go"
|
"github.com/nbutton23/zxcvbn-go"
|
||||||
"github.com/pkg/errors"
|
|
||||||
"golang.org/x/crypto/bcrypt"
|
"golang.org/x/crypto/bcrypt"
|
||||||
|
|
||||||
runnerErrors "github.com/cloudbase/garm-provider-common/errors"
|
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) {
|
func (a *Authenticator) GetJWTToken(ctx context.Context) (string, error) {
|
||||||
tokenID, err := util.GetRandomString(16)
|
tokenID, err := util.GetRandomString(16)
|
||||||
if err != nil {
|
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())
|
expireToken := time.Now().Add(a.cfg.TimeToLive.Duration())
|
||||||
expires := &jwt.NumericDate{
|
expires := &jwt.NumericDate{
|
||||||
|
|
@ -72,7 +73,7 @@ func (a *Authenticator) GetJWTToken(ctx context.Context) (string, error) {
|
||||||
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
|
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
|
||||||
tokenString, err := token.SignedString([]byte(a.cfg.Secret))
|
tokenString, err := token.SignedString([]byte(a.cfg.Secret))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", errors.Wrap(err, "fetching token string")
|
return "", fmt.Errorf("error fetching token string: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return tokenString, nil
|
return tokenString, nil
|
||||||
|
|
@ -87,7 +88,7 @@ func (a *Authenticator) GetJWTMetricsToken(ctx context.Context) (string, error)
|
||||||
|
|
||||||
tokenID, err := util.GetRandomString(16)
|
tokenID, err := util.GetRandomString(16)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", errors.Wrap(err, "generating random string")
|
return "", fmt.Errorf("error generating random string: %w", err)
|
||||||
}
|
}
|
||||||
// nolint:golangci-lint,godox
|
// nolint:golangci-lint,godox
|
||||||
// TODO: currently this is the same TTL as the normal Token
|
// 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)
|
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
|
||||||
tokenString, err := token.SignedString([]byte(a.cfg.Secret))
|
tokenString, err := token.SignedString([]byte(a.cfg.Secret))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", errors.Wrap(err, "fetching token string")
|
return "", fmt.Errorf("error fetching token string: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return tokenString, nil
|
return tokenString, nil
|
||||||
|
|
@ -121,7 +122,7 @@ func (a *Authenticator) InitController(ctx context.Context, param params.NewUser
|
||||||
_, err := a.store.ControllerInfo()
|
_, err := a.store.ControllerInfo()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if !errors.Is(err, runnerErrors.ErrNotFound) {
|
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) {
|
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)
|
hashed, err := util.PaswsordToBcrypt(param.Password)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return params.User{}, errors.Wrap(err, "creating user")
|
return params.User{}, fmt.Errorf("error creating user: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
param.Password = hashed
|
param.Password = hashed
|
||||||
|
|
@ -169,7 +170,7 @@ func (a *Authenticator) AuthenticateUser(ctx context.Context, info params.Passwo
|
||||||
if errors.Is(err, runnerErrors.ErrNotFound) {
|
if errors.Is(err, runnerErrors.ErrNotFound) {
|
||||||
return ctx, runnerErrors.ErrUnauthorized
|
return ctx, runnerErrors.ErrUnauthorized
|
||||||
}
|
}
|
||||||
return ctx, errors.Wrap(err, "authenticating")
|
return ctx, fmt.Errorf("error authenticating: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !user.Enabled {
|
if !user.Enabled {
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,6 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
jwt "github.com/golang-jwt/jwt/v5"
|
jwt "github.com/golang-jwt/jwt/v5"
|
||||||
"github.com/pkg/errors"
|
|
||||||
|
|
||||||
runnerErrors "github.com/cloudbase/garm-provider-common/errors"
|
runnerErrors "github.com/cloudbase/garm-provider-common/errors"
|
||||||
commonParams "github.com/cloudbase/garm-provider-common/params"
|
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)
|
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
|
||||||
tokenString, err := token.SignedString([]byte(i.jwtSecret))
|
tokenString, err := token.SignedString([]byte(i.jwtSecret))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", errors.Wrap(err, "signing token")
|
return "", fmt.Errorf("error signing token: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return tokenString, nil
|
return tokenString, nil
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,6 @@ import (
|
||||||
|
|
||||||
openapiRuntimeClient "github.com/go-openapi/runtime/client"
|
openapiRuntimeClient "github.com/go-openapi/runtime/client"
|
||||||
"github.com/jedib0t/go-pretty/v6/table"
|
"github.com/jedib0t/go-pretty/v6/table"
|
||||||
"github.com/pkg/errors"
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
apiClientController "github.com/cloudbase/garm/client/controller"
|
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)
|
response, err := apiCli.FirstRun.FirstRun(newUserReq, authToken)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "initializing manager")
|
return fmt.Errorf("error initializing manager: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
newLoginParamsReq := apiClientLogin.NewLoginParams()
|
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)
|
token, err := apiCli.Login.Login(newLoginParamsReq, authToken)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "authenticating")
|
return fmt.Errorf("error authenticating: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
cfg.Managers = append(cfg.Managers, config.Manager{
|
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
|
cfg.ActiveManager = loginProfileName
|
||||||
|
|
||||||
if err := cfg.SaveConfig(); err != nil {
|
if err := cfg.SaveConfig(); err != nil {
|
||||||
return errors.Wrap(err, "saving config")
|
return fmt.Errorf("error saving config: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
updateUrlsReq := apiClientController.NewUpdateControllerParams()
|
updateUrlsReq := apiClientController.NewUpdateControllerParams()
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,6 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/jedib0t/go-pretty/v6/table"
|
"github.com/jedib0t/go-pretty/v6/table"
|
||||||
"github.com/pkg/errors"
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
commonParams "github.com/cloudbase/garm-provider-common/params"
|
commonParams "github.com/cloudbase/garm-provider-common/params"
|
||||||
|
|
@ -471,7 +470,7 @@ func init() {
|
||||||
func extraSpecsFromFile(specsFile string) (json.RawMessage, error) {
|
func extraSpecsFromFile(specsFile string) (json.RawMessage, error) {
|
||||||
data, err := os.ReadFile(specsFile)
|
data, err := os.ReadFile(specsFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "opening specs file")
|
return nil, fmt.Errorf("error opening specs file: %w", err)
|
||||||
}
|
}
|
||||||
return asRawMessage(data)
|
return asRawMessage(data)
|
||||||
}
|
}
|
||||||
|
|
@ -481,14 +480,14 @@ func asRawMessage(data []byte) (json.RawMessage, error) {
|
||||||
// have a valid json.
|
// have a valid json.
|
||||||
var unmarshaled interface{}
|
var unmarshaled interface{}
|
||||||
if err := json.Unmarshal(data, &unmarshaled); err != nil {
|
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 asRawJSON json.RawMessage
|
||||||
var err error
|
var err error
|
||||||
asRawJSON, err = json.Marshal(unmarshaled)
|
asRawJSON, err = json.Marshal(unmarshaled)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "marshaling json")
|
return nil, fmt.Errorf("error marshaling json: %w", err)
|
||||||
}
|
}
|
||||||
return asRawJSON, nil
|
return asRawJSON, nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,13 +15,13 @@
|
||||||
package config
|
package config
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/BurntSushi/toml"
|
"github.com/BurntSushi/toml"
|
||||||
"github.com/pkg/errors"
|
|
||||||
|
|
||||||
runnerErrors "github.com/cloudbase/garm-provider-common/errors"
|
runnerErrors "github.com/cloudbase/garm-provider-common/errors"
|
||||||
)
|
)
|
||||||
|
|
@ -34,11 +34,11 @@ const (
|
||||||
func getConfigFilePath() (string, error) {
|
func getConfigFilePath() (string, error) {
|
||||||
configDir, err := getHomeDir()
|
configDir, err := getHomeDir()
|
||||||
if err != nil {
|
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 {
|
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)
|
cfgFile := filepath.Join(configDir, DefaultConfigFileName)
|
||||||
|
|
@ -48,7 +48,7 @@ func getConfigFilePath() (string, error) {
|
||||||
func LoadConfig() (*Config, error) {
|
func LoadConfig() (*Config, error) {
|
||||||
cfgFile, err := getConfigFilePath()
|
cfgFile, err := getConfigFilePath()
|
||||||
if err != nil {
|
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 {
|
if _, err := os.Stat(cfgFile); err != nil {
|
||||||
|
|
@ -56,12 +56,12 @@ func LoadConfig() (*Config, error) {
|
||||||
// return empty config
|
// return empty config
|
||||||
return &Config{}, nil
|
return &Config{}, nil
|
||||||
}
|
}
|
||||||
return nil, errors.Wrap(err, "accessing config file")
|
return nil, fmt.Errorf("error accessing config file: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var config Config
|
var config Config
|
||||||
if _, err := toml.DecodeFile(cfgFile, &config); err != nil {
|
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
|
return &config, nil
|
||||||
|
|
@ -157,17 +157,17 @@ func (c *Config) SaveConfig() error {
|
||||||
cfgFile, err := getConfigFilePath()
|
cfgFile, err := getConfigFilePath()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if !errors.Is(err, os.ErrNotExist) {
|
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)
|
cfgHandle, err := os.Create(cfgFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "getting file handle")
|
return fmt.Errorf("error getting file handle: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
encoder := toml.NewEncoder(cfgHandle)
|
encoder := toml.NewEncoder(cfgHandle)
|
||||||
if err := encoder.Encode(c); err != nil {
|
if err := encoder.Encode(c); err != nil {
|
||||||
return errors.Wrap(err, "saving config")
|
return fmt.Errorf("error saving config: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
|
||||||
|
|
@ -15,19 +15,19 @@
|
||||||
package config
|
package config
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func ensureHomeDir(folder string) error {
|
func ensureHomeDir(folder string) error {
|
||||||
if _, err := os.Stat(folder); err != nil {
|
if _, err := os.Stat(folder); err != nil {
|
||||||
if !errors.Is(err, os.ErrNotExist) {
|
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 {
|
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
|
package config
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func getHomeDir() (string, error) {
|
func getHomeDir() (string, error) {
|
||||||
home, err := os.UserHomeDir()
|
home, err := os.UserHomeDir()
|
||||||
if err != nil {
|
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
|
return filepath.Join(home, ".local", "share", DefaultAppFolder), nil
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,6 @@ import (
|
||||||
|
|
||||||
"github.com/gorilla/handlers"
|
"github.com/gorilla/handlers"
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
"github.com/pkg/errors"
|
|
||||||
lumberjack "gopkg.in/natefinch/lumberjack.v2"
|
lumberjack "gopkg.in/natefinch/lumberjack.v2"
|
||||||
|
|
||||||
"github.com/cloudbase/garm-provider-common/util"
|
"github.com/cloudbase/garm-provider-common/util"
|
||||||
|
|
@ -73,7 +72,7 @@ func maybeInitController(db common.Store) (params.ControllerInfo, error) {
|
||||||
|
|
||||||
info, err := db.InitController()
|
info, err := db.InitController()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return params.ControllerInfo{}, errors.Wrap(err, "initializing controller")
|
return params.ControllerInfo{}, fmt.Errorf("error initializing controller: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return info, nil
|
return info, nil
|
||||||
|
|
@ -152,7 +151,7 @@ func setupLogging(ctx context.Context, logCfg config.Logging, hub *websocket.Hub
|
||||||
func maybeUpdateURLsFromConfig(cfg config.Config, store common.Store) error {
|
func maybeUpdateURLsFromConfig(cfg config.Config, store common.Store) error {
|
||||||
info, err := store.ControllerInfo()
|
info, err := store.ControllerInfo()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "fetching controller info")
|
return fmt.Errorf("error fetching controller info: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var updateParams params.UpdateControllerParams
|
var updateParams params.UpdateControllerParams
|
||||||
|
|
@ -176,7 +175,7 @@ func maybeUpdateURLsFromConfig(cfg config.Config, store common.Store) error {
|
||||||
|
|
||||||
_, err = store.UpdateController(updateParams)
|
_, err = store.UpdateController(updateParams)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "updating controller info")
|
return fmt.Errorf("error updating controller info: %w", err)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,6 @@ import (
|
||||||
"github.com/BurntSushi/toml"
|
"github.com/BurntSushi/toml"
|
||||||
"github.com/bradleyfalzon/ghinstallation/v2"
|
"github.com/bradleyfalzon/ghinstallation/v2"
|
||||||
zxcvbn "github.com/nbutton23/zxcvbn-go"
|
zxcvbn "github.com/nbutton23/zxcvbn-go"
|
||||||
"github.com/pkg/errors"
|
|
||||||
"golang.org/x/oauth2"
|
"golang.org/x/oauth2"
|
||||||
|
|
||||||
"github.com/cloudbase/garm/params"
|
"github.com/cloudbase/garm/params"
|
||||||
|
|
@ -84,10 +83,10 @@ const (
|
||||||
func NewConfig(cfgFile string) (*Config, error) {
|
func NewConfig(cfgFile string) (*Config, error) {
|
||||||
var config Config
|
var config Config
|
||||||
if _, err := toml.DecodeFile(cfgFile, &config); err != nil {
|
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 {
|
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
|
return &config, nil
|
||||||
}
|
}
|
||||||
|
|
@ -496,19 +495,19 @@ type Database struct {
|
||||||
// GormParams returns the database type and connection URI
|
// GormParams returns the database type and connection URI
|
||||||
func (d *Database) GormParams() (dbType DBBackendType, uri string, err error) {
|
func (d *Database) GormParams() (dbType DBBackendType, uri string, err error) {
|
||||||
if err := d.Validate(); err != nil {
|
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
|
dbType = d.DbBackend
|
||||||
switch dbType {
|
switch dbType {
|
||||||
case MySQLBackend:
|
case MySQLBackend:
|
||||||
uri, err = d.MySQL.ConnectionString()
|
uri, err = d.MySQL.ConnectionString()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", "", errors.Wrap(err, "fetching mysql connection string")
|
return "", "", fmt.Errorf("error fetching mysql connection string: %w", err)
|
||||||
}
|
}
|
||||||
case SQLiteBackend:
|
case SQLiteBackend:
|
||||||
uri, err = d.SQLite.ConnectionString()
|
uri, err = d.SQLite.ConnectionString()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", "", errors.Wrap(err, "fetching sqlite3 connection string")
|
return "", "", fmt.Errorf("error fetching sqlite3 connection string: %w", err)
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
return "", "", fmt.Errorf("invalid database backend: %s", dbType)
|
return "", "", fmt.Errorf("invalid database backend: %s", dbType)
|
||||||
|
|
|
||||||
|
|
@ -517,7 +517,6 @@ func TestJWTAuthConfig(t *testing.T) {
|
||||||
|
|
||||||
func TestTimeToLiveDuration(t *testing.T) {
|
func TestTimeToLiveDuration(t *testing.T) {
|
||||||
cfg := JWTAuth{
|
cfg := JWTAuth{
|
||||||
Secret: EncryptionPassphrase,
|
|
||||||
TimeToLive: "48h",
|
TimeToLive: "48h",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,10 +15,11 @@
|
||||||
package sql
|
package sql
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
"github.com/pkg/errors"
|
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
|
|
||||||
runnerErrors "github.com/cloudbase/garm-provider-common/errors"
|
runnerErrors "github.com/cloudbase/garm-provider-common/errors"
|
||||||
|
|
@ -30,7 +31,7 @@ import (
|
||||||
func dbControllerToCommonController(dbInfo ControllerInfo) (params.ControllerInfo, error) {
|
func dbControllerToCommonController(dbInfo ControllerInfo) (params.ControllerInfo, error) {
|
||||||
url, err := url.JoinPath(dbInfo.WebhookBaseURL, dbInfo.ControllerID.String())
|
url, err := url.JoinPath(dbInfo.WebhookBaseURL, dbInfo.ControllerID.String())
|
||||||
if err != nil {
|
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{
|
return params.ControllerInfo{
|
||||||
|
|
@ -49,14 +50,14 @@ func (s *sqlDatabase) ControllerInfo() (params.ControllerInfo, error) {
|
||||||
q := s.conn.Model(&ControllerInfo{}).First(&info)
|
q := s.conn.Model(&ControllerInfo{}).First(&info)
|
||||||
if q.Error != nil {
|
if q.Error != nil {
|
||||||
if errors.Is(q.Error, gorm.ErrRecordNotFound) {
|
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)
|
paramInfo, err := dbControllerToCommonController(info)
|
||||||
if err != nil {
|
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
|
return paramInfo, nil
|
||||||
|
|
@ -69,7 +70,7 @@ func (s *sqlDatabase) InitController() (params.ControllerInfo, error) {
|
||||||
|
|
||||||
newID, err := uuid.NewRandom()
|
newID, err := uuid.NewRandom()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return params.ControllerInfo{}, errors.Wrap(err, "generating UUID")
|
return params.ControllerInfo{}, fmt.Errorf("error generating UUID: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
newInfo := ControllerInfo{
|
newInfo := ControllerInfo{
|
||||||
|
|
@ -79,7 +80,7 @@ func (s *sqlDatabase) InitController() (params.ControllerInfo, error) {
|
||||||
|
|
||||||
q := s.conn.Save(&newInfo)
|
q := s.conn.Save(&newInfo)
|
||||||
if q.Error != nil {
|
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{
|
return params.ControllerInfo{
|
||||||
|
|
@ -98,13 +99,13 @@ func (s *sqlDatabase) UpdateController(info params.UpdateControllerParams) (para
|
||||||
q := tx.Model(&ControllerInfo{}).First(&dbInfo)
|
q := tx.Model(&ControllerInfo{}).First(&dbInfo)
|
||||||
if q.Error != nil {
|
if q.Error != nil {
|
||||||
if errors.Is(q.Error, gorm.ErrRecordNotFound) {
|
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 {
|
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 {
|
if info.MetadataURL != nil {
|
||||||
|
|
@ -125,17 +126,17 @@ func (s *sqlDatabase) UpdateController(info params.UpdateControllerParams) (para
|
||||||
|
|
||||||
q = tx.Save(&dbInfo)
|
q = tx.Save(&dbInfo)
|
||||||
if q.Error != nil {
|
if q.Error != nil {
|
||||||
return errors.Wrap(q.Error, "saving controller info")
|
return fmt.Errorf("error saving controller info: %w", q.Error)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
if err != 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)
|
paramInfo, err = dbControllerToCommonController(dbInfo)
|
||||||
if err != nil {
|
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
|
return paramInfo, nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,10 +16,11 @@ package sql
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
|
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
"github.com/pkg/errors"
|
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
|
|
||||||
runnerErrors "github.com/cloudbase/garm-provider-common/errors"
|
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")
|
return params.Enterprise{}, errors.New("creating enterprise: missing secret")
|
||||||
}
|
}
|
||||||
if credentials.ForgeType != params.GithubEndpointType {
|
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))
|
secret, err := util.Seal([]byte(webhookSecret), []byte(s.cfg.Passphrase))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return params.Enterprise{}, errors.Wrap(err, "encoding secret")
|
return params.Enterprise{}, fmt.Errorf("error encoding secret: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
|
|
@ -57,22 +58,22 @@ func (s *sqlDatabase) CreateEnterprise(ctx context.Context, name string, credent
|
||||||
|
|
||||||
q := tx.Create(&newEnterprise)
|
q := tx.Create(&newEnterprise)
|
||||||
if q.Error != nil {
|
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")
|
newEnterprise, err = s.getEnterpriseByID(ctx, tx, newEnterprise.ID.String(), "Pools", "Credentials", "Endpoint", "Credentials.Endpoint")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "creating enterprise")
|
return fmt.Errorf("error creating enterprise: %w", err)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
if err != 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())
|
ret, err := s.GetEnterpriseByID(ctx, newEnterprise.ID.String())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return params.Enterprise{}, errors.Wrap(err, "creating enterprise")
|
return params.Enterprise{}, fmt.Errorf("error creating enterprise: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret, nil
|
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) {
|
func (s *sqlDatabase) GetEnterprise(ctx context.Context, name, endpointName string) (params.Enterprise, error) {
|
||||||
enterprise, err := s.getEnterprise(ctx, name, endpointName)
|
enterprise, err := s.getEnterprise(ctx, name, endpointName)
|
||||||
if err != nil {
|
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)
|
param, err := s.sqlToCommonEnterprise(enterprise, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return params.Enterprise{}, errors.Wrap(err, "fetching enterprise")
|
return params.Enterprise{}, fmt.Errorf("error fetching enterprise: %w", err)
|
||||||
}
|
}
|
||||||
return param, nil
|
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...)
|
enterprise, err := s.getEnterpriseByID(ctx, s.conn, enterpriseID, preloadList...)
|
||||||
if err != nil {
|
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)
|
param, err := s.sqlToCommonEnterprise(enterprise, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return params.Enterprise{}, errors.Wrap(err, "fetching enterprise")
|
return params.Enterprise{}, fmt.Errorf("error fetching enterprise: %w", err)
|
||||||
}
|
}
|
||||||
return param, nil
|
return param, nil
|
||||||
}
|
}
|
||||||
|
|
@ -125,7 +126,7 @@ func (s *sqlDatabase) ListEnterprises(_ context.Context, filter params.Enterpris
|
||||||
}
|
}
|
||||||
q = q.Find(&enterprises)
|
q = q.Find(&enterprises)
|
||||||
if q.Error != nil {
|
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))
|
ret := make([]params.Enterprise, len(enterprises))
|
||||||
|
|
@ -133,7 +134,7 @@ func (s *sqlDatabase) ListEnterprises(_ context.Context, filter params.Enterpris
|
||||||
var err error
|
var err error
|
||||||
ret[idx], err = s.sqlToCommonEnterprise(val, true)
|
ret[idx], err = s.sqlToCommonEnterprise(val, true)
|
||||||
if err != nil {
|
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 {
|
func (s *sqlDatabase) DeleteEnterprise(ctx context.Context, enterpriseID string) error {
|
||||||
enterprise, err := s.getEnterpriseByID(ctx, s.conn, enterpriseID, "Endpoint", "Credentials", "Credentials.Endpoint")
|
enterprise, err := s.getEnterpriseByID(ctx, s.conn, enterpriseID, "Endpoint", "Credentials", "Credentials.Endpoint")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "fetching enterprise")
|
return fmt.Errorf("error fetching enterprise: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
defer func(ent Enterprise) {
|
defer func(ent Enterprise) {
|
||||||
|
|
@ -159,7 +160,7 @@ func (s *sqlDatabase) DeleteEnterprise(ctx context.Context, enterpriseID string)
|
||||||
|
|
||||||
q := s.conn.Unscoped().Delete(&enterprise)
|
q := s.conn.Unscoped().Delete(&enterprise)
|
||||||
if q.Error != nil && !errors.Is(q.Error, gorm.ErrRecordNotFound) {
|
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
|
return nil
|
||||||
|
|
@ -177,31 +178,31 @@ func (s *sqlDatabase) UpdateEnterprise(ctx context.Context, enterpriseID string,
|
||||||
var err error
|
var err error
|
||||||
enterprise, err = s.getEnterpriseByID(ctx, tx, enterpriseID)
|
enterprise, err = s.getEnterpriseByID(ctx, tx, enterpriseID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "fetching enterprise")
|
return fmt.Errorf("error fetching enterprise: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if enterprise.EndpointName == nil {
|
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 != "" {
|
if param.CredentialsName != "" {
|
||||||
creds, err = s.getGithubCredentialsByName(ctx, tx, param.CredentialsName, false)
|
creds, err = s.getGithubCredentialsByName(ctx, tx, param.CredentialsName, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "fetching credentials")
|
return fmt.Errorf("error fetching credentials: %w", err)
|
||||||
}
|
}
|
||||||
if creds.EndpointName == nil {
|
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 {
|
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
|
enterprise.CredentialsID = &creds.ID
|
||||||
}
|
}
|
||||||
if param.WebhookSecret != "" {
|
if param.WebhookSecret != "" {
|
||||||
secret, err := util.Seal([]byte(param.WebhookSecret), []byte(s.cfg.Passphrase))
|
secret, err := util.Seal([]byte(param.WebhookSecret), []byte(s.cfg.Passphrase))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "encoding secret")
|
return fmt.Errorf("error encoding secret: %w", err)
|
||||||
}
|
}
|
||||||
enterprise.WebhookSecret = secret
|
enterprise.WebhookSecret = secret
|
||||||
}
|
}
|
||||||
|
|
@ -212,22 +213,22 @@ func (s *sqlDatabase) UpdateEnterprise(ctx context.Context, enterpriseID string,
|
||||||
|
|
||||||
q := tx.Save(&enterprise)
|
q := tx.Save(&enterprise)
|
||||||
if q.Error != nil {
|
if q.Error != nil {
|
||||||
return errors.Wrap(q.Error, "saving enterprise")
|
return fmt.Errorf("error saving enterprise: %w", q.Error)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
if err != 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")
|
enterprise, err = s.getEnterpriseByID(ctx, s.conn, enterpriseID, "Endpoint", "Credentials", "Credentials.Endpoint")
|
||||||
if err != nil {
|
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)
|
newParams, err = s.sqlToCommonEnterprise(enterprise, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return params.Enterprise{}, errors.Wrap(err, "updating enterprise")
|
return params.Enterprise{}, fmt.Errorf("error updating enterprise: %w", err)
|
||||||
}
|
}
|
||||||
return newParams, nil
|
return newParams, nil
|
||||||
}
|
}
|
||||||
|
|
@ -244,7 +245,7 @@ func (s *sqlDatabase) getEnterprise(_ context.Context, name, endpointName string
|
||||||
if errors.Is(q.Error, gorm.ErrRecordNotFound) {
|
if errors.Is(q.Error, gorm.ErrRecordNotFound) {
|
||||||
return Enterprise{}, runnerErrors.ErrNotFound
|
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
|
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) {
|
func (s *sqlDatabase) getEnterpriseByID(_ context.Context, tx *gorm.DB, id string, preload ...string) (Enterprise, error) {
|
||||||
u, err := uuid.Parse(id)
|
u, err := uuid.Parse(id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return Enterprise{}, errors.Wrap(runnerErrors.ErrBadRequest, "parsing id")
|
return Enterprise{}, fmt.Errorf("error parsing id: %w", runnerErrors.ErrBadRequest)
|
||||||
}
|
}
|
||||||
var enterprise Enterprise
|
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) {
|
if errors.Is(q.Error, gorm.ErrRecordNotFound) {
|
||||||
return Enterprise{}, runnerErrors.ErrNotFound
|
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
|
return enterprise, nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -218,7 +218,7 @@ func (s *EnterpriseTestSuite) TestCreateEnterpriseInvalidDBPassphrase() {
|
||||||
params.PoolBalancerTypeRoundRobin)
|
params.PoolBalancerTypeRoundRobin)
|
||||||
|
|
||||||
s.Require().NotNil(err)
|
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() {
|
func (s *EnterpriseTestSuite) TestCreateEnterpriseDBCreateErr() {
|
||||||
|
|
@ -236,7 +236,7 @@ func (s *EnterpriseTestSuite) TestCreateEnterpriseDBCreateErr() {
|
||||||
params.PoolBalancerTypeRoundRobin)
|
params.PoolBalancerTypeRoundRobin)
|
||||||
|
|
||||||
s.Require().NotNil(err)
|
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()
|
s.assertSQLMockExpectations()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -259,7 +259,7 @@ func (s *EnterpriseTestSuite) TestGetEnterpriseNotFound() {
|
||||||
_, err := s.Store.GetEnterprise(s.adminCtx, "dummy-name", "github.com")
|
_, err := s.Store.GetEnterprise(s.adminCtx, "dummy-name", "github.com")
|
||||||
|
|
||||||
s.Require().NotNil(err)
|
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() {
|
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)
|
_, err := s.StoreSQLMocked.GetEnterprise(s.adminCtx, s.Fixtures.Enterprises[0].Name, s.Fixtures.Enterprises[0].Endpoint.Name)
|
||||||
|
|
||||||
s.Require().NotNil(err)
|
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()
|
s.assertSQLMockExpectations()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -341,7 +341,7 @@ func (s *EnterpriseTestSuite) TestListEnterprisesDBFetchErr() {
|
||||||
|
|
||||||
s.assertSQLMockExpectations()
|
s.assertSQLMockExpectations()
|
||||||
s.Require().NotNil(err)
|
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() {
|
func (s *EnterpriseTestSuite) TestDeleteEnterprise() {
|
||||||
|
|
@ -350,14 +350,14 @@ func (s *EnterpriseTestSuite) TestDeleteEnterprise() {
|
||||||
s.Require().Nil(err)
|
s.Require().Nil(err)
|
||||||
_, err = s.Store.GetEnterpriseByID(s.adminCtx, s.Fixtures.Enterprises[0].ID)
|
_, err = s.Store.GetEnterpriseByID(s.adminCtx, s.Fixtures.Enterprises[0].ID)
|
||||||
s.Require().NotNil(err)
|
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() {
|
func (s *EnterpriseTestSuite) TestDeleteEnterpriseInvalidEnterpriseID() {
|
||||||
err := s.Store.DeleteEnterprise(s.adminCtx, "dummy-enterprise-id")
|
err := s.Store.DeleteEnterprise(s.adminCtx, "dummy-enterprise-id")
|
||||||
|
|
||||||
s.Require().NotNil(err)
|
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() {
|
func (s *EnterpriseTestSuite) TestDeleteEnterpriseDBDeleteErr() {
|
||||||
|
|
@ -375,7 +375,7 @@ func (s *EnterpriseTestSuite) TestDeleteEnterpriseDBDeleteErr() {
|
||||||
err := s.StoreSQLMocked.DeleteEnterprise(s.adminCtx, s.Fixtures.Enterprises[0].ID)
|
err := s.StoreSQLMocked.DeleteEnterprise(s.adminCtx, s.Fixtures.Enterprises[0].ID)
|
||||||
|
|
||||||
s.Require().NotNil(err)
|
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()
|
s.assertSQLMockExpectations()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -391,7 +391,7 @@ func (s *EnterpriseTestSuite) TestUpdateEnterpriseInvalidEnterpriseID() {
|
||||||
_, err := s.Store.UpdateEnterprise(s.adminCtx, "dummy-enterprise-id", s.Fixtures.UpdateRepoParams)
|
_, err := s.Store.UpdateEnterprise(s.adminCtx, "dummy-enterprise-id", s.Fixtures.UpdateRepoParams)
|
||||||
|
|
||||||
s.Require().NotNil(err)
|
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() {
|
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)
|
_, err := s.StoreSQLMocked.UpdateEnterprise(s.adminCtx, s.Fixtures.Enterprises[0].ID, s.Fixtures.UpdateRepoParams)
|
||||||
|
|
||||||
s.Require().NotNil(err)
|
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()
|
s.assertSQLMockExpectations()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -444,7 +444,7 @@ func (s *EnterpriseTestSuite) TestUpdateEnterpriseDBSaveErr() {
|
||||||
_, err := s.StoreSQLMocked.UpdateEnterprise(s.adminCtx, s.Fixtures.Enterprises[0].ID, s.Fixtures.UpdateRepoParams)
|
_, err := s.StoreSQLMocked.UpdateEnterprise(s.adminCtx, s.Fixtures.Enterprises[0].ID, s.Fixtures.UpdateRepoParams)
|
||||||
|
|
||||||
s.Require().NotNil(err)
|
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()
|
s.assertSQLMockExpectations()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -472,7 +472,7 @@ func (s *EnterpriseTestSuite) TestUpdateEnterpriseDBDecryptingErr() {
|
||||||
_, err := s.StoreSQLMocked.UpdateEnterprise(s.adminCtx, s.Fixtures.Enterprises[0].ID, s.Fixtures.UpdateRepoParams)
|
_, err := s.StoreSQLMocked.UpdateEnterprise(s.adminCtx, s.Fixtures.Enterprises[0].ID, s.Fixtures.UpdateRepoParams)
|
||||||
|
|
||||||
s.Require().NotNil(err)
|
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()
|
s.assertSQLMockExpectations()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -487,7 +487,7 @@ func (s *EnterpriseTestSuite) TestGetEnterpriseByIDInvalidEnterpriseID() {
|
||||||
_, err := s.Store.GetEnterpriseByID(s.adminCtx, "dummy-enterprise-id")
|
_, err := s.Store.GetEnterpriseByID(s.adminCtx, "dummy-enterprise-id")
|
||||||
|
|
||||||
s.Require().NotNil(err)
|
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() {
|
func (s *EnterpriseTestSuite) TestGetEnterpriseByIDDBDecryptingErr() {
|
||||||
|
|
@ -508,7 +508,7 @@ func (s *EnterpriseTestSuite) TestGetEnterpriseByIDDBDecryptingErr() {
|
||||||
|
|
||||||
s.assertSQLMockExpectations()
|
s.assertSQLMockExpectations()
|
||||||
s.Require().NotNil(err)
|
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() {
|
func (s *EnterpriseTestSuite) TestCreateEnterprisePool() {
|
||||||
|
|
@ -547,7 +547,7 @@ func (s *EnterpriseTestSuite) TestCreateEnterprisePoolInvalidEnterpriseID() {
|
||||||
_, err := s.Store.CreateEntityPool(s.adminCtx, entity, s.Fixtures.CreatePoolParams)
|
_, err := s.Store.CreateEntityPool(s.adminCtx, entity, s.Fixtures.CreatePoolParams)
|
||||||
|
|
||||||
s.Require().NotNil(err)
|
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() {
|
func (s *EnterpriseTestSuite) TestCreateEnterprisePoolDBFetchTagErr() {
|
||||||
|
|
@ -565,7 +565,7 @@ func (s *EnterpriseTestSuite) TestCreateEnterprisePoolDBFetchTagErr() {
|
||||||
_, err = s.StoreSQLMocked.CreateEntityPool(s.adminCtx, entity, s.Fixtures.CreatePoolParams)
|
_, err = s.StoreSQLMocked.CreateEntityPool(s.adminCtx, entity, s.Fixtures.CreatePoolParams)
|
||||||
|
|
||||||
s.Require().NotNil(err)
|
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()
|
s.assertSQLMockExpectations()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -592,7 +592,7 @@ func (s *EnterpriseTestSuite) TestCreateEnterprisePoolDBAddingPoolErr() {
|
||||||
_, err = s.StoreSQLMocked.CreateEntityPool(s.adminCtx, entity, s.Fixtures.CreatePoolParams)
|
_, err = s.StoreSQLMocked.CreateEntityPool(s.adminCtx, entity, s.Fixtures.CreatePoolParams)
|
||||||
|
|
||||||
s.Require().NotNil(err)
|
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()
|
s.assertSQLMockExpectations()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -623,7 +623,7 @@ func (s *EnterpriseTestSuite) TestCreateEnterprisePoolDBSaveTagErr() {
|
||||||
_, err = s.StoreSQLMocked.CreateEntityPool(s.adminCtx, entity, s.Fixtures.CreatePoolParams)
|
_, err = s.StoreSQLMocked.CreateEntityPool(s.adminCtx, entity, s.Fixtures.CreatePoolParams)
|
||||||
|
|
||||||
s.Require().NotNil(err)
|
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()
|
s.assertSQLMockExpectations()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -663,7 +663,7 @@ func (s *EnterpriseTestSuite) TestCreateEnterprisePoolDBFetchPoolErr() {
|
||||||
_, err = s.StoreSQLMocked.CreateEntityPool(s.adminCtx, entity, s.Fixtures.CreatePoolParams)
|
_, err = s.StoreSQLMocked.CreateEntityPool(s.adminCtx, entity, s.Fixtures.CreatePoolParams)
|
||||||
|
|
||||||
s.Require().NotNil(err)
|
s.Require().NotNil(err)
|
||||||
s.Require().Equal("fetching pool: not found", err.Error())
|
s.Require().Equal("error fetching pool: not found", err.Error())
|
||||||
s.assertSQLMockExpectations()
|
s.assertSQLMockExpectations()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -694,7 +694,7 @@ func (s *EnterpriseTestSuite) TestListEnterprisePoolsInvalidEnterpriseID() {
|
||||||
_, err := s.Store.ListEntityPools(s.adminCtx, entity)
|
_, err := s.Store.ListEntityPools(s.adminCtx, entity)
|
||||||
|
|
||||||
s.Require().NotNil(err)
|
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() {
|
func (s *EnterpriseTestSuite) TestGetEnterprisePool() {
|
||||||
|
|
@ -719,7 +719,7 @@ func (s *EnterpriseTestSuite) TestGetEnterprisePoolInvalidEnterpriseID() {
|
||||||
_, err := s.Store.GetEntityPool(s.adminCtx, entity, "dummy-pool-id")
|
_, err := s.Store.GetEntityPool(s.adminCtx, entity, "dummy-pool-id")
|
||||||
|
|
||||||
s.Require().NotNil(err)
|
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() {
|
func (s *EnterpriseTestSuite) TestDeleteEnterprisePool() {
|
||||||
|
|
@ -734,7 +734,7 @@ func (s *EnterpriseTestSuite) TestDeleteEnterprisePool() {
|
||||||
|
|
||||||
s.Require().Nil(err)
|
s.Require().Nil(err)
|
||||||
_, err = s.Store.GetEntityPool(s.adminCtx, entity, pool.ID)
|
_, 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() {
|
func (s *EnterpriseTestSuite) TestDeleteEnterprisePoolInvalidEnterpriseID() {
|
||||||
|
|
@ -745,7 +745,7 @@ func (s *EnterpriseTestSuite) TestDeleteEnterprisePoolInvalidEnterpriseID() {
|
||||||
err := s.Store.DeleteEntityPool(s.adminCtx, entity, "dummy-pool-id")
|
err := s.Store.DeleteEntityPool(s.adminCtx, entity, "dummy-pool-id")
|
||||||
|
|
||||||
s.Require().NotNil(err)
|
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() {
|
func (s *EnterpriseTestSuite) TestDeleteEnterprisePoolDBDeleteErr() {
|
||||||
|
|
@ -765,7 +765,7 @@ func (s *EnterpriseTestSuite) TestDeleteEnterprisePoolDBDeleteErr() {
|
||||||
|
|
||||||
err = s.StoreSQLMocked.DeleteEntityPool(s.adminCtx, entity, pool.ID)
|
err = s.StoreSQLMocked.DeleteEntityPool(s.adminCtx, entity, pool.ID)
|
||||||
s.Require().NotNil(err)
|
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()
|
s.assertSQLMockExpectations()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -800,7 +800,7 @@ func (s *EnterpriseTestSuite) TestListEnterpriseInstancesInvalidEnterpriseID() {
|
||||||
_, err := s.Store.ListEntityInstances(s.adminCtx, entity)
|
_, err := s.Store.ListEntityInstances(s.adminCtx, entity)
|
||||||
|
|
||||||
s.Require().NotNil(err)
|
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() {
|
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)
|
_, err := s.Store.UpdateEntityPool(s.adminCtx, entity, "dummy-pool-id", s.Fixtures.UpdatePoolParams)
|
||||||
|
|
||||||
s.Require().NotNil(err)
|
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() {
|
func (s *EnterpriseTestSuite) TestAddRepoEntityEvent() {
|
||||||
|
|
|
||||||
|
|
@ -16,9 +16,10 @@ package sql
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
|
|
||||||
runnerErrors "github.com/cloudbase/garm-provider-common/errors"
|
runnerErrors "github.com/cloudbase/garm-provider-common/errors"
|
||||||
|
|
@ -36,7 +37,7 @@ func (s *sqlDatabase) CreateGiteaEndpoint(_ context.Context, param params.Create
|
||||||
var endpoint GithubEndpoint
|
var endpoint GithubEndpoint
|
||||||
err = s.conn.Transaction(func(tx *gorm.DB) error {
|
err = s.conn.Transaction(func(tx *gorm.DB) error {
|
||||||
if err := tx.Where("name = ?", param.Name).First(&endpoint).Error; err == nil {
|
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{
|
endpoint = GithubEndpoint{
|
||||||
Name: param.Name,
|
Name: param.Name,
|
||||||
|
|
@ -48,16 +49,16 @@ func (s *sqlDatabase) CreateGiteaEndpoint(_ context.Context, param params.Create
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := tx.Create(&endpoint).Error; err != nil {
|
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
|
return nil
|
||||||
})
|
})
|
||||||
if err != 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)
|
ghEndpoint, err = s.sqlToCommonGithubEndpoint(endpoint)
|
||||||
if err != nil {
|
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
|
return ghEndpoint, nil
|
||||||
}
|
}
|
||||||
|
|
@ -66,14 +67,14 @@ func (s *sqlDatabase) ListGiteaEndpoints(_ context.Context) ([]params.ForgeEndpo
|
||||||
var endpoints []GithubEndpoint
|
var endpoints []GithubEndpoint
|
||||||
err := s.conn.Where("endpoint_type = ?", params.GiteaEndpointType).Find(&endpoints).Error
|
err := s.conn.Where("endpoint_type = ?", params.GiteaEndpointType).Find(&endpoints).Error
|
||||||
if err != nil {
|
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
|
var ret []params.ForgeEndpoint
|
||||||
for _, ep := range endpoints {
|
for _, ep := range endpoints {
|
||||||
commonEp, err := s.sqlToCommonGithubEndpoint(ep)
|
commonEp, err := s.sqlToCommonGithubEndpoint(ep)
|
||||||
if err != nil {
|
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)
|
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 {
|
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 err := tx.Where("name = ? and endpoint_type = ?", name, params.GiteaEndpointType).First(&endpoint).Error; err != nil {
|
||||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
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
|
var credsCount int64
|
||||||
if err := tx.Model(&GiteaCredentials{}).Where("endpoint_name = ?", endpoint.Name).Count(&credsCount).Error; err != nil {
|
if err := tx.Model(&GiteaCredentials{}).Where("endpoint_name = ?", endpoint.Name).Count(&credsCount).Error; err != nil {
|
||||||
if !errors.Is(err, gorm.ErrRecordNotFound) {
|
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) {
|
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 {
|
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 {
|
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
|
return nil
|
||||||
})
|
})
|
||||||
if err != 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)
|
ghEndpoint, err = s.sqlToCommonGithubEndpoint(endpoint)
|
||||||
if err != nil {
|
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
|
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
|
err := s.conn.Where("name = ? and endpoint_type = ?", name, params.GiteaEndpointType).First(&endpoint).Error
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
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)
|
return s.sqlToCommonGithubEndpoint(endpoint)
|
||||||
|
|
@ -162,41 +163,41 @@ func (s *sqlDatabase) DeleteGiteaEndpoint(_ context.Context, name string) (err e
|
||||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return errors.Wrap(err, "fetching gitea endpoint")
|
return fmt.Errorf("error fetching gitea endpoint: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var credsCount int64
|
var credsCount int64
|
||||||
if err := tx.Model(&GiteaCredentials{}).Where("endpoint_name = ?", endpoint.Name).Count(&credsCount).Error; err != nil {
|
if err := tx.Model(&GiteaCredentials{}).Where("endpoint_name = ?", endpoint.Name).Count(&credsCount).Error; err != nil {
|
||||||
if !errors.Is(err, gorm.ErrRecordNotFound) {
|
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
|
var repoCnt int64
|
||||||
if err := tx.Model(&Repository{}).Where("endpoint_name = ?", endpoint.Name).Count(&repoCnt).Error; err != nil {
|
if err := tx.Model(&Repository{}).Where("endpoint_name = ?", endpoint.Name).Count(&repoCnt).Error; err != nil {
|
||||||
if !errors.Is(err, gorm.ErrRecordNotFound) {
|
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
|
var orgCnt int64
|
||||||
if err := tx.Model(&Organization{}).Where("endpoint_name = ?", endpoint.Name).Count(&orgCnt).Error; err != nil {
|
if err := tx.Model(&Organization{}).Where("endpoint_name = ?", endpoint.Name).Count(&orgCnt).Error; err != nil {
|
||||||
if !errors.Is(err, gorm.ErrRecordNotFound) {
|
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 {
|
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 {
|
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
|
return nil
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "deleting gitea endpoint")
|
return fmt.Errorf("error deleting gitea endpoint: %w", err)
|
||||||
}
|
}
|
||||||
return nil
|
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) {
|
func (s *sqlDatabase) CreateGiteaCredentials(ctx context.Context, param params.CreateGiteaCredentialsParams) (gtCreds params.ForgeCredentials, err error) {
|
||||||
userID, err := getUIDFromContext(ctx)
|
userID, err := getUIDFromContext(ctx)
|
||||||
if err != nil {
|
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 == "" {
|
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() {
|
defer func() {
|
||||||
|
|
@ -220,13 +221,13 @@ func (s *sqlDatabase) CreateGiteaCredentials(ctx context.Context, param params.C
|
||||||
var endpoint GithubEndpoint
|
var endpoint GithubEndpoint
|
||||||
if err := tx.Where("name = ? and endpoint_type = ?", param.Endpoint, params.GiteaEndpointType).First(&endpoint).Error; err != nil {
|
if err := tx.Where("name = ? and endpoint_type = ?", param.Endpoint, params.GiteaEndpointType).First(&endpoint).Error; err != nil {
|
||||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
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 {
|
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
|
var data []byte
|
||||||
|
|
@ -235,10 +236,10 @@ func (s *sqlDatabase) CreateGiteaCredentials(ctx context.Context, param params.C
|
||||||
case params.ForgeAuthTypePAT:
|
case params.ForgeAuthTypePAT:
|
||||||
data, err = s.marshalAndSeal(param.PAT)
|
data, err = s.marshalAndSeal(param.PAT)
|
||||||
default:
|
default:
|
||||||
return errors.Wrap(runnerErrors.ErrBadRequest, "invalid auth type")
|
return runnerErrors.NewBadRequestError("invalid auth type %q", param.AuthType)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "marshaling and sealing credentials")
|
return fmt.Errorf("error marshaling and sealing credentials: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
creds = GiteaCredentials{
|
creds = GiteaCredentials{
|
||||||
|
|
@ -251,7 +252,7 @@ func (s *sqlDatabase) CreateGiteaCredentials(ctx context.Context, param params.C
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := tx.Create(&creds).Error; err != nil {
|
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.
|
// Skip making an extra query.
|
||||||
creds.Endpoint = endpoint
|
creds.Endpoint = endpoint
|
||||||
|
|
@ -259,11 +260,11 @@ func (s *sqlDatabase) CreateGiteaCredentials(ctx context.Context, param params.C
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
if err != 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)
|
gtCreds, err = s.sqlGiteaToCommonForgeCredentials(creds)
|
||||||
if err != nil {
|
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
|
return gtCreds, nil
|
||||||
}
|
}
|
||||||
|
|
@ -284,16 +285,16 @@ func (s *sqlDatabase) getGiteaCredentialsByName(ctx context.Context, tx *gorm.DB
|
||||||
|
|
||||||
userID, err := getUIDFromContext(ctx)
|
userID, err := getUIDFromContext(ctx)
|
||||||
if err != nil {
|
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)
|
q = q.Where("user_id = ?", userID)
|
||||||
|
|
||||||
err = q.Where("name = ?", name).First(&creds).Error
|
err = q.Where("name = ?", name).First(&creds).Error
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
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
|
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) {
|
func (s *sqlDatabase) GetGiteaCredentialsByName(ctx context.Context, name string, detailed bool) (params.ForgeCredentials, error) {
|
||||||
creds, err := s.getGiteaCredentialsByName(ctx, s.conn, name, detailed)
|
creds, err := s.getGiteaCredentialsByName(ctx, s.conn, name, detailed)
|
||||||
if err != nil {
|
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)
|
return s.sqlGiteaToCommonForgeCredentials(creds)
|
||||||
|
|
@ -325,7 +326,7 @@ func (s *sqlDatabase) GetGiteaCredentials(ctx context.Context, id uint, detailed
|
||||||
if !auth.IsAdmin(ctx) {
|
if !auth.IsAdmin(ctx) {
|
||||||
userID, err := getUIDFromContext(ctx)
|
userID, err := getUIDFromContext(ctx)
|
||||||
if err != nil {
|
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)
|
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
|
err := q.Where("id = ?", id).First(&creds).Error
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
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)
|
return s.sqlGiteaToCommonForgeCredentials(creds)
|
||||||
|
|
@ -346,7 +347,7 @@ func (s *sqlDatabase) ListGiteaCredentials(ctx context.Context) ([]params.ForgeC
|
||||||
if !auth.IsAdmin(ctx) {
|
if !auth.IsAdmin(ctx) {
|
||||||
userID, err := getUIDFromContext(ctx)
|
userID, err := getUIDFromContext(ctx)
|
||||||
if err != nil {
|
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)
|
q = q.Where("user_id = ?", userID)
|
||||||
}
|
}
|
||||||
|
|
@ -354,14 +355,14 @@ func (s *sqlDatabase) ListGiteaCredentials(ctx context.Context) ([]params.ForgeC
|
||||||
var creds []GiteaCredentials
|
var creds []GiteaCredentials
|
||||||
err := q.Preload("Endpoint").Find(&creds).Error
|
err := q.Preload("Endpoint").Find(&creds).Error
|
||||||
if err != nil {
|
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
|
var ret []params.ForgeCredentials
|
||||||
for _, c := range creds {
|
for _, c := range creds {
|
||||||
commonCreds, err := s.sqlGiteaToCommonForgeCredentials(c)
|
commonCreds, err := s.sqlGiteaToCommonForgeCredentials(c)
|
||||||
if err != nil {
|
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)
|
ret = append(ret, commonCreds)
|
||||||
}
|
}
|
||||||
|
|
@ -380,16 +381,16 @@ func (s *sqlDatabase) UpdateGiteaCredentials(ctx context.Context, id uint, param
|
||||||
if !auth.IsAdmin(ctx) {
|
if !auth.IsAdmin(ctx) {
|
||||||
userID, err := getUIDFromContext(ctx)
|
userID, err := getUIDFromContext(ctx)
|
||||||
if err != nil {
|
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)
|
q = q.Where("user_id = ?", userID)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := q.Where("id = ?", id).First(&creds).Error; err != nil {
|
if err := q.Where("id = ?", id).First(&creds).Error; err != nil {
|
||||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
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 {
|
if param.Name != nil {
|
||||||
|
|
@ -407,28 +408,28 @@ func (s *sqlDatabase) UpdateGiteaCredentials(ctx context.Context, id uint, param
|
||||||
data, err = s.marshalAndSeal(param.PAT)
|
data, err = s.marshalAndSeal(param.PAT)
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
return errors.Wrap(runnerErrors.ErrBadRequest, "invalid auth type")
|
return runnerErrors.NewBadRequestError("invalid auth type %q", creds.AuthType)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
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 {
|
if len(data) > 0 {
|
||||||
creds.Payload = data
|
creds.Payload = data
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := tx.Save(&creds).Error; err != nil {
|
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
|
return nil
|
||||||
})
|
})
|
||||||
if err != 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)
|
gtCreds, err = s.sqlGiteaToCommonForgeCredentials(creds)
|
||||||
if err != nil {
|
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
|
return gtCreds, nil
|
||||||
}
|
}
|
||||||
|
|
@ -454,7 +455,7 @@ func (s *sqlDatabase) DeleteGiteaCredentials(ctx context.Context, id uint) (err
|
||||||
if !auth.IsAdmin(ctx) {
|
if !auth.IsAdmin(ctx) {
|
||||||
userID, err := getUIDFromContext(ctx)
|
userID, err := getUIDFromContext(ctx)
|
||||||
if err != nil {
|
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)
|
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) {
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return errors.Wrap(err, "fetching gitea credentials")
|
return fmt.Errorf("error fetching gitea credentials: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(creds.Repositories) > 0 {
|
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 {
|
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 {
|
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
|
return nil
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "deleting gitea credentials")
|
return fmt.Errorf("error deleting gitea credentials: %w", err)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -236,7 +236,7 @@ func (s *GiteaTestSuite) TestCreateCredentialsFailsWhenEndpointDoesNotExist() {
|
||||||
_, err := s.db.CreateGiteaCredentials(ctx, params.CreateGiteaCredentialsParams{Endpoint: "non-existing"})
|
_, err := s.db.CreateGiteaCredentials(ctx, params.CreateGiteaCredentialsParams{Endpoint: "non-existing"})
|
||||||
s.Require().Error(err)
|
s.Require().Error(err)
|
||||||
s.Require().ErrorIs(err, runnerErrors.ErrNotFound)
|
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() {
|
func (s *GiteaTestSuite) TestCreateCredentialsFailsWhenAuthTypeIsInvalid() {
|
||||||
|
|
@ -807,7 +807,7 @@ func (s *GiteaTestSuite) TestUpdateEndpointURLsFailsIfCredentialsAreAssociated()
|
||||||
_, err = s.db.UpdateGiteaEndpoint(ctx, testEndpointName, updateEpParams)
|
_, err = s.db.UpdateGiteaEndpoint(ctx, testEndpointName, updateEpParams)
|
||||||
s.Require().Error(err)
|
s.Require().Error(err)
|
||||||
s.Require().ErrorIs(err, runnerErrors.ErrBadRequest)
|
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{
|
updateEpParams = params.UpdateGiteaEndpointParams{
|
||||||
APIBaseURL: &newAPIBaseURL,
|
APIBaseURL: &newAPIBaseURL,
|
||||||
|
|
@ -815,7 +815,7 @@ func (s *GiteaTestSuite) TestUpdateEndpointURLsFailsIfCredentialsAreAssociated()
|
||||||
_, err = s.db.UpdateGiteaEndpoint(ctx, testEndpointName, updateEpParams)
|
_, err = s.db.UpdateGiteaEndpoint(ctx, testEndpointName, updateEpParams)
|
||||||
s.Require().Error(err)
|
s.Require().Error(err)
|
||||||
s.Require().ErrorIs(err, runnerErrors.ErrBadRequest)
|
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{
|
updateEpParams = params.UpdateGiteaEndpointParams{
|
||||||
Description: &newDescription,
|
Description: &newDescription,
|
||||||
|
|
|
||||||
|
|
@ -16,8 +16,9 @@ package sql
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
|
|
||||||
runnerErrors "github.com/cloudbase/garm-provider-common/errors"
|
runnerErrors "github.com/cloudbase/garm-provider-common/errors"
|
||||||
|
|
@ -35,7 +36,7 @@ func (s *sqlDatabase) CreateGithubEndpoint(_ context.Context, param params.Creat
|
||||||
var endpoint GithubEndpoint
|
var endpoint GithubEndpoint
|
||||||
err = s.conn.Transaction(func(tx *gorm.DB) error {
|
err = s.conn.Transaction(func(tx *gorm.DB) error {
|
||||||
if err := tx.Where("name = ?", param.Name).First(&endpoint).Error; err == nil {
|
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{
|
endpoint = GithubEndpoint{
|
||||||
Name: param.Name,
|
Name: param.Name,
|
||||||
|
|
@ -48,16 +49,16 @@ func (s *sqlDatabase) CreateGithubEndpoint(_ context.Context, param params.Creat
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := tx.Create(&endpoint).Error; err != nil {
|
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
|
return nil
|
||||||
})
|
})
|
||||||
if err != 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)
|
ghEndpoint, err = s.sqlToCommonGithubEndpoint(endpoint)
|
||||||
if err != nil {
|
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
|
return ghEndpoint, nil
|
||||||
}
|
}
|
||||||
|
|
@ -66,14 +67,14 @@ func (s *sqlDatabase) ListGithubEndpoints(_ context.Context) ([]params.ForgeEndp
|
||||||
var endpoints []GithubEndpoint
|
var endpoints []GithubEndpoint
|
||||||
err := s.conn.Where("endpoint_type = ?", params.GithubEndpointType).Find(&endpoints).Error
|
err := s.conn.Where("endpoint_type = ?", params.GithubEndpointType).Find(&endpoints).Error
|
||||||
if err != nil {
|
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
|
var ret []params.ForgeEndpoint
|
||||||
for _, ep := range endpoints {
|
for _, ep := range endpoints {
|
||||||
commonEp, err := s.sqlToCommonGithubEndpoint(ep)
|
commonEp, err := s.sqlToCommonGithubEndpoint(ep)
|
||||||
if err != nil {
|
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)
|
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 {
|
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 err := tx.Where("name = ? and endpoint_type = ?", name, params.GithubEndpointType).First(&endpoint).Error; err != nil {
|
||||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
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
|
var credsCount int64
|
||||||
if err := tx.Model(&GithubCredentials{}).Where("endpoint_name = ?", endpoint.Name).Count(&credsCount).Error; err != nil {
|
if err := tx.Model(&GithubCredentials{}).Where("endpoint_name = ?", endpoint.Name).Count(&credsCount).Error; err != nil {
|
||||||
if !errors.Is(err, gorm.ErrRecordNotFound) {
|
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) {
|
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 {
|
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 {
|
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
|
return nil
|
||||||
})
|
})
|
||||||
if err != 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)
|
ghEndpoint, err = s.sqlToCommonGithubEndpoint(endpoint)
|
||||||
if err != nil {
|
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
|
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
|
err := s.conn.Where("name = ? and endpoint_type = ?", name, params.GithubEndpointType).First(&endpoint).Error
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
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)
|
return s.sqlToCommonGithubEndpoint(endpoint)
|
||||||
|
|
@ -167,48 +168,48 @@ func (s *sqlDatabase) DeleteGithubEndpoint(_ context.Context, name string) (err
|
||||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return errors.Wrap(err, "fetching github endpoint")
|
return fmt.Errorf("error fetching github endpoint: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var credsCount int64
|
var credsCount int64
|
||||||
if err := tx.Model(&GithubCredentials{}).Where("endpoint_name = ?", endpoint.Name).Count(&credsCount).Error; err != nil {
|
if err := tx.Model(&GithubCredentials{}).Where("endpoint_name = ?", endpoint.Name).Count(&credsCount).Error; err != nil {
|
||||||
if !errors.Is(err, gorm.ErrRecordNotFound) {
|
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
|
var repoCnt int64
|
||||||
if err := tx.Model(&Repository{}).Where("endpoint_name = ?", endpoint.Name).Count(&repoCnt).Error; err != nil {
|
if err := tx.Model(&Repository{}).Where("endpoint_name = ?", endpoint.Name).Count(&repoCnt).Error; err != nil {
|
||||||
if !errors.Is(err, gorm.ErrRecordNotFound) {
|
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
|
var orgCnt int64
|
||||||
if err := tx.Model(&Organization{}).Where("endpoint_name = ?", endpoint.Name).Count(&orgCnt).Error; err != nil {
|
if err := tx.Model(&Organization{}).Where("endpoint_name = ?", endpoint.Name).Count(&orgCnt).Error; err != nil {
|
||||||
if !errors.Is(err, gorm.ErrRecordNotFound) {
|
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
|
var entCnt int64
|
||||||
if err := tx.Model(&Enterprise{}).Where("endpoint_name = ?", endpoint.Name).Count(&entCnt).Error; err != nil {
|
if err := tx.Model(&Enterprise{}).Where("endpoint_name = ?", endpoint.Name).Count(&entCnt).Error; err != nil {
|
||||||
if !errors.Is(err, gorm.ErrRecordNotFound) {
|
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 {
|
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 {
|
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
|
return nil
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "deleting github endpoint")
|
return fmt.Errorf("error deleting github endpoint: %w", err)
|
||||||
}
|
}
|
||||||
return nil
|
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) {
|
func (s *sqlDatabase) CreateGithubCredentials(ctx context.Context, param params.CreateGithubCredentialsParams) (ghCreds params.ForgeCredentials, err error) {
|
||||||
userID, err := getUIDFromContext(ctx)
|
userID, err := getUIDFromContext(ctx)
|
||||||
if err != nil {
|
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 == "" {
|
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() {
|
defer func() {
|
||||||
|
|
@ -232,13 +233,13 @@ func (s *sqlDatabase) CreateGithubCredentials(ctx context.Context, param params.
|
||||||
var endpoint GithubEndpoint
|
var endpoint GithubEndpoint
|
||||||
if err := tx.Where("name = ? and endpoint_type = ?", param.Endpoint, params.GithubEndpointType).First(&endpoint).Error; err != nil {
|
if err := tx.Where("name = ? and endpoint_type = ?", param.Endpoint, params.GithubEndpointType).First(&endpoint).Error; err != nil {
|
||||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
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 {
|
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
|
var data []byte
|
||||||
|
|
@ -249,10 +250,10 @@ func (s *sqlDatabase) CreateGithubCredentials(ctx context.Context, param params.
|
||||||
case params.ForgeAuthTypeApp:
|
case params.ForgeAuthTypeApp:
|
||||||
data, err = s.marshalAndSeal(param.App)
|
data, err = s.marshalAndSeal(param.App)
|
||||||
default:
|
default:
|
||||||
return errors.Wrap(runnerErrors.ErrBadRequest, "invalid auth type")
|
return fmt.Errorf("invalid auth type: %w", runnerErrors.ErrBadRequest)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "marshaling and sealing credentials")
|
return fmt.Errorf("error marshaling and sealing credentials: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
creds = GithubCredentials{
|
creds = GithubCredentials{
|
||||||
|
|
@ -265,7 +266,7 @@ func (s *sqlDatabase) CreateGithubCredentials(ctx context.Context, param params.
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := tx.Create(&creds).Error; err != nil {
|
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.
|
// Skip making an extra query.
|
||||||
creds.Endpoint = endpoint
|
creds.Endpoint = endpoint
|
||||||
|
|
@ -273,11 +274,11 @@ func (s *sqlDatabase) CreateGithubCredentials(ctx context.Context, param params.
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
if err != 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)
|
ghCreds, err = s.sqlToCommonForgeCredentials(creds)
|
||||||
if err != nil {
|
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
|
return ghCreds, nil
|
||||||
}
|
}
|
||||||
|
|
@ -298,16 +299,16 @@ func (s *sqlDatabase) getGithubCredentialsByName(ctx context.Context, tx *gorm.D
|
||||||
|
|
||||||
userID, err := getUIDFromContext(ctx)
|
userID, err := getUIDFromContext(ctx)
|
||||||
if err != nil {
|
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)
|
q = q.Where("user_id = ?", userID)
|
||||||
|
|
||||||
err = q.Where("name = ?", name).First(&creds).Error
|
err = q.Where("name = ?", name).First(&creds).Error
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
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
|
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) {
|
func (s *sqlDatabase) GetGithubCredentialsByName(ctx context.Context, name string, detailed bool) (params.ForgeCredentials, error) {
|
||||||
creds, err := s.getGithubCredentialsByName(ctx, s.conn, name, detailed)
|
creds, err := s.getGithubCredentialsByName(ctx, s.conn, name, detailed)
|
||||||
if err != nil {
|
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)
|
return s.sqlToCommonForgeCredentials(creds)
|
||||||
}
|
}
|
||||||
|
|
@ -338,7 +339,7 @@ func (s *sqlDatabase) GetGithubCredentials(ctx context.Context, id uint, detaile
|
||||||
if !auth.IsAdmin(ctx) {
|
if !auth.IsAdmin(ctx) {
|
||||||
userID, err := getUIDFromContext(ctx)
|
userID, err := getUIDFromContext(ctx)
|
||||||
if err != nil {
|
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)
|
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
|
err := q.Where("id = ?", id).First(&creds).Error
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
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)
|
return s.sqlToCommonForgeCredentials(creds)
|
||||||
|
|
@ -359,7 +360,7 @@ func (s *sqlDatabase) ListGithubCredentials(ctx context.Context) ([]params.Forge
|
||||||
if !auth.IsAdmin(ctx) {
|
if !auth.IsAdmin(ctx) {
|
||||||
userID, err := getUIDFromContext(ctx)
|
userID, err := getUIDFromContext(ctx)
|
||||||
if err != nil {
|
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)
|
q = q.Where("user_id = ?", userID)
|
||||||
}
|
}
|
||||||
|
|
@ -367,14 +368,14 @@ func (s *sqlDatabase) ListGithubCredentials(ctx context.Context) ([]params.Forge
|
||||||
var creds []GithubCredentials
|
var creds []GithubCredentials
|
||||||
err := q.Preload("Endpoint").Find(&creds).Error
|
err := q.Preload("Endpoint").Find(&creds).Error
|
||||||
if err != nil {
|
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
|
var ret []params.ForgeCredentials
|
||||||
for _, c := range creds {
|
for _, c := range creds {
|
||||||
commonCreds, err := s.sqlToCommonForgeCredentials(c)
|
commonCreds, err := s.sqlToCommonForgeCredentials(c)
|
||||||
if err != nil {
|
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)
|
ret = append(ret, commonCreds)
|
||||||
}
|
}
|
||||||
|
|
@ -393,16 +394,16 @@ func (s *sqlDatabase) UpdateGithubCredentials(ctx context.Context, id uint, para
|
||||||
if !auth.IsAdmin(ctx) {
|
if !auth.IsAdmin(ctx) {
|
||||||
userID, err := getUIDFromContext(ctx)
|
userID, err := getUIDFromContext(ctx)
|
||||||
if err != nil {
|
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)
|
q = q.Where("user_id = ?", userID)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := q.Where("id = ?", id).First(&creds).Error; err != nil {
|
if err := q.Where("id = ?", id).First(&creds).Error; err != nil {
|
||||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
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 {
|
if param.Name != nil {
|
||||||
|
|
@ -421,7 +422,7 @@ func (s *sqlDatabase) UpdateGithubCredentials(ctx context.Context, id uint, para
|
||||||
}
|
}
|
||||||
|
|
||||||
if param.App != nil {
|
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:
|
case params.ForgeAuthTypeApp:
|
||||||
if param.App != nil {
|
if param.App != nil {
|
||||||
|
|
@ -429,33 +430,33 @@ func (s *sqlDatabase) UpdateGithubCredentials(ctx context.Context, id uint, para
|
||||||
}
|
}
|
||||||
|
|
||||||
if param.PAT != nil {
|
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:
|
default:
|
||||||
// This should never happen, unless there was a bug in the DB migration code,
|
// This should never happen, unless there was a bug in the DB migration code,
|
||||||
// or the DB was manually modified.
|
// 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 {
|
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 {
|
if len(data) > 0 {
|
||||||
creds.Payload = data
|
creds.Payload = data
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := tx.Save(&creds).Error; err != nil {
|
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
|
return nil
|
||||||
})
|
})
|
||||||
if err != 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)
|
ghCreds, err = s.sqlToCommonForgeCredentials(creds)
|
||||||
if err != nil {
|
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
|
return ghCreds, nil
|
||||||
}
|
}
|
||||||
|
|
@ -475,7 +476,7 @@ func (s *sqlDatabase) DeleteGithubCredentials(ctx context.Context, id uint) (err
|
||||||
if !auth.IsAdmin(ctx) {
|
if !auth.IsAdmin(ctx) {
|
||||||
userID, err := getUIDFromContext(ctx)
|
userID, err := getUIDFromContext(ctx)
|
||||||
if err != nil {
|
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)
|
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) {
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return errors.Wrap(err, "fetching github credentials")
|
return fmt.Errorf("error fetching github credentials: %w", err)
|
||||||
}
|
}
|
||||||
name = creds.Name
|
name = creds.Name
|
||||||
|
|
||||||
if len(creds.Repositories) > 0 {
|
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 {
|
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 {
|
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 {
|
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
|
return nil
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "deleting github credentials")
|
return fmt.Errorf("error deleting github credentials: %w", err)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -265,7 +265,7 @@ func (s *GithubTestSuite) TestUpdateEndpointURLsFailsIfCredentialsAreAssociated(
|
||||||
_, err = s.db.UpdateGithubEndpoint(ctx, testEndpointName, updateEpParams)
|
_, err = s.db.UpdateGithubEndpoint(ctx, testEndpointName, updateEpParams)
|
||||||
s.Require().Error(err)
|
s.Require().Error(err)
|
||||||
s.Require().ErrorIs(err, runnerErrors.ErrBadRequest)
|
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{
|
updateEpParams = params.UpdateGithubEndpointParams{
|
||||||
UploadBaseURL: &newUploadBaseURL,
|
UploadBaseURL: &newUploadBaseURL,
|
||||||
|
|
@ -274,7 +274,7 @@ func (s *GithubTestSuite) TestUpdateEndpointURLsFailsIfCredentialsAreAssociated(
|
||||||
_, err = s.db.UpdateGithubEndpoint(ctx, testEndpointName, updateEpParams)
|
_, err = s.db.UpdateGithubEndpoint(ctx, testEndpointName, updateEpParams)
|
||||||
s.Require().Error(err)
|
s.Require().Error(err)
|
||||||
s.Require().ErrorIs(err, runnerErrors.ErrBadRequest)
|
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{
|
updateEpParams = params.UpdateGithubEndpointParams{
|
||||||
APIBaseURL: &newAPIBaseURL,
|
APIBaseURL: &newAPIBaseURL,
|
||||||
|
|
@ -282,7 +282,7 @@ func (s *GithubTestSuite) TestUpdateEndpointURLsFailsIfCredentialsAreAssociated(
|
||||||
_, err = s.db.UpdateGithubEndpoint(ctx, testEndpointName, updateEpParams)
|
_, err = s.db.UpdateGithubEndpoint(ctx, testEndpointName, updateEpParams)
|
||||||
s.Require().Error(err)
|
s.Require().Error(err)
|
||||||
s.Require().ErrorIs(err, runnerErrors.ErrBadRequest)
|
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{
|
updateEpParams = params.UpdateGithubEndpointParams{
|
||||||
Description: &newDescription,
|
Description: &newDescription,
|
||||||
|
|
@ -737,7 +737,7 @@ func (s *GithubTestSuite) TestUpdateGithubCredentialsFailIfWrongCredentialTypeIs
|
||||||
_, err = s.db.UpdateGithubCredentials(ctx, creds.ID, updateCredParams)
|
_, err = s.db.UpdateGithubCredentials(ctx, creds.ID, updateCredParams)
|
||||||
s.Require().Error(err)
|
s.Require().Error(err)
|
||||||
s.Require().ErrorIs(err, runnerErrors.ErrBadRequest)
|
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{
|
credParamsWithApp := params.CreateGithubCredentialsParams{
|
||||||
Name: "test-credsApp",
|
Name: "test-credsApp",
|
||||||
|
|
@ -764,7 +764,7 @@ func (s *GithubTestSuite) TestUpdateGithubCredentialsFailIfWrongCredentialTypeIs
|
||||||
_, err = s.db.UpdateGithubCredentials(ctx, credsApp.ID, updateCredParams)
|
_, err = s.db.UpdateGithubCredentials(ctx, credsApp.ID, updateCredParams)
|
||||||
s.Require().Error(err)
|
s.Require().Error(err)
|
||||||
s.Require().ErrorIs(err, runnerErrors.ErrBadRequest)
|
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() {
|
func (s *GithubTestSuite) TestUpdateCredentialsFailsForNonExistingCredentials() {
|
||||||
|
|
|
||||||
|
|
@ -17,10 +17,11 @@ package sql
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
|
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
"github.com/pkg/errors"
|
|
||||||
"gorm.io/datatypes"
|
"gorm.io/datatypes"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
"gorm.io/gorm/clause"
|
"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) {
|
func (s *sqlDatabase) CreateInstance(_ context.Context, poolID string, param params.CreateInstanceParams) (instance params.Instance, err error) {
|
||||||
pool, err := s.getPoolByID(s.conn, poolID)
|
pool, err := s.getPoolByID(s.conn, poolID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return params.Instance{}, errors.Wrap(err, "fetching pool")
|
return params.Instance{}, fmt.Errorf("error fetching pool: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
|
|
@ -46,7 +47,7 @@ func (s *sqlDatabase) CreateInstance(_ context.Context, poolID string, param par
|
||||||
if len(param.AditionalLabels) > 0 {
|
if len(param.AditionalLabels) > 0 {
|
||||||
labels, err = json.Marshal(param.AditionalLabels)
|
labels, err = json.Marshal(param.AditionalLabels)
|
||||||
if err != nil {
|
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 {
|
if len(param.JitConfiguration) > 0 {
|
||||||
secret, err = s.marshalAndSeal(param.JitConfiguration)
|
secret, err = s.marshalAndSeal(param.JitConfiguration)
|
||||||
if err != nil {
|
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)
|
q := s.conn.Create(&newInstance)
|
||||||
if q.Error != nil {
|
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)
|
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) {
|
func (s *sqlDatabase) getPoolInstanceByName(poolID string, instanceName string) (Instance, error) {
|
||||||
pool, err := s.getPoolByID(s.conn, poolID)
|
pool, err := s.getPoolByID(s.conn, poolID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return Instance{}, errors.Wrap(err, "fetching pool")
|
return Instance{}, fmt.Errorf("error fetching pool: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var instance Instance
|
var instance Instance
|
||||||
|
|
@ -93,9 +94,9 @@ func (s *sqlDatabase) getPoolInstanceByName(poolID string, instanceName string)
|
||||||
First(&instance)
|
First(&instance)
|
||||||
if q.Error != nil {
|
if q.Error != nil {
|
||||||
if errors.Is(q.Error, gorm.ErrRecordNotFound) {
|
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
|
instance.Pool = pool
|
||||||
|
|
@ -119,9 +120,9 @@ func (s *sqlDatabase) getInstanceByName(_ context.Context, instanceName string,
|
||||||
First(&instance)
|
First(&instance)
|
||||||
if q.Error != nil {
|
if q.Error != nil {
|
||||||
if errors.Is(q.Error, gorm.ErrRecordNotFound) {
|
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
|
return instance, nil
|
||||||
}
|
}
|
||||||
|
|
@ -129,7 +130,7 @@ func (s *sqlDatabase) getInstanceByName(_ context.Context, instanceName string,
|
||||||
func (s *sqlDatabase) GetPoolInstanceByName(_ context.Context, poolID string, instanceName string) (params.Instance, error) {
|
func (s *sqlDatabase) GetPoolInstanceByName(_ context.Context, poolID string, instanceName string) (params.Instance, error) {
|
||||||
instance, err := s.getPoolInstanceByName(poolID, instanceName)
|
instance, err := s.getPoolInstanceByName(poolID, instanceName)
|
||||||
if err != nil {
|
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)
|
return s.sqlToParamsInstance(instance)
|
||||||
|
|
@ -138,7 +139,7 @@ func (s *sqlDatabase) GetPoolInstanceByName(_ context.Context, poolID string, in
|
||||||
func (s *sqlDatabase) GetInstanceByName(ctx context.Context, instanceName string) (params.Instance, error) {
|
func (s *sqlDatabase) GetInstanceByName(ctx context.Context, instanceName string) (params.Instance, error) {
|
||||||
instance, err := s.getInstanceByName(ctx, instanceName, "StatusMessages", "Pool", "ScaleSet")
|
instance, err := s.getInstanceByName(ctx, instanceName, "StatusMessages", "Pool", "ScaleSet")
|
||||||
if err != nil {
|
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)
|
return s.sqlToParamsInstance(instance)
|
||||||
|
|
@ -150,7 +151,7 @@ func (s *sqlDatabase) DeleteInstance(_ context.Context, poolID string, instanceN
|
||||||
if errors.Is(err, runnerErrors.ErrNotFound) {
|
if errors.Is(err, runnerErrors.ErrNotFound) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return errors.Wrap(err, "deleting instance")
|
return fmt.Errorf("error deleting instance: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
|
|
@ -182,7 +183,7 @@ func (s *sqlDatabase) DeleteInstance(_ context.Context, poolID string, instanceN
|
||||||
if errors.Is(q.Error, gorm.ErrRecordNotFound) {
|
if errors.Is(q.Error, gorm.ErrRecordNotFound) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return errors.Wrap(q.Error, "deleting instance")
|
return fmt.Errorf("error deleting instance: %w", q.Error)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -193,7 +194,7 @@ func (s *sqlDatabase) DeleteInstanceByName(ctx context.Context, instanceName str
|
||||||
if errors.Is(err, runnerErrors.ErrNotFound) {
|
if errors.Is(err, runnerErrors.ErrNotFound) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return errors.Wrap(err, "deleting instance")
|
return fmt.Errorf("error deleting instance: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
|
|
@ -224,7 +225,7 @@ func (s *sqlDatabase) DeleteInstanceByName(ctx context.Context, instanceName str
|
||||||
if errors.Is(q.Error, gorm.ErrRecordNotFound) {
|
if errors.Is(q.Error, gorm.ErrRecordNotFound) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return errors.Wrap(q.Error, "deleting instance")
|
return fmt.Errorf("error deleting instance: %w", q.Error)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -232,7 +233,7 @@ func (s *sqlDatabase) DeleteInstanceByName(ctx context.Context, instanceName str
|
||||||
func (s *sqlDatabase) AddInstanceEvent(ctx context.Context, instanceName string, event params.EventType, eventLevel params.EventLevel, statusMessage string) error {
|
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.getInstanceByName(ctx, instanceName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "updating instance")
|
return fmt.Errorf("error updating instance: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
msg := InstanceStatusUpdate{
|
msg := InstanceStatusUpdate{
|
||||||
|
|
@ -242,7 +243,7 @@ func (s *sqlDatabase) AddInstanceEvent(ctx context.Context, instanceName string,
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := s.conn.Model(&instance).Association("StatusMessages").Append(&msg); err != nil {
|
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
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -250,7 +251,7 @@ func (s *sqlDatabase) AddInstanceEvent(ctx context.Context, instanceName string,
|
||||||
func (s *sqlDatabase) UpdateInstance(ctx context.Context, instanceName string, param params.UpdateInstanceParams) (params.Instance, error) {
|
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.getInstanceByName(ctx, instanceName, "Pool", "ScaleSet")
|
||||||
if err != nil {
|
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 {
|
if param.AgentID != 0 {
|
||||||
|
|
@ -287,7 +288,7 @@ func (s *sqlDatabase) UpdateInstance(ctx context.Context, instanceName string, p
|
||||||
if param.JitConfiguration != nil {
|
if param.JitConfiguration != nil {
|
||||||
secret, err := s.marshalAndSeal(param.JitConfiguration)
|
secret, err := s.marshalAndSeal(param.JitConfiguration)
|
||||||
if err != nil {
|
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
|
instance.JitConfiguration = secret
|
||||||
}
|
}
|
||||||
|
|
@ -296,7 +297,7 @@ func (s *sqlDatabase) UpdateInstance(ctx context.Context, instanceName string, p
|
||||||
|
|
||||||
q := s.conn.Save(&instance)
|
q := s.conn.Save(&instance)
|
||||||
if q.Error != nil {
|
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 {
|
if len(param.Addresses) > 0 {
|
||||||
|
|
@ -308,12 +309,12 @@ func (s *sqlDatabase) UpdateInstance(ctx context.Context, instanceName string, p
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
if err := s.conn.Model(&instance).Association("Addresses").Replace(addrs); err != nil {
|
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)
|
inst, err := s.sqlToParamsInstance(instance)
|
||||||
if err != nil {
|
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)
|
s.sendNotify(common.InstanceEntityType, common.UpdateOperation, inst)
|
||||||
return inst, nil
|
return inst, nil
|
||||||
|
|
@ -322,7 +323,7 @@ func (s *sqlDatabase) UpdateInstance(ctx context.Context, instanceName string, p
|
||||||
func (s *sqlDatabase) ListPoolInstances(_ context.Context, poolID string) ([]params.Instance, error) {
|
func (s *sqlDatabase) ListPoolInstances(_ context.Context, poolID string) ([]params.Instance, error) {
|
||||||
u, err := uuid.Parse(poolID)
|
u, err := uuid.Parse(poolID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(runnerErrors.ErrBadRequest, "parsing id")
|
return nil, fmt.Errorf("error parsing id: %w", runnerErrors.ErrBadRequest)
|
||||||
}
|
}
|
||||||
|
|
||||||
var instances []Instance
|
var instances []Instance
|
||||||
|
|
@ -332,14 +333,14 @@ func (s *sqlDatabase) ListPoolInstances(_ context.Context, poolID string) ([]par
|
||||||
Where("pool_id = ?", u)
|
Where("pool_id = ?", u)
|
||||||
|
|
||||||
if err := query.Find(&instances); err.Error != nil {
|
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))
|
ret := make([]params.Instance, len(instances))
|
||||||
for idx, inst := range instances {
|
for idx, inst := range instances {
|
||||||
ret[idx], err = s.sqlToParamsInstance(inst)
|
ret[idx], err = s.sqlToParamsInstance(inst)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "converting instance")
|
return nil, fmt.Errorf("error converting instance: %w", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ret, nil
|
return ret, nil
|
||||||
|
|
@ -354,14 +355,14 @@ func (s *sqlDatabase) ListAllInstances(_ context.Context) ([]params.Instance, er
|
||||||
Preload("Job").
|
Preload("Job").
|
||||||
Find(&instances)
|
Find(&instances)
|
||||||
if q.Error != nil {
|
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))
|
ret := make([]params.Instance, len(instances))
|
||||||
var err error
|
var err error
|
||||||
for idx, instance := range instances {
|
for idx, instance := range instances {
|
||||||
ret[idx], err = s.sqlToParamsInstance(instance)
|
ret[idx], err = s.sqlToParamsInstance(instance)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "converting instance")
|
return nil, fmt.Errorf("error converting instance: %w", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ret, nil
|
return ret, nil
|
||||||
|
|
@ -370,13 +371,13 @@ func (s *sqlDatabase) ListAllInstances(_ context.Context) ([]params.Instance, er
|
||||||
func (s *sqlDatabase) PoolInstanceCount(_ context.Context, poolID string) (int64, error) {
|
func (s *sqlDatabase) PoolInstanceCount(_ context.Context, poolID string) (int64, error) {
|
||||||
pool, err := s.getPoolByID(s.conn, poolID)
|
pool, err := s.getPoolByID(s.conn, poolID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, errors.Wrap(err, "fetching pool")
|
return 0, fmt.Errorf("error fetching pool: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var cnt int64
|
var cnt int64
|
||||||
q := s.conn.Model(&Instance{}).Where("pool_id = ?", pool.ID).Count(&cnt)
|
q := s.conn.Model(&Instance{}).Where("pool_id = ?", pool.ID).Count(&cnt)
|
||||||
if q.Error != nil {
|
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
|
return cnt, nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -210,7 +210,7 @@ func (s *InstancesTestSuite) TestCreateInstance() {
|
||||||
func (s *InstancesTestSuite) TestCreateInstanceInvalidPoolID() {
|
func (s *InstancesTestSuite) TestCreateInstanceInvalidPoolID() {
|
||||||
_, err := s.Store.CreateInstance(s.adminCtx, "dummy-pool-id", params.CreateInstanceParams{})
|
_, 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() {
|
func (s *InstancesTestSuite) TestCreateInstanceDBCreateErr() {
|
||||||
|
|
@ -233,7 +233,7 @@ func (s *InstancesTestSuite) TestCreateInstanceDBCreateErr() {
|
||||||
|
|
||||||
s.assertSQLMockExpectations()
|
s.assertSQLMockExpectations()
|
||||||
s.Require().NotNil(err)
|
s.Require().NotNil(err)
|
||||||
s.Require().Equal("creating instance: mocked insert instance error", err.Error())
|
s.Require().Equal("error creating instance: mocked insert instance error", err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *InstancesTestSuite) TestGetPoolInstanceByName() {
|
func (s *InstancesTestSuite) TestGetPoolInstanceByName() {
|
||||||
|
|
@ -252,7 +252,7 @@ func (s *InstancesTestSuite) TestGetPoolInstanceByName() {
|
||||||
func (s *InstancesTestSuite) TestGetPoolInstanceByNameNotFound() {
|
func (s *InstancesTestSuite) TestGetPoolInstanceByNameNotFound() {
|
||||||
_, err := s.Store.GetPoolInstanceByName(s.adminCtx, s.Fixtures.Pool.ID, "not-existent-instance-name")
|
_, 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 fetching instance: error fetching pool instance by name: not found", err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *InstancesTestSuite) TestGetInstanceByName() {
|
func (s *InstancesTestSuite) TestGetInstanceByName() {
|
||||||
|
|
@ -271,7 +271,7 @@ func (s *InstancesTestSuite) TestGetInstanceByName() {
|
||||||
func (s *InstancesTestSuite) TestGetInstanceByNameFetchInstanceFailed() {
|
func (s *InstancesTestSuite) TestGetInstanceByNameFetchInstanceFailed() {
|
||||||
_, err := s.Store.GetInstanceByName(s.adminCtx, "not-existent-instance-name")
|
_, err := s.Store.GetInstanceByName(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() {
|
func (s *InstancesTestSuite) TestDeleteInstance() {
|
||||||
|
|
@ -282,7 +282,7 @@ func (s *InstancesTestSuite) TestDeleteInstance() {
|
||||||
s.Require().Nil(err)
|
s.Require().Nil(err)
|
||||||
|
|
||||||
_, err = s.Store.GetPoolInstanceByName(s.adminCtx, s.Fixtures.Pool.ID, storeInstance.Name)
|
_, 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())
|
s.Require().Equal("error fetching instance: error fetching pool instance by name: not found", err.Error())
|
||||||
|
|
||||||
err = s.Store.DeleteInstance(s.adminCtx, s.Fixtures.Pool.ID, storeInstance.Name)
|
err = s.Store.DeleteInstance(s.adminCtx, s.Fixtures.Pool.ID, storeInstance.Name)
|
||||||
s.Require().Nil(err)
|
s.Require().Nil(err)
|
||||||
|
|
@ -296,7 +296,7 @@ func (s *InstancesTestSuite) TestDeleteInstanceByName() {
|
||||||
s.Require().Nil(err)
|
s.Require().Nil(err)
|
||||||
|
|
||||||
_, err = s.Store.GetPoolInstanceByName(s.adminCtx, s.Fixtures.Pool.ID, storeInstance.Name)
|
_, 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())
|
s.Require().Equal("error fetching instance: error fetching pool instance by name: not found", err.Error())
|
||||||
|
|
||||||
err = s.Store.DeleteInstanceByName(s.adminCtx, storeInstance.Name)
|
err = s.Store.DeleteInstanceByName(s.adminCtx, storeInstance.Name)
|
||||||
s.Require().Nil(err)
|
s.Require().Nil(err)
|
||||||
|
|
@ -305,7 +305,7 @@ func (s *InstancesTestSuite) TestDeleteInstanceByName() {
|
||||||
func (s *InstancesTestSuite) TestDeleteInstanceInvalidPoolID() {
|
func (s *InstancesTestSuite) TestDeleteInstanceInvalidPoolID() {
|
||||||
err := s.Store.DeleteInstance(s.adminCtx, "dummy-pool-id", "dummy-instance-name")
|
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() {
|
func (s *InstancesTestSuite) TestDeleteInstanceDBRecordNotFoundErr() {
|
||||||
|
|
@ -380,7 +380,7 @@ func (s *InstancesTestSuite) TestDeleteInstanceDBDeleteErr() {
|
||||||
|
|
||||||
s.assertSQLMockExpectations()
|
s.assertSQLMockExpectations()
|
||||||
s.Require().NotNil(err)
|
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() {
|
func (s *InstancesTestSuite) TestAddInstanceEvent() {
|
||||||
|
|
@ -431,7 +431,7 @@ func (s *InstancesTestSuite) TestAddInstanceEventDBUpdateErr() {
|
||||||
err := s.StoreSQLMocked.AddInstanceEvent(s.adminCtx, instance.Name, params.StatusEvent, params.EventInfo, statusMsg)
|
err := s.StoreSQLMocked.AddInstanceEvent(s.adminCtx, instance.Name, params.StatusEvent, params.EventInfo, statusMsg)
|
||||||
|
|
||||||
s.Require().NotNil(err)
|
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()
|
s.assertSQLMockExpectations()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -476,7 +476,7 @@ func (s *InstancesTestSuite) TestUpdateInstanceDBUpdateInstanceErr() {
|
||||||
_, err := s.StoreSQLMocked.UpdateInstance(s.adminCtx, instance.Name, s.Fixtures.UpdateInstanceParams)
|
_, err := s.StoreSQLMocked.UpdateInstance(s.adminCtx, instance.Name, s.Fixtures.UpdateInstanceParams)
|
||||||
|
|
||||||
s.Require().NotNil(err)
|
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()
|
s.assertSQLMockExpectations()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -522,7 +522,7 @@ func (s *InstancesTestSuite) TestUpdateInstanceDBUpdateAddressErr() {
|
||||||
_, err := s.StoreSQLMocked.UpdateInstance(s.adminCtx, instance.Name, s.Fixtures.UpdateInstanceParams)
|
_, err := s.StoreSQLMocked.UpdateInstance(s.adminCtx, instance.Name, s.Fixtures.UpdateInstanceParams)
|
||||||
|
|
||||||
s.Require().NotNil(err)
|
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()
|
s.assertSQLMockExpectations()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -536,7 +536,7 @@ func (s *InstancesTestSuite) TestListPoolInstances() {
|
||||||
func (s *InstancesTestSuite) TestListPoolInstancesInvalidPoolID() {
|
func (s *InstancesTestSuite) TestListPoolInstancesInvalidPoolID() {
|
||||||
_, err := s.Store.ListPoolInstances(s.adminCtx, "dummy-pool-id")
|
_, 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() {
|
func (s *InstancesTestSuite) TestListAllInstances() {
|
||||||
|
|
@ -555,7 +555,7 @@ func (s *InstancesTestSuite) TestListAllInstancesDBFetchErr() {
|
||||||
|
|
||||||
s.assertSQLMockExpectations()
|
s.assertSQLMockExpectations()
|
||||||
s.Require().NotNil(err)
|
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() {
|
func (s *InstancesTestSuite) TestPoolInstanceCount() {
|
||||||
|
|
@ -568,7 +568,7 @@ func (s *InstancesTestSuite) TestPoolInstanceCount() {
|
||||||
func (s *InstancesTestSuite) TestPoolInstanceCountInvalidPoolID() {
|
func (s *InstancesTestSuite) TestPoolInstanceCountInvalidPoolID() {
|
||||||
_, err := s.Store.PoolInstanceCount(s.adminCtx, "dummy-pool-id")
|
_, 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() {
|
func (s *InstancesTestSuite) TestPoolInstanceCountDBCountErr() {
|
||||||
|
|
@ -587,7 +587,7 @@ func (s *InstancesTestSuite) TestPoolInstanceCountDBCountErr() {
|
||||||
|
|
||||||
s.assertSQLMockExpectations()
|
s.assertSQLMockExpectations()
|
||||||
s.Require().NotNil(err)
|
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) {
|
func TestInstTestSuite(t *testing.T) {
|
||||||
|
|
|
||||||
|
|
@ -17,10 +17,11 @@ package sql
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
|
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
"github.com/pkg/errors"
|
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
"gorm.io/gorm/clause"
|
"gorm.io/gorm/clause"
|
||||||
|
|
||||||
|
|
@ -35,7 +36,7 @@ func sqlWorkflowJobToParamsJob(job WorkflowJob) (params.Job, error) {
|
||||||
labels := []string{}
|
labels := []string{}
|
||||||
if job.Labels != nil {
|
if job.Labels != nil {
|
||||||
if err := json.Unmarshal(job.Labels, &labels); err != 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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -73,7 +74,7 @@ func sqlWorkflowJobToParamsJob(job WorkflowJob) (params.Job, error) {
|
||||||
func (s *sqlDatabase) paramsJobToWorkflowJob(ctx context.Context, job params.Job) (WorkflowJob, error) {
|
func (s *sqlDatabase) paramsJobToWorkflowJob(ctx context.Context, job params.Job) (WorkflowJob, error) {
|
||||||
asJSON, err := json.Marshal(job.Labels)
|
asJSON, err := json.Marshal(job.Labels)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return WorkflowJob{}, errors.Wrap(err, "marshaling labels")
|
return WorkflowJob{}, fmt.Errorf("error marshaling labels: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
workflofJob := WorkflowJob{
|
workflofJob := WorkflowJob{
|
||||||
|
|
@ -118,11 +119,11 @@ func (s *sqlDatabase) DeleteJob(_ context.Context, jobID int64) (err error) {
|
||||||
if errors.Is(q.Error, gorm.ErrRecordNotFound) {
|
if errors.Is(q.Error, gorm.ErrRecordNotFound) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return errors.Wrap(q.Error, "fetching job")
|
return fmt.Errorf("error fetching job: %w", q.Error)
|
||||||
}
|
}
|
||||||
removedJob, err := sqlWorkflowJobToParamsJob(workflowJob)
|
removedJob, err := sqlWorkflowJobToParamsJob(workflowJob)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "converting job")
|
return fmt.Errorf("error converting job: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
|
|
@ -137,7 +138,7 @@ func (s *sqlDatabase) DeleteJob(_ context.Context, jobID int64) (err error) {
|
||||||
if errors.Is(q.Error, gorm.ErrRecordNotFound) {
|
if errors.Is(q.Error, gorm.ErrRecordNotFound) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return errors.Wrap(q.Error, "deleting job")
|
return fmt.Errorf("error deleting job: %w", q.Error)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -145,7 +146,7 @@ func (s *sqlDatabase) DeleteJob(_ context.Context, jobID int64) (err error) {
|
||||||
func (s *sqlDatabase) LockJob(_ context.Context, jobID int64, entityID string) error {
|
func (s *sqlDatabase) LockJob(_ context.Context, jobID int64, entityID string) error {
|
||||||
entityUUID, err := uuid.Parse(entityID)
|
entityUUID, err := uuid.Parse(entityID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "parsing entity id")
|
return fmt.Errorf("error parsing entity id: %w", err)
|
||||||
}
|
}
|
||||||
var workflowJob WorkflowJob
|
var workflowJob WorkflowJob
|
||||||
q := s.conn.Preload("Instance").Where("id = ?", jobID).First(&workflowJob)
|
q := s.conn.Preload("Instance").Where("id = ?", jobID).First(&workflowJob)
|
||||||
|
|
@ -154,7 +155,7 @@ func (s *sqlDatabase) LockJob(_ context.Context, jobID int64, entityID string) e
|
||||||
if errors.Is(q.Error, gorm.ErrRecordNotFound) {
|
if errors.Is(q.Error, gorm.ErrRecordNotFound) {
|
||||||
return runnerErrors.ErrNotFound
|
return runnerErrors.ErrNotFound
|
||||||
}
|
}
|
||||||
return errors.Wrap(q.Error, "fetching job")
|
return fmt.Errorf("error fetching job: %w", q.Error)
|
||||||
}
|
}
|
||||||
|
|
||||||
if workflowJob.LockedBy.String() == entityID {
|
if workflowJob.LockedBy.String() == entityID {
|
||||||
|
|
@ -169,12 +170,12 @@ func (s *sqlDatabase) LockJob(_ context.Context, jobID int64, entityID string) e
|
||||||
workflowJob.LockedBy = entityUUID
|
workflowJob.LockedBy = entityUUID
|
||||||
|
|
||||||
if err := s.conn.Save(&workflowJob).Error; err != 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)
|
asParams, err := sqlWorkflowJobToParamsJob(workflowJob)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "converting job")
|
return fmt.Errorf("error converting job: %w", err)
|
||||||
}
|
}
|
||||||
s.sendNotify(common.JobEntityType, common.UpdateOperation, asParams)
|
s.sendNotify(common.JobEntityType, common.UpdateOperation, asParams)
|
||||||
|
|
||||||
|
|
@ -189,7 +190,7 @@ func (s *sqlDatabase) BreakLockJobIsQueued(_ context.Context, jobID int64) (err
|
||||||
if errors.Is(q.Error, gorm.ErrRecordNotFound) {
|
if errors.Is(q.Error, gorm.ErrRecordNotFound) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return errors.Wrap(q.Error, "fetching job")
|
return fmt.Errorf("error fetching job: %w", q.Error)
|
||||||
}
|
}
|
||||||
|
|
||||||
if workflowJob.LockedBy == uuid.Nil {
|
if workflowJob.LockedBy == uuid.Nil {
|
||||||
|
|
@ -199,11 +200,11 @@ func (s *sqlDatabase) BreakLockJobIsQueued(_ context.Context, jobID int64) (err
|
||||||
|
|
||||||
workflowJob.LockedBy = uuid.Nil
|
workflowJob.LockedBy = uuid.Nil
|
||||||
if err := s.conn.Save(&workflowJob).Error; err != 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)
|
asParams, err := sqlWorkflowJobToParamsJob(workflowJob)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "converting job")
|
return fmt.Errorf("error converting job: %w", err)
|
||||||
}
|
}
|
||||||
s.sendNotify(common.JobEntityType, common.UpdateOperation, asParams)
|
s.sendNotify(common.JobEntityType, common.UpdateOperation, asParams)
|
||||||
return nil
|
return nil
|
||||||
|
|
@ -217,7 +218,7 @@ func (s *sqlDatabase) UnlockJob(_ context.Context, jobID int64, entityID string)
|
||||||
if errors.Is(q.Error, gorm.ErrRecordNotFound) {
|
if errors.Is(q.Error, gorm.ErrRecordNotFound) {
|
||||||
return runnerErrors.ErrNotFound
|
return runnerErrors.ErrNotFound
|
||||||
}
|
}
|
||||||
return errors.Wrap(q.Error, "fetching job")
|
return fmt.Errorf("error fetching job: %w", q.Error)
|
||||||
}
|
}
|
||||||
|
|
||||||
if workflowJob.LockedBy == uuid.Nil {
|
if workflowJob.LockedBy == uuid.Nil {
|
||||||
|
|
@ -231,12 +232,12 @@ func (s *sqlDatabase) UnlockJob(_ context.Context, jobID int64, entityID string)
|
||||||
|
|
||||||
workflowJob.LockedBy = uuid.Nil
|
workflowJob.LockedBy = uuid.Nil
|
||||||
if err := s.conn.Save(&workflowJob).Error; err != 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)
|
asParams, err := sqlWorkflowJobToParamsJob(workflowJob)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "converting job")
|
return fmt.Errorf("error converting job: %w", err)
|
||||||
}
|
}
|
||||||
s.sendNotify(common.JobEntityType, common.UpdateOperation, asParams)
|
s.sendNotify(common.JobEntityType, common.UpdateOperation, asParams)
|
||||||
return nil
|
return nil
|
||||||
|
|
@ -256,7 +257,7 @@ func (s *sqlDatabase) CreateOrUpdateJob(ctx context.Context, job params.Job) (pa
|
||||||
|
|
||||||
if q.Error != nil {
|
if q.Error != nil {
|
||||||
if !errors.Is(q.Error, gorm.ErrRecordNotFound) {
|
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
|
var operation common.OperationType
|
||||||
|
|
@ -302,23 +303,23 @@ func (s *sqlDatabase) CreateOrUpdateJob(ctx context.Context, job params.Job) (pa
|
||||||
workflowJob.EnterpriseID = job.EnterpriseID
|
workflowJob.EnterpriseID = job.EnterpriseID
|
||||||
}
|
}
|
||||||
if err := s.conn.Save(&workflowJob).Error; err != nil {
|
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 {
|
} else {
|
||||||
operation = common.CreateOperation
|
operation = common.CreateOperation
|
||||||
|
|
||||||
workflowJob, err = s.paramsJobToWorkflowJob(ctx, job)
|
workflowJob, err = s.paramsJobToWorkflowJob(ctx, job)
|
||||||
if err != nil {
|
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 {
|
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)
|
asParams, err := sqlWorkflowJobToParamsJob(workflowJob)
|
||||||
if err != nil {
|
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)
|
s.sendNotify(common.JobEntityType, operation, asParams)
|
||||||
|
|
||||||
|
|
@ -338,7 +339,7 @@ func (s *sqlDatabase) ListJobsByStatus(_ context.Context, status params.JobStatu
|
||||||
for idx, job := range jobs {
|
for idx, job := range jobs {
|
||||||
jobParam, err := sqlWorkflowJobToParamsJob(job)
|
jobParam, err := sqlWorkflowJobToParamsJob(job)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "converting job")
|
return nil, fmt.Errorf("error converting job: %w", err)
|
||||||
}
|
}
|
||||||
ret[idx] = jobParam
|
ret[idx] = jobParam
|
||||||
}
|
}
|
||||||
|
|
@ -379,7 +380,7 @@ func (s *sqlDatabase) ListEntityJobsByStatus(_ context.Context, entityType param
|
||||||
for idx, job := range jobs {
|
for idx, job := range jobs {
|
||||||
jobParam, err := sqlWorkflowJobToParamsJob(job)
|
jobParam, err := sqlWorkflowJobToParamsJob(job)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "converting job")
|
return nil, fmt.Errorf("error converting job: %w", err)
|
||||||
}
|
}
|
||||||
ret[idx] = jobParam
|
ret[idx] = jobParam
|
||||||
}
|
}
|
||||||
|
|
@ -401,7 +402,7 @@ func (s *sqlDatabase) ListAllJobs(_ context.Context) ([]params.Job, error) {
|
||||||
for idx, job := range jobs {
|
for idx, job := range jobs {
|
||||||
jobParam, err := sqlWorkflowJobToParamsJob(job)
|
jobParam, err := sqlWorkflowJobToParamsJob(job)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "converting job")
|
return nil, fmt.Errorf("error converting job: %w", err)
|
||||||
}
|
}
|
||||||
ret[idx] = jobParam
|
ret[idx] = jobParam
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,10 +15,10 @@
|
||||||
package sql
|
package sql
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
"github.com/pkg/errors"
|
|
||||||
"gorm.io/datatypes"
|
"gorm.io/datatypes"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
|
|
||||||
|
|
@ -40,7 +40,7 @@ func (b *Base) BeforeCreate(_ *gorm.DB) error {
|
||||||
}
|
}
|
||||||
newID, err := uuid.NewRandom()
|
newID, err := uuid.NewRandom()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "generating id")
|
return fmt.Errorf("error generating id: %w", err)
|
||||||
}
|
}
|
||||||
b.ID = newID
|
b.ID = newID
|
||||||
return nil
|
return nil
|
||||||
|
|
|
||||||
|
|
@ -16,11 +16,11 @@ package sql
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
|
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
"github.com/pkg/errors"
|
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
|
|
||||||
runnerErrors "github.com/cloudbase/garm-provider-common/errors"
|
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))
|
secret, err := util.Seal([]byte(webhookSecret), []byte(s.cfg.Passphrase))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return params.Organization{}, errors.Wrap(err, "encoding secret")
|
return params.Organization{}, fmt.Errorf("error encoding secret: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
|
|
@ -56,23 +56,23 @@ func (s *sqlDatabase) CreateOrganization(ctx context.Context, name string, crede
|
||||||
case params.GiteaEndpointType:
|
case params.GiteaEndpointType:
|
||||||
newOrg.GiteaCredentialsID = &credentials.ID
|
newOrg.GiteaCredentialsID = &credentials.ID
|
||||||
default:
|
default:
|
||||||
return errors.Wrap(runnerErrors.ErrBadRequest, "unsupported credentials type")
|
return fmt.Errorf("unsupported credentials type: %w", runnerErrors.ErrBadRequest)
|
||||||
}
|
}
|
||||||
|
|
||||||
newOrg.EndpointName = &credentials.Endpoint.Name
|
newOrg.EndpointName = &credentials.Endpoint.Name
|
||||||
q := tx.Create(&newOrg)
|
q := tx.Create(&newOrg)
|
||||||
if q.Error != nil {
|
if q.Error != nil {
|
||||||
return errors.Wrap(q.Error, "creating org")
|
return fmt.Errorf("error creating org: %w", q.Error)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
if err != 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())
|
ret, err := s.GetOrganizationByID(ctx, newOrg.ID.String())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return params.Organization{}, errors.Wrap(err, "creating org")
|
return params.Organization{}, fmt.Errorf("error creating org: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret, nil
|
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) {
|
func (s *sqlDatabase) GetOrganization(ctx context.Context, name, endpointName string) (params.Organization, error) {
|
||||||
org, err := s.getOrg(ctx, name, endpointName)
|
org, err := s.getOrg(ctx, name, endpointName)
|
||||||
if err != nil {
|
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)
|
param, err := s.sqlToCommonOrganization(org, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return params.Organization{}, errors.Wrap(err, "fetching org")
|
return params.Organization{}, fmt.Errorf("error fetching org: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return param, nil
|
return param, nil
|
||||||
|
|
@ -110,7 +110,7 @@ func (s *sqlDatabase) ListOrganizations(_ context.Context, filter params.Organiz
|
||||||
}
|
}
|
||||||
q = q.Find(&orgs)
|
q = q.Find(&orgs)
|
||||||
if q.Error != nil {
|
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))
|
ret := make([]params.Organization, len(orgs))
|
||||||
|
|
@ -118,7 +118,7 @@ func (s *sqlDatabase) ListOrganizations(_ context.Context, filter params.Organiz
|
||||||
var err error
|
var err error
|
||||||
ret[idx], err = s.sqlToCommonOrganization(val, true)
|
ret[idx], err = s.sqlToCommonOrganization(val, true)
|
||||||
if err != nil {
|
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) {
|
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")
|
org, err := s.getOrgByID(ctx, s.conn, orgID, "Endpoint", "Credentials", "Credentials.Endpoint", "GiteaCredentials", "GiteaCredentials.Endpoint")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "fetching org")
|
return fmt.Errorf("error fetching org: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
defer func(org Organization) {
|
defer func(org Organization) {
|
||||||
|
|
@ -144,7 +144,7 @@ func (s *sqlDatabase) DeleteOrganization(ctx context.Context, orgID string) (err
|
||||||
|
|
||||||
q := s.conn.Unscoped().Delete(&org)
|
q := s.conn.Unscoped().Delete(&org)
|
||||||
if q.Error != nil && !errors.Is(q.Error, gorm.ErrRecordNotFound) {
|
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
|
return nil
|
||||||
|
|
@ -162,23 +162,23 @@ func (s *sqlDatabase) UpdateOrganization(ctx context.Context, orgID string, para
|
||||||
var err error
|
var err error
|
||||||
org, err = s.getOrgByID(ctx, tx, orgID)
|
org, err = s.getOrgByID(ctx, tx, orgID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "fetching org")
|
return fmt.Errorf("error fetching org: %w", err)
|
||||||
}
|
}
|
||||||
if org.EndpointName == nil {
|
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 != "" {
|
if param.CredentialsName != "" {
|
||||||
creds, err = s.getGithubCredentialsByName(ctx, tx, param.CredentialsName, false)
|
creds, err = s.getGithubCredentialsByName(ctx, tx, param.CredentialsName, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "fetching credentials")
|
return fmt.Errorf("error fetching credentials: %w", err)
|
||||||
}
|
}
|
||||||
if creds.EndpointName == nil {
|
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 {
|
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
|
org.CredentialsID = &creds.ID
|
||||||
}
|
}
|
||||||
|
|
@ -197,22 +197,22 @@ func (s *sqlDatabase) UpdateOrganization(ctx context.Context, orgID string, para
|
||||||
|
|
||||||
q := tx.Save(&org)
|
q := tx.Save(&org)
|
||||||
if q.Error != nil {
|
if q.Error != nil {
|
||||||
return errors.Wrap(q.Error, "saving org")
|
return fmt.Errorf("error saving org: %w", q.Error)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
if err != 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")
|
org, err = s.getOrgByID(ctx, s.conn, orgID, "Endpoint", "Credentials", "Credentials.Endpoint", "GiteaCredentials", "GiteaCredentials.Endpoint")
|
||||||
if err != nil {
|
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)
|
paramOrg, err = s.sqlToCommonOrganization(org, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return params.Organization{}, errors.Wrap(err, "saving org")
|
return params.Organization{}, fmt.Errorf("error saving org: %w", err)
|
||||||
}
|
}
|
||||||
return paramOrg, nil
|
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...)
|
org, err := s.getOrgByID(ctx, s.conn, orgID, preloadList...)
|
||||||
if err != nil {
|
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)
|
param, err := s.sqlToCommonOrganization(org, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return params.Organization{}, errors.Wrap(err, "fetching org")
|
return params.Organization{}, fmt.Errorf("error fetching org: %w", err)
|
||||||
}
|
}
|
||||||
return param, nil
|
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) {
|
func (s *sqlDatabase) getOrgByID(_ context.Context, db *gorm.DB, id string, preload ...string) (Organization, error) {
|
||||||
u, err := uuid.Parse(id)
|
u, err := uuid.Parse(id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return Organization{}, errors.Wrap(runnerErrors.ErrBadRequest, "parsing id")
|
return Organization{}, fmt.Errorf("error parsing id: %w", runnerErrors.ErrBadRequest)
|
||||||
}
|
}
|
||||||
var org Organization
|
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) {
|
if errors.Is(q.Error, gorm.ErrRecordNotFound) {
|
||||||
return Organization{}, runnerErrors.ErrNotFound
|
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
|
return org, nil
|
||||||
}
|
}
|
||||||
|
|
@ -277,7 +277,7 @@ func (s *sqlDatabase) getOrg(_ context.Context, name, endpointName string) (Orga
|
||||||
if errors.Is(q.Error, gorm.ErrRecordNotFound) {
|
if errors.Is(q.Error, gorm.ErrRecordNotFound) {
|
||||||
return Organization{}, runnerErrors.ErrNotFound
|
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
|
return org, nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -251,7 +251,7 @@ func (s *OrgTestSuite) TestCreateOrganizationInvalidForgeType() {
|
||||||
s.Fixtures.CreateOrgParams.WebhookSecret,
|
s.Fixtures.CreateOrgParams.WebhookSecret,
|
||||||
params.PoolBalancerTypeRoundRobin)
|
params.PoolBalancerTypeRoundRobin)
|
||||||
s.Require().NotNil(err)
|
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() {
|
func (s *OrgTestSuite) TestCreateOrganizationInvalidDBPassphrase() {
|
||||||
|
|
@ -275,7 +275,7 @@ func (s *OrgTestSuite) TestCreateOrganizationInvalidDBPassphrase() {
|
||||||
params.PoolBalancerTypeRoundRobin)
|
params.PoolBalancerTypeRoundRobin)
|
||||||
|
|
||||||
s.Require().NotNil(err)
|
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() {
|
func (s *OrgTestSuite) TestCreateOrganizationDBCreateErr() {
|
||||||
|
|
@ -293,7 +293,7 @@ func (s *OrgTestSuite) TestCreateOrganizationDBCreateErr() {
|
||||||
params.PoolBalancerTypeRoundRobin)
|
params.PoolBalancerTypeRoundRobin)
|
||||||
|
|
||||||
s.Require().NotNil(err)
|
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()
|
s.assertSQLMockExpectations()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -316,7 +316,7 @@ func (s *OrgTestSuite) TestGetOrganizationNotFound() {
|
||||||
_, err := s.Store.GetOrganization(s.adminCtx, "dummy-name", "github.com")
|
_, err := s.Store.GetOrganization(s.adminCtx, "dummy-name", "github.com")
|
||||||
|
|
||||||
s.Require().NotNil(err)
|
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() {
|
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)
|
_, err := s.StoreSQLMocked.GetOrganization(s.adminCtx, s.Fixtures.Orgs[0].Name, s.Fixtures.Orgs[0].Endpoint.Name)
|
||||||
|
|
||||||
s.Require().NotNil(err)
|
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()
|
s.assertSQLMockExpectations()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -404,7 +404,7 @@ func (s *OrgTestSuite) TestListOrganizationsDBFetchErr() {
|
||||||
|
|
||||||
s.assertSQLMockExpectations()
|
s.assertSQLMockExpectations()
|
||||||
s.Require().NotNil(err)
|
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() {
|
func (s *OrgTestSuite) TestDeleteOrganization() {
|
||||||
|
|
@ -413,14 +413,14 @@ func (s *OrgTestSuite) TestDeleteOrganization() {
|
||||||
s.Require().Nil(err)
|
s.Require().Nil(err)
|
||||||
_, err = s.Store.GetOrganizationByID(s.adminCtx, s.Fixtures.Orgs[0].ID)
|
_, err = s.Store.GetOrganizationByID(s.adminCtx, s.Fixtures.Orgs[0].ID)
|
||||||
s.Require().NotNil(err)
|
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() {
|
func (s *OrgTestSuite) TestDeleteOrganizationInvalidOrgID() {
|
||||||
err := s.Store.DeleteOrganization(s.adminCtx, "dummy-org-id")
|
err := s.Store.DeleteOrganization(s.adminCtx, "dummy-org-id")
|
||||||
|
|
||||||
s.Require().NotNil(err)
|
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() {
|
func (s *OrgTestSuite) TestDeleteOrganizationDBDeleteErr() {
|
||||||
|
|
@ -439,7 +439,7 @@ func (s *OrgTestSuite) TestDeleteOrganizationDBDeleteErr() {
|
||||||
|
|
||||||
s.assertSQLMockExpectations()
|
s.assertSQLMockExpectations()
|
||||||
s.Require().NotNil(err)
|
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() {
|
func (s *OrgTestSuite) TestUpdateOrganization() {
|
||||||
|
|
@ -454,7 +454,7 @@ func (s *OrgTestSuite) TestUpdateOrganizationInvalidOrgID() {
|
||||||
_, err := s.Store.UpdateOrganization(s.adminCtx, "dummy-org-id", s.Fixtures.UpdateRepoParams)
|
_, err := s.Store.UpdateOrganization(s.adminCtx, "dummy-org-id", s.Fixtures.UpdateRepoParams)
|
||||||
|
|
||||||
s.Require().NotNil(err)
|
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() {
|
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)
|
_, err := s.StoreSQLMocked.UpdateOrganization(s.adminCtx, s.Fixtures.Orgs[0].ID, s.Fixtures.UpdateRepoParams)
|
||||||
|
|
||||||
s.Require().NotNil(err)
|
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()
|
s.assertSQLMockExpectations()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -507,7 +507,7 @@ func (s *OrgTestSuite) TestUpdateOrganizationDBSaveErr() {
|
||||||
_, err := s.StoreSQLMocked.UpdateOrganization(s.adminCtx, s.Fixtures.Orgs[0].ID, s.Fixtures.UpdateRepoParams)
|
_, err := s.StoreSQLMocked.UpdateOrganization(s.adminCtx, s.Fixtures.Orgs[0].ID, s.Fixtures.UpdateRepoParams)
|
||||||
|
|
||||||
s.Require().NotNil(err)
|
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()
|
s.assertSQLMockExpectations()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -535,7 +535,7 @@ func (s *OrgTestSuite) TestUpdateOrganizationDBDecryptingErr() {
|
||||||
_, err := s.StoreSQLMocked.UpdateOrganization(s.adminCtx, s.Fixtures.Orgs[0].ID, s.Fixtures.UpdateRepoParams)
|
_, err := s.StoreSQLMocked.UpdateOrganization(s.adminCtx, s.Fixtures.Orgs[0].ID, s.Fixtures.UpdateRepoParams)
|
||||||
|
|
||||||
s.Require().NotNil(err)
|
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()
|
s.assertSQLMockExpectations()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -550,7 +550,7 @@ func (s *OrgTestSuite) TestGetOrganizationByIDInvalidOrgID() {
|
||||||
_, err := s.Store.GetOrganizationByID(s.adminCtx, "dummy-org-id")
|
_, err := s.Store.GetOrganizationByID(s.adminCtx, "dummy-org-id")
|
||||||
|
|
||||||
s.Require().NotNil(err)
|
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() {
|
func (s *OrgTestSuite) TestGetOrganizationByIDDBDecryptingErr() {
|
||||||
|
|
@ -571,7 +571,7 @@ func (s *OrgTestSuite) TestGetOrganizationByIDDBDecryptingErr() {
|
||||||
|
|
||||||
s.assertSQLMockExpectations()
|
s.assertSQLMockExpectations()
|
||||||
s.Require().NotNil(err)
|
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() {
|
func (s *OrgTestSuite) TestCreateOrganizationPool() {
|
||||||
|
|
@ -610,7 +610,7 @@ func (s *OrgTestSuite) TestCreateOrganizationPoolInvalidOrgID() {
|
||||||
_, err := s.Store.CreateEntityPool(s.adminCtx, entity, s.Fixtures.CreatePoolParams)
|
_, err := s.Store.CreateEntityPool(s.adminCtx, entity, s.Fixtures.CreatePoolParams)
|
||||||
|
|
||||||
s.Require().NotNil(err)
|
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() {
|
func (s *OrgTestSuite) TestCreateOrganizationPoolDBFetchTagErr() {
|
||||||
|
|
@ -628,7 +628,7 @@ func (s *OrgTestSuite) TestCreateOrganizationPoolDBFetchTagErr() {
|
||||||
_, err = s.StoreSQLMocked.CreateEntityPool(s.adminCtx, entity, s.Fixtures.CreatePoolParams)
|
_, err = s.StoreSQLMocked.CreateEntityPool(s.adminCtx, entity, s.Fixtures.CreatePoolParams)
|
||||||
|
|
||||||
s.Require().NotNil(err)
|
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()
|
s.assertSQLMockExpectations()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -656,7 +656,7 @@ func (s *OrgTestSuite) TestCreateOrganizationPoolDBAddingPoolErr() {
|
||||||
_, err = s.StoreSQLMocked.CreateEntityPool(s.adminCtx, entity, s.Fixtures.CreatePoolParams)
|
_, err = s.StoreSQLMocked.CreateEntityPool(s.adminCtx, entity, s.Fixtures.CreatePoolParams)
|
||||||
|
|
||||||
s.Require().NotNil(err)
|
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()
|
s.assertSQLMockExpectations()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -687,7 +687,7 @@ func (s *OrgTestSuite) TestCreateOrganizationPoolDBSaveTagErr() {
|
||||||
_, err = s.StoreSQLMocked.CreateEntityPool(s.adminCtx, entity, s.Fixtures.CreatePoolParams)
|
_, err = s.StoreSQLMocked.CreateEntityPool(s.adminCtx, entity, s.Fixtures.CreatePoolParams)
|
||||||
|
|
||||||
s.Require().NotNil(err)
|
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()
|
s.assertSQLMockExpectations()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -728,7 +728,7 @@ func (s *OrgTestSuite) TestCreateOrganizationPoolDBFetchPoolErr() {
|
||||||
_, err = s.StoreSQLMocked.CreateEntityPool(s.adminCtx, entity, s.Fixtures.CreatePoolParams)
|
_, err = s.StoreSQLMocked.CreateEntityPool(s.adminCtx, entity, s.Fixtures.CreatePoolParams)
|
||||||
|
|
||||||
s.Require().NotNil(err)
|
s.Require().NotNil(err)
|
||||||
s.Require().Equal("fetching pool: not found", err.Error())
|
s.Require().Equal("error fetching pool: not found", err.Error())
|
||||||
s.assertSQLMockExpectations()
|
s.assertSQLMockExpectations()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -758,7 +758,7 @@ func (s *OrgTestSuite) TestListOrgPoolsInvalidOrgID() {
|
||||||
_, err := s.Store.ListEntityPools(s.adminCtx, entity)
|
_, err := s.Store.ListEntityPools(s.adminCtx, entity)
|
||||||
|
|
||||||
s.Require().NotNil(err)
|
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() {
|
func (s *OrgTestSuite) TestGetOrganizationPool() {
|
||||||
|
|
@ -783,7 +783,7 @@ func (s *OrgTestSuite) TestGetOrganizationPoolInvalidOrgID() {
|
||||||
_, err := s.Store.GetEntityPool(s.adminCtx, entity, "dummy-pool-id")
|
_, err := s.Store.GetEntityPool(s.adminCtx, entity, "dummy-pool-id")
|
||||||
|
|
||||||
s.Require().NotNil(err)
|
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() {
|
func (s *OrgTestSuite) TestDeleteOrganizationPool() {
|
||||||
|
|
@ -798,7 +798,7 @@ func (s *OrgTestSuite) TestDeleteOrganizationPool() {
|
||||||
|
|
||||||
s.Require().Nil(err)
|
s.Require().Nil(err)
|
||||||
_, err = s.Store.GetEntityPool(s.adminCtx, entity, pool.ID)
|
_, 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() {
|
func (s *OrgTestSuite) TestDeleteOrganizationPoolInvalidOrgID() {
|
||||||
|
|
@ -809,7 +809,7 @@ func (s *OrgTestSuite) TestDeleteOrganizationPoolInvalidOrgID() {
|
||||||
err := s.Store.DeleteEntityPool(s.adminCtx, entity, "dummy-pool-id")
|
err := s.Store.DeleteEntityPool(s.adminCtx, entity, "dummy-pool-id")
|
||||||
|
|
||||||
s.Require().NotNil(err)
|
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() {
|
func (s *OrgTestSuite) TestDeleteOrganizationPoolDBDeleteErr() {
|
||||||
|
|
@ -831,7 +831,7 @@ func (s *OrgTestSuite) TestDeleteOrganizationPoolDBDeleteErr() {
|
||||||
err = s.StoreSQLMocked.DeleteEntityPool(s.adminCtx, entity, pool.ID)
|
err = s.StoreSQLMocked.DeleteEntityPool(s.adminCtx, entity, pool.ID)
|
||||||
|
|
||||||
s.Require().NotNil(err)
|
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()
|
s.assertSQLMockExpectations()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -866,7 +866,7 @@ func (s *OrgTestSuite) TestListOrgInstancesInvalidOrgID() {
|
||||||
_, err := s.Store.ListEntityInstances(s.adminCtx, entity)
|
_, err := s.Store.ListEntityInstances(s.adminCtx, entity)
|
||||||
|
|
||||||
s.Require().NotNil(err)
|
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() {
|
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)
|
_, err := s.Store.UpdateEntityPool(s.adminCtx, entity, "dummy-pool-id", s.Fixtures.UpdatePoolParams)
|
||||||
|
|
||||||
s.Require().NotNil(err)
|
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) {
|
func TestOrgTestSuite(t *testing.T) {
|
||||||
|
|
|
||||||
|
|
@ -16,10 +16,10 @@ package sql
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
"github.com/pkg/errors"
|
|
||||||
"gorm.io/datatypes"
|
"gorm.io/datatypes"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
|
|
||||||
|
|
@ -48,7 +48,7 @@ func (s *sqlDatabase) ListAllPools(_ context.Context) ([]params.Pool, error) {
|
||||||
Omit("extra_specs").
|
Omit("extra_specs").
|
||||||
Find(&pools)
|
Find(&pools)
|
||||||
if q.Error != nil {
|
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))
|
ret := make([]params.Pool, len(pools))
|
||||||
|
|
@ -56,7 +56,7 @@ func (s *sqlDatabase) ListAllPools(_ context.Context) ([]params.Pool, error) {
|
||||||
for idx, val := range pools {
|
for idx, val := range pools {
|
||||||
ret[idx], err = s.sqlToCommonPool(val)
|
ret[idx], err = s.sqlToCommonPool(val)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "converting pool")
|
return nil, fmt.Errorf("error converting pool: %w", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ret, nil
|
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...)
|
pool, err := s.getPoolByID(s.conn, poolID, preloadList...)
|
||||||
if err != nil {
|
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)
|
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) {
|
func (s *sqlDatabase) DeletePoolByID(_ context.Context, poolID string) (err error) {
|
||||||
pool, err := s.getPoolByID(s.conn, poolID)
|
pool, err := s.getPoolByID(s.conn, poolID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "fetching pool by ID")
|
return fmt.Errorf("error fetching pool by ID: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
defer func() {
|
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 {
|
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
|
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) {
|
func (s *sqlDatabase) getEntityPool(tx *gorm.DB, entityType params.ForgeEntityType, entityID, poolID string, preload ...string) (Pool, error) {
|
||||||
if entityID == "" {
|
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)
|
u, err := uuid.Parse(poolID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return Pool{}, errors.Wrap(runnerErrors.ErrBadRequest, "parsing id")
|
return Pool{}, fmt.Errorf("error parsing id: %w", runnerErrors.ErrBadRequest)
|
||||||
}
|
}
|
||||||
|
|
||||||
var fieldName string
|
var fieldName string
|
||||||
|
|
@ -140,9 +140,9 @@ func (s *sqlDatabase) getEntityPool(tx *gorm.DB, entityType params.ForgeEntityTy
|
||||||
First(&pool).Error
|
First(&pool).Error
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
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
|
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) {
|
func (s *sqlDatabase) listEntityPools(tx *gorm.DB, entityType params.ForgeEntityType, entityID string, preload ...string) ([]Pool, error) {
|
||||||
if _, err := uuid.Parse(entityID); err != nil {
|
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 {
|
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
|
var preloadEntity string
|
||||||
|
|
@ -191,7 +191,7 @@ func (s *sqlDatabase) listEntityPools(tx *gorm.DB, entityType params.ForgeEntity
|
||||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||||
return []Pool{}, nil
|
return []Pool{}, nil
|
||||||
}
|
}
|
||||||
return nil, errors.Wrap(err, "fetching pool")
|
return nil, fmt.Errorf("error fetching pool: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return pools, nil
|
return pools, nil
|
||||||
|
|
@ -203,7 +203,7 @@ func (s *sqlDatabase) findPoolByTags(id string, poolType params.ForgeEntityType,
|
||||||
}
|
}
|
||||||
u, err := uuid.Parse(id)
|
u, err := uuid.Parse(id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(runnerErrors.ErrBadRequest, "parsing id")
|
return nil, fmt.Errorf("error parsing id: %w", runnerErrors.ErrBadRequest)
|
||||||
}
|
}
|
||||||
|
|
||||||
var fieldName string
|
var fieldName string
|
||||||
|
|
@ -233,7 +233,7 @@ func (s *sqlDatabase) findPoolByTags(id string, poolType params.ForgeEntityType,
|
||||||
if errors.Is(q.Error, gorm.ErrRecordNotFound) {
|
if errors.Is(q.Error, gorm.ErrRecordNotFound) {
|
||||||
return nil, runnerErrors.ErrNotFound
|
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 {
|
if len(pools) == 0 {
|
||||||
|
|
@ -244,7 +244,7 @@ func (s *sqlDatabase) findPoolByTags(id string, poolType params.ForgeEntityType,
|
||||||
for idx, val := range pools {
|
for idx, val := range pools {
|
||||||
ret[idx], err = s.sqlToCommonPool(val)
|
ret[idx], err = s.sqlToCommonPool(val)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "converting pool")
|
return nil, fmt.Errorf("error converting pool: %w", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -261,7 +261,7 @@ func (s *sqlDatabase) FindPoolsMatchingAllTags(_ context.Context, entityType par
|
||||||
if errors.Is(err, runnerErrors.ErrNotFound) {
|
if errors.Is(err, runnerErrors.ErrNotFound) {
|
||||||
return []params.Pool{}, nil
|
return []params.Pool{}, nil
|
||||||
}
|
}
|
||||||
return nil, errors.Wrap(err, "fetching pools")
|
return nil, fmt.Errorf("error fetching pools: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return pools, nil
|
return pools, nil
|
||||||
|
|
@ -298,7 +298,7 @@ func (s *sqlDatabase) CreateEntityPool(_ context.Context, entity params.ForgeEnt
|
||||||
|
|
||||||
entityID, err := uuid.Parse(entity.ID)
|
entityID, err := uuid.Parse(entity.ID)
|
||||||
if err != nil {
|
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 {
|
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 {
|
err = s.conn.Transaction(func(tx *gorm.DB) error {
|
||||||
if err := s.hasGithubEntity(tx, entity.EntityType, entity.ID); err != nil {
|
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{}
|
tags := []Tag{}
|
||||||
for _, val := range param.Tags {
|
for _, val := range param.Tags {
|
||||||
t, err := s.getOrCreateTag(tx, val)
|
t, err := s.getOrCreateTag(tx, val)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "creating tag")
|
return fmt.Errorf("error creating tag: %w", err)
|
||||||
}
|
}
|
||||||
tags = append(tags, t)
|
tags = append(tags, t)
|
||||||
}
|
}
|
||||||
|
|
||||||
q := tx.Create(&newPool)
|
q := tx.Create(&newPool)
|
||||||
if q.Error != nil {
|
if q.Error != nil {
|
||||||
return errors.Wrap(q.Error, "creating pool")
|
return fmt.Errorf("error creating pool: %w", q.Error)
|
||||||
}
|
}
|
||||||
|
|
||||||
for i := range tags {
|
for i := range tags {
|
||||||
if err := tx.Model(&newPool).Association("Tags").Append(&tags[i]); err != nil {
|
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
|
return nil
|
||||||
|
|
@ -341,7 +341,7 @@ func (s *sqlDatabase) CreateEntityPool(_ context.Context, entity params.ForgeEnt
|
||||||
|
|
||||||
dbPool, err := s.getPoolByID(s.conn, newPool.ID.String(), "Tags", "Instances", "Enterprise", "Organization", "Repository")
|
dbPool, err := s.getPoolByID(s.conn, newPool.ID.String(), "Tags", "Instances", "Enterprise", "Organization", "Repository")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return params.Pool{}, errors.Wrap(err, "fetching pool")
|
return params.Pool{}, fmt.Errorf("error fetching pool: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return s.sqlToCommonPool(dbPool)
|
return s.sqlToCommonPool(dbPool)
|
||||||
|
|
@ -358,7 +358,7 @@ func (s *sqlDatabase) GetEntityPool(_ context.Context, entity params.ForgeEntity
|
||||||
func (s *sqlDatabase) DeleteEntityPool(_ context.Context, entity params.ForgeEntity, poolID string) (err error) {
|
func (s *sqlDatabase) DeleteEntityPool(_ context.Context, entity params.ForgeEntity, poolID string) (err error) {
|
||||||
entityID, err := uuid.Parse(entity.ID)
|
entityID, err := uuid.Parse(entity.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(runnerErrors.ErrBadRequest, "parsing id")
|
return fmt.Errorf("error parsing id: %w", runnerErrors.ErrBadRequest)
|
||||||
}
|
}
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
|
|
@ -372,7 +372,7 @@ func (s *sqlDatabase) DeleteEntityPool(_ context.Context, entity params.ForgeEnt
|
||||||
|
|
||||||
poolUUID, err := uuid.Parse(poolID)
|
poolUUID, err := uuid.Parse(poolID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(runnerErrors.ErrBadRequest, "parsing pool id")
|
return fmt.Errorf("error parsing pool id: %w", runnerErrors.ErrBadRequest)
|
||||||
}
|
}
|
||||||
var fieldName string
|
var fieldName string
|
||||||
switch entity.EntityType {
|
switch entity.EntityType {
|
||||||
|
|
@ -387,7 +387,7 @@ func (s *sqlDatabase) DeleteEntityPool(_ context.Context, entity params.ForgeEnt
|
||||||
}
|
}
|
||||||
condition := fmt.Sprintf("id = ? and %s = ?", fieldName)
|
condition := fmt.Sprintf("id = ? and %s = ?", fieldName)
|
||||||
if err := s.conn.Unscoped().Where(condition, poolUUID, entityID).Delete(&Pool{}).Error; err != nil {
|
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
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -401,12 +401,12 @@ func (s *sqlDatabase) UpdateEntityPool(ctx context.Context, entity params.ForgeE
|
||||||
err = s.conn.Transaction(func(tx *gorm.DB) error {
|
err = s.conn.Transaction(func(tx *gorm.DB) error {
|
||||||
pool, err := s.getEntityPool(tx, entity.EntityType, entity.ID, poolID, "Tags", "Instances")
|
pool, err := s.getEntityPool(tx, entity.EntityType, entity.ID, poolID, "Tags", "Instances")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "fetching pool")
|
return fmt.Errorf("error fetching pool: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
updatedPool, err = s.updatePool(tx, pool, param)
|
updatedPool, err = s.updatePool(tx, pool, param)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "updating pool")
|
return fmt.Errorf("error updating pool: %w", err)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
|
|
@ -424,14 +424,14 @@ func (s *sqlDatabase) UpdateEntityPool(ctx context.Context, entity params.ForgeE
|
||||||
func (s *sqlDatabase) ListEntityPools(_ context.Context, entity params.ForgeEntity) ([]params.Pool, error) {
|
func (s *sqlDatabase) ListEntityPools(_ context.Context, entity params.ForgeEntity) ([]params.Pool, error) {
|
||||||
pools, err := s.listEntityPools(s.conn, entity.EntityType, entity.ID, "Tags")
|
pools, err := s.listEntityPools(s.conn, entity.EntityType, entity.ID, "Tags")
|
||||||
if err != nil {
|
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))
|
ret := make([]params.Pool, len(pools))
|
||||||
for idx, pool := range pools {
|
for idx, pool := range pools {
|
||||||
ret[idx], err = s.sqlToCommonPool(pool)
|
ret[idx], err = s.sqlToCommonPool(pool)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "fetching pool")
|
return nil, fmt.Errorf("error fetching pool: %w", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -441,7 +441,7 @@ func (s *sqlDatabase) ListEntityPools(_ context.Context, entity params.ForgeEnti
|
||||||
func (s *sqlDatabase) ListEntityInstances(_ context.Context, entity params.ForgeEntity) ([]params.Instance, error) {
|
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")
|
pools, err := s.listEntityPools(s.conn, entity.EntityType, entity.ID, "Instances", "Instances.Job")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "fetching entity")
|
return nil, fmt.Errorf("error fetching entity: %w", err)
|
||||||
}
|
}
|
||||||
ret := []params.Instance{}
|
ret := []params.Instance{}
|
||||||
for _, pool := range pools {
|
for _, pool := range pools {
|
||||||
|
|
@ -451,7 +451,7 @@ func (s *sqlDatabase) ListEntityInstances(_ context.Context, entity params.Forge
|
||||||
instance.Pool = pool
|
instance.Pool = pool
|
||||||
paramsInstance, err := s.sqlToParamsInstance(instance)
|
paramsInstance, err := s.sqlToParamsInstance(instance)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "fetching instance")
|
return nil, fmt.Errorf("error fetching instance: %w", err)
|
||||||
}
|
}
|
||||||
ret = append(ret, paramsInstance)
|
ret = append(ret, paramsInstance)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -157,7 +157,7 @@ func (s *PoolsTestSuite) TestListAllPoolsDBFetchErr() {
|
||||||
|
|
||||||
s.assertSQLMockExpectations()
|
s.assertSQLMockExpectations()
|
||||||
s.Require().NotNil(err)
|
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() {
|
func (s *PoolsTestSuite) TestGetPoolByID() {
|
||||||
|
|
@ -171,7 +171,7 @@ func (s *PoolsTestSuite) TestGetPoolByIDInvalidPoolID() {
|
||||||
_, err := s.Store.GetPoolByID(s.adminCtx, "dummy-pool-id")
|
_, err := s.Store.GetPoolByID(s.adminCtx, "dummy-pool-id")
|
||||||
|
|
||||||
s.Require().NotNil(err)
|
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() {
|
func (s *PoolsTestSuite) TestDeletePoolByID() {
|
||||||
|
|
@ -179,14 +179,14 @@ func (s *PoolsTestSuite) TestDeletePoolByID() {
|
||||||
|
|
||||||
s.Require().Nil(err)
|
s.Require().Nil(err)
|
||||||
_, err = s.Store.GetPoolByID(s.adminCtx, s.Fixtures.Pools[0].ID)
|
_, 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() {
|
func (s *PoolsTestSuite) TestDeletePoolByIDInvalidPoolID() {
|
||||||
err := s.Store.DeletePoolByID(s.adminCtx, "dummy-pool-id")
|
err := s.Store.DeletePoolByID(s.adminCtx, "dummy-pool-id")
|
||||||
|
|
||||||
s.Require().NotNil(err)
|
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() {
|
func (s *PoolsTestSuite) TestDeletePoolByIDDBRemoveErr() {
|
||||||
|
|
@ -204,7 +204,7 @@ func (s *PoolsTestSuite) TestDeletePoolByIDDBRemoveErr() {
|
||||||
|
|
||||||
s.assertSQLMockExpectations()
|
s.assertSQLMockExpectations()
|
||||||
s.Require().NotNil(err)
|
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() {
|
func (s *PoolsTestSuite) TestEntityPoolOperations() {
|
||||||
|
|
|
||||||
|
|
@ -16,11 +16,11 @@ package sql
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
|
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
"github.com/pkg/errors"
|
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
|
|
||||||
runnerErrors "github.com/cloudbase/garm-provider-common/errors"
|
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:
|
case params.GiteaEndpointType:
|
||||||
newRepo.GiteaCredentialsID = &credentials.ID
|
newRepo.GiteaCredentialsID = &credentials.ID
|
||||||
default:
|
default:
|
||||||
return errors.Wrap(runnerErrors.ErrBadRequest, "unsupported credentials type")
|
return runnerErrors.NewBadRequestError("unsupported credentials type")
|
||||||
}
|
}
|
||||||
|
|
||||||
newRepo.EndpointName = &credentials.Endpoint.Name
|
newRepo.EndpointName = &credentials.Endpoint.Name
|
||||||
q := tx.Create(&newRepo)
|
q := tx.Create(&newRepo)
|
||||||
if q.Error != nil {
|
if q.Error != nil {
|
||||||
return errors.Wrap(q.Error, "creating repository")
|
return fmt.Errorf("error creating repository: %w", q.Error)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
if err != 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())
|
ret, err := s.GetRepositoryByID(ctx, newRepo.ID.String())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return params.Repository{}, errors.Wrap(err, "creating repository")
|
return params.Repository{}, fmt.Errorf("error creating repository: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret, nil
|
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) {
|
func (s *sqlDatabase) GetRepository(ctx context.Context, owner, name, endpointName string) (params.Repository, error) {
|
||||||
repo, err := s.getRepo(ctx, owner, name, endpointName)
|
repo, err := s.getRepo(ctx, owner, name, endpointName)
|
||||||
if err != nil {
|
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)
|
param, err := s.sqlToCommonRepository(repo, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return params.Repository{}, errors.Wrap(err, "fetching repo")
|
return params.Repository{}, fmt.Errorf("error fetching repo: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return param, nil
|
return param, nil
|
||||||
|
|
@ -112,7 +112,7 @@ func (s *sqlDatabase) ListRepositories(_ context.Context, filter params.Reposito
|
||||||
}
|
}
|
||||||
q = q.Find(&repos)
|
q = q.Find(&repos)
|
||||||
if q.Error != nil {
|
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))
|
ret := make([]params.Repository, len(repos))
|
||||||
|
|
@ -120,7 +120,7 @@ func (s *sqlDatabase) ListRepositories(_ context.Context, filter params.Reposito
|
||||||
var err error
|
var err error
|
||||||
ret[idx], err = s.sqlToCommonRepository(val, true)
|
ret[idx], err = s.sqlToCommonRepository(val, true)
|
||||||
if err != nil {
|
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) {
|
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")
|
repo, err := s.getRepoByID(ctx, s.conn, repoID, "Endpoint", "Credentials", "Credentials.Endpoint", "GiteaCredentials", "GiteaCredentials.Endpoint")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "fetching repo")
|
return fmt.Errorf("error fetching repo: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
defer func(repo Repository) {
|
defer func(repo Repository) {
|
||||||
|
|
@ -146,7 +146,7 @@ func (s *sqlDatabase) DeleteRepository(ctx context.Context, repoID string) (err
|
||||||
|
|
||||||
q := s.conn.Unscoped().Delete(&repo)
|
q := s.conn.Unscoped().Delete(&repo)
|
||||||
if q.Error != nil && !errors.Is(q.Error, gorm.ErrRecordNotFound) {
|
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
|
return nil
|
||||||
|
|
@ -164,23 +164,23 @@ func (s *sqlDatabase) UpdateRepository(ctx context.Context, repoID string, param
|
||||||
var err error
|
var err error
|
||||||
repo, err = s.getRepoByID(ctx, tx, repoID)
|
repo, err = s.getRepoByID(ctx, tx, repoID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "fetching repo")
|
return fmt.Errorf("error fetching repo: %w", err)
|
||||||
}
|
}
|
||||||
if repo.EndpointName == nil {
|
if repo.EndpointName == nil {
|
||||||
return errors.Wrap(runnerErrors.ErrUnprocessable, "repository has no endpoint")
|
return runnerErrors.NewUnprocessableError("repository has no endpoint")
|
||||||
}
|
}
|
||||||
|
|
||||||
if param.CredentialsName != "" {
|
if param.CredentialsName != "" {
|
||||||
creds, err = s.getGithubCredentialsByName(ctx, tx, param.CredentialsName, false)
|
creds, err = s.getGithubCredentialsByName(ctx, tx, param.CredentialsName, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "fetching credentials")
|
return fmt.Errorf("error fetching credentials: %w", err)
|
||||||
}
|
}
|
||||||
if creds.EndpointName == nil {
|
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 {
|
if *creds.EndpointName != *repo.EndpointName {
|
||||||
return errors.Wrap(runnerErrors.ErrBadRequest, "endpoint mismatch")
|
return runnerErrors.NewBadRequestError("endpoint mismatch")
|
||||||
}
|
}
|
||||||
repo.CredentialsID = &creds.ID
|
repo.CredentialsID = &creds.ID
|
||||||
}
|
}
|
||||||
|
|
@ -199,23 +199,23 @@ func (s *sqlDatabase) UpdateRepository(ctx context.Context, repoID string, param
|
||||||
|
|
||||||
q := tx.Save(&repo)
|
q := tx.Save(&repo)
|
||||||
if q.Error != nil {
|
if q.Error != nil {
|
||||||
return errors.Wrap(q.Error, "saving repo")
|
return fmt.Errorf("error saving repo: %w", q.Error)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
if err != 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")
|
repo, err = s.getRepoByID(ctx, s.conn, repoID, "Endpoint", "Credentials", "Credentials.Endpoint", "GiteaCredentials", "GiteaCredentials.Endpoint")
|
||||||
if err != nil {
|
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)
|
newParams, err = s.sqlToCommonRepository(repo, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return params.Repository{}, errors.Wrap(err, "saving repo")
|
return params.Repository{}, fmt.Errorf("error saving repo: %w", err)
|
||||||
}
|
}
|
||||||
return newParams, nil
|
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...)
|
repo, err := s.getRepoByID(ctx, s.conn, repoID, preloadList...)
|
||||||
if err != nil {
|
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)
|
param, err := s.sqlToCommonRepository(repo, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return params.Repository{}, errors.Wrap(err, "fetching repo")
|
return params.Repository{}, fmt.Errorf("error fetching repo: %w", err)
|
||||||
}
|
}
|
||||||
return param, nil
|
return param, nil
|
||||||
}
|
}
|
||||||
|
|
@ -259,7 +259,7 @@ func (s *sqlDatabase) getRepo(_ context.Context, owner, name, endpointName strin
|
||||||
if errors.Is(q.Error, gorm.ErrRecordNotFound) {
|
if errors.Is(q.Error, gorm.ErrRecordNotFound) {
|
||||||
return Repository{}, runnerErrors.ErrNotFound
|
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
|
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) {
|
func (s *sqlDatabase) getRepoByID(_ context.Context, tx *gorm.DB, id string, preload ...string) (Repository, error) {
|
||||||
u, err := uuid.Parse(id)
|
u, err := uuid.Parse(id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return Repository{}, errors.Wrap(runnerErrors.ErrBadRequest, "parsing id")
|
return Repository{}, runnerErrors.NewBadRequestError("error parsing id: %s", err)
|
||||||
}
|
}
|
||||||
var repo Repository
|
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) {
|
if errors.Is(q.Error, gorm.ErrRecordNotFound) {
|
||||||
return Repository{}, runnerErrors.ErrNotFound
|
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
|
return repo, nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -284,7 +284,7 @@ func (s *RepoTestSuite) TestCreateRepositoryInvalidForgeType() {
|
||||||
)
|
)
|
||||||
|
|
||||||
s.Require().NotNil(err)
|
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() {
|
func (s *RepoTestSuite) TestCreateRepositoryInvalidDBPassphrase() {
|
||||||
|
|
@ -330,7 +330,7 @@ func (s *RepoTestSuite) TestCreateRepositoryInvalidDBCreateErr() {
|
||||||
)
|
)
|
||||||
|
|
||||||
s.Require().NotNil(err)
|
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()
|
s.assertSQLMockExpectations()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -355,7 +355,7 @@ func (s *RepoTestSuite) TestGetRepositoryNotFound() {
|
||||||
_, err := s.Store.GetRepository(s.adminCtx, "dummy-owner", "dummy-name", "github.com")
|
_, err := s.Store.GetRepository(s.adminCtx, "dummy-owner", "dummy-name", "github.com")
|
||||||
|
|
||||||
s.Require().NotNil(err)
|
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() {
|
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)
|
_, 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().NotNil(err)
|
||||||
s.Require().Equal("fetching repo: missing secret", err.Error())
|
s.Require().Equal("error fetching repo: missing secret", err.Error())
|
||||||
s.assertSQLMockExpectations()
|
s.assertSQLMockExpectations()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -471,7 +471,7 @@ func (s *RepoTestSuite) TestListRepositoriesDBFetchErr() {
|
||||||
_, err := s.StoreSQLMocked.ListRepositories(s.adminCtx, params.RepositoryFilter{})
|
_, err := s.StoreSQLMocked.ListRepositories(s.adminCtx, params.RepositoryFilter{})
|
||||||
|
|
||||||
s.Require().NotNil(err)
|
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()
|
s.assertSQLMockExpectations()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -485,7 +485,7 @@ func (s *RepoTestSuite) TestListRepositoriesDBDecryptingErr() {
|
||||||
_, err := s.StoreSQLMocked.ListRepositories(s.adminCtx, params.RepositoryFilter{})
|
_, err := s.StoreSQLMocked.ListRepositories(s.adminCtx, params.RepositoryFilter{})
|
||||||
|
|
||||||
s.Require().NotNil(err)
|
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()
|
s.assertSQLMockExpectations()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -495,14 +495,14 @@ func (s *RepoTestSuite) TestDeleteRepository() {
|
||||||
s.Require().Nil(err)
|
s.Require().Nil(err)
|
||||||
_, err = s.Store.GetRepositoryByID(s.adminCtx, s.Fixtures.Repos[0].ID)
|
_, err = s.Store.GetRepositoryByID(s.adminCtx, s.Fixtures.Repos[0].ID)
|
||||||
s.Require().NotNil(err)
|
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() {
|
func (s *RepoTestSuite) TestDeleteRepositoryInvalidRepoID() {
|
||||||
err := s.Store.DeleteRepository(s.adminCtx, "dummy-repo-id")
|
err := s.Store.DeleteRepository(s.adminCtx, "dummy-repo-id")
|
||||||
|
|
||||||
s.Require().NotNil(err)
|
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() {
|
func (s *RepoTestSuite) TestDeleteRepositoryDBRemoveErr() {
|
||||||
|
|
@ -520,7 +520,7 @@ func (s *RepoTestSuite) TestDeleteRepositoryDBRemoveErr() {
|
||||||
err := s.StoreSQLMocked.DeleteRepository(s.adminCtx, s.Fixtures.Repos[0].ID)
|
err := s.StoreSQLMocked.DeleteRepository(s.adminCtx, s.Fixtures.Repos[0].ID)
|
||||||
|
|
||||||
s.Require().NotNil(err)
|
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()
|
s.assertSQLMockExpectations()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -536,7 +536,7 @@ func (s *RepoTestSuite) TestUpdateRepositoryInvalidRepoID() {
|
||||||
_, err := s.Store.UpdateRepository(s.adminCtx, "dummy-repo-id", s.Fixtures.UpdateRepoParams)
|
_, err := s.Store.UpdateRepository(s.adminCtx, "dummy-repo-id", s.Fixtures.UpdateRepoParams)
|
||||||
|
|
||||||
s.Require().NotNil(err)
|
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() {
|
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)
|
_, err := s.StoreSQLMocked.UpdateRepository(s.adminCtx, s.Fixtures.Repos[0].ID, s.Fixtures.UpdateRepoParams)
|
||||||
|
|
||||||
s.Require().NotNil(err)
|
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()
|
s.assertSQLMockExpectations()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -589,7 +589,7 @@ func (s *RepoTestSuite) TestUpdateRepositoryDBSaveErr() {
|
||||||
_, err := s.StoreSQLMocked.UpdateRepository(s.adminCtx, s.Fixtures.Repos[0].ID, s.Fixtures.UpdateRepoParams)
|
_, err := s.StoreSQLMocked.UpdateRepository(s.adminCtx, s.Fixtures.Repos[0].ID, s.Fixtures.UpdateRepoParams)
|
||||||
|
|
||||||
s.Require().NotNil(err)
|
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()
|
s.assertSQLMockExpectations()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -616,7 +616,7 @@ func (s *RepoTestSuite) TestUpdateRepositoryDBDecryptingErr() {
|
||||||
_, err := s.StoreSQLMocked.UpdateRepository(s.adminCtx, s.Fixtures.Repos[0].ID, s.Fixtures.UpdateRepoParams)
|
_, err := s.StoreSQLMocked.UpdateRepository(s.adminCtx, s.Fixtures.Repos[0].ID, s.Fixtures.UpdateRepoParams)
|
||||||
|
|
||||||
s.Require().NotNil(err)
|
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()
|
s.assertSQLMockExpectations()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -631,7 +631,7 @@ func (s *RepoTestSuite) TestGetRepositoryByIDInvalidRepoID() {
|
||||||
_, err := s.Store.GetRepositoryByID(s.adminCtx, "dummy-repo-id")
|
_, err := s.Store.GetRepositoryByID(s.adminCtx, "dummy-repo-id")
|
||||||
|
|
||||||
s.Require().NotNil(err)
|
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() {
|
func (s *RepoTestSuite) TestGetRepositoryByIDDBDecryptingErr() {
|
||||||
|
|
@ -651,7 +651,7 @@ func (s *RepoTestSuite) TestGetRepositoryByIDDBDecryptingErr() {
|
||||||
_, err := s.StoreSQLMocked.GetRepositoryByID(s.adminCtx, s.Fixtures.Repos[0].ID)
|
_, err := s.StoreSQLMocked.GetRepositoryByID(s.adminCtx, s.Fixtures.Repos[0].ID)
|
||||||
|
|
||||||
s.Require().NotNil(err)
|
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()
|
s.assertSQLMockExpectations()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -690,7 +690,7 @@ func (s *RepoTestSuite) TestCreateRepositoryPoolInvalidRepoID() {
|
||||||
_, err := s.Store.CreateEntityPool(s.adminCtx, entity, s.Fixtures.CreatePoolParams)
|
_, err := s.Store.CreateEntityPool(s.adminCtx, entity, s.Fixtures.CreatePoolParams)
|
||||||
|
|
||||||
s.Require().NotNil(err)
|
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() {
|
func (s *RepoTestSuite) TestCreateRepositoryPoolDBFetchTagErr() {
|
||||||
|
|
@ -709,7 +709,7 @@ func (s *RepoTestSuite) TestCreateRepositoryPoolDBFetchTagErr() {
|
||||||
_, err = s.StoreSQLMocked.CreateEntityPool(s.adminCtx, entity, s.Fixtures.CreatePoolParams)
|
_, err = s.StoreSQLMocked.CreateEntityPool(s.adminCtx, entity, s.Fixtures.CreatePoolParams)
|
||||||
|
|
||||||
s.Require().NotNil(err)
|
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()
|
s.assertSQLMockExpectations()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -738,7 +738,7 @@ func (s *RepoTestSuite) TestCreateRepositoryPoolDBAddingPoolErr() {
|
||||||
_, err = s.StoreSQLMocked.CreateEntityPool(s.adminCtx, entity, s.Fixtures.CreatePoolParams)
|
_, err = s.StoreSQLMocked.CreateEntityPool(s.adminCtx, entity, s.Fixtures.CreatePoolParams)
|
||||||
|
|
||||||
s.Require().NotNil(err)
|
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()
|
s.assertSQLMockExpectations()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -769,7 +769,7 @@ func (s *RepoTestSuite) TestCreateRepositoryPoolDBSaveTagErr() {
|
||||||
|
|
||||||
_, err = s.StoreSQLMocked.CreateEntityPool(s.adminCtx, entity, s.Fixtures.CreatePoolParams)
|
_, err = s.StoreSQLMocked.CreateEntityPool(s.adminCtx, entity, s.Fixtures.CreatePoolParams)
|
||||||
s.Require().NotNil(err)
|
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()
|
s.assertSQLMockExpectations()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -810,7 +810,7 @@ func (s *RepoTestSuite) TestCreateRepositoryPoolDBFetchPoolErr() {
|
||||||
_, err = s.StoreSQLMocked.CreateEntityPool(s.adminCtx, entity, s.Fixtures.CreatePoolParams)
|
_, err = s.StoreSQLMocked.CreateEntityPool(s.adminCtx, entity, s.Fixtures.CreatePoolParams)
|
||||||
|
|
||||||
s.Require().NotNil(err)
|
s.Require().NotNil(err)
|
||||||
s.Require().Equal("fetching pool: not found", err.Error())
|
s.Require().Equal("error fetching pool: not found", err.Error())
|
||||||
s.assertSQLMockExpectations()
|
s.assertSQLMockExpectations()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -841,7 +841,7 @@ func (s *RepoTestSuite) TestListRepoPoolsInvalidRepoID() {
|
||||||
_, err := s.Store.ListEntityPools(s.adminCtx, entity)
|
_, err := s.Store.ListEntityPools(s.adminCtx, entity)
|
||||||
|
|
||||||
s.Require().NotNil(err)
|
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() {
|
func (s *RepoTestSuite) TestGetRepositoryPool() {
|
||||||
|
|
@ -866,7 +866,7 @@ func (s *RepoTestSuite) TestGetRepositoryPoolInvalidRepoID() {
|
||||||
_, err := s.Store.GetEntityPool(s.adminCtx, entity, "dummy-pool-id")
|
_, err := s.Store.GetEntityPool(s.adminCtx, entity, "dummy-pool-id")
|
||||||
|
|
||||||
s.Require().NotNil(err)
|
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() {
|
func (s *RepoTestSuite) TestDeleteRepositoryPool() {
|
||||||
|
|
@ -881,7 +881,7 @@ func (s *RepoTestSuite) TestDeleteRepositoryPool() {
|
||||||
|
|
||||||
s.Require().Nil(err)
|
s.Require().Nil(err)
|
||||||
_, err = s.Store.GetEntityPool(s.adminCtx, entity, pool.ID)
|
_, 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() {
|
func (s *RepoTestSuite) TestDeleteRepositoryPoolInvalidRepoID() {
|
||||||
|
|
@ -892,7 +892,7 @@ func (s *RepoTestSuite) TestDeleteRepositoryPoolInvalidRepoID() {
|
||||||
err := s.Store.DeleteEntityPool(s.adminCtx, entity, "dummy-pool-id")
|
err := s.Store.DeleteEntityPool(s.adminCtx, entity, "dummy-pool-id")
|
||||||
|
|
||||||
s.Require().NotNil(err)
|
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() {
|
func (s *RepoTestSuite) TestDeleteRepositoryPoolDBDeleteErr() {
|
||||||
|
|
@ -913,7 +913,7 @@ func (s *RepoTestSuite) TestDeleteRepositoryPoolDBDeleteErr() {
|
||||||
|
|
||||||
err = s.StoreSQLMocked.DeleteEntityPool(s.adminCtx, entity, pool.ID)
|
err = s.StoreSQLMocked.DeleteEntityPool(s.adminCtx, entity, pool.ID)
|
||||||
s.Require().NotNil(err)
|
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()
|
s.assertSQLMockExpectations()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -948,7 +948,7 @@ func (s *RepoTestSuite) TestListRepoInstancesInvalidRepoID() {
|
||||||
_, err := s.Store.ListEntityInstances(s.adminCtx, entity)
|
_, err := s.Store.ListEntityInstances(s.adminCtx, entity)
|
||||||
|
|
||||||
s.Require().NotNil(err)
|
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() {
|
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)
|
_, err := s.Store.UpdateEntityPool(s.adminCtx, entity, "dummy-repo-id", s.Fixtures.UpdatePoolParams)
|
||||||
|
|
||||||
s.Require().NotNil(err)
|
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() {
|
func (s *RepoTestSuite) TestAddRepoEntityEvent() {
|
||||||
|
|
|
||||||
|
|
@ -16,8 +16,7 @@ package sql
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
"github.com/pkg/errors"
|
|
||||||
|
|
||||||
"github.com/cloudbase/garm/database/common"
|
"github.com/cloudbase/garm/database/common"
|
||||||
"github.com/cloudbase/garm/params"
|
"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) {
|
func (s *sqlDatabase) CreateScaleSetInstance(_ context.Context, scaleSetID uint, param params.CreateInstanceParams) (instance params.Instance, err error) {
|
||||||
scaleSet, err := s.getScaleSetByID(s.conn, scaleSetID)
|
scaleSet, err := s.getScaleSetByID(s.conn, scaleSetID)
|
||||||
if err != nil {
|
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() {
|
defer func() {
|
||||||
|
|
@ -39,7 +38,7 @@ func (s *sqlDatabase) CreateScaleSetInstance(_ context.Context, scaleSetID uint,
|
||||||
if len(param.JitConfiguration) > 0 {
|
if len(param.JitConfiguration) > 0 {
|
||||||
secret, err = s.marshalAndSeal(param.JitConfiguration)
|
secret, err = s.marshalAndSeal(param.JitConfiguration)
|
||||||
if err != nil {
|
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)
|
q := s.conn.Create(&newInstance)
|
||||||
if q.Error != nil {
|
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)
|
return s.sqlToParamsInstance(newInstance)
|
||||||
|
|
@ -72,7 +71,7 @@ func (s *sqlDatabase) ListScaleSetInstances(_ context.Context, scalesetID uint)
|
||||||
Where("scale_set_fk_id = ?", scalesetID)
|
Where("scale_set_fk_id = ?", scalesetID)
|
||||||
|
|
||||||
if err := query.Find(&instances); err.Error != nil {
|
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
|
var err error
|
||||||
|
|
@ -80,7 +79,7 @@ func (s *sqlDatabase) ListScaleSetInstances(_ context.Context, scalesetID uint)
|
||||||
for idx, inst := range instances {
|
for idx, inst := range instances {
|
||||||
ret[idx], err = s.sqlToParamsInstance(inst)
|
ret[idx], err = s.sqlToParamsInstance(inst)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "converting instance")
|
return nil, fmt.Errorf("error converting instance: %w", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ret, nil
|
return ret, nil
|
||||||
|
|
|
||||||
|
|
@ -16,10 +16,10 @@ package sql
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
"github.com/pkg/errors"
|
|
||||||
"gorm.io/datatypes"
|
"gorm.io/datatypes"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
|
|
||||||
|
|
@ -42,7 +42,7 @@ func (s *sqlDatabase) ListAllScaleSets(_ context.Context) ([]params.ScaleSet, er
|
||||||
Omit("status_messages").
|
Omit("status_messages").
|
||||||
Find(&scaleSets)
|
Find(&scaleSets)
|
||||||
if q.Error != nil {
|
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))
|
ret := make([]params.ScaleSet, len(scaleSets))
|
||||||
|
|
@ -50,7 +50,7 @@ func (s *sqlDatabase) ListAllScaleSets(_ context.Context) ([]params.ScaleSet, er
|
||||||
for idx, val := range scaleSets {
|
for idx, val := range scaleSets {
|
||||||
ret[idx], err = s.sqlToCommonScaleSet(val)
|
ret[idx], err = s.sqlToCommonScaleSet(val)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "converting scale sets")
|
return nil, fmt.Errorf("error converting scale sets: %w", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ret, nil
|
return ret, nil
|
||||||
|
|
@ -91,7 +91,7 @@ func (s *sqlDatabase) CreateEntityScaleSet(_ context.Context, entity params.Forg
|
||||||
|
|
||||||
entityID, err := uuid.Parse(entity.ID)
|
entityID, err := uuid.Parse(entity.ID)
|
||||||
if err != nil {
|
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 {
|
switch entity.EntityType {
|
||||||
|
|
@ -104,12 +104,12 @@ func (s *sqlDatabase) CreateEntityScaleSet(_ context.Context, entity params.Forg
|
||||||
}
|
}
|
||||||
err = s.conn.Transaction(func(tx *gorm.DB) error {
|
err = s.conn.Transaction(func(tx *gorm.DB) error {
|
||||||
if err := s.hasGithubEntity(tx, entity.EntityType, entity.ID); err != nil {
|
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)
|
q := tx.Create(&newScaleSet)
|
||||||
if q.Error != nil {
|
if q.Error != nil {
|
||||||
return errors.Wrap(q.Error, "creating scale set")
|
return fmt.Errorf("error creating scale set: %w", q.Error)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
@ -120,7 +120,7 @@ func (s *sqlDatabase) CreateEntityScaleSet(_ context.Context, entity params.Forg
|
||||||
|
|
||||||
dbScaleSet, err := s.getScaleSetByID(s.conn, newScaleSet.ID, "Instances", "Enterprise", "Organization", "Repository")
|
dbScaleSet, err := s.getScaleSetByID(s.conn, newScaleSet.ID, "Instances", "Enterprise", "Organization", "Repository")
|
||||||
if err != nil {
|
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)
|
return s.sqlToCommonScaleSet(dbScaleSet)
|
||||||
|
|
@ -128,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) {
|
func (s *sqlDatabase) listEntityScaleSets(tx *gorm.DB, entityType params.ForgeEntityType, entityID string, preload ...string) ([]ScaleSet, error) {
|
||||||
if _, err := uuid.Parse(entityID); err != nil {
|
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 {
|
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
|
var preloadEntity string
|
||||||
|
|
@ -170,7 +170,7 @@ func (s *sqlDatabase) listEntityScaleSets(tx *gorm.DB, entityType params.ForgeEn
|
||||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||||
return []ScaleSet{}, nil
|
return []ScaleSet{}, nil
|
||||||
}
|
}
|
||||||
return nil, errors.Wrap(err, "fetching scale sets")
|
return nil, fmt.Errorf("error fetching scale sets: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return scaleSets, nil
|
return scaleSets, nil
|
||||||
|
|
@ -179,14 +179,14 @@ func (s *sqlDatabase) listEntityScaleSets(tx *gorm.DB, entityType params.ForgeEn
|
||||||
func (s *sqlDatabase) ListEntityScaleSets(_ context.Context, entity params.ForgeEntity) ([]params.ScaleSet, error) {
|
func (s *sqlDatabase) ListEntityScaleSets(_ context.Context, entity params.ForgeEntity) ([]params.ScaleSet, error) {
|
||||||
scaleSets, err := s.listEntityScaleSets(s.conn, entity.EntityType, entity.ID)
|
scaleSets, err := s.listEntityScaleSets(s.conn, entity.EntityType, entity.ID)
|
||||||
if err != nil {
|
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))
|
ret := make([]params.ScaleSet, len(scaleSets))
|
||||||
for idx, set := range scaleSets {
|
for idx, set := range scaleSets {
|
||||||
ret[idx], err = s.sqlToCommonScaleSet(set)
|
ret[idx], err = s.sqlToCommonScaleSet(set)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "conbverting scale set")
|
return nil, fmt.Errorf("error conbverting scale set: %w", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -202,22 +202,22 @@ func (s *sqlDatabase) UpdateEntityScaleSet(ctx context.Context, entity params.Fo
|
||||||
err = s.conn.Transaction(func(tx *gorm.DB) error {
|
err = s.conn.Transaction(func(tx *gorm.DB) error {
|
||||||
scaleSet, err := s.getEntityScaleSet(tx, entity.EntityType, entity.ID, scaleSetID, "Instances")
|
scaleSet, err := s.getEntityScaleSet(tx, entity.EntityType, entity.ID, scaleSetID, "Instances")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "fetching scale set")
|
return fmt.Errorf("error fetching scale set: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
old, err := s.sqlToCommonScaleSet(scaleSet)
|
old, err := s.sqlToCommonScaleSet(scaleSet)
|
||||||
if err != nil {
|
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)
|
updatedScaleSet, err = s.updateScaleSet(tx, scaleSet, param)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "updating scale set")
|
return fmt.Errorf("error updating scale set: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if callback != nil {
|
if callback != nil {
|
||||||
if err := callback(old, updatedScaleSet); err != 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
|
return nil
|
||||||
|
|
@ -235,11 +235,11 @@ func (s *sqlDatabase) UpdateEntityScaleSet(ctx context.Context, entity params.Fo
|
||||||
|
|
||||||
func (s *sqlDatabase) getEntityScaleSet(tx *gorm.DB, entityType params.ForgeEntityType, entityID string, scaleSetID uint, preload ...string) (ScaleSet, error) {
|
func (s *sqlDatabase) getEntityScaleSet(tx *gorm.DB, entityType params.ForgeEntityType, entityID string, scaleSetID uint, preload ...string) (ScaleSet, error) {
|
||||||
if entityID == "" {
|
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 {
|
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
|
var fieldName string
|
||||||
|
|
@ -273,9 +273,9 @@ func (s *sqlDatabase) getEntityScaleSet(tx *gorm.DB, entityType params.ForgeEnti
|
||||||
First(&scaleSet).Error
|
First(&scaleSet).Error
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
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
|
return scaleSet, nil
|
||||||
|
|
@ -343,7 +343,7 @@ func (s *sqlDatabase) updateScaleSet(tx *gorm.DB, scaleSet ScaleSet, param param
|
||||||
}
|
}
|
||||||
|
|
||||||
if q := tx.Save(&scaleSet); q.Error != nil {
|
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)
|
return s.sqlToCommonScaleSet(scaleSet)
|
||||||
|
|
@ -362,7 +362,7 @@ func (s *sqlDatabase) GetScaleSetByID(_ context.Context, scaleSet uint) (params.
|
||||||
"Repository.Endpoint",
|
"Repository.Endpoint",
|
||||||
)
|
)
|
||||||
if err != nil {
|
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)
|
return s.sqlToCommonScaleSet(set)
|
||||||
}
|
}
|
||||||
|
|
@ -377,7 +377,7 @@ func (s *sqlDatabase) DeleteScaleSetByID(_ context.Context, scaleSetID uint) (er
|
||||||
err = s.conn.Transaction(func(tx *gorm.DB) error {
|
err = s.conn.Transaction(func(tx *gorm.DB) error {
|
||||||
dbSet, err := s.getScaleSetByID(tx, scaleSetID, "Instances", "Enterprise", "Organization", "Repository")
|
dbSet, err := s.getScaleSetByID(tx, scaleSetID, "Instances", "Enterprise", "Organization", "Repository")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "fetching scale set")
|
return fmt.Errorf("error fetching scale set: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(dbSet.Instances) > 0 {
|
if len(dbSet.Instances) > 0 {
|
||||||
|
|
@ -385,16 +385,16 @@ func (s *sqlDatabase) DeleteScaleSetByID(_ context.Context, scaleSetID uint) (er
|
||||||
}
|
}
|
||||||
scaleSet, err = s.sqlToCommonScaleSet(dbSet)
|
scaleSet, err = s.sqlToCommonScaleSet(dbSet)
|
||||||
if err != nil {
|
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 {
|
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
|
return nil
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "removing scale set")
|
return fmt.Errorf("error removing scale set: %w", err)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -409,19 +409,19 @@ func (s *sqlDatabase) SetScaleSetLastMessageID(_ context.Context, scaleSetID uin
|
||||||
if err := s.conn.Transaction(func(tx *gorm.DB) error {
|
if err := s.conn.Transaction(func(tx *gorm.DB) error {
|
||||||
dbSet, err := s.getScaleSetByID(tx, scaleSetID, "Instances", "Enterprise", "Organization", "Repository")
|
dbSet, err := s.getScaleSetByID(tx, scaleSetID, "Instances", "Enterprise", "Organization", "Repository")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "fetching scale set")
|
return fmt.Errorf("error fetching scale set: %w", err)
|
||||||
}
|
}
|
||||||
dbSet.LastMessageID = lastMessageID
|
dbSet.LastMessageID = lastMessageID
|
||||||
if err := tx.Save(&dbSet).Error; err != nil {
|
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)
|
scaleSet, err = s.sqlToCommonScaleSet(dbSet)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "converting scale set")
|
return fmt.Errorf("error converting scale set: %w", err)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return errors.Wrap(err, "setting last message ID")
|
return fmt.Errorf("error setting last message ID: %w", err)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -436,19 +436,19 @@ func (s *sqlDatabase) SetScaleSetDesiredRunnerCount(_ context.Context, scaleSetI
|
||||||
if err := s.conn.Transaction(func(tx *gorm.DB) error {
|
if err := s.conn.Transaction(func(tx *gorm.DB) error {
|
||||||
dbSet, err := s.getScaleSetByID(tx, scaleSetID, "Instances", "Enterprise", "Organization", "Repository")
|
dbSet, err := s.getScaleSetByID(tx, scaleSetID, "Instances", "Enterprise", "Organization", "Repository")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "fetching scale set")
|
return fmt.Errorf("error fetching scale set: %w", err)
|
||||||
}
|
}
|
||||||
dbSet.DesiredRunnerCount = desiredRunnerCount
|
dbSet.DesiredRunnerCount = desiredRunnerCount
|
||||||
if err := tx.Save(&dbSet).Error; err != nil {
|
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)
|
scaleSet, err = s.sqlToCommonScaleSet(dbSet)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "converting scale set")
|
return fmt.Errorf("error converting scale set: %w", err)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return errors.Wrap(err, "setting desired runner count")
|
return fmt.Errorf("error setting desired runner count: %w", err)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,12 +16,12 @@ package sql
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
"net/url"
|
"net/url"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
"gorm.io/driver/mysql"
|
"gorm.io/driver/mysql"
|
||||||
"gorm.io/driver/sqlite"
|
"gorm.io/driver/sqlite"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
|
|
@ -46,7 +46,7 @@ const (
|
||||||
func newDBConn(dbCfg config.Database) (conn *gorm.DB, err error) {
|
func newDBConn(dbCfg config.Database) (conn *gorm.DB, err error) {
|
||||||
dbType, connURI, err := dbCfg.GormParams()
|
dbType, connURI, err := dbCfg.GormParams()
|
||||||
if err != nil {
|
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{}
|
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)
|
conn, err = gorm.Open(sqlite.Open(connURI), gormConfig)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "connecting to database")
|
return nil, fmt.Errorf("error connecting to database: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if dbCfg.Debug {
|
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) {
|
func NewSQLDatabase(ctx context.Context, cfg config.Database) (common.Store, error) {
|
||||||
conn, err := newDBConn(cfg)
|
conn, err := newDBConn(cfg)
|
||||||
if err != nil {
|
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")
|
producer, err := watcher.RegisterProducer(ctx, "sql")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "registering producer")
|
return nil, fmt.Errorf("error registering producer: %w", err)
|
||||||
}
|
}
|
||||||
db := &sqlDatabase{
|
db := &sqlDatabase{
|
||||||
conn: conn,
|
conn: conn,
|
||||||
|
|
@ -87,7 +87,7 @@ func NewSQLDatabase(ctx context.Context, cfg config.Database) (common.Store, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := db.migrateDB(); err != nil {
|
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
|
return db, nil
|
||||||
}
|
}
|
||||||
|
|
@ -221,14 +221,14 @@ func (s *sqlDatabase) ensureGithubEndpoint() error {
|
||||||
var epCount int64
|
var epCount int64
|
||||||
if err := s.conn.Model(&GithubEndpoint{}).Count(&epCount).Error; err != nil {
|
if err := s.conn.Model(&GithubEndpoint{}).Count(&epCount).Error; err != nil {
|
||||||
if !errors.Is(err, gorm.ErrRecordNotFound) {
|
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 epCount == 0 {
|
||||||
if _, err := s.CreateGithubEndpoint(context.Background(), createEndpointParams); err != nil {
|
if _, err := s.CreateGithubEndpoint(context.Background(), createEndpointParams); err != nil {
|
||||||
if !errors.Is(err, runnerErrors.ErrDuplicateEntity) {
|
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.
|
// Admin user doesn't exist. This is a new deploy. Nothing to migrate.
|
||||||
return nil
|
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
|
// 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("migrating credentials to DB")
|
||||||
slog.Info("creating github endpoints table")
|
slog.Info("creating github endpoints table")
|
||||||
if err := s.conn.AutoMigrate(&GithubEndpoint{}); err != nil {
|
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() {
|
defer func() {
|
||||||
|
|
@ -271,7 +271,7 @@ func (s *sqlDatabase) migrateCredentialsToDB() (err error) {
|
||||||
|
|
||||||
slog.Info("creating github credentials table")
|
slog.Info("creating github credentials table")
|
||||||
if err := s.conn.AutoMigrate(&GithubCredentials{}); err != nil {
|
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() {
|
defer func() {
|
||||||
|
|
@ -291,12 +291,12 @@ func (s *sqlDatabase) migrateCredentialsToDB() (err error) {
|
||||||
slog.Info("importing credential", "name", cred.Name)
|
slog.Info("importing credential", "name", cred.Name)
|
||||||
parsed, err := url.Parse(cred.BaseEndpoint())
|
parsed, err := url.Parse(cred.BaseEndpoint())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "parsing base URL")
|
return fmt.Errorf("error parsing base URL: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
certBundle, err := cred.CACertBundle()
|
certBundle, err := cred.CACertBundle()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "getting CA cert bundle")
|
return fmt.Errorf("error getting CA cert bundle: %w", err)
|
||||||
}
|
}
|
||||||
hostname := parsed.Hostname()
|
hostname := parsed.Hostname()
|
||||||
createParams := params.CreateGithubEndpointParams{
|
createParams := params.CreateGithubEndpointParams{
|
||||||
|
|
@ -312,11 +312,11 @@ func (s *sqlDatabase) migrateCredentialsToDB() (err error) {
|
||||||
endpoint, err = s.GetGithubEndpoint(adminCtx, hostname)
|
endpoint, err = s.GetGithubEndpoint(adminCtx, hostname)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if !errors.Is(err, runnerErrors.ErrNotFound) {
|
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)
|
endpoint, err = s.CreateGithubEndpoint(adminCtx, createParams)
|
||||||
if err != nil {
|
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:
|
case params.ForgeAuthTypeApp:
|
||||||
keyBytes, err := cred.App.PrivateKeyBytes()
|
keyBytes, err := cred.App.PrivateKeyBytes()
|
||||||
if err != nil {
|
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{
|
credParams.App = params.GithubApp{
|
||||||
AppID: cred.App.AppID,
|
AppID: cred.App.AppID,
|
||||||
|
|
@ -339,7 +339,7 @@ func (s *sqlDatabase) migrateCredentialsToDB() (err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := credParams.App.Validate(); err != nil {
|
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:
|
case params.ForgeAuthTypePAT:
|
||||||
token := cred.PAT.OAuth2Token
|
token := cred.PAT.OAuth2Token
|
||||||
|
|
@ -356,19 +356,19 @@ func (s *sqlDatabase) migrateCredentialsToDB() (err error) {
|
||||||
|
|
||||||
creds, err := s.CreateGithubCredentials(adminCtx, credParams)
|
creds, err := s.CreateGithubCredentials(adminCtx, credParams)
|
||||||
if err != nil {
|
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 {
|
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 {
|
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 {
|
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
|
return nil
|
||||||
|
|
@ -380,10 +380,10 @@ func (s *sqlDatabase) migrateWorkflow() error {
|
||||||
// Remove jobs that are not in "queued" status. We really only care about queued jobs. Once they transition
|
// 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.
|
// 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 {
|
if err := s.conn.Exec("delete from workflow_jobs where status is not 'queued'").Error; err != nil {
|
||||||
return errors.Wrap(err, "updating workflow_jobs")
|
return fmt.Errorf("error updating workflow_jobs: %w", err)
|
||||||
}
|
}
|
||||||
if err := s.conn.Migrator().DropColumn(&WorkflowJob{}, "runner_name"); err != nil {
|
if err := s.conn.Migrator().DropColumn(&WorkflowJob{}, "runner_name"); err != nil {
|
||||||
return errors.Wrap(err, "updating workflow_jobs")
|
return fmt.Errorf("error updating workflow_jobs: %w", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -404,34 +404,34 @@ func (s *sqlDatabase) migrateDB() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := s.cascadeMigration(); err != nil {
|
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 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 {
|
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 {
|
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 {
|
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 err := s.migrateWorkflow(); err != nil {
|
if err := s.migrateWorkflow(); err != nil {
|
||||||
return errors.Wrap(err, "migrating workflows")
|
return fmt.Errorf("error migrating workflows: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if s.conn.Migrator().HasTable(&GithubEndpoint{}) {
|
if s.conn.Migrator().HasTable(&GithubEndpoint{}) {
|
||||||
if !s.conn.Migrator().HasColumn(&GithubEndpoint{}, "endpoint_type") {
|
if !s.conn.Migrator().HasColumn(&GithubEndpoint{}, "endpoint_type") {
|
||||||
if err := s.conn.Migrator().AutoMigrate(&GithubEndpoint{}); err != nil {
|
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 {
|
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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -467,7 +467,7 @@ func (s *sqlDatabase) migrateDB() error {
|
||||||
&WorkflowJob{},
|
&WorkflowJob{},
|
||||||
&ScaleSet{},
|
&ScaleSet{},
|
||||||
); err != nil {
|
); 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")
|
s.conn.Exec("PRAGMA foreign_keys = ON")
|
||||||
|
|
||||||
|
|
@ -475,23 +475,23 @@ func (s *sqlDatabase) migrateDB() error {
|
||||||
var controller ControllerInfo
|
var controller ControllerInfo
|
||||||
if err := s.conn.First(&controller).Error; err != nil {
|
if err := s.conn.First(&controller).Error; err != nil {
|
||||||
if !errors.Is(err, gorm.ErrRecordNotFound) {
|
if !errors.Is(err, gorm.ErrRecordNotFound) {
|
||||||
return errors.Wrap(err, "updating controller info")
|
return fmt.Errorf("error updating controller info: %w", err)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
controller.MinimumJobAgeBackoff = 30
|
controller.MinimumJobAgeBackoff = 30
|
||||||
if err := s.conn.Save(&controller).Error; err != nil {
|
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 {
|
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 needsCredentialMigration {
|
||||||
if err := s.migrateCredentialsToDB(); err != nil {
|
if err := s.migrateCredentialsToDB(); err != nil {
|
||||||
return errors.Wrap(err, "migrating credentials")
|
return fmt.Errorf("error migrating credentials: %w", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|
|
||||||
|
|
@ -16,9 +16,9 @@ package sql
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
|
|
||||||
runnerErrors "github.com/cloudbase/garm-provider-common/errors"
|
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) {
|
if errors.Is(q.Error, gorm.ErrRecordNotFound) {
|
||||||
return User{}, runnerErrors.ErrNotFound
|
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
|
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) {
|
if errors.Is(q.Error, gorm.ErrRecordNotFound) {
|
||||||
return User{}, runnerErrors.ErrNotFound
|
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
|
return dbUser, nil
|
||||||
}
|
}
|
||||||
|
|
@ -82,12 +82,12 @@ func (s *sqlDatabase) CreateUser(_ context.Context, user params.NewUserParams) (
|
||||||
|
|
||||||
q := tx.Save(&newUser)
|
q := tx.Save(&newUser)
|
||||||
if q.Error != nil {
|
if q.Error != nil {
|
||||||
return errors.Wrap(q.Error, "creating user")
|
return fmt.Errorf("error creating user: %w", q.Error)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
if err != 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
|
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) {
|
func (s *sqlDatabase) GetUser(_ context.Context, user string) (params.User, error) {
|
||||||
dbUser, err := s.getUserByUsernameOrEmail(s.conn, user)
|
dbUser, err := s.getUserByUsernameOrEmail(s.conn, user)
|
||||||
if err != nil {
|
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
|
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) {
|
func (s *sqlDatabase) GetUserByID(_ context.Context, userID string) (params.User, error) {
|
||||||
dbUser, err := s.getUserByID(s.conn, userID)
|
dbUser, err := s.getUserByID(s.conn, userID)
|
||||||
if err != nil {
|
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
|
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 {
|
err = s.conn.Transaction(func(tx *gorm.DB) error {
|
||||||
dbUser, err = s.getUserByUsernameOrEmail(tx, user)
|
dbUser, err = s.getUserByUsernameOrEmail(tx, user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "fetching user")
|
return fmt.Errorf("error fetching user: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if param.FullName != "" {
|
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 {
|
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
|
return nil
|
||||||
})
|
})
|
||||||
if err != 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
|
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) {
|
if errors.Is(q.Error, gorm.ErrRecordNotFound) {
|
||||||
return params.User{}, runnerErrors.ErrNotFound
|
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
|
return s.sqlToParamsUser(user), nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -161,7 +161,7 @@ func (s *UserTestSuite) TestCreateUserUsernameAlreadyExist() {
|
||||||
_, err := s.Store.CreateUser(context.Background(), s.Fixtures.NewUserParams)
|
_, err := s.Store.CreateUser(context.Background(), s.Fixtures.NewUserParams)
|
||||||
|
|
||||||
s.Require().NotNil(err)
|
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() {
|
func (s *UserTestSuite) TestCreateUserEmailAlreadyExist() {
|
||||||
|
|
@ -170,7 +170,7 @@ func (s *UserTestSuite) TestCreateUserEmailAlreadyExist() {
|
||||||
_, err := s.Store.CreateUser(context.Background(), s.Fixtures.NewUserParams)
|
_, err := s.Store.CreateUser(context.Background(), s.Fixtures.NewUserParams)
|
||||||
|
|
||||||
s.Require().NotNil(err)
|
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() {
|
func (s *UserTestSuite) TestCreateUserDBCreateErr() {
|
||||||
|
|
@ -191,7 +191,7 @@ func (s *UserTestSuite) TestCreateUserDBCreateErr() {
|
||||||
_, err := s.StoreSQLMocked.CreateUser(context.Background(), s.Fixtures.NewUserParams)
|
_, err := s.StoreSQLMocked.CreateUser(context.Background(), s.Fixtures.NewUserParams)
|
||||||
|
|
||||||
s.Require().NotNil(err)
|
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()
|
s.assertSQLMockExpectations()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -230,7 +230,7 @@ func (s *UserTestSuite) TestGetUserNotFound() {
|
||||||
_, err := s.Store.GetUser(context.Background(), "dummy-user")
|
_, err := s.Store.GetUser(context.Background(), "dummy-user")
|
||||||
|
|
||||||
s.Require().NotNil(err)
|
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() {
|
func (s *UserTestSuite) TestGetUserByID() {
|
||||||
|
|
@ -244,7 +244,7 @@ func (s *UserTestSuite) TestGetUserByIDNotFound() {
|
||||||
_, err := s.Store.GetUserByID(context.Background(), "dummy-user-id")
|
_, err := s.Store.GetUserByID(context.Background(), "dummy-user-id")
|
||||||
|
|
||||||
s.Require().NotNil(err)
|
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() {
|
func (s *UserTestSuite) TestUpdateUser() {
|
||||||
|
|
@ -260,7 +260,7 @@ func (s *UserTestSuite) TestUpdateUserNotFound() {
|
||||||
_, err := s.Store.UpdateUser(context.Background(), "dummy-user", s.Fixtures.UpdateUserParams)
|
_, err := s.Store.UpdateUser(context.Background(), "dummy-user", s.Fixtures.UpdateUserParams)
|
||||||
|
|
||||||
s.Require().NotNil(err)
|
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() {
|
func (s *UserTestSuite) TestUpdateUserDBSaveErr() {
|
||||||
|
|
@ -278,7 +278,7 @@ func (s *UserTestSuite) TestUpdateUserDBSaveErr() {
|
||||||
|
|
||||||
s.assertSQLMockExpectations()
|
s.assertSQLMockExpectations()
|
||||||
s.Require().NotNil(err)
|
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) {
|
func TestUserTestSuite(t *testing.T) {
|
||||||
|
|
|
||||||
|
|
@ -17,10 +17,10 @@ package sql
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
"github.com/pkg/errors"
|
|
||||||
"gorm.io/datatypes"
|
"gorm.io/datatypes"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
|
|
||||||
|
|
@ -41,14 +41,14 @@ func (s *sqlDatabase) sqlToParamsInstance(instance Instance) (params.Instance, e
|
||||||
var labels []string
|
var labels []string
|
||||||
if len(instance.AditionalLabels) > 0 {
|
if len(instance.AditionalLabels) > 0 {
|
||||||
if err := json.Unmarshal(instance.AditionalLabels, &labels); err != nil {
|
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
|
var jitConfig map[string]string
|
||||||
if len(instance.JitConfiguration) > 0 {
|
if len(instance.JitConfiguration) > 0 {
|
||||||
if err := s.unsealAndUnmarshal(instance.JitConfiguration, &jitConfig); err != nil {
|
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{
|
ret := params.Instance{
|
||||||
|
|
@ -95,7 +95,7 @@ func (s *sqlDatabase) sqlToParamsInstance(instance Instance) (params.Instance, e
|
||||||
if instance.Job != nil {
|
if instance.Job != nil {
|
||||||
paramJob, err := sqlWorkflowJobToParamsJob(*instance.Job)
|
paramJob, err := sqlWorkflowJobToParamsJob(*instance.Job)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return params.Instance{}, errors.Wrap(err, "converting job")
|
return params.Instance{}, fmt.Errorf("error converting job: %w", err)
|
||||||
}
|
}
|
||||||
ret.Job = ¶mJob
|
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))
|
secret, err := util.Unseal(org.WebhookSecret, []byte(s.cfg.Passphrase))
|
||||||
if err != nil {
|
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)
|
endpoint, err := s.sqlToCommonGithubEndpoint(org.Endpoint)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return params.Organization{}, errors.Wrap(err, "converting endpoint")
|
return params.Organization{}, fmt.Errorf("error converting endpoint: %w", err)
|
||||||
}
|
}
|
||||||
ret := params.Organization{
|
ret := params.Organization{
|
||||||
ID: org.ID.String(),
|
ID: org.ID.String(),
|
||||||
|
|
@ -163,7 +163,7 @@ func (s *sqlDatabase) sqlToCommonOrganization(org Organization, detailed bool) (
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
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 {
|
if len(org.Events) > 0 {
|
||||||
|
|
@ -191,7 +191,7 @@ func (s *sqlDatabase) sqlToCommonOrganization(org Organization, detailed bool) (
|
||||||
for idx, pool := range org.Pools {
|
for idx, pool := range org.Pools {
|
||||||
ret.Pools[idx], err = s.sqlToCommonPool(pool)
|
ret.Pools[idx], err = s.sqlToCommonPool(pool)
|
||||||
if err != nil {
|
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))
|
secret, err := util.Unseal(enterprise.WebhookSecret, []byte(s.cfg.Passphrase))
|
||||||
if err != nil {
|
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)
|
endpoint, err := s.sqlToCommonGithubEndpoint(enterprise.Endpoint)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return params.Enterprise{}, errors.Wrap(err, "converting endpoint")
|
return params.Enterprise{}, fmt.Errorf("error converting endpoint: %w", err)
|
||||||
}
|
}
|
||||||
ret := params.Enterprise{
|
ret := params.Enterprise{
|
||||||
ID: enterprise.ID.String(),
|
ID: enterprise.ID.String(),
|
||||||
|
|
@ -243,7 +243,7 @@ func (s *sqlDatabase) sqlToCommonEnterprise(enterprise Enterprise, detailed bool
|
||||||
if detailed {
|
if detailed {
|
||||||
creds, err := s.sqlToCommonForgeCredentials(enterprise.Credentials)
|
creds, err := s.sqlToCommonForgeCredentials(enterprise.Credentials)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return params.Enterprise{}, errors.Wrap(err, "converting credentials")
|
return params.Enterprise{}, fmt.Errorf("error converting credentials: %w", err)
|
||||||
}
|
}
|
||||||
ret.Credentials = creds
|
ret.Credentials = creds
|
||||||
}
|
}
|
||||||
|
|
@ -255,7 +255,7 @@ func (s *sqlDatabase) sqlToCommonEnterprise(enterprise Enterprise, detailed bool
|
||||||
for idx, pool := range enterprise.Pools {
|
for idx, pool := range enterprise.Pools {
|
||||||
ret.Pools[idx], err = s.sqlToCommonPool(pool)
|
ret.Pools[idx], err = s.sqlToCommonPool(pool)
|
||||||
if err != nil {
|
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)
|
endpoint, err := s.sqlToCommonGithubEndpoint(ep)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return params.Pool{}, errors.Wrap(err, "converting endpoint")
|
return params.Pool{}, fmt.Errorf("error converting endpoint: %w", err)
|
||||||
}
|
}
|
||||||
ret.Endpoint = endpoint
|
ret.Endpoint = endpoint
|
||||||
|
|
||||||
|
|
@ -320,7 +320,7 @@ func (s *sqlDatabase) sqlToCommonPool(pool Pool) (params.Pool, error) {
|
||||||
for idx, inst := range pool.Instances {
|
for idx, inst := range pool.Instances {
|
||||||
ret.Instances[idx], err = s.sqlToParamsInstance(inst)
|
ret.Instances[idx], err = s.sqlToParamsInstance(inst)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return params.Pool{}, errors.Wrap(err, "converting instance")
|
return params.Pool{}, fmt.Errorf("error converting instance: %w", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -380,14 +380,14 @@ func (s *sqlDatabase) sqlToCommonScaleSet(scaleSet ScaleSet) (params.ScaleSet, e
|
||||||
|
|
||||||
endpoint, err := s.sqlToCommonGithubEndpoint(ep)
|
endpoint, err := s.sqlToCommonGithubEndpoint(ep)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return params.ScaleSet{}, errors.Wrap(err, "converting endpoint")
|
return params.ScaleSet{}, fmt.Errorf("error converting endpoint: %w", err)
|
||||||
}
|
}
|
||||||
ret.Endpoint = endpoint
|
ret.Endpoint = endpoint
|
||||||
|
|
||||||
for idx, inst := range scaleSet.Instances {
|
for idx, inst := range scaleSet.Instances {
|
||||||
ret.Instances[idx], err = s.sqlToParamsInstance(inst)
|
ret.Instances[idx], err = s.sqlToParamsInstance(inst)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return params.ScaleSet{}, errors.Wrap(err, "converting instance")
|
return params.ScaleSet{}, fmt.Errorf("error converting instance: %w", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -407,11 +407,11 @@ func (s *sqlDatabase) sqlToCommonRepository(repo Repository, detailed bool) (par
|
||||||
}
|
}
|
||||||
secret, err := util.Unseal(repo.WebhookSecret, []byte(s.cfg.Passphrase))
|
secret, err := util.Unseal(repo.WebhookSecret, []byte(s.cfg.Passphrase))
|
||||||
if err != nil {
|
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)
|
endpoint, err := s.sqlToCommonGithubEndpoint(repo.Endpoint)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return params.Repository{}, errors.Wrap(err, "converting endpoint")
|
return params.Repository{}, fmt.Errorf("error converting endpoint: %w", err)
|
||||||
}
|
}
|
||||||
ret := params.Repository{
|
ret := params.Repository{
|
||||||
ID: repo.ID.String(),
|
ID: repo.ID.String(),
|
||||||
|
|
@ -442,7 +442,7 @@ func (s *sqlDatabase) sqlToCommonRepository(repo Repository, detailed bool) (par
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
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 {
|
if len(repo.Events) > 0 {
|
||||||
|
|
@ -470,7 +470,7 @@ func (s *sqlDatabase) sqlToCommonRepository(repo Repository, detailed bool) (par
|
||||||
for idx, pool := range repo.Pools {
|
for idx, pool := range repo.Pools {
|
||||||
ret.Pools[idx], err = s.sqlToCommonPool(pool)
|
ret.Pools[idx], err = s.sqlToCommonPool(pool)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return params.Repository{}, errors.Wrap(err, "converting pool")
|
return params.Repository{}, fmt.Errorf("error converting pool: %w", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -499,14 +499,14 @@ func (s *sqlDatabase) getOrCreateTag(tx *gorm.DB, tagName string) (Tag, error) {
|
||||||
return tag, nil
|
return tag, nil
|
||||||
}
|
}
|
||||||
if !errors.Is(q.Error, gorm.ErrRecordNotFound) {
|
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{
|
newTag := Tag{
|
||||||
Name: tagName,
|
Name: tagName,
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := tx.Create(&newTag).Error; err != nil {
|
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
|
return newTag, nil
|
||||||
}
|
}
|
||||||
|
|
@ -561,7 +561,7 @@ func (s *sqlDatabase) updatePool(tx *gorm.DB, pool Pool, param params.UpdatePool
|
||||||
}
|
}
|
||||||
|
|
||||||
if q := tx.Save(&pool); q.Error != nil {
|
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{}
|
tags := []Tag{}
|
||||||
|
|
@ -569,13 +569,13 @@ func (s *sqlDatabase) updatePool(tx *gorm.DB, pool Pool, param params.UpdatePool
|
||||||
for _, val := range param.Tags {
|
for _, val := range param.Tags {
|
||||||
t, err := s.getOrCreateTag(tx, val)
|
t, err := s.getOrCreateTag(tx, val)
|
||||||
if err != nil {
|
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)
|
tags = append(tags, t)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := tx.Model(&pool).Association("Tags").Replace(&tags); err != nil {
|
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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -585,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) {
|
func (s *sqlDatabase) getPoolByID(tx *gorm.DB, poolID string, preload ...string) (Pool, error) {
|
||||||
u, err := uuid.Parse(poolID)
|
u, err := uuid.Parse(poolID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return Pool{}, errors.Wrap(runnerErrors.ErrBadRequest, "parsing id")
|
return Pool{}, fmt.Errorf("error parsing id: %w", runnerErrors.ErrBadRequest)
|
||||||
}
|
}
|
||||||
var pool Pool
|
var pool Pool
|
||||||
q := tx.Model(&Pool{})
|
q := tx.Model(&Pool{})
|
||||||
|
|
@ -601,7 +601,7 @@ func (s *sqlDatabase) getPoolByID(tx *gorm.DB, poolID string, preload ...string)
|
||||||
if errors.Is(q.Error, gorm.ErrRecordNotFound) {
|
if errors.Is(q.Error, gorm.ErrRecordNotFound) {
|
||||||
return Pool{}, runnerErrors.ErrNotFound
|
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
|
return pool, nil
|
||||||
}
|
}
|
||||||
|
|
@ -621,7 +621,7 @@ func (s *sqlDatabase) getScaleSetByID(tx *gorm.DB, scaleSetID uint, preload ...s
|
||||||
if errors.Is(q.Error, gorm.ErrRecordNotFound) {
|
if errors.Is(q.Error, gorm.ErrRecordNotFound) {
|
||||||
return ScaleSet{}, runnerErrors.ErrNotFound
|
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
|
return scaleSet, nil
|
||||||
}
|
}
|
||||||
|
|
@ -629,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 {
|
func (s *sqlDatabase) hasGithubEntity(tx *gorm.DB, entityType params.ForgeEntityType, entityID string) error {
|
||||||
u, err := uuid.Parse(entityID)
|
u, err := uuid.Parse(entityID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(runnerErrors.ErrBadRequest, "parsing id")
|
return fmt.Errorf("error parsing id: %w", runnerErrors.ErrBadRequest)
|
||||||
}
|
}
|
||||||
var q *gorm.DB
|
var q *gorm.DB
|
||||||
switch entityType {
|
switch entityType {
|
||||||
|
|
@ -640,15 +640,15 @@ func (s *sqlDatabase) hasGithubEntity(tx *gorm.DB, entityType params.ForgeEntity
|
||||||
case params.ForgeEntityTypeEnterprise:
|
case params.ForgeEntityTypeEnterprise:
|
||||||
q = tx.Model(&Enterprise{}).Where("id = ?", u)
|
q = tx.Model(&Enterprise{}).Where("id = ?", u)
|
||||||
default:
|
default:
|
||||||
return errors.Wrap(runnerErrors.ErrBadRequest, "invalid entity type")
|
return fmt.Errorf("error invalid entity type: %w", runnerErrors.ErrBadRequest)
|
||||||
}
|
}
|
||||||
|
|
||||||
var entity interface{}
|
var entity interface{}
|
||||||
if err := q.First(entity).Error; err != nil {
|
if err := q.First(entity).Error; err != nil {
|
||||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
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
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -656,7 +656,7 @@ func (s *sqlDatabase) hasGithubEntity(tx *gorm.DB, entityType params.ForgeEntity
|
||||||
func (s *sqlDatabase) marshalAndSeal(data interface{}) ([]byte, error) {
|
func (s *sqlDatabase) marshalAndSeal(data interface{}) ([]byte, error) {
|
||||||
enc, err := json.Marshal(data)
|
enc, err := json.Marshal(data)
|
||||||
if err != nil {
|
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))
|
return util.Seal(enc, []byte(s.cfg.Passphrase))
|
||||||
}
|
}
|
||||||
|
|
@ -664,10 +664,10 @@ func (s *sqlDatabase) marshalAndSeal(data interface{}) ([]byte, error) {
|
||||||
func (s *sqlDatabase) unsealAndUnmarshal(data []byte, target interface{}) error {
|
func (s *sqlDatabase) unsealAndUnmarshal(data []byte, target interface{}) error {
|
||||||
decrypted, err := util.Unseal(data, []byte(s.cfg.Passphrase))
|
decrypted, err := util.Unseal(data, []byte(s.cfg.Passphrase))
|
||||||
if err != nil {
|
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 {
|
if err := json.Unmarshal(decrypted, target); err != nil {
|
||||||
return errors.Wrap(err, "unmarshalling data")
|
return fmt.Errorf("error unmarshalling data: %w", err)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -699,15 +699,15 @@ func (s *sqlDatabase) GetForgeEntity(_ context.Context, entityType params.ForgeE
|
||||||
case params.ForgeEntityTypeRepository:
|
case params.ForgeEntityTypeRepository:
|
||||||
ghEntity, err = s.GetRepositoryByID(s.ctx, entityID)
|
ghEntity, err = s.GetRepositoryByID(s.ctx, entityID)
|
||||||
default:
|
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 {
|
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()
|
entity, err := ghEntity.GetEntity()
|
||||||
if err != nil {
|
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
|
return entity, nil
|
||||||
}
|
}
|
||||||
|
|
@ -715,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 {
|
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)
|
repo, err := s.getRepoByID(ctx, s.conn, repoID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "updating instance")
|
return fmt.Errorf("error updating instance: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
msg := RepositoryEvent{
|
msg := RepositoryEvent{
|
||||||
|
|
@ -725,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 {
|
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 {
|
if maxEvents > 0 {
|
||||||
|
|
@ -734,12 +734,12 @@ func (s *sqlDatabase) addRepositoryEvent(ctx context.Context, repoID string, eve
|
||||||
Limit(maxEvents).Order("id desc").
|
Limit(maxEvents).Order("id desc").
|
||||||
Where("repo_id = ?", repo.ID).Find(&latestEvents)
|
Where("repo_id = ?", repo.ID).Find(&latestEvents)
|
||||||
if q.Error != nil {
|
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 {
|
if len(latestEvents) == maxEvents {
|
||||||
lastInList := latestEvents[len(latestEvents)-1]
|
lastInList := latestEvents[len(latestEvents)-1]
|
||||||
if err := s.conn.Where("repo_id = ? and id < ?", repo.ID, lastInList.ID).Unscoped().Delete(&RepositoryEvent{}).Error; err != nil {
|
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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -749,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 {
|
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)
|
org, err := s.getOrgByID(ctx, s.conn, orgID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "updating instance")
|
return fmt.Errorf("error updating instance: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
msg := OrganizationEvent{
|
msg := OrganizationEvent{
|
||||||
|
|
@ -759,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 {
|
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 {
|
if maxEvents > 0 {
|
||||||
|
|
@ -768,12 +768,12 @@ func (s *sqlDatabase) addOrgEvent(ctx context.Context, orgID string, event param
|
||||||
Limit(maxEvents).Order("id desc").
|
Limit(maxEvents).Order("id desc").
|
||||||
Where("org_id = ?", org.ID).Find(&latestEvents)
|
Where("org_id = ?", org.ID).Find(&latestEvents)
|
||||||
if q.Error != nil {
|
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 {
|
if len(latestEvents) == maxEvents {
|
||||||
lastInList := latestEvents[len(latestEvents)-1]
|
lastInList := latestEvents[len(latestEvents)-1]
|
||||||
if err := s.conn.Where("org_id = ? and id < ?", org.ID, lastInList.ID).Unscoped().Delete(&OrganizationEvent{}).Error; err != nil {
|
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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -783,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 {
|
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)
|
ent, err := s.getEnterpriseByID(ctx, s.conn, entID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "updating instance")
|
return fmt.Errorf("error updating instance: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
msg := EnterpriseEvent{
|
msg := EnterpriseEvent{
|
||||||
|
|
@ -793,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 {
|
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 {
|
if maxEvents > 0 {
|
||||||
|
|
@ -802,12 +802,12 @@ func (s *sqlDatabase) addEnterpriseEvent(ctx context.Context, entID string, even
|
||||||
Limit(maxEvents).Order("id desc").
|
Limit(maxEvents).Order("id desc").
|
||||||
Where("enterprise_id = ?", ent.ID).Find(&latestEvents)
|
Where("enterprise_id = ?", ent.ID).Find(&latestEvents)
|
||||||
if q.Error != nil {
|
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 {
|
if len(latestEvents) == maxEvents {
|
||||||
lastInList := latestEvents[len(latestEvents)-1]
|
lastInList := latestEvents[len(latestEvents)-1]
|
||||||
if err := s.conn.Where("enterprise_id = ? and id < ?", ent.ID, lastInList.ID).Unscoped().Delete(&EnterpriseEvent{}).Error; err != nil {
|
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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -817,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 {
|
func (s *sqlDatabase) AddEntityEvent(ctx context.Context, entity params.ForgeEntity, event params.EventType, eventLevel params.EventLevel, statusMessage string, maxEvents int) error {
|
||||||
if maxEvents == 0 {
|
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 {
|
switch entity.EntityType {
|
||||||
|
|
@ -828,7 +828,7 @@ func (s *sqlDatabase) AddEntityEvent(ctx context.Context, entity params.ForgeEnt
|
||||||
case params.ForgeEntityTypeEnterprise:
|
case params.ForgeEntityTypeEnterprise:
|
||||||
return s.addEnterpriseEvent(ctx, entity.ID, event, eventLevel, statusMessage, maxEvents)
|
return s.addEnterpriseEvent(ctx, entity.ID, event, eventLevel, statusMessage, maxEvents)
|
||||||
default:
|
default:
|
||||||
return errors.Wrap(runnerErrors.ErrBadRequest, "invalid entity type")
|
return fmt.Errorf("invalid entity type: %w", runnerErrors.ErrBadRequest)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -838,12 +838,12 @@ func (s *sqlDatabase) sqlToCommonForgeCredentials(creds GithubCredentials) (para
|
||||||
}
|
}
|
||||||
data, err := util.Unseal(creds.Payload, []byte(s.cfg.Passphrase))
|
data, err := util.Unseal(creds.Payload, []byte(s.cfg.Passphrase))
|
||||||
if err != nil {
|
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)
|
ep, err := s.sqlToCommonGithubEndpoint(creds.Endpoint)
|
||||||
if err != nil {
|
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{
|
commonCreds := params.ForgeCredentials{
|
||||||
|
|
@ -865,7 +865,7 @@ func (s *sqlDatabase) sqlToCommonForgeCredentials(creds GithubCredentials) (para
|
||||||
for _, repo := range creds.Repositories {
|
for _, repo := range creds.Repositories {
|
||||||
commonRepo, err := s.sqlToCommonRepository(repo, false)
|
commonRepo, err := s.sqlToCommonRepository(repo, false)
|
||||||
if err != nil {
|
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)
|
commonCreds.Repositories = append(commonCreds.Repositories, commonRepo)
|
||||||
}
|
}
|
||||||
|
|
@ -873,7 +873,7 @@ func (s *sqlDatabase) sqlToCommonForgeCredentials(creds GithubCredentials) (para
|
||||||
for _, org := range creds.Organizations {
|
for _, org := range creds.Organizations {
|
||||||
commonOrg, err := s.sqlToCommonOrganization(org, false)
|
commonOrg, err := s.sqlToCommonOrganization(org, false)
|
||||||
if err != nil {
|
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)
|
commonCreds.Organizations = append(commonCreds.Organizations, commonOrg)
|
||||||
}
|
}
|
||||||
|
|
@ -881,7 +881,7 @@ func (s *sqlDatabase) sqlToCommonForgeCredentials(creds GithubCredentials) (para
|
||||||
for _, ent := range creds.Enterprises {
|
for _, ent := range creds.Enterprises {
|
||||||
commonEnt, err := s.sqlToCommonEnterprise(ent, false)
|
commonEnt, err := s.sqlToCommonEnterprise(ent, false)
|
||||||
if err != nil {
|
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)
|
commonCreds.Enterprises = append(commonCreds.Enterprises, commonEnt)
|
||||||
}
|
}
|
||||||
|
|
@ -895,12 +895,12 @@ func (s *sqlDatabase) sqlGiteaToCommonForgeCredentials(creds GiteaCredentials) (
|
||||||
}
|
}
|
||||||
data, err := util.Unseal(creds.Payload, []byte(s.cfg.Passphrase))
|
data, err := util.Unseal(creds.Payload, []byte(s.cfg.Passphrase))
|
||||||
if err != nil {
|
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)
|
ep, err := s.sqlToCommonGithubEndpoint(creds.Endpoint)
|
||||||
if err != nil {
|
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{
|
commonCreds := params.ForgeCredentials{
|
||||||
|
|
@ -921,7 +921,7 @@ func (s *sqlDatabase) sqlGiteaToCommonForgeCredentials(creds GiteaCredentials) (
|
||||||
for _, repo := range creds.Repositories {
|
for _, repo := range creds.Repositories {
|
||||||
commonRepo, err := s.sqlToCommonRepository(repo, false)
|
commonRepo, err := s.sqlToCommonRepository(repo, false)
|
||||||
if err != nil {
|
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)
|
commonCreds.Repositories = append(commonCreds.Repositories, commonRepo)
|
||||||
}
|
}
|
||||||
|
|
@ -929,7 +929,7 @@ func (s *sqlDatabase) sqlGiteaToCommonForgeCredentials(creds GiteaCredentials) (
|
||||||
for _, org := range creds.Organizations {
|
for _, org := range creds.Organizations {
|
||||||
commonOrg, err := s.sqlToCommonOrganization(org, false)
|
commonOrg, err := s.sqlToCommonOrganization(org, false)
|
||||||
if err != nil {
|
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)
|
commonCreds.Organizations = append(commonCreds.Organizations, commonOrg)
|
||||||
}
|
}
|
||||||
|
|
@ -954,12 +954,12 @@ func (s *sqlDatabase) sqlToCommonGithubEndpoint(ep GithubEndpoint) (params.Forge
|
||||||
func getUIDFromContext(ctx context.Context) (uuid.UUID, error) {
|
func getUIDFromContext(ctx context.Context) (uuid.UUID, error) {
|
||||||
userID := auth.UserID(ctx)
|
userID := auth.UserID(ctx)
|
||||||
if userID == "" {
|
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)
|
asUUID, err := uuid.Parse(userID)
|
||||||
if err != nil {
|
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
|
return asUUID, nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,11 +16,10 @@ package watcher
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
|
|
||||||
"github.com/cloudbase/garm/database/common"
|
"github.com/cloudbase/garm/database/common"
|
||||||
garmUtil "github.com/cloudbase/garm/util"
|
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()
|
defer w.mux.Unlock()
|
||||||
|
|
||||||
if _, ok := w.producers[id]; ok {
|
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{
|
p := &producer{
|
||||||
id: id,
|
id: id,
|
||||||
|
|
|
||||||
|
|
@ -17,11 +17,11 @@ package watcher_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
"github.com/pkg/errors"
|
|
||||||
"github.com/stretchr/testify/suite"
|
"github.com/stretchr/testify/suite"
|
||||||
|
|
||||||
commonParams "github.com/cloudbase/garm-provider-common/params"
|
commonParams "github.com/cloudbase/garm-provider-common/params"
|
||||||
|
|
@ -310,7 +310,7 @@ func maybeInitController(db common.Store) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := db.InitController(); err != nil {
|
if _, err := db.InitController(); err != nil {
|
||||||
return errors.Wrap(err, "initializing controller")
|
return fmt.Errorf("error initializing controller: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
|
||||||
7
go.mod
7
go.mod
|
|
@ -20,11 +20,8 @@ require (
|
||||||
github.com/gorilla/mux v1.8.1
|
github.com/gorilla/mux v1.8.1
|
||||||
github.com/gorilla/websocket v1.5.4-0.20240702125206-a62d9d2a8413
|
github.com/gorilla/websocket v1.5.4-0.20240702125206-a62d9d2a8413
|
||||||
github.com/jedib0t/go-pretty/v6 v6.6.8
|
github.com/jedib0t/go-pretty/v6 v6.6.8
|
||||||
github.com/juju/clock v1.1.1
|
|
||||||
github.com/juju/retry v1.0.1
|
|
||||||
github.com/manifoldco/promptui v0.9.0
|
github.com/manifoldco/promptui v0.9.0
|
||||||
github.com/nbutton23/zxcvbn-go v0.0.0-20210217022336-fa2cb2858354
|
github.com/nbutton23/zxcvbn-go v0.0.0-20210217022336-fa2cb2858354
|
||||||
github.com/pkg/errors v0.9.1
|
|
||||||
github.com/prometheus/client_golang v1.23.0
|
github.com/prometheus/client_golang v1.23.0
|
||||||
github.com/spf13/cobra v1.9.1
|
github.com/spf13/cobra v1.9.1
|
||||||
github.com/stretchr/testify v1.10.0
|
github.com/stretchr/testify v1.10.0
|
||||||
|
|
@ -62,9 +59,6 @@ require (
|
||||||
github.com/jinzhu/inflection v1.0.0 // indirect
|
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||||
github.com/jinzhu/now v1.1.5 // indirect
|
github.com/jinzhu/now v1.1.5 // indirect
|
||||||
github.com/josharian/intern v1.0.0 // 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/mailru/easyjson v0.9.0 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||||
github.com/mattn/go-runewidth v0.0.16 // indirect
|
github.com/mattn/go-runewidth v0.0.16 // indirect
|
||||||
|
|
@ -74,6 +68,7 @@ require (
|
||||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||||
github.com/oklog/ulid v1.3.1 // indirect
|
github.com/oklog/ulid v1.3.1 // indirect
|
||||||
github.com/opentracing/opentracing-go v1.2.0 // 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/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||||
github.com/prometheus/client_model v0.6.2 // indirect
|
github.com/prometheus/client_model v0.6.2 // indirect
|
||||||
github.com/prometheus/common v0.65.0 // indirect
|
github.com/prometheus/common v0.65.0 // indirect
|
||||||
|
|
|
||||||
19
go.sum
19
go.sum
|
|
@ -95,19 +95,6 @@ github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
|
||||||
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
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 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
|
||||||
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
|
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 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
|
||||||
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
|
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
|
||||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||||
|
|
@ -116,13 +103,10 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
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 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
|
||||||
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
|
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 h1:PrnmzHw7262yW8sTBwxi1PdJA3Iw/EKBa8psRf7d9a4=
|
||||||
github.com/mailru/easyjson v0.9.0/go.mod h1:1+xMtQp2MRNVL/V1bOzuP3aP8VNwRW55fQUto+XFtTU=
|
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 h1:3V4HzJk1TtXW1MTZMP7mdlwbBpIinw3HztaIlYthEiA=
|
||||||
github.com/manifoldco/promptui v0.9.0/go.mod h1:ka04sppxSGFAtxX0qhlYQjISsg9mR4GWtQEhdbn6Pgg=
|
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 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
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 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
|
||||||
|
|
@ -213,13 +197,10 @@ google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/
|
||||||
gopkg.in/DATA-DOG/go-sqlmock.v1 v1.3.0 h1:FVCohIoYO7IJoDDVpV2pdq7SgrMH6wHnuTyrdrxJNoY=
|
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/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 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 h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
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 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc=
|
||||||
gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc=
|
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 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gorm.io/datatypes v1.2.6 h1:KafLdXvFUhzNeL2ncm03Gl3eTLONQfNKZ+wJ+9Y4Nck=
|
gorm.io/datatypes v1.2.6 h1:KafLdXvFUhzNeL2ncm03Gl3eTLONQfNKZ+wJ+9Y4Nck=
|
||||||
|
|
|
||||||
|
|
@ -19,13 +19,13 @@ package testing
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"sort"
|
"sort"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
runnerErrors "github.com/cloudbase/garm-provider-common/errors"
|
runnerErrors "github.com/cloudbase/garm-provider-common/errors"
|
||||||
|
|
|
||||||
|
|
@ -21,8 +21,6 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
|
|
||||||
runnerErrors "github.com/cloudbase/garm-provider-common/errors"
|
runnerErrors "github.com/cloudbase/garm-provider-common/errors"
|
||||||
commonParams "github.com/cloudbase/garm-provider-common/params"
|
commonParams "github.com/cloudbase/garm-provider-common/params"
|
||||||
)
|
)
|
||||||
|
|
@ -497,7 +495,7 @@ func (c CreateGithubCredentialsParams) Validate() error {
|
||||||
|
|
||||||
if c.AuthType == ForgeAuthTypeApp {
|
if c.AuthType == ForgeAuthTypeApp {
|
||||||
if err := c.App.Validate(); err != nil {
|
if err := c.App.Validate(); err != nil {
|
||||||
return errors.Wrap(err, "invalid app")
|
return fmt.Errorf("invalid app: %w", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -525,7 +523,7 @@ func (u UpdateGithubCredentialsParams) Validate() error {
|
||||||
|
|
||||||
if u.App != nil {
|
if u.App != nil {
|
||||||
if err := u.App.Validate(); err != nil {
|
if err := u.App.Validate(); err != nil {
|
||||||
return errors.Wrap(err, "invalid app")
|
return fmt.Errorf("invalid app: %w", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,8 @@ package runner
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
"github.com/pkg/errors"
|
"fmt"
|
||||||
|
|
||||||
runnerErrors "github.com/cloudbase/garm-provider-common/errors"
|
runnerErrors "github.com/cloudbase/garm-provider-common/errors"
|
||||||
"github.com/cloudbase/garm/params"
|
"github.com/cloudbase/garm/params"
|
||||||
|
|
@ -12,11 +12,11 @@ import (
|
||||||
func (r *Runner) ResolveForgeCredentialByName(ctx context.Context, credentialsName string) (params.ForgeCredentials, error) {
|
func (r *Runner) ResolveForgeCredentialByName(ctx context.Context, credentialsName string) (params.ForgeCredentials, error) {
|
||||||
githubCred, err := r.store.GetGithubCredentialsByName(ctx, credentialsName, false)
|
githubCred, err := r.store.GetGithubCredentialsByName(ctx, credentialsName, false)
|
||||||
if err != nil && !errors.Is(err, runnerErrors.ErrNotFound) {
|
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)
|
giteaCred, err := r.store.GetGiteaCredentialsByName(ctx, credentialsName, false)
|
||||||
if err != nil && !errors.Is(err, runnerErrors.ErrNotFound) {
|
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 {
|
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)
|
return params.ForgeCredentials{}, runnerErrors.NewBadRequestError("credentials %s are defined for both GitHub and Gitea, please specify the forge type", credentialsName)
|
||||||
|
|
|
||||||
|
|
@ -16,12 +16,11 @@ package runner
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
|
|
||||||
runnerErrors "github.com/cloudbase/garm-provider-common/errors"
|
runnerErrors "github.com/cloudbase/garm-provider-common/errors"
|
||||||
"github.com/cloudbase/garm/auth"
|
"github.com/cloudbase/garm/auth"
|
||||||
"github.com/cloudbase/garm/params"
|
"github.com/cloudbase/garm/params"
|
||||||
|
|
@ -36,7 +35,7 @@ func (r *Runner) CreateEnterprise(ctx context.Context, param params.CreateEnterp
|
||||||
|
|
||||||
err = param.Validate()
|
err = param.Validate()
|
||||||
if err != nil {
|
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)
|
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)
|
_, err = r.store.GetEnterprise(ctx, param.Name, creds.Endpoint.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if !errors.Is(err, runnerErrors.ErrNotFound) {
|
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 {
|
} else {
|
||||||
return params.Enterprise{}, runnerErrors.NewConflictError("enterprise %s already exists", param.Name)
|
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)
|
enterprise, err = r.store.CreateEnterprise(ctx, param.Name, creds, param.WebhookSecret, param.PoolBalancerType)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return params.Enterprise{}, errors.Wrap(err, "creating enterprise")
|
return params.Enterprise{}, fmt.Errorf("error creating enterprise: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
|
|
@ -73,7 +72,7 @@ func (r *Runner) CreateEnterprise(ctx context.Context, param params.CreateEnterp
|
||||||
var poolMgr common.PoolManager
|
var poolMgr common.PoolManager
|
||||||
poolMgr, err = r.poolManagerCtrl.CreateEnterprisePoolManager(r.ctx, enterprise, r.providers, r.store)
|
poolMgr, err = r.poolManagerCtrl.CreateEnterprisePoolManager(r.ctx, enterprise, r.providers, r.store)
|
||||||
if err != nil {
|
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 err := poolMgr.Start(); err != nil {
|
||||||
if deleteErr := r.poolManagerCtrl.DeleteEnterprisePoolManager(enterprise); deleteErr != 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",
|
ctx, "failed to cleanup pool manager for enterprise",
|
||||||
"enterprise_id", enterprise.ID)
|
"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
|
return enterprise, nil
|
||||||
}
|
}
|
||||||
|
|
@ -93,7 +92,7 @@ func (r *Runner) ListEnterprises(ctx context.Context, filter params.EnterpriseFi
|
||||||
|
|
||||||
enterprises, err := r.store.ListEnterprises(ctx, filter)
|
enterprises, err := r.store.ListEnterprises(ctx, filter)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "listing enterprises")
|
return nil, fmt.Errorf("error listing enterprises: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var allEnterprises []params.Enterprise
|
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)
|
enterprise, err := r.store.GetEnterpriseByID(ctx, enterpriseID)
|
||||||
if err != nil {
|
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)
|
poolMgr, err := r.poolManagerCtrl.GetEnterprisePoolManager(enterprise)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -137,17 +136,17 @@ func (r *Runner) DeleteEnterprise(ctx context.Context, enterpriseID string) erro
|
||||||
|
|
||||||
enterprise, err := r.store.GetEnterpriseByID(ctx, enterpriseID)
|
enterprise, err := r.store.GetEnterpriseByID(ctx, enterpriseID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "fetching enterprise")
|
return fmt.Errorf("error fetching enterprise: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
entity, err := enterprise.GetEntity()
|
entity, err := enterprise.GetEntity()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "getting entity")
|
return fmt.Errorf("error getting entity: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
pools, err := r.store.ListEntityPools(ctx, entity)
|
pools, err := r.store.ListEntityPools(ctx, entity)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "fetching enterprise pools")
|
return fmt.Errorf("error fetching enterprise pools: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(pools) > 0 {
|
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)
|
scaleSets, err := r.store.ListEntityScaleSets(ctx, entity)
|
||||||
if err != nil {
|
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 {
|
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 {
|
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 {
|
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
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -194,7 +193,7 @@ func (r *Runner) UpdateEnterprise(ctx context.Context, enterpriseID string, para
|
||||||
|
|
||||||
enterprise, err := r.store.UpdateEnterprise(ctx, enterpriseID, param)
|
enterprise, err := r.store.UpdateEnterprise(ctx, enterpriseID, param)
|
||||||
if err != nil {
|
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)
|
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)
|
pool, err := r.store.GetEntityPool(ctx, entity, poolID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return params.Pool{}, errors.Wrap(err, "fetching pool")
|
return params.Pool{}, fmt.Errorf("error fetching pool: %w", err)
|
||||||
}
|
}
|
||||||
return pool, nil
|
return pool, nil
|
||||||
}
|
}
|
||||||
|
|
@ -260,7 +259,7 @@ func (r *Runner) DeleteEnterprisePool(ctx context.Context, enterpriseID, poolID
|
||||||
|
|
||||||
pool, err := r.store.GetEntityPool(ctx, entity, poolID)
|
pool, err := r.store.GetEntityPool(ctx, entity, poolID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "fetching pool")
|
return fmt.Errorf("error fetching pool: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// nolint:golangci-lint,godox
|
// 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 {
|
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
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -290,7 +289,7 @@ func (r *Runner) ListEnterprisePools(ctx context.Context, enterpriseID string) (
|
||||||
}
|
}
|
||||||
pools, err := r.store.ListEntityPools(ctx, entity)
|
pools, err := r.store.ListEntityPools(ctx, entity)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "fetching pools")
|
return nil, fmt.Errorf("error fetching pools: %w", err)
|
||||||
}
|
}
|
||||||
return pools, nil
|
return pools, nil
|
||||||
}
|
}
|
||||||
|
|
@ -306,7 +305,7 @@ func (r *Runner) UpdateEnterprisePool(ctx context.Context, enterpriseID, poolID
|
||||||
}
|
}
|
||||||
pool, err := r.store.GetEntityPool(ctx, entity, poolID)
|
pool, err := r.store.GetEntityPool(ctx, entity, poolID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return params.Pool{}, errors.Wrap(err, "fetching pool")
|
return params.Pool{}, fmt.Errorf("error fetching pool: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
maxRunners := pool.MaxRunners
|
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)
|
newPool, err := r.store.UpdateEntityPool(ctx, entity, poolID, param)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return params.Pool{}, errors.Wrap(err, "updating pool")
|
return params.Pool{}, fmt.Errorf("error updating pool: %w", err)
|
||||||
}
|
}
|
||||||
return newPool, nil
|
return newPool, nil
|
||||||
}
|
}
|
||||||
|
|
@ -340,7 +339,7 @@ func (r *Runner) ListEnterpriseInstances(ctx context.Context, enterpriseID strin
|
||||||
}
|
}
|
||||||
instances, err := r.store.ListEntityInstances(ctx, entity)
|
instances, err := r.store.ListEntityInstances(ctx, entity)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return []params.Instance{}, errors.Wrap(err, "fetching instances")
|
return []params.Instance{}, fmt.Errorf("error fetching instances: %w", err)
|
||||||
}
|
}
|
||||||
return instances, nil
|
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)
|
enterprise, err := r.store.GetEnterprise(r.ctx, name, endpointName)
|
||||||
if err != nil {
|
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)
|
poolManager, err := r.poolManagerCtrl.GetEnterprisePoolManager(enterprise)
|
||||||
if err != nil {
|
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
|
return poolManager, nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,10 +16,10 @@ package runner
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
"github.com/stretchr/testify/mock"
|
"github.com/stretchr/testify/mock"
|
||||||
"github.com/stretchr/testify/suite"
|
"github.com/stretchr/testify/suite"
|
||||||
|
|
||||||
|
|
@ -210,7 +210,7 @@ func (s *EnterpriseTestSuite) TestCreateEnterprisePoolMgrFailed() {
|
||||||
|
|
||||||
s.Fixtures.PoolMgrMock.AssertExpectations(s.T())
|
s.Fixtures.PoolMgrMock.AssertExpectations(s.T())
|
||||||
s.Fixtures.PoolMgrCtrlMock.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() {
|
func (s *EnterpriseTestSuite) TestCreateEnterpriseStartPoolMgrFailed() {
|
||||||
|
|
@ -222,7 +222,7 @@ func (s *EnterpriseTestSuite) TestCreateEnterpriseStartPoolMgrFailed() {
|
||||||
|
|
||||||
s.Fixtures.PoolMgrMock.AssertExpectations(s.T())
|
s.Fixtures.PoolMgrMock.AssertExpectations(s.T())
|
||||||
s.Fixtures.PoolMgrCtrlMock.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() {
|
func (s *EnterpriseTestSuite) TestListEnterprises() {
|
||||||
|
|
@ -324,7 +324,7 @@ func (s *EnterpriseTestSuite) TestDeleteEnterprise() {
|
||||||
s.Require().Nil(err)
|
s.Require().Nil(err)
|
||||||
|
|
||||||
_, err = s.Fixtures.Store.GetEnterpriseByID(s.Fixtures.AdminContext, s.Fixtures.StoreEnterprises["test-enterprise-3"].ID)
|
_, 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() {
|
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)
|
err := s.Runner.DeleteEnterprise(s.Fixtures.AdminContext, s.Fixtures.StoreEnterprises["test-enterprise-1"].ID)
|
||||||
|
|
||||||
s.Fixtures.PoolMgrCtrlMock.AssertExpectations(s.T())
|
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() {
|
func (s *EnterpriseTestSuite) TestUpdateEnterprise() {
|
||||||
|
|
@ -477,7 +477,7 @@ func (s *EnterpriseTestSuite) TestDeleteEnterprisePool() {
|
||||||
s.Require().Nil(err)
|
s.Require().Nil(err)
|
||||||
|
|
||||||
_, err = s.Fixtures.Store.GetEntityPool(s.Fixtures.AdminContext, entity, pool.ID)
|
_, 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() {
|
func (s *EnterpriseTestSuite) TestDeleteEnterprisePoolErrUnauthorized() {
|
||||||
|
|
|
||||||
|
|
@ -16,8 +16,7 @@ package runner
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
"github.com/pkg/errors"
|
|
||||||
|
|
||||||
runnerErrors "github.com/cloudbase/garm-provider-common/errors"
|
runnerErrors "github.com/cloudbase/garm-provider-common/errors"
|
||||||
"github.com/cloudbase/garm/auth"
|
"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.
|
// there is a posibillity that not all creds will be in the cache.
|
||||||
creds, err := r.store.ListGiteaCredentials(ctx)
|
creds, err := r.store.ListGiteaCredentials(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "fetching gitea credentials")
|
return nil, fmt.Errorf("error fetching gitea credentials: %w", err)
|
||||||
}
|
}
|
||||||
return creds, nil
|
return creds, nil
|
||||||
}
|
}
|
||||||
|
|
@ -46,12 +45,12 @@ func (r *Runner) CreateGiteaCredentials(ctx context.Context, param params.Create
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := param.Validate(); err != nil {
|
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)
|
creds, err := r.store.CreateGiteaCredentials(ctx, param)
|
||||||
if err != nil {
|
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
|
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)
|
creds, err := r.store.GetGiteaCredentials(ctx, id, true)
|
||||||
if err != nil {
|
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
|
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 {
|
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
|
return nil
|
||||||
|
|
@ -88,12 +87,12 @@ func (r *Runner) UpdateGiteaCredentials(ctx context.Context, id uint, param para
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := param.Validate(); err != nil {
|
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)
|
newCreds, err := r.store.UpdateGiteaCredentials(ctx, id, param)
|
||||||
if err != nil {
|
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
|
return newCreds, nil
|
||||||
|
|
|
||||||
|
|
@ -16,8 +16,7 @@ package runner
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
"github.com/pkg/errors"
|
|
||||||
|
|
||||||
runnerErrors "github.com/cloudbase/garm-provider-common/errors"
|
runnerErrors "github.com/cloudbase/garm-provider-common/errors"
|
||||||
"github.com/cloudbase/garm/auth"
|
"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 {
|
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)
|
ep, err := r.store.CreateGiteaEndpoint(ctx, param)
|
||||||
if err != nil {
|
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
|
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)
|
endpoint, err := r.store.GetGiteaEndpoint(ctx, name)
|
||||||
if err != nil {
|
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
|
return endpoint, nil
|
||||||
|
|
@ -60,7 +59,7 @@ func (r *Runner) DeleteGiteaEndpoint(ctx context.Context, name string) error {
|
||||||
|
|
||||||
err := r.store.DeleteGiteaEndpoint(ctx, name)
|
err := r.store.DeleteGiteaEndpoint(ctx, name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "failed to delete gitea endpoint")
|
return fmt.Errorf("failed to delete gitea endpoint: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
@ -72,12 +71,12 @@ func (r *Runner) UpdateGiteaEndpoint(ctx context.Context, name string, param par
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := param.Validate(); err != nil {
|
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)
|
newEp, err := r.store.UpdateGiteaEndpoint(ctx, name, param)
|
||||||
if err != nil {
|
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
|
return newEp, nil
|
||||||
}
|
}
|
||||||
|
|
@ -89,7 +88,7 @@ func (r *Runner) ListGiteaEndpoints(ctx context.Context) ([]params.ForgeEndpoint
|
||||||
|
|
||||||
endpoints, err := r.store.ListGiteaEndpoints(ctx)
|
endpoints, err := r.store.ListGiteaEndpoints(ctx)
|
||||||
if err != nil {
|
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
|
return endpoints, nil
|
||||||
|
|
|
||||||
|
|
@ -16,8 +16,7 @@ package runner
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
"github.com/pkg/errors"
|
|
||||||
|
|
||||||
runnerErrors "github.com/cloudbase/garm-provider-common/errors"
|
runnerErrors "github.com/cloudbase/garm-provider-common/errors"
|
||||||
"github.com/cloudbase/garm/auth"
|
"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.
|
// there is a posibillity that not all creds will be in the cache.
|
||||||
creds, err := r.store.ListGithubCredentials(ctx)
|
creds, err := r.store.ListGithubCredentials(ctx)
|
||||||
if err != nil {
|
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
|
// 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 {
|
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)
|
creds, err := r.store.CreateGithubCredentials(ctx, param)
|
||||||
if err != nil {
|
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
|
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)
|
creds, err := r.store.GetGithubCredentials(ctx, id, true)
|
||||||
if err != nil {
|
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))
|
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 {
|
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
|
return nil
|
||||||
|
|
@ -104,12 +103,12 @@ func (r *Runner) UpdateGithubCredentials(ctx context.Context, id uint, param par
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := param.Validate(); err != nil {
|
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)
|
newCreds, err := r.store.UpdateGithubCredentials(ctx, id, param)
|
||||||
if err != nil {
|
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
|
return newCreds, nil
|
||||||
|
|
|
||||||
|
|
@ -16,8 +16,7 @@ package runner
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
"github.com/pkg/errors"
|
|
||||||
|
|
||||||
runnerErrors "github.com/cloudbase/garm-provider-common/errors"
|
runnerErrors "github.com/cloudbase/garm-provider-common/errors"
|
||||||
"github.com/cloudbase/garm/auth"
|
"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 {
|
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)
|
ep, err := r.store.CreateGithubEndpoint(ctx, param)
|
||||||
if err != nil {
|
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
|
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)
|
endpoint, err := r.store.GetGithubEndpoint(ctx, name)
|
||||||
if err != nil {
|
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
|
return endpoint, nil
|
||||||
|
|
@ -60,7 +59,7 @@ func (r *Runner) DeleteGithubEndpoint(ctx context.Context, name string) error {
|
||||||
|
|
||||||
err := r.store.DeleteGithubEndpoint(ctx, name)
|
err := r.store.DeleteGithubEndpoint(ctx, name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "failed to delete github endpoint")
|
return fmt.Errorf("failed to delete github endpoint: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
@ -72,12 +71,12 @@ func (r *Runner) UpdateGithubEndpoint(ctx context.Context, name string, param pa
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := param.Validate(); err != nil {
|
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)
|
newEp, err := r.store.UpdateGithubEndpoint(ctx, name, param)
|
||||||
if err != nil {
|
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
|
return newEp, nil
|
||||||
}
|
}
|
||||||
|
|
@ -89,7 +88,7 @@ func (r *Runner) ListGithubEndpoints(ctx context.Context) ([]params.ForgeEndpoin
|
||||||
|
|
||||||
endpoints, err := r.store.ListGithubEndpoints(ctx)
|
endpoints, err := r.store.ListGithubEndpoints(ctx)
|
||||||
if err != nil {
|
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
|
return endpoints, nil
|
||||||
|
|
|
||||||
|
|
@ -18,12 +18,11 @@ import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"html/template"
|
"html/template"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
|
|
||||||
"github.com/cloudbase/garm-provider-common/defaults"
|
"github.com/cloudbase/garm-provider-common/defaults"
|
||||||
runnerErrors "github.com/cloudbase/garm-provider-common/errors"
|
runnerErrors "github.com/cloudbase/garm-provider-common/errors"
|
||||||
"github.com/cloudbase/garm/auth"
|
"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(
|
slog.With(slog.Any("error", err)).ErrorContext(
|
||||||
ctx, "failed to get entity getter",
|
ctx, "failed to get entity getter",
|
||||||
"instance", instance.Name)
|
"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()
|
poolEntity, err := entityGetter.GetEntity()
|
||||||
|
|
@ -100,7 +99,7 @@ func (r *Runner) getForgeEntityFromInstance(ctx context.Context, instance params
|
||||||
slog.With(slog.Any("error", err)).ErrorContext(
|
slog.With(slog.Any("error", err)).ErrorContext(
|
||||||
ctx, "failed to get entity",
|
ctx, "failed to get entity",
|
||||||
"instance", instance.Name)
|
"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)
|
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(
|
slog.With(slog.Any("error", err)).ErrorContext(
|
||||||
ctx, "failed to get entity",
|
ctx, "failed to get entity",
|
||||||
"instance", instance.Name)
|
"instance", instance.Name)
|
||||||
return params.ForgeEntity{}, errors.Wrap(err, "fetching entity")
|
return params.ForgeEntity{}, fmt.Errorf("error fetching entity: %w", err)
|
||||||
}
|
}
|
||||||
return entity, nil
|
return entity, nil
|
||||||
}
|
}
|
||||||
|
|
@ -136,13 +135,13 @@ func (r *Runner) GetRunnerServiceName(ctx context.Context) (string, error) {
|
||||||
entity, err := r.getForgeEntityFromInstance(ctx, instance)
|
entity, err := r.getForgeEntityFromInstance(ctx, instance)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
slog.ErrorContext(r.ctx, "failed to get entity", "error", err)
|
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)
|
serviceName, err := r.getServiceNameForEntity(entity)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
slog.ErrorContext(r.ctx, "failed to get service name", "error", err)
|
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
|
return serviceName, nil
|
||||||
}
|
}
|
||||||
|
|
@ -157,13 +156,13 @@ func (r *Runner) GenerateSystemdUnitFile(ctx context.Context, runAsUser string)
|
||||||
entity, err := r.getForgeEntityFromInstance(ctx, instance)
|
entity, err := r.getForgeEntityFromInstance(ctx, instance)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
slog.ErrorContext(r.ctx, "failed to get entity", "error", err)
|
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)
|
serviceName, err := r.getServiceNameForEntity(entity)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
slog.ErrorContext(r.ctx, "failed to get service name", "error", err)
|
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
|
var unitTemplate *template.Template
|
||||||
|
|
@ -178,7 +177,7 @@ func (r *Runner) GenerateSystemdUnitFile(ctx context.Context, runAsUser string)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
slog.ErrorContext(r.ctx, "failed to parse template", "error", err)
|
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 == "" {
|
if runAsUser == "" {
|
||||||
|
|
@ -196,14 +195,14 @@ func (r *Runner) GenerateSystemdUnitFile(ctx context.Context, runAsUser string)
|
||||||
var unitFile bytes.Buffer
|
var unitFile bytes.Buffer
|
||||||
if err := unitTemplate.Execute(&unitFile, data); err != nil {
|
if err := unitTemplate.Execute(&unitFile, data); err != nil {
|
||||||
slog.ErrorContext(r.ctx, "failed to execute template", "error", err)
|
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
|
return unitFile.Bytes(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Runner) GetJITConfigFile(ctx context.Context, file string) ([]byte, error) {
|
func (r *Runner) GetJITConfigFile(ctx context.Context, file string) ([]byte, error) {
|
||||||
if !auth.InstanceHasJITConfig(ctx) {
|
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)
|
instance, err := validateInstanceState(ctx)
|
||||||
|
|
@ -215,12 +214,12 @@ func (r *Runner) GetJITConfigFile(ctx context.Context, file string) ([]byte, err
|
||||||
jitConfig := instance.JitConfiguration
|
jitConfig := instance.JitConfiguration
|
||||||
contents, ok := jitConfig[file]
|
contents, ok := jitConfig[file]
|
||||||
if !ok {
|
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)
|
decoded, err := base64.StdEncoding.DecodeString(contents)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "decoding file contents")
|
return nil, fmt.Errorf("error decoding file contents: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return decoded, nil
|
return decoded, nil
|
||||||
|
|
@ -249,12 +248,12 @@ func (r *Runner) GetInstanceGithubRegistrationToken(ctx context.Context) (string
|
||||||
|
|
||||||
poolMgr, err := r.getPoolManagerFromInstance(ctx, instance)
|
poolMgr, err := r.getPoolManagerFromInstance(ctx, instance)
|
||||||
if err != nil {
|
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()
|
token, err := poolMgr.GithubRunnerRegistrationToken()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", errors.Wrap(err, "fetching runner token")
|
return "", fmt.Errorf("error fetching runner token: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
tokenFetched := true
|
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 {
|
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 {
|
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
|
return token, nil
|
||||||
|
|
@ -283,7 +282,7 @@ func (r *Runner) GetRootCertificateBundle(ctx context.Context) (params.Certifica
|
||||||
|
|
||||||
poolMgr, err := r.getPoolManagerFromInstance(ctx, instance)
|
poolMgr, err := r.getPoolManagerFromInstance(ctx, instance)
|
||||||
if err != nil {
|
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()
|
bundle, err := poolMgr.RootCABundle()
|
||||||
|
|
|
||||||
|
|
@ -16,12 +16,11 @@ package runner
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
|
|
||||||
runnerErrors "github.com/cloudbase/garm-provider-common/errors"
|
runnerErrors "github.com/cloudbase/garm-provider-common/errors"
|
||||||
"github.com/cloudbase/garm/auth"
|
"github.com/cloudbase/garm/auth"
|
||||||
"github.com/cloudbase/garm/params"
|
"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 {
|
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
|
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)
|
_, err = r.store.GetOrganization(ctx, param.Name, creds.Endpoint.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if !errors.Is(err, runnerErrors.ErrNotFound) {
|
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 {
|
} else {
|
||||||
return params.Organization{}, runnerErrors.NewConflictError("organization %s already exists", param.Name)
|
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)
|
org, err = r.store.CreateOrganization(ctx, param.Name, creds, param.WebhookSecret, param.PoolBalancerType)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return params.Organization{}, errors.Wrap(err, "creating organization")
|
return params.Organization{}, fmt.Errorf("error creating organization: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
|
|
@ -82,7 +81,7 @@ func (r *Runner) CreateOrganization(ctx context.Context, param params.CreateOrgP
|
||||||
// updating the store.
|
// updating the store.
|
||||||
poolMgr, err := r.poolManagerCtrl.CreateOrgPoolManager(r.ctx, org, r.providers, r.store)
|
poolMgr, err := r.poolManagerCtrl.CreateOrgPoolManager(r.ctx, org, r.providers, r.store)
|
||||||
if err != nil {
|
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 err := poolMgr.Start(); err != nil {
|
||||||
if deleteErr := r.poolManagerCtrl.DeleteOrgPoolManager(org); deleteErr != 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",
|
ctx, "failed to cleanup pool manager for org",
|
||||||
"org_id", org.ID)
|
"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
|
return org, nil
|
||||||
}
|
}
|
||||||
|
|
@ -102,7 +101,7 @@ func (r *Runner) ListOrganizations(ctx context.Context, filter params.Organizati
|
||||||
|
|
||||||
orgs, err := r.store.ListOrganizations(ctx, filter)
|
orgs, err := r.store.ListOrganizations(ctx, filter)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "listing organizations")
|
return nil, fmt.Errorf("error listing organizations: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var allOrgs []params.Organization
|
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)
|
org, err := r.store.GetOrganizationByID(ctx, orgID)
|
||||||
if err != nil {
|
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)
|
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)
|
org, err := r.store.GetOrganizationByID(ctx, orgID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "fetching org")
|
return fmt.Errorf("error fetching org: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
entity, err := org.GetEntity()
|
entity, err := org.GetEntity()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "getting entity")
|
return fmt.Errorf("error getting entity: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
pools, err := r.store.ListEntityPools(ctx, entity)
|
pools, err := r.store.ListEntityPools(ctx, entity)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "fetching org pools")
|
return fmt.Errorf("error fetching org pools: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(pools) > 0 {
|
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)
|
scaleSets, err := r.store.ListEntityScaleSets(ctx, entity)
|
||||||
if err != nil {
|
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 {
|
if len(scaleSets) > 0 {
|
||||||
|
|
@ -182,7 +181,7 @@ func (r *Runner) DeleteOrganization(ctx context.Context, orgID string, keepWebho
|
||||||
if !keepWebhook && r.config.Default.EnableWebhookManagement {
|
if !keepWebhook && r.config.Default.EnableWebhookManagement {
|
||||||
poolMgr, err := r.poolManagerCtrl.GetOrgPoolManager(org)
|
poolMgr, err := r.poolManagerCtrl.GetOrgPoolManager(org)
|
||||||
if err != nil {
|
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 {
|
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 {
|
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 {
|
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
|
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)
|
org, err := r.store.UpdateOrganization(ctx, orgID, param)
|
||||||
if err != nil {
|
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)
|
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)
|
createPoolParams, err := r.appendTagsToCreatePoolParams(param)
|
||||||
if err != nil {
|
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 {
|
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)
|
pool, err := r.store.CreateEntityPool(ctx, entity, createPoolParams)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return params.Pool{}, errors.Wrap(err, "creating pool")
|
return params.Pool{}, fmt.Errorf("error creating pool: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return pool, nil
|
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)
|
pool, err := r.store.GetEntityPool(ctx, entity, poolID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return params.Pool{}, errors.Wrap(err, "fetching pool")
|
return params.Pool{}, fmt.Errorf("error fetching pool: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return pool, nil
|
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)
|
pool, err := r.store.GetEntityPool(ctx, entity, poolID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if !errors.Is(err, runnerErrors.ErrNotFound) {
|
if !errors.Is(err, runnerErrors.ErrNotFound) {
|
||||||
return errors.Wrap(err, "fetching pool")
|
return fmt.Errorf("error fetching pool: %w", err)
|
||||||
}
|
}
|
||||||
return nil
|
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 {
|
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
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -321,7 +320,7 @@ func (r *Runner) ListOrgPools(ctx context.Context, orgID string) ([]params.Pool,
|
||||||
}
|
}
|
||||||
pools, err := r.store.ListEntityPools(ctx, entity)
|
pools, err := r.store.ListEntityPools(ctx, entity)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "fetching pools")
|
return nil, fmt.Errorf("error fetching pools: %w", err)
|
||||||
}
|
}
|
||||||
return pools, nil
|
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)
|
pool, err := r.store.GetEntityPool(ctx, entity, poolID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return params.Pool{}, errors.Wrap(err, "fetching pool")
|
return params.Pool{}, fmt.Errorf("error fetching pool: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
maxRunners := pool.MaxRunners
|
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)
|
newPool, err := r.store.UpdateEntityPool(ctx, entity, poolID, param)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return params.Pool{}, errors.Wrap(err, "updating pool")
|
return params.Pool{}, fmt.Errorf("error updating pool: %w", err)
|
||||||
}
|
}
|
||||||
return newPool, nil
|
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)
|
instances, err := r.store.ListEntityInstances(ctx, entity)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return []params.Instance{}, errors.Wrap(err, "fetching instances")
|
return []params.Instance{}, fmt.Errorf("error fetching instances: %w", err)
|
||||||
}
|
}
|
||||||
return instances, nil
|
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)
|
org, err := r.store.GetOrganization(r.ctx, name, endpointName)
|
||||||
if err != nil {
|
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)
|
poolManager, err := r.poolManagerCtrl.GetOrgPoolManager(org)
|
||||||
if err != nil {
|
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
|
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)
|
org, err := r.store.GetOrganizationByID(ctx, orgID)
|
||||||
if err != nil {
|
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)
|
poolMgr, err := r.poolManagerCtrl.GetOrgPoolManager(org)
|
||||||
if err != nil {
|
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)
|
info, err := poolMgr.InstallWebhook(ctx, param)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return params.HookInfo{}, errors.Wrap(err, "installing webhook")
|
return params.HookInfo{}, fmt.Errorf("error installing webhook: %w", err)
|
||||||
}
|
}
|
||||||
return info, nil
|
return info, nil
|
||||||
}
|
}
|
||||||
|
|
@ -424,16 +423,16 @@ func (r *Runner) UninstallOrgWebhook(ctx context.Context, orgID string) error {
|
||||||
|
|
||||||
org, err := r.store.GetOrganizationByID(ctx, orgID)
|
org, err := r.store.GetOrganizationByID(ctx, orgID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "fetching org")
|
return fmt.Errorf("error fetching org: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
poolMgr, err := r.poolManagerCtrl.GetOrgPoolManager(org)
|
poolMgr, err := r.poolManagerCtrl.GetOrgPoolManager(org)
|
||||||
if err != nil {
|
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 {
|
if err := poolMgr.UninstallWebhook(ctx); err != nil {
|
||||||
return errors.Wrap(err, "uninstalling webhook")
|
return fmt.Errorf("error uninstalling webhook: %w", err)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -445,17 +444,17 @@ func (r *Runner) GetOrgWebhookInfo(ctx context.Context, orgID string) (params.Ho
|
||||||
|
|
||||||
org, err := r.store.GetOrganizationByID(ctx, orgID)
|
org, err := r.store.GetOrganizationByID(ctx, orgID)
|
||||||
if err != nil {
|
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)
|
poolMgr, err := r.poolManagerCtrl.GetOrgPoolManager(org)
|
||||||
if err != nil {
|
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)
|
info, err := poolMgr.GetWebhookInfo(ctx)
|
||||||
if err != nil {
|
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
|
return info, nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,10 +16,10 @@ package runner
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
"github.com/stretchr/testify/mock"
|
"github.com/stretchr/testify/mock"
|
||||||
"github.com/stretchr/testify/suite"
|
"github.com/stretchr/testify/suite"
|
||||||
|
|
||||||
|
|
@ -224,7 +224,7 @@ func (s *OrgTestSuite) TestCreateOrganizationPoolMgrFailed() {
|
||||||
|
|
||||||
s.Fixtures.PoolMgrMock.AssertExpectations(s.T())
|
s.Fixtures.PoolMgrMock.AssertExpectations(s.T())
|
||||||
s.Fixtures.PoolMgrCtrlMock.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() {
|
func (s *OrgTestSuite) TestCreateOrganizationStartPoolMgrFailed() {
|
||||||
|
|
@ -236,7 +236,7 @@ func (s *OrgTestSuite) TestCreateOrganizationStartPoolMgrFailed() {
|
||||||
|
|
||||||
s.Fixtures.PoolMgrMock.AssertExpectations(s.T())
|
s.Fixtures.PoolMgrMock.AssertExpectations(s.T())
|
||||||
s.Fixtures.PoolMgrCtrlMock.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() {
|
func (s *OrgTestSuite) TestListOrganizations() {
|
||||||
|
|
@ -338,7 +338,7 @@ func (s *OrgTestSuite) TestDeleteOrganization() {
|
||||||
s.Require().Nil(err)
|
s.Require().Nil(err)
|
||||||
|
|
||||||
_, err = s.Fixtures.Store.GetOrganizationByID(s.Fixtures.AdminContext, s.Fixtures.StoreOrgs["test-org-3"].ID)
|
_, 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() {
|
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)
|
err := s.Runner.DeleteOrganization(s.Fixtures.AdminContext, s.Fixtures.StoreOrgs["test-org-1"].ID, true)
|
||||||
|
|
||||||
s.Fixtures.PoolMgrCtrlMock.AssertExpectations(s.T())
|
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() {
|
func (s *OrgTestSuite) TestUpdateOrganization() {
|
||||||
|
|
@ -502,7 +502,7 @@ func (s *OrgTestSuite) TestDeleteOrgPool() {
|
||||||
s.Require().Nil(err)
|
s.Require().Nil(err)
|
||||||
|
|
||||||
_, err = s.Fixtures.Store.GetEntityPool(s.Fixtures.AdminContext, entity, pool.ID)
|
_, 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() {
|
func (s *OrgTestSuite) TestDeleteOrgPoolErrUnauthorized() {
|
||||||
|
|
|
||||||
|
|
@ -16,12 +16,12 @@ package pool
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/google/go-github/v72/github"
|
"github.com/google/go-github/v72/github"
|
||||||
"github.com/pkg/errors"
|
|
||||||
|
|
||||||
runnerErrors "github.com/cloudbase/garm-provider-common/errors"
|
runnerErrors "github.com/cloudbase/garm-provider-common/errors"
|
||||||
"github.com/cloudbase/garm/params"
|
"github.com/cloudbase/garm/params"
|
||||||
|
|
@ -30,7 +30,7 @@ import (
|
||||||
func validateHookRequest(controllerID, baseURL string, allHooks []*github.Hook, req *github.Hook) error {
|
func validateHookRequest(controllerID, baseURL string, allHooks []*github.Hook, req *github.Hook) error {
|
||||||
parsed, err := url.Parse(baseURL)
|
parsed, err := url.Parse(baseURL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "parsing webhook url")
|
return fmt.Errorf("error parsing webhook url: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
partialMatches := []string{}
|
partialMatches := []string{}
|
||||||
|
|
@ -80,7 +80,7 @@ func (r *basePoolManager) listHooks(ctx context.Context) ([]*github.Hook, error)
|
||||||
if ghResp != nil && ghResp.StatusCode == http.StatusNotFound {
|
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, runnerErrors.NewBadRequestError("repository not found or your PAT does not have access to manage webhooks")
|
||||||
}
|
}
|
||||||
return nil, errors.Wrap(err, "fetching hooks")
|
return nil, fmt.Errorf("error fetching hooks: %w", err)
|
||||||
}
|
}
|
||||||
allHooks = append(allHooks, hooks...)
|
allHooks = append(allHooks, hooks...)
|
||||||
if ghResp.NextPage == 0 {
|
if ghResp.NextPage == 0 {
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ package pool
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
"math"
|
"math"
|
||||||
|
|
@ -29,7 +30,6 @@ import (
|
||||||
|
|
||||||
"github.com/google/go-github/v72/github"
|
"github.com/google/go-github/v72/github"
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
"github.com/pkg/errors"
|
|
||||||
"golang.org/x/sync/errgroup"
|
"golang.org/x/sync/errgroup"
|
||||||
|
|
||||||
runnerErrors "github.com/cloudbase/garm-provider-common/errors"
|
runnerErrors "github.com/cloudbase/garm-provider-common/errors"
|
||||||
|
|
@ -76,16 +76,16 @@ func NewEntityPoolManager(ctx context.Context, entity params.ForgeEntity, instan
|
||||||
)
|
)
|
||||||
ghc, err := ghClient.Client(ctx, entity)
|
ghc, err := ghClient.Client(ctx, entity)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "getting github client")
|
return nil, fmt.Errorf("error getting github client: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if entity.WebhookSecret == "" {
|
if entity.WebhookSecret == "" {
|
||||||
return nil, errors.New("webhook secret is empty")
|
return nil, fmt.Errorf("webhook secret is empty")
|
||||||
}
|
}
|
||||||
|
|
||||||
controllerInfo, err := store.ControllerInfo()
|
controllerInfo, err := store.ControllerInfo()
|
||||||
if err != nil {
|
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)
|
consumerID := fmt.Sprintf("pool-manager-%s-%s", entity.String(), entity.Credentials.Endpoint.Name)
|
||||||
|
|
@ -95,13 +95,13 @@ func NewEntityPoolManager(ctx context.Context, entity params.ForgeEntity, instan
|
||||||
composeWatcherFilters(entity),
|
composeWatcherFilters(entity),
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "registering consumer")
|
return nil, fmt.Errorf("error registering consumer: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
wg := &sync.WaitGroup{}
|
wg := &sync.WaitGroup{}
|
||||||
backoff, err := locking.NewInstanceDeleteBackoff(ctx)
|
backoff, err := locking.NewInstanceDeleteBackoff(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "creating backoff")
|
return nil, fmt.Errorf("error creating backoff: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
repo := &basePoolManager{
|
repo := &basePoolManager{
|
||||||
|
|
@ -158,7 +158,7 @@ func (r *basePoolManager) getProviderBaseParams(pool params.Pool) common.Provide
|
||||||
func (r *basePoolManager) HandleWorkflowJob(job params.WorkflowJob) error {
|
func (r *basePoolManager) HandleWorkflowJob(job params.WorkflowJob) error {
|
||||||
if err := r.ValidateOwner(job); err != nil {
|
if err := r.ValidateOwner(job); err != nil {
|
||||||
slog.ErrorContext(r.ctx, "failed to validate owner", "error", err)
|
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
|
// we see events where the lables seem to be missing. We should ignore these
|
||||||
|
|
@ -171,7 +171,7 @@ func (r *basePoolManager) HandleWorkflowJob(job params.WorkflowJob) error {
|
||||||
jobParams, err := r.paramsWorkflowJobToParamsJob(job)
|
jobParams, err := r.paramsWorkflowJobToParamsJob(job)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
slog.ErrorContext(r.ctx, "failed to convert job to params", "error", err)
|
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
|
var triggeredBy int64
|
||||||
|
|
@ -249,7 +249,7 @@ func (r *basePoolManager) HandleWorkflowJob(job params.WorkflowJob) error {
|
||||||
slog.With(slog.Any("error", err)).ErrorContext(
|
slog.With(slog.Any("error", err)).ErrorContext(
|
||||||
r.ctx, "failed to update runner status",
|
r.ctx, "failed to update runner status",
|
||||||
"runner_name", util.SanitizeLogEntry(jobParams.RunnerName))
|
"runner_name", util.SanitizeLogEntry(jobParams.RunnerName))
|
||||||
return errors.Wrap(err, "updating runner")
|
return fmt.Errorf("error updating runner: %w", err)
|
||||||
}
|
}
|
||||||
slog.DebugContext(
|
slog.DebugContext(
|
||||||
r.ctx, "marking instance as pending_delete",
|
r.ctx, "marking instance as pending_delete",
|
||||||
|
|
@ -261,7 +261,7 @@ func (r *basePoolManager) HandleWorkflowJob(job params.WorkflowJob) error {
|
||||||
slog.With(slog.Any("error", err)).ErrorContext(
|
slog.With(slog.Any("error", err)).ErrorContext(
|
||||||
r.ctx, "failed to update runner status",
|
r.ctx, "failed to update runner status",
|
||||||
"runner_name", util.SanitizeLogEntry(jobParams.RunnerName))
|
"runner_name", util.SanitizeLogEntry(jobParams.RunnerName))
|
||||||
return errors.Wrap(err, "updating runner")
|
return fmt.Errorf("error updating runner: %w", err)
|
||||||
}
|
}
|
||||||
case "in_progress":
|
case "in_progress":
|
||||||
fromCache, ok := cache.GetInstanceCache(jobParams.RunnerName)
|
fromCache, ok := cache.GetInstanceCache(jobParams.RunnerName)
|
||||||
|
|
@ -284,7 +284,7 @@ func (r *basePoolManager) HandleWorkflowJob(job params.WorkflowJob) error {
|
||||||
slog.With(slog.Any("error", err)).ErrorContext(
|
slog.With(slog.Any("error", err)).ErrorContext(
|
||||||
r.ctx, "failed to update runner status",
|
r.ctx, "failed to update runner status",
|
||||||
"runner_name", util.SanitizeLogEntry(jobParams.RunnerName))
|
"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.
|
// Set triggeredBy here so we break the lock on any potential queued job.
|
||||||
triggeredBy = jobIDFromLabels(instance.AditionalLabels)
|
triggeredBy = jobIDFromLabels(instance.AditionalLabels)
|
||||||
|
|
@ -396,7 +396,7 @@ func (r *basePoolManager) updateTools() error {
|
||||||
func (r *basePoolManager) cleanupOrphanedProviderRunners(runners []*github.Runner) error {
|
func (r *basePoolManager) cleanupOrphanedProviderRunners(runners []*github.Runner) error {
|
||||||
dbInstances, err := r.store.ListEntityInstances(r.ctx, r.entity)
|
dbInstances, err := r.store.ListEntityInstances(r.ctx, r.entity)
|
||||||
if err != nil {
|
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{}
|
runnerNames := map[string]bool{}
|
||||||
|
|
@ -435,7 +435,7 @@ func (r *basePoolManager) cleanupOrphanedProviderRunners(runners []*github.Runne
|
||||||
}
|
}
|
||||||
pool, err := r.store.GetEntityPool(r.ctx, r.entity, instance.PoolID)
|
pool, err := r.store.GetEntityPool(r.ctx, r.entity, instance.PoolID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "fetching instance pool info")
|
return fmt.Errorf("error fetching instance pool info: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
switch instance.RunnerStatus {
|
switch instance.RunnerStatus {
|
||||||
|
|
@ -463,7 +463,7 @@ func (r *basePoolManager) cleanupOrphanedProviderRunners(runners []*github.Runne
|
||||||
slog.With(slog.Any("error", err)).ErrorContext(
|
slog.With(slog.Any("error", err)).ErrorContext(
|
||||||
r.ctx, "failed to update runner",
|
r.ctx, "failed to update runner",
|
||||||
"runner_name", instance.Name)
|
"runner_name", instance.Name)
|
||||||
return errors.Wrap(err, "updating runner")
|
return fmt.Errorf("error updating runner: %w", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -476,7 +476,7 @@ func (r *basePoolManager) cleanupOrphanedProviderRunners(runners []*github.Runne
|
||||||
func (r *basePoolManager) reapTimedOutRunners(runners []*github.Runner) error {
|
func (r *basePoolManager) reapTimedOutRunners(runners []*github.Runner) error {
|
||||||
dbInstances, err := r.store.ListEntityInstances(r.ctx, r.entity)
|
dbInstances, err := r.store.ListEntityInstances(r.ctx, r.entity)
|
||||||
if err != nil {
|
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]*github.Runner{}
|
||||||
|
|
@ -510,7 +510,7 @@ func (r *basePoolManager) reapTimedOutRunners(runners []*github.Runner) error {
|
||||||
|
|
||||||
pool, err := r.store.GetEntityPool(r.ctx, r.entity, instance.PoolID)
|
pool, err := r.store.GetEntityPool(r.ctx, r.entity, instance.PoolID)
|
||||||
if err != nil {
|
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()) {
|
if time.Since(instance.UpdatedAt).Minutes() < float64(pool.RunnerTimeout()) {
|
||||||
continue
|
continue
|
||||||
|
|
@ -529,7 +529,7 @@ func (r *basePoolManager) reapTimedOutRunners(runners []*github.Runner) error {
|
||||||
slog.With(slog.Any("error", err)).ErrorContext(
|
slog.With(slog.Any("error", err)).ErrorContext(
|
||||||
r.ctx, "failed to update runner status",
|
r.ctx, "failed to update runner status",
|
||||||
"runner_name", instance.Name)
|
"runner_name", instance.Name)
|
||||||
return errors.Wrap(err, "updating runner")
|
return fmt.Errorf("error updating runner: %w", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -560,7 +560,7 @@ func (r *basePoolManager) cleanupOrphanedGithubRunners(runners []*github.Runner)
|
||||||
dbInstance, err := r.store.GetInstanceByName(r.ctx, *runner.Name)
|
dbInstance, err := r.store.GetInstanceByName(r.ctx, *runner.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if !errors.Is(err, runnerErrors.ErrNotFound) {
|
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.
|
// We no longer have a DB entry for this instance, and the runner appears offline in github.
|
||||||
// Previous forceful removal may have failed?
|
// Previous forceful removal may have failed?
|
||||||
|
|
@ -572,7 +572,7 @@ func (r *basePoolManager) cleanupOrphanedGithubRunners(runners []*github.Runner)
|
||||||
if errors.Is(err, runnerErrors.ErrNotFound) {
|
if errors.Is(err, runnerErrors.ErrNotFound) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
return errors.Wrap(err, "removing runner")
|
return fmt.Errorf("error removing runner: %w", err)
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
@ -606,7 +606,7 @@ func (r *basePoolManager) cleanupOrphanedGithubRunners(runners []*github.Runner)
|
||||||
|
|
||||||
pool, err := r.store.GetEntityPool(r.ctx, r.entity, dbInstance.PoolID)
|
pool, err := r.store.GetEntityPool(r.ctx, r.entity, dbInstance.PoolID)
|
||||||
if err != nil {
|
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.
|
// check if the provider still has the instance.
|
||||||
|
|
@ -628,7 +628,7 @@ func (r *basePoolManager) cleanupOrphanedGithubRunners(runners []*github.Runner)
|
||||||
}
|
}
|
||||||
poolInstances, err = provider.ListInstances(r.ctx, pool.ID, listInstancesParams)
|
poolInstances, err = provider.ListInstances(r.ctx, pool.ID, listInstancesParams)
|
||||||
if err != nil {
|
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
|
poolInstanceCache[dbInstance.PoolID] = poolInstances
|
||||||
}
|
}
|
||||||
|
|
@ -662,7 +662,7 @@ func (r *basePoolManager) cleanupOrphanedGithubRunners(runners []*github.Runner)
|
||||||
r.ctx, "runner disappeared from github",
|
r.ctx, "runner disappeared from github",
|
||||||
"runner_name", dbInstance.Name)
|
"runner_name", dbInstance.Name)
|
||||||
} else {
|
} 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.
|
// Remove the database entry for the runner.
|
||||||
|
|
@ -670,7 +670,7 @@ func (r *basePoolManager) cleanupOrphanedGithubRunners(runners []*github.Runner)
|
||||||
r.ctx, "Removing from database",
|
r.ctx, "Removing from database",
|
||||||
"runner_name", dbInstance.Name)
|
"runner_name", dbInstance.Name)
|
||||||
if err := r.store.DeleteInstance(ctx, dbInstance.PoolID, dbInstance.Name); err != nil {
|
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
|
deleteMux = true
|
||||||
return nil
|
return nil
|
||||||
|
|
@ -696,13 +696,13 @@ func (r *basePoolManager) cleanupOrphanedGithubRunners(runners []*github.Runner)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
if err := provider.Start(r.ctx, dbInstance.ProviderID, startParams); err != nil {
|
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
|
return nil
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
if err := r.waitForErrorGroupOrContextCancelled(g); err != 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
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -732,7 +732,7 @@ func (r *basePoolManager) setInstanceRunnerStatus(runnerName string, status para
|
||||||
}
|
}
|
||||||
instance, err := r.store.UpdateInstance(r.ctx, runnerName, updateParams)
|
instance, err := r.store.UpdateInstance(r.ctx, runnerName, updateParams)
|
||||||
if err != nil {
|
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
|
return instance, nil
|
||||||
}
|
}
|
||||||
|
|
@ -745,7 +745,7 @@ func (r *basePoolManager) setInstanceStatus(runnerName string, status commonPara
|
||||||
|
|
||||||
instance, err := r.store.UpdateInstance(r.ctx, runnerName, updateParams)
|
instance, err := r.store.UpdateInstance(r.ctx, runnerName, updateParams)
|
||||||
if err != nil {
|
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
|
return instance, nil
|
||||||
}
|
}
|
||||||
|
|
@ -753,7 +753,7 @@ func (r *basePoolManager) setInstanceStatus(runnerName string, status commonPara
|
||||||
func (r *basePoolManager) AddRunner(ctx context.Context, poolID string, aditionalLabels []string) (err error) {
|
func (r *basePoolManager) AddRunner(ctx context.Context, poolID string, aditionalLabels []string) (err error) {
|
||||||
pool, err := r.store.GetEntityPool(r.ctx, r.entity, poolID)
|
pool, err := r.store.GetEntityPool(r.ctx, r.entity, poolID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "fetching pool")
|
return fmt.Errorf("error fetching pool: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
provider, ok := r.providers[pool.ProviderName]
|
provider, ok := r.providers[pool.ProviderName]
|
||||||
|
|
@ -796,7 +796,7 @@ func (r *basePoolManager) AddRunner(ctx context.Context, poolID string, aditiona
|
||||||
|
|
||||||
instance, err := r.store.CreateInstance(r.ctx, poolID, createParams)
|
instance, err := r.store.CreateInstance(r.ctx, poolID, createParams)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "creating instance")
|
return fmt.Errorf("error creating instance: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
|
|
@ -864,7 +864,7 @@ func (r *basePoolManager) getLabelsForInstance(pool params.Pool) []string {
|
||||||
func (r *basePoolManager) addInstanceToProvider(instance params.Instance) error {
|
func (r *basePoolManager) addInstanceToProvider(instance params.Instance) error {
|
||||||
pool, err := r.store.GetEntityPool(r.ctx, r.entity, instance.PoolID)
|
pool, err := r.store.GetEntityPool(r.ctx, r.entity, instance.PoolID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "fetching pool")
|
return fmt.Errorf("error fetching pool: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
provider, ok := r.providers[pool.ProviderName]
|
provider, ok := r.providers[pool.ProviderName]
|
||||||
|
|
@ -876,7 +876,7 @@ func (r *basePoolManager) addInstanceToProvider(instance params.Instance) error
|
||||||
|
|
||||||
jwtToken, err := r.instanceTokenGetter.NewInstanceJWTToken(instance, r.entity, pool.PoolType(), jwtValidity)
|
jwtToken, err := r.instanceTokenGetter.NewInstanceJWTToken(instance, r.entity, pool.PoolType(), jwtValidity)
|
||||||
if err != nil {
|
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
|
hasJITConfig := len(instance.JitConfiguration) > 0
|
||||||
|
|
@ -933,7 +933,7 @@ func (r *basePoolManager) addInstanceToProvider(instance params.Instance) error
|
||||||
providerInstance, err := provider.CreateInstance(r.ctx, bootstrapArgs, createInstanceParams)
|
providerInstance, err := provider.CreateInstance(r.ctx, bootstrapArgs, createInstanceParams)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
instanceIDToDelete = instance.Name
|
instanceIDToDelete = instance.Name
|
||||||
return errors.Wrap(err, "creating instance")
|
return fmt.Errorf("error creating instance: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if providerInstance.Status == commonParams.InstanceError {
|
if providerInstance.Status == commonParams.InstanceError {
|
||||||
|
|
@ -945,7 +945,7 @@ func (r *basePoolManager) addInstanceToProvider(instance params.Instance) error
|
||||||
|
|
||||||
updateInstanceArgs := r.updateArgsFromProviderInstance(providerInstance)
|
updateInstanceArgs := r.updateArgsFromProviderInstance(providerInstance)
|
||||||
if _, err := r.store.UpdateInstance(r.ctx, instance.Name, updateInstanceArgs); err != nil {
|
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
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -966,7 +966,7 @@ func (r *basePoolManager) addInstanceToProvider(instance params.Instance) error
|
||||||
func (r *basePoolManager) paramsWorkflowJobToParamsJob(job params.WorkflowJob) (params.Job, error) {
|
func (r *basePoolManager) paramsWorkflowJobToParamsJob(job params.WorkflowJob) (params.Job, error) {
|
||||||
asUUID, err := uuid.Parse(r.ID())
|
asUUID, err := uuid.Parse(r.ID())
|
||||||
if err != nil {
|
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{
|
jobParams := params.Job{
|
||||||
|
|
@ -995,7 +995,7 @@ func (r *basePoolManager) paramsWorkflowJobToParamsJob(job params.WorkflowJob) (
|
||||||
case params.ForgeEntityTypeOrganization:
|
case params.ForgeEntityTypeOrganization:
|
||||||
jobParams.OrgID = &asUUID
|
jobParams.OrgID = &asUUID
|
||||||
default:
|
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
|
return jobParams, nil
|
||||||
|
|
@ -1101,7 +1101,7 @@ func (r *basePoolManager) scaleDownOnePool(ctx context.Context, pool params.Pool
|
||||||
// instead of returning a bunch of results and filtering manually.
|
// 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)
|
queued, err := r.store.ListEntityJobsByStatus(r.ctx, r.entity.EntityType, r.entity.ID, params.JobStatusQueued)
|
||||||
if err != nil && !errors.Is(err, runnerErrors.ErrNotFound) {
|
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 {
|
for _, job := range queued {
|
||||||
|
|
@ -1341,7 +1341,7 @@ func (r *basePoolManager) ensureMinIdleRunners() error {
|
||||||
func (r *basePoolManager) deleteInstanceFromProvider(ctx context.Context, instance params.Instance) error {
|
func (r *basePoolManager) deleteInstanceFromProvider(ctx context.Context, instance params.Instance) error {
|
||||||
pool, err := r.store.GetEntityPool(r.ctx, r.entity, instance.PoolID)
|
pool, err := r.store.GetEntityPool(r.ctx, r.entity, instance.PoolID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "fetching pool")
|
return fmt.Errorf("error fetching pool: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
provider, ok := r.providers[instance.ProviderName]
|
provider, ok := r.providers[instance.ProviderName]
|
||||||
|
|
@ -1367,7 +1367,7 @@ func (r *basePoolManager) deleteInstanceFromProvider(ctx context.Context, instan
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
if err := provider.DeleteInstance(ctx, identifier, deleteInstanceParams); err != nil {
|
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
|
return nil
|
||||||
|
|
@ -1583,7 +1583,7 @@ func (r *basePoolManager) Wait() error {
|
||||||
select {
|
select {
|
||||||
case <-done:
|
case <-done:
|
||||||
case <-timer.C:
|
case <-timer.C:
|
||||||
return errors.Wrap(runnerErrors.ErrTimeout, "waiting for pool to stop")
|
return runnerErrors.NewTimeoutError("waiting for pool to stop")
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -1609,11 +1609,11 @@ func (r *basePoolManager) runnerCleanup() (err error) {
|
||||||
|
|
||||||
func (r *basePoolManager) cleanupOrphanedRunners(runners []*github.Runner) error {
|
func (r *basePoolManager) cleanupOrphanedRunners(runners []*github.Runner) error {
|
||||||
if err := r.cleanupOrphanedProviderRunners(runners); err != nil {
|
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 {
|
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
|
return nil
|
||||||
|
|
@ -1693,10 +1693,10 @@ func (r *basePoolManager) DeleteRunner(runner params.Instance, forceRemove, bypa
|
||||||
if bypassGHUnauthorizedError {
|
if bypassGHUnauthorizedError {
|
||||||
slog.Info("bypass github unauthorized error is set, marking runner for deletion")
|
slog.Info("bypass github unauthorized error is set, marking runner for deletion")
|
||||||
} else {
|
} else {
|
||||||
return errors.Wrap(err, "removing runner")
|
return fmt.Errorf("error removing runner: %w", err)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return errors.Wrap(err, "removing runner")
|
return fmt.Errorf("error removing runner: %w", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1714,7 +1714,7 @@ func (r *basePoolManager) DeleteRunner(runner params.Instance, forceRemove, bypa
|
||||||
slog.With(slog.Any("error", err)).ErrorContext(
|
slog.With(slog.Any("error", err)).ErrorContext(
|
||||||
r.ctx, "failed to update runner",
|
r.ctx, "failed to update runner",
|
||||||
"runner_name", runner.Name)
|
"runner_name", runner.Name)
|
||||||
return errors.Wrap(err, "updating runner")
|
return fmt.Errorf("error updating runner: %w", err)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -1745,7 +1745,7 @@ func (r *basePoolManager) DeleteRunner(runner params.Instance, forceRemove, bypa
|
||||||
func (r *basePoolManager) consumeQueuedJobs() error {
|
func (r *basePoolManager) consumeQueuedJobs() error {
|
||||||
queued, err := r.store.ListEntityJobsByStatus(r.ctx, r.entity.EntityType, r.entity.ID, params.JobStatusQueued)
|
queued, err := r.store.ListEntityJobsByStatus(r.ctx, r.entity.EntityType, r.entity.ID, params.JobStatusQueued)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "listing queued jobs")
|
return fmt.Errorf("error listing queued jobs: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
poolsCache := poolsForTags{
|
poolsCache := poolsForTags{
|
||||||
|
|
@ -1860,7 +1860,7 @@ func (r *basePoolManager) consumeQueuedJobs() error {
|
||||||
slog.With(slog.Any("error", err)).ErrorContext(
|
slog.With(slog.Any("error", err)).ErrorContext(
|
||||||
r.ctx, "failed to unlock job",
|
r.ctx, "failed to unlock job",
|
||||||
"job_id", job.WorkflowJobID)
|
"job_id", job.WorkflowJobID)
|
||||||
return errors.Wrap(err, "unlocking job")
|
return fmt.Errorf("error unlocking job: %w", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1874,12 +1874,12 @@ func (r *basePoolManager) consumeQueuedJobs() error {
|
||||||
|
|
||||||
func (r *basePoolManager) UninstallWebhook(ctx context.Context) error {
|
func (r *basePoolManager) UninstallWebhook(ctx context.Context) error {
|
||||||
if r.controllerInfo.ControllerWebhookURL == "" {
|
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)
|
allHooks, err := r.listHooks(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "listing hooks")
|
return fmt.Errorf("error listing hooks: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var controllerHookID int64
|
var controllerHookID int64
|
||||||
|
|
@ -1917,16 +1917,16 @@ func (r *basePoolManager) UninstallWebhook(ctx context.Context) error {
|
||||||
func (r *basePoolManager) InstallHook(ctx context.Context, req *github.Hook) (params.HookInfo, error) {
|
func (r *basePoolManager) InstallHook(ctx context.Context, req *github.Hook) (params.HookInfo, error) {
|
||||||
allHooks, err := r.listHooks(ctx)
|
allHooks, err := r.listHooks(ctx)
|
||||||
if err != nil {
|
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 {
|
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)
|
hook, err := r.ghcli.CreateEntityHook(ctx, req)
|
||||||
if err != nil {
|
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 {
|
if _, err := r.ghcli.PingEntityHook(ctx, hook.GetID()); err != nil {
|
||||||
|
|
@ -1941,7 +1941,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) {
|
func (r *basePoolManager) InstallWebhook(ctx context.Context, param params.InstallWebhookParams) (params.HookInfo, error) {
|
||||||
if r.controllerInfo.ControllerWebhookURL == "" {
|
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"
|
insecureSSL := "0"
|
||||||
|
|
@ -1989,9 +1989,9 @@ func (r *basePoolManager) GithubRunnerRegistrationToken() (string, error) {
|
||||||
tk, ghResp, err := r.ghcli.CreateEntityRegistrationToken(r.ctx)
|
tk, ghResp, err := r.ghcli.CreateEntityRegistrationToken(r.ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if ghResp != nil && ghResp.StatusCode == http.StatusUnauthorized {
|
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
|
return *tk.Token, nil
|
||||||
}
|
}
|
||||||
|
|
@ -2000,9 +2000,9 @@ func (r *basePoolManager) FetchTools() ([]commonParams.RunnerApplicationDownload
|
||||||
tools, ghResp, err := r.ghcli.ListEntityRunnerApplicationDownloads(r.ctx)
|
tools, ghResp, err := r.ghcli.ListEntityRunnerApplicationDownloads(r.ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if ghResp != nil && ghResp.StatusCode == http.StatusUnauthorized {
|
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{}
|
ret := []commonParams.RunnerApplicationDownload{}
|
||||||
|
|
@ -2027,9 +2027,9 @@ func (r *basePoolManager) GetGithubRunners() ([]*github.Runner, error) {
|
||||||
runners, ghResp, err := r.ghcli.ListEntityRunners(r.ctx, &opts)
|
runners, ghResp, err := r.ghcli.ListEntityRunners(r.ctx, &opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if ghResp != nil && ghResp.StatusCode == http.StatusUnauthorized {
|
if ghResp != nil && ghResp.StatusCode == http.StatusUnauthorized {
|
||||||
return nil, errors.Wrap(runnerErrors.ErrUnauthorized, "fetching runners")
|
return nil, runnerErrors.NewUnauthorizedError("error fetching runners")
|
||||||
}
|
}
|
||||||
return nil, errors.Wrap(err, "fetching runners")
|
return nil, fmt.Errorf("error fetching runners: %w", err)
|
||||||
}
|
}
|
||||||
allRunners = append(allRunners, runners.Runners...)
|
allRunners = append(allRunners, runners.Runners...)
|
||||||
if ghResp.NextPage == 0 {
|
if ghResp.NextPage == 0 {
|
||||||
|
|
@ -2044,7 +2044,7 @@ func (r *basePoolManager) GetGithubRunners() ([]*github.Runner, error) {
|
||||||
func (r *basePoolManager) GetWebhookInfo(ctx context.Context) (params.HookInfo, error) {
|
func (r *basePoolManager) GetWebhookInfo(ctx context.Context) (params.HookInfo, error) {
|
||||||
allHooks, err := r.listHooks(ctx)
|
allHooks, err := r.listHooks(ctx)
|
||||||
if err != nil {
|
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, "/")
|
trimmedBase := strings.TrimRight(r.controllerInfo.WebhookURL, "/")
|
||||||
trimmedController := strings.TrimRight(r.controllerInfo.ControllerWebhookURL, "/")
|
trimmedController := strings.TrimRight(r.controllerInfo.ControllerWebhookURL, "/")
|
||||||
|
|
|
||||||
|
|
@ -17,8 +17,6 @@ package pool
|
||||||
import (
|
import (
|
||||||
"log/slog"
|
"log/slog"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
|
|
||||||
runnerErrors "github.com/cloudbase/garm-provider-common/errors"
|
runnerErrors "github.com/cloudbase/garm-provider-common/errors"
|
||||||
"github.com/cloudbase/garm/database/common"
|
"github.com/cloudbase/garm/database/common"
|
||||||
"github.com/cloudbase/garm/params"
|
"github.com/cloudbase/garm/params"
|
||||||
|
|
@ -46,7 +44,7 @@ func (r *basePoolManager) getClientOrStub() runnerCommon.GithubClient {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
slog.WarnContext(r.ctx, "failed to create github client", "error", err)
|
slog.WarnContext(r.ctx, "failed to create github client", "error", err)
|
||||||
ghc = &stubGithubClient{
|
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
|
return ghc
|
||||||
|
|
|
||||||
|
|
@ -16,8 +16,8 @@ package runner
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
"github.com/pkg/errors"
|
"fmt"
|
||||||
|
|
||||||
runnerErrors "github.com/cloudbase/garm-provider-common/errors"
|
runnerErrors "github.com/cloudbase/garm-provider-common/errors"
|
||||||
"github.com/cloudbase/garm/auth"
|
"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)
|
pools, err := r.store.ListAllPools(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "fetching pools")
|
return nil, fmt.Errorf("error fetching pools: %w", err)
|
||||||
}
|
}
|
||||||
return pools, nil
|
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)
|
pool, err := r.store.GetPoolByID(ctx, poolID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return params.Pool{}, errors.Wrap(err, "fetching pool")
|
return params.Pool{}, fmt.Errorf("error fetching pool: %w", err)
|
||||||
}
|
}
|
||||||
return pool, nil
|
return pool, nil
|
||||||
}
|
}
|
||||||
|
|
@ -56,7 +56,7 @@ func (r *Runner) DeletePoolByID(ctx context.Context, poolID string) error {
|
||||||
pool, err := r.store.GetPoolByID(ctx, poolID)
|
pool, err := r.store.GetPoolByID(ctx, poolID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if !errors.Is(err, runnerErrors.ErrNotFound) {
|
if !errors.Is(err, runnerErrors.ErrNotFound) {
|
||||||
return errors.Wrap(err, "fetching pool")
|
return fmt.Errorf("error fetching pool: %w", err)
|
||||||
}
|
}
|
||||||
return nil
|
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 {
|
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
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -78,7 +78,7 @@ func (r *Runner) UpdatePoolByID(ctx context.Context, poolID string, param params
|
||||||
|
|
||||||
pool, err := r.store.GetPoolByID(ctx, poolID)
|
pool, err := r.store.GetPoolByID(ctx, poolID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return params.Pool{}, errors.Wrap(err, "fetching pool")
|
return params.Pool{}, fmt.Errorf("error fetching pool: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
maxRunners := pool.MaxRunners
|
maxRunners := pool.MaxRunners
|
||||||
|
|
@ -101,12 +101,12 @@ func (r *Runner) UpdatePoolByID(ctx context.Context, poolID string, param params
|
||||||
|
|
||||||
entity, err := pool.GetEntity()
|
entity, err := pool.GetEntity()
|
||||||
if err != nil {
|
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)
|
newPool, err := r.store.UpdateEntityPool(ctx, entity, poolID, param)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return params.Pool{}, errors.Wrap(err, "updating pool")
|
return params.Pool{}, fmt.Errorf("error updating pool: %w", err)
|
||||||
}
|
}
|
||||||
return newPool, nil
|
return newPool, nil
|
||||||
}
|
}
|
||||||
|
|
@ -118,7 +118,7 @@ func (r *Runner) ListAllJobs(ctx context.Context) ([]params.Job, error) {
|
||||||
|
|
||||||
jobs, err := r.store.ListAllJobs(ctx)
|
jobs, err := r.store.ListAllJobs(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "fetching jobs")
|
return nil, fmt.Errorf("error fetching jobs: %w", err)
|
||||||
}
|
}
|
||||||
return jobs, nil
|
return jobs, nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -169,7 +169,7 @@ func (s *PoolTestSuite) TestGetPoolByIDNotFound() {
|
||||||
s.Require().Nil(err)
|
s.Require().Nil(err)
|
||||||
_, err = s.Runner.GetPoolByID(s.Fixtures.AdminContext, s.Fixtures.Pools[0].ID)
|
_, err = s.Runner.GetPoolByID(s.Fixtures.AdminContext, s.Fixtures.Pools[0].ID)
|
||||||
s.Require().NotNil(err)
|
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() {
|
func (s *PoolTestSuite) TestDeletePoolByID() {
|
||||||
|
|
@ -178,7 +178,7 @@ func (s *PoolTestSuite) TestDeletePoolByID() {
|
||||||
s.Require().Nil(err)
|
s.Require().Nil(err)
|
||||||
_, err = s.Fixtures.Store.GetPoolByID(s.Fixtures.AdminContext, s.Fixtures.Pools[0].ID)
|
_, err = s.Fixtures.Store.GetPoolByID(s.Fixtures.AdminContext, s.Fixtures.Pools[0].ID)
|
||||||
s.Require().NotNil(err)
|
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() {
|
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)
|
_, err := s.Runner.UpdatePoolByID(s.Fixtures.AdminContext, "dummy-pool-id", s.Fixtures.UpdatePoolParams)
|
||||||
|
|
||||||
s.Require().NotNil(err)
|
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() {
|
func (s *PoolTestSuite) TestTestUpdatePoolByIDRunnerBootstrapTimeoutFailed() {
|
||||||
|
|
|
||||||
|
|
@ -16,10 +16,9 @@ package providers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
|
|
||||||
"github.com/cloudbase/garm/config"
|
"github.com/cloudbase/garm/config"
|
||||||
"github.com/cloudbase/garm/params"
|
"github.com/cloudbase/garm/params"
|
||||||
"github.com/cloudbase/garm/runner/common"
|
"github.com/cloudbase/garm/runner/common"
|
||||||
|
|
@ -39,11 +38,11 @@ func LoadProvidersFromConfig(ctx context.Context, cfg config.Config, controllerI
|
||||||
conf := providerCfg
|
conf := providerCfg
|
||||||
provider, err := external.NewProvider(ctx, &conf, controllerID)
|
provider, err := external.NewProvider(ctx, &conf, controllerID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "creating provider")
|
return nil, fmt.Errorf("error creating provider: %w", err)
|
||||||
}
|
}
|
||||||
providers[providerCfg.Name] = provider
|
providers[providerCfg.Name] = provider
|
||||||
default:
|
default:
|
||||||
return nil, errors.Errorf("unknown provider type %s", providerCfg.ProviderType)
|
return nil, fmt.Errorf("unknown provider type %s", providerCfg.ProviderType)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return providers, nil
|
return providers, nil
|
||||||
|
|
|
||||||
|
|
@ -17,12 +17,11 @@ package v010
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
|
|
||||||
garmErrors "github.com/cloudbase/garm-provider-common/errors"
|
garmErrors "github.com/cloudbase/garm-provider-common/errors"
|
||||||
commonExecution "github.com/cloudbase/garm-provider-common/execution/common"
|
commonExecution "github.com/cloudbase/garm-provider-common/execution/common"
|
||||||
commonParams "github.com/cloudbase/garm-provider-common/params"
|
commonParams "github.com/cloudbase/garm-provider-common/params"
|
||||||
|
|
@ -44,7 +43,7 @@ func NewProvider(ctx context.Context, cfg *config.Provider, controllerID string)
|
||||||
|
|
||||||
execPath, err := cfg.External.ExecutablePath()
|
execPath, err := cfg.External.ExecutablePath()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "fetching executable path")
|
return nil, fmt.Errorf("error fetching executable path: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set GARM_INTERFACE_VERSION to the version of the interface that the external
|
// Set GARM_INTERFACE_VERSION to the version of the interface that the external
|
||||||
|
|
@ -83,7 +82,7 @@ func (e *external) CreateInstance(ctx context.Context, bootstrapParams commonPar
|
||||||
|
|
||||||
asJs, err := json.Marshal(bootstrapParams)
|
asJs, err := json.Marshal(bootstrapParams)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return commonParams.ProviderInstance{}, errors.Wrap(err, "serializing bootstrap params")
|
return commonParams.ProviderInstance{}, fmt.Errorf("error serializing bootstrap params: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
metrics.InstanceOperationCount.WithLabelValues(
|
metrics.InstanceOperationCount.WithLabelValues(
|
||||||
|
|
|
||||||
|
|
@ -18,12 +18,11 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
|
|
||||||
garmErrors "github.com/cloudbase/garm-provider-common/errors"
|
garmErrors "github.com/cloudbase/garm-provider-common/errors"
|
||||||
commonExecution "github.com/cloudbase/garm-provider-common/execution/common"
|
commonExecution "github.com/cloudbase/garm-provider-common/execution/common"
|
||||||
commonParams "github.com/cloudbase/garm-provider-common/params"
|
commonParams "github.com/cloudbase/garm-provider-common/params"
|
||||||
|
|
@ -44,7 +43,7 @@ func NewProvider(ctx context.Context, cfg *config.Provider, controllerID string)
|
||||||
|
|
||||||
execPath, err := cfg.External.ExecutablePath()
|
execPath, err := cfg.External.ExecutablePath()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "fetching executable path")
|
return nil, fmt.Errorf("error fetching executable path: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set GARM_INTERFACE_VERSION to the version of the interface that the external
|
// Set GARM_INTERFACE_VERSION to the version of the interface that the external
|
||||||
|
|
@ -75,7 +74,7 @@ func (e *external) CreateInstance(ctx context.Context, bootstrapParams commonPar
|
||||||
extraspecs := bootstrapParams.ExtraSpecs
|
extraspecs := bootstrapParams.ExtraSpecs
|
||||||
extraspecsValue, err := json.Marshal(extraspecs)
|
extraspecsValue, err := json.Marshal(extraspecs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return commonParams.ProviderInstance{}, errors.Wrap(err, "serializing extraspecs")
|
return commonParams.ProviderInstance{}, fmt.Errorf("error serializing extraspecs: %w", err)
|
||||||
}
|
}
|
||||||
// Encode the extraspecs as base64 to avoid issues with special characters.
|
// Encode the extraspecs as base64 to avoid issues with special characters.
|
||||||
base64EncodedExtraSpecs := base64.StdEncoding.EncodeToString(extraspecsValue)
|
base64EncodedExtraSpecs := base64.StdEncoding.EncodeToString(extraspecsValue)
|
||||||
|
|
@ -90,7 +89,7 @@ func (e *external) CreateInstance(ctx context.Context, bootstrapParams commonPar
|
||||||
|
|
||||||
asJs, err := json.Marshal(bootstrapParams)
|
asJs, err := json.Marshal(bootstrapParams)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return commonParams.ProviderInstance{}, errors.Wrap(err, "serializing bootstrap params")
|
return commonParams.ProviderInstance{}, fmt.Errorf("error serializing bootstrap params: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
metrics.InstanceOperationCount.WithLabelValues(
|
metrics.InstanceOperationCount.WithLabelValues(
|
||||||
|
|
@ -136,7 +135,7 @@ func (e *external) DeleteInstance(ctx context.Context, instance string, deleteIn
|
||||||
extraspecs := deleteInstanceParams.DeleteInstanceV011.PoolInfo.ExtraSpecs
|
extraspecs := deleteInstanceParams.DeleteInstanceV011.PoolInfo.ExtraSpecs
|
||||||
extraspecsValue, err := json.Marshal(extraspecs)
|
extraspecsValue, err := json.Marshal(extraspecs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "serializing extraspecs")
|
return fmt.Errorf("error serializing extraspecs: %w", err)
|
||||||
}
|
}
|
||||||
// Encode the extraspecs as base64 to avoid issues with special characters.
|
// Encode the extraspecs as base64 to avoid issues with special characters.
|
||||||
base64EncodedExtraSpecs := base64.StdEncoding.EncodeToString(extraspecsValue)
|
base64EncodedExtraSpecs := base64.StdEncoding.EncodeToString(extraspecsValue)
|
||||||
|
|
@ -173,7 +172,7 @@ func (e *external) GetInstance(ctx context.Context, instance string, getInstance
|
||||||
extraspecs := getInstanceParams.GetInstanceV011.PoolInfo.ExtraSpecs
|
extraspecs := getInstanceParams.GetInstanceV011.PoolInfo.ExtraSpecs
|
||||||
extraspecsValue, err := json.Marshal(extraspecs)
|
extraspecsValue, err := json.Marshal(extraspecs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return commonParams.ProviderInstance{}, errors.Wrap(err, "serializing extraspecs")
|
return commonParams.ProviderInstance{}, fmt.Errorf("error serializing extraspecs: %w", err)
|
||||||
}
|
}
|
||||||
// Encode the extraspecs as base64 to avoid issues with special characters.
|
// Encode the extraspecs as base64 to avoid issues with special characters.
|
||||||
base64EncodedExtraSpecs := base64.StdEncoding.EncodeToString(extraspecsValue)
|
base64EncodedExtraSpecs := base64.StdEncoding.EncodeToString(extraspecsValue)
|
||||||
|
|
@ -228,7 +227,7 @@ func (e *external) ListInstances(ctx context.Context, poolID string, listInstanc
|
||||||
extraspecs := listInstancesParams.ListInstancesV011.PoolInfo.ExtraSpecs
|
extraspecs := listInstancesParams.ListInstancesV011.PoolInfo.ExtraSpecs
|
||||||
extraspecsValue, err := json.Marshal(extraspecs)
|
extraspecsValue, err := json.Marshal(extraspecs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return []commonParams.ProviderInstance{}, errors.Wrap(err, "serializing extraspecs")
|
return []commonParams.ProviderInstance{}, fmt.Errorf("error serializing extraspecs: %w", err)
|
||||||
}
|
}
|
||||||
// Encode the extraspecs as base64 to avoid issues with special characters.
|
// Encode the extraspecs as base64 to avoid issues with special characters.
|
||||||
base64EncodedExtraSpecs := base64.StdEncoding.EncodeToString(extraspecsValue)
|
base64EncodedExtraSpecs := base64.StdEncoding.EncodeToString(extraspecsValue)
|
||||||
|
|
@ -283,7 +282,7 @@ func (e *external) RemoveAllInstances(ctx context.Context, removeAllInstances co
|
||||||
extraspecs := removeAllInstances.RemoveAllInstancesV011.PoolInfo.ExtraSpecs
|
extraspecs := removeAllInstances.RemoveAllInstancesV011.PoolInfo.ExtraSpecs
|
||||||
extraspecsValue, err := json.Marshal(extraspecs)
|
extraspecsValue, err := json.Marshal(extraspecs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "serializing extraspecs")
|
return fmt.Errorf("error serializing extraspecs: %w", err)
|
||||||
}
|
}
|
||||||
// Encode the extraspecs as base64 to avoid issues with special characters.
|
// Encode the extraspecs as base64 to avoid issues with special characters.
|
||||||
base64EncodedExtraSpecs := base64.StdEncoding.EncodeToString(extraspecsValue)
|
base64EncodedExtraSpecs := base64.StdEncoding.EncodeToString(extraspecsValue)
|
||||||
|
|
@ -317,7 +316,7 @@ func (e *external) Stop(ctx context.Context, instance string, stopParams common.
|
||||||
extraspecs := stopParams.StopV011.PoolInfo.ExtraSpecs
|
extraspecs := stopParams.StopV011.PoolInfo.ExtraSpecs
|
||||||
extraspecsValue, err := json.Marshal(extraspecs)
|
extraspecsValue, err := json.Marshal(extraspecs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "serializing extraspecs")
|
return fmt.Errorf("error serializing extraspecs: %w", err)
|
||||||
}
|
}
|
||||||
// Encode the extraspecs as base64 to avoid issues with special characters.
|
// Encode the extraspecs as base64 to avoid issues with special characters.
|
||||||
base64EncodedExtraSpecs := base64.StdEncoding.EncodeToString(extraspecsValue)
|
base64EncodedExtraSpecs := base64.StdEncoding.EncodeToString(extraspecsValue)
|
||||||
|
|
@ -351,7 +350,7 @@ func (e *external) Start(ctx context.Context, instance string, startParams commo
|
||||||
extraspecs := startParams.StartV011.PoolInfo.ExtraSpecs
|
extraspecs := startParams.StartV011.PoolInfo.ExtraSpecs
|
||||||
extraspecsValue, err := json.Marshal(extraspecs)
|
extraspecsValue, err := json.Marshal(extraspecs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "serializing extraspecs")
|
return fmt.Errorf("error serializing extraspecs: %w", err)
|
||||||
}
|
}
|
||||||
// Encode the extraspecs as base64 to avoid issues with special characters.
|
// Encode the extraspecs as base64 to avoid issues with special characters.
|
||||||
base64EncodedExtraSpecs := base64.StdEncoding.EncodeToString(extraspecsValue)
|
base64EncodedExtraSpecs := base64.StdEncoding.EncodeToString(extraspecsValue)
|
||||||
|
|
|
||||||
|
|
@ -16,12 +16,11 @@ package runner
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
|
|
||||||
runnerErrors "github.com/cloudbase/garm-provider-common/errors"
|
runnerErrors "github.com/cloudbase/garm-provider-common/errors"
|
||||||
"github.com/cloudbase/garm/auth"
|
"github.com/cloudbase/garm/auth"
|
||||||
"github.com/cloudbase/garm/params"
|
"github.com/cloudbase/garm/params"
|
||||||
|
|
@ -35,7 +34,7 @@ func (r *Runner) CreateRepository(ctx context.Context, param params.CreateRepoPa
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := param.Validate(); err != nil {
|
if err := param.Validate(); err != nil {
|
||||||
return params.Repository{}, errors.Wrap(err, "validating params")
|
return params.Repository{}, fmt.Errorf("error validating params: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var creds params.ForgeCredentials
|
var creds params.ForgeCredentials
|
||||||
|
|
@ -55,7 +54,7 @@ func (r *Runner) CreateRepository(ctx context.Context, param params.CreateRepoPa
|
||||||
_, err = r.store.GetRepository(ctx, param.Owner, param.Name, creds.Endpoint.Name)
|
_, err = r.store.GetRepository(ctx, param.Owner, param.Name, creds.Endpoint.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if !errors.Is(err, runnerErrors.ErrNotFound) {
|
if !errors.Is(err, runnerErrors.ErrNotFound) {
|
||||||
return params.Repository{}, errors.Wrap(err, "fetching repo")
|
return params.Repository{}, fmt.Errorf("error fetching repo: %w", err)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return params.Repository{}, runnerErrors.NewConflictError("repository %s/%s already exists", param.Owner, param.Name)
|
return params.Repository{}, runnerErrors.NewConflictError("repository %s/%s already exists", param.Owner, param.Name)
|
||||||
|
|
@ -63,7 +62,7 @@ func (r *Runner) CreateRepository(ctx context.Context, param params.CreateRepoPa
|
||||||
|
|
||||||
repo, err = r.store.CreateRepository(ctx, param.Owner, param.Name, creds, param.WebhookSecret, param.PoolBalancerType)
|
repo, err = r.store.CreateRepository(ctx, param.Owner, param.Name, creds, param.WebhookSecret, param.PoolBalancerType)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return params.Repository{}, errors.Wrap(err, "creating repository")
|
return params.Repository{}, fmt.Errorf("error creating repository: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
|
|
@ -80,7 +79,7 @@ func (r *Runner) CreateRepository(ctx context.Context, param params.CreateRepoPa
|
||||||
// updating the store.
|
// updating the store.
|
||||||
poolMgr, err := r.poolManagerCtrl.CreateRepoPoolManager(r.ctx, repo, r.providers, r.store)
|
poolMgr, err := r.poolManagerCtrl.CreateRepoPoolManager(r.ctx, repo, r.providers, r.store)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return params.Repository{}, errors.Wrap(err, "creating repo pool manager")
|
return params.Repository{}, fmt.Errorf("error creating repo pool manager: %w", err)
|
||||||
}
|
}
|
||||||
if err := poolMgr.Start(); err != nil {
|
if err := poolMgr.Start(); err != nil {
|
||||||
if deleteErr := r.poolManagerCtrl.DeleteRepoPoolManager(repo); deleteErr != nil {
|
if deleteErr := r.poolManagerCtrl.DeleteRepoPoolManager(repo); deleteErr != nil {
|
||||||
|
|
@ -88,7 +87,7 @@ func (r *Runner) CreateRepository(ctx context.Context, param params.CreateRepoPa
|
||||||
ctx, "failed to cleanup pool manager for repo",
|
ctx, "failed to cleanup pool manager for repo",
|
||||||
"repository_id", repo.ID)
|
"repository_id", repo.ID)
|
||||||
}
|
}
|
||||||
return params.Repository{}, errors.Wrap(err, "starting repo pool manager")
|
return params.Repository{}, fmt.Errorf("error starting repo pool manager: %w", err)
|
||||||
}
|
}
|
||||||
return repo, nil
|
return repo, nil
|
||||||
}
|
}
|
||||||
|
|
@ -100,7 +99,7 @@ func (r *Runner) ListRepositories(ctx context.Context, filter params.RepositoryF
|
||||||
|
|
||||||
repos, err := r.store.ListRepositories(ctx, filter)
|
repos, err := r.store.ListRepositories(ctx, filter)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "listing repositories")
|
return nil, fmt.Errorf("error listing repositories: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var allRepos []params.Repository
|
var allRepos []params.Repository
|
||||||
|
|
@ -126,7 +125,7 @@ func (r *Runner) GetRepositoryByID(ctx context.Context, repoID string) (params.R
|
||||||
|
|
||||||
repo, err := r.store.GetRepositoryByID(ctx, repoID)
|
repo, err := r.store.GetRepositoryByID(ctx, repoID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return params.Repository{}, errors.Wrap(err, "fetching repository")
|
return params.Repository{}, fmt.Errorf("error fetching repository: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
poolMgr, err := r.poolManagerCtrl.GetRepoPoolManager(repo)
|
poolMgr, err := r.poolManagerCtrl.GetRepoPoolManager(repo)
|
||||||
|
|
@ -145,17 +144,17 @@ func (r *Runner) DeleteRepository(ctx context.Context, repoID string, keepWebhoo
|
||||||
|
|
||||||
repo, err := r.store.GetRepositoryByID(ctx, repoID)
|
repo, err := r.store.GetRepositoryByID(ctx, repoID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "fetching repo")
|
return fmt.Errorf("error fetching repo: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
entity, err := repo.GetEntity()
|
entity, err := repo.GetEntity()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "getting entity")
|
return fmt.Errorf("error getting entity: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
pools, err := r.store.ListEntityPools(ctx, entity)
|
pools, err := r.store.ListEntityPools(ctx, entity)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "fetching repo pools")
|
return fmt.Errorf("error fetching repo pools: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(pools) > 0 {
|
if len(pools) > 0 {
|
||||||
|
|
@ -169,7 +168,7 @@ func (r *Runner) DeleteRepository(ctx context.Context, repoID string, keepWebhoo
|
||||||
|
|
||||||
scaleSets, err := r.store.ListEntityScaleSets(ctx, entity)
|
scaleSets, err := r.store.ListEntityScaleSets(ctx, entity)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "fetching repo scale sets")
|
return fmt.Errorf("error fetching repo scale sets: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(scaleSets) > 0 {
|
if len(scaleSets) > 0 {
|
||||||
|
|
@ -179,7 +178,7 @@ func (r *Runner) DeleteRepository(ctx context.Context, repoID string, keepWebhoo
|
||||||
if !keepWebhook && r.config.Default.EnableWebhookManagement {
|
if !keepWebhook && r.config.Default.EnableWebhookManagement {
|
||||||
poolMgr, err := r.poolManagerCtrl.GetRepoPoolManager(repo)
|
poolMgr, err := r.poolManagerCtrl.GetRepoPoolManager(repo)
|
||||||
if err != nil {
|
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 {
|
if err := poolMgr.UninstallWebhook(ctx); err != nil {
|
||||||
|
|
@ -192,11 +191,11 @@ func (r *Runner) DeleteRepository(ctx context.Context, repoID string, keepWebhoo
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := r.poolManagerCtrl.DeleteRepoPoolManager(repo); err != nil {
|
if err := r.poolManagerCtrl.DeleteRepoPoolManager(repo); err != nil {
|
||||||
return errors.Wrap(err, "deleting repo pool manager")
|
return fmt.Errorf("error deleting repo pool manager: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := r.store.DeleteRepository(ctx, repoID); err != nil {
|
if err := r.store.DeleteRepository(ctx, repoID); err != nil {
|
||||||
return errors.Wrap(err, "removing repository")
|
return fmt.Errorf("error removing repository: %w", err)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -218,12 +217,12 @@ func (r *Runner) UpdateRepository(ctx context.Context, repoID string, param para
|
||||||
slog.InfoContext(ctx, "updating repository", "repo_id", repoID, "param", param)
|
slog.InfoContext(ctx, "updating repository", "repo_id", repoID, "param", param)
|
||||||
repo, err := r.store.UpdateRepository(ctx, repoID, param)
|
repo, err := r.store.UpdateRepository(ctx, repoID, param)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return params.Repository{}, errors.Wrap(err, "updating repo")
|
return params.Repository{}, fmt.Errorf("error updating repo: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
poolMgr, err := r.poolManagerCtrl.GetRepoPoolManager(repo)
|
poolMgr, err := r.poolManagerCtrl.GetRepoPoolManager(repo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return params.Repository{}, errors.Wrap(err, "getting pool manager")
|
return params.Repository{}, fmt.Errorf("error getting pool manager: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
repo.PoolManagerStatus = poolMgr.Status()
|
repo.PoolManagerStatus = poolMgr.Status()
|
||||||
|
|
@ -237,7 +236,7 @@ func (r *Runner) CreateRepoPool(ctx context.Context, repoID string, param params
|
||||||
|
|
||||||
createPoolParams, err := r.appendTagsToCreatePoolParams(param)
|
createPoolParams, err := r.appendTagsToCreatePoolParams(param)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return params.Pool{}, errors.Wrap(err, "appending tags to create pool params")
|
return params.Pool{}, fmt.Errorf("error appending tags to create pool params: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if createPoolParams.RunnerBootstrapTimeout == 0 {
|
if createPoolParams.RunnerBootstrapTimeout == 0 {
|
||||||
|
|
@ -251,7 +250,7 @@ func (r *Runner) CreateRepoPool(ctx context.Context, repoID string, param params
|
||||||
|
|
||||||
pool, err := r.store.CreateEntityPool(ctx, entity, createPoolParams)
|
pool, err := r.store.CreateEntityPool(ctx, entity, createPoolParams)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return params.Pool{}, errors.Wrap(err, "creating pool")
|
return params.Pool{}, fmt.Errorf("error creating pool: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return pool, nil
|
return pool, nil
|
||||||
|
|
@ -269,7 +268,7 @@ func (r *Runner) GetRepoPoolByID(ctx context.Context, repoID, poolID string) (pa
|
||||||
|
|
||||||
pool, err := r.store.GetEntityPool(ctx, entity, poolID)
|
pool, err := r.store.GetEntityPool(ctx, entity, poolID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return params.Pool{}, errors.Wrap(err, "fetching pool")
|
return params.Pool{}, fmt.Errorf("error fetching pool: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return pool, nil
|
return pool, nil
|
||||||
|
|
@ -286,7 +285,7 @@ func (r *Runner) DeleteRepoPool(ctx context.Context, repoID, poolID string) erro
|
||||||
}
|
}
|
||||||
pool, err := r.store.GetEntityPool(ctx, entity, poolID)
|
pool, err := r.store.GetEntityPool(ctx, entity, poolID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "fetching pool")
|
return fmt.Errorf("error fetching pool: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// nolint:golangci-lint,godox
|
// nolint:golangci-lint,godox
|
||||||
|
|
@ -300,7 +299,7 @@ func (r *Runner) DeleteRepoPool(ctx context.Context, repoID, poolID string) erro
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := r.store.DeleteEntityPool(ctx, entity, poolID); err != nil {
|
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
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -315,7 +314,7 @@ func (r *Runner) ListRepoPools(ctx context.Context, repoID string) ([]params.Poo
|
||||||
}
|
}
|
||||||
pools, err := r.store.ListEntityPools(ctx, entity)
|
pools, err := r.store.ListEntityPools(ctx, entity)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "fetching pools")
|
return nil, fmt.Errorf("error fetching pools: %w", err)
|
||||||
}
|
}
|
||||||
return pools, nil
|
return pools, nil
|
||||||
}
|
}
|
||||||
|
|
@ -327,7 +326,7 @@ func (r *Runner) ListPoolInstances(ctx context.Context, poolID string) ([]params
|
||||||
|
|
||||||
instances, err := r.store.ListPoolInstances(ctx, poolID)
|
instances, err := r.store.ListPoolInstances(ctx, poolID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return []params.Instance{}, errors.Wrap(err, "fetching instances")
|
return []params.Instance{}, fmt.Errorf("error fetching instances: %w", err)
|
||||||
}
|
}
|
||||||
return instances, nil
|
return instances, nil
|
||||||
}
|
}
|
||||||
|
|
@ -343,7 +342,7 @@ func (r *Runner) UpdateRepoPool(ctx context.Context, repoID, poolID string, para
|
||||||
}
|
}
|
||||||
pool, err := r.store.GetEntityPool(ctx, entity, poolID)
|
pool, err := r.store.GetEntityPool(ctx, entity, poolID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return params.Pool{}, errors.Wrap(err, "fetching pool")
|
return params.Pool{}, fmt.Errorf("error fetching pool: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
maxRunners := pool.MaxRunners
|
maxRunners := pool.MaxRunners
|
||||||
|
|
@ -362,7 +361,7 @@ func (r *Runner) UpdateRepoPool(ctx context.Context, repoID, poolID string, para
|
||||||
|
|
||||||
newPool, err := r.store.UpdateEntityPool(ctx, entity, poolID, param)
|
newPool, err := r.store.UpdateEntityPool(ctx, entity, poolID, param)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return params.Pool{}, errors.Wrap(err, "updating pool")
|
return params.Pool{}, fmt.Errorf("error updating pool: %w", err)
|
||||||
}
|
}
|
||||||
return newPool, nil
|
return newPool, nil
|
||||||
}
|
}
|
||||||
|
|
@ -377,7 +376,7 @@ func (r *Runner) ListRepoInstances(ctx context.Context, repoID string) ([]params
|
||||||
}
|
}
|
||||||
instances, err := r.store.ListEntityInstances(ctx, entity)
|
instances, err := r.store.ListEntityInstances(ctx, entity)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return []params.Instance{}, errors.Wrap(err, "fetching instances")
|
return []params.Instance{}, fmt.Errorf("error , errfetching instances: %w", err)
|
||||||
}
|
}
|
||||||
return instances, nil
|
return instances, nil
|
||||||
}
|
}
|
||||||
|
|
@ -388,12 +387,12 @@ func (r *Runner) findRepoPoolManager(owner, name, endpointName string) (common.P
|
||||||
|
|
||||||
repo, err := r.store.GetRepository(r.ctx, owner, name, endpointName)
|
repo, err := r.store.GetRepository(r.ctx, owner, name, endpointName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "fetching repo")
|
return nil, fmt.Errorf("error fetching repo: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
poolManager, err := r.poolManagerCtrl.GetRepoPoolManager(repo)
|
poolManager, err := r.poolManagerCtrl.GetRepoPoolManager(repo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "fetching pool manager for repo")
|
return nil, fmt.Errorf("error fetching pool manager for repo: %w", err)
|
||||||
}
|
}
|
||||||
return poolManager, nil
|
return poolManager, nil
|
||||||
}
|
}
|
||||||
|
|
@ -405,17 +404,17 @@ func (r *Runner) InstallRepoWebhook(ctx context.Context, repoID string, param pa
|
||||||
|
|
||||||
repo, err := r.store.GetRepositoryByID(ctx, repoID)
|
repo, err := r.store.GetRepositoryByID(ctx, repoID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return params.HookInfo{}, errors.Wrap(err, "fetching repo")
|
return params.HookInfo{}, fmt.Errorf("error fetching repo: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
poolManager, err := r.poolManagerCtrl.GetRepoPoolManager(repo)
|
poolManager, err := r.poolManagerCtrl.GetRepoPoolManager(repo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return params.HookInfo{}, errors.Wrap(err, "fetching pool manager for repo")
|
return params.HookInfo{}, fmt.Errorf("error fetching pool manager for repo: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
info, err := poolManager.InstallWebhook(ctx, param)
|
info, err := poolManager.InstallWebhook(ctx, param)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return params.HookInfo{}, errors.Wrap(err, "installing webhook")
|
return params.HookInfo{}, fmt.Errorf("error installing webhook: %w", err)
|
||||||
}
|
}
|
||||||
return info, nil
|
return info, nil
|
||||||
}
|
}
|
||||||
|
|
@ -427,16 +426,16 @@ func (r *Runner) UninstallRepoWebhook(ctx context.Context, repoID string) error
|
||||||
|
|
||||||
repo, err := r.store.GetRepositoryByID(ctx, repoID)
|
repo, err := r.store.GetRepositoryByID(ctx, repoID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "fetching repo")
|
return fmt.Errorf("error fetching repo: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
poolManager, err := r.poolManagerCtrl.GetRepoPoolManager(repo)
|
poolManager, err := r.poolManagerCtrl.GetRepoPoolManager(repo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "fetching pool manager for repo")
|
return fmt.Errorf("error fetching pool manager for repo: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := poolManager.UninstallWebhook(ctx); err != nil {
|
if err := poolManager.UninstallWebhook(ctx); err != nil {
|
||||||
return errors.Wrap(err, "uninstalling webhook")
|
return fmt.Errorf("error uninstalling webhook: %w", err)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -448,17 +447,17 @@ func (r *Runner) GetRepoWebhookInfo(ctx context.Context, repoID string) (params.
|
||||||
|
|
||||||
repo, err := r.store.GetRepositoryByID(ctx, repoID)
|
repo, err := r.store.GetRepositoryByID(ctx, repoID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return params.HookInfo{}, errors.Wrap(err, "fetching repo")
|
return params.HookInfo{}, fmt.Errorf("error fetching repo: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
poolManager, err := r.poolManagerCtrl.GetRepoPoolManager(repo)
|
poolManager, err := r.poolManagerCtrl.GetRepoPoolManager(repo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return params.HookInfo{}, errors.Wrap(err, "fetching pool manager for repo")
|
return params.HookInfo{}, fmt.Errorf("error fetching pool manager for repo: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
info, err := poolManager.GetWebhookInfo(ctx)
|
info, err := poolManager.GetWebhookInfo(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return params.HookInfo{}, errors.Wrap(err, "getting webhook info")
|
return params.HookInfo{}, fmt.Errorf("error getting webhook info: %w", err)
|
||||||
}
|
}
|
||||||
return info, nil
|
return info, nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,10 +16,10 @@ package runner
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
"github.com/stretchr/testify/mock"
|
"github.com/stretchr/testify/mock"
|
||||||
"github.com/stretchr/testify/suite"
|
"github.com/stretchr/testify/suite"
|
||||||
|
|
||||||
|
|
@ -240,7 +240,7 @@ func (s *RepoTestSuite) TestCreateRepositoryPoolMgrFailed() {
|
||||||
|
|
||||||
s.Fixtures.PoolMgrMock.AssertExpectations(s.T())
|
s.Fixtures.PoolMgrMock.AssertExpectations(s.T())
|
||||||
s.Fixtures.PoolMgrCtrlMock.AssertExpectations(s.T())
|
s.Fixtures.PoolMgrCtrlMock.AssertExpectations(s.T())
|
||||||
s.Require().Equal(fmt.Sprintf("creating repo pool manager: %s", s.Fixtures.ErrMock.Error()), err.Error())
|
s.Require().Equal(fmt.Sprintf("error creating repo pool manager: %s", s.Fixtures.ErrMock.Error()), err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *RepoTestSuite) TestCreateRepositoryStartPoolMgrFailed() {
|
func (s *RepoTestSuite) TestCreateRepositoryStartPoolMgrFailed() {
|
||||||
|
|
@ -252,7 +252,7 @@ func (s *RepoTestSuite) TestCreateRepositoryStartPoolMgrFailed() {
|
||||||
|
|
||||||
s.Fixtures.PoolMgrMock.AssertExpectations(s.T())
|
s.Fixtures.PoolMgrMock.AssertExpectations(s.T())
|
||||||
s.Fixtures.PoolMgrCtrlMock.AssertExpectations(s.T())
|
s.Fixtures.PoolMgrCtrlMock.AssertExpectations(s.T())
|
||||||
s.Require().Equal(fmt.Sprintf("starting repo pool manager: %s", s.Fixtures.ErrMock.Error()), err.Error())
|
s.Require().Equal(fmt.Sprintf("error starting repo pool manager: %s", s.Fixtures.ErrMock.Error()), err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *RepoTestSuite) TestListRepositories() {
|
func (s *RepoTestSuite) TestListRepositories() {
|
||||||
|
|
@ -361,7 +361,7 @@ func (s *RepoTestSuite) TestDeleteRepository() {
|
||||||
s.Require().Nil(err)
|
s.Require().Nil(err)
|
||||||
|
|
||||||
_, err = s.Fixtures.Store.GetRepositoryByID(s.Fixtures.AdminContext, s.Fixtures.StoreRepos["test-repo-1"].ID)
|
_, err = s.Fixtures.Store.GetRepositoryByID(s.Fixtures.AdminContext, s.Fixtures.StoreRepos["test-repo-1"].ID)
|
||||||
s.Require().Equal("fetching repo: not found", err.Error())
|
s.Require().Equal("error fetching repo: not found", err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *RepoTestSuite) TestDeleteRepositoryErrUnauthorized() {
|
func (s *RepoTestSuite) TestDeleteRepositoryErrUnauthorized() {
|
||||||
|
|
@ -391,7 +391,7 @@ func (s *RepoTestSuite) TestDeleteRepositoryPoolMgrFailed() {
|
||||||
err := s.Runner.DeleteRepository(s.Fixtures.AdminContext, s.Fixtures.StoreRepos["test-repo-1"].ID, true)
|
err := s.Runner.DeleteRepository(s.Fixtures.AdminContext, s.Fixtures.StoreRepos["test-repo-1"].ID, true)
|
||||||
|
|
||||||
s.Fixtures.PoolMgrCtrlMock.AssertExpectations(s.T())
|
s.Fixtures.PoolMgrCtrlMock.AssertExpectations(s.T())
|
||||||
s.Require().Equal(fmt.Sprintf("deleting repo pool manager: %s", s.Fixtures.ErrMock.Error()), err.Error())
|
s.Require().Equal(fmt.Sprintf("error deleting repo pool manager: %s", s.Fixtures.ErrMock.Error()), err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *RepoTestSuite) TestUpdateRepository() {
|
func (s *RepoTestSuite) TestUpdateRepository() {
|
||||||
|
|
@ -445,7 +445,7 @@ func (s *RepoTestSuite) TestUpdateRepositoryPoolMgrFailed() {
|
||||||
_, err := s.Runner.UpdateRepository(s.Fixtures.AdminContext, s.Fixtures.StoreRepos["test-repo-1"].ID, s.Fixtures.UpdateRepoParams)
|
_, err := s.Runner.UpdateRepository(s.Fixtures.AdminContext, s.Fixtures.StoreRepos["test-repo-1"].ID, s.Fixtures.UpdateRepoParams)
|
||||||
|
|
||||||
s.Fixtures.PoolMgrCtrlMock.AssertExpectations(s.T())
|
s.Fixtures.PoolMgrCtrlMock.AssertExpectations(s.T())
|
||||||
s.Require().Equal(fmt.Sprintf("getting pool manager: %s", s.Fixtures.ErrMock.Error()), err.Error())
|
s.Require().Equal(fmt.Sprintf("error getting pool manager: %s", s.Fixtures.ErrMock.Error()), err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *RepoTestSuite) TestUpdateRepositoryCreateRepoPoolMgrFailed() {
|
func (s *RepoTestSuite) TestUpdateRepositoryCreateRepoPoolMgrFailed() {
|
||||||
|
|
@ -454,7 +454,7 @@ func (s *RepoTestSuite) TestUpdateRepositoryCreateRepoPoolMgrFailed() {
|
||||||
_, err := s.Runner.UpdateRepository(s.Fixtures.AdminContext, s.Fixtures.StoreRepos["test-repo-1"].ID, s.Fixtures.UpdateRepoParams)
|
_, err := s.Runner.UpdateRepository(s.Fixtures.AdminContext, s.Fixtures.StoreRepos["test-repo-1"].ID, s.Fixtures.UpdateRepoParams)
|
||||||
|
|
||||||
s.Fixtures.PoolMgrCtrlMock.AssertExpectations(s.T())
|
s.Fixtures.PoolMgrCtrlMock.AssertExpectations(s.T())
|
||||||
s.Require().Equal(fmt.Sprintf("getting pool manager: %s", s.Fixtures.ErrMock.Error()), err.Error())
|
s.Require().Equal(fmt.Sprintf("error getting pool manager: %s", s.Fixtures.ErrMock.Error()), err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *RepoTestSuite) TestCreateRepoPool() {
|
func (s *RepoTestSuite) TestCreateRepoPool() {
|
||||||
|
|
@ -527,7 +527,7 @@ func (s *RepoTestSuite) TestDeleteRepoPool() {
|
||||||
s.Require().Nil(err)
|
s.Require().Nil(err)
|
||||||
|
|
||||||
_, err = s.Fixtures.Store.GetEntityPool(s.Fixtures.AdminContext, entity, pool.ID)
|
_, 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 *RepoTestSuite) TestDeleteRepoPoolErrUnauthorized() {
|
func (s *RepoTestSuite) TestDeleteRepoPoolErrUnauthorized() {
|
||||||
|
|
|
||||||
158
runner/runner.go
158
runner/runner.go
|
|
@ -21,6 +21,7 @@ import (
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"hash"
|
"hash"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
|
|
@ -30,9 +31,6 @@ import (
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/juju/clock"
|
|
||||||
"github.com/juju/retry"
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
"golang.org/x/sync/errgroup"
|
"golang.org/x/sync/errgroup"
|
||||||
|
|
||||||
runnerErrors "github.com/cloudbase/garm-provider-common/errors"
|
runnerErrors "github.com/cloudbase/garm-provider-common/errors"
|
||||||
|
|
@ -52,12 +50,12 @@ import (
|
||||||
func NewRunner(ctx context.Context, cfg config.Config, db dbCommon.Store) (*Runner, error) {
|
func NewRunner(ctx context.Context, cfg config.Config, db dbCommon.Store) (*Runner, error) {
|
||||||
ctrlID, err := db.ControllerInfo()
|
ctrlID, err := db.ControllerInfo()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "fetching controller info")
|
return nil, fmt.Errorf("error fetching controller info: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
providers, err := providers.LoadProvidersFromConfig(ctx, cfg, ctrlID.ControllerID.String())
|
providers, err := providers.LoadProvidersFromConfig(ctx, cfg, ctrlID.ControllerID.String())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "loading providers")
|
return nil, fmt.Errorf("error loading providers: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
creds := map[string]config.Github{}
|
creds := map[string]config.Github{}
|
||||||
|
|
@ -82,7 +80,7 @@ func NewRunner(ctx context.Context, cfg config.Config, db dbCommon.Store) (*Runn
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := runner.loadReposOrgsAndEnterprises(); err != nil {
|
if err := runner.loadReposOrgsAndEnterprises(); err != nil {
|
||||||
return nil, errors.Wrap(err, "loading pool managers")
|
return nil, fmt.Errorf("error loading pool managers: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return runner, nil
|
return runner, nil
|
||||||
|
|
@ -105,16 +103,16 @@ func (p *poolManagerCtrl) CreateRepoPoolManager(ctx context.Context, repo params
|
||||||
|
|
||||||
entity, err := repo.GetEntity()
|
entity, err := repo.GetEntity()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "getting entity")
|
return nil, fmt.Errorf("error getting entity: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
instanceTokenGetter, err := auth.NewInstanceTokenGetter(p.config.JWTAuth.Secret)
|
instanceTokenGetter, err := auth.NewInstanceTokenGetter(p.config.JWTAuth.Secret)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "creating instance token getter")
|
return nil, fmt.Errorf("error creating instance token getter: %w", err)
|
||||||
}
|
}
|
||||||
poolManager, err := pool.NewEntityPoolManager(ctx, entity, instanceTokenGetter, providers, store)
|
poolManager, err := pool.NewEntityPoolManager(ctx, entity, instanceTokenGetter, providers, store)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "creating repo pool manager")
|
return nil, fmt.Errorf("error creating repo pool manager: %w", err)
|
||||||
}
|
}
|
||||||
p.repositories[repo.ID] = poolManager
|
p.repositories[repo.ID] = poolManager
|
||||||
return poolManager, nil
|
return poolManager, nil
|
||||||
|
|
@ -124,7 +122,7 @@ func (p *poolManagerCtrl) GetRepoPoolManager(repo params.Repository) (common.Poo
|
||||||
if repoPoolMgr, ok := p.repositories[repo.ID]; ok {
|
if repoPoolMgr, ok := p.repositories[repo.ID]; ok {
|
||||||
return repoPoolMgr, nil
|
return repoPoolMgr, nil
|
||||||
}
|
}
|
||||||
return nil, errors.Wrapf(runnerErrors.ErrNotFound, "repository %s/%s pool manager not loaded", repo.Owner, repo.Name)
|
return nil, fmt.Errorf("repository %s/%s pool manager not loaded: %w", repo.Owner, repo.Name, runnerErrors.ErrNotFound)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *poolManagerCtrl) DeleteRepoPoolManager(repo params.Repository) error {
|
func (p *poolManagerCtrl) DeleteRepoPoolManager(repo params.Repository) error {
|
||||||
|
|
@ -134,7 +132,7 @@ func (p *poolManagerCtrl) DeleteRepoPoolManager(repo params.Repository) error {
|
||||||
poolMgr, ok := p.repositories[repo.ID]
|
poolMgr, ok := p.repositories[repo.ID]
|
||||||
if ok {
|
if ok {
|
||||||
if err := poolMgr.Stop(); err != nil {
|
if err := poolMgr.Stop(); err != nil {
|
||||||
return errors.Wrap(err, "stopping repo pool manager")
|
return fmt.Errorf("error stopping repo pool manager: %w", err)
|
||||||
}
|
}
|
||||||
delete(p.repositories, repo.ID)
|
delete(p.repositories, repo.ID)
|
||||||
}
|
}
|
||||||
|
|
@ -151,16 +149,16 @@ func (p *poolManagerCtrl) CreateOrgPoolManager(ctx context.Context, org params.O
|
||||||
|
|
||||||
entity, err := org.GetEntity()
|
entity, err := org.GetEntity()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "getting entity")
|
return nil, fmt.Errorf("error getting entity: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
instanceTokenGetter, err := auth.NewInstanceTokenGetter(p.config.JWTAuth.Secret)
|
instanceTokenGetter, err := auth.NewInstanceTokenGetter(p.config.JWTAuth.Secret)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "creating instance token getter")
|
return nil, fmt.Errorf("error creating instance token getter: %w", err)
|
||||||
}
|
}
|
||||||
poolManager, err := pool.NewEntityPoolManager(ctx, entity, instanceTokenGetter, providers, store)
|
poolManager, err := pool.NewEntityPoolManager(ctx, entity, instanceTokenGetter, providers, store)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "creating org pool manager")
|
return nil, fmt.Errorf("error creating org pool manager: %w", err)
|
||||||
}
|
}
|
||||||
p.organizations[org.ID] = poolManager
|
p.organizations[org.ID] = poolManager
|
||||||
return poolManager, nil
|
return poolManager, nil
|
||||||
|
|
@ -170,7 +168,7 @@ func (p *poolManagerCtrl) GetOrgPoolManager(org params.Organization) (common.Poo
|
||||||
if orgPoolMgr, ok := p.organizations[org.ID]; ok {
|
if orgPoolMgr, ok := p.organizations[org.ID]; ok {
|
||||||
return orgPoolMgr, nil
|
return orgPoolMgr, nil
|
||||||
}
|
}
|
||||||
return nil, errors.Wrapf(runnerErrors.ErrNotFound, "organization %s pool manager not loaded", org.Name)
|
return nil, fmt.Errorf("organization %s pool manager not loaded: %w", org.Name, runnerErrors.ErrNotFound)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *poolManagerCtrl) DeleteOrgPoolManager(org params.Organization) error {
|
func (p *poolManagerCtrl) DeleteOrgPoolManager(org params.Organization) error {
|
||||||
|
|
@ -180,7 +178,7 @@ func (p *poolManagerCtrl) DeleteOrgPoolManager(org params.Organization) error {
|
||||||
poolMgr, ok := p.organizations[org.ID]
|
poolMgr, ok := p.organizations[org.ID]
|
||||||
if ok {
|
if ok {
|
||||||
if err := poolMgr.Stop(); err != nil {
|
if err := poolMgr.Stop(); err != nil {
|
||||||
return errors.Wrap(err, "stopping org pool manager")
|
return fmt.Errorf("error stopping org pool manager: %w", err)
|
||||||
}
|
}
|
||||||
delete(p.organizations, org.ID)
|
delete(p.organizations, org.ID)
|
||||||
}
|
}
|
||||||
|
|
@ -197,16 +195,16 @@ func (p *poolManagerCtrl) CreateEnterprisePoolManager(ctx context.Context, enter
|
||||||
|
|
||||||
entity, err := enterprise.GetEntity()
|
entity, err := enterprise.GetEntity()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "getting entity")
|
return nil, fmt.Errorf("error getting entity: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
instanceTokenGetter, err := auth.NewInstanceTokenGetter(p.config.JWTAuth.Secret)
|
instanceTokenGetter, err := auth.NewInstanceTokenGetter(p.config.JWTAuth.Secret)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "creating instance token getter")
|
return nil, fmt.Errorf("error creating instance token getter: %w", err)
|
||||||
}
|
}
|
||||||
poolManager, err := pool.NewEntityPoolManager(ctx, entity, instanceTokenGetter, providers, store)
|
poolManager, err := pool.NewEntityPoolManager(ctx, entity, instanceTokenGetter, providers, store)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "creating enterprise pool manager")
|
return nil, fmt.Errorf("error creating enterprise pool manager: %w", err)
|
||||||
}
|
}
|
||||||
p.enterprises[enterprise.ID] = poolManager
|
p.enterprises[enterprise.ID] = poolManager
|
||||||
return poolManager, nil
|
return poolManager, nil
|
||||||
|
|
@ -216,7 +214,7 @@ func (p *poolManagerCtrl) GetEnterprisePoolManager(enterprise params.Enterprise)
|
||||||
if enterprisePoolMgr, ok := p.enterprises[enterprise.ID]; ok {
|
if enterprisePoolMgr, ok := p.enterprises[enterprise.ID]; ok {
|
||||||
return enterprisePoolMgr, nil
|
return enterprisePoolMgr, nil
|
||||||
}
|
}
|
||||||
return nil, errors.Wrapf(runnerErrors.ErrNotFound, "enterprise %s pool manager not loaded", enterprise.Name)
|
return nil, fmt.Errorf("enterprise %s pool manager not loaded: %w", enterprise.Name, runnerErrors.ErrNotFound)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *poolManagerCtrl) DeleteEnterprisePoolManager(enterprise params.Enterprise) error {
|
func (p *poolManagerCtrl) DeleteEnterprisePoolManager(enterprise params.Enterprise) error {
|
||||||
|
|
@ -226,7 +224,7 @@ func (p *poolManagerCtrl) DeleteEnterprisePoolManager(enterprise params.Enterpri
|
||||||
poolMgr, ok := p.enterprises[enterprise.ID]
|
poolMgr, ok := p.enterprises[enterprise.ID]
|
||||||
if ok {
|
if ok {
|
||||||
if err := poolMgr.Stop(); err != nil {
|
if err := poolMgr.Stop(); err != nil {
|
||||||
return errors.Wrap(err, "stopping enterprise pool manager")
|
return fmt.Errorf("error stopping enterprise pool manager: %w", err)
|
||||||
}
|
}
|
||||||
delete(p.enterprises, enterprise.ID)
|
delete(p.enterprises, enterprise.ID)
|
||||||
}
|
}
|
||||||
|
|
@ -256,12 +254,12 @@ func (r *Runner) UpdateController(ctx context.Context, param params.UpdateContro
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := param.Validate(); err != nil {
|
if err := param.Validate(); err != nil {
|
||||||
return params.ControllerInfo{}, errors.Wrap(err, "validating controller update params")
|
return params.ControllerInfo{}, fmt.Errorf("error validating controller update params: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
info, err := r.store.UpdateController(param)
|
info, err := r.store.UpdateController(param)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return params.ControllerInfo{}, errors.Wrap(err, "updating controller info")
|
return params.ControllerInfo{}, fmt.Errorf("error updating controller info: %w", err)
|
||||||
}
|
}
|
||||||
return info, nil
|
return info, nil
|
||||||
}
|
}
|
||||||
|
|
@ -281,26 +279,26 @@ func (r *Runner) GetControllerInfo(ctx context.Context) (params.ControllerInfo,
|
||||||
// As a side note, Windows requires a reboot for the hostname change to take effect,
|
// As a side note, Windows requires a reboot for the hostname change to take effect,
|
||||||
// so if we'll ever support Windows as a target system, the hostname can be cached.
|
// so if we'll ever support Windows as a target system, the hostname can be cached.
|
||||||
var hostname string
|
var hostname string
|
||||||
err := retry.Call(retry.CallArgs{
|
var err error
|
||||||
Func: func() error {
|
for range 10 {
|
||||||
var err error
|
hostname, err = os.Hostname()
|
||||||
hostname, err = os.Hostname()
|
if err != nil {
|
||||||
if err != nil {
|
select {
|
||||||
return errors.Wrap(err, "fetching hostname")
|
case <-time.After(10 * time.Millisecond):
|
||||||
|
continue
|
||||||
|
case <-ctx.Done():
|
||||||
}
|
}
|
||||||
return nil
|
return params.ControllerInfo{}, fmt.Errorf("error fetching hostname: %w", err)
|
||||||
},
|
}
|
||||||
Attempts: 10,
|
break
|
||||||
Delay: 100 * time.Millisecond,
|
}
|
||||||
Clock: clock.WallClock,
|
|
||||||
})
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return params.ControllerInfo{}, errors.Wrap(err, "fetching hostname")
|
return params.ControllerInfo{}, fmt.Errorf("error fetching hostname: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
info, err := r.store.ControllerInfo()
|
info, err := r.store.ControllerInfo()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return params.ControllerInfo{}, errors.Wrap(err, "fetching controller info")
|
return params.ControllerInfo{}, fmt.Errorf("error fetching controller info: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is temporary. Right now, GARM is a single-instance deployment. When we add the
|
// This is temporary. Right now, GARM is a single-instance deployment. When we add the
|
||||||
|
|
@ -329,17 +327,17 @@ func (r *Runner) loadReposOrgsAndEnterprises() error {
|
||||||
|
|
||||||
repos, err := r.store.ListRepositories(r.ctx, params.RepositoryFilter{})
|
repos, err := r.store.ListRepositories(r.ctx, params.RepositoryFilter{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "fetching repositories")
|
return fmt.Errorf("error fetching repositories: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
orgs, err := r.store.ListOrganizations(r.ctx, params.OrganizationFilter{})
|
orgs, err := r.store.ListOrganizations(r.ctx, params.OrganizationFilter{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "fetching organizations")
|
return fmt.Errorf("error fetching organizations: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
enterprises, err := r.store.ListEnterprises(r.ctx, params.EnterpriseFilter{})
|
enterprises, err := r.store.ListEnterprises(r.ctx, params.EnterpriseFilter{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "fetching enterprises")
|
return fmt.Errorf("error fetching enterprises: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
g, _ := errgroup.WithContext(r.ctx)
|
g, _ := errgroup.WithContext(r.ctx)
|
||||||
|
|
@ -384,17 +382,17 @@ func (r *Runner) Start() error {
|
||||||
|
|
||||||
repositories, err := r.poolManagerCtrl.GetRepoPoolManagers()
|
repositories, err := r.poolManagerCtrl.GetRepoPoolManagers()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "fetch repo pool managers")
|
return fmt.Errorf("error fetch repo pool managers: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
organizations, err := r.poolManagerCtrl.GetOrgPoolManagers()
|
organizations, err := r.poolManagerCtrl.GetOrgPoolManagers()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "fetch org pool managers")
|
return fmt.Errorf("error fetch org pool managers: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
enterprises, err := r.poolManagerCtrl.GetEnterprisePoolManagers()
|
enterprises, err := r.poolManagerCtrl.GetEnterprisePoolManagers()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "fetch enterprise pool managers")
|
return fmt.Errorf("error fetch enterprise pool managers: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
g, _ := errgroup.WithContext(r.ctx)
|
g, _ := errgroup.WithContext(r.ctx)
|
||||||
|
|
@ -450,17 +448,17 @@ func (r *Runner) Stop() error {
|
||||||
|
|
||||||
repos, err := r.poolManagerCtrl.GetRepoPoolManagers()
|
repos, err := r.poolManagerCtrl.GetRepoPoolManagers()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "fetch repo pool managers")
|
return fmt.Errorf("error fetching repo pool managers: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
orgs, err := r.poolManagerCtrl.GetOrgPoolManagers()
|
orgs, err := r.poolManagerCtrl.GetOrgPoolManagers()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "fetch org pool managers")
|
return fmt.Errorf("error fetching org pool managers: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
enterprises, err := r.poolManagerCtrl.GetEnterprisePoolManagers()
|
enterprises, err := r.poolManagerCtrl.GetEnterprisePoolManagers()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "fetch enterprise pool managers")
|
return fmt.Errorf("error fetching enterprise pool managers: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
g, _ := errgroup.WithContext(r.ctx)
|
g, _ := errgroup.WithContext(r.ctx)
|
||||||
|
|
@ -512,17 +510,17 @@ func (r *Runner) Wait() error {
|
||||||
|
|
||||||
repos, err := r.poolManagerCtrl.GetRepoPoolManagers()
|
repos, err := r.poolManagerCtrl.GetRepoPoolManagers()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "fetch repo pool managers")
|
return fmt.Errorf("error fetching repo pool managers: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
orgs, err := r.poolManagerCtrl.GetOrgPoolManagers()
|
orgs, err := r.poolManagerCtrl.GetOrgPoolManagers()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "fetch org pool managers")
|
return fmt.Errorf("error fetching org pool managers: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
enterprises, err := r.poolManagerCtrl.GetEnterprisePoolManagers()
|
enterprises, err := r.poolManagerCtrl.GetEnterprisePoolManagers()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "fetch enterprise pool managers")
|
return fmt.Errorf("error fetching enterprise pool managers: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
for poolID, repo := range repos {
|
for poolID, repo := range repos {
|
||||||
|
|
@ -591,7 +589,7 @@ func (r *Runner) validateHookBody(signature, secret string, body []byte) error {
|
||||||
mac := hmac.New(hashFunc, []byte(secret))
|
mac := hmac.New(hashFunc, []byte(secret))
|
||||||
_, err := mac.Write(body)
|
_, err := mac.Write(body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "failed to compute sha256")
|
return fmt.Errorf("failed to compute sha256: %w", err)
|
||||||
}
|
}
|
||||||
expectedMAC := hex.EncodeToString(mac.Sum(nil))
|
expectedMAC := hex.EncodeToString(mac.Sum(nil))
|
||||||
|
|
||||||
|
|
@ -605,7 +603,7 @@ func (r *Runner) validateHookBody(signature, secret string, body []byte) error {
|
||||||
func (r *Runner) findEndpointForJob(job params.WorkflowJob, forgeType params.EndpointType) (params.ForgeEndpoint, error) {
|
func (r *Runner) findEndpointForJob(job params.WorkflowJob, forgeType params.EndpointType) (params.ForgeEndpoint, error) {
|
||||||
uri, err := url.ParseRequestURI(job.WorkflowJob.HTMLURL)
|
uri, err := url.ParseRequestURI(job.WorkflowJob.HTMLURL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return params.ForgeEndpoint{}, errors.Wrap(err, "parsing job URL")
|
return params.ForgeEndpoint{}, fmt.Errorf("error parsing job URL: %w", err)
|
||||||
}
|
}
|
||||||
baseURI := fmt.Sprintf("%s://%s", uri.Scheme, uri.Host)
|
baseURI := fmt.Sprintf("%s://%s", uri.Scheme, uri.Host)
|
||||||
|
|
||||||
|
|
@ -625,7 +623,7 @@ func (r *Runner) findEndpointForJob(job params.WorkflowJob, forgeType params.End
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return params.ForgeEndpoint{}, errors.Wrap(err, "fetching github endpoints")
|
return params.ForgeEndpoint{}, fmt.Errorf("error fetching github endpoints: %w", err)
|
||||||
}
|
}
|
||||||
for _, ep := range endpoints {
|
for _, ep := range endpoints {
|
||||||
slog.DebugContext(r.ctx, "checking endpoint", "base_uri", baseURI, "endpoint", ep.BaseURL)
|
slog.DebugContext(r.ctx, "checking endpoint", "base_uri", baseURI, "endpoint", ep.BaseURL)
|
||||||
|
|
@ -647,13 +645,13 @@ func (r *Runner) DispatchWorkflowJob(hookTargetType, signature string, forgeType
|
||||||
var job params.WorkflowJob
|
var job params.WorkflowJob
|
||||||
if err := json.Unmarshal(jobData, &job); err != nil {
|
if err := json.Unmarshal(jobData, &job); err != nil {
|
||||||
slog.ErrorContext(r.ctx, "failed to unmarshal job data", "error", err)
|
slog.ErrorContext(r.ctx, "failed to unmarshal job data", "error", err)
|
||||||
return errors.Wrapf(runnerErrors.ErrBadRequest, "invalid job data: %s", err)
|
return fmt.Errorf("invalid job data %s: %w", err, runnerErrors.ErrBadRequest)
|
||||||
}
|
}
|
||||||
|
|
||||||
endpoint, err := r.findEndpointForJob(job, forgeType)
|
endpoint, err := r.findEndpointForJob(job, forgeType)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
slog.ErrorContext(r.ctx, "failed to find endpoint for job", "error", err)
|
slog.ErrorContext(r.ctx, "failed to find endpoint for job", "error", err)
|
||||||
return errors.Wrap(err, "finding endpoint for job")
|
return fmt.Errorf("error finding endpoint for job: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var poolManager common.PoolManager
|
var poolManager common.PoolManager
|
||||||
|
|
@ -687,7 +685,7 @@ func (r *Runner) DispatchWorkflowJob(hookTargetType, signature string, forgeType
|
||||||
slog.ErrorContext(r.ctx, "failed to find pool manager", "error", err, "hook_target_type", hookTargetType)
|
slog.ErrorContext(r.ctx, "failed to find pool manager", "error", err, "hook_target_type", hookTargetType)
|
||||||
// We don't have a repository or organization configured that
|
// We don't have a repository or organization configured that
|
||||||
// can handle this workflow job.
|
// can handle this workflow job.
|
||||||
return errors.Wrap(err, "fetching poolManager")
|
return fmt.Errorf("error fetching poolManager: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// We found a pool. Validate the webhook job. If a secret is configured,
|
// We found a pool. Validate the webhook job. If a secret is configured,
|
||||||
|
|
@ -695,12 +693,12 @@ func (r *Runner) DispatchWorkflowJob(hookTargetType, signature string, forgeType
|
||||||
secret := poolManager.WebhookSecret()
|
secret := poolManager.WebhookSecret()
|
||||||
if err := r.validateHookBody(signature, secret, jobData); err != nil {
|
if err := r.validateHookBody(signature, secret, jobData); err != nil {
|
||||||
slog.ErrorContext(r.ctx, "failed to validate webhook data", "error", err)
|
slog.ErrorContext(r.ctx, "failed to validate webhook data", "error", err)
|
||||||
return errors.Wrap(err, "validating webhook data")
|
return fmt.Errorf("error validating webhook data: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := poolManager.HandleWorkflowJob(job); err != nil {
|
if err := poolManager.HandleWorkflowJob(job); err != nil {
|
||||||
slog.ErrorContext(r.ctx, "failed to handle workflow job", "error", err)
|
slog.ErrorContext(r.ctx, "failed to handle workflow job", "error", err)
|
||||||
return errors.Wrap(err, "handling workflow job")
|
return fmt.Errorf("error handling workflow job: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
@ -735,7 +733,7 @@ func (r *Runner) GetInstance(ctx context.Context, instanceName string) (params.I
|
||||||
|
|
||||||
instance, err := r.store.GetInstanceByName(ctx, instanceName)
|
instance, err := r.store.GetInstanceByName(ctx, instanceName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return params.Instance{}, errors.Wrap(err, "fetching instance")
|
return params.Instance{}, fmt.Errorf("error fetching instance: %w", err)
|
||||||
}
|
}
|
||||||
return instance, nil
|
return instance, nil
|
||||||
}
|
}
|
||||||
|
|
@ -747,7 +745,7 @@ func (r *Runner) ListAllInstances(ctx context.Context) ([]params.Instance, error
|
||||||
|
|
||||||
instances, err := r.store.ListAllInstances(ctx)
|
instances, err := r.store.ListAllInstances(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "fetching instances")
|
return nil, fmt.Errorf("error fetching instances: %w", err)
|
||||||
}
|
}
|
||||||
return instances, nil
|
return instances, nil
|
||||||
}
|
}
|
||||||
|
|
@ -759,7 +757,7 @@ func (r *Runner) AddInstanceStatusMessage(ctx context.Context, param params.Inst
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := r.store.AddInstanceEvent(ctx, instanceName, params.StatusEvent, params.EventInfo, param.Message); err != nil {
|
if err := r.store.AddInstanceEvent(ctx, instanceName, params.StatusEvent, params.EventInfo, param.Message); err != nil {
|
||||||
return errors.Wrap(err, "adding status update")
|
return fmt.Errorf("error adding status update: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
updateParams := params.UpdateInstanceParams{
|
updateParams := params.UpdateInstanceParams{
|
||||||
|
|
@ -771,7 +769,7 @@ func (r *Runner) AddInstanceStatusMessage(ctx context.Context, param params.Inst
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := r.store.UpdateInstance(r.ctx, instanceName, updateParams); err != nil {
|
if _, err := r.store.UpdateInstance(r.ctx, instanceName, updateParams); err != nil {
|
||||||
return errors.Wrap(err, "updating runner agent ID")
|
return fmt.Errorf("error updating runner agent ID: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
@ -799,7 +797,7 @@ func (r *Runner) UpdateSystemInfo(ctx context.Context, param params.UpdateSystem
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := r.store.UpdateInstance(r.ctx, instanceName, updateParams); err != nil {
|
if _, err := r.store.UpdateInstance(r.ctx, instanceName, updateParams); err != nil {
|
||||||
return errors.Wrap(err, "updating runner system info")
|
return fmt.Errorf("error updating runner system info: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
@ -808,7 +806,7 @@ func (r *Runner) UpdateSystemInfo(ctx context.Context, param params.UpdateSystem
|
||||||
func (r *Runner) getPoolManagerFromInstance(ctx context.Context, instance params.Instance) (common.PoolManager, error) {
|
func (r *Runner) getPoolManagerFromInstance(ctx context.Context, instance params.Instance) (common.PoolManager, error) {
|
||||||
pool, err := r.store.GetPoolByID(ctx, instance.PoolID)
|
pool, err := r.store.GetPoolByID(ctx, instance.PoolID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "fetching pool")
|
return nil, fmt.Errorf("error fetching pool: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var poolMgr common.PoolManager
|
var poolMgr common.PoolManager
|
||||||
|
|
@ -817,29 +815,29 @@ func (r *Runner) getPoolManagerFromInstance(ctx context.Context, instance params
|
||||||
case pool.RepoID != "":
|
case pool.RepoID != "":
|
||||||
repo, err := r.store.GetRepositoryByID(ctx, pool.RepoID)
|
repo, err := r.store.GetRepositoryByID(ctx, pool.RepoID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "fetching repo")
|
return nil, fmt.Errorf("error fetching repo: %w", err)
|
||||||
}
|
}
|
||||||
poolMgr, err = r.findRepoPoolManager(repo.Owner, repo.Name, repo.Endpoint.Name)
|
poolMgr, err = r.findRepoPoolManager(repo.Owner, repo.Name, repo.Endpoint.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrapf(err, "fetching pool manager for repo %s", pool.RepoName)
|
return nil, fmt.Errorf("error fetching pool manager for repo %s: %w", pool.RepoName, err)
|
||||||
}
|
}
|
||||||
case pool.OrgID != "":
|
case pool.OrgID != "":
|
||||||
org, err := r.store.GetOrganizationByID(ctx, pool.OrgID)
|
org, err := r.store.GetOrganizationByID(ctx, pool.OrgID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "fetching org")
|
return nil, fmt.Errorf("error fetching org: %w", err)
|
||||||
}
|
}
|
||||||
poolMgr, err = r.findOrgPoolManager(org.Name, org.Endpoint.Name)
|
poolMgr, err = r.findOrgPoolManager(org.Name, org.Endpoint.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrapf(err, "fetching pool manager for org %s", pool.OrgName)
|
return nil, fmt.Errorf("error fetching pool manager for org %s: %w", pool.OrgName, err)
|
||||||
}
|
}
|
||||||
case pool.EnterpriseID != "":
|
case pool.EnterpriseID != "":
|
||||||
enterprise, err := r.store.GetEnterpriseByID(ctx, pool.EnterpriseID)
|
enterprise, err := r.store.GetEnterpriseByID(ctx, pool.EnterpriseID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "fetching enterprise")
|
return nil, fmt.Errorf("error fetching enterprise: %w", err)
|
||||||
}
|
}
|
||||||
poolMgr, err = r.findEnterprisePoolManager(enterprise.Name, enterprise.Endpoint.Name)
|
poolMgr, err = r.findEnterprisePoolManager(enterprise.Name, enterprise.Endpoint.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrapf(err, "fetching pool manager for enterprise %s", pool.EnterpriseName)
|
return nil, fmt.Errorf("error fetching pool manager for enterprise %s: %w", pool.EnterpriseName, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -856,7 +854,7 @@ func (r *Runner) DeleteRunner(ctx context.Context, instanceName string, forceDel
|
||||||
|
|
||||||
instance, err := r.store.GetInstanceByName(ctx, instanceName)
|
instance, err := r.store.GetInstanceByName(ctx, instanceName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "fetching instance")
|
return fmt.Errorf("error fetching instance: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
switch instance.Status {
|
switch instance.Status {
|
||||||
|
|
@ -874,7 +872,7 @@ func (r *Runner) DeleteRunner(ctx context.Context, instanceName string, forceDel
|
||||||
|
|
||||||
ghCli, ssCli, err := r.getGHCliFromInstance(ctx, instance)
|
ghCli, ssCli, err := r.getGHCliFromInstance(ctx, instance)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "fetching github client")
|
return fmt.Errorf("error fetching github client: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if instance.AgentID != 0 {
|
if instance.AgentID != 0 {
|
||||||
|
|
@ -892,12 +890,12 @@ func (r *Runner) DeleteRunner(ctx context.Context, instanceName string, forceDel
|
||||||
if errors.Is(err, runnerErrors.ErrUnauthorized) && instance.PoolID != "" {
|
if errors.Is(err, runnerErrors.ErrUnauthorized) && instance.PoolID != "" {
|
||||||
poolMgr, err := r.getPoolManagerFromInstance(ctx, instance)
|
poolMgr, err := r.getPoolManagerFromInstance(ctx, instance)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "fetching pool manager for instance")
|
return fmt.Errorf("error fetching pool manager for instance: %w", err)
|
||||||
}
|
}
|
||||||
poolMgr.SetPoolRunningState(false, fmt.Sprintf("failed to remove runner: %q", err))
|
poolMgr.SetPoolRunningState(false, fmt.Sprintf("failed to remove runner: %q", err))
|
||||||
}
|
}
|
||||||
if !bypassGithubUnauthorized {
|
if !bypassGithubUnauthorized {
|
||||||
return errors.Wrap(err, "removing runner from github")
|
return fmt.Errorf("error removing runner from github: %w", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -918,7 +916,7 @@ func (r *Runner) DeleteRunner(ctx context.Context, instanceName string, forceDel
|
||||||
}
|
}
|
||||||
_, err = r.store.UpdateInstance(r.ctx, instance.Name, updateParams)
|
_, err = r.store.UpdateInstance(r.ctx, instance.Name, updateParams)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "updating runner state")
|
return fmt.Errorf("error updating runner state: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
@ -934,12 +932,12 @@ func (r *Runner) getGHCliFromInstance(ctx context.Context, instance params.Insta
|
||||||
case instance.PoolID != "":
|
case instance.PoolID != "":
|
||||||
entityGetter, err = r.store.GetPoolByID(ctx, instance.PoolID)
|
entityGetter, err = r.store.GetPoolByID(ctx, instance.PoolID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, errors.Wrap(err, "fetching pool")
|
return nil, nil, fmt.Errorf("error fetching pool: %w", err)
|
||||||
}
|
}
|
||||||
case instance.ScaleSetID != 0:
|
case instance.ScaleSetID != 0:
|
||||||
entityGetter, err = r.store.GetScaleSetByID(ctx, instance.ScaleSetID)
|
entityGetter, err = r.store.GetScaleSetByID(ctx, instance.ScaleSetID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, errors.Wrap(err, "fetching scale set")
|
return nil, nil, fmt.Errorf("error fetching scale set: %w", err)
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
return nil, nil, errors.New("instance does not have a pool or scale set")
|
return nil, nil, errors.New("instance does not have a pool or scale set")
|
||||||
|
|
@ -947,23 +945,23 @@ func (r *Runner) getGHCliFromInstance(ctx context.Context, instance params.Insta
|
||||||
|
|
||||||
entity, err := entityGetter.GetEntity()
|
entity, err := entityGetter.GetEntity()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, errors.Wrap(err, "fetching entity")
|
return nil, nil, fmt.Errorf("error fetching entity: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fetching the entity from the database will populate all fields, including credentials.
|
// Fetching the entity from the database will populate all fields, including credentials.
|
||||||
entity, err = r.store.GetForgeEntity(ctx, entity.EntityType, entity.ID)
|
entity, err = r.store.GetForgeEntity(ctx, entity.EntityType, entity.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, errors.Wrap(err, "fetching entity")
|
return nil, nil, fmt.Errorf("error fetching entity: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
ghCli, err := github.Client(ctx, entity)
|
ghCli, err := github.Client(ctx, entity)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, errors.Wrap(err, "creating github client")
|
return nil, nil, fmt.Errorf("error creating github client: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
scaleSetCli, err := scalesets.NewClient(ghCli)
|
scaleSetCli, err := scalesets.NewClient(ghCli)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, errors.Wrap(err, "creating scaleset client")
|
return nil, nil, fmt.Errorf("error creating scaleset client: %w", err)
|
||||||
}
|
}
|
||||||
return ghCli, scaleSetCli, nil
|
return ghCli, scaleSetCli, nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,11 +16,10 @@ package runner
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
|
|
||||||
runnerErrors "github.com/cloudbase/garm-provider-common/errors"
|
runnerErrors "github.com/cloudbase/garm-provider-common/errors"
|
||||||
"github.com/cloudbase/garm/auth"
|
"github.com/cloudbase/garm/auth"
|
||||||
"github.com/cloudbase/garm/params"
|
"github.com/cloudbase/garm/params"
|
||||||
|
|
@ -36,7 +35,7 @@ func (r *Runner) ListAllScaleSets(ctx context.Context) ([]params.ScaleSet, error
|
||||||
|
|
||||||
scalesets, err := r.store.ListAllScaleSets(ctx)
|
scalesets, err := r.store.ListAllScaleSets(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "fetching pools")
|
return nil, fmt.Errorf("error fetching pools: %w", err)
|
||||||
}
|
}
|
||||||
return scalesets, nil
|
return scalesets, nil
|
||||||
}
|
}
|
||||||
|
|
@ -48,7 +47,7 @@ func (r *Runner) GetScaleSetByID(ctx context.Context, scaleSet uint) (params.Sca
|
||||||
|
|
||||||
set, err := r.store.GetScaleSetByID(ctx, scaleSet)
|
set, err := r.store.GetScaleSetByID(ctx, scaleSet)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return params.ScaleSet{}, errors.Wrap(err, "fetching scale set")
|
return params.ScaleSet{}, fmt.Errorf("error fetching scale set: %w", err)
|
||||||
}
|
}
|
||||||
return set, nil
|
return set, nil
|
||||||
}
|
}
|
||||||
|
|
@ -61,7 +60,7 @@ func (r *Runner) DeleteScaleSetByID(ctx context.Context, scaleSetID uint) error
|
||||||
scaleSet, err := r.store.GetScaleSetByID(ctx, scaleSetID)
|
scaleSet, err := r.store.GetScaleSetByID(ctx, scaleSetID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if !errors.Is(err, runnerErrors.ErrNotFound) {
|
if !errors.Is(err, runnerErrors.ErrNotFound) {
|
||||||
return errors.Wrap(err, "fetching scale set")
|
return fmt.Errorf("error fetching scale set: %w", err)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -76,22 +75,22 @@ func (r *Runner) DeleteScaleSetByID(ctx context.Context, scaleSetID uint) error
|
||||||
|
|
||||||
paramEntity, err := scaleSet.GetEntity()
|
paramEntity, err := scaleSet.GetEntity()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "getting entity")
|
return fmt.Errorf("error getting entity: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
entity, err := r.store.GetForgeEntity(ctx, paramEntity.EntityType, paramEntity.ID)
|
entity, err := r.store.GetForgeEntity(ctx, paramEntity.EntityType, paramEntity.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "getting entity")
|
return fmt.Errorf("error getting entity: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
ghCli, err := github.Client(ctx, entity)
|
ghCli, err := github.Client(ctx, entity)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "creating github client")
|
return fmt.Errorf("error creating github client: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
scalesetCli, err := scalesets.NewClient(ghCli)
|
scalesetCli, err := scalesets.NewClient(ghCli)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "getting scaleset client")
|
return fmt.Errorf("error getting scaleset client: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
slog.DebugContext(ctx, "deleting scale set", "scale_set_id", scaleSet.ScaleSetID)
|
slog.DebugContext(ctx, "deleting scale set", "scale_set_id", scaleSet.ScaleSetID)
|
||||||
|
|
@ -101,10 +100,10 @@ func (r *Runner) DeleteScaleSetByID(ctx context.Context, scaleSetID uint) error
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
slog.With(slog.Any("error", err)).ErrorContext(ctx, "failed to delete scale set from github")
|
slog.With(slog.Any("error", err)).ErrorContext(ctx, "failed to delete scale set from github")
|
||||||
return errors.Wrap(err, "deleting scale set from github")
|
return fmt.Errorf("error deleting scale set from github: %w", err)
|
||||||
}
|
}
|
||||||
if err := r.store.DeleteScaleSetByID(ctx, scaleSetID); err != nil {
|
if err := r.store.DeleteScaleSetByID(ctx, scaleSetID); err != nil {
|
||||||
return errors.Wrap(err, "deleting scale set")
|
return fmt.Errorf("error deleting scale set: %w", err)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -116,7 +115,7 @@ func (r *Runner) UpdateScaleSetByID(ctx context.Context, scaleSetID uint, param
|
||||||
|
|
||||||
scaleSet, err := r.store.GetScaleSetByID(ctx, scaleSetID)
|
scaleSet, err := r.store.GetScaleSetByID(ctx, scaleSetID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return params.ScaleSet{}, errors.Wrap(err, "fetching scale set")
|
return params.ScaleSet{}, fmt.Errorf("error fetching scale set: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
maxRunners := scaleSet.MaxRunners
|
maxRunners := scaleSet.MaxRunners
|
||||||
|
|
@ -139,22 +138,22 @@ func (r *Runner) UpdateScaleSetByID(ctx context.Context, scaleSetID uint, param
|
||||||
|
|
||||||
paramEntity, err := scaleSet.GetEntity()
|
paramEntity, err := scaleSet.GetEntity()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return params.ScaleSet{}, errors.Wrap(err, "getting entity")
|
return params.ScaleSet{}, fmt.Errorf("error getting entity: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
entity, err := r.store.GetForgeEntity(ctx, paramEntity.EntityType, paramEntity.ID)
|
entity, err := r.store.GetForgeEntity(ctx, paramEntity.EntityType, paramEntity.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return params.ScaleSet{}, errors.Wrap(err, "getting entity")
|
return params.ScaleSet{}, fmt.Errorf("error getting entity: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
ghCli, err := github.Client(ctx, entity)
|
ghCli, err := github.Client(ctx, entity)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return params.ScaleSet{}, errors.Wrap(err, "creating github client")
|
return params.ScaleSet{}, fmt.Errorf("error creating github client: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
scalesetCli, err := scalesets.NewClient(ghCli)
|
scalesetCli, err := scalesets.NewClient(ghCli)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return params.ScaleSet{}, errors.Wrap(err, "getting scaleset client")
|
return params.ScaleSet{}, fmt.Errorf("error getting scaleset client: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
callback := func(old, newSet params.ScaleSet) error {
|
callback := func(old, newSet params.ScaleSet) error {
|
||||||
|
|
@ -190,7 +189,7 @@ func (r *Runner) UpdateScaleSetByID(ctx context.Context, scaleSetID uint, param
|
||||||
|
|
||||||
newScaleSet, err := r.store.UpdateEntityScaleSet(ctx, entity, scaleSetID, param, callback)
|
newScaleSet, err := r.store.UpdateEntityScaleSet(ctx, entity, scaleSetID, param, callback)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return params.ScaleSet{}, errors.Wrap(err, "updating pool")
|
return params.ScaleSet{}, fmt.Errorf("error updating pool: %w", err)
|
||||||
}
|
}
|
||||||
return newScaleSet, nil
|
return newScaleSet, nil
|
||||||
}
|
}
|
||||||
|
|
@ -210,7 +209,7 @@ func (r *Runner) CreateEntityScaleSet(ctx context.Context, entityType params.For
|
||||||
|
|
||||||
entity, err := r.store.GetForgeEntity(ctx, entityType, entityID)
|
entity, err := r.store.GetForgeEntity(ctx, entityType, entityID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return params.ScaleSet{}, errors.Wrap(err, "getting entity")
|
return params.ScaleSet{}, fmt.Errorf("error getting entity: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if entity.Credentials.ForgeType != params.GithubEndpointType {
|
if entity.Credentials.ForgeType != params.GithubEndpointType {
|
||||||
|
|
@ -219,18 +218,18 @@ func (r *Runner) CreateEntityScaleSet(ctx context.Context, entityType params.For
|
||||||
|
|
||||||
ghCli, err := github.Client(ctx, entity)
|
ghCli, err := github.Client(ctx, entity)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return params.ScaleSet{}, errors.Wrap(err, "creating github client")
|
return params.ScaleSet{}, fmt.Errorf("error creating github client: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
scalesetCli, err := scalesets.NewClient(ghCli)
|
scalesetCli, err := scalesets.NewClient(ghCli)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return params.ScaleSet{}, errors.Wrap(err, "getting scaleset client")
|
return params.ScaleSet{}, fmt.Errorf("error getting scaleset client: %w", err)
|
||||||
}
|
}
|
||||||
var runnerGroupID int64 = 1
|
var runnerGroupID int64 = 1
|
||||||
if param.GitHubRunnerGroup != "Default" {
|
if param.GitHubRunnerGroup != "Default" {
|
||||||
runnerGroup, err := scalesetCli.GetRunnerGroupByName(ctx, param.GitHubRunnerGroup)
|
runnerGroup, err := scalesetCli.GetRunnerGroupByName(ctx, param.GitHubRunnerGroup)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return params.ScaleSet{}, errors.Wrap(err, "getting runner group")
|
return params.ScaleSet{}, fmt.Errorf("error getting runner group: %w", err)
|
||||||
}
|
}
|
||||||
runnerGroupID = runnerGroup.ID
|
runnerGroupID = runnerGroup.ID
|
||||||
}
|
}
|
||||||
|
|
@ -253,7 +252,7 @@ func (r *Runner) CreateEntityScaleSet(ctx context.Context, entityType params.For
|
||||||
|
|
||||||
runnerScaleSet, err := scalesetCli.CreateRunnerScaleSet(ctx, createParam)
|
runnerScaleSet, err := scalesetCli.CreateRunnerScaleSet(ctx, createParam)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return params.ScaleSet{}, errors.Wrap(err, "creating runner scale set")
|
return params.ScaleSet{}, fmt.Errorf("error creating runner scale set: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
|
|
@ -267,7 +266,7 @@ func (r *Runner) CreateEntityScaleSet(ctx context.Context, entityType params.For
|
||||||
|
|
||||||
scaleSet, err := r.store.CreateEntityScaleSet(ctx, entity, param)
|
scaleSet, err := r.store.CreateEntityScaleSet(ctx, entity, param)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return params.ScaleSet{}, errors.Wrap(err, "creating scale set")
|
return params.ScaleSet{}, fmt.Errorf("error creating scale set: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return scaleSet, nil
|
return scaleSet, nil
|
||||||
|
|
@ -280,7 +279,7 @@ func (r *Runner) ListScaleSetInstances(ctx context.Context, scalesetID uint) ([]
|
||||||
|
|
||||||
instances, err := r.store.ListScaleSetInstances(ctx, scalesetID)
|
instances, err := r.store.ListScaleSetInstances(ctx, scalesetID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return []params.Instance{}, errors.Wrap(err, "fetching instances")
|
return []params.Instance{}, fmt.Errorf("error fetching instances: %w", err)
|
||||||
}
|
}
|
||||||
return instances, nil
|
return instances, nil
|
||||||
}
|
}
|
||||||
|
|
@ -295,7 +294,7 @@ func (r *Runner) ListEntityScaleSets(ctx context.Context, entityType params.Forg
|
||||||
}
|
}
|
||||||
scaleSets, err := r.store.ListEntityScaleSets(ctx, entity)
|
scaleSets, err := r.store.ListEntityScaleSets(ctx, entity)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "fetching scale sets")
|
return nil, fmt.Errorf("error fetching scale sets: %w", err)
|
||||||
}
|
}
|
||||||
return scaleSets, nil
|
return scaleSets, nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
@ -25,7 +26,6 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/google/go-github/v72/github"
|
"github.com/google/go-github/v72/github"
|
||||||
"github.com/pkg/errors"
|
|
||||||
|
|
||||||
runnerErrors "github.com/cloudbase/garm-provider-common/errors"
|
runnerErrors "github.com/cloudbase/garm-provider-common/errors"
|
||||||
"github.com/cloudbase/garm/metrics"
|
"github.com/cloudbase/garm/metrics"
|
||||||
|
|
@ -309,7 +309,7 @@ func (g *githubClient) RemoveEntityRunner(ctx context.Context, runnerID int64) e
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := parseError(response, err); err != nil {
|
if err := parseError(response, err); err != nil {
|
||||||
return errors.Wrapf(err, "removing runner %d", runnerID)
|
return fmt.Errorf("error removing runner %d: %w", runnerID, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
@ -366,9 +366,9 @@ func (g *githubClient) getOrganizationRunnerGroupIDByName(ctx context.Context, e
|
||||||
entity.LabelScope(), // label: scope
|
entity.LabelScope(), // label: scope
|
||||||
).Inc()
|
).Inc()
|
||||||
if ghResp != nil && ghResp.StatusCode == http.StatusUnauthorized {
|
if ghResp != nil && ghResp.StatusCode == http.StatusUnauthorized {
|
||||||
return 0, errors.Wrap(runnerErrors.ErrUnauthorized, "fetching runners")
|
return 0, fmt.Errorf("error fetching runners: %w", runnerErrors.ErrUnauthorized)
|
||||||
}
|
}
|
||||||
return 0, errors.Wrap(err, "fetching runners")
|
return 0, fmt.Errorf("error fetching runners: %w", err)
|
||||||
}
|
}
|
||||||
for _, runnerGroup := range runnerGroups.RunnerGroups {
|
for _, runnerGroup := range runnerGroups.RunnerGroups {
|
||||||
if runnerGroup.Name != nil && *runnerGroup.Name == rgName {
|
if runnerGroup.Name != nil && *runnerGroup.Name == rgName {
|
||||||
|
|
@ -402,9 +402,9 @@ func (g *githubClient) getEnterpriseRunnerGroupIDByName(ctx context.Context, ent
|
||||||
entity.LabelScope(), // label: scope
|
entity.LabelScope(), // label: scope
|
||||||
).Inc()
|
).Inc()
|
||||||
if ghResp != nil && ghResp.StatusCode == http.StatusUnauthorized {
|
if ghResp != nil && ghResp.StatusCode == http.StatusUnauthorized {
|
||||||
return 0, errors.Wrap(runnerErrors.ErrUnauthorized, "fetching runners")
|
return 0, fmt.Errorf("error fetching runners: %w", runnerErrors.ErrUnauthorized)
|
||||||
}
|
}
|
||||||
return 0, errors.Wrap(err, "fetching runners")
|
return 0, fmt.Errorf("error fetching runners: %w", err)
|
||||||
}
|
}
|
||||||
for _, runnerGroup := range runnerGroups.RunnerGroups {
|
for _, runnerGroup := range runnerGroups.RunnerGroups {
|
||||||
if runnerGroup.Name != nil && *runnerGroup.Name == rgName {
|
if runnerGroup.Name != nil && *runnerGroup.Name == rgName {
|
||||||
|
|
@ -520,7 +520,7 @@ func (g *githubClient) GithubBaseURL() *url.URL {
|
||||||
func NewRateLimitClient(ctx context.Context, credentials params.ForgeCredentials) (common.RateLimitClient, error) {
|
func NewRateLimitClient(ctx context.Context, credentials params.ForgeCredentials) (common.RateLimitClient, error) {
|
||||||
httpClient, err := credentials.GetHTTPClient(ctx)
|
httpClient, err := credentials.GetHTTPClient(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "fetching http client")
|
return nil, fmt.Errorf("error fetching http client: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
slog.DebugContext(
|
slog.DebugContext(
|
||||||
|
|
@ -531,7 +531,7 @@ func NewRateLimitClient(ctx context.Context, credentials params.ForgeCredentials
|
||||||
ghClient, err := github.NewClient(httpClient).WithEnterpriseURLs(
|
ghClient, err := github.NewClient(httpClient).WithEnterpriseURLs(
|
||||||
credentials.APIBaseURL, credentials.UploadBaseURL)
|
credentials.APIBaseURL, credentials.UploadBaseURL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "fetching github client")
|
return nil, fmt.Errorf("error fetching github client: %w", err)
|
||||||
}
|
}
|
||||||
cli := &githubClient{
|
cli := &githubClient{
|
||||||
rateLimit: ghClient.RateLimit,
|
rateLimit: ghClient.RateLimit,
|
||||||
|
|
@ -552,7 +552,7 @@ func withGiteaURLs(client *github.Client, apiBaseURL string) (*github.Client, er
|
||||||
|
|
||||||
parsedBaseURL, err := url.ParseRequestURI(apiBaseURL)
|
parsedBaseURL, err := url.ParseRequestURI(apiBaseURL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "parsing gitea base URL")
|
return nil, fmt.Errorf("error parsing gitea base URL: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !strings.HasSuffix(parsedBaseURL.Path, "/") {
|
if !strings.HasSuffix(parsedBaseURL.Path, "/") {
|
||||||
|
|
@ -573,7 +573,7 @@ func Client(ctx context.Context, entity params.ForgeEntity) (common.GithubClient
|
||||||
// func GithubClient(ctx context.Context, entity params.ForgeEntity) (common.GithubClient, error) {
|
// func GithubClient(ctx context.Context, entity params.ForgeEntity) (common.GithubClient, error) {
|
||||||
httpClient, err := entity.Credentials.GetHTTPClient(ctx)
|
httpClient, err := entity.Credentials.GetHTTPClient(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "fetching http client")
|
return nil, fmt.Errorf("error fetching http client: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
slog.DebugContext(
|
slog.DebugContext(
|
||||||
|
|
@ -590,7 +590,7 @@ func Client(ctx context.Context, entity params.ForgeEntity) (common.GithubClient
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "fetching github client")
|
return nil, fmt.Errorf("error fetching github client: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
cli := &githubClient{
|
cli := &githubClient{
|
||||||
|
|
|
||||||
|
|
@ -16,11 +16,11 @@ package github
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/google/go-github/v72/github"
|
"github.com/google/go-github/v72/github"
|
||||||
"github.com/pkg/errors"
|
|
||||||
|
|
||||||
"github.com/cloudbase/garm/metrics"
|
"github.com/cloudbase/garm/metrics"
|
||||||
"github.com/cloudbase/garm/params"
|
"github.com/cloudbase/garm/params"
|
||||||
|
|
|
||||||
|
|
@ -16,11 +16,10 @@ package util
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"unicode/utf8"
|
"unicode/utf8"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
|
|
||||||
runnerErrors "github.com/cloudbase/garm-provider-common/errors"
|
runnerErrors "github.com/cloudbase/garm-provider-common/errors"
|
||||||
commonParams "github.com/cloudbase/garm-provider-common/params"
|
commonParams "github.com/cloudbase/garm-provider-common/params"
|
||||||
"github.com/cloudbase/garm/runner/common"
|
"github.com/cloudbase/garm/runner/common"
|
||||||
|
|
@ -30,9 +29,9 @@ func FetchTools(ctx context.Context, cli common.GithubClient) ([]commonParams.Ru
|
||||||
tools, ghResp, err := cli.ListEntityRunnerApplicationDownloads(ctx)
|
tools, ghResp, err := cli.ListEntityRunnerApplicationDownloads(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if ghResp != nil && ghResp.StatusCode == http.StatusUnauthorized {
|
if ghResp != nil && ghResp.StatusCode == http.StatusUnauthorized {
|
||||||
return nil, errors.Wrap(runnerErrors.ErrUnauthorized, "fetching tools")
|
return nil, fmt.Errorf("error fetching tools: %w", runnerErrors.ErrUnauthorized)
|
||||||
}
|
}
|
||||||
return nil, errors.Wrap(err, "fetching runner tools")
|
return nil, fmt.Errorf("error fetching runner tools: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
ret := []commonParams.RunnerApplicationDownload{}
|
ret := []commonParams.RunnerApplicationDownload{}
|
||||||
|
|
|
||||||
1
vendor/github.com/juju/clock/.gitignore
generated
vendored
1
vendor/github.com/juju/clock/.gitignore
generated
vendored
|
|
@ -1 +0,0 @@
|
||||||
.vscode/
|
|
||||||
191
vendor/github.com/juju/clock/LICENSE
generated
vendored
191
vendor/github.com/juju/clock/LICENSE
generated
vendored
|
|
@ -1,191 +0,0 @@
|
||||||
All files in this repository are licensed as follows. If you contribute
|
|
||||||
to this repository, it is assumed that you license your contribution
|
|
||||||
under the same license unless you state otherwise.
|
|
||||||
|
|
||||||
All files Copyright (C) 2015 Canonical Ltd. unless otherwise specified in the file.
|
|
||||||
|
|
||||||
This software is licensed under the LGPLv3, included below.
|
|
||||||
|
|
||||||
As a special exception to the GNU Lesser General Public License version 3
|
|
||||||
("LGPL3"), the copyright holders of this Library give you permission to
|
|
||||||
convey to a third party a Combined Work that links statically or dynamically
|
|
||||||
to this Library without providing any Minimal Corresponding Source or
|
|
||||||
Minimal Application Code as set out in 4d or providing the installation
|
|
||||||
information set out in section 4e, provided that you comply with the other
|
|
||||||
provisions of LGPL3 and provided that you meet, for the Application the
|
|
||||||
terms and conditions of the license(s) which apply to the Application.
|
|
||||||
|
|
||||||
Except as stated in this special exception, the provisions of LGPL3 will
|
|
||||||
continue to comply in full to this Library. If you modify this Library, you
|
|
||||||
may apply this exception to your version of this Library, but you are not
|
|
||||||
obliged to do so. If you do not wish to do so, delete this exception
|
|
||||||
statement from your version. This exception does not (and cannot) modify any
|
|
||||||
license terms which apply to the Application, with which you must still
|
|
||||||
comply.
|
|
||||||
|
|
||||||
|
|
||||||
GNU LESSER GENERAL PUBLIC LICENSE
|
|
||||||
Version 3, 29 June 2007
|
|
||||||
|
|
||||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
|
||||||
Everyone is permitted to copy and distribute verbatim copies
|
|
||||||
of this license document, but changing it is not allowed.
|
|
||||||
|
|
||||||
|
|
||||||
This version of the GNU Lesser General Public License incorporates
|
|
||||||
the terms and conditions of version 3 of the GNU General Public
|
|
||||||
License, supplemented by the additional permissions listed below.
|
|
||||||
|
|
||||||
0. Additional Definitions.
|
|
||||||
|
|
||||||
As used herein, "this License" refers to version 3 of the GNU Lesser
|
|
||||||
General Public License, and the "GNU GPL" refers to version 3 of the GNU
|
|
||||||
General Public License.
|
|
||||||
|
|
||||||
"The Library" refers to a covered work governed by this License,
|
|
||||||
other than an Application or a Combined Work as defined below.
|
|
||||||
|
|
||||||
An "Application" is any work that makes use of an interface provided
|
|
||||||
by the Library, but which is not otherwise based on the Library.
|
|
||||||
Defining a subclass of a class defined by the Library is deemed a mode
|
|
||||||
of using an interface provided by the Library.
|
|
||||||
|
|
||||||
A "Combined Work" is a work produced by combining or linking an
|
|
||||||
Application with the Library. The particular version of the Library
|
|
||||||
with which the Combined Work was made is also called the "Linked
|
|
||||||
Version".
|
|
||||||
|
|
||||||
The "Minimal Corresponding Source" for a Combined Work means the
|
|
||||||
Corresponding Source for the Combined Work, excluding any source code
|
|
||||||
for portions of the Combined Work that, considered in isolation, are
|
|
||||||
based on the Application, and not on the Linked Version.
|
|
||||||
|
|
||||||
The "Corresponding Application Code" for a Combined Work means the
|
|
||||||
object code and/or source code for the Application, including any data
|
|
||||||
and utility programs needed for reproducing the Combined Work from the
|
|
||||||
Application, but excluding the System Libraries of the Combined Work.
|
|
||||||
|
|
||||||
1. Exception to Section 3 of the GNU GPL.
|
|
||||||
|
|
||||||
You may convey a covered work under sections 3 and 4 of this License
|
|
||||||
without being bound by section 3 of the GNU GPL.
|
|
||||||
|
|
||||||
2. Conveying Modified Versions.
|
|
||||||
|
|
||||||
If you modify a copy of the Library, and, in your modifications, a
|
|
||||||
facility refers to a function or data to be supplied by an Application
|
|
||||||
that uses the facility (other than as an argument passed when the
|
|
||||||
facility is invoked), then you may convey a copy of the modified
|
|
||||||
version:
|
|
||||||
|
|
||||||
a) under this License, provided that you make a good faith effort to
|
|
||||||
ensure that, in the event an Application does not supply the
|
|
||||||
function or data, the facility still operates, and performs
|
|
||||||
whatever part of its purpose remains meaningful, or
|
|
||||||
|
|
||||||
b) under the GNU GPL, with none of the additional permissions of
|
|
||||||
this License applicable to that copy.
|
|
||||||
|
|
||||||
3. Object Code Incorporating Material from Library Header Files.
|
|
||||||
|
|
||||||
The object code form of an Application may incorporate material from
|
|
||||||
a header file that is part of the Library. You may convey such object
|
|
||||||
code under terms of your choice, provided that, if the incorporated
|
|
||||||
material is not limited to numerical parameters, data structure
|
|
||||||
layouts and accessors, or small macros, inline functions and templates
|
|
||||||
(ten or fewer lines in length), you do both of the following:
|
|
||||||
|
|
||||||
a) Give prominent notice with each copy of the object code that the
|
|
||||||
Library is used in it and that the Library and its use are
|
|
||||||
covered by this License.
|
|
||||||
|
|
||||||
b) Accompany the object code with a copy of the GNU GPL and this license
|
|
||||||
document.
|
|
||||||
|
|
||||||
4. Combined Works.
|
|
||||||
|
|
||||||
You may convey a Combined Work under terms of your choice that,
|
|
||||||
taken together, effectively do not restrict modification of the
|
|
||||||
portions of the Library contained in the Combined Work and reverse
|
|
||||||
engineering for debugging such modifications, if you also do each of
|
|
||||||
the following:
|
|
||||||
|
|
||||||
a) Give prominent notice with each copy of the Combined Work that
|
|
||||||
the Library is used in it and that the Library and its use are
|
|
||||||
covered by this License.
|
|
||||||
|
|
||||||
b) Accompany the Combined Work with a copy of the GNU GPL and this license
|
|
||||||
document.
|
|
||||||
|
|
||||||
c) For a Combined Work that displays copyright notices during
|
|
||||||
execution, include the copyright notice for the Library among
|
|
||||||
these notices, as well as a reference directing the user to the
|
|
||||||
copies of the GNU GPL and this license document.
|
|
||||||
|
|
||||||
d) Do one of the following:
|
|
||||||
|
|
||||||
0) Convey the Minimal Corresponding Source under the terms of this
|
|
||||||
License, and the Corresponding Application Code in a form
|
|
||||||
suitable for, and under terms that permit, the user to
|
|
||||||
recombine or relink the Application with a modified version of
|
|
||||||
the Linked Version to produce a modified Combined Work, in the
|
|
||||||
manner specified by section 6 of the GNU GPL for conveying
|
|
||||||
Corresponding Source.
|
|
||||||
|
|
||||||
1) Use a suitable shared library mechanism for linking with the
|
|
||||||
Library. A suitable mechanism is one that (a) uses at run time
|
|
||||||
a copy of the Library already present on the user's computer
|
|
||||||
system, and (b) will operate properly with a modified version
|
|
||||||
of the Library that is interface-compatible with the Linked
|
|
||||||
Version.
|
|
||||||
|
|
||||||
e) Provide Installation Information, but only if you would otherwise
|
|
||||||
be required to provide such information under section 6 of the
|
|
||||||
GNU GPL, and only to the extent that such information is
|
|
||||||
necessary to install and execute a modified version of the
|
|
||||||
Combined Work produced by recombining or relinking the
|
|
||||||
Application with a modified version of the Linked Version. (If
|
|
||||||
you use option 4d0, the Installation Information must accompany
|
|
||||||
the Minimal Corresponding Source and Corresponding Application
|
|
||||||
Code. If you use option 4d1, you must provide the Installation
|
|
||||||
Information in the manner specified by section 6 of the GNU GPL
|
|
||||||
for conveying Corresponding Source.)
|
|
||||||
|
|
||||||
5. Combined Libraries.
|
|
||||||
|
|
||||||
You may place library facilities that are a work based on the
|
|
||||||
Library side by side in a single library together with other library
|
|
||||||
facilities that are not Applications and are not covered by this
|
|
||||||
License, and convey such a combined library under terms of your
|
|
||||||
choice, if you do both of the following:
|
|
||||||
|
|
||||||
a) Accompany the combined library with a copy of the same work based
|
|
||||||
on the Library, uncombined with any other library facilities,
|
|
||||||
conveyed under the terms of this License.
|
|
||||||
|
|
||||||
b) Give prominent notice with the combined library that part of it
|
|
||||||
is a work based on the Library, and explaining where to find the
|
|
||||||
accompanying uncombined form of the same work.
|
|
||||||
|
|
||||||
6. Revised Versions of the GNU Lesser General Public License.
|
|
||||||
|
|
||||||
The Free Software Foundation may publish revised and/or new versions
|
|
||||||
of the GNU Lesser General Public License from time to time. Such new
|
|
||||||
versions will be similar in spirit to the present version, but may
|
|
||||||
differ in detail to address new problems or concerns.
|
|
||||||
|
|
||||||
Each version is given a distinguishing version number. If the
|
|
||||||
Library as you received it specifies that a certain numbered version
|
|
||||||
of the GNU Lesser General Public License "or any later version"
|
|
||||||
applies to it, you have the option of following the terms and
|
|
||||||
conditions either of that published version or of any later version
|
|
||||||
published by the Free Software Foundation. If the Library as you
|
|
||||||
received it does not specify a version number of the GNU Lesser
|
|
||||||
General Public License, you may choose any version of the GNU Lesser
|
|
||||||
General Public License ever published by the Free Software Foundation.
|
|
||||||
|
|
||||||
If the Library as you received it specifies that a proxy can decide
|
|
||||||
whether future versions of the GNU Lesser General Public License shall
|
|
||||||
apply, that proxy's public statement of acceptance of any version is
|
|
||||||
permanent authorization for you to choose that version for the
|
|
||||||
Library.
|
|
||||||
20
vendor/github.com/juju/clock/Makefile
generated
vendored
20
vendor/github.com/juju/clock/Makefile
generated
vendored
|
|
@ -1,20 +0,0 @@
|
||||||
PROJECT := github.com/juju/clock
|
|
||||||
|
|
||||||
.PHONY: check-licence check-go check
|
|
||||||
|
|
||||||
check: check-licence check-go
|
|
||||||
go test $(PROJECT)/...
|
|
||||||
|
|
||||||
check-licence:
|
|
||||||
@(fgrep -rl "Licensed under the LGPLv3" --exclude *.s .;\
|
|
||||||
fgrep -rl "MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT" --exclude *.s .;\
|
|
||||||
find . -name "*.go") | sed -e 's,\./,,' | sort | uniq -u | \
|
|
||||||
xargs -I {} echo FAIL: licence missed: {}
|
|
||||||
|
|
||||||
check-go:
|
|
||||||
$(eval GOFMT := $(strip $(shell gofmt -l .| sed -e "s/^/ /g")))
|
|
||||||
@(if [ x$(GOFMT) != x"" ]; then \
|
|
||||||
echo go fmt is sad: $(GOFMT); \
|
|
||||||
exit 1; \
|
|
||||||
fi )
|
|
||||||
@(go vet -all -composites=false -copylocks=false .)
|
|
||||||
7
vendor/github.com/juju/clock/README.md
generated
vendored
7
vendor/github.com/juju/clock/README.md
generated
vendored
|
|
@ -1,7 +0,0 @@
|
||||||
# clock
|
|
||||||
|
|
||||||
An interface definition for a fully defined clock.
|
|
||||||
|
|
||||||
An WallClock implementation of that interface using the time package.
|
|
||||||
|
|
||||||
A testing clock.
|
|
||||||
77
vendor/github.com/juju/clock/clock.go
generated
vendored
77
vendor/github.com/juju/clock/clock.go
generated
vendored
|
|
@ -1,77 +0,0 @@
|
||||||
// Copyright 2015 Canonical Ltd.
|
|
||||||
// Licensed under the LGPLv3, see LICENCE file for details.
|
|
||||||
|
|
||||||
package clock
|
|
||||||
|
|
||||||
import "time"
|
|
||||||
|
|
||||||
// Clock provides an interface for dealing with clocks.
|
|
||||||
type Clock interface {
|
|
||||||
// Now returns the current clock time.
|
|
||||||
Now() time.Time
|
|
||||||
|
|
||||||
// After waits for the duration to elapse and then sends the
|
|
||||||
// current time on the returned channel.
|
|
||||||
After(time.Duration) <-chan time.Time
|
|
||||||
|
|
||||||
// AfterFunc waits for the duration to elapse and then calls f in its own goroutine.
|
|
||||||
// It returns a Timer that can be used to cancel the call using its Stop method.
|
|
||||||
AfterFunc(d time.Duration, f func()) Timer
|
|
||||||
|
|
||||||
// NewTimer creates a new Timer that will send the current time
|
|
||||||
// on its channel after at least duration d.
|
|
||||||
NewTimer(d time.Duration) Timer
|
|
||||||
|
|
||||||
// At waits for the time to pass and then sends the
|
|
||||||
// current time on the returned channel.
|
|
||||||
At(t time.Time) <-chan time.Time
|
|
||||||
|
|
||||||
// AtFunc waits for the time to pass and then calls f in its own goroutine.
|
|
||||||
// It returns an Alarm that can be used to cancel the call using its Stop method.
|
|
||||||
AtFunc(t time.Time, f func()) Alarm
|
|
||||||
|
|
||||||
// NewAlarm creates a new Alarm that will send the current time
|
|
||||||
// on its channel at or after time t has passed.
|
|
||||||
NewAlarm(t time.Time) Alarm
|
|
||||||
}
|
|
||||||
|
|
||||||
// Timer type represents a single event.
|
|
||||||
// Timers must be created with AfterFunc or NewTimer.
|
|
||||||
// This interface follows time.Timer's methods but provides easier mocking.
|
|
||||||
type Timer interface {
|
|
||||||
// When the timer expires, the current time will be sent on the
|
|
||||||
// channel returned from Chan, unless the timer was created by
|
|
||||||
// AfterFunc.
|
|
||||||
Chan() <-chan time.Time
|
|
||||||
|
|
||||||
// Reset changes the timer to expire after duration d.
|
|
||||||
// It returns true if the timer had been active, false if
|
|
||||||
// the timer had expired or been stopped.
|
|
||||||
Reset(d time.Duration) bool
|
|
||||||
|
|
||||||
// Stop prevents the Timer from firing. It returns true if
|
|
||||||
// the call stops the timer, false if the timer has already expired or been stopped.
|
|
||||||
// Stop does not close the channel, to prevent a read
|
|
||||||
// from the channel succeeding incorrectly.
|
|
||||||
Stop() bool
|
|
||||||
}
|
|
||||||
|
|
||||||
// Alarm type represents a single event.
|
|
||||||
// Alarms must be created with AtFunc or NewAlarm.
|
|
||||||
type Alarm interface {
|
|
||||||
// When the alarm expires, the current time will be sent on the
|
|
||||||
// channel returned from Chan, unless the alarm was created by
|
|
||||||
// AtFunc.
|
|
||||||
Chan() <-chan time.Time
|
|
||||||
|
|
||||||
// Reset changes the alarm to expire at or after time t.
|
|
||||||
// It returns true if the alarm had been active, false if
|
|
||||||
// the alarm had fired or been stopped.
|
|
||||||
Reset(t time.Time) bool
|
|
||||||
|
|
||||||
// Stop prevents the alarm from firing. It returns true if
|
|
||||||
// the call stops the alarm, false if the alarm has already fired or been stopped.
|
|
||||||
// Stop does not close the channel, to prevent a read
|
|
||||||
// from the channel succeeding incorrectly.
|
|
||||||
Stop() bool
|
|
||||||
}
|
|
||||||
77
vendor/github.com/juju/clock/wall.go
generated
vendored
77
vendor/github.com/juju/clock/wall.go
generated
vendored
|
|
@ -1,77 +0,0 @@
|
||||||
// Copyright 2015 Canonical Ltd.
|
|
||||||
// Licensed under the LGPLv3, see LICENCE file for details.
|
|
||||||
|
|
||||||
package clock
|
|
||||||
|
|
||||||
import (
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
// WallClock exposes wall-clock time via the Clock interface.
|
|
||||||
var WallClock wallClock
|
|
||||||
|
|
||||||
// ensure that WallClock does actually implement the Clock interface.
|
|
||||||
var _ Clock = WallClock
|
|
||||||
|
|
||||||
// WallClock exposes wall-clock time as returned by time.Now.
|
|
||||||
type wallClock struct{}
|
|
||||||
|
|
||||||
// Now is part of the Clock interface.
|
|
||||||
func (wallClock) Now() time.Time {
|
|
||||||
return time.Now()
|
|
||||||
}
|
|
||||||
|
|
||||||
// After implements Clock.After.
|
|
||||||
func (wallClock) After(d time.Duration) <-chan time.Time {
|
|
||||||
return time.After(d)
|
|
||||||
}
|
|
||||||
|
|
||||||
// AfterFunc implements Clock.AfterFunc.
|
|
||||||
func (wallClock) AfterFunc(d time.Duration, f func()) Timer {
|
|
||||||
return wallTimer{time.AfterFunc(d, f)}
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewTimer implements Clock.NewTimer.
|
|
||||||
func (wallClock) NewTimer(d time.Duration) Timer {
|
|
||||||
return wallTimer{time.NewTimer(d)}
|
|
||||||
}
|
|
||||||
|
|
||||||
// wallTimer implements the Timer interface.
|
|
||||||
type wallTimer struct {
|
|
||||||
*time.Timer
|
|
||||||
}
|
|
||||||
|
|
||||||
// Chan implements Timer.Chan.
|
|
||||||
func (t wallTimer) Chan() <-chan time.Time {
|
|
||||||
return t.C
|
|
||||||
}
|
|
||||||
|
|
||||||
// At implements Clock.At.
|
|
||||||
func (wallClock) At(t time.Time) <-chan time.Time {
|
|
||||||
return time.After(time.Until(t))
|
|
||||||
}
|
|
||||||
|
|
||||||
// AtFunc implements Clock.AtFunc.
|
|
||||||
func (wallClock) AtFunc(t time.Time, f func()) Alarm {
|
|
||||||
return wallAlarm{time.AfterFunc(time.Until(t), f)}
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewAlarm implements Clock.NewAlarm.
|
|
||||||
func (wallClock) NewAlarm(t time.Time) Alarm {
|
|
||||||
return wallAlarm{time.NewTimer(time.Until(t))}
|
|
||||||
}
|
|
||||||
|
|
||||||
// wallAlarm implements the Alarm interface.
|
|
||||||
type wallAlarm struct {
|
|
||||||
*time.Timer
|
|
||||||
}
|
|
||||||
|
|
||||||
// Chan implements Alarm.Chan.
|
|
||||||
func (a wallAlarm) Chan() <-chan time.Time {
|
|
||||||
return a.C
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reset implements Alarm.Reset
|
|
||||||
func (a wallAlarm) Reset(t time.Time) bool {
|
|
||||||
return a.Timer.Reset(time.Until(t))
|
|
||||||
}
|
|
||||||
23
vendor/github.com/juju/errors/.gitignore
generated
vendored
23
vendor/github.com/juju/errors/.gitignore
generated
vendored
|
|
@ -1,23 +0,0 @@
|
||||||
# Compiled Object files, Static and Dynamic libs (Shared Objects)
|
|
||||||
*.o
|
|
||||||
*.a
|
|
||||||
*.so
|
|
||||||
|
|
||||||
# Folders
|
|
||||||
_obj
|
|
||||||
_test
|
|
||||||
|
|
||||||
# Architecture specific extensions/prefixes
|
|
||||||
*.[568vq]
|
|
||||||
[568vq].out
|
|
||||||
|
|
||||||
*.cgo1.go
|
|
||||||
*.cgo2.c
|
|
||||||
_cgo_defun.c
|
|
||||||
_cgo_gotypes.go
|
|
||||||
_cgo_export.*
|
|
||||||
|
|
||||||
_testmain.go
|
|
||||||
|
|
||||||
*.exe
|
|
||||||
*.test
|
|
||||||
191
vendor/github.com/juju/errors/LICENSE
generated
vendored
191
vendor/github.com/juju/errors/LICENSE
generated
vendored
|
|
@ -1,191 +0,0 @@
|
||||||
All files in this repository are licensed as follows. If you contribute
|
|
||||||
to this repository, it is assumed that you license your contribution
|
|
||||||
under the same license unless you state otherwise.
|
|
||||||
|
|
||||||
All files Copyright (C) 2015 Canonical Ltd. unless otherwise specified in the file.
|
|
||||||
|
|
||||||
This software is licensed under the LGPLv3, included below.
|
|
||||||
|
|
||||||
As a special exception to the GNU Lesser General Public License version 3
|
|
||||||
("LGPL3"), the copyright holders of this Library give you permission to
|
|
||||||
convey to a third party a Combined Work that links statically or dynamically
|
|
||||||
to this Library without providing any Minimal Corresponding Source or
|
|
||||||
Minimal Application Code as set out in 4d or providing the installation
|
|
||||||
information set out in section 4e, provided that you comply with the other
|
|
||||||
provisions of LGPL3 and provided that you meet, for the Application the
|
|
||||||
terms and conditions of the license(s) which apply to the Application.
|
|
||||||
|
|
||||||
Except as stated in this special exception, the provisions of LGPL3 will
|
|
||||||
continue to comply in full to this Library. If you modify this Library, you
|
|
||||||
may apply this exception to your version of this Library, but you are not
|
|
||||||
obliged to do so. If you do not wish to do so, delete this exception
|
|
||||||
statement from your version. This exception does not (and cannot) modify any
|
|
||||||
license terms which apply to the Application, with which you must still
|
|
||||||
comply.
|
|
||||||
|
|
||||||
|
|
||||||
GNU LESSER GENERAL PUBLIC LICENSE
|
|
||||||
Version 3, 29 June 2007
|
|
||||||
|
|
||||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
|
||||||
Everyone is permitted to copy and distribute verbatim copies
|
|
||||||
of this license document, but changing it is not allowed.
|
|
||||||
|
|
||||||
|
|
||||||
This version of the GNU Lesser General Public License incorporates
|
|
||||||
the terms and conditions of version 3 of the GNU General Public
|
|
||||||
License, supplemented by the additional permissions listed below.
|
|
||||||
|
|
||||||
0. Additional Definitions.
|
|
||||||
|
|
||||||
As used herein, "this License" refers to version 3 of the GNU Lesser
|
|
||||||
General Public License, and the "GNU GPL" refers to version 3 of the GNU
|
|
||||||
General Public License.
|
|
||||||
|
|
||||||
"The Library" refers to a covered work governed by this License,
|
|
||||||
other than an Application or a Combined Work as defined below.
|
|
||||||
|
|
||||||
An "Application" is any work that makes use of an interface provided
|
|
||||||
by the Library, but which is not otherwise based on the Library.
|
|
||||||
Defining a subclass of a class defined by the Library is deemed a mode
|
|
||||||
of using an interface provided by the Library.
|
|
||||||
|
|
||||||
A "Combined Work" is a work produced by combining or linking an
|
|
||||||
Application with the Library. The particular version of the Library
|
|
||||||
with which the Combined Work was made is also called the "Linked
|
|
||||||
Version".
|
|
||||||
|
|
||||||
The "Minimal Corresponding Source" for a Combined Work means the
|
|
||||||
Corresponding Source for the Combined Work, excluding any source code
|
|
||||||
for portions of the Combined Work that, considered in isolation, are
|
|
||||||
based on the Application, and not on the Linked Version.
|
|
||||||
|
|
||||||
The "Corresponding Application Code" for a Combined Work means the
|
|
||||||
object code and/or source code for the Application, including any data
|
|
||||||
and utility programs needed for reproducing the Combined Work from the
|
|
||||||
Application, but excluding the System Libraries of the Combined Work.
|
|
||||||
|
|
||||||
1. Exception to Section 3 of the GNU GPL.
|
|
||||||
|
|
||||||
You may convey a covered work under sections 3 and 4 of this License
|
|
||||||
without being bound by section 3 of the GNU GPL.
|
|
||||||
|
|
||||||
2. Conveying Modified Versions.
|
|
||||||
|
|
||||||
If you modify a copy of the Library, and, in your modifications, a
|
|
||||||
facility refers to a function or data to be supplied by an Application
|
|
||||||
that uses the facility (other than as an argument passed when the
|
|
||||||
facility is invoked), then you may convey a copy of the modified
|
|
||||||
version:
|
|
||||||
|
|
||||||
a) under this License, provided that you make a good faith effort to
|
|
||||||
ensure that, in the event an Application does not supply the
|
|
||||||
function or data, the facility still operates, and performs
|
|
||||||
whatever part of its purpose remains meaningful, or
|
|
||||||
|
|
||||||
b) under the GNU GPL, with none of the additional permissions of
|
|
||||||
this License applicable to that copy.
|
|
||||||
|
|
||||||
3. Object Code Incorporating Material from Library Header Files.
|
|
||||||
|
|
||||||
The object code form of an Application may incorporate material from
|
|
||||||
a header file that is part of the Library. You may convey such object
|
|
||||||
code under terms of your choice, provided that, if the incorporated
|
|
||||||
material is not limited to numerical parameters, data structure
|
|
||||||
layouts and accessors, or small macros, inline functions and templates
|
|
||||||
(ten or fewer lines in length), you do both of the following:
|
|
||||||
|
|
||||||
a) Give prominent notice with each copy of the object code that the
|
|
||||||
Library is used in it and that the Library and its use are
|
|
||||||
covered by this License.
|
|
||||||
|
|
||||||
b) Accompany the object code with a copy of the GNU GPL and this license
|
|
||||||
document.
|
|
||||||
|
|
||||||
4. Combined Works.
|
|
||||||
|
|
||||||
You may convey a Combined Work under terms of your choice that,
|
|
||||||
taken together, effectively do not restrict modification of the
|
|
||||||
portions of the Library contained in the Combined Work and reverse
|
|
||||||
engineering for debugging such modifications, if you also do each of
|
|
||||||
the following:
|
|
||||||
|
|
||||||
a) Give prominent notice with each copy of the Combined Work that
|
|
||||||
the Library is used in it and that the Library and its use are
|
|
||||||
covered by this License.
|
|
||||||
|
|
||||||
b) Accompany the Combined Work with a copy of the GNU GPL and this license
|
|
||||||
document.
|
|
||||||
|
|
||||||
c) For a Combined Work that displays copyright notices during
|
|
||||||
execution, include the copyright notice for the Library among
|
|
||||||
these notices, as well as a reference directing the user to the
|
|
||||||
copies of the GNU GPL and this license document.
|
|
||||||
|
|
||||||
d) Do one of the following:
|
|
||||||
|
|
||||||
0) Convey the Minimal Corresponding Source under the terms of this
|
|
||||||
License, and the Corresponding Application Code in a form
|
|
||||||
suitable for, and under terms that permit, the user to
|
|
||||||
recombine or relink the Application with a modified version of
|
|
||||||
the Linked Version to produce a modified Combined Work, in the
|
|
||||||
manner specified by section 6 of the GNU GPL for conveying
|
|
||||||
Corresponding Source.
|
|
||||||
|
|
||||||
1) Use a suitable shared library mechanism for linking with the
|
|
||||||
Library. A suitable mechanism is one that (a) uses at run time
|
|
||||||
a copy of the Library already present on the user's computer
|
|
||||||
system, and (b) will operate properly with a modified version
|
|
||||||
of the Library that is interface-compatible with the Linked
|
|
||||||
Version.
|
|
||||||
|
|
||||||
e) Provide Installation Information, but only if you would otherwise
|
|
||||||
be required to provide such information under section 6 of the
|
|
||||||
GNU GPL, and only to the extent that such information is
|
|
||||||
necessary to install and execute a modified version of the
|
|
||||||
Combined Work produced by recombining or relinking the
|
|
||||||
Application with a modified version of the Linked Version. (If
|
|
||||||
you use option 4d0, the Installation Information must accompany
|
|
||||||
the Minimal Corresponding Source and Corresponding Application
|
|
||||||
Code. If you use option 4d1, you must provide the Installation
|
|
||||||
Information in the manner specified by section 6 of the GNU GPL
|
|
||||||
for conveying Corresponding Source.)
|
|
||||||
|
|
||||||
5. Combined Libraries.
|
|
||||||
|
|
||||||
You may place library facilities that are a work based on the
|
|
||||||
Library side by side in a single library together with other library
|
|
||||||
facilities that are not Applications and are not covered by this
|
|
||||||
License, and convey such a combined library under terms of your
|
|
||||||
choice, if you do both of the following:
|
|
||||||
|
|
||||||
a) Accompany the combined library with a copy of the same work based
|
|
||||||
on the Library, uncombined with any other library facilities,
|
|
||||||
conveyed under the terms of this License.
|
|
||||||
|
|
||||||
b) Give prominent notice with the combined library that part of it
|
|
||||||
is a work based on the Library, and explaining where to find the
|
|
||||||
accompanying uncombined form of the same work.
|
|
||||||
|
|
||||||
6. Revised Versions of the GNU Lesser General Public License.
|
|
||||||
|
|
||||||
The Free Software Foundation may publish revised and/or new versions
|
|
||||||
of the GNU Lesser General Public License from time to time. Such new
|
|
||||||
versions will be similar in spirit to the present version, but may
|
|
||||||
differ in detail to address new problems or concerns.
|
|
||||||
|
|
||||||
Each version is given a distinguishing version number. If the
|
|
||||||
Library as you received it specifies that a certain numbered version
|
|
||||||
of the GNU Lesser General Public License "or any later version"
|
|
||||||
applies to it, you have the option of following the terms and
|
|
||||||
conditions either of that published version or of any later version
|
|
||||||
published by the Free Software Foundation. If the Library as you
|
|
||||||
received it does not specify a version number of the GNU Lesser
|
|
||||||
General Public License, you may choose any version of the GNU Lesser
|
|
||||||
General Public License ever published by the Free Software Foundation.
|
|
||||||
|
|
||||||
If the Library as you received it specifies that a proxy can decide
|
|
||||||
whether future versions of the GNU Lesser General Public License shall
|
|
||||||
apply, that proxy's public statement of acceptance of any version is
|
|
||||||
permanent authorization for you to choose that version for the
|
|
||||||
Library.
|
|
||||||
24
vendor/github.com/juju/errors/Makefile
generated
vendored
24
vendor/github.com/juju/errors/Makefile
generated
vendored
|
|
@ -1,24 +0,0 @@
|
||||||
PROJECT := github.com/juju/errors
|
|
||||||
|
|
||||||
.PHONY: check-licence check-go check docs
|
|
||||||
|
|
||||||
check: check-licence check-go
|
|
||||||
go test $(PROJECT)/...
|
|
||||||
|
|
||||||
check-licence:
|
|
||||||
@(fgrep -rl "Licensed under the LGPLv3" --exclude *.s .;\
|
|
||||||
fgrep -rl "MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT" --exclude *.s .;\
|
|
||||||
find . -name "*.go") | sed -e 's,\./,,' | sort | uniq -u | \
|
|
||||||
xargs -I {} echo FAIL: licence missed: {}
|
|
||||||
|
|
||||||
check-go:
|
|
||||||
$(eval GOFMT := $(strip $(shell gofmt -l .| sed -e "s/^/ /g")))
|
|
||||||
@(if [ x$(GOFMT) != x"" ]; then \
|
|
||||||
echo go fmt is sad: $(GOFMT); \
|
|
||||||
exit 1; \
|
|
||||||
fi )
|
|
||||||
@(go vet -all -composites=false -copylocks=false .)
|
|
||||||
|
|
||||||
docs:
|
|
||||||
godoc2md github.com/juju/errors > README.md
|
|
||||||
sed -i '5i[\[GoDoc](https://godoc.org/github.com/juju/errors?status.svg)](https://godoc.org/github.com/juju/errors)' README.md
|
|
||||||
707
vendor/github.com/juju/errors/README.md
generated
vendored
707
vendor/github.com/juju/errors/README.md
generated
vendored
|
|
@ -1,707 +0,0 @@
|
||||||
|
|
||||||
# errors
|
|
||||||
import "github.com/juju/errors"
|
|
||||||
|
|
||||||
[](https://godoc.org/github.com/juju/errors)
|
|
||||||
|
|
||||||
The juju/errors provides an easy way to annotate errors without losing the
|
|
||||||
original error context.
|
|
||||||
|
|
||||||
The exported `New` and `Errorf` functions are designed to replace the
|
|
||||||
`errors.New` and `fmt.Errorf` functions respectively. The same underlying
|
|
||||||
error is there, but the package also records the location at which the error
|
|
||||||
was created.
|
|
||||||
|
|
||||||
A primary use case for this library is to add extra context any time an
|
|
||||||
error is returned from a function.
|
|
||||||
|
|
||||||
|
|
||||||
if err := SomeFunc(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
This instead becomes:
|
|
||||||
|
|
||||||
|
|
||||||
if err := SomeFunc(); err != nil {
|
|
||||||
return errors.Trace(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
which just records the file and line number of the Trace call, or
|
|
||||||
|
|
||||||
|
|
||||||
if err := SomeFunc(); err != nil {
|
|
||||||
return errors.Annotate(err, "more context")
|
|
||||||
}
|
|
||||||
|
|
||||||
which also adds an annotation to the error.
|
|
||||||
|
|
||||||
When you want to check to see if an error is of a particular type, a helper
|
|
||||||
function is normally exported by the package that returned the error, like the
|
|
||||||
`os` package does. The underlying cause of the error is available using the
|
|
||||||
`Cause` function.
|
|
||||||
|
|
||||||
|
|
||||||
os.IsNotExist(errors.Cause(err))
|
|
||||||
|
|
||||||
The result of the `Error()` call on an annotated error is the annotations joined
|
|
||||||
with colons, then the result of the `Error()` method for the underlying error
|
|
||||||
that was the cause.
|
|
||||||
|
|
||||||
|
|
||||||
err := errors.Errorf("original")
|
|
||||||
err = errors.Annotatef(err, "context")
|
|
||||||
err = errors.Annotatef(err, "more context")
|
|
||||||
err.Error() -> "more context: context: original"
|
|
||||||
|
|
||||||
Obviously recording the file, line and functions is not very useful if you
|
|
||||||
cannot get them back out again.
|
|
||||||
|
|
||||||
|
|
||||||
errors.ErrorStack(err)
|
|
||||||
|
|
||||||
will return something like:
|
|
||||||
|
|
||||||
|
|
||||||
first error
|
|
||||||
github.com/juju/errors/annotation_test.go:193:
|
|
||||||
github.com/juju/errors/annotation_test.go:194: annotation
|
|
||||||
github.com/juju/errors/annotation_test.go:195:
|
|
||||||
github.com/juju/errors/annotation_test.go:196: more context
|
|
||||||
github.com/juju/errors/annotation_test.go:197:
|
|
||||||
|
|
||||||
The first error was generated by an external system, so there was no location
|
|
||||||
associated. The second, fourth, and last lines were generated with Trace calls,
|
|
||||||
and the other two through Annotate.
|
|
||||||
|
|
||||||
Sometimes when responding to an error you want to return a more specific error
|
|
||||||
for the situation.
|
|
||||||
|
|
||||||
|
|
||||||
if err := FindField(field); err != nil {
|
|
||||||
return errors.Wrap(err, errors.NotFoundf(field))
|
|
||||||
}
|
|
||||||
|
|
||||||
This returns an error where the complete error stack is still available, and
|
|
||||||
`errors.Cause()` will return the `NotFound` error.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## func AlreadyExistsf
|
|
||||||
``` go
|
|
||||||
func AlreadyExistsf(format string, args ...interface{}) error
|
|
||||||
```
|
|
||||||
AlreadyExistsf returns an error which satisfies IsAlreadyExists().
|
|
||||||
|
|
||||||
|
|
||||||
## func Annotate
|
|
||||||
``` go
|
|
||||||
func Annotate(other error, message string) error
|
|
||||||
```
|
|
||||||
Annotate is used to add extra context to an existing error. The location of
|
|
||||||
the Annotate call is recorded with the annotations. The file, line and
|
|
||||||
function are also recorded.
|
|
||||||
|
|
||||||
For example:
|
|
||||||
|
|
||||||
|
|
||||||
if err := SomeFunc(); err != nil {
|
|
||||||
return errors.Annotate(err, "failed to frombulate")
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
## func Annotatef
|
|
||||||
``` go
|
|
||||||
func Annotatef(other error, format string, args ...interface{}) error
|
|
||||||
```
|
|
||||||
Annotatef is used to add extra context to an existing error. The location of
|
|
||||||
the Annotate call is recorded with the annotations. The file, line and
|
|
||||||
function are also recorded.
|
|
||||||
|
|
||||||
For example:
|
|
||||||
|
|
||||||
|
|
||||||
if err := SomeFunc(); err != nil {
|
|
||||||
return errors.Annotatef(err, "failed to frombulate the %s", arg)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
## func BadRequestf
|
|
||||||
``` go
|
|
||||||
func BadRequestf(format string, args ...interface{}) error
|
|
||||||
```
|
|
||||||
BadRequestf returns an error which satisfies IsBadRequest().
|
|
||||||
|
|
||||||
|
|
||||||
## func Cause
|
|
||||||
``` go
|
|
||||||
func Cause(err error) error
|
|
||||||
```
|
|
||||||
Cause returns the cause of the given error. This will be either the
|
|
||||||
original error, or the result of a Wrap or Mask call.
|
|
||||||
|
|
||||||
Cause is the usual way to diagnose errors that may have been wrapped by
|
|
||||||
the other errors functions.
|
|
||||||
|
|
||||||
|
|
||||||
## func DeferredAnnotatef
|
|
||||||
``` go
|
|
||||||
func DeferredAnnotatef(err *error, format string, args ...interface{})
|
|
||||||
```
|
|
||||||
DeferredAnnotatef annotates the given error (when it is not nil) with the given
|
|
||||||
format string and arguments (like fmt.Sprintf). If *err is nil, DeferredAnnotatef
|
|
||||||
does nothing. This method is used in a defer statement in order to annotate any
|
|
||||||
resulting error with the same message.
|
|
||||||
|
|
||||||
For example:
|
|
||||||
|
|
||||||
|
|
||||||
defer DeferredAnnotatef(&err, "failed to frombulate the %s", arg)
|
|
||||||
|
|
||||||
|
|
||||||
## func Details
|
|
||||||
``` go
|
|
||||||
func Details(err error) string
|
|
||||||
```
|
|
||||||
Details returns information about the stack of errors wrapped by err, in
|
|
||||||
the format:
|
|
||||||
|
|
||||||
|
|
||||||
[{filename:99: error one} {otherfile:55: cause of error one}]
|
|
||||||
|
|
||||||
This is a terse alternative to ErrorStack as it returns a single line.
|
|
||||||
|
|
||||||
|
|
||||||
## func ErrorStack
|
|
||||||
``` go
|
|
||||||
func ErrorStack(err error) string
|
|
||||||
```
|
|
||||||
ErrorStack returns a string representation of the annotated error. If the
|
|
||||||
error passed as the parameter is not an annotated error, the result is
|
|
||||||
simply the result of the Error() method on that error.
|
|
||||||
|
|
||||||
If the error is an annotated error, a multi-line string is returned where
|
|
||||||
each line represents one entry in the annotation stack. The full filename
|
|
||||||
from the call stack is used in the output.
|
|
||||||
|
|
||||||
|
|
||||||
first error
|
|
||||||
github.com/juju/errors/annotation_test.go:193:
|
|
||||||
github.com/juju/errors/annotation_test.go:194: annotation
|
|
||||||
github.com/juju/errors/annotation_test.go:195:
|
|
||||||
github.com/juju/errors/annotation_test.go:196: more context
|
|
||||||
github.com/juju/errors/annotation_test.go:197:
|
|
||||||
|
|
||||||
|
|
||||||
## func Errorf
|
|
||||||
``` go
|
|
||||||
func Errorf(format string, args ...interface{}) error
|
|
||||||
```
|
|
||||||
Errorf creates a new annotated error and records the location that the
|
|
||||||
error is created. This should be a drop in replacement for fmt.Errorf.
|
|
||||||
|
|
||||||
For example:
|
|
||||||
|
|
||||||
|
|
||||||
return errors.Errorf("validation failed: %s", message)
|
|
||||||
|
|
||||||
|
|
||||||
## func Forbiddenf
|
|
||||||
``` go
|
|
||||||
func Forbiddenf(format string, args ...interface{}) error
|
|
||||||
```
|
|
||||||
Forbiddenf returns an error which satistifes IsForbidden()
|
|
||||||
|
|
||||||
|
|
||||||
## func IsAlreadyExists
|
|
||||||
``` go
|
|
||||||
func IsAlreadyExists(err error) bool
|
|
||||||
```
|
|
||||||
IsAlreadyExists reports whether the error was created with
|
|
||||||
AlreadyExistsf() or NewAlreadyExists().
|
|
||||||
|
|
||||||
|
|
||||||
## func IsBadRequest
|
|
||||||
``` go
|
|
||||||
func IsBadRequest(err error) bool
|
|
||||||
```
|
|
||||||
IsBadRequest reports whether err was created with BadRequestf() or
|
|
||||||
NewBadRequest().
|
|
||||||
|
|
||||||
|
|
||||||
## func IsForbidden
|
|
||||||
``` go
|
|
||||||
func IsForbidden(err error) bool
|
|
||||||
```
|
|
||||||
IsForbidden reports whether err was created with Forbiddenf() or
|
|
||||||
NewForbidden().
|
|
||||||
|
|
||||||
|
|
||||||
## func IsMethodNotAllowed
|
|
||||||
``` go
|
|
||||||
func IsMethodNotAllowed(err error) bool
|
|
||||||
```
|
|
||||||
IsMethodNotAllowed reports whether err was created with MethodNotAllowedf() or
|
|
||||||
NewMethodNotAllowed().
|
|
||||||
|
|
||||||
|
|
||||||
## func IsNotAssigned
|
|
||||||
``` go
|
|
||||||
func IsNotAssigned(err error) bool
|
|
||||||
```
|
|
||||||
IsNotAssigned reports whether err was created with NotAssignedf() or
|
|
||||||
NewNotAssigned().
|
|
||||||
|
|
||||||
|
|
||||||
## func IsNotFound
|
|
||||||
``` go
|
|
||||||
func IsNotFound(err error) bool
|
|
||||||
```
|
|
||||||
IsNotFound reports whether err was created with NotFoundf() or
|
|
||||||
NewNotFound().
|
|
||||||
|
|
||||||
|
|
||||||
## func IsNotImplemented
|
|
||||||
``` go
|
|
||||||
func IsNotImplemented(err error) bool
|
|
||||||
```
|
|
||||||
IsNotImplemented reports whether err was created with
|
|
||||||
NotImplementedf() or NewNotImplemented().
|
|
||||||
|
|
||||||
|
|
||||||
## func IsNotProvisioned
|
|
||||||
``` go
|
|
||||||
func IsNotProvisioned(err error) bool
|
|
||||||
```
|
|
||||||
IsNotProvisioned reports whether err was created with NotProvisionedf() or
|
|
||||||
NewNotProvisioned().
|
|
||||||
|
|
||||||
|
|
||||||
## func IsNotSupported
|
|
||||||
``` go
|
|
||||||
func IsNotSupported(err error) bool
|
|
||||||
```
|
|
||||||
IsNotSupported reports whether the error was created with
|
|
||||||
NotSupportedf() or NewNotSupported().
|
|
||||||
|
|
||||||
|
|
||||||
## func IsNotValid
|
|
||||||
``` go
|
|
||||||
func IsNotValid(err error) bool
|
|
||||||
```
|
|
||||||
IsNotValid reports whether the error was created with NotValidf() or
|
|
||||||
NewNotValid().
|
|
||||||
|
|
||||||
|
|
||||||
## func IsUnauthorized
|
|
||||||
``` go
|
|
||||||
func IsUnauthorized(err error) bool
|
|
||||||
```
|
|
||||||
IsUnauthorized reports whether err was created with Unauthorizedf() or
|
|
||||||
NewUnauthorized().
|
|
||||||
|
|
||||||
|
|
||||||
## func IsUserNotFound
|
|
||||||
``` go
|
|
||||||
func IsUserNotFound(err error) bool
|
|
||||||
```
|
|
||||||
IsUserNotFound reports whether err was created with UserNotFoundf() or
|
|
||||||
NewUserNotFound().
|
|
||||||
|
|
||||||
|
|
||||||
## func Mask
|
|
||||||
``` go
|
|
||||||
func Mask(other error) error
|
|
||||||
```
|
|
||||||
Mask hides the underlying error type, and records the location of the masking.
|
|
||||||
|
|
||||||
|
|
||||||
## func Maskf
|
|
||||||
``` go
|
|
||||||
func Maskf(other error, format string, args ...interface{}) error
|
|
||||||
```
|
|
||||||
Mask masks the given error with the given format string and arguments (like
|
|
||||||
fmt.Sprintf), returning a new error that maintains the error stack, but
|
|
||||||
hides the underlying error type. The error string still contains the full
|
|
||||||
annotations. If you want to hide the annotations, call Wrap.
|
|
||||||
|
|
||||||
|
|
||||||
## func MethodNotAllowedf
|
|
||||||
``` go
|
|
||||||
func MethodNotAllowedf(format string, args ...interface{}) error
|
|
||||||
```
|
|
||||||
MethodNotAllowedf returns an error which satisfies IsMethodNotAllowed().
|
|
||||||
|
|
||||||
|
|
||||||
## func New
|
|
||||||
``` go
|
|
||||||
func New(message string) error
|
|
||||||
```
|
|
||||||
New is a drop in replacement for the standard library errors module that records
|
|
||||||
the location that the error is created.
|
|
||||||
|
|
||||||
For example:
|
|
||||||
|
|
||||||
|
|
||||||
return errors.New("validation failed")
|
|
||||||
|
|
||||||
|
|
||||||
## func NewAlreadyExists
|
|
||||||
``` go
|
|
||||||
func NewAlreadyExists(err error, msg string) error
|
|
||||||
```
|
|
||||||
NewAlreadyExists returns an error which wraps err and satisfies
|
|
||||||
IsAlreadyExists().
|
|
||||||
|
|
||||||
|
|
||||||
## func NewBadRequest
|
|
||||||
``` go
|
|
||||||
func NewBadRequest(err error, msg string) error
|
|
||||||
```
|
|
||||||
NewBadRequest returns an error which wraps err that satisfies
|
|
||||||
IsBadRequest().
|
|
||||||
|
|
||||||
|
|
||||||
## func NewForbidden
|
|
||||||
``` go
|
|
||||||
func NewForbidden(err error, msg string) error
|
|
||||||
```
|
|
||||||
NewForbidden returns an error which wraps err that satisfies
|
|
||||||
IsForbidden().
|
|
||||||
|
|
||||||
|
|
||||||
## func NewMethodNotAllowed
|
|
||||||
``` go
|
|
||||||
func NewMethodNotAllowed(err error, msg string) error
|
|
||||||
```
|
|
||||||
NewMethodNotAllowed returns an error which wraps err that satisfies
|
|
||||||
IsMethodNotAllowed().
|
|
||||||
|
|
||||||
|
|
||||||
## func NewNotAssigned
|
|
||||||
``` go
|
|
||||||
func NewNotAssigned(err error, msg string) error
|
|
||||||
```
|
|
||||||
NewNotAssigned returns an error which wraps err that satisfies
|
|
||||||
IsNotAssigned().
|
|
||||||
|
|
||||||
|
|
||||||
## func NewNotFound
|
|
||||||
``` go
|
|
||||||
func NewNotFound(err error, msg string) error
|
|
||||||
```
|
|
||||||
NewNotFound returns an error which wraps err that satisfies
|
|
||||||
IsNotFound().
|
|
||||||
|
|
||||||
|
|
||||||
## func NewNotImplemented
|
|
||||||
``` go
|
|
||||||
func NewNotImplemented(err error, msg string) error
|
|
||||||
```
|
|
||||||
NewNotImplemented returns an error which wraps err and satisfies
|
|
||||||
IsNotImplemented().
|
|
||||||
|
|
||||||
|
|
||||||
## func NewNotProvisioned
|
|
||||||
``` go
|
|
||||||
func NewNotProvisioned(err error, msg string) error
|
|
||||||
```
|
|
||||||
NewNotProvisioned returns an error which wraps err that satisfies
|
|
||||||
IsNotProvisioned().
|
|
||||||
|
|
||||||
|
|
||||||
## func NewNotSupported
|
|
||||||
``` go
|
|
||||||
func NewNotSupported(err error, msg string) error
|
|
||||||
```
|
|
||||||
NewNotSupported returns an error which wraps err and satisfies
|
|
||||||
IsNotSupported().
|
|
||||||
|
|
||||||
|
|
||||||
## func NewNotValid
|
|
||||||
``` go
|
|
||||||
func NewNotValid(err error, msg string) error
|
|
||||||
```
|
|
||||||
NewNotValid returns an error which wraps err and satisfies IsNotValid().
|
|
||||||
|
|
||||||
|
|
||||||
## func NewUnauthorized
|
|
||||||
``` go
|
|
||||||
func NewUnauthorized(err error, msg string) error
|
|
||||||
```
|
|
||||||
NewUnauthorized returns an error which wraps err and satisfies
|
|
||||||
IsUnauthorized().
|
|
||||||
|
|
||||||
|
|
||||||
## func NewUserNotFound
|
|
||||||
``` go
|
|
||||||
func NewUserNotFound(err error, msg string) error
|
|
||||||
```
|
|
||||||
NewUserNotFound returns an error which wraps err and satisfies
|
|
||||||
IsUserNotFound().
|
|
||||||
|
|
||||||
|
|
||||||
## func NotAssignedf
|
|
||||||
``` go
|
|
||||||
func NotAssignedf(format string, args ...interface{}) error
|
|
||||||
```
|
|
||||||
NotAssignedf returns an error which satisfies IsNotAssigned().
|
|
||||||
|
|
||||||
|
|
||||||
## func NotFoundf
|
|
||||||
``` go
|
|
||||||
func NotFoundf(format string, args ...interface{}) error
|
|
||||||
```
|
|
||||||
NotFoundf returns an error which satisfies IsNotFound().
|
|
||||||
|
|
||||||
|
|
||||||
## func NotImplementedf
|
|
||||||
``` go
|
|
||||||
func NotImplementedf(format string, args ...interface{}) error
|
|
||||||
```
|
|
||||||
NotImplementedf returns an error which satisfies IsNotImplemented().
|
|
||||||
|
|
||||||
|
|
||||||
## func NotProvisionedf
|
|
||||||
``` go
|
|
||||||
func NotProvisionedf(format string, args ...interface{}) error
|
|
||||||
```
|
|
||||||
NotProvisionedf returns an error which satisfies IsNotProvisioned().
|
|
||||||
|
|
||||||
|
|
||||||
## func NotSupportedf
|
|
||||||
``` go
|
|
||||||
func NotSupportedf(format string, args ...interface{}) error
|
|
||||||
```
|
|
||||||
NotSupportedf returns an error which satisfies IsNotSupported().
|
|
||||||
|
|
||||||
|
|
||||||
## func NotValidf
|
|
||||||
``` go
|
|
||||||
func NotValidf(format string, args ...interface{}) error
|
|
||||||
```
|
|
||||||
NotValidf returns an error which satisfies IsNotValid().
|
|
||||||
|
|
||||||
|
|
||||||
## func Trace
|
|
||||||
``` go
|
|
||||||
func Trace(other error) error
|
|
||||||
```
|
|
||||||
Trace adds the location of the Trace call to the stack. The Cause of the
|
|
||||||
resulting error is the same as the error parameter. If the other error is
|
|
||||||
nil, the result will be nil.
|
|
||||||
|
|
||||||
For example:
|
|
||||||
|
|
||||||
|
|
||||||
if err := SomeFunc(); err != nil {
|
|
||||||
return errors.Trace(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
## func Unauthorizedf
|
|
||||||
``` go
|
|
||||||
func Unauthorizedf(format string, args ...interface{}) error
|
|
||||||
```
|
|
||||||
Unauthorizedf returns an error which satisfies IsUnauthorized().
|
|
||||||
|
|
||||||
|
|
||||||
## func UserNotFoundf
|
|
||||||
``` go
|
|
||||||
func UserNotFoundf(format string, args ...interface{}) error
|
|
||||||
```
|
|
||||||
UserNotFoundf returns an error which satisfies IsUserNotFound().
|
|
||||||
|
|
||||||
|
|
||||||
## func Wrap
|
|
||||||
``` go
|
|
||||||
func Wrap(other, newDescriptive error) error
|
|
||||||
```
|
|
||||||
Wrap changes the Cause of the error. The location of the Wrap call is also
|
|
||||||
stored in the error stack.
|
|
||||||
|
|
||||||
For example:
|
|
||||||
|
|
||||||
|
|
||||||
if err := SomeFunc(); err != nil {
|
|
||||||
newErr := &packageError{"more context", private_value}
|
|
||||||
return errors.Wrap(err, newErr)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
## func Wrapf
|
|
||||||
``` go
|
|
||||||
func Wrapf(other, newDescriptive error, format string, args ...interface{}) error
|
|
||||||
```
|
|
||||||
Wrapf changes the Cause of the error, and adds an annotation. The location
|
|
||||||
of the Wrap call is also stored in the error stack.
|
|
||||||
|
|
||||||
For example:
|
|
||||||
|
|
||||||
|
|
||||||
if err := SomeFunc(); err != nil {
|
|
||||||
return errors.Wrapf(err, simpleErrorType, "invalid value %q", value)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## type Err
|
|
||||||
``` go
|
|
||||||
type Err struct {
|
|
||||||
// contains filtered or unexported fields
|
|
||||||
}
|
|
||||||
```
|
|
||||||
Err holds a description of an error along with information about
|
|
||||||
where the error was created.
|
|
||||||
|
|
||||||
It may be embedded in custom error types to add extra information that
|
|
||||||
this errors package can understand.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### func NewErr
|
|
||||||
``` go
|
|
||||||
func NewErr(format string, args ...interface{}) Err
|
|
||||||
```
|
|
||||||
NewErr is used to return an Err for the purpose of embedding in other
|
|
||||||
structures. The location is not specified, and needs to be set with a call
|
|
||||||
to SetLocation.
|
|
||||||
|
|
||||||
For example:
|
|
||||||
|
|
||||||
|
|
||||||
type FooError struct {
|
|
||||||
errors.Err
|
|
||||||
code int
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewFooError(code int) error {
|
|
||||||
err := &FooError{errors.NewErr("foo"), code}
|
|
||||||
err.SetLocation(1)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
### func NewErrWithCause
|
|
||||||
``` go
|
|
||||||
func NewErrWithCause(other error, format string, args ...interface{}) Err
|
|
||||||
```
|
|
||||||
NewErrWithCause is used to return an Err with cause by other error for the purpose of embedding in other
|
|
||||||
structures. The location is not specified, and needs to be set with a call
|
|
||||||
to SetLocation.
|
|
||||||
|
|
||||||
For example:
|
|
||||||
|
|
||||||
|
|
||||||
type FooError struct {
|
|
||||||
errors.Err
|
|
||||||
code int
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *FooError) Annotate(format string, args ...interface{}) error {
|
|
||||||
err := &FooError{errors.NewErrWithCause(e.Err, format, args...), e.code}
|
|
||||||
err.SetLocation(1)
|
|
||||||
return err
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### func (\*Err) Cause
|
|
||||||
``` go
|
|
||||||
func (e *Err) Cause() error
|
|
||||||
```
|
|
||||||
The Cause of an error is the most recent error in the error stack that
|
|
||||||
meets one of these criteria: the original error that was raised; the new
|
|
||||||
error that was passed into the Wrap function; the most recently masked
|
|
||||||
error; or nil if the error itself is considered the Cause. Normally this
|
|
||||||
method is not invoked directly, but instead through the Cause stand alone
|
|
||||||
function.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### func (\*Err) Error
|
|
||||||
``` go
|
|
||||||
func (e *Err) Error() string
|
|
||||||
```
|
|
||||||
Error implements error.Error.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### func (\*Err) Format
|
|
||||||
``` go
|
|
||||||
func (e *Err) Format(s fmt.State, verb rune)
|
|
||||||
```
|
|
||||||
Format implements fmt.Formatter
|
|
||||||
When printing errors with %+v it also prints the stack trace.
|
|
||||||
%#v unsurprisingly will print the real underlying type.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### func (\*Err) Location
|
|
||||||
``` go
|
|
||||||
func (e *Err) Location() (filename string, line int)
|
|
||||||
```
|
|
||||||
Location is the file and line of where the error was most recently
|
|
||||||
created or annotated.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### func (\*Err) Message
|
|
||||||
``` go
|
|
||||||
func (e *Err) Message() string
|
|
||||||
```
|
|
||||||
Message returns the message stored with the most recent location. This is
|
|
||||||
the empty string if the most recent call was Trace, or the message stored
|
|
||||||
with Annotate or Mask.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### func (\*Err) SetLocation
|
|
||||||
``` go
|
|
||||||
func (e *Err) SetLocation(callDepth int)
|
|
||||||
```
|
|
||||||
SetLocation records the source location of the error at callDepth stack
|
|
||||||
frames above the call.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### func (\*Err) StackTrace
|
|
||||||
``` go
|
|
||||||
func (e *Err) StackTrace() []string
|
|
||||||
```
|
|
||||||
StackTrace returns one string for each location recorded in the stack of
|
|
||||||
errors. The first value is the originating error, with a line for each
|
|
||||||
other annotation or tracing of the error.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### func (\*Err) Underlying
|
|
||||||
``` go
|
|
||||||
func (e *Err) Underlying() error
|
|
||||||
```
|
|
||||||
Underlying returns the previous error in the error stack, if any. A client
|
|
||||||
should not ever really call this method. It is used to build the error
|
|
||||||
stack and should not be introspected by client calls. Or more
|
|
||||||
specifically, clients should not depend on anything but the `Cause` of an
|
|
||||||
error.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
- - -
|
|
||||||
Generated by [godoc2md](http://godoc.org/github.com/davecheney/godoc2md)
|
|
||||||
79
vendor/github.com/juju/errors/doc.go
generated
vendored
79
vendor/github.com/juju/errors/doc.go
generated
vendored
|
|
@ -1,79 +0,0 @@
|
||||||
// Copyright 2013, 2014 Canonical Ltd.
|
|
||||||
// Licensed under the LGPLv3, see LICENCE file for details.
|
|
||||||
|
|
||||||
/*
|
|
||||||
Package errors provides an easy way to annotate errors without losing the
|
|
||||||
original error context.
|
|
||||||
|
|
||||||
The exported `New` and `Errorf` functions are designed to replace the
|
|
||||||
`errors.New` and `fmt.Errorf` functions respectively. The same underlying
|
|
||||||
error is there, but the package also records the location at which the error
|
|
||||||
was created.
|
|
||||||
|
|
||||||
A primary use case for this library is to add extra context any time an
|
|
||||||
error is returned from a function.
|
|
||||||
|
|
||||||
if err := SomeFunc(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
This instead becomes:
|
|
||||||
|
|
||||||
if err := SomeFunc(); err != nil {
|
|
||||||
return errors.Trace(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
which just records the file and line number of the Trace call, or
|
|
||||||
|
|
||||||
if err := SomeFunc(); err != nil {
|
|
||||||
return errors.Annotate(err, "more context")
|
|
||||||
}
|
|
||||||
|
|
||||||
which also adds an annotation to the error.
|
|
||||||
|
|
||||||
When you want to check to see if an error is of a particular type, a helper
|
|
||||||
function is normally exported by the package that returned the error, like the
|
|
||||||
`os` package does. The underlying cause of the error is available using the
|
|
||||||
`Cause` function.
|
|
||||||
|
|
||||||
os.IsNotExist(errors.Cause(err))
|
|
||||||
|
|
||||||
The result of the `Error()` call on an annotated error is the annotations joined
|
|
||||||
with colons, then the result of the `Error()` method for the underlying error
|
|
||||||
that was the cause.
|
|
||||||
|
|
||||||
err := errors.Errorf("original")
|
|
||||||
err = errors.Annotatef(err, "context")
|
|
||||||
err = errors.Annotatef(err, "more context")
|
|
||||||
err.Error() -> "more context: context: original"
|
|
||||||
|
|
||||||
Obviously recording the file, line and functions is not very useful if you
|
|
||||||
cannot get them back out again.
|
|
||||||
|
|
||||||
errors.ErrorStack(err)
|
|
||||||
|
|
||||||
will return something like:
|
|
||||||
|
|
||||||
first error
|
|
||||||
github.com/juju/errors/annotation_test.go:193:
|
|
||||||
github.com/juju/errors/annotation_test.go:194: annotation
|
|
||||||
github.com/juju/errors/annotation_test.go:195:
|
|
||||||
github.com/juju/errors/annotation_test.go:196: more context
|
|
||||||
github.com/juju/errors/annotation_test.go:197:
|
|
||||||
|
|
||||||
The first error was generated by an external system, so there was no location
|
|
||||||
associated. The second, fourth, and last lines were generated with Trace calls,
|
|
||||||
and the other two through Annotate.
|
|
||||||
|
|
||||||
Sometimes when responding to an error you want to return a more specific error
|
|
||||||
for the situation.
|
|
||||||
|
|
||||||
if err := FindField(field); err != nil {
|
|
||||||
return errors.Wrap(err, errors.NotFoundf(field))
|
|
||||||
}
|
|
||||||
|
|
||||||
This returns an error where the complete error stack is still available, and
|
|
||||||
`errors.Cause()` will return the `NotFound` error.
|
|
||||||
|
|
||||||
*/
|
|
||||||
package errors
|
|
||||||
227
vendor/github.com/juju/errors/error.go
generated
vendored
227
vendor/github.com/juju/errors/error.go
generated
vendored
|
|
@ -1,227 +0,0 @@
|
||||||
// Copyright 2014 Canonical Ltd.
|
|
||||||
// Licensed under the LGPLv3, see LICENCE file for details.
|
|
||||||
|
|
||||||
package errors
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"reflect"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Err holds a description of an error along with information about
|
|
||||||
// where the error was created.
|
|
||||||
//
|
|
||||||
// It may be embedded in custom error types to add extra information that
|
|
||||||
// this errors package can understand.
|
|
||||||
type Err struct {
|
|
||||||
// message holds an annotation of the error.
|
|
||||||
message string
|
|
||||||
|
|
||||||
// cause holds the cause of the error as returned
|
|
||||||
// by the Cause method.
|
|
||||||
cause error
|
|
||||||
|
|
||||||
// previous holds the previous error in the error stack, if any.
|
|
||||||
previous error
|
|
||||||
|
|
||||||
// function is the package path-qualified function name where the
|
|
||||||
// error was created.
|
|
||||||
function string
|
|
||||||
|
|
||||||
// line is the line number the error was created on inside of function
|
|
||||||
line int
|
|
||||||
}
|
|
||||||
|
|
||||||
// Locationer is an interface that represents a certain class of errors that
|
|
||||||
// contain the location information from where they were raised.
|
|
||||||
type Locationer interface {
|
|
||||||
// Location returns the path-qualified function name where the error was
|
|
||||||
// created and the line number
|
|
||||||
Location() (function string, line int)
|
|
||||||
}
|
|
||||||
|
|
||||||
// locationError is the internal implementation of the Locationer interface.
|
|
||||||
type locationError struct {
|
|
||||||
error
|
|
||||||
|
|
||||||
// function is the package path-qualified function name where the
|
|
||||||
// error was created.
|
|
||||||
function string
|
|
||||||
|
|
||||||
// line is the line number the error was created on inside of function
|
|
||||||
line int
|
|
||||||
}
|
|
||||||
|
|
||||||
// newLocationError constructs a new Locationer error from the supplied error
|
|
||||||
// with the location set to callDepth in the stack. If a nill error is provided
|
|
||||||
// to this function then a new empty error is constructed.
|
|
||||||
func newLocationError(err error, callDepth int) *locationError {
|
|
||||||
le := &locationError{error: err}
|
|
||||||
le.function, le.line = getLocation(callDepth + 1)
|
|
||||||
return le
|
|
||||||
}
|
|
||||||
|
|
||||||
// Error implementes the error interface.
|
|
||||||
func (l *locationError) Error() string {
|
|
||||||
if l.error == nil {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
return l.error.Error()
|
|
||||||
}
|
|
||||||
|
|
||||||
// *locationError implements Locationer.Location interface
|
|
||||||
func (l *locationError) Location() (string, int) {
|
|
||||||
return l.function, l.line
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l *locationError) Unwrap() error {
|
|
||||||
return l.error
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewErr is used to return an Err for the purpose of embedding in other
|
|
||||||
// structures. The location is not specified, and needs to be set with a call
|
|
||||||
// to SetLocation.
|
|
||||||
//
|
|
||||||
// For example:
|
|
||||||
// type FooError struct {
|
|
||||||
// errors.Err
|
|
||||||
// code int
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// func NewFooError(code int) error {
|
|
||||||
// err := &FooError{errors.NewErr("foo"), code}
|
|
||||||
// err.SetLocation(1)
|
|
||||||
// return err
|
|
||||||
// }
|
|
||||||
func NewErr(format string, args ...interface{}) Err {
|
|
||||||
return Err{
|
|
||||||
message: fmt.Sprintf(format, args...),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewErrWithCause is used to return an Err with cause by other error for the purpose of embedding in other
|
|
||||||
// structures. The location is not specified, and needs to be set with a call
|
|
||||||
// to SetLocation.
|
|
||||||
//
|
|
||||||
// For example:
|
|
||||||
// type FooError struct {
|
|
||||||
// errors.Err
|
|
||||||
// code int
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// func (e *FooError) Annotate(format string, args ...interface{}) error {
|
|
||||||
// err := &FooError{errors.NewErrWithCause(e.Err, format, args...), e.code}
|
|
||||||
// err.SetLocation(1)
|
|
||||||
// return err
|
|
||||||
// })
|
|
||||||
func NewErrWithCause(other error, format string, args ...interface{}) Err {
|
|
||||||
return Err{
|
|
||||||
message: fmt.Sprintf(format, args...),
|
|
||||||
cause: Cause(other),
|
|
||||||
previous: other,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Location returns the package path-qualified function name and line of where
|
|
||||||
// the error was most recently created or annotated.
|
|
||||||
func (e *Err) Location() (function string, line int) {
|
|
||||||
return e.function, e.line
|
|
||||||
}
|
|
||||||
|
|
||||||
// Underlying returns the previous error in the error stack, if any. A client
|
|
||||||
// should not ever really call this method. It is used to build the error
|
|
||||||
// stack and should not be introspected by client calls. Or more
|
|
||||||
// specifically, clients should not depend on anything but the `Cause` of an
|
|
||||||
// error.
|
|
||||||
func (e *Err) Underlying() error {
|
|
||||||
return e.previous
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cause returns the most recent error in the error stack that
|
|
||||||
// meets one of these criteria: the original error that was raised; the new
|
|
||||||
// error that was passed into the Wrap function; the most recently masked
|
|
||||||
// error; or nil if the error itself is considered the Cause. Normally this
|
|
||||||
// method is not invoked directly, but instead through the Cause stand alone
|
|
||||||
// function.
|
|
||||||
func (e *Err) Cause() error {
|
|
||||||
return e.cause
|
|
||||||
}
|
|
||||||
|
|
||||||
// Message returns the message stored with the most recent location. This is
|
|
||||||
// the empty string if the most recent call was Trace, or the message stored
|
|
||||||
// with Annotate or Mask.
|
|
||||||
func (e *Err) Message() string {
|
|
||||||
return e.message
|
|
||||||
}
|
|
||||||
|
|
||||||
// Error implements error.Error.
|
|
||||||
func (e *Err) Error() string {
|
|
||||||
// We want to walk up the stack of errors showing the annotations
|
|
||||||
// as long as the cause is the same.
|
|
||||||
err := e.previous
|
|
||||||
if !sameError(Cause(err), e.cause) && e.cause != nil {
|
|
||||||
err = e.cause
|
|
||||||
}
|
|
||||||
switch {
|
|
||||||
case err == nil:
|
|
||||||
return e.message
|
|
||||||
case e.message == "":
|
|
||||||
return err.Error()
|
|
||||||
}
|
|
||||||
return fmt.Sprintf("%s: %v", e.message, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Format implements fmt.Formatter
|
|
||||||
// When printing errors with %+v it also prints the stack trace.
|
|
||||||
// %#v unsurprisingly will print the real underlying type.
|
|
||||||
func (e *Err) Format(s fmt.State, verb rune) {
|
|
||||||
switch verb {
|
|
||||||
case 'v':
|
|
||||||
switch {
|
|
||||||
case s.Flag('+'):
|
|
||||||
fmt.Fprintf(s, "%s", ErrorStack(e))
|
|
||||||
return
|
|
||||||
case s.Flag('#'):
|
|
||||||
// avoid infinite recursion by wrapping e into a type
|
|
||||||
// that doesn't implement Formatter.
|
|
||||||
fmt.Fprintf(s, "%#v", (*unformatter)(e))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
fallthrough
|
|
||||||
case 's':
|
|
||||||
fmt.Fprintf(s, "%s", e.Error())
|
|
||||||
case 'q':
|
|
||||||
fmt.Fprintf(s, "%q", e.Error())
|
|
||||||
default:
|
|
||||||
fmt.Fprintf(s, "%%!%c(%T=%s)", verb, e, e.Error())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// helper for Format
|
|
||||||
type unformatter Err
|
|
||||||
|
|
||||||
func (unformatter) Format() { /* break the fmt.Formatter interface */ }
|
|
||||||
|
|
||||||
// SetLocation records the package path-qualified function name of the error at
|
|
||||||
// callDepth stack frames above the call.
|
|
||||||
func (e *Err) SetLocation(callDepth int) {
|
|
||||||
e.function, e.line = getLocation(callDepth + 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
// StackTrace returns one string for each location recorded in the stack of
|
|
||||||
// errors. The first value is the originating error, with a line for each
|
|
||||||
// other annotation or tracing of the error.
|
|
||||||
func (e *Err) StackTrace() []string {
|
|
||||||
return errorStack(e)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ideally we'd have a way to check identity, but deep equals will do.
|
|
||||||
func sameError(e1, e2 error) bool {
|
|
||||||
return reflect.DeepEqual(e1, e2)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unwrap is a synonym for Underlying, which allows Err to be used with the
|
|
||||||
// Unwrap, Is and As functions in Go's standard `errors` library.
|
|
||||||
func (e *Err) Unwrap() error {
|
|
||||||
return e.previous
|
|
||||||
}
|
|
||||||
473
vendor/github.com/juju/errors/errortypes.go
generated
vendored
473
vendor/github.com/juju/errors/errortypes.go
generated
vendored
|
|
@ -1,473 +0,0 @@
|
||||||
// Copyright 2014 Canonical Ltd.
|
|
||||||
// Licensed under the LGPLv3, see LICENCE file for details.
|
|
||||||
|
|
||||||
package errors
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
stderror "errors"
|
|
||||||
"fmt"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
// a ConstError is a prototype for a certain type of error
|
|
||||||
type ConstError string
|
|
||||||
|
|
||||||
// ConstError implements error
|
|
||||||
func (e ConstError) Error() string {
|
|
||||||
return string(e)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Different types of errors
|
|
||||||
const (
|
|
||||||
// Timeout represents an error on timeout.
|
|
||||||
Timeout = ConstError("timeout")
|
|
||||||
// NotFound represents an error when something has not been found.
|
|
||||||
NotFound = ConstError("not found")
|
|
||||||
// UserNotFound represents an error when a non-existent user is looked up.
|
|
||||||
UserNotFound = ConstError("user not found")
|
|
||||||
// Unauthorized represents an error when an operation is unauthorized.
|
|
||||||
Unauthorized = ConstError("unauthorized")
|
|
||||||
// NotImplemented represents an error when something is not
|
|
||||||
// implemented.
|
|
||||||
NotImplemented = ConstError("not implemented")
|
|
||||||
// AlreadyExists represents and error when something already exists.
|
|
||||||
AlreadyExists = ConstError("already exists")
|
|
||||||
// NotSupported represents an error when something is not supported.
|
|
||||||
NotSupported = ConstError("not supported")
|
|
||||||
// NotValid represents an error when something is not valid.
|
|
||||||
NotValid = ConstError("not valid")
|
|
||||||
// NotProvisioned represents an error when something is not yet provisioned.
|
|
||||||
NotProvisioned = ConstError("not provisioned")
|
|
||||||
// NotAssigned represents an error when something is not yet assigned to
|
|
||||||
// something else.
|
|
||||||
NotAssigned = ConstError("not assigned")
|
|
||||||
// BadRequest represents an error when a request has bad parameters.
|
|
||||||
BadRequest = ConstError("bad request")
|
|
||||||
// MethodNotAllowed represents an error when an HTTP request
|
|
||||||
// is made with an inappropriate method.
|
|
||||||
MethodNotAllowed = ConstError("method not allowed")
|
|
||||||
// Forbidden represents an error when a request cannot be completed because of
|
|
||||||
// missing privileges.
|
|
||||||
Forbidden = ConstError("forbidden")
|
|
||||||
// QuotaLimitExceeded is emitted when an action failed due to a quota limit check.
|
|
||||||
QuotaLimitExceeded = ConstError("quota limit exceeded")
|
|
||||||
// NotYetAvailable is the error returned when a resource is not yet available
|
|
||||||
// but it might be in the future.
|
|
||||||
NotYetAvailable = ConstError("not yet available")
|
|
||||||
)
|
|
||||||
|
|
||||||
// errWithType is an Err bundled with its error type (a ConstError)
|
|
||||||
type errWithType struct {
|
|
||||||
error
|
|
||||||
errType ConstError
|
|
||||||
}
|
|
||||||
|
|
||||||
// Is compares `target` with e's error type
|
|
||||||
func (e *errWithType) Is(target error) bool {
|
|
||||||
if &e.errType == nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return target == e.errType
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unwrap an errWithType gives the underlying Err
|
|
||||||
func (e *errWithType) Unwrap() error {
|
|
||||||
return e.error
|
|
||||||
}
|
|
||||||
|
|
||||||
func wrapErrorWithMsg(err error, msg string) error {
|
|
||||||
if err == nil {
|
|
||||||
return stderror.New(msg)
|
|
||||||
}
|
|
||||||
if msg == "" {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return fmt.Errorf("%s: %w", msg, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
func makeWrappedConstError(err error, format string, args ...interface{}) error {
|
|
||||||
separator := " "
|
|
||||||
if err.Error() == "" || errors.Is(err, &fmtNoop{}) {
|
|
||||||
separator = ""
|
|
||||||
}
|
|
||||||
return fmt.Errorf(strings.Join([]string{format, "%w"}, separator), append(args, err)...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithType is responsible for annotating an already existing error so that it
|
|
||||||
// also satisfies that of a ConstError. The resultant error returned should
|
|
||||||
// satisfy Is(err, errType). If err is nil then a nil error will also be returned.
|
|
||||||
//
|
|
||||||
// Now with Go's Is, As and Unwrap support it no longer makes sense to Wrap()
|
|
||||||
// 2 errors as both of those errors could be chains of errors in their own right.
|
|
||||||
// WithType aims to solve some of the usefulness of Wrap with the ability to
|
|
||||||
// make a pre-existing error also satisfy a ConstError type.
|
|
||||||
func WithType(err error, errType ConstError) error {
|
|
||||||
if err == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return &errWithType{
|
|
||||||
error: err,
|
|
||||||
errType: errType,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Timeoutf returns an error which satisfies Is(err, Timeout) and the Locationer
|
|
||||||
// interface.
|
|
||||||
func Timeoutf(format string, args ...interface{}) error {
|
|
||||||
return newLocationError(
|
|
||||||
makeWrappedConstError(Timeout, format, args...),
|
|
||||||
1,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewTimeout returns an error which wraps err and satisfies Is(err, Timeout)
|
|
||||||
// and the Locationer interface.
|
|
||||||
func NewTimeout(err error, msg string) error {
|
|
||||||
return &errWithType{
|
|
||||||
error: newLocationError(wrapErrorWithMsg(err, msg), 1),
|
|
||||||
errType: Timeout,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deprecated: IsTimeout reports whether err is a Timeout error. Use
|
|
||||||
// Is(err, Timeout).
|
|
||||||
func IsTimeout(err error) bool {
|
|
||||||
return Is(err, Timeout)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NotFoundf returns an error which satisfies Is(err, NotFound) and the
|
|
||||||
// Locationer interface.
|
|
||||||
func NotFoundf(format string, args ...interface{}) error {
|
|
||||||
return newLocationError(
|
|
||||||
makeWrappedConstError(NotFound, format, args...),
|
|
||||||
1,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewNotFound returns an error which wraps err and satisfies Is(err, NotFound)
|
|
||||||
// and the Locationer interface.
|
|
||||||
func NewNotFound(err error, msg string) error {
|
|
||||||
return &errWithType{
|
|
||||||
error: newLocationError(wrapErrorWithMsg(err, msg), 1),
|
|
||||||
errType: NotFound,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deprecated: IsNotFound reports whether err is a NotFound error. Use
|
|
||||||
// Is(err, NotFound).
|
|
||||||
func IsNotFound(err error) bool {
|
|
||||||
return Is(err, NotFound)
|
|
||||||
}
|
|
||||||
|
|
||||||
// UserNotFoundf returns an error which satisfies Is(err, UserNotFound) and the
|
|
||||||
// Locationer interface.
|
|
||||||
func UserNotFoundf(format string, args ...interface{}) error {
|
|
||||||
return newLocationError(
|
|
||||||
makeWrappedConstError(UserNotFound, format, args...),
|
|
||||||
1,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewUserNotFound returns an error which wraps err and satisfies
|
|
||||||
// Is(err, UserNotFound) and the Locationer interface.
|
|
||||||
func NewUserNotFound(err error, msg string) error {
|
|
||||||
return &errWithType{
|
|
||||||
error: newLocationError(wrapErrorWithMsg(err, msg), 1),
|
|
||||||
errType: UserNotFound,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deprecated: IsUserNotFound reports whether err is a UserNotFound error. Use
|
|
||||||
// Is(err, UserNotFound).
|
|
||||||
func IsUserNotFound(err error) bool {
|
|
||||||
return Is(err, UserNotFound)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unauthorizedf returns an error that satisfies Is(err, Unauthorized) and
|
|
||||||
// the Locationer interface.
|
|
||||||
func Unauthorizedf(format string, args ...interface{}) error {
|
|
||||||
return newLocationError(
|
|
||||||
makeWrappedConstError(Hide(Unauthorized), format, args...),
|
|
||||||
1,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewUnauthorized returns an error which wraps err and satisfies
|
|
||||||
// Is(err, Unathorized) and the Locationer interface.
|
|
||||||
func NewUnauthorized(err error, msg string) error {
|
|
||||||
return &errWithType{
|
|
||||||
error: newLocationError(wrapErrorWithMsg(err, msg), 1),
|
|
||||||
errType: Unauthorized,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deprecated: IsUnauthorized reports whether err is a Unauthorized error. Use
|
|
||||||
// Is(err, Unauthorized).
|
|
||||||
func IsUnauthorized(err error) bool {
|
|
||||||
return Is(err, Unauthorized)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NotImplementedf returns an error which satisfies Is(err, NotImplemented) and
|
|
||||||
// the Locationer interface.
|
|
||||||
func NotImplementedf(format string, args ...interface{}) error {
|
|
||||||
return newLocationError(
|
|
||||||
makeWrappedConstError(NotImplemented, format, args...),
|
|
||||||
1,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewNotImplemented returns an error which wraps err and satisfies
|
|
||||||
// Is(err, NotImplemented) and the Locationer interface.
|
|
||||||
func NewNotImplemented(err error, msg string) error {
|
|
||||||
return &errWithType{
|
|
||||||
error: newLocationError(wrapErrorWithMsg(err, msg), 1),
|
|
||||||
errType: NotImplemented,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deprecated: IsNotImplemented reports whether err is a NotImplemented error.
|
|
||||||
// Use Is(err, NotImplemented).
|
|
||||||
func IsNotImplemented(err error) bool {
|
|
||||||
return Is(err, NotImplemented)
|
|
||||||
}
|
|
||||||
|
|
||||||
// AlreadyExistsf returns an error which satisfies Is(err, AlreadyExists) and
|
|
||||||
// the Locationer interface.
|
|
||||||
func AlreadyExistsf(format string, args ...interface{}) error {
|
|
||||||
return newLocationError(
|
|
||||||
makeWrappedConstError(AlreadyExists, format, args...),
|
|
||||||
1,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewAlreadyExists returns an error which wraps err and satisfies
|
|
||||||
// Is(err, AlreadyExists) and the Locationer interface.
|
|
||||||
func NewAlreadyExists(err error, msg string) error {
|
|
||||||
return &errWithType{
|
|
||||||
error: newLocationError(wrapErrorWithMsg(err, msg), 1),
|
|
||||||
errType: AlreadyExists,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deprecated: IsAlreadyExists reports whether the err is a AlreadyExists
|
|
||||||
// error. Use Is(err, AlreadyExists).
|
|
||||||
func IsAlreadyExists(err error) bool {
|
|
||||||
return Is(err, AlreadyExists)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NotSupportedf returns an error which satisfies Is(err, NotSupported) and the
|
|
||||||
// Locationer interface.
|
|
||||||
func NotSupportedf(format string, args ...interface{}) error {
|
|
||||||
return newLocationError(
|
|
||||||
makeWrappedConstError(NotSupported, format, args...),
|
|
||||||
1,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewNotSupported returns an error which satisfies Is(err, NotSupported) and
|
|
||||||
// the Locationer interface.
|
|
||||||
func NewNotSupported(err error, msg string) error {
|
|
||||||
return &errWithType{
|
|
||||||
error: newLocationError(wrapErrorWithMsg(err, msg), 1),
|
|
||||||
errType: NotSupported,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deprecated: IsNotSupported reports whether err is a NotSupported error. Use
|
|
||||||
// Is(err, NotSupported).
|
|
||||||
func IsNotSupported(err error) bool {
|
|
||||||
return Is(err, NotSupported)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NotValidf returns an error which satisfies Is(err, NotValid) and the
|
|
||||||
// Locationer interface.
|
|
||||||
func NotValidf(format string, args ...interface{}) error {
|
|
||||||
return newLocationError(
|
|
||||||
makeWrappedConstError(NotValid, format, args...),
|
|
||||||
1,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewNotValid returns an error which wraps err and satisfies Is(err, NotValid)
|
|
||||||
// and the Locationer interface.
|
|
||||||
func NewNotValid(err error, msg string) error {
|
|
||||||
return &errWithType{
|
|
||||||
error: newLocationError(wrapErrorWithMsg(err, msg), 1),
|
|
||||||
errType: NotValid,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deprecated: IsNotValid reports whether err is a NotValid error. Use
|
|
||||||
// Is(err, NotValid).
|
|
||||||
func IsNotValid(err error) bool {
|
|
||||||
return Is(err, NotValid)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NotProvisionedf returns an error which satisfies Is(err, NotProvisioned) and
|
|
||||||
// the Locationer interface.
|
|
||||||
func NotProvisionedf(format string, args ...interface{}) error {
|
|
||||||
return newLocationError(
|
|
||||||
makeWrappedConstError(NotProvisioned, format, args...),
|
|
||||||
1,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewNotProvisioned returns an error which wraps err and satisfies
|
|
||||||
// Is(err, NotProvisioned) and the Locationer interface.
|
|
||||||
func NewNotProvisioned(err error, msg string) error {
|
|
||||||
return &errWithType{
|
|
||||||
error: newLocationError(wrapErrorWithMsg(err, msg), 1),
|
|
||||||
errType: NotProvisioned,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deprecated: IsNotProvisioned reports whether err is a NotProvisioned error.
|
|
||||||
// Use Is(err, NotProvisioned).
|
|
||||||
func IsNotProvisioned(err error) bool {
|
|
||||||
return Is(err, NotProvisioned)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NotAssignedf returns an error which satisfies Is(err, NotAssigned) and the
|
|
||||||
// Locationer interface.
|
|
||||||
func NotAssignedf(format string, args ...interface{}) error {
|
|
||||||
return newLocationError(
|
|
||||||
makeWrappedConstError(NotAssigned, format, args...),
|
|
||||||
1,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewNotAssigned returns an error which wraps err and satisfies
|
|
||||||
// Is(err, NotAssigned) and the Locationer interface.
|
|
||||||
func NewNotAssigned(err error, msg string) error {
|
|
||||||
return &errWithType{
|
|
||||||
error: newLocationError(wrapErrorWithMsg(err, msg), 1),
|
|
||||||
errType: NotAssigned,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deprecated: IsNotAssigned reports whether err is a NotAssigned error.
|
|
||||||
// Use Is(err, NotAssigned)
|
|
||||||
func IsNotAssigned(err error) bool {
|
|
||||||
return Is(err, NotAssigned)
|
|
||||||
}
|
|
||||||
|
|
||||||
// BadRequestf returns an error which satisfies Is(err, BadRequest) and the
|
|
||||||
// Locationer interface.
|
|
||||||
func BadRequestf(format string, args ...interface{}) error {
|
|
||||||
return newLocationError(
|
|
||||||
makeWrappedConstError(Hide(BadRequest), format, args...),
|
|
||||||
1,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewBadRequest returns an error which wraps err and satisfies
|
|
||||||
// Is(err, BadRequest) and the Locationer interface.
|
|
||||||
func NewBadRequest(err error, msg string) error {
|
|
||||||
return &errWithType{
|
|
||||||
error: newLocationError(wrapErrorWithMsg(err, msg), 1),
|
|
||||||
errType: BadRequest,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deprecated: IsBadRequest reports whether err is a BadRequest error.
|
|
||||||
// Use Is(err, BadRequest)
|
|
||||||
func IsBadRequest(err error) bool {
|
|
||||||
return Is(err, BadRequest)
|
|
||||||
}
|
|
||||||
|
|
||||||
// MethodNotAllowedf returns an error which satisfies Is(err, MethodNotAllowed)
|
|
||||||
// and the Locationer interface.
|
|
||||||
func MethodNotAllowedf(format string, args ...interface{}) error {
|
|
||||||
return newLocationError(
|
|
||||||
makeWrappedConstError(Hide(MethodNotAllowed), format, args...),
|
|
||||||
1,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewMethodNotAllowed returns an error which wraps err and satisfies
|
|
||||||
// Is(err, MethodNotAllowed) and the Locationer interface.
|
|
||||||
func NewMethodNotAllowed(err error, msg string) error {
|
|
||||||
return &errWithType{
|
|
||||||
error: newLocationError(wrapErrorWithMsg(err, msg), 1),
|
|
||||||
errType: MethodNotAllowed,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deprecated: IsMethodNotAllowed reports whether err is a MethodNotAllowed
|
|
||||||
// error. Use Is(err, MethodNotAllowed)
|
|
||||||
func IsMethodNotAllowed(err error) bool {
|
|
||||||
return Is(err, MethodNotAllowed)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Forbiddenf returns an error which satistifes Is(err, Forbidden) and the
|
|
||||||
// Locationer interface.
|
|
||||||
func Forbiddenf(format string, args ...interface{}) error {
|
|
||||||
return newLocationError(
|
|
||||||
makeWrappedConstError(Hide(Forbidden), format, args...),
|
|
||||||
1,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewForbidden returns an error which wraps err and satisfies
|
|
||||||
// Is(err, Forbidden) and the Locationer interface.
|
|
||||||
func NewForbidden(err error, msg string) error {
|
|
||||||
return &errWithType{
|
|
||||||
error: newLocationError(wrapErrorWithMsg(err, msg), 1),
|
|
||||||
errType: Forbidden,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deprecated: IsForbidden reports whether err is a Forbidden error. Use
|
|
||||||
// Is(err, Forbidden).
|
|
||||||
func IsForbidden(err error) bool {
|
|
||||||
return Is(err, Forbidden)
|
|
||||||
}
|
|
||||||
|
|
||||||
// QuotaLimitExceededf returns an error which satisfies
|
|
||||||
// Is(err, QuotaLimitExceeded) and the Locationer interface.
|
|
||||||
func QuotaLimitExceededf(format string, args ...interface{}) error {
|
|
||||||
return newLocationError(
|
|
||||||
makeWrappedConstError(Hide(QuotaLimitExceeded), format, args...),
|
|
||||||
1,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewQuotaLimitExceeded returns an error which wraps err and satisfies
|
|
||||||
// Is(err, QuotaLimitExceeded) and the Locationer interface.
|
|
||||||
func NewQuotaLimitExceeded(err error, msg string) error {
|
|
||||||
return &errWithType{
|
|
||||||
error: newLocationError(wrapErrorWithMsg(err, msg), 1),
|
|
||||||
errType: QuotaLimitExceeded,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deprecated: IsQuotaLimitExceeded reports whether err is a QuoteLimitExceeded
|
|
||||||
// err. Use Is(err, QuotaLimitExceeded).
|
|
||||||
func IsQuotaLimitExceeded(err error) bool {
|
|
||||||
return Is(err, QuotaLimitExceeded)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NotYetAvailablef returns an error which satisfies Is(err, NotYetAvailable)
|
|
||||||
// and the Locationer interface.
|
|
||||||
func NotYetAvailablef(format string, args ...interface{}) error {
|
|
||||||
return newLocationError(
|
|
||||||
makeWrappedConstError(Hide(NotYetAvailable), format, args...),
|
|
||||||
1,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewNotYetAvailable returns an error which wraps err and satisfies
|
|
||||||
// Is(err, NotYetAvailable) and the Locationer interface.
|
|
||||||
func NewNotYetAvailable(err error, msg string) error {
|
|
||||||
return &errWithType{
|
|
||||||
error: newLocationError(wrapErrorWithMsg(err, msg), 1),
|
|
||||||
errType: NotYetAvailable,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deprecated: IsNotYetAvailable reports whether err is a NotYetAvailable err.
|
|
||||||
// Use Is(err, NotYetAvailable)
|
|
||||||
func IsNotYetAvailable(err error) bool {
|
|
||||||
return Is(err, NotYetAvailable)
|
|
||||||
}
|
|
||||||
454
vendor/github.com/juju/errors/functions.go
generated
vendored
454
vendor/github.com/juju/errors/functions.go
generated
vendored
|
|
@ -1,454 +0,0 @@
|
||||||
// Copyright 2014 Canonical Ltd.
|
|
||||||
// Licensed under the LGPLv3, see LICENCE file for details.
|
|
||||||
|
|
||||||
package errors
|
|
||||||
|
|
||||||
import (
|
|
||||||
stderrors "errors"
|
|
||||||
"fmt"
|
|
||||||
"runtime"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
// New is a drop in replacement for the standard library errors module that records
|
|
||||||
// the location that the error is created.
|
|
||||||
//
|
|
||||||
// For example:
|
|
||||||
// return errors.New("validation failed")
|
|
||||||
//
|
|
||||||
func New(message string) error {
|
|
||||||
err := &Err{message: message}
|
|
||||||
err.SetLocation(1)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Errorf creates a new annotated error and records the location that the
|
|
||||||
// error is created. This should be a drop in replacement for fmt.Errorf.
|
|
||||||
//
|
|
||||||
// For example:
|
|
||||||
// return errors.Errorf("validation failed: %s", message)
|
|
||||||
//
|
|
||||||
func Errorf(format string, args ...interface{}) error {
|
|
||||||
err := &Err{message: fmt.Sprintf(format, args...)}
|
|
||||||
err.SetLocation(1)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// getLocation records the package path-qualified function name of the error at
|
|
||||||
// callDepth stack frames above the call.
|
|
||||||
func getLocation(callDepth int) (string, int) {
|
|
||||||
rpc := make([]uintptr, 1)
|
|
||||||
n := runtime.Callers(callDepth+2, rpc[:])
|
|
||||||
if n < 1 {
|
|
||||||
return "", 0
|
|
||||||
}
|
|
||||||
frame, _ := runtime.CallersFrames(rpc).Next()
|
|
||||||
return frame.Function, frame.Line
|
|
||||||
}
|
|
||||||
|
|
||||||
// Trace adds the location of the Trace call to the stack. The Cause of the
|
|
||||||
// resulting error is the same as the error parameter. If the other error is
|
|
||||||
// nil, the result will be nil.
|
|
||||||
//
|
|
||||||
// For example:
|
|
||||||
// if err := SomeFunc(); err != nil {
|
|
||||||
// return errors.Trace(err)
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
func Trace(other error) error {
|
|
||||||
//return SetLocation(other, 2)
|
|
||||||
if other == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
err := &Err{previous: other, cause: Cause(other)}
|
|
||||||
err.SetLocation(1)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Annotate is used to add extra context to an existing error. The location of
|
|
||||||
// the Annotate call is recorded with the annotations. The file, line and
|
|
||||||
// function are also recorded.
|
|
||||||
//
|
|
||||||
// For example:
|
|
||||||
// if err := SomeFunc(); err != nil {
|
|
||||||
// return errors.Annotate(err, "failed to frombulate")
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
func Annotate(other error, message string) error {
|
|
||||||
if other == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
err := &Err{
|
|
||||||
previous: other,
|
|
||||||
cause: Cause(other),
|
|
||||||
message: message,
|
|
||||||
}
|
|
||||||
err.SetLocation(1)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Annotatef is used to add extra context to an existing error. The location of
|
|
||||||
// the Annotate call is recorded with the annotations. The file, line and
|
|
||||||
// function are also recorded.
|
|
||||||
//
|
|
||||||
// For example:
|
|
||||||
// if err := SomeFunc(); err != nil {
|
|
||||||
// return errors.Annotatef(err, "failed to frombulate the %s", arg)
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
func Annotatef(other error, format string, args ...interface{}) error {
|
|
||||||
if other == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
err := &Err{
|
|
||||||
previous: other,
|
|
||||||
cause: Cause(other),
|
|
||||||
message: fmt.Sprintf(format, args...),
|
|
||||||
}
|
|
||||||
err.SetLocation(1)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeferredAnnotatef annotates the given error (when it is not nil) with the given
|
|
||||||
// format string and arguments (like fmt.Sprintf). If *err is nil, DeferredAnnotatef
|
|
||||||
// does nothing. This method is used in a defer statement in order to annotate any
|
|
||||||
// resulting error with the same message.
|
|
||||||
//
|
|
||||||
// For example:
|
|
||||||
//
|
|
||||||
// defer DeferredAnnotatef(&err, "failed to frombulate the %s", arg)
|
|
||||||
//
|
|
||||||
func DeferredAnnotatef(err *error, format string, args ...interface{}) {
|
|
||||||
if *err == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
newErr := &Err{
|
|
||||||
message: fmt.Sprintf(format, args...),
|
|
||||||
cause: Cause(*err),
|
|
||||||
previous: *err,
|
|
||||||
}
|
|
||||||
newErr.SetLocation(1)
|
|
||||||
*err = newErr
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wrap changes the Cause of the error. The location of the Wrap call is also
|
|
||||||
// stored in the error stack.
|
|
||||||
//
|
|
||||||
// For example:
|
|
||||||
// if err := SomeFunc(); err != nil {
|
|
||||||
// newErr := &packageError{"more context", private_value}
|
|
||||||
// return errors.Wrap(err, newErr)
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
func Wrap(other, newDescriptive error) error {
|
|
||||||
err := &Err{
|
|
||||||
previous: other,
|
|
||||||
cause: newDescriptive,
|
|
||||||
}
|
|
||||||
err.SetLocation(1)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wrapf changes the Cause of the error, and adds an annotation. The location
|
|
||||||
// of the Wrap call is also stored in the error stack.
|
|
||||||
//
|
|
||||||
// For example:
|
|
||||||
// if err := SomeFunc(); err != nil {
|
|
||||||
// return errors.Wrapf(err, simpleErrorType, "invalid value %q", value)
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
func Wrapf(other, newDescriptive error, format string, args ...interface{}) error {
|
|
||||||
err := &Err{
|
|
||||||
message: fmt.Sprintf(format, args...),
|
|
||||||
previous: other,
|
|
||||||
cause: newDescriptive,
|
|
||||||
}
|
|
||||||
err.SetLocation(1)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Maskf masks the given error with the given format string and arguments (like
|
|
||||||
// fmt.Sprintf), returning a new error that maintains the error stack, but
|
|
||||||
// hides the underlying error type. The error string still contains the full
|
|
||||||
// annotations. If you want to hide the annotations, call Wrap.
|
|
||||||
func Maskf(other error, format string, args ...interface{}) error {
|
|
||||||
if other == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
err := &Err{
|
|
||||||
message: fmt.Sprintf(format, args...),
|
|
||||||
previous: other,
|
|
||||||
}
|
|
||||||
err.SetLocation(1)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Mask hides the underlying error type, and records the location of the masking.
|
|
||||||
func Mask(other error) error {
|
|
||||||
if other == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
err := &Err{
|
|
||||||
previous: other,
|
|
||||||
}
|
|
||||||
err.SetLocation(1)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cause returns the cause of the given error. This will be either the
|
|
||||||
// original error, or the result of a Wrap or Mask call.
|
|
||||||
//
|
|
||||||
// Cause is the usual way to diagnose errors that may have been wrapped by
|
|
||||||
// the other errors functions.
|
|
||||||
func Cause(err error) error {
|
|
||||||
var diag error
|
|
||||||
if err, ok := err.(causer); ok {
|
|
||||||
diag = err.Cause()
|
|
||||||
}
|
|
||||||
if diag != nil {
|
|
||||||
return diag
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
type causer interface {
|
|
||||||
Cause() error
|
|
||||||
}
|
|
||||||
|
|
||||||
type wrapper interface {
|
|
||||||
// Message returns the top level error message,
|
|
||||||
// not including the message from the Previous
|
|
||||||
// error.
|
|
||||||
Message() string
|
|
||||||
|
|
||||||
// Underlying returns the Previous error, or nil
|
|
||||||
// if there is none.
|
|
||||||
Underlying() error
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
_ wrapper = (*Err)(nil)
|
|
||||||
_ Locationer = (*Err)(nil)
|
|
||||||
_ causer = (*Err)(nil)
|
|
||||||
)
|
|
||||||
|
|
||||||
// Details returns information about the stack of errors wrapped by err, in
|
|
||||||
// the format:
|
|
||||||
//
|
|
||||||
// [{filename:99: error one} {otherfile:55: cause of error one}]
|
|
||||||
//
|
|
||||||
// This is a terse alternative to ErrorStack as it returns a single line.
|
|
||||||
func Details(err error) string {
|
|
||||||
if err == nil {
|
|
||||||
return "[]"
|
|
||||||
}
|
|
||||||
var s []byte
|
|
||||||
s = append(s, '[')
|
|
||||||
for {
|
|
||||||
s = append(s, '{')
|
|
||||||
if err, ok := err.(Locationer); ok {
|
|
||||||
file, line := err.Location()
|
|
||||||
if file != "" {
|
|
||||||
s = append(s, fmt.Sprintf("%s:%d", file, line)...)
|
|
||||||
s = append(s, ": "...)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if cerr, ok := err.(wrapper); ok {
|
|
||||||
s = append(s, cerr.Message()...)
|
|
||||||
err = cerr.Underlying()
|
|
||||||
} else {
|
|
||||||
s = append(s, err.Error()...)
|
|
||||||
err = nil
|
|
||||||
}
|
|
||||||
s = append(s, '}')
|
|
||||||
if err == nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
s = append(s, ' ')
|
|
||||||
}
|
|
||||||
s = append(s, ']')
|
|
||||||
return string(s)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ErrorStack returns a string representation of the annotated error. If the
|
|
||||||
// error passed as the parameter is not an annotated error, the result is
|
|
||||||
// simply the result of the Error() method on that error.
|
|
||||||
//
|
|
||||||
// If the error is an annotated error, a multi-line string is returned where
|
|
||||||
// each line represents one entry in the annotation stack. The full filename
|
|
||||||
// from the call stack is used in the output.
|
|
||||||
//
|
|
||||||
// first error
|
|
||||||
// github.com/juju/errors/annotation_test.go:193:
|
|
||||||
// github.com/juju/errors/annotation_test.go:194: annotation
|
|
||||||
// github.com/juju/errors/annotation_test.go:195:
|
|
||||||
// github.com/juju/errors/annotation_test.go:196: more context
|
|
||||||
// github.com/juju/errors/annotation_test.go:197:
|
|
||||||
func ErrorStack(err error) string {
|
|
||||||
return strings.Join(errorStack(err), "\n")
|
|
||||||
}
|
|
||||||
|
|
||||||
func errorStack(err error) []string {
|
|
||||||
if err == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// We want the first error first
|
|
||||||
var lines []string
|
|
||||||
for {
|
|
||||||
var buff []byte
|
|
||||||
if err, ok := err.(Locationer); ok {
|
|
||||||
file, line := err.Location()
|
|
||||||
// Strip off the leading GOPATH/src path elements.
|
|
||||||
if file != "" {
|
|
||||||
buff = append(buff, fmt.Sprintf("%s:%d", file, line)...)
|
|
||||||
buff = append(buff, ": "...)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if cerr, ok := err.(wrapper); ok {
|
|
||||||
message := cerr.Message()
|
|
||||||
buff = append(buff, message...)
|
|
||||||
// If there is a cause for this error, and it is different to the cause
|
|
||||||
// of the underlying error, then output the error string in the stack trace.
|
|
||||||
var cause error
|
|
||||||
if err1, ok := err.(causer); ok {
|
|
||||||
cause = err1.Cause()
|
|
||||||
}
|
|
||||||
err = cerr.Underlying()
|
|
||||||
if cause != nil && !sameError(Cause(err), cause) {
|
|
||||||
if message != "" {
|
|
||||||
buff = append(buff, ": "...)
|
|
||||||
}
|
|
||||||
buff = append(buff, cause.Error()...)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
buff = append(buff, err.Error()...)
|
|
||||||
err = nil
|
|
||||||
}
|
|
||||||
lines = append(lines, string(buff))
|
|
||||||
if err == nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// reverse the lines to get the original error, which was at the end of
|
|
||||||
// the list, back to the start.
|
|
||||||
var result []string
|
|
||||||
for i := len(lines); i > 0; i-- {
|
|
||||||
result = append(result, lines[i-1])
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unwrap is a proxy for the Unwrap function in Go's standard `errors` library
|
|
||||||
// (pkg.go.dev/errors).
|
|
||||||
func Unwrap(err error) error {
|
|
||||||
return stderrors.Unwrap(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Is is a proxy for the Is function in Go's standard `errors` library
|
|
||||||
// (pkg.go.dev/errors).
|
|
||||||
func Is(err, target error) bool {
|
|
||||||
return stderrors.Is(err, target)
|
|
||||||
}
|
|
||||||
|
|
||||||
// HasType is a function wrapper around AsType dropping the where return value
|
|
||||||
// from AsType() making a function that can be used like this:
|
|
||||||
//
|
|
||||||
// return HasType[*MyError](err)
|
|
||||||
//
|
|
||||||
// Or
|
|
||||||
//
|
|
||||||
// if HasType[*MyError](err) {}
|
|
||||||
func HasType[T error](err error) bool {
|
|
||||||
_, rval := AsType[T](err)
|
|
||||||
return rval
|
|
||||||
}
|
|
||||||
|
|
||||||
// As is a proxy for the As function in Go's standard `errors` library
|
|
||||||
// (pkg.go.dev/errors).
|
|
||||||
func As(err error, target interface{}) bool {
|
|
||||||
return stderrors.As(err, target)
|
|
||||||
}
|
|
||||||
|
|
||||||
// AsType is a convenience method for checking and getting an error from within
|
|
||||||
// a chain that is of type T. If no error is found of type T in the chain the
|
|
||||||
// zero value of T is returned with false. If an error in the chain implementes
|
|
||||||
// As(any) bool then it's As method will be called if it's type is not of type T.
|
|
||||||
|
|
||||||
// AsType finds the first error in err's chain that is assignable to type T, and
|
|
||||||
// if a match is found, returns that error value and true. Otherwise, it returns
|
|
||||||
// T's zero value and false.
|
|
||||||
//
|
|
||||||
// AsType is equivalent to errors.As, but uses a type parameter and returns
|
|
||||||
// the target, to avoid having to define a variable before the call. For
|
|
||||||
// example, callers can replace this:
|
|
||||||
//
|
|
||||||
// var pathError *fs.PathError
|
|
||||||
// if errors.As(err, &pathError) {
|
|
||||||
// fmt.Println("Failed at path:", pathError.Path)
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// With:
|
|
||||||
//
|
|
||||||
// if pathError, ok := errors.AsType[*fs.PathError](err); ok {
|
|
||||||
// fmt.Println("Failed at path:", pathError.Path)
|
|
||||||
// }
|
|
||||||
func AsType[T error](err error) (T, bool) {
|
|
||||||
for err != nil {
|
|
||||||
if e, is := err.(T); is {
|
|
||||||
return e, true
|
|
||||||
}
|
|
||||||
var res T
|
|
||||||
if x, ok := err.(interface{ As(any) bool }); ok && x.As(&res) {
|
|
||||||
return res, true
|
|
||||||
}
|
|
||||||
err = stderrors.Unwrap(err)
|
|
||||||
}
|
|
||||||
var zero T
|
|
||||||
return zero, false
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetLocation takes a given error and records where in the stack SetLocation
|
|
||||||
// was called from and returns the wrapped error with the location information
|
|
||||||
// set. The returned error implements the Locationer interface. If err is nil
|
|
||||||
// then a nil error is returned.
|
|
||||||
func SetLocation(err error, callDepth int) error {
|
|
||||||
if err == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return newLocationError(err, callDepth)
|
|
||||||
}
|
|
||||||
|
|
||||||
// fmtNoop provides an internal type for wrapping errors so they won't be
|
|
||||||
// printed in fmt type commands. As this type is used by the Hide function it's
|
|
||||||
// expected that error not be nil.
|
|
||||||
type fmtNoop struct {
|
|
||||||
error
|
|
||||||
}
|
|
||||||
|
|
||||||
// Format implements the fmt.Formatter interface so that the error wrapped by
|
|
||||||
// fmtNoop will not be printed.
|
|
||||||
func (*fmtNoop) Format(_ fmt.State, r rune) {}
|
|
||||||
|
|
||||||
// Is implements errors.Is. It useful for us to be able to check if an error
|
|
||||||
// chain has fmtNoop for formatting purposes.
|
|
||||||
func (f *fmtNoop) Is(err error) bool {
|
|
||||||
_, is := err.(*fmtNoop)
|
|
||||||
return is
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unwrap implements the errors.Unwrap method returning the error wrapped by
|
|
||||||
// fmtNoop.
|
|
||||||
func (f *fmtNoop) Unwrap() error {
|
|
||||||
return f.error
|
|
||||||
}
|
|
||||||
|
|
||||||
// Hide takes an error and silences it's error string from appearing in fmt
|
|
||||||
// like
|
|
||||||
func Hide(err error) error {
|
|
||||||
if err == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return &fmtNoop{err}
|
|
||||||
}
|
|
||||||
1
vendor/github.com/juju/retry/.gitignore
generated
vendored
1
vendor/github.com/juju/retry/.gitignore
generated
vendored
|
|
@ -1 +0,0 @@
|
||||||
*.test
|
|
||||||
191
vendor/github.com/juju/retry/LICENSE
generated
vendored
191
vendor/github.com/juju/retry/LICENSE
generated
vendored
|
|
@ -1,191 +0,0 @@
|
||||||
All files in this repository are licensed as follows. If you contribute
|
|
||||||
to this repository, it is assumed that you license your contribution
|
|
||||||
under the same license unless you state otherwise.
|
|
||||||
|
|
||||||
All files Copyright (C) 2015 Canonical Ltd. unless otherwise specified in the file.
|
|
||||||
|
|
||||||
This software is licensed under the LGPLv3, included below.
|
|
||||||
|
|
||||||
As a special exception to the GNU Lesser General Public License version 3
|
|
||||||
("LGPL3"), the copyright holders of this Library give you permission to
|
|
||||||
convey to a third party a Combined Work that links statically or dynamically
|
|
||||||
to this Library without providing any Minimal Corresponding Source or
|
|
||||||
Minimal Application Code as set out in 4d or providing the installation
|
|
||||||
information set out in section 4e, provided that you comply with the other
|
|
||||||
provisions of LGPL3 and provided that you meet, for the Application the
|
|
||||||
terms and conditions of the license(s) which apply to the Application.
|
|
||||||
|
|
||||||
Except as stated in this special exception, the provisions of LGPL3 will
|
|
||||||
continue to comply in full to this Library. If you modify this Library, you
|
|
||||||
may apply this exception to your version of this Library, but you are not
|
|
||||||
obliged to do so. If you do not wish to do so, delete this exception
|
|
||||||
statement from your version. This exception does not (and cannot) modify any
|
|
||||||
license terms which apply to the Application, with which you must still
|
|
||||||
comply.
|
|
||||||
|
|
||||||
|
|
||||||
GNU LESSER GENERAL PUBLIC LICENSE
|
|
||||||
Version 3, 29 June 2007
|
|
||||||
|
|
||||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
|
||||||
Everyone is permitted to copy and distribute verbatim copies
|
|
||||||
of this license document, but changing it is not allowed.
|
|
||||||
|
|
||||||
|
|
||||||
This version of the GNU Lesser General Public License incorporates
|
|
||||||
the terms and conditions of version 3 of the GNU General Public
|
|
||||||
License, supplemented by the additional permissions listed below.
|
|
||||||
|
|
||||||
0. Additional Definitions.
|
|
||||||
|
|
||||||
As used herein, "this License" refers to version 3 of the GNU Lesser
|
|
||||||
General Public License, and the "GNU GPL" refers to version 3 of the GNU
|
|
||||||
General Public License.
|
|
||||||
|
|
||||||
"The Library" refers to a covered work governed by this License,
|
|
||||||
other than an Application or a Combined Work as defined below.
|
|
||||||
|
|
||||||
An "Application" is any work that makes use of an interface provided
|
|
||||||
by the Library, but which is not otherwise based on the Library.
|
|
||||||
Defining a subclass of a class defined by the Library is deemed a mode
|
|
||||||
of using an interface provided by the Library.
|
|
||||||
|
|
||||||
A "Combined Work" is a work produced by combining or linking an
|
|
||||||
Application with the Library. The particular version of the Library
|
|
||||||
with which the Combined Work was made is also called the "Linked
|
|
||||||
Version".
|
|
||||||
|
|
||||||
The "Minimal Corresponding Source" for a Combined Work means the
|
|
||||||
Corresponding Source for the Combined Work, excluding any source code
|
|
||||||
for portions of the Combined Work that, considered in isolation, are
|
|
||||||
based on the Application, and not on the Linked Version.
|
|
||||||
|
|
||||||
The "Corresponding Application Code" for a Combined Work means the
|
|
||||||
object code and/or source code for the Application, including any data
|
|
||||||
and utility programs needed for reproducing the Combined Work from the
|
|
||||||
Application, but excluding the System Libraries of the Combined Work.
|
|
||||||
|
|
||||||
1. Exception to Section 3 of the GNU GPL.
|
|
||||||
|
|
||||||
You may convey a covered work under sections 3 and 4 of this License
|
|
||||||
without being bound by section 3 of the GNU GPL.
|
|
||||||
|
|
||||||
2. Conveying Modified Versions.
|
|
||||||
|
|
||||||
If you modify a copy of the Library, and, in your modifications, a
|
|
||||||
facility refers to a function or data to be supplied by an Application
|
|
||||||
that uses the facility (other than as an argument passed when the
|
|
||||||
facility is invoked), then you may convey a copy of the modified
|
|
||||||
version:
|
|
||||||
|
|
||||||
a) under this License, provided that you make a good faith effort to
|
|
||||||
ensure that, in the event an Application does not supply the
|
|
||||||
function or data, the facility still operates, and performs
|
|
||||||
whatever part of its purpose remains meaningful, or
|
|
||||||
|
|
||||||
b) under the GNU GPL, with none of the additional permissions of
|
|
||||||
this License applicable to that copy.
|
|
||||||
|
|
||||||
3. Object Code Incorporating Material from Library Header Files.
|
|
||||||
|
|
||||||
The object code form of an Application may incorporate material from
|
|
||||||
a header file that is part of the Library. You may convey such object
|
|
||||||
code under terms of your choice, provided that, if the incorporated
|
|
||||||
material is not limited to numerical parameters, data structure
|
|
||||||
layouts and accessors, or small macros, inline functions and templates
|
|
||||||
(ten or fewer lines in length), you do both of the following:
|
|
||||||
|
|
||||||
a) Give prominent notice with each copy of the object code that the
|
|
||||||
Library is used in it and that the Library and its use are
|
|
||||||
covered by this License.
|
|
||||||
|
|
||||||
b) Accompany the object code with a copy of the GNU GPL and this license
|
|
||||||
document.
|
|
||||||
|
|
||||||
4. Combined Works.
|
|
||||||
|
|
||||||
You may convey a Combined Work under terms of your choice that,
|
|
||||||
taken together, effectively do not restrict modification of the
|
|
||||||
portions of the Library contained in the Combined Work and reverse
|
|
||||||
engineering for debugging such modifications, if you also do each of
|
|
||||||
the following:
|
|
||||||
|
|
||||||
a) Give prominent notice with each copy of the Combined Work that
|
|
||||||
the Library is used in it and that the Library and its use are
|
|
||||||
covered by this License.
|
|
||||||
|
|
||||||
b) Accompany the Combined Work with a copy of the GNU GPL and this license
|
|
||||||
document.
|
|
||||||
|
|
||||||
c) For a Combined Work that displays copyright notices during
|
|
||||||
execution, include the copyright notice for the Library among
|
|
||||||
these notices, as well as a reference directing the user to the
|
|
||||||
copies of the GNU GPL and this license document.
|
|
||||||
|
|
||||||
d) Do one of the following:
|
|
||||||
|
|
||||||
0) Convey the Minimal Corresponding Source under the terms of this
|
|
||||||
License, and the Corresponding Application Code in a form
|
|
||||||
suitable for, and under terms that permit, the user to
|
|
||||||
recombine or relink the Application with a modified version of
|
|
||||||
the Linked Version to produce a modified Combined Work, in the
|
|
||||||
manner specified by section 6 of the GNU GPL for conveying
|
|
||||||
Corresponding Source.
|
|
||||||
|
|
||||||
1) Use a suitable shared library mechanism for linking with the
|
|
||||||
Library. A suitable mechanism is one that (a) uses at run time
|
|
||||||
a copy of the Library already present on the user's computer
|
|
||||||
system, and (b) will operate properly with a modified version
|
|
||||||
of the Library that is interface-compatible with the Linked
|
|
||||||
Version.
|
|
||||||
|
|
||||||
e) Provide Installation Information, but only if you would otherwise
|
|
||||||
be required to provide such information under section 6 of the
|
|
||||||
GNU GPL, and only to the extent that such information is
|
|
||||||
necessary to install and execute a modified version of the
|
|
||||||
Combined Work produced by recombining or relinking the
|
|
||||||
Application with a modified version of the Linked Version. (If
|
|
||||||
you use option 4d0, the Installation Information must accompany
|
|
||||||
the Minimal Corresponding Source and Corresponding Application
|
|
||||||
Code. If you use option 4d1, you must provide the Installation
|
|
||||||
Information in the manner specified by section 6 of the GNU GPL
|
|
||||||
for conveying Corresponding Source.)
|
|
||||||
|
|
||||||
5. Combined Libraries.
|
|
||||||
|
|
||||||
You may place library facilities that are a work based on the
|
|
||||||
Library side by side in a single library together with other library
|
|
||||||
facilities that are not Applications and are not covered by this
|
|
||||||
License, and convey such a combined library under terms of your
|
|
||||||
choice, if you do both of the following:
|
|
||||||
|
|
||||||
a) Accompany the combined library with a copy of the same work based
|
|
||||||
on the Library, uncombined with any other library facilities,
|
|
||||||
conveyed under the terms of this License.
|
|
||||||
|
|
||||||
b) Give prominent notice with the combined library that part of it
|
|
||||||
is a work based on the Library, and explaining where to find the
|
|
||||||
accompanying uncombined form of the same work.
|
|
||||||
|
|
||||||
6. Revised Versions of the GNU Lesser General Public License.
|
|
||||||
|
|
||||||
The Free Software Foundation may publish revised and/or new versions
|
|
||||||
of the GNU Lesser General Public License from time to time. Such new
|
|
||||||
versions will be similar in spirit to the present version, but may
|
|
||||||
differ in detail to address new problems or concerns.
|
|
||||||
|
|
||||||
Each version is given a distinguishing version number. If the
|
|
||||||
Library as you received it specifies that a certain numbered version
|
|
||||||
of the GNU Lesser General Public License "or any later version"
|
|
||||||
applies to it, you have the option of following the terms and
|
|
||||||
conditions either of that published version or of any later version
|
|
||||||
published by the Free Software Foundation. If the Library as you
|
|
||||||
received it does not specify a version number of the GNU Lesser
|
|
||||||
General Public License, you may choose any version of the GNU Lesser
|
|
||||||
General Public License ever published by the Free Software Foundation.
|
|
||||||
|
|
||||||
If the Library as you received it specifies that a proxy can decide
|
|
||||||
whether future versions of the GNU Lesser General Public License shall
|
|
||||||
apply, that proxy's public statement of acceptance of any version is
|
|
||||||
permanent authorization for you to choose that version for the
|
|
||||||
Library.
|
|
||||||
15
vendor/github.com/juju/retry/Makefile
generated
vendored
15
vendor/github.com/juju/retry/Makefile
generated
vendored
|
|
@ -1,15 +0,0 @@
|
||||||
PROJECT := github.com/juju/retry
|
|
||||||
|
|
||||||
default: check
|
|
||||||
|
|
||||||
check-licence:
|
|
||||||
@(fgrep -rl "Licensed under the LGPLv3" .;\
|
|
||||||
fgrep -rl "MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT" .;\
|
|
||||||
find . -name "*.go") | sed -e 's,\./,,' | sort | uniq -u | \
|
|
||||||
xargs -I {} echo FAIL: licence missed: {}
|
|
||||||
|
|
||||||
check: check-licence
|
|
||||||
go test $(PROJECT)/...
|
|
||||||
|
|
||||||
docs:
|
|
||||||
godoc2md $(PROJECT) > README.md
|
|
||||||
277
vendor/github.com/juju/retry/README.md
generated
vendored
277
vendor/github.com/juju/retry/README.md
generated
vendored
|
|
@ -1,277 +0,0 @@
|
||||||
|
|
||||||
# retry
|
|
||||||
import "github.com/juju/retry"
|
|
||||||
|
|
||||||
The retry package encapsulates the mechanism around retrying commands.
|
|
||||||
|
|
||||||
The simple use is to call retry.Call with a function closure.
|
|
||||||
|
|
||||||
```go
|
|
||||||
|
|
||||||
|
|
||||||
err := retry.Call(retry.CallArgs{
|
|
||||||
Func: func() error { ... },
|
|
||||||
Attempts: 5,
|
|
||||||
Delay: time.Minute,
|
|
||||||
Clock: clock.WallClock,
|
|
||||||
})
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
The bare minimum arguments that need to be specified are:
|
|
||||||
* Func - the function to call
|
|
||||||
* Attempts - the number of times to try Func before giving up, or a negative number for unlimited attempts (`retry.UnlimitedAttempts`)
|
|
||||||
* Delay - how long to wait between each try that returns an error
|
|
||||||
* Clock - either the wall clock, or some testing clock
|
|
||||||
|
|
||||||
Any error that is returned from the `Func` is considered transient.
|
|
||||||
In order to identify some errors as fatal, pass in a function for the
|
|
||||||
`IsFatalError` CallArgs value.
|
|
||||||
|
|
||||||
In order to have the `Delay` change for each iteration, a `BackoffFunc`
|
|
||||||
needs to be set on the CallArgs. A simple doubling delay function is
|
|
||||||
provided by `DoubleDelay`.
|
|
||||||
|
|
||||||
An example of a more complex `BackoffFunc` could be a stepped function such
|
|
||||||
as:
|
|
||||||
|
|
||||||
```go
|
|
||||||
|
|
||||||
|
|
||||||
func StepDelay(last time.Duration, attempt int) time.Duration {
|
|
||||||
switch attempt{
|
|
||||||
case 1:
|
|
||||||
return time.Second
|
|
||||||
case 2:
|
|
||||||
return 5 * time.Second
|
|
||||||
case 3:
|
|
||||||
return 20 * time.Second
|
|
||||||
case 4:
|
|
||||||
return time.Minute
|
|
||||||
case 5:
|
|
||||||
return 5 * time.Minute
|
|
||||||
default:
|
|
||||||
return 2 * last
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
Consider some package `foo` that has a `TryAgainError`, which looks something
|
|
||||||
like this:
|
|
||||||
```go
|
|
||||||
|
|
||||||
|
|
||||||
type TryAgainError struct {
|
|
||||||
After time.Duration
|
|
||||||
}
|
|
||||||
|
|
||||||
```
|
|
||||||
and we create something that looks like this:
|
|
||||||
|
|
||||||
```go
|
|
||||||
|
|
||||||
|
|
||||||
type TryAgainHelper struct {
|
|
||||||
next time.Duration
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *TryAgainHelper) notify(lastError error, attempt int) {
|
|
||||||
if tryAgain, ok := lastError.(*foo.TryAgainError); ok {
|
|
||||||
h.next = tryAgain.After
|
|
||||||
} else {
|
|
||||||
h.next = 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *TryAgainHelper) next(last time.Duration) time.Duration {
|
|
||||||
if h.next != 0 {
|
|
||||||
return h.next
|
|
||||||
}
|
|
||||||
return last
|
|
||||||
}
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
Then we could do this:
|
|
||||||
```go
|
|
||||||
|
|
||||||
|
|
||||||
helper := TryAgainHelper{}
|
|
||||||
retry.Call(retry.CallArgs{
|
|
||||||
Func: func() error {
|
|
||||||
return foo.SomeFunc()
|
|
||||||
},
|
|
||||||
NotifyFunc: helper.notify,
|
|
||||||
BackoffFunc: helper.next,
|
|
||||||
Attempts: 20,
|
|
||||||
Delay: 100 * time.Millisecond,
|
|
||||||
Clock: clock.WallClock,
|
|
||||||
})
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Constants
|
|
||||||
``` go
|
|
||||||
const (
|
|
||||||
// UnlimitedAttempts can be used as a value for `Attempts` to clearly
|
|
||||||
// show to the reader that there is no limit to the number of attempts.
|
|
||||||
UnlimitedAttempts = -1
|
|
||||||
)
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
## func Call
|
|
||||||
``` go
|
|
||||||
func Call(args CallArgs) error
|
|
||||||
```
|
|
||||||
Call will repeatedly execute the Func until either the function returns no
|
|
||||||
error, the retry count is exceeded or the stop channel is closed.
|
|
||||||
|
|
||||||
|
|
||||||
## func DoubleDelay
|
|
||||||
``` go
|
|
||||||
func DoubleDelay(delay time.Duration, attempt int) time.Duration
|
|
||||||
```
|
|
||||||
DoubleDelay provides a simple function that doubles the duration passed in.
|
|
||||||
This can then be easily used as the `BackoffFunc` in the `CallArgs`
|
|
||||||
structure.
|
|
||||||
|
|
||||||
## func ExpBackoff
|
|
||||||
``` go
|
|
||||||
func ExpBackoff(minDelay, maxDelay time.Duration, exp float64, applyJitter bool) func(time.Duration, int) time.Duration {
|
|
||||||
```
|
|
||||||
ExpBackoff returns a function a which generates time.Duration values using an
|
|
||||||
exponential back-off algorithm with the specified parameters. The returned value
|
|
||||||
can then be easily used as the `BackoffFunc` in the `CallArgs` structure.
|
|
||||||
|
|
||||||
The next delay value is calculated using the following formula:
|
|
||||||
`newDelay = min(minDelay * exp^attempt, maxDelay)`
|
|
||||||
|
|
||||||
If `applyJitter` is set to `true`, the function will randomly select and return
|
|
||||||
back a value in the `[minDelay, newDelay]` range.
|
|
||||||
|
|
||||||
## func IsAttemptsExceeded
|
|
||||||
``` go
|
|
||||||
func IsAttemptsExceeded(err error) bool
|
|
||||||
```
|
|
||||||
IsAttemptsExceeded returns true if the error is the result of the `Call`
|
|
||||||
function finishing due to hitting the requested number of `Attempts`.
|
|
||||||
|
|
||||||
|
|
||||||
## func IsDurationExceeded
|
|
||||||
``` go
|
|
||||||
func IsDurationExceeded(err error) bool
|
|
||||||
```
|
|
||||||
IsDurationExceeded returns true if the error is the result of the `Call`
|
|
||||||
function finishing due to the total duration exceeding the specified
|
|
||||||
`MaxDuration` value.
|
|
||||||
|
|
||||||
|
|
||||||
## func IsRetryStopped
|
|
||||||
``` go
|
|
||||||
func IsRetryStopped(err error) bool
|
|
||||||
```
|
|
||||||
IsRetryStopped returns true if the error is the result of the `Call`
|
|
||||||
function finishing due to the stop channel being closed.
|
|
||||||
|
|
||||||
|
|
||||||
## func LastError
|
|
||||||
``` go
|
|
||||||
func LastError(err error) error
|
|
||||||
```
|
|
||||||
LastError retrieves the last error returned from `Func` before iteration
|
|
||||||
was terminated due to the attempt count being exceeded, the maximum
|
|
||||||
duration being exceeded, or the stop channel being closed.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## type CallArgs
|
|
||||||
``` go
|
|
||||||
type CallArgs struct {
|
|
||||||
// Func is the function that will be retried if it returns an error result.
|
|
||||||
Func func() error
|
|
||||||
|
|
||||||
// IsFatalError is a function that, if set, will be called for every non-
|
|
||||||
// nil error result from `Func`. If `IsFatalError` returns true, the error
|
|
||||||
// is immediately returned breaking out from any further retries.
|
|
||||||
IsFatalError func(error) bool
|
|
||||||
|
|
||||||
// NotifyFunc is a function that is called if Func fails, and the attempt
|
|
||||||
// number. The first time this function is called attempt is 1, the second
|
|
||||||
// time, attempt is 2 and so on.
|
|
||||||
NotifyFunc func(lastError error, attempt int)
|
|
||||||
|
|
||||||
// Attempts specifies the number of times Func should be retried before
|
|
||||||
// giving up and returning the `AttemptsExceeded` error. If a negative
|
|
||||||
// value is specified, the `Call` will retry forever.
|
|
||||||
Attempts int
|
|
||||||
|
|
||||||
// Delay specifies how long to wait between retries.
|
|
||||||
Delay time.Duration
|
|
||||||
|
|
||||||
// MaxDelay specifies how longest time to wait between retries. If no
|
|
||||||
// value is specified there is no maximum delay.
|
|
||||||
MaxDelay time.Duration
|
|
||||||
|
|
||||||
// MaxDuration specifies the maximum time the `Call` function should spend
|
|
||||||
// iterating over `Func`. The duration is calculated from the start of the
|
|
||||||
// `Call` function. If the next delay time would take the total duration
|
|
||||||
// of the call over MaxDuration, then a DurationExceeded error is
|
|
||||||
// returned. If no value is specified, Call will continue until the number
|
|
||||||
// of attempts is complete.
|
|
||||||
MaxDuration time.Duration
|
|
||||||
|
|
||||||
// BackoffFunc allows the caller to provide a function that alters the
|
|
||||||
// delay each time through the loop. If this function is not provided the
|
|
||||||
// delay is the same each iteration. Alternatively a function such as
|
|
||||||
// `retry.DoubleDelay` can be used that will provide an exponential
|
|
||||||
// backoff. The first time this function is called attempt is 1, the
|
|
||||||
// second time, attempt is 2 and so on.
|
|
||||||
BackoffFunc func(delay time.Duration, attempt int) time.Duration
|
|
||||||
|
|
||||||
// Clock provides the mechanism for waiting. Normal program execution is
|
|
||||||
// expected to use something like clock.WallClock, and tests can override
|
|
||||||
// this to not actually sleep in tests.
|
|
||||||
Clock clock.Clock
|
|
||||||
|
|
||||||
// Stop is a channel that can be used to indicate that the waiting should
|
|
||||||
// be interrupted. If Stop is nil, then the Call function cannot be interrupted.
|
|
||||||
// If the channel is closed prior to the Call function being executed, the
|
|
||||||
// Func is still attempted once.
|
|
||||||
Stop <-chan struct{}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
CallArgs is a simple structure used to define the behaviour of the Call
|
|
||||||
function.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### func (\*CallArgs) Validate
|
|
||||||
``` go
|
|
||||||
func (args *CallArgs) Validate() error
|
|
||||||
```
|
|
||||||
Validate the values are valid. The ensures that the Func, Delay, Attempts
|
|
||||||
and Clock have been specified.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
- - -
|
|
||||||
Generated by [godoc2md](http://godoc.org/github.com/davecheney/godoc2md)
|
|
||||||
16
vendor/github.com/juju/retry/clock.go
generated
vendored
16
vendor/github.com/juju/retry/clock.go
generated
vendored
|
|
@ -1,16 +0,0 @@
|
||||||
// Copyright 2015 Canonical Ltd.
|
|
||||||
// Licensed under the LGPLv3, see LICENCE file for details.
|
|
||||||
|
|
||||||
package retry
|
|
||||||
|
|
||||||
import "time"
|
|
||||||
|
|
||||||
// Clock provides an interface for dealing with clocks.
|
|
||||||
type Clock interface {
|
|
||||||
// Now returns the current clock time.
|
|
||||||
Now() time.Time
|
|
||||||
|
|
||||||
// After waits for the duration to elapse and then sends the
|
|
||||||
// current time on the returned channel.
|
|
||||||
After(time.Duration) <-chan time.Time
|
|
||||||
}
|
|
||||||
90
vendor/github.com/juju/retry/doc.go
generated
vendored
90
vendor/github.com/juju/retry/doc.go
generated
vendored
|
|
@ -1,90 +0,0 @@
|
||||||
// Copyright 2015 Canonical Ltd.
|
|
||||||
// Licensed under the LGPLv3, see LICENCE file for details.
|
|
||||||
|
|
||||||
// The retry package encapsulates the mechanism around retrying commands.
|
|
||||||
//
|
|
||||||
// The simple use is to call retry.Call with a function closure.
|
|
||||||
//
|
|
||||||
// err := retry.Call(retry.CallArgs{
|
|
||||||
// Func: func() error { ... },
|
|
||||||
// Attempts: 5,
|
|
||||||
// Delay: time.Minute,
|
|
||||||
// Clock: clock.WallClock,
|
|
||||||
// })
|
|
||||||
//
|
|
||||||
// The bare minimum arguments that need to be specified are:
|
|
||||||
// - Func - the function to call
|
|
||||||
// - Attempts - the number of times to try Func before giving up, or a negative number for unlimited attempts (`retry.UnlimitedAttempts`)
|
|
||||||
// - Delay - how long to wait between each try that returns an error
|
|
||||||
// - Clock - either the wall clock, or some testing clock
|
|
||||||
//
|
|
||||||
// Any error that is returned from the Func is considered transient.
|
|
||||||
// In order to identify some errors as fatal, pass in a function for the
|
|
||||||
// IsFatalError CallArgs value.
|
|
||||||
//
|
|
||||||
// In order to have the Delay change for each iteration, a BackoffFunc
|
|
||||||
// needs to be set on the CallArgs. A simple doubling delay function is
|
|
||||||
// provided by DoubleDelay.
|
|
||||||
//
|
|
||||||
// An example of a more complex BackoffFunc could be a stepped function such
|
|
||||||
// as:
|
|
||||||
//
|
|
||||||
// func StepDelay(last time.Duration, attempt int) time.Duration {
|
|
||||||
// switch attempt{
|
|
||||||
// case 1:
|
|
||||||
// return time.Second
|
|
||||||
// case 2:
|
|
||||||
// return 5 * time.Second
|
|
||||||
// case 3:
|
|
||||||
// return 20 * time.Second
|
|
||||||
// case 4:
|
|
||||||
// return time.Minute
|
|
||||||
// case 5:
|
|
||||||
// return 5 * time.Minute
|
|
||||||
// default:
|
|
||||||
// return 2 * last
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// Consider some package foo that has a TryAgainError, which looks something
|
|
||||||
// like this:
|
|
||||||
//
|
|
||||||
// type TryAgainError struct {
|
|
||||||
// After time.Duration
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// and we create something that looks like this:
|
|
||||||
//
|
|
||||||
// type TryAgainHelper struct {
|
|
||||||
// next time.Duration
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// func (h *TryAgainHelper) notify(lastError error, attempt int) {
|
|
||||||
// if tryAgain, ok := lastError.(*foo.TryAgainError); ok {
|
|
||||||
// h.next = tryAgain.After
|
|
||||||
// } else {
|
|
||||||
// h.next = 0
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// func (h *TryAgainHelper) next(last time.Duration) time.Duration {
|
|
||||||
// if h.next != 0 {
|
|
||||||
// return h.next
|
|
||||||
// }
|
|
||||||
// return last
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// Then we could do this:
|
|
||||||
//
|
|
||||||
// helper := TryAgainHelper{}
|
|
||||||
// retry.Call(retry.CallArgs{
|
|
||||||
// Func: func() error {
|
|
||||||
// return foo.SomeFunc()
|
|
||||||
// },
|
|
||||||
// NotifyFunc: helper.notify,
|
|
||||||
// BackoffFunc: helper.next,
|
|
||||||
// Attempts: 20,
|
|
||||||
// Delay: 100 * time.Millisecond,
|
|
||||||
// Clock: clock.WallClock,
|
|
||||||
// })
|
|
||||||
package retry
|
|
||||||
260
vendor/github.com/juju/retry/retry.go
generated
vendored
260
vendor/github.com/juju/retry/retry.go
generated
vendored
|
|
@ -1,260 +0,0 @@
|
||||||
// Copyright 2015 Canonical Ltd.
|
|
||||||
// Licensed under the LGPLv3, see LICENCE file for details.
|
|
||||||
|
|
||||||
package retry
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"math"
|
|
||||||
"math/rand"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/juju/errors"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
// UnlimitedAttempts can be used as a value for Attempts to clearly
|
|
||||||
// show to the reader that there is no limit to the number of attempts.
|
|
||||||
UnlimitedAttempts = -1
|
|
||||||
)
|
|
||||||
|
|
||||||
// retryStopped is the error that is returned from the Call function
|
|
||||||
// when the stop channel has been closed.
|
|
||||||
type retryStopped struct {
|
|
||||||
lastError error
|
|
||||||
}
|
|
||||||
|
|
||||||
// Error provides the implementation for the error interface method.
|
|
||||||
func (e *retryStopped) Error() string {
|
|
||||||
return fmt.Sprintf("retry stopped")
|
|
||||||
}
|
|
||||||
|
|
||||||
// attemptsExceeded is the error that is returned when the retry count has
|
|
||||||
// been hit without the function returning a nil error result. The last error
|
|
||||||
// returned from the function being retried is available as the LastError
|
|
||||||
// attribute.
|
|
||||||
type attemptsExceeded struct {
|
|
||||||
lastError error
|
|
||||||
}
|
|
||||||
|
|
||||||
// Error provides the implementation for the error interface method.
|
|
||||||
func (e *attemptsExceeded) Error() string {
|
|
||||||
return fmt.Sprintf("attempt count exceeded: %s", e.lastError)
|
|
||||||
}
|
|
||||||
|
|
||||||
// durationExceeded is the error that is returned when the total time that the
|
|
||||||
// Call function would have executed exceeds the MaxDuration specified.
|
|
||||||
// The last error returned from the function being retried is available as the
|
|
||||||
// LastError attribute.
|
|
||||||
type durationExceeded struct {
|
|
||||||
lastError error
|
|
||||||
}
|
|
||||||
|
|
||||||
// Error provides the implementation for the error interface method.
|
|
||||||
func (e *durationExceeded) Error() string {
|
|
||||||
return fmt.Sprintf("max duration exceeded: %s", e.lastError)
|
|
||||||
}
|
|
||||||
|
|
||||||
// LastError retrieves the last error returned from Func before iteration
|
|
||||||
// was terminated due to the attempt count being exceeded, the maximum
|
|
||||||
// duration being exceeded, or the stop channel being closed.
|
|
||||||
func LastError(err error) error {
|
|
||||||
cause := errors.Cause(err)
|
|
||||||
switch err := cause.(type) {
|
|
||||||
case *attemptsExceeded:
|
|
||||||
return err.lastError
|
|
||||||
case *retryStopped:
|
|
||||||
return err.lastError
|
|
||||||
case *durationExceeded:
|
|
||||||
return err.lastError
|
|
||||||
}
|
|
||||||
return errors.Errorf("unexpected error type: %T, %s", cause, cause)
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsAttemptsExceeded returns true if the error is the result of the Call
|
|
||||||
// function finishing due to hitting the requested number of Attempts.
|
|
||||||
func IsAttemptsExceeded(err error) bool {
|
|
||||||
cause := errors.Cause(err)
|
|
||||||
_, ok := cause.(*attemptsExceeded)
|
|
||||||
return ok
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsDurationExceeded returns true if the error is the result of the Call
|
|
||||||
// function finishing due to the total duration exceeding the specified
|
|
||||||
// MaxDuration value.
|
|
||||||
func IsDurationExceeded(err error) bool {
|
|
||||||
cause := errors.Cause(err)
|
|
||||||
_, ok := cause.(*durationExceeded)
|
|
||||||
return ok
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsRetryStopped returns true if the error is the result of the Call
|
|
||||||
// function finishing due to the stop channel being closed.
|
|
||||||
func IsRetryStopped(err error) bool {
|
|
||||||
cause := errors.Cause(err)
|
|
||||||
_, ok := cause.(*retryStopped)
|
|
||||||
return ok
|
|
||||||
}
|
|
||||||
|
|
||||||
// CallArgs is a simple structure used to define the behaviour of the Call
|
|
||||||
// function.
|
|
||||||
type CallArgs struct {
|
|
||||||
// Func is the function that will be retried if it returns an error result.
|
|
||||||
Func func() error
|
|
||||||
|
|
||||||
// IsFatalError is a function that, if set, will be called for every non-
|
|
||||||
// nil error result from Func. If IsFatalError returns true, the error
|
|
||||||
// is immediately returned breaking out from any further retries.
|
|
||||||
IsFatalError func(error) bool
|
|
||||||
|
|
||||||
// NotifyFunc is a function that is called if Func fails, and the attempt
|
|
||||||
// number. The first time this function is called attempt is 1, the second
|
|
||||||
// time, attempt is 2 and so on.
|
|
||||||
NotifyFunc func(lastError error, attempt int)
|
|
||||||
|
|
||||||
// Attempts specifies the number of times Func should be retried before
|
|
||||||
// giving up and returning the AttemptsExceeded error. If a negative
|
|
||||||
// value is specified, the Call will retry forever.
|
|
||||||
Attempts int
|
|
||||||
|
|
||||||
// Delay specifies how long to wait between retries.
|
|
||||||
Delay time.Duration
|
|
||||||
|
|
||||||
// MaxDelay specifies how longest time to wait between retries. If no
|
|
||||||
// value is specified there is no maximum delay.
|
|
||||||
MaxDelay time.Duration
|
|
||||||
|
|
||||||
// MaxDuration specifies the maximum time the Call function should spend
|
|
||||||
// iterating over Func. The duration is calculated from the start of the
|
|
||||||
// Call function. If the next delay time would take the total duration
|
|
||||||
// of the call over MaxDuration, then a DurationExceeded error is
|
|
||||||
// returned. If no value is specified, Call will continue until the number
|
|
||||||
// of attempts is complete.
|
|
||||||
MaxDuration time.Duration
|
|
||||||
|
|
||||||
// BackoffFunc allows the caller to provide a function that alters the
|
|
||||||
// delay each time through the loop. If this function is not provided the
|
|
||||||
// delay is the same each iteration. Alternatively a function such as
|
|
||||||
// retry.DoubleDelay can be used that will provide an exponential
|
|
||||||
// backoff. The first time this function is called attempt is 1, the
|
|
||||||
// second time, attempt is 2 and so on.
|
|
||||||
BackoffFunc func(delay time.Duration, attempt int) time.Duration
|
|
||||||
|
|
||||||
// Clock provides the mechanism for waiting. Normal program execution is
|
|
||||||
// expected to use something like clock.WallClock, and tests can override
|
|
||||||
// this to not actually sleep in tests.
|
|
||||||
Clock Clock
|
|
||||||
|
|
||||||
// Stop is a channel that can be used to indicate that the waiting should
|
|
||||||
// be interrupted. If Stop is nil, then the Call function cannot be interrupted.
|
|
||||||
// If the channel is closed prior to the Call function being executed, the
|
|
||||||
// Func is still attempted once.
|
|
||||||
Stop <-chan struct{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validate the values are valid. The ensures that the Func, Delay, Attempts
|
|
||||||
// and Clock have been specified.
|
|
||||||
func (args *CallArgs) Validate() error {
|
|
||||||
if args.Func == nil {
|
|
||||||
return errors.NotValidf("missing Func")
|
|
||||||
}
|
|
||||||
if args.Delay == 0 {
|
|
||||||
return errors.NotValidf("missing Delay")
|
|
||||||
}
|
|
||||||
if args.Clock == nil {
|
|
||||||
return errors.NotValidf("missing Clock")
|
|
||||||
}
|
|
||||||
// One of Attempts or MaxDuration need to be specified
|
|
||||||
if args.Attempts == 0 && args.MaxDuration == 0 {
|
|
||||||
return errors.NotValidf("missing Attempts or MaxDuration")
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Call will repeatedly execute the Func until either the function returns no
|
|
||||||
// error, the retry count is exceeded or the stop channel is closed.
|
|
||||||
func Call(args CallArgs) error {
|
|
||||||
err := args.Validate()
|
|
||||||
if err != nil {
|
|
||||||
return errors.Trace(err)
|
|
||||||
}
|
|
||||||
start := args.Clock.Now()
|
|
||||||
for i := 1; args.Attempts <= 0 || i <= args.Attempts; i++ {
|
|
||||||
err = args.Func()
|
|
||||||
if err == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if args.IsFatalError != nil && args.IsFatalError(err) {
|
|
||||||
return errors.Trace(err)
|
|
||||||
}
|
|
||||||
if args.NotifyFunc != nil {
|
|
||||||
args.NotifyFunc(err, i)
|
|
||||||
}
|
|
||||||
if i == args.Attempts && args.Attempts > 0 {
|
|
||||||
break // don't wait before returning the error
|
|
||||||
}
|
|
||||||
|
|
||||||
if args.BackoffFunc != nil {
|
|
||||||
delay := args.BackoffFunc(args.Delay, i)
|
|
||||||
if delay > args.MaxDelay && args.MaxDelay > 0 {
|
|
||||||
delay = args.MaxDelay
|
|
||||||
}
|
|
||||||
args.Delay = delay
|
|
||||||
}
|
|
||||||
elapsedTime := args.Clock.Now().Sub(start)
|
|
||||||
if args.MaxDuration > 0 && (elapsedTime+args.Delay) > args.MaxDuration {
|
|
||||||
return errors.Wrap(err, &durationExceeded{err})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wait for the delay, and retry
|
|
||||||
select {
|
|
||||||
case <-args.Clock.After(args.Delay):
|
|
||||||
case <-args.Stop:
|
|
||||||
return errors.Wrap(err, &retryStopped{err})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return errors.Wrap(err, &attemptsExceeded{err})
|
|
||||||
}
|
|
||||||
|
|
||||||
// DoubleDelay provides a simple function that doubles the duration passed in.
|
|
||||||
// This can then be easily used as the BackoffFunc in the CallArgs
|
|
||||||
// structure.
|
|
||||||
func DoubleDelay(delay time.Duration, attempt int) time.Duration {
|
|
||||||
if attempt == 1 {
|
|
||||||
return delay
|
|
||||||
}
|
|
||||||
return delay * 2
|
|
||||||
}
|
|
||||||
|
|
||||||
// ExpBackoff returns a function a which generates time.Duration values using
|
|
||||||
// an exponential back-off algorithm with the specified parameters. The
|
|
||||||
// returned value can then be easily used as the BackoffFunc in the CallArgs
|
|
||||||
// structure.
|
|
||||||
//
|
|
||||||
// The next delay value is calculated using the following formula:
|
|
||||||
//
|
|
||||||
// newDelay = min(minDelay * exp^attempt, maxDelay)
|
|
||||||
//
|
|
||||||
// If applyJitter is set to true, the function will randomly select and return
|
|
||||||
// back a value in the [minDelay, newDelay] range.
|
|
||||||
func ExpBackoff(minDelay, maxDelay time.Duration, exp float64, applyJitter bool) func(time.Duration, int) time.Duration {
|
|
||||||
minDelayF := float64(minDelay)
|
|
||||||
maxDelayF := float64(maxDelay)
|
|
||||||
return func(_ time.Duration, attempt int) time.Duration {
|
|
||||||
newDelay := minDelayF * math.Pow(exp, float64(attempt))
|
|
||||||
|
|
||||||
// Return a random value in the [minDelay, newDelay) range.
|
|
||||||
if applyJitter {
|
|
||||||
// We want to go +/- 20%, which is a 40% swing, and
|
|
||||||
// Float64 returns in the range 0-1
|
|
||||||
newDelay = (1 + rand.Float64()*0.4 - 0.2) * newDelay
|
|
||||||
}
|
|
||||||
if newDelay < minDelayF {
|
|
||||||
newDelay = minDelayF
|
|
||||||
}
|
|
||||||
if newDelay > maxDelayF {
|
|
||||||
newDelay = maxDelayF
|
|
||||||
}
|
|
||||||
return time.Duration(newDelay).Round(time.Millisecond)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
13
vendor/modules.txt
vendored
13
vendor/modules.txt
vendored
|
|
@ -131,19 +131,6 @@ github.com/jinzhu/now
|
||||||
# github.com/josharian/intern v1.0.0
|
# github.com/josharian/intern v1.0.0
|
||||||
## explicit; go 1.5
|
## explicit; go 1.5
|
||||||
github.com/josharian/intern
|
github.com/josharian/intern
|
||||||
# github.com/juju/clock v1.1.1
|
|
||||||
## explicit; go 1.18
|
|
||||||
github.com/juju/clock
|
|
||||||
# github.com/juju/errors v1.0.0
|
|
||||||
## explicit; go 1.18
|
|
||||||
github.com/juju/errors
|
|
||||||
# github.com/juju/loggo v1.0.0
|
|
||||||
## explicit; go 1.14
|
|
||||||
# github.com/juju/retry v1.0.1
|
|
||||||
## explicit; go 1.17
|
|
||||||
github.com/juju/retry
|
|
||||||
# github.com/juju/testing v1.0.2
|
|
||||||
## explicit; go 1.17
|
|
||||||
# github.com/mailru/easyjson v0.9.0
|
# github.com/mailru/easyjson v0.9.0
|
||||||
## explicit; go 1.20
|
## explicit; go 1.20
|
||||||
github.com/mailru/easyjson/buffer
|
github.com/mailru/easyjson/buffer
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ package websocket
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
"net"
|
"net"
|
||||||
|
|
@ -24,7 +25,6 @@ import (
|
||||||
|
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
"github.com/gorilla/websocket"
|
"github.com/gorilla/websocket"
|
||||||
"github.com/pkg/errors"
|
|
||||||
|
|
||||||
"github.com/cloudbase/garm/auth"
|
"github.com/cloudbase/garm/auth"
|
||||||
"github.com/cloudbase/garm/database/common"
|
"github.com/cloudbase/garm/database/common"
|
||||||
|
|
@ -63,7 +63,7 @@ func NewClient(ctx context.Context, conn *websocket.Conn) (*Client, error) {
|
||||||
watcher.WithUserIDFilter(user),
|
watcher.WithUserIDFilter(user),
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "registering consumer")
|
return nil, fmt.Errorf("error registering consumer: %w", err)
|
||||||
}
|
}
|
||||||
return &Client{
|
return &Client{
|
||||||
id: clientID.String(),
|
id: clientID.String(),
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue