From eadbe784b92e02ec729b93386007f9376cd941b4 Mon Sep 17 00:00:00 2001 From: Gabriel Adrian Samfira Date: Fri, 19 Apr 2024 08:47:44 +0000 Subject: [PATCH] Add github credentials API and cli code Signed-off-by: Gabriel Adrian Samfira --- apiserver/controllers/controllers.go | 5 +- apiserver/controllers/credentials.go | 201 +++++++++ apiserver/routers/routers.go | 26 +- apiserver/swagger-models.yaml | 16 +- apiserver/swagger.yaml | 132 +++++- .../create_credentials_parameters.go | 151 +++++++ .../create_credentials_responses.go | 174 ++++++++ client/credentials/credentials_client.go | 159 ++++++- .../delete_credentials_parameters.go | 152 +++++++ .../delete_credentials_responses.go | 103 +++++ .../credentials/get_credentials_parameters.go | 152 +++++++ .../credentials/get_credentials_responses.go | 174 ++++++++ .../credentials/list_credentials_responses.go | 10 +- .../update_credentials_parameters.go | 174 ++++++++ .../update_credentials_responses.go | 174 ++++++++ cmd/garm-cli/cmd/credentials.go | 76 ---- cmd/garm-cli/cmd/github_credentials.go | 388 ++++++++++++++++++ cmd/garm-cli/cmd/github_endpoints.go | 12 +- database/common/common.go | 2 +- database/common/mocks/Store.go | 18 +- database/sql/github.go | 7 +- database/sql/sql.go | 3 +- internal/testing/testing.go | 3 +- params/params.go | 4 + params/requests.go | 127 ++++-- runner/github_credentials.go | 83 ++++ runner/{endpoints.go => github_endpoints.go} | 0 runner/runner.go | 13 - 28 files changed, 2364 insertions(+), 175 deletions(-) create mode 100644 client/credentials/create_credentials_parameters.go create mode 100644 client/credentials/create_credentials_responses.go create mode 100644 client/credentials/delete_credentials_parameters.go create mode 100644 client/credentials/delete_credentials_responses.go create mode 100644 client/credentials/get_credentials_parameters.go create mode 100644 client/credentials/get_credentials_responses.go create mode 100644 client/credentials/update_credentials_parameters.go create mode 100644 client/credentials/update_credentials_responses.go delete mode 100644 cmd/garm-cli/cmd/credentials.go create mode 100644 cmd/garm-cli/cmd/github_credentials.go create mode 100644 runner/github_credentials.go rename runner/{endpoints.go => github_endpoints.go} (100%) diff --git a/apiserver/controllers/controllers.go b/apiserver/controllers/controllers.go index c1d4561e..56745b82 100644 --- a/apiserver/controllers/controllers.go +++ b/apiserver/controllers/controllers.go @@ -102,10 +102,7 @@ func (a *APIController) handleWorkflowJobEvent(ctx context.Context, w http.Respo handleError(ctx, w, gErrors.NewBadRequestError("invalid post body: %s", err)) return } - slog.Info("received webhook", "body", string(body)) - for k, v := range r.Header { - slog.InfoContext(ctx, "header", "key", k, "value", v) - } + signature := r.Header.Get("X-Hub-Signature-256") hookType := r.Header.Get("X-Github-Hook-Installation-Target-Type") diff --git a/apiserver/controllers/credentials.go b/apiserver/controllers/credentials.go index bfc3d494..70869b54 100644 --- a/apiserver/controllers/credentials.go +++ b/apiserver/controllers/credentials.go @@ -3,10 +3,18 @@ package controllers import ( "encoding/json" "log/slog" + "math" "net/http" + "strconv" + + "github.com/gorilla/mux" + + gErrors "github.com/cloudbase/garm-provider-common/errors" + "github.com/cloudbase/garm/params" ) // swagger:route GET /credentials credentials ListCredentials +// swagger:route GET /github/credentials credentials ListCredentials // // List all credentials. // @@ -26,3 +34,196 @@ func (a *APIController) ListCredentials(w http.ResponseWriter, r *http.Request) slog.With(slog.Any("error", err)).ErrorContext(ctx, "failed to encode response") } } + +// swagger:route POST /github/credentials credentials CreateCredentials +// +// Create a GitHub credential. +// +// Parameters: +// + name: Body +// description: Parameters used when creating a GitHub credential. +// type: CreateGithubCredentialsParams +// in: body +// required: true +// +// Responses: +// 200: GithubCredentials +// 400: APIErrorResponse +func (a *APIController) CreateGithubCredential(w http.ResponseWriter, r *http.Request) { + ctx := r.Context() + + var params params.CreateGithubCredentialsParams + if err := json.NewDecoder(r.Body).Decode(¶ms); err != nil { + slog.With(slog.Any("error", err)).ErrorContext(ctx, "failed to decode request") + handleError(ctx, w, gErrors.ErrBadRequest) + return + } + + cred, err := a.r.CreateGithubCredentials(ctx, params) + if err != nil { + slog.With(slog.Any("error", err)).ErrorContext(ctx, "failed to create GitHub credential") + handleError(ctx, w, err) + return + } + w.Header().Set("Content-Type", "application/json") + if err := json.NewEncoder(w).Encode(cred); err != nil { + slog.With(slog.Any("error", err)).ErrorContext(ctx, "failed to encode response") + } +} + +// swagger:route GET /github/credentials/{id} credentials GetCredentials +// +// Get a GitHub credential. +// +// Parameters: +// + name: id +// description: ID of the GitHub credential. +// type: integer +// in: path +// required: true +// +// Responses: +// 200: GithubCredentials +// 400: APIErrorResponse +func (a *APIController) GetGithubCredential(w http.ResponseWriter, r *http.Request) { + ctx := r.Context() + vars := mux.Vars(r) + idParam, ok := vars["id"] + if !ok { + slog.ErrorContext(ctx, "missing id in request") + handleError(ctx, w, gErrors.ErrBadRequest) + return + } + + id, err := strconv.ParseUint(idParam, 10, 64) + if err != nil { + slog.With(slog.Any("error", err)).ErrorContext(ctx, "failed to parse id") + handleError(ctx, w, gErrors.ErrBadRequest) + return + } + + if id > math.MaxUint { + slog.With(slog.Any("error", err)).ErrorContext(ctx, "id is too large") + handleError(ctx, w, gErrors.ErrBadRequest) + return + } + + cred, err := a.r.GetGithubCredentials(ctx, uint(id)) + if err != nil { + slog.With(slog.Any("error", err)).ErrorContext(ctx, "failed to get GitHub credential") + handleError(ctx, w, err) + return + } + + w.Header().Set("Content-Type", "application/json") + if err := json.NewEncoder(w).Encode(cred); err != nil { + slog.With(slog.Any("error", err)).ErrorContext(ctx, "failed to encode response") + } +} + +// swagger:route DELETE /github/credentials/{id} credentials DeleteCredentials +// +// Delete a GitHub credential. +// +// Parameters: +// + name: id +// description: ID of the GitHub credential. +// type: integer +// in: path +// required: true +// +// Responses: +// default: APIErrorResponse +func (a *APIController) DeleteGithubCredential(w http.ResponseWriter, r *http.Request) { + ctx := r.Context() + vars := mux.Vars(r) + idParam, ok := vars["id"] + if !ok { + slog.ErrorContext(ctx, "missing id in request") + handleError(ctx, w, gErrors.ErrBadRequest) + return + } + + id, err := strconv.ParseUint(idParam, 10, 64) + if err != nil { + slog.With(slog.Any("error", err)).ErrorContext(ctx, "failed to parse id") + handleError(ctx, w, gErrors.ErrBadRequest) + return + } + + if id > math.MaxUint { + slog.With(slog.Any("error", err)).ErrorContext(ctx, "id is too large") + handleError(ctx, w, gErrors.ErrBadRequest) + return + } + + if err := a.r.DeleteGithubCredentials(ctx, uint(id)); err != nil { + slog.With(slog.Any("error", err)).ErrorContext(ctx, "failed to delete GitHub credential") + handleError(ctx, w, err) + return + } + + w.WriteHeader(http.StatusNoContent) +} + +// swagger:route PUT /github/credentials/{id} credentials UpdateCredentials +// +// Update a GitHub credential. +// +// Parameters: +// + name: id +// description: ID of the GitHub credential. +// type: integer +// in: path +// required: true +// + name: Body +// description: Parameters used when updating a GitHub credential. +// type: UpdateGithubCredentialsParams +// in: body +// required: true +// +// Responses: +// 200: GithubCredentials +// 400: APIErrorResponse +func (a *APIController) UpdateGithubCredential(w http.ResponseWriter, r *http.Request) { + ctx := r.Context() + vars := mux.Vars(r) + idParam, ok := vars["id"] + if !ok { + slog.ErrorContext(ctx, "missing id in request") + handleError(ctx, w, gErrors.ErrBadRequest) + return + } + + id, err := strconv.ParseUint(idParam, 10, 64) + if err != nil { + slog.With(slog.Any("error", err)).ErrorContext(ctx, "failed to parse id") + handleError(ctx, w, gErrors.ErrBadRequest) + return + } + + if id > math.MaxUint { + slog.With(slog.Any("error", err)).ErrorContext(ctx, "id is too large") + handleError(ctx, w, gErrors.ErrBadRequest) + return + } + + var params params.UpdateGithubCredentialsParams + if err := json.NewDecoder(r.Body).Decode(¶ms); err != nil { + slog.With(slog.Any("error", err)).ErrorContext(ctx, "failed to decode request") + handleError(ctx, w, gErrors.ErrBadRequest) + return + } + + cred, err := a.r.UpdateGithubCredentials(ctx, uint(id), params) + if err != nil { + slog.With(slog.Any("error", err)).ErrorContext(ctx, "failed to update GitHub credential") + handleError(ctx, w, err) + return + } + + w.Header().Set("Content-Type", "application/json") + if err := json.NewEncoder(w).Encode(cred); err != nil { + slog.With(slog.Any("error", err)).ErrorContext(ctx, "failed to encode response") + } +} diff --git a/apiserver/routers/routers.go b/apiserver/routers/routers.go index fcb971d0..583fb8ac 100644 --- a/apiserver/routers/routers.go +++ b/apiserver/routers/routers.go @@ -339,10 +339,6 @@ func NewAPIRouter(han *controllers.APIController, authMiddleware, initMiddleware apiRouter.Handle("/enterprises/", http.HandlerFunc(han.CreateEnterpriseHandler)).Methods("POST", "OPTIONS") apiRouter.Handle("/enterprises", http.HandlerFunc(han.CreateEnterpriseHandler)).Methods("POST", "OPTIONS") - // Credentials - apiRouter.Handle("/credentials/", http.HandlerFunc(han.ListCredentials)).Methods("GET", "OPTIONS") - apiRouter.Handle("/credentials", http.HandlerFunc(han.ListCredentials)).Methods("GET", "OPTIONS") - // Providers apiRouter.Handle("/providers/", http.HandlerFunc(han.ListProviders)).Methods("GET", "OPTIONS") apiRouter.Handle("/providers", http.HandlerFunc(han.ListProviders)).Methods("GET", "OPTIONS") @@ -370,6 +366,28 @@ func NewAPIRouter(han *controllers.APIController, authMiddleware, initMiddleware apiRouter.Handle("/github/endpoints/{name}/", http.HandlerFunc(han.UpdateGithubEndpoint)).Methods("PUT", "OPTIONS") apiRouter.Handle("/github/endpoints/{name}", http.HandlerFunc(han.UpdateGithubEndpoint)).Methods("PUT", "OPTIONS") + //////////////////////// + // Github credentials // + //////////////////////// + // Legacy credentials path + apiRouter.Handle("/credentials/", http.HandlerFunc(han.ListCredentials)).Methods("GET", "OPTIONS") + apiRouter.Handle("/credentials", http.HandlerFunc(han.ListCredentials)).Methods("GET", "OPTIONS") + // List Github Credentials + apiRouter.Handle("/github/credentials/", http.HandlerFunc(han.ListCredentials)).Methods("GET", "OPTIONS") + apiRouter.Handle("/github/credentials", http.HandlerFunc(han.ListCredentials)).Methods("GET", "OPTIONS") + // Create Github Credentials + apiRouter.Handle("/github/credentials/", http.HandlerFunc(han.CreateGithubCredential)).Methods("POST", "OPTIONS") + apiRouter.Handle("/github/credentials", http.HandlerFunc(han.CreateGithubCredential)).Methods("POST", "OPTIONS") + // Get Github Credential + apiRouter.Handle("/github/credentials/{id}/", http.HandlerFunc(han.GetGithubCredential)).Methods("GET", "OPTIONS") + apiRouter.Handle("/github/credentials/{id}", http.HandlerFunc(han.GetGithubCredential)).Methods("GET", "OPTIONS") + // Delete Github Credential + apiRouter.Handle("/github/credentials/{id}/", http.HandlerFunc(han.DeleteGithubCredential)).Methods("DELETE", "OPTIONS") + apiRouter.Handle("/github/credentials/{id}", http.HandlerFunc(han.DeleteGithubCredential)).Methods("DELETE", "OPTIONS") + // Update Github Credential + apiRouter.Handle("/github/credentials/{id}/", http.HandlerFunc(han.UpdateGithubCredential)).Methods("PUT", "OPTIONS") + apiRouter.Handle("/github/credentials/{id}", http.HandlerFunc(han.UpdateGithubCredential)).Methods("PUT", "OPTIONS") + // Websocket log writer apiRouter.Handle("/{ws:ws\\/?}", http.HandlerFunc(han.WSHandler)).Methods("GET") diff --git a/apiserver/swagger-models.yaml b/apiserver/swagger-models.yaml index ae9bdd0b..b9ab5670 100644 --- a/apiserver/swagger-models.yaml +++ b/apiserver/swagger-models.yaml @@ -263,4 +263,18 @@ definitions: type: CreateGithubEndpointParams import: package: github.com/cloudbase/garm/params - alias: garm_params \ No newline at end of file + alias: garm_params + CreateGithubCredentialsParams: + type: object + x-go-type: + type: CreateGithubCredentialsParams + import: + package: github.com/cloudbase/garm/params + alias: garm_params + UpdateGithubCredentialsParams: + type: object + x-go-type: + type: UpdateGithubCredentialsParams + import: + package: github.com/cloudbase/garm/params + alias: garm_params diff --git a/apiserver/swagger.yaml b/apiserver/swagger.yaml index 53ca9309..afed3747 100644 --- a/apiserver/swagger.yaml +++ b/apiserver/swagger.yaml @@ -23,6 +23,13 @@ definitions: alias: garm_params package: github.com/cloudbase/garm/params type: CreateEnterpriseParams + CreateGithubCredentialsParams: + type: object + x-go-type: + import: + alias: garm_params + package: github.com/cloudbase/garm/params + type: CreateGithubCredentialsParams CreateGithubEndpointParams: type: object x-go-type: @@ -244,6 +251,13 @@ definitions: alias: garm_params package: github.com/cloudbase/garm/params type: UpdateEntityParams + UpdateGithubCredentialsParams: + type: object + x-go-type: + import: + alias: garm_params + package: github.com/cloudbase/garm/params + type: UpdateGithubCredentialsParams UpdateGithubEndpointParams: type: object x-go-type: @@ -312,21 +326,6 @@ paths: summary: Get controller info. tags: - controllerInfo - /credentials: - get: - operationId: ListCredentials - responses: - "200": - description: Credentials - schema: - $ref: '#/definitions/Credentials' - "400": - description: APIErrorResponse - schema: - $ref: '#/definitions/APIErrorResponse' - summary: List all credentials. - tags: - - credentials /enterprises: get: operationId: ListEnterprises @@ -610,6 +609,109 @@ paths: summary: Initialize the first run of the controller. tags: - first-run + /github/credentials: + get: + operationId: ListCredentials + responses: + "200": + description: Credentials + schema: + $ref: '#/definitions/Credentials' + "400": + description: APIErrorResponse + schema: + $ref: '#/definitions/APIErrorResponse' + summary: List all credentials. + tags: + - credentials + post: + operationId: CreateCredentials + parameters: + - description: Parameters used when creating a GitHub credential. + in: body + name: Body + required: true + schema: + $ref: '#/definitions/CreateGithubCredentialsParams' + description: Parameters used when creating a GitHub credential. + type: object + responses: + "200": + description: GithubCredentials + schema: + $ref: '#/definitions/GithubCredentials' + "400": + description: APIErrorResponse + schema: + $ref: '#/definitions/APIErrorResponse' + summary: Create a GitHub credential. + tags: + - credentials + /github/credentials/{id}: + delete: + operationId: DeleteCredentials + parameters: + - description: ID of the GitHub credential. + in: path + name: id + required: true + type: integer + responses: + default: + description: APIErrorResponse + schema: + $ref: '#/definitions/APIErrorResponse' + summary: Delete a GitHub credential. + tags: + - credentials + get: + operationId: GetCredentials + parameters: + - description: ID of the GitHub credential. + in: path + name: id + required: true + type: integer + responses: + "200": + description: GithubCredentials + schema: + $ref: '#/definitions/GithubCredentials' + "400": + description: APIErrorResponse + schema: + $ref: '#/definitions/APIErrorResponse' + summary: Get a GitHub credential. + tags: + - credentials + put: + operationId: UpdateCredentials + parameters: + - description: ID of the GitHub credential. + in: path + name: id + required: true + type: integer + - description: Parameters used when updating a GitHub credential. + in: body + name: Body + required: true + schema: + $ref: '#/definitions/UpdateGithubCredentialsParams' + description: Parameters used when updating a GitHub credential. + type: object + responses: + "200": + description: GithubCredentials + schema: + $ref: '#/definitions/GithubCredentials' + "400": + description: APIErrorResponse + schema: + $ref: '#/definitions/APIErrorResponse' + summary: Update a GitHub credential. + tags: + - credentials /github/endpoints: get: operationId: ListGithubEndpoints diff --git a/client/credentials/create_credentials_parameters.go b/client/credentials/create_credentials_parameters.go new file mode 100644 index 00000000..4288808f --- /dev/null +++ b/client/credentials/create_credentials_parameters.go @@ -0,0 +1,151 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package credentials + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "context" + "net/http" + "time" + + "github.com/go-openapi/errors" + "github.com/go-openapi/runtime" + cr "github.com/go-openapi/runtime/client" + "github.com/go-openapi/strfmt" + + garm_params "github.com/cloudbase/garm/params" +) + +// NewCreateCredentialsParams creates a new CreateCredentialsParams object, +// with the default timeout for this client. +// +// Default values are not hydrated, since defaults are normally applied by the API server side. +// +// To enforce default values in parameter, use SetDefaults or WithDefaults. +func NewCreateCredentialsParams() *CreateCredentialsParams { + return &CreateCredentialsParams{ + timeout: cr.DefaultTimeout, + } +} + +// NewCreateCredentialsParamsWithTimeout creates a new CreateCredentialsParams object +// with the ability to set a timeout on a request. +func NewCreateCredentialsParamsWithTimeout(timeout time.Duration) *CreateCredentialsParams { + return &CreateCredentialsParams{ + timeout: timeout, + } +} + +// NewCreateCredentialsParamsWithContext creates a new CreateCredentialsParams object +// with the ability to set a context for a request. +func NewCreateCredentialsParamsWithContext(ctx context.Context) *CreateCredentialsParams { + return &CreateCredentialsParams{ + Context: ctx, + } +} + +// NewCreateCredentialsParamsWithHTTPClient creates a new CreateCredentialsParams object +// with the ability to set a custom HTTPClient for a request. +func NewCreateCredentialsParamsWithHTTPClient(client *http.Client) *CreateCredentialsParams { + return &CreateCredentialsParams{ + HTTPClient: client, + } +} + +/* +CreateCredentialsParams contains all the parameters to send to the API endpoint + + for the create credentials operation. + + Typically these are written to a http.Request. +*/ +type CreateCredentialsParams struct { + + /* Body. + + Parameters used when creating a GitHub credential. + */ + Body garm_params.CreateGithubCredentialsParams + + timeout time.Duration + Context context.Context + HTTPClient *http.Client +} + +// WithDefaults hydrates default values in the create credentials params (not the query body). +// +// All values with no default are reset to their zero value. +func (o *CreateCredentialsParams) WithDefaults() *CreateCredentialsParams { + o.SetDefaults() + return o +} + +// SetDefaults hydrates default values in the create credentials params (not the query body). +// +// All values with no default are reset to their zero value. +func (o *CreateCredentialsParams) SetDefaults() { + // no default values defined for this parameter +} + +// WithTimeout adds the timeout to the create credentials params +func (o *CreateCredentialsParams) WithTimeout(timeout time.Duration) *CreateCredentialsParams { + o.SetTimeout(timeout) + return o +} + +// SetTimeout adds the timeout to the create credentials params +func (o *CreateCredentialsParams) SetTimeout(timeout time.Duration) { + o.timeout = timeout +} + +// WithContext adds the context to the create credentials params +func (o *CreateCredentialsParams) WithContext(ctx context.Context) *CreateCredentialsParams { + o.SetContext(ctx) + return o +} + +// SetContext adds the context to the create credentials params +func (o *CreateCredentialsParams) SetContext(ctx context.Context) { + o.Context = ctx +} + +// WithHTTPClient adds the HTTPClient to the create credentials params +func (o *CreateCredentialsParams) WithHTTPClient(client *http.Client) *CreateCredentialsParams { + o.SetHTTPClient(client) + return o +} + +// SetHTTPClient adds the HTTPClient to the create credentials params +func (o *CreateCredentialsParams) SetHTTPClient(client *http.Client) { + o.HTTPClient = client +} + +// WithBody adds the body to the create credentials params +func (o *CreateCredentialsParams) WithBody(body garm_params.CreateGithubCredentialsParams) *CreateCredentialsParams { + o.SetBody(body) + return o +} + +// SetBody adds the body to the create credentials params +func (o *CreateCredentialsParams) SetBody(body garm_params.CreateGithubCredentialsParams) { + o.Body = body +} + +// WriteToRequest writes these params to a swagger request +func (o *CreateCredentialsParams) WriteToRequest(r runtime.ClientRequest, reg strfmt.Registry) error { + + if err := r.SetTimeout(o.timeout); err != nil { + return err + } + var res []error + if err := r.SetBodyParam(o.Body); err != nil { + return err + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} diff --git a/client/credentials/create_credentials_responses.go b/client/credentials/create_credentials_responses.go new file mode 100644 index 00000000..1b6dbe94 --- /dev/null +++ b/client/credentials/create_credentials_responses.go @@ -0,0 +1,174 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package credentials + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "fmt" + "io" + + "github.com/go-openapi/runtime" + "github.com/go-openapi/strfmt" + + apiserver_params "github.com/cloudbase/garm/apiserver/params" + garm_params "github.com/cloudbase/garm/params" +) + +// CreateCredentialsReader is a Reader for the CreateCredentials structure. +type CreateCredentialsReader struct { + formats strfmt.Registry +} + +// ReadResponse reads a server response into the received o. +func (o *CreateCredentialsReader) ReadResponse(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) { + switch response.Code() { + case 200: + result := NewCreateCredentialsOK() + if err := result.readResponse(response, consumer, o.formats); err != nil { + return nil, err + } + return result, nil + case 400: + result := NewCreateCredentialsBadRequest() + if err := result.readResponse(response, consumer, o.formats); err != nil { + return nil, err + } + return nil, result + default: + return nil, runtime.NewAPIError("[POST /github/credentials] CreateCredentials", response, response.Code()) + } +} + +// NewCreateCredentialsOK creates a CreateCredentialsOK with default headers values +func NewCreateCredentialsOK() *CreateCredentialsOK { + return &CreateCredentialsOK{} +} + +/* +CreateCredentialsOK describes a response with status code 200, with default header values. + +GithubCredentials +*/ +type CreateCredentialsOK struct { + Payload garm_params.GithubCredentials +} + +// IsSuccess returns true when this create credentials o k response has a 2xx status code +func (o *CreateCredentialsOK) IsSuccess() bool { + return true +} + +// IsRedirect returns true when this create credentials o k response has a 3xx status code +func (o *CreateCredentialsOK) IsRedirect() bool { + return false +} + +// IsClientError returns true when this create credentials o k response has a 4xx status code +func (o *CreateCredentialsOK) IsClientError() bool { + return false +} + +// IsServerError returns true when this create credentials o k response has a 5xx status code +func (o *CreateCredentialsOK) IsServerError() bool { + return false +} + +// IsCode returns true when this create credentials o k response a status code equal to that given +func (o *CreateCredentialsOK) IsCode(code int) bool { + return code == 200 +} + +// Code gets the status code for the create credentials o k response +func (o *CreateCredentialsOK) Code() int { + return 200 +} + +func (o *CreateCredentialsOK) Error() string { + return fmt.Sprintf("[POST /github/credentials][%d] createCredentialsOK %+v", 200, o.Payload) +} + +func (o *CreateCredentialsOK) String() string { + return fmt.Sprintf("[POST /github/credentials][%d] createCredentialsOK %+v", 200, o.Payload) +} + +func (o *CreateCredentialsOK) GetPayload() garm_params.GithubCredentials { + return o.Payload +} + +func (o *CreateCredentialsOK) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error { + + // response payload + if err := consumer.Consume(response.Body(), &o.Payload); err != nil && err != io.EOF { + return err + } + + return nil +} + +// NewCreateCredentialsBadRequest creates a CreateCredentialsBadRequest with default headers values +func NewCreateCredentialsBadRequest() *CreateCredentialsBadRequest { + return &CreateCredentialsBadRequest{} +} + +/* +CreateCredentialsBadRequest describes a response with status code 400, with default header values. + +APIErrorResponse +*/ +type CreateCredentialsBadRequest struct { + Payload apiserver_params.APIErrorResponse +} + +// IsSuccess returns true when this create credentials bad request response has a 2xx status code +func (o *CreateCredentialsBadRequest) IsSuccess() bool { + return false +} + +// IsRedirect returns true when this create credentials bad request response has a 3xx status code +func (o *CreateCredentialsBadRequest) IsRedirect() bool { + return false +} + +// IsClientError returns true when this create credentials bad request response has a 4xx status code +func (o *CreateCredentialsBadRequest) IsClientError() bool { + return true +} + +// IsServerError returns true when this create credentials bad request response has a 5xx status code +func (o *CreateCredentialsBadRequest) IsServerError() bool { + return false +} + +// IsCode returns true when this create credentials bad request response a status code equal to that given +func (o *CreateCredentialsBadRequest) IsCode(code int) bool { + return code == 400 +} + +// Code gets the status code for the create credentials bad request response +func (o *CreateCredentialsBadRequest) Code() int { + return 400 +} + +func (o *CreateCredentialsBadRequest) Error() string { + return fmt.Sprintf("[POST /github/credentials][%d] createCredentialsBadRequest %+v", 400, o.Payload) +} + +func (o *CreateCredentialsBadRequest) String() string { + return fmt.Sprintf("[POST /github/credentials][%d] createCredentialsBadRequest %+v", 400, o.Payload) +} + +func (o *CreateCredentialsBadRequest) GetPayload() apiserver_params.APIErrorResponse { + return o.Payload +} + +func (o *CreateCredentialsBadRequest) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error { + + // response payload + if err := consumer.Consume(response.Body(), &o.Payload); err != nil && err != io.EOF { + return err + } + + return nil +} diff --git a/client/credentials/credentials_client.go b/client/credentials/credentials_client.go index 226b702d..9e19f1f3 100644 --- a/client/credentials/credentials_client.go +++ b/client/credentials/credentials_client.go @@ -30,11 +30,129 @@ type ClientOption func(*runtime.ClientOperation) // ClientService is the interface for Client methods type ClientService interface { + CreateCredentials(params *CreateCredentialsParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*CreateCredentialsOK, error) + + DeleteCredentials(params *DeleteCredentialsParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) error + + GetCredentials(params *GetCredentialsParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*GetCredentialsOK, error) + ListCredentials(params *ListCredentialsParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*ListCredentialsOK, error) + UpdateCredentials(params *UpdateCredentialsParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*UpdateCredentialsOK, error) + SetTransport(transport runtime.ClientTransport) } +/* +CreateCredentials creates a git hub credential +*/ +func (a *Client) CreateCredentials(params *CreateCredentialsParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*CreateCredentialsOK, error) { + // TODO: Validate the params before sending + if params == nil { + params = NewCreateCredentialsParams() + } + op := &runtime.ClientOperation{ + ID: "CreateCredentials", + Method: "POST", + PathPattern: "/github/credentials", + ProducesMediaTypes: []string{"application/json"}, + ConsumesMediaTypes: []string{"application/json"}, + Schemes: []string{"http"}, + Params: params, + Reader: &CreateCredentialsReader{formats: a.formats}, + AuthInfo: authInfo, + Context: params.Context, + Client: params.HTTPClient, + } + for _, opt := range opts { + opt(op) + } + + result, err := a.transport.Submit(op) + if err != nil { + return nil, err + } + success, ok := result.(*CreateCredentialsOK) + if ok { + return success, nil + } + // unexpected success response + // safeguard: normally, absent a default response, unknown success responses return an error above: so this is a codegen issue + msg := fmt.Sprintf("unexpected success response for CreateCredentials: API contract not enforced by server. Client expected to get an error, but got: %T", result) + panic(msg) +} + +/* +DeleteCredentials deletes a git hub credential +*/ +func (a *Client) DeleteCredentials(params *DeleteCredentialsParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) error { + // TODO: Validate the params before sending + if params == nil { + params = NewDeleteCredentialsParams() + } + op := &runtime.ClientOperation{ + ID: "DeleteCredentials", + Method: "DELETE", + PathPattern: "/github/credentials/{id}", + ProducesMediaTypes: []string{"application/json"}, + ConsumesMediaTypes: []string{"application/json"}, + Schemes: []string{"http"}, + Params: params, + Reader: &DeleteCredentialsReader{formats: a.formats}, + AuthInfo: authInfo, + Context: params.Context, + Client: params.HTTPClient, + } + for _, opt := range opts { + opt(op) + } + + _, err := a.transport.Submit(op) + if err != nil { + return err + } + return nil +} + +/* +GetCredentials gets a git hub credential +*/ +func (a *Client) GetCredentials(params *GetCredentialsParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*GetCredentialsOK, error) { + // TODO: Validate the params before sending + if params == nil { + params = NewGetCredentialsParams() + } + op := &runtime.ClientOperation{ + ID: "GetCredentials", + Method: "GET", + PathPattern: "/github/credentials/{id}", + ProducesMediaTypes: []string{"application/json"}, + ConsumesMediaTypes: []string{"application/json"}, + Schemes: []string{"http"}, + Params: params, + Reader: &GetCredentialsReader{formats: a.formats}, + AuthInfo: authInfo, + Context: params.Context, + Client: params.HTTPClient, + } + for _, opt := range opts { + opt(op) + } + + result, err := a.transport.Submit(op) + if err != nil { + return nil, err + } + success, ok := result.(*GetCredentialsOK) + if ok { + return success, nil + } + // unexpected success response + // safeguard: normally, absent a default response, unknown success responses return an error above: so this is a codegen issue + msg := fmt.Sprintf("unexpected success response for GetCredentials: API contract not enforced by server. Client expected to get an error, but got: %T", result) + panic(msg) +} + /* ListCredentials lists all credentials */ @@ -46,7 +164,7 @@ func (a *Client) ListCredentials(params *ListCredentialsParams, authInfo runtime op := &runtime.ClientOperation{ ID: "ListCredentials", Method: "GET", - PathPattern: "/credentials", + PathPattern: "/github/credentials", ProducesMediaTypes: []string{"application/json"}, ConsumesMediaTypes: []string{"application/json"}, Schemes: []string{"http"}, @@ -74,6 +192,45 @@ func (a *Client) ListCredentials(params *ListCredentialsParams, authInfo runtime panic(msg) } +/* +UpdateCredentials updates a git hub credential +*/ +func (a *Client) UpdateCredentials(params *UpdateCredentialsParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*UpdateCredentialsOK, error) { + // TODO: Validate the params before sending + if params == nil { + params = NewUpdateCredentialsParams() + } + op := &runtime.ClientOperation{ + ID: "UpdateCredentials", + Method: "PUT", + PathPattern: "/github/credentials/{id}", + ProducesMediaTypes: []string{"application/json"}, + ConsumesMediaTypes: []string{"application/json"}, + Schemes: []string{"http"}, + Params: params, + Reader: &UpdateCredentialsReader{formats: a.formats}, + AuthInfo: authInfo, + Context: params.Context, + Client: params.HTTPClient, + } + for _, opt := range opts { + opt(op) + } + + result, err := a.transport.Submit(op) + if err != nil { + return nil, err + } + success, ok := result.(*UpdateCredentialsOK) + if ok { + return success, nil + } + // unexpected success response + // safeguard: normally, absent a default response, unknown success responses return an error above: so this is a codegen issue + msg := fmt.Sprintf("unexpected success response for UpdateCredentials: API contract not enforced by server. Client expected to get an error, but got: %T", result) + panic(msg) +} + // SetTransport changes the transport on the client func (a *Client) SetTransport(transport runtime.ClientTransport) { a.transport = transport diff --git a/client/credentials/delete_credentials_parameters.go b/client/credentials/delete_credentials_parameters.go new file mode 100644 index 00000000..f36f8725 --- /dev/null +++ b/client/credentials/delete_credentials_parameters.go @@ -0,0 +1,152 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package credentials + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "context" + "net/http" + "time" + + "github.com/go-openapi/errors" + "github.com/go-openapi/runtime" + cr "github.com/go-openapi/runtime/client" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" +) + +// NewDeleteCredentialsParams creates a new DeleteCredentialsParams object, +// with the default timeout for this client. +// +// Default values are not hydrated, since defaults are normally applied by the API server side. +// +// To enforce default values in parameter, use SetDefaults or WithDefaults. +func NewDeleteCredentialsParams() *DeleteCredentialsParams { + return &DeleteCredentialsParams{ + timeout: cr.DefaultTimeout, + } +} + +// NewDeleteCredentialsParamsWithTimeout creates a new DeleteCredentialsParams object +// with the ability to set a timeout on a request. +func NewDeleteCredentialsParamsWithTimeout(timeout time.Duration) *DeleteCredentialsParams { + return &DeleteCredentialsParams{ + timeout: timeout, + } +} + +// NewDeleteCredentialsParamsWithContext creates a new DeleteCredentialsParams object +// with the ability to set a context for a request. +func NewDeleteCredentialsParamsWithContext(ctx context.Context) *DeleteCredentialsParams { + return &DeleteCredentialsParams{ + Context: ctx, + } +} + +// NewDeleteCredentialsParamsWithHTTPClient creates a new DeleteCredentialsParams object +// with the ability to set a custom HTTPClient for a request. +func NewDeleteCredentialsParamsWithHTTPClient(client *http.Client) *DeleteCredentialsParams { + return &DeleteCredentialsParams{ + HTTPClient: client, + } +} + +/* +DeleteCredentialsParams contains all the parameters to send to the API endpoint + + for the delete credentials operation. + + Typically these are written to a http.Request. +*/ +type DeleteCredentialsParams struct { + + /* ID. + + ID of the GitHub credential. + */ + ID int64 + + timeout time.Duration + Context context.Context + HTTPClient *http.Client +} + +// WithDefaults hydrates default values in the delete credentials params (not the query body). +// +// All values with no default are reset to their zero value. +func (o *DeleteCredentialsParams) WithDefaults() *DeleteCredentialsParams { + o.SetDefaults() + return o +} + +// SetDefaults hydrates default values in the delete credentials params (not the query body). +// +// All values with no default are reset to their zero value. +func (o *DeleteCredentialsParams) SetDefaults() { + // no default values defined for this parameter +} + +// WithTimeout adds the timeout to the delete credentials params +func (o *DeleteCredentialsParams) WithTimeout(timeout time.Duration) *DeleteCredentialsParams { + o.SetTimeout(timeout) + return o +} + +// SetTimeout adds the timeout to the delete credentials params +func (o *DeleteCredentialsParams) SetTimeout(timeout time.Duration) { + o.timeout = timeout +} + +// WithContext adds the context to the delete credentials params +func (o *DeleteCredentialsParams) WithContext(ctx context.Context) *DeleteCredentialsParams { + o.SetContext(ctx) + return o +} + +// SetContext adds the context to the delete credentials params +func (o *DeleteCredentialsParams) SetContext(ctx context.Context) { + o.Context = ctx +} + +// WithHTTPClient adds the HTTPClient to the delete credentials params +func (o *DeleteCredentialsParams) WithHTTPClient(client *http.Client) *DeleteCredentialsParams { + o.SetHTTPClient(client) + return o +} + +// SetHTTPClient adds the HTTPClient to the delete credentials params +func (o *DeleteCredentialsParams) SetHTTPClient(client *http.Client) { + o.HTTPClient = client +} + +// WithID adds the id to the delete credentials params +func (o *DeleteCredentialsParams) WithID(id int64) *DeleteCredentialsParams { + o.SetID(id) + return o +} + +// SetID adds the id to the delete credentials params +func (o *DeleteCredentialsParams) SetID(id int64) { + o.ID = id +} + +// WriteToRequest writes these params to a swagger request +func (o *DeleteCredentialsParams) WriteToRequest(r runtime.ClientRequest, reg strfmt.Registry) error { + + if err := r.SetTimeout(o.timeout); err != nil { + return err + } + var res []error + + // path param id + if err := r.SetPathParam("id", swag.FormatInt64(o.ID)); err != nil { + return err + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} diff --git a/client/credentials/delete_credentials_responses.go b/client/credentials/delete_credentials_responses.go new file mode 100644 index 00000000..a174c172 --- /dev/null +++ b/client/credentials/delete_credentials_responses.go @@ -0,0 +1,103 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package credentials + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "fmt" + "io" + + "github.com/go-openapi/runtime" + "github.com/go-openapi/strfmt" + + apiserver_params "github.com/cloudbase/garm/apiserver/params" +) + +// DeleteCredentialsReader is a Reader for the DeleteCredentials structure. +type DeleteCredentialsReader struct { + formats strfmt.Registry +} + +// ReadResponse reads a server response into the received o. +func (o *DeleteCredentialsReader) ReadResponse(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) { + result := NewDeleteCredentialsDefault(response.Code()) + if err := result.readResponse(response, consumer, o.formats); err != nil { + return nil, err + } + if response.Code()/100 == 2 { + return result, nil + } + return nil, result +} + +// NewDeleteCredentialsDefault creates a DeleteCredentialsDefault with default headers values +func NewDeleteCredentialsDefault(code int) *DeleteCredentialsDefault { + return &DeleteCredentialsDefault{ + _statusCode: code, + } +} + +/* +DeleteCredentialsDefault describes a response with status code -1, with default header values. + +APIErrorResponse +*/ +type DeleteCredentialsDefault struct { + _statusCode int + + Payload apiserver_params.APIErrorResponse +} + +// IsSuccess returns true when this delete credentials default response has a 2xx status code +func (o *DeleteCredentialsDefault) IsSuccess() bool { + return o._statusCode/100 == 2 +} + +// IsRedirect returns true when this delete credentials default response has a 3xx status code +func (o *DeleteCredentialsDefault) IsRedirect() bool { + return o._statusCode/100 == 3 +} + +// IsClientError returns true when this delete credentials default response has a 4xx status code +func (o *DeleteCredentialsDefault) IsClientError() bool { + return o._statusCode/100 == 4 +} + +// IsServerError returns true when this delete credentials default response has a 5xx status code +func (o *DeleteCredentialsDefault) IsServerError() bool { + return o._statusCode/100 == 5 +} + +// IsCode returns true when this delete credentials default response a status code equal to that given +func (o *DeleteCredentialsDefault) IsCode(code int) bool { + return o._statusCode == code +} + +// Code gets the status code for the delete credentials default response +func (o *DeleteCredentialsDefault) Code() int { + return o._statusCode +} + +func (o *DeleteCredentialsDefault) Error() string { + return fmt.Sprintf("[DELETE /github/credentials/{id}][%d] DeleteCredentials default %+v", o._statusCode, o.Payload) +} + +func (o *DeleteCredentialsDefault) String() string { + return fmt.Sprintf("[DELETE /github/credentials/{id}][%d] DeleteCredentials default %+v", o._statusCode, o.Payload) +} + +func (o *DeleteCredentialsDefault) GetPayload() apiserver_params.APIErrorResponse { + return o.Payload +} + +func (o *DeleteCredentialsDefault) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error { + + // response payload + if err := consumer.Consume(response.Body(), &o.Payload); err != nil && err != io.EOF { + return err + } + + return nil +} diff --git a/client/credentials/get_credentials_parameters.go b/client/credentials/get_credentials_parameters.go new file mode 100644 index 00000000..ff8305e8 --- /dev/null +++ b/client/credentials/get_credentials_parameters.go @@ -0,0 +1,152 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package credentials + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "context" + "net/http" + "time" + + "github.com/go-openapi/errors" + "github.com/go-openapi/runtime" + cr "github.com/go-openapi/runtime/client" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" +) + +// NewGetCredentialsParams creates a new GetCredentialsParams object, +// with the default timeout for this client. +// +// Default values are not hydrated, since defaults are normally applied by the API server side. +// +// To enforce default values in parameter, use SetDefaults or WithDefaults. +func NewGetCredentialsParams() *GetCredentialsParams { + return &GetCredentialsParams{ + timeout: cr.DefaultTimeout, + } +} + +// NewGetCredentialsParamsWithTimeout creates a new GetCredentialsParams object +// with the ability to set a timeout on a request. +func NewGetCredentialsParamsWithTimeout(timeout time.Duration) *GetCredentialsParams { + return &GetCredentialsParams{ + timeout: timeout, + } +} + +// NewGetCredentialsParamsWithContext creates a new GetCredentialsParams object +// with the ability to set a context for a request. +func NewGetCredentialsParamsWithContext(ctx context.Context) *GetCredentialsParams { + return &GetCredentialsParams{ + Context: ctx, + } +} + +// NewGetCredentialsParamsWithHTTPClient creates a new GetCredentialsParams object +// with the ability to set a custom HTTPClient for a request. +func NewGetCredentialsParamsWithHTTPClient(client *http.Client) *GetCredentialsParams { + return &GetCredentialsParams{ + HTTPClient: client, + } +} + +/* +GetCredentialsParams contains all the parameters to send to the API endpoint + + for the get credentials operation. + + Typically these are written to a http.Request. +*/ +type GetCredentialsParams struct { + + /* ID. + + ID of the GitHub credential. + */ + ID int64 + + timeout time.Duration + Context context.Context + HTTPClient *http.Client +} + +// WithDefaults hydrates default values in the get credentials params (not the query body). +// +// All values with no default are reset to their zero value. +func (o *GetCredentialsParams) WithDefaults() *GetCredentialsParams { + o.SetDefaults() + return o +} + +// SetDefaults hydrates default values in the get credentials params (not the query body). +// +// All values with no default are reset to their zero value. +func (o *GetCredentialsParams) SetDefaults() { + // no default values defined for this parameter +} + +// WithTimeout adds the timeout to the get credentials params +func (o *GetCredentialsParams) WithTimeout(timeout time.Duration) *GetCredentialsParams { + o.SetTimeout(timeout) + return o +} + +// SetTimeout adds the timeout to the get credentials params +func (o *GetCredentialsParams) SetTimeout(timeout time.Duration) { + o.timeout = timeout +} + +// WithContext adds the context to the get credentials params +func (o *GetCredentialsParams) WithContext(ctx context.Context) *GetCredentialsParams { + o.SetContext(ctx) + return o +} + +// SetContext adds the context to the get credentials params +func (o *GetCredentialsParams) SetContext(ctx context.Context) { + o.Context = ctx +} + +// WithHTTPClient adds the HTTPClient to the get credentials params +func (o *GetCredentialsParams) WithHTTPClient(client *http.Client) *GetCredentialsParams { + o.SetHTTPClient(client) + return o +} + +// SetHTTPClient adds the HTTPClient to the get credentials params +func (o *GetCredentialsParams) SetHTTPClient(client *http.Client) { + o.HTTPClient = client +} + +// WithID adds the id to the get credentials params +func (o *GetCredentialsParams) WithID(id int64) *GetCredentialsParams { + o.SetID(id) + return o +} + +// SetID adds the id to the get credentials params +func (o *GetCredentialsParams) SetID(id int64) { + o.ID = id +} + +// WriteToRequest writes these params to a swagger request +func (o *GetCredentialsParams) WriteToRequest(r runtime.ClientRequest, reg strfmt.Registry) error { + + if err := r.SetTimeout(o.timeout); err != nil { + return err + } + var res []error + + // path param id + if err := r.SetPathParam("id", swag.FormatInt64(o.ID)); err != nil { + return err + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} diff --git a/client/credentials/get_credentials_responses.go b/client/credentials/get_credentials_responses.go new file mode 100644 index 00000000..ef2d041d --- /dev/null +++ b/client/credentials/get_credentials_responses.go @@ -0,0 +1,174 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package credentials + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "fmt" + "io" + + "github.com/go-openapi/runtime" + "github.com/go-openapi/strfmt" + + apiserver_params "github.com/cloudbase/garm/apiserver/params" + garm_params "github.com/cloudbase/garm/params" +) + +// GetCredentialsReader is a Reader for the GetCredentials structure. +type GetCredentialsReader struct { + formats strfmt.Registry +} + +// ReadResponse reads a server response into the received o. +func (o *GetCredentialsReader) ReadResponse(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) { + switch response.Code() { + case 200: + result := NewGetCredentialsOK() + if err := result.readResponse(response, consumer, o.formats); err != nil { + return nil, err + } + return result, nil + case 400: + result := NewGetCredentialsBadRequest() + if err := result.readResponse(response, consumer, o.formats); err != nil { + return nil, err + } + return nil, result + default: + return nil, runtime.NewAPIError("[GET /github/credentials/{id}] GetCredentials", response, response.Code()) + } +} + +// NewGetCredentialsOK creates a GetCredentialsOK with default headers values +func NewGetCredentialsOK() *GetCredentialsOK { + return &GetCredentialsOK{} +} + +/* +GetCredentialsOK describes a response with status code 200, with default header values. + +GithubCredentials +*/ +type GetCredentialsOK struct { + Payload garm_params.GithubCredentials +} + +// IsSuccess returns true when this get credentials o k response has a 2xx status code +func (o *GetCredentialsOK) IsSuccess() bool { + return true +} + +// IsRedirect returns true when this get credentials o k response has a 3xx status code +func (o *GetCredentialsOK) IsRedirect() bool { + return false +} + +// IsClientError returns true when this get credentials o k response has a 4xx status code +func (o *GetCredentialsOK) IsClientError() bool { + return false +} + +// IsServerError returns true when this get credentials o k response has a 5xx status code +func (o *GetCredentialsOK) IsServerError() bool { + return false +} + +// IsCode returns true when this get credentials o k response a status code equal to that given +func (o *GetCredentialsOK) IsCode(code int) bool { + return code == 200 +} + +// Code gets the status code for the get credentials o k response +func (o *GetCredentialsOK) Code() int { + return 200 +} + +func (o *GetCredentialsOK) Error() string { + return fmt.Sprintf("[GET /github/credentials/{id}][%d] getCredentialsOK %+v", 200, o.Payload) +} + +func (o *GetCredentialsOK) String() string { + return fmt.Sprintf("[GET /github/credentials/{id}][%d] getCredentialsOK %+v", 200, o.Payload) +} + +func (o *GetCredentialsOK) GetPayload() garm_params.GithubCredentials { + return o.Payload +} + +func (o *GetCredentialsOK) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error { + + // response payload + if err := consumer.Consume(response.Body(), &o.Payload); err != nil && err != io.EOF { + return err + } + + return nil +} + +// NewGetCredentialsBadRequest creates a GetCredentialsBadRequest with default headers values +func NewGetCredentialsBadRequest() *GetCredentialsBadRequest { + return &GetCredentialsBadRequest{} +} + +/* +GetCredentialsBadRequest describes a response with status code 400, with default header values. + +APIErrorResponse +*/ +type GetCredentialsBadRequest struct { + Payload apiserver_params.APIErrorResponse +} + +// IsSuccess returns true when this get credentials bad request response has a 2xx status code +func (o *GetCredentialsBadRequest) IsSuccess() bool { + return false +} + +// IsRedirect returns true when this get credentials bad request response has a 3xx status code +func (o *GetCredentialsBadRequest) IsRedirect() bool { + return false +} + +// IsClientError returns true when this get credentials bad request response has a 4xx status code +func (o *GetCredentialsBadRequest) IsClientError() bool { + return true +} + +// IsServerError returns true when this get credentials bad request response has a 5xx status code +func (o *GetCredentialsBadRequest) IsServerError() bool { + return false +} + +// IsCode returns true when this get credentials bad request response a status code equal to that given +func (o *GetCredentialsBadRequest) IsCode(code int) bool { + return code == 400 +} + +// Code gets the status code for the get credentials bad request response +func (o *GetCredentialsBadRequest) Code() int { + return 400 +} + +func (o *GetCredentialsBadRequest) Error() string { + return fmt.Sprintf("[GET /github/credentials/{id}][%d] getCredentialsBadRequest %+v", 400, o.Payload) +} + +func (o *GetCredentialsBadRequest) String() string { + return fmt.Sprintf("[GET /github/credentials/{id}][%d] getCredentialsBadRequest %+v", 400, o.Payload) +} + +func (o *GetCredentialsBadRequest) GetPayload() apiserver_params.APIErrorResponse { + return o.Payload +} + +func (o *GetCredentialsBadRequest) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error { + + // response payload + if err := consumer.Consume(response.Body(), &o.Payload); err != nil && err != io.EOF { + return err + } + + return nil +} diff --git a/client/credentials/list_credentials_responses.go b/client/credentials/list_credentials_responses.go index 2d4c2f9a..ac763e44 100644 --- a/client/credentials/list_credentials_responses.go +++ b/client/credentials/list_credentials_responses.go @@ -37,7 +37,7 @@ func (o *ListCredentialsReader) ReadResponse(response runtime.ClientResponse, co } return nil, result default: - return nil, runtime.NewAPIError("[GET /credentials] ListCredentials", response, response.Code()) + return nil, runtime.NewAPIError("[GET /github/credentials] ListCredentials", response, response.Code()) } } @@ -86,11 +86,11 @@ func (o *ListCredentialsOK) Code() int { } func (o *ListCredentialsOK) Error() string { - return fmt.Sprintf("[GET /credentials][%d] listCredentialsOK %+v", 200, o.Payload) + return fmt.Sprintf("[GET /github/credentials][%d] listCredentialsOK %+v", 200, o.Payload) } func (o *ListCredentialsOK) String() string { - return fmt.Sprintf("[GET /credentials][%d] listCredentialsOK %+v", 200, o.Payload) + return fmt.Sprintf("[GET /github/credentials][%d] listCredentialsOK %+v", 200, o.Payload) } func (o *ListCredentialsOK) GetPayload() garm_params.Credentials { @@ -152,11 +152,11 @@ func (o *ListCredentialsBadRequest) Code() int { } func (o *ListCredentialsBadRequest) Error() string { - return fmt.Sprintf("[GET /credentials][%d] listCredentialsBadRequest %+v", 400, o.Payload) + return fmt.Sprintf("[GET /github/credentials][%d] listCredentialsBadRequest %+v", 400, o.Payload) } func (o *ListCredentialsBadRequest) String() string { - return fmt.Sprintf("[GET /credentials][%d] listCredentialsBadRequest %+v", 400, o.Payload) + return fmt.Sprintf("[GET /github/credentials][%d] listCredentialsBadRequest %+v", 400, o.Payload) } func (o *ListCredentialsBadRequest) GetPayload() apiserver_params.APIErrorResponse { diff --git a/client/credentials/update_credentials_parameters.go b/client/credentials/update_credentials_parameters.go new file mode 100644 index 00000000..bba26c95 --- /dev/null +++ b/client/credentials/update_credentials_parameters.go @@ -0,0 +1,174 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package credentials + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "context" + "net/http" + "time" + + "github.com/go-openapi/errors" + "github.com/go-openapi/runtime" + cr "github.com/go-openapi/runtime/client" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" + + garm_params "github.com/cloudbase/garm/params" +) + +// NewUpdateCredentialsParams creates a new UpdateCredentialsParams object, +// with the default timeout for this client. +// +// Default values are not hydrated, since defaults are normally applied by the API server side. +// +// To enforce default values in parameter, use SetDefaults or WithDefaults. +func NewUpdateCredentialsParams() *UpdateCredentialsParams { + return &UpdateCredentialsParams{ + timeout: cr.DefaultTimeout, + } +} + +// NewUpdateCredentialsParamsWithTimeout creates a new UpdateCredentialsParams object +// with the ability to set a timeout on a request. +func NewUpdateCredentialsParamsWithTimeout(timeout time.Duration) *UpdateCredentialsParams { + return &UpdateCredentialsParams{ + timeout: timeout, + } +} + +// NewUpdateCredentialsParamsWithContext creates a new UpdateCredentialsParams object +// with the ability to set a context for a request. +func NewUpdateCredentialsParamsWithContext(ctx context.Context) *UpdateCredentialsParams { + return &UpdateCredentialsParams{ + Context: ctx, + } +} + +// NewUpdateCredentialsParamsWithHTTPClient creates a new UpdateCredentialsParams object +// with the ability to set a custom HTTPClient for a request. +func NewUpdateCredentialsParamsWithHTTPClient(client *http.Client) *UpdateCredentialsParams { + return &UpdateCredentialsParams{ + HTTPClient: client, + } +} + +/* +UpdateCredentialsParams contains all the parameters to send to the API endpoint + + for the update credentials operation. + + Typically these are written to a http.Request. +*/ +type UpdateCredentialsParams struct { + + /* Body. + + Parameters used when updating a GitHub credential. + */ + Body garm_params.UpdateGithubCredentialsParams + + /* ID. + + ID of the GitHub credential. + */ + ID int64 + + timeout time.Duration + Context context.Context + HTTPClient *http.Client +} + +// WithDefaults hydrates default values in the update credentials params (not the query body). +// +// All values with no default are reset to their zero value. +func (o *UpdateCredentialsParams) WithDefaults() *UpdateCredentialsParams { + o.SetDefaults() + return o +} + +// SetDefaults hydrates default values in the update credentials params (not the query body). +// +// All values with no default are reset to their zero value. +func (o *UpdateCredentialsParams) SetDefaults() { + // no default values defined for this parameter +} + +// WithTimeout adds the timeout to the update credentials params +func (o *UpdateCredentialsParams) WithTimeout(timeout time.Duration) *UpdateCredentialsParams { + o.SetTimeout(timeout) + return o +} + +// SetTimeout adds the timeout to the update credentials params +func (o *UpdateCredentialsParams) SetTimeout(timeout time.Duration) { + o.timeout = timeout +} + +// WithContext adds the context to the update credentials params +func (o *UpdateCredentialsParams) WithContext(ctx context.Context) *UpdateCredentialsParams { + o.SetContext(ctx) + return o +} + +// SetContext adds the context to the update credentials params +func (o *UpdateCredentialsParams) SetContext(ctx context.Context) { + o.Context = ctx +} + +// WithHTTPClient adds the HTTPClient to the update credentials params +func (o *UpdateCredentialsParams) WithHTTPClient(client *http.Client) *UpdateCredentialsParams { + o.SetHTTPClient(client) + return o +} + +// SetHTTPClient adds the HTTPClient to the update credentials params +func (o *UpdateCredentialsParams) SetHTTPClient(client *http.Client) { + o.HTTPClient = client +} + +// WithBody adds the body to the update credentials params +func (o *UpdateCredentialsParams) WithBody(body garm_params.UpdateGithubCredentialsParams) *UpdateCredentialsParams { + o.SetBody(body) + return o +} + +// SetBody adds the body to the update credentials params +func (o *UpdateCredentialsParams) SetBody(body garm_params.UpdateGithubCredentialsParams) { + o.Body = body +} + +// WithID adds the id to the update credentials params +func (o *UpdateCredentialsParams) WithID(id int64) *UpdateCredentialsParams { + o.SetID(id) + return o +} + +// SetID adds the id to the update credentials params +func (o *UpdateCredentialsParams) SetID(id int64) { + o.ID = id +} + +// WriteToRequest writes these params to a swagger request +func (o *UpdateCredentialsParams) WriteToRequest(r runtime.ClientRequest, reg strfmt.Registry) error { + + if err := r.SetTimeout(o.timeout); err != nil { + return err + } + var res []error + if err := r.SetBodyParam(o.Body); err != nil { + return err + } + + // path param id + if err := r.SetPathParam("id", swag.FormatInt64(o.ID)); err != nil { + return err + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} diff --git a/client/credentials/update_credentials_responses.go b/client/credentials/update_credentials_responses.go new file mode 100644 index 00000000..1d1d98cd --- /dev/null +++ b/client/credentials/update_credentials_responses.go @@ -0,0 +1,174 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package credentials + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "fmt" + "io" + + "github.com/go-openapi/runtime" + "github.com/go-openapi/strfmt" + + apiserver_params "github.com/cloudbase/garm/apiserver/params" + garm_params "github.com/cloudbase/garm/params" +) + +// UpdateCredentialsReader is a Reader for the UpdateCredentials structure. +type UpdateCredentialsReader struct { + formats strfmt.Registry +} + +// ReadResponse reads a server response into the received o. +func (o *UpdateCredentialsReader) ReadResponse(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) { + switch response.Code() { + case 200: + result := NewUpdateCredentialsOK() + if err := result.readResponse(response, consumer, o.formats); err != nil { + return nil, err + } + return result, nil + case 400: + result := NewUpdateCredentialsBadRequest() + if err := result.readResponse(response, consumer, o.formats); err != nil { + return nil, err + } + return nil, result + default: + return nil, runtime.NewAPIError("[PUT /github/credentials/{id}] UpdateCredentials", response, response.Code()) + } +} + +// NewUpdateCredentialsOK creates a UpdateCredentialsOK with default headers values +func NewUpdateCredentialsOK() *UpdateCredentialsOK { + return &UpdateCredentialsOK{} +} + +/* +UpdateCredentialsOK describes a response with status code 200, with default header values. + +GithubCredentials +*/ +type UpdateCredentialsOK struct { + Payload garm_params.GithubCredentials +} + +// IsSuccess returns true when this update credentials o k response has a 2xx status code +func (o *UpdateCredentialsOK) IsSuccess() bool { + return true +} + +// IsRedirect returns true when this update credentials o k response has a 3xx status code +func (o *UpdateCredentialsOK) IsRedirect() bool { + return false +} + +// IsClientError returns true when this update credentials o k response has a 4xx status code +func (o *UpdateCredentialsOK) IsClientError() bool { + return false +} + +// IsServerError returns true when this update credentials o k response has a 5xx status code +func (o *UpdateCredentialsOK) IsServerError() bool { + return false +} + +// IsCode returns true when this update credentials o k response a status code equal to that given +func (o *UpdateCredentialsOK) IsCode(code int) bool { + return code == 200 +} + +// Code gets the status code for the update credentials o k response +func (o *UpdateCredentialsOK) Code() int { + return 200 +} + +func (o *UpdateCredentialsOK) Error() string { + return fmt.Sprintf("[PUT /github/credentials/{id}][%d] updateCredentialsOK %+v", 200, o.Payload) +} + +func (o *UpdateCredentialsOK) String() string { + return fmt.Sprintf("[PUT /github/credentials/{id}][%d] updateCredentialsOK %+v", 200, o.Payload) +} + +func (o *UpdateCredentialsOK) GetPayload() garm_params.GithubCredentials { + return o.Payload +} + +func (o *UpdateCredentialsOK) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error { + + // response payload + if err := consumer.Consume(response.Body(), &o.Payload); err != nil && err != io.EOF { + return err + } + + return nil +} + +// NewUpdateCredentialsBadRequest creates a UpdateCredentialsBadRequest with default headers values +func NewUpdateCredentialsBadRequest() *UpdateCredentialsBadRequest { + return &UpdateCredentialsBadRequest{} +} + +/* +UpdateCredentialsBadRequest describes a response with status code 400, with default header values. + +APIErrorResponse +*/ +type UpdateCredentialsBadRequest struct { + Payload apiserver_params.APIErrorResponse +} + +// IsSuccess returns true when this update credentials bad request response has a 2xx status code +func (o *UpdateCredentialsBadRequest) IsSuccess() bool { + return false +} + +// IsRedirect returns true when this update credentials bad request response has a 3xx status code +func (o *UpdateCredentialsBadRequest) IsRedirect() bool { + return false +} + +// IsClientError returns true when this update credentials bad request response has a 4xx status code +func (o *UpdateCredentialsBadRequest) IsClientError() bool { + return true +} + +// IsServerError returns true when this update credentials bad request response has a 5xx status code +func (o *UpdateCredentialsBadRequest) IsServerError() bool { + return false +} + +// IsCode returns true when this update credentials bad request response a status code equal to that given +func (o *UpdateCredentialsBadRequest) IsCode(code int) bool { + return code == 400 +} + +// Code gets the status code for the update credentials bad request response +func (o *UpdateCredentialsBadRequest) Code() int { + return 400 +} + +func (o *UpdateCredentialsBadRequest) Error() string { + return fmt.Sprintf("[PUT /github/credentials/{id}][%d] updateCredentialsBadRequest %+v", 400, o.Payload) +} + +func (o *UpdateCredentialsBadRequest) String() string { + return fmt.Sprintf("[PUT /github/credentials/{id}][%d] updateCredentialsBadRequest %+v", 400, o.Payload) +} + +func (o *UpdateCredentialsBadRequest) GetPayload() apiserver_params.APIErrorResponse { + return o.Payload +} + +func (o *UpdateCredentialsBadRequest) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error { + + // response payload + if err := consumer.Consume(response.Body(), &o.Payload); err != nil && err != io.EOF { + return err + } + + return nil +} diff --git a/cmd/garm-cli/cmd/credentials.go b/cmd/garm-cli/cmd/credentials.go deleted file mode 100644 index e5ed7b5a..00000000 --- a/cmd/garm-cli/cmd/credentials.go +++ /dev/null @@ -1,76 +0,0 @@ -// Copyright 2022 Cloudbase Solutions SRL -// -// Licensed under the Apache License, Version 2.0 (the "License"); you may -// not use this file except in compliance with the License. You may obtain -// a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations -// under the License. - -package cmd - -import ( - "fmt" - - "github.com/jedib0t/go-pretty/v6/table" - "github.com/spf13/cobra" - - apiClientCreds "github.com/cloudbase/garm/client/credentials" - "github.com/cloudbase/garm/params" -) - -// credentialsCmd represents the credentials command -var credentialsCmd = &cobra.Command{ - Use: "credentials", - Aliases: []string{"creds"}, - Short: "List configured credentials", - Long: `List all available credentials configured in the service -config file. - -Currently, github personal tokens are configured statically in the config file -of the garm service. This command lists the names of those credentials, -which in turn can be used to define pools of runners within repositories.`, - Run: nil, -} - -func init() { - credentialsCmd.AddCommand( - &cobra.Command{ - Use: "list", - Aliases: []string{"ls"}, - Short: "List configured github credentials", - Long: `List the names of the github personal access tokens available to the garm.`, - SilenceUsage: true, - RunE: func(_ *cobra.Command, _ []string) error { - if needsInit { - return errNeedsInitError - } - - listCredsReq := apiClientCreds.NewListCredentialsParams() - response, err := apiCli.Credentials.ListCredentials(listCredsReq, authToken) - if err != nil { - return err - } - formatGithubCredentials(response.Payload) - return nil - }, - }) - - rootCmd.AddCommand(credentialsCmd) -} - -func formatGithubCredentials(creds []params.GithubCredentials) { - t := table.NewWriter() - header := table.Row{"Name", "Description", "Base URL", "API URL", "Upload URL", "Type"} - t.AppendHeader(header) - for _, val := range creds { - t.AppendRow(table.Row{val.Name, val.Description, val.BaseURL, val.APIBaseURL, val.UploadBaseURL, val.AuthType}) - t.AppendSeparator() - } - fmt.Println(t.Render()) -} diff --git a/cmd/garm-cli/cmd/github_credentials.go b/cmd/garm-cli/cmd/github_credentials.go new file mode 100644 index 00000000..d328f5ee --- /dev/null +++ b/cmd/garm-cli/cmd/github_credentials.go @@ -0,0 +1,388 @@ +// Copyright 2022 Cloudbase Solutions SRL +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations +// under the License. + +package cmd + +import ( + "crypto/x509" + "encoding/pem" + "fmt" + "os" + "strconv" + + "github.com/jedib0t/go-pretty/v6/table" + "github.com/spf13/cobra" + + apiClientCreds "github.com/cloudbase/garm/client/credentials" + "github.com/cloudbase/garm/params" +) + +var ( + credentialsName string + credentialsDescription string + credentialsOAuthToken string + credentialsAppInstallationID int64 + credentialsAppID int64 + credentialsPrivateKeyPath string + credentialsType string + credentialsEndpoint string +) + +// credentialsCmd represents the credentials command +var credentialsCmd = &cobra.Command{ + Use: "credentials", + Aliases: []string{"creds"}, + Short: "List configured credentials", + Long: `List all available github credentials. + +This command is an alias for the garm-cli github credentials command.`, + Run: nil, +} + +// githubCredentialsCmd represents the github credentials command +var githubCredentialsCmd = &cobra.Command{ + Use: "credentials", + Aliases: []string{"creds"}, + Short: "Manage github credentials", + Long: `Manage GitHub credentials stored in GARM. + +This command allows you to add, update, list and delete GitHub credentials.`, + Run: nil, +} + +var githubCredentialsListCmd = &cobra.Command{ + Use: "list", + Aliases: []string{"ls"}, + Short: "List configured github credentials", + Long: `List the names of the github personal access tokens available to the garm.`, + SilenceUsage: true, + RunE: func(_ *cobra.Command, _ []string) error { + if needsInit { + return errNeedsInitError + } + + listCredsReq := apiClientCreds.NewListCredentialsParams() + response, err := apiCli.Credentials.ListCredentials(listCredsReq, authToken) + if err != nil { + return err + } + formatGithubCredentials(response.Payload) + return nil + }, +} + +var githubCredentialsShowCmd = &cobra.Command{ + Use: "show", + Aliases: []string{"get"}, + Short: "Show details of a configured github credential", + Long: `Show the details of a configured github credential.`, + SilenceUsage: true, + RunE: func(_ *cobra.Command, args []string) error { + if needsInit { + return errNeedsInitError + } + + if len(args) < 1 { + return fmt.Errorf("missing required argument: credential ID") + } + + credID, err := strconv.ParseInt(args[0], 10, 64) + if err != nil { + return fmt.Errorf("invalid credential ID: %s", args[0]) + } + showCredsReq := apiClientCreds.NewGetCredentialsParams().WithID(credID) + response, err := apiCli.Credentials.GetCredentials(showCredsReq, authToken) + if err != nil { + return err + } + formatOneGithubCredential(response.Payload) + return nil + }, +} + +var githubCredentialsUpdateCmd = &cobra.Command{ + Use: "update", + Short: "Update a github credential", + Long: "Update a github credential", + SilenceUsage: true, + RunE: func(_ *cobra.Command, args []string) error { + if needsInit { + return errNeedsInitError + } + + if len(args) < 1 { + return fmt.Errorf("missing required argument: credential ID") + } + + if len(args) > 1 { + return fmt.Errorf("too many arguments") + } + + credID, err := strconv.ParseInt(args[0], 10, 64) + if err != nil { + return fmt.Errorf("invalid credential ID: %s", args[0]) + } + + updateParams, err := parseCredentialsUpdateParams() + if err != nil { + return err + } + + updateCredsReq := apiClientCreds.NewUpdateCredentialsParams().WithID(credID) + updateCredsReq.Body = updateParams + + response, err := apiCli.Credentials.UpdateCredentials(updateCredsReq, authToken) + if err != nil { + return err + } + formatOneGithubCredential(response.Payload) + return nil + }, +} + +var githubCredentialsDeleteCmd = &cobra.Command{ + Use: "delete", + Aliases: []string{"remove", "rm"}, + Short: "Delete a github credential", + Long: "Delete a github credential", + SilenceUsage: true, + RunE: func(_ *cobra.Command, args []string) error { + if needsInit { + return errNeedsInitError + } + + if len(args) < 1 { + return fmt.Errorf("missing required argument: credential ID") + } + + if len(args) > 1 { + return fmt.Errorf("too many arguments") + } + + credID, err := strconv.ParseInt(args[0], 10, 64) + if err != nil { + return fmt.Errorf("invalid credential ID: %s", args[0]) + } + + deleteCredsReq := apiClientCreds.NewDeleteCredentialsParams().WithID(credID) + if err := apiCli.Credentials.DeleteCredentials(deleteCredsReq, authToken); err != nil { + return err + } + return nil + }, +} + +var githubCredentialsAddCmd = &cobra.Command{ + Use: "add", + Short: "Add a github credential", + Long: "Add a github credential", + SilenceUsage: true, + RunE: func(_ *cobra.Command, args []string) error { + if needsInit { + return errNeedsInitError + } + + if len(args) > 0 { + return fmt.Errorf("too many arguments") + } + + addParams, err := parseCredentialsAddParams() + if err != nil { + return err + } + + addCredsReq := apiClientCreds.NewCreateCredentialsParams() + addCredsReq.Body = addParams + + response, err := apiCli.Credentials.CreateCredentials(addCredsReq, authToken) + if err != nil { + return err + } + formatOneGithubCredential(response.Payload) + return nil + }, +} + +func init() { + githubCredentialsUpdateCmd.Flags().StringVar(&credentialsName, "name", "", "Name of the credential") + githubCredentialsUpdateCmd.Flags().StringVar(&credentialsDescription, "description", "", "Description of the credential") + githubCredentialsUpdateCmd.Flags().StringVar(&credentialsOAuthToken, "pat-oauth-token", "", "If the credential is a personal access token, the OAuth token") + githubCredentialsUpdateCmd.Flags().Int64Var(&credentialsAppInstallationID, "app-installation-id", 0, "If the credential is an app, the installation ID") + githubCredentialsUpdateCmd.Flags().Int64Var(&credentialsAppID, "app-id", 0, "If the credential is an app, the app ID") + githubCredentialsUpdateCmd.Flags().StringVar(&credentialsPrivateKeyPath, "private-key-path", "", "If the credential is an app, the path to the private key file") + + githubCredentialsUpdateCmd.MarkFlagsMutuallyExclusive("pat-oauth-token", "app-installation-id") + githubCredentialsUpdateCmd.MarkFlagsMutuallyExclusive("pat-oauth-token", "app-id") + githubCredentialsUpdateCmd.MarkFlagsMutuallyExclusive("pat-oauth-token", "private-key-path") + githubCredentialsUpdateCmd.MarkFlagsRequiredTogether("app-installation-id", "app-id", "private-key-path") + + githubCredentialsAddCmd.Flags().StringVar(&credentialsName, "name", "", "Name of the credential") + githubCredentialsAddCmd.Flags().StringVar(&credentialsDescription, "description", "", "Description of the credential") + githubCredentialsAddCmd.Flags().StringVar(&credentialsOAuthToken, "pat-oauth-token", "", "If the credential is a personal access token, the OAuth token") + githubCredentialsAddCmd.Flags().Int64Var(&credentialsAppInstallationID, "app-installation-id", 0, "If the credential is an app, the installation ID") + githubCredentialsAddCmd.Flags().Int64Var(&credentialsAppID, "app-id", 0, "If the credential is an app, the app ID") + githubCredentialsAddCmd.Flags().StringVar(&credentialsPrivateKeyPath, "private-key-path", "", "If the credential is an app, the path to the private key file") + githubCredentialsAddCmd.Flags().StringVar(&credentialsType, "auth-type", "", "The type of the credential") + githubCredentialsAddCmd.Flags().StringVar(&credentialsEndpoint, "endpoint", "", "The endpoint to associate the credential with") + + githubCredentialsAddCmd.MarkFlagsMutuallyExclusive("pat-oauth-token", "app-installation-id") + githubCredentialsAddCmd.MarkFlagsMutuallyExclusive("pat-oauth-token", "app-id") + githubCredentialsAddCmd.MarkFlagsMutuallyExclusive("pat-oauth-token", "private-key-path") + githubCredentialsAddCmd.MarkFlagsRequiredTogether("app-installation-id", "app-id", "private-key-path") + + githubCredentialsAddCmd.MarkFlagRequired("name") + githubCredentialsAddCmd.MarkFlagRequired("auth-type") + githubCredentialsAddCmd.MarkFlagRequired("description") + githubCredentialsAddCmd.MarkFlagRequired("endpoint") + + githubCredentialsCmd.AddCommand( + githubCredentialsListCmd, + githubCredentialsShowCmd, + githubCredentialsUpdateCmd, + githubCredentialsDeleteCmd, + githubCredentialsAddCmd, + ) + githubCmd.AddCommand(githubCredentialsCmd) + + credentialsCmd.AddCommand(githubCredentialsListCmd) + rootCmd.AddCommand(credentialsCmd) +} + +func parsePrivateKeyFromPath(path string) ([]byte, error) { + if _, err := os.Stat(path); err != nil { + return nil, fmt.Errorf("private key file not found: %s", credentialsPrivateKeyPath) + } + keyContents, err := os.ReadFile(path) + if err != nil { + return nil, fmt.Errorf("failed to read private key file: %w", err) + } + pemBlock, _ := pem.Decode(keyContents) + if pemBlock == nil { + return nil, fmt.Errorf("failed to decode PEM block") + } + if _, err := x509.ParsePKCS1PrivateKey(pemBlock.Bytes); err != nil { + return nil, fmt.Errorf("failed to parse private key: %w", err) + } + return keyContents, nil +} + +func parseCredentialsAddParams() (ret params.CreateGithubCredentialsParams, err error) { + ret.Name = credentialsName + ret.Description = credentialsDescription + ret.AuthType = params.GithubAuthType(credentialsType) + ret.Endpoint = credentialsEndpoint + switch ret.AuthType { + case params.GithubAuthTypePAT: + ret.PAT.OAuth2Token = credentialsOAuthToken + case params.GithubAuthTypeApp: + ret.App.InstallationID = credentialsAppInstallationID + ret.App.AppID = credentialsAppID + keyContents, err := parsePrivateKeyFromPath(credentialsPrivateKeyPath) + if err != nil { + return params.CreateGithubCredentialsParams{}, err + } + ret.App.PrivateKeyBytes = keyContents + default: + return params.CreateGithubCredentialsParams{}, fmt.Errorf("invalid auth type: %s (supported are: app, pat)", credentialsType) + } + + return ret, nil +} + +func parseCredentialsUpdateParams() (params.UpdateGithubCredentialsParams, error) { + var updateParams params.UpdateGithubCredentialsParams + + if credentialsName != "" { + updateParams.Name = &credentialsName + } + + if credentialsDescription != "" { + updateParams.Description = &credentialsDescription + } + + if credentialsOAuthToken != "" { + updateParams.PAT.OAuth2Token = credentialsOAuthToken + } + + if credentialsAppInstallationID != 0 { + updateParams.App.InstallationID = credentialsAppInstallationID + } + + if credentialsAppID != 0 { + updateParams.App.AppID = credentialsAppID + } + + if credentialsPrivateKeyPath != "" { + keyContents, err := parsePrivateKeyFromPath(credentialsPrivateKeyPath) + if err != nil { + return params.UpdateGithubCredentialsParams{}, err + } + updateParams.App.PrivateKeyBytes = keyContents + } + + return updateParams, nil +} + +func formatGithubCredentials(creds []params.GithubCredentials) { + t := table.NewWriter() + header := table.Row{"ID", "Name", "Description", "Base URL", "API URL", "Upload URL", "Type"} + t.AppendHeader(header) + for _, val := range creds { + t.AppendRow(table.Row{val.ID, val.Name, val.Description, val.BaseURL, val.APIBaseURL, val.UploadBaseURL, val.AuthType}) + t.AppendSeparator() + } + fmt.Println(t.Render()) +} + +func formatOneGithubCredential(cred params.GithubCredentials) { + t := table.NewWriter() + header := table.Row{"Field", "Value"} + t.AppendHeader(header) + + t.AppendRow(table.Row{"ID", cred.ID}) + t.AppendRow(table.Row{"Name", cred.Name}) + t.AppendRow(table.Row{"Description", cred.Description}) + t.AppendRow(table.Row{"Base URL", cred.BaseURL}) + t.AppendRow(table.Row{"API URL", cred.APIBaseURL}) + t.AppendRow(table.Row{"Upload URL", cred.UploadBaseURL}) + t.AppendRow(table.Row{"Type", cred.AuthType}) + t.AppendRow(table.Row{"Endpoint", cred.Endpoint.Name}) + + if len(cred.Repositories) > 0 { + t.AppendRow(table.Row{"", ""}) + for _, repo := range cred.Repositories { + t.AppendRow(table.Row{"Repositories", repo.String()}) + } + } + + if len(cred.Organizations) > 0 { + t.AppendRow(table.Row{"", ""}) + for _, org := range cred.Organizations { + t.AppendRow(table.Row{"Organizations", org.Name}) + } + } + + if len(cred.Enterprises) > 0 { + t.AppendRow(table.Row{"", ""}) + for _, ent := range cred.Enterprises { + t.AppendRow(table.Row{"Enterprises", ent.Name}) + } + } + + t.SetColumnConfigs([]table.ColumnConfig{ + {Number: 1, AutoMerge: true}, + {Number: 2, AutoMerge: false, WidthMax: 100}, + }) + fmt.Println(t.Render()) +} diff --git a/cmd/garm-cli/cmd/github_endpoints.go b/cmd/garm-cli/cmd/github_endpoints.go index a841d3dc..b12ba2e7 100644 --- a/cmd/garm-cli/cmd/github_endpoints.go +++ b/cmd/garm-cli/cmd/github_endpoints.go @@ -199,11 +199,13 @@ func init() { githubEndpointUpdateCmd.Flags().StringVar(&endpointAPIBaseURL, "api-base-url", "", "API Base URL of the GitHub endpoint") githubEndpointUpdateCmd.Flags().StringVar(&endpointCACertPath, "ca-cert-path", "", "CA Cert Path of the GitHub endpoint") - githubEndpointCmd.AddCommand(githubEndpointListCmd) - githubEndpointCmd.AddCommand(githubEndpointShowCmd) - githubEndpointCmd.AddCommand(githubEndpointCreateCmd) - githubEndpointCmd.AddCommand(githubEndpointDeleteCmd) - githubEndpointCmd.AddCommand(githubEndpointUpdateCmd) + githubEndpointCmd.AddCommand( + githubEndpointListCmd, + githubEndpointShowCmd, + githubEndpointCreateCmd, + githubEndpointDeleteCmd, + githubEndpointUpdateCmd, + ) githubCmd.AddCommand(githubEndpointCmd) } diff --git a/database/common/common.go b/database/common/common.go index 8f901ab7..5af12780 100644 --- a/database/common/common.go +++ b/database/common/common.go @@ -29,7 +29,7 @@ type GithubEndpointStore interface { } type GithubCredentialsStore interface { - CreateGithubCredentials(ctx context.Context, endpointName string, param params.CreateGithubCredentialsParams) (params.GithubCredentials, error) + CreateGithubCredentials(ctx context.Context, param params.CreateGithubCredentialsParams) (params.GithubCredentials, error) GetGithubCredentials(ctx context.Context, id uint, detailed bool) (params.GithubCredentials, error) GetGithubCredentialsByName(ctx context.Context, name string, detailed bool) (params.GithubCredentials, error) ListGithubCredentials(ctx context.Context) ([]params.GithubCredentials, error) diff --git a/database/common/mocks/Store.go b/database/common/mocks/Store.go index f8877ef7..9310e5c4 100644 --- a/database/common/mocks/Store.go +++ b/database/common/mocks/Store.go @@ -134,9 +134,9 @@ func (_m *Store) CreateEntityPool(ctx context.Context, entity params.GithubEntit return r0, r1 } -// CreateGithubCredentials provides a mock function with given fields: ctx, endpointName, param -func (_m *Store) CreateGithubCredentials(ctx context.Context, endpointName string, param params.CreateGithubCredentialsParams) (params.GithubCredentials, error) { - ret := _m.Called(ctx, endpointName, param) +// CreateGithubCredentials provides a mock function with given fields: ctx, param +func (_m *Store) CreateGithubCredentials(ctx context.Context, param params.CreateGithubCredentialsParams) (params.GithubCredentials, error) { + ret := _m.Called(ctx, param) if len(ret) == 0 { panic("no return value specified for CreateGithubCredentials") @@ -144,17 +144,17 @@ func (_m *Store) CreateGithubCredentials(ctx context.Context, endpointName strin var r0 params.GithubCredentials var r1 error - if rf, ok := ret.Get(0).(func(context.Context, string, params.CreateGithubCredentialsParams) (params.GithubCredentials, error)); ok { - return rf(ctx, endpointName, param) + if rf, ok := ret.Get(0).(func(context.Context, params.CreateGithubCredentialsParams) (params.GithubCredentials, error)); ok { + return rf(ctx, param) } - if rf, ok := ret.Get(0).(func(context.Context, string, params.CreateGithubCredentialsParams) params.GithubCredentials); ok { - r0 = rf(ctx, endpointName, param) + if rf, ok := ret.Get(0).(func(context.Context, params.CreateGithubCredentialsParams) params.GithubCredentials); ok { + r0 = rf(ctx, param) } else { r0 = ret.Get(0).(params.GithubCredentials) } - if rf, ok := ret.Get(1).(func(context.Context, string, params.CreateGithubCredentialsParams) error); ok { - r1 = rf(ctx, endpointName, param) + if rf, ok := ret.Get(1).(func(context.Context, params.CreateGithubCredentialsParams) error); ok { + r1 = rf(ctx, param) } else { r1 = ret.Error(1) } diff --git a/database/sql/github.go b/database/sql/github.go index 8a3bb50c..252f8f6f 100644 --- a/database/sql/github.go +++ b/database/sql/github.go @@ -257,15 +257,18 @@ func (s *sqlDatabase) DeleteGithubEndpoint(_ context.Context, name string) error return nil } -func (s *sqlDatabase) CreateGithubCredentials(ctx context.Context, endpointName string, param params.CreateGithubCredentialsParams) (params.GithubCredentials, error) { +func (s *sqlDatabase) CreateGithubCredentials(ctx context.Context, param params.CreateGithubCredentialsParams) (params.GithubCredentials, error) { userID, err := getUIDFromContext(ctx) if err != nil { return params.GithubCredentials{}, errors.Wrap(err, "creating github credentials") } + if param.Endpoint == "" { + return params.GithubCredentials{}, errors.New("endpoint name is required") + } var creds GithubCredentials err = s.conn.Transaction(func(tx *gorm.DB) error { var endpoint GithubEndpoint - if err := tx.Where("name = ?", endpointName).First(&endpoint).Error; err != nil { + if err := tx.Where("name = ?", param.Endpoint).First(&endpoint).Error; err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { return errors.Wrap(runnerErrors.ErrNotFound, "github endpoint not found") } diff --git a/database/sql/sql.go b/database/sql/sql.go index 2436dc3d..a15cfd71 100644 --- a/database/sql/sql.go +++ b/database/sql/sql.go @@ -297,6 +297,7 @@ func (s *sqlDatabase) migrateCredentialsToDB() (err error) { credParams := params.CreateGithubCredentialsParams{ Name: cred.Name, Description: cred.Description, + Endpoint: endpoint.Name, AuthType: params.GithubAuthType(cred.GetAuthType()), } switch credParams.AuthType { @@ -327,7 +328,7 @@ func (s *sqlDatabase) migrateCredentialsToDB() (err error) { } } - creds, err := s.CreateGithubCredentials(adminCtx, endpoint.Name, credParams) + creds, err := s.CreateGithubCredentials(adminCtx, credParams) if err != nil { return errors.Wrap(err, "creating github credentials") } diff --git a/internal/testing/testing.go b/internal/testing/testing.go index d599aca4..bb1f580a 100644 --- a/internal/testing/testing.go +++ b/internal/testing/testing.go @@ -80,11 +80,12 @@ func CreateTestGithubCredentials(ctx context.Context, credsName string, db commo Name: credsName, Description: "Test creds", AuthType: params.GithubAuthTypePAT, + Endpoint: endpoint.Name, PAT: params.GithubPAT{ OAuth2Token: "test-token", }, } - newCreds, err := db.CreateGithubCredentials(ctx, endpoint.Name, newCredsParams) + newCreds, err := db.CreateGithubCredentials(ctx, newCredsParams) if err != nil { s.Fatalf("failed to create database object (new-creds): %v", err) } diff --git a/params/params.go b/params/params.go index c28990d7..522dc954 100644 --- a/params/params.go +++ b/params/params.go @@ -437,6 +437,10 @@ func (r Repository) GetBalancerType() PoolBalancerType { return r.PoolBalancerType } +func (r Repository) String() string { + return fmt.Sprintf("%s/%s", r.Owner, r.Name) +} + // used by swagger client generated code type Repositories []Repository diff --git a/params/requests.go b/params/requests.go index ff7a3824..db7e7da2 100644 --- a/params/requests.go +++ b/params/requests.go @@ -21,7 +21,9 @@ import ( "fmt" "net/url" - "github.com/cloudbase/garm-provider-common/errors" + "github.com/pkg/errors" + + runnerErrors "github.com/cloudbase/garm-provider-common/errors" commonParams "github.com/cloudbase/garm-provider-common/params" ) @@ -47,24 +49,24 @@ type CreateRepoParams struct { func (c *CreateRepoParams) Validate() error { if c.Owner == "" { - return errors.NewBadRequestError("missing owner") + return runnerErrors.NewBadRequestError("missing owner") } if c.Name == "" { - return errors.NewBadRequestError("missing repo name") + return runnerErrors.NewBadRequestError("missing repo name") } if c.CredentialsName == "" { - return errors.NewBadRequestError("missing credentials name") + return runnerErrors.NewBadRequestError("missing credentials name") } if c.WebhookSecret == "" { - return errors.NewMissingSecretError("missing secret") + return runnerErrors.NewMissingSecretError("missing secret") } switch c.PoolBalancerType { case PoolBalancerTypeRoundRobin, PoolBalancerTypePack, PoolBalancerTypeNone: default: - return errors.NewBadRequestError("invalid pool balancer type") + return runnerErrors.NewBadRequestError("invalid pool balancer type") } return nil @@ -79,20 +81,20 @@ type CreateOrgParams struct { func (c *CreateOrgParams) Validate() error { if c.Name == "" { - return errors.NewBadRequestError("missing org name") + return runnerErrors.NewBadRequestError("missing org name") } if c.CredentialsName == "" { - return errors.NewBadRequestError("missing credentials name") + return runnerErrors.NewBadRequestError("missing credentials name") } if c.WebhookSecret == "" { - return errors.NewMissingSecretError("missing secret") + return runnerErrors.NewMissingSecretError("missing secret") } switch c.PoolBalancerType { case PoolBalancerTypeRoundRobin, PoolBalancerTypePack, PoolBalancerTypeNone: default: - return errors.NewBadRequestError("invalid pool balancer type") + return runnerErrors.NewBadRequestError("invalid pool balancer type") } return nil } @@ -106,19 +108,19 @@ type CreateEnterpriseParams struct { func (c *CreateEnterpriseParams) Validate() error { if c.Name == "" { - return errors.NewBadRequestError("missing enterprise name") + return runnerErrors.NewBadRequestError("missing enterprise name") } if c.CredentialsName == "" { - return errors.NewBadRequestError("missing credentials name") + return runnerErrors.NewBadRequestError("missing credentials name") } if c.WebhookSecret == "" { - return errors.NewMissingSecretError("missing secret") + return runnerErrors.NewMissingSecretError("missing secret") } switch c.PoolBalancerType { case PoolBalancerTypeRoundRobin, PoolBalancerTypePack, PoolBalancerTypeNone: default: - return errors.NewBadRequestError("invalid pool balancer type") + return runnerErrors.NewBadRequestError("invalid pool balancer type") } return nil } @@ -256,7 +258,7 @@ type PasswordLoginParams struct { // Validate checks if the username and password are set func (p PasswordLoginParams) Validate() error { if p.Username == "" || p.Password == "" { - return errors.ErrUnauthorized + return runnerErrors.ErrUnauthorized } return nil } @@ -284,56 +286,56 @@ type CreateGithubEndpointParams struct { func (c CreateGithubEndpointParams) Validate() error { if c.APIBaseURL == "" { - return errors.NewBadRequestError("missing api_base_url") + return runnerErrors.NewBadRequestError("missing api_base_url") } url, err := url.Parse(c.APIBaseURL) if err != nil || url.Scheme == "" || url.Host == "" { - return errors.NewBadRequestError("invalid api_base_url") + return runnerErrors.NewBadRequestError("invalid api_base_url") } switch url.Scheme { case httpsScheme, httpScheme: default: - return errors.NewBadRequestError("invalid api_base_url") + return runnerErrors.NewBadRequestError("invalid api_base_url") } if c.UploadBaseURL == "" { - return errors.NewBadRequestError("missing upload_base_url") + return runnerErrors.NewBadRequestError("missing upload_base_url") } url, err = url.Parse(c.UploadBaseURL) if err != nil || url.Scheme == "" || url.Host == "" { - return errors.NewBadRequestError("invalid upload_base_url") + return runnerErrors.NewBadRequestError("invalid upload_base_url") } switch url.Scheme { case httpsScheme, httpScheme: default: - return errors.NewBadRequestError("invalid api_base_url") + return runnerErrors.NewBadRequestError("invalid api_base_url") } if c.BaseURL == "" { - return errors.NewBadRequestError("missing base_url") + return runnerErrors.NewBadRequestError("missing base_url") } url, err = url.Parse(c.BaseURL) if err != nil || url.Scheme == "" || url.Host == "" { - return errors.NewBadRequestError("invalid base_url") + return runnerErrors.NewBadRequestError("invalid base_url") } switch url.Scheme { case httpsScheme, httpScheme: default: - return errors.NewBadRequestError("invalid api_base_url") + return runnerErrors.NewBadRequestError("invalid api_base_url") } if c.CACertBundle != nil { block, _ := pem.Decode(c.CACertBundle) if block == nil { - return errors.NewBadRequestError("invalid ca_cert_bundle") + return runnerErrors.NewBadRequestError("invalid ca_cert_bundle") } if _, err := x509.ParseCertificates(block.Bytes); err != nil { - return errors.NewBadRequestError("invalid ca_cert_bundle") + return runnerErrors.NewBadRequestError("invalid ca_cert_bundle") } } @@ -352,46 +354,46 @@ func (u UpdateGithubEndpointParams) Validate() error { if u.APIBaseURL != nil { url, err := url.Parse(*u.APIBaseURL) if err != nil || url.Scheme == "" || url.Host == "" { - return errors.NewBadRequestError("invalid api_base_url") + return runnerErrors.NewBadRequestError("invalid api_base_url") } switch url.Scheme { case httpsScheme, httpScheme: default: - return errors.NewBadRequestError("invalid api_base_url") + return runnerErrors.NewBadRequestError("invalid api_base_url") } } if u.UploadBaseURL != nil { url, err := url.Parse(*u.UploadBaseURL) if err != nil || url.Scheme == "" || url.Host == "" { - return errors.NewBadRequestError("invalid upload_base_url") + return runnerErrors.NewBadRequestError("invalid upload_base_url") } switch url.Scheme { case httpsScheme, httpScheme: default: - return errors.NewBadRequestError("invalid api_base_url") + return runnerErrors.NewBadRequestError("invalid api_base_url") } } if u.BaseURL != nil { url, err := url.Parse(*u.BaseURL) if err != nil || url.Scheme == "" || url.Host == "" { - return errors.NewBadRequestError("invalid base_url") + return runnerErrors.NewBadRequestError("invalid base_url") } switch url.Scheme { case httpsScheme, httpScheme: default: - return errors.NewBadRequestError("invalid api_base_url") + return runnerErrors.NewBadRequestError("invalid api_base_url") } } if u.CACertBundle != nil { block, _ := pem.Decode(u.CACertBundle) if block == nil { - return errors.NewBadRequestError("invalid ca_cert_bundle") + return runnerErrors.NewBadRequestError("invalid ca_cert_bundle") } if _, err := x509.ParseCertificates(block.Bytes); err != nil { - return errors.NewBadRequestError("invalid ca_cert_bundle") + return runnerErrors.NewBadRequestError("invalid ca_cert_bundle") } } @@ -410,15 +412,15 @@ type GithubApp struct { func (g GithubApp) Validate() error { if g.AppID == 0 { - return errors.NewBadRequestError("missing app_id") + return runnerErrors.NewBadRequestError("missing app_id") } if g.InstallationID == 0 { - return errors.NewBadRequestError("missing installation_id") + return runnerErrors.NewBadRequestError("missing installation_id") } if len(g.PrivateKeyBytes) == 0 { - return errors.NewBadRequestError("missing private_key_bytes") + return runnerErrors.NewBadRequestError("missing private_key_bytes") } block, _ := pem.Decode(g.PrivateKeyBytes) @@ -434,14 +436,65 @@ func (g GithubApp) Validate() error { type CreateGithubCredentialsParams struct { Name string `json:"name"` Description string `json:"description"` + Endpoint string `json:"endpoint"` AuthType GithubAuthType `json:"auth_type"` PAT GithubPAT `json:"pat,omitempty"` App GithubApp `json:"app,omitempty"` } +func (c CreateGithubCredentialsParams) Validate() error { + if c.Name == "" { + return runnerErrors.NewBadRequestError("missing name") + } + + if c.Endpoint == "" { + return runnerErrors.NewBadRequestError("missing endpoint") + } + + switch c.AuthType { + case GithubAuthTypePAT, GithubAuthTypeApp: + default: + return runnerErrors.NewBadRequestError("invalid auth_type") + } + + if c.AuthType == GithubAuthTypePAT { + if c.PAT.OAuth2Token == "" { + return runnerErrors.NewBadRequestError("missing oauth2_token") + } + } + + if c.AuthType == GithubAuthTypeApp { + if err := c.App.Validate(); err != nil { + return errors.Wrap(err, "invalid app") + } + } + + return nil +} + type UpdateGithubCredentialsParams struct { Name *string `json:"name,omitempty"` Description *string `json:"description,omitempty"` PAT *GithubPAT `json:"pat,omitempty"` App *GithubApp `json:"app,omitempty"` } + +func (u UpdateGithubCredentialsParams) Validate() error { + if u.PAT != nil && u.App != nil { + return runnerErrors.NewBadRequestError("cannot update both PAT and App") + } + + if u.PAT != nil { + if u.PAT.OAuth2Token == "" { + return runnerErrors.NewBadRequestError("missing oauth2_token") + } + } + + if u.App != nil { + if err := u.App.Validate(); err != nil { + return errors.Wrap(err, "invalid app") + } + } + + return nil +} diff --git a/runner/github_credentials.go b/runner/github_credentials.go new file mode 100644 index 00000000..fbf9d330 --- /dev/null +++ b/runner/github_credentials.go @@ -0,0 +1,83 @@ +package runner + +import ( + "context" + + "github.com/pkg/errors" + + runnerErrors "github.com/cloudbase/garm-provider-common/errors" + "github.com/cloudbase/garm/auth" + "github.com/cloudbase/garm/params" +) + +func (r *Runner) ListCredentials(ctx context.Context) ([]params.GithubCredentials, error) { + if !auth.IsAdmin(ctx) { + return nil, runnerErrors.ErrUnauthorized + } + + creds, err := r.store.ListGithubCredentials(ctx) + if err != nil { + return nil, errors.Wrap(err, "fetching github credentials") + } + + return creds, nil +} + +func (r *Runner) CreateGithubCredentials(ctx context.Context, param params.CreateGithubCredentialsParams) (params.GithubCredentials, error) { + if !auth.IsAdmin(ctx) { + return params.GithubCredentials{}, runnerErrors.ErrUnauthorized + } + + if err := param.Validate(); err != nil { + return params.GithubCredentials{}, errors.Wrap(err, "failed to validate github credentials params") + } + + creds, err := r.store.CreateGithubCredentials(ctx, param) + if err != nil { + return params.GithubCredentials{}, errors.Wrap(err, "failed to create github credentials") + } + + return creds, nil +} + +func (r *Runner) GetGithubCredentials(ctx context.Context, id uint) (params.GithubCredentials, error) { + if !auth.IsAdmin(ctx) { + return params.GithubCredentials{}, runnerErrors.ErrUnauthorized + } + + creds, err := r.store.GetGithubCredentials(ctx, id, true) + if err != nil { + return params.GithubCredentials{}, errors.Wrap(err, "failed to get github credentials") + } + + return creds, nil +} + +func (r *Runner) DeleteGithubCredentials(ctx context.Context, id uint) error { + if !auth.IsAdmin(ctx) { + return runnerErrors.ErrUnauthorized + } + + if err := r.store.DeleteGithubCredentials(ctx, id); err != nil { + return errors.Wrap(err, "failed to delete github credentials") + } + + return nil +} + +func (r *Runner) UpdateGithubCredentials(ctx context.Context, id uint, param params.UpdateGithubCredentialsParams) (params.GithubCredentials, error) { + if !auth.IsAdmin(ctx) { + return params.GithubCredentials{}, runnerErrors.ErrUnauthorized + } + + if err := param.Validate(); err != nil { + return params.GithubCredentials{}, errors.Wrap(err, "failed to validate github credentials params") + } + + newCreds, err := r.store.UpdateGithubCredentials(ctx, id, param) + if err != nil { + return params.GithubCredentials{}, errors.Wrap(err, "failed to update github credentials") + } + + return newCreds, nil +} diff --git a/runner/endpoints.go b/runner/github_endpoints.go similarity index 100% rename from runner/endpoints.go rename to runner/github_endpoints.go diff --git a/runner/runner.go b/runner/runner.go index bc28a6c3..453980a0 100644 --- a/runner/runner.go +++ b/runner/runner.go @@ -395,19 +395,6 @@ func (r *Runner) GetControllerInfo(ctx context.Context) (params.ControllerInfo, }, nil } -func (r *Runner) ListCredentials(ctx context.Context) ([]params.GithubCredentials, error) { - if !auth.IsAdmin(ctx) { - return nil, runnerErrors.ErrUnauthorized - } - - creds, err := r.store.ListGithubCredentials(ctx) - if err != nil { - return nil, errors.Wrap(err, "fetching github credentials") - } - - return creds, nil -} - func (r *Runner) ListProviders(ctx context.Context) ([]params.Provider, error) { if !auth.IsAdmin(ctx) { return nil, runnerErrors.ErrUnauthorized