Use watcher and get rid of RefreshState()
This change uses the database watcher to watch for changes to the github entities, credentials and controller info. Signed-off-by: Gabriel Adrian Samfira <gsamfira@cloudbasesolutions.com>
This commit is contained in:
parent
38127af747
commit
daaca0bd8f
23 changed files with 452 additions and 462 deletions
|
|
@ -46,7 +46,20 @@ type InstanceJWTClaims struct {
|
||||||
jwt.RegisteredClaims
|
jwt.RegisteredClaims
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewInstanceJWTToken(instance params.Instance, secret, entity string, poolType params.GithubEntityType, ttlMinutes uint) (string, error) {
|
func NewInstanceTokenGetter(jwtSecret string) (InstanceTokenGetter, error) {
|
||||||
|
if jwtSecret == "" {
|
||||||
|
return nil, fmt.Errorf("jwt secret is required")
|
||||||
|
}
|
||||||
|
return &instanceToken{
|
||||||
|
jwtSecret: jwtSecret,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type instanceToken struct {
|
||||||
|
jwtSecret string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *instanceToken) NewInstanceJWTToken(instance params.Instance, entity string, poolType params.GithubEntityType, ttlMinutes uint) (string, error) {
|
||||||
// Token expiration is equal to the bootstrap timeout set on the pool plus the polling
|
// Token expiration is equal to the bootstrap timeout set on the pool plus the polling
|
||||||
// interval garm uses to check for timed out runners. Runners that have not sent their info
|
// interval garm uses to check for timed out runners. Runners that have not sent their info
|
||||||
// by the end of this interval are most likely failed and will be reaped by garm anyway.
|
// by the end of this interval are most likely failed and will be reaped by garm anyway.
|
||||||
|
|
@ -67,7 +80,7 @@ func NewInstanceJWTToken(instance params.Instance, secret, entity string, poolTy
|
||||||
CreateAttempt: instance.CreateAttempt,
|
CreateAttempt: instance.CreateAttempt,
|
||||||
}
|
}
|
||||||
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
|
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
|
||||||
tokenString, err := token.SignedString([]byte(secret))
|
tokenString, err := token.SignedString([]byte(i.jwtSecret))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", errors.Wrap(err, "signing token")
|
return "", errors.Wrap(err, "signing token")
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,9 +14,17 @@
|
||||||
|
|
||||||
package auth
|
package auth
|
||||||
|
|
||||||
import "net/http"
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/cloudbase/garm/params"
|
||||||
|
)
|
||||||
|
|
||||||
// Middleware defines an authentication middleware
|
// Middleware defines an authentication middleware
|
||||||
type Middleware interface {
|
type Middleware interface {
|
||||||
Middleware(next http.Handler) http.Handler
|
Middleware(next http.Handler) http.Handler
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type InstanceTokenGetter interface {
|
||||||
|
NewInstanceJWTToken(instance params.Instance, entity string, poolType params.GithubEntityType, ttlMinutes uint) (string, error)
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -303,6 +303,10 @@ func parseCredentialsAddParams() (ret params.CreateGithubCredentialsParams, err
|
||||||
func parseCredentialsUpdateParams() (params.UpdateGithubCredentialsParams, error) {
|
func parseCredentialsUpdateParams() (params.UpdateGithubCredentialsParams, error) {
|
||||||
var updateParams params.UpdateGithubCredentialsParams
|
var updateParams params.UpdateGithubCredentialsParams
|
||||||
|
|
||||||
|
if credentialsAppInstallationID != 0 || credentialsAppID != 0 || credentialsPrivateKeyPath != "" {
|
||||||
|
updateParams.App = ¶ms.GithubApp{}
|
||||||
|
}
|
||||||
|
|
||||||
if credentialsName != "" {
|
if credentialsName != "" {
|
||||||
updateParams.Name = &credentialsName
|
updateParams.Name = &credentialsName
|
||||||
}
|
}
|
||||||
|
|
@ -312,6 +316,9 @@ func parseCredentialsUpdateParams() (params.UpdateGithubCredentialsParams, error
|
||||||
}
|
}
|
||||||
|
|
||||||
if credentialsOAuthToken != "" {
|
if credentialsOAuthToken != "" {
|
||||||
|
if updateParams.PAT == nil {
|
||||||
|
updateParams.PAT = ¶ms.GithubPAT{}
|
||||||
|
}
|
||||||
updateParams.PAT.OAuth2Token = credentialsOAuthToken
|
updateParams.PAT.OAuth2Token = credentialsOAuthToken
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -132,7 +132,7 @@ func (s *sqlDatabase) ListEnterprises(_ context.Context) ([]params.Enterprise, e
|
||||||
}
|
}
|
||||||
|
|
||||||
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")
|
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 errors.Wrap(err, "fetching enterprise")
|
||||||
}
|
}
|
||||||
|
|
@ -206,17 +206,13 @@ func (s *sqlDatabase) UpdateEnterprise(ctx context.Context, enterpriseID string,
|
||||||
return errors.Wrap(q.Error, "saving enterprise")
|
return errors.Wrap(q.Error, "saving enterprise")
|
||||||
}
|
}
|
||||||
|
|
||||||
if creds.ID != 0 {
|
|
||||||
enterprise.Credentials = creds
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return params.Enterprise{}, errors.Wrap(err, "updating enterprise")
|
return params.Enterprise{}, errors.Wrap(err, "updating enterprise")
|
||||||
}
|
}
|
||||||
|
|
||||||
enterprise, err = s.getEnterpriseByID(ctx, s.conn, enterpriseID, "Endpoint", "Credentials")
|
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{}, errors.Wrap(err, "updating enterprise")
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -123,7 +123,7 @@ func (s *sqlDatabase) ListOrganizations(_ context.Context) ([]params.Organizatio
|
||||||
}
|
}
|
||||||
|
|
||||||
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")
|
org, err := s.getOrgByID(ctx, s.conn, orgID, "Endpoint", "Credentials", "Credentials.Endpoint")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "fetching org")
|
return errors.Wrap(err, "fetching org")
|
||||||
}
|
}
|
||||||
|
|
@ -198,17 +198,13 @@ func (s *sqlDatabase) UpdateOrganization(ctx context.Context, orgID string, para
|
||||||
return errors.Wrap(q.Error, "saving org")
|
return errors.Wrap(q.Error, "saving org")
|
||||||
}
|
}
|
||||||
|
|
||||||
if creds.ID != 0 {
|
|
||||||
org.Credentials = creds
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return params.Organization{}, errors.Wrap(err, "saving org")
|
return params.Organization{}, errors.Wrap(err, "saving org")
|
||||||
}
|
}
|
||||||
|
|
||||||
org, err = s.getOrgByID(ctx, s.conn, orgID, "Endpoint", "Credentials")
|
org, err = s.getOrgByID(ctx, s.conn, orgID, "Endpoint", "Credentials", "Credentials.Endpoint")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return params.Organization{}, errors.Wrap(err, "updating enterprise")
|
return params.Organization{}, errors.Wrap(err, "updating enterprise")
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -122,7 +122,7 @@ func (s *sqlDatabase) ListRepositories(_ context.Context) ([]params.Repository,
|
||||||
}
|
}
|
||||||
|
|
||||||
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")
|
repo, err := s.getRepoByID(ctx, s.conn, repoID, "Endpoint", "Credentials", "Credentials.Endpoint")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "fetching repo")
|
return errors.Wrap(err, "fetching repo")
|
||||||
}
|
}
|
||||||
|
|
@ -197,16 +197,13 @@ func (s *sqlDatabase) UpdateRepository(ctx context.Context, repoID string, param
|
||||||
return errors.Wrap(q.Error, "saving repo")
|
return errors.Wrap(q.Error, "saving repo")
|
||||||
}
|
}
|
||||||
|
|
||||||
if creds.ID != 0 {
|
|
||||||
repo.Credentials = creds
|
|
||||||
}
|
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return params.Repository{}, errors.Wrap(err, "saving repo")
|
return params.Repository{}, errors.Wrap(err, "saving repo")
|
||||||
}
|
}
|
||||||
|
|
||||||
repo, err = s.getRepoByID(ctx, s.conn, repoID, "Endpoint", "Credentials")
|
repo, err = s.getRepoByID(ctx, s.conn, repoID, "Endpoint", "Credentials", "Credentials.Endpoint")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return params.Repository{}, errors.Wrap(err, "updating enterprise")
|
return params.Repository{}, errors.Wrap(err, "updating enterprise")
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,18 @@ func WithAny(filters ...dbCommon.PayloadFilterFunc) dbCommon.PayloadFilterFunc {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WithAll returns a filter function that returns true if all of the provided filters return true.
|
||||||
|
func WithAll(filters ...dbCommon.PayloadFilterFunc) dbCommon.PayloadFilterFunc {
|
||||||
|
return func(payload dbCommon.ChangePayload) bool {
|
||||||
|
for _, filter := range filters {
|
||||||
|
if !filter(payload) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// WithEntityTypeFilter returns a filter function that filters payloads by entity type.
|
// WithEntityTypeFilter returns a filter function that filters payloads by entity type.
|
||||||
// The filter function returns true if the payload's entity type matches the provided entity type.
|
// The filter function returns true if the payload's entity type matches the provided entity type.
|
||||||
func WithEntityTypeFilter(entityType dbCommon.DatabaseEntityType) dbCommon.PayloadFilterFunc {
|
func WithEntityTypeFilter(entityType dbCommon.DatabaseEntityType) dbCommon.PayloadFilterFunc {
|
||||||
|
|
@ -139,3 +151,17 @@ func WithEntityJobFilter(ghEntity params.GithubEntity) dbCommon.PayloadFilterFun
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WithGithubCredentialsFilter returns a filter function that filters payloads by Github credentials.
|
||||||
|
func WithGithubCredentialsFilter(creds params.GithubCredentials) dbCommon.PayloadFilterFunc {
|
||||||
|
return func(payload dbCommon.ChangePayload) bool {
|
||||||
|
if payload.EntityType != dbCommon.GithubCredentialsEntityType {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
credsPayload, ok := payload.Payload.(params.GithubCredentials)
|
||||||
|
if !ok {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return credsPayload.ID == creds.ID
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -419,10 +419,13 @@ func (r Repository) GetEntity() (GithubEntity, error) {
|
||||||
return GithubEntity{}, fmt.Errorf("repository has no ID")
|
return GithubEntity{}, fmt.Errorf("repository has no ID")
|
||||||
}
|
}
|
||||||
return GithubEntity{
|
return GithubEntity{
|
||||||
ID: r.ID,
|
ID: r.ID,
|
||||||
EntityType: GithubEntityTypeRepository,
|
EntityType: GithubEntityTypeRepository,
|
||||||
Owner: r.Owner,
|
Owner: r.Owner,
|
||||||
Name: r.Name,
|
Name: r.Name,
|
||||||
|
PoolBalancerType: r.PoolBalancerType,
|
||||||
|
Credentials: r.Credentials,
|
||||||
|
WebhookSecret: r.WebhookSecret,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -470,10 +473,12 @@ func (o Organization) GetEntity() (GithubEntity, error) {
|
||||||
return GithubEntity{}, fmt.Errorf("organization has no ID")
|
return GithubEntity{}, fmt.Errorf("organization has no ID")
|
||||||
}
|
}
|
||||||
return GithubEntity{
|
return GithubEntity{
|
||||||
ID: o.ID,
|
ID: o.ID,
|
||||||
EntityType: GithubEntityTypeOrganization,
|
EntityType: GithubEntityTypeOrganization,
|
||||||
Owner: o.Name,
|
Owner: o.Name,
|
||||||
WebhookSecret: o.WebhookSecret,
|
WebhookSecret: o.WebhookSecret,
|
||||||
|
PoolBalancerType: o.PoolBalancerType,
|
||||||
|
Credentials: o.Credentials,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -517,10 +522,12 @@ func (e Enterprise) GetEntity() (GithubEntity, error) {
|
||||||
return GithubEntity{}, fmt.Errorf("enterprise has no ID")
|
return GithubEntity{}, fmt.Errorf("enterprise has no ID")
|
||||||
}
|
}
|
||||||
return GithubEntity{
|
return GithubEntity{
|
||||||
ID: e.ID,
|
ID: e.ID,
|
||||||
EntityType: GithubEntityTypeEnterprise,
|
EntityType: GithubEntityTypeEnterprise,
|
||||||
Owner: e.Name,
|
Owner: e.Name,
|
||||||
WebhookSecret: e.WebhookSecret,
|
WebhookSecret: e.WebhookSecret,
|
||||||
|
PoolBalancerType: e.PoolBalancerType,
|
||||||
|
Credentials: e.Credentials,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -685,11 +692,6 @@ type Provider struct {
|
||||||
// used by swagger client generated code
|
// used by swagger client generated code
|
||||||
type Providers []Provider
|
type Providers []Provider
|
||||||
|
|
||||||
type UpdatePoolStateParams struct {
|
|
||||||
WebhookSecret string
|
|
||||||
InternalConfig *Internal
|
|
||||||
}
|
|
||||||
|
|
||||||
type PoolManagerStatus struct {
|
type PoolManagerStatus struct {
|
||||||
IsRunning bool `json:"running"`
|
IsRunning bool `json:"running"`
|
||||||
FailureReason string `json:"failure_reason,omitempty"`
|
FailureReason string `json:"failure_reason,omitempty"`
|
||||||
|
|
@ -788,15 +790,23 @@ type UpdateSystemInfoParams struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type GithubEntity struct {
|
type GithubEntity struct {
|
||||||
Owner string `json:"owner"`
|
Owner string `json:"owner"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
ID string `json:"id"`
|
ID string `json:"id"`
|
||||||
EntityType GithubEntityType `json:"entity_type"`
|
EntityType GithubEntityType `json:"entity_type"`
|
||||||
Credentials GithubCredentials `json:"credentials"`
|
Credentials GithubCredentials `json:"credentials"`
|
||||||
|
PoolBalancerType PoolBalancerType `json:"pool_balancing_type"`
|
||||||
|
|
||||||
WebhookSecret string `json:"-"`
|
WebhookSecret string `json:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (g GithubEntity) GetPoolBalancerType() PoolBalancerType {
|
||||||
|
if g.PoolBalancerType == "" {
|
||||||
|
return PoolBalancerTypeRoundRobin
|
||||||
|
}
|
||||||
|
return g.PoolBalancerType
|
||||||
|
}
|
||||||
|
|
||||||
func (g GithubEntity) LabelScope() string {
|
func (g GithubEntity) LabelScope() string {
|
||||||
switch g.EntityType {
|
switch g.EntityType {
|
||||||
case GithubEntityTypeRepository:
|
case GithubEntityTypeRepository:
|
||||||
|
|
|
||||||
|
|
@ -152,24 +152,6 @@ func (_m *PoolManager) InstallWebhook(ctx context.Context, param params.InstallW
|
||||||
return r0, r1
|
return r0, r1
|
||||||
}
|
}
|
||||||
|
|
||||||
// RefreshState provides a mock function with given fields: param
|
|
||||||
func (_m *PoolManager) RefreshState(param params.UpdatePoolStateParams) error {
|
|
||||||
ret := _m.Called(param)
|
|
||||||
|
|
||||||
if len(ret) == 0 {
|
|
||||||
panic("no return value specified for RefreshState")
|
|
||||||
}
|
|
||||||
|
|
||||||
var r0 error
|
|
||||||
if rf, ok := ret.Get(0).(func(params.UpdatePoolStateParams) error); ok {
|
|
||||||
r0 = rf(param)
|
|
||||||
} else {
|
|
||||||
r0 = ret.Error(0)
|
|
||||||
}
|
|
||||||
|
|
||||||
return r0
|
|
||||||
}
|
|
||||||
|
|
||||||
// RootCABundle provides a mock function with given fields:
|
// RootCABundle provides a mock function with given fields:
|
||||||
func (_m *PoolManager) RootCABundle() (params.CertificateBundle, error) {
|
func (_m *PoolManager) RootCABundle() (params.CertificateBundle, error) {
|
||||||
ret := _m.Called()
|
ret := _m.Called()
|
||||||
|
|
|
||||||
|
|
@ -53,8 +53,6 @@ type PoolManager interface {
|
||||||
// a repo, org or enterprise, we determine the destination of that webhook, retrieve the pool manager
|
// a repo, org or enterprise, we determine the destination of that webhook, retrieve the pool manager
|
||||||
// for it and call this function with the WorkflowJob as a parameter.
|
// for it and call this function with the WorkflowJob as a parameter.
|
||||||
HandleWorkflowJob(job params.WorkflowJob) error
|
HandleWorkflowJob(job params.WorkflowJob) error
|
||||||
// RefreshState allows us to update webhook secrets and configuration for a pool manager.
|
|
||||||
RefreshState(param params.UpdatePoolStateParams) error
|
|
||||||
|
|
||||||
// DeleteRunner will attempt to remove a runner from the pool. If forceRemove is true, any error
|
// DeleteRunner will attempt to remove a runner from the pool. If forceRemove is true, any error
|
||||||
// received from the provider will be ignored and we will proceed to remove the runner from the database.
|
// received from the provider will be ignored and we will proceed to remove the runner from the database.
|
||||||
|
|
|
||||||
|
|
@ -174,11 +174,9 @@ func (r *Runner) UpdateEnterprise(ctx context.Context, enterpriseID string, para
|
||||||
return params.Enterprise{}, errors.Wrap(err, "updating enterprise")
|
return params.Enterprise{}, errors.Wrap(err, "updating enterprise")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use the admin context in the pool manager. Any access control is already done above when
|
poolMgr, err := r.poolManagerCtrl.GetEnterprisePoolManager(enterprise)
|
||||||
// updating the store.
|
|
||||||
poolMgr, err := r.poolManagerCtrl.UpdateEnterprisePoolManager(r.ctx, enterprise)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return params.Enterprise{}, fmt.Errorf("failed to update enterprise pool manager: %w", err)
|
return params.Enterprise{}, fmt.Errorf("failed to get enterprise pool manager: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
enterprise.PoolManagerStatus = poolMgr.Status()
|
enterprise.PoolManagerStatus = poolMgr.Status()
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,6 @@ type EnterpriseTestFixtures struct {
|
||||||
CreateInstanceParams params.CreateInstanceParams
|
CreateInstanceParams params.CreateInstanceParams
|
||||||
UpdateRepoParams params.UpdateEntityParams
|
UpdateRepoParams params.UpdateEntityParams
|
||||||
UpdatePoolParams params.UpdatePoolParams
|
UpdatePoolParams params.UpdatePoolParams
|
||||||
UpdatePoolStateParams params.UpdatePoolStateParams
|
|
||||||
ErrMock error
|
ErrMock error
|
||||||
ProviderMock *runnerCommonMocks.Provider
|
ProviderMock *runnerCommonMocks.Provider
|
||||||
PoolMgrMock *runnerCommonMocks.PoolManager
|
PoolMgrMock *runnerCommonMocks.PoolManager
|
||||||
|
|
@ -138,9 +137,6 @@ func (s *EnterpriseTestSuite) SetupTest() {
|
||||||
Image: "test-images-updated",
|
Image: "test-images-updated",
|
||||||
Flavor: "test-flavor-updated",
|
Flavor: "test-flavor-updated",
|
||||||
},
|
},
|
||||||
UpdatePoolStateParams: params.UpdatePoolStateParams{
|
|
||||||
WebhookSecret: "test-update-repo-webhook-secret",
|
|
||||||
},
|
|
||||||
ErrMock: fmt.Errorf("mock error"),
|
ErrMock: fmt.Errorf("mock error"),
|
||||||
ProviderMock: providerMock,
|
ProviderMock: providerMock,
|
||||||
PoolMgrMock: runnerCommonMocks.NewPoolManager(s.T()),
|
PoolMgrMock: runnerCommonMocks.NewPoolManager(s.T()),
|
||||||
|
|
@ -298,7 +294,7 @@ func (s *EnterpriseTestSuite) TestDeleteEnterprisePoolMgrFailed() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *EnterpriseTestSuite) TestUpdateEnterprise() {
|
func (s *EnterpriseTestSuite) TestUpdateEnterprise() {
|
||||||
s.Fixtures.PoolMgrCtrlMock.On("UpdateEnterprisePoolManager", s.Fixtures.AdminContext, mock.AnythingOfType("params.Enterprise")).Return(s.Fixtures.PoolMgrMock, nil)
|
s.Fixtures.PoolMgrCtrlMock.On("GetEnterprisePoolManager", mock.AnythingOfType("params.Enterprise")).Return(s.Fixtures.PoolMgrMock, nil)
|
||||||
s.Fixtures.PoolMgrMock.On("Status").Return(params.PoolManagerStatus{IsRunning: true}, nil)
|
s.Fixtures.PoolMgrMock.On("Status").Return(params.PoolManagerStatus{IsRunning: true}, nil)
|
||||||
|
|
||||||
param := s.Fixtures.UpdateRepoParams
|
param := s.Fixtures.UpdateRepoParams
|
||||||
|
|
@ -330,21 +326,21 @@ func (s *EnterpriseTestSuite) TestUpdateEnterpriseInvalidCreds() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *EnterpriseTestSuite) TestUpdateEnterprisePoolMgrFailed() {
|
func (s *EnterpriseTestSuite) TestUpdateEnterprisePoolMgrFailed() {
|
||||||
s.Fixtures.PoolMgrCtrlMock.On("UpdateEnterprisePoolManager", s.Fixtures.AdminContext, mock.AnythingOfType("params.Enterprise")).Return(s.Fixtures.PoolMgrMock, s.Fixtures.ErrMock)
|
s.Fixtures.PoolMgrCtrlMock.On("GetEnterprisePoolManager", mock.AnythingOfType("params.Enterprise")).Return(s.Fixtures.PoolMgrMock, s.Fixtures.ErrMock)
|
||||||
|
|
||||||
_, err := s.Runner.UpdateEnterprise(s.Fixtures.AdminContext, s.Fixtures.StoreEnterprises["test-enterprise-1"].ID, s.Fixtures.UpdateRepoParams)
|
_, err := s.Runner.UpdateEnterprise(s.Fixtures.AdminContext, s.Fixtures.StoreEnterprises["test-enterprise-1"].ID, s.Fixtures.UpdateRepoParams)
|
||||||
|
|
||||||
s.Fixtures.PoolMgrCtrlMock.AssertExpectations(s.T())
|
s.Fixtures.PoolMgrCtrlMock.AssertExpectations(s.T())
|
||||||
s.Require().Equal(fmt.Sprintf("failed to update enterprise pool manager: %s", s.Fixtures.ErrMock.Error()), err.Error())
|
s.Require().Equal(fmt.Sprintf("failed to get enterprise pool manager: %s", s.Fixtures.ErrMock.Error()), err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *EnterpriseTestSuite) TestUpdateEnterpriseCreateEnterprisePoolMgrFailed() {
|
func (s *EnterpriseTestSuite) TestUpdateEnterpriseCreateEnterprisePoolMgrFailed() {
|
||||||
s.Fixtures.PoolMgrCtrlMock.On("UpdateEnterprisePoolManager", s.Fixtures.AdminContext, mock.AnythingOfType("params.Enterprise")).Return(s.Fixtures.PoolMgrMock, s.Fixtures.ErrMock)
|
s.Fixtures.PoolMgrCtrlMock.On("GetEnterprisePoolManager", mock.AnythingOfType("params.Enterprise")).Return(s.Fixtures.PoolMgrMock, s.Fixtures.ErrMock)
|
||||||
|
|
||||||
_, err := s.Runner.UpdateEnterprise(s.Fixtures.AdminContext, s.Fixtures.StoreEnterprises["test-enterprise-1"].ID, s.Fixtures.UpdateRepoParams)
|
_, err := s.Runner.UpdateEnterprise(s.Fixtures.AdminContext, s.Fixtures.StoreEnterprises["test-enterprise-1"].ID, s.Fixtures.UpdateRepoParams)
|
||||||
|
|
||||||
s.Fixtures.PoolMgrCtrlMock.AssertExpectations(s.T())
|
s.Fixtures.PoolMgrCtrlMock.AssertExpectations(s.T())
|
||||||
s.Require().Equal(fmt.Sprintf("failed to update enterprise pool manager: %s", s.Fixtures.ErrMock.Error()), err.Error())
|
s.Require().Equal(fmt.Sprintf("failed to get enterprise pool manager: %s", s.Fixtures.ErrMock.Error()), err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *EnterpriseTestSuite) TestCreateEnterprisePool() {
|
func (s *EnterpriseTestSuite) TestCreateEnterprisePool() {
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,6 @@ import (
|
||||||
|
|
||||||
type RepoPoolManager interface {
|
type RepoPoolManager interface {
|
||||||
CreateRepoPoolManager(ctx context.Context, repo params.Repository, providers map[string]common.Provider, store dbCommon.Store) (common.PoolManager, error)
|
CreateRepoPoolManager(ctx context.Context, repo params.Repository, providers map[string]common.Provider, store dbCommon.Store) (common.PoolManager, error)
|
||||||
UpdateRepoPoolManager(ctx context.Context, repo params.Repository) (common.PoolManager, error)
|
|
||||||
GetRepoPoolManager(repo params.Repository) (common.PoolManager, error)
|
GetRepoPoolManager(repo params.Repository) (common.PoolManager, error)
|
||||||
DeleteRepoPoolManager(repo params.Repository) error
|
DeleteRepoPoolManager(repo params.Repository) error
|
||||||
GetRepoPoolManagers() (map[string]common.PoolManager, error)
|
GetRepoPoolManagers() (map[string]common.PoolManager, error)
|
||||||
|
|
@ -32,7 +31,6 @@ type RepoPoolManager interface {
|
||||||
|
|
||||||
type OrgPoolManager interface {
|
type OrgPoolManager interface {
|
||||||
CreateOrgPoolManager(ctx context.Context, org params.Organization, providers map[string]common.Provider, store dbCommon.Store) (common.PoolManager, error)
|
CreateOrgPoolManager(ctx context.Context, org params.Organization, providers map[string]common.Provider, store dbCommon.Store) (common.PoolManager, error)
|
||||||
UpdateOrgPoolManager(ctx context.Context, org params.Organization) (common.PoolManager, error)
|
|
||||||
GetOrgPoolManager(org params.Organization) (common.PoolManager, error)
|
GetOrgPoolManager(org params.Organization) (common.PoolManager, error)
|
||||||
DeleteOrgPoolManager(org params.Organization) error
|
DeleteOrgPoolManager(org params.Organization) error
|
||||||
GetOrgPoolManagers() (map[string]common.PoolManager, error)
|
GetOrgPoolManagers() (map[string]common.PoolManager, error)
|
||||||
|
|
@ -40,7 +38,6 @@ type OrgPoolManager interface {
|
||||||
|
|
||||||
type EnterprisePoolManager interface {
|
type EnterprisePoolManager interface {
|
||||||
CreateEnterprisePoolManager(ctx context.Context, enterprise params.Enterprise, providers map[string]common.Provider, store dbCommon.Store) (common.PoolManager, error)
|
CreateEnterprisePoolManager(ctx context.Context, enterprise params.Enterprise, providers map[string]common.Provider, store dbCommon.Store) (common.PoolManager, error)
|
||||||
UpdateEnterprisePoolManager(ctx context.Context, enterprise params.Enterprise) (common.PoolManager, error)
|
|
||||||
GetEnterprisePoolManager(enterprise params.Enterprise) (common.PoolManager, error)
|
GetEnterprisePoolManager(enterprise params.Enterprise) (common.PoolManager, error)
|
||||||
DeleteEnterprisePoolManager(enterprise params.Enterprise) error
|
DeleteEnterprisePoolManager(enterprise params.Enterprise) error
|
||||||
GetEnterprisePoolManagers() (map[string]common.PoolManager, error)
|
GetEnterprisePoolManagers() (map[string]common.PoolManager, error)
|
||||||
|
|
|
||||||
|
|
@ -343,96 +343,6 @@ func (_m *PoolManagerController) GetRepoPoolManagers() (map[string]common.PoolMa
|
||||||
return r0, r1
|
return r0, r1
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateEnterprisePoolManager provides a mock function with given fields: ctx, enterprise
|
|
||||||
func (_m *PoolManagerController) UpdateEnterprisePoolManager(ctx context.Context, enterprise params.Enterprise) (common.PoolManager, error) {
|
|
||||||
ret := _m.Called(ctx, enterprise)
|
|
||||||
|
|
||||||
if len(ret) == 0 {
|
|
||||||
panic("no return value specified for UpdateEnterprisePoolManager")
|
|
||||||
}
|
|
||||||
|
|
||||||
var r0 common.PoolManager
|
|
||||||
var r1 error
|
|
||||||
if rf, ok := ret.Get(0).(func(context.Context, params.Enterprise) (common.PoolManager, error)); ok {
|
|
||||||
return rf(ctx, enterprise)
|
|
||||||
}
|
|
||||||
if rf, ok := ret.Get(0).(func(context.Context, params.Enterprise) common.PoolManager); ok {
|
|
||||||
r0 = rf(ctx, enterprise)
|
|
||||||
} else {
|
|
||||||
if ret.Get(0) != nil {
|
|
||||||
r0 = ret.Get(0).(common.PoolManager)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if rf, ok := ret.Get(1).(func(context.Context, params.Enterprise) error); ok {
|
|
||||||
r1 = rf(ctx, enterprise)
|
|
||||||
} else {
|
|
||||||
r1 = ret.Error(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
return r0, r1
|
|
||||||
}
|
|
||||||
|
|
||||||
// UpdateOrgPoolManager provides a mock function with given fields: ctx, org
|
|
||||||
func (_m *PoolManagerController) UpdateOrgPoolManager(ctx context.Context, org params.Organization) (common.PoolManager, error) {
|
|
||||||
ret := _m.Called(ctx, org)
|
|
||||||
|
|
||||||
if len(ret) == 0 {
|
|
||||||
panic("no return value specified for UpdateOrgPoolManager")
|
|
||||||
}
|
|
||||||
|
|
||||||
var r0 common.PoolManager
|
|
||||||
var r1 error
|
|
||||||
if rf, ok := ret.Get(0).(func(context.Context, params.Organization) (common.PoolManager, error)); ok {
|
|
||||||
return rf(ctx, org)
|
|
||||||
}
|
|
||||||
if rf, ok := ret.Get(0).(func(context.Context, params.Organization) common.PoolManager); ok {
|
|
||||||
r0 = rf(ctx, org)
|
|
||||||
} else {
|
|
||||||
if ret.Get(0) != nil {
|
|
||||||
r0 = ret.Get(0).(common.PoolManager)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if rf, ok := ret.Get(1).(func(context.Context, params.Organization) error); ok {
|
|
||||||
r1 = rf(ctx, org)
|
|
||||||
} else {
|
|
||||||
r1 = ret.Error(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
return r0, r1
|
|
||||||
}
|
|
||||||
|
|
||||||
// UpdateRepoPoolManager provides a mock function with given fields: ctx, repo
|
|
||||||
func (_m *PoolManagerController) UpdateRepoPoolManager(ctx context.Context, repo params.Repository) (common.PoolManager, error) {
|
|
||||||
ret := _m.Called(ctx, repo)
|
|
||||||
|
|
||||||
if len(ret) == 0 {
|
|
||||||
panic("no return value specified for UpdateRepoPoolManager")
|
|
||||||
}
|
|
||||||
|
|
||||||
var r0 common.PoolManager
|
|
||||||
var r1 error
|
|
||||||
if rf, ok := ret.Get(0).(func(context.Context, params.Repository) (common.PoolManager, error)); ok {
|
|
||||||
return rf(ctx, repo)
|
|
||||||
}
|
|
||||||
if rf, ok := ret.Get(0).(func(context.Context, params.Repository) common.PoolManager); ok {
|
|
||||||
r0 = rf(ctx, repo)
|
|
||||||
} else {
|
|
||||||
if ret.Get(0) != nil {
|
|
||||||
r0 = ret.Get(0).(common.PoolManager)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if rf, ok := ret.Get(1).(func(context.Context, params.Repository) error); ok {
|
|
||||||
r1 = rf(ctx, repo)
|
|
||||||
} else {
|
|
||||||
r1 = ret.Error(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
return r0, r1
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewPoolManagerController creates a new instance of PoolManagerController. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
|
// NewPoolManagerController creates a new instance of PoolManagerController. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
|
||||||
// The first argument is typically a *testing.T value.
|
// The first argument is typically a *testing.T value.
|
||||||
func NewPoolManagerController(t interface {
|
func NewPoolManagerController(t interface {
|
||||||
|
|
|
||||||
|
|
@ -203,11 +203,9 @@ func (r *Runner) UpdateOrganization(ctx context.Context, orgID string, param par
|
||||||
return params.Organization{}, errors.Wrap(err, "updating org")
|
return params.Organization{}, errors.Wrap(err, "updating org")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use the admin context in the pool manager. Any access control is already done above when
|
poolMgr, err := r.poolManagerCtrl.GetOrgPoolManager(org)
|
||||||
// updating the store.
|
|
||||||
poolMgr, err := r.poolManagerCtrl.UpdateOrgPoolManager(r.ctx, org)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return params.Organization{}, fmt.Errorf("updating org pool manager: %w", err)
|
return params.Organization{}, fmt.Errorf("failed to get org pool manager: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
org.PoolManagerStatus = poolMgr.Status()
|
org.PoolManagerStatus = poolMgr.Status()
|
||||||
|
|
|
||||||
|
|
@ -34,22 +34,21 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type OrgTestFixtures struct {
|
type OrgTestFixtures struct {
|
||||||
AdminContext context.Context
|
AdminContext context.Context
|
||||||
DBFile string
|
DBFile string
|
||||||
Store dbCommon.Store
|
Store dbCommon.Store
|
||||||
StoreOrgs map[string]params.Organization
|
StoreOrgs map[string]params.Organization
|
||||||
Providers map[string]common.Provider
|
Providers map[string]common.Provider
|
||||||
Credentials map[string]params.GithubCredentials
|
Credentials map[string]params.GithubCredentials
|
||||||
CreateOrgParams params.CreateOrgParams
|
CreateOrgParams params.CreateOrgParams
|
||||||
CreatePoolParams params.CreatePoolParams
|
CreatePoolParams params.CreatePoolParams
|
||||||
CreateInstanceParams params.CreateInstanceParams
|
CreateInstanceParams params.CreateInstanceParams
|
||||||
UpdateRepoParams params.UpdateEntityParams
|
UpdateRepoParams params.UpdateEntityParams
|
||||||
UpdatePoolParams params.UpdatePoolParams
|
UpdatePoolParams params.UpdatePoolParams
|
||||||
UpdatePoolStateParams params.UpdatePoolStateParams
|
ErrMock error
|
||||||
ErrMock error
|
ProviderMock *runnerCommonMocks.Provider
|
||||||
ProviderMock *runnerCommonMocks.Provider
|
PoolMgrMock *runnerCommonMocks.PoolManager
|
||||||
PoolMgrMock *runnerCommonMocks.PoolManager
|
PoolMgrCtrlMock *runnerMocks.PoolManagerController
|
||||||
PoolMgrCtrlMock *runnerMocks.PoolManagerController
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type OrgTestSuite struct {
|
type OrgTestSuite struct {
|
||||||
|
|
@ -139,9 +138,6 @@ func (s *OrgTestSuite) SetupTest() {
|
||||||
Image: "test-images-updated",
|
Image: "test-images-updated",
|
||||||
Flavor: "test-flavor-updated",
|
Flavor: "test-flavor-updated",
|
||||||
},
|
},
|
||||||
UpdatePoolStateParams: params.UpdatePoolStateParams{
|
|
||||||
WebhookSecret: "test-update-repo-webhook-secret",
|
|
||||||
},
|
|
||||||
ErrMock: fmt.Errorf("mock error"),
|
ErrMock: fmt.Errorf("mock error"),
|
||||||
ProviderMock: providerMock,
|
ProviderMock: providerMock,
|
||||||
PoolMgrMock: runnerCommonMocks.NewPoolManager(s.T()),
|
PoolMgrMock: runnerCommonMocks.NewPoolManager(s.T()),
|
||||||
|
|
@ -312,7 +308,7 @@ func (s *OrgTestSuite) TestDeleteOrganizationPoolMgrFailed() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *OrgTestSuite) TestUpdateOrganization() {
|
func (s *OrgTestSuite) TestUpdateOrganization() {
|
||||||
s.Fixtures.PoolMgrCtrlMock.On("UpdateOrgPoolManager", s.Fixtures.AdminContext, mock.AnythingOfType("params.Organization")).Return(s.Fixtures.PoolMgrMock, nil)
|
s.Fixtures.PoolMgrCtrlMock.On("GetOrgPoolManager", mock.AnythingOfType("params.Organization")).Return(s.Fixtures.PoolMgrMock, nil)
|
||||||
s.Fixtures.PoolMgrMock.On("Status").Return(params.PoolManagerStatus{IsRunning: true}, nil)
|
s.Fixtures.PoolMgrMock.On("Status").Return(params.PoolManagerStatus{IsRunning: true}, nil)
|
||||||
|
|
||||||
org, err := s.Runner.UpdateOrganization(s.Fixtures.AdminContext, s.Fixtures.StoreOrgs["test-org-1"].ID, s.Fixtures.UpdateRepoParams)
|
org, err := s.Runner.UpdateOrganization(s.Fixtures.AdminContext, s.Fixtures.StoreOrgs["test-org-1"].ID, s.Fixtures.UpdateRepoParams)
|
||||||
|
|
@ -326,7 +322,7 @@ func (s *OrgTestSuite) TestUpdateOrganization() {
|
||||||
|
|
||||||
func (s *OrgTestSuite) TestUpdateRepositoryBalancingType() {
|
func (s *OrgTestSuite) TestUpdateRepositoryBalancingType() {
|
||||||
s.Fixtures.UpdateRepoParams.PoolBalancerType = params.PoolBalancerTypePack
|
s.Fixtures.UpdateRepoParams.PoolBalancerType = params.PoolBalancerTypePack
|
||||||
s.Fixtures.PoolMgrCtrlMock.On("UpdateOrgPoolManager", s.Fixtures.AdminContext, mock.AnythingOfType("params.Organization")).Return(s.Fixtures.PoolMgrMock, nil)
|
s.Fixtures.PoolMgrCtrlMock.On("GetOrgPoolManager", mock.AnythingOfType("params.Organization")).Return(s.Fixtures.PoolMgrMock, nil)
|
||||||
s.Fixtures.PoolMgrMock.On("Status").Return(params.PoolManagerStatus{IsRunning: true}, nil)
|
s.Fixtures.PoolMgrMock.On("Status").Return(params.PoolManagerStatus{IsRunning: true}, nil)
|
||||||
|
|
||||||
param := s.Fixtures.UpdateRepoParams
|
param := s.Fixtures.UpdateRepoParams
|
||||||
|
|
@ -355,21 +351,21 @@ func (s *OrgTestSuite) TestUpdateOrganizationInvalidCreds() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *OrgTestSuite) TestUpdateOrganizationPoolMgrFailed() {
|
func (s *OrgTestSuite) TestUpdateOrganizationPoolMgrFailed() {
|
||||||
s.Fixtures.PoolMgrCtrlMock.On("UpdateOrgPoolManager", s.Fixtures.AdminContext, mock.AnythingOfType("params.Organization")).Return(s.Fixtures.PoolMgrMock, s.Fixtures.ErrMock)
|
s.Fixtures.PoolMgrCtrlMock.On("GetOrgPoolManager", mock.AnythingOfType("params.Organization")).Return(s.Fixtures.PoolMgrMock, s.Fixtures.ErrMock)
|
||||||
|
|
||||||
_, err := s.Runner.UpdateOrganization(s.Fixtures.AdminContext, s.Fixtures.StoreOrgs["test-org-1"].ID, s.Fixtures.UpdateRepoParams)
|
_, err := s.Runner.UpdateOrganization(s.Fixtures.AdminContext, s.Fixtures.StoreOrgs["test-org-1"].ID, s.Fixtures.UpdateRepoParams)
|
||||||
|
|
||||||
s.Fixtures.PoolMgrCtrlMock.AssertExpectations(s.T())
|
s.Fixtures.PoolMgrCtrlMock.AssertExpectations(s.T())
|
||||||
s.Require().Equal(fmt.Sprintf("updating org pool manager: %s", s.Fixtures.ErrMock.Error()), err.Error())
|
s.Require().Equal(fmt.Sprintf("failed to get org pool manager: %s", s.Fixtures.ErrMock.Error()), err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *OrgTestSuite) TestUpdateOrganizationCreateOrgPoolMgrFailed() {
|
func (s *OrgTestSuite) TestUpdateOrganizationCreateOrgPoolMgrFailed() {
|
||||||
s.Fixtures.PoolMgrCtrlMock.On("UpdateOrgPoolManager", s.Fixtures.AdminContext, mock.AnythingOfType("params.Organization")).Return(s.Fixtures.PoolMgrMock, s.Fixtures.ErrMock)
|
s.Fixtures.PoolMgrCtrlMock.On("GetOrgPoolManager", mock.AnythingOfType("params.Organization")).Return(s.Fixtures.PoolMgrMock, s.Fixtures.ErrMock)
|
||||||
|
|
||||||
_, err := s.Runner.UpdateOrganization(s.Fixtures.AdminContext, s.Fixtures.StoreOrgs["test-org-1"].ID, s.Fixtures.UpdateRepoParams)
|
_, err := s.Runner.UpdateOrganization(s.Fixtures.AdminContext, s.Fixtures.StoreOrgs["test-org-1"].ID, s.Fixtures.UpdateRepoParams)
|
||||||
|
|
||||||
s.Fixtures.PoolMgrCtrlMock.AssertExpectations(s.T())
|
s.Fixtures.PoolMgrCtrlMock.AssertExpectations(s.T())
|
||||||
s.Require().Equal(fmt.Sprintf("updating org pool manager: %s", s.Fixtures.ErrMock.Error()), err.Error())
|
s.Require().Equal(fmt.Sprintf("failed to get org pool manager: %s", s.Fixtures.ErrMock.Error()), err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *OrgTestSuite) TestCreateOrgPool() {
|
func (s *OrgTestSuite) TestCreateOrgPool() {
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,7 @@ import (
|
||||||
"github.com/cloudbase/garm-provider-common/util"
|
"github.com/cloudbase/garm-provider-common/util"
|
||||||
"github.com/cloudbase/garm/auth"
|
"github.com/cloudbase/garm/auth"
|
||||||
dbCommon "github.com/cloudbase/garm/database/common"
|
dbCommon "github.com/cloudbase/garm/database/common"
|
||||||
|
"github.com/cloudbase/garm/database/watcher"
|
||||||
"github.com/cloudbase/garm/params"
|
"github.com/cloudbase/garm/params"
|
||||||
"github.com/cloudbase/garm/runner/common"
|
"github.com/cloudbase/garm/runner/common"
|
||||||
garmUtil "github.com/cloudbase/garm/util"
|
garmUtil "github.com/cloudbase/garm/util"
|
||||||
|
|
@ -61,16 +62,9 @@ const (
|
||||||
maxCreateAttempts = 5
|
maxCreateAttempts = 5
|
||||||
)
|
)
|
||||||
|
|
||||||
type urls struct {
|
func NewEntityPoolManager(ctx context.Context, entity params.GithubEntity, instanceTokenGetter auth.InstanceTokenGetter, providers map[string]common.Provider, store dbCommon.Store) (common.PoolManager, error) {
|
||||||
callbackURL string
|
|
||||||
metadataURL string
|
|
||||||
webhookURL string
|
|
||||||
controllerWebhookURL string
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewEntityPoolManager(ctx context.Context, entity params.GithubEntity, cfgInternal params.Internal, providers map[string]common.Provider, store dbCommon.Store) (common.PoolManager, error) {
|
|
||||||
ctx = garmUtil.WithContext(ctx, slog.Any("pool_mgr", entity.String()), slog.Any("pool_type", entity.EntityType))
|
ctx = garmUtil.WithContext(ctx, slog.Any("pool_mgr", entity.String()), slog.Any("pool_type", entity.EntityType))
|
||||||
ghc, err := garmUtil.GithubClient(ctx, entity, cfgInternal.GithubCredentialsDetails)
|
ghc, err := garmUtil.GithubClient(ctx, entity, entity.Credentials)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "getting github client")
|
return nil, errors.Wrap(err, "getting github client")
|
||||||
}
|
}
|
||||||
|
|
@ -79,38 +73,47 @@ func NewEntityPoolManager(ctx context.Context, entity params.GithubEntity, cfgIn
|
||||||
return nil, errors.New("webhook secret is empty")
|
return nil, errors.New("webhook secret is empty")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
controllerInfo, err := store.ControllerInfo()
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "getting controller info")
|
||||||
|
}
|
||||||
|
|
||||||
|
consumerID := fmt.Sprintf("pool-manager-%s", entity.String())
|
||||||
|
consumer, err := watcher.RegisterConsumer(
|
||||||
|
ctx, consumerID,
|
||||||
|
composeWatcherFilters(entity),
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "registering consumer")
|
||||||
|
}
|
||||||
|
|
||||||
wg := &sync.WaitGroup{}
|
wg := &sync.WaitGroup{}
|
||||||
keyMuxes := &keyMutex{}
|
keyMuxes := &keyMutex{}
|
||||||
|
|
||||||
repo := &basePoolManager{
|
repo := &basePoolManager{
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
cfgInternal: cfgInternal,
|
entity: entity,
|
||||||
entity: entity,
|
ghcli: ghc,
|
||||||
ghcli: ghc,
|
controllerInfo: controllerInfo,
|
||||||
|
instanceTokenGetter: instanceTokenGetter,
|
||||||
|
|
||||||
store: store,
|
store: store,
|
||||||
providers: providers,
|
providers: providers,
|
||||||
controllerID: cfgInternal.ControllerID,
|
quit: make(chan struct{}),
|
||||||
urls: urls{
|
wg: wg,
|
||||||
webhookURL: cfgInternal.BaseWebhookURL,
|
keyMux: keyMuxes,
|
||||||
callbackURL: cfgInternal.InstanceCallbackURL,
|
consumer: consumer,
|
||||||
metadataURL: cfgInternal.InstanceMetadataURL,
|
|
||||||
controllerWebhookURL: cfgInternal.ControllerWebhookURL,
|
|
||||||
},
|
|
||||||
quit: make(chan struct{}),
|
|
||||||
credsDetails: cfgInternal.GithubCredentialsDetails,
|
|
||||||
wg: wg,
|
|
||||||
keyMux: keyMuxes,
|
|
||||||
}
|
}
|
||||||
return repo, nil
|
return repo, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type basePoolManager struct {
|
type basePoolManager struct {
|
||||||
ctx context.Context
|
ctx context.Context
|
||||||
controllerID string
|
entity params.GithubEntity
|
||||||
entity params.GithubEntity
|
ghcli common.GithubClient
|
||||||
ghcli common.GithubClient
|
controllerInfo params.ControllerInfo
|
||||||
cfgInternal params.Internal
|
instanceTokenGetter auth.InstanceTokenGetter
|
||||||
|
consumer dbCommon.Consumer
|
||||||
|
|
||||||
store dbCommon.Store
|
store dbCommon.Store
|
||||||
|
|
||||||
|
|
@ -118,13 +121,9 @@ type basePoolManager struct {
|
||||||
tools []commonParams.RunnerApplicationDownload
|
tools []commonParams.RunnerApplicationDownload
|
||||||
quit chan struct{}
|
quit chan struct{}
|
||||||
|
|
||||||
credsDetails params.GithubCredentials
|
|
||||||
|
|
||||||
managerIsRunning bool
|
managerIsRunning bool
|
||||||
managerErrorReason string
|
managerErrorReason string
|
||||||
|
|
||||||
urls urls
|
|
||||||
|
|
||||||
mux sync.Mutex
|
mux sync.Mutex
|
||||||
wg *sync.WaitGroup
|
wg *sync.WaitGroup
|
||||||
keyMux *keyMutex
|
keyMux *keyMutex
|
||||||
|
|
@ -353,9 +352,9 @@ func (r *basePoolManager) updateTools() error {
|
||||||
tools, err := r.FetchTools()
|
tools, err := r.FetchTools()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
slog.With(slog.Any("error", err)).ErrorContext(
|
slog.With(slog.Any("error", err)).ErrorContext(
|
||||||
r.ctx, "failed to update tools for repo")
|
r.ctx, "failed to update tools for entity", "entity", r.entity.String())
|
||||||
r.setPoolRunningState(false, err.Error())
|
r.setPoolRunningState(false, err.Error())
|
||||||
return fmt.Errorf("failed to update tools for repo %s: %w", r.entity.String(), err)
|
return fmt.Errorf("failed to update tools for entity %s: %w", r.entity.String(), err)
|
||||||
}
|
}
|
||||||
r.mux.Lock()
|
r.mux.Lock()
|
||||||
r.tools = tools
|
r.tools = tools
|
||||||
|
|
@ -381,7 +380,7 @@ func (r *basePoolManager) cleanupOrphanedProviderRunners(runners []*github.Runne
|
||||||
|
|
||||||
runnerNames := map[string]bool{}
|
runnerNames := map[string]bool{}
|
||||||
for _, run := range runners {
|
for _, run := range runners {
|
||||||
if !isManagedRunner(labelsFromRunner(run), r.controllerID) {
|
if !isManagedRunner(labelsFromRunner(run), r.controllerInfo.ControllerID.String()) {
|
||||||
slog.DebugContext(
|
slog.DebugContext(
|
||||||
r.ctx, "runner is not managed by a pool we manage",
|
r.ctx, "runner is not managed by a pool we manage",
|
||||||
"runner_name", run.GetName())
|
"runner_name", run.GetName())
|
||||||
|
|
@ -457,7 +456,7 @@ func (r *basePoolManager) reapTimedOutRunners(runners []*github.Runner) error {
|
||||||
|
|
||||||
runnersByName := map[string]*github.Runner{}
|
runnersByName := map[string]*github.Runner{}
|
||||||
for _, run := range runners {
|
for _, run := range runners {
|
||||||
if !isManagedRunner(labelsFromRunner(run), r.controllerID) {
|
if !isManagedRunner(labelsFromRunner(run), r.controllerInfo.ControllerID.String()) {
|
||||||
slog.DebugContext(
|
slog.DebugContext(
|
||||||
r.ctx, "runner is not managed by a pool we manage",
|
r.ctx, "runner is not managed by a pool we manage",
|
||||||
"runner_name", run.GetName())
|
"runner_name", run.GetName())
|
||||||
|
|
@ -515,7 +514,7 @@ func (r *basePoolManager) cleanupOrphanedGithubRunners(runners []*github.Runner)
|
||||||
poolInstanceCache := map[string][]commonParams.ProviderInstance{}
|
poolInstanceCache := map[string][]commonParams.ProviderInstance{}
|
||||||
g, ctx := errgroup.WithContext(r.ctx)
|
g, ctx := errgroup.WithContext(r.ctx)
|
||||||
for _, runner := range runners {
|
for _, runner := range runners {
|
||||||
if !isManagedRunner(labelsFromRunner(runner), r.controllerID) {
|
if !isManagedRunner(labelsFromRunner(runner), r.controllerInfo.ControllerID.String()) {
|
||||||
slog.DebugContext(
|
slog.DebugContext(
|
||||||
r.ctx, "runner is not managed by a pool we manage",
|
r.ctx, "runner is not managed by a pool we manage",
|
||||||
"runner_name", runner.GetName())
|
"runner_name", runner.GetName())
|
||||||
|
|
@ -741,8 +740,8 @@ func (r *basePoolManager) AddRunner(ctx context.Context, poolID string, aditiona
|
||||||
RunnerStatus: params.RunnerPending,
|
RunnerStatus: params.RunnerPending,
|
||||||
OSArch: pool.OSArch,
|
OSArch: pool.OSArch,
|
||||||
OSType: pool.OSType,
|
OSType: pool.OSType,
|
||||||
CallbackURL: r.urls.callbackURL,
|
CallbackURL: r.controllerInfo.CallbackURL,
|
||||||
MetadataURL: r.urls.metadataURL,
|
MetadataURL: r.controllerInfo.MetadataURL,
|
||||||
CreateAttempt: 1,
|
CreateAttempt: 1,
|
||||||
GitHubRunnerGroup: pool.GitHubRunnerGroup,
|
GitHubRunnerGroup: pool.GitHubRunnerGroup,
|
||||||
AditionalLabels: aditionalLabels,
|
AditionalLabels: aditionalLabels,
|
||||||
|
|
@ -832,7 +831,7 @@ func (r *basePoolManager) addInstanceToProvider(instance params.Instance) error
|
||||||
jwtValidity := pool.RunnerTimeout()
|
jwtValidity := pool.RunnerTimeout()
|
||||||
|
|
||||||
entity := r.entity.String()
|
entity := r.entity.String()
|
||||||
jwtToken, err := auth.NewInstanceJWTToken(instance, r.cfgInternal.JWTSecret, entity, pool.PoolType(), jwtValidity)
|
jwtToken, err := r.instanceTokenGetter.NewInstanceJWTToken(instance, entity, pool.PoolType(), jwtValidity)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "fetching instance jwt token")
|
return errors.Wrap(err, "fetching instance jwt token")
|
||||||
}
|
}
|
||||||
|
|
@ -852,7 +851,7 @@ func (r *basePoolManager) addInstanceToProvider(instance params.Instance) error
|
||||||
Image: pool.Image,
|
Image: pool.Image,
|
||||||
ExtraSpecs: pool.ExtraSpecs,
|
ExtraSpecs: pool.ExtraSpecs,
|
||||||
PoolID: instance.PoolID,
|
PoolID: instance.PoolID,
|
||||||
CACertBundle: r.credsDetails.CABundle,
|
CACertBundle: r.entity.Credentials.CABundle,
|
||||||
GitHubRunnerGroup: instance.GitHubRunnerGroup,
|
GitHubRunnerGroup: instance.GitHubRunnerGroup,
|
||||||
JitConfigEnabled: hasJITConfig,
|
JitConfigEnabled: hasJITConfig,
|
||||||
}
|
}
|
||||||
|
|
@ -954,7 +953,7 @@ func (r *basePoolManager) poolLabel(poolID string) string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *basePoolManager) controllerLabel() string {
|
func (r *basePoolManager) controllerLabel() string {
|
||||||
return fmt.Sprintf("%s%s", controllerLabelPrefix, r.controllerID)
|
return fmt.Sprintf("%s%s", controllerLabelPrefix, r.controllerInfo.ControllerID.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *basePoolManager) updateArgsFromProviderInstance(providerInstance commonParams.ProviderInstance) params.UpdateInstanceParams {
|
func (r *basePoolManager) updateArgsFromProviderInstance(providerInstance commonParams.ProviderInstance) params.UpdateInstanceParams {
|
||||||
|
|
@ -1525,6 +1524,7 @@ func (r *basePoolManager) Start() error {
|
||||||
initialToolUpdate <- struct{}{}
|
initialToolUpdate <- struct{}{}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
go r.runWatcher()
|
||||||
go func() {
|
go func() {
|
||||||
select {
|
select {
|
||||||
case <-r.quit:
|
case <-r.quit:
|
||||||
|
|
@ -1552,37 +1552,6 @@ func (r *basePoolManager) Stop() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *basePoolManager) RefreshState(param params.UpdatePoolStateParams) error {
|
|
||||||
r.mux.Lock()
|
|
||||||
|
|
||||||
if param.WebhookSecret != "" {
|
|
||||||
r.entity.WebhookSecret = param.WebhookSecret
|
|
||||||
}
|
|
||||||
if param.InternalConfig != nil {
|
|
||||||
r.cfgInternal = *param.InternalConfig
|
|
||||||
r.urls = urls{
|
|
||||||
webhookURL: r.cfgInternal.BaseWebhookURL,
|
|
||||||
callbackURL: r.cfgInternal.InstanceCallbackURL,
|
|
||||||
metadataURL: r.cfgInternal.InstanceMetadataURL,
|
|
||||||
controllerWebhookURL: r.cfgInternal.ControllerWebhookURL,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ghc, err := garmUtil.GithubClient(r.ctx, r.entity, r.cfgInternal.GithubCredentialsDetails)
|
|
||||||
if err != nil {
|
|
||||||
return errors.Wrap(err, "getting github client")
|
|
||||||
}
|
|
||||||
r.ghcli = ghc
|
|
||||||
r.mux.Unlock()
|
|
||||||
|
|
||||||
// Update the tools as soon as state is updated. This should revive a stopped pool manager
|
|
||||||
// or stop one if the supplied credentials are not okay.
|
|
||||||
if err := r.updateTools(); err != nil {
|
|
||||||
return fmt.Errorf("failed to update tools: %w", err)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *basePoolManager) WebhookSecret() string {
|
func (r *basePoolManager) WebhookSecret() string {
|
||||||
return r.entity.WebhookSecret
|
return r.entity.WebhookSecret
|
||||||
}
|
}
|
||||||
|
|
@ -1688,7 +1657,7 @@ func (r *basePoolManager) consumeQueuedJobs() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
poolsCache := poolsForTags{
|
poolsCache := poolsForTags{
|
||||||
poolCacheType: r.PoolBalancerType(),
|
poolCacheType: r.entity.GetPoolBalancerType(),
|
||||||
}
|
}
|
||||||
|
|
||||||
slog.DebugContext(
|
slog.DebugContext(
|
||||||
|
|
@ -1812,7 +1781,7 @@ func (r *basePoolManager) consumeQueuedJobs() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *basePoolManager) UninstallWebhook(ctx context.Context) error {
|
func (r *basePoolManager) UninstallWebhook(ctx context.Context) error {
|
||||||
if r.urls.controllerWebhookURL == "" {
|
if r.controllerInfo.ControllerWebhookURL == "" {
|
||||||
return errors.Wrap(runnerErrors.ErrBadRequest, "controller webhook url is empty")
|
return errors.Wrap(runnerErrors.ErrBadRequest, "controller webhook url is empty")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1823,8 +1792,8 @@ func (r *basePoolManager) UninstallWebhook(ctx context.Context) error {
|
||||||
|
|
||||||
var controllerHookID int64
|
var controllerHookID int64
|
||||||
var baseHook string
|
var baseHook string
|
||||||
trimmedBase := strings.TrimRight(r.urls.webhookURL, "/")
|
trimmedBase := strings.TrimRight(r.controllerInfo.WebhookURL, "/")
|
||||||
trimmedController := strings.TrimRight(r.urls.controllerWebhookURL, "/")
|
trimmedController := strings.TrimRight(r.controllerInfo.ControllerWebhookURL, "/")
|
||||||
|
|
||||||
for _, hook := range allHooks {
|
for _, hook := range allHooks {
|
||||||
hookInfo := hookToParamsHookInfo(hook)
|
hookInfo := hookToParamsHookInfo(hook)
|
||||||
|
|
@ -1859,7 +1828,7 @@ func (r *basePoolManager) InstallHook(ctx context.Context, req *github.Hook) (pa
|
||||||
return params.HookInfo{}, errors.Wrap(err, "listing hooks")
|
return params.HookInfo{}, errors.Wrap(err, "listing hooks")
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := validateHookRequest(r.cfgInternal.ControllerID, r.cfgInternal.BaseWebhookURL, 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{}, errors.Wrap(err, "validating hook request")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1879,7 +1848,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.urls.controllerWebhookURL == "" {
|
if r.controllerInfo.ControllerWebhookURL == "" {
|
||||||
return params.HookInfo{}, errors.Wrap(runnerErrors.ErrBadRequest, "controller webhook url is empty")
|
return params.HookInfo{}, errors.Wrap(runnerErrors.ErrBadRequest, "controller webhook url is empty")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1890,7 +1859,7 @@ func (r *basePoolManager) InstallWebhook(ctx context.Context, param params.Insta
|
||||||
req := &github.Hook{
|
req := &github.Hook{
|
||||||
Active: github.Bool(true),
|
Active: github.Bool(true),
|
||||||
Config: map[string]interface{}{
|
Config: map[string]interface{}{
|
||||||
"url": r.urls.controllerWebhookURL,
|
"url": r.controllerInfo.ControllerWebhookURL,
|
||||||
"content_type": "json",
|
"content_type": "json",
|
||||||
"insecure_ssl": insecureSSL,
|
"insecure_ssl": insecureSSL,
|
||||||
"secret": r.WebhookSecret(),
|
"secret": r.WebhookSecret(),
|
||||||
|
|
@ -1978,21 +1947,14 @@ func (r *basePoolManager) GetGithubRunners() ([]*github.Runner, error) {
|
||||||
return allRunners, nil
|
return allRunners, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *basePoolManager) PoolBalancerType() params.PoolBalancerType {
|
|
||||||
if r.cfgInternal.PoolBalancerType == "" {
|
|
||||||
return params.PoolBalancerTypeRoundRobin
|
|
||||||
}
|
|
||||||
return r.cfgInternal.PoolBalancerType
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *basePoolManager) GithubURL() string {
|
func (r *basePoolManager) GithubURL() string {
|
||||||
switch r.entity.EntityType {
|
switch r.entity.EntityType {
|
||||||
case params.GithubEntityTypeRepository:
|
case params.GithubEntityTypeRepository:
|
||||||
return fmt.Sprintf("%s/%s/%s", r.cfgInternal.GithubCredentialsDetails.BaseURL, r.entity.Owner, r.entity.Name)
|
return fmt.Sprintf("%s/%s/%s", r.entity.Credentials.BaseURL, r.entity.Owner, r.entity.Name)
|
||||||
case params.GithubEntityTypeOrganization:
|
case params.GithubEntityTypeOrganization:
|
||||||
return fmt.Sprintf("%s/%s", r.cfgInternal.GithubCredentialsDetails.BaseURL, r.entity.Owner)
|
return fmt.Sprintf("%s/%s", r.entity.Credentials.BaseURL, r.entity.Owner)
|
||||||
case params.GithubEntityTypeEnterprise:
|
case params.GithubEntityTypeEnterprise:
|
||||||
return fmt.Sprintf("%s/enterprises/%s", r.cfgInternal.GithubCredentialsDetails.BaseURL, r.entity.Owner)
|
return fmt.Sprintf("%s/enterprises/%s", r.entity.Credentials.BaseURL, r.entity.Owner)
|
||||||
}
|
}
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
@ -2002,8 +1964,8 @@ func (r *basePoolManager) GetWebhookInfo(ctx context.Context) (params.HookInfo,
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return params.HookInfo{}, errors.Wrap(err, "listing hooks")
|
return params.HookInfo{}, errors.Wrap(err, "listing hooks")
|
||||||
}
|
}
|
||||||
trimmedBase := strings.TrimRight(r.urls.webhookURL, "/")
|
trimmedBase := strings.TrimRight(r.controllerInfo.WebhookURL, "/")
|
||||||
trimmedController := strings.TrimRight(r.urls.controllerWebhookURL, "/")
|
trimmedController := strings.TrimRight(r.controllerInfo.ControllerWebhookURL, "/")
|
||||||
|
|
||||||
var controllerHookInfo *params.HookInfo
|
var controllerHookInfo *params.HookInfo
|
||||||
var baseHookInfo *params.HookInfo
|
var baseHookInfo *params.HookInfo
|
||||||
|
|
@ -2034,5 +1996,5 @@ func (r *basePoolManager) GetWebhookInfo(ctx context.Context) (params.HookInfo,
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *basePoolManager) RootCABundle() (params.CertificateBundle, error) {
|
func (r *basePoolManager) RootCABundle() (params.CertificateBundle, error) {
|
||||||
return r.credsDetails.RootCertificateBundle()
|
return r.entity.Credentials.RootCertificateBundle()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
57
runner/pool/stub_client.go
Normal file
57
runner/pool/stub_client.go
Normal file
|
|
@ -0,0 +1,57 @@
|
||||||
|
package pool
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/google/go-github/v57/github"
|
||||||
|
|
||||||
|
"github.com/cloudbase/garm/params"
|
||||||
|
)
|
||||||
|
|
||||||
|
type stubGithubClient struct {
|
||||||
|
err error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *stubGithubClient) ListEntityHooks(_ context.Context, _ *github.ListOptions) ([]*github.Hook, *github.Response, error) {
|
||||||
|
return nil, nil, s.err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *stubGithubClient) GetEntityHook(_ context.Context, _ int64) (*github.Hook, error) {
|
||||||
|
return nil, s.err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *stubGithubClient) CreateEntityHook(_ context.Context, _ *github.Hook) (*github.Hook, error) {
|
||||||
|
return nil, s.err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *stubGithubClient) DeleteEntityHook(_ context.Context, _ int64) (*github.Response, error) {
|
||||||
|
return nil, s.err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *stubGithubClient) PingEntityHook(_ context.Context, _ int64) (*github.Response, error) {
|
||||||
|
return nil, s.err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *stubGithubClient) ListEntityRunners(_ context.Context, _ *github.ListOptions) (*github.Runners, *github.Response, error) {
|
||||||
|
return nil, nil, s.err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *stubGithubClient) ListEntityRunnerApplicationDownloads(_ context.Context) ([]*github.RunnerApplicationDownload, *github.Response, error) {
|
||||||
|
return nil, nil, s.err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *stubGithubClient) RemoveEntityRunner(_ context.Context, _ int64) (*github.Response, error) {
|
||||||
|
return nil, s.err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *stubGithubClient) CreateEntityRegistrationToken(_ context.Context) (*github.RegistrationToken, *github.Response, error) {
|
||||||
|
return nil, nil, s.err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *stubGithubClient) GetEntityJITConfig(_ context.Context, _ string, _ params.Pool, _ []string) (map[string]string, *github.Runner, error) {
|
||||||
|
return nil, nil, s.err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *stubGithubClient) GetWorkflowJobByID(_ context.Context, _, _ string, _ int64) (*github.WorkflowJob, *github.Response, error) {
|
||||||
|
return nil, nil, s.err
|
||||||
|
}
|
||||||
|
|
@ -10,6 +10,8 @@ import (
|
||||||
|
|
||||||
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"
|
||||||
|
dbCommon "github.com/cloudbase/garm/database/common"
|
||||||
|
"github.com/cloudbase/garm/database/watcher"
|
||||||
"github.com/cloudbase/garm/params"
|
"github.com/cloudbase/garm/params"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -116,3 +118,19 @@ func isManagedRunner(labels []string, controllerID string) bool {
|
||||||
runnerControllerID := controllerIDFromLabels(labels)
|
runnerControllerID := controllerIDFromLabels(labels)
|
||||||
return runnerControllerID == controllerID
|
return runnerControllerID == controllerID
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func composeWatcherFilters(entity params.GithubEntity) dbCommon.PayloadFilterFunc {
|
||||||
|
// We want to watch for changes in either the controller or the
|
||||||
|
// entity itself.
|
||||||
|
return watcher.WithAny(
|
||||||
|
watcher.WithAll(
|
||||||
|
// Updates to the controller
|
||||||
|
watcher.WithEntityTypeFilter(dbCommon.ControllerEntityType),
|
||||||
|
watcher.WithOperationTypeFilter(dbCommon.UpdateOperation),
|
||||||
|
),
|
||||||
|
// Any operation on the entity we're managing the pool for.
|
||||||
|
watcher.WithEntityFilter(entity),
|
||||||
|
// Watch for changes to the github credentials
|
||||||
|
watcher.WithGithubCredentialsFilter(entity.Credentials),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
|
||||||
154
runner/pool/watcher.go
Normal file
154
runner/pool/watcher.go
Normal file
|
|
@ -0,0 +1,154 @@
|
||||||
|
package pool
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log/slog"
|
||||||
|
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
|
||||||
|
runnerErrors "github.com/cloudbase/garm-provider-common/errors"
|
||||||
|
"github.com/cloudbase/garm/database/common"
|
||||||
|
"github.com/cloudbase/garm/params"
|
||||||
|
runnerCommon "github.com/cloudbase/garm/runner/common"
|
||||||
|
garmUtil "github.com/cloudbase/garm/util"
|
||||||
|
)
|
||||||
|
|
||||||
|
// entityGetter is implemented by all github entities (repositories, organizations and enterprises)
|
||||||
|
type entityGetter interface {
|
||||||
|
GetEntity() (params.GithubEntity, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *basePoolManager) handleControllerUpdateEvent(controllerInfo params.ControllerInfo) {
|
||||||
|
r.mux.Lock()
|
||||||
|
defer r.mux.Unlock()
|
||||||
|
|
||||||
|
slog.DebugContext(r.ctx, "updating controller info", "controller_info", controllerInfo)
|
||||||
|
r.controllerInfo = controllerInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *basePoolManager) getClientOrStub() runnerCommon.GithubClient {
|
||||||
|
var err error
|
||||||
|
var ghc runnerCommon.GithubClient
|
||||||
|
ghc, err = garmUtil.GithubClient(r.ctx, r.entity, r.entity.Credentials)
|
||||||
|
if err != nil {
|
||||||
|
slog.WarnContext(r.ctx, "failed to create github client", "error", err)
|
||||||
|
ghc = &stubGithubClient{
|
||||||
|
err: errors.Wrapf(runnerErrors.ErrUnauthorized, "failed to create github client; please update credentials: %v", err),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ghc
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *basePoolManager) handleEntityUpdate(entity params.GithubEntity) {
|
||||||
|
slog.DebugContext(r.ctx, "received entity update", "entity", entity.ID)
|
||||||
|
credentialsUpdate := r.entity.Credentials.ID != entity.Credentials.ID
|
||||||
|
defer func() {
|
||||||
|
slog.DebugContext(r.ctx, "deferred tools update", "credentials_update", credentialsUpdate)
|
||||||
|
if !credentialsUpdate {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
slog.DebugContext(r.ctx, "updating tools", "entity", entity.ID)
|
||||||
|
if err := r.updateTools(); err != nil {
|
||||||
|
slog.ErrorContext(r.ctx, "failed to update tools", "error", err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
slog.DebugContext(r.ctx, "updating entity", "entity", entity.ID)
|
||||||
|
r.mux.Lock()
|
||||||
|
slog.DebugContext(r.ctx, "lock acquired", "entity", entity.ID)
|
||||||
|
|
||||||
|
r.entity = entity
|
||||||
|
if credentialsUpdate {
|
||||||
|
if r.consumer != nil {
|
||||||
|
filters := composeWatcherFilters(r.entity)
|
||||||
|
r.consumer.SetFilters(filters)
|
||||||
|
}
|
||||||
|
slog.DebugContext(r.ctx, "credentials update", "entity", entity.ID)
|
||||||
|
r.ghcli = r.getClientOrStub()
|
||||||
|
}
|
||||||
|
r.mux.Unlock()
|
||||||
|
slog.DebugContext(r.ctx, "lock released", "entity", entity.ID)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *basePoolManager) handleCredentialsUpdate(credentials params.GithubCredentials) {
|
||||||
|
// when we switch credentials on an entity (like from one app to another or from an app
|
||||||
|
// to a PAT), we may still get events for the previous credentials as the channel is buffered.
|
||||||
|
// The watcher will watch for changes to the entity itself, which includes events that
|
||||||
|
// change the credentials name on the entity, but we also watch for changes to the credentials
|
||||||
|
// themselves, like an updated PAT token set on existing credentials entity.
|
||||||
|
// The handleCredentialsUpdate function handles situations where we have changes on the
|
||||||
|
// credentials entity itself, not on the entity that the credentials are set on.
|
||||||
|
// For example, we may have a credentials entity called org_pat set on a repo called
|
||||||
|
// test-repo. This function would handle situations where "org_pat" is updated.
|
||||||
|
// If "test-repo" is updated with new credentials, that event is handled above in
|
||||||
|
// handleEntityUpdate.
|
||||||
|
shouldUpdateTools := r.entity.Credentials.ID == credentials.ID
|
||||||
|
defer func() {
|
||||||
|
if !shouldUpdateTools {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
slog.DebugContext(r.ctx, "deferred tools update", "credentials_id", credentials.ID)
|
||||||
|
if err := r.updateTools(); err != nil {
|
||||||
|
slog.ErrorContext(r.ctx, "failed to update tools", "error", err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
r.mux.Lock()
|
||||||
|
if !shouldUpdateTools {
|
||||||
|
slog.InfoContext(r.ctx, "credential ID mismatch; stale event?", "credentials_id", credentials.ID)
|
||||||
|
r.mux.Unlock()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
slog.DebugContext(r.ctx, "updating credentials", "credentials_id", credentials.ID)
|
||||||
|
r.entity.Credentials = credentials
|
||||||
|
r.ghcli = r.getClientOrStub()
|
||||||
|
r.mux.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *basePoolManager) handleWatcherEvent(event common.ChangePayload) {
|
||||||
|
dbEntityType := common.DatabaseEntityType(r.entity.EntityType)
|
||||||
|
switch event.EntityType {
|
||||||
|
case common.GithubCredentialsEntityType:
|
||||||
|
credentials, ok := event.Payload.(params.GithubCredentials)
|
||||||
|
if !ok {
|
||||||
|
slog.ErrorContext(r.ctx, "failed to cast payload to github credentials")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
r.handleCredentialsUpdate(credentials)
|
||||||
|
case common.ControllerEntityType:
|
||||||
|
controllerInfo, ok := event.Payload.(params.ControllerInfo)
|
||||||
|
if !ok {
|
||||||
|
slog.ErrorContext(r.ctx, "failed to cast payload to controller info")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
r.handleControllerUpdateEvent(controllerInfo)
|
||||||
|
case dbEntityType:
|
||||||
|
entity, ok := event.Payload.(entityGetter)
|
||||||
|
if !ok {
|
||||||
|
slog.ErrorContext(r.ctx, "failed to cast payload to entity")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
entityInfo, err := entity.GetEntity()
|
||||||
|
if err != nil {
|
||||||
|
slog.ErrorContext(r.ctx, "failed to get entity", "error", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
r.handleEntityUpdate(entityInfo)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *basePoolManager) runWatcher() {
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-r.quit:
|
||||||
|
return
|
||||||
|
case <-r.ctx.Done():
|
||||||
|
return
|
||||||
|
case event, ok := <-r.consumer.Watch():
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
go r.handleWatcherEvent(event)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -197,16 +197,15 @@ func (r *Runner) UpdateRepository(ctx context.Context, repoID string, param para
|
||||||
return params.Repository{}, runnerErrors.NewBadRequestError("invalid pool balancer type: %s", param.PoolBalancerType)
|
return params.Repository{}, runnerErrors.NewBadRequestError("invalid pool balancer type: %s", param.PoolBalancerType)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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{}, errors.Wrap(err, "updating repo")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use the admin context in the pool manager. Any access control is already done above when
|
poolMgr, err := r.poolManagerCtrl.GetRepoPoolManager(repo)
|
||||||
// updating the store.
|
|
||||||
poolMgr, err := r.poolManagerCtrl.UpdateRepoPoolManager(r.ctx, repo)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return params.Repository{}, fmt.Errorf("failed to update pool manager: %w", err)
|
return params.Repository{}, fmt.Errorf("failed to get pool manager: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
repo.PoolManagerStatus = poolMgr.Status()
|
repo.PoolManagerStatus = poolMgr.Status()
|
||||||
|
|
|
||||||
|
|
@ -35,21 +35,20 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type RepoTestFixtures struct {
|
type RepoTestFixtures struct {
|
||||||
AdminContext context.Context
|
AdminContext context.Context
|
||||||
Store dbCommon.Store
|
Store dbCommon.Store
|
||||||
StoreRepos map[string]params.Repository
|
StoreRepos map[string]params.Repository
|
||||||
Providers map[string]common.Provider
|
Providers map[string]common.Provider
|
||||||
Credentials map[string]params.GithubCredentials
|
Credentials map[string]params.GithubCredentials
|
||||||
CreateRepoParams params.CreateRepoParams
|
CreateRepoParams params.CreateRepoParams
|
||||||
CreatePoolParams params.CreatePoolParams
|
CreatePoolParams params.CreatePoolParams
|
||||||
CreateInstanceParams params.CreateInstanceParams
|
CreateInstanceParams params.CreateInstanceParams
|
||||||
UpdateRepoParams params.UpdateEntityParams
|
UpdateRepoParams params.UpdateEntityParams
|
||||||
UpdatePoolParams params.UpdatePoolParams
|
UpdatePoolParams params.UpdatePoolParams
|
||||||
UpdatePoolStateParams params.UpdatePoolStateParams
|
ErrMock error
|
||||||
ErrMock error
|
ProviderMock *runnerCommonMocks.Provider
|
||||||
ProviderMock *runnerCommonMocks.Provider
|
PoolMgrMock *runnerCommonMocks.PoolManager
|
||||||
PoolMgrMock *runnerCommonMocks.PoolManager
|
PoolMgrCtrlMock *runnerMocks.PoolManagerController
|
||||||
PoolMgrCtrlMock *runnerMocks.PoolManagerController
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
|
@ -143,9 +142,6 @@ func (s *RepoTestSuite) SetupTest() {
|
||||||
Image: "test-images-updated",
|
Image: "test-images-updated",
|
||||||
Flavor: "test-flavor-updated",
|
Flavor: "test-flavor-updated",
|
||||||
},
|
},
|
||||||
UpdatePoolStateParams: params.UpdatePoolStateParams{
|
|
||||||
WebhookSecret: "test-update-repo-webhook-secret",
|
|
||||||
},
|
|
||||||
ErrMock: fmt.Errorf("mock error"),
|
ErrMock: fmt.Errorf("mock error"),
|
||||||
ProviderMock: providerMock,
|
ProviderMock: providerMock,
|
||||||
PoolMgrMock: runnerCommonMocks.NewPoolManager(s.T()),
|
PoolMgrMock: runnerCommonMocks.NewPoolManager(s.T()),
|
||||||
|
|
@ -327,7 +323,7 @@ func (s *RepoTestSuite) TestDeleteRepositoryPoolMgrFailed() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *RepoTestSuite) TestUpdateRepository() {
|
func (s *RepoTestSuite) TestUpdateRepository() {
|
||||||
s.Fixtures.PoolMgrCtrlMock.On("UpdateRepoPoolManager", s.Fixtures.AdminContext, mock.AnythingOfType("params.Repository")).Return(s.Fixtures.PoolMgrMock, nil)
|
s.Fixtures.PoolMgrCtrlMock.On("GetRepoPoolManager", mock.AnythingOfType("params.Repository")).Return(s.Fixtures.PoolMgrMock, nil)
|
||||||
s.Fixtures.PoolMgrMock.On("Status").Return(params.PoolManagerStatus{IsRunning: true}, nil)
|
s.Fixtures.PoolMgrMock.On("Status").Return(params.PoolManagerStatus{IsRunning: true}, nil)
|
||||||
|
|
||||||
repo, err := s.Runner.UpdateRepository(s.Fixtures.AdminContext, s.Fixtures.StoreRepos["test-repo-1"].ID, s.Fixtures.UpdateRepoParams)
|
repo, err := s.Runner.UpdateRepository(s.Fixtures.AdminContext, s.Fixtures.StoreRepos["test-repo-1"].ID, s.Fixtures.UpdateRepoParams)
|
||||||
|
|
@ -341,7 +337,7 @@ func (s *RepoTestSuite) TestUpdateRepository() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *RepoTestSuite) TestUpdateRepositoryBalancingType() {
|
func (s *RepoTestSuite) TestUpdateRepositoryBalancingType() {
|
||||||
s.Fixtures.PoolMgrCtrlMock.On("UpdateRepoPoolManager", s.Fixtures.AdminContext, mock.AnythingOfType("params.Repository")).Return(s.Fixtures.PoolMgrMock, nil)
|
s.Fixtures.PoolMgrCtrlMock.On("GetRepoPoolManager", mock.AnythingOfType("params.Repository")).Return(s.Fixtures.PoolMgrMock, nil)
|
||||||
s.Fixtures.PoolMgrMock.On("Status").Return(params.PoolManagerStatus{IsRunning: true}, nil)
|
s.Fixtures.PoolMgrMock.On("Status").Return(params.PoolManagerStatus{IsRunning: true}, nil)
|
||||||
|
|
||||||
updateRepoParams := s.Fixtures.UpdateRepoParams
|
updateRepoParams := s.Fixtures.UpdateRepoParams
|
||||||
|
|
@ -372,21 +368,21 @@ func (s *RepoTestSuite) TestUpdateRepositoryInvalidCreds() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *RepoTestSuite) TestUpdateRepositoryPoolMgrFailed() {
|
func (s *RepoTestSuite) TestUpdateRepositoryPoolMgrFailed() {
|
||||||
s.Fixtures.PoolMgrCtrlMock.On("UpdateRepoPoolManager", s.Fixtures.AdminContext, mock.AnythingOfType("params.Repository")).Return(s.Fixtures.PoolMgrMock, s.Fixtures.ErrMock)
|
s.Fixtures.PoolMgrCtrlMock.On("GetRepoPoolManager", mock.AnythingOfType("params.Repository")).Return(s.Fixtures.PoolMgrMock, s.Fixtures.ErrMock)
|
||||||
|
|
||||||
_, 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("failed to update pool manager: %s", s.Fixtures.ErrMock.Error()), err.Error())
|
s.Require().Equal(fmt.Sprintf("failed to get pool manager: %s", s.Fixtures.ErrMock.Error()), err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *RepoTestSuite) TestUpdateRepositoryCreateRepoPoolMgrFailed() {
|
func (s *RepoTestSuite) TestUpdateRepositoryCreateRepoPoolMgrFailed() {
|
||||||
s.Fixtures.PoolMgrCtrlMock.On("UpdateRepoPoolManager", s.Fixtures.AdminContext, mock.AnythingOfType("params.Repository")).Return(s.Fixtures.PoolMgrMock, s.Fixtures.ErrMock)
|
s.Fixtures.PoolMgrCtrlMock.On("GetRepoPoolManager", mock.AnythingOfType("params.Repository")).Return(s.Fixtures.PoolMgrMock, s.Fixtures.ErrMock)
|
||||||
|
|
||||||
_, 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("failed to update pool manager: %s", s.Fixtures.ErrMock.Error()), err.Error())
|
s.Require().Equal(fmt.Sprintf("failed to get pool manager: %s", s.Fixtures.ErrMock.Error()), err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *RepoTestSuite) TestCreateRepoPool() {
|
func (s *RepoTestSuite) TestCreateRepoPool() {
|
||||||
|
|
|
||||||
158
runner/runner.go
158
runner/runner.go
|
|
@ -100,23 +100,16 @@ func (p *poolManagerCtrl) CreateRepoPoolManager(ctx context.Context, repo params
|
||||||
p.mux.Lock()
|
p.mux.Lock()
|
||||||
defer p.mux.Unlock()
|
defer p.mux.Unlock()
|
||||||
|
|
||||||
creds, err := p.store.GetGithubCredentials(ctx, repo.CredentialsID, true)
|
entity, err := repo.GetEntity()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "fetching credentials")
|
return nil, errors.Wrap(err, "getting entity")
|
||||||
}
|
}
|
||||||
|
|
||||||
cfgInternal, err := p.getInternalConfig(ctx, creds, repo.GetBalancerType())
|
instanceTokenGetter, err := auth.NewInstanceTokenGetter(p.config.JWTAuth.Secret)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "fetching internal config")
|
return nil, errors.Wrap(err, "creating instance token getter")
|
||||||
}
|
}
|
||||||
entity := params.GithubEntity{
|
poolManager, err := pool.NewEntityPoolManager(ctx, entity, instanceTokenGetter, providers, store)
|
||||||
Owner: repo.Owner,
|
|
||||||
Name: repo.Name,
|
|
||||||
ID: repo.ID,
|
|
||||||
WebhookSecret: repo.WebhookSecret,
|
|
||||||
EntityType: params.GithubEntityTypeRepository,
|
|
||||||
}
|
|
||||||
poolManager, err := pool.NewEntityPoolManager(ctx, entity, cfgInternal, providers, store)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "creating repo pool manager")
|
return nil, errors.Wrap(err, "creating repo pool manager")
|
||||||
}
|
}
|
||||||
|
|
@ -124,36 +117,6 @@ func (p *poolManagerCtrl) CreateRepoPoolManager(ctx context.Context, repo params
|
||||||
return poolManager, nil
|
return poolManager, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *poolManagerCtrl) UpdateRepoPoolManager(ctx context.Context, repo params.Repository) (common.PoolManager, error) {
|
|
||||||
p.mux.Lock()
|
|
||||||
defer p.mux.Unlock()
|
|
||||||
|
|
||||||
poolMgr, ok := p.repositories[repo.ID]
|
|
||||||
if !ok {
|
|
||||||
return nil, errors.Wrapf(runnerErrors.ErrNotFound, "repository %s/%s pool manager not loaded", repo.Owner, repo.Name)
|
|
||||||
}
|
|
||||||
|
|
||||||
creds, err := p.store.GetGithubCredentials(ctx, repo.CredentialsID, true)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Wrap(err, "fetching credentials")
|
|
||||||
}
|
|
||||||
|
|
||||||
internalCfg, err := p.getInternalConfig(ctx, creds, repo.GetBalancerType())
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Wrap(err, "fetching internal config")
|
|
||||||
}
|
|
||||||
|
|
||||||
newState := params.UpdatePoolStateParams{
|
|
||||||
WebhookSecret: repo.WebhookSecret,
|
|
||||||
InternalConfig: &internalCfg,
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := poolMgr.RefreshState(newState); err != nil {
|
|
||||||
return nil, errors.Wrap(err, "updating repo pool manager")
|
|
||||||
}
|
|
||||||
return poolMgr, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *poolManagerCtrl) GetRepoPoolManager(repo params.Repository) (common.PoolManager, error) {
|
func (p *poolManagerCtrl) GetRepoPoolManager(repo params.Repository) (common.PoolManager, error) {
|
||||||
if repoPoolMgr, ok := p.repositories[repo.ID]; ok {
|
if repoPoolMgr, ok := p.repositories[repo.ID]; ok {
|
||||||
return repoPoolMgr, nil
|
return repoPoolMgr, nil
|
||||||
|
|
@ -183,21 +146,16 @@ func (p *poolManagerCtrl) CreateOrgPoolManager(ctx context.Context, org params.O
|
||||||
p.mux.Lock()
|
p.mux.Lock()
|
||||||
defer p.mux.Unlock()
|
defer p.mux.Unlock()
|
||||||
|
|
||||||
creds, err := p.store.GetGithubCredentials(ctx, org.CredentialsID, true)
|
entity, err := org.GetEntity()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "fetching credentials")
|
return nil, errors.Wrap(err, "getting entity")
|
||||||
}
|
}
|
||||||
cfgInternal, err := p.getInternalConfig(ctx, creds, org.GetBalancerType())
|
|
||||||
|
instanceTokenGetter, err := auth.NewInstanceTokenGetter(p.config.JWTAuth.Secret)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "fetching internal config")
|
return nil, errors.Wrap(err, "creating instance token getter")
|
||||||
}
|
}
|
||||||
entity := params.GithubEntity{
|
poolManager, err := pool.NewEntityPoolManager(ctx, entity, instanceTokenGetter, providers, store)
|
||||||
Owner: org.Name,
|
|
||||||
ID: org.ID,
|
|
||||||
WebhookSecret: org.WebhookSecret,
|
|
||||||
EntityType: params.GithubEntityTypeOrganization,
|
|
||||||
}
|
|
||||||
poolManager, err := pool.NewEntityPoolManager(ctx, entity, cfgInternal, providers, store)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "creating org pool manager")
|
return nil, errors.Wrap(err, "creating org pool manager")
|
||||||
}
|
}
|
||||||
|
|
@ -205,35 +163,6 @@ func (p *poolManagerCtrl) CreateOrgPoolManager(ctx context.Context, org params.O
|
||||||
return poolManager, nil
|
return poolManager, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *poolManagerCtrl) UpdateOrgPoolManager(ctx context.Context, org params.Organization) (common.PoolManager, error) {
|
|
||||||
p.mux.Lock()
|
|
||||||
defer p.mux.Unlock()
|
|
||||||
|
|
||||||
poolMgr, ok := p.organizations[org.ID]
|
|
||||||
if !ok {
|
|
||||||
return nil, errors.Wrapf(runnerErrors.ErrNotFound, "org %s pool manager not loaded", org.Name)
|
|
||||||
}
|
|
||||||
|
|
||||||
creds, err := p.store.GetGithubCredentials(ctx, org.CredentialsID, true)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Wrap(err, "fetching credentials")
|
|
||||||
}
|
|
||||||
internalCfg, err := p.getInternalConfig(ctx, creds, org.GetBalancerType())
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Wrap(err, "fetching internal config")
|
|
||||||
}
|
|
||||||
|
|
||||||
newState := params.UpdatePoolStateParams{
|
|
||||||
WebhookSecret: org.WebhookSecret,
|
|
||||||
InternalConfig: &internalCfg,
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := poolMgr.RefreshState(newState); err != nil {
|
|
||||||
return nil, errors.Wrap(err, "updating repo pool manager")
|
|
||||||
}
|
|
||||||
return poolMgr, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *poolManagerCtrl) GetOrgPoolManager(org params.Organization) (common.PoolManager, error) {
|
func (p *poolManagerCtrl) GetOrgPoolManager(org params.Organization) (common.PoolManager, error) {
|
||||||
if orgPoolMgr, ok := p.organizations[org.ID]; ok {
|
if orgPoolMgr, ok := p.organizations[org.ID]; ok {
|
||||||
return orgPoolMgr, nil
|
return orgPoolMgr, nil
|
||||||
|
|
@ -263,22 +192,16 @@ func (p *poolManagerCtrl) CreateEnterprisePoolManager(ctx context.Context, enter
|
||||||
p.mux.Lock()
|
p.mux.Lock()
|
||||||
defer p.mux.Unlock()
|
defer p.mux.Unlock()
|
||||||
|
|
||||||
creds, err := p.store.GetGithubCredentials(ctx, enterprise.CredentialsID, true)
|
entity, err := enterprise.GetEntity()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "fetching credentials")
|
return nil, errors.Wrap(err, "getting entity")
|
||||||
}
|
|
||||||
cfgInternal, err := p.getInternalConfig(ctx, creds, enterprise.GetBalancerType())
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Wrap(err, "fetching internal config")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
entity := params.GithubEntity{
|
instanceTokenGetter, err := auth.NewInstanceTokenGetter(p.config.JWTAuth.Secret)
|
||||||
Owner: enterprise.Name,
|
if err != nil {
|
||||||
ID: enterprise.ID,
|
return nil, errors.Wrap(err, "creating instance token getter")
|
||||||
WebhookSecret: enterprise.WebhookSecret,
|
|
||||||
EntityType: params.GithubEntityTypeEnterprise,
|
|
||||||
}
|
}
|
||||||
poolManager, err := pool.NewEntityPoolManager(ctx, entity, cfgInternal, 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, errors.Wrap(err, "creating enterprise pool manager")
|
||||||
}
|
}
|
||||||
|
|
@ -286,35 +209,6 @@ func (p *poolManagerCtrl) CreateEnterprisePoolManager(ctx context.Context, enter
|
||||||
return poolManager, nil
|
return poolManager, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *poolManagerCtrl) UpdateEnterprisePoolManager(ctx context.Context, enterprise params.Enterprise) (common.PoolManager, error) {
|
|
||||||
p.mux.Lock()
|
|
||||||
defer p.mux.Unlock()
|
|
||||||
|
|
||||||
poolMgr, ok := p.enterprises[enterprise.ID]
|
|
||||||
if !ok {
|
|
||||||
return nil, errors.Wrapf(runnerErrors.ErrNotFound, "enterprise %s pool manager not loaded", enterprise.Name)
|
|
||||||
}
|
|
||||||
|
|
||||||
creds, err := p.store.GetGithubCredentials(ctx, enterprise.CredentialsID, true)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Wrap(err, "fetching credentials")
|
|
||||||
}
|
|
||||||
internalCfg, err := p.getInternalConfig(ctx, creds, enterprise.GetBalancerType())
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Wrap(err, "fetching internal config")
|
|
||||||
}
|
|
||||||
|
|
||||||
newState := params.UpdatePoolStateParams{
|
|
||||||
WebhookSecret: enterprise.WebhookSecret,
|
|
||||||
InternalConfig: &internalCfg,
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := poolMgr.RefreshState(newState); err != nil {
|
|
||||||
return nil, errors.Wrap(err, "updating repo pool manager")
|
|
||||||
}
|
|
||||||
return poolMgr, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *poolManagerCtrl) GetEnterprisePoolManager(enterprise params.Enterprise) (common.PoolManager, error) {
|
func (p *poolManagerCtrl) GetEnterprisePoolManager(enterprise params.Enterprise) (common.PoolManager, error) {
|
||||||
if enterprisePoolMgr, ok := p.enterprises[enterprise.ID]; ok {
|
if enterprisePoolMgr, ok := p.enterprises[enterprise.ID]; ok {
|
||||||
return enterprisePoolMgr, nil
|
return enterprisePoolMgr, nil
|
||||||
|
|
@ -340,24 +234,6 @@ func (p *poolManagerCtrl) GetEnterprisePoolManagers() (map[string]common.PoolMan
|
||||||
return p.enterprises, nil
|
return p.enterprises, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *poolManagerCtrl) getInternalConfig(_ context.Context, creds params.GithubCredentials, poolBalancerType params.PoolBalancerType) (params.Internal, error) {
|
|
||||||
controllerInfo, err := p.store.ControllerInfo()
|
|
||||||
if err != nil {
|
|
||||||
return params.Internal{}, errors.Wrap(err, "fetching controller info")
|
|
||||||
}
|
|
||||||
|
|
||||||
return params.Internal{
|
|
||||||
ControllerID: controllerInfo.ControllerID.String(),
|
|
||||||
InstanceCallbackURL: controllerInfo.CallbackURL,
|
|
||||||
InstanceMetadataURL: controllerInfo.MetadataURL,
|
|
||||||
BaseWebhookURL: controllerInfo.WebhookURL,
|
|
||||||
ControllerWebhookURL: controllerInfo.ControllerWebhookURL,
|
|
||||||
JWTSecret: p.config.JWTAuth.Secret,
|
|
||||||
PoolBalancerType: poolBalancerType,
|
|
||||||
GithubCredentialsDetails: creds,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type Runner struct {
|
type Runner struct {
|
||||||
mux sync.Mutex
|
mux sync.Mutex
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue