gateway: move secret logic from api to actions

This commit is contained in:
Simone Gotti 2019-05-05 14:11:29 +02:00
parent f73f0ba434
commit 64044df94d
3 changed files with 154 additions and 57 deletions

View File

@ -0,0 +1,119 @@
// Copyright 2019 Sorint.lab
//
// 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 action
import (
"context"
"net/http"
csapi "github.com/sorintlab/agola/internal/services/configstore/api"
"github.com/sorintlab/agola/internal/services/types"
"github.com/sorintlab/agola/internal/util"
"go.uber.org/zap"
"github.com/pkg/errors"
)
type GetSecretsRequest struct {
ParentType types.ConfigType
ParentRef string
Tree bool
}
func (h *ActionHandler) GetSecrets(ctx context.Context, req *GetSecretsRequest) ([]*csapi.Secret, error) {
var cssecrets []*csapi.Secret
var resp *http.Response
var err error
switch req.ParentType {
case types.ConfigTypeProjectGroup:
cssecrets, resp, err = h.configstoreClient.GetProjectGroupSecrets(ctx, req.ParentRef, req.Tree)
case types.ConfigTypeProject:
cssecrets, resp, err = h.configstoreClient.GetProjectSecrets(ctx, req.ParentRef, req.Tree)
}
if err != nil {
return nil, ErrFromRemote(resp, err)
}
return cssecrets, nil
}
type CreateSecretRequest struct {
Name string
ParentType types.ConfigType
ParentRef string
Type types.SecretType
// internal secret
Data map[string]string
// external secret
SecretProviderID string
Path string
}
type CreateSecretHandler struct {
log *zap.SugaredLogger
configstoreClient *csapi.Client
}
func (h *ActionHandler) CreateSecret(ctx context.Context, req *CreateSecretRequest) (*csapi.Secret, error) {
if !util.ValidateName(req.Name) {
return nil, util.NewErrBadRequest(errors.Errorf("invalid secret name %q", req.Name))
}
s := &types.Secret{
Name: req.Name,
Type: req.Type,
Data: req.Data,
}
var resp *http.Response
var rs *csapi.Secret
var err error
switch req.ParentType {
case types.ConfigTypeProjectGroup:
h.log.Infof("creating project group secret")
rs, resp, err = h.configstoreClient.CreateProjectGroupSecret(ctx, req.ParentRef, s)
case types.ConfigTypeProject:
h.log.Infof("creating project secret")
rs, resp, err = h.configstoreClient.CreateProjectSecret(ctx, req.ParentRef, s)
}
if err != nil {
return nil, ErrFromRemote(resp, errors.Wrapf(err, "failed to create secret"))
}
h.log.Infof("secret %s created, ID: %s", rs.Name, rs.ID)
return rs, nil
}
func (h *ActionHandler) DeleteSecret(ctx context.Context, parentType types.ConfigType, parentRef, name string) error {
var resp *http.Response
var err error
switch parentType {
case types.ConfigTypeProjectGroup:
h.log.Infof("deleting project group secret")
resp, err = h.configstoreClient.DeleteProjectGroupSecret(ctx, parentRef, name)
case types.ConfigTypeProject:
h.log.Infof("deleting project secret")
resp, err = h.configstoreClient.DeleteProjectSecret(ctx, parentRef, name)
}
if err != nil {
return ErrFromRemote(resp, errors.Wrapf(err, "failed to delete secret"))
}
return nil
}

View File

@ -19,12 +19,12 @@ import (
"net/http" "net/http"
csapi "github.com/sorintlab/agola/internal/services/configstore/api" csapi "github.com/sorintlab/agola/internal/services/configstore/api"
"github.com/sorintlab/agola/internal/services/gateway/action"
"github.com/sorintlab/agola/internal/services/types" "github.com/sorintlab/agola/internal/services/types"
"github.com/sorintlab/agola/internal/util" "github.com/sorintlab/agola/internal/util"
"go.uber.org/zap" "go.uber.org/zap"
"github.com/gorilla/mux" "github.com/gorilla/mux"
"github.com/pkg/errors"
) )
type SecretResponse struct { type SecretResponse struct {
@ -42,12 +42,12 @@ func createSecretResponse(s *csapi.Secret) *SecretResponse {
} }
type SecretHandler struct { type SecretHandler struct {
log *zap.SugaredLogger log *zap.SugaredLogger
configstoreClient *csapi.Client ah *action.ActionHandler
} }
func NewSecretHandler(logger *zap.Logger, configstoreClient *csapi.Client) *SecretHandler { func NewSecretHandler(logger *zap.Logger, ah *action.ActionHandler) *SecretHandler {
return &SecretHandler{log: logger.Sugar(), configstoreClient: configstoreClient} return &SecretHandler{log: logger.Sugar(), ah: ah}
} }
func (h *SecretHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { func (h *SecretHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
@ -61,15 +61,13 @@ func (h *SecretHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
return return
} }
var cssecrets []*csapi.Secret areq := &action.GetSecretsRequest{
var resp *http.Response ParentType: parentType,
switch parentType { ParentRef: parentRef,
case types.ConfigTypeProjectGroup: Tree: tree,
cssecrets, resp, err = h.configstoreClient.GetProjectGroupSecrets(ctx, parentRef, tree)
case types.ConfigTypeProject:
cssecrets, resp, err = h.configstoreClient.GetProjectSecrets(ctx, parentRef, tree)
} }
if httpErrorFromRemote(w, resp, err) { cssecrets, err := h.ah.GetSecrets(ctx, areq)
if httpError(w, err) {
h.log.Errorf("err: %+v", err) h.log.Errorf("err: %+v", err)
return return
} }
@ -98,12 +96,12 @@ type CreateSecretRequest struct {
} }
type CreateSecretHandler struct { type CreateSecretHandler struct {
log *zap.SugaredLogger log *zap.SugaredLogger
configstoreClient *csapi.Client ah *action.ActionHandler
} }
func NewCreateSecretHandler(logger *zap.Logger, configstoreClient *csapi.Client) *CreateSecretHandler { func NewCreateSecretHandler(logger *zap.Logger, ah *action.ActionHandler) *CreateSecretHandler {
return &CreateSecretHandler{log: logger.Sugar(), configstoreClient: configstoreClient} return &CreateSecretHandler{log: logger.Sugar(), ah: ah}
} }
func (h *CreateSecretHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { func (h *CreateSecretHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
@ -120,46 +118,34 @@ func (h *CreateSecretHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)
return return
} }
if !util.ValidateName(req.Name) { areq := &action.CreateSecretRequest{
httpError(w, util.NewErrBadRequest(errors.Errorf("invalid secret name %q", req.Name))) Name: req.Name,
return ParentType: parentType,
ParentRef: parentRef,
Type: req.Type,
Data: req.Data,
SecretProviderID: req.SecretProviderID,
Path: req.Path,
} }
cssecret, err := h.ah.CreateSecret(ctx, areq)
s := &types.Secret{ if httpError(w, err) {
Name: req.Name,
Type: req.Type,
Data: req.Data,
}
var resp *http.Response
var rs *csapi.Secret
switch parentType {
case types.ConfigTypeProjectGroup:
h.log.Infof("creating project group secret")
rs, resp, err = h.configstoreClient.CreateProjectGroupSecret(ctx, parentRef, s)
case types.ConfigTypeProject:
h.log.Infof("creating project secret")
rs, resp, err = h.configstoreClient.CreateProjectSecret(ctx, parentRef, s)
}
if httpErrorFromRemote(w, resp, err) {
h.log.Errorf("err: %+v", err) h.log.Errorf("err: %+v", err)
return return
} }
h.log.Infof("secret %s created, ID: %s", rs.Name, rs.ID)
res := createSecretResponse(rs) res := createSecretResponse(cssecret)
if err := httpResponse(w, http.StatusOK, res); err != nil { if err := httpResponse(w, http.StatusOK, res); err != nil {
h.log.Errorf("err: %+v", err) h.log.Errorf("err: %+v", err)
} }
} }
type DeleteSecretHandler struct { type DeleteSecretHandler struct {
log *zap.SugaredLogger log *zap.SugaredLogger
configstoreClient *csapi.Client ah *action.ActionHandler
} }
func NewDeleteSecretHandler(logger *zap.Logger, configstoreClient *csapi.Client) *DeleteSecretHandler { func NewDeleteSecretHandler(logger *zap.Logger, ah *action.ActionHandler) *DeleteSecretHandler {
return &DeleteSecretHandler{log: logger.Sugar(), configstoreClient: configstoreClient} return &DeleteSecretHandler{log: logger.Sugar(), ah: ah}
} }
func (h *DeleteSecretHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { func (h *DeleteSecretHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
@ -172,16 +158,8 @@ func (h *DeleteSecretHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)
return return
} }
var resp *http.Response err = h.ah.DeleteSecret(ctx, parentType, parentRef, secretName)
switch parentType { if httpError(w, err) {
case types.ConfigTypeProjectGroup:
h.log.Infof("deleting project group secret")
resp, err = h.configstoreClient.DeleteProjectGroupSecret(ctx, parentRef, secretName)
case types.ConfigTypeProject:
h.log.Infof("deleting project secret")
resp, err = h.configstoreClient.DeleteProjectSecret(ctx, parentRef, secretName)
}
if httpErrorFromRemote(w, resp, err) {
h.log.Errorf("err: %+v", err) h.log.Errorf("err: %+v", err)
return return
} }

View File

@ -158,9 +158,9 @@ func (g *Gateway) Run(ctx context.Context) error {
deleteProjectHandler := api.NewDeleteProjectHandler(logger, g.configstoreClient) deleteProjectHandler := api.NewDeleteProjectHandler(logger, g.configstoreClient)
projectReconfigHandler := api.NewProjectReconfigHandler(logger, g.ah, g.configstoreClient, g.c.APIExposedURL) projectReconfigHandler := api.NewProjectReconfigHandler(logger, g.ah, g.configstoreClient, g.c.APIExposedURL)
secretHandler := api.NewSecretHandler(logger, g.configstoreClient) secretHandler := api.NewSecretHandler(logger, g.ah)
createSecretHandler := api.NewCreateSecretHandler(logger, g.configstoreClient) createSecretHandler := api.NewCreateSecretHandler(logger, g.ah)
deleteSecretHandler := api.NewDeleteSecretHandler(logger, g.configstoreClient) deleteSecretHandler := api.NewDeleteSecretHandler(logger, g.ah)
variableHandler := api.NewVariableHandler(logger, g.ah) variableHandler := api.NewVariableHandler(logger, g.ah)
createVariableHandler := api.NewCreateVariableHandler(logger, g.ah) createVariableHandler := api.NewCreateVariableHandler(logger, g.ah)