configstore: implement variable update
This commit is contained in:
parent
28c44ce1fc
commit
ac0c1fc2bd
|
@ -48,24 +48,32 @@ func (h *ActionHandler) GetVariables(ctx context.Context, parentType types.Confi
|
||||||
return variables, nil
|
return variables, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *ActionHandler) CreateVariable(ctx context.Context, variable *types.Variable) (*types.Variable, error) {
|
func (h *ActionHandler) ValidateVariable(ctx context.Context, variable *types.Variable) error {
|
||||||
if variable.Name == "" {
|
if variable.Name == "" {
|
||||||
return nil, util.NewErrBadRequest(errors.Errorf("variable name required"))
|
return util.NewErrBadRequest(errors.Errorf("variable name required"))
|
||||||
}
|
}
|
||||||
if !util.ValidateName(variable.Name) {
|
if !util.ValidateName(variable.Name) {
|
||||||
return nil, util.NewErrBadRequest(errors.Errorf("invalid variable name %q", variable.Name))
|
return util.NewErrBadRequest(errors.Errorf("invalid variable name %q", variable.Name))
|
||||||
}
|
}
|
||||||
if len(variable.Values) == 0 {
|
if len(variable.Values) == 0 {
|
||||||
return nil, util.NewErrBadRequest(errors.Errorf("variable values required"))
|
return util.NewErrBadRequest(errors.Errorf("variable values required"))
|
||||||
}
|
}
|
||||||
if variable.Parent.Type == "" {
|
if variable.Parent.Type == "" {
|
||||||
return nil, util.NewErrBadRequest(errors.Errorf("variable parent type required"))
|
return util.NewErrBadRequest(errors.Errorf("variable parent type required"))
|
||||||
}
|
}
|
||||||
if variable.Parent.ID == "" {
|
if variable.Parent.ID == "" {
|
||||||
return nil, util.NewErrBadRequest(errors.Errorf("variable parent id required"))
|
return util.NewErrBadRequest(errors.Errorf("variable parent id required"))
|
||||||
}
|
}
|
||||||
if variable.Parent.Type != types.ConfigTypeProject && variable.Parent.Type != types.ConfigTypeProjectGroup {
|
if variable.Parent.Type != types.ConfigTypeProject && variable.Parent.Type != types.ConfigTypeProjectGroup {
|
||||||
return nil, util.NewErrBadRequest(errors.Errorf("invalid variable parent type %q", variable.Parent.Type))
|
return util.NewErrBadRequest(errors.Errorf("invalid variable parent type %q", variable.Parent.Type))
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *ActionHandler) CreateVariable(ctx context.Context, variable *types.Variable) (*types.Variable, error) {
|
||||||
|
if err := h.ValidateVariable(ctx, variable); err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var cgt *datamanager.ChangeGroupsUpdateToken
|
var cgt *datamanager.ChangeGroupsUpdateToken
|
||||||
|
@ -120,6 +128,86 @@ func (h *ActionHandler) CreateVariable(ctx context.Context, variable *types.Vari
|
||||||
return variable, err
|
return variable, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type UpdateVariableRequest struct {
|
||||||
|
VariableName string
|
||||||
|
|
||||||
|
Variable *types.Variable
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *ActionHandler) UpdateVariable(ctx context.Context, req *UpdateVariableRequest) (*types.Variable, error) {
|
||||||
|
if err := h.ValidateVariable(ctx, req.Variable); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var curVariable *types.Variable
|
||||||
|
var cgt *datamanager.ChangeGroupsUpdateToken
|
||||||
|
// changegroup is the variable name
|
||||||
|
|
||||||
|
// must do all the checks in a single transaction to avoid concurrent changes
|
||||||
|
err := h.readDB.Do(func(tx *db.Tx) error {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
parentID, err := h.readDB.ResolveConfigID(tx, req.Variable.Parent.Type, req.Variable.Parent.ID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
req.Variable.Parent.ID = parentID
|
||||||
|
|
||||||
|
// check variable exists
|
||||||
|
curVariable, err = h.readDB.GetVariableByName(tx, req.Variable.Parent.ID, req.VariableName)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if curVariable == nil {
|
||||||
|
return util.NewErrBadRequest(errors.Errorf("variable with name %q for %s with id %q doesn't exists", req.VariableName, req.Variable.Parent.Type, req.Variable.Parent.ID))
|
||||||
|
}
|
||||||
|
|
||||||
|
if curVariable.Name != req.Variable.Name {
|
||||||
|
// check duplicate variable name
|
||||||
|
u, err := h.readDB.GetVariableByName(tx, req.Variable.Parent.ID, req.Variable.Name)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if u != nil {
|
||||||
|
return util.NewErrBadRequest(errors.Errorf("variable with name %q for %s with id %q already exists", req.Variable.Name, req.Variable.Parent.Type, req.Variable.Parent.ID))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// set/override ID that must be kept from the current variable
|
||||||
|
req.Variable.ID = curVariable.ID
|
||||||
|
|
||||||
|
cgNames := []string{
|
||||||
|
util.EncodeSha256Hex("variablename-" + req.Variable.ID),
|
||||||
|
util.EncodeSha256Hex("variablename-" + req.Variable.Name),
|
||||||
|
}
|
||||||
|
cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
variablej, err := json.Marshal(req.Variable)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Errorf("failed to marshal variable: %w", err)
|
||||||
|
}
|
||||||
|
actions := []*datamanager.Action{
|
||||||
|
{
|
||||||
|
ActionType: datamanager.ActionTypePut,
|
||||||
|
DataType: string(types.ConfigTypeVariable),
|
||||||
|
ID: req.Variable.ID,
|
||||||
|
Data: variablej,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = h.dm.WriteWal(ctx, actions, cgt)
|
||||||
|
return req.Variable, err
|
||||||
|
}
|
||||||
|
|
||||||
func (h *ActionHandler) DeleteVariable(ctx context.Context, parentType types.ConfigType, parentRef, variableName string) error {
|
func (h *ActionHandler) DeleteVariable(ctx context.Context, parentType types.ConfigType, parentRef, variableName string) error {
|
||||||
var variable *types.Variable
|
var variable *types.Variable
|
||||||
|
|
||||||
|
|
|
@ -267,6 +267,17 @@ func (c *Client) CreateProjectGroupVariable(ctx context.Context, projectGroupRef
|
||||||
return resVariable, resp, err
|
return resVariable, resp, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Client) UpdateProjectGroupVariable(ctx context.Context, projectGroupRef, variableName string, variable *types.Variable) (*Variable, *http.Response, error) {
|
||||||
|
pj, err := json.Marshal(variable)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
resVariable := new(Variable)
|
||||||
|
resp, err := c.getParsedResponse(ctx, "PUT", fmt.Sprintf("/projectgroups/%s/variables/%s", url.PathEscape(projectGroupRef), variableName), nil, jsonContent, bytes.NewReader(pj), resVariable)
|
||||||
|
return resVariable, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
func (c *Client) CreateProjectVariable(ctx context.Context, projectRef string, variable *types.Variable) (*Variable, *http.Response, error) {
|
func (c *Client) CreateProjectVariable(ctx context.Context, projectRef string, variable *types.Variable) (*Variable, *http.Response, error) {
|
||||||
pj, err := json.Marshal(variable)
|
pj, err := json.Marshal(variable)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -278,6 +289,17 @@ func (c *Client) CreateProjectVariable(ctx context.Context, projectRef string, v
|
||||||
return resVariable, resp, err
|
return resVariable, resp, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Client) UpdateProjectVariable(ctx context.Context, projectRef, variableName string, variable *types.Variable) (*Variable, *http.Response, error) {
|
||||||
|
pj, err := json.Marshal(variable)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
resVariable := new(Variable)
|
||||||
|
resp, err := c.getParsedResponse(ctx, "PUT", fmt.Sprintf("/projects/%s/variables/%s", url.PathEscape(projectRef), variableName), nil, jsonContent, bytes.NewReader(pj), resVariable)
|
||||||
|
return resVariable, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
func (c *Client) DeleteProjectGroupVariable(ctx context.Context, projectGroupRef, variableName string) (*http.Response, error) {
|
func (c *Client) DeleteProjectGroupVariable(ctx context.Context, projectGroupRef, variableName string) (*http.Response, error) {
|
||||||
return c.getResponse(ctx, "DELETE", fmt.Sprintf("/projectgroups/%s/variables/%s", url.PathEscape(projectGroupRef), variableName), nil, jsonContent, nil)
|
return c.getResponse(ctx, "DELETE", fmt.Sprintf("/projectgroups/%s/variables/%s", url.PathEscape(projectGroupRef), variableName), nil, jsonContent, nil)
|
||||||
}
|
}
|
||||||
|
|
|
@ -127,6 +127,51 @@ func (h *CreateVariableHandler) ServeHTTP(w http.ResponseWriter, r *http.Request
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type UpdateVariableHandler struct {
|
||||||
|
log *zap.SugaredLogger
|
||||||
|
ah *action.ActionHandler
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewUpdateVariableHandler(logger *zap.Logger, ah *action.ActionHandler) *UpdateVariableHandler {
|
||||||
|
return &UpdateVariableHandler{log: logger.Sugar(), ah: ah}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *UpdateVariableHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
|
ctx := r.Context()
|
||||||
|
vars := mux.Vars(r)
|
||||||
|
variableName := vars["variablename"]
|
||||||
|
|
||||||
|
parentType, parentRef, err := GetConfigTypeRef(r)
|
||||||
|
if httpError(w, err) {
|
||||||
|
h.log.Errorf("err: %+v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var variable *types.Variable
|
||||||
|
d := json.NewDecoder(r.Body)
|
||||||
|
if err := d.Decode(&variable); err != nil {
|
||||||
|
httpError(w, util.NewErrBadRequest(err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
variable.Parent.Type = parentType
|
||||||
|
variable.Parent.ID = parentRef
|
||||||
|
|
||||||
|
areq := &action.UpdateVariableRequest{
|
||||||
|
VariableName: variableName,
|
||||||
|
Variable: variable,
|
||||||
|
}
|
||||||
|
variable, err = h.ah.UpdateVariable(ctx, areq)
|
||||||
|
if httpError(w, err) {
|
||||||
|
h.log.Errorf("err: %+v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := httpResponse(w, http.StatusOK, variable); err != nil {
|
||||||
|
h.log.Errorf("err: %+v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type DeleteVariableHandler struct {
|
type DeleteVariableHandler struct {
|
||||||
log *zap.SugaredLogger
|
log *zap.SugaredLogger
|
||||||
ah *action.ActionHandler
|
ah *action.ActionHandler
|
||||||
|
|
|
@ -138,6 +138,7 @@ func (s *Configstore) Run(ctx context.Context) error {
|
||||||
|
|
||||||
variablesHandler := api.NewVariablesHandler(logger, s.ah, s.readDB)
|
variablesHandler := api.NewVariablesHandler(logger, s.ah, s.readDB)
|
||||||
createVariableHandler := api.NewCreateVariableHandler(logger, s.ah)
|
createVariableHandler := api.NewCreateVariableHandler(logger, s.ah)
|
||||||
|
updateVariableHandler := api.NewUpdateVariableHandler(logger, s.ah)
|
||||||
deleteVariableHandler := api.NewDeleteVariableHandler(logger, s.ah)
|
deleteVariableHandler := api.NewDeleteVariableHandler(logger, s.ah)
|
||||||
|
|
||||||
userHandler := api.NewUserHandler(logger, s.readDB)
|
userHandler := api.NewUserHandler(logger, s.readDB)
|
||||||
|
@ -196,6 +197,8 @@ func (s *Configstore) Run(ctx context.Context) error {
|
||||||
apirouter.Handle("/projects/{projectref}/variables", variablesHandler).Methods("GET")
|
apirouter.Handle("/projects/{projectref}/variables", variablesHandler).Methods("GET")
|
||||||
apirouter.Handle("/projectgroups/{projectgroupref}/variables", createVariableHandler).Methods("POST")
|
apirouter.Handle("/projectgroups/{projectgroupref}/variables", createVariableHandler).Methods("POST")
|
||||||
apirouter.Handle("/projects/{projectref}/variables", createVariableHandler).Methods("POST")
|
apirouter.Handle("/projects/{projectref}/variables", createVariableHandler).Methods("POST")
|
||||||
|
apirouter.Handle("/projectgroups/{projectgroupref}/variables/{variablename}", updateVariableHandler).Methods("PUT")
|
||||||
|
apirouter.Handle("/projects/{projectref}/variables/{variablename}", updateVariableHandler).Methods("PUT")
|
||||||
apirouter.Handle("/projectgroups/{projectgroupref}/variables/{variablename}", deleteVariableHandler).Methods("DELETE")
|
apirouter.Handle("/projectgroups/{projectgroupref}/variables/{variablename}", deleteVariableHandler).Methods("DELETE")
|
||||||
apirouter.Handle("/projects/{projectref}/variables/{variablename}", deleteVariableHandler).Methods("DELETE")
|
apirouter.Handle("/projects/{projectref}/variables/{variablename}", deleteVariableHandler).Methods("DELETE")
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue