Skip to content

Commit

Permalink
Add flag to toggle webhook management
Browse files Browse the repository at this point in the history
Signed-off-by: Gabriel Adrian Samfira <[email protected]>
  • Loading branch information
gabriel-samfira committed Aug 16, 2023
1 parent 5d57d86 commit abf4b98
Show file tree
Hide file tree
Showing 8 changed files with 48 additions and 27 deletions.
5 changes: 3 additions & 2 deletions apiserver/controllers/controllers.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ type APIController struct {
}

func handleError(w http.ResponseWriter, err error) {
w.Header().Add("Content-Type", "application/json")
w.Header().Set("Content-Type", "application/json")
origErr := errors.Cause(err)
apiErr := params.APIErrorResponse{
Details: origErr.Error(),
Expand Down Expand Up @@ -214,8 +214,9 @@ func (a *APIController) NotFoundHandler(w http.ResponseWriter, r *http.Request)
Details: "Resource not found",
Error: "Not found",
}
w.WriteHeader(http.StatusNotFound)

w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusNotFound)
if err := json.NewEncoder(w).Encode(apiErr); err != nil {
log.Printf("failet to write response: %q", err)
}
Expand Down
47 changes: 26 additions & 21 deletions apiserver/routers/routers.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ func WithDebugServer(parentRouter *mux.Router) *mux.Router {
return parentRouter
}

func NewAPIRouter(han *controllers.APIController, logWriter io.Writer, authMiddleware, initMiddleware, instanceMiddleware auth.Middleware) *mux.Router {
func NewAPIRouter(han *controllers.APIController, logWriter io.Writer, authMiddleware, initMiddleware, instanceMiddleware auth.Middleware, manageWebhooks bool) *mux.Router {
router := mux.NewRouter()
logMiddleware := util.NewLoggingMiddleware(logWriter)
router.Use(logMiddleware)
Expand Down Expand Up @@ -204,16 +204,17 @@ func NewAPIRouter(han *controllers.APIController, logWriter io.Writer, authMiddl
apiRouter.Handle("/repositories/", http.HandlerFunc(han.CreateRepoHandler)).Methods("POST", "OPTIONS")
apiRouter.Handle("/repositories", http.HandlerFunc(han.CreateRepoHandler)).Methods("POST", "OPTIONS")

// Install Webhook
apiRouter.Handle("/repositories/{repoID}/webhook/", http.HandlerFunc(han.InstallRepoWebhookHandler)).Methods("POST", "OPTIONS")
apiRouter.Handle("/repositories/{repoID}/webhook", http.HandlerFunc(han.InstallRepoWebhookHandler)).Methods("POST", "OPTIONS")
// Uninstall Webhook
apiRouter.Handle("/repositories/{repoID}/webhook/", http.HandlerFunc(han.UninstallRepoWebhookHandler)).Methods("DELETE", "OPTIONS")
apiRouter.Handle("/repositories/{repoID}/webhook", http.HandlerFunc(han.UninstallRepoWebhookHandler)).Methods("DELETE", "OPTIONS")
// Get webhook info
apiRouter.Handle("/repositories/{repoID}/webhook/", http.HandlerFunc(han.GetRepoWebhookInfoHandler)).Methods("GET", "OPTIONS")
apiRouter.Handle("/repositories/{repoID}/webhook", http.HandlerFunc(han.GetRepoWebhookInfoHandler)).Methods("GET", "OPTIONS")

if manageWebhooks {
// Install Webhook
apiRouter.Handle("/repositories/{repoID}/webhook/", http.HandlerFunc(han.InstallRepoWebhookHandler)).Methods("POST", "OPTIONS")
apiRouter.Handle("/repositories/{repoID}/webhook", http.HandlerFunc(han.InstallRepoWebhookHandler)).Methods("POST", "OPTIONS")
// Uninstall Webhook
apiRouter.Handle("/repositories/{repoID}/webhook/", http.HandlerFunc(han.UninstallRepoWebhookHandler)).Methods("DELETE", "OPTIONS")
apiRouter.Handle("/repositories/{repoID}/webhook", http.HandlerFunc(han.UninstallRepoWebhookHandler)).Methods("DELETE", "OPTIONS")
// Get webhook info
apiRouter.Handle("/repositories/{repoID}/webhook/", http.HandlerFunc(han.GetRepoWebhookInfoHandler)).Methods("GET", "OPTIONS")
apiRouter.Handle("/repositories/{repoID}/webhook", http.HandlerFunc(han.GetRepoWebhookInfoHandler)).Methods("GET", "OPTIONS")
}
/////////////////////////////
// Organizations and pools //
/////////////////////////////
Expand Down Expand Up @@ -253,16 +254,17 @@ func NewAPIRouter(han *controllers.APIController, logWriter io.Writer, authMiddl
apiRouter.Handle("/organizations/", http.HandlerFunc(han.CreateOrgHandler)).Methods("POST", "OPTIONS")
apiRouter.Handle("/organizations", http.HandlerFunc(han.CreateOrgHandler)).Methods("POST", "OPTIONS")

// Install Webhook
apiRouter.Handle("/organizations/{orgID}/webhook/", http.HandlerFunc(han.InstallOrgWebhookHandler)).Methods("POST", "OPTIONS")
apiRouter.Handle("/organizations/{orgID}/webhook", http.HandlerFunc(han.InstallOrgWebhookHandler)).Methods("POST", "OPTIONS")
// Uninstall Webhook
apiRouter.Handle("/organizations/{orgID}/webhook/", http.HandlerFunc(han.UninstallOrgWebhookHandler)).Methods("DELETE", "OPTIONS")
apiRouter.Handle("/organizations/{orgID}/webhook", http.HandlerFunc(han.UninstallOrgWebhookHandler)).Methods("DELETE", "OPTIONS")
// Get webhook info
apiRouter.Handle("/organizations/{orgID}/webhook/", http.HandlerFunc(han.GetOrgWebhookInfoHandler)).Methods("GET", "OPTIONS")
apiRouter.Handle("/organizations/{orgID}/webhook", http.HandlerFunc(han.GetOrgWebhookInfoHandler)).Methods("GET", "OPTIONS")

if manageWebhooks {
// Install Webhook
apiRouter.Handle("/organizations/{orgID}/webhook/", http.HandlerFunc(han.InstallOrgWebhookHandler)).Methods("POST", "OPTIONS")
apiRouter.Handle("/organizations/{orgID}/webhook", http.HandlerFunc(han.InstallOrgWebhookHandler)).Methods("POST", "OPTIONS")
// Uninstall Webhook
apiRouter.Handle("/organizations/{orgID}/webhook/", http.HandlerFunc(han.UninstallOrgWebhookHandler)).Methods("DELETE", "OPTIONS")
apiRouter.Handle("/organizations/{orgID}/webhook", http.HandlerFunc(han.UninstallOrgWebhookHandler)).Methods("DELETE", "OPTIONS")
// Get webhook info
apiRouter.Handle("/organizations/{orgID}/webhook/", http.HandlerFunc(han.GetOrgWebhookInfoHandler)).Methods("GET", "OPTIONS")
apiRouter.Handle("/organizations/{orgID}/webhook", http.HandlerFunc(han.GetOrgWebhookInfoHandler)).Methods("GET", "OPTIONS")
}
/////////////////////////////
// Enterprises and pools //
/////////////////////////////
Expand Down Expand Up @@ -314,5 +316,8 @@ func NewAPIRouter(han *controllers.APIController, logWriter io.Writer, authMiddl

// Websocket log writer
apiRouter.Handle("/{ws:ws\\/?}", http.HandlerFunc(han.WSHandler)).Methods("GET")

// NotFound handler
apiRouter.PathPrefix("/").HandlerFunc(han.NotFoundHandler).Methods("GET", "POST", "PUT", "DELETE", "OPTIONS")
return router
}
2 changes: 1 addition & 1 deletion cmd/garm/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ func main() {
log.Fatal(err)
}

router := routers.NewAPIRouter(controller, multiWriter, jwtMiddleware, initMiddleware, instanceMiddleware)
router := routers.NewAPIRouter(controller, multiWriter, jwtMiddleware, initMiddleware, instanceMiddleware, cfg.Default.EnableWebhookManagement)

if cfg.Metrics.Enable {
log.Printf("registering prometheus metrics collectors")
Expand Down
2 changes: 2 additions & 0 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,8 @@ type Default struct {
MetadataURL string `toml:"metadata_url" json:"metadata-url"`
// WebhookURL is the URL that will be installed as a webhook target in github.
WebhookURL string `toml:"webhook_url" json:"webhook-url"`
// EnableWebhookManagement enables the webhook management API.
EnableWebhookManagement bool `toml:"enable_webhook_management" json:"enable-webhook-management"`

// LogFile is the location of the log file.
LogFile string `toml:"log_file,omitempty" json:"log-file"`
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ require (
github.com/go-openapi/errors v0.20.4
github.com/go-openapi/runtime v0.26.0
github.com/go-openapi/strfmt v0.21.7
github.com/go-openapi/swag v0.22.4
github.com/golang-jwt/jwt v3.2.2+incompatible
github.com/google/go-github/v53 v53.2.0
github.com/google/uuid v1.3.0
Expand Down Expand Up @@ -55,7 +56,6 @@ require (
github.com/go-openapi/jsonreference v0.20.0 // indirect
github.com/go-openapi/loads v0.21.2 // indirect
github.com/go-openapi/spec v0.20.8 // indirect
github.com/go-openapi/swag v0.22.4 // indirect
github.com/go-openapi/validate v0.22.1 // indirect
github.com/go-sql-driver/mysql v1.7.0 // indirect
github.com/golang/protobuf v1.5.3 // indirect
Expand Down
2 changes: 1 addition & 1 deletion runner/organizations.go
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ func (r *Runner) DeleteOrganization(ctx context.Context, orgID string, keepWebho
return runnerErrors.NewBadRequestError("org has pools defined (%s)", strings.Join(poolIds, ", "))
}

if !keepWebhook {
if !keepWebhook && r.config.Default.EnableWebhookManagement {
poolMgr, err := r.poolManagerCtrl.GetOrgPoolManager(org)
if err != nil {
return errors.Wrap(err, "fetching pool manager")
Expand Down
2 changes: 1 addition & 1 deletion runner/repositories.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ func (r *Runner) DeleteRepository(ctx context.Context, repoID string, keepWebhoo
return runnerErrors.NewBadRequestError("repo has pools defined (%s)", strings.Join(poolIds, ", "))
}

if !keepWebhook {
if !keepWebhook && r.config.Default.EnableWebhookManagement {
poolMgr, err := r.poolManagerCtrl.GetRepoPoolManager(repo)
if err != nil {
return errors.Wrap(err, "fetching pool manager")
Expand Down
13 changes: 13 additions & 0 deletions testdata/config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,21 @@ callback_url = "https://garm.example.com/api/v1/callbacks"
# highly encouraged.
metadata_url = "https://garm.example.com/api/v1/metadata"

# This is the base URL where GARM will listen for webhook events from github. This
# URL can be directly configured in github to send events to.
# If GARM is allowed to manage webhooks, this URL will be used as a base to optionally
# create webhooks for repositories and organizations. To avoid clashes, the unique
# controller ID that gets generated when GARM is first installed, will be added as a suffix
# to this URL.
#
# For example, assuming that your GARM controller ID is "18225ce4-e3bd-43f0-9c85-7d7858bcc5b2"
# the webhook URL will be "https://garm.example.com/webhooks/18225ce4-e3bd-43f0-9c85-7d7858bcc5b2"
webhook_url = "https://garm.example.com/webhooks"

# This option enables GARM to manage webhooks for repositories and organizations. Set this
# to false to disable the API routes that manage webhooks.
enable_webhook_management = true

# Uncomment this line if you'd like to log to a file instead of standard output.
# log_file = "/tmp/runner-manager.log"

Expand Down

0 comments on commit abf4b98

Please sign in to comment.