Fix #1329: Add wait flag to wait for project to be ready. (#1367)

* Fix #1329: Add wait flag to wait for project to be ready.

* Watch for projects instead of Namespaces.

* Add e2e test for project creation and wait.
This commit is contained in:
Chris Laprun
2019-02-27 14:23:45 +01:00
committed by GitHub
parent b59f9ce64f
commit 88f0d05e69
4 changed files with 87 additions and 12 deletions

View File

@@ -465,7 +465,7 @@ func (c *Client) GetProjectNames() ([]string, error) {
}
// CreateNewProject creates project with given projectName
func (c *Client) CreateNewProject(projectName string) error {
func (c *Client) CreateNewProject(projectName string, wait bool) error {
projectRequest := &projectv1.ProjectRequest{
ObjectMeta: metav1.ObjectMeta{
Name: projectName,
@@ -475,6 +475,28 @@ func (c *Client) CreateNewProject(projectName string) error {
if err != nil {
return errors.Wrapf(err, "unable to create new project %s", projectName)
}
if wait {
w, err := c.projectClient.Projects().Watch(metav1.ListOptions{
FieldSelector: fields.Set{"metadata.name": projectName}.AsSelector().String(),
})
if err != nil {
return errors.Wrapf(err, "unable to watch new project %s creation", projectName)
}
defer w.Stop()
for {
val, ok := <-w.ResultChan()
if !ok {
break
}
if e, ok := val.Object.(*projectv1.Project); ok {
glog.V(4).Infof("Project %s now exists", e.Name)
return nil
}
}
}
return nil
}

View File

@@ -2747,11 +2747,19 @@ func TestCreateNewProject(t *testing.T) {
tests := []struct {
name string
projName string
wait bool
wantErr bool
}{
{
name: "Case 1: valid project name",
name: "Case 1: valid project name, not waiting",
projName: "testing",
wait: false,
wantErr: false,
},
{
name: "Case 2: valid project name, waiting",
projName: "testing2",
wait: true,
wantErr: false,
},
@@ -2767,6 +2775,24 @@ func TestCreateNewProject(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
fkclient, fkclientset := FakeNew()
if tt.wait {
fkWatch := watch.NewFake()
// Change the status
go func() {
fkWatch.Modify(&projectv1.Project{
ObjectMeta: metav1.ObjectMeta{
Name: tt.projName,
},
})
}()
fkclientset.ProjClientset.PrependWatchReactor("projects", func(action ktesting.Action) (handled bool, ret watch.Interface, err error) {
if len(tt.projName) == 0 {
return true, nil, fmt.Errorf("error watching project")
}
return true, fkWatch, nil
})
}
fkclientset.ProjClientset.PrependReactor("create", "projectrequests", func(action ktesting.Action) (bool, runtime.Object, error) {
proj := projectv1.Project{
ObjectMeta: metav1.ObjectMeta{
@@ -2776,21 +2802,35 @@ func TestCreateNewProject(t *testing.T) {
return true, &proj, nil
})
err := fkclient.CreateNewProject(tt.projName)
err := fkclient.CreateNewProject(tt.projName, tt.wait)
if !tt.wantErr == (err != nil) {
t.Errorf("client.CreateNewProject(string) unexpected error %v, wantErr %v", err, tt.wantErr)
}
if len(fkclientset.ProjClientset.Actions()) != 1 {
t.Errorf("expected 1 action in CreateNewProject got: %v", fkclientset.ProjClientset.Actions())
actions := fkclientset.ProjClientset.Actions()
actionsNb := len(actions)
if !tt.wait && actionsNb != 1 {
t.Errorf("expected 1 action in CreateNewProject got: %v", actions)
}
if tt.wait && actionsNb != 2 {
t.Errorf("expected 2 actions in CreateNewProject when waiting for project creation got: %v", actions)
}
if err == nil {
createdProj := fkclientset.ProjClientset.Actions()[0].(ktesting.CreateAction).GetObject().(*projectv1.ProjectRequest)
createdProj := actions[0].(ktesting.CreateAction).GetObject().(*projectv1.ProjectRequest)
if createdProj.Name != tt.projName {
t.Errorf("project name does not match the expected name, expected: %s, got: %s", tt.projName, createdProj.Name)
}
if tt.wait {
expectedFields := fields.OneTermEqualSelector("metadata.name", tt.projName)
gotFields := actions[1].(ktesting.WatchAction).GetWatchRestrictions().Fields
if !reflect.DeepEqual(expectedFields, gotFields) {
t.Errorf("Fields not matching: expected: %s, got %s", expectedFields, gotFields)
}
}
}
})

View File

@@ -26,9 +26,9 @@ var (
// ProjectCreateOptions encapsulates the options for the odo project create command
type ProjectCreateOptions struct {
// name of the project
projectName string
wait bool
// generic context options common to all commands
*genericclioptions.Context
@@ -53,10 +53,22 @@ func (pco *ProjectCreateOptions) Validate() (err error) {
// Run runs the project create command
func (pco *ProjectCreateOptions) Run() (err error) {
err = project.Create(pco.Client, pco.projectName)
if err != nil {
return err
if pco.wait {
s := log.Spinner("Waiting for project to come up")
err = project.Create(pco.Client, pco.projectName, true)
if err != nil {
return err
} else {
s.End(true)
log.Successf(`Project '%s' is ready for use`, pco.projectName)
}
} else {
err = project.Create(pco.Client, pco.projectName, false)
if err != nil {
return err
}
}
err = project.SetCurrent(pco.Client, pco.projectName)
if err != nil {
return err
@@ -80,5 +92,6 @@ func NewCmdProjectCreate(name, fullName string) *cobra.Command {
},
}
projectCreateCmd.Flags().BoolVarP(&o.wait, "wait", "w", false, "Wait until the project is ready")
return projectCreateCmd
}

View File

@@ -46,8 +46,8 @@ func SetCurrent(client *occlient.Client, projectName string) error {
return nil
}
func Create(client *occlient.Client, projectName string) error {
err := client.CreateNewProject(projectName)
func Create(client *occlient.Client, projectName string, wait bool) error {
err := client.CreateNewProject(projectName, wait)
if err != nil {
return errors.Wrap(err, "unable to create new project")
}