<commit_before>package aphgrpc

import (
	"fmt"
	"math"
	"net/http"
	"strings"
	"time"

	"gopkg.in/mgutz/dat.v2/dat"
	"gopkg.in/mgutz/dat.v2/sqlx-runner"

	"github.com/dictyBase/go-genproto/dictybaseapis/api/jsonapi"
	"github.com/fatih/structs"
	"github.com/golang/protobuf/proto"
	"github.com/golang/protobuf/ptypes"
	"github.com/golang/protobuf/ptypes/timestamp"
	"github.com/grpc-ecosystem/grpc-gateway/runtime"
	context "golang.org/x/net/context"
	"google.golang.org/grpc/metadata"
)

const (
	DefaultPagenum  int64 = 1
	DefaultPagesize int64 = 10
)

// JSONAPIParamsInfo interface should be implement by all grpc-gateway services
// that supports JSON API specifications.
type JSONAPIParamsInfo interface {
	// Relationships that could be included
	AllowedInclude() []string
	// Attribute fields that are allowed
	AllowedFields() []string
	// Filter fields that are allowed
	AllowedFilter() []string
	// FilterToColumns provides mapping between filter and storage columns
	FilterToColumns() map[string]string
	// RequiredAttrs are the mandatory attributes for creating a new resource
	RequiredAttrs() []string
}

// JSONAPIResource interface provides information about HTTP resource. All
// grpc-gateway services that supports JSONAPI should implement this interface.
type JSONAPIResource interface {
	//GetResourceName returns canonical resource name
	GetResourceName() string
	// GetBaseURL returns the base url with the scheme
	GetBaseURL() string
	// GetPrefix returns the path that could be appended to base url
	GetPathPrefix() string
}

func NullToTime(nt dat.NullTime) *timestamp.Timestamp {
	var ts *timestamp.Timestamp
	if nt.Valid {
		ts, _ := ptypes.TimestampProto(nt.Time)
		return ts
	}
	return ts
}

func ProtoTimeStamp(ts *timestamp.Timestamp) time.Time {
	t, _ := ptypes.Timestamp(ts)
	return t
}

func TimestampProto(t time.Time) *timestamp.Timestamp {
	ts, _ := ptypes.TimestampProto(t)
	return ts
}

func NullToString(s dat.NullString) string {
	if s.Valid {
		return s.String
	}
	return ""
}

func NullToInt64(i dat.NullInt64) int64 {
	if i.Valid {
		return i.Int64
	}
	var i64 int64
	return i64
}

// GetTotalPageNum calculate total no of pages from total no. records and page size
func GetTotalPageNum(record, pagesize int64) int64 {
	total := int64(math.Floor(float64(record) / float64(pagesize)))
	if math.Mod(float64(record), float64(pagesize)) > 0 {
		total += 1
	}
	return total
}

// GenPaginatedLinks generates paginated resource links
// from various page properties.
func GenPaginatedLinks(url string, lastpage, pagenum, pagesize int64) map[string]string {
	var links map[string]string
	links["self"] = AppendPaginationParams(url, pagenum, pagesize)
	links["first"] = AppendPaginationParams(url, 1, pagesize)
	if pagenum != 1 {
		links["previous"] = AppendPaginationParams(url, pagenum-1, pagesize)
	}
	links["last"] = AppendPaginationParams(url, lastpage, pagesize)
	if pagenum != lastpage {
		links["next"] = AppendPaginationParams(url, pagenum+1, pagesize)
	}
	return links
}

func GenBaseLink(rs JSONAPIResource) string {
	return fmt.Sprintf(
		"%s/%s",
		strings.Trim(rs.GetBaseURL(), "/"),
		strings.Trim(rs.GetPathPrefix(), "/"),
	)
}

func GenSingleResourceLink(rs JSONAPIResource, id int64) string {
	return fmt.Sprintf(
		"%s/%d",
		GenBaseLink(rs),
		id,
	)
}

func GenMultiResourceLink(rs JSONAPIResource) string {
	return fmt.Sprintf(
		"%s/%s",
		GenBaseLink(rs),
		rs.GetResourceName(),
	)
}

func AppendPaginationParams(url string, pagenum, pagesize int64) string {
	return fmt.Sprintf("%s?pagenum=%d&pagesize=%d", url, pagenum, pagesize)
}

func GenPaginatedResourceLink(rs JSONAPIResource, pagenum, pagesize int64) string {
	return fmt.Sprintf(
		"%s/%s?pagenum=%d&pagesize=%d",
		GenBaseLink(rs),
		rs.GetResourceName(),
		pagenum,
		pagesize,
	)
}

func GenSelfRelationshipLink(rs JSONAPIResource, rel string, id int64) string {
	return fmt.Sprintf(
		"%s/%s/%d/relationships/%s",
		GenBaseLink(rs),
		rs.GetResourceName(),
		id,
		rel,
	)
}

func GenRelatedRelationshipLink(rs JSONAPIResource, rel string, id int64) string {
	return fmt.Sprintf(
		"%s/%s/%d/%s",
		GenBaseLink(rs),
		rs.GetResourceName(),
		id,
		rel,
	)
}

//GetDefinedTagsWithValue check for fields that are initialized and returns a map
//with the tag and their values
func GetDefinedTagsWithValue(i interface{}, key string) map[string]interface{} {
	m := make(map[string]interface{})
	s := structs.New(i)
	for _, f := range s.Fields() {
		if !f.IsZero() {
			m[f.Tag(key)] = f.Value()
		}
	}
	return m
}

//GetDefinedTags check for fields that are initialized and returns a slice of
//their matching tag values
func GetDefinedTags(i interface{}, tag string) []string {
	var v []string
	s := structs.New(i)
	for _, f := range s.Fields() {
		if !f.IsZero() {
			v = append(v, f.Tag(tag))
		}
	}
	return v
}

// HandleCreateResponse modifies the grpc gateway filter which adds the JSON API header and
// modifies the http status response for POST request
func HandleCreateResponse(ctx context.Context, w http.ResponseWriter, resp proto.Message) error {
	w.Header().Set("Content-Type", "application/vnd.api+json")
	md, ok := runtime.ServerMetadataFromContext(ctx)
	if ok {
		trMD := md.TrailerMD
		if _, ok := trMD["method"]; ok {
			switch trMD["method"][0] {
			case "POST":
				w.WriteHeader(http.StatusCreated)
			case "POST_NO_CONTENT":
				w.WriteHeader(http.StatusNoContent)
			}
		}
	}
	return nil
}

type Service struct {
	Dbh             *runner.DB
	PathPrefix      string
	Include         []string
	IncludeStr      string
	FieldsToColumns map[string]string
	FieldsStr       string
	Resource        string
	BaseURL         string
	FilToColumns    map[string]string
	FilterStr       string
	Params          *JSONAPIParams
	ListMethod      bool
	ReqAttrs        []string
}

func (s *Service) RequiredAttrs() []string {
	return s.ReqAttrs
}

func (s *Service) IsListMethod() bool {
	return s.ListMethod
}

func (s *Service) FilterToColumns() map[string]string {
	return s.FilToColumns
}

func (s *Service) AllowedFilter() []string {
	var f []string
	for k, _ := range s.FilterToColumns() {
		f = append(f, k)
	}
	return f
}

func (s *Service) AllowedInclude() []string {
	return s.Include
}

func (s *Service) AllowedFields() []string {
	var f []string
	for k, _ := range s.FieldsToColumns {
		f = append(f, k)
	}
	return f
}

func (s *Service) GetResourceName() string {
	return s.Resource
}

func (s *Service) GetBaseURL() string {
	return s.BaseURL
}

func (s *Service) GetPathPrefix() string {
	return s.PathPrefix
}

func (s *Service) SetBaseURL(ctx context.Context) error {
	md, ok := metadata.FromIncomingContext(ctx)
	if !ok {
		return ErrRetrieveMetadata
	}
	slice, ok := md["x-forwarded-host"]
	if !ok {
		return ErrXForwardedHost
	}
	s.BaseURL = slice[0]
	return nil
}

func (s *Service) MapFieldsToColumns(fields []string) []string {
	var columns []string
	for _, v := range fields {
		columns = append(columns, s.FieldsToColumns[v])
	}
	return columns
}

func (s *Service) GetCount(table string) (int64, error) {
	var count int64
	err := s.Dbh.Select("COUNT(*)").From(table).QueryScalar(&count)
	return count, err
}

func (s *Service) GetAllFilteredCount(table string) (int64, error) {
	var count int64
	err := s.Dbh.Select("COUNT(*)").
		From(table).
		Scope(
			FilterToWhereClause(s, s.Params.Filters),
			FilterToBindValue(s.Params.Filters)...,
		).QueryScalar(&count)
	return count, err
}

// GetRelatedPagination generates JSONAPI pagination links for relation resources
func (s *Service) GetRelatedPagination(id, record, pagenum, pagesize int64, relation string) (*jsonapi.PaginationLinks, int64) {
	pages := GetTotalPageNum(record, pagesize)
	baseLink := s.GenCollResourceRelSelfLink(id, relation)
	pageLinks := GenPaginatedLinks(baseLink, pages, pagenum, pagesize)
	jsapiLinks := &jsonapi.PaginationLinks{
		Self:  pageLinks["self"],
		Last:  pageLinks["last"],
		First: pageLinks["first"],
	}
	if _, ok := pageLinks["previous"]; ok {
		jsapiLinks.Prev = pageLinks["previous"]
	}
	if _, ok := pageLinks["next"]; ok {
		jsapiLinks.Next = pageLinks["next"]
	}
	return jsapiLinks, pages
}

// GetPagination generates JSONAPI pagination links along with fields, include and filter query parameters
func (s *Service) GetPagination(record, pagenum, pagesize int64) (*jsonapi.PaginationLinks, int64) {
	pages := GetTotalPageNum(record, pagesize)
	baseLink := s.GenCollResourceSelfLink()
	pageLinks := GenPaginatedLinks(baseLink, pages, pagenum, pagesize)
	pageType := []string{"self", "last", "first", "previous", "next"}

	if s.Params != nil {
		params := s.Params
		switch {
		case params.HasFields && params.HasInclude && params.HasFilter:
			for _, v := range pageType {
				if _, ok := pageLinks[v]; ok {
					pageLinks[v] += fmt.Sprintf("&fields=%s&include=%s&filter=%s", s.FieldsStr, s.IncludeStr, s.FilterStr)
				}
			}
		case params.HasFields && params.HasInclude:
			for _, v := range pageType {
				if _, ok := pageLinks[v]; ok {
					pageLinks[v] += fmt.Sprintf("&fields=%s&include=%s", s.FieldsStr, s.IncludeStr)
				}
			}
		case params.HasFields && params.HasFilter:
			for _, v := range pageType {
				if _, ok := pageLinks[v]; ok {
					pageLinks[v] += fmt.Sprintf("&fields=%s&filter=%s", s.FieldsStr, s.FilterStr)
				}
			}
		case params.HasInclude && params.HasFilter:
			for _, v := range pageType {
				if _, ok := pageLinks[v]; ok {
					pageLinks[v] += fmt.Sprintf("&include=%s&filter=%s", s.IncludeStr, s.FilterStr)
				}
			}
		case params.HasInclude:
			for _, v := range pageType {
				if _, ok := pageLinks[v]; ok {
					pageLinks[v] += fmt.Sprintf("&include=%s", s.IncludeStr)
				}
			}
		case params.HasFilter:
			for _, v := range pageType {
				if _, ok := pageLinks[v]; ok {
					pageLinks[v] += fmt.Sprintf("&filter=%s", s.FilterStr)
				}
			}
		case params.HasFields:
			for _, v := range pageType {
				if _, ok := pageLinks[v]; ok {
					pageLinks[v] += fmt.Sprintf("&fields=%s", s.FieldsStr)
				}
			}
		}
	}
	jsapiLinks := &jsonapi.PaginationLinks{
		Self:  pageLinks["self"],
		Last:  pageLinks["last"],
		First: pageLinks["first"],
	}
	if _, ok := pageLinks["previous"]; ok {
		jsapiLinks.Prev = pageLinks["previous"]
	}
	if _, ok := pageLinks["next"]; ok {
		jsapiLinks.Next = pageLinks["next"]
	}
	return jsapiLinks, pages
}

func (s *Service) GenCollResourceRelSelfLink(id int64, relation string) string {
	return fmt.Sprintf(
		"%s/%d/%s",
		GenMultiResourceLink(s),
		id,
		relation,
	)
}

func (s *Service) GenCollResourceSelfLink() string {
	link := GenMultiResourceLink(s)
	if s.Params == nil {
		return link
	}
	params := s.Params
	switch {
	case params.HasFields && params.HasFilter && params.HasInclude:
		link += fmt.Sprintf("?fields=%s&include=%s&filter=%s", s.FieldsStr, s.IncludeStr, s.FilterStr)
	case params.HasFields && params.HasFilter:
		link += fmt.Sprintf("?fields=%s&filter=%s", s.FieldsStr, s.FilterStr)
	case params.HasFields && params.HasInclude:
		link += fmt.Sprintf("?fields=%s&include=%s", s.FieldsStr, s.IncludeStr)
	case params.HasFilter && params.HasInclude:
		link += fmt.Sprintf("?filter=%s&include=%s", s.FilterStr, s.IncludeStr)
	case params.HasInclude:
		link += fmt.Sprintf("?include=%s", s.IncludeStr)
	case params.HasFilter:
		link += fmt.Sprintf("?filter=%s", s.FilterStr)
	case params.HasFields:
		link += fmt.Sprintf("?fields=%s", s.FieldsStr)
	}
	return link
}

func (s *Service) GenResourceSelfLink(id int64) string {
	links := GenSingleResourceLink(s, id)
	if !s.IsListMethod() && s.Params != nil {
		params := s.Params
		switch {
		case params.HasFields && params.HasInclude:
			links += fmt.Sprintf("?fields=%s&include=%s", s.FieldsStr, s.IncludeStr)
		case params.HasFields:
			links += fmt.Sprintf("?fields=%s", s.FieldsStr)
		case params.HasInclude:
			links += fmt.Sprintf("?include=%s", s.IncludeStr)
		}
	}
	return links
}
<commit_msg>Added http prefix for the host name<commit_after>package aphgrpc

import (
	"fmt"
	"math"
	"net/http"
	"strings"
	"time"

	"gopkg.in/mgutz/dat.v2/dat"
	"gopkg.in/mgutz/dat.v2/sqlx-runner"

	"github.com/dictyBase/go-genproto/dictybaseapis/api/jsonapi"
	"github.com/fatih/structs"
	"github.com/golang/protobuf/proto"
	"github.com/golang/protobuf/ptypes"
	"github.com/golang/protobuf/ptypes/timestamp"
	"github.com/grpc-ecosystem/grpc-gateway/runtime"
	context "golang.org/x/net/context"
	"google.golang.org/grpc/metadata"
)

const (
	DefaultPagenum  int64 = 1
	DefaultPagesize int64 = 10
)

// JSONAPIParamsInfo interface should be implement by all grpc-gateway services
// that supports JSON API specifications.
type JSONAPIParamsInfo interface {
	// Relationships that could be included
	AllowedInclude() []string
	// Attribute fields that are allowed
	AllowedFields() []string
	// Filter fields that are allowed
	AllowedFilter() []string
	// FilterToColumns provides mapping between filter and storage columns
	FilterToColumns() map[string]string
	// RequiredAttrs are the mandatory attributes for creating a new resource
	RequiredAttrs() []string
}

// JSONAPIResource interface provides information about HTTP resource. All
// grpc-gateway services that supports JSONAPI should implement this interface.
type JSONAPIResource interface {
	//GetResourceName returns canonical resource name
	GetResourceName() string
	// GetBaseURL returns the base url with the scheme
	GetBaseURL() string
	// GetPrefix returns the path that could be appended to base url
	GetPathPrefix() string
}

func NullToTime(nt dat.NullTime) *timestamp.Timestamp {
	var ts *timestamp.Timestamp
	if nt.Valid {
		ts, _ := ptypes.TimestampProto(nt.Time)
		return ts
	}
	return ts
}

func ProtoTimeStamp(ts *timestamp.Timestamp) time.Time {
	t, _ := ptypes.Timestamp(ts)
	return t
}

func TimestampProto(t time.Time) *timestamp.Timestamp {
	ts, _ := ptypes.TimestampProto(t)
	return ts
}

func NullToString(s dat.NullString) string {
	if s.Valid {
		return s.String
	}
	return ""
}

func NullToInt64(i dat.NullInt64) int64 {
	if i.Valid {
		return i.Int64
	}
	var i64 int64
	return i64
}

// GetTotalPageNum calculate total no of pages from total no. records and page size
func GetTotalPageNum(record, pagesize int64) int64 {
	total := int64(math.Floor(float64(record) / float64(pagesize)))
	if math.Mod(float64(record), float64(pagesize)) > 0 {
		total += 1
	}
	return total
}

// GenPaginatedLinks generates paginated resource links
// from various page properties.
func GenPaginatedLinks(url string, lastpage, pagenum, pagesize int64) map[string]string {
	var links map[string]string
	links["self"] = AppendPaginationParams(url, pagenum, pagesize)
	links["first"] = AppendPaginationParams(url, 1, pagesize)
	if pagenum != 1 {
		links["previous"] = AppendPaginationParams(url, pagenum-1, pagesize)
	}
	links["last"] = AppendPaginationParams(url, lastpage, pagesize)
	if pagenum != lastpage {
		links["next"] = AppendPaginationParams(url, pagenum+1, pagesize)
	}
	return links
}

func GenBaseLink(rs JSONAPIResource) string {
	return fmt.Sprintf(
		"%s/%s",
		strings.Trim(rs.GetBaseURL(), "/"),
		strings.Trim(rs.GetPathPrefix(), "/"),
	)
}

func GenSingleResourceLink(rs JSONAPIResource, id int64) string {
	return fmt.Sprintf(
		"%s/%d",
		GenBaseLink(rs),
		id,
	)
}

func GenMultiResourceLink(rs JSONAPIResource) string {
	return fmt.Sprintf(
		"%s/%s",
		GenBaseLink(rs),
		rs.GetResourceName(),
	)
}

func AppendPaginationParams(url string, pagenum, pagesize int64) string {
	return fmt.Sprintf("%s?pagenum=%d&pagesize=%d", url, pagenum, pagesize)
}

func GenPaginatedResourceLink(rs JSONAPIResource, pagenum, pagesize int64) string {
	return fmt.Sprintf(
		"%s/%s?pagenum=%d&pagesize=%d",
		GenBaseLink(rs),
		rs.GetResourceName(),
		pagenum,
		pagesize,
	)
}

func GenSelfRelationshipLink(rs JSONAPIResource, rel string, id int64) string {
	return fmt.Sprintf(
		"%s/%s/%d/relationships/%s",
		GenBaseLink(rs),
		rs.GetResourceName(),
		id,
		rel,
	)
}

func GenRelatedRelationshipLink(rs JSONAPIResource, rel string, id int64) string {
	return fmt.Sprintf(
		"%s/%s/%d/%s",
		GenBaseLink(rs),
		rs.GetResourceName(),
		id,
		rel,
	)
}

//GetDefinedTagsWithValue check for fields that are initialized and returns a map
//with the tag and their values
func GetDefinedTagsWithValue(i interface{}, key string) map[string]interface{} {
	m := make(map[string]interface{})
	s := structs.New(i)
	for _, f := range s.Fields() {
		if !f.IsZero() {
			m[f.Tag(key)] = f.Value()
		}
	}
	return m
}

//GetDefinedTags check for fields that are initialized and returns a slice of
//their matching tag values
func GetDefinedTags(i interface{}, tag string) []string {
	var v []string
	s := structs.New(i)
	for _, f := range s.Fields() {
		if !f.IsZero() {
			v = append(v, f.Tag(tag))
		}
	}
	return v
}

// HandleCreateResponse modifies the grpc gateway filter which adds the JSON API header and
// modifies the http status response for POST request
func HandleCreateResponse(ctx context.Context, w http.ResponseWriter, resp proto.Message) error {
	w.Header().Set("Content-Type", "application/vnd.api+json")
	md, ok := runtime.ServerMetadataFromContext(ctx)
	if ok {
		trMD := md.TrailerMD
		if _, ok := trMD["method"]; ok {
			switch trMD["method"][0] {
			case "POST":
				w.WriteHeader(http.StatusCreated)
			case "POST_NO_CONTENT":
				w.WriteHeader(http.StatusNoContent)
			}
		}
	}
	return nil
}

type Service struct {
	Dbh             *runner.DB
	PathPrefix      string
	Include         []string
	IncludeStr      string
	FieldsToColumns map[string]string
	FieldsStr       string
	Resource        string
	BaseURL         string
	FilToColumns    map[string]string
	FilterStr       string
	Params          *JSONAPIParams
	ListMethod      bool
	ReqAttrs        []string
}

func (s *Service) RequiredAttrs() []string {
	return s.ReqAttrs
}

func (s *Service) IsListMethod() bool {
	return s.ListMethod
}

func (s *Service) FilterToColumns() map[string]string {
	return s.FilToColumns
}

func (s *Service) AllowedFilter() []string {
	var f []string
	for k, _ := range s.FilterToColumns() {
		f = append(f, k)
	}
	return f
}

func (s *Service) AllowedInclude() []string {
	return s.Include
}

func (s *Service) AllowedFields() []string {
	var f []string
	for k, _ := range s.FieldsToColumns {
		f = append(f, k)
	}
	return f
}

func (s *Service) GetResourceName() string {
	return s.Resource
}

func (s *Service) GetBaseURL() string {
	return s.BaseURL
}

func (s *Service) GetPathPrefix() string {
	return s.PathPrefix
}

func (s *Service) SetBaseURL(ctx context.Context) error {
	md, ok := metadata.FromIncomingContext(ctx)
	if !ok {
		return ErrRetrieveMetadata
	}
	slice, ok := md["x-forwarded-host"]
	if !ok {
		return ErrXForwardedHost
	}
	s.BaseURL = fmt.Sprintf("http://%s", slice[0])
	return nil
}

func (s *Service) MapFieldsToColumns(fields []string) []string {
	var columns []string
	for _, v := range fields {
		columns = append(columns, s.FieldsToColumns[v])
	}
	return columns
}

func (s *Service) GetCount(table string) (int64, error) {
	var count int64
	err := s.Dbh.Select("COUNT(*)").From(table).QueryScalar(&count)
	return count, err
}

func (s *Service) GetAllFilteredCount(table string) (int64, error) {
	var count int64
	err := s.Dbh.Select("COUNT(*)").
		From(table).
		Scope(
			FilterToWhereClause(s, s.Params.Filters),
			FilterToBindValue(s.Params.Filters)...,
		).QueryScalar(&count)
	return count, err
}

// GetRelatedPagination generates JSONAPI pagination links for relation resources
func (s *Service) GetRelatedPagination(id, record, pagenum, pagesize int64, relation string) (*jsonapi.PaginationLinks, int64) {
	pages := GetTotalPageNum(record, pagesize)
	baseLink := s.GenCollResourceRelSelfLink(id, relation)
	pageLinks := GenPaginatedLinks(baseLink, pages, pagenum, pagesize)
	jsapiLinks := &jsonapi.PaginationLinks{
		Self:  pageLinks["self"],
		Last:  pageLinks["last"],
		First: pageLinks["first"],
	}
	if _, ok := pageLinks["previous"]; ok {
		jsapiLinks.Prev = pageLinks["previous"]
	}
	if _, ok := pageLinks["next"]; ok {
		jsapiLinks.Next = pageLinks["next"]
	}
	return jsapiLinks, pages
}

// GetPagination generates JSONAPI pagination links along with fields, include and filter query parameters
func (s *Service) GetPagination(record, pagenum, pagesize int64) (*jsonapi.PaginationLinks, int64) {
	pages := GetTotalPageNum(record, pagesize)
	baseLink := s.GenCollResourceSelfLink()
	pageLinks := GenPaginatedLinks(baseLink, pages, pagenum, pagesize)
	pageType := []string{"self", "last", "first", "previous", "next"}

	if s.Params != nil {
		params := s.Params
		switch {
		case params.HasFields && params.HasInclude && params.HasFilter:
			for _, v := range pageType {
				if _, ok := pageLinks[v]; ok {
					pageLinks[v] += fmt.Sprintf("&fields=%s&include=%s&filter=%s", s.FieldsStr, s.IncludeStr, s.FilterStr)
				}
			}
		case params.HasFields && params.HasInclude:
			for _, v := range pageType {
				if _, ok := pageLinks[v]; ok {
					pageLinks[v] += fmt.Sprintf("&fields=%s&include=%s", s.FieldsStr, s.IncludeStr)
				}
			}
		case params.HasFields && params.HasFilter:
			for _, v := range pageType {
				if _, ok := pageLinks[v]; ok {
					pageLinks[v] += fmt.Sprintf("&fields=%s&filter=%s", s.FieldsStr, s.FilterStr)
				}
			}
		case params.HasInclude && params.HasFilter:
			for _, v := range pageType {
				if _, ok := pageLinks[v]; ok {
					pageLinks[v] += fmt.Sprintf("&include=%s&filter=%s", s.IncludeStr, s.FilterStr)
				}
			}
		case params.HasInclude:
			for _, v := range pageType {
				if _, ok := pageLinks[v]; ok {
					pageLinks[v] += fmt.Sprintf("&include=%s", s.IncludeStr)
				}
			}
		case params.HasFilter:
			for _, v := range pageType {
				if _, ok := pageLinks[v]; ok {
					pageLinks[v] += fmt.Sprintf("&filter=%s", s.FilterStr)
				}
			}
		case params.HasFields:
			for _, v := range pageType {
				if _, ok := pageLinks[v]; ok {
					pageLinks[v] += fmt.Sprintf("&fields=%s", s.FieldsStr)
				}
			}
		}
	}
	jsapiLinks := &jsonapi.PaginationLinks{
		Self:  pageLinks["self"],
		Last:  pageLinks["last"],
		First: pageLinks["first"],
	}
	if _, ok := pageLinks["previous"]; ok {
		jsapiLinks.Prev = pageLinks["previous"]
	}
	if _, ok := pageLinks["next"]; ok {
		jsapiLinks.Next = pageLinks["next"]
	}
	return jsapiLinks, pages
}

func (s *Service) GenCollResourceRelSelfLink(id int64, relation string) string {
	return fmt.Sprintf(
		"%s/%d/%s",
		GenMultiResourceLink(s),
		id,
		relation,
	)
}

func (s *Service) GenCollResourceSelfLink() string {
	link := GenMultiResourceLink(s)
	if s.Params == nil {
		return link
	}
	params := s.Params
	switch {
	case params.HasFields && params.HasFilter && params.HasInclude:
		link += fmt.Sprintf("?fields=%s&include=%s&filter=%s", s.FieldsStr, s.IncludeStr, s.FilterStr)
	case params.HasFields && params.HasFilter:
		link += fmt.Sprintf("?fields=%s&filter=%s", s.FieldsStr, s.FilterStr)
	case params.HasFields && params.HasInclude:
		link += fmt.Sprintf("?fields=%s&include=%s", s.FieldsStr, s.IncludeStr)
	case params.HasFilter && params.HasInclude:
		link += fmt.Sprintf("?filter=%s&include=%s", s.FilterStr, s.IncludeStr)
	case params.HasInclude:
		link += fmt.Sprintf("?include=%s", s.IncludeStr)
	case params.HasFilter:
		link += fmt.Sprintf("?filter=%s", s.FilterStr)
	case params.HasFields:
		link += fmt.Sprintf("?fields=%s", s.FieldsStr)
	}
	return link
}

func (s *Service) GenResourceSelfLink(id int64) string {
	links := GenSingleResourceLink(s, id)
	if !s.IsListMethod() && s.Params != nil {
		params := s.Params
		switch {
		case params.HasFields && params.HasInclude:
			links += fmt.Sprintf("?fields=%s&include=%s", s.FieldsStr, s.IncludeStr)
		case params.HasFields:
			links += fmt.Sprintf("?fields=%s", s.FieldsStr)
		case params.HasInclude:
			links += fmt.Sprintf("?include=%s", s.IncludeStr)
		}
	}
	return links
}
<|endoftext|>


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

// Package starter provides a single function that starts up servers for a
// mounttable and a device manager that is mounted on it.
package starter

import (
	"encoding/base64"
	"os"
	"path/filepath"
	"time"

	"v.io/v23"
	"v.io/v23/context"
	"v.io/v23/naming"
	"v.io/v23/rpc"
	"v.io/v23/security"
	"v.io/v23/verror"
	displib "v.io/x/ref/lib/dispatcher"
	_ "v.io/x/ref/runtime/factories/roaming"
	"v.io/x/ref/services/debug/debuglib"
	"v.io/x/ref/services/device/deviced/internal/impl"
	"v.io/x/ref/services/device/deviced/internal/versioning"
	"v.io/x/ref/services/device/internal/claim"
	"v.io/x/ref/services/device/internal/config"
	"v.io/x/ref/services/internal/pathperms"
	"v.io/x/ref/services/mounttable/mounttablelib"
)

const pkgPath = "v.io/x/ref/services/device/deviced/internal/starter"

var (
	errCantSaveInfo = verror.Register(pkgPath+".errCantSaveInfo", verror.NoRetry, "{1:}{2:} failed to save info{:_}")
)

type NamespaceArgs struct {
	Name            string         // Name to publish the mounttable service under (after claiming).
	ListenSpec      rpc.ListenSpec // ListenSpec for the server.
	PermissionsFile string         // Path to the Permissions file used by the mounttable.
	PersistenceDir  string         // Path to the directory holding persistent acls.
	// Name in the local neighborhood on which to make the mounttable
	// visible. If empty, the mounttable will not be visible in the local
	// neighborhood.
	Neighborhood string
}

type DeviceArgs struct {
	Name            string         // Name to publish the device service under (after claiming).
	ListenSpec      rpc.ListenSpec // ListenSpec for the device server.
	ConfigState     *config.State  // Configuration for the device.
	TestMode        bool           // Whether the device is running in test mode or not.
	RestartCallback func()         // Callback invoked when the device service is restarted.
	PairingToken    string         // PairingToken that a claimer needs to provide.
}

func (d *DeviceArgs) name(mt string) string {
	if d.Name != "" {
		return d.Name
	}
	return naming.Join(mt, "devmgr")
}

type Args struct {
	Namespace NamespaceArgs
	Device    DeviceArgs

	// If true, the global namespace will be made available on the
	// mounttable server under "global/".
	MountGlobalNamespaceInLocalNamespace bool
}

// Start creates servers for the mounttable and device services and links them together.
//
// Returns the endpoints for the claimable service (empty if already claimed),
// a callback to be invoked to shutdown the services on success, or an error on
// failure.
func Start(ctx *context.T, args Args) ([]naming.Endpoint, func(), error) {
	// Is this binary compatible with the state on disk?
	if err := versioning.CheckCompatibility(ctx, args.Device.ConfigState.Root); err != nil {
		return nil, nil, err
	}
	// In test mode, we skip writing the info file to disk, and we skip
	// attempting to start the claimable service: the device must have been
	// claimed already to enable updates anyway, and checking for perms in
	// NewClaimableDispatcher needlessly prints a perms signature
	// verification error to the logs.
	if args.Device.TestMode {
		cleanup, err := startClaimedDevice(ctx, args)
		return nil, cleanup, err
	}

	// TODO(caprita): use some mechanism (a file lock or presence of entry
	// in mounttable) to ensure only one device manager is running in an
	// installation?
	mi := &impl.ManagerInfo{
		Pid: os.Getpid(),
	}
	if err := impl.SaveManagerInfo(filepath.Join(args.Device.ConfigState.Root, "device-manager"), mi); err != nil {
		return nil, nil, verror.New(errCantSaveInfo, ctx, err)
	}

	// If the device has not yet been claimed, start the mounttable and
	// claimable service and wait for it to be claimed.
	// Once a device is claimed, close any previously running servers and
	// start a new mounttable and device service.
	claimable, claimed := claim.NewClaimableDispatcher(ctx, impl.PermsDir(args.Device.ConfigState), args.Device.PairingToken, security.AllowEveryone())
	if claimable == nil {
		// Device has already been claimed, bypass claimable service
		// stage.
		cleanup, err := startClaimedDevice(ctx, args)
		return nil, cleanup, err
	}
	eps, stopClaimable, err := startClaimableDevice(ctx, claimable, args)
	if err != nil {
		return nil, nil, err
	}
	stop := make(chan struct{})
	stopped := make(chan struct{})
	go waitToBeClaimedAndStartClaimedDevice(ctx, stopClaimable, claimed, stop, stopped, args)
	return eps, func() {
		close(stop)
		<-stopped
	}, nil
}

func startClaimableDevice(ctx *context.T, dispatcher rpc.Dispatcher, args Args) ([]naming.Endpoint, func(), error) {
	ctx, cancel := context.WithCancel(ctx)
	ctx = v23.WithListenSpec(ctx, args.Device.ListenSpec)
	ctx, server, err := v23.WithNewDispatchingServer(ctx, "", dispatcher)
	if err != nil {
		cancel()
		return nil, nil, err
	}
	shutdown := func() {
		cancel()
		ctx.Infof("Stopping claimable server...")
		<-server.Closed()
		ctx.Infof("Stopped claimable server.")
	}
	publicKey, err := v23.GetPrincipal(ctx).PublicKey().MarshalBinary()
	if err != nil {
		shutdown()
		return nil, nil, err
	}
	var eps []naming.Endpoint
	if proxy := args.Device.ListenSpec.Proxy; proxy != "" {
		for {
			status := server.Status()
			if err, ok := status.ProxyErrors[proxy]; ok && err == nil {
				eps = status.Endpoints
				break
			}
			ctx.Infof("Waiting for proxy address to appear...")
			<-status.Dirty
		}
	} else {
		eps = server.Status().Endpoints
	}
	ctx.Infof("Unclaimed device manager with public_key: %s", base64.URLEncoding.EncodeToString(publicKey))
	for _, ep := range eps {
		ctx.Infof("Unclaimed device manager endpoint: %v", ep.Name())
	}
	ctx.FlushLog()
	return eps, shutdown, nil
}

func waitToBeClaimedAndStartClaimedDevice(ctx *context.T, stopClaimable func(), claimed, stop <-chan struct{}, stopped chan<- struct{}, args Args) {
	// Wait for either the claimable service to complete, or be stopped
	defer close(stopped)
	select {
	case <-claimed:
		// TODO(caprita): There seems to be a race between the claimable
		// service sending the reply to the claiming client, and the
		// claimable service shutting down.  This delay is meant to
		// verify the hypothesis that postponing shutting down the
		// claimable service resolves the flakiness in
		// https://vanadium-review.googlesource.com/#/c/21576/
		time.Sleep(2 * time.Second)
		stopClaimable()
	case <-stop:
		stopClaimable()
		return
	}
	shutdown, err := startClaimedDevice(ctx, args)
	if err != nil {
		ctx.Errorf("Failed to start device service after it was claimed: %v", err)
		v23.GetAppCycle(ctx).Stop(ctx)
		return
	}
	defer shutdown()
	<-stop // Wait to be stopped
}

func startClaimedDevice(ctx *context.T, args Args) (func(), error) {
	ctx.Infof("Starting claimed device services...")
	permStore := pathperms.NewPathStore(ctx)
	permsDir := impl.PermsDir(args.Device.ConfigState)
	debugAuth, err := pathperms.NewHierarchicalAuthorizer(permsDir, permsDir, permStore)
	if err != nil {
		return nil, err
	}

	debugDisp := debuglib.NewDispatcher(debugAuth)

	ctx = v23.WithReservedNameDispatcher(ctx, debugDisp)

	ctx.Infof("Starting mount table...")
	mtName, stopMT, err := startMounttable(ctx, args.Namespace)
	if err != nil {
		ctx.Errorf("Failed to start mounttable service: %v", err)
		return nil, err
	} else {
		ctx.Infof("Started mount table.")
	}
	ctx.Infof("Starting device service...")
	stopDevice, err := startDeviceServer(ctx, args.Device, mtName, permStore)
	if err != nil {
		ctx.Errorf("Failed to start device service: %v", err)
		stopMT()
		return nil, err
	} else {
		ctx.Infof("Started device service.")
	}
	if args.MountGlobalNamespaceInLocalNamespace {
		ctx.Infof("Mounting %v ...", mtName)
		mountGlobalNamespaceInLocalNamespace(ctx, mtName)
		ctx.Infof("Mounted %v", mtName)
	}

	impl.InvokeCallback(ctx, args.Device.ConfigState.Name)

	ctx.Infof("Started claimed device services.")
	return func() {
		stopDevice()
		stopMT()
	}, nil
}

func startMounttable(ctx *context.T, n NamespaceArgs) (string, func(), error) {
	mtName, stopMT, err := mounttablelib.StartServers(ctx, n.ListenSpec, n.Name, n.Neighborhood, n.PermissionsFile, n.PersistenceDir, "mounttable")
	if err != nil {
		ctx.Errorf("mounttablelib.StartServers(%#v) failed: %v", n, err)
	} else {
		ctx.Infof("Local mounttable (%v) published as %q", mtName, n.Name)
	}
	return mtName, func() {
		ctx.Infof("Stopping mounttable...")
		stopMT()
		ctx.Infof("Stopped mounttable.")
	}, err
}

// startDeviceServer creates an rpc.Server and sets it up to server the Device service.
//
// ls: ListenSpec for the server
// configState: configuration for the Device service dispatcher
// mt: Object address of the mounttable
// dm: Name to publish the device service under
// testMode: whether the service is to be run in test mode
// restarted: callback invoked when the device manager is restarted.
//
// Returns:
// (1) Function to be called to force the service to shutdown
// (2) Any errors in starting the service (in which case, (1) will be nil)
func startDeviceServer(ctx *context.T, args DeviceArgs, mt string, permStore *pathperms.PathStore) (shutdown func(), err error) {
	ctx = v23.WithListenSpec(ctx, args.ListenSpec)
	wrapper := displib.NewDispatcherWrapper()
	ctx, cancel := context.WithCancel(ctx)
	ctx, server, err := v23.WithNewDispatchingServer(ctx, args.name(mt), wrapper)
	if err != nil {
		return nil, err
	}
	args.ConfigState.Name = server.Status().Endpoints[0].Name()

	dispatcher, dShutdown, err := impl.NewDispatcher(ctx, args.ConfigState, mt, args.TestMode, args.RestartCallback, permStore)
	if err != nil {
		cancel()
		<-server.Closed()
		return nil, err
	}

	shutdown = func() {
		// TODO(caprita): Capture the Dying state by feeding it back to
		// the dispatcher and exposing it in Status.
		ctx.Infof("Stopping device server...")
		cancel()
		<-server.Closed()
		dShutdown()
		ctx.Infof("Stopped device.")
	}
	wrapper.SetDispatcher(dispatcher)
	ctx.Infof("Device manager (%v) published as %v", args.ConfigState.Name, args.name(mt))
	return shutdown, nil
}

func mountGlobalNamespaceInLocalNamespace(ctx *context.T, localMT string) {
	ns := v23.GetNamespace(ctx)
	for _, root := range ns.Roots() {
		go func(r string) {
			for {
				err := ns.Mount(ctx, naming.Join(localMT, "global"), r, 0 /* forever */, naming.ServesMountTable(true))
				if err == nil {
					break
				}
				ctx.Infof("Failed to Mount global namespace: %v", err)
				time.Sleep(time.Second)
			}
		}(root)
	}
}
<commit_msg>services/device/deviced/internal/starter: increase lame duck timeout<commit_after>// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Package starter provides a single function that starts up servers for a
// mounttable and a device manager that is mounted on it.
package starter

import (
	"encoding/base64"
	"os"
	"path/filepath"
	"time"

	"v.io/v23"
	"v.io/v23/context"
	"v.io/v23/naming"
	"v.io/v23/options"
	"v.io/v23/rpc"
	"v.io/v23/security"
	"v.io/v23/verror"
	displib "v.io/x/ref/lib/dispatcher"
	_ "v.io/x/ref/runtime/factories/roaming"
	"v.io/x/ref/services/debug/debuglib"
	"v.io/x/ref/services/device/deviced/internal/impl"
	"v.io/x/ref/services/device/deviced/internal/versioning"
	"v.io/x/ref/services/device/internal/claim"
	"v.io/x/ref/services/device/internal/config"
	"v.io/x/ref/services/internal/pathperms"
	"v.io/x/ref/services/mounttable/mounttablelib"
)

const pkgPath = "v.io/x/ref/services/device/deviced/internal/starter"

var (
	errCantSaveInfo = verror.Register(pkgPath+".errCantSaveInfo", verror.NoRetry, "{1:}{2:} failed to save info{:_}")
)

type NamespaceArgs struct {
	Name            string         // Name to publish the mounttable service under (after claiming).
	ListenSpec      rpc.ListenSpec // ListenSpec for the server.
	PermissionsFile string         // Path to the Permissions file used by the mounttable.
	PersistenceDir  string         // Path to the directory holding persistent acls.
	// Name in the local neighborhood on which to make the mounttable
	// visible. If empty, the mounttable will not be visible in the local
	// neighborhood.
	Neighborhood string
}

type DeviceArgs struct {
	Name            string         // Name to publish the device service under (after claiming).
	ListenSpec      rpc.ListenSpec // ListenSpec for the device server.
	ConfigState     *config.State  // Configuration for the device.
	TestMode        bool           // Whether the device is running in test mode or not.
	RestartCallback func()         // Callback invoked when the device service is restarted.
	PairingToken    string         // PairingToken that a claimer needs to provide.
}

func (d *DeviceArgs) name(mt string) string {
	if d.Name != "" {
		return d.Name
	}
	return naming.Join(mt, "devmgr")
}

type Args struct {
	Namespace NamespaceArgs
	Device    DeviceArgs

	// If true, the global namespace will be made available on the
	// mounttable server under "global/".
	MountGlobalNamespaceInLocalNamespace bool
}

// Start creates servers for the mounttable and device services and links them together.
//
// Returns the endpoints for the claimable service (empty if already claimed),
// a callback to be invoked to shutdown the services on success, or an error on
// failure.
func Start(ctx *context.T, args Args) ([]naming.Endpoint, func(), error) {
	// Is this binary compatible with the state on disk?
	if err := versioning.CheckCompatibility(ctx, args.Device.ConfigState.Root); err != nil {
		return nil, nil, err
	}
	// In test mode, we skip writing the info file to disk, and we skip
	// attempting to start the claimable service: the device must have been
	// claimed already to enable updates anyway, and checking for perms in
	// NewClaimableDispatcher needlessly prints a perms signature
	// verification error to the logs.
	if args.Device.TestMode {
		cleanup, err := startClaimedDevice(ctx, args)
		return nil, cleanup, err
	}

	// TODO(caprita): use some mechanism (a file lock or presence of entry
	// in mounttable) to ensure only one device manager is running in an
	// installation?
	mi := &impl.ManagerInfo{
		Pid: os.Getpid(),
	}
	if err := impl.SaveManagerInfo(filepath.Join(args.Device.ConfigState.Root, "device-manager"), mi); err != nil {
		return nil, nil, verror.New(errCantSaveInfo, ctx, err)
	}

	// If the device has not yet been claimed, start the mounttable and
	// claimable service and wait for it to be claimed.
	// Once a device is claimed, close any previously running servers and
	// start a new mounttable and device service.
	claimable, claimed := claim.NewClaimableDispatcher(ctx, impl.PermsDir(args.Device.ConfigState), args.Device.PairingToken, security.AllowEveryone())
	if claimable == nil {
		// Device has already been claimed, bypass claimable service
		// stage.
		cleanup, err := startClaimedDevice(ctx, args)
		return nil, cleanup, err
	}
	eps, stopClaimable, err := startClaimableDevice(ctx, claimable, args)
	if err != nil {
		return nil, nil, err
	}
	stop := make(chan struct{})
	stopped := make(chan struct{})
	go waitToBeClaimedAndStartClaimedDevice(ctx, stopClaimable, claimed, stop, stopped, args)
	return eps, func() {
		close(stop)
		<-stopped
	}, nil
}

func startClaimableDevice(ctx *context.T, dispatcher rpc.Dispatcher, args Args) ([]naming.Endpoint, func(), error) {
	ctx, cancel := context.WithCancel(ctx)
	ctx = v23.WithListenSpec(ctx, args.Device.ListenSpec)
	ctx, server, err := v23.WithNewDispatchingServer(ctx, "", dispatcher, options.LameDuckTimeout(30*time.Second))
	if err != nil {
		cancel()
		return nil, nil, err
	}
	shutdown := func() {
		cancel()
		ctx.Infof("Stopping claimable server...")
		<-server.Closed()
		ctx.Infof("Stopped claimable server.")
	}
	publicKey, err := v23.GetPrincipal(ctx).PublicKey().MarshalBinary()
	if err != nil {
		shutdown()
		return nil, nil, err
	}
	var eps []naming.Endpoint
	if proxy := args.Device.ListenSpec.Proxy; proxy != "" {
		for {
			status := server.Status()
			if err, ok := status.ProxyErrors[proxy]; ok && err == nil {
				eps = status.Endpoints
				break
			}
			ctx.Infof("Waiting for proxy address to appear...")
			<-status.Dirty
		}
	} else {
		eps = server.Status().Endpoints
	}
	ctx.Infof("Unclaimed device manager with public_key: %s", base64.URLEncoding.EncodeToString(publicKey))
	for _, ep := range eps {
		ctx.Infof("Unclaimed device manager endpoint: %v", ep.Name())
	}
	ctx.FlushLog()
	return eps, shutdown, nil
}

func waitToBeClaimedAndStartClaimedDevice(ctx *context.T, stopClaimable func(), claimed, stop <-chan struct{}, stopped chan<- struct{}, args Args) {
	// Wait for either the claimable service to complete, or be stopped
	defer close(stopped)
	select {
	case <-claimed:
		stopClaimable()
	case <-stop:
		stopClaimable()
		return
	}
	shutdown, err := startClaimedDevice(ctx, args)
	if err != nil {
		ctx.Errorf("Failed to start device service after it was claimed: %v", err)
		v23.GetAppCycle(ctx).Stop(ctx)
		return
	}
	defer shutdown()
	<-stop // Wait to be stopped
}

func startClaimedDevice(ctx *context.T, args Args) (func(), error) {
	ctx.Infof("Starting claimed device services...")
	permStore := pathperms.NewPathStore(ctx)
	permsDir := impl.PermsDir(args.Device.ConfigState)
	debugAuth, err := pathperms.NewHierarchicalAuthorizer(permsDir, permsDir, permStore)
	if err != nil {
		return nil, err
	}

	debugDisp := debuglib.NewDispatcher(debugAuth)

	ctx = v23.WithReservedNameDispatcher(ctx, debugDisp)

	ctx.Infof("Starting mount table...")
	mtName, stopMT, err := startMounttable(ctx, args.Namespace)
	if err != nil {
		ctx.Errorf("Failed to start mounttable service: %v", err)
		return nil, err
	} else {
		ctx.Infof("Started mount table.")
	}
	ctx.Infof("Starting device service...")
	stopDevice, err := startDeviceServer(ctx, args.Device, mtName, permStore)
	if err != nil {
		ctx.Errorf("Failed to start device service: %v", err)
		stopMT()
		return nil, err
	} else {
		ctx.Infof("Started device service.")
	}
	if args.MountGlobalNamespaceInLocalNamespace {
		ctx.Infof("Mounting %v ...", mtName)
		mountGlobalNamespaceInLocalNamespace(ctx, mtName)
		ctx.Infof("Mounted %v", mtName)
	}

	impl.InvokeCallback(ctx, args.Device.ConfigState.Name)

	ctx.Infof("Started claimed device services.")
	return func() {
		stopDevice()
		stopMT()
	}, nil
}

func startMounttable(ctx *context.T, n NamespaceArgs) (string, func(), error) {
	mtName, stopMT, err := mounttablelib.StartServers(ctx, n.ListenSpec, n.Name, n.Neighborhood, n.PermissionsFile, n.PersistenceDir, "mounttable")
	if err != nil {
		ctx.Errorf("mounttablelib.StartServers(%#v) failed: %v", n, err)
	} else {
		ctx.Infof("Local mounttable (%v) published as %q", mtName, n.Name)
	}
	return mtName, func() {
		ctx.Infof("Stopping mounttable...")
		stopMT()
		ctx.Infof("Stopped mounttable.")
	}, err
}

// startDeviceServer creates an rpc.Server and sets it up to server the Device service.
//
// ls: ListenSpec for the server
// configState: configuration for the Device service dispatcher
// mt: Object address of the mounttable
// dm: Name to publish the device service under
// testMode: whether the service is to be run in test mode
// restarted: callback invoked when the device manager is restarted.
//
// Returns:
// (1) Function to be called to force the service to shutdown
// (2) Any errors in starting the service (in which case, (1) will be nil)
func startDeviceServer(ctx *context.T, args DeviceArgs, mt string, permStore *pathperms.PathStore) (shutdown func(), err error) {
	ctx = v23.WithListenSpec(ctx, args.ListenSpec)
	wrapper := displib.NewDispatcherWrapper()
	ctx, cancel := context.WithCancel(ctx)
	ctx, server, err := v23.WithNewDispatchingServer(ctx, args.name(mt), wrapper)
	if err != nil {
		return nil, err
	}
	args.ConfigState.Name = server.Status().Endpoints[0].Name()

	dispatcher, dShutdown, err := impl.NewDispatcher(ctx, args.ConfigState, mt, args.TestMode, args.RestartCallback, permStore)
	if err != nil {
		cancel()
		<-server.Closed()
		return nil, err
	}

	shutdown = func() {
		// TODO(caprita): Capture the Dying state by feeding it back to
		// the dispatcher and exposing it in Status.
		ctx.Infof("Stopping device server...")
		cancel()
		<-server.Closed()
		dShutdown()
		ctx.Infof("Stopped device.")
	}
	wrapper.SetDispatcher(dispatcher)
	ctx.Infof("Device manager (%v) published as %v", args.ConfigState.Name, args.name(mt))
	return shutdown, nil
}

func mountGlobalNamespaceInLocalNamespace(ctx *context.T, localMT string) {
	ns := v23.GetNamespace(ctx)
	for _, root := range ns.Roots() {
		go func(r string) {
			for {
				err := ns.Mount(ctx, naming.Join(localMT, "global"), r, 0 /* forever */, naming.ServesMountTable(true))
				if err == nil {
					break
				}
				ctx.Infof("Failed to Mount global namespace: %v", err)
				time.Sleep(time.Second)
			}
		}(root)
	}
}
<|endoftext|>


<commit_before>package quaternion

/*
Quaternion array package
A Quaternion array is a struct with 4 columns defined as x y z w
it can be created simply using slice.
*/

import "math"

type qMatrix struct{
	qMat []float
}

//
func (qm *qMatrix) ArrayDot(){

}

//Inverse of quaternion array q
func (qm *qMatrix) Inverse() {

}

func (qm *qMatrix) Amplitude(){

}

//Normalize quaternion array q or array list to unit quaternions
func (qm *qMatrix) Norm(){

}

//
func Division(){

}

//
func Mul(){

}

//Exponential of a quaternion array
func (qm *qMatrix) Exp(){

}

//Neprien logarithm of a quaternion array
func (qm *qMatrix) Ln(){

}

//Real power of a quaternion array
func (qm *qMatrix) Pow(){

}

//Rotate vector or array of vectors v by quaternion q
func Rotate(q []float64) {

}

//
func Toaxisangle(){

}<commit_msg>change folder name<commit_after><|endoftext|>


<commit_before>package main

import (
	"net/http"
	vc "github.com/vercel/go-bridge/go/bridgee"
)

func main() {
	vc.Start(http.HandlerFunc(__NOW_HANDLER_FUNC_NAME))
}
<commit_msg>[go] Fix typo in `go-bridge` import (#4578)<commit_after>package main

import (
	"net/http"
	vc "github.com/vercel/go-bridge/go/bridge"
)

func main() {
	vc.Start(http.HandlerFunc(__NOW_HANDLER_FUNC_NAME))
}
<|endoftext|>


<commit_before>package core

import (
	"github.com/ory-am/fosite"
	"golang.org/x/net/context"
	"net/http"
)

type AccessTokenStrategy interface {
	GenerateAccessToken(ctx context.Context, req *http.Request, requester fosite.AccessRequester, session interface{}) (token string, signature string, err error)
	ValidateAccessToken(token string) (signature string, err error)
}

type RefreshTokenStrategy interface {
	GenerateRefreshToken(ctx context.Context, req *http.Request, requester fosite.AccessRequester, session interface{}) (token string, signature string, err error)
	ValidateRefreshToken(token string) (signature string, err error)
}

type AuthorizeCodeStrategy interface {
	GenerateAuthorizeCode(ctx context.Context, req *http.Request, requester fosite.AuthorizeRequester, session interface{}) (token string, signature string, err error)
	ValidateAuthorizeCode(token string, ctx context.Context, req *http.Request, requester fosite.AuthorizeRequester, session interface{}) (signature string, err error)
}
<commit_msg>unstaged<commit_after>package core

import (
	"github.com/ory-am/fosite"
	"golang.org/x/net/context"
	"net/http"
)

type AccessTokenStrategy interface {
	GenerateAccessToken(ctx context.Context, req *http.Request, requester fosite.AccessRequester, session interface{}) (token string, signature string, err error)
	ValidateAccessToken(token string, ctx context.Context, req *http.Request, requester fosite.AccessRequester, session interface{}) (signature string, err error)
}

type RefreshTokenStrategy interface {
	GenerateRefreshToken(ctx context.Context, req *http.Request, requester fosite.AccessRequester, session interface{}) (token string, signature string, err error)
	ValidateRefreshToken(token string, ctx context.Context, req *http.Request, requester fosite.AccessRequester, session interface{}) (signature string, err error)
}

type AuthorizeCodeStrategy interface {
	GenerateAuthorizeCode(ctx context.Context, req *http.Request, requester fosite.AuthorizeRequester, session interface{}) (token string, signature string, err error)
	ValidateAuthorizeCode(token string, ctx context.Context, req *http.Request, requester fosite.AuthorizeRequester, session interface{}) (signature string, err error)
}
<|endoftext|>


<commit_before>package fuzz

import (
	"encoding/binary"
	"github.com/pkg/errors"
	"io"
	"io/ioutil"
	"os"
	"os/exec"
	"runtime/debug"
	"sync"
	"syscall"
	"unsafe"

	"github.com/lunixbochs/usercorn/go/cmd"
	"github.com/lunixbochs/usercorn/go/models"

	uc "github.com/unicorn-engine/unicorn/bindings/go/unicorn"
)

/*
#include <stdlib.h>
#include <sys/shm.h>
#include <string.h>

#include <unicorn/unicorn.h>
#cgo LDFLAGS: -lunicorn

void *afl_setup() {
	char *id = getenv("__AFL_SHM_ID");
	if (id == NULL) {
		return NULL;
	}
	void *afl_area = shmat(atoi(id), NULL, 0);
	if (afl_area == (void *)-1) {
		return NULL;
	}
	return afl_area;
}

typedef struct {
	uint64_t prev;
	uint8_t *area;
	uint64_t size;
	uc_hook hh;
} afl_state;

uint64_t murmur64(uint64_t val) {
	uint64_t h = val;
	h ^= val >> 33;
	h *= 0xff51afd7ed558ccd;
	h ^= h >> 33;
	h *= 0xc4ceb9fe1a85ec53;
	h ^= h >> 33;
	return h;
}

void afl_block_cb(uc_engine *uc, uint64_t addr, uint32_t size, void *user) {
	afl_state *state = user;
	// size must be a power of two
	uint64_t cur = murmur64(addr) & (state->size - 1);
	state->area[cur ^ state->prev]++;
	state->prev = cur;
}

afl_state *afl_uc_hook(void *uc, void *area, uint64_t size) {
	afl_state *state = malloc(sizeof(afl_state));
	state->area = area;
	state->size = size;
	if (uc_hook_add(uc, &state->hh, UC_HOOK_BLOCK, afl_block_cb, state, 1, 0) != UC_ERR_OK) {
		free(state);
		return NULL;
	}
	return state;
}
*/
import "C"

var MAP_SIZE uint64 = 1 << 16
var FORKSRV_FD = 198
var aflHello = []byte{1, 2, 3, 4}

type FakeProc struct {
	Argv     []string
	Stdin    io.WriteCloser
	Usercorn models.Usercorn
	*exec.Cmd
	sync.Mutex
}

func (p *FakeProc) Start() error {
	p.Lock()
	defer p.Unlock()
	if p.Cmd != nil {
		// kill(0) to see if it's still running
		if p.Process.Signal(syscall.Signal(0)) == nil {
			return nil
		}
	}
	var err error
	p.Cmd = exec.Command(p.Argv[0], p.Argv[1:]...)
	p.Stdin, err = p.StdinPipe()
	if err != nil {
		p.Usercorn.Printf("failed to open stdin: %s\n", err)
		return errors.Wrap(err, "failed to open stdin")
	}
	if err = p.Cmd.Start(); err != nil {
		p.Usercorn.Printf("failed to spawn child: %s\n", err)
		return errors.Wrap(err, "failed to spawn child")
	}
	go func() {
		p.Wait()
		p.Lock()
		defer p.Unlock()
		p.Usercorn.Stop()
		p.Stdin.Close()
		p.Cmd = nil
	}()
	return nil
}

func Main(args []string) {
	message := []byte("In fuzz main")
	ioutil.WriteFile("/tmp/outfile", message, 0444)

	forksrvCtrl := os.NewFile(uintptr(FORKSRV_FD), "afl_ctrl")
	forksrvStatus := os.NewFile(uintptr(FORKSRV_FD+1), "afl_status")

	c := cmd.NewUsercornCmd()
	var forkAddr *uint64
	var fuzzInterp *bool

	nofork := os.Getenv("AFL_NO_FORKSRV") == "1"

	aflArea := C.afl_setup()
	if aflArea == nil {
		panic("could not set up AFL shared memory")
	}

	c.SetupFlags = func() error {
		forkAddr = c.Flags.Uint64("forkaddr", 0, "wait until this address to fork and begin fuzzing")
		fuzzInterp = c.Flags.Bool("fuzzinterp", false, "controls whether fuzzing is delayed until program's main entry point")
		return nil
	}
	c.RunUsercorn = func() error {
		var err error
		u := c.Usercorn
		defer func() {
			if r := recover(); r != nil {
				u.Println("caught panic", r)
				u.Println(string(debug.Stack()))
			}
		}()

		aflState := C.afl_uc_hook(unsafe.Pointer(u.Backend().(uc.Unicorn).Handle()), aflArea, C.uint64_t(MAP_SIZE))
		if aflState == nil {
			panic("failed to setup hooks")
		}
		if nofork {
			status := 0
			err = u.Run()
			if _, ok := err.(models.ExitStatus); ok {
			} else if err != nil {
				u.Printf("Usercorn err: %s\n", err)
				status = 257
			}
			os.Exit(status)
		}

		// save cpu and memory state
		savedCtx, err := models.ContextSave(u)
		if err != nil {
			u.Println("context save failed.")
			return err
		}

		if _, err := forksrvStatus.Write(aflHello); err != nil {
			u.Println("AFL hello failed.")
			return errors.Wrap(err, "AFL hello failed.")
		}
		child := FakeProc{Argv: []string{"/bin/cat"}, Usercorn: u}
		var aflMsg [4]byte
		// afl forkserver loop
		u.Println("starting forkserver")
		for {
			if _, err := forksrvCtrl.Read(aflMsg[:]); err != nil {
				u.Printf("Failed to receive control signal from AFL: %s\n", err)
				return errors.Wrapf(err, "Failed to receive control signal from AFL: %s", err)
			}

			// spawn a fake child so AFL has something other than us to kill
			// monitor it and if afl kills it, stop the current emulation

			if err := child.Start(); err != nil {
				return err
			}
			// restore cpu and memory state
			if err := models.ContextRestore(u, savedCtx); err != nil {
				u.Println("context restore failed.")
				return err
			}

			binary.LittleEndian.PutUint32(aflMsg[:], uint32(child.Process.Pid))
			if _, err := forksrvStatus.Write(aflMsg[:]); err != nil {
				u.Printf("Failed to send pid to AFL: %s\n", err)
				return errors.Wrap(err, "failed to send PID to AFL")
			}

			status := 0
			err = u.Run()
			if _, ok := err.(models.ExitStatus); ok {
			} else if err != nil {
				u.Printf("Usercorn err: %s\n", err)
				status = 257
			}
			binary.LittleEndian.PutUint32(aflMsg[:], uint32(status))
			if _, err := forksrvStatus.Write(aflMsg[:]); err != nil {
				u.Printf("Failed to send status to AFL: %s\n", err)
				return errors.Wrap(err, "failed to send status to AFL")
			}
		}
	}
	os.Exit(c.Run(args, os.Environ()))
}

func init() { cmd.Register("fuzz", "fuzz acts as an AFL fork server", Main) }
<commit_msg>fix fuzz -help<commit_after>package fuzz

import (
	"encoding/binary"
	"github.com/pkg/errors"
	"io"
	"io/ioutil"
	"os"
	"os/exec"
	"runtime/debug"
	"sync"
	"syscall"
	"unsafe"

	"github.com/lunixbochs/usercorn/go/cmd"
	"github.com/lunixbochs/usercorn/go/models"

	uc "github.com/unicorn-engine/unicorn/bindings/go/unicorn"
)

/*
#include <stdlib.h>
#include <sys/shm.h>
#include <string.h>

#include <unicorn/unicorn.h>
#cgo LDFLAGS: -lunicorn

void *afl_setup() {
	char *id = getenv("__AFL_SHM_ID");
	if (id == NULL) {
		return NULL;
	}
	void *afl_area = shmat(atoi(id), NULL, 0);
	if (afl_area == (void *)-1) {
		return NULL;
	}
	return afl_area;
}

typedef struct {
	uint64_t prev;
	uint8_t *area;
	uint64_t size;
	uc_hook hh;
} afl_state;

uint64_t murmur64(uint64_t val) {
	uint64_t h = val;
	h ^= val >> 33;
	h *= 0xff51afd7ed558ccd;
	h ^= h >> 33;
	h *= 0xc4ceb9fe1a85ec53;
	h ^= h >> 33;
	return h;
}

void afl_block_cb(uc_engine *uc, uint64_t addr, uint32_t size, void *user) {
	afl_state *state = user;
	// size must be a power of two
	uint64_t cur = murmur64(addr) & (state->size - 1);
	state->area[cur ^ state->prev]++;
	state->prev = cur;
}

afl_state *afl_uc_hook(void *uc, void *area, uint64_t size) {
	afl_state *state = malloc(sizeof(afl_state));
	state->area = area;
	state->size = size;
	if (uc_hook_add(uc, &state->hh, UC_HOOK_BLOCK, afl_block_cb, state, 1, 0) != UC_ERR_OK) {
		free(state);
		return NULL;
	}
	return state;
}
*/
import "C"

var MAP_SIZE uint64 = 1 << 16
var FORKSRV_FD = 198
var aflHello = []byte{1, 2, 3, 4}

type FakeProc struct {
	Argv     []string
	Stdin    io.WriteCloser
	Usercorn models.Usercorn
	*exec.Cmd
	sync.Mutex
}

func (p *FakeProc) Start() error {
	p.Lock()
	defer p.Unlock()
	if p.Cmd != nil {
		// kill(0) to see if it's still running
		if p.Process.Signal(syscall.Signal(0)) == nil {
			return nil
		}
	}
	var err error
	p.Cmd = exec.Command(p.Argv[0], p.Argv[1:]...)
	p.Stdin, err = p.StdinPipe()
	if err != nil {
		p.Usercorn.Printf("failed to open stdin: %s\n", err)
		return errors.Wrap(err, "failed to open stdin")
	}
	if err = p.Cmd.Start(); err != nil {
		p.Usercorn.Printf("failed to spawn child: %s\n", err)
		return errors.Wrap(err, "failed to spawn child")
	}
	go func() {
		p.Wait()
		p.Lock()
		defer p.Unlock()
		p.Usercorn.Stop()
		p.Stdin.Close()
		p.Cmd = nil
	}()
	return nil
}

func Main(args []string) {
	message := []byte("In fuzz main")
	ioutil.WriteFile("/tmp/outfile", message, 0444)

	forksrvCtrl := os.NewFile(uintptr(FORKSRV_FD), "afl_ctrl")
	forksrvStatus := os.NewFile(uintptr(FORKSRV_FD+1), "afl_status")

	c := cmd.NewUsercornCmd()
	var forkAddr *uint64
	var fuzzInterp *bool

	nofork := os.Getenv("AFL_NO_FORKSRV") == "1"

	c.SetupFlags = func() error {
		forkAddr = c.Flags.Uint64("forkaddr", 0, "wait until this address to fork and begin fuzzing")
		fuzzInterp = c.Flags.Bool("fuzzinterp", false, "controls whether fuzzing is delayed until program's main entry point")
		return nil
	}
	c.RunUsercorn = func() error {
		aflArea := C.afl_setup()
		if aflArea == nil {
			panic("could not set up AFL shared memory")
		}

		var err error
		u := c.Usercorn
		defer func() {
			if r := recover(); r != nil {
				u.Println("caught panic", r)
				u.Println(string(debug.Stack()))
			}
		}()

		aflState := C.afl_uc_hook(unsafe.Pointer(u.Backend().(uc.Unicorn).Handle()), aflArea, C.uint64_t(MAP_SIZE))
		if aflState == nil {
			panic("failed to setup hooks")
		}
		if nofork {
			err = u.Run()
			if _, ok := err.(models.ExitStatus); ok {
			} else if err != nil {
				u.Printf("Usercorn err: %s\n", err)
				return models.ExitStatus(257)
			}
			return err
		}

		// save cpu and memory state
		savedCtx, err := models.ContextSave(u)
		if err != nil {
			u.Println("context save failed.")
			return err
		}

		if _, err := forksrvStatus.Write(aflHello); err != nil {
			u.Println("AFL hello failed.")
			return errors.Wrap(err, "AFL hello failed.")
		}
		child := FakeProc{Argv: []string{"/bin/cat"}, Usercorn: u}
		var aflMsg [4]byte
		// afl forkserver loop
		u.Println("starting forkserver")
		for {
			if _, err := forksrvCtrl.Read(aflMsg[:]); err != nil {
				u.Printf("Failed to receive control signal from AFL: %s\n", err)
				return errors.Wrapf(err, "Failed to receive control signal from AFL: %s", err)
			}

			// spawn a fake child so AFL has something other than us to kill
			// monitor it and if afl kills it, stop the current emulation

			if err := child.Start(); err != nil {
				return err
			}
			// restore cpu and memory state
			if err := models.ContextRestore(u, savedCtx); err != nil {
				u.Println("context restore failed.")
				return err
			}

			binary.LittleEndian.PutUint32(aflMsg[:], uint32(child.Process.Pid))
			if _, err := forksrvStatus.Write(aflMsg[:]); err != nil {
				u.Printf("Failed to send pid to AFL: %s\n", err)
				return errors.Wrap(err, "failed to send PID to AFL")
			}

			status := 0
			err = u.Run()
			if _, ok := err.(models.ExitStatus); ok {
			} else if err != nil {
				u.Printf("Usercorn err: %s\n", err)
				status = 257
			}
			binary.LittleEndian.PutUint32(aflMsg[:], uint32(status))
			if _, err := forksrvStatus.Write(aflMsg[:]); err != nil {
				u.Printf("Failed to send status to AFL: %s\n", err)
				return errors.Wrap(err, "failed to send status to AFL")
			}
		}
	}
	os.Exit(c.Run(args, os.Environ()))
}

func init() { cmd.Register("fuzz", "fuzz acts as an AFL fork server", Main) }
<|endoftext|>


<commit_before>/*
   Copyright 2015 Shlomi Noach, courtesy Booking.com

   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 http

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

	"github.com/martini-contrib/auth"

	"github.com/github/orchestrator/go/config"
	"github.com/github/orchestrator/go/process"
)

func getProxyAuthUser(req *http.Request) string {
	for _, user := range req.Header[config.Config.AuthUserHeader] {
		return user
	}
	return ""
}

// isAuthorizedForAction checks req to see whether authenticated user has write-privileges.
// This depends on configured authentication method.
func isAuthorizedForAction(req *http.Request, user auth.User) bool {
	if config.Config.ReadOnly {
		return false
	}

	switch strings.ToLower(config.Config.AuthenticationMethod) {
	case "basic":
		{
			// The mere fact we're here means the user has passed authentication
			return true
		}
	case "multi":
		{
			if string(user) == "readonly" {
				// read only
				return false
			}
			// passed authentication ==> writeable
			return true
		}
	case "proxy":
		{
			authUser := getProxyAuthUser(req)
			for _, configPowerAuthUser := range config.Config.PowerAuthUsers {
				if configPowerAuthUser == "*" || configPowerAuthUser == authUser {
					return true
				}
			}
			return false
		}
	case "token":
		{
			cookie, err := req.Cookie("access-token")
			if err != nil {
				return false
			}

			publicToken := strings.Split(cookie.Value, ":")[0]
			secretToken := strings.Split(cookie.Value, ":")[1]
			result, _ := process.TokenIsValid(publicToken, secretToken)
			return result
		}
	case "oauth":
		{
			return false
		}
	default:
		{
			// Default: no authentication method
			return true
		}
	}
}

func authenticateToken(publicToken string, resp http.ResponseWriter) error {
	secretToken, err := process.AcquireAccessToken(publicToken)
	if err != nil {
		return err
	}
	cookieValue := fmt.Sprintf("%s:%s", publicToken, secretToken)
	cookie := &http.Cookie{Name: "access-token", Value: cookieValue, Path: "/"}
	http.SetCookie(resp, cookie)
	return nil
}

// getUserId returns the authenticated user id, if available, depending on authertication method.
func getUserId(req *http.Request, user auth.User) string {
	if config.Config.ReadOnly {
		return ""
	}

	switch strings.ToLower(config.Config.AuthenticationMethod) {
	case "basic":
		{
			return string(user)
		}
	case "multi":
		{
			return string(user)
		}
	case "proxy":
		{
			return getProxyAuthUser(req)
		}
	case "token":
		{
			return ""
		}
	default:
		{
			return ""
		}
	}
}
<commit_msg>unauthorizing API for non-leader raft members<commit_after>/*
   Copyright 2015 Shlomi Noach, courtesy Booking.com

   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 http

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

	"github.com/martini-contrib/auth"

	"github.com/github/orchestrator/go/config"
	"github.com/github/orchestrator/go/process"
	"github.com/github/orchestrator/go/raft"
)

func getProxyAuthUser(req *http.Request) string {
	for _, user := range req.Header[config.Config.AuthUserHeader] {
		return user
	}
	return ""
}

// isAuthorizedForAction checks req to see whether authenticated user has write-privileges.
// This depends on configured authentication method.
func isAuthorizedForAction(req *http.Request, user auth.User) bool {
	if config.Config.ReadOnly {
		return false
	}

	if orcraft.IsRaftEnabled() && !orcraft.IsLeader() {
		// A raft member that is not a leader is unauthorized.
		return false
	}

	switch strings.ToLower(config.Config.AuthenticationMethod) {
	case "basic":
		{
			// The mere fact we're here means the user has passed authentication
			return true
		}
	case "multi":
		{
			if string(user) == "readonly" {
				// read only
				return false
			}
			// passed authentication ==> writeable
			return true
		}
	case "proxy":
		{
			authUser := getProxyAuthUser(req)
			for _, configPowerAuthUser := range config.Config.PowerAuthUsers {
				if configPowerAuthUser == "*" || configPowerAuthUser == authUser {
					return true
				}
			}
			return false
		}
	case "token":
		{
			cookie, err := req.Cookie("access-token")
			if err != nil {
				return false
			}

			publicToken := strings.Split(cookie.Value, ":")[0]
			secretToken := strings.Split(cookie.Value, ":")[1]
			result, _ := process.TokenIsValid(publicToken, secretToken)
			return result
		}
	case "oauth":
		{
			return false
		}
	default:
		{
			// Default: no authentication method
			return true
		}
	}
}

func authenticateToken(publicToken string, resp http.ResponseWriter) error {
	secretToken, err := process.AcquireAccessToken(publicToken)
	if err != nil {
		return err
	}
	cookieValue := fmt.Sprintf("%s:%s", publicToken, secretToken)
	cookie := &http.Cookie{Name: "access-token", Value: cookieValue, Path: "/"}
	http.SetCookie(resp, cookie)
	return nil
}

// getUserId returns the authenticated user id, if available, depending on authertication method.
func getUserId(req *http.Request, user auth.User) string {
	if config.Config.ReadOnly {
		return ""
	}

	switch strings.ToLower(config.Config.AuthenticationMethod) {
	case "basic":
		{
			return string(user)
		}
	case "multi":
		{
			return string(user)
		}
	case "proxy":
		{
			return getProxyAuthUser(req)
		}
	case "token":
		{
			return ""
		}
	default:
		{
			return ""
		}
	}
}
<|endoftext|>


<commit_before>// Copyright 2017 Keybase, Inc. All rights reserved. Use of
// this source code is governed by the included BSD license.

package service

import (
	"fmt"
	"strings"

	"github.com/keybase/client/go/chat"
	"github.com/keybase/client/go/chat/globals"
	"github.com/keybase/client/go/libkb"
	"github.com/keybase/client/go/protocol/chat1"
	keybase1 "github.com/keybase/client/go/protocol/keybase1"
	"github.com/keybase/client/go/teams"
	"github.com/keybase/go-framed-msgpack-rpc/rpc"
	"golang.org/x/net/context"
)

type TeamsHandler struct {
	*BaseHandler
	globals.Contextified
	gregor *gregorHandler
	connID libkb.ConnectionID
}

var _ keybase1.TeamsInterface = (*TeamsHandler)(nil)

func NewTeamsHandler(xp rpc.Transporter, id libkb.ConnectionID, g *globals.Context, gregor *gregorHandler) *TeamsHandler {
	return &TeamsHandler{
		BaseHandler:  NewBaseHandler(xp),
		Contextified: globals.NewContextified(g),
		gregor:       gregor,
		connID:       id,
	}
}

func (h *TeamsHandler) TeamCreate(ctx context.Context, arg keybase1.TeamCreateArg) (res keybase1.TeamCreateResult, err error) {
	h.G().CTrace(ctx, fmt.Sprintf("TeamCreate(%s)", arg.Name), func() error { return err })()
	teamName, err := keybase1.TeamNameFromString(arg.Name)
	if err != nil {
		return res, err
	}
	if !teamName.IsRootTeam() {
		h.G().Log.CDebugf(ctx, "TeamCreate: creating a new subteam: %s", arg.Name)
		if teamName.Depth() == 0 {
			return res, fmt.Errorf("empty team name")
		}
		parentName, err := teamName.Parent()
		if err != nil {
			return res, err
		}
		if _, err = teams.CreateSubteam(ctx, h.G().ExternalG(), string(teamName.LastPart()), parentName); err != nil {
			return res, err
		}
	} else {
		if err := teams.CreateRootTeam(ctx, h.G().ExternalG(), teamName.String()); err != nil {
			return res, err
		}
		res.CreatorAdded = true
	}

	if arg.SendChatNotification {
		res.ChatSent = h.sendTeamChatWelcomeMessage(ctx, teamName.String(), h.G().Env.GetUsername().String())
	}
	return res, nil
}

func (h *TeamsHandler) TeamGet(ctx context.Context, arg keybase1.TeamGetArg) (keybase1.TeamDetails, error) {
	return teams.Details(ctx, h.G().ExternalG(), arg.Name, arg.ForceRepoll)
}

func (h *TeamsHandler) TeamList(ctx context.Context, arg keybase1.TeamListArg) (keybase1.AnnotatedTeamList, error) {
	x, err := teams.List(ctx, h.G().ExternalG(), arg)
	if err != nil {
		return keybase1.AnnotatedTeamList{}, err
	}
	return *x, nil
}

func (h *TeamsHandler) TeamChangeMembership(ctx context.Context, arg keybase1.TeamChangeMembershipArg) error {
	return teams.ChangeRoles(ctx, h.G().ExternalG(), arg.Name, arg.Req)
}

func (h *TeamsHandler) sendTeamChatWelcomeMessage(ctx context.Context, team, user string) (res bool) {
	var err error
	defer func() {
		if err != nil {
			h.G().Log.CWarningf(ctx, "failed to send team welcome message: %s", err.Error())
		}
	}()
	teamDetails, err := teams.Details(ctx, h.G().ExternalG(), team, true)
	if err != nil {
		return false
	}

	var ownerNames, adminNames, writerNames, readerNames []string
	for _, owner := range teamDetails.Members.Owners {
		ownerNames = append(ownerNames, owner.Username)
	}
	for _, admin := range teamDetails.Members.Admins {
		adminNames = append(adminNames, admin.Username)
	}
	for _, writer := range teamDetails.Members.Writers {
		writerNames = append(writerNames, writer.Username)
	}
	for _, reader := range teamDetails.Members.Readers {
		readerNames = append(readerNames, reader.Username)
	}
	var lines []string
	if len(ownerNames) > 0 {
		lines = append(lines, fmt.Sprintf("  owners: %s", strings.Join(ownerNames, ",")))
	}
	if len(adminNames) > 0 {
		lines = append(lines, fmt.Sprintf("  admins: %s", strings.Join(adminNames, ",")))
	}
	if len(writerNames) > 0 {
		lines = append(lines, fmt.Sprintf("  writers: %s", strings.Join(writerNames, ",")))
	}
	if len(readerNames) > 0 {
		lines = append(lines, fmt.Sprintf("  readers: %s", strings.Join(readerNames, ",")))
	}
	memberBody := strings.Join(lines, "\n")
	body := fmt.Sprintf("Hello @channel! I've just added @%s to this team. Current members:\n\n```%s```\n\n_More info on teams:_ keybase.io/blog/introducing-keybase-teams\n_To leave this team, visit the team tab or run `keybase team leave %s`_",
		user, memberBody, team)

	// Ensure we have chat available, since TeamAddMember may also be
	// coming from a standalone launch.
	h.G().ExternalG().StartStandaloneChat()

	if err = chat.SendTextByName(ctx, h.G(), team, &chat.DefaultTeamTopic, chat1.ConversationMembersType_TEAM,
		keybase1.TLFIdentifyBehavior_CHAT_CLI, body, h.gregor.GetClient); err != nil {
		return false
	}

	return true
}

func (h *TeamsHandler) TeamAddMember(ctx context.Context, arg keybase1.TeamAddMemberArg) (keybase1.TeamAddMemberResult, error) {
	if arg.Email != "" {
		if err := teams.InviteEmailMember(ctx, h.G().ExternalG(), arg.Name, arg.Email, arg.Role); err != nil {
			return keybase1.TeamAddMemberResult{}, err
		}
		return keybase1.TeamAddMemberResult{Invited: true, EmailSent: true}, nil
	}
	result, err := teams.AddMember(ctx, h.G().ExternalG(), arg.Name, arg.Username, arg.Role)
	if err != nil {
		return keybase1.TeamAddMemberResult{}, err
	}
	if !arg.SendChatNotification {
		return result, nil
	}

	if result.Invited {
		return result, nil
	}

	result.ChatSent = h.sendTeamChatWelcomeMessage(ctx, arg.Name, result.User.Username)
	return result, nil
}

func (h *TeamsHandler) TeamRemoveMember(ctx context.Context, arg keybase1.TeamRemoveMemberArg) error {
	return teams.RemoveMember(ctx, h.G().ExternalG(), arg.Name, arg.Username)
}

func (h *TeamsHandler) TeamEditMember(ctx context.Context, arg keybase1.TeamEditMemberArg) error {
	return teams.EditMember(ctx, h.G().ExternalG(), arg.Name, arg.Username, arg.Role)
}

func (h *TeamsHandler) TeamLeave(ctx context.Context, arg keybase1.TeamLeaveArg) error {
	return teams.Leave(ctx, h.G().ExternalG(), arg.Name, arg.Permanent)
}

func (h *TeamsHandler) TeamRename(ctx context.Context, arg keybase1.TeamRenameArg) error {
	return teams.RenameSubteam(ctx, h.G().ExternalG(), arg.PrevName, arg.NewName)
}

func (h *TeamsHandler) TeamAcceptInvite(ctx context.Context, arg keybase1.TeamAcceptInviteArg) error {
	return teams.AcceptInvite(ctx, h.G().ExternalG(), arg.Token)
}

func (h *TeamsHandler) TeamRequestAccess(ctx context.Context, arg keybase1.TeamRequestAccessArg) error {
	return teams.RequestAccess(ctx, h.G().ExternalG(), arg.Name)
}

func (h *TeamsHandler) TeamAcceptInviteOrRequestAccess(ctx context.Context, arg keybase1.TeamAcceptInviteOrRequestAccessArg) error {
	return teams.TeamAcceptInviteOrRequestAccess(ctx, h.G().ExternalG(), arg.TokenOrName)
}

func (h *TeamsHandler) TeamListRequests(ctx context.Context, sessionID int) ([]keybase1.TeamJoinRequest, error) {
	return teams.ListRequests(ctx, h.G().ExternalG())
}

func (h *TeamsHandler) TeamIgnoreRequest(ctx context.Context, arg keybase1.TeamIgnoreRequestArg) error {
	return teams.IgnoreRequest(ctx, h.G().ExternalG(), arg.Name, arg.Username)
}

func (h *TeamsHandler) TeamTree(ctx context.Context, arg keybase1.TeamTreeArg) (res keybase1.TeamTreeResult, err error) {
	return teams.TeamTree(ctx, h.G().ExternalG(), arg)
}

func (h *TeamsHandler) TeamDelete(ctx context.Context, arg keybase1.TeamDeleteArg) error {
	ui := h.getTeamsUI(arg.SessionID)
	return teams.Delete(ctx, h.G().ExternalG(), ui, arg.Name)
}

func (h *TeamsHandler) LoadTeamPlusApplicationKeys(netCtx context.Context, arg keybase1.LoadTeamPlusApplicationKeysArg) (keybase1.TeamPlusApplicationKeys, error) {
	netCtx = libkb.WithLogTag(netCtx, "LTPAK")
	h.G().Log.CDebugf(netCtx, "+ TeamHandler#LoadTeamPlusApplicationKeys(%+v)", arg)
	return teams.LoadTeamPlusApplicationKeys(netCtx, h.G().ExternalG(), arg.Id, arg.Application, arg.Refreshers)
}

func (h *TeamsHandler) GetTeamRootID(ctx context.Context, id keybase1.TeamID) (keybase1.TeamID, error) {
	return teams.GetRootID(ctx, h.G().ExternalG(), id)
}

func (h *TeamsHandler) LookupImplicitTeam(ctx context.Context, arg keybase1.LookupImplicitTeamArg) (keybase1.TeamID, error) {
	teamID, _, err := teams.LookupImplicitTeam(ctx, h.G().ExternalG(), arg.Name, arg.Public)
	return teamID, err
}

func (h *TeamsHandler) LookupOrCreateImplicitTeam(ctx context.Context, arg keybase1.LookupOrCreateImplicitTeamArg) (keybase1.TeamID, error) {
	teamID, _, err := teams.LookupOrCreateImplicitTeam(ctx, h.G().ExternalG(), arg.Name, arg.Public)
	return teamID, err
}

func (h *TeamsHandler) TeamReAddMemberAfterReset(ctx context.Context, arg keybase1.TeamReAddMemberAfterResetArg) error {
	return teams.ReAddMemberAfterReset(ctx, h.G().ExternalG(), arg.Id, arg.Username)
}
<commit_msg>add tracing for team local RPCs<commit_after>// Copyright 2017 Keybase, Inc. All rights reserved. Use of
// this source code is governed by the included BSD license.

package service

import (
	"fmt"
	"strings"

	"github.com/keybase/client/go/chat"
	"github.com/keybase/client/go/chat/globals"
	"github.com/keybase/client/go/libkb"
	"github.com/keybase/client/go/protocol/chat1"
	keybase1 "github.com/keybase/client/go/protocol/keybase1"
	"github.com/keybase/client/go/teams"
	"github.com/keybase/go-framed-msgpack-rpc/rpc"
	"golang.org/x/net/context"
)

type TeamsHandler struct {
	*BaseHandler
	globals.Contextified
	gregor *gregorHandler
	connID libkb.ConnectionID
}

var _ keybase1.TeamsInterface = (*TeamsHandler)(nil)

func NewTeamsHandler(xp rpc.Transporter, id libkb.ConnectionID, g *globals.Context, gregor *gregorHandler) *TeamsHandler {
	return &TeamsHandler{
		BaseHandler:  NewBaseHandler(xp),
		Contextified: globals.NewContextified(g),
		gregor:       gregor,
		connID:       id,
	}
}

func (h *TeamsHandler) TeamCreate(ctx context.Context, arg keybase1.TeamCreateArg) (res keybase1.TeamCreateResult, err error) {
	defer h.G().CTrace(ctx, fmt.Sprintf("TeamCreate(%s)", arg.Name), func() error { return err })()
	teamName, err := keybase1.TeamNameFromString(arg.Name)
	if err != nil {
		return res, err
	}
	if !teamName.IsRootTeam() {
		h.G().Log.CDebugf(ctx, "TeamCreate: creating a new subteam: %s", arg.Name)
		if teamName.Depth() == 0 {
			return res, fmt.Errorf("empty team name")
		}
		parentName, err := teamName.Parent()
		if err != nil {
			return res, err
		}
		if _, err = teams.CreateSubteam(ctx, h.G().ExternalG(), string(teamName.LastPart()), parentName); err != nil {
			return res, err
		}
	} else {
		if err := teams.CreateRootTeam(ctx, h.G().ExternalG(), teamName.String()); err != nil {
			return res, err
		}
		res.CreatorAdded = true
	}

	if arg.SendChatNotification {
		res.ChatSent = h.sendTeamChatWelcomeMessage(ctx, teamName.String(), h.G().Env.GetUsername().String())
	}
	return res, nil
}

func (h *TeamsHandler) TeamGet(ctx context.Context, arg keybase1.TeamGetArg) (res keybase1.TeamDetails, err error) {
	defer h.G().CTrace(ctx, fmt.Sprintf("TeamGet(%s)", arg.Name), func() error { return err })()
	return teams.Details(ctx, h.G().ExternalG(), arg.Name, arg.ForceRepoll)
}

func (h *TeamsHandler) TeamList(ctx context.Context, arg keybase1.TeamListArg) (res keybase1.AnnotatedTeamList, err error) {
	defer h.G().CTrace(ctx, fmt.Sprintf("TeamList(%s)", arg.UserAssertion), func() error { return err })()
	x, err := teams.List(ctx, h.G().ExternalG(), arg)
	if err != nil {
		return keybase1.AnnotatedTeamList{}, err
	}
	return *x, nil
}

func (h *TeamsHandler) TeamChangeMembership(ctx context.Context, arg keybase1.TeamChangeMembershipArg) error {
	return teams.ChangeRoles(ctx, h.G().ExternalG(), arg.Name, arg.Req)
}

func (h *TeamsHandler) sendTeamChatWelcomeMessage(ctx context.Context, team, user string) (res bool) {
	var err error
	defer func() {
		if err != nil {
			h.G().Log.CWarningf(ctx, "failed to send team welcome message: %s", err.Error())
		}
	}()
	teamDetails, err := teams.Details(ctx, h.G().ExternalG(), team, true)
	if err != nil {
		return false
	}

	var ownerNames, adminNames, writerNames, readerNames []string
	for _, owner := range teamDetails.Members.Owners {
		ownerNames = append(ownerNames, owner.Username)
	}
	for _, admin := range teamDetails.Members.Admins {
		adminNames = append(adminNames, admin.Username)
	}
	for _, writer := range teamDetails.Members.Writers {
		writerNames = append(writerNames, writer.Username)
	}
	for _, reader := range teamDetails.Members.Readers {
		readerNames = append(readerNames, reader.Username)
	}
	var lines []string
	if len(ownerNames) > 0 {
		lines = append(lines, fmt.Sprintf("  owners: %s", strings.Join(ownerNames, ",")))
	}
	if len(adminNames) > 0 {
		lines = append(lines, fmt.Sprintf("  admins: %s", strings.Join(adminNames, ",")))
	}
	if len(writerNames) > 0 {
		lines = append(lines, fmt.Sprintf("  writers: %s", strings.Join(writerNames, ",")))
	}
	if len(readerNames) > 0 {
		lines = append(lines, fmt.Sprintf("  readers: %s", strings.Join(readerNames, ",")))
	}
	memberBody := strings.Join(lines, "\n")
	body := fmt.Sprintf("Hello @channel! I've just added @%s to this team. Current members:\n\n```%s```\n\n_More info on teams:_ keybase.io/blog/introducing-keybase-teams\n_To leave this team, visit the team tab or run `keybase team leave %s`_",
		user, memberBody, team)

	// Ensure we have chat available, since TeamAddMember may also be
	// coming from a standalone launch.
	h.G().ExternalG().StartStandaloneChat()

	if err = chat.SendTextByName(ctx, h.G(), team, &chat.DefaultTeamTopic, chat1.ConversationMembersType_TEAM,
		keybase1.TLFIdentifyBehavior_CHAT_CLI, body, h.gregor.GetClient); err != nil {
		return false
	}

	return true
}

func (h *TeamsHandler) TeamAddMember(ctx context.Context, arg keybase1.TeamAddMemberArg) (res keybase1.TeamAddMemberResult, err error) {
	defer h.G().CTrace(ctx, fmt.Sprintf("TeamAddMember(%s,%s)", arg.Name, arg.Username),
		func() error { return err })()
	if arg.Email != "" {
		if err := teams.InviteEmailMember(ctx, h.G().ExternalG(), arg.Name, arg.Email, arg.Role); err != nil {
			return keybase1.TeamAddMemberResult{}, err
		}
		return keybase1.TeamAddMemberResult{Invited: true, EmailSent: true}, nil
	}
	result, err := teams.AddMember(ctx, h.G().ExternalG(), arg.Name, arg.Username, arg.Role)
	if err != nil {
		return keybase1.TeamAddMemberResult{}, err
	}
	if !arg.SendChatNotification {
		return result, nil
	}

	if result.Invited {
		return result, nil
	}

	result.ChatSent = h.sendTeamChatWelcomeMessage(ctx, arg.Name, result.User.Username)
	return result, nil
}

func (h *TeamsHandler) TeamRemoveMember(ctx context.Context, arg keybase1.TeamRemoveMemberArg) (err error) {
	defer h.G().CTrace(ctx, fmt.Sprintf("TeamRemoveMember(%s,%s)", arg.Name, arg.Username),
		func() error { return err })()
	return teams.RemoveMember(ctx, h.G().ExternalG(), arg.Name, arg.Username)
}

func (h *TeamsHandler) TeamEditMember(ctx context.Context, arg keybase1.TeamEditMemberArg) (err error) {
	defer h.G().CTrace(ctx, fmt.Sprintf("TeamEditMember(%s,%s)", arg.Name, arg.Username),
		func() error { return err })()
	return teams.EditMember(ctx, h.G().ExternalG(), arg.Name, arg.Username, arg.Role)
}

func (h *TeamsHandler) TeamLeave(ctx context.Context, arg keybase1.TeamLeaveArg) (err error) {
	defer h.G().CTrace(ctx, fmt.Sprintf("TeamLeave(%s)", arg.Name), func() error { return err })()
	return teams.Leave(ctx, h.G().ExternalG(), arg.Name, arg.Permanent)
}

func (h *TeamsHandler) TeamRename(ctx context.Context, arg keybase1.TeamRenameArg) (err error) {
	defer h.G().CTrace(ctx, fmt.Sprintf("TeamRename(%s)", arg.PrevName), func() error { return err })()
	return teams.RenameSubteam(ctx, h.G().ExternalG(), arg.PrevName, arg.NewName)
}

func (h *TeamsHandler) TeamAcceptInvite(ctx context.Context, arg keybase1.TeamAcceptInviteArg) (err error) {
	defer h.G().CTrace(ctx, "TeamAcceptInvite", func() error { return err })()
	return teams.AcceptInvite(ctx, h.G().ExternalG(), arg.Token)
}

func (h *TeamsHandler) TeamRequestAccess(ctx context.Context, arg keybase1.TeamRequestAccessArg) (err error) {
	h.G().CTrace(ctx, "TeamRequestAccess", func() error { return err })()
	return teams.RequestAccess(ctx, h.G().ExternalG(), arg.Name)
}

func (h *TeamsHandler) TeamAcceptInviteOrRequestAccess(ctx context.Context, arg keybase1.TeamAcceptInviteOrRequestAccessArg) (err error) {
	defer h.G().CTrace(ctx, "TeamAcceptInviteOrRequestAccess", func() error { return err })()
	return teams.TeamAcceptInviteOrRequestAccess(ctx, h.G().ExternalG(), arg.TokenOrName)
}

func (h *TeamsHandler) TeamListRequests(ctx context.Context, sessionID int) (res []keybase1.TeamJoinRequest, err error) {
	defer h.G().CTrace(ctx, "TeamListRequests", func() error { return err })()
	return teams.ListRequests(ctx, h.G().ExternalG())
}

func (h *TeamsHandler) TeamIgnoreRequest(ctx context.Context, arg keybase1.TeamIgnoreRequestArg) (err error) {
	defer h.G().CTrace(ctx, "TeamIgnoreRequest", func() error { return err })()
	return teams.IgnoreRequest(ctx, h.G().ExternalG(), arg.Name, arg.Username)
}

func (h *TeamsHandler) TeamTree(ctx context.Context, arg keybase1.TeamTreeArg) (res keybase1.TeamTreeResult, err error) {
	defer h.G().CTrace(ctx, "TeamTree", func() error { return err })()
	return teams.TeamTree(ctx, h.G().ExternalG(), arg)
}

func (h *TeamsHandler) TeamDelete(ctx context.Context, arg keybase1.TeamDeleteArg) (err error) {
	defer h.G().CTrace(ctx, fmt.Sprintf("TeamDelete(%s)", arg.Name), func() error { return err })()
	ui := h.getTeamsUI(arg.SessionID)
	return teams.Delete(ctx, h.G().ExternalG(), ui, arg.Name)
}

func (h *TeamsHandler) LoadTeamPlusApplicationKeys(netCtx context.Context, arg keybase1.LoadTeamPlusApplicationKeysArg) (keybase1.TeamPlusApplicationKeys, error) {
	netCtx = libkb.WithLogTag(netCtx, "LTPAK")
	h.G().Log.CDebugf(netCtx, "+ TeamHandler#LoadTeamPlusApplicationKeys(%+v)", arg)
	return teams.LoadTeamPlusApplicationKeys(netCtx, h.G().ExternalG(), arg.Id, arg.Application, arg.Refreshers)
}

func (h *TeamsHandler) GetTeamRootID(ctx context.Context, id keybase1.TeamID) (keybase1.TeamID, error) {
	return teams.GetRootID(ctx, h.G().ExternalG(), id)
}

func (h *TeamsHandler) LookupImplicitTeam(ctx context.Context, arg keybase1.LookupImplicitTeamArg) (res keybase1.TeamID, err error) {
	defer h.G().CTrace(ctx, fmt.Sprintf("LookupImplicitTeam(%s)", arg.Name), func() error { return err })()
	teamID, _, err := teams.LookupImplicitTeam(ctx, h.G().ExternalG(), arg.Name, arg.Public)
	return teamID, err
}

func (h *TeamsHandler) LookupOrCreateImplicitTeam(ctx context.Context, arg keybase1.LookupOrCreateImplicitTeamArg) (res keybase1.TeamID, err error) {
	defer h.G().CTrace(ctx, fmt.Sprintf("LookupOrCreateImplicitTeam(%s)", arg.Name),
		func() error { return err })()
	teamID, _, err := teams.LookupOrCreateImplicitTeam(ctx, h.G().ExternalG(), arg.Name, arg.Public)
	return teamID, err
}

func (h *TeamsHandler) TeamReAddMemberAfterReset(ctx context.Context, arg keybase1.TeamReAddMemberAfterResetArg) error {
	return teams.ReAddMemberAfterReset(ctx, h.G().ExternalG(), arg.Id, arg.Username)
}
<|endoftext|>


<commit_before>// Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.

package main

import (
	"github.com/MustWin/baremetal-sdk-go"
	"github.com/hashicorp/terraform/helper/schema"
	"github.com/hashicorp/terraform/helper/validation"
)

func resourceObjectStorageMapToMetadata(rm map[string]interface{}) map[string]string {
	result := map[string]string{}
	for k, v := range rm {
		result[k] = v.(string)
	}
	return result
}

var bucketSchema = map[string]*schema.Schema{
	"compartment_id": {
		Type:     schema.TypeString,
		Required: true,
		Computed: false,
	},
	"name": {
		Type:     schema.TypeString,
		Required: true,
		Computed: false,
	},
	"namespace": {
		Type:     schema.TypeString,
		Required: true,
		Computed: false,
	},
	"access_type": {
		Type:     schema.TypeString,
		Computed: false,
		Default:  baremetal.NoPublicAccess,
		Optional: true,
		ValidateFunc: validation.StringInSlice([]string{
			string(baremetal.NoPublicAccess),
			string(baremetal.ObjectRead)}, true),
	},
	"metadata": {
		Type:     schema.TypeMap,
		Optional: true,
	},
}

var objectSchema = map[string]*schema.Schema{
	"namespace": {
		Type:     schema.TypeString,
		Required: true,
		Computed: false,
	},
	"bucket": {
		Type:     schema.TypeString,
		Required: true,
		Computed: false,
	},
	"object": {
		Type:     schema.TypeString,
		Required: true,
		Computed: false,
	},
	"content": {
		Type:     schema.TypeString,
		Optional: true,
	},
	"metadata": {
		Type:     schema.TypeMap,
		Optional: true,
	},
}

var preauthenticatedRequestSchema = map[string]*schema.Schema{
	"id": {
		Type:     schema.TypeString,
		Optional: true,
		Computed: true,
	},
	"namespace": {
		Type:     schema.TypeString,
		Required: true,
		Computed: false,
	},
	"name": {
		Type:     schema.TypeString,
		Required: true,
		Computed: false,
	},
	"bucket": {
		Type:     schema.TypeString,
		Required: true,
		Computed: false,
	},
	"object": {
		Type:     schema.TypeString,
		Optional: true,
		Computed: false,
	},
	"access_type": {
		Type:     schema.TypeString,
		Computed: false,
		Default:  baremetal.ObjectRead,
		Optional: true,
		ValidateFunc: validation.StringInSlice([]string{
			string(baremetal.PARAnyObjectWrite),
			string(baremetal.PARObjectRead),
			string(baremetal.PARObjectReadWrite),
			string(baremetal.ObjectRead)}, true),
	},
	"time_expires": {
		Type:     schema.TypeString,
		Computed: false,
		Required: true,
	},
}
<commit_msg>175 adding missing access_uri to schema<commit_after>// Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.

package main

import (
	"github.com/MustWin/baremetal-sdk-go"
	"github.com/hashicorp/terraform/helper/schema"
	"github.com/hashicorp/terraform/helper/validation"
)

func resourceObjectStorageMapToMetadata(rm map[string]interface{}) map[string]string {
	result := map[string]string{}
	for k, v := range rm {
		result[k] = v.(string)
	}
	return result
}

var bucketSchema = map[string]*schema.Schema{
	"compartment_id": {
		Type:     schema.TypeString,
		Required: true,
		Computed: false,
	},
	"name": {
		Type:     schema.TypeString,
		Required: true,
		Computed: false,
	},
	"namespace": {
		Type:     schema.TypeString,
		Required: true,
		Computed: false,
	},
	"access_type": {
		Type:     schema.TypeString,
		Computed: false,
		Default:  baremetal.NoPublicAccess,
		Optional: true,
		ValidateFunc: validation.StringInSlice([]string{
			string(baremetal.NoPublicAccess),
			string(baremetal.ObjectRead)}, true),
	},
	"metadata": {
		Type:     schema.TypeMap,
		Optional: true,
	},
}

var objectSchema = map[string]*schema.Schema{
	"namespace": {
		Type:     schema.TypeString,
		Required: true,
		Computed: false,
	},
	"bucket": {
		Type:     schema.TypeString,
		Required: true,
		Computed: false,
	},
	"object": {
		Type:     schema.TypeString,
		Required: true,
		Computed: false,
	},
	"content": {
		Type:     schema.TypeString,
		Optional: true,
	},
	"metadata": {
		Type:     schema.TypeMap,
		Optional: true,
	},
}

var preauthenticatedRequestSchema = map[string]*schema.Schema{
	"id": {
		Type:     schema.TypeString,
		Optional: true,
		Computed: true,
	},
	"namespace": {
		Type:     schema.TypeString,
		Required: true,
		Computed: false,
	},
	"name": {
		Type:     schema.TypeString,
		Required: true,
		Computed: false,
	},
	"bucket": {
		Type:     schema.TypeString,
		Required: true,
		Computed: false,
	},
	"object": {
		Type:     schema.TypeString,
		Optional: true,
		Computed: false,
	},
	"access_type": {
		Type:     schema.TypeString,
		Computed: false,
		Default:  baremetal.ObjectRead,
		Optional: true,
		ValidateFunc: validation.StringInSlice([]string{
			string(baremetal.PARAnyObjectWrite),
			string(baremetal.PARObjectRead),
			string(baremetal.PARObjectReadWrite),
			string(baremetal.ObjectRead)}, true),
	},
	"access_uri": {
		Type: schema.TypeString,
		Computed: true,
		Optional: true,
	},
	"time_expires": {
		Type:     schema.TypeString,
		Computed: false,
		Required: true,
	},
}
<|endoftext|>


<commit_before>package db

import (
	"database/sql"
	"time"

	sq "github.com/Masterminds/squirrel"
	"github.com/lib/pq"
)

var componentsQuery = psql.Select("c.id, c.name, c.interval, c.last_ran, c.paused").
	From("components c")

//go:generate counterfeiter . Component

type Component interface {
	ID() int
	Name() string
	Interval() string
	LastRan() time.Time
	Paused() bool

	Reload() (bool, error)
	IntervalElapsed() bool
	UpdateLastRan() error
}

type component struct {
	id       int
	name     string
	interval string
	lastRan  time.Time
	paused   bool

	conn Conn
}

func (c *component) ID() int            { return c.id }
func (c *component) Name() string       { return c.name }
func (c *component) Interval() string   { return c.interval }
func (c *component) LastRan() time.Time { return c.lastRan }
func (c *component) Paused() bool       { return c.paused }

func (c *component) Reload() (bool, error) {
	row := componentsQuery.Where(sq.Eq{"c.id": c.id}).
		RunWith(c.conn).
		QueryRow()

	err := scanComponent(c, row)
	if err != nil {
		if err == sql.ErrNoRows {
			return false, nil
		}
		return false, err
	}

	return true, nil
}

func (c *component) IntervalElapsed() bool {
	inveral, err := time.ParseDuration(c.interval)

	if err != nil {
		panic(err)
	}

	return time.Now().After(c.lastRan.Add(inveral))
}

func (c *component) UpdateLastRan() error {

	_, err := psql.Update("components").
		Set("last_ran", sq.Expr("now()")).
		Where(sq.Eq{
			"id": c.id,
		}).
		RunWith(c.conn).
		Exec()
	if err != nil {
		return err
	}

	return nil
}

func scanComponent(c *component, row scannable) error {
	var (
		lastRan pq.NullTime
	)

	err := row.Scan(
		&c.id,
		&c.name,
		&c.interval,
		&lastRan,
		&c.paused,
	)
	if err != nil {
		return err
	}

	c.lastRan = lastRan.Time

	return nil
}
<commit_msg>nit: fix typo atc/db/component<commit_after>package db

import (
	"database/sql"
	"time"

	sq "github.com/Masterminds/squirrel"
	"github.com/lib/pq"
)

var componentsQuery = psql.Select("c.id, c.name, c.interval, c.last_ran, c.paused").
	From("components c")

//go:generate counterfeiter . Component

type Component interface {
	ID() int
	Name() string
	Interval() string
	LastRan() time.Time
	Paused() bool

	Reload() (bool, error)
	IntervalElapsed() bool
	UpdateLastRan() error
}

type component struct {
	id       int
	name     string
	interval string
	lastRan  time.Time
	paused   bool

	conn Conn
}

func (c *component) ID() int            { return c.id }
func (c *component) Name() string       { return c.name }
func (c *component) Interval() string   { return c.interval }
func (c *component) LastRan() time.Time { return c.lastRan }
func (c *component) Paused() bool       { return c.paused }

func (c *component) Reload() (bool, error) {
	row := componentsQuery.Where(sq.Eq{"c.id": c.id}).
		RunWith(c.conn).
		QueryRow()

	err := scanComponent(c, row)
	if err != nil {
		if err == sql.ErrNoRows {
			return false, nil
		}
		return false, err
	}

	return true, nil
}

func (c *component) IntervalElapsed() bool {
	interval, err := time.ParseDuration(c.interval)

	if err != nil {
		panic(err)
	}

	return time.Now().After(c.lastRan.Add(interval))
}

func (c *component) UpdateLastRan() error {

	_, err := psql.Update("components").
		Set("last_ran", sq.Expr("now()")).
		Where(sq.Eq{
			"id": c.id,
		}).
		RunWith(c.conn).
		Exec()
	if err != nil {
		return err
	}

	return nil
}

func scanComponent(c *component, row scannable) error {
	var (
		lastRan pq.NullTime
	)

	err := row.Scan(
		&c.id,
		&c.name,
		&c.interval,
		&lastRan,
		&c.paused,
	)
	if err != nil {
		return err
	}

	c.lastRan = lastRan.Time

	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"github.com/cpuguy83/docker-grand-ambassador/docker"
	"github.com/cpuguy83/docker-grand-ambassador/proxy"
	"github.com/cpuguy83/docker-grand-ambassador/utils"
	"log"
	"net"
	"os"
)

var (
	dockerClient docker.Docker
)

func main() {
	var (
		socket        = flag.String("sock", "/var/run/docker.sock", "Path to docker socket")
		containerName = flag.String("name", "", "Name/ID of container to ambassadorize")
		err           error
	)

	flag.Parse()

	if *containerName == "" {
		fmt.Println("Missing required arguments")
		os.Exit(1)
	}

	dockerClient, err := docker.NewClient(*socket)
	if err != nil {
		log.Printf("Could not connect to Docker: %s", err)
		os.Exit(1)
	}
	container, err := dockerClient.FetchContainer(*containerName)
	if err != nil {
		log.Printf("%v", err)
		os.Exit(1)
	}

	proxyChan := makeProxyChan(container)

	log.Printf("Initializing proxy")
	if err = proxyContainer(container, proxyChan); err != nil {
		log.Printf("%v", err)
		os.Exit(1)
	}

	events := dockerClient.GetEvents()
	go handleEvents(container, events, dockerClient, proxyChan)

	wait := make(chan bool)
	<-wait
}

func handleEvents(container *docker.Container, eventChan chan *docker.Event, dockerClient docker.Docker, proxyChan chan net.Listener) error {
	var err error
	log.Printf("Handling Events for: %v: %v", container.Id, container.Name)
	for event := range eventChan {
		if container.Id == event.ContainerId {
			log.Printf("Received event: %v", event)
			switch event.Status {
			case "die", "stop", "kill":
				log.Printf("Handling event for stop/die/kill")
				for srv := range proxyChan {
					srv.Close()
				}
			case "start", "restart":
				log.Printf("Handling event start/restart")
				c, err := dockerClient.FetchContainer(event.ContainerId)
				if err != nil {
					log.Printf("%v", err)
					os.Exit(2)
				}
				log.Printf("Closing old servers")
				for srv := range proxyChan {
					srv.Close()
				}
				log.Printf("Servers closed")
				proxyChan = makeProxyChan(container)
				if err = proxyContainer(c, proxyChan); err != nil {
					log.Printf("%v", err)
					os.Exit(2)
				}
			default:
				log.Printf("Not handling event: %v", event)
			}
		}
	}
	log.Printf("Stopped handling events")
	return nil
}

func proxyContainer(container *docker.Container, proxyChan chan net.Listener) error {
	ip := container.NetworkSettings.IpAddress
	ports := container.NetworkSettings.Ports
	if len(ports) != 0 {
		for key, _ := range ports {
			port, proto := utils.SplitPort(key)
			local := fmt.Sprintf("%v://0.0.0.0:%v", proto, port)
			remote := fmt.Sprintf("%v://%v:%v", proto, ip, port)
			out := fmt.Sprintf("Proxying %s:%s/%s", ip, port, proto)
			log.Printf(out)
			srv, err := gocat.NewProxy(local, remote)
			if err != nil {
				return err
			}
			proxyChan <- srv
		}
	}
	close(proxyChan)
	return nil
}

func makeProxyChan(container *docker.Container) chan net.Listener {
	return make(chan net.Listener, len(container.NetworkSettings.Ports))
}
<commit_msg>Fix issues referring to old `gocat` package<commit_after>package main

import (
	"flag"
	"fmt"
	"log"
	"net"
	"os"

	"github.com/cpuguy83/docker-grand-ambassador/docker"
	"github.com/cpuguy83/docker-grand-ambassador/proxy"
	"github.com/cpuguy83/docker-grand-ambassador/utils"
)

var (
	dockerClient docker.Docker
)

func main() {
	var (
		socket        = flag.String("sock", "/var/run/docker.sock", "Path to docker socket")
		containerName = flag.String("name", "", "Name/ID of container to ambassadorize")
		err           error
	)

	flag.Parse()

	if *containerName == "" {
		fmt.Println("Missing required arguments")
		os.Exit(1)
	}

	dockerClient, err := docker.NewClient(*socket)
	if err != nil {
		log.Printf("Could not connect to Docker: %s", err)
		os.Exit(1)
	}
	container, err := dockerClient.FetchContainer(*containerName)
	if err != nil {
		log.Printf("%v", err)
		os.Exit(1)
	}

	proxyChan := makeProxyChan(container)

	log.Printf("Initializing proxy")
	if err = proxyContainer(container, proxyChan); err != nil {
		log.Printf("%v", err)
		os.Exit(1)
	}

	events := dockerClient.GetEvents()
	go handleEvents(container, events, dockerClient, proxyChan)

	wait := make(chan bool)
	<-wait
}

func handleEvents(container *docker.Container, eventChan chan *docker.Event, dockerClient docker.Docker, proxyChan chan net.Listener) {
	log.Printf("Handling Events for: %v: %v", container.Id, container.Name)
	for event := range eventChan {
		if container.Id == event.ContainerId {
			log.Printf("Received event: %v", event)
			switch event.Status {
			case "die", "stop", "kill":
				log.Printf("Handling event for stop/die/kill")
				for srv := range proxyChan {
					srv.Close()
				}
			case "start", "restart":
				log.Printf("Handling event start/restart")
				c, err := dockerClient.FetchContainer(event.ContainerId)
				if err != nil {
					log.Printf("%v", err)
					os.Exit(2)
				}
				log.Printf("Closing old servers")
				for srv := range proxyChan {
					srv.Close()
				}
				log.Printf("Servers closed")
				proxyChan = makeProxyChan(container)
				if err = proxyContainer(c, proxyChan); err != nil {
					log.Printf("%v", err)
					os.Exit(2)
				}
			default:
				log.Printf("Not handling event: %v", event)
			}
		}
	}
	log.Printf("Stopped handling events")
}

func proxyContainer(container *docker.Container, proxyChan chan net.Listener) error {
	ip := container.NetworkSettings.IpAddress
	ports := container.NetworkSettings.Ports
	if len(ports) != 0 {
		for key, _ := range ports {
			port, proto := utils.SplitPort(key)
			local := fmt.Sprintf("%v://0.0.0.0:%v", proto, port)
			remote := fmt.Sprintf("%v://%v:%v", proto, ip, port)
			out := fmt.Sprintf("Proxying %s:%s/%s", ip, port, proto)
			log.Printf(out)
			srv, err := proxy.NewProxy(local, remote)
			if err != nil {
				return err
			}
			proxyChan <- srv
		}
	}
	close(proxyChan)
	return nil
}

func makeProxyChan(container *docker.Container) chan net.Listener {
	return make(chan net.Listener, len(container.NetworkSettings.Ports))
}
<|endoftext|>