configstore: add project/projectgroup visibility
This commit is contained in:
parent
b1c9892378
commit
68e6bd5bdf
|
@ -19,6 +19,7 @@ import (
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/sorintlab/agola/internal/services/gateway/api"
|
"github.com/sorintlab/agola/internal/services/gateway/api"
|
||||||
|
"github.com/sorintlab/agola/internal/services/types"
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
@ -39,6 +40,7 @@ type projectCreateOptions struct {
|
||||||
repoPath string
|
repoPath string
|
||||||
remoteSourceName string
|
remoteSourceName string
|
||||||
skipSSHHostKeyCheck bool
|
skipSSHHostKeyCheck bool
|
||||||
|
visibility string
|
||||||
}
|
}
|
||||||
|
|
||||||
var projectCreateOpts projectCreateOptions
|
var projectCreateOpts projectCreateOptions
|
||||||
|
@ -51,6 +53,7 @@ func init() {
|
||||||
flags.StringVar(&projectCreateOpts.remoteSourceName, "remote-source", "", "remote source name")
|
flags.StringVar(&projectCreateOpts.remoteSourceName, "remote-source", "", "remote source name")
|
||||||
flags.BoolVarP(&projectCreateOpts.skipSSHHostKeyCheck, "skip-ssh-host-key-check", "s", false, "skip ssh host key check")
|
flags.BoolVarP(&projectCreateOpts.skipSSHHostKeyCheck, "skip-ssh-host-key-check", "s", false, "skip ssh host key check")
|
||||||
flags.StringVar(&projectCreateOpts.parentPath, "parent", "", `parent project group path (i.e "org/org01" for root project group in org01, "user/user01/group01/subgroub01") or project group id where the project should be created`)
|
flags.StringVar(&projectCreateOpts.parentPath, "parent", "", `parent project group path (i.e "org/org01" for root project group in org01, "user/user01/group01/subgroub01") or project group id where the project should be created`)
|
||||||
|
flags.StringVar(&projectCreateOpts.visibility, "visibility", "public", `project visibility (public or private)`)
|
||||||
|
|
||||||
cmdProjectCreate.MarkFlagRequired("name")
|
cmdProjectCreate.MarkFlagRequired("name")
|
||||||
cmdProjectCreate.MarkFlagRequired("parent")
|
cmdProjectCreate.MarkFlagRequired("parent")
|
||||||
|
@ -63,9 +66,15 @@ func init() {
|
||||||
func projectCreate(cmd *cobra.Command, args []string) error {
|
func projectCreate(cmd *cobra.Command, args []string) error {
|
||||||
gwclient := api.NewClient(gatewayURL, token)
|
gwclient := api.NewClient(gatewayURL, token)
|
||||||
|
|
||||||
|
// TODO(sgotti) make this a custom pflag Value?
|
||||||
|
if !types.IsValidVisibility(types.Visibility(projectCreateOpts.visibility)) {
|
||||||
|
return errors.Errorf("invalid visibility %q", projectCreateOpts.visibility)
|
||||||
|
}
|
||||||
|
|
||||||
req := &api.CreateProjectRequest{
|
req := &api.CreateProjectRequest{
|
||||||
Name: projectCreateOpts.name,
|
Name: projectCreateOpts.name,
|
||||||
ParentID: projectCreateOpts.parentPath,
|
ParentID: projectCreateOpts.parentPath,
|
||||||
|
Visibility: types.Visibility(projectCreateOpts.visibility),
|
||||||
RepoPath: projectCreateOpts.repoPath,
|
RepoPath: projectCreateOpts.repoPath,
|
||||||
RemoteSourceName: projectCreateOpts.remoteSourceName,
|
RemoteSourceName: projectCreateOpts.remoteSourceName,
|
||||||
SkipSSHHostKeyCheck: projectCreateOpts.skipSSHHostKeyCheck,
|
SkipSSHHostKeyCheck: projectCreateOpts.skipSSHHostKeyCheck,
|
||||||
|
|
|
@ -19,6 +19,7 @@ import (
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/sorintlab/agola/internal/services/gateway/api"
|
"github.com/sorintlab/agola/internal/services/gateway/api"
|
||||||
|
"github.com/sorintlab/agola/internal/services/types"
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
@ -36,6 +37,7 @@ var cmdProjectGroupCreate = &cobra.Command{
|
||||||
type projectGroupCreateOptions struct {
|
type projectGroupCreateOptions struct {
|
||||||
name string
|
name string
|
||||||
parentPath string
|
parentPath string
|
||||||
|
visibility string
|
||||||
}
|
}
|
||||||
|
|
||||||
var projectGroupCreateOpts projectGroupCreateOptions
|
var projectGroupCreateOpts projectGroupCreateOptions
|
||||||
|
@ -45,6 +47,7 @@ func init() {
|
||||||
|
|
||||||
flags.StringVarP(&projectGroupCreateOpts.name, "name", "n", "", "project group name")
|
flags.StringVarP(&projectGroupCreateOpts.name, "name", "n", "", "project group name")
|
||||||
flags.StringVar(&projectGroupCreateOpts.parentPath, "parent", "", `parent project group path (i.e "org/org01" for root project group in org01, "user/user01/group01/subgroub01") or project group id where the project group should be created`)
|
flags.StringVar(&projectGroupCreateOpts.parentPath, "parent", "", `parent project group path (i.e "org/org01" for root project group in org01, "user/user01/group01/subgroub01") or project group id where the project group should be created`)
|
||||||
|
flags.StringVar(&projectGroupCreateOpts.visibility, "visibility", "public", `project group visibility (public or private)`)
|
||||||
|
|
||||||
cmdProjectGroupCreate.MarkFlagRequired("name")
|
cmdProjectGroupCreate.MarkFlagRequired("name")
|
||||||
cmdProjectGroupCreate.MarkFlagRequired("parent")
|
cmdProjectGroupCreate.MarkFlagRequired("parent")
|
||||||
|
@ -55,9 +58,15 @@ func init() {
|
||||||
func projectGroupCreate(cmd *cobra.Command, args []string) error {
|
func projectGroupCreate(cmd *cobra.Command, args []string) error {
|
||||||
gwclient := api.NewClient(gatewayURL, token)
|
gwclient := api.NewClient(gatewayURL, token)
|
||||||
|
|
||||||
|
// TODO(sgotti) make this a custom pflag Value?
|
||||||
|
if !types.IsValidVisibility(types.Visibility(projectCreateOpts.visibility)) {
|
||||||
|
return errors.Errorf("invalid visibility %q", projectCreateOpts.visibility)
|
||||||
|
}
|
||||||
|
|
||||||
req := &api.CreateProjectGroupRequest{
|
req := &api.CreateProjectGroupRequest{
|
||||||
Name: projectGroupCreateOpts.name,
|
Name: projectGroupCreateOpts.name,
|
||||||
ParentID: projectGroupCreateOpts.parentPath,
|
ParentID: projectGroupCreateOpts.parentPath,
|
||||||
|
Visibility: types.Visibility(projectCreateOpts.visibility),
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Infof("creating project group")
|
log.Infof("creating project group")
|
||||||
|
|
|
@ -37,8 +37,9 @@ type Project struct {
|
||||||
*types.Project
|
*types.Project
|
||||||
|
|
||||||
// dynamic data
|
// dynamic data
|
||||||
Path string
|
Path string
|
||||||
ParentPath string
|
ParentPath string
|
||||||
|
GlobalVisibility types.Visibility
|
||||||
}
|
}
|
||||||
|
|
||||||
func projectResponse(readDB *readdb.ReadDB, project *types.Project) (*Project, error) {
|
func projectResponse(readDB *readdb.ReadDB, project *types.Project) (*Project, error) {
|
||||||
|
@ -58,20 +59,51 @@ func projectsResponse(readDB *readdb.ReadDB, projects []*types.Project) ([]*Proj
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// calculate global visibility
|
||||||
|
visibility, err := getGlobalVisibility(readDB, tx, project.Visibility, &project.Parent)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
// we calculate the path here from parent path since the db could not yet be
|
// we calculate the path here from parent path since the db could not yet be
|
||||||
// updated on create
|
// updated on create
|
||||||
resProjects[i] = &Project{
|
resProjects[i] = &Project{
|
||||||
Project: project,
|
Project: project,
|
||||||
Path: path.Join(pp, project.Name),
|
Path: path.Join(pp, project.Name),
|
||||||
ParentPath: pp,
|
ParentPath: pp,
|
||||||
|
GlobalVisibility: visibility,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
|
|
||||||
return resProjects, err
|
return resProjects, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getGlobalVisibility(readDB *readdb.ReadDB, tx *db.Tx, curVisibility types.Visibility, parent *types.Parent) (types.Visibility, error) {
|
||||||
|
curParent := parent
|
||||||
|
if curVisibility == types.VisibilityPrivate {
|
||||||
|
return curVisibility, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
for curParent.Type == types.ConfigTypeProjectGroup {
|
||||||
|
projectGroup, err := readDB.GetProjectGroupByID(tx, curParent.ID)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
if projectGroup.Visibility == types.VisibilityPrivate {
|
||||||
|
curVisibility = types.VisibilityPrivate
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
curParent = &projectGroup.Parent
|
||||||
|
}
|
||||||
|
|
||||||
|
return curVisibility, nil
|
||||||
|
}
|
||||||
|
|
||||||
type ProjectHandler struct {
|
type ProjectHandler struct {
|
||||||
log *zap.SugaredLogger
|
log *zap.SugaredLogger
|
||||||
readDB *readdb.ReadDB
|
readDB *readdb.ReadDB
|
||||||
|
|
|
@ -36,8 +36,9 @@ type ProjectGroup struct {
|
||||||
*types.ProjectGroup
|
*types.ProjectGroup
|
||||||
|
|
||||||
// dynamic data
|
// dynamic data
|
||||||
Path string
|
Path string
|
||||||
ParentPath string
|
ParentPath string
|
||||||
|
GlobalVisibility types.Visibility
|
||||||
}
|
}
|
||||||
|
|
||||||
func projectGroupResponse(readDB *readdb.ReadDB, projectGroup *types.ProjectGroup) (*ProjectGroup, error) {
|
func projectGroupResponse(readDB *readdb.ReadDB, projectGroup *types.ProjectGroup) (*ProjectGroup, error) {
|
||||||
|
@ -57,13 +58,22 @@ func projectGroupsResponse(readDB *readdb.ReadDB, projectGroups []*types.Project
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// calculate global visibility
|
||||||
|
visibility, err := getGlobalVisibility(readDB, tx, projectGroup.Visibility, &projectGroup.Parent)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
// we calculate the path here from parent path since the db could not yet be
|
// we calculate the path here from parent path since the db could not yet be
|
||||||
// updated on create
|
// updated on create
|
||||||
resProjectGroups[i] = &ProjectGroup{
|
resProjectGroups[i] = &ProjectGroup{
|
||||||
ProjectGroup: projectGroup,
|
ProjectGroup: projectGroup,
|
||||||
Path: path.Join(pp, projectGroup.Name),
|
Path: path.Join(pp, projectGroup.Name),
|
||||||
ParentPath: pp,
|
ParentPath: pp,
|
||||||
|
GlobalVisibility: visibility,
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
|
|
|
@ -52,6 +52,9 @@ func (s *CommandHandler) CreateProjectGroup(ctx context.Context, projectGroup *t
|
||||||
if projectGroup.Parent.ID == "" {
|
if projectGroup.Parent.ID == "" {
|
||||||
return nil, util.NewErrBadRequest(errors.Errorf("project group parent id required"))
|
return nil, util.NewErrBadRequest(errors.Errorf("project group parent id required"))
|
||||||
}
|
}
|
||||||
|
if !types.IsValidVisibility(projectGroup.Visibility) {
|
||||||
|
return nil, util.NewErrBadRequest(errors.Errorf("invalid project group visibility"))
|
||||||
|
}
|
||||||
|
|
||||||
var cgt *datamanager.ChangeGroupsUpdateToken
|
var cgt *datamanager.ChangeGroupsUpdateToken
|
||||||
|
|
||||||
|
@ -129,6 +132,9 @@ func (s *CommandHandler) CreateProject(ctx context.Context, project *types.Proje
|
||||||
if project.Parent.ID == "" {
|
if project.Parent.ID == "" {
|
||||||
return nil, util.NewErrBadRequest(errors.Errorf("project parent id required"))
|
return nil, util.NewErrBadRequest(errors.Errorf("project parent id required"))
|
||||||
}
|
}
|
||||||
|
if !types.IsValidVisibility(project.Visibility) {
|
||||||
|
return nil, util.NewErrBadRequest(errors.Errorf("invalid project visibility"))
|
||||||
|
}
|
||||||
|
|
||||||
var cgt *datamanager.ChangeGroupsUpdateToken
|
var cgt *datamanager.ChangeGroupsUpdateToken
|
||||||
|
|
||||||
|
|
|
@ -394,37 +394,37 @@ func TestProjectGroupsAndProjects(t *testing.T) {
|
||||||
time.Sleep(2 * time.Second)
|
time.Sleep(2 * time.Second)
|
||||||
|
|
||||||
t.Run("create a project in user root project group", func(t *testing.T) {
|
t.Run("create a project in user root project group", func(t *testing.T) {
|
||||||
_, err := cs.ch.CreateProject(ctx, &types.Project{Name: "project01", Parent: types.Parent{Type: types.ConfigTypeProjectGroup, ID: path.Join("user", user.Name)}})
|
_, err := cs.ch.CreateProject(ctx, &types.Project{Name: "project01", Parent: types.Parent{Type: types.ConfigTypeProjectGroup, ID: path.Join("user", user.Name)}, Visibility: types.VisibilityPublic})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected err: %v", err)
|
t.Fatalf("unexpected err: %v", err)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
t.Run("create a project in org root project group", func(t *testing.T) {
|
t.Run("create a project in org root project group", func(t *testing.T) {
|
||||||
_, err := cs.ch.CreateProject(ctx, &types.Project{Name: "project01", Parent: types.Parent{Type: types.ConfigTypeProjectGroup, ID: path.Join("org", org.Name)}})
|
_, err := cs.ch.CreateProject(ctx, &types.Project{Name: "project01", Parent: types.Parent{Type: types.ConfigTypeProjectGroup, ID: path.Join("org", org.Name)}, Visibility: types.VisibilityPublic})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected err: %v", err)
|
t.Fatalf("unexpected err: %v", err)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
t.Run("create a projectgroup in user root project group", func(t *testing.T) {
|
t.Run("create a projectgroup in user root project group", func(t *testing.T) {
|
||||||
_, err := cs.ch.CreateProjectGroup(ctx, &types.ProjectGroup{Name: "projectgroup01", Parent: types.Parent{Type: types.ConfigTypeProjectGroup, ID: path.Join("user", user.Name)}})
|
_, err := cs.ch.CreateProjectGroup(ctx, &types.ProjectGroup{Name: "projectgroup01", Parent: types.Parent{Type: types.ConfigTypeProjectGroup, ID: path.Join("user", user.Name)}, Visibility: types.VisibilityPublic})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected err: %v", err)
|
t.Fatalf("unexpected err: %v", err)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
t.Run("create a projectgroup in org root project group", func(t *testing.T) {
|
t.Run("create a projectgroup in org root project group", func(t *testing.T) {
|
||||||
_, err := cs.ch.CreateProjectGroup(ctx, &types.ProjectGroup{Name: "projectgroup01", Parent: types.Parent{Type: types.ConfigTypeProjectGroup, ID: path.Join("org", org.Name)}})
|
_, err := cs.ch.CreateProjectGroup(ctx, &types.ProjectGroup{Name: "projectgroup01", Parent: types.Parent{Type: types.ConfigTypeProjectGroup, ID: path.Join("org", org.Name)}, Visibility: types.VisibilityPublic})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected err: %v", err)
|
t.Fatalf("unexpected err: %v", err)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
t.Run("create a project in user non root project group with same name as a root project", func(t *testing.T) {
|
t.Run("create a project in user non root project group with same name as a root project", func(t *testing.T) {
|
||||||
_, err := cs.ch.CreateProject(ctx, &types.Project{Name: "project01", Parent: types.Parent{Type: types.ConfigTypeProjectGroup, ID: path.Join("user", user.Name, "projectgroup01")}})
|
_, err := cs.ch.CreateProject(ctx, &types.Project{Name: "project01", Parent: types.Parent{Type: types.ConfigTypeProjectGroup, ID: path.Join("user", user.Name, "projectgroup01")}, Visibility: types.VisibilityPublic})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected err: %+#v", err)
|
t.Fatalf("unexpected err: %+#v", err)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
t.Run("create a project in org non root project group with same name as a root project", func(t *testing.T) {
|
t.Run("create a project in org non root project group with same name as a root project", func(t *testing.T) {
|
||||||
_, err := cs.ch.CreateProject(ctx, &types.Project{Name: "project01", Parent: types.Parent{Type: types.ConfigTypeProjectGroup, ID: path.Join("org", org.Name, "projectgroup01")}})
|
_, err := cs.ch.CreateProject(ctx, &types.Project{Name: "project01", Parent: types.Parent{Type: types.ConfigTypeProjectGroup, ID: path.Join("org", org.Name, "projectgroup01")}, Visibility: types.VisibilityPublic})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected err: %v", err)
|
t.Fatalf("unexpected err: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -433,7 +433,7 @@ func TestProjectGroupsAndProjects(t *testing.T) {
|
||||||
t.Run("create duplicated project in user root project group", func(t *testing.T) {
|
t.Run("create duplicated project in user root project group", func(t *testing.T) {
|
||||||
projectName := "project01"
|
projectName := "project01"
|
||||||
expectedErr := fmt.Sprintf("project with name %q, path %q already exists", projectName, path.Join("user", user.Name, projectName))
|
expectedErr := fmt.Sprintf("project with name %q, path %q already exists", projectName, path.Join("user", user.Name, projectName))
|
||||||
_, err := cs.ch.CreateProject(ctx, &types.Project{Name: projectName, Parent: types.Parent{Type: types.ConfigTypeProjectGroup, ID: path.Join("user", user.Name)}})
|
_, err := cs.ch.CreateProject(ctx, &types.Project{Name: projectName, Parent: types.Parent{Type: types.ConfigTypeProjectGroup, ID: path.Join("user", user.Name)}, Visibility: types.VisibilityPublic})
|
||||||
if err.Error() != expectedErr {
|
if err.Error() != expectedErr {
|
||||||
t.Fatalf("expected err %v, got err: %v", expectedErr, err)
|
t.Fatalf("expected err %v, got err: %v", expectedErr, err)
|
||||||
}
|
}
|
||||||
|
@ -441,7 +441,7 @@ func TestProjectGroupsAndProjects(t *testing.T) {
|
||||||
t.Run("create duplicated project in org root project group", func(t *testing.T) {
|
t.Run("create duplicated project in org root project group", func(t *testing.T) {
|
||||||
projectName := "project01"
|
projectName := "project01"
|
||||||
expectedErr := fmt.Sprintf("project with name %q, path %q already exists", projectName, path.Join("org", org.Name, projectName))
|
expectedErr := fmt.Sprintf("project with name %q, path %q already exists", projectName, path.Join("org", org.Name, projectName))
|
||||||
_, err := cs.ch.CreateProject(ctx, &types.Project{Name: projectName, Parent: types.Parent{Type: types.ConfigTypeProjectGroup, ID: path.Join("org", org.Name)}})
|
_, err := cs.ch.CreateProject(ctx, &types.Project{Name: projectName, Parent: types.Parent{Type: types.ConfigTypeProjectGroup, ID: path.Join("org", org.Name)}, Visibility: types.VisibilityPublic})
|
||||||
if err.Error() != expectedErr {
|
if err.Error() != expectedErr {
|
||||||
t.Fatalf("expected err %v, got err: %v", expectedErr, err)
|
t.Fatalf("expected err %v, got err: %v", expectedErr, err)
|
||||||
}
|
}
|
||||||
|
@ -450,7 +450,7 @@ func TestProjectGroupsAndProjects(t *testing.T) {
|
||||||
t.Run("create duplicated project in user non root project group", func(t *testing.T) {
|
t.Run("create duplicated project in user non root project group", func(t *testing.T) {
|
||||||
projectName := "project01"
|
projectName := "project01"
|
||||||
expectedErr := fmt.Sprintf("project with name %q, path %q already exists", projectName, path.Join("user", user.Name, "projectgroup01", projectName))
|
expectedErr := fmt.Sprintf("project with name %q, path %q already exists", projectName, path.Join("user", user.Name, "projectgroup01", projectName))
|
||||||
_, err := cs.ch.CreateProject(ctx, &types.Project{Name: projectName, Parent: types.Parent{Type: types.ConfigTypeProjectGroup, ID: path.Join("user", user.Name, "projectgroup01")}})
|
_, err := cs.ch.CreateProject(ctx, &types.Project{Name: projectName, Parent: types.Parent{Type: types.ConfigTypeProjectGroup, ID: path.Join("user", user.Name, "projectgroup01")}, Visibility: types.VisibilityPublic})
|
||||||
if err.Error() != expectedErr {
|
if err.Error() != expectedErr {
|
||||||
t.Fatalf("expected err %v, got err: %v", expectedErr, err)
|
t.Fatalf("expected err %v, got err: %v", expectedErr, err)
|
||||||
}
|
}
|
||||||
|
@ -458,7 +458,7 @@ func TestProjectGroupsAndProjects(t *testing.T) {
|
||||||
t.Run("create duplicated project in org non root project group", func(t *testing.T) {
|
t.Run("create duplicated project in org non root project group", func(t *testing.T) {
|
||||||
projectName := "project01"
|
projectName := "project01"
|
||||||
expectedErr := fmt.Sprintf("project with name %q, path %q already exists", projectName, path.Join("org", org.Name, "projectgroup01", projectName))
|
expectedErr := fmt.Sprintf("project with name %q, path %q already exists", projectName, path.Join("org", org.Name, "projectgroup01", projectName))
|
||||||
_, err := cs.ch.CreateProject(ctx, &types.Project{Name: projectName, Parent: types.Parent{Type: types.ConfigTypeProjectGroup, ID: path.Join("org", org.Name, "projectgroup01")}})
|
_, err := cs.ch.CreateProject(ctx, &types.Project{Name: projectName, Parent: types.Parent{Type: types.ConfigTypeProjectGroup, ID: path.Join("org", org.Name, "projectgroup01")}, Visibility: types.VisibilityPublic})
|
||||||
if err.Error() != expectedErr {
|
if err.Error() != expectedErr {
|
||||||
t.Fatalf("expected err %v, got err: %v", expectedErr, err)
|
t.Fatalf("expected err %v, got err: %v", expectedErr, err)
|
||||||
}
|
}
|
||||||
|
@ -466,14 +466,14 @@ func TestProjectGroupsAndProjects(t *testing.T) {
|
||||||
|
|
||||||
t.Run("create project in unexistent project group", func(t *testing.T) {
|
t.Run("create project in unexistent project group", func(t *testing.T) {
|
||||||
expectedErr := `project group with id "unexistentid" doesn't exist`
|
expectedErr := `project group with id "unexistentid" doesn't exist`
|
||||||
_, err := cs.ch.CreateProject(ctx, &types.Project{Name: "project01", Parent: types.Parent{Type: types.ConfigTypeProjectGroup, ID: "unexistentid"}})
|
_, err := cs.ch.CreateProject(ctx, &types.Project{Name: "project01", Parent: types.Parent{Type: types.ConfigTypeProjectGroup, ID: "unexistentid"}, Visibility: types.VisibilityPublic})
|
||||||
if err.Error() != expectedErr {
|
if err.Error() != expectedErr {
|
||||||
t.Fatalf("expected err %v, got err: %v", expectedErr, err)
|
t.Fatalf("expected err %v, got err: %v", expectedErr, err)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
t.Run("create project without parent id specified", func(t *testing.T) {
|
t.Run("create project without parent id specified", func(t *testing.T) {
|
||||||
expectedErr := "project parent id required"
|
expectedErr := "project parent id required"
|
||||||
_, err := cs.ch.CreateProject(ctx, &types.Project{Name: "project01"})
|
_, err := cs.ch.CreateProject(ctx, &types.Project{Name: "project01", Visibility: types.VisibilityPublic})
|
||||||
if err.Error() != expectedErr {
|
if err.Error() != expectedErr {
|
||||||
t.Fatalf("expected err %v, got err: %v", expectedErr, err)
|
t.Fatalf("expected err %v, got err: %v", expectedErr, err)
|
||||||
}
|
}
|
||||||
|
@ -488,7 +488,7 @@ func TestProjectGroupsAndProjects(t *testing.T) {
|
||||||
wg := sync.WaitGroup{}
|
wg := sync.WaitGroup{}
|
||||||
for i := 0; i < 10; i++ {
|
for i := 0; i < 10; i++ {
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
go cs.ch.CreateProject(ctx, &types.Project{Name: "project02", Parent: types.Parent{Type: types.ConfigTypeProjectGroup, ID: path.Join("user", user.Name)}})
|
go cs.ch.CreateProject(ctx, &types.Project{Name: "project02", Parent: types.Parent{Type: types.ConfigTypeProjectGroup, ID: path.Join("user", user.Name)}, Visibility: types.VisibilityPublic})
|
||||||
wg.Done()
|
wg.Done()
|
||||||
}
|
}
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
|
|
|
@ -22,6 +22,7 @@ import (
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
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/command"
|
"github.com/sorintlab/agola/internal/services/gateway/command"
|
||||||
|
"github.com/sorintlab/agola/internal/services/types"
|
||||||
"github.com/sorintlab/agola/internal/util"
|
"github.com/sorintlab/agola/internal/util"
|
||||||
|
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
|
@ -29,11 +30,12 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type CreateProjectRequest struct {
|
type CreateProjectRequest struct {
|
||||||
Name string `json:"name,omitempty"`
|
Name string `json:"name,omitempty"`
|
||||||
ParentID string `json:"parent_id,omitempty"`
|
ParentID string `json:"parent_id,omitempty"`
|
||||||
RepoPath string `json:"repo_path,omitempty"`
|
Visibility types.Visibility `json:"visibility,omitempty"`
|
||||||
RemoteSourceName string `json:"remote_source_name,omitempty"`
|
RepoPath string `json:"repo_path,omitempty"`
|
||||||
SkipSSHHostKeyCheck bool `json:"skip_ssh_host_key_check,omitempty"`
|
RemoteSourceName string `json:"remote_source_name,omitempty"`
|
||||||
|
SkipSSHHostKeyCheck bool `json:"skip_ssh_host_key_check,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type CreateProjectHandler struct {
|
type CreateProjectHandler struct {
|
||||||
|
@ -68,6 +70,7 @@ func (h *CreateProjectHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)
|
||||||
creq := &command.CreateProjectRequest{
|
creq := &command.CreateProjectRequest{
|
||||||
Name: req.Name,
|
Name: req.Name,
|
||||||
ParentID: req.ParentID,
|
ParentID: req.ParentID,
|
||||||
|
Visibility: req.Visibility,
|
||||||
RepoPath: req.RepoPath,
|
RepoPath: req.RepoPath,
|
||||||
RemoteSourceName: req.RemoteSourceName,
|
RemoteSourceName: req.RemoteSourceName,
|
||||||
CurrentUserID: userID,
|
CurrentUserID: userID,
|
||||||
|
@ -181,18 +184,20 @@ func (h *ProjectHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
}
|
}
|
||||||
|
|
||||||
type ProjectResponse struct {
|
type ProjectResponse struct {
|
||||||
ID string `json:"id,omitempty"`
|
ID string `json:"id,omitempty"`
|
||||||
Name string `json:"name,omitempty"`
|
Name string `json:"name,omitempty"`
|
||||||
Path string `json:"path,omitempty"`
|
Path string `json:"path,omitempty"`
|
||||||
ParentPath string `json:"parent_path,omitempty"`
|
ParentPath string `json:"parent_path,omitempty"`
|
||||||
|
GlobalVisibility string `json:"global_visibility,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func createProjectResponse(r *csapi.Project) *ProjectResponse {
|
func createProjectResponse(r *csapi.Project) *ProjectResponse {
|
||||||
res := &ProjectResponse{
|
res := &ProjectResponse{
|
||||||
ID: r.ID,
|
ID: r.ID,
|
||||||
Name: r.Name,
|
Name: r.Name,
|
||||||
Path: r.Path,
|
Path: r.Path,
|
||||||
ParentPath: r.ParentPath,
|
ParentPath: r.ParentPath,
|
||||||
|
GlobalVisibility: string(r.GlobalVisibility),
|
||||||
}
|
}
|
||||||
|
|
||||||
return res
|
return res
|
||||||
|
|
|
@ -22,6 +22,7 @@ import (
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
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/command"
|
"github.com/sorintlab/agola/internal/services/gateway/command"
|
||||||
|
"github.com/sorintlab/agola/internal/services/types"
|
||||||
"github.com/sorintlab/agola/internal/util"
|
"github.com/sorintlab/agola/internal/util"
|
||||||
|
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
|
@ -29,8 +30,9 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type CreateProjectGroupRequest struct {
|
type CreateProjectGroupRequest struct {
|
||||||
Name string `json:"name,omitempty"`
|
Name string `json:"name,omitempty"`
|
||||||
ParentID string `json:"parent_id,omitempty"`
|
ParentID string `json:"parent_id,omitempty"`
|
||||||
|
Visibility types.Visibility `json:"visibility,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type CreateProjectGroupHandler struct {
|
type CreateProjectGroupHandler struct {
|
||||||
|
@ -65,6 +67,7 @@ func (h *CreateProjectGroupHandler) ServeHTTP(w http.ResponseWriter, r *http.Req
|
||||||
creq := &command.CreateProjectGroupRequest{
|
creq := &command.CreateProjectGroupRequest{
|
||||||
Name: req.Name,
|
Name: req.Name,
|
||||||
ParentID: req.ParentID,
|
ParentID: req.ParentID,
|
||||||
|
Visibility: req.Visibility,
|
||||||
CurrentUserID: userID,
|
CurrentUserID: userID,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -179,18 +182,20 @@ func (h *ProjectGroupSubgroupsHandler) ServeHTTP(w http.ResponseWriter, r *http.
|
||||||
}
|
}
|
||||||
|
|
||||||
type ProjectGroupResponse struct {
|
type ProjectGroupResponse struct {
|
||||||
ID string `json:"id,omitempty"`
|
ID string `json:"id,omitempty"`
|
||||||
Name string `json:"name,omitempty"`
|
Name string `json:"name,omitempty"`
|
||||||
Path string `json:"path,omitempty"`
|
Path string `json:"path,omitempty"`
|
||||||
ParentPath string `json:"parent_path,omitempty"`
|
ParentPath string `json:"parent_path,omitempty"`
|
||||||
|
GlobalVisibility string `json:"global_visibility,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func createProjectGroupResponse(r *csapi.ProjectGroup) *ProjectGroupResponse {
|
func createProjectGroupResponse(r *csapi.ProjectGroup) *ProjectGroupResponse {
|
||||||
run := &ProjectGroupResponse{
|
run := &ProjectGroupResponse{
|
||||||
ID: r.ID,
|
ID: r.ID,
|
||||||
Name: r.Name,
|
Name: r.Name,
|
||||||
Path: r.Path,
|
Path: r.Path,
|
||||||
ParentPath: r.ParentPath,
|
ParentPath: r.ParentPath,
|
||||||
|
GlobalVisibility: string(r.GlobalVisibility),
|
||||||
}
|
}
|
||||||
|
|
||||||
return run
|
return run
|
||||||
|
|
|
@ -31,6 +31,7 @@ type CreateProjectRequest struct {
|
||||||
CurrentUserID string
|
CurrentUserID string
|
||||||
Name string
|
Name string
|
||||||
ParentID string
|
ParentID string
|
||||||
|
Visibility types.Visibility
|
||||||
RemoteSourceName string
|
RemoteSourceName string
|
||||||
RepoPath string
|
RepoPath string
|
||||||
SkipSSHHostKeyCheck bool
|
SkipSSHHostKeyCheck bool
|
||||||
|
@ -92,6 +93,7 @@ func (c *CommandHandler) CreateProject(ctx context.Context, req *CreateProjectRe
|
||||||
Type: types.ConfigTypeProjectGroup,
|
Type: types.ConfigTypeProjectGroup,
|
||||||
ID: parentID,
|
ID: parentID,
|
||||||
},
|
},
|
||||||
|
Visibility: req.Visibility,
|
||||||
LinkedAccountID: la.ID,
|
LinkedAccountID: la.ID,
|
||||||
RepositoryID: repo.ID,
|
RepositoryID: repo.ID,
|
||||||
RepositoryPath: req.RepoPath,
|
RepositoryPath: req.RepoPath,
|
||||||
|
|
|
@ -29,6 +29,7 @@ type CreateProjectGroupRequest struct {
|
||||||
CurrentUserID string
|
CurrentUserID string
|
||||||
Name string
|
Name string
|
||||||
ParentID string
|
ParentID string
|
||||||
|
Visibility types.Visibility
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *CommandHandler) CreateProjectGroup(ctx context.Context, req *CreateProjectGroupRequest) (*csapi.ProjectGroup, error) {
|
func (c *CommandHandler) CreateProjectGroup(ctx context.Context, req *CreateProjectGroupRequest) (*csapi.ProjectGroup, error) {
|
||||||
|
@ -53,6 +54,7 @@ func (c *CommandHandler) CreateProjectGroup(ctx context.Context, req *CreateProj
|
||||||
Type: types.ConfigTypeProjectGroup,
|
Type: types.ConfigTypeProjectGroup,
|
||||||
ID: parentID,
|
ID: parentID,
|
||||||
},
|
},
|
||||||
|
Visibility: req.Visibility,
|
||||||
}
|
}
|
||||||
|
|
||||||
c.log.Infof("creating projectGroup")
|
c.log.Infof("creating projectGroup")
|
||||||
|
|
|
@ -33,6 +33,23 @@ const (
|
||||||
ConfigTypeVariable ConfigType = "variable"
|
ConfigTypeVariable ConfigType = "variable"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type Visibility string
|
||||||
|
|
||||||
|
const (
|
||||||
|
VisibilityPublic Visibility = "public"
|
||||||
|
VisibilityPrivate Visibility = "private"
|
||||||
|
)
|
||||||
|
|
||||||
|
func IsValidVisibility(v Visibility) bool {
|
||||||
|
switch v {
|
||||||
|
case VisibilityPublic:
|
||||||
|
case VisibilityPrivate:
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
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"`
|
||||||
|
@ -73,6 +90,8 @@ type ProjectGroup struct {
|
||||||
Name string `json:"name,omitempty"`
|
Name string `json:"name,omitempty"`
|
||||||
|
|
||||||
Parent Parent `json:"parent,omitempty"`
|
Parent Parent `json:"parent,omitempty"`
|
||||||
|
|
||||||
|
Visibility Visibility `json:"visibility,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type RemoteSourceType string
|
type RemoteSourceType string
|
||||||
|
@ -139,6 +158,8 @@ type Project struct {
|
||||||
|
|
||||||
Parent Parent `json:"parent,omitempty"`
|
Parent Parent `json:"parent,omitempty"`
|
||||||
|
|
||||||
|
Visibility Visibility `json:"visibility,omitempty"`
|
||||||
|
|
||||||
// The remote repository id
|
// The remote repository id
|
||||||
RepositoryID string `json:"repository_id,omitempty"`
|
RepositoryID string `json:"repository_id,omitempty"`
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue