예제 #1
0
func (s *S) TestAppLocker(c *gocheck.C) {
	appName := "myapp"
	conn, err := db.Conn()
	c.Assert(err, gocheck.IsNil)
	defer conn.Close()
	appDB := &app.App{Name: appName}
	defer conn.Apps().Remove(bson.M{"name": appName})
	err = conn.Apps().Insert(appDB)
	c.Assert(err, gocheck.IsNil)
	locker := &appLocker{}
	hasLock := locker.lock(appName)
	c.Assert(hasLock, gocheck.Equals, true)
	c.Assert(locker.refCount[appName], gocheck.Equals, 1)
	appDB, err = app.GetByName(appName)
	c.Assert(err, gocheck.IsNil)
	c.Assert(appDB.Lock.Locked, gocheck.Equals, true)
	c.Assert(appDB.Lock.Owner, gocheck.Equals, app.InternalAppName)
	c.Assert(appDB.Lock.Reason, gocheck.Equals, "container-move")
	hasLock = locker.lock(appName)
	c.Assert(hasLock, gocheck.Equals, true)
	c.Assert(locker.refCount[appName], gocheck.Equals, 2)
	locker.unlock(appName)
	c.Assert(locker.refCount[appName], gocheck.Equals, 1)
	appDB, err = app.GetByName(appName)
	c.Assert(err, gocheck.IsNil)
	c.Assert(appDB.Lock.Locked, gocheck.Equals, true)
	locker.unlock(appName)
	c.Assert(locker.refCount[appName], gocheck.Equals, 0)
	appDB, err = app.GetByName(appName)
	c.Assert(err, gocheck.IsNil)
	c.Assert(appDB.Lock.Locked, gocheck.Equals, false)
}
예제 #2
0
func (s *S) TestAppLocker(c *check.C) {
	appName := "myapp"
	appDB := &app.App{Name: appName}
	err := s.storage.Apps().Insert(appDB)
	c.Assert(err, check.IsNil)
	locker := &appLocker{}
	hasLock := locker.Lock(appName)
	c.Assert(hasLock, check.Equals, true)
	c.Assert(locker.refCount[appName], check.Equals, 1)
	appDB, err = app.GetByName(appName)
	c.Assert(err, check.IsNil)
	c.Assert(appDB.Lock.Locked, check.Equals, true)
	c.Assert(appDB.Lock.Owner, check.Equals, app.InternalAppName)
	c.Assert(appDB.Lock.Reason, check.Equals, "container-move")
	hasLock = locker.Lock(appName)
	c.Assert(hasLock, check.Equals, true)
	c.Assert(locker.refCount[appName], check.Equals, 2)
	locker.Unlock(appName)
	c.Assert(locker.refCount[appName], check.Equals, 1)
	appDB, err = app.GetByName(appName)
	c.Assert(err, check.IsNil)
	c.Assert(appDB.Lock.Locked, check.Equals, true)
	locker.Unlock(appName)
	c.Assert(locker.refCount[appName], check.Equals, 0)
	appDB, err = app.GetByName(appName)
	c.Assert(err, check.IsNil)
	c.Assert(appDB.Lock.Locked, check.Equals, false)
}
예제 #3
0
func (s *HandlerSuite) TestLocksAppDuringAppRequests(c *check.C) {
	myApp := app.App{
		Name: "my-app",
	}
	err := s.conn.Apps().Insert(myApp)
	c.Assert(err, check.IsNil)
	defer s.conn.Apps().Remove(bson.M{"name": myApp.Name})
	recorder := httptest.NewRecorder()
	request, err := http.NewRequest("POST", "/apps/my-app/", nil)
	c.Assert(err, check.IsNil)
	request.Header.Set("Authorization", "bearer "+s.token.GetValue())
	handler := func(w http.ResponseWriter, r *http.Request, t auth.Token) error {
		a, appErr := app.GetByName(r.URL.Query().Get(":app"))
		c.Assert(appErr, check.IsNil)
		c.Assert(a.Lock.Reason, check.Equals, "POST /apps/my-app/")
		c.Assert(a.Lock.Owner, check.Equals, s.token.GetUserName())
		c.Assert(a.Lock.Locked, check.Equals, true)
		c.Assert(a.Lock.AcquireDate, check.NotNil)
		return nil
	}
	RegisterHandler("/apps/{app}/", "POST", authorizationRequiredHandler(handler))
	defer resetHandlers()
	m := RunServer(true)
	m.ServeHTTP(recorder, request)
	c.Assert(recorder.Code, check.Equals, http.StatusOK)
	a, err := app.GetByName(request.URL.Query().Get(":app"))
	c.Assert(err, check.IsNil)
	c.Assert(a.Lock.Locked, check.Equals, false)
}
예제 #4
0
파일: rebuild_test.go 프로젝트: tsuru/tsuru
func (s *S) TestRebuildRoutesTCPRoutes(c *check.C) {
	a := app.App{Name: "my-test-app", TeamOwner: s.team.Name}
	err := app.CreateApp(&a, s.user)
	c.Assert(err, check.IsNil)
	err = provisiontest.ProvisionerInstance.AddUnits(&a, 3, "web", nil)
	c.Assert(err, check.IsNil)
	units, err := a.Units()
	c.Assert(err, check.IsNil)
	for _, u := range units {
		routertest.FakeRouter.RemoveRoute(a.Name, u.Address)
		routertest.FakeRouter.AddRoute(a.Name, &url.URL{Scheme: "tcp", Host: u.Address.Host})
	}
	changes, err := rebuild.RebuildRoutes(&a)
	c.Assert(err, check.IsNil)
	c.Assert(changes.Added, check.IsNil)
	c.Assert(changes.Removed, check.IsNil)
	routes, err := routertest.FakeRouter.Routes(a.Name)
	c.Assert(err, check.IsNil)
	c.Assert(routes, check.HasLen, 3)
	c.Assert(routertest.FakeRouter.HasRoute(a.Name, units[0].Address.Host), check.Equals, true)
	c.Assert(routertest.FakeRouter.HasRoute(a.Name, units[1].Address.Host), check.Equals, true)
	c.Assert(routertest.FakeRouter.HasRoute(a.Name, units[2].Address.Host), check.Equals, true)
	app, err := app.GetByName(a.Name)
	c.Assert(err, check.IsNil)
	addr, err := routertest.FakeRouter.Addr(app.Name)
	c.Assert(err, check.IsNil)
	c.Assert(app.Ip, check.Equals, addr)
}
예제 #5
0
파일: handlers.go 프로젝트: reoring/tsuru
func listContainersHandler(w http.ResponseWriter, r *http.Request, t auth.Token) error {
	address := r.URL.Query().Get(":address")
	if address != "" {
		node, err := mainDockerProvisioner.Cluster().GetNode(address)
		if err != nil {
			return err
		}
		hasAccess := permission.Check(t, permission.PermNodeRead,
			permission.Context(permission.CtxPool, node.Metadata["pool"]))
		if !hasAccess {
			return permission.ErrUnauthorized
		}
		containerList, err := mainDockerProvisioner.listContainersByHost(address)
		if err != nil {
			return err
		}
		return json.NewEncoder(w).Encode(containerList)
	}
	appName := r.URL.Query().Get(":appname")
	a, err := app.GetByName(appName)
	if err != nil {
		return err
	}
	hasAccess := permission.Check(t, permission.PermNodeRead,
		permission.Context(permission.CtxPool, a.Pool))
	if !hasAccess {
		return permission.ErrUnauthorized
	}
	containerList, err := mainDockerProvisioner.listContainersByApp(appName)
	if err != nil {
		return err
	}
	return json.NewEncoder(w).Encode(containerList)
}
예제 #6
0
파일: app.go 프로젝트: tsuru/tsuru
func getApp(name string) (*app.App, error) {
	a, err := app.GetByName(name)
	if err != nil {
		return nil, &errors.HTTP{Code: http.StatusNotFound, Message: fmt.Sprintf("App %s not found.", name)}
	}
	return a, nil
}
예제 #7
0
파일: app.go 프로젝트: edulemasson/tsuru
func addLog(w http.ResponseWriter, r *http.Request, t auth.Token) error {
	queryValues := r.URL.Query()
	app, err := app.GetByName(queryValues.Get(":app"))
	if err != nil {
		return err
	}
	defer r.Body.Close()
	body, err := ioutil.ReadAll(r.Body)
	if err != nil {
		return err
	}
	var logs []string
	err = json.Unmarshal(body, &logs)
	source := queryValues.Get("source")
	if len(source) == 0 {
		source = "app"
	}
	unit := queryValues.Get("unit")
	for _, log := range logs {
		err := app.Log(log, source, unit)
		if err != nil {
			return err
		}
	}
	w.WriteHeader(http.StatusOK)
	return nil
}
예제 #8
0
파일: app.go 프로젝트: edulemasson/tsuru
func registerUnit(w http.ResponseWriter, r *http.Request, t auth.Token) error {
	appName := r.URL.Query().Get(":app")
	data, err := ioutil.ReadAll(r.Body)
	if err != nil {
		return err
	}
	val, err := url.ParseQuery(string(data))
	if err != nil {
		return err
	}
	hostname := val.Get("hostname")
	var customData map[string]interface{}
	rawCustomData := val.Get("customdata")
	if rawCustomData != "" {
		err = json.Unmarshal([]byte(rawCustomData), &customData)
		if err != nil {
			return err
		}
	}
	a, err := app.GetByName(appName)
	if err != nil {
		return err
	}
	err = a.RegisterUnit(hostname, customData)
	if err != nil {
		if _, ok := err.(*provision.UnitNotFoundError); ok {
			return &errors.HTTP{Code: http.StatusNotFound, Message: err.Error()}
		}
		return err
	}
	return writeEnvVars(w, a)
}
예제 #9
0
파일: scheduler.go 프로젝트: 4eek/tsuru
func (s *segregatedScheduler) Schedule(c *cluster.Cluster, opts docker.CreateContainerOptions, schedulerOpts cluster.SchedulerOptions) (cluster.Node, error) {
	schedOpts, _ := schedulerOpts.([]string)
	if len(schedOpts) != 2 {
		return cluster.Node{}, fmt.Errorf("invalid scheduler opts: %#v", schedulerOpts)
	}
	appName := schedOpts[0]
	processName := schedOpts[1]
	a, _ := app.GetByName(appName)
	nodes, err := s.provisioner.Nodes(a)
	if err != nil {
		return cluster.Node{}, err
	}
	nodes, err = s.filterByMemoryUsage(a, nodes, s.maxMemoryRatio, s.TotalMemoryMetadata)
	if err != nil {
		return cluster.Node{}, err
	}
	node, err := s.chooseNode(nodes, opts.Name, appName, processName)
	if err != nil {
		return cluster.Node{}, err
	}
	var pool string
	if len(nodes) > 0 {
		pool = nodes[0].Metadata["pool"]
	}
	err = bs.CreateContainer(node, pool, mainDockerProvisioner, false)
	if err != nil && err != docker.ErrContainerAlreadyExists {
		return cluster.Node{Address: node}, err
	}
	return cluster.Node{Address: node}, nil
}
예제 #10
0
파일: app.go 프로젝트: philiptzou/tsuru
func deploy(w http.ResponseWriter, r *http.Request, t auth.Token) error {
	version := r.PostFormValue("version")
	archiveURL := r.PostFormValue("archive-url")
	if version == "" && archiveURL == "" {
		return &errors.HTTP{
			Code:    http.StatusBadRequest,
			Message: "you must specify either the version or the archive-url",
		}
	}
	if version != "" && archiveURL != "" {
		return &errors.HTTP{
			Code:    http.StatusBadRequest,
			Message: "you must specify either the version or the archive-url, but not both",
		}
	}
	commit := r.PostFormValue("commit")
	w.Header().Set("Content-Type", "text")
	appName := r.URL.Query().Get(":appname")
	instance, err := app.GetByName(appName)
	if err != nil {
		return &errors.HTTP{Code: http.StatusNotFound, Message: fmt.Sprintf("App %s not found.", appName)}
	}
	return app.Deploy(app.DeployOptions{
		App:          instance,
		Version:      version,
		Commit:       commit,
		ArchiveURL:   archiveURL,
		OutputStream: w,
	})

}
예제 #11
0
파일: quota_test.go 프로젝트: tsuru/tsuru
func (s *QuotaSuite) TestChangeAppQuota(c *check.C) {
	conn, err := db.Conn()
	c.Assert(err, check.IsNil)
	defer conn.Close()
	a := &app.App{
		Name:  "shangrila",
		Quota: quota.Quota{Limit: 4, InUse: 2},
		Teams: []string{s.team.Name},
	}
	err = conn.Apps().Insert(a)
	c.Assert(err, check.IsNil)
	defer conn.Apps().Remove(bson.M{"name": a.Name})
	body := bytes.NewBufferString("limit=40")
	request, _ := http.NewRequest("PUT", "/apps/shangrila/quota", body)
	request.Header.Set("Content-Type", "application/x-www-form-urlencoded")
	request.Header.Set("Authorization", "bearer "+s.token.GetValue())
	recorder := httptest.NewRecorder()
	handler := RunServer(true)
	handler.ServeHTTP(recorder, request)
	c.Assert(recorder.Code, check.Equals, http.StatusOK)
	a, err = app.GetByName(a.Name)
	c.Assert(err, check.IsNil)
	c.Assert(a.Quota.InUse, check.Equals, 2)
	c.Assert(a.Quota.Limit, check.Equals, 40)
	c.Assert(eventtest.EventDesc{
		Target: event.Target{Type: event.TargetTypeApp, Value: a.Name},
		Owner:  s.token.GetUserName(),
		Kind:   "app.admin.quota",
		StartCustomData: []map[string]interface{}{
			{"name": ":appname", "value": a.Name},
			{"name": "limit", "value": "40"},
		},
	}, eventtest.HasEvent)
}
예제 #12
0
func (s *S) TestSaveUnitsForwardShouldMaintainData(c *gocheck.C) {
	a := app.App{
		Name:     "otherapp",
		Platform: "zend",
		Deploys:  10,
	}
	conn, err := db.Conn()
	c.Assert(err, gocheck.IsNil)
	defer conn.Close()
	err = conn.Apps().Insert(a)
	c.Assert(err, gocheck.IsNil)
	a.Deploys = 0
	defer conn.Apps().Remove(bson.M{"name": a.Name})
	container := container{
		ID:       "id",
		Type:     "python",
		HostAddr: "",
		AppName:  a.Name,
	}
	coll := collection()
	c.Assert(err, gocheck.IsNil)
	coll.Insert(&container)
	context := action.FWContext{Params: []interface{}{&a}}
	_, err = saveUnits.Forward(context)
	c.Assert(err, gocheck.IsNil)
	app, err := app.GetByName(a.Name)
	c.Assert(err, gocheck.IsNil)
	c.Assert(app.Units[0].Name, gocheck.Equals, "id")
	c.Assert(int(app.Deploys), gocheck.Equals, 10)
}
예제 #13
0
파일: suite_test.go 프로젝트: tsuru/tsuru
func (s *S) SetUpTest(c *check.C) {
	queue.ResetQueue()
	err := rebuild.RegisterTask(func(appName string) (rebuild.RebuildApp, error) {
		a, err := app.GetByName(appName)
		if err == app.ErrAppNotFound {
			return nil, nil
		}
		return a, err
	})
	c.Assert(err, check.IsNil)
	routertest.FakeRouter.Reset()
	provisiontest.ProvisionerInstance.Reset()
	err = dbtest.ClearAllCollections(s.conn.Apps().Database)
	c.Assert(err, check.IsNil)
	s.user = &auth.User{Email: "*****@*****.**", Password: "******", Quota: quota.Unlimited}
	nativeScheme := auth.ManagedScheme(native.NativeScheme{})
	app.AuthScheme = nativeScheme
	_, err = nativeScheme.Create(s.user)
	c.Assert(err, check.IsNil)
	s.team = &auth.Team{Name: "admin"}
	c.Assert(err, check.IsNil)
	err = s.conn.Teams().Insert(s.team)
	c.Assert(err, check.IsNil)
	err = provision.AddPool(provision.AddPoolOptions{
		Name:        "p1",
		Default:     true,
		Provisioner: "fake",
	})
	c.Assert(err, check.IsNil)
}
예제 #14
0
func (p *dockerProvisioner) fixContainer(container *container.Container, info container.NetworkInfo) error {
	if info.HTTPHostPort == "" {
		return nil
	}
	appInstance, err := app.GetByName(container.AppName)
	if err != nil {
		return err
	}
	r, err := getRouterForApp(appInstance)
	if err != nil {
		return err
	}
	err = r.RemoveRoute(container.AppName, container.Address())
	if err != nil && err != router.ErrRouteNotFound {
		return err
	}
	container.IP = info.IP
	container.HostPort = info.HTTPHostPort
	err = r.AddRoute(container.AppName, container.Address())
	if err != nil && err != router.ErrRouteExists {
		return err
	}
	coll := p.Collection()
	defer coll.Close()
	return coll.Update(bson.M{"id": container.ID}, container)
}
예제 #15
0
파일: scheduler.go 프로젝트: tsuru/tsuru
func (s *segregatedScheduler) Schedule(c *cluster.Cluster, opts docker.CreateContainerOptions, schedulerOpts cluster.SchedulerOptions) (cluster.Node, error) {
	schedOpts, ok := schedulerOpts.(*container.SchedulerOpts)
	if !ok {
		return cluster.Node{}, &container.SchedulerError{
			Base: errors.Errorf("invalid scheduler opts: %#v", schedulerOpts),
		}
	}
	a, _ := app.GetByName(schedOpts.AppName)
	nodes, err := s.provisioner.Nodes(a)
	if err != nil {
		return cluster.Node{}, &container.SchedulerError{Base: err}
	}
	nodes, err = s.filterByMemoryUsage(a, nodes, s.maxMemoryRatio, s.TotalMemoryMetadata)
	if err != nil {
		return cluster.Node{}, &container.SchedulerError{Base: err}
	}
	node, err := s.chooseNodeToAdd(nodes, opts.Name, schedOpts.AppName, schedOpts.ProcessName)
	if err != nil {
		return cluster.Node{}, &container.SchedulerError{Base: err}
	}
	if schedOpts.ActionLimiter != nil {
		schedOpts.LimiterDone = schedOpts.ActionLimiter.Start(net.URLToHost(node))
	}
	return cluster.Node{Address: node}, nil
}
예제 #16
0
func (s *QuotaSuite) TestChangeAppQuota(c *check.C) {
	conn, err := db.Conn()
	c.Assert(err, check.IsNil)
	defer conn.Close()
	a := &app.App{
		Name:  "shangrila",
		Quota: quota.Quota{Limit: 4, InUse: 2},
		Teams: []string{s.team.Name},
	}
	err = conn.Apps().Insert(a)
	c.Assert(err, check.IsNil)
	defer conn.Apps().Remove(bson.M{"name": a.Name})
	body := bytes.NewBufferString("limit=40")
	request, _ := http.NewRequest("PUT", "/apps/shangrila/quota", body)
	request.Header.Set("Content-Type", "application/x-www-form-urlencoded")
	request.Header.Set("Authorization", "bearer "+s.token.GetValue())
	recorder := httptest.NewRecorder()
	handler := RunServer(true)
	handler.ServeHTTP(recorder, request)
	c.Assert(recorder.Code, check.Equals, http.StatusOK)
	a, err = app.GetByName(a.Name)
	c.Assert(err, check.IsNil)
	c.Assert(a.Quota.InUse, check.Equals, 2)
	c.Assert(a.Quota.Limit, check.Equals, 40)
}
예제 #17
0
파일: docker.go 프로젝트: kennylixi/tsuru
func moveOneContainer(c container, toHost string, errors chan error, wg *sync.WaitGroup, encoder *json.Encoder) {
	a, err := app.GetByName(c.AppName)
	defer wg.Done()
	if err != nil {
		errors <- err
		return
	}
	logProgress(encoder, "Moving unit %s for %q: %s -> %s...", c.ID, c.AppName, c.HostAddr, toHost)
	pipeline := action.NewPipeline(
		&provisionAddUnitToHost,
		&provisionRemoveOldUnit,
	)
	err = pipeline.Execute(a, toHost, c)
	if err != nil {
		errors <- err
		return
	}
	logProgress(encoder, "Finished moving unit %s for %q.", c.ID, c.AppName)
	addedUnit := pipeline.Result().(provision.Unit)
	err = moveOneContainerInDB(a, c, addedUnit)
	if err != nil {
		errors <- err
		return
	}
	logProgress(encoder, "Moved unit %s -> %s for %s in DB.", c.ID, addedUnit.Name, c.AppName)
}
예제 #18
0
func nodesForAppName(c *cluster.Cluster, appName string) ([]cluster.Node, error) {
	a, err := app.GetByName(appName)
	if err != nil {
		return nil, err
	}
	return nodesForApp(c, a)
}
예제 #19
0
파일: auth.go 프로젝트: renanoliveira/tsuru
func generateAppToken(w http.ResponseWriter, r *http.Request, t *auth.Token) error {
	var body jToken
	defer r.Body.Close()
	err := json.NewDecoder(r.Body).Decode(&body)
	if err != nil {
		return err
	}
	if body.Client == "" {
		return &errors.HTTP{
			Code:    http.StatusBadRequest,
			Message: "Missing client name in JSON body",
		}
	}
	token, err := auth.CreateApplicationToken(body.Client)
	if err != nil {
		return err
	}
	if body.Export {
		if a, err := app.GetByName(body.Client); err == nil {
			envs := []bind.EnvVar{
				{
					Name:   "TSURU_APP_TOKEN",
					Value:  token.Token,
					Public: false,
				},
			}
			a.SetEnvs(envs, false)
		}
	}
	return json.NewEncoder(w).Encode(token)
}
예제 #20
0
파일: auto_scale.go 프로젝트: keymon/tsuru
func (a *memoryScaler) nodesMemoryData(prov *dockerProvisioner, nodes []*cluster.Node) (map[string]*nodeMemoryData, error) {
	nodesMemoryData := make(map[string]*nodeMemoryData)
	containersMap, err := prov.runningContainersByNode(nodes)
	if err != nil {
		return nil, err
	}
	for _, node := range nodes {
		totalMemory, _ := strconv.ParseFloat(node.Metadata[a.totalMemoryMetadata], 64)
		if totalMemory == 0.0 {
			return nil, fmt.Errorf("no value found for memory metadata (%s) in node %s", a.totalMemoryMetadata, node.Address)
		}
		maxMemory := int64(float64(a.maxMemoryRatio) * totalMemory)
		data := &nodeMemoryData{
			containersMemory: make(map[string]int64),
			node:             node,
			maxMemory:        maxMemory,
		}
		nodesMemoryData[node.Address] = data
		for _, cont := range containersMap[node.Address] {
			a, err := app.GetByName(cont.AppName)
			if err != nil {
				return nil, fmt.Errorf("couldn't find container app (%s): %s", cont.AppName, err)
			}
			data.containersMemory[cont.ID] = a.Plan.Memory
			data.reserved += a.Plan.Memory
		}
		data.available = data.maxMemory - data.reserved
	}
	return nodesMemoryData, nil
}
예제 #21
0
파일: app.go 프로젝트: edulemasson/tsuru
func setUnitStatus(w http.ResponseWriter, r *http.Request, t auth.Token) error {
	unitName := r.URL.Query().Get(":unit")
	if unitName == "" {
		return &errors.HTTP{
			Code:    http.StatusBadRequest,
			Message: "missing unit",
		}
	}
	postStatus := r.FormValue("status")
	status, err := provision.ParseStatus(postStatus)
	if err != nil {
		return &errors.HTTP{
			Code:    http.StatusBadRequest,
			Message: err.Error(),
		}
	}
	appName := r.URL.Query().Get(":app")
	a, err := app.GetByName(appName)
	if err != nil {
		return &errors.HTTP{Code: http.StatusNotFound, Message: err.Error()}
	}
	err = a.SetUnitStatus(unitName, status)
	if _, ok := err.(*provision.UnitNotFoundError); ok {
		return &errors.HTTP{Code: http.StatusNotFound, Message: err.Error()}
	}
	if err == nil {
		w.WriteHeader(http.StatusOK)
	}
	return err
}
예제 #22
0
파일: deploy.go 프로젝트: RichardKnop/tsuru
func deployRollback(w http.ResponseWriter, r *http.Request, t auth.Token) error {
	appName := r.URL.Query().Get(":appname")
	instance, err := app.GetByName(appName)
	if err != nil {
		return &errors.HTTP{Code: http.StatusNotFound, Message: fmt.Sprintf("App %s not found.", appName)}
	}
	image := r.PostFormValue("image")
	if image == "" {
		return &errors.HTTP{
			Code:    http.StatusBadRequest,
			Message: "you cannot rollback without an image name",
		}
	}
	w.Header().Set("Content-Type", "application/json")
	writer := &io.SimpleJsonMessageEncoderWriter{Encoder: json.NewEncoder(w)}
	err = app.Deploy(app.DeployOptions{
		App:          instance,
		OutputStream: writer,
		Image:        image,
		User:         t.GetUserName(),
	})
	if err != nil {
		writer.Encode(io.SimpleJsonMessage{Error: err.Error()})
	}
	return nil
}
예제 #23
0
파일: plan_test.go 프로젝트: Endika/tsuru
func (s *S) TestChangePlan(c *check.C) {
	config.Set("docker:router", "fake")
	defer config.Unset("docker:router")
	plans := []app.Plan{
		{Name: "hiperplan", Memory: 536870912, Swap: 536870912, CpuShare: 100},
		{Name: "superplan", Memory: 268435456, Swap: 268435456, CpuShare: 100},
	}
	for _, plan := range plans {
		err := plan.Save()
		c.Assert(err, check.IsNil)
		defer app.PlanRemove(plan.Name)
	}
	a := app.App{Name: "someapp", Platform: "zend", TeamOwner: s.team.Name, Plan: plans[1]}
	err := app.CreateApp(&a, s.user)
	c.Assert(err, check.IsNil)
	defer s.logConn.Logs(a.Name).DropCollection()
	request, err := http.NewRequest("POST", "/apps/someapp/plan", strings.NewReader(`{"name":"hiperplan"}`))
	c.Assert(err, check.IsNil)
	request.Header.Set("Authorization", "bearer "+s.token.GetValue())
	recorder := httptest.NewRecorder()
	m := RunServer(true)
	m.ServeHTTP(recorder, request)
	c.Assert(recorder.Code, check.Equals, http.StatusOK)
	app, err := app.GetByName(a.Name)
	c.Assert(err, check.IsNil)
	c.Assert(app.Plan, check.DeepEquals, plans[0])
	c.Assert(s.provisioner.Restarts(&a, ""), check.Equals, 1)
}
예제 #24
0
func (s *S) TestUpdateTwice(c *gocheck.C) {
	a := getApp(s.conn, c)
	defer s.conn.Apps().Remove(bson.M{"name": a.Name})
	out := getOutput()
	update(out)
	a, err := app.GetByName(a.Name)
	c.Assert(err, gocheck.IsNil)
	c.Assert(a.Units[0].Ip, gocheck.Equals, "192.168.0.11")
	c.Assert(a.Units[0].Machine, gocheck.Equals, 1)
	c.Assert(a.Units[0].InstanceId, gocheck.Equals, "i-0800")
	c.Assert(a.Units[0].State, gocheck.Equals, provision.StatusStarted.String())
	update(out)
	a, err = app.GetByName(a.Name)
	c.Assert(err, gocheck.IsNil)
	c.Assert(len(a.Units), gocheck.Equals, 1)
}
예제 #25
0
파일: app.go 프로젝트: tsuru/tsuru
// title: app log
// path: /apps/{app}/log
// method: POST
// consume: application/x-www-form-urlencoded
// responses:
//   200: Ok
//   400: Invalid data
//   401: Unauthorized
//   404: App not found
func addLog(w http.ResponseWriter, r *http.Request, t auth.Token) error {
	a, err := app.GetByName(r.URL.Query().Get(":app"))
	if err != nil {
		return err
	}
	err = r.ParseForm()
	if err != nil {
		return &errors.HTTP{Code: http.StatusBadRequest, Message: err.Error()}
	}
	if t.GetAppName() != app.InternalAppName {
		allowed := permission.Check(t, permission.PermAppUpdateLog,
			contextsForApp(a)...,
		)
		if !allowed {
			return permission.ErrUnauthorized
		}
	}
	logs := r.Form["message"]
	source := r.FormValue("source")
	if source == "" {
		source = "app"
	}
	unit := r.FormValue("unit")
	for _, log := range logs {
		err := a.Log(log, source, unit)
		if err != nil {
			return err
		}
	}
	return nil
}
예제 #26
0
func (s *S) TestUpdateWithMultipleUnits(c *gocheck.C) {
	a := getApp(s.conn, c)
	out := getOutput()
	u := provision.Unit{
		Name:       "i-00000zz9",
		AppName:    "umaappqq",
		Type:       "python",
		Machine:    2,
		InstanceId: "i-0900",
		Ip:         "192.168.0.12",
		Status:     provision.StatusStarted,
	}
	out = append(out, u)
	update(out)
	a, err := app.GetByName(a.Name)
	c.Assert(err, gocheck.IsNil)
	c.Assert(len(a.Units), gocheck.Equals, 2)
	var unit app.Unit
	for _, unit = range a.Units {
		if unit.Machine == 2 {
			break
		}
	}
	c.Assert(unit.Name, gocheck.Equals, "i-00000zz9")
	c.Assert(unit.Ip, gocheck.Equals, "192.168.0.12")
	c.Assert(unit.InstanceId, gocheck.Equals, "i-0900")
	c.Assert(unit.State, gocheck.Equals, provision.StatusStarted.String())
	addr, _ := s.provisioner.Addr(a)
	c.Assert(a.Ip, gocheck.Equals, addr)
	c.Assert(a.State, gocheck.Equals, "ready")
}
예제 #27
0
파일: app.go 프로젝트: tsuru/tsuru
// title: set unit status
// path: /apps/{app}/units/{unit}
// method: POST
// consume: application/x-www-form-urlencoded
// responses:
//   200: Ok
//   400: Invalid data
//   401: Unauthorized
//   404: App or unit not found
func setUnitStatus(w http.ResponseWriter, r *http.Request, t auth.Token) error {
	unitName := r.URL.Query().Get(":unit")
	if unitName == "" {
		return &errors.HTTP{
			Code:    http.StatusBadRequest,
			Message: "missing unit",
		}
	}
	postStatus := r.FormValue("status")
	status, err := provision.ParseStatus(postStatus)
	if err != nil {
		return &errors.HTTP{
			Code:    http.StatusBadRequest,
			Message: err.Error(),
		}
	}
	appName := r.URL.Query().Get(":app")
	a, err := app.GetByName(appName)
	if err != nil {
		return &errors.HTTP{Code: http.StatusNotFound, Message: err.Error()}
	}
	allowed := permission.Check(t, permission.PermAppUpdateUnitStatus,
		contextsForApp(a)...,
	)
	if !allowed {
		return permission.ErrUnauthorized
	}
	err = a.SetUnitStatus(unitName, status)
	if _, ok := err.(*provision.UnitNotFoundError); ok {
		return &errors.HTTP{Code: http.StatusNotFound, Message: err.Error()}
	}
	return err
}
예제 #28
0
func (s segregatedScheduler) Schedule(opts docker.CreateContainerOptions, schedulerOpts cluster.SchedulerOptions) (cluster.Node, error) {
	conn, err := db.Conn()
	if err != nil {
		return cluster.Node{}, err
	}
	defer conn.Close()
	var cont container
	coll := collection()
	defer coll.Close()
	err = coll.Find(bson.M{"name": opts.Name}).One(&cont)
	if err != nil {
		return cluster.Node{}, err
	}
	app, err := app.GetByName(cont.AppName)
	if err != nil {
		return s.fallback(opts, cont)
	}
	var nodes []node
	var query bson.M
	if app.TeamOwner != "" {
		query = bson.M{"teams": app.TeamOwner}
	} else {
		query = bson.M{"teams": bson.M{"$in": app.Teams}}
	}
	err = conn.Collection(schedulerCollection).Find(query).All(&nodes)
	if err != nil || len(nodes) < 1 {
		return s.fallback(opts, cont)
	}
	return s.handle(opts, nodes, cont)
}
예제 #29
0
func deployRollback(w http.ResponseWriter, r *http.Request, t auth.Token) error {
	appName := r.URL.Query().Get(":appname")
	instance, err := app.GetByName(appName)
	if err != nil {
		return &errors.HTTP{Code: http.StatusNotFound, Message: fmt.Sprintf("App %s not found.", appName)}
	}
	image := r.PostFormValue("image")
	if image == "" {
		return &errors.HTTP{
			Code:    http.StatusBadRequest,
			Message: "you cannot rollback without an image name",
		}
	}
	w.Header().Set("Content-Type", "application/json")
	keepAliveWriter := io.NewKeepAliveWriter(w, 30*time.Second, "")
	defer keepAliveWriter.Stop()
	writer := &io.SimpleJsonMessageEncoderWriter{Encoder: json.NewEncoder(keepAliveWriter)}
	if !regexp.MustCompile(":v[0-9]+$").MatchString(image) {
		img, err := getImage(appName, image)
		//err is not handled because it is treated in funcion app.Deploy()
		if err == nil {
			image = img
		}
	}
	err = app.Deploy(app.DeployOptions{
		App:          instance,
		OutputStream: writer,
		Image:        image,
		User:         t.GetUserName(),
	})
	if err != nil {
		writer.Encode(io.SimpleJsonMessage{Error: err.Error()})
	}
	return nil
}
예제 #30
0
파일: rebuild_test.go 프로젝트: tsuru/tsuru
func (s *S) TestRebuildRoutes(c *check.C) {
	a := app.App{Name: "my-test-app", TeamOwner: s.team.Name}
	err := app.CreateApp(&a, s.user)
	c.Assert(err, check.IsNil)
	err = provisiontest.ProvisionerInstance.AddUnits(&a, 3, "web", nil)
	c.Assert(err, check.IsNil)
	units, err := a.Units()
	c.Assert(err, check.IsNil)
	routertest.FakeRouter.RemoveRoute(a.Name, units[2].Address)
	routertest.FakeRouter.AddRoute(a.Name, &url.URL{Scheme: "http", Host: "invalid:1234"})
	changes, err := rebuild.RebuildRoutes(&a)
	c.Assert(err, check.IsNil)
	c.Assert(changes.Added, check.DeepEquals, []string{units[2].Address.String()})
	c.Assert(changes.Removed, check.DeepEquals, []string{"http://invalid:1234"})
	routes, err := routertest.FakeRouter.Routes(a.Name)
	c.Assert(err, check.IsNil)
	c.Assert(routes, check.HasLen, 3)
	c.Assert(routertest.FakeRouter.HasRoute(a.Name, units[0].Address.String()), check.Equals, true)
	c.Assert(routertest.FakeRouter.HasRoute(a.Name, units[1].Address.String()), check.Equals, true)
	c.Assert(routertest.FakeRouter.HasRoute(a.Name, units[2].Address.String()), check.Equals, true)
	app, err := app.GetByName(a.Name)
	c.Assert(err, check.IsNil)
	addr, err := routertest.FakeRouter.Addr(app.Name)
	c.Assert(err, check.IsNil)
	c.Assert(app.Ip, check.Equals, addr)
}