configstore: use augmented types for vars/secrets dynamic values
This commit is contained in:
parent
da2ac0ab38
commit
984efb539e
@ -156,48 +156,48 @@ func (c *Client) DeleteProject(ctx context.Context, projectRef string) (*http.Re
|
|||||||
return c.getResponse(ctx, "DELETE", fmt.Sprintf("/projects/%s", url.PathEscape(projectRef)), nil, jsonContent, nil)
|
return c.getResponse(ctx, "DELETE", fmt.Sprintf("/projects/%s", url.PathEscape(projectRef)), nil, jsonContent, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) GetProjectGroupSecrets(ctx context.Context, projectGroupRef string, tree bool) ([]*types.Secret, *http.Response, error) {
|
func (c *Client) GetProjectGroupSecrets(ctx context.Context, projectGroupRef string, tree bool) ([]*Secret, *http.Response, error) {
|
||||||
q := url.Values{}
|
q := url.Values{}
|
||||||
if tree {
|
if tree {
|
||||||
q.Add("tree", "")
|
q.Add("tree", "")
|
||||||
}
|
}
|
||||||
|
|
||||||
secrets := []*types.Secret{}
|
secrets := []*Secret{}
|
||||||
resp, err := c.getParsedResponse(ctx, "GET", fmt.Sprintf("/projectgroups/%s/secrets", url.PathEscape(projectGroupRef)), q, jsonContent, nil, &secrets)
|
resp, err := c.getParsedResponse(ctx, "GET", fmt.Sprintf("/projectgroups/%s/secrets", url.PathEscape(projectGroupRef)), q, jsonContent, nil, &secrets)
|
||||||
return secrets, resp, err
|
return secrets, resp, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) GetProjectSecrets(ctx context.Context, projectRef string, tree bool) ([]*types.Secret, *http.Response, error) {
|
func (c *Client) GetProjectSecrets(ctx context.Context, projectRef string, tree bool) ([]*Secret, *http.Response, error) {
|
||||||
q := url.Values{}
|
q := url.Values{}
|
||||||
if tree {
|
if tree {
|
||||||
q.Add("tree", "")
|
q.Add("tree", "")
|
||||||
}
|
}
|
||||||
|
|
||||||
secrets := []*types.Secret{}
|
secrets := []*Secret{}
|
||||||
resp, err := c.getParsedResponse(ctx, "GET", fmt.Sprintf("/projects/%s/secrets", url.PathEscape(projectRef)), q, jsonContent, nil, &secrets)
|
resp, err := c.getParsedResponse(ctx, "GET", fmt.Sprintf("/projects/%s/secrets", url.PathEscape(projectRef)), q, jsonContent, nil, &secrets)
|
||||||
return secrets, resp, err
|
return secrets, resp, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) CreateProjectGroupSecret(ctx context.Context, projectGroupRef string, secret *types.Secret) (*types.Secret, *http.Response, error) {
|
func (c *Client) CreateProjectGroupSecret(ctx context.Context, projectGroupRef string, secret *types.Secret) (*Secret, *http.Response, error) {
|
||||||
pj, err := json.Marshal(secret)
|
pj, err := json.Marshal(secret)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
secret = new(types.Secret)
|
resSecret := new(Secret)
|
||||||
resp, err := c.getParsedResponse(ctx, "POST", fmt.Sprintf("/projectgroups/%s/secrets", url.PathEscape(projectGroupRef)), nil, jsonContent, bytes.NewReader(pj), secret)
|
resp, err := c.getParsedResponse(ctx, "POST", fmt.Sprintf("/projectgroups/%s/secrets", url.PathEscape(projectGroupRef)), nil, jsonContent, bytes.NewReader(pj), resSecret)
|
||||||
return secret, resp, err
|
return resSecret, resp, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) CreateProjectSecret(ctx context.Context, projectRef string, secret *types.Secret) (*types.Secret, *http.Response, error) {
|
func (c *Client) CreateProjectSecret(ctx context.Context, projectRef string, secret *types.Secret) (*Secret, *http.Response, error) {
|
||||||
pj, err := json.Marshal(secret)
|
pj, err := json.Marshal(secret)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
secret = new(types.Secret)
|
resSecret := new(Secret)
|
||||||
resp, err := c.getParsedResponse(ctx, "POST", fmt.Sprintf("/projects/%s/secrets", url.PathEscape(projectRef)), nil, jsonContent, bytes.NewReader(pj), secret)
|
resp, err := c.getParsedResponse(ctx, "POST", fmt.Sprintf("/projects/%s/secrets", url.PathEscape(projectRef)), nil, jsonContent, bytes.NewReader(pj), resSecret)
|
||||||
return secret, resp, err
|
return resSecret, resp, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) DeleteProjectGroupSecret(ctx context.Context, projectGroupRef, secretName string) (*http.Response, error) {
|
func (c *Client) DeleteProjectGroupSecret(ctx context.Context, projectGroupRef, secretName string) (*http.Response, error) {
|
||||||
@ -208,48 +208,48 @@ func (c *Client) DeleteProjectSecret(ctx context.Context, projectRef, secretName
|
|||||||
return c.getResponse(ctx, "DELETE", fmt.Sprintf("/projects/%s/secrets/%s", url.PathEscape(projectRef), secretName), nil, jsonContent, nil)
|
return c.getResponse(ctx, "DELETE", fmt.Sprintf("/projects/%s/secrets/%s", url.PathEscape(projectRef), secretName), nil, jsonContent, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) GetProjectGroupVariables(ctx context.Context, projectGroupRef string, tree bool) ([]*types.Variable, *http.Response, error) {
|
func (c *Client) GetProjectGroupVariables(ctx context.Context, projectGroupRef string, tree bool) ([]*Variable, *http.Response, error) {
|
||||||
q := url.Values{}
|
q := url.Values{}
|
||||||
if tree {
|
if tree {
|
||||||
q.Add("tree", "")
|
q.Add("tree", "")
|
||||||
}
|
}
|
||||||
|
|
||||||
variables := []*types.Variable{}
|
variables := []*Variable{}
|
||||||
resp, err := c.getParsedResponse(ctx, "GET", fmt.Sprintf("/projectgroups/%s/variables", url.PathEscape(projectGroupRef)), q, jsonContent, nil, &variables)
|
resp, err := c.getParsedResponse(ctx, "GET", fmt.Sprintf("/projectgroups/%s/variables", url.PathEscape(projectGroupRef)), q, jsonContent, nil, &variables)
|
||||||
return variables, resp, err
|
return variables, resp, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) GetProjectVariables(ctx context.Context, projectRef string, tree bool) ([]*types.Variable, *http.Response, error) {
|
func (c *Client) GetProjectVariables(ctx context.Context, projectRef string, tree bool) ([]*Variable, *http.Response, error) {
|
||||||
q := url.Values{}
|
q := url.Values{}
|
||||||
if tree {
|
if tree {
|
||||||
q.Add("tree", "")
|
q.Add("tree", "")
|
||||||
}
|
}
|
||||||
|
|
||||||
variables := []*types.Variable{}
|
variables := []*Variable{}
|
||||||
resp, err := c.getParsedResponse(ctx, "GET", fmt.Sprintf("/projects/%s/variables", url.PathEscape(projectRef)), q, jsonContent, nil, &variables)
|
resp, err := c.getParsedResponse(ctx, "GET", fmt.Sprintf("/projects/%s/variables", url.PathEscape(projectRef)), q, jsonContent, nil, &variables)
|
||||||
return variables, resp, err
|
return variables, resp, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) CreateProjectGroupVariable(ctx context.Context, projectGroupRef string, variable *types.Variable) (*types.Variable, *http.Response, error) {
|
func (c *Client) CreateProjectGroupVariable(ctx context.Context, projectGroupRef string, variable *types.Variable) (*Variable, *http.Response, error) {
|
||||||
pj, err := json.Marshal(variable)
|
pj, err := json.Marshal(variable)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
variable = new(types.Variable)
|
resVariable := new(Variable)
|
||||||
resp, err := c.getParsedResponse(ctx, "POST", fmt.Sprintf("/projectgroups/%s/variables", url.PathEscape(projectGroupRef)), nil, jsonContent, bytes.NewReader(pj), variable)
|
resp, err := c.getParsedResponse(ctx, "POST", fmt.Sprintf("/projectgroups/%s/variables", url.PathEscape(projectGroupRef)), nil, jsonContent, bytes.NewReader(pj), resVariable)
|
||||||
return variable, resp, err
|
return resVariable, resp, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) CreateProjectVariable(ctx context.Context, projectRef string, variable *types.Variable) (*types.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 {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
variable = new(types.Variable)
|
resVariable := new(Variable)
|
||||||
resp, err := c.getParsedResponse(ctx, "POST", fmt.Sprintf("/projects/%s/variables", url.PathEscape(projectRef)), nil, jsonContent, bytes.NewReader(pj), variable)
|
resp, err := c.getParsedResponse(ctx, "POST", fmt.Sprintf("/projects/%s/variables", url.PathEscape(projectRef)), nil, jsonContent, bytes.NewReader(pj), resVariable)
|
||||||
return variable, resp, err
|
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) {
|
||||||
|
@ -29,6 +29,14 @@ import (
|
|||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Secret augments types.Secret with dynamic data
|
||||||
|
type Secret struct {
|
||||||
|
*types.Secret
|
||||||
|
|
||||||
|
// dynamic data
|
||||||
|
ParentPath string
|
||||||
|
}
|
||||||
|
|
||||||
type SecretHandler struct {
|
type SecretHandler struct {
|
||||||
log *zap.SugaredLogger
|
log *zap.SugaredLogger
|
||||||
readDB *readdb.ReadDB
|
readDB *readdb.ReadDB
|
||||||
@ -95,13 +103,27 @@ func (h *SecretsHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||||||
} else {
|
} else {
|
||||||
secrets, err = h.readDB.GetSecrets(tx, parentID)
|
secrets, err = h.readDB.GetSecrets(tx, parentID)
|
||||||
}
|
}
|
||||||
|
return err
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
h.log.Errorf("err: %+v", err)
|
||||||
|
httpError(w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
resSecrets := make([]*Secret, len(secrets))
|
||||||
|
for i, s := range secrets {
|
||||||
|
resSecrets[i] = &Secret{Secret: s}
|
||||||
|
}
|
||||||
|
|
||||||
|
err = h.readDB.Do(func(tx *db.Tx) error {
|
||||||
// populate parent path
|
// populate parent path
|
||||||
for _, s := range secrets {
|
for _, s := range resSecrets {
|
||||||
pp, err := h.readDB.GetParentPath(tx, s.Parent.Type, s.Parent.ID)
|
pp, err := h.readDB.GetParentPath(tx, s.Parent.Type, s.Parent.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
s.Parent.Path = pp
|
s.ParentPath = pp
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
})
|
})
|
||||||
@ -111,7 +133,7 @@ func (h *SecretsHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := httpResponse(w, http.StatusOK, secrets); err != nil {
|
if err := httpResponse(w, http.StatusOK, resSecrets); err != nil {
|
||||||
h.log.Errorf("err: %+v", err)
|
h.log.Errorf("err: %+v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,6 +28,14 @@ import (
|
|||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Variable augments types.Variable with dynamic data
|
||||||
|
type Variable struct {
|
||||||
|
*types.Variable
|
||||||
|
|
||||||
|
// dynamic data
|
||||||
|
ParentPath string
|
||||||
|
}
|
||||||
|
|
||||||
type VariablesHandler struct {
|
type VariablesHandler struct {
|
||||||
log *zap.SugaredLogger
|
log *zap.SugaredLogger
|
||||||
readDB *readdb.ReadDB
|
readDB *readdb.ReadDB
|
||||||
@ -59,13 +67,26 @@ func (h *VariablesHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||||||
} else {
|
} else {
|
||||||
variables, err = h.readDB.GetVariables(tx, parentID)
|
variables, err = h.readDB.GetVariables(tx, parentID)
|
||||||
}
|
}
|
||||||
|
return err
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
h.log.Errorf("err: %+v", err)
|
||||||
|
httpError(w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
resVariables := make([]*Variable, len(variables))
|
||||||
|
for i, v := range variables {
|
||||||
|
resVariables[i] = &Variable{Variable: v}
|
||||||
|
}
|
||||||
|
err = h.readDB.Do(func(tx *db.Tx) error {
|
||||||
// populate parent path
|
// populate parent path
|
||||||
for _, v := range variables {
|
for _, v := range resVariables {
|
||||||
pp, err := h.readDB.GetParentPath(tx, v.Parent.Type, v.Parent.ID)
|
pp, err := h.readDB.GetParentPath(tx, v.Parent.Type, v.Parent.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
v.Parent.Path = pp
|
v.ParentPath = pp
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
})
|
})
|
||||||
@ -75,7 +96,7 @@ func (h *VariablesHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := httpResponse(w, http.StatusOK, variables); err != nil {
|
if err := httpResponse(w, http.StatusOK, resVariables); err != nil {
|
||||||
h.log.Errorf("err: %+v", err)
|
h.log.Errorf("err: %+v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -108,8 +129,6 @@ func (h *CreateVariableHandler) ServeHTTP(w http.ResponseWriter, r *http.Request
|
|||||||
variable.Parent.Type = parentType
|
variable.Parent.Type = parentType
|
||||||
variable.Parent.ID = parentRef
|
variable.Parent.ID = parentRef
|
||||||
|
|
||||||
h.log.Infof("variable: %s", util.Dump(variable))
|
|
||||||
|
|
||||||
variable, err = h.ch.CreateVariable(ctx, variable)
|
variable, err = h.ch.CreateVariable(ctx, variable)
|
||||||
if httpError(w, err) {
|
if httpError(w, err) {
|
||||||
h.log.Errorf("err: %+v", err)
|
h.log.Errorf("err: %+v", err)
|
||||||
|
@ -33,11 +33,11 @@ type SecretResponse struct {
|
|||||||
ParentPath string `json:"parent_path"`
|
ParentPath string `json:"parent_path"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func createSecretResponse(s *types.Secret) *SecretResponse {
|
func createSecretResponse(s *csapi.Secret) *SecretResponse {
|
||||||
return &SecretResponse{
|
return &SecretResponse{
|
||||||
ID: s.ID,
|
ID: s.ID,
|
||||||
Name: s.Name,
|
Name: s.Name,
|
||||||
ParentPath: s.Parent.Path,
|
ParentPath: s.ParentPath,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -61,7 +61,7 @@ func (h *SecretHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var cssecrets []*types.Secret
|
var cssecrets []*csapi.Secret
|
||||||
var resp *http.Response
|
var resp *http.Response
|
||||||
switch parentType {
|
switch parentType {
|
||||||
case types.ConfigTypeProjectGroup:
|
case types.ConfigTypeProjectGroup:
|
||||||
@ -132,21 +132,22 @@ func (h *CreateSecretHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)
|
|||||||
}
|
}
|
||||||
|
|
||||||
var resp *http.Response
|
var resp *http.Response
|
||||||
|
var rs *csapi.Secret
|
||||||
switch parentType {
|
switch parentType {
|
||||||
case types.ConfigTypeProjectGroup:
|
case types.ConfigTypeProjectGroup:
|
||||||
h.log.Infof("creating project group secret")
|
h.log.Infof("creating project group secret")
|
||||||
s, resp, err = h.configstoreClient.CreateProjectGroupSecret(ctx, parentRef, s)
|
rs, resp, err = h.configstoreClient.CreateProjectGroupSecret(ctx, parentRef, s)
|
||||||
case types.ConfigTypeProject:
|
case types.ConfigTypeProject:
|
||||||
h.log.Infof("creating project secret")
|
h.log.Infof("creating project secret")
|
||||||
s, resp, err = h.configstoreClient.CreateProjectSecret(ctx, parentRef, s)
|
rs, resp, err = h.configstoreClient.CreateProjectSecret(ctx, parentRef, s)
|
||||||
}
|
}
|
||||||
if httpErrorFromRemote(w, resp, err) {
|
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", s.Name, s.ID)
|
h.log.Infof("secret %s created, ID: %s", rs.Name, rs.ID)
|
||||||
|
|
||||||
res := createSecretResponse(s)
|
res := createSecretResponse(rs)
|
||||||
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)
|
||||||
}
|
}
|
||||||
|
@ -43,12 +43,12 @@ type VariableResponse struct {
|
|||||||
ParentPath string `json:"parent_path"`
|
ParentPath string `json:"parent_path"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func createVariableResponse(v *types.Variable, secrets []*types.Secret) *VariableResponse {
|
func createVariableResponse(v *csapi.Variable, secrets []*csapi.Secret) *VariableResponse {
|
||||||
nv := &VariableResponse{
|
nv := &VariableResponse{
|
||||||
ID: v.ID,
|
ID: v.ID,
|
||||||
Name: v.Name,
|
Name: v.Name,
|
||||||
Values: make([]VariableValue, len(v.Values)),
|
Values: make([]VariableValue, len(v.Values)),
|
||||||
ParentPath: v.Parent.Path,
|
ParentPath: v.ParentPath,
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, varvalue := range v.Values {
|
for i, varvalue := range v.Values {
|
||||||
@ -58,9 +58,9 @@ func createVariableResponse(v *types.Variable, secrets []*types.Secret) *Variabl
|
|||||||
When: varvalue.When,
|
When: varvalue.When,
|
||||||
}
|
}
|
||||||
// get matching secret for var value
|
// get matching secret for var value
|
||||||
secret := common.GetVarValueMatchingSecret(varvalue, v.Parent.Path, secrets)
|
secret := common.GetVarValueMatchingSecret(varvalue, v.ParentPath, secrets)
|
||||||
if secret != nil {
|
if secret != nil {
|
||||||
nv.Values[i].MatchingSecretParentPath = secret.Parent.Path
|
nv.Values[i].MatchingSecretParentPath = secret.ParentPath
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -88,8 +88,8 @@ func (h *VariableHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var csvars []*types.Variable
|
var csvars []*csapi.Variable
|
||||||
var cssecrets []*types.Secret
|
var cssecrets []*csapi.Secret
|
||||||
|
|
||||||
switch parentType {
|
switch parentType {
|
||||||
case types.ConfigTypeProjectGroup:
|
case types.ConfigTypeProjectGroup:
|
||||||
@ -184,7 +184,8 @@ func (h *CreateVariableHandler) ServeHTTP(w http.ResponseWriter, r *http.Request
|
|||||||
Values: req.Values,
|
Values: req.Values,
|
||||||
}
|
}
|
||||||
|
|
||||||
var cssecrets []*types.Secret
|
var cssecrets []*csapi.Secret
|
||||||
|
var rv *csapi.Variable
|
||||||
|
|
||||||
switch parentType {
|
switch parentType {
|
||||||
case types.ConfigTypeProjectGroup:
|
case types.ConfigTypeProjectGroup:
|
||||||
@ -197,7 +198,7 @@ func (h *CreateVariableHandler) ServeHTTP(w http.ResponseWriter, r *http.Request
|
|||||||
}
|
}
|
||||||
|
|
||||||
h.log.Infof("creating project group variable")
|
h.log.Infof("creating project group variable")
|
||||||
v, resp, err = h.configstoreClient.CreateProjectGroupVariable(ctx, parentRef, v)
|
rv, resp, err = h.configstoreClient.CreateProjectGroupVariable(ctx, parentRef, v)
|
||||||
if httpErrorFromRemote(w, resp, err) {
|
if httpErrorFromRemote(w, resp, err) {
|
||||||
h.log.Errorf("err: %+v", err)
|
h.log.Errorf("err: %+v", err)
|
||||||
return
|
return
|
||||||
@ -212,15 +213,15 @@ func (h *CreateVariableHandler) ServeHTTP(w http.ResponseWriter, r *http.Request
|
|||||||
}
|
}
|
||||||
|
|
||||||
h.log.Infof("creating project variable")
|
h.log.Infof("creating project variable")
|
||||||
v, resp, err = h.configstoreClient.CreateProjectVariable(ctx, parentRef, v)
|
rv, resp, err = h.configstoreClient.CreateProjectVariable(ctx, parentRef, v)
|
||||||
if httpErrorFromRemote(w, resp, err) {
|
if httpErrorFromRemote(w, resp, err) {
|
||||||
h.log.Errorf("err: %+v", err)
|
h.log.Errorf("err: %+v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
h.log.Infof("variable %s created, ID: %s", v.Name, v.ID)
|
h.log.Infof("variable %s created, ID: %s", rv.Name, rv.ID)
|
||||||
|
|
||||||
res := createVariableResponse(v, cssecrets)
|
res := createVariableResponse(rv, cssecrets)
|
||||||
if err := httpResponse(w, http.StatusCreated, res); err != nil {
|
if err := httpResponse(w, http.StatusCreated, res); err != nil {
|
||||||
h.log.Errorf("err: %+v", err)
|
h.log.Errorf("err: %+v", err)
|
||||||
}
|
}
|
||||||
|
@ -15,20 +15,20 @@
|
|||||||
package common
|
package common
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"strings"
|
csapi "github.com/sorintlab/agola/internal/services/configstore/api"
|
||||||
|
|
||||||
"github.com/sorintlab/agola/internal/services/types"
|
"github.com/sorintlab/agola/internal/services/types"
|
||||||
|
"github.com/sorintlab/agola/internal/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
func FilterOverridenVariables(variables []*types.Variable) []*types.Variable {
|
func FilterOverridenVariables(variables []*csapi.Variable) []*csapi.Variable {
|
||||||
variablesMap := map[string]*types.Variable{}
|
variablesMap := map[string]*csapi.Variable{}
|
||||||
for _, v := range variables {
|
for _, v := range variables {
|
||||||
if _, ok := variablesMap[v.Name]; !ok {
|
if _, ok := variablesMap[v.Name]; !ok {
|
||||||
variablesMap[v.Name] = v
|
variablesMap[v.Name] = v
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
filteredVariables := make([]*types.Variable, len(variablesMap))
|
filteredVariables := make([]*csapi.Variable, len(variablesMap))
|
||||||
i := 0
|
i := 0
|
||||||
// keep the original order
|
// keep the original order
|
||||||
for _, v := range variables {
|
for _, v := range variables {
|
||||||
@ -43,15 +43,15 @@ func FilterOverridenVariables(variables []*types.Variable) []*types.Variable {
|
|||||||
return filteredVariables
|
return filteredVariables
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetVarValueMatchingSecret(varval types.VariableValue, varParentPath string, secrets []*types.Secret) *types.Secret {
|
func GetVarValueMatchingSecret(varval types.VariableValue, varParentPath string, secrets []*csapi.Secret) *csapi.Secret {
|
||||||
// get the secret value referenced by the variable, it must be a secret at the same level or a lower level
|
// get the secret value referenced by the variable, it must be a secret at the same level or a lower level
|
||||||
var secret *types.Secret
|
var secret *csapi.Secret
|
||||||
for _, s := range secrets {
|
for _, s := range secrets {
|
||||||
// we assume the root path will be the same
|
// we assume the root path will be the same
|
||||||
if s.Name != varval.SecretName {
|
if s.Name != varval.SecretName {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if strings.Contains(varParentPath, s.Parent.Path) {
|
if util.IsSameOrParentPath(s.ParentPath, varParentPath) {
|
||||||
secret = s
|
secret = s
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
@ -18,86 +18,87 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/google/go-cmp/cmp"
|
"github.com/google/go-cmp/cmp"
|
||||||
|
csapi "github.com/sorintlab/agola/internal/services/configstore/api"
|
||||||
"github.com/sorintlab/agola/internal/services/types"
|
"github.com/sorintlab/agola/internal/services/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestFilterOverridenVariables(t *testing.T) {
|
func TestFilterOverridenVariables(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
variables []*types.Variable
|
variables []*csapi.Variable
|
||||||
out []*types.Variable
|
out []*csapi.Variable
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "test empty variables",
|
name: "test empty variables",
|
||||||
variables: []*types.Variable{},
|
variables: []*csapi.Variable{},
|
||||||
out: []*types.Variable{},
|
out: []*csapi.Variable{},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "test variable overrides",
|
name: "test variable overrides",
|
||||||
variables: []*types.Variable{
|
variables: []*csapi.Variable{
|
||||||
// variables must be in depth (from leaves to root) order as returned by the
|
// variables must be in depth (from leaves to root) order as returned by the
|
||||||
// configstore apis
|
// configstore apis
|
||||||
&types.Variable{
|
&csapi.Variable{
|
||||||
|
Variable: &types.Variable{
|
||||||
Name: "var04",
|
Name: "var04",
|
||||||
Parent: types.Parent{
|
|
||||||
Path: "org/org01/projectgroup02/projectgroup03/project02",
|
|
||||||
},
|
},
|
||||||
|
ParentPath: "org/org01/projectgroup02/projectgroup03/project02",
|
||||||
},
|
},
|
||||||
&types.Variable{
|
&csapi.Variable{
|
||||||
|
Variable: &types.Variable{
|
||||||
Name: "var03",
|
Name: "var03",
|
||||||
Parent: types.Parent{
|
|
||||||
Path: "org/org01/projectgroup01/project01",
|
|
||||||
},
|
},
|
||||||
|
ParentPath: "org/org01/projectgroup01/project01",
|
||||||
},
|
},
|
||||||
&types.Variable{
|
&csapi.Variable{
|
||||||
|
Variable: &types.Variable{
|
||||||
Name: "var02",
|
Name: "var02",
|
||||||
Parent: types.Parent{
|
|
||||||
Path: "org/org01/projectgroup01/project01",
|
|
||||||
},
|
},
|
||||||
|
ParentPath: "org/org01/projectgroup01/project01",
|
||||||
},
|
},
|
||||||
&types.Variable{
|
&csapi.Variable{
|
||||||
|
Variable: &types.Variable{
|
||||||
Name: "var02",
|
Name: "var02",
|
||||||
Parent: types.Parent{
|
|
||||||
Path: "org/org01/projectgroup01",
|
|
||||||
},
|
},
|
||||||
|
ParentPath: "org/org01/projectgroup01",
|
||||||
},
|
},
|
||||||
&types.Variable{
|
&csapi.Variable{
|
||||||
|
Variable: &types.Variable{
|
||||||
Name: "var01",
|
Name: "var01",
|
||||||
Parent: types.Parent{
|
|
||||||
Path: "org/org01/projectgroup01",
|
|
||||||
},
|
},
|
||||||
|
ParentPath: "org/org01/projectgroup01",
|
||||||
},
|
},
|
||||||
&types.Variable{
|
&csapi.Variable{
|
||||||
|
Variable: &types.Variable{
|
||||||
Name: "var01",
|
Name: "var01",
|
||||||
Parent: types.Parent{
|
},
|
||||||
Path: "org/org01",
|
ParentPath: "org/org01",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
out: []*csapi.Variable{
|
||||||
out: []*types.Variable{
|
&csapi.Variable{
|
||||||
&types.Variable{
|
Variable: &types.Variable{
|
||||||
Name: "var04",
|
Name: "var04",
|
||||||
Parent: types.Parent{
|
|
||||||
Path: "org/org01/projectgroup02/projectgroup03/project02",
|
|
||||||
},
|
},
|
||||||
|
ParentPath: "org/org01/projectgroup02/projectgroup03/project02",
|
||||||
},
|
},
|
||||||
&types.Variable{
|
&csapi.Variable{
|
||||||
|
Variable: &types.Variable{
|
||||||
Name: "var03",
|
Name: "var03",
|
||||||
Parent: types.Parent{
|
|
||||||
Path: "org/org01/projectgroup01/project01",
|
|
||||||
},
|
},
|
||||||
|
ParentPath: "org/org01/projectgroup01/project01",
|
||||||
},
|
},
|
||||||
&types.Variable{
|
&csapi.Variable{
|
||||||
|
Variable: &types.Variable{
|
||||||
Name: "var02",
|
Name: "var02",
|
||||||
Parent: types.Parent{
|
|
||||||
Path: "org/org01/projectgroup01/project01",
|
|
||||||
},
|
},
|
||||||
|
ParentPath: "org/org01/projectgroup01/project01",
|
||||||
},
|
},
|
||||||
&types.Variable{
|
&csapi.Variable{
|
||||||
|
Variable: &types.Variable{
|
||||||
Name: "var01",
|
Name: "var01",
|
||||||
Parent: types.Parent{
|
|
||||||
Path: "org/org01/projectgroup01",
|
|
||||||
},
|
},
|
||||||
|
ParentPath: "org/org01/projectgroup01",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -119,8 +120,8 @@ func TestGetVarValueMatchingSecret(t *testing.T) {
|
|||||||
name string
|
name string
|
||||||
varValue types.VariableValue
|
varValue types.VariableValue
|
||||||
varParentPath string
|
varParentPath string
|
||||||
secrets []*types.Secret
|
secrets []*csapi.Secret
|
||||||
out *types.Secret
|
out *csapi.Secret
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "test empty secrets",
|
name: "test empty secrets",
|
||||||
@ -129,7 +130,7 @@ func TestGetVarValueMatchingSecret(t *testing.T) {
|
|||||||
SecretVar: "secretvar01",
|
SecretVar: "secretvar01",
|
||||||
},
|
},
|
||||||
varParentPath: "org/org01/projectgroup01/project01",
|
varParentPath: "org/org01/projectgroup01/project01",
|
||||||
secrets: []*types.Secret{},
|
secrets: []*csapi.Secret{},
|
||||||
out: nil,
|
out: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -139,12 +140,12 @@ func TestGetVarValueMatchingSecret(t *testing.T) {
|
|||||||
SecretVar: "secretvar01",
|
SecretVar: "secretvar01",
|
||||||
},
|
},
|
||||||
varParentPath: "org/org01/projectgroup01/projectgroup02",
|
varParentPath: "org/org01/projectgroup01/projectgroup02",
|
||||||
secrets: []*types.Secret{
|
secrets: []*csapi.Secret{
|
||||||
&types.Secret{
|
&csapi.Secret{
|
||||||
|
Secret: &types.Secret{
|
||||||
Name: "secret02",
|
Name: "secret02",
|
||||||
Parent: types.Parent{
|
|
||||||
Path: "org/org01/projectgroup01/projectgroup02",
|
|
||||||
},
|
},
|
||||||
|
ParentPath: "org/org01/projectgroup01/projectgroup02",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
out: nil,
|
out: nil,
|
||||||
@ -156,12 +157,12 @@ func TestGetVarValueMatchingSecret(t *testing.T) {
|
|||||||
SecretVar: "secretvar01",
|
SecretVar: "secretvar01",
|
||||||
},
|
},
|
||||||
varParentPath: "org/org01/projectgroup01/projectgroup02",
|
varParentPath: "org/org01/projectgroup01/projectgroup02",
|
||||||
secrets: []*types.Secret{
|
secrets: []*csapi.Secret{
|
||||||
&types.Secret{
|
&csapi.Secret{
|
||||||
|
Secret: &types.Secret{
|
||||||
Name: "secret02",
|
Name: "secret02",
|
||||||
Parent: types.Parent{
|
|
||||||
Path: "org/org01/projectgroup01/projectgroup03",
|
|
||||||
},
|
},
|
||||||
|
ParentPath: "org/org01/projectgroup01/projectgroup03",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
out: nil,
|
out: nil,
|
||||||
@ -173,12 +174,12 @@ func TestGetVarValueMatchingSecret(t *testing.T) {
|
|||||||
SecretVar: "secretvar01",
|
SecretVar: "secretvar01",
|
||||||
},
|
},
|
||||||
varParentPath: "org/org01/projectgroup01/projectgroup02",
|
varParentPath: "org/org01/projectgroup01/projectgroup02",
|
||||||
secrets: []*types.Secret{
|
secrets: []*csapi.Secret{
|
||||||
&types.Secret{
|
&csapi.Secret{
|
||||||
|
Secret: &types.Secret{
|
||||||
Name: "secret01",
|
Name: "secret01",
|
||||||
Parent: types.Parent{
|
|
||||||
Path: "org/org01/projectgroup01/projectgroup02/project01",
|
|
||||||
},
|
},
|
||||||
|
ParentPath: "org/org01/projectgroup01/projectgroup02/project01",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
out: nil,
|
out: nil,
|
||||||
@ -190,25 +191,25 @@ func TestGetVarValueMatchingSecret(t *testing.T) {
|
|||||||
SecretVar: "secretvar01",
|
SecretVar: "secretvar01",
|
||||||
},
|
},
|
||||||
varParentPath: "org/org01/projectgroup01/projectgroup02",
|
varParentPath: "org/org01/projectgroup01/projectgroup02",
|
||||||
secrets: []*types.Secret{
|
secrets: []*csapi.Secret{
|
||||||
&types.Secret{
|
&csapi.Secret{
|
||||||
|
Secret: &types.Secret{
|
||||||
Name: "secret01",
|
Name: "secret01",
|
||||||
Parent: types.Parent{
|
|
||||||
Path: "org/org01/projectgroup01/projectgroup02/project01",
|
|
||||||
},
|
},
|
||||||
|
ParentPath: "org/org01/projectgroup01/projectgroup02/project01",
|
||||||
},
|
},
|
||||||
&types.Secret{
|
&csapi.Secret{
|
||||||
|
Secret: &types.Secret{
|
||||||
Name: "secret01",
|
Name: "secret01",
|
||||||
Parent: types.Parent{
|
},
|
||||||
Path: "org/org01/projectgroup01/projectgroup02",
|
ParentPath: "org/org01/projectgroup01/projectgroup02",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
out: &csapi.Secret{
|
||||||
out: &types.Secret{
|
Secret: &types.Secret{
|
||||||
Name: "secret01",
|
Name: "secret01",
|
||||||
Parent: types.Parent{
|
|
||||||
Path: "org/org01/projectgroup01/projectgroup02",
|
|
||||||
},
|
},
|
||||||
|
ParentPath: "org/org01/projectgroup01/projectgroup02",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -218,19 +219,19 @@ func TestGetVarValueMatchingSecret(t *testing.T) {
|
|||||||
SecretVar: "secretvar01",
|
SecretVar: "secretvar01",
|
||||||
},
|
},
|
||||||
varParentPath: "org/org01/projectgroup01/projectgroup02",
|
varParentPath: "org/org01/projectgroup01/projectgroup02",
|
||||||
secrets: []*types.Secret{
|
secrets: []*csapi.Secret{
|
||||||
&types.Secret{
|
&csapi.Secret{
|
||||||
|
Secret: &types.Secret{
|
||||||
Name: "secret01",
|
Name: "secret01",
|
||||||
Parent: types.Parent{
|
},
|
||||||
Path: "org/org01/projectgroup01",
|
ParentPath: "org/org01/projectgroup01",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
out: &csapi.Secret{
|
||||||
out: &types.Secret{
|
Secret: &types.Secret{
|
||||||
Name: "secret01",
|
Name: "secret01",
|
||||||
Parent: types.Parent{
|
|
||||||
Path: "org/org01/projectgroup01",
|
|
||||||
},
|
},
|
||||||
|
ParentPath: "org/org01/projectgroup01",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -240,33 +241,33 @@ func TestGetVarValueMatchingSecret(t *testing.T) {
|
|||||||
SecretVar: "secretvar01",
|
SecretVar: "secretvar01",
|
||||||
},
|
},
|
||||||
varParentPath: "org/org01/projectgroup01/projectgroup02",
|
varParentPath: "org/org01/projectgroup01/projectgroup02",
|
||||||
secrets: []*types.Secret{
|
secrets: []*csapi.Secret{
|
||||||
// secrets must be in depth (from leaves to root) order as returned by the
|
// secrets must be in depth (from leaves to root) order as returned by the
|
||||||
// configstore apis
|
// configstore apis
|
||||||
&types.Secret{
|
&csapi.Secret{
|
||||||
|
Secret: &types.Secret{
|
||||||
Name: "secret01",
|
Name: "secret01",
|
||||||
Parent: types.Parent{
|
|
||||||
Path: "org/org01/projectgroup01/projectgroup02/project01",
|
|
||||||
},
|
},
|
||||||
|
ParentPath: "org/org01/projectgroup01/projectgroup02/project01",
|
||||||
},
|
},
|
||||||
&types.Secret{
|
&csapi.Secret{
|
||||||
|
Secret: &types.Secret{
|
||||||
Name: "secret01",
|
Name: "secret01",
|
||||||
Parent: types.Parent{
|
|
||||||
Path: "org/org01/projectgroup01/projectgroup02",
|
|
||||||
},
|
},
|
||||||
|
ParentPath: "org/org01/projectgroup01/projectgroup02",
|
||||||
},
|
},
|
||||||
&types.Secret{
|
&csapi.Secret{
|
||||||
|
Secret: &types.Secret{
|
||||||
Name: "secret01",
|
Name: "secret01",
|
||||||
Parent: types.Parent{
|
},
|
||||||
Path: "org/org01/projectgroup01",
|
ParentPath: "org/org01/projectgroup01",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
out: &csapi.Secret{
|
||||||
out: &types.Secret{
|
Secret: &types.Secret{
|
||||||
Name: "secret01",
|
Name: "secret01",
|
||||||
Parent: types.Parent{
|
|
||||||
Path: "org/org01/projectgroup01/projectgroup02",
|
|
||||||
},
|
},
|
||||||
|
ParentPath: "org/org01/projectgroup01/projectgroup02",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -217,7 +217,7 @@ func (h *webhooksHandler) handleWebhook(r *http.Request) (int, string, error) {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
// get the secret value referenced by the variable, it must be a secret at the same level or a lower level
|
// get the secret value referenced by the variable, it must be a secret at the same level or a lower level
|
||||||
secret := common.GetVarValueMatchingSecret(varval, pvar.Parent.Path, secrets)
|
secret := common.GetVarValueMatchingSecret(varval, pvar.ParentPath, secrets)
|
||||||
h.log.Infof("secret: %v", util.Dump(secret))
|
h.log.Infof("secret: %v", util.Dump(secret))
|
||||||
if secret != nil {
|
if secret != nil {
|
||||||
varValue, ok := secret.Data[varval.SecretVar]
|
varValue, ok := secret.Data[varval.SecretVar]
|
||||||
|
@ -36,9 +36,6 @@ const (
|
|||||||
type Parent struct {
|
type Parent struct {
|
||||||
Type ConfigType `json:"type,omitempty"`
|
Type ConfigType `json:"type,omitempty"`
|
||||||
ID string `json:"id,omitempty"`
|
ID string `json:"id,omitempty"`
|
||||||
|
|
||||||
// fields the is only used in api response and shoukd be empty when saved in the store
|
|
||||||
Path string `json:"path,omitempty"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type User struct {
|
type User struct {
|
||||||
|
Loading…
Reference in New Issue
Block a user