<commit_before>ckage models

type Identity interface {
	GetID()    string
	GetName()  string
	GetEmail() string
}

type User struct {
	ID    string `json:"id"`
	Name  string `json:"name"`
	Email string `json:"email"`
}

func (u User) GetID() string {
	return u.ID
}

func (u User) GetName() string {
	return u.Name
}

func (u User) GetEmail() string {
	return u.Email
}

<commit_msg>last changes<commit_after>package models

type Identity interface {
	GetID()    string
	GetName()  string
	GetEmail() string
}

type User struct {
	ID    string `json:"id"`
	Name  string `json:"name"`
	Email string `json:"email"`
}

func (u User) GetID() string {
	return u.ID
}

func (u User) GetName() string {
	return u.Name
}

func (u User) GetEmail() string {
	return u.Email
}

<|endoftext|>


<commit_before>// Code generated by go-swagger; DO NOT EDIT.

package models

// This file was generated by the swagger tool.
// Editing this file might prove futile when you re-run the swagger generate command

import (
	"strconv"

	strfmt "github.com/go-openapi/strfmt"

	"github.com/go-openapi/errors"
	"github.com/go-openapi/swag"
	"github.com/go-openapi/validate"
)

// Material material
// swagger:model Material
type Material struct {

	// false if not archived, true if archived
	// Required: true
	Archived *bool `json:"archived"`

	// configuration
	Configuration *MaterialConfiguration `json:"configuration,omitempty"`

	// configuration history
	ConfigurationHistory []*MaterialConfiguration `json:"configurationHistory"`

	// identifier for the active configuration for this material
	// Required: true
	ConfigurationID *int32 `json:"configurationId"`

	// version of the core material this material was derived from
	// Required: true
	CoreVersion *string `json:"coreVersion"`

	// created time stamp, set server-side, read only field
	// Required: true
	Created *strfmt.DateTime `json:"created"`

	// creating user, set server-side, read only field
	// Required: true
	CreatedBy *string `json:"createdBy"`

	// material description
	// Max Length: 2048
	Description string `json:"description,omitempty"`

	// item identifier
	// Required: true
	ID *int32 `json:"id"`

	// flag whether it is a core material or a custom material
	// Required: true
	IsCore *bool `json:"isCore"`

	// key associated with this material.  e.g. Ti64
	// Required: true
	// Max Length: 16
	Key *string `json:"key"`

	// last modified time stamp, set server-side, read only field
	// Required: true
	LastModified *strfmt.DateTime `json:"lastModified"`

	// modifying user, set server-side, read only field
	// Required: true
	LastModifiedBy *string `json:"lastModifiedBy"`

	// material name
	// Required: true
	// Max Length: 128
	Name *string `json:"name"`

	// organization identifier
	// Required: true
	OrganizationID *int32 `json:"organizationId"`

	// true if the material properites have been tuned for thermal simulations
	ThermalSimulationApproved bool `json:"thermalSimulationApproved,omitempty"`
}

// Validate validates this material
func (m *Material) Validate(formats strfmt.Registry) error {
	var res []error

	if err := m.validateArchived(formats); err != nil {
		// prop
		res = append(res, err)
	}

	if err := m.validateConfiguration(formats); err != nil {
		// prop
		res = append(res, err)
	}

	if err := m.validateConfigurationHistory(formats); err != nil {
		// prop
		res = append(res, err)
	}

	if err := m.validateConfigurationID(formats); err != nil {
		// prop
		res = append(res, err)
	}

	if err := m.validateCoreVersion(formats); err != nil {
		// prop
		res = append(res, err)
	}

	if err := m.validateCreated(formats); err != nil {
		// prop
		res = append(res, err)
	}

	if err := m.validateCreatedBy(formats); err != nil {
		// prop
		res = append(res, err)
	}

	if err := m.validateDescription(formats); err != nil {
		// prop
		res = append(res, err)
	}

	if err := m.validateID(formats); err != nil {
		// prop
		res = append(res, err)
	}

	if err := m.validateIsCore(formats); err != nil {
		// prop
		res = append(res, err)
	}

	if err := m.validateKey(formats); err != nil {
		// prop
		res = append(res, err)
	}

	if err := m.validateLastModified(formats); err != nil {
		// prop
		res = append(res, err)
	}

	if err := m.validateLastModifiedBy(formats); err != nil {
		// prop
		res = append(res, err)
	}

	if err := m.validateName(formats); err != nil {
		// prop
		res = append(res, err)
	}

	if err := m.validateOrganizationID(formats); err != nil {
		// prop
		res = append(res, err)
	}

	if len(res) > 0 {
		return errors.CompositeValidationError(res...)
	}
	return nil
}

func (m *Material) validateArchived(formats strfmt.Registry) error {

	if err := validate.Required("archived", "body", m.Archived); err != nil {
		return err
	}

	return nil
}

func (m *Material) validateConfiguration(formats strfmt.Registry) error {

	if swag.IsZero(m.Configuration) { // not required
		return nil
	}

	if m.Configuration != nil {

		if err := m.Configuration.Validate(formats); err != nil {
			if ve, ok := err.(*errors.Validation); ok {
				return ve.ValidateName("configuration")
			}
			return err
		}
	}

	return nil
}

func (m *Material) validateConfigurationHistory(formats strfmt.Registry) error {

	if swag.IsZero(m.ConfigurationHistory) { // not required
		return nil
	}

	for i := 0; i < len(m.ConfigurationHistory); i++ {

		if swag.IsZero(m.ConfigurationHistory[i]) { // not required
			continue
		}

		if m.ConfigurationHistory[i] != nil {

			if err := m.ConfigurationHistory[i].Validate(formats); err != nil {
				if ve, ok := err.(*errors.Validation); ok {
					return ve.ValidateName("configurationHistory" + "." + strconv.Itoa(i))
				}
				return err
			}
		}

	}

	return nil
}

func (m *Material) validateConfigurationID(formats strfmt.Registry) error {

	if err := validate.Required("configurationId", "body", m.ConfigurationID); err != nil {
		return err
	}

	return nil
}

func (m *Material) validateCoreVersion(formats strfmt.Registry) error {

	if err := validate.Required("coreVersion", "body", m.CoreVersion); err != nil {
		return err
	}

	return nil
}

func (m *Material) validateCreated(formats strfmt.Registry) error {

	if err := validate.Required("created", "body", m.Created); err != nil {
		return err
	}

	return nil
}

func (m *Material) validateCreatedBy(formats strfmt.Registry) error {

	if err := validate.Required("createdBy", "body", m.CreatedBy); err != nil {
		return err
	}

	return nil
}

func (m *Material) validateDescription(formats strfmt.Registry) error {

	if swag.IsZero(m.Description) { // not required
		return nil
	}

	if err := validate.MaxLength("description", "body", string(m.Description), 2048); err != nil {
		return err
	}

	return nil
}

func (m *Material) validateID(formats strfmt.Registry) error {

	if err := validate.Required("id", "body", m.ID); err != nil {
		return err
	}

	return nil
}

func (m *Material) validateIsCore(formats strfmt.Registry) error {

	if err := validate.Required("isCore", "body", m.IsCore); err != nil {
		return err
	}

	return nil
}

func (m *Material) validateKey(formats strfmt.Registry) error {

	if err := validate.Required("key", "body", m.Key); err != nil {
		return err
	}

	if err := validate.MaxLength("key", "body", string(*m.Key), 16); err != nil {
		return err
	}

	return nil
}

func (m *Material) validateLastModified(formats strfmt.Registry) error {

	if err := validate.Required("lastModified", "body", m.LastModified); err != nil {
		return err
	}

	return nil
}

func (m *Material) validateLastModifiedBy(formats strfmt.Registry) error {

	if err := validate.Required("lastModifiedBy", "body", m.LastModifiedBy); err != nil {
		return err
	}

	return nil
}

func (m *Material) validateName(formats strfmt.Registry) error {

	if err := validate.Required("name", "body", m.Name); err != nil {
		return err
	}

	if err := validate.MaxLength("name", "body", string(*m.Name), 128); err != nil {
		return err
	}

	return nil
}

func (m *Material) validateOrganizationID(formats strfmt.Registry) error {

	if err := validate.Required("organizationId", "body", m.OrganizationID); err != nil {
		return err
	}

	return nil
}

// MarshalBinary interface implementation
func (m *Material) MarshalBinary() ([]byte, error) {
	if m == nil {
		return nil, nil
	}
	return swag.WriteJSON(m)
}

// UnmarshalBinary interface implementation
func (m *Material) UnmarshalBinary(b []byte) error {
	var res Material
	if err := swag.ReadJSON(b, &res); err != nil {
		return err
	}
	*m = res
	return nil
}
<commit_msg>Update to match simulation-api-specification 3.26.3<commit_after>// Code generated by go-swagger; DO NOT EDIT.

package models

// This file was generated by the swagger tool.
// Editing this file might prove futile when you re-run the swagger generate command

import (
	"strconv"

	strfmt "github.com/go-openapi/strfmt"

	"github.com/go-openapi/errors"
	"github.com/go-openapi/swag"
	"github.com/go-openapi/validate"
)

// Material material
// swagger:model Material
type Material struct {

	// false if not archived, true if archived
	// Required: true
	Archived *bool `json:"archived"`

	// configuration
	Configuration *MaterialConfiguration `json:"configuration,omitempty"`

	// configuration history
	ConfigurationHistory []*MaterialConfiguration `json:"configurationHistory"`

	// identifier for the active configuration for this material
	// Required: true
	ConfigurationID *int32 `json:"configurationId"`

	// version of the core material this material was derived from
	// Required: true
	CoreVersion *string `json:"coreVersion"`

	// created time stamp, set server-side, read only field
	// Required: true
	Created *strfmt.DateTime `json:"created"`

	// creating user, set server-side, read only field
	// Required: true
	CreatedBy *string `json:"createdBy"`

	// material description
	// Max Length: 2048
	Description string `json:"description,omitempty"`

	// item identifier
	// Required: true
	ID *int32 `json:"id"`

	// flag whether it is a core material or a custom material
	// Required: true
	IsCore *bool `json:"isCore"`

	// key associated with this material.  e.g. Ti64
	// Required: true
	// Max Length: 16
	Key *string `json:"key"`

	// last modified time stamp, set server-side, read only field
	// Required: true
	LastModified *strfmt.DateTime `json:"lastModified"`

	// modifying user, set server-side, read only field
	// Required: true
	LastModifiedBy *string `json:"lastModifiedBy"`

	// true if the material properites have been tuned for microstructure simulations
	MicrostructureSimulationApproved bool `json:"microstructureSimulationApproved,omitempty"`

	// material name
	// Required: true
	// Max Length: 128
	Name *string `json:"name"`

	// organization identifier
	// Required: true
	OrganizationID *int32 `json:"organizationId"`

	// true if the material properites have been tuned for thermal simulations
	ThermalSimulationApproved bool `json:"thermalSimulationApproved,omitempty"`
}

// Validate validates this material
func (m *Material) Validate(formats strfmt.Registry) error {
	var res []error

	if err := m.validateArchived(formats); err != nil {
		// prop
		res = append(res, err)
	}

	if err := m.validateConfiguration(formats); err != nil {
		// prop
		res = append(res, err)
	}

	if err := m.validateConfigurationHistory(formats); err != nil {
		// prop
		res = append(res, err)
	}

	if err := m.validateConfigurationID(formats); err != nil {
		// prop
		res = append(res, err)
	}

	if err := m.validateCoreVersion(formats); err != nil {
		// prop
		res = append(res, err)
	}

	if err := m.validateCreated(formats); err != nil {
		// prop
		res = append(res, err)
	}

	if err := m.validateCreatedBy(formats); err != nil {
		// prop
		res = append(res, err)
	}

	if err := m.validateDescription(formats); err != nil {
		// prop
		res = append(res, err)
	}

	if err := m.validateID(formats); err != nil {
		// prop
		res = append(res, err)
	}

	if err := m.validateIsCore(formats); err != nil {
		// prop
		res = append(res, err)
	}

	if err := m.validateKey(formats); err != nil {
		// prop
		res = append(res, err)
	}

	if err := m.validateLastModified(formats); err != nil {
		// prop
		res = append(res, err)
	}

	if err := m.validateLastModifiedBy(formats); err != nil {
		// prop
		res = append(res, err)
	}

	if err := m.validateName(formats); err != nil {
		// prop
		res = append(res, err)
	}

	if err := m.validateOrganizationID(formats); err != nil {
		// prop
		res = append(res, err)
	}

	if len(res) > 0 {
		return errors.CompositeValidationError(res...)
	}
	return nil
}

func (m *Material) validateArchived(formats strfmt.Registry) error {

	if err := validate.Required("archived", "body", m.Archived); err != nil {
		return err
	}

	return nil
}

func (m *Material) validateConfiguration(formats strfmt.Registry) error {

	if swag.IsZero(m.Configuration) { // not required
		return nil
	}

	if m.Configuration != nil {

		if err := m.Configuration.Validate(formats); err != nil {
			if ve, ok := err.(*errors.Validation); ok {
				return ve.ValidateName("configuration")
			}
			return err
		}
	}

	return nil
}

func (m *Material) validateConfigurationHistory(formats strfmt.Registry) error {

	if swag.IsZero(m.ConfigurationHistory) { // not required
		return nil
	}

	for i := 0; i < len(m.ConfigurationHistory); i++ {

		if swag.IsZero(m.ConfigurationHistory[i]) { // not required
			continue
		}

		if m.ConfigurationHistory[i] != nil {

			if err := m.ConfigurationHistory[i].Validate(formats); err != nil {
				if ve, ok := err.(*errors.Validation); ok {
					return ve.ValidateName("configurationHistory" + "." + strconv.Itoa(i))
				}
				return err
			}
		}

	}

	return nil
}

func (m *Material) validateConfigurationID(formats strfmt.Registry) error {

	if err := validate.Required("configurationId", "body", m.ConfigurationID); err != nil {
		return err
	}

	return nil
}

func (m *Material) validateCoreVersion(formats strfmt.Registry) error {

	if err := validate.Required("coreVersion", "body", m.CoreVersion); err != nil {
		return err
	}

	return nil
}

func (m *Material) validateCreated(formats strfmt.Registry) error {

	if err := validate.Required("created", "body", m.Created); err != nil {
		return err
	}

	return nil
}

func (m *Material) validateCreatedBy(formats strfmt.Registry) error {

	if err := validate.Required("createdBy", "body", m.CreatedBy); err != nil {
		return err
	}

	return nil
}

func (m *Material) validateDescription(formats strfmt.Registry) error {

	if swag.IsZero(m.Description) { // not required
		return nil
	}

	if err := validate.MaxLength("description", "body", string(m.Description), 2048); err != nil {
		return err
	}

	return nil
}

func (m *Material) validateID(formats strfmt.Registry) error {

	if err := validate.Required("id", "body", m.ID); err != nil {
		return err
	}

	return nil
}

func (m *Material) validateIsCore(formats strfmt.Registry) error {

	if err := validate.Required("isCore", "body", m.IsCore); err != nil {
		return err
	}

	return nil
}

func (m *Material) validateKey(formats strfmt.Registry) error {

	if err := validate.Required("key", "body", m.Key); err != nil {
		return err
	}

	if err := validate.MaxLength("key", "body", string(*m.Key), 16); err != nil {
		return err
	}

	return nil
}

func (m *Material) validateLastModified(formats strfmt.Registry) error {

	if err := validate.Required("lastModified", "body", m.LastModified); err != nil {
		return err
	}

	return nil
}

func (m *Material) validateLastModifiedBy(formats strfmt.Registry) error {

	if err := validate.Required("lastModifiedBy", "body", m.LastModifiedBy); err != nil {
		return err
	}

	return nil
}

func (m *Material) validateName(formats strfmt.Registry) error {

	if err := validate.Required("name", "body", m.Name); err != nil {
		return err
	}

	if err := validate.MaxLength("name", "body", string(*m.Name), 128); err != nil {
		return err
	}

	return nil
}

func (m *Material) validateOrganizationID(formats strfmt.Registry) error {

	if err := validate.Required("organizationId", "body", m.OrganizationID); err != nil {
		return err
	}

	return nil
}

// MarshalBinary interface implementation
func (m *Material) MarshalBinary() ([]byte, error) {
	if m == nil {
		return nil, nil
	}
	return swag.WriteJSON(m)
}

// UnmarshalBinary interface implementation
func (m *Material) UnmarshalBinary(b []byte) error {
	var res Material
	if err := swag.ReadJSON(b, &res); err != nil {
		return err
	}
	*m = res
	return nil
}
<|endoftext|>


<commit_before>// Copyright © 2014-2016 Thomas Rabaix <thomas.rabaix@gmail.com>.
//
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file.

package api

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"

	log "github.com/Sirupsen/logrus"
	sq "github.com/lann/squirrel"
	"github.com/rande/gonode/core/helper"
	"github.com/rande/gonode/core/security"
	"github.com/rande/gonode/core/squirrel"
	"github.com/rande/gonode/modules/base"
)

const (
	OPERATION_OK = "OK"
	OPERATION_KO = "KO"
)

type ApiPager struct {
	Elements []interface{} `json:"elements"`
	Page     uint64        `json:"page"`
	PerPage  uint64        `json:"per_page"`
	Next     uint64        `json:"next"`
	Previous uint64        `json:"previous"`
}

type Api struct {
	Version    string
	Manager    base.NodeManager
	BaseUrl    string
	Serializer *base.Serializer
	Logger     *log.Logger
	Authorizer security.AuthorizationChecker
}

type ApiOperation struct {
	Status  string `json:"status"`
	Message string `json:"message"`
}

func (a *Api) SelectBuilder(options *base.SelectOptions) sq.SelectBuilder {
	return a.Manager.SelectBuilder(options)
}

func (a *Api) Find(w io.Writer, query sq.SelectBuilder, page uint64, perPage uint64, options *base.AccessOptions) error {

	if options != nil && len(options.Roles) > 0 {
		value, _ := options.Roles.ToStringSlice()

		query = query.Where(squirrel.NewExprSlice(fmt.Sprintf("\"%s\" && ARRAY["+sq.Placeholders(len(options.Roles))+"]", "access"), value))
	}

	list := a.Manager.FindBy(query, (page-1)*perPage, perPage+1)

	pager := &ApiPager{
		Page:    page,
		PerPage: perPage,
	}

	pager.Elements = make([]interface{}, 0)

	if page > 1 {
		pager.Previous = page - 1
	}

	counter := uint64(0)
	for e := list.Front(); e != nil; e = e.Next() {
		if counter == perPage {
			pager.Next = page + 1
			break
		}

		b := bytes.NewBuffer([]byte{})
		a.Serializer.Serialize(b, e.Value.(*base.Node))

		message := json.RawMessage(b.Bytes())
		pager.Elements = append(pager.Elements, &message)

		counter++
	}

	base.Serialize(w, pager)

	return nil
}

func (a *Api) Save(r io.Reader, w io.Writer, options *base.AccessOptions) error {
	node := base.NewNode()

	err := a.Serializer.Deserialize(r, node)

	helper.PanicOnError(err)

	if a.Logger != nil {
		a.Logger.Printf("trying to save node.uuid=%s, node.type=%s", node.Uuid, node.Type)
	}

	saved := a.Manager.Find(node.Uuid)

	if saved != nil {
		a.Logger.Printf("find uuid: %s", node.Uuid)

		helper.PanicUnless(node.Type == saved.Type, "Type mismatch")

		if options != nil {
			result, _ := a.Authorizer.IsGranted(options.Token, nil, node)

			if !result {
				return base.AccessForbiddenError
			}
		}

		if node.Deleted == true {
			return base.AlreadyDeletedError
		}

		if node.Revision != saved.Revision {
			return base.RevisionError
		}

		node.Id = saved.Id

		// we cannot overwrite the Parents, Or the ParentUuid, need to use the http API
		node.Parents = saved.Parents
		node.ParentUuid = saved.ParentUuid

	} else if a.Logger != nil {
		a.Logger.Printf("cannot find uuid: %s, create a new one", node.Uuid)
	}

	if a.Logger != nil {
		a.Logger.Printf("saving node.id=%d, node.uuid=%s", node.Id, node.Uuid)
	}

	if ok, errors := a.Manager.Validate(node); !ok {
		base.Serialize(w, errors)

		return base.ValidationError
	}

	a.Manager.Save(node, true)

	a.Serializer.Serialize(w, node)

	return nil
}

func (a *Api) Move(nodeUuid, parentUuid string, w io.Writer, options *base.AccessOptions) error {
	nodeReference, err := base.GetReferenceFromString(nodeUuid)

	if err != nil {
		return err
	}

	parentReference, err := base.GetReferenceFromString(parentUuid)

	if err != nil {
		return err
	}

	affectedNodes, err := a.Manager.Move(nodeReference, parentReference)

	if err != nil {
		return err
	}

	a.Serializer.Serialize(w, &ApiOperation{
		Status:  OPERATION_OK,
		Message: fmt.Sprintf("Node altered: %d", affectedNodes),
	})

	return nil
}

func (a *Api) FindOne(uuid string, w io.Writer, options *base.AccessOptions) error {
	reference, err := base.GetReferenceFromString(uuid)

	if err != nil {
		return base.NotFoundError
	}

	query := a.Manager.SelectBuilder(base.NewSelectOptions()).Where(sq.Eq{"uuid": reference.String()})

	return a.FindOneBy(query, w, options)
}

func (a *Api) FindOneBy(query sq.SelectBuilder, w io.Writer, options *base.AccessOptions) error {
	node := a.Manager.FindOneBy(query)

	if node == nil {
		return base.NotFoundError
	}

	if options != nil {
		result, _ := a.Authorizer.IsGranted(options.Token, nil, node)

		if !result {
			return base.AccessForbiddenError
		}
	}

	a.Serializer.Serialize(w, node)

	return nil
}

func (a *Api) RemoveOne(uuid string, w io.Writer, options *base.AccessOptions) error {
	reference, err := base.GetReferenceFromString(uuid)

	if err != nil {
		return err
	}

	node := a.Manager.Find(reference)

	if node == nil {
		return base.NotFoundError
	}

	if options != nil {
		result, _ := a.Authorizer.IsGranted(options.Token, nil, node)

		if !result {
			return base.AccessForbiddenError
		}
	}

	if node.Deleted {
		return base.AlreadyDeletedError
	}

	node, _ = a.Manager.RemoveOne(node)

	a.Serializer.Serialize(w, node)

	return nil
}

func (a *Api) Remove(query sq.SelectBuilder, w io.Writer, options *base.AccessOptions) error {
	if options != nil && len(options.Roles) > 0 {
		value, _ := options.Roles.ToStringSlice()

		query = query.Where(squirrel.NewExprSlice(fmt.Sprintf("\"%s\" && ARRAY["+sq.Placeholders(len(options.Roles))+"]", "access"), value))
	}

	a.Manager.Remove(query)

	a.Find(w, query, 0, 0, options)

	return nil
}
<commit_msg>feat(access): check access on move action<commit_after>// Copyright © 2014-2016 Thomas Rabaix <thomas.rabaix@gmail.com>.
//
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file.

package api

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"

	log "github.com/Sirupsen/logrus"
	sq "github.com/lann/squirrel"
	"github.com/rande/gonode/core/helper"
	"github.com/rande/gonode/core/security"
	"github.com/rande/gonode/core/squirrel"
	"github.com/rande/gonode/modules/base"
)

const (
	OPERATION_OK = "OK"
	OPERATION_KO = "KO"
)

type ApiPager struct {
	Elements []interface{} `json:"elements"`
	Page     uint64        `json:"page"`
	PerPage  uint64        `json:"per_page"`
	Next     uint64        `json:"next"`
	Previous uint64        `json:"previous"`
}

type Api struct {
	Version    string
	Manager    base.NodeManager
	BaseUrl    string
	Serializer *base.Serializer
	Logger     *log.Logger
	Authorizer security.AuthorizationChecker
}

type ApiOperation struct {
	Status  string `json:"status"`
	Message string `json:"message"`
}

func (a *Api) SelectBuilder(options *base.SelectOptions) sq.SelectBuilder {
	return a.Manager.SelectBuilder(options)
}

func (a *Api) Find(w io.Writer, query sq.SelectBuilder, page uint64, perPage uint64, options *base.AccessOptions) error {

	if options != nil && len(options.Roles) > 0 {
		value, _ := options.Roles.ToStringSlice()

		query = query.Where(squirrel.NewExprSlice(fmt.Sprintf("\"%s\" && ARRAY["+sq.Placeholders(len(options.Roles))+"]", "access"), value))
	}

	list := a.Manager.FindBy(query, (page-1)*perPage, perPage+1)

	pager := &ApiPager{
		Page:    page,
		PerPage: perPage,
	}

	pager.Elements = make([]interface{}, 0)

	if page > 1 {
		pager.Previous = page - 1
	}

	counter := uint64(0)
	for e := list.Front(); e != nil; e = e.Next() {
		if counter == perPage {
			pager.Next = page + 1
			break
		}

		b := bytes.NewBuffer([]byte{})
		a.Serializer.Serialize(b, e.Value.(*base.Node))

		message := json.RawMessage(b.Bytes())
		pager.Elements = append(pager.Elements, &message)

		counter++
	}

	base.Serialize(w, pager)

	return nil
}

func (a *Api) Save(r io.Reader, w io.Writer, options *base.AccessOptions) error {
	node := base.NewNode()

	err := a.Serializer.Deserialize(r, node)

	helper.PanicOnError(err)

	if a.Logger != nil {
		a.Logger.Printf("trying to save node.uuid=%s, node.type=%s", node.Uuid, node.Type)
	}

	saved := a.Manager.Find(node.Uuid)

	if saved != nil {
		a.Logger.Printf("find uuid: %s", node.Uuid)

		helper.PanicUnless(node.Type == saved.Type, "Type mismatch")

		if options != nil {
			result, _ := a.Authorizer.IsGranted(options.Token, nil, node)

			if !result {
				return base.AccessForbiddenError
			}
		}

		if node.Deleted == true {
			return base.AlreadyDeletedError
		}

		if node.Revision != saved.Revision {
			return base.RevisionError
		}

		node.Id = saved.Id

		// we cannot overwrite the Parents, Or the ParentUuid, need to use the http API
		node.Parents = saved.Parents
		node.ParentUuid = saved.ParentUuid

	} else if a.Logger != nil {
		a.Logger.Printf("cannot find uuid: %s, create a new one", node.Uuid)
	}

	if a.Logger != nil {
		a.Logger.Printf("saving node.id=%d, node.uuid=%s", node.Id, node.Uuid)
	}

	if ok, errors := a.Manager.Validate(node); !ok {
		base.Serialize(w, errors)

		return base.ValidationError
	}

	a.Manager.Save(node, true)

	a.Serializer.Serialize(w, node)

	return nil
}

func (a *Api) Move(nodeUuid, parentUuid string, w io.Writer, options *base.AccessOptions) error {
	// handle node
	nodeReference, err := base.GetReferenceFromString(nodeUuid)

	if err != nil {
		return err
	}

	if node := a.Manager.Find(nodeReference); node == nil {
		return base.NotFoundError
	} else if result, _ := a.Authorizer.IsGranted(options.Token, nil, node); !result {
		return base.AccessForbiddenError
	}

	// parent node
	parentReference, err := base.GetReferenceFromString(parentUuid)

	if err != nil {
		return err
	}

	if parent := a.Manager.Find(parentReference); parent == nil {
		return base.NotFoundError
	} else if result, _ := a.Authorizer.IsGranted(options.Token, nil, parent); !result {
		return base.AccessForbiddenError
	}

	// move node
	if affectedNodes, err := a.Manager.Move(nodeReference, parentReference); err != nil {
		return err
	} else {
		a.Serializer.Serialize(w, &ApiOperation{
			Status:  OPERATION_OK,
			Message: fmt.Sprintf("Node altered: %d", affectedNodes),
		})
	}

	return nil
}

func (a *Api) FindOne(uuid string, w io.Writer, options *base.AccessOptions) error {
	reference, err := base.GetReferenceFromString(uuid)

	if err != nil {
		return base.NotFoundError
	}

	query := a.Manager.SelectBuilder(base.NewSelectOptions()).Where(sq.Eq{"uuid": reference.String()})

	return a.FindOneBy(query, w, options)
}

func (a *Api) FindOneBy(query sq.SelectBuilder, w io.Writer, options *base.AccessOptions) error {
	node := a.Manager.FindOneBy(query)

	if node == nil {
		return base.NotFoundError
	}

	if options != nil {
		result, _ := a.Authorizer.IsGranted(options.Token, nil, node)

		if !result {
			return base.AccessForbiddenError
		}
	}

	a.Serializer.Serialize(w, node)

	return nil
}

func (a *Api) RemoveOne(uuid string, w io.Writer, options *base.AccessOptions) error {
	reference, err := base.GetReferenceFromString(uuid)

	if err != nil {
		return err
	}

	node := a.Manager.Find(reference)

	if node == nil {
		return base.NotFoundError
	}

	if options != nil {
		result, _ := a.Authorizer.IsGranted(options.Token, nil, node)

		if !result {
			return base.AccessForbiddenError
		}
	}

	if node.Deleted {
		return base.AlreadyDeletedError
	}

	node, _ = a.Manager.RemoveOne(node)

	a.Serializer.Serialize(w, node)

	return nil
}

func (a *Api) Remove(query sq.SelectBuilder, w io.Writer, options *base.AccessOptions) error {
	if options != nil && len(options.Roles) > 0 {
		value, _ := options.Roles.ToStringSlice()

		query = query.Where(squirrel.NewExprSlice(fmt.Sprintf("\"%s\" && ARRAY["+sq.Placeholders(len(options.Roles))+"]", "access"), value))
	}

	a.Manager.Remove(query)

	a.Find(w, query, 0, 0, options)

	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"encoding/binary"
	"fmt"
	"io"

	"github.com/disorganizer/brig/util"
	"github.com/golang/snappy"
)

type writer struct {
	sizeAcc   *util.SizeAccumulator
	rawW      io.Writer
	zipW      io.Writer
	chunkBuf  *bytes.Buffer
	index     []Block
	rawOff    int64
	algorithm Algorithm
}

func (w *writer) addToIndex() {
	a, b := w.rawOff, int64(w.sizeAcc.Size())
	fmt.Println(a, b)
	w.index = append(w.index, Block{a, b})
}

func (w *writer) flushBuffer(flushSize int) (int, error) {
	w.addToIndex()
	// Compress and flush the current block.
	rawN, err := w.zipW.Write(w.chunkBuf.Next(flushSize))
	if err != nil {
		return rawN, err
	}

	// Build and update index for the current block.
	w.rawOff += int64(rawN)
	return rawN, nil
}

func (w *writer) Write(p []byte) (n int, err error) {

	pSize := len(p)
	// Compress only MaxBlockSize equal chunks.
	for {
		n, _ := w.chunkBuf.Write(p[:util.Min(len(p), MaxBlockSize)])

		// Flush the current block.
		//fmt.Println("buflen und max:", w.chunkBuf.Len(), MaxBlockSize)
		if w.chunkBuf.Len() >= MaxBlockSize {
			if _, err := w.flushBuffer(MaxBlockSize); err != nil {
				fmt.Println(err)
				return 0, err
			}
			// Forget flushed input.
			//fmt.Println("p1", len(p), n)
			p = p[n:]
			//fmt.Println("p2", len(p), n)
			continue
		}
		break
	}

	// Fake bytes written, as expeted by some functions.
	return pSize, nil
}

//TODO: Make algorithm a function parameter.
func NewWriter(w io.Writer) io.WriteCloser {
	s := &util.SizeAccumulator{}
	return &writer{
		sizeAcc:   s,
		zipW:      snappy.NewWriter(io.MultiWriter(w, s)),
		rawW:      w,
		chunkBuf:  &bytes.Buffer{},
		algorithm: AlgoSnappy,
	}
}

func (w *writer) Close() error {

	// Write remaining bytes left in buffer.
	if _, err := w.flushBuffer(w.chunkBuf.Len()); err != nil {

		fmt.Println("Close():", err)
		return err
	}
	w.addToIndex()

	// Write compression index tail and close stream.
	indexSize := uint64(IndexBlockSize * len(w.index))

	// TODO: Variablen bezeichnungen noch etwas aufräumen?
	tailBuf := make([]byte, indexSize)
	tailBufStart := tailBuf
	for _, blkidx := range w.index {
		blkidx.marshal(tailBuf)
		tailBuf = tailBuf[IndexBlockSize:]
	}

	if n, err := w.rawW.Write(tailBufStart); err != nil || uint64(n) != indexSize {
		return err
	}

	// Write index tail size at the end of stream.
	var tailSizeBuf = make([]byte, TailSize)
	binary.LittleEndian.PutUint32(tailSizeBuf[0:4], uint32(w.algorithm))
	binary.LittleEndian.PutUint32(tailSizeBuf[4:8], MaxBlockSize)
	binary.LittleEndian.PutUint64(tailSizeBuf[8:], indexSize)
	if _, err := w.rawW.Write(tailSizeBuf); err != nil {
		fmt.Println("Error writing tailSizeBuf:", err)
		return err
	}

	if cl, ok := w.rawW.(io.Closer); ok {
		return cl.Close()
	}

	return nil
}
<commit_msg>writer.go: Write method for loop simplified.<commit_after>package main

import (
	"bytes"
	"encoding/binary"
	"fmt"
	"io"

	"github.com/disorganizer/brig/util"
	"github.com/golang/snappy"
)

type writer struct {
	sizeAcc   *util.SizeAccumulator
	rawW      io.Writer
	zipW      io.Writer
	chunkBuf  *bytes.Buffer
	index     []Block
	rawOff    int64
	algorithm Algorithm
}

func (w *writer) addToIndex() {
	a, b := w.rawOff, int64(w.sizeAcc.Size())
	fmt.Println(a, b)
	w.index = append(w.index, Block{a, b})
}

func (w *writer) flushBuffer(flushSize int) (int, error) {
	w.addToIndex()
	// Compress and flush the current block.
	rawN, err := w.zipW.Write(w.chunkBuf.Next(flushSize))
	if err != nil {
		return rawN, err
	}

	// Build and update index for the current block.
	w.rawOff += int64(rawN)
	return rawN, nil
}

func (w *writer) Write(p []byte) (n int, err error) {
	pSize := len(p)
	// Compress only MaxBlockSize equal chunks.
	for {
		n, _ := w.chunkBuf.Write(p[:util.Min(len(p), MaxBlockSize)])

		if w.chunkBuf.Len() < MaxBlockSize {
			break
		}

		if _, err := w.flushBuffer(MaxBlockSize); err != nil {
			return 0, err
		}
		p = p[n:]
	}
	return pSize, nil
}

//TODO: Make algorithm a function parameter.
func NewWriter(w io.Writer) io.WriteCloser {
	s := &util.SizeAccumulator{}
	return &writer{
		sizeAcc:   s,
		zipW:      snappy.NewWriter(io.MultiWriter(w, s)),
		rawW:      w,
		chunkBuf:  &bytes.Buffer{},
		algorithm: AlgoSnappy,
	}
}

func (w *writer) Close() error {

	// Write remaining bytes left in buffer.
	if _, err := w.flushBuffer(w.chunkBuf.Len()); err != nil {

		fmt.Println("Close():", err)
		return err
	}
	w.addToIndex()

	// Write compression index tail and close stream.
	indexSize := uint64(IndexBlockSize * len(w.index))

	// TODO: Variablen bezeichnungen noch etwas aufräumen?
	tailBuf := make([]byte, indexSize)
	tailBufStart := tailBuf
	for _, blkidx := range w.index {
		blkidx.marshal(tailBuf)
		tailBuf = tailBuf[IndexBlockSize:]
	}

	if n, err := w.rawW.Write(tailBufStart); err != nil || uint64(n) != indexSize {
		return err
	}

	// Write index tail size at the end of stream.
	var tailSizeBuf = make([]byte, TailSize)
	binary.LittleEndian.PutUint32(tailSizeBuf[0:4], uint32(w.algorithm))
	binary.LittleEndian.PutUint32(tailSizeBuf[4:8], MaxBlockSize)
	binary.LittleEndian.PutUint64(tailSizeBuf[8:], indexSize)
	if _, err := w.rawW.Write(tailSizeBuf); err != nil {
		fmt.Println("Error writing tailSizeBuf:", err)
		return err
	}

	if cl, ok := w.rawW.(io.Closer); ok {
		return cl.Close()
	}

	return nil
}
<|endoftext|>


<commit_before>// Copyright 2017 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package ssh

import (
	"bytes"
	"crypto/rand"
	"crypto/rsa"
	"crypto/x509"
	"encoding/pem"
	"fmt"
	"io"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
	"sync"
	"syscall"

	"code.gitea.io/gitea/models"
	"code.gitea.io/gitea/modules/log"
	"code.gitea.io/gitea/modules/setting"
	"code.gitea.io/gitea/modules/util"

	"github.com/gliderlabs/ssh"
	gossh "golang.org/x/crypto/ssh"
)

type contextKey string

const giteaKeyID = contextKey("gitea-key-id")

func getExitStatusFromError(err error) int {
	if err == nil {
		return 0
	}

	exitErr, ok := err.(*exec.ExitError)
	if !ok {
		return 1
	}

	waitStatus, ok := exitErr.Sys().(syscall.WaitStatus)
	if !ok {
		// This is a fallback and should at least let us return something useful
		// when running on Windows, even if it isn't completely accurate.
		if exitErr.Success() {
			return 0
		}

		return 1
	}

	return waitStatus.ExitStatus()
}

func sessionHandler(session ssh.Session) {
	keyID := fmt.Sprintf("%d", session.Context().Value(giteaKeyID).(int64))

	command := session.RawCommand()

	log.Trace("SSH: Payload: %v", command)

	args := []string{"serv", "key-" + keyID, "--config=" + setting.CustomConf}
	log.Trace("SSH: Arguments: %v", args)
	cmd := exec.Command(setting.AppPath, args...)
	cmd.Env = append(
		os.Environ(),
		"SSH_ORIGINAL_COMMAND="+command,
		"SKIP_MINWINSVC=1",
	)

	stdout, err := cmd.StdoutPipe()
	if err != nil {
		log.Error("SSH: StdoutPipe: %v", err)
		return
	}
	stderr, err := cmd.StderrPipe()
	if err != nil {
		log.Error("SSH: StderrPipe: %v", err)
		return
	}
	stdin, err := cmd.StdinPipe()
	if err != nil {
		log.Error("SSH: StdinPipe: %v", err)
		return
	}

	wg := &sync.WaitGroup{}
	wg.Add(2)

	if err = cmd.Start(); err != nil {
		log.Error("SSH: Start: %v", err)
		return
	}

	go func() {
		defer stdin.Close()
		if _, err := io.Copy(stdin, session); err != nil {
			log.Error("Failed to write session to stdin. %s", err)
		}
	}()

	go func() {
		defer wg.Done()
		if _, err := io.Copy(session, stdout); err != nil {
			log.Error("Failed to write stdout to session. %s", err)
		}
	}()

	go func() {
		defer wg.Done()
		if _, err := io.Copy(session.Stderr(), stderr); err != nil {
			log.Error("Failed to write stderr to session. %s", err)
		}
	}()

	// Ensure all the output has been written before we wait on the command
	// to exit.
	wg.Wait()

	// Wait for the command to exit and log any errors we get
	err = cmd.Wait()
	if err != nil {
		log.Error("SSH: Wait: %v", err)
	}

	if err := session.Exit(getExitStatusFromError(err)); err != nil {
		log.Error("Session failed to exit. %s", err)
	}
}

func publicKeyHandler(ctx ssh.Context, key ssh.PublicKey) bool {
	if log.IsDebug() { // <- FingerprintSHA256 is kinda expensive so only calculate it if necessary
		log.Debug("Handle Public Key: Fingerprint: %s from %s", gossh.FingerprintSHA256(key), ctx.RemoteAddr())
	}

	if ctx.User() != setting.SSH.BuiltinServerUser {
		log.Warn("Invalid SSH username %s - must use %s for all git operations via ssh", ctx.User(), setting.SSH.BuiltinServerUser)
		log.Warn("Failed authentication attempt from %s", ctx.RemoteAddr())
		return false
	}

	// check if we have a certificate
	if cert, ok := key.(*gossh.Certificate); ok {
		if log.IsDebug() { // <- FingerprintSHA256 is kinda expensive so only calculate it if necessary
			log.Debug("Handle Certificate: %s Fingerprint: %s is a certificate", ctx.RemoteAddr(), gossh.FingerprintSHA256(key))
		}

		if len(setting.SSH.TrustedUserCAKeys) == 0 {
			log.Warn("Certificate Rejected: No trusted certificate authorities for this server")
			log.Warn("Failed authentication attempt from %s", ctx.RemoteAddr())
			return false
		}

		// look for the exact principal
	principalLoop:
		for _, principal := range cert.ValidPrincipals {
			pkey, err := models.SearchPublicKeyByContentExact(principal)
			if err != nil {
				if models.IsErrKeyNotExist(err) {
					log.Debug("Principal Rejected: %s Unknown Principal: %s", ctx.RemoteAddr(), principal)
					continue principalLoop
				}
				log.Error("SearchPublicKeyByContentExact: %v", err)
				return false
			}

			c := &gossh.CertChecker{
				IsUserAuthority: func(auth gossh.PublicKey) bool {
					for _, k := range setting.SSH.TrustedUserCAKeysParsed {
						if bytes.Equal(auth.Marshal(), k.Marshal()) {
							return true
						}
					}

					return false
				},
			}

			// check the CA of the cert
			if !c.IsUserAuthority(cert.SignatureKey) {
				if log.IsDebug() {
					log.Debug("Principal Rejected: %s Untrusted Authority Signature Fingerprint %s for Principal: %s", ctx.RemoteAddr(), gossh.FingerprintSHA256(cert.SignatureKey), principal)
				}
				continue principalLoop
			}

			// validate the cert for this principal
			if err := c.CheckCert(principal, cert); err != nil {
				// User is presenting an invalid certificate - STOP any further processing
				if log.IsError() {
					log.Error("Invalid Certificate KeyID %s with Signature Fingerprint %s presented for Principal: %s from %s", cert.KeyId, gossh.FingerprintSHA256(cert.SignatureKey), principal, ctx.RemoteAddr())
				}
				log.Warn("Failed authentication attempt from %s", ctx.RemoteAddr())

				return false
			}

			if log.IsDebug() { // <- FingerprintSHA256 is kinda expensive so only calculate it if necessary
				log.Debug("Successfully authenticated: %s Certificate Fingerprint: %s Principal: %s", ctx.RemoteAddr(), gossh.FingerprintSHA256(key), principal)
			}
			ctx.SetValue(giteaKeyID, pkey.ID)

			return true
		}

		if log.IsWarn() {
			log.Warn("From %s Fingerprint: %s is a certificate, but no valid principals found", ctx.RemoteAddr(), gossh.FingerprintSHA256(key))
			log.Warn("Failed authentication attempt from %s", ctx.RemoteAddr())
		}
		return false
	}

	if log.IsDebug() { // <- FingerprintSHA256 is kinda expensive so only calculate it if necessary
		log.Debug("Handle Public Key: %s Fingerprint: %s is not a certificate", ctx.RemoteAddr(), gossh.FingerprintSHA256(key))
	}

	pkey, err := models.SearchPublicKeyByContent(strings.TrimSpace(string(gossh.MarshalAuthorizedKey(key))))
	if err != nil {
		if models.IsErrKeyNotExist(err) {
			if log.IsWarn() {
				log.Warn("Unknown public key: %s from %s", gossh.FingerprintSHA256(key), ctx.RemoteAddr())
				log.Warn("Failed authentication attempt from %s", ctx.RemoteAddr())
			}
			return false
		}
		log.Error("SearchPublicKeyByContent: %v", err)
		return false
	}

	if log.IsDebug() { // <- FingerprintSHA256 is kinda expensive so only calculate it if necessary
		log.Debug("Successfully authenticated: %s Public Key Fingerprint: %s", ctx.RemoteAddr(), gossh.FingerprintSHA256(key))
	}
	ctx.SetValue(giteaKeyID, pkey.ID)

	return true
}

// Listen starts a SSH server listens on given port.
func Listen(host string, port int, ciphers []string, keyExchanges []string, macs []string) {
	// TODO: Handle ciphers, keyExchanges, and macs

	srv := ssh.Server{
		Addr:             fmt.Sprintf("%s:%d", host, port),
		PublicKeyHandler: publicKeyHandler,
		Handler:          sessionHandler,

		// We need to explicitly disable the PtyCallback so text displays
		// properly.
		PtyCallback: func(ctx ssh.Context, pty ssh.Pty) bool {
			return false
		},
	}

	keyPath := filepath.Join(setting.AppDataPath, "ssh/gogs.rsa")
	isExist, err := util.IsExist(keyPath)
	if err != nil {
		log.Fatal("Unable to check if %s exists. Error: %v", keyPath, err)
	}
	if !isExist {
		filePath := filepath.Dir(keyPath)

		if err := os.MkdirAll(filePath, os.ModePerm); err != nil {
			log.Error("Failed to create dir %s: %v", filePath, err)
		}

		err := GenKeyPair(keyPath)
		if err != nil {
			log.Fatal("Failed to generate private key: %v", err)
		}
		log.Trace("New private key is generated: %s", keyPath)
	}

	err = srv.SetOption(ssh.HostKeyFile(keyPath))
	if err != nil {
		log.Error("Failed to set Host Key. %s", err)
	}

	go listen(&srv)

}

// GenKeyPair make a pair of public and private keys for SSH access.
// Public key is encoded in the format for inclusion in an OpenSSH authorized_keys file.
// Private Key generated is PEM encoded
func GenKeyPair(keyPath string) error {
	privateKey, err := rsa.GenerateKey(rand.Reader, 2048)
	if err != nil {
		return err
	}

	privateKeyPEM := &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(privateKey)}
	f, err := os.OpenFile(keyPath, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600)
	if err != nil {
		return err
	}
	defer func() {
		if err = f.Close(); err != nil {
			log.Error("Close: %v", err)
		}
	}()

	if err := pem.Encode(f, privateKeyPEM); err != nil {
		return err
	}

	// generate public key
	pub, err := gossh.NewPublicKey(&privateKey.PublicKey)
	if err != nil {
		return err
	}

	public := gossh.MarshalAuthorizedKey(pub)
	p, err := os.OpenFile(keyPath+".pub", os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600)
	if err != nil {
		return err
	}
	defer func() {
		if err = p.Close(); err != nil {
			log.Error("Close: %v", err)
		}
	}()
	_, err = p.Write(public)
	return err
}
<commit_msg>Internal ssh server respect Ciphers, MACs and KeyExchanges settings (#14523)<commit_after>// Copyright 2017 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package ssh

import (
	"bytes"
	"crypto/rand"
	"crypto/rsa"
	"crypto/x509"
	"encoding/pem"
	"fmt"
	"io"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
	"sync"
	"syscall"

	"code.gitea.io/gitea/models"
	"code.gitea.io/gitea/modules/log"
	"code.gitea.io/gitea/modules/setting"
	"code.gitea.io/gitea/modules/util"

	"github.com/gliderlabs/ssh"
	gossh "golang.org/x/crypto/ssh"
)

type contextKey string

const giteaKeyID = contextKey("gitea-key-id")

func getExitStatusFromError(err error) int {
	if err == nil {
		return 0
	}

	exitErr, ok := err.(*exec.ExitError)
	if !ok {
		return 1
	}

	waitStatus, ok := exitErr.Sys().(syscall.WaitStatus)
	if !ok {
		// This is a fallback and should at least let us return something useful
		// when running on Windows, even if it isn't completely accurate.
		if exitErr.Success() {
			return 0
		}

		return 1
	}

	return waitStatus.ExitStatus()
}

func sessionHandler(session ssh.Session) {
	keyID := fmt.Sprintf("%d", session.Context().Value(giteaKeyID).(int64))

	command := session.RawCommand()

	log.Trace("SSH: Payload: %v", command)

	args := []string{"serv", "key-" + keyID, "--config=" + setting.CustomConf}
	log.Trace("SSH: Arguments: %v", args)
	cmd := exec.Command(setting.AppPath, args...)
	cmd.Env = append(
		os.Environ(),
		"SSH_ORIGINAL_COMMAND="+command,
		"SKIP_MINWINSVC=1",
	)

	stdout, err := cmd.StdoutPipe()
	if err != nil {
		log.Error("SSH: StdoutPipe: %v", err)
		return
	}
	stderr, err := cmd.StderrPipe()
	if err != nil {
		log.Error("SSH: StderrPipe: %v", err)
		return
	}
	stdin, err := cmd.StdinPipe()
	if err != nil {
		log.Error("SSH: StdinPipe: %v", err)
		return
	}

	wg := &sync.WaitGroup{}
	wg.Add(2)

	if err = cmd.Start(); err != nil {
		log.Error("SSH: Start: %v", err)
		return
	}

	go func() {
		defer stdin.Close()
		if _, err := io.Copy(stdin, session); err != nil {
			log.Error("Failed to write session to stdin. %s", err)
		}
	}()

	go func() {
		defer wg.Done()
		if _, err := io.Copy(session, stdout); err != nil {
			log.Error("Failed to write stdout to session. %s", err)
		}
	}()

	go func() {
		defer wg.Done()
		if _, err := io.Copy(session.Stderr(), stderr); err != nil {
			log.Error("Failed to write stderr to session. %s", err)
		}
	}()

	// Ensure all the output has been written before we wait on the command
	// to exit.
	wg.Wait()

	// Wait for the command to exit and log any errors we get
	err = cmd.Wait()
	if err != nil {
		log.Error("SSH: Wait: %v", err)
	}

	if err := session.Exit(getExitStatusFromError(err)); err != nil {
		log.Error("Session failed to exit. %s", err)
	}
}

func publicKeyHandler(ctx ssh.Context, key ssh.PublicKey) bool {
	if log.IsDebug() { // <- FingerprintSHA256 is kinda expensive so only calculate it if necessary
		log.Debug("Handle Public Key: Fingerprint: %s from %s", gossh.FingerprintSHA256(key), ctx.RemoteAddr())
	}

	if ctx.User() != setting.SSH.BuiltinServerUser {
		log.Warn("Invalid SSH username %s - must use %s for all git operations via ssh", ctx.User(), setting.SSH.BuiltinServerUser)
		log.Warn("Failed authentication attempt from %s", ctx.RemoteAddr())
		return false
	}

	// check if we have a certificate
	if cert, ok := key.(*gossh.Certificate); ok {
		if log.IsDebug() { // <- FingerprintSHA256 is kinda expensive so only calculate it if necessary
			log.Debug("Handle Certificate: %s Fingerprint: %s is a certificate", ctx.RemoteAddr(), gossh.FingerprintSHA256(key))
		}

		if len(setting.SSH.TrustedUserCAKeys) == 0 {
			log.Warn("Certificate Rejected: No trusted certificate authorities for this server")
			log.Warn("Failed authentication attempt from %s", ctx.RemoteAddr())
			return false
		}

		// look for the exact principal
	principalLoop:
		for _, principal := range cert.ValidPrincipals {
			pkey, err := models.SearchPublicKeyByContentExact(principal)
			if err != nil {
				if models.IsErrKeyNotExist(err) {
					log.Debug("Principal Rejected: %s Unknown Principal: %s", ctx.RemoteAddr(), principal)
					continue principalLoop
				}
				log.Error("SearchPublicKeyByContentExact: %v", err)
				return false
			}

			c := &gossh.CertChecker{
				IsUserAuthority: func(auth gossh.PublicKey) bool {
					for _, k := range setting.SSH.TrustedUserCAKeysParsed {
						if bytes.Equal(auth.Marshal(), k.Marshal()) {
							return true
						}
					}

					return false
				},
			}

			// check the CA of the cert
			if !c.IsUserAuthority(cert.SignatureKey) {
				if log.IsDebug() {
					log.Debug("Principal Rejected: %s Untrusted Authority Signature Fingerprint %s for Principal: %s", ctx.RemoteAddr(), gossh.FingerprintSHA256(cert.SignatureKey), principal)
				}
				continue principalLoop
			}

			// validate the cert for this principal
			if err := c.CheckCert(principal, cert); err != nil {
				// User is presenting an invalid certificate - STOP any further processing
				if log.IsError() {
					log.Error("Invalid Certificate KeyID %s with Signature Fingerprint %s presented for Principal: %s from %s", cert.KeyId, gossh.FingerprintSHA256(cert.SignatureKey), principal, ctx.RemoteAddr())
				}
				log.Warn("Failed authentication attempt from %s", ctx.RemoteAddr())

				return false
			}

			if log.IsDebug() { // <- FingerprintSHA256 is kinda expensive so only calculate it if necessary
				log.Debug("Successfully authenticated: %s Certificate Fingerprint: %s Principal: %s", ctx.RemoteAddr(), gossh.FingerprintSHA256(key), principal)
			}
			ctx.SetValue(giteaKeyID, pkey.ID)

			return true
		}

		if log.IsWarn() {
			log.Warn("From %s Fingerprint: %s is a certificate, but no valid principals found", ctx.RemoteAddr(), gossh.FingerprintSHA256(key))
			log.Warn("Failed authentication attempt from %s", ctx.RemoteAddr())
		}
		return false
	}

	if log.IsDebug() { // <- FingerprintSHA256 is kinda expensive so only calculate it if necessary
		log.Debug("Handle Public Key: %s Fingerprint: %s is not a certificate", ctx.RemoteAddr(), gossh.FingerprintSHA256(key))
	}

	pkey, err := models.SearchPublicKeyByContent(strings.TrimSpace(string(gossh.MarshalAuthorizedKey(key))))
	if err != nil {
		if models.IsErrKeyNotExist(err) {
			if log.IsWarn() {
				log.Warn("Unknown public key: %s from %s", gossh.FingerprintSHA256(key), ctx.RemoteAddr())
				log.Warn("Failed authentication attempt from %s", ctx.RemoteAddr())
			}
			return false
		}
		log.Error("SearchPublicKeyByContent: %v", err)
		return false
	}

	if log.IsDebug() { // <- FingerprintSHA256 is kinda expensive so only calculate it if necessary
		log.Debug("Successfully authenticated: %s Public Key Fingerprint: %s", ctx.RemoteAddr(), gossh.FingerprintSHA256(key))
	}
	ctx.SetValue(giteaKeyID, pkey.ID)

	return true
}

// Listen starts a SSH server listens on given port.
func Listen(host string, port int, ciphers []string, keyExchanges []string, macs []string) {
	srv := ssh.Server{
		Addr:             fmt.Sprintf("%s:%d", host, port),
		PublicKeyHandler: publicKeyHandler,
		Handler:          sessionHandler,
		ServerConfigCallback: func(ctx ssh.Context) *gossh.ServerConfig {
			config := &gossh.ServerConfig{}
			config.KeyExchanges = keyExchanges
			config.MACs = macs
			config.Ciphers = ciphers
			return config
		},
		// We need to explicitly disable the PtyCallback so text displays
		// properly.
		PtyCallback: func(ctx ssh.Context, pty ssh.Pty) bool {
			return false
		},
	}

	keyPath := filepath.Join(setting.AppDataPath, "ssh/gogs.rsa")
	isExist, err := util.IsExist(keyPath)
	if err != nil {
		log.Fatal("Unable to check if %s exists. Error: %v", keyPath, err)
	}
	if !isExist {
		filePath := filepath.Dir(keyPath)

		if err := os.MkdirAll(filePath, os.ModePerm); err != nil {
			log.Error("Failed to create dir %s: %v", filePath, err)
		}

		err := GenKeyPair(keyPath)
		if err != nil {
			log.Fatal("Failed to generate private key: %v", err)
		}
		log.Trace("New private key is generated: %s", keyPath)
	}

	err = srv.SetOption(ssh.HostKeyFile(keyPath))
	if err != nil {
		log.Error("Failed to set Host Key. %s", err)
	}

	go listen(&srv)

}

// GenKeyPair make a pair of public and private keys for SSH access.
// Public key is encoded in the format for inclusion in an OpenSSH authorized_keys file.
// Private Key generated is PEM encoded
func GenKeyPair(keyPath string) error {
	privateKey, err := rsa.GenerateKey(rand.Reader, 2048)
	if err != nil {
		return err
	}

	privateKeyPEM := &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(privateKey)}
	f, err := os.OpenFile(keyPath, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600)
	if err != nil {
		return err
	}
	defer func() {
		if err = f.Close(); err != nil {
			log.Error("Close: %v", err)
		}
	}()

	if err := pem.Encode(f, privateKeyPEM); err != nil {
		return err
	}

	// generate public key
	pub, err := gossh.NewPublicKey(&privateKey.PublicKey)
	if err != nil {
		return err
	}

	public := gossh.MarshalAuthorizedKey(pub)
	p, err := os.OpenFile(keyPath+".pub", os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600)
	if err != nil {
		return err
	}
	defer func() {
		if err = p.Close(); err != nil {
			log.Error("Close: %v", err)
		}
	}()
	_, err = p.Write(public)
	return err
}
<|endoftext|>


<commit_before>package redis

import (
	"bufio"
	"fmt"
	"net"
	"strconv"
	"strings"
)

type Client interface {
	Send(s string) (n int, err error)
	RawReply() (resp []byte, err error)
	Reply() (resp interface{}, err error)
	Set(key, value []byte) (err error)
	Get(key string) (value []byte)
}

type client struct {
	Conn   net.Conn
	Writer *bufio.Writer
	Reader *bufio.Reader
}

func (c *client) Send(s string) (n int, err error) {
	n, err = c.Writer.WriteString(s)
	c.Writer.Flush()
	return
}

func (c *client) RawReply() ([]byte, error) {
	resp, err := c.Reader.ReadSlice('\n')
	if err != nil {
		return resp, err
	}
	symbol := resp[0] // +,-,:,$,*
	switch symbol {
	case '+', '-', ':':
		break
	case '$':
		line, _ := c.Reader.ReadSlice('\n')
		resp = append(resp, line...)
	case '*':
		d := strings.Trim(string(resp), "*\r\n")
		length, _ := strconv.Atoi(d)
		for i := 0; i < length; i++ {
			line, _ := c.RawReply()
			resp = append(resp, line...)
		}
	default:
		panic(fmt.Sprintf("Protocol Error: %s, %s", string(symbol), string(resp)))
	}
	return resp, err
}
func (c *client) Reply() (interface{}, error) {
	line, err := c.Reader.ReadSlice('\n')
	if err != nil {
		return nil, err
	}
	symbol, resp := line[0], line[1:len(line)-2] // trim first bit and CRLF
	switch symbol {
	case '+', '-':
		return string(resp), nil
	case ':':
		return strconv.Atoi(string(resp))
	case '$':
		length, _ := strconv.Atoi(string(resp))
		if length == -1 {
			return nil, nil
		} else {
			s, _ := c.Reader.ReadSlice('\n')
			return string(s[0 : len(s)-2]), nil
		}
	case '*':
		length, _ := strconv.Atoi(string(resp))
		if length == -1 {
			return nil, nil
		}
		reslt := make([]interface{}, 0)
		for i := 0; i < length; i++ {
			rep, _ := c.Reply()
			reslt = append(reslt, rep)
		}
		return reslt, nil
	default:
		panic(fmt.Sprintf("Protocol Error: %s, %s", string(symbol), string(resp)))
	}
}

func (c *client) Set(key, value []byte) (err error) {
	return nil
}

func (c *client) Get(key string) (value []byte) {
	//line, _ := c.br.ReadSlice('\n')
	return nil
}

func NewClient(network, address string) (cmd Client, err error) {
	conn, err := net.Dial(network, address)
	if err != nil {
		return nil, err
	}
	w := bufio.NewWriter(conn)
	rd := bufio.NewReader(conn)
	c := client{Conn: conn, Writer: w, Reader: rd}
	return Client(&c), nil
}
<commit_msg>Update redis/redis.go<commit_after>package redis

import (
	"bufio"
	"bytes"
	"fmt"
	"net"
	"strconv"
	"strings"
)

type Client interface {
	RESPStrings
	Send(s string) (n int, err error)
	Receive() (resp interface{}, err error)
	RawReceive() (resp []byte, err error)
	Close() (err error)
}

type client struct {
	conn net.Conn
	bw   *bufio.Writer
	br   *bufio.Reader
}

func (c *client) Send(s string) (n int, err error) {
	n, err = c.bw.WriteString(s)
	c.bw.Flush()
	return
}

func (c *client) Receive() (interface{}, error) {
	line, err := c.br.ReadSlice('\n')
	if err != nil {
		return nil, err
	}
	symbol, resp := line[0], line[1:len(line)-2] // trim first bit and CRLF
	switch symbol {
	case '+', '-':
		return string(resp), nil
	case ':':
		return strconv.Atoi(string(resp))
	case '$':
		length, _ := strconv.Atoi(string(resp))
		if length == -1 {
			return nil, nil
		} else {
			s, _ := c.br.ReadSlice('\n')
			return string(s[0 : len(s)-2]), nil
		}
	case '*':
		length, _ := strconv.Atoi(string(resp))
		if length == -1 {
			return nil, nil
		}
		reslt := make([]interface{}, 0)
		for i := 0; i < length; i++ {
			rep, _ := c.Receive()
			reslt = append(reslt, rep)
		}
		return reslt, nil
	default:
		panic(fmt.Sprintf("Protocol Error: %s, %s", string(symbol), string(resp)))
	}
}

func (c *client) RawReceive() ([]byte, error) {
	resp, err := c.br.ReadSlice('\n')
	if err != nil {
		return resp, err
	}
	symbol := resp[0] // +,-,:,$,*
	switch symbol {
	case '+', '-', ':':
		break
	case '$':
		line, _ := c.br.ReadSlice('\n')
		resp = append(resp, line...)
	case '*':
		d := strings.Trim(string(resp), "*\r\n")
		length, _ := strconv.Atoi(d)
		for i := 0; i < length; i++ {
			line, _ := c.RawReceive()
			resp = append(resp, line...)
		}
	default:
		panic(fmt.Sprintf("Protocol Error: %s, %s", string(symbol), string(resp)))
	}
	return resp, err
}

func (c *client) Close() (err error) {
	return c.conn.Close()
}

func (c *client) writeBytes(p []byte) error {
	err := c.writeHeader('$', int64(len(p)))
	if err != nil {
		return err
	}
	_, err = c.bw.Write(p)
	if err == nil {
		_, err = c.bw.Write([]byte{'\r', '\n'})
	}
	return err
}

//  2\r\n
func (c *client) writeInt(n int64) error {
	var p []byte
	p = strconv.AppendInt(p, n, 10)
	return c.writeBytes(p)
}

func (c *client) writeFloat(f float64) error {
	var p []byte
	p = strconv.AppendFloat(p, f, 'g', -1, 64)
	return c.writeBytes(p)
}

//  *2\r\n
func (c *client) writeHeader(symbol byte, n int64) error {
	err := c.bw.WriteByte(symbol)
	if err == nil {
		err = c.writeInt(n)
	}
	return err
}

//  LLEN\r\n
func (c *client) writeString(s string) error {
	return c.writeBytes([]byte(s))
}

func (c *client) executeCommand(commandName string, args ...interface{}) error {
	err := c.writeHeader('*', int64(1+len(args)))
	if err != nil {
		return nil
	}
	err = c.writeString(commandName)
	for _, arg := range args {
		if err != nil {
			break
		}
		switch arg.(type) {
		case string:
			err = c.writeString(arg.(string))
		case []byte:
			err = c.writeBytes(arg.([]byte))
		case int:
			err = c.writeInt(int64(arg.(int)))
		case float32:
			err = c.writeFloat(float64(arg.(float32)))
		case float64:
			err = c.writeFloat(arg.(float64))
		case bool:
			if arg.(bool) {
				err = c.writeString("1")
			} else {
				err = c.writeString("0")
			}
		case nil:
			err = c.writeString("")
		default:
			var buf bytes.Buffer
			fmt.Fprint(&buf, arg)
			err = c.writeBytes(buf.Bytes())
		}
	}
	return err
}

func (c *client) Get(key string) (value interface{}, err error) {
	err = c.executeCommand("GET", key)
	if err == nil {
		return c.Receive()
	}
	return nil, err
}

func NewClient(network, address string) (Client, error) {
	conn, err := net.Dial(network, address)
	if err != nil {
		return nil, err
	}
	w := bufio.NewWriter(conn)
	r := bufio.NewReader(conn)
	cli := client{conn: conn, bw: w, br: r}
	return Client(&cli), nil
}
<|endoftext|>


<commit_before>/*
Copyright 2015 The Kubernetes Authors All rights reserved.

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 e2e

import (
	"bufio"
	"fmt"
	"strings"
	"sync"

	"k8s.io/contrib/mungegithub/mungers/jenkins"
	"k8s.io/contrib/test-utils/utils"

	"github.com/golang/glog"
)

// BuildInfo tells the build ID and the build success
type BuildInfo struct {
	Status string
	ID     string
}

// E2ETester is the object which will contact a jenkins instance and get
// information about recent jobs
type E2ETester struct {
	JenkinsHost        string
	JobNames           []string
	WeakStableJobNames []string

	sync.Mutex
	BuildStatus map[string]BuildInfo // protect by mutex
}

func (e *E2ETester) locked(f func()) {
	e.Lock()
	defer e.Unlock()
	f()
}

// GetBuildStatus returns the build status. This map is a copy and is thus safe
// for the caller to use in any way.
func (e *E2ETester) GetBuildStatus() map[string]BuildInfo {
	e.Lock()
	defer e.Unlock()
	out := map[string]BuildInfo{}
	for k, v := range e.BuildStatus {
		out[k] = v
	}
	return out
}

func (e *E2ETester) setBuildStatus(build, status string, id string) {
	e.Lock()
	defer e.Unlock()
	e.BuildStatus[build] = BuildInfo{Status: status, ID: id}
}

// Stable is called to make sure all of the jenkins jobs are stable
func (e *E2ETester) Stable() bool {
	// Test if the build is stable in Jenkins
	jenkinsClient := &jenkins.JenkinsClient{Host: e.JenkinsHost}

	allStable := true
	for _, job := range e.JobNames {
		glog.V(2).Infof("Checking build stability for %s", job)
		build, err := jenkinsClient.GetLastCompletedBuild(job)
		if err != nil {
			glog.Errorf("Error checking job %v : %v", job, err)
			e.setBuildStatus(job, "Error checking: "+err.Error(), "0")
			allStable = false
			continue
		}
		if build.IsStable() {
			e.setBuildStatus(job, "Stable", build.ID)
		} else {
			e.setBuildStatus(job, "Not Stable", build.ID)
			allStable = false
		}
	}
	return allStable
}

const (
	expectedXMLHeader = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
)

// GCSBasedStable is a version of Stable function that depends on files stored in GCS instead of Jenkis
func (e *E2ETester) GCSBasedStable() bool {
	for _, job := range e.JobNames {
		lastBuildNumber, err := utils.GetLastestBuildNumberFromJenkinsGoogleBucket(job)
		glog.V(4).Infof("Checking status of %v, %v", job, lastBuildNumber)
		if err != nil {
			glog.Errorf("Error while getting data for %v: %v", job, err)
			continue
		}
		if stable, err := utils.CheckFinishedStatus(job, lastBuildNumber); !stable || err != nil {
			// TODO: decrese verbosity when we feel comfortable with this check.
			glog.Infof("Found unstable job: %v, build number: %v", job, lastBuildNumber)
			return false
		}
	}

	return true
}

// GCSWeakStable is a version of GCSBasedStable with a slightly relaxed condition.
// This function says that e2e's are unstable only if there were real test failures
// (i.e. there was a test that failed, so no timeouts/cluster startup failures counts),
// or test failed for any reason 3 times in a row.
func (e *E2ETester) GCSWeakStable() bool {
	for _, job := range e.WeakStableJobNames {
		lastBuildNumber, err := utils.GetLastestBuildNumberFromJenkinsGoogleBucket(job)
		glog.Infof("Checking status of %v, %v", job, lastBuildNumber)
		if err != nil {
			glog.Errorf("Error while getting data for %v: %v", job, err)
			continue
		}
		if stable, err := utils.CheckFinishedStatus(job, lastBuildNumber); stable && err == nil {
			continue
		}

		// If we're here it means that build failed, so we need to look for a reason
		// by iterating over junit_XX.xml files and look for failures
		i := 0
		for {
			i++
			path := fmt.Sprintf("artifacts/junit_%02d.xml", i)
			response, err := utils.GetFileFromJenkinsGoogleBucket(job, lastBuildNumber, path)
			if err != nil {
				glog.Errorf("Error while getting data for %v/%v/%v: %v", job, lastBuildNumber, path, err)
				continue
			}
			if response.StatusCode != 200 {
				break
			}
			defer response.Body.Close()
			reader := bufio.NewReader(response.Body)
			body, err := reader.ReadString('\n')
			if err != nil {
				glog.Errorf("Failed to read the response for %v/%v/%v: %v", job, lastBuildNumber, path, err)
				continue
			}
			if strings.TrimSpace(body) != expectedXMLHeader {
				glog.Errorf("Invalid header for %v/%v/%v: %v, expected %v", job, lastBuildNumber, path, body, expectedXMLHeader)
				continue
			}
			body, err = reader.ReadString('\n')
			if err != nil {
				glog.Errorf("Failed to read the response for %v/%v/%v: %v", job, lastBuildNumber, path, err)
				continue
			}
			numberOfTests := 0
			nubmerOfFailures := 0
			timestamp := 0.0
			fmt.Sscanf(strings.TrimSpace(body), "<testsuite tests=\"%d\" failures=\"%d\" time=\"%f\">", &numberOfTests, &nubmerOfFailures, &timestamp)
			glog.V(4).Infof("%v, numberOfTests: %v, numberOfFailures: %v", string(body), numberOfTests, nubmerOfFailures)
			if nubmerOfFailures > 0 {
				glog.V(4).Infof("Found failure in %v for job %v build number %v", path, job, lastBuildNumber)
				return false
			}
		}

		// If we're here it means that we weren't able to find a test that failed, which means that the reason of build failure is comming from the infrastructure
		// Check results of previous two builds.
		if stable, err := utils.CheckFinishedStatus(job, lastBuildNumber-1); !stable || err != nil {
			return false
		}
		if stable, err := utils.CheckFinishedStatus(job, lastBuildNumber-2); !stable || err != nil {
			return false
		}
	}
	return true
}
<commit_msg>Add even more logging to munger<commit_after>/*
Copyright 2015 The Kubernetes Authors All rights reserved.

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 e2e

import (
	"bufio"
	"fmt"
	"strings"
	"sync"

	"k8s.io/contrib/mungegithub/mungers/jenkins"
	"k8s.io/contrib/test-utils/utils"

	"github.com/golang/glog"
)

// BuildInfo tells the build ID and the build success
type BuildInfo struct {
	Status string
	ID     string
}

// E2ETester is the object which will contact a jenkins instance and get
// information about recent jobs
type E2ETester struct {
	JenkinsHost        string
	JobNames           []string
	WeakStableJobNames []string

	sync.Mutex
	BuildStatus map[string]BuildInfo // protect by mutex
}

func (e *E2ETester) locked(f func()) {
	e.Lock()
	defer e.Unlock()
	f()
}

// GetBuildStatus returns the build status. This map is a copy and is thus safe
// for the caller to use in any way.
func (e *E2ETester) GetBuildStatus() map[string]BuildInfo {
	e.Lock()
	defer e.Unlock()
	out := map[string]BuildInfo{}
	for k, v := range e.BuildStatus {
		out[k] = v
	}
	return out
}

func (e *E2ETester) setBuildStatus(build, status string, id string) {
	e.Lock()
	defer e.Unlock()
	e.BuildStatus[build] = BuildInfo{Status: status, ID: id}
}

// Stable is called to make sure all of the jenkins jobs are stable
func (e *E2ETester) Stable() bool {
	// Test if the build is stable in Jenkins
	jenkinsClient := &jenkins.JenkinsClient{Host: e.JenkinsHost}

	allStable := true
	for _, job := range e.JobNames {
		glog.V(2).Infof("Checking build stability for %s", job)
		build, err := jenkinsClient.GetLastCompletedBuild(job)
		if err != nil {
			glog.Errorf("Error checking job %v : %v", job, err)
			e.setBuildStatus(job, "Error checking: "+err.Error(), "0")
			allStable = false
			continue
		}
		if build.IsStable() {
			e.setBuildStatus(job, "Stable", build.ID)
		} else {
			e.setBuildStatus(job, "Not Stable", build.ID)
			glog.Infof("Jenkis based check for %v build %v returned false", job, build.ID)
			allStable = false
		}
	}
	return allStable
}

const (
	expectedXMLHeader = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
)

// GCSBasedStable is a version of Stable function that depends on files stored in GCS instead of Jenkis
func (e *E2ETester) GCSBasedStable() bool {
	for _, job := range e.JobNames {
		lastBuildNumber, err := utils.GetLastestBuildNumberFromJenkinsGoogleBucket(job)
		glog.V(4).Infof("Checking status of %v, %v", job, lastBuildNumber)
		if err != nil {
			glog.Errorf("Error while getting data for %v: %v", job, err)
			continue
		}
		if stable, err := utils.CheckFinishedStatus(job, lastBuildNumber); !stable || err != nil {
			// TODO: decrese verbosity when we feel comfortable with this check.
			glog.Infof("Found unstable job: %v, build number: %v", job, lastBuildNumber)
			return false
		}
	}

	return true
}

// GCSWeakStable is a version of GCSBasedStable with a slightly relaxed condition.
// This function says that e2e's are unstable only if there were real test failures
// (i.e. there was a test that failed, so no timeouts/cluster startup failures counts),
// or test failed for any reason 3 times in a row.
func (e *E2ETester) GCSWeakStable() bool {
	for _, job := range e.WeakStableJobNames {
		lastBuildNumber, err := utils.GetLastestBuildNumberFromJenkinsGoogleBucket(job)
		glog.Infof("Checking status of %v, %v", job, lastBuildNumber)
		if err != nil {
			glog.Errorf("Error while getting data for %v: %v", job, err)
			continue
		}
		if stable, err := utils.CheckFinishedStatus(job, lastBuildNumber); stable && err == nil {
			continue
		}

		// If we're here it means that build failed, so we need to look for a reason
		// by iterating over junit_XX.xml files and look for failures
		i := 0
		for {
			i++
			path := fmt.Sprintf("artifacts/junit_%02d.xml", i)
			response, err := utils.GetFileFromJenkinsGoogleBucket(job, lastBuildNumber, path)
			if err != nil {
				glog.Errorf("Error while getting data for %v/%v/%v: %v", job, lastBuildNumber, path, err)
				continue
			}
			if response.StatusCode != 200 {
				break
			}
			defer response.Body.Close()
			reader := bufio.NewReader(response.Body)
			body, err := reader.ReadString('\n')
			if err != nil {
				glog.Errorf("Failed to read the response for %v/%v/%v: %v", job, lastBuildNumber, path, err)
				continue
			}
			if strings.TrimSpace(body) != expectedXMLHeader {
				glog.Errorf("Invalid header for %v/%v/%v: %v, expected %v", job, lastBuildNumber, path, body, expectedXMLHeader)
				continue
			}
			body, err = reader.ReadString('\n')
			if err != nil {
				glog.Errorf("Failed to read the response for %v/%v/%v: %v", job, lastBuildNumber, path, err)
				continue
			}
			numberOfTests := 0
			nubmerOfFailures := 0
			timestamp := 0.0
			fmt.Sscanf(strings.TrimSpace(body), "<testsuite tests=\"%d\" failures=\"%d\" time=\"%f\">", &numberOfTests, &nubmerOfFailures, &timestamp)
			glog.V(4).Infof("%v, numberOfTests: %v, numberOfFailures: %v", string(body), numberOfTests, nubmerOfFailures)
			if nubmerOfFailures > 0 {
				glog.V(4).Infof("Found failure in %v for job %v build number %v", path, job, lastBuildNumber)
				return false
			}
		}

		// If we're here it means that we weren't able to find a test that failed, which means that the reason of build failure is comming from the infrastructure
		// Check results of previous two builds.
		if stable, err := utils.CheckFinishedStatus(job, lastBuildNumber-1); !stable || err != nil {
			return false
		}
		if stable, err := utils.CheckFinishedStatus(job, lastBuildNumber-2); !stable || err != nil {
			return false
		}
	}
	return true
}
<|endoftext|>


<commit_before>package ecs

import (
	"github.com/jagregory/cfval/constraints"
	. "github.com/jagregory/cfval/schema"
)

// see: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ecs-taskdefinition-containerdefinitions.html
var containerDefinition = NestedResource{
	Description: "EC2 Container Service TaskDefinition ContainerDefinition",

	Properties: Properties{
		"Command": Schema{
			Type: Multiple(ValueString),
		},

		"Cpu": Schema{
			Type: ValueNumber,
		},

		"EntryPoint": Schema{
			Type: Multiple(ValueString),
		},

		"Environment": Schema{
			Type: Multiple(containerDefinitionEnvironment),
		},

		"Essential": Schema{
			Type:     ValueBool,
			Required: constraints.Always,
		},

		"Image": Schema{
			Type:     ValueString,
			Required: constraints.Always,
		},

		"Links": Schema{
			Type: Multiple(ValueString),
		},

		"Memory": Schema{
			Type: Multiple(ValueString),
		},

		"MountPoints": Schema{
			Type:     Multiple(containerDefinitionMountPoint),
			Required: constraints.Always,
		},

		"Name": Schema{
			Type:     ValueString,
			Required: constraints.Always,
		},

		"PortMappings": Schema{
			Type: Multiple(containerDefinitionPortMapping),
		},

		"VolumesFrom": Schema{
			Type: Multiple(containerDefinitionVolumesFrom),
		},
	},
}
<commit_msg>Corrections to ContainerDefinition<commit_after>package ecs

import (
	"github.com/jagregory/cfval/constraints"
	. "github.com/jagregory/cfval/schema"
)

// see: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ecs-taskdefinition-containerdefinitions.html
var containerDefinition = NestedResource{
	Description: "EC2 Container Service TaskDefinition ContainerDefinition",

	Properties: Properties{
		"Command": Schema{
			Type: Multiple(ValueString),
		},

		"Cpu": Schema{
			Type: ValueNumber,
		},

		"EntryPoint": Schema{
			Type: Multiple(ValueString),
		},

		"Environment": Schema{
			Type: Multiple(containerDefinitionEnvironment),
		},

		"Essential": Schema{
			Type:     ValueBool,
			Required: constraints.Always,
		},

		"Image": Schema{
			Type:     ValueString,
			Required: constraints.Always,
		},

		"Links": Schema{
			Type: Multiple(ValueString),
		},

		"Memory": Schema{
			Type:     ValueNumber,
			Required: constraints.Always,
		},

		"MountPoints": Schema{
			Type: Multiple(containerDefinitionMountPoint),
		},

		"Name": Schema{
			Type:     ValueString,
			Required: constraints.Always,
		},

		"PortMappings": Schema{
			Type: Multiple(containerDefinitionPortMapping),
		},

		"VolumesFrom": Schema{
			Type: Multiple(containerDefinitionVolumesFrom),
		},
	},
}
<|endoftext|>


<commit_before>package models

import (
	"airdispat.ch/identity"
	"airdispat.ch/message"
	"airdispat.ch/routing"
	"airdispat.ch/server"
	"airdispat.ch/wire"
	"errors"
	"github.com/coopernurse/gorp"
	"strconv"
	"time"
)

type Selectable interface {
	Select(i interface{}, query string, args ...interface{}) ([]interface{}, error)
}

type Editable interface {
	Insert(list ...interface{}) error
	Update(list ...interface{}) (int64, error)
}

type Message struct {
	MessageId int
	Name      string
	From      string
	To        []string
	Timestamp int
}

func CreateMessage(db Editable, from string, to []string, comp []*Component) (*Message, error) {
	stamp := time.Now().Unix()
	msg := &Message{
		From:      from,
		To:        to,
		Timestamp: int(stamp),
	}

	err := db.Insert(msg)
	if err != nil {
		return nil, err
	}

	msg.Name = strconv.Itoa(msg.MessageId)
	_, err = db.Update(msg)
	if err != nil {
		return nil, err
	}

	for _, v := range comp {
		v.MessageId = msg.MessageId
		err := db.Insert(v)
		if err != nil {
			return nil, err
		}
	}

	return msg, nil
}

func (m *Message) ToDispatch(dbm *gorp.DbMap, to string) (*message.Mail, error) {
	legal := false
	for _, v := range m.To {
		if v == to {
			legal = true
			break
		}
	}
	if !legal {
		return nil, errors.New("Unable to find message for user.")
	}

	var components []*Component
	_, err := dbm.Select(&components, "select * from dispatch_components where messageid = $1", m.MessageId)
	if err != nil {
		return nil, err
	}

	fromAddr := identity.CreateAddressFromString(m.From)
	toAddr := identity.CreateAddressFromString(to)
	newMessage := message.CreateMail(fromAddr, toAddr)

	for _, v := range components {
		newMessage.Components.AddComponent(message.CreateComponent(v.Name, v.Data))
	}
	return newMessage, nil
}

func (m *Message) ToDescription(to string) (*server.MessageDescription, error) {
	// Location: "SERVER LOCATION"
	legal := false
	for _, v := range m.To {
		if v == to {
			legal = true
			break
		}
	}
	if !legal {
		return nil, errors.New("Unable to find user for that message.")
	}

	fromAddr := identity.CreateAddressFromString(m.From)
	toAddr := identity.CreateAddressFromString(to)
	return server.CreateMessageDescription(m.Name, "LOCATION", fromAddr, toAddr), nil
}

type Component struct {
	ComponentId int
	MessageId   int
	Name        string
	Data        []byte
}

type Alert struct {
	AlertId   int
	From      string
	To        string
	Timestamp int64
	Location  string
	Name      string
}

func CreateAlertFromDescription(desc *server.MessageDescription) *Alert {
	h := desc.Header()
	return &Alert{
		From:      h.From.String(),
		To:        h.To.String(),
		Timestamp: h.Timestamp,
		Location:  desc.Location,
		Name:      desc.Name,
	}
}

func (a *Alert) DownloadMessageFromAlert(db Selectable, r routing.Router) (*message.Mail, error) {
	addr, err := r.Lookup(a.From)
	if err != nil {
		return nil, err
	}

	sender := IdentityFromFingerprint(a.To, db)
	if sender == nil {
		return nil, errors.New("adsf")
	}

	msgDescription := server.CreateTransferMessage("testMessage", sender.Address, addr)

	data, messageType, h, err := message.SendMessageAndReceive(msgDescription, sender, addr)

	if messageType != wire.MailCode {
		return nil, errors.New("Unexpected message type.")
	}

	return message.CreateMailFromBytes(data, h)
}

func DownloadPublicMessages(since uint64, addr *identity.Address, from *identity.Identity) ([]*Alert, error) {
	t := server.CreateTransferMessageList(since, from.Address, addr)

	data, messageType, h, err := message.SendMessageAndReceive(t, from, addr)

	if messageType != wire.MessageListCode {
		return nil, errors.New("Unexpected message type.")
	}

	ml, err := server.CreateMessageListFromBytes(data, h)
	if err != nil {
		return nil, err
	}

	out := make([]*Alert, len(ml.Content))
	for i, v := range ml.Content {
		out[i] = CreateAlertFromDescription(v)
	}

	return out, nil
}
<commit_msg>Correctly Serialized To Addresses<commit_after>package models

import (
	"airdispat.ch/identity"
	"airdispat.ch/message"
	"airdispat.ch/routing"
	"airdispat.ch/server"
	"airdispat.ch/wire"
	"errors"
	"strconv"
	"strings"
	"time"
)

type Selectable interface {
	Select(i interface{}, query string, args ...interface{}) ([]interface{}, error)
}

type Editable interface {
	Insert(list ...interface{}) error
	Update(list ...interface{}) (int64, error)
}

type Message struct {
	MessageId int
	Name      string
	From      string
	To        string
	Timestamp int
}

func CreateMessage(db Editable, from string, to []string, comp []*Component) (*Message, error) {
	stamp := time.Now().Unix()
	msg := &Message{
		From:      from,
		To:        strings.Join(to, ","),
		Timestamp: int(stamp),
	}

	err := db.Insert(msg)
	if err != nil {
		return nil, err
	}

	msg.Name = strconv.Itoa(msg.MessageId)
	_, err = db.Update(msg)
	if err != nil {
		return nil, err
	}

	for _, v := range comp {
		v.MessageId = msg.MessageId
		err := db.Insert(v)
		if err != nil {
			return nil, err
		}
	}

	return msg, nil
}

func (m *Message) ToDispatch(dbm Selectable, to string) (*message.Mail, error) {
	legal := false
	for _, v := range strings.Split(m.To, ",") {
		if v == to {
			legal = true
			break
		}
	}
	if !legal {
		return nil, errors.New("Unable to find message for user.")
	}

	var components []*Component
	_, err := dbm.Select(&components, "select * from dispatch_components where messageid = $1", m.MessageId)
	if err != nil {
		return nil, err
	}

	fromAddr := identity.CreateAddressFromString(m.From)
	toAddr := identity.CreateAddressFromString(to)
	newMessage := message.CreateMail(fromAddr, toAddr, time.Unix(int64(m.Timestamp), 0))

	for _, v := range components {
		newMessage.Components.AddComponent(message.CreateComponent(v.Name, v.Data))
	}
	return newMessage, nil
}

func (m *Message) ToDescription(to string) (*server.MessageDescription, error) {
	// Location: "SERVER LOCATION"
	legal := false
	for _, v := range strings.Split(m.To, ",") {
		if v == to {
			legal = true
			break
		}
	}
	if !legal {
		return nil, errors.New("Unable to find user for that message.")
	}

	fromAddr := identity.CreateAddressFromString(m.From)
	toAddr := identity.CreateAddressFromString(to)
	return server.CreateMessageDescription(m.Name, "LOCATION", fromAddr, toAddr), nil
}

type Component struct {
	ComponentId int
	MessageId   int
	Name        string
	Data        []byte
}

type Alert struct {
	AlertId   int
	From      string
	To        string
	Timestamp int64
	Location  string
	Name      string
}

func CreateAlertFromDescription(desc *server.MessageDescription) *Alert {
	h := desc.Header()
	return &Alert{
		From:      h.From.String(),
		To:        h.To.String(),
		Timestamp: h.Timestamp,
		Location:  desc.Location,
		Name:      desc.Name,
	}
}

func (a *Alert) DownloadMessageFromAlert(db Selectable, r routing.Router) (*message.Mail, error) {
	addr, err := r.Lookup(a.From)
	if err != nil {
		return nil, err
	}

	sender := IdentityFromFingerprint(a.To, db)
	if sender == nil {
		return nil, errors.New("adsf")
	}

	msgDescription := server.CreateTransferMessage("testMessage", sender.Address, addr)

	data, messageType, h, err := message.SendMessageAndReceive(msgDescription, sender, addr)

	if messageType != wire.MailCode {
		return nil, errors.New("Unexpected message type.")
	}

	return message.CreateMailFromBytes(data, h)
}

func DownloadPublicMessages(since uint64, addr *identity.Address, from *identity.Identity) ([]*Alert, error) {
	t := server.CreateTransferMessageList(since, from.Address, addr)

	data, messageType, h, err := message.SendMessageAndReceive(t, from, addr)

	if messageType != wire.MessageListCode {
		return nil, errors.New("Unexpected message type.")
	}

	ml, err := server.CreateMessageListFromBytes(data, h)
	if err != nil {
		return nil, err
	}

	out := make([]*Alert, len(ml.Content))
	for i, v := range ml.Content {
		out[i] = CreateAlertFromDescription(v)
	}

	return out, nil
}
<|endoftext|>


<commit_before>// Copyright (c) 2017 The ivi developers. All rights reserved.
// Project site: https://github.com/gotmc/ivi
// Use of this source code is governed by a MIT-style license that
// can be found in the LICENSE.txt file for the project.

package agilente36xx

import "strings"

func (dcpwr *AgilentE36xx) InstrumentManufacturer() (string, error) {
	s, err := dcpwr.inst.Query("*IDN?\n")
	if err != nil {
		return "", err
	}
	ret := strings.Split(s, ",")
	return ret[0], nil
}
<commit_msg>Remove duplicate code in agilente36xx<commit_after><|endoftext|>


<commit_before>// package network implements micro network node
package network

import (
	"os"
	"strings"
	"time"

	"github.com/micro/cli"
	"github.com/micro/go-micro"
	"github.com/micro/go-micro/network"
	"github.com/micro/go-micro/network/handler"
	"github.com/micro/go-micro/network/resolver"
	"github.com/micro/go-micro/network/resolver/dns"
	"github.com/micro/go-micro/network/resolver/http"
	"github.com/micro/go-micro/network/resolver/registry"
	"github.com/micro/go-micro/proxy"
	"github.com/micro/go-micro/proxy/mucp"
	"github.com/micro/go-micro/router"
	"github.com/micro/go-micro/server"
	"github.com/micro/go-micro/tunnel"
	"github.com/micro/go-micro/util/log"
	"github.com/micro/go-micro/util/mux"
)

var (
	// Name of the network service
	Name = "go.micro.network"
	// Name of the micro network
	Network = "go.micro"
	// Address is the network address
	Address = ":8085"
	// Resolver is the network resolver
	Resolver = "registry"
)

// run runs the micro server
func run(ctx *cli.Context, srvOpts ...micro.Option) {
	// Init plugins
	for _, p := range Plugins() {
		p.Init(ctx)
	}

	if len(ctx.GlobalString("server_name")) > 0 {
		Name = ctx.GlobalString("server_name")
	}
	if len(ctx.String("address")) > 0 {
		Address = ctx.String("address")
	}
	if len(ctx.String("network")) > 0 {
		Network = ctx.String("network")
	}
	var nodes []string
	if len(ctx.String("node")) > 0 {
		nodes = strings.Split(ctx.String("node"), ",")
	}
	if len(ctx.String("resolver")) > 0 {
		Resolver = ctx.String("resolver")
	}
	var res resolver.Resolver
	switch Resolver {
	case "dns":
		res = &dns.Resolver{}
	case "http":
		res = &http.Resolver{}
	case "registry":
		res = &registry.Resolver{}
	}

	// Initialise service
	service := micro.NewService(
		micro.Name(Name),
		micro.RegisterTTL(time.Duration(ctx.GlobalInt("register_ttl"))*time.Second),
		micro.RegisterInterval(time.Duration(ctx.GlobalInt("register_interval"))*time.Second),
	)

	// create a tunnel
	tun := tunnel.NewTunnel(
		tunnel.Address(Address),
		tunnel.Nodes(nodes...),
	)

	// local tunnel router
	rtr := router.NewRouter(
		router.Network(Network),
		router.Id(service.Server().Options().Id),
		router.Registry(service.Client().Options().Registry),
	)

	// creaate new network
	net := network.NewNetwork(
		network.Id(service.Server().Options().Id),
		network.Name(Network),
		network.Address(Address),
		network.Nodes(nodes...),
		network.Tunnel(tun),
		network.Router(rtr),
		network.Resolver(res),
	)

	// local proxy
	prx := mucp.NewProxy(
		proxy.WithRouter(rtr),
		proxy.WithClient(service.Client()),
		proxy.WithLink("network", net.Client()),
	)

	// create a handler
	h := server.DefaultRouter.NewHandler(
		&handler.Network{
			Network: net,
		},
	)

	// register the handler
	server.DefaultRouter.Handle(h)

	// create a new muxer
	mux := mux.New(Name, prx)

	// init server
	service.Server().Init(
		server.WithRouter(mux),
	)

	// set network server to proxy
	net.Server().Init(
		server.WithRouter(mux),
	)

	// connect network
	if err := net.Connect(); err != nil {
		log.Logf("Network failed to connect: %v", err)
		os.Exit(1)
	}
	// close on exit
	defer net.Close()

	log.Logf("Network [%s] listening on %s", Name, Address)

	if err := service.Run(); err != nil {
		log.Logf("Network %s failed: %v", Name, err)
		net.Close()
		os.Exit(1)
	}
}

func Commands(options ...micro.Option) []cli.Command {
	command := cli.Command{
		Name:  "network",
		Usage: "Run the micro network node",
		Flags: []cli.Flag{
			cli.StringFlag{
				Name:   "address",
				Usage:  "Set the micro network address :8085",
				EnvVar: "MICRO_NETWORK_ADDRESS",
			},
			cli.StringFlag{
				Name:   "network",
				Usage:  "Set the micro network name: go.micro",
				EnvVar: "MICRO_NETWORK",
			},
			cli.StringFlag{
				Name:   "node",
				Usage:  "Set the micro network server node address. This can be a comma separated list.",
				EnvVar: "MICRO_NETWORK_NODE",
			},
			cli.StringFlag{
				Name:   "resolver",
				Usage:  "Set the micro network resolver. This can be a comma separated list.",
				EnvVar: "MICRO_NETWORK_RESOLVER",
			},
		},
		Action: func(ctx *cli.Context) {
			run(ctx, options...)
		},
	}

	for _, p := range Plugins() {
		if cmds := p.Commands(); len(cmds) > 0 {
			command.Subcommands = append(command.Subcommands, cmds...)
		}

		if flags := p.Flags(); len(flags) > 0 {
			command.Flags = append(command.Flags, flags...)
		}
	}

	return []cli.Command{command}
}
<commit_msg>Force kill network service after 1 second when net.Close blocks<commit_after>// package network implements micro network node
package network

import (
	"errors"
	"os"
	"strings"
	"time"

	"github.com/micro/cli"
	"github.com/micro/go-micro"
	"github.com/micro/go-micro/network"
	"github.com/micro/go-micro/network/handler"
	"github.com/micro/go-micro/network/resolver"
	"github.com/micro/go-micro/network/resolver/dns"
	"github.com/micro/go-micro/network/resolver/http"
	"github.com/micro/go-micro/network/resolver/registry"
	"github.com/micro/go-micro/proxy"
	"github.com/micro/go-micro/proxy/mucp"
	"github.com/micro/go-micro/router"
	"github.com/micro/go-micro/server"
	"github.com/micro/go-micro/tunnel"
	"github.com/micro/go-micro/util/log"
	"github.com/micro/go-micro/util/mux"
)

var (
	// Name of the network service
	Name = "go.micro.network"
	// Name of the micro network
	Network = "go.micro"
	// Address is the network address
	Address = ":8085"
	// Resolver is the network resolver
	Resolver = "registry"
)

// run runs the micro server
func run(ctx *cli.Context, srvOpts ...micro.Option) {
	// Init plugins
	for _, p := range Plugins() {
		p.Init(ctx)
	}

	if len(ctx.GlobalString("server_name")) > 0 {
		Name = ctx.GlobalString("server_name")
	}
	if len(ctx.String("address")) > 0 {
		Address = ctx.String("address")
	}
	if len(ctx.String("network")) > 0 {
		Network = ctx.String("network")
	}
	var nodes []string
	if len(ctx.String("node")) > 0 {
		nodes = strings.Split(ctx.String("node"), ",")
	}
	if len(ctx.String("resolver")) > 0 {
		Resolver = ctx.String("resolver")
	}
	var res resolver.Resolver
	switch Resolver {
	case "dns":
		res = &dns.Resolver{}
	case "http":
		res = &http.Resolver{}
	case "registry":
		res = &registry.Resolver{}
	}

	// Initialise service
	service := micro.NewService(
		micro.Name(Name),
		micro.RegisterTTL(time.Duration(ctx.GlobalInt("register_ttl"))*time.Second),
		micro.RegisterInterval(time.Duration(ctx.GlobalInt("register_interval"))*time.Second),
	)

	// create a tunnel
	tun := tunnel.NewTunnel(
		tunnel.Address(Address),
		tunnel.Nodes(nodes...),
	)

	// local tunnel router
	rtr := router.NewRouter(
		router.Network(Network),
		router.Id(service.Server().Options().Id),
		router.Registry(service.Client().Options().Registry),
	)

	// creaate new network
	net := network.NewNetwork(
		network.Id(service.Server().Options().Id),
		network.Name(Network),
		network.Address(Address),
		network.Nodes(nodes...),
		network.Tunnel(tun),
		network.Router(rtr),
		network.Resolver(res),
	)

	// local proxy
	prx := mucp.NewProxy(
		proxy.WithRouter(rtr),
		proxy.WithClient(service.Client()),
		proxy.WithLink("network", net.Client()),
	)

	// create a handler
	h := server.DefaultRouter.NewHandler(
		&handler.Network{
			Network: net,
		},
	)

	// register the handler
	server.DefaultRouter.Handle(h)

	// create a new muxer
	mux := mux.New(Name, prx)

	// init server
	service.Server().Init(
		server.WithRouter(mux),
	)

	// set network server to proxy
	net.Server().Init(
		server.WithRouter(mux),
	)

	// connect network
	if err := net.Connect(); err != nil {
		log.Logf("Network failed to connect: %v", err)
		os.Exit(1)
	}

	// netClose hard exits if we have problems
	netClose := func(net network.Network) error {
		errChan := make(chan error, 1)

		go func() {
			errChan <- net.Close()
		}()

		select {
		case err := <-errChan:
			return err
		case <-time.After(time.Second):
			return errors.New("Network timeout closing")
		}
	}

	log.Logf("Network [%s] listening on %s", Name, Address)

	if err := service.Run(); err != nil {
		log.Logf("Network %s failed: %v", Name, err)
		netClose(net)
		os.Exit(1)
	}

	// close the network
	netClose(net)
}

func Commands(options ...micro.Option) []cli.Command {
	command := cli.Command{
		Name:  "network",
		Usage: "Run the micro network node",
		Flags: []cli.Flag{
			cli.StringFlag{
				Name:   "address",
				Usage:  "Set the micro network address :8085",
				EnvVar: "MICRO_NETWORK_ADDRESS",
			},
			cli.StringFlag{
				Name:   "network",
				Usage:  "Set the micro network name: go.micro",
				EnvVar: "MICRO_NETWORK",
			},
			cli.StringFlag{
				Name:   "node",
				Usage:  "Set the micro network server node address. This can be a comma separated list.",
				EnvVar: "MICRO_NETWORK_NODE",
			},
			cli.StringFlag{
				Name:   "resolver",
				Usage:  "Set the micro network resolver. This can be a comma separated list.",
				EnvVar: "MICRO_NETWORK_RESOLVER",
			},
		},
		Action: func(ctx *cli.Context) {
			run(ctx, options...)
		},
	}

	for _, p := range Plugins() {
		if cmds := p.Commands(); len(cmds) > 0 {
			command.Subcommands = append(command.Subcommands, cmds...)
		}

		if flags := p.Flags(); len(flags) > 0 {
			command.Flags = append(command.Flags, flags...)
		}
	}

	return []cli.Command{command}
}
<|endoftext|>


<commit_before>package apidsl_test

import (
	. "github.com/goadesign/goa/design"
	. "github.com/goadesign/goa/design/apidsl"
	"github.com/goadesign/goa/dslengine"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

var _ = Describe("Metadata", func() {
	var name string
	var dt DataType
	var dsl func()
	var mtd *MediaTypeDefinition
	var api *APIDefinition
	var rd *ResourceDefinition
	var metadataKey string
	var metadataValue string

	BeforeEach(func() {
		InitDesign()
		dslengine.Errors = nil
		name = ""
		dsl = nil
		dt = nil
	})

	Context("with Metadata declaration", func() {
		JustBeforeEach(func() {
			api = API("Example API", func() {
				Metadata(metadataKey, metadataValue)
			})

			rd = Resource("Example Resource", func() {
				Metadata(metadataKey, metadataValue)
				Action("Example Action", func() {
					Metadata(metadataKey, metadataValue)
				})
				Response("Example Response", func() {
					Metadata(metadataKey, metadataValue)
				})
			})

			mtd = MediaType("Example MediaType", func() {
				Metadata(metadataKey, metadataValue)
				Attribute("Example Attribute", func() {
					Metadata(metadataKey, metadataValue)
				})
			})

			dslengine.Run()
		})

		Context("with blank metadata string", func() {
			BeforeEach(func() {
				metadataKey = ""
				metadataValue = ""
			})

			It("has metadata", func() {
				expected := dslengine.MetadataDefinition{"": []string{""}}
				Ω(api.Metadata).To(Equal(expected))
				Ω(rd.Metadata).To(Equal(expected))
				Ω(rd.Actions["Example Action"].Metadata).To(Equal(expected))
				Ω(rd.Responses["Example Response"].Metadata).To(Equal(expected))
				Ω(mtd.Metadata).To(Equal(expected))

				var mtdAttribute AttributeDefinition
				mtd.Type.ToObject().IterateAttributes(func(s string, ad *AttributeDefinition) error {
					mtdAttribute = *ad
					return nil
				})
				Ω(mtdAttribute.Metadata).To(Equal(expected))
			})
		})
		Context("with valid metadata string", func() {
			BeforeEach(func() {
				metadataKey = "struct:tag=json"
				metadataValue = "myName,omitempty"
			})

			It("has metadata", func() {
				expected := dslengine.MetadataDefinition{"struct:tag=json": []string{"myName,omitempty"}}
				Ω(api.Metadata).To(Equal(expected))
				Ω(rd.Metadata).To(Equal(expected))
				Ω(rd.Actions["Example Action"].Metadata).To(Equal(expected))
				Ω(rd.Responses["Example Response"].Metadata).To(Equal(expected))
				Ω(mtd.Metadata).To(Equal(expected))

				var mtdAttribute AttributeDefinition
				mtd.Type.ToObject().IterateAttributes(func(s string, ad *AttributeDefinition) error {
					mtdAttribute = *ad
					return nil
				})
				Ω(mtdAttribute.Metadata).To(Equal(expected))
			})
		})
		Context("with invalid metadata string", func() {
			BeforeEach(func() {
				metadataKey = "abc123一二三"
				metadataValue = "˜µ≤≈ç√"
			})

			It("has metadata", func() {
				expected := dslengine.MetadataDefinition{"abc123一二三": []string{"˜µ≤≈ç√"}}
				Ω(api.Metadata).To(Equal(expected))
				Ω(rd.Metadata).To(Equal(expected))
				Ω(rd.Actions["Example Action"].Metadata).To(Equal(expected))
				Ω(rd.Responses["Example Response"].Metadata).To(Equal(expected))
				Ω(mtd.Metadata).To(Equal(expected))

				var mtdAttribute AttributeDefinition
				mtd.Type.ToObject().IterateAttributes(func(s string, ad *AttributeDefinition) error {
					mtdAttribute = *ad
					return nil
				})
				Ω(mtdAttribute.Metadata).To(Equal(expected))
			})
		})

	})

	Context("with no Metadata declaration", func() {
		JustBeforeEach(func() {
			api = API("Example API", func() {})

			rd = Resource("Example Resource", func() {
				Action("Example Action", func() {
				})
				Response("Example Response", func() {
				})
			})

			mtd = MediaType("Example MediaType", func() {
				Attribute("Example Attribute", func() {
				})
			})

			dslengine.Run()
		})
		It("has no metadata", func() {
			Ω(api.Metadata).To(BeNil())
			Ω(rd.Metadata).To(BeNil())
			Ω(mtd.Metadata).To(BeNil())
			var mtdAttribute AttributeDefinition
			mtd.Type.ToObject().IterateAttributes(func(s string, ad *AttributeDefinition) error {
				mtdAttribute = *ad
				return nil
			})
			Ω(mtdAttribute.Metadata).To(BeNil())
		})
	})

})
<commit_msg>removed string type declaration<commit_after>package apidsl_test

import (
	. "github.com/goadesign/goa/design"
	. "github.com/goadesign/goa/design/apidsl"
	"github.com/goadesign/goa/dslengine"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

var _ = Describe("Metadata", func() {
	var name string
	var dt DataType
	var dsl func()
	var mtd *MediaTypeDefinition
	var api *APIDefinition
	var rd *ResourceDefinition
	var metadataKey string
	var metadataValue string

	BeforeEach(func() {
		InitDesign()
		dslengine.Errors = nil
		name = ""
		dsl = nil
		dt = nil
	})

	Context("with Metadata declaration", func() {
		JustBeforeEach(func() {
			api = API("Example API", func() {
				Metadata(metadataKey, metadataValue)
			})

			rd = Resource("Example Resource", func() {
				Metadata(metadataKey, metadataValue)
				Action("Example Action", func() {
					Metadata(metadataKey, metadataValue)
				})
				Response("Example Response", func() {
					Metadata(metadataKey, metadataValue)
				})
			})

			mtd = MediaType("Example MediaType", func() {
				Metadata(metadataKey, metadataValue)
				Attribute("Example Attribute", func() {
					Metadata(metadataKey, metadataValue)
				})
			})

			dslengine.Run()
		})

		Context("with blank metadata string", func() {
			BeforeEach(func() {
				metadataKey = ""
				metadataValue = ""
			})

			It("has metadata", func() {
				expected := dslengine.MetadataDefinition{"": {""}}
				Ω(api.Metadata).To(Equal(expected))
				Ω(rd.Metadata).To(Equal(expected))
				Ω(rd.Actions["Example Action"].Metadata).To(Equal(expected))
				Ω(rd.Responses["Example Response"].Metadata).To(Equal(expected))
				Ω(mtd.Metadata).To(Equal(expected))

				var mtdAttribute AttributeDefinition
				mtd.Type.ToObject().IterateAttributes(func(s string, ad *AttributeDefinition) error {
					mtdAttribute = *ad
					return nil
				})
				Ω(mtdAttribute.Metadata).To(Equal(expected))
			})
		})
		Context("with valid metadata string", func() {
			BeforeEach(func() {
				metadataKey = "struct:tag=json"
				metadataValue = "myName,omitempty"
			})

			It("has metadata", func() {
				expected := dslengine.MetadataDefinition{"struct:tag=json": {"myName,omitempty"}}
				Ω(api.Metadata).To(Equal(expected))
				Ω(rd.Metadata).To(Equal(expected))
				Ω(rd.Actions["Example Action"].Metadata).To(Equal(expected))
				Ω(rd.Responses["Example Response"].Metadata).To(Equal(expected))
				Ω(mtd.Metadata).To(Equal(expected))

				var mtdAttribute AttributeDefinition
				mtd.Type.ToObject().IterateAttributes(func(s string, ad *AttributeDefinition) error {
					mtdAttribute = *ad
					return nil
				})
				Ω(mtdAttribute.Metadata).To(Equal(expected))
			})
		})
		Context("with invalid metadata string", func() {
			BeforeEach(func() {
				metadataKey = "abc123一二三"
				metadataValue = "˜µ≤≈ç√"
			})

			It("has metadata", func() {
				expected := dslengine.MetadataDefinition{"abc123一二三": {"˜µ≤≈ç√"}}
				Ω(api.Metadata).To(Equal(expected))
				Ω(rd.Metadata).To(Equal(expected))
				Ω(rd.Actions["Example Action"].Metadata).To(Equal(expected))
				Ω(rd.Responses["Example Response"].Metadata).To(Equal(expected))
				Ω(mtd.Metadata).To(Equal(expected))

				var mtdAttribute AttributeDefinition
				mtd.Type.ToObject().IterateAttributes(func(s string, ad *AttributeDefinition) error {
					mtdAttribute = *ad
					return nil
				})
				Ω(mtdAttribute.Metadata).To(Equal(expected))
			})
		})

	})

	Context("with no Metadata declaration", func() {
		JustBeforeEach(func() {
			api = API("Example API", func() {})

			rd = Resource("Example Resource", func() {
				Action("Example Action", func() {
				})
				Response("Example Response", func() {
				})
			})

			mtd = MediaType("Example MediaType", func() {
				Attribute("Example Attribute", func() {
				})
			})

			dslengine.Run()
		})
		It("has no metadata", func() {
			Ω(api.Metadata).To(BeNil())
			Ω(rd.Metadata).To(BeNil())
			Ω(mtd.Metadata).To(BeNil())
			var mtdAttribute AttributeDefinition
			mtd.Type.ToObject().IterateAttributes(func(s string, ad *AttributeDefinition) error {
				mtdAttribute = *ad
				return nil
			})
			Ω(mtdAttribute.Metadata).To(BeNil())
		})
	})

})
<|endoftext|>