mirror of https://github.com/rancher/cli.git
365 lines
8.0 KiB
Go
365 lines
8.0 KiB
Go
package cmd
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"github.com/rancher/cli/cliclient"
|
|
managementClient "github.com/rancher/rancher/pkg/client/generated/management/v3"
|
|
"github.com/urfave/cli"
|
|
)
|
|
|
|
type ProjectData struct {
|
|
ID string
|
|
Project managementClient.Project
|
|
}
|
|
|
|
func ProjectCommand() cli.Command {
|
|
return cli.Command{
|
|
Name: "projects",
|
|
Aliases: []string{"project"},
|
|
Usage: "Operations on projects",
|
|
Action: defaultAction(projectLs),
|
|
Subcommands: []cli.Command{
|
|
{
|
|
Name: "ls",
|
|
Usage: "List projects",
|
|
Description: "\nLists all projects in the current cluster.",
|
|
ArgsUsage: "None",
|
|
Action: projectLs,
|
|
Flags: []cli.Flag{
|
|
cli.StringFlag{
|
|
Name: "format",
|
|
Usage: "'json', 'yaml' or Custom format: '{{.Project.ID}} {{.Project.Name}}'",
|
|
},
|
|
quietFlag,
|
|
},
|
|
},
|
|
{
|
|
Name: "create",
|
|
Usage: "Create a project",
|
|
Description: "\nCreates a project in the current cluster.",
|
|
ArgsUsage: "[NEWPROJECTNAME...]",
|
|
Action: projectCreate,
|
|
Flags: []cli.Flag{
|
|
cli.StringFlag{
|
|
Name: "cluster",
|
|
Usage: "Cluster ID to create the project in",
|
|
},
|
|
cli.StringFlag{
|
|
Name: "description",
|
|
Usage: "Description to apply to the project",
|
|
},
|
|
},
|
|
},
|
|
{
|
|
Name: "delete",
|
|
Aliases: []string{"rm"},
|
|
Usage: "Delete a project by ID",
|
|
ArgsUsage: "[PROJECTID PROJECTNAME]",
|
|
Action: projectDelete,
|
|
},
|
|
{
|
|
Name: "add-member-role",
|
|
Usage: "Add a member to the project",
|
|
Action: addProjectMemberRoles,
|
|
Description: "Examples:\n #Create the roles of 'create-ns' and 'services-manage' for a user named 'user1'\n rancher project add-member-role user1 create-ns services-manage\n",
|
|
ArgsUsage: "[USERNAME, ROLE...]",
|
|
Flags: []cli.Flag{
|
|
cli.StringFlag{
|
|
Name: "project-id",
|
|
Usage: "Optional project ID to apply this change to, defaults to the current context",
|
|
},
|
|
},
|
|
},
|
|
{
|
|
Name: "delete-member-role",
|
|
Usage: "Delete a member from the project",
|
|
Action: deleteProjectMemberRoles,
|
|
Description: "Examples:\n #Delete the roles of 'create-ns' and 'services-manage' for a user named 'user1'\n rancher project delete-member-role user1 create-ns services-manage\n",
|
|
ArgsUsage: "[USERNAME, ROLE...]",
|
|
Flags: []cli.Flag{
|
|
cli.StringFlag{
|
|
Name: "project-id",
|
|
Usage: "Optional project ID to apply this change to, defaults to the current context",
|
|
},
|
|
},
|
|
},
|
|
{
|
|
Name: "list-roles",
|
|
Usage: "List all available roles for a project",
|
|
Action: listProjectRoles,
|
|
},
|
|
{
|
|
Name: "list-members",
|
|
Usage: "List current members of the project",
|
|
Action: listProjectMembers,
|
|
Flags: []cli.Flag{
|
|
cli.StringFlag{
|
|
Name: "project-id",
|
|
Usage: "Optional project ID to list members for, defaults to the current context",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
}
|
|
|
|
func projectLs(ctx *cli.Context) error {
|
|
c, err := GetClient(ctx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
collection, err := getProjectList(ctx, c)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
writer := NewTableWriter([][]string{
|
|
{"ID", "ID"},
|
|
{"NAME", "Project.Name"},
|
|
{"STATE", "Project.State"},
|
|
{"DESCRIPTION", "Project.Description"},
|
|
}, ctx)
|
|
|
|
defer writer.Close()
|
|
|
|
for _, item := range collection.Data {
|
|
writer.Write(&ProjectData{
|
|
ID: item.ID,
|
|
Project: item,
|
|
})
|
|
}
|
|
|
|
return writer.Err()
|
|
}
|
|
|
|
func projectCreate(ctx *cli.Context) error {
|
|
if ctx.NArg() == 0 {
|
|
return cli.ShowSubcommandHelp(ctx)
|
|
}
|
|
|
|
c, err := GetClient(ctx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
clusterID := c.UserConfig.FocusedCluster()
|
|
if ctx.String("cluster") != "" {
|
|
resource, err := Lookup(c, ctx.String("cluster"), "cluster")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
clusterID = resource.ID
|
|
}
|
|
|
|
newProj := &managementClient.Project{
|
|
Name: ctx.Args().First(),
|
|
ClusterID: clusterID,
|
|
Description: ctx.String("description"),
|
|
}
|
|
|
|
_, err = c.ManagementClient.Project.Create(newProj)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func projectDelete(ctx *cli.Context) error {
|
|
if ctx.NArg() == 0 {
|
|
return cli.ShowSubcommandHelp(ctx)
|
|
}
|
|
|
|
c, err := GetClient(ctx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
for _, arg := range ctx.Args() {
|
|
resource, err := Lookup(c, arg, "project")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
project, err := getProjectByID(c, resource.ID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
err = c.ManagementClient.Project.Delete(project)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func addProjectMemberRoles(ctx *cli.Context) error {
|
|
if len(ctx.Args()) < 2 {
|
|
return cli.ShowSubcommandHelp(ctx)
|
|
}
|
|
|
|
memberName := ctx.Args().First()
|
|
|
|
roles := ctx.Args()[1:]
|
|
|
|
c, err := GetClient(ctx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
member, err := searchForMember(ctx, c, memberName)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
projectID := c.UserConfig.Project
|
|
if ctx.String("project-id") != "" {
|
|
projectID = ctx.String("project-id")
|
|
}
|
|
|
|
for _, role := range roles {
|
|
rtb := managementClient.ProjectRoleTemplateBinding{
|
|
ProjectID: projectID,
|
|
RoleTemplateID: role,
|
|
}
|
|
if member.PrincipalType == "user" {
|
|
rtb.UserPrincipalID = member.ID
|
|
} else {
|
|
rtb.GroupPrincipalID = member.ID
|
|
}
|
|
_, err = c.ManagementClient.ProjectRoleTemplateBinding.Create(&rtb)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func deleteProjectMemberRoles(ctx *cli.Context) error {
|
|
if len(ctx.Args()) < 2 {
|
|
return cli.ShowSubcommandHelp(ctx)
|
|
}
|
|
|
|
memberName := ctx.Args().First()
|
|
|
|
roles := ctx.Args()[1:]
|
|
|
|
c, err := GetClient(ctx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
member, err := searchForMember(ctx, c, memberName)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
projectID := c.UserConfig.Project
|
|
if ctx.String("project-id") != "" {
|
|
projectID = ctx.String("project-id")
|
|
}
|
|
|
|
for _, role := range roles {
|
|
filter := defaultListOpts(ctx)
|
|
filter.Filters["projectId"] = projectID
|
|
filter.Filters["roleTemplateId"] = role
|
|
|
|
if member.PrincipalType == "user" {
|
|
filter.Filters["userPrincipalId"] = member.ID
|
|
} else {
|
|
filter.Filters["groupPrincipalId"] = member.ID
|
|
}
|
|
|
|
bindings, err := c.ManagementClient.ProjectRoleTemplateBinding.List(filter)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
for _, binding := range bindings.Data {
|
|
err = c.ManagementClient.ProjectRoleTemplateBinding.Delete(&binding)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func listProjectRoles(ctx *cli.Context) error {
|
|
return listRoles(ctx, "project")
|
|
}
|
|
|
|
func listProjectMembers(ctx *cli.Context) error {
|
|
c, err := GetClient(ctx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
projectID := c.UserConfig.Project
|
|
if ctx.String("project-id") != "" {
|
|
projectID = ctx.String("project-id")
|
|
}
|
|
|
|
filter := defaultListOpts(ctx)
|
|
filter.Filters["projectId"] = projectID
|
|
bindings, err := c.ManagementClient.ProjectRoleTemplateBinding.List(filter)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
userFilter := defaultListOpts(ctx)
|
|
users, err := c.ManagementClient.User.List(userFilter)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
userMap := usersToNameMapping(users.Data)
|
|
|
|
var b []RoleTemplateBinding
|
|
|
|
for _, binding := range bindings.Data {
|
|
parsedTime, err := createdTimetoHuman(binding.Created)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
b = append(b, RoleTemplateBinding{
|
|
ID: binding.ID,
|
|
User: userMap[binding.UserID],
|
|
Role: binding.RoleTemplateID,
|
|
Created: parsedTime,
|
|
})
|
|
}
|
|
|
|
return listRoleTemplateBindings(ctx, b)
|
|
}
|
|
|
|
func getProjectList(
|
|
ctx *cli.Context,
|
|
c *cliclient.MasterClient,
|
|
) (*managementClient.ProjectCollection, error) {
|
|
filter := defaultListOpts(ctx)
|
|
filter.Filters["clusterId"] = c.UserConfig.FocusedCluster()
|
|
|
|
collection, err := c.ManagementClient.Project.List(filter)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return collection, nil
|
|
}
|
|
|
|
func getProjectByID(
|
|
c *cliclient.MasterClient,
|
|
projectID string,
|
|
) (*managementClient.Project, error) {
|
|
project, err := c.ManagementClient.Project.ByID(projectID)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("no project found with the ID [%s], run "+
|
|
"`rancher projects` to see available projects: %s", projectID, err)
|
|
}
|
|
return project, nil
|
|
}
|