From c00048e128ca382d8b79b19a029be635875319bb Mon Sep 17 00:00:00 2001 From: Gabriel Adrian Samfira Date: Wed, 16 Aug 2023 10:02:22 +0000 Subject: [PATCH] Add optional keepWebhook flag when removing an entity The user can opt to not delete the webhook (if installed) when removing the entity from garm. Garm will only ever try to remove a webhook that exactly matches the URL that is composed of the base webhook URL configured in the config.toml file and the unique controller ID that is generated when the controller is first installed. It should be safe to remove the webhook when the entity is removed. Of course, this behavior can be disabled. Signed-off-by: Gabriel Adrian Samfira --- apiserver/controllers/organizations.go | 11 +++++- apiserver/controllers/repositories.go | 10 +++++- apiserver/swagger.yaml | 8 +++++ client/organizations/delete_org_parameters.go | 35 +++++++++++++++++++ client/repositories/delete_repo_parameters.go | 35 +++++++++++++++++++ cmd/garm-cli/cmd/organization.go | 5 +++ cmd/garm-cli/cmd/repository.go | 6 ++++ 7 files changed, 108 insertions(+), 2 deletions(-) diff --git a/apiserver/controllers/organizations.go b/apiserver/controllers/organizations.go index ad158a84..02f93fc4 100644 --- a/apiserver/controllers/organizations.go +++ b/apiserver/controllers/organizations.go @@ -18,6 +18,7 @@ import ( "encoding/json" "log" "net/http" + "strconv" gErrors "github.com/cloudbase/garm-provider-common/errors" "github.com/cloudbase/garm/apiserver/params" @@ -139,6 +140,12 @@ func (a *APIController) GetOrgByIDHandler(w http.ResponseWriter, r *http.Request // in: path // required: true // +// + name: keepWebhook +// description: If true and a webhook is installed for this organization, it will not be removed. +// type: boolean +// in: query +// required: false +// // Responses: // default: APIErrorResponse func (a *APIController) DeleteOrgHandler(w http.ResponseWriter, r *http.Request) { @@ -157,7 +164,9 @@ func (a *APIController) DeleteOrgHandler(w http.ResponseWriter, r *http.Request) return } - if err := a.r.DeleteOrganization(ctx, orgID, false); err != nil { + keepWebhook, _ := strconv.ParseBool(r.URL.Query().Get("keepWebhook")) + + if err := a.r.DeleteOrganization(ctx, orgID, keepWebhook); err != nil { log.Printf("removing org: %+v", err) handleError(w, err) return diff --git a/apiserver/controllers/repositories.go b/apiserver/controllers/repositories.go index 20eac630..ae2a3040 100644 --- a/apiserver/controllers/repositories.go +++ b/apiserver/controllers/repositories.go @@ -18,6 +18,7 @@ import ( "encoding/json" "log" "net/http" + "strconv" gErrors "github.com/cloudbase/garm-provider-common/errors" "github.com/cloudbase/garm/apiserver/params" @@ -139,6 +140,12 @@ func (a *APIController) GetRepoByIDHandler(w http.ResponseWriter, r *http.Reques // in: path // required: true // +// + name: keepWebhook +// description: If true and a webhook is installed for this repo, it will not be removed. +// type: boolean +// in: query +// required: false +// // Responses: // default: APIErrorResponse func (a *APIController) DeleteRepoHandler(w http.ResponseWriter, r *http.Request) { @@ -157,7 +164,8 @@ func (a *APIController) DeleteRepoHandler(w http.ResponseWriter, r *http.Request return } - if err := a.r.DeleteRepository(ctx, repoID, false); err != nil { + keepWebhook, _ := strconv.ParseBool(r.URL.Query().Get("keepWebhook")) + if err := a.r.DeleteRepository(ctx, repoID, keepWebhook); err != nil { log.Printf("fetching repo: %s", err) handleError(w, err) return diff --git a/apiserver/swagger.yaml b/apiserver/swagger.yaml index dba80a58..1d5f33b1 100644 --- a/apiserver/swagger.yaml +++ b/apiserver/swagger.yaml @@ -702,6 +702,10 @@ paths: name: orgID required: true type: string + - description: If true and a webhook is installed for this organization, it will not be removed. + in: query + name: keepWebhook + type: boolean responses: default: description: APIErrorResponse @@ -1147,6 +1151,10 @@ paths: name: repoID required: true type: string + - description: If true and a webhook is installed for this repo, it will not be removed. + in: query + name: keepWebhook + type: boolean responses: default: description: APIErrorResponse diff --git a/client/organizations/delete_org_parameters.go b/client/organizations/delete_org_parameters.go index 92e27495..daf36813 100644 --- a/client/organizations/delete_org_parameters.go +++ b/client/organizations/delete_org_parameters.go @@ -14,6 +14,7 @@ import ( "github.com/go-openapi/runtime" cr "github.com/go-openapi/runtime/client" "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" ) // NewDeleteOrgParams creates a new DeleteOrgParams object, @@ -61,6 +62,12 @@ DeleteOrgParams contains all the parameters to send to the API endpoint */ type DeleteOrgParams struct { + /* KeepWebhook. + + If true and a webhook is installed for this organization, it will not be removed. + */ + KeepWebhook *bool + /* OrgID. ID of the organization to delete. @@ -120,6 +127,17 @@ func (o *DeleteOrgParams) SetHTTPClient(client *http.Client) { o.HTTPClient = client } +// WithKeepWebhook adds the keepWebhook to the delete org params +func (o *DeleteOrgParams) WithKeepWebhook(keepWebhook *bool) *DeleteOrgParams { + o.SetKeepWebhook(keepWebhook) + return o +} + +// SetKeepWebhook adds the keepWebhook to the delete org params +func (o *DeleteOrgParams) SetKeepWebhook(keepWebhook *bool) { + o.KeepWebhook = keepWebhook +} + // WithOrgID adds the orgID to the delete org params func (o *DeleteOrgParams) WithOrgID(orgID string) *DeleteOrgParams { o.SetOrgID(orgID) @@ -139,6 +157,23 @@ func (o *DeleteOrgParams) WriteToRequest(r runtime.ClientRequest, reg strfmt.Reg } var res []error + if o.KeepWebhook != nil { + + // query param keepWebhook + var qrKeepWebhook bool + + if o.KeepWebhook != nil { + qrKeepWebhook = *o.KeepWebhook + } + qKeepWebhook := swag.FormatBool(qrKeepWebhook) + if qKeepWebhook != "" { + + if err := r.SetQueryParam("keepWebhook", qKeepWebhook); err != nil { + return err + } + } + } + // path param orgID if err := r.SetPathParam("orgID", o.OrgID); err != nil { return err diff --git a/client/repositories/delete_repo_parameters.go b/client/repositories/delete_repo_parameters.go index 08ea11d9..8bfd54eb 100644 --- a/client/repositories/delete_repo_parameters.go +++ b/client/repositories/delete_repo_parameters.go @@ -14,6 +14,7 @@ import ( "github.com/go-openapi/runtime" cr "github.com/go-openapi/runtime/client" "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" ) // NewDeleteRepoParams creates a new DeleteRepoParams object, @@ -61,6 +62,12 @@ DeleteRepoParams contains all the parameters to send to the API endpoint */ type DeleteRepoParams struct { + /* KeepWebhook. + + If true and a webhook is installed for this repo, it will not be removed. + */ + KeepWebhook *bool + /* RepoID. ID of the repository to delete. @@ -120,6 +127,17 @@ func (o *DeleteRepoParams) SetHTTPClient(client *http.Client) { o.HTTPClient = client } +// WithKeepWebhook adds the keepWebhook to the delete repo params +func (o *DeleteRepoParams) WithKeepWebhook(keepWebhook *bool) *DeleteRepoParams { + o.SetKeepWebhook(keepWebhook) + return o +} + +// SetKeepWebhook adds the keepWebhook to the delete repo params +func (o *DeleteRepoParams) SetKeepWebhook(keepWebhook *bool) { + o.KeepWebhook = keepWebhook +} + // WithRepoID adds the repoID to the delete repo params func (o *DeleteRepoParams) WithRepoID(repoID string) *DeleteRepoParams { o.SetRepoID(repoID) @@ -139,6 +157,23 @@ func (o *DeleteRepoParams) WriteToRequest(r runtime.ClientRequest, reg strfmt.Re } var res []error + if o.KeepWebhook != nil { + + // query param keepWebhook + var qrKeepWebhook bool + + if o.KeepWebhook != nil { + qrKeepWebhook = *o.KeepWebhook + } + qKeepWebhook := swag.FormatBool(qrKeepWebhook) + if qKeepWebhook != "" { + + if err := r.SetQueryParam("keepWebhook", qKeepWebhook); err != nil { + return err + } + } + } + // path param repoID if err := r.SetPathParam("repoID", o.RepoID); err != nil { return err diff --git a/cmd/garm-cli/cmd/organization.go b/cmd/garm-cli/cmd/organization.go index 26943638..b3dbd0e1 100644 --- a/cmd/garm-cli/cmd/organization.go +++ b/cmd/garm-cli/cmd/organization.go @@ -31,6 +31,7 @@ var ( orgCreds string orgRandomWebhookSecret bool insecureOrgWebhook bool + keepOrgWebhook bool ) // organizationCmd represents the organization command @@ -271,6 +272,7 @@ var orgDeleteCmd = &cobra.Command{ } deleteOrgReq := apiClientOrgs.NewDeleteOrgParams() deleteOrgReq.OrgID = args[0] + deleteOrgReq.KeepWebhook = &keepOrgWebhook if err := apiCli.Organizations.DeleteOrg(deleteOrgReq, authToken); err != nil { return err } @@ -289,6 +291,9 @@ func init() { orgAddCmd.MarkFlagRequired("credentials") //nolint orgAddCmd.MarkFlagRequired("name") //nolint + + orgDeleteCmd.Flags().BoolVar(&keepOrgWebhook, "keep-webhook", false, "Do not delete any existing webhook when removing the organization from GARM.") + orgUpdateCmd.Flags().StringVar(&orgWebhookSecret, "webhook-secret", "", "The webhook secret for this organization") orgUpdateCmd.Flags().StringVar(&orgCreds, "credentials", "", "Credentials name. See credentials list.") diff --git a/cmd/garm-cli/cmd/repository.go b/cmd/garm-cli/cmd/repository.go index bac9ace2..5d596dd6 100644 --- a/cmd/garm-cli/cmd/repository.go +++ b/cmd/garm-cli/cmd/repository.go @@ -32,6 +32,7 @@ var ( repoCreds string randomWebhookSecret bool insecureRepoWebhook bool + keepRepoWebhook bool ) // repositoryCmd represents the repository command @@ -274,6 +275,7 @@ var repoDeleteCmd = &cobra.Command{ } deleteRepoReq := apiClientRepos.NewDeleteRepoParams() deleteRepoReq.RepoID = args[0] + deleteRepoReq.KeepWebhook = &keepRepoWebhook if err := apiCli.Repositories.DeleteRepo(deleteRepoReq, authToken); err != nil { return err } @@ -294,10 +296,14 @@ func init() { repoAddCmd.MarkFlagRequired("credentials") //nolint repoAddCmd.MarkFlagRequired("owner") //nolint repoAddCmd.MarkFlagRequired("name") //nolint + + repoDeleteCmd.Flags().BoolVar(&keepRepoWebhook, "keep-webhook", false, "Do not delete any existing webhook when removing the repo from GARM.") + repoUpdateCmd.Flags().StringVar(&repoWebhookSecret, "webhook-secret", "", "The webhook secret for this repository. If you update this secret, you will have to manually update the secret in GitHub as well.") repoUpdateCmd.Flags().StringVar(&repoCreds, "credentials", "", "Credentials name. See credentials list.") repoWebhookInstallCmd.Flags().BoolVar(&insecureRepoWebhook, "insecure", false, "Ignore self signed certificate errors.") + repoWebhookCmd.AddCommand( repoWebhookInstallCmd, repoWebhookUninstallCmd,