コード例 #1
0
ファイル: app.go プロジェクト: tsuru/tsuru
func (app *App) getPoolForApp(poolName string) (string, error) {
	var pools []provision.Pool
	var err error
	if poolName != "" {
		var pool *provision.Pool
		pool, err = provision.GetPoolByName(poolName)
		if err != nil {
			return "", err
		}
		pools = append(pools, *pool)
	} else {
		pools, err = provision.ListPoolsForTeam(app.TeamOwner)
	}
	if err != nil {
		return "", err
	}
	if len(pools) > 1 {
		return "", errors.New("you have access to more than one pool, please choose one in app creation")
	}
	if len(pools) == 0 {
		return "", nil
	}
	var poolTeam bool
	for _, team := range pools[0].Teams {
		if team == app.TeamOwner {
			poolTeam = true
			break
		}
	}
	if !pools[0].Public && !poolTeam {
		return "", errors.Errorf("App team owner %q has no access to pool %q", app.TeamOwner, poolName)
	}
	return pools[0].Name, nil
}
コード例 #2
0
ファイル: pool_test.go プロジェクト: tsuru/tsuru
func (s *S) TestPoolUpdateProvisioner(c *check.C) {
	provision.RemovePool("test1")
	opts := provision.AddPoolOptions{Name: "pool1", Public: true, Default: true}
	err := provision.AddPool(opts)
	c.Assert(err, check.IsNil)
	defer provision.RemovePool("pool1")
	b := bytes.NewBufferString("provisioner=myprov&default=false")
	req, err := http.NewRequest("PUT", "/pools/pool1", b)
	c.Assert(err, check.IsNil)
	req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
	req.Header.Set("Authorization", "bearer "+s.token.GetValue())
	rec := httptest.NewRecorder()
	m := RunServer(true)
	m.ServeHTTP(rec, req)
	c.Assert(rec.Code, check.Equals, http.StatusOK)
	c.Assert(err, check.IsNil)
	p, err := provision.GetPoolByName("pool1")
	c.Assert(err, check.IsNil)
	c.Assert(p.Provisioner, check.Equals, "myprov")
	c.Assert(p.Public, check.Equals, true)
	c.Assert(p.Default, check.Equals, false)
	c.Assert(eventtest.EventDesc{
		Target: event.Target{Type: event.TargetTypePool, Value: "pool1"},
		Owner:  s.token.GetUserName(),
		Kind:   "pool.update",
		StartCustomData: []map[string]interface{}{
			{"name": ":name", "value": "pool1"},
			{"name": "default", "value": "false"},
			{"name": "provisioner", "value": "myprov"},
		},
	}, eventtest.HasEvent)
}
コード例 #3
0
ファイル: pool_test.go プロジェクト: tsuru/tsuru
func (s *S) TestAddTeamsToPool(c *check.C) {
	pool := provision.Pool{Name: "pool1"}
	opts := provision.AddPoolOptions{Name: pool.Name}
	err := provision.AddPool(opts)
	c.Assert(err, check.IsNil)
	defer provision.RemovePool(pool.Name)
	b := strings.NewReader("team=test")
	req, err := http.NewRequest("POST", "/pools/pool1/team", b)
	c.Assert(err, check.IsNil)
	req.Header.Set("Authorization", "bearer "+s.token.GetValue())
	req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
	rec := httptest.NewRecorder()
	m := RunServer(true)
	m.ServeHTTP(rec, req)
	c.Assert(rec.Code, check.Equals, http.StatusOK)
	p, err := provision.GetPoolByName("pool1")
	c.Assert(err, check.IsNil)
	c.Assert(p.Teams, check.DeepEquals, []string{"test"})
	c.Assert(eventtest.EventDesc{
		Target: event.Target{Type: event.TargetTypePool, Value: "pool1"},
		Owner:  s.token.GetUserName(),
		Kind:   "pool.update.team.add",
		StartCustomData: []map[string]interface{}{
			{"name": ":name", "value": "pool1"},
			{"name": "team", "value": "test"},
		},
	}, eventtest.HasEvent)
}
コード例 #4
0
ファイル: pool_test.go プロジェクト: tsuru/tsuru
func (s *S) TestAddPool(c *check.C) {
	b := bytes.NewBufferString("name=pool1")
	req, err := http.NewRequest("POST", "/pools", b)
	c.Assert(err, check.IsNil)
	req.Header.Set("Authorization", "bearer "+s.token.GetValue())
	req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
	rec := httptest.NewRecorder()
	defer provision.RemovePool("pool1")
	m := RunServer(true)
	m.ServeHTTP(rec, req)
	c.Assert(rec.Code, check.Equals, http.StatusCreated)
	c.Assert(err, check.IsNil)
	_, err = provision.GetPoolByName("pool1")
	c.Assert(err, check.IsNil)
	b = bytes.NewBufferString("name=pool2&public=true")
	req, err = http.NewRequest("POST", "/pools", b)
	c.Assert(err, check.IsNil)
	req.Header.Set("Authorization", "bearer "+s.token.GetValue())
	req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
	rec = httptest.NewRecorder()
	defer provision.RemovePool("pool2")
	m.ServeHTTP(rec, req)
	c.Assert(rec.Code, check.Equals, http.StatusCreated)
	pool, err := provision.GetPoolByName("pool2")
	c.Assert(err, check.IsNil)
	c.Assert(pool.Public, check.Equals, true)
	c.Assert(eventtest.EventDesc{
		Target: event.Target{Type: event.TargetTypePool, Value: "pool1"},
		Owner:  s.token.GetUserName(),
		Kind:   "pool.create",
		StartCustomData: []map[string]interface{}{
			{"name": "name", "value": "pool1"},
		},
	}, eventtest.HasEvent)
	c.Assert(eventtest.EventDesc{
		Target: event.Target{Type: event.TargetTypePool, Value: "pool2"},
		Owner:  s.token.GetUserName(),
		Kind:   "pool.create",
		StartCustomData: []map[string]interface{}{
			{"name": "name", "value": "pool2"},
			{"name": "public", "value": "true"},
		},
	}, eventtest.HasEvent)
}
コード例 #5
0
ファイル: app.go プロジェクト: tsuru/tsuru
func (app *App) getProvisioner() (provision.Provisioner, error) {
	if app.provisioner == nil {
		if app.Pool == "" {
			return provision.GetDefault()
		}
		pool, err := provision.GetPoolByName(app.Pool)
		if err != nil {
			return nil, err
		}
		app.provisioner, err = pool.GetProvisioner()
		if err != nil {
			return nil, err
		}
	}
	return app.provisioner, nil
}
コード例 #6
0
ファイル: pool_test.go プロジェクト: tsuru/tsuru
func (s *S) TestPoolUpdateToDefaultPoolHandler(c *check.C) {
	provision.RemovePool("test1")
	opts := provision.AddPoolOptions{Name: "pool1"}
	err := provision.AddPool(opts)
	c.Assert(err, check.IsNil)
	defer provision.RemovePool("pool1")
	b := bytes.NewBufferString("default=true")
	req, err := http.NewRequest("PUT", "/pools/pool1", b)
	c.Assert(err, check.IsNil)
	req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
	req.Header.Set("Authorization", "bearer "+s.token.GetValue())
	rec := httptest.NewRecorder()
	m := RunServer(true)
	m.ServeHTTP(rec, req)
	c.Assert(rec.Code, check.Equals, http.StatusOK)
	c.Assert(err, check.IsNil)
	p, err := provision.GetPoolByName("pool1")
	c.Assert(err, check.IsNil)
	c.Assert(p.Default, check.Equals, true)
}
コード例 #7
0
ファイル: pool_test.go プロジェクト: tsuru/tsuru
func (s *S) TestRemovePoolHandler(c *check.C) {
	opts := provision.AddPoolOptions{
		Name: "pool1",
	}
	err := provision.AddPool(opts)
	c.Assert(err, check.IsNil)
	req, err := http.NewRequest("DELETE", "/pools/pool1", nil)
	c.Assert(err, check.IsNil)
	req.Header.Set("Authorization", "bearer "+s.token.GetValue())
	rec := httptest.NewRecorder()
	m := RunServer(true)
	m.ServeHTTP(rec, req)
	c.Assert(rec.Code, check.Equals, http.StatusOK)
	_, err = provision.GetPoolByName("pool1")
	c.Assert(err, check.Equals, provision.ErrPoolNotFound)
	c.Assert(eventtest.EventDesc{
		Target: event.Target{Type: event.TargetTypePool, Value: "pool1"},
		Owner:  s.token.GetUserName(),
		Kind:   "pool.delete",
		StartCustomData: []map[string]interface{}{
			{"name": ":name", "value": "pool1"},
		},
	}, eventtest.HasEvent)
}
コード例 #8
0
ファイル: node.go プロジェクト: tsuru/tsuru
// title: add node
// path: /{provisioner}/node
// method: POST
// consume: application/x-www-form-urlencoded
// produce: application/x-json-stream
// responses:
//   201: Ok
//   401: Unauthorized
//   404: Not found
func addNodeHandler(w http.ResponseWriter, r *http.Request, t auth.Token) (err error) {
	err = r.ParseForm()
	if err != nil {
		return &tsuruErrors.HTTP{Code: http.StatusBadRequest, Message: err.Error()}
	}
	var params provision.AddNodeOptions
	dec := form.NewDecoder(nil)
	dec.IgnoreUnknownKeys(true)
	err = dec.DecodeValues(&params, r.Form)
	if err != nil {
		return &tsuruErrors.HTTP{Code: http.StatusBadRequest, Message: err.Error()}
	}
	if templateName, ok := params.Metadata["template"]; ok {
		params.Metadata, err = iaas.ExpandTemplate(templateName, params.Metadata)
		if err != nil {
			return &tsuruErrors.HTTP{Code: http.StatusBadRequest, Message: err.Error()}
		}
	}
	poolName := params.Metadata["pool"]
	if poolName == "" {
		return &tsuruErrors.HTTP{Code: http.StatusBadRequest, Message: "pool is required"}
	}
	if !permission.Check(t, permission.PermNodeCreate, permission.Context(permission.CtxPool, poolName)) {
		return permission.ErrUnauthorized
	}
	if !params.Register {
		canCreateMachine := permission.Check(t, permission.PermMachineCreate,
			permission.Context(permission.CtxIaaS, params.Metadata["iaas"]))
		if !canCreateMachine {
			return permission.ErrUnauthorized
		}
	}
	evt, err := event.New(&event.Opts{
		Target:      event.Target{Type: event.TargetTypeNode},
		Kind:        permission.PermNodeCreate,
		Owner:       t,
		CustomData:  event.FormToCustomData(r.Form),
		DisableLock: true,
		Allowed:     event.Allowed(permission.PermPoolReadEvents, permission.Context(permission.CtxPool, poolName)),
	})
	if err != nil {
		return err
	}
	defer func() { evt.Done(err) }()
	pool, err := provision.GetPoolByName(poolName)
	if err != nil {
		return err
	}
	prov, err := pool.GetProvisioner()
	if err != nil {
		return err
	}
	nodeProv, ok := prov.(provision.NodeProvisioner)
	if !ok {
		return provision.ProvisionerNotSupported{Prov: prov, Action: "node operations"}
	}
	w.Header().Set("Content-Type", "application/x-json-stream")
	w.WriteHeader(http.StatusCreated)
	keepAliveWriter := tsuruIo.NewKeepAliveWriter(w, 15*time.Second, "")
	defer keepAliveWriter.Stop()
	addr, response, err := addNodeForParams(nodeProv, params)
	evt.Target.Value = addr
	if err != nil {
		if desc := response["description"]; desc != "" {
			return errors.Wrapf(err, "Instructions:\n%s", desc)
		}
		return err
	}
	return nil
}