<commit_before>// Copyright 2013 tsuru authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package api

import (
	"encoding/json"
	"fmt"
	"io"
	"mime/multipart"
	"net/http"
	"strconv"
	"strings"
	"time"

	"github.com/pkg/errors"
	"github.com/tsuru/tsuru/app"
	"github.com/tsuru/tsuru/auth"
	tsuruErrors "github.com/tsuru/tsuru/errors"
	"github.com/tsuru/tsuru/event"
	tsuruIo "github.com/tsuru/tsuru/io"
	"github.com/tsuru/tsuru/permission"
	"github.com/tsuru/tsuru/repository"
)

// title: app deploy
// path: /apps/{appname}/deploy
// method: POST
// consume: application/x-www-form-urlencoded
// responses:
//   200: OK
//   400: Invalid data
//   403: Forbidden
//   404: Not found
func deploy(w http.ResponseWriter, r *http.Request, t auth.Token) (err error) {
	var file multipart.File
	var fileSize int64
	if strings.HasPrefix(r.Header.Get("Content-Type"), "multipart/") {
		file, _, err = r.FormFile("file")
		if err != nil {
			return &tsuruErrors.HTTP{
				Code:    http.StatusBadRequest,
				Message: err.Error(),
			}
		}
		fileSize, err = file.Seek(0, io.SeekEnd)
		if err != nil {
			return errors.Wrap(err, "unable to find uploaded file size")
		}
		file.Seek(0, io.SeekStart)
		defer file.Close()
	}
	archiveURL := r.FormValue("archive-url")
	image := r.FormValue("image")
	if image == "" && archiveURL == "" && file == nil {
		return &tsuruErrors.HTTP{
			Code:    http.StatusBadRequest,
			Message: "you must specify either the archive-url, a image url or upload a file.",
		}
	}
	commit := r.FormValue("commit")
	w.Header().Set("Content-Type", "text")
	appName := r.URL.Query().Get(":appname")
	origin := r.FormValue("origin")
	if image != "" {
		origin = "image"
	}
	if origin != "" {
		if !app.ValidateOrigin(origin) {
			return &tsuruErrors.HTTP{
				Code:    http.StatusBadRequest,
				Message: "Invalid deployment origin",
			}
		}
	}
	var userName string
	if t.IsAppToken() {
		if t.GetAppName() != appName && t.GetAppName() != app.InternalAppName {
			return &tsuruErrors.HTTP{Code: http.StatusUnauthorized, Message: "invalid app token"}
		}
		userName = r.FormValue("user")
	} else {
		commit = ""
		userName = t.GetUserName()
	}
	instance, err := app.GetByName(appName)
	if err != nil {
		return &tsuruErrors.HTTP{Code: http.StatusNotFound, Message: err.Error()}
	}
	if (instance.GetPlatform() == "") && (origin != "image") {
		return &tsuruErrors.HTTP{Code: http.StatusUnauthorized, Message: "can't deploy app without platform, if it's not an image"}
	}
	var build bool
	buildString := r.FormValue("build")
	if buildString != "" {
		build, err = strconv.ParseBool(buildString)
		if err != nil {
			return &tsuruErrors.HTTP{
				Code:    http.StatusBadRequest,
				Message: err.Error(),
			}
		}
	}
	message := r.FormValue("message")
	if commit != "" && message == "" {
		var messages []string
		messages, err = repository.Manager().CommitMessages(instance.Name, commit, 1)
		if err != nil {
			return err
		}
		if len(messages) > 0 {
			message = messages[0]
		}
	}
	if origin == "" && commit != "" {
		origin = "git"
	}
	opts := app.DeployOptions{
		App:        instance,
		Commit:     commit,
		FileSize:   fileSize,
		File:       file,
		ArchiveURL: archiveURL,
		User:       userName,
		Image:      image,
		Origin:     origin,
		Build:      build,
		Message:    message,
	}
	opts.GetKind()
	if t.GetAppName() != app.InternalAppName {
		canDeploy := permission.Check(t, permSchemeForDeploy(opts), contextsForApp(instance)...)
		if !canDeploy {
			return &tsuruErrors.HTTP{Code: http.StatusForbidden, Message: "User does not have permission to do this action in this app"}
		}
	}
	var imageID string
	evt, err := event.New(&event.Opts{
		Target:        appTarget(appName),
		Kind:          permission.PermAppDeploy,
		RawOwner:      event.Owner{Type: event.OwnerTypeUser, Name: userName},
		CustomData:    opts,
		Allowed:       event.Allowed(permission.PermAppReadEvents, contextsForApp(instance)...),
		AllowedCancel: event.Allowed(permission.PermAppUpdateEvents, contextsForApp(instance)...),
		Cancelable:    true,
	})
	if err != nil {
		return err
	}
	defer func() { evt.DoneCustomData(err, map[string]string{"image": imageID}) }()
	opts.Event = evt
	writer := tsuruIo.NewKeepAliveWriter(w, 30*time.Second, "please wait...")
	defer writer.Stop()
	opts.OutputStream = writer
	imageID, err = app.Deploy(opts)
	if err == nil {
		fmt.Fprintln(w, "\nOK")
	}
	return err
}

func permSchemeForDeploy(opts app.DeployOptions) *permission.PermissionScheme {
	switch opts.GetKind() {
	case app.DeployGit:
		return permission.PermAppDeployGit
	case app.DeployImage:
		return permission.PermAppDeployImage
	case app.DeployUpload:
		return permission.PermAppDeployUpload
	case app.DeployUploadBuild:
		return permission.PermAppDeployBuild
	case app.DeployArchiveURL:
		return permission.PermAppDeployArchiveUrl
	case app.DeployRollback:
		return permission.PermAppDeployRollback
	default:
		return permission.PermAppDeploy
	}
}

// title: deploy diff
// path: /apps/{appname}/diff
// method: POST
// consume: application/x-www-form-urlencoded
// responses:
//   200: OK
//   400: Invalid data
//   403: Forbidden
//   404: Not found
func diffDeploy(w http.ResponseWriter, r *http.Request, t auth.Token) error {
	writer := tsuruIo.NewKeepAliveWriter(w, 30*time.Second, "")
	defer writer.Stop()
	fmt.Fprint(w, "Saving the difference between the old and new code\n")
	appName := r.URL.Query().Get(":appname")
	diff := r.FormValue("customdata")
	instance, err := app.GetByName(appName)
	if err != nil {
		return &tsuruErrors.HTTP{Code: http.StatusNotFound, Message: err.Error()}
	}
	if t.GetAppName() != app.InternalAppName {
		canDiffDeploy := permission.Check(t, permission.PermAppReadDeploy, contextsForApp(instance)...)
		if !canDiffDeploy {
			return &tsuruErrors.HTTP{Code: http.StatusForbidden, Message: permission.ErrUnauthorized.Error()}
		}
	}
	evt, err := event.GetRunning(appTarget(appName), permission.PermAppDeploy.FullName())
	if err != nil {
		return err
	}
	return evt.SetOtherCustomData(map[string]string{
		"diff": diff,
	})
}

// title: rollback
// path: /apps/{appname}/deploy/rollback
// method: POST
// consume: application/x-www-form-urlencoded
// produce: application/x-json-stream
// responses:
//   200: OK
//   400: Invalid data
//   403: Forbidden
//   404: Not found
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 &tsuruErrors.HTTP{Code: http.StatusNotFound, Message: fmt.Sprintf("App %s not found.", appName)}
	}
	image := r.FormValue("image")
	if image == "" {
		return &tsuruErrors.HTTP{
			Code:    http.StatusBadRequest,
			Message: "you cannot rollback without an image name",
		}
	}
	origin := r.FormValue("origin")
	if origin != "" {
		if !app.ValidateOrigin(origin) {
			return &tsuruErrors.HTTP{
				Code:    http.StatusBadRequest,
				Message: "Invalid deployment origin",
			}
		}
	}
	w.Header().Set("Content-Type", "application/x-json-stream")
	keepAliveWriter := tsuruIo.NewKeepAliveWriter(w, 30*time.Second, "")
	defer keepAliveWriter.Stop()
	writer := &tsuruIo.SimpleJsonMessageEncoderWriter{Encoder: json.NewEncoder(keepAliveWriter)}
	opts := app.DeployOptions{
		App:          instance,
		OutputStream: writer,
		Image:        image,
		User:         t.GetUserName(),
		Origin:       origin,
		Rollback:     true,
	}
	opts.GetKind()
	canRollback := permission.Check(t, permSchemeForDeploy(opts), contextsForApp(instance)...)
	if !canRollback {
		return &tsuruErrors.HTTP{Code: http.StatusForbidden, Message: permission.ErrUnauthorized.Error()}
	}
	var imageID string
	evt, err := event.New(&event.Opts{
		Target:        appTarget(appName),
		Kind:          permission.PermAppDeploy,
		Owner:         t,
		CustomData:    opts,
		Allowed:       event.Allowed(permission.PermAppReadEvents, contextsForApp(instance)...),
		AllowedCancel: event.Allowed(permission.PermAppUpdateEvents, contextsForApp(instance)...),
		Cancelable:    true,
	})
	if err != nil {
		return err
	}
	defer func() { evt.DoneCustomData(err, map[string]string{"image": imageID}) }()
	opts.Event = evt
	imageID, err = app.Deploy(opts)
	if err != nil {
		writer.Encode(tsuruIo.SimpleJsonMessage{Error: err.Error()})
	}
	return nil
}

// title: deploy list
// path: /deploys
// method: GET
// produce: application/json
// responses:
//   200: OK
//   204: No content
func deploysList(w http.ResponseWriter, r *http.Request, t auth.Token) error {
	contexts := permission.ContextsForPermission(t, permission.PermAppReadDeploy)
	if len(contexts) == 0 {
		w.WriteHeader(http.StatusNoContent)
		return nil
	}
	filter := appFilterByContext(contexts, nil)
	filter.Name = r.URL.Query().Get("app")
	skip := r.URL.Query().Get("skip")
	limit := r.URL.Query().Get("limit")
	skipInt, _ := strconv.Atoi(skip)
	limitInt, _ := strconv.Atoi(limit)
	deploys, err := app.ListDeploys(filter, skipInt, limitInt)
	if err != nil {
		return err
	}
	if len(deploys) == 0 {
		w.WriteHeader(http.StatusNoContent)
		return nil
	}
	w.Header().Add("Content-Type", "application/json")
	return json.NewEncoder(w).Encode(deploys)
}

// title: deploy info
// path: /deploys/{deploy}
// method: GET
// produce: application/json
// responses:
//   200: OK
//   401: Unauthorized
//   404: Not found
func deployInfo(w http.ResponseWriter, r *http.Request, t auth.Token) error {
	depID := r.URL.Query().Get(":deploy")
	deploy, err := app.GetDeploy(depID)
	if err != nil {
		if err == event.ErrEventNotFound {
			return &tsuruErrors.HTTP{Code: http.StatusNotFound, Message: "Deploy not found."}
		}
		return err
	}
	dbApp, err := app.GetByName(deploy.App)
	if err != nil {
		return err
	}
	canGet := permission.Check(t, permission.PermAppReadDeploy, contextsForApp(dbApp)...)
	if !canGet {
		return &tsuruErrors.HTTP{Code: http.StatusNotFound, Message: "Deploy not found."}
	}
	w.Header().Add("Content-Type", "application/json")
	return json.NewEncoder(w).Encode(deploy)
}

// title: rebuild
// path: /apps/{appname}/deploy/rebuild
// method: POST
// consume: application/x-www-form-urlencoded
// produce: application/x-json-stream
// responses:
//   200: OK
//   400: Invalid data
//   403: Forbidden
//   404: Not found
func deployRebuild(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 &tsuruErrors.HTTP{Code: http.StatusNotFound, Message: fmt.Sprintf("App %s not found.", appName)}
	}
	origin := r.FormValue("origin")
	if !app.ValidateOrigin(origin) {
		return &tsuruErrors.HTTP{
			Code:    http.StatusBadRequest,
			Message: "Invalid deployment origin",
		}
	}
	w.Header().Set("Content-Type", "application/x-json-stream")
	keepAliveWriter := tsuruIo.NewKeepAliveWriter(w, 30*time.Second, "")
	defer keepAliveWriter.Stop()
	writer := &tsuruIo.SimpleJsonMessageEncoderWriter{Encoder: json.NewEncoder(keepAliveWriter)}
	opts := app.DeployOptions{
		App:          instance,
		OutputStream: writer,
		User:         t.GetUserName(),
		Origin:       origin,
		Kind:         app.DeployRebuild,
	}
	canDeploy := permission.Check(t, permSchemeForDeploy(opts), contextsForApp(instance)...)
	if !canDeploy {
		return &tsuruErrors.HTTP{Code: http.StatusForbidden, Message: permission.ErrUnauthorized.Error()}
	}
	var imageID string
	evt, err := event.New(&event.Opts{
		Target:        appTarget(appName),
		Kind:          permission.PermAppDeploy,
		Owner:         t,
		CustomData:    opts,
		Allowed:       event.Allowed(permission.PermAppReadEvents, contextsForApp(instance)...),
		AllowedCancel: event.Allowed(permission.PermAppUpdateEvents, contextsForApp(instance)...),
		Cancelable:    true,
	})
	if err != nil {
		return err
	}
	defer func() { evt.DoneCustomData(err, map[string]string{"image": imageID}) }()
	opts.Event = evt
	imageID, err = app.Deploy(opts)
	if err != nil {
		writer.Encode(tsuruIo.SimpleJsonMessage{Error: err.Error()})
	}
	return nil
}
<commit_msg>api: changes response error status<commit_after>// Copyright 2013 tsuru authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package api

import (
	"encoding/json"
	"fmt"
	"io"
	"mime/multipart"
	"net/http"
	"strconv"
	"strings"
	"time"

	"github.com/pkg/errors"
	"github.com/tsuru/tsuru/app"
	"github.com/tsuru/tsuru/auth"
	tsuruErrors "github.com/tsuru/tsuru/errors"
	"github.com/tsuru/tsuru/event"
	tsuruIo "github.com/tsuru/tsuru/io"
	"github.com/tsuru/tsuru/permission"
	"github.com/tsuru/tsuru/repository"
)

// title: app deploy
// path: /apps/{appname}/deploy
// method: POST
// consume: application/x-www-form-urlencoded
// responses:
//   200: OK
//   400: Invalid data
//   403: Forbidden
//   404: Not found
func deploy(w http.ResponseWriter, r *http.Request, t auth.Token) (err error) {
	var file multipart.File
	var fileSize int64
	if strings.HasPrefix(r.Header.Get("Content-Type"), "multipart/") {
		file, _, err = r.FormFile("file")
		if err != nil {
			return &tsuruErrors.HTTP{
				Code:    http.StatusBadRequest,
				Message: err.Error(),
			}
		}
		fileSize, err = file.Seek(0, io.SeekEnd)
		if err != nil {
			return errors.Wrap(err, "unable to find uploaded file size")
		}
		file.Seek(0, io.SeekStart)
		defer file.Close()
	}
	archiveURL := r.FormValue("archive-url")
	image := r.FormValue("image")
	if image == "" && archiveURL == "" && file == nil {
		return &tsuruErrors.HTTP{
			Code:    http.StatusBadRequest,
			Message: "you must specify either the archive-url, a image url or upload a file.",
		}
	}
	commit := r.FormValue("commit")
	w.Header().Set("Content-Type", "text")
	appName := r.URL.Query().Get(":appname")
	origin := r.FormValue("origin")
	if image != "" {
		origin = "image"
	}
	if origin != "" {
		if !app.ValidateOrigin(origin) {
			return &tsuruErrors.HTTP{
				Code:    http.StatusBadRequest,
				Message: "Invalid deployment origin",
			}
		}
	}
	var userName string
	if t.IsAppToken() {
		if t.GetAppName() != appName && t.GetAppName() != app.InternalAppName {
			return &tsuruErrors.HTTP{Code: http.StatusUnauthorized, Message: "invalid app token"}
		}
		userName = r.FormValue("user")
	} else {
		commit = ""
		userName = t.GetUserName()
	}
	instance, err := app.GetByName(appName)
	if err != nil {
		return &tsuruErrors.HTTP{Code: http.StatusNotFound, Message: err.Error()}
	}
	if (instance.GetPlatform() == "") && (origin != "image") {
		return &tsuruErrors.HTTP{Code: http.StatusBadRequest, Message: "can't deploy app without platform, if it's not an image"}
	}
	var build bool
	buildString := r.FormValue("build")
	if buildString != "" {
		build, err = strconv.ParseBool(buildString)
		if err != nil {
			return &tsuruErrors.HTTP{
				Code:    http.StatusBadRequest,
				Message: err.Error(),
			}
		}
	}
	message := r.FormValue("message")
	if commit != "" && message == "" {
		var messages []string
		messages, err = repository.Manager().CommitMessages(instance.Name, commit, 1)
		if err != nil {
			return err
		}
		if len(messages) > 0 {
			message = messages[0]
		}
	}
	if origin == "" && commit != "" {
		origin = "git"
	}
	opts := app.DeployOptions{
		App:        instance,
		Commit:     commit,
		FileSize:   fileSize,
		File:       file,
		ArchiveURL: archiveURL,
		User:       userName,
		Image:      image,
		Origin:     origin,
		Build:      build,
		Message:    message,
	}
	opts.GetKind()
	if t.GetAppName() != app.InternalAppName {
		canDeploy := permission.Check(t, permSchemeForDeploy(opts), contextsForApp(instance)...)
		if !canDeploy {
			return &tsuruErrors.HTTP{Code: http.StatusForbidden, Message: "User does not have permission to do this action in this app"}
		}
	}
	var imageID string
	evt, err := event.New(&event.Opts{
		Target:        appTarget(appName),
		Kind:          permission.PermAppDeploy,
		RawOwner:      event.Owner{Type: event.OwnerTypeUser, Name: userName},
		CustomData:    opts,
		Allowed:       event.Allowed(permission.PermAppReadEvents, contextsForApp(instance)...),
		AllowedCancel: event.Allowed(permission.PermAppUpdateEvents, contextsForApp(instance)...),
		Cancelable:    true,
	})
	if err != nil {
		return err
	}
	defer func() { evt.DoneCustomData(err, map[string]string{"image": imageID}) }()
	opts.Event = evt
	writer := tsuruIo.NewKeepAliveWriter(w, 30*time.Second, "please wait...")
	defer writer.Stop()
	opts.OutputStream = writer
	imageID, err = app.Deploy(opts)
	if err == nil {
		fmt.Fprintln(w, "\nOK")
	}
	return err
}

func permSchemeForDeploy(opts app.DeployOptions) *permission.PermissionScheme {
	switch opts.GetKind() {
	case app.DeployGit:
		return permission.PermAppDeployGit
	case app.DeployImage:
		return permission.PermAppDeployImage
	case app.DeployUpload:
		return permission.PermAppDeployUpload
	case app.DeployUploadBuild:
		return permission.PermAppDeployBuild
	case app.DeployArchiveURL:
		return permission.PermAppDeployArchiveUrl
	case app.DeployRollback:
		return permission.PermAppDeployRollback
	default:
		return permission.PermAppDeploy
	}
}

// title: deploy diff
// path: /apps/{appname}/diff
// method: POST
// consume: application/x-www-form-urlencoded
// responses:
//   200: OK
//   400: Invalid data
//   403: Forbidden
//   404: Not found
func diffDeploy(w http.ResponseWriter, r *http.Request, t auth.Token) error {
	writer := tsuruIo.NewKeepAliveWriter(w, 30*time.Second, "")
	defer writer.Stop()
	fmt.Fprint(w, "Saving the difference between the old and new code\n")
	appName := r.URL.Query().Get(":appname")
	diff := r.FormValue("customdata")
	instance, err := app.GetByName(appName)
	if err != nil {
		return &tsuruErrors.HTTP{Code: http.StatusNotFound, Message: err.Error()}
	}
	if t.GetAppName() != app.InternalAppName {
		canDiffDeploy := permission.Check(t, permission.PermAppReadDeploy, contextsForApp(instance)...)
		if !canDiffDeploy {
			return &tsuruErrors.HTTP{Code: http.StatusForbidden, Message: permission.ErrUnauthorized.Error()}
		}
	}
	evt, err := event.GetRunning(appTarget(appName), permission.PermAppDeploy.FullName())
	if err != nil {
		return err
	}
	return evt.SetOtherCustomData(map[string]string{
		"diff": diff,
	})
}

// title: rollback
// path: /apps/{appname}/deploy/rollback
// method: POST
// consume: application/x-www-form-urlencoded
// produce: application/x-json-stream
// responses:
//   200: OK
//   400: Invalid data
//   403: Forbidden
//   404: Not found
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 &tsuruErrors.HTTP{Code: http.StatusNotFound, Message: fmt.Sprintf("App %s not found.", appName)}
	}
	image := r.FormValue("image")
	if image == "" {
		return &tsuruErrors.HTTP{
			Code:    http.StatusBadRequest,
			Message: "you cannot rollback without an image name",
		}
	}
	origin := r.FormValue("origin")
	if origin != "" {
		if !app.ValidateOrigin(origin) {
			return &tsuruErrors.HTTP{
				Code:    http.StatusBadRequest,
				Message: "Invalid deployment origin",
			}
		}
	}
	w.Header().Set("Content-Type", "application/x-json-stream")
	keepAliveWriter := tsuruIo.NewKeepAliveWriter(w, 30*time.Second, "")
	defer keepAliveWriter.Stop()
	writer := &tsuruIo.SimpleJsonMessageEncoderWriter{Encoder: json.NewEncoder(keepAliveWriter)}
	opts := app.DeployOptions{
		App:          instance,
		OutputStream: writer,
		Image:        image,
		User:         t.GetUserName(),
		Origin:       origin,
		Rollback:     true,
	}
	opts.GetKind()
	canRollback := permission.Check(t, permSchemeForDeploy(opts), contextsForApp(instance)...)
	if !canRollback {
		return &tsuruErrors.HTTP{Code: http.StatusForbidden, Message: permission.ErrUnauthorized.Error()}
	}
	var imageID string
	evt, err := event.New(&event.Opts{
		Target:        appTarget(appName),
		Kind:          permission.PermAppDeploy,
		Owner:         t,
		CustomData:    opts,
		Allowed:       event.Allowed(permission.PermAppReadEvents, contextsForApp(instance)...),
		AllowedCancel: event.Allowed(permission.PermAppUpdateEvents, contextsForApp(instance)...),
		Cancelable:    true,
	})
	if err != nil {
		return err
	}
	defer func() { evt.DoneCustomData(err, map[string]string{"image": imageID}) }()
	opts.Event = evt
	imageID, err = app.Deploy(opts)
	if err != nil {
		writer.Encode(tsuruIo.SimpleJsonMessage{Error: err.Error()})
	}
	return nil
}

// title: deploy list
// path: /deploys
// method: GET
// produce: application/json
// responses:
//   200: OK
//   204: No content
func deploysList(w http.ResponseWriter, r *http.Request, t auth.Token) error {
	contexts := permission.ContextsForPermission(t, permission.PermAppReadDeploy)
	if len(contexts) == 0 {
		w.WriteHeader(http.StatusNoContent)
		return nil
	}
	filter := appFilterByContext(contexts, nil)
	filter.Name = r.URL.Query().Get("app")
	skip := r.URL.Query().Get("skip")
	limit := r.URL.Query().Get("limit")
	skipInt, _ := strconv.Atoi(skip)
	limitInt, _ := strconv.Atoi(limit)
	deploys, err := app.ListDeploys(filter, skipInt, limitInt)
	if err != nil {
		return err
	}
	if len(deploys) == 0 {
		w.WriteHeader(http.StatusNoContent)
		return nil
	}
	w.Header().Add("Content-Type", "application/json")
	return json.NewEncoder(w).Encode(deploys)
}

// title: deploy info
// path: /deploys/{deploy}
// method: GET
// produce: application/json
// responses:
//   200: OK
//   401: Unauthorized
//   404: Not found
func deployInfo(w http.ResponseWriter, r *http.Request, t auth.Token) error {
	depID := r.URL.Query().Get(":deploy")
	deploy, err := app.GetDeploy(depID)
	if err != nil {
		if err == event.ErrEventNotFound {
			return &tsuruErrors.HTTP{Code: http.StatusNotFound, Message: "Deploy not found."}
		}
		return err
	}
	dbApp, err := app.GetByName(deploy.App)
	if err != nil {
		return err
	}
	canGet := permission.Check(t, permission.PermAppReadDeploy, contextsForApp(dbApp)...)
	if !canGet {
		return &tsuruErrors.HTTP{Code: http.StatusNotFound, Message: "Deploy not found."}
	}
	w.Header().Add("Content-Type", "application/json")
	return json.NewEncoder(w).Encode(deploy)
}

// title: rebuild
// path: /apps/{appname}/deploy/rebuild
// method: POST
// consume: application/x-www-form-urlencoded
// produce: application/x-json-stream
// responses:
//   200: OK
//   400: Invalid data
//   403: Forbidden
//   404: Not found
func deployRebuild(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 &tsuruErrors.HTTP{Code: http.StatusNotFound, Message: fmt.Sprintf("App %s not found.", appName)}
	}
	origin := r.FormValue("origin")
	if !app.ValidateOrigin(origin) {
		return &tsuruErrors.HTTP{
			Code:    http.StatusBadRequest,
			Message: "Invalid deployment origin",
		}
	}
	w.Header().Set("Content-Type", "application/x-json-stream")
	keepAliveWriter := tsuruIo.NewKeepAliveWriter(w, 30*time.Second, "")
	defer keepAliveWriter.Stop()
	writer := &tsuruIo.SimpleJsonMessageEncoderWriter{Encoder: json.NewEncoder(keepAliveWriter)}
	opts := app.DeployOptions{
		App:          instance,
		OutputStream: writer,
		User:         t.GetUserName(),
		Origin:       origin,
		Kind:         app.DeployRebuild,
	}
	canDeploy := permission.Check(t, permSchemeForDeploy(opts), contextsForApp(instance)...)
	if !canDeploy {
		return &tsuruErrors.HTTP{Code: http.StatusForbidden, Message: permission.ErrUnauthorized.Error()}
	}
	var imageID string
	evt, err := event.New(&event.Opts{
		Target:        appTarget(appName),
		Kind:          permission.PermAppDeploy,
		Owner:         t,
		CustomData:    opts,
		Allowed:       event.Allowed(permission.PermAppReadEvents, contextsForApp(instance)...),
		AllowedCancel: event.Allowed(permission.PermAppUpdateEvents, contextsForApp(instance)...),
		Cancelable:    true,
	})
	if err != nil {
		return err
	}
	defer func() { evt.DoneCustomData(err, map[string]string{"image": imageID}) }()
	opts.Event = evt
	imageID, err = app.Deploy(opts)
	if err != nil {
		writer.Encode(tsuruIo.SimpleJsonMessage{Error: err.Error()})
	}
	return nil
}
<|endoftext|>


<commit_before>package api

import (
	"github.com/martinp/atbapi/atb"
	"strconv"
	"strings"
	"time"
)

type BusStops struct {
	Stops []BusStop `json:"stops"`
}

type BusStop struct {
	StopId      int     `json:"stopId"`
	NodeId      int     `json:"nodeId"`
	Description string  `json:"description"`
	Longitude   float64 `json:"longitude"`
	Latitude    float64 `json:"latitude"`
	MobileCode  string  `json:"mobileCode"`
	MobileName  string  `json:"mobileName"`
}

type Departures struct {
	TowardsCentrum bool        `json:"isGoingTowardsCentrum"`
	Departures     []Departure `json:"departures"`
}

type Departure struct {
	LineId                  string `json:"line"`
	RegisteredDepartureTime string `json:"registeredDepartureTime"`
	ScheduledDepartureTime  string `json:"scheduledDepartureTime"`
	Destination             string `json:"destination"`
	IsRealtimeData          bool   `json:"isRealtimeData"`
}

func convertBusStop(s atb.BusStop) (BusStop, error) {
	nodeId, err := strconv.Atoi(s.NodeId)
	if err != nil {
		return BusStop{}, err
	}
	longitude, err := strconv.ParseFloat(s.Longitude, 64)
	if err != nil {
		return BusStop{}, err
	}
	latitude := float64(s.Latitude)
	return BusStop{
		StopId:      s.StopId,
		NodeId:      nodeId,
		Description: s.Description,
		Longitude:   longitude,
		Latitude:    latitude,
		MobileCode:  s.MobileCode,
		MobileName:  s.MobileName,
	}, nil
}

func convertBusStops(s atb.BusStops) (BusStops, error) {
	stops := make([]BusStop, 0, len(s.Stops))
	for _, stop := range s.Stops {
		converted, err := convertBusStop(stop)
		if err != nil {
			return BusStops{}, err
		}
		stops = append(stops, converted)
	}
	return BusStops{Stops: stops}, nil
}

func convertTime(src string) (string, error) {
	t, err := time.Parse("02.01.2006 15:04", src)
	if err != nil {
		return "", err
	}
	return t.Format("2006-01-02T15:04:05.000"), nil
}

func isRealtime(s string) bool {
	return strings.EqualFold(s, "prev")
}

func convertForecast(f atb.Forecast) (Departure, error) {
	registeredDeparture, err := convertTime(f.RegisteredDepartureTime)
	if err != nil {
		return Departure{}, err
	}
	scheduledDeparture, err := convertTime(f.ScheduledDepartureTime)
	if err != nil {
		return Departure{}, err
	}
	return Departure{
		LineId:                  f.LineId,
		Destination:             f.Destination,
		RegisteredDepartureTime: registeredDeparture,
		ScheduledDepartureTime:  scheduledDeparture,
		IsRealtimeData:          isRealtime(f.StationForecast),
	}, nil
}

func isTowardsCentrum(nodeId int) bool {
	return (nodeId/1000)%2 == 1
}

func convertForecasts(f atb.Forecasts) (Departures, error) {
	towardsCentrum := false
	if len(f.Nodes) > 0 {
		nodeId, err := strconv.Atoi(f.Nodes[0].NodeId)
		if err != nil {
			return Departures{}, err
		}
		towardsCentrum = isTowardsCentrum(nodeId)
	}
	departures := make([]Departure, 0, len(f.Forecasts))
	for _, forecast := range f.Forecasts {
		departure, err := convertForecast(forecast)
		if err != nil {
			return Departures{}, err
		}
		departures = append(departures, departure)
	}
	return Departures{
		TowardsCentrum: towardsCentrum,
		Departures:     departures,
	}, nil
}
<commit_msg>Use int for bus stop lat/lon<commit_after>package api

import (
	"github.com/martinp/atbapi/atb"
	"strconv"
	"strings"
	"time"
)

type BusStops struct {
	Stops []BusStop `json:"stops"`
}

type BusStop struct {
	StopId      int    `json:"stopId"`
	NodeId      int    `json:"nodeId"`
	Description string `json:"description"`
	Longitude   int    `json:"longitude"`
	Latitude    int    `json:"latitude"`
	MobileCode  string `json:"mobileCode"`
	MobileName  string `json:"mobileName"`
}

type Departures struct {
	TowardsCentrum bool        `json:"isGoingTowardsCentrum"`
	Departures     []Departure `json:"departures"`
}

type Departure struct {
	LineId                  string `json:"line"`
	RegisteredDepartureTime string `json:"registeredDepartureTime"`
	ScheduledDepartureTime  string `json:"scheduledDepartureTime"`
	Destination             string `json:"destination"`
	IsRealtimeData          bool   `json:"isRealtimeData"`
}

func convertBusStop(s atb.BusStop) (BusStop, error) {
	nodeId, err := strconv.Atoi(s.NodeId)
	if err != nil {
		return BusStop{}, err
	}
	longitude, err := strconv.Atoi(s.Longitude)
	if err != nil {
		return BusStop{}, err
	}
	return BusStop{
		StopId:      s.StopId,
		NodeId:      nodeId,
		Description: s.Description,
		Longitude:   longitude,
		Latitude:    s.Latitude,
		MobileCode:  s.MobileCode,
		MobileName:  s.MobileName,
	}, nil
}

func convertBusStops(s atb.BusStops) (BusStops, error) {
	stops := make([]BusStop, 0, len(s.Stops))
	for _, stop := range s.Stops {
		converted, err := convertBusStop(stop)
		if err != nil {
			return BusStops{}, err
		}
		stops = append(stops, converted)
	}
	return BusStops{Stops: stops}, nil
}

func convertTime(src string) (string, error) {
	t, err := time.Parse("02.01.2006 15:04", src)
	if err != nil {
		return "", err
	}
	return t.Format("2006-01-02T15:04:05.000"), nil
}

func isRealtime(s string) bool {
	return strings.EqualFold(s, "prev")
}

func convertForecast(f atb.Forecast) (Departure, error) {
	registeredDeparture, err := convertTime(f.RegisteredDepartureTime)
	if err != nil {
		return Departure{}, err
	}
	scheduledDeparture, err := convertTime(f.ScheduledDepartureTime)
	if err != nil {
		return Departure{}, err
	}
	return Departure{
		LineId:                  f.LineId,
		Destination:             f.Destination,
		RegisteredDepartureTime: registeredDeparture,
		ScheduledDepartureTime:  scheduledDeparture,
		IsRealtimeData:          isRealtime(f.StationForecast),
	}, nil
}

func isTowardsCentrum(nodeId int) bool {
	return (nodeId/1000)%2 == 1
}

func convertForecasts(f atb.Forecasts) (Departures, error) {
	towardsCentrum := false
	if len(f.Nodes) > 0 {
		nodeId, err := strconv.Atoi(f.Nodes[0].NodeId)
		if err != nil {
			return Departures{}, err
		}
		towardsCentrum = isTowardsCentrum(nodeId)
	}
	departures := make([]Departure, 0, len(f.Forecasts))
	for _, forecast := range f.Forecasts {
		departure, err := convertForecast(forecast)
		if err != nil {
			return Departures{}, err
		}
		departures = append(departures, departure)
	}
	return Departures{
		TowardsCentrum: towardsCentrum,
		Departures:     departures,
	}, nil
}
<|endoftext|>


<commit_before>package configuration

import (
	"github.com/bborbe/monitoring/check"
	"github.com/bborbe/monitoring/check/http"
)

type Configuration interface {
	Checks() []check.Check
}

type configuration struct {
}

func New() Configuration {
	return new(configuration)
}

func (c *configuration) Checks() []check.Check {
	list := make([]check.Check, 0)
	list = append(list, http.New("http://www.benjamin-borbe.de").ExpectTitle("Benjamin Borbe Fotografie"))
	list = append(list, http.New("https://www.benjamin-borbe.de").ExpectTitle("Benjamin Borbe Fotografie"))
	list = append(list, http.New("http://www.benjaminborbe.de").ExpectTitle("Benjamin Borbe Fotografie"))
	list = append(list, http.New("http://jenkins.benjamin-borbe.de").ExpectTitle("Dashboard [Jenkins]"))
	list = append(list, http.New("http://www.harteslicht.de").ExpectTitle("www.Harteslicht.com | Fotografieren das Spass macht."))
	list = append(list, http.New("http://www.harteslicht.com").ExpectTitle("www.Harteslicht.com | Fotografieren das Spass macht."))
	list = append(list, http.New("http://kickstart.benjamin-borbe.de").ExpectContent("ks.cfg"))
	list = append(list, http.New("http://ip.benjamin-borbe.de"))
	list = append(list, http.New("http://slideshow.benjamin-borbe.de").ExpectContent("go.html"))
	list = append(list, http.New("https://www.benjamin-borbe.de/confluence/").ExpectTitle("Dashboard - Confluence"))
	return list
}
<commit_msg>add checks<commit_after>package configuration

import (
	"github.com/bborbe/monitoring/check"
	"github.com/bborbe/monitoring/check/http"
)

type Configuration interface {
	Checks() []check.Check
}

type configuration struct {
}

func New() Configuration {
	return new(configuration)
}

func (c *configuration) Checks() []check.Check {
	list := make([]check.Check, 0)
	list = append(list, http.New("http://www.benjamin-borbe.de").ExpectTitle("Benjamin Borbe Fotografie"))
	list = append(list, http.New("https://www.benjamin-borbe.de").ExpectTitle("Benjamin Borbe Fotografie"))
	list = append(list, http.New("http://www.benjaminborbe.de").ExpectTitle("Benjamin Borbe Fotografie"))
	list = append(list, http.New("http://jenkins.benjamin-borbe.de").ExpectTitle("Dashboard [Jenkins]"))
	list = append(list, http.New("http://www.harteslicht.de").ExpectTitle("www.Harteslicht.com | Fotografieren das Spass macht."))
	list = append(list, http.New("http://www.harteslicht.com").ExpectTitle("www.Harteslicht.com | Fotografieren das Spass macht."))
	list = append(list, http.New("http://kickstart.benjamin-borbe.de").ExpectContent("ks.cfg"))
	list = append(list, http.New("http://ip.benjamin-borbe.de"))
	list = append(list, http.New("http://slideshow.benjamin-borbe.de").ExpectContent("go.html"))
	list = append(list, http.New("https://www.benjamin-borbe.de/confluence/").ExpectTitle("Dashboard - Confluence"))
	list = append(list, http.New("http://apt.benjamin-borbe.de").ExpectTitle("403 Forbidden"))
	list = append(list, http.New("http://blog.benjamin-borbe.de").ExpectTitle("Benjamin Borbe Fotografie"))
	return list
}
<|endoftext|>


<commit_before>// Copyright 2015 CloudAwan LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package configuration

import (
	"encoding/json"
	"github.com/cloudawan/kubernetes_management_utility/configuration/Godeps/_workspace/src/code.google.com/p/log4go"
	"github.com/cloudawan/kubernetes_management_utility/configuration/Godeps/_workspace/src/github.com/cloudawan/kubernetes_management_utility/logger"
	"io"
	"os"
)

var log log4go.Logger = logger.GetLogger("utility")

const (
	rootPath = "/etc"
	fileName = "configuration.json"
)

type Configuration struct {
	jsonMap         map[string]interface{}
	fileNameAndPath string
}

func CreateConfiguration(programName string, configurationContent string) (*Configuration, error) {
	configuration := new(Configuration)
	if err := configuration.createConfigurationFileIfNotExist(programName, configurationContent); err != nil {
		return nil, err
	}
	if err := configuration.readConfigurationFromFile(); err != nil {
		return nil, err
	}
	return configuration, nil
}

func (configuration *Configuration) GetNative(key string) interface{} {
	return configuration.jsonMap[key]
}

func (configuration *Configuration) GetString(key string) (string, bool) {
	value, ok := configuration.jsonMap[key].(string)
	return value, ok
}

func (configuration *Configuration) GetStringSlice(key string) ([]string, bool) {
	stringSlice := make([]string, 0)
	valueSlice, ok := configuration.jsonMap[key].([]interface{})
	if ok == false {
		return nil, false
	}
	for _, value := range valueSlice {
		text, ok := value.(string)
		if ok == false {
			return nil, false
		}
		stringSlice = append(stringSlice, text)
	}
	return stringSlice, true
}

func (configuration *Configuration) GetInt(key string) (int, bool) {
	number, ok := configuration.jsonMap[key].(float64)
	if ok {
		return int(number), true
	} else {
		return 0, false
	}
}

func (configuration *Configuration) GetFloat64(key string) (float64, bool) {
	value, ok := configuration.jsonMap[key].(float64)
	return value, ok
}

func (configuration *Configuration) createConfigurationFileIfNotExist(programName string, configurationContent string) (returnedError error) {
	defer func() {
		if err := recover(); err != nil {
			log.Error("configuration Error: %s", err)
			log.Error(logger.GetStackTrace(4096, false))
			returnedError = err.(error)
		}
	}()

	directoryPath := rootPath + string(os.PathSeparator) + programName
	if err := os.MkdirAll(directoryPath, os.ModePerm); err != nil {
		return err
	}

	fileNameAndPath := directoryPath + string(os.PathSeparator) + fileName

	if _, err := os.Stat(fileNameAndPath); os.IsNotExist(err) {
		outputFile, err := os.Create(fileNameAndPath)
		if err != nil {
			log.Error("createConfigurationFileIfNotExist create file %s with error: %s", fileNameAndPath, err)
			return err
		}
		outputFile.WriteString(configurationContent)
	}

	configuration.fileNameAndPath = fileNameAndPath

	return nil
}

func (configuration *Configuration) Reload() error {
	return configuration.readConfigurationFromFile()
}

func (configuration *Configuration) readConfigurationFromFile() (returnedError error) {
	defer func() {
		if err := recover(); err != nil {
			log.Error("readConfigurationFromFile Error: %s", err)
			log.Error(logger.GetStackTrace(4096, false))
			returnedError = err.(error)
		}
	}()

	// open input file
	inputFile, err := os.Open(configuration.fileNameAndPath)
	if err != nil {
		log.Error("readConfigurationFromFile open file error: %s", err)
		return err
	}
	defer inputFile.Close()

	byteSlice := make([]byte, 0)
	buffer := make([]byte, 1024)
	for {
		// read a chunk
		n, err := inputFile.Read(buffer)
		if err != nil && err != io.EOF {
			log.Error("readConfigurationFromFile read file error: %s", err)
			return err
		}
		if n == 0 {
			break
		}

		byteSlice = append(byteSlice, buffer[0:n]...)
	}

	jsonMap := make(map[string]interface{})
	err = json.Unmarshal(byteSlice, &jsonMap)
	if err != nil {
		log.Error("readConfigurationFromFile parse file error: %s", err)
		return err
	}

	configuration.jsonMap = jsonMap

	return nil
}
<commit_msg>Fix Godeps<commit_after>// Copyright 2015 CloudAwan LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package configuration

import (
	"code.google.com/p/log4go"
	"encoding/json"
	"github.com/cloudawan/kubernetes_management_utility/logger"
	"io"
	"os"
)

var log log4go.Logger = logger.GetLogger("utility")

const (
	rootPath = "/etc"
	fileName = "configuration.json"
)

type Configuration struct {
	jsonMap         map[string]interface{}
	fileNameAndPath string
}

func CreateConfiguration(programName string, configurationContent string) (*Configuration, error) {
	configuration := new(Configuration)
	if err := configuration.createConfigurationFileIfNotExist(programName, configurationContent); err != nil {
		return nil, err
	}
	if err := configuration.readConfigurationFromFile(); err != nil {
		return nil, err
	}
	return configuration, nil
}

func (configuration *Configuration) GetNative(key string) interface{} {
	return configuration.jsonMap[key]
}

func (configuration *Configuration) GetString(key string) (string, bool) {
	value, ok := configuration.jsonMap[key].(string)
	return value, ok
}

func (configuration *Configuration) GetStringSlice(key string) ([]string, bool) {
	stringSlice := make([]string, 0)
	valueSlice, ok := configuration.jsonMap[key].([]interface{})
	if ok == false {
		return nil, false
	}
	for _, value := range valueSlice {
		text, ok := value.(string)
		if ok == false {
			return nil, false
		}
		stringSlice = append(stringSlice, text)
	}
	return stringSlice, true
}

func (configuration *Configuration) GetInt(key string) (int, bool) {
	number, ok := configuration.jsonMap[key].(float64)
	if ok {
		return int(number), true
	} else {
		return 0, false
	}
}

func (configuration *Configuration) GetFloat64(key string) (float64, bool) {
	value, ok := configuration.jsonMap[key].(float64)
	return value, ok
}

func (configuration *Configuration) createConfigurationFileIfNotExist(programName string, configurationContent string) (returnedError error) {
	defer func() {
		if err := recover(); err != nil {
			log.Error("configuration Error: %s", err)
			log.Error(logger.GetStackTrace(4096, false))
			returnedError = err.(error)
		}
	}()

	directoryPath := rootPath + string(os.PathSeparator) + programName
	if err := os.MkdirAll(directoryPath, os.ModePerm); err != nil {
		return err
	}

	fileNameAndPath := directoryPath + string(os.PathSeparator) + fileName

	if _, err := os.Stat(fileNameAndPath); os.IsNotExist(err) {
		outputFile, err := os.Create(fileNameAndPath)
		if err != nil {
			log.Error("createConfigurationFileIfNotExist create file %s with error: %s", fileNameAndPath, err)
			return err
		}
		outputFile.WriteString(configurationContent)
	}

	configuration.fileNameAndPath = fileNameAndPath

	return nil
}

func (configuration *Configuration) Reload() error {
	return configuration.readConfigurationFromFile()
}

func (configuration *Configuration) readConfigurationFromFile() (returnedError error) {
	defer func() {
		if err := recover(); err != nil {
			log.Error("readConfigurationFromFile Error: %s", err)
			log.Error(logger.GetStackTrace(4096, false))
			returnedError = err.(error)
		}
	}()

	// open input file
	inputFile, err := os.Open(configuration.fileNameAndPath)
	if err != nil {
		log.Error("readConfigurationFromFile open file error: %s", err)
		return err
	}
	defer inputFile.Close()

	byteSlice := make([]byte, 0)
	buffer := make([]byte, 1024)
	for {
		// read a chunk
		n, err := inputFile.Read(buffer)
		if err != nil && err != io.EOF {
			log.Error("readConfigurationFromFile read file error: %s", err)
			return err
		}
		if n == 0 {
			break
		}

		byteSlice = append(byteSlice, buffer[0:n]...)
	}

	jsonMap := make(map[string]interface{})
	err = json.Unmarshal(byteSlice, &jsonMap)
	if err != nil {
		log.Error("readConfigurationFromFile parse file error: %s", err)
		return err
	}

	configuration.jsonMap = jsonMap

	return nil
}
<|endoftext|>


<commit_before>package api

import (
	"fmt"
	"github.com/loadimpact/k6/api/common"
	"github.com/loadimpact/k6/api/v1"
	"github.com/loadimpact/k6/api/v2"
	"github.com/loadimpact/k6/lib"
	"github.com/urfave/negroni"
	"net/http"
)

func ListenAndServe(addr string, engine *lib.Engine) error {
	mux := http.NewServeMux()
	mux.Handle("/v1/", v1.NewHandler())
	mux.Handle("/v2/", v2.NewHandler())
	mux.HandleFunc("/ping", HandlePing)

	n := negroni.Classic()
	n.UseFunc(WithEngine(engine))
	n.UseHandler(mux)
	return http.ListenAndServe(addr, n)
}

func WithEngine(engine *lib.Engine) negroni.HandlerFunc {
	return negroni.HandlerFunc(func(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
		r = r.WithContext(common.WithEngine(r.Context(), engine))
		next(rw, r)
	})
}

func HandlePing(rw http.ResponseWriter, r *http.Request) {
	rw.Header().Add("Content-Type", "text/plain; charset=utf-8")
	fmt.Fprint(rw, "ok")
}
<commit_msg>[feat] Panic recovery + request logging<commit_after>package api

import (
	"fmt"
	log "github.com/Sirupsen/logrus"
	"github.com/loadimpact/k6/api/common"
	"github.com/loadimpact/k6/api/v1"
	"github.com/loadimpact/k6/api/v2"
	"github.com/loadimpact/k6/lib"
	"github.com/urfave/negroni"
	"net/http"
)

func ListenAndServe(addr string, engine *lib.Engine) error {
	mux := http.NewServeMux()
	mux.Handle("/v1/", v1.NewHandler())
	mux.Handle("/v2/", v2.NewHandler())
	mux.HandleFunc("/ping", HandlePing)

	n := negroni.New()
	n.Use(negroni.NewRecovery())
	n.UseFunc(WithEngine(engine))
	n.UseFunc(Logger)
	n.UseHandler(mux)

	return http.ListenAndServe(addr, n)
}

func Logger(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
	next(rw, r)

	res := rw.(negroni.ResponseWriter)
	log.WithFields(log.Fields{"status": res.Status()}).Debugf("%s %s", r.Method, r.URL.Path)
}

func WithEngine(engine *lib.Engine) negroni.HandlerFunc {
	return negroni.HandlerFunc(func(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
		r = r.WithContext(common.WithEngine(r.Context(), engine))
		next(rw, r)
	})
}

func HandlePing(rw http.ResponseWriter, r *http.Request) {
	rw.Header().Add("Content-Type", "text/plain; charset=utf-8")
	fmt.Fprint(rw, "ok")
}
<|endoftext|>


<commit_before>// Copyright 2014 tsuru authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package api

import (
	"fmt"
	"net"
	"net/http"

	"github.com/codegangsta/negroni"
	"github.com/tsuru/config"
	"github.com/tsuru/tsuru/app"
	"github.com/tsuru/tsuru/auth"
	_ "github.com/tsuru/tsuru/auth/native"
	_ "github.com/tsuru/tsuru/auth/oauth"
	"github.com/tsuru/tsuru/db"
	"github.com/tsuru/tsuru/log"
	"github.com/tsuru/tsuru/provision"
)

func getProvisioner() (string, error) {
	provisioner, err := config.GetString("provisioner")
	if provisioner == "" {
		provisioner = "docker"
	}
	return provisioner, err
}

type TsuruHandler struct {
	method string
	path   string
	h      http.Handler
}

func fatal(err error) {
	fmt.Println(err.Error())
	log.Fatal(err.Error())
}

var tsuruHandlerList []TsuruHandler

//RegisterHandler inserts a handler on a list of handlers
func RegisterHandler(path string, method string, h http.Handler) {
	var th TsuruHandler
	th.path = path
	th.method = method
	th.h = h
	tsuruHandlerList = append(tsuruHandlerList, th)
}

func getAuthScheme() (string, error) {
	name, err := config.GetString("auth:scheme")
	if name == "" {
		name = "native"
	}
	return name, err
}

// RunServer starts tsuru API server. The dry parameter indicates whether the
// server should run in dry mode, not starting the HTTP listener (for testing
// purposes).
func RunServer(dry bool) http.Handler {
	log.Init()
	connString, err := config.GetString("database:url")
	if err != nil {
		connString = db.DefaultDatabaseURL
	}
	dbName, err := config.GetString("database:name")
	if err != nil {
		dbName = db.DefaultDatabaseName
	}
	fmt.Printf("Using the database %q from the server %q.\n\n", dbName, connString)

	m := &delayedRouter{}

	for _, handler := range tsuruHandlerList {
		m.Add(handler.method, handler.path, handler.h)
	}

	m.Add("Get", "/services/instances", authorizationRequiredHandler(serviceInstances))
	m.Add("Get", "/services/instances/{name}", authorizationRequiredHandler(serviceInstance))
	m.Add("Delete", "/services/instances/{name}", authorizationRequiredHandler(removeServiceInstance))
	m.Add("Post", "/services/instances", authorizationRequiredHandler(createServiceInstance))
	m.Add("Put", "/services/instances/{instance}/{app}", authorizationRequiredHandler(bindServiceInstance))
	m.Add("Delete", "/services/instances/{instance}/{app}", authorizationRequiredHandler(unbindServiceInstance))
	m.Add("Get", "/services/instances/{instance}/status", authorizationRequiredHandler(serviceInstanceStatus))

	m.AddAll("/services/proxy/{instance}", authorizationRequiredHandler(serviceProxy))

	m.Add("Get", "/services", authorizationRequiredHandler(serviceList))
	m.Add("Post", "/services", authorizationRequiredHandler(serviceCreate))
	m.Add("Put", "/services", authorizationRequiredHandler(serviceUpdate))
	m.Add("Delete", "/services/{name}", authorizationRequiredHandler(serviceDelete))
	m.Add("Get", "/services/{name}", authorizationRequiredHandler(serviceInfo))
	m.Add("Get", "/services/{name}/plans", authorizationRequiredHandler(servicePlans))
	m.Add("Get", "/services/{name}/doc", authorizationRequiredHandler(serviceDoc))
	m.Add("Put", "/services/{name}/doc", authorizationRequiredHandler(serviceAddDoc))
	m.Add("Put", "/services/{service}/{team}", authorizationRequiredHandler(grantServiceAccess))
	m.Add("Delete", "/services/{service}/{team}", authorizationRequiredHandler(revokeServiceAccess))

	m.Add("Delete", "/apps/{app}", authorizationRequiredHandler(appDelete))
	m.Add("Get", "/apps/{app}", authorizationRequiredHandler(appInfo))
	m.Add("Post", "/apps/{app}/cname", authorizationRequiredHandler(setCName))
	m.Add("Delete", "/apps/{app}/cname", authorizationRequiredHandler(unsetCName))
	runHandler := authorizationRequiredHandler(runCommand)
	m.Add("Post", "/apps/{app}/run", runHandler)
	m.Add("Post", "/apps/{app}/restart", authorizationRequiredHandler(restart))
	m.Add("Post", "/apps/{app}/start", authorizationRequiredHandler(start))
	m.Add("Post", "/apps/{app}/stop", authorizationRequiredHandler(stop))
	m.Add("Get", "/apps/{appname}/quota", AdminRequiredHandler(getAppQuota))
	m.Add("Post", "/apps/{appname}/quota", AdminRequiredHandler(changeAppQuota))
	m.Add("Get", "/apps/{app}/env", authorizationRequiredHandler(getEnv))
	m.Add("Post", "/apps/{app}/env", authorizationRequiredHandler(setEnv))
	m.Add("Delete", "/apps/{app}/env", authorizationRequiredHandler(unsetEnv))
	m.Add("Get", "/apps", authorizationRequiredHandler(appList))
	m.Add("Post", "/apps", authorizationRequiredHandler(createApp))
	m.Add("Post", "/apps/{app}/team-owner", authorizationRequiredHandler(setTeamOwner))
	forceDeleteLockHandler := AdminRequiredHandler(forceDeleteLock)
	m.Add("Delete", "/apps/{app}/lock", forceDeleteLockHandler)
	m.Add("Put", "/apps/{app}/units", authorizationRequiredHandler(addUnits))
	m.Add("Delete", "/apps/{app}/units", authorizationRequiredHandler(removeUnits))
	registerUnitHandler := authorizationRequiredHandler(registerUnit)
	m.Add("Post", "/apps/{app}/units/register", registerUnitHandler)
	setUnitStatusHandler := authorizationRequiredHandler(setUnitStatus)
	m.Add("Post", "/apps/{app}/units/{unit}", setUnitStatusHandler)
	m.Add("Put", "/apps/{app}/teams/{team}", authorizationRequiredHandler(grantAppAccess))
	m.Add("Delete", "/apps/{app}/teams/{team}", authorizationRequiredHandler(revokeAppAccess))
	m.Add("Get", "/apps/{app}/log", authorizationRequiredHandler(appLog))
	logPostHandler := authorizationRequiredHandler(addLog)
	m.Add("Post", "/apps/{app}/log", logPostHandler)
	saveCustomDataHandler := authorizationRequiredHandler(saveAppCustomData)
	m.Add("Post", "/apps/{app}/customdata", saveCustomDataHandler)

	m.Add("Get", "/autoscale", authorizationRequiredHandler(autoScaleHistoryHandler))
	m.Add("Put", "/autoscale/{app}", authorizationRequiredHandler(autoScaleConfig))
	m.Add("Put", "/autoscale/{app}/enable", authorizationRequiredHandler(autoScaleEnable))
	m.Add("Put", "/autoscale/{app}/disable", authorizationRequiredHandler(autoScaleDisable))

	m.Add("Get", "/deploys", AdminRequiredHandler(deploysList))
	m.Add("Get", "/deploys/{deploy}", authorizationRequiredHandler(deployInfo))

	m.Add("Get", "/platforms", authorizationRequiredHandler(platformList))
	m.Add("Post", "/platforms", AdminRequiredHandler(platformAdd))
	m.Add("Put", "/platforms/{name}", AdminRequiredHandler(platformUpdate))
	m.Add("Delete", "/platforms/{name}", AdminRequiredHandler(platformRemove))

	// These handlers don't use :app on purpose. Using :app means that only
	// the token generate for the given app is valid, but these handlers
	// use a token generated for Gandalf.
	m.Add("Get", "/apps/{appname}/available", authorizationRequiredHandler(appIsAvailable))
	m.Add("Post", "/apps/{appname}/repository/clone", authorizationRequiredHandler(deploy))
	m.Add("Post", "/apps/{appname}/deploy", authorizationRequiredHandler(deploy))

	m.Add("Get", "/users", AdminRequiredHandler(listUsers))
	m.Add("Post", "/users", Handler(createUser))
	m.Add("Get", "/auth/scheme", Handler(authScheme))
	m.Add("Post", "/auth/login", Handler(login))
	m.Add("Post", "/users/{email}/password", Handler(resetPassword))
	m.Add("Post", "/users/{email}/tokens", Handler(login))
	m.Add("Get", "/users/{email}/quota", AdminRequiredHandler(getUserQuota))
	m.Add("Post", "/users/{email}/quota", AdminRequiredHandler(changeUserQuota))
	m.Add("Delete", "/users/tokens", authorizationRequiredHandler(logout))
	m.Add("Put", "/users/password", authorizationRequiredHandler(changePassword))
	m.Add("Delete", "/users", authorizationRequiredHandler(removeUser))
	m.Add("Get", "/users/keys", authorizationRequiredHandler(listKeys))
	m.Add("Post", "/users/keys", authorizationRequiredHandler(addKeyToUser))
	m.Add("Delete", "/users/keys", authorizationRequiredHandler(removeKeyFromUser))
	m.Add("Get", "/users/api-key", authorizationRequiredHandler(showAPIToken))
	m.Add("Post", "/users/api-key", authorizationRequiredHandler(regenerateAPIToken))

	m.Add("Post", "/tokens", AdminRequiredHandler(generateAppToken))

	m.Add("Delete", "/logs", AdminRequiredHandler(logRemove))

	m.Add("Get", "/teams", authorizationRequiredHandler(teamList))
	m.Add("Post", "/teams", authorizationRequiredHandler(createTeam))
	m.Add("Get", "/teams/{name}", authorizationRequiredHandler(getTeam))
	m.Add("Delete", "/teams/{name}", authorizationRequiredHandler(removeTeam))
	m.Add("Put", "/teams/{team}/{user}", authorizationRequiredHandler(addUserToTeam))
	m.Add("Delete", "/teams/{team}/{user}", authorizationRequiredHandler(removeUserFromTeam))

	m.Add("Put", "/swap", authorizationRequiredHandler(swap))

	m.Add("Get", "/healthcheck/", http.HandlerFunc(healthcheck))

	m.Add("Get", "/iaas/machines", AdminRequiredHandler(machinesList))
	m.Add("Delete", "/iaas/machines/{machine_id}", AdminRequiredHandler(machineDestroy))
	m.Add("Get", "/iaas/templates", AdminRequiredHandler(templatesList))
	m.Add("Post", "/iaas/templates", AdminRequiredHandler(templateCreate))
	m.Add("Delete", "/iaas/templates/{template_name}", AdminRequiredHandler(templateDestroy))

	m.Add("Get", "/plans", authorizationRequiredHandler(listPlans))
	m.Add("Post", "/plans", AdminRequiredHandler(addPlan))
	m.Add("Delete", "/plans/{planname}", AdminRequiredHandler(removePlan))

	m.Add("Get", "/debug/goroutines", AdminRequiredHandler(dumpGoroutines))

	n := negroni.New()
	n.Use(negroni.NewRecovery())
	n.Use(newLoggerMiddleware())
	n.UseHandler(m)
	n.Use(negroni.HandlerFunc(contextClearerMiddleware))
	n.Use(negroni.HandlerFunc(flushingWriterMiddleware))
	n.Use(negroni.HandlerFunc(errorHandlingMiddleware))
	n.Use(negroni.HandlerFunc(setVersionHeadersMiddleware))
	n.Use(negroni.HandlerFunc(authTokenMiddleware))
	n.Use(&appLockMiddleware{excludedHandlers: []http.Handler{
		logPostHandler,
		runHandler,
		forceDeleteLockHandler,
		registerUnitHandler,
		saveCustomDataHandler,
		setUnitStatusHandler,
	}})
	n.UseHandler(http.HandlerFunc(runDelayedHandler))

	if !dry {
		provisioner, err := getProvisioner()
		if err != nil {
			fmt.Printf("Warning: configuration didn't declare a provisioner, using default provisioner.\n")
		}
		app.Provisioner, err = provision.Get(provisioner)
		if err != nil {
			fatal(err)
		}
		fmt.Printf("Using %q provisioner.\n\n", provisioner)
		if initializableProvisioner, ok := app.Provisioner.(provision.InitializableProvisioner); ok {
			err = initializableProvisioner.Initialize()
			if err != nil {
				fatal(err)
			}
		}
		scheme, err := getAuthScheme()
		if err != nil {
			fmt.Printf("Warning: configuration didn't declare a auth:scheme, using default scheme.\n")
		}
		app.AuthScheme, err = auth.GetScheme(scheme)
		if err != nil {
			fatal(err)
		}
		fmt.Printf("Using %q auth scheme.\n\n", scheme)
		listen, err := config.GetString("listen")
		if err != nil {
			fatal(err)
		}
		app.StartAutoScale()
		tls, _ := config.GetBool("use-tls")
		if tls {
			certFile, err := config.GetString("tls:cert-file")
			if err != nil {
				fatal(err)
			}
			keyFile, err := config.GetString("tls:key-file")
			if err != nil {
				fatal(err)
			}
			fmt.Printf("tsuru HTTP/TLS server listening at %s...\n", listen)
			fatal(http.ListenAndServeTLS(listen, certFile, keyFile, n))
		} else {
			listener, err := net.Listen("tcp", listen)
			if err != nil {
				fatal(err)
			}
			fmt.Printf("tsuru HTTP server listening at %s...\n", listen)
			http.Handle("/", n)
			fatal(http.Serve(listener, nil))
		}
	}
	return n
}
<commit_msg>Less newlines in RunServer<commit_after>// Copyright 2014 tsuru authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package api

import (
	"fmt"
	"net"
	"net/http"

	"github.com/codegangsta/negroni"
	"github.com/tsuru/config"
	"github.com/tsuru/tsuru/app"
	"github.com/tsuru/tsuru/auth"
	_ "github.com/tsuru/tsuru/auth/native"
	_ "github.com/tsuru/tsuru/auth/oauth"
	"github.com/tsuru/tsuru/db"
	"github.com/tsuru/tsuru/log"
	"github.com/tsuru/tsuru/provision"
)

func getProvisioner() (string, error) {
	provisioner, err := config.GetString("provisioner")
	if provisioner == "" {
		provisioner = "docker"
	}
	return provisioner, err
}

type TsuruHandler struct {
	method string
	path   string
	h      http.Handler
}

func fatal(err error) {
	fmt.Println(err.Error())
	log.Fatal(err.Error())
}

var tsuruHandlerList []TsuruHandler

//RegisterHandler inserts a handler on a list of handlers
func RegisterHandler(path string, method string, h http.Handler) {
	var th TsuruHandler
	th.path = path
	th.method = method
	th.h = h
	tsuruHandlerList = append(tsuruHandlerList, th)
}

func getAuthScheme() (string, error) {
	name, err := config.GetString("auth:scheme")
	if name == "" {
		name = "native"
	}
	return name, err
}

// RunServer starts tsuru API server. The dry parameter indicates whether the
// server should run in dry mode, not starting the HTTP listener (for testing
// purposes).
func RunServer(dry bool) http.Handler {
	log.Init()
	connString, err := config.GetString("database:url")
	if err != nil {
		connString = db.DefaultDatabaseURL
	}
	dbName, err := config.GetString("database:name")
	if err != nil {
		dbName = db.DefaultDatabaseName
	}
	fmt.Printf("Using the database %q from the server %q.\n", dbName, connString)

	m := &delayedRouter{}

	for _, handler := range tsuruHandlerList {
		m.Add(handler.method, handler.path, handler.h)
	}

	m.Add("Get", "/services/instances", authorizationRequiredHandler(serviceInstances))
	m.Add("Get", "/services/instances/{name}", authorizationRequiredHandler(serviceInstance))
	m.Add("Delete", "/services/instances/{name}", authorizationRequiredHandler(removeServiceInstance))
	m.Add("Post", "/services/instances", authorizationRequiredHandler(createServiceInstance))
	m.Add("Put", "/services/instances/{instance}/{app}", authorizationRequiredHandler(bindServiceInstance))
	m.Add("Delete", "/services/instances/{instance}/{app}", authorizationRequiredHandler(unbindServiceInstance))
	m.Add("Get", "/services/instances/{instance}/status", authorizationRequiredHandler(serviceInstanceStatus))

	m.AddAll("/services/proxy/{instance}", authorizationRequiredHandler(serviceProxy))

	m.Add("Get", "/services", authorizationRequiredHandler(serviceList))
	m.Add("Post", "/services", authorizationRequiredHandler(serviceCreate))
	m.Add("Put", "/services", authorizationRequiredHandler(serviceUpdate))
	m.Add("Delete", "/services/{name}", authorizationRequiredHandler(serviceDelete))
	m.Add("Get", "/services/{name}", authorizationRequiredHandler(serviceInfo))
	m.Add("Get", "/services/{name}/plans", authorizationRequiredHandler(servicePlans))
	m.Add("Get", "/services/{name}/doc", authorizationRequiredHandler(serviceDoc))
	m.Add("Put", "/services/{name}/doc", authorizationRequiredHandler(serviceAddDoc))
	m.Add("Put", "/services/{service}/{team}", authorizationRequiredHandler(grantServiceAccess))
	m.Add("Delete", "/services/{service}/{team}", authorizationRequiredHandler(revokeServiceAccess))

	m.Add("Delete", "/apps/{app}", authorizationRequiredHandler(appDelete))
	m.Add("Get", "/apps/{app}", authorizationRequiredHandler(appInfo))
	m.Add("Post", "/apps/{app}/cname", authorizationRequiredHandler(setCName))
	m.Add("Delete", "/apps/{app}/cname", authorizationRequiredHandler(unsetCName))
	runHandler := authorizationRequiredHandler(runCommand)
	m.Add("Post", "/apps/{app}/run", runHandler)
	m.Add("Post", "/apps/{app}/restart", authorizationRequiredHandler(restart))
	m.Add("Post", "/apps/{app}/start", authorizationRequiredHandler(start))
	m.Add("Post", "/apps/{app}/stop", authorizationRequiredHandler(stop))
	m.Add("Get", "/apps/{appname}/quota", AdminRequiredHandler(getAppQuota))
	m.Add("Post", "/apps/{appname}/quota", AdminRequiredHandler(changeAppQuota))
	m.Add("Get", "/apps/{app}/env", authorizationRequiredHandler(getEnv))
	m.Add("Post", "/apps/{app}/env", authorizationRequiredHandler(setEnv))
	m.Add("Delete", "/apps/{app}/env", authorizationRequiredHandler(unsetEnv))
	m.Add("Get", "/apps", authorizationRequiredHandler(appList))
	m.Add("Post", "/apps", authorizationRequiredHandler(createApp))
	m.Add("Post", "/apps/{app}/team-owner", authorizationRequiredHandler(setTeamOwner))
	forceDeleteLockHandler := AdminRequiredHandler(forceDeleteLock)
	m.Add("Delete", "/apps/{app}/lock", forceDeleteLockHandler)
	m.Add("Put", "/apps/{app}/units", authorizationRequiredHandler(addUnits))
	m.Add("Delete", "/apps/{app}/units", authorizationRequiredHandler(removeUnits))
	registerUnitHandler := authorizationRequiredHandler(registerUnit)
	m.Add("Post", "/apps/{app}/units/register", registerUnitHandler)
	setUnitStatusHandler := authorizationRequiredHandler(setUnitStatus)
	m.Add("Post", "/apps/{app}/units/{unit}", setUnitStatusHandler)
	m.Add("Put", "/apps/{app}/teams/{team}", authorizationRequiredHandler(grantAppAccess))
	m.Add("Delete", "/apps/{app}/teams/{team}", authorizationRequiredHandler(revokeAppAccess))
	m.Add("Get", "/apps/{app}/log", authorizationRequiredHandler(appLog))
	logPostHandler := authorizationRequiredHandler(addLog)
	m.Add("Post", "/apps/{app}/log", logPostHandler)
	saveCustomDataHandler := authorizationRequiredHandler(saveAppCustomData)
	m.Add("Post", "/apps/{app}/customdata", saveCustomDataHandler)

	m.Add("Get", "/autoscale", authorizationRequiredHandler(autoScaleHistoryHandler))
	m.Add("Put", "/autoscale/{app}", authorizationRequiredHandler(autoScaleConfig))
	m.Add("Put", "/autoscale/{app}/enable", authorizationRequiredHandler(autoScaleEnable))
	m.Add("Put", "/autoscale/{app}/disable", authorizationRequiredHandler(autoScaleDisable))

	m.Add("Get", "/deploys", AdminRequiredHandler(deploysList))
	m.Add("Get", "/deploys/{deploy}", authorizationRequiredHandler(deployInfo))

	m.Add("Get", "/platforms", authorizationRequiredHandler(platformList))
	m.Add("Post", "/platforms", AdminRequiredHandler(platformAdd))
	m.Add("Put", "/platforms/{name}", AdminRequiredHandler(platformUpdate))
	m.Add("Delete", "/platforms/{name}", AdminRequiredHandler(platformRemove))

	// These handlers don't use :app on purpose. Using :app means that only
	// the token generate for the given app is valid, but these handlers
	// use a token generated for Gandalf.
	m.Add("Get", "/apps/{appname}/available", authorizationRequiredHandler(appIsAvailable))
	m.Add("Post", "/apps/{appname}/repository/clone", authorizationRequiredHandler(deploy))
	m.Add("Post", "/apps/{appname}/deploy", authorizationRequiredHandler(deploy))

	m.Add("Get", "/users", AdminRequiredHandler(listUsers))
	m.Add("Post", "/users", Handler(createUser))
	m.Add("Get", "/auth/scheme", Handler(authScheme))
	m.Add("Post", "/auth/login", Handler(login))
	m.Add("Post", "/users/{email}/password", Handler(resetPassword))
	m.Add("Post", "/users/{email}/tokens", Handler(login))
	m.Add("Get", "/users/{email}/quota", AdminRequiredHandler(getUserQuota))
	m.Add("Post", "/users/{email}/quota", AdminRequiredHandler(changeUserQuota))
	m.Add("Delete", "/users/tokens", authorizationRequiredHandler(logout))
	m.Add("Put", "/users/password", authorizationRequiredHandler(changePassword))
	m.Add("Delete", "/users", authorizationRequiredHandler(removeUser))
	m.Add("Get", "/users/keys", authorizationRequiredHandler(listKeys))
	m.Add("Post", "/users/keys", authorizationRequiredHandler(addKeyToUser))
	m.Add("Delete", "/users/keys", authorizationRequiredHandler(removeKeyFromUser))
	m.Add("Get", "/users/api-key", authorizationRequiredHandler(showAPIToken))
	m.Add("Post", "/users/api-key", authorizationRequiredHandler(regenerateAPIToken))

	m.Add("Post", "/tokens", AdminRequiredHandler(generateAppToken))

	m.Add("Delete", "/logs", AdminRequiredHandler(logRemove))

	m.Add("Get", "/teams", authorizationRequiredHandler(teamList))
	m.Add("Post", "/teams", authorizationRequiredHandler(createTeam))
	m.Add("Get", "/teams/{name}", authorizationRequiredHandler(getTeam))
	m.Add("Delete", "/teams/{name}", authorizationRequiredHandler(removeTeam))
	m.Add("Put", "/teams/{team}/{user}", authorizationRequiredHandler(addUserToTeam))
	m.Add("Delete", "/teams/{team}/{user}", authorizationRequiredHandler(removeUserFromTeam))

	m.Add("Put", "/swap", authorizationRequiredHandler(swap))

	m.Add("Get", "/healthcheck/", http.HandlerFunc(healthcheck))

	m.Add("Get", "/iaas/machines", AdminRequiredHandler(machinesList))
	m.Add("Delete", "/iaas/machines/{machine_id}", AdminRequiredHandler(machineDestroy))
	m.Add("Get", "/iaas/templates", AdminRequiredHandler(templatesList))
	m.Add("Post", "/iaas/templates", AdminRequiredHandler(templateCreate))
	m.Add("Delete", "/iaas/templates/{template_name}", AdminRequiredHandler(templateDestroy))

	m.Add("Get", "/plans", authorizationRequiredHandler(listPlans))
	m.Add("Post", "/plans", AdminRequiredHandler(addPlan))
	m.Add("Delete", "/plans/{planname}", AdminRequiredHandler(removePlan))

	m.Add("Get", "/debug/goroutines", AdminRequiredHandler(dumpGoroutines))

	n := negroni.New()
	n.Use(negroni.NewRecovery())
	n.Use(newLoggerMiddleware())
	n.UseHandler(m)
	n.Use(negroni.HandlerFunc(contextClearerMiddleware))
	n.Use(negroni.HandlerFunc(flushingWriterMiddleware))
	n.Use(negroni.HandlerFunc(errorHandlingMiddleware))
	n.Use(negroni.HandlerFunc(setVersionHeadersMiddleware))
	n.Use(negroni.HandlerFunc(authTokenMiddleware))
	n.Use(&appLockMiddleware{excludedHandlers: []http.Handler{
		logPostHandler,
		runHandler,
		forceDeleteLockHandler,
		registerUnitHandler,
		saveCustomDataHandler,
		setUnitStatusHandler,
	}})
	n.UseHandler(http.HandlerFunc(runDelayedHandler))

	if !dry {
		provisioner, err := getProvisioner()
		if err != nil {
			fmt.Printf("Warning: configuration didn't declare a provisioner, using default provisioner.\n")
		}
		app.Provisioner, err = provision.Get(provisioner)
		if err != nil {
			fatal(err)
		}
		fmt.Printf("Using %q provisioner.\n", provisioner)
		if initializableProvisioner, ok := app.Provisioner.(provision.InitializableProvisioner); ok {
			err = initializableProvisioner.Initialize()
			if err != nil {
				fatal(err)
			}
		}
		scheme, err := getAuthScheme()
		if err != nil {
			fmt.Printf("Warning: configuration didn't declare a auth:scheme, using default scheme.\n")
		}
		app.AuthScheme, err = auth.GetScheme(scheme)
		if err != nil {
			fatal(err)
		}
		fmt.Printf("Using %q auth scheme.\n", scheme)
		listen, err := config.GetString("listen")
		if err != nil {
			fatal(err)
		}
		app.StartAutoScale()
		tls, _ := config.GetBool("use-tls")
		if tls {
			certFile, err := config.GetString("tls:cert-file")
			if err != nil {
				fatal(err)
			}
			keyFile, err := config.GetString("tls:key-file")
			if err != nil {
				fatal(err)
			}
			fmt.Printf("tsuru HTTP/TLS server listening at %s...\n", listen)
			fatal(http.ListenAndServeTLS(listen, certFile, keyFile, n))
		} else {
			listener, err := net.Listen("tcp", listen)
			if err != nil {
				fatal(err)
			}
			fmt.Printf("tsuru HTTP server listening at %s...\n", listen)
			http.Handle("/", n)
			fatal(http.Serve(listener, nil))
		}
	}
	return n
}
<|endoftext|>


<commit_before>package apiv3

import (
	"bytes"
	"crypto/tls"
	"encoding/json"
	"errors"
	"fmt"
	"log"
	"net/http"
	"net/http/httputil"
	"net/url"
)

type XMS struct {
	endpoint   string
	insecure   bool
	username   string
	password   string
	httpClient *http.Client
}

func New(endpoint string, insecure bool, username string, password string) (*XMS, error) {
	if endpoint == "" || username == "" || password == "" {
		return nil, errors.New("Missing endpoint, username, or password")
	}

	var client *http.Client
	if insecure {
		client = &http.Client{
			Transport: &http.Transport{
				TLSClientConfig: &tls.Config{
					InsecureSkipVerify: insecure,
				},
			},
		}
	} else {
		client = &http.Client{}
	}

	return &XMS{endpoint, insecure, username, password, client}, nil
}

func multimap(p map[string]string) url.Values {
	q := make(url.Values, len(p))
	for k, v := range p {
		if v != "" {
			q[k] = []string{v}
		}
	}
	return q
}

type Error struct {
	StatusCode int
	Message    string `json:"message"`
	Code       int    `json:"error_code"`
}

func (err *Error) Error() string {
	if err.Code == 0 {
		return err.Message
	}

	return fmt.Sprintf("%s", err.Message)
}

func buildError(r *http.Response) error {
	jsonError := Error{}
	json.NewDecoder(r.Body).Decode(&jsonError)

	jsonError.StatusCode = r.StatusCode
	if jsonError.Message == "" {
		jsonError.Message = r.Status
	}

	return &jsonError
}

func (xms *XMS) query(method string, path string, id string, params map[string]string, body interface{}, resp interface{}) error {

	endpoint := fmt.Sprintf("%s/%s", xms.endpoint, path)
	if id != "" {
		endpoint = fmt.Sprintf("%s/%s", endpoint, id)
	}

	encodedParams := multimap(params).Encode()
	if encodedParams != "" {
		endpoint = fmt.Sprintf("%s?%s", endpoint, encodedParams)
	}

	bodyBytes, _ := json.Marshal(body)

	if debug {
		log.Printf("endpoint: %v\n", endpoint)
	}

	if debug && body != nil {
		log.Printf("body:\n")
		log.Printf("%v\n", string(bodyBytes))
	}

	req, err := http.NewRequest(method, endpoint, bytes.NewBuffer(bodyBytes))
	req.SetBasicAuth(xms.username, xms.password)

	r, err := xms.httpClient.Do(req)
	if err != nil {
		return err
	}
	defer r.Body.Close()

	if debug {
		dump, _ := httputil.DumpResponse(r, true)
		log.Printf("response:\n")
		log.Printf("%v\n}\n", string(dump))
	}

	switch {
	case r.StatusCode == 400:
		return buildError(r)
	case resp == nil:
		return nil
	case r.StatusCode == 200 || r.StatusCode == 201:
		err = json.NewDecoder(r.Body).Decode(resp)
		return err
	default:
		return buildError(r)
	}

}
<commit_msg>Logrus Support<commit_after>package apiv3

import (
	"bytes"
	"crypto/tls"
	"encoding/json"
	"errors"
	"fmt"
	"net/http"
	"net/http/httputil"
	"net/url"

	log "github.com/Sirupsen/logrus"
)

type XMS struct {
	endpoint   string
	insecure   bool
	username   string
	password   string
	httpClient *http.Client
}

func New(endpoint string, insecure bool, username string, password string) (*XMS, error) {
	if endpoint == "" || username == "" || password == "" {
		return nil, errors.New("Missing endpoint, username, or password")
	}

	var client *http.Client
	if insecure {
		client = &http.Client{
			Transport: &http.Transport{
				TLSClientConfig: &tls.Config{
					InsecureSkipVerify: insecure,
				},
			},
		}
	} else {
		client = &http.Client{}
	}

	return &XMS{endpoint, insecure, username, password, client}, nil
}

func multimap(p map[string]string) url.Values {
	q := make(url.Values, len(p))
	for k, v := range p {
		if v != "" {
			q[k] = []string{v}
		}
	}
	return q
}

type Error struct {
	StatusCode int
	Message    string `json:"message"`
	Code       int    `json:"error_code"`
}

func (err *Error) Error() string {
	if err.Code == 0 {
		return err.Message
	}

	return fmt.Sprintf("%s", err.Message)
}

func buildError(r *http.Response) error {
	jsonError := Error{}
	json.NewDecoder(r.Body).Decode(&jsonError)

	jsonError.StatusCode = r.StatusCode
	if jsonError.Message == "" {
		jsonError.Message = r.Status
	}

	return &jsonError
}

func (xms *XMS) query(method string, path string, id string, params map[string]string, body interface{}, resp interface{}) error {

	endpoint := fmt.Sprintf("%s/%s", xms.endpoint, path)
	if id != "" {
		endpoint = fmt.Sprintf("%s/%s", endpoint, id)
	}

	encodedParams := multimap(params).Encode()
	if encodedParams != "" {
		endpoint = fmt.Sprintf("%s?%s", endpoint, encodedParams)
	}

	bodyBytes, _ := json.Marshal(body)

	if debug {
		log.Printf("endpoint: %v\n", endpoint)
	}

	if debug && body != nil {
		log.Printf("body:\n")
		log.Printf("%v\n", string(bodyBytes))
	}

	req, err := http.NewRequest(method, endpoint, bytes.NewBuffer(bodyBytes))
	req.SetBasicAuth(xms.username, xms.password)

	r, err := xms.httpClient.Do(req)
	if err != nil {
		return err
	}
	defer r.Body.Close()

	if debug {
		dump, _ := httputil.DumpResponse(r, true)
		log.Printf("response:\n")
		log.Printf("%v\n}\n", string(dump))
	}

	switch {
	case r.StatusCode == 400:
		return buildError(r)
	case resp == nil:
		return nil
	case r.StatusCode == 200 || r.StatusCode == 201:
		err = json.NewDecoder(r.Body).Decode(resp)
		return err
	default:
		return buildError(r)
	}

}
<|endoftext|>


<commit_before><commit_msg>atg. doc++ on GetHalter() vs Done()<commit_after><|endoftext|>


<commit_before>package main

import (
	"./db"
	"fmt"
	"math/rand"
	"strings"
	"time"
)

const (
	_FOLLOW   = iota
	_UNFOLLOW = iota
	_FAVORITE = iota
	_TWEET    = iota
	_REPLY    = iota
)

type Action struct {
	name   int
	weight int
}

func performAction() {
	actions := make([]Action, 0, 5)

	actions = append(actions, Action{name: _FOLLOW, weight: ACTION_FOLLOW_WEIGHT * rand.Intn(100)})
	actions = append(actions, Action{name: _UNFOLLOW, weight: ACTION_UNFOLLOW_WEIGHT * rand.Intn(100)})
	actions = append(actions, Action{name: _FAVORITE, weight: ACTION_FAVORITE_WEIGHT * rand.Intn(100)})
	actions = append(actions, Action{name: _TWEET, weight: ACTION_TWEET_WEIGHT * rand.Intn(100)})
	actions = append(actions, Action{name: _REPLY, weight: ACTION_REPLY_WEIGHT * rand.Intn(100)})

	selectedAction := Action{name: -1, weight: -1}

	for _, action := range actions {
		if action.weight > selectedAction.weight {
			selectedAction = action
		}
	}

	switch selectedAction.name {
	case _FOLLOW:
		actionFollow()
		break
	case _UNFOLLOW:
		actionUnfollow()
		break
	case _FAVORITE:
		actionFavorite()
		break
	case _TWEET:
		actionTweet()
		break
	case _REPLY:
		actionReply()
		break
	}
}

func actionFollow() {
	fmt.Println("Action follow")

	search, v := generateAPISearchValues(KEYWORDS[rand.Intn(len(KEYWORDS))])

	searchResult, err := api.GetSearch(search, v)
	if err != nil {
		fmt.Println("Error while querying twitter API", err)
		return
	}

	for _, tweet := range searchResult.Statuses {

		if !isUserAcceptable(tweet) {
			fmt.Println("Ignoring user for follow : @" + tweet.User.ScreenName)
			continue
		}

		follow, err := db.AlreadyFollow(tweet.User.Id)
		if err == nil && !follow {

			err := db.Follow{UserId: tweet.User.Id, UserName: tweet.User.ScreenName, Status: tweet.Text, FollowDate: time.Now()}.Persist()
			if err != nil {
				fmt.Println("Error while persisting follow", err)
				return
			}

			_, err = api.FollowUser(tweet.User.ScreenName)
			if err != nil {
				fmt.Println("Error while following user "+tweet.User.ScreenName+" : ", err)
			}

			fmt.Println("Now follow ", tweet.User.ScreenName)
			return
		}

	}
}

func actionUnfollow() {
	fmt.Println("Action unfollow")

	date := time.Now()
	duration, err := time.ParseDuration("-72") // -3 days
	date = date.Add(duration)

	follows, err := db.GetNotUnfollowed(date, UNFOLLOW_LIMIT_IN_A_ROW)
	if err != nil {
		fmt.Println("Error while querying db to find people to unfollow", err)
		return
	}

	for _, follow := range follows {
		follow.LastAction = time.Now()

		isFollowing, err := isUserFollowing(follow.UserName)
		if err != nil {
			fmt.Println("Error while querying API for friendships", err)
			return
		}

		if isFollowing {
			err = follow.Persist()
			if err != nil {
				fmt.Println("Error while persisting follow", err)
				return
			}

			continue
		}

		follow.UnfollowDate = time.Now()

		err = follow.Persist()
		if err != nil {
			fmt.Println("Error while persisting follow", err)
			return
		}

		_, err = api.UnfollowUser(follow.UserName)
		if err != nil {
			fmt.Println("Error while querying API to unfollow @"+follow.UserName, err)
			return
		}

		fmt.Println("Unfollowed @" + follow.UserName)
	}
}

func actionFavorite() {
	fmt.Println("Action fav")

	search, v := generateAPISearchValues(KEYWORDS[rand.Intn(len(KEYWORDS))])

	searchResult, err := api.GetSearch(search, v)
	if err != nil {
		fmt.Println("Error while querying twitter API", err)
		return
	}

	i := 0
	for _, tweet := range searchResult.Statuses {
		if i >= FAV_LIMIT_IN_A_ROW {
			return
		}

		if !isUserAcceptable(tweet) {
			fmt.Println("Ignoring user for favorite : @" + tweet.User.ScreenName)
			continue
		}

		_, err = api.Favorite(tweet.Id)
		if err != nil {
			if strings.Contains(err.Error(), "139") { // Case of an already favorited tweet
				continue
			}

			fmt.Println("Error while favoriting tweet", err)
		} else {
			fmt.Println("Just favorited tweet : ", tweet.Text)
		}

		i++
	}
}

func actionTweet() {
	fmt.Println("Action tweet")

	content, err := generateTweetContent()
	if err != nil {
		fmt.Println("Error while getting tweet content : ", err)
		return
	}

	tweetText := content.text + " " + content.url + content.hashtags

	err = db.Tweet{Content: tweetText, Date: time.Now()}.Persist()
	if err != nil {
		fmt.Println("Error while persisting tweet", err)
		return
	}

	tweet, err := api.PostTweet(tweetText, nil)
	if err != nil {
		fmt.Println("Error while posting tweet", err)
		return
	}

	fmt.Println("Tweet posted : ", tweet.Text)
}

func actionReply() {
	fmt.Println("Action reply")

	tweets, err := api.GetMentionsTimeline(nil)
	if err != nil {
		fmt.Println("Error while querying twitter mention API", err)
		return
	}

	for _, tweet := range tweets {

		replied, err := db.HasAlreadyReplied(tweet.Id)
		if err == nil && !replied {
			fmt.Println("Building reply for tweet : " + tweet.Text)

			response, err := buildReply(tweet)
			if err != nil {
				fmt.Println("Error while building reply", err)
				return
			}

			err = db.Reply{UserId: tweet.User.Id, UserName: tweet.User.ScreenName, TweetId: tweet.Id, Status: tweet.Text, Answer: response, ReplyDate: time.Now()}.Persist()
			if err != nil {
				fmt.Println("Error while persisting reply", err)
				return
			}

			if response != "" {
				respTweet, err := api.PostTweet(response, nil)
				if err != nil {
					fmt.Println("Error while posting reply", err)
					return
				}

				fmt.Println("Reply posted : ", respTweet.Text)
			} else {
				fmt.Println("No response found for tweet : " + tweet.Text)
			}

			return
		}
	}

	fmt.Println("Nothing to reply found :(")
}
<commit_msg>Add in reply for status API call for replies<commit_after>package main

import (
	"./db"
	"fmt"
	"math/rand"
	"net/url"
	"strings"
	"time"
)

const (
	_FOLLOW   = iota
	_UNFOLLOW = iota
	_FAVORITE = iota
	_TWEET    = iota
	_REPLY    = iota
)

type Action struct {
	name   int
	weight int
}

func performAction() {
	actions := make([]Action, 0, 5)

	actions = append(actions, Action{name: _FOLLOW, weight: ACTION_FOLLOW_WEIGHT * rand.Intn(100)})
	actions = append(actions, Action{name: _UNFOLLOW, weight: ACTION_UNFOLLOW_WEIGHT * rand.Intn(100)})
	actions = append(actions, Action{name: _FAVORITE, weight: ACTION_FAVORITE_WEIGHT * rand.Intn(100)})
	actions = append(actions, Action{name: _TWEET, weight: ACTION_TWEET_WEIGHT * rand.Intn(100)})
	actions = append(actions, Action{name: _REPLY, weight: ACTION_REPLY_WEIGHT * rand.Intn(100)})

	selectedAction := Action{name: -1, weight: -1}

	for _, action := range actions {
		if action.weight > selectedAction.weight {
			selectedAction = action
		}
	}

	switch selectedAction.name {
	case _FOLLOW:
		actionFollow()
		break
	case _UNFOLLOW:
		actionUnfollow()
		break
	case _FAVORITE:
		actionFavorite()
		break
	case _TWEET:
		actionTweet()
		break
	case _REPLY:
		actionReply()
		break
	}
}

func actionFollow() {
	fmt.Println("Action follow")

	search, v := generateAPISearchValues(KEYWORDS[rand.Intn(len(KEYWORDS))])

	searchResult, err := api.GetSearch(search, v)
	if err != nil {
		fmt.Println("Error while querying twitter API", err)
		return
	}

	for _, tweet := range searchResult.Statuses {

		if !isUserAcceptable(tweet) {
			fmt.Println("Ignoring user for follow : @" + tweet.User.ScreenName)
			continue
		}

		follow, err := db.AlreadyFollow(tweet.User.Id)
		if err == nil && !follow {

			err := db.Follow{UserId: tweet.User.Id, UserName: tweet.User.ScreenName, Status: tweet.Text, FollowDate: time.Now()}.Persist()
			if err != nil {
				fmt.Println("Error while persisting follow", err)
				return
			}

			_, err = api.FollowUser(tweet.User.ScreenName)
			if err != nil {
				fmt.Println("Error while following user "+tweet.User.ScreenName+" : ", err)
			}

			fmt.Println("Now follow ", tweet.User.ScreenName)
			return
		}

	}
}

func actionUnfollow() {
	fmt.Println("Action unfollow")

	date := time.Now()
	duration, err := time.ParseDuration("-72") // -3 days
	date = date.Add(duration)

	follows, err := db.GetNotUnfollowed(date, UNFOLLOW_LIMIT_IN_A_ROW)
	if err != nil {
		fmt.Println("Error while querying db to find people to unfollow", err)
		return
	}

	for _, follow := range follows {
		follow.LastAction = time.Now()

		isFollowing, err := isUserFollowing(follow.UserName)
		if err != nil {
			fmt.Println("Error while querying API for friendships", err)
			return
		}

		if isFollowing {
			err = follow.Persist()
			if err != nil {
				fmt.Println("Error while persisting follow", err)
				return
			}

			continue
		}

		follow.UnfollowDate = time.Now()

		err = follow.Persist()
		if err != nil {
			fmt.Println("Error while persisting follow", err)
			return
		}

		_, err = api.UnfollowUser(follow.UserName)
		if err != nil {
			fmt.Println("Error while querying API to unfollow @"+follow.UserName, err)
			return
		}

		fmt.Println("Unfollowed @" + follow.UserName)
	}
}

func actionFavorite() {
	fmt.Println("Action fav")

	search, v := generateAPISearchValues(KEYWORDS[rand.Intn(len(KEYWORDS))])

	searchResult, err := api.GetSearch(search, v)
	if err != nil {
		fmt.Println("Error while querying twitter API", err)
		return
	}

	i := 0
	for _, tweet := range searchResult.Statuses {
		if i >= FAV_LIMIT_IN_A_ROW {
			return
		}

		if !isUserAcceptable(tweet) {
			fmt.Println("Ignoring user for favorite : @" + tweet.User.ScreenName)
			continue
		}

		_, err = api.Favorite(tweet.Id)
		if err != nil {
			if strings.Contains(err.Error(), "139") { // Case of an already favorited tweet
				continue
			}

			fmt.Println("Error while favoriting tweet", err)
		} else {
			fmt.Println("Just favorited tweet : ", tweet.Text)
		}

		i++
	}
}

func actionTweet() {
	fmt.Println("Action tweet")

	content, err := generateTweetContent()
	if err != nil {
		fmt.Println("Error while getting tweet content : ", err)
		return
	}

	tweetText := content.text + " " + content.url + content.hashtags

	err = db.Tweet{Content: tweetText, Date: time.Now()}.Persist()
	if err != nil {
		fmt.Println("Error while persisting tweet", err)
		return
	}

	tweet, err := api.PostTweet(tweetText, nil)
	if err != nil {
		fmt.Println("Error while posting tweet", err)
		return
	}

	fmt.Println("Tweet posted : ", tweet.Text)
}

func actionReply() {
	fmt.Println("Action reply")

	tweets, err := api.GetMentionsTimeline(nil)
	if err != nil {
		fmt.Println("Error while querying twitter mention API", err)
		return
	}

	for _, tweet := range tweets {

		replied, err := db.HasAlreadyReplied(tweet.Id)
		if err == nil && !replied {
			fmt.Println("Building reply for tweet : " + tweet.Text)

			response, err := buildReply(tweet)
			if err != nil {
				fmt.Println("Error while building reply", err)
				return
			}

			err = db.Reply{UserId: tweet.User.Id, UserName: tweet.User.ScreenName, TweetId: tweet.Id, Status: tweet.Text, Answer: response, ReplyDate: time.Now()}.Persist()
			if err != nil {
				fmt.Println("Error while persisting reply", err)
				return
			}

			if response != "" {
				v := url.Values{}
				v.Add("in_reply_to_status_id", tweet.Id)

				respTweet, err := api.PostTweet(response, v)
				if err != nil {
					fmt.Println("Error while posting reply", err)
					return
				}

				fmt.Println("Reply posted : ", respTweet.Text)
			} else {
				fmt.Println("No response found for tweet : " + tweet.Text)
			}

			return
		}
	}

	fmt.Println("Nothing to reply found :(")
}
<|endoftext|>


<commit_before>package importer

import (
	"github.com/jbowtie/gokogiri/xml"
	"github.com/jbowtie/gokogiri/xpath"
	"github.com/pebbe/util"
	"github.com/projectcypress/cdatools/models"
)

func EncounterOrderExtractor(entry *models.Entry, entryElement xml.Node) interface{} {
	encounterOrder := models.Encounter{}
	encounterOrder.Entry = *entry

	//extract codes
	var codePath = xpath.Compile("cda:code")
	ExtractCodes(&encounterOrder.Entry.Coded, entryElement, codePath)

	//extract order specific dates
	var orderTimeXPath = xpath.Compile("cda:author/cda:time/@value")
	encounterOrder.StartTime = GetTimestamp(orderTimeXPath, entryElement)
	encounterOrder.EndTime = GetTimestamp(orderTimeXPath, entryElement)

	return encounterOrder
}

func EncounterPerformedExtractor(entry *models.Entry, entryElement xml.Node) interface{} {
	encounter := models.Encounter{}
	encounter.Entry = *entry

	//extract codes
	var codePath = xpath.Compile("cda:code")
	ExtractCodes(&encounter.Entry.Coded, entryElement, codePath)

	//set admit/discharge times
	encounter.AdmitTime = encounter.Entry.StartTime
	encounter.DischargeTime = encounter.Entry.EndTime

	//extract reason
	extractReason(&encounter, entryElement)

	//extract diagnoses
	var pdXPath = xpath.Compile("cda:entryRelationship/cda:observation[cda:code/@code='8319008']/cda:value")
	var diagXPath = xpath.Compile("cda:entryRelationship/cda:act/cda:entryRelationship/cda:observation[cda:templateId/@root='2.16.840.1.113883.10.20.22.4.4']/cda:value")
	encounter.PrincipalDiagnosis.Coded.Codes = map[string][]string{}
	encounter.Diagnosis.Coded.Codes = map[string][]string{}
	ExtractCodes(&encounter.PrincipalDiagnosis.Coded, entryElement, pdXPath)
	ExtractCodes(&encounter.Diagnosis.Coded, entryElement, diagXPath)

	//encounter.PrincipalDiagnosis.Code = &models.CodedConcept{}
	ExtractCodedConcept(&encounter.PrincipalDiagnosis.CodedConcept, entryElement, pdXPath)
	//encounter.Diagnosis.Code = &models.CodedConcept{}
	ExtractCodedConcept(&encounter.Diagnosis.CodedConcept, entryElement, diagXPath)

	//extract facility
	extractFacility(&encounter, entryElement)

	//extract discharge disposition
	var dischargeDispositionCodeXPath = xpath.Compile("sdtc:dischargeDispositionCode/@code")
	var dischargeDispositionCodeSystemXPath = xpath.Compile("sdtc:dischargeDispositionCode/@codeSystem")
	dischargeDispositionCode := FirstElementContent(dischargeDispositionCodeXPath, entryElement)
	dischargeDispositionCodeSystemOid := FirstElementContent(dischargeDispositionCodeSystemXPath, entryElement)
	dischargeDispositionCodeSystem := models.CodeSystemFor(dischargeDispositionCodeSystemOid)
	if dischargeDispositionCode != "" {
		encounter.DischargeDisposition = map[string]string{
			"code":          dischargeDispositionCode,
			"codeSystem":    dischargeDispositionCodeSystem,
			"codeSystemOid": dischargeDispositionCodeSystemOid,
		}
	}

	return encounter
}

func extractFacility(encounter *models.Encounter, entryElement xml.Node) {
	var participantXPath = xpath.Compile("cda:participant[@typeCode='LOC']/cda:participantRole[@classCode='SDLOC']")
	participantElement := FirstElement(participantXPath, entryElement)

	if participantElement != nil {
		var facility = models.Facility{}

		var nameXPath = xpath.Compile("cda:playingEntity/cda:name")
		facility.Name = FirstElementContent(nameXPath, participantElement)

		addressXPath := xpath.Compile("cda:addr")
		addressElements, err := participantElement.Search(addressXPath)
		util.CheckErr(err)
		facility.Addresses = make([]models.Address, len(addressElements))
		for i, addressElement := range addressElements {
			facility.Addresses[i] = ImportAddress(addressElement)
		}

		telecomXPath := xpath.Compile("cda:telecom")
		telecomElements, err := participantElement.Search(telecomXPath)
		util.CheckErr(err)
		facility.Telecoms = make([]models.Telecom, len(telecomElements))
		for i, telecomElement := range telecomElements {
			facility.Telecoms[i] = ImportTelecom(telecomElement)
		}

		facility.Code = &models.CodedConcept{}
		ExtractCodedConcept(facility.Code, participantElement, xpath.Compile("cda:code"))

		var timeLowXPath = xpath.Compile("cda:effectiveTime/cda:low/@value")
		var timeHighXPath = xpath.Compile("cda:effectiveTime/cda:high/@value")
		facility.StartTime = GetTimestamp(timeLowXPath, entryElement)
		facility.EndTime = GetTimestamp(timeHighXPath, entryElement)

		encounter.Facility = facility
	}
}

func extractReason(encounter *models.Encounter, entryElement xml.Node) {
	var reasonXPath = xpath.Compile("cda:entryRelationship[@typeCode='RSON']/cda:observation")
	reasonElement := FirstElement(reasonXPath, entryElement)

	if reasonElement != nil {
		//extract reason value code
		var valueCodeXPath = xpath.Compile("cda:value/@code")
		var valueCodeSystemXPath = xpath.Compile("cda:value/@codeSystem")
		valueCode := FirstElementContent(valueCodeXPath, reasonElement)
		valueCodeSystem := models.CodeSystemFor(FirstElementContent(valueCodeSystemXPath, reasonElement))
		encounter.Reason.Code = valueCode
		encounter.Reason.CodeSystem = valueCodeSystem
		encounter.Reason.CodeSystemName = valueCodeSystem
	}
}
<commit_msg>remove unnecessary commented out lines<commit_after>package importer

import (
	"github.com/jbowtie/gokogiri/xml"
	"github.com/jbowtie/gokogiri/xpath"
	"github.com/pebbe/util"
	"github.com/projectcypress/cdatools/models"
)

func EncounterOrderExtractor(entry *models.Entry, entryElement xml.Node) interface{} {
	encounterOrder := models.Encounter{}
	encounterOrder.Entry = *entry

	//extract codes
	var codePath = xpath.Compile("cda:code")
	ExtractCodes(&encounterOrder.Entry.Coded, entryElement, codePath)

	//extract order specific dates
	var orderTimeXPath = xpath.Compile("cda:author/cda:time/@value")
	encounterOrder.StartTime = GetTimestamp(orderTimeXPath, entryElement)
	encounterOrder.EndTime = GetTimestamp(orderTimeXPath, entryElement)

	return encounterOrder
}

func EncounterPerformedExtractor(entry *models.Entry, entryElement xml.Node) interface{} {
	encounter := models.Encounter{}
	encounter.Entry = *entry

	//extract codes
	var codePath = xpath.Compile("cda:code")
	ExtractCodes(&encounter.Entry.Coded, entryElement, codePath)

	//set admit/discharge times
	encounter.AdmitTime = encounter.Entry.StartTime
	encounter.DischargeTime = encounter.Entry.EndTime

	//extract reason
	extractReason(&encounter, entryElement)

	//extract diagnoses
	var pdXPath = xpath.Compile("cda:entryRelationship/cda:observation[cda:code/@code='8319008']/cda:value")
	var diagXPath = xpath.Compile("cda:entryRelationship/cda:act/cda:entryRelationship/cda:observation[cda:templateId/@root='2.16.840.1.113883.10.20.22.4.4']/cda:value")
	encounter.PrincipalDiagnosis.Coded.Codes = map[string][]string{}
	encounter.Diagnosis.Coded.Codes = map[string][]string{}
	ExtractCodes(&encounter.PrincipalDiagnosis.Coded, entryElement, pdXPath)
	ExtractCodes(&encounter.Diagnosis.Coded, entryElement, diagXPath)
	ExtractCodedConcept(&encounter.PrincipalDiagnosis.CodedConcept, entryElement, pdXPath)
	ExtractCodedConcept(&encounter.Diagnosis.CodedConcept, entryElement, diagXPath)

	//extract facility
	extractFacility(&encounter, entryElement)

	//extract discharge disposition
	var dischargeDispositionCodeXPath = xpath.Compile("sdtc:dischargeDispositionCode/@code")
	var dischargeDispositionCodeSystemXPath = xpath.Compile("sdtc:dischargeDispositionCode/@codeSystem")
	dischargeDispositionCode := FirstElementContent(dischargeDispositionCodeXPath, entryElement)
	dischargeDispositionCodeSystemOid := FirstElementContent(dischargeDispositionCodeSystemXPath, entryElement)
	dischargeDispositionCodeSystem := models.CodeSystemFor(dischargeDispositionCodeSystemOid)
	if dischargeDispositionCode != "" {
		encounter.DischargeDisposition = map[string]string{
			"code":          dischargeDispositionCode,
			"codeSystem":    dischargeDispositionCodeSystem,
			"codeSystemOid": dischargeDispositionCodeSystemOid,
		}
	}

	return encounter
}

func extractFacility(encounter *models.Encounter, entryElement xml.Node) {
	var participantXPath = xpath.Compile("cda:participant[@typeCode='LOC']/cda:participantRole[@classCode='SDLOC']")
	participantElement := FirstElement(participantXPath, entryElement)

	if participantElement != nil {
		var facility = models.Facility{}

		var nameXPath = xpath.Compile("cda:playingEntity/cda:name")
		facility.Name = FirstElementContent(nameXPath, participantElement)

		addressXPath := xpath.Compile("cda:addr")
		addressElements, err := participantElement.Search(addressXPath)
		util.CheckErr(err)
		facility.Addresses = make([]models.Address, len(addressElements))
		for i, addressElement := range addressElements {
			facility.Addresses[i] = ImportAddress(addressElement)
		}

		telecomXPath := xpath.Compile("cda:telecom")
		telecomElements, err := participantElement.Search(telecomXPath)
		util.CheckErr(err)
		facility.Telecoms = make([]models.Telecom, len(telecomElements))
		for i, telecomElement := range telecomElements {
			facility.Telecoms[i] = ImportTelecom(telecomElement)
		}

		facility.Code = &models.CodedConcept{}
		ExtractCodedConcept(facility.Code, participantElement, xpath.Compile("cda:code"))

		var timeLowXPath = xpath.Compile("cda:effectiveTime/cda:low/@value")
		var timeHighXPath = xpath.Compile("cda:effectiveTime/cda:high/@value")
		facility.StartTime = GetTimestamp(timeLowXPath, entryElement)
		facility.EndTime = GetTimestamp(timeHighXPath, entryElement)

		encounter.Facility = facility
	}
}

func extractReason(encounter *models.Encounter, entryElement xml.Node) {
	var reasonXPath = xpath.Compile("cda:entryRelationship[@typeCode='RSON']/cda:observation")
	reasonElement := FirstElement(reasonXPath, entryElement)

	if reasonElement != nil {
		//extract reason value code
		var valueCodeXPath = xpath.Compile("cda:value/@code")
		var valueCodeSystemXPath = xpath.Compile("cda:value/@codeSystem")
		valueCode := FirstElementContent(valueCodeXPath, reasonElement)
		valueCodeSystem := models.CodeSystemFor(FirstElementContent(valueCodeSystemXPath, reasonElement))
		encounter.Reason.Code = valueCode
		encounter.Reason.CodeSystem = valueCodeSystem
		encounter.Reason.CodeSystemName = valueCodeSystem
	}
}
<|endoftext|>