forked from openshift/origin
-
Notifications
You must be signed in to change notification settings - Fork 0
/
new_project.go
140 lines (114 loc) · 4.54 KB
/
new_project.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
package project
import (
"errors"
"fmt"
"io"
"github.com/spf13/cobra"
kerrors "k8s.io/kubernetes/pkg/api/errors"
kcmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
errorsutil "k8s.io/kubernetes/pkg/util/errors"
"github.com/openshift/origin/pkg/client"
"github.com/openshift/origin/pkg/cmd/admin/policy"
"github.com/openshift/origin/pkg/cmd/server/bootstrappolicy"
"github.com/openshift/origin/pkg/cmd/util/clientcmd"
projectapi "github.com/openshift/origin/pkg/project/api"
)
const NewProjectRecommendedName = "new-project"
type NewProjectOptions struct {
ProjectName string
DisplayName string
Description string
NodeSelector string
Client client.Interface
AdminRole string
AdminUser string
}
const newProjectLong = `
Create a new project
Use this command to create a project. You may optionally specify metadata about the project,
an admin user (and role, if you want to use a non-default admin role), and a node selector
to restrict which nodes pods in this project can be scheduled to.`
// NewCmdNewProject implements the OpenShift cli new-project command
func NewCmdNewProject(name, fullName string, f *clientcmd.Factory, out io.Writer) *cobra.Command {
options := &NewProjectOptions{}
cmd := &cobra.Command{
Use: name + " NAME [--display-name=DISPLAYNAME] [--description=DESCRIPTION]",
Short: "Create a new project",
Long: newProjectLong,
Run: func(cmd *cobra.Command, args []string) {
if err := options.complete(args); err != nil {
kcmdutil.CheckErr(kcmdutil.UsageError(cmd, err.Error()))
}
var err error
if options.Client, _, err = f.Clients(); err != nil {
kcmdutil.CheckErr(err)
}
// We can't depend on len(options.NodeSelector) > 0 as node-selector="" is valid
// and we want to populate node selector as project annotation only if explicitly set by user
useNodeSelector := cmd.Flag("node-selector").Changed
if err := options.Run(useNodeSelector); err != nil {
kcmdutil.CheckErr(err)
}
},
}
cmd.Flags().StringVar(&options.AdminRole, "admin-role", bootstrappolicy.AdminRoleName, "Project admin role name in the cluster policy")
cmd.Flags().StringVar(&options.AdminUser, "admin", "", "Project admin username")
cmd.Flags().StringVar(&options.DisplayName, "display-name", "", "Project display name")
cmd.Flags().StringVar(&options.Description, "description", "", "Project description")
cmd.Flags().StringVar(&options.NodeSelector, "node-selector", "", "Restrict pods onto nodes matching given label selector. Format: '<key1>=<value1>, <key2>=<value2>...'. Specifying \"\" means any node, not default. If unspecified, cluster default node selector will be used.")
return cmd
}
func (o *NewProjectOptions) complete(args []string) error {
if len(args) != 1 {
return errors.New("you must specify one argument: project name")
}
o.ProjectName = args[0]
return nil
}
func (o *NewProjectOptions) Run(useNodeSelector bool) error {
if _, err := o.Client.Projects().Get(o.ProjectName); err != nil {
if !kerrors.IsNotFound(err) {
return err
}
} else {
return fmt.Errorf("project %v already exists", o.ProjectName)
}
project := &projectapi.Project{}
project.Name = o.ProjectName
project.Annotations = make(map[string]string)
project.Annotations[projectapi.ProjectDescription] = o.Description
project.Annotations[projectapi.ProjectDisplayName] = o.DisplayName
if useNodeSelector {
project.Annotations[projectapi.ProjectNodeSelector] = o.NodeSelector
}
project, err := o.Client.Projects().Create(project)
if err != nil {
return err
}
fmt.Printf("Created project %v\n", o.ProjectName)
errs := []error{}
if len(o.AdminUser) != 0 {
adduser := &policy.RoleModificationOptions{
RoleName: o.AdminRole,
RoleBindingAccessor: policy.NewLocalRoleBindingAccessor(project.Name, o.Client),
Users: []string{o.AdminUser},
}
if err := adduser.AddRole(); err != nil {
fmt.Printf("%v could not be added to the %v role: %v\n", o.AdminUser, o.AdminRole, err)
errs = append(errs, err)
}
}
for _, binding := range bootstrappolicy.GetBootstrapServiceAccountProjectRoleBindings(o.ProjectName) {
addRole := &policy.RoleModificationOptions{
RoleName: binding.RoleRef.Name,
RoleNamespace: binding.RoleRef.Namespace,
RoleBindingAccessor: policy.NewLocalRoleBindingAccessor(o.ProjectName, o.Client),
Subjects: binding.Subjects,
}
if err := addRole.AddRole(); err != nil {
fmt.Printf("Could not add service accounts to the %v role: %v\n", binding.RoleRef.Name, err)
errs = append(errs, err)
}
}
return errorsutil.NewAggregate(errs)
}