<commit_before>package githubprovider

import (
	"errors"
	"fmt"
	"strings"

	"github.com/google/go-github/github"
	"github.com/hashicorp/terraform/helper/schema"
)

var (
	admin  string = "admin"
	member string = "member"
)

// required field are here for adding a user to the organization
func resourceGithubAddUser() *schema.Resource {
	return &schema.Resource{
		Create: resourceGithubAddUserCreate,
		Read:   resourceGithubAddUserRead,
		Update: resourceGithubAddUserCreate,
		Delete: resourceGithubAddUserDelete,

		Schema: map[string]*schema.Schema{
			"username": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
			},

			// role is the required for the membership
			// its value is member as default.
			"role": &schema.Schema{
				Type:     schema.TypeString,
				Optional: true,
				Default:  "member",
			},

			// repos is the repos that the organization has
			"repos": &schema.Schema{
				Type:     schema.TypeList,
				Elem:     &schema.Schema{Type: schema.TypeString},
				Required: true,
			},

			// organization is the name of the organization
			"organization": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
			},

			"teams": &schema.Schema{
				Type:     schema.TypeList,
				Elem:     &schema.Schema{Type: schema.TypeString},
				Required: true,
			},

			// title is the title of the SSH Key
			"title": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
			},

			// SSHKey is the public key of the user
			"SSHKey": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
			},
		},
	}
}

// GetTeamIDs gets the teams id of the organization
func GetTeamIDs(client *github.Client, org string, teamNames []string) ([]int, error) {
	currentPage := 1

	var teamIDs []int

	for {
		options := &github.ListOptions{
			PerPage: 100,
			Page:    currentPage,
		}

		teams, resp, err := client.Organizations.ListTeams(org, options)
		if err != nil {
			return nil, err
		}

		if len(teams) == 0 {
			break
		}
		// Iterate over all teams and add current user to related team(s)
		for i, team := range teams {
			for _, teamName := range teamNames {
				if *team.Name == teamName {
					teamIDs = append(teamIDs, *teams[i].ID)
				}
			}
		}

		if currentPage == resp.LastPage {
			break
		}

		currentPage = resp.NextPage
	}

	return teamIDs, nil
}

// resourceGithubAddUserCreate adds the user to the organization & the teams
func resourceGithubAddUserCreate(d *schema.ResourceData, meta interface{}) error {
	clientOrg := meta.(*Clients).OrgClient
	client := meta.(*Clients).UserClient

	org := d.Get("organization").(string)
	user := d.Get("username").(string)
	teamNames := interfaceToStringSlice(d.Get("teams"))
	role := d.Get("role").(string)

	if err := checkScopePermissions(client, user); err != nil {
		return err
	}

	if len(teamNames) == 0 {
		return errors.New("team name is not defined")
	}

	member, _, err := client.Organizations.GetOrgMembership("", org)
	if err != nil {
		return err
	}

	// override member role here if user is admin of organization
	if member.Role == &admin {
		role = admin
	}

	teamIDs, err := GetTeamIDs(clientOrg, org, teamNames)

	optAddOrgMembership := &github.OrganizationAddTeamMembershipOptions{
		Role: role,
	}

	if len(teamNames) != len(teamIDs) {
		return errors.New("team name is not found")
	}

	for _, teamID := range teamIDs {
		_, _, err := clientOrg.Organizations.AddTeamMembership(teamID, user, optAddOrgMembership)
		if err != nil {
			return err
		}
	}

	active := "active"

	membership := &github.Membership{
		// state should be active to add the user into organization
		State: &active,

		// Role is the required for the membership
		Role: &role,
	}

	// EditOrgMembership edits the membership for user in specified organization.
	// if user is authenticated, we dont need to set 1.parameter as user
	_, _, err = client.Organizations.EditOrgMembership("", org, membership)
	if err != nil {
		return err
	}

	for _, repo := range interfaceToStringSlice(d.Get("repos")) {
		// Creates a fork for the authenticated user.
		_, _, err = client.Repositories.CreateFork(org, repo, nil)
		if err != nil {
			return err
		}
	}

	title := d.Get("title").(string)
	keySSH := d.Get("SSHKey").(string)

	key := &github.Key{
		Title: &title,
		Key:   &keySSH,
	}

	// CreateKey creates a public key. Requires that you are authenticated via Basic Auth,
	// or OAuth with at least `write:public_key` scope.
	//
	// If SSH key is already set up, when u try to add same SSHKEY then
	//you are gonna get 422: Validation error.
	_, _, err = client.Users.CreateKey(key)
	if err != nil && !isErr422ValidationFailed(err) {
		return err
	}

	d.SetId(user)

	return nil
}

func resourceGithubAddUserRead(d *schema.ResourceData, meta interface{}) error {
	org := d.Get("organization").(string)
	user := d.Get("username").(string)
	role := d.Get("role").(string)
	teamNames := interfaceToStringSlice(d.Get("teams"))
	repos := interfaceToStringSlice(d.Get("repos"))
	fmt.Println("org: %v, user: %v,role: %v, teamnames: %v, repos: %v",
		org,
		user,
		role,
		teamNames,
		repos,
	)

	return nil
}

// resourceGithubAddUserCreate removes the user from the organization & the teams
func resourceGithubAddUserDelete(d *schema.ResourceData, meta interface{}) error {
	// We'r not gonna use removemember for now.
	// And then we can simply return here
	return nil

	client := meta.(*Clients).OrgClient

	user := d.Get("username").(string)
	org := d.Get("organization").(string)

	// Removing a user from this list will remove them from all teams and
	// they will no longer have any access to the organization’s repositories.
	_, err := client.Organizations.RemoveMember(org, user)
	return err
}

func getKeyID(client *github.Client, user, title string) (int, error) {
	keys, _, err := client.Users.ListKeys(user, nil)
	if err != nil {
		return 0, err
	}

	for _, key := range keys {
		if *key.Title == title {
			return *key.ID, nil
		}
	}

	return 0, err
}

// interfaceToStringSlice converts the interface to slice of string
func interfaceToStringSlice(s interface{}) []string {
	slice, ok := s.([]interface{})
	if !ok {
		return nil
	}

	sslice := make([]string, len(slice))
	for i := range slice {
		sslice[i] = slice[i].(string)
	}

	return sslice
}

func checkScopePermissions(client *github.Client, username string) error {
	arr, err := getScopes(client, username)
	if err != nil {
		return err
	}

	// we created 2-dimensional array for scopes.
	scopeArray := [][]string{
		// if user enables one of this scopes, then its OK to go..
		{"write:public_key", "admin:public_key"},
		{"user"},
		{"repo", "public_repo"},
		{"admin:org"},
	}

	for _, scopeElement := range scopeArray {
		if !(isInArray(arr, scopeElement)) {
			scopeErr := fmt.Errorf("Could not find required scope :", scopeElement)
			return scopeErr
		}
	}

	return nil
}

func getScopes(client *github.Client, username string) ([]string, error) {
	var scopes []string
	_, resp, err := client.Users.Get(username)
	if err != nil {
		return scopes, err
	}

	list := resp.Header.Get("X-Oauth-Scopes")
	scopes = strings.Split(list, ", ")

	return scopes, nil
}

func isInArray(arr, item []string) bool {
	for _, a := range arr {
		for _, i := range item {
			if a == i {
				return true
			}
		}
	}
	return false
}

// isErr422ValidationFailed return true if error contains the string:
// '422 Validation Failed'. This error is special cased so we can ignore it on
// when it occurs during rebuilding of stack template.
func isErr422ValidationFailed(err error) bool {
	return err != nil && strings.Contains(err.Error(), "422 Validation Failed")
}
<commit_msg>github: change current page value as 0 from 1<commit_after>package githubprovider

import (
	"errors"
	"fmt"
	"strings"

	"github.com/google/go-github/github"
	"github.com/hashicorp/terraform/helper/schema"
)

var (
	admin  string = "admin"
	member string = "member"
)

// required field are here for adding a user to the organization
func resourceGithubAddUser() *schema.Resource {
	return &schema.Resource{
		Create: resourceGithubAddUserCreate,
		Read:   resourceGithubAddUserRead,
		Update: resourceGithubAddUserCreate,
		Delete: resourceGithubAddUserDelete,

		Schema: map[string]*schema.Schema{
			"username": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
			},

			// role is the required for the membership
			// its value is member as default.
			"role": &schema.Schema{
				Type:     schema.TypeString,
				Optional: true,
				Default:  "member",
			},

			// repos is the repos that the organization has
			"repos": &schema.Schema{
				Type:     schema.TypeList,
				Elem:     &schema.Schema{Type: schema.TypeString},
				Required: true,
			},

			// organization is the name of the organization
			"organization": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
			},

			"teams": &schema.Schema{
				Type:     schema.TypeList,
				Elem:     &schema.Schema{Type: schema.TypeString},
				Required: true,
			},

			// title is the title of the SSH Key
			"title": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
			},

			// SSHKey is the public key of the user
			"SSHKey": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
			},
		},
	}
}

// GetTeamIDs gets the teams id of the organization
func GetTeamIDs(client *github.Client, org string, teamNames []string) ([]int, error) {
	currentPage := 0

	var teamIDs []int

	for {
		options := &github.ListOptions{
			PerPage: 100,
			Page:    currentPage,
		}

		teams, resp, err := client.Organizations.ListTeams(org, options)
		if err != nil {
			return nil, err
		}

		if len(teams) == 0 {
			break
		}
		// Iterate over all teams and add current user to related team(s)
		for i, team := range teams {
			for _, teamName := range teamNames {
				if *team.Name == teamName {
					teamIDs = append(teamIDs, *teams[i].ID)
				}
			}
		}

		if currentPage == resp.LastPage {
			break
		}

		currentPage = resp.NextPage
	}

	return teamIDs, nil
}

// resourceGithubAddUserCreate adds the user to the organization & the teams
func resourceGithubAddUserCreate(d *schema.ResourceData, meta interface{}) error {
	clientOrg := meta.(*Clients).OrgClient
	client := meta.(*Clients).UserClient

	org := d.Get("organization").(string)
	user := d.Get("username").(string)
	teamNames := interfaceToStringSlice(d.Get("teams"))
	role := d.Get("role").(string)

	if err := checkScopePermissions(client, user); err != nil {
		return err
	}

	if len(teamNames) == 0 {
		return errors.New("team name is not defined")
	}

	member, _, err := client.Organizations.GetOrgMembership("", org)
	if err != nil {
		return err
	}

	// override member role here if user is admin of organization
	if member.Role == &admin {
		role = admin
	}

	teamIDs, err := GetTeamIDs(clientOrg, org, teamNames)

	optAddOrgMembership := &github.OrganizationAddTeamMembershipOptions{
		Role: role,
	}

	if len(teamNames) != len(teamIDs) {
		return errors.New("team name is not found")
	}

	for _, teamID := range teamIDs {
		_, _, err := clientOrg.Organizations.AddTeamMembership(teamID, user, optAddOrgMembership)
		if err != nil {
			return err
		}
	}

	active := "active"

	membership := &github.Membership{
		// state should be active to add the user into organization
		State: &active,

		// Role is the required for the membership
		Role: &role,
	}

	// EditOrgMembership edits the membership for user in specified organization.
	// if user is authenticated, we dont need to set 1.parameter as user
	_, _, err = client.Organizations.EditOrgMembership("", org, membership)
	if err != nil {
		return err
	}

	for _, repo := range interfaceToStringSlice(d.Get("repos")) {
		// Creates a fork for the authenticated user.
		_, _, err = client.Repositories.CreateFork(org, repo, nil)
		if err != nil {
			return err
		}
	}

	title := d.Get("title").(string)
	keySSH := d.Get("SSHKey").(string)

	key := &github.Key{
		Title: &title,
		Key:   &keySSH,
	}

	// CreateKey creates a public key. Requires that you are authenticated via Basic Auth,
	// or OAuth with at least `write:public_key` scope.
	//
	// If SSH key is already set up, when u try to add same SSHKEY then
	//you are gonna get 422: Validation error.
	_, _, err = client.Users.CreateKey(key)
	if err != nil && !isErr422ValidationFailed(err) {
		return err
	}

	d.SetId(user)

	return nil
}

func resourceGithubAddUserRead(d *schema.ResourceData, meta interface{}) error {
	org := d.Get("organization").(string)
	user := d.Get("username").(string)
	role := d.Get("role").(string)
	teamNames := interfaceToStringSlice(d.Get("teams"))
	repos := interfaceToStringSlice(d.Get("repos"))
	fmt.Println("org: %v, user: %v,role: %v, teamnames: %v, repos: %v",
		org,
		user,
		role,
		teamNames,
		repos,
	)

	return nil
}

// resourceGithubAddUserCreate removes the user from the organization & the teams
func resourceGithubAddUserDelete(d *schema.ResourceData, meta interface{}) error {
	// We'r not gonna use removemember for now.
	// And then we can simply return here
	return nil

	client := meta.(*Clients).OrgClient

	user := d.Get("username").(string)
	org := d.Get("organization").(string)

	// Removing a user from this list will remove them from all teams and
	// they will no longer have any access to the organization’s repositories.
	_, err := client.Organizations.RemoveMember(org, user)
	return err
}

func getKeyID(client *github.Client, user, title string) (int, error) {
	keys, _, err := client.Users.ListKeys(user, nil)
	if err != nil {
		return 0, err
	}

	for _, key := range keys {
		if *key.Title == title {
			return *key.ID, nil
		}
	}

	return 0, err
}

// interfaceToStringSlice converts the interface to slice of string
func interfaceToStringSlice(s interface{}) []string {
	slice, ok := s.([]interface{})
	if !ok {
		return nil
	}

	sslice := make([]string, len(slice))
	for i := range slice {
		sslice[i] = slice[i].(string)
	}

	return sslice
}

func checkScopePermissions(client *github.Client, username string) error {
	arr, err := getScopes(client, username)
	if err != nil {
		return err
	}

	// we created 2-dimensional array for scopes.
	scopeArray := [][]string{
		// if user enables one of this scopes, then its OK to go..
		{"write:public_key", "admin:public_key"},
		{"user"},
		{"repo", "public_repo"},
		{"admin:org"},
	}

	for _, scopeElement := range scopeArray {
		if !(isInArray(arr, scopeElement)) {
			scopeErr := fmt.Errorf("Could not find required scope :", scopeElement)
			return scopeErr
		}
	}

	return nil
}

func getScopes(client *github.Client, username string) ([]string, error) {
	var scopes []string
	_, resp, err := client.Users.Get(username)
	if err != nil {
		return scopes, err
	}

	list := resp.Header.Get("X-Oauth-Scopes")
	scopes = strings.Split(list, ", ")

	return scopes, nil
}

func isInArray(arr, item []string) bool {
	for _, a := range arr {
		for _, i := range item {
			if a == i {
				return true
			}
		}
	}
	return false
}

// isErr422ValidationFailed return true if error contains the string:
// '422 Validation Failed'. This error is special cased so we can ignore it on
// when it occurs during rebuilding of stack template.
func isErr422ValidationFailed(err error) bool {
	return err != nil && strings.Contains(err.Error(), "422 Validation Failed")
}
<|endoftext|>


<commit_before>package pexlist

import (
	"net"
	"strings"

	"github.com/cenkalti/rain/torrent/internal/tracker"
)

type PEXList struct {
	added   map[tracker.CompactPeer]struct{}
	dropped map[tracker.CompactPeer]struct{}
}

func New() *PEXList {
	return &PEXList{
		added:   make(map[tracker.CompactPeer]struct{}),
		dropped: make(map[tracker.CompactPeer]struct{}),
	}
}

func (l *PEXList) Add(addr *net.TCPAddr) {
	p := tracker.NewCompactPeer(addr)
	l.added[p] = struct{}{}
	delete(l.dropped, p)
}

func (l *PEXList) Drop(addr *net.TCPAddr) {
	peer := tracker.NewCompactPeer(addr)
	l.dropped[peer] = struct{}{}
	delete(l.added, peer)
}

func (l *PEXList) Clear() {
	l.added = make(map[tracker.CompactPeer]struct{})
	l.dropped = make(map[tracker.CompactPeer]struct{})
}

func (l *PEXList) Flush() (added, dropped string) {
	return l.flush(l.added), l.flush(l.dropped)
}

func (l *PEXList) flush(m map[tracker.CompactPeer]struct{}) string {
	var s strings.Builder
	s.Grow(len(l.added) * 6)
	for p := range m {
		b, err := p.MarshalBinary()
		if err != nil {
			panic(err)
		}
		s.Write(b)
		delete(m, p)
	}
	return s.String()
}
<commit_msg>fix pex<commit_after>package pexlist

import (
	"net"
	"strings"

	"github.com/cenkalti/rain/torrent/internal/tracker"
)

type PEXList struct {
	added   map[tracker.CompactPeer]struct{}
	dropped map[tracker.CompactPeer]struct{}
}

func New() *PEXList {
	return &PEXList{
		added:   make(map[tracker.CompactPeer]struct{}),
		dropped: make(map[tracker.CompactPeer]struct{}),
	}
}

func (l *PEXList) Add(addr *net.TCPAddr) {
	p := tracker.NewCompactPeer(addr)
	l.added[p] = struct{}{}
	delete(l.dropped, p)
}

func (l *PEXList) Drop(addr *net.TCPAddr) {
	peer := tracker.NewCompactPeer(addr)
	l.dropped[peer] = struct{}{}
	delete(l.added, peer)
}

func (l *PEXList) Clear() {
	l.added = make(map[tracker.CompactPeer]struct{})
	l.dropped = make(map[tracker.CompactPeer]struct{})
}

func (l *PEXList) Flush() (added, dropped string) {
	return l.flush(l.added), l.flush(l.dropped)
}

func (l *PEXList) flush(m map[tracker.CompactPeer]struct{}) string {
	var s strings.Builder
	s.Grow(len(m) * 6)
	for p := range m {
		b, err := p.MarshalBinary()
		if err != nil {
			panic(err)
		}
		s.Write(b)
		delete(m, p)
	}
	return s.String()
}
<|endoftext|>


<commit_before>// Copyright 2016-2020 The Libsacloud Authors
//
// 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 archive

import (
	"context"
	"io"

	"github.com/sacloud/libsacloud/v2/sacloud"
	"github.com/sacloud/libsacloud/v2/sacloud/types"
)

// Builder アーカイブビルダーが持つ共通インターフェース
type Builder interface {
	Build(ctx context.Context, zone string) (*sacloud.Archive, error)
	Validate(ctx context.Context, zone string) error
}

// Director パラメータに応じて適切なアーカイブビルダーを返す
type Director struct {
	Name        string
	Description string
	Tags        types.Tags
	IconID      types.ID
	SizeGB      int

	// for blank builder
	SourceReader io.Reader

	// for standard builder
	SourceDiskID    types.ID
	SourceArchiveID types.ID

	// transfer archive builder
	SourceArchiveZone string

	// for shared archive builder
	SourceSharedKey types.ArchiveShareKey

	Client *APIClient
}

// パラメータに応じて適切なアーカイブビルダーを返す
//
// Note: 他ゾーンからの転送の場合、転送元/先でゾーンが同一でもエラーとならない。
// このためDirectorでは転送元/先ゾーンを意識せずにSourceArchiveZoneが指定されていた場合は
// 一律でTransferArchiveBuilderを返す。
//
// もしこの挙動で問題が発生する場合は呼び出し側で適切にビルダーを切り替える実装を行う必要がある。
func (d *Director) Builder() Builder {
	if d.SourceReader != nil {
		return &BlankArchiveBuilder{
			Name:         d.Name,
			Description:  d.Description,
			Tags:         d.Tags,
			IconID:       d.IconID,
			SizeGB:       d.SizeGB,
			SourceReader: d.SourceReader,
			Client:       d.Client,
		}
	}
	if d.SourceSharedKey.String() != "" {
		return &FromSharedArchiveBuilder{
			Name:            d.Name,
			Description:     d.Description,
			Tags:            d.Tags,
			IconID:          d.IconID,
			SourceSharedKey: d.SourceSharedKey,
			Client:          d.Client,
		}
	}

	if d.SourceArchiveZone != "" {
		return &TransferArchiveBuilder{
			Name:              d.Name,
			Description:       d.Description,
			Tags:              d.Tags,
			IconID:            d.IconID,
			SourceArchiveID:   d.SourceArchiveID,
			SourceArchiveZone: d.SourceArchiveZone,
			Client:            nil,
		}
	}

	return &StandardArchiveBuilder{
		Name:            d.Name,
		Description:     d.Description,
		Tags:            d.Tags,
		IconID:          d.IconID,
		SourceDiskID:    d.SourceDiskID,
		SourceArchiveID: d.SourceArchiveID,
		Client:          d.Client,
	}
}
<commit_msg>Fix ArchiveDirector<commit_after>// Copyright 2016-2020 The Libsacloud Authors
//
// 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 archive

import (
	"context"
	"io"

	"github.com/sacloud/libsacloud/v2/sacloud"
	"github.com/sacloud/libsacloud/v2/sacloud/types"
)

// Builder アーカイブビルダーが持つ共通インターフェース
type Builder interface {
	Build(ctx context.Context, zone string) (*sacloud.Archive, error)
	Validate(ctx context.Context, zone string) error
}

// Director パラメータに応じて適切なアーカイブビルダーを返す
type Director struct {
	Name        string
	Description string
	Tags        types.Tags
	IconID      types.ID
	SizeGB      int

	// for blank builder
	SourceReader io.Reader

	// for standard builder
	SourceDiskID    types.ID
	SourceArchiveID types.ID

	// transfer archive builder
	SourceArchiveZone string

	// for shared archive builder
	SourceSharedKey types.ArchiveShareKey

	Client *APIClient
}

// パラメータに応じて適切なアーカイブビルダーを返す
//
// Note: 他ゾーンからの転送の場合、転送元/先でゾーンが同一でもエラーとならない。
// このためDirectorでは転送元/先ゾーンを意識せずにSourceArchiveZoneが指定されていた場合は
// 一律でTransferArchiveBuilderを返す。
//
// もしこの挙動で問題が発生する場合は呼び出し側で適切にビルダーを切り替える実装を行う必要がある。
func (d *Director) Builder() Builder {
	if d.SourceReader != nil {
		return &BlankArchiveBuilder{
			Name:         d.Name,
			Description:  d.Description,
			Tags:         d.Tags,
			IconID:       d.IconID,
			SizeGB:       d.SizeGB,
			SourceReader: d.SourceReader,
			Client:       d.Client,
		}
	}
	if d.SourceSharedKey.String() != "" {
		return &FromSharedArchiveBuilder{
			Name:            d.Name,
			Description:     d.Description,
			Tags:            d.Tags,
			IconID:          d.IconID,
			SourceSharedKey: d.SourceSharedKey,
			Client:          d.Client,
		}
	}

	if d.SourceArchiveZone != "" {
		return &TransferArchiveBuilder{
			Name:              d.Name,
			Description:       d.Description,
			Tags:              d.Tags,
			IconID:            d.IconID,
			SourceArchiveID:   d.SourceArchiveID,
			SourceArchiveZone: d.SourceArchiveZone,
			Client:            d.Client,
		}
	}

	return &StandardArchiveBuilder{
		Name:            d.Name,
		Description:     d.Description,
		Tags:            d.Tags,
		IconID:          d.IconID,
		SourceDiskID:    d.SourceDiskID,
		SourceArchiveID: d.SourceArchiveID,
		Client:          d.Client,
	}
}
<|endoftext|>


<commit_before>package venom

import "encoding/xml"

const (
	// DetailsLow prints only summary results
	DetailsLow = "low"
	// DetailsMedium prints progress bar and summary
	DetailsMedium = "medium"
	// DetailsHigh prints progress bar and details
	DetailsHigh = "high"
)

// Aliases contains list of aliases
type Aliases map[string]string

// ExecutorResult represents an executor result on a test step
type ExecutorResult map[string]interface{}

// StepAssertions contains step assertions
type StepAssertions struct {
	Assertions []string `json:"assertions,omitempty" yaml:"assertions,omitempty"`
}

// StepExtracts contains "step extracts"
type StepExtracts struct {
	Extracts map[string]string `json:"extracts,omitempty" yaml:"extracts,omitempty"`
}

// Executor execute a testStep.
type Executor interface {
	// Run run a Test Step
	Run(TestCaseContext, Logger, TestStep) (ExecutorResult, error)
}

// TestCaseContext represents the context of a testcase
type TestCaseContext interface {
	Init() error
	Close() error
	SetTestCase(tc TestCase)
	GetName() string
}

// CommonTestCaseContext represents a Default TestCase Context
type CommonTestCaseContext struct {
	TestCaseContext
	TestCase TestCase
	Name     string
}

// SetTestCase set testcase in context
func (tcc *CommonTestCaseContext) SetTestCase(tc TestCase) {
	tcc.TestCase = tc
}

// GetName Get the context name
func (tcc *CommonTestCaseContext) GetName() string {
	return tcc.Name
}

// ExecutorWrap contains an executor implementation and some attributes
type ExecutorWrap struct {
	executor Executor
	retry    int // nb retry a test case if it is in failure.
	delay    int // delay between two retries
	timeout  int // timeout on executor
}

// executorWithDefaultAssertions execute a testStep.
type executorWithDefaultAssertions interface {
	// GetDefaultAssertion returns default assertions
	GetDefaultAssertions() *StepAssertions
}

type executorWithZeroValueResult interface {
	ZeroValueResult() ExecutorResult
}

// Tests contains all informations about tests in a pipeline build
type Tests struct {
	XMLName      xml.Name    `xml:"testsuites" json:"-" yaml:"-"`
	Total        int         `xml:"-" json:"total"`
	TotalOK      int         `xml:"-" json:"ok"`
	TotalKO      int         `xml:"-" json:"ko"`
	TotalSkipped int         `xml:"-" json:"skipped"`
	TestSuites   []TestSuite `xml:"testsuite" json:"test_suites"`
}

// TestSuite is a single JUnit test suite which may contain many
// testcases.
type TestSuite struct {
	XMLName    xml.Name               `xml:"testsuite" json:"-" yaml:"-"`
	Disabled   int                    `xml:"disabled,attr,omitempty" json:"disabled" yaml:"-"`
	Errors     int                    `xml:"errors,attr,omitempty" json:"errors" yaml:"-"`
	Failures   int                    `xml:"failures,attr,omitempty" json:"failures" yaml:"-"`
	Hostname   string                 `xml:"hostname,attr,omitempty" json:"hostname" yaml:"-"`
	ID         string                 `xml:"id,attr,omitempty" json:"id" yaml:"-"`
	Name       string                 `xml:"name,attr" json:"name" yaml:"name"`
	Package    string                 `xml:"package,attr,omitempty" json:"package" yaml:"-"`
	Properties []Property             `xml:"-" json:"properties" yaml:"-"`
	Skipped    int                    `xml:"skipped,attr,omitempty" json:"skipped" yaml:"skipped,omitempty"`
	Total      int                    `xml:"tests,attr" json:"total" yaml:"total,omitempty"`
	TestCases  []TestCase             `xml:"testcase" hcl:"testcase" json:"tests" yaml:"testcases"`
	Time       string                 `xml:"time,attr,omitempty" json:"time" yaml:"-"`
	Timestamp  string                 `xml:"timestamp,attr,omitempty" json:"timestamp" yaml:"-"`
	Vars       map[string]interface{} `xml:"-" json:"-" yaml:"vars"`
	Templater  *Templater             `xml:"-" json:"-" yaml:"-"`
}

// Property represents a key/value pair used to define properties.
type Property struct {
	XMLName xml.Name `xml:"property" json:"-" yaml:"-"`
	Name    string   `xml:"name,attr" json:"name" yaml:"-"`
	Value   string   `xml:"value,attr" json:"value" yaml:"-"`
}

// TestCase is a single test case with its result.
type TestCase struct {
	XMLName    xml.Name               `xml:"testcase" json:"-" yaml:"-"`
	Assertions []string               `xml:"assertions,attr,omitempty" json:"assertions" yaml:"-"`
	Classname  string                 `xml:"classname,attr,omitempty" json:"classname" yaml:"-"`
	Errors     []Failure              `xml:"error,omitempty" json:"errors" yaml:"errors,omitempty"`
	Failures   []Failure              `xml:"failure,omitempty" json:"failures" yaml:"failures,omitempty"`
	Name       string                 `xml:"name,attr" json:"name" yaml:"name"`
	Skipped    []Skipped              `xml:"skipped,omitempty" json:"skipped" yaml:"skipped,omitempty"`
	Status     string                 `xml:"status,attr,omitempty" json:"status" yaml:"status,omitempty"`
	Systemout  InnerResult            `xml:"system-out,omitempty" json:"systemout" yaml:"systemout,omitempty"`
	Systemerr  InnerResult            `xml:"system-err,omitempty" json:"systemerr" yaml:"systemerr,omitempty"`
	Time       string                 `xml:"time,attr,omitempty" json:"time" yaml:"time,omitempty"`
	TestSteps  []TestStep             `xml:"-" hcl:"step" json:"steps" yaml:"steps"`
	Context    map[string]interface{} `xml:"-" json:"-" yaml:"context,omitempty"`
}

// TestStep represents a testStep
type TestStep map[string]interface{}

// Failure contains data related to a failed test.
type Skipped struct {
	Value string `xml:",cdata" json:"value" yaml:"value,omitempty"`
}
type Failure struct {
	Value   string `xml:",cdata" json:"value" yaml:"value,omitempty"`
	Type    string `xml:"type,attr,omitempty" json:"type" yaml:"type,omitempty"`
	Message string `xml:"message,attr,omitempty" json:"message" yaml:"message,omitempty"`
}

// InnerResult is used by TestCase
type InnerResult struct {
	Value string `xml:",cdata" json:"value" yaml:"value"`
}

//Logger is basically an interface for logrus.Entry
type Logger interface {
	Debugf(format string, args ...interface{})
	Infof(format string, args ...interface{})
	Warnf(format string, args ...interface{})
	Warningf(format string, args ...interface{})
	Errorf(format string, args ...interface{})
	Fatalf(format string, args ...interface{})
}
<commit_msg>fix (engine): remove assertions on testcase (#1970)<commit_after>package venom

import "encoding/xml"

const (
	// DetailsLow prints only summary results
	DetailsLow = "low"
	// DetailsMedium prints progress bar and summary
	DetailsMedium = "medium"
	// DetailsHigh prints progress bar and details
	DetailsHigh = "high"
)

// Aliases contains list of aliases
type Aliases map[string]string

// ExecutorResult represents an executor result on a test step
type ExecutorResult map[string]interface{}

// StepAssertions contains step assertions
type StepAssertions struct {
	Assertions []string `json:"assertions,omitempty" yaml:"assertions,omitempty"`
}

// StepExtracts contains "step extracts"
type StepExtracts struct {
	Extracts map[string]string `json:"extracts,omitempty" yaml:"extracts,omitempty"`
}

// Executor execute a testStep.
type Executor interface {
	// Run run a Test Step
	Run(TestCaseContext, Logger, TestStep) (ExecutorResult, error)
}

// TestCaseContext represents the context of a testcase
type TestCaseContext interface {
	Init() error
	Close() error
	SetTestCase(tc TestCase)
	GetName() string
}

// CommonTestCaseContext represents a Default TestCase Context
type CommonTestCaseContext struct {
	TestCaseContext
	TestCase TestCase
	Name     string
}

// SetTestCase set testcase in context
func (tcc *CommonTestCaseContext) SetTestCase(tc TestCase) {
	tcc.TestCase = tc
}

// GetName Get the context name
func (tcc *CommonTestCaseContext) GetName() string {
	return tcc.Name
}

// ExecutorWrap contains an executor implementation and some attributes
type ExecutorWrap struct {
	executor Executor
	retry    int // nb retry a test case if it is in failure.
	delay    int // delay between two retries
	timeout  int // timeout on executor
}

// executorWithDefaultAssertions execute a testStep.
type executorWithDefaultAssertions interface {
	// GetDefaultAssertion returns default assertions
	GetDefaultAssertions() *StepAssertions
}

type executorWithZeroValueResult interface {
	ZeroValueResult() ExecutorResult
}

// Tests contains all informations about tests in a pipeline build
type Tests struct {
	XMLName      xml.Name    `xml:"testsuites" json:"-" yaml:"-"`
	Total        int         `xml:"-" json:"total"`
	TotalOK      int         `xml:"-" json:"ok"`
	TotalKO      int         `xml:"-" json:"ko"`
	TotalSkipped int         `xml:"-" json:"skipped"`
	TestSuites   []TestSuite `xml:"testsuite" json:"test_suites"`
}

// TestSuite is a single JUnit test suite which may contain many
// testcases.
type TestSuite struct {
	XMLName    xml.Name               `xml:"testsuite" json:"-" yaml:"-"`
	Disabled   int                    `xml:"disabled,attr,omitempty" json:"disabled" yaml:"-"`
	Errors     int                    `xml:"errors,attr,omitempty" json:"errors" yaml:"-"`
	Failures   int                    `xml:"failures,attr,omitempty" json:"failures" yaml:"-"`
	Hostname   string                 `xml:"hostname,attr,omitempty" json:"hostname" yaml:"-"`
	ID         string                 `xml:"id,attr,omitempty" json:"id" yaml:"-"`
	Name       string                 `xml:"name,attr" json:"name" yaml:"name"`
	Package    string                 `xml:"package,attr,omitempty" json:"package" yaml:"-"`
	Properties []Property             `xml:"-" json:"properties" yaml:"-"`
	Skipped    int                    `xml:"skipped,attr,omitempty" json:"skipped" yaml:"skipped,omitempty"`
	Total      int                    `xml:"tests,attr" json:"total" yaml:"total,omitempty"`
	TestCases  []TestCase             `xml:"testcase" hcl:"testcase" json:"tests" yaml:"testcases"`
	Time       string                 `xml:"time,attr,omitempty" json:"time" yaml:"-"`
	Timestamp  string                 `xml:"timestamp,attr,omitempty" json:"timestamp" yaml:"-"`
	Vars       map[string]interface{} `xml:"-" json:"-" yaml:"vars"`
	Templater  *Templater             `xml:"-" json:"-" yaml:"-"`
}

// Property represents a key/value pair used to define properties.
type Property struct {
	XMLName xml.Name `xml:"property" json:"-" yaml:"-"`
	Name    string   `xml:"name,attr" json:"name" yaml:"-"`
	Value   string   `xml:"value,attr" json:"value" yaml:"-"`
}

// TestCase is a single test case with its result.
type TestCase struct {
	XMLName   xml.Name               `xml:"testcase" json:"-" yaml:"-"`
	Classname string                 `xml:"classname,attr,omitempty" json:"classname" yaml:"-"`
	Errors    []Failure              `xml:"error,omitempty" json:"errors" yaml:"errors,omitempty"`
	Failures  []Failure              `xml:"failure,omitempty" json:"failures" yaml:"failures,omitempty"`
	Name      string                 `xml:"name,attr" json:"name" yaml:"name"`
	Skipped   []Skipped              `xml:"skipped,omitempty" json:"skipped" yaml:"skipped,omitempty"`
	Status    string                 `xml:"status,attr,omitempty" json:"status" yaml:"status,omitempty"`
	Systemout InnerResult            `xml:"system-out,omitempty" json:"systemout" yaml:"systemout,omitempty"`
	Systemerr InnerResult            `xml:"system-err,omitempty" json:"systemerr" yaml:"systemerr,omitempty"`
	Time      string                 `xml:"time,attr,omitempty" json:"time" yaml:"time,omitempty"`
	TestSteps []TestStep             `xml:"-" hcl:"step" json:"steps" yaml:"steps"`
	Context   map[string]interface{} `xml:"-" json:"-" yaml:"context,omitempty"`
}

// TestStep represents a testStep
type TestStep map[string]interface{}

// Failure contains data related to a failed test.
type Skipped struct {
	Value string `xml:",cdata" json:"value" yaml:"value,omitempty"`
}
type Failure struct {
	Value   string `xml:",cdata" json:"value" yaml:"value,omitempty"`
	Type    string `xml:"type,attr,omitempty" json:"type" yaml:"type,omitempty"`
	Message string `xml:"message,attr,omitempty" json:"message" yaml:"message,omitempty"`
}

// InnerResult is used by TestCase
type InnerResult struct {
	Value string `xml:",cdata" json:"value" yaml:"value"`
}

//Logger is basically an interface for logrus.Entry
type Logger interface {
	Debugf(format string, args ...interface{})
	Infof(format string, args ...interface{})
	Warnf(format string, args ...interface{})
	Warningf(format string, args ...interface{})
	Errorf(format string, args ...interface{})
	Fatalf(format string, args ...interface{})
}
<|endoftext|>


<commit_before>package main

type Spring struct {
	K, L0 float64
}

type Hooke struct {
	Springs [][]Spring
}

func (h Hooke) Accel(bs []Body, i int) (a Vector) {

	f := NewZeroVector()

	b := bs[i]

	for j, b2 := range bs {

		spring := h.Springs[i][j]

		dir, l := b2.Xs[0].Minus(b.Xs[0]).UnitAndNorm()

		f = f.Plus(dir.Scale(spring.K * (l - spring.L0)))
	}

	return f.Scale(1 / b.M)
}

func main() {

	shm := AnalyticSHM{
		K: 1, M: 1, A: NewVector(1, 0, 0),
	}

	shm.Run(0.05, 5000)

}
<commit_msg>Shorten the simulation<commit_after>package main

type Spring struct {
	K, L0 float64
}

type Hooke struct {
	Springs [][]Spring
}

func (h Hooke) Accel(bs []Body, i int) (a Vector) {

	f := NewZeroVector()

	b := bs[i]

	for j, b2 := range bs {

		spring := h.Springs[i][j]

		dir, l := b2.Xs[0].Minus(b.Xs[0]).UnitAndNorm()

		f = f.Plus(dir.Scale(spring.K * (l - spring.L0)))
	}

	return f.Scale(1 / b.M)
}

func main() {

	shm := AnalyticSHM{
		K: 1, M: 1, A: NewVector(1, 0, 0),
	}

	shm.Run(0.05, 500)

}
<|endoftext|>


<commit_before>package main

import (
	"big"
	"sort"
)

type Point [3]int64
type Vector [3]int64
type Triangle [3]Point

func NewVector(p1, p2 Point) Vector {
	return Vector{p2[0] - p1[0], p2[1] - p1[1], p2[2] - p1[2]}
}

func VectorProduct(a, b Vector) Vector {
	return Vector{
		a[1]*b[2] - a[2]*b[1],
		a[2]*b[0] - a[0]*b[2],
		a[0]*b[1] - a[1]*b[0],
	}
}

func ScalarProduct(a, b Vector) (s *big.Int) {
	s = big.NewInt(0)
	for i := 0; i < 3; i++ {
		tmp := big.NewInt(0)
		s.Add(s, tmp.Mul(big.NewInt(a[i]), big.NewInt(b[i])))
	}
	return
}

func DotInPlane(p, a, b, c Point, r int64) bool {
	va := NewVector(c, a)
	vb := NewVector(c, b)
	vc := NewVector(c, p)
	v := VectorProduct(va, vb)

	s := ScalarProduct(vc, v)
	s.Mul(s, s)
	s.Mul(s, big.NewInt(4))

	r2 := big.NewInt(r)
	r2.Mul(r2, r2)

	v2 := ScalarProduct(v, v)

	t := big.NewInt(0)
	t.Mul(r2, v2)

	return t.Cmp(s) >= 0
}

func len2(v Vector) (s *big.Int) {
	s = big.NewInt(0)
	for i := 0; i < 3; i++ {
		tmp := big.NewInt(v[i])
		tmp.Mul(tmp, tmp)
		s.Add(s, tmp)
	}
	return
}

func sameSide(p, a, b, c Point, r int64) bool {
	ab := NewVector(a, b)
	ac := NewVector(a, c)
	ap := NewVector(a, p)
	v1 := VectorProduct(ab, ac)
	v2 := VectorProduct(ab, ap)
	s := ScalarProduct(v1, v2)
	if s.Cmp(big.NewInt(0)) >= 0 {
		return true
	}
	h2 := len2(v2)
	h2.Mul(h2, big.NewInt(4))
	r2 := big.NewInt(r)
	r2.Mul(r2, r2)
	r2.Mul(r2, len2(ab))
	return r2.Cmp(h2) >= 0
}

func inplaneDotInTriangle(p, a, b, c Point, r int64) bool {
	return sameSide(p, a, b, c, r) &&
		sameSide(p, b, c, a, r) &&
		sameSide(p, c, a, b, r)
}

func DotInTriangle(p, a, b, c Point, r int64) bool {
	return DotInPlane(p, a, b, c, r) && inplaneDotInTriangle(p, a, b, c, r)
}

func hash(p Point) uint64 {
	return (uint64(p[0]) << 42) + (uint64(p[1] << 21)) + uint64(p[2])
}

func adjacent(p Point) (res []Point) {
	res = make([]Point, 8)[0:0]
	for dx := -1; dx <= 1; dx++ {
		for dy := -1; dy <= 1; dy++ {
			for dz := -1; dz <= 1; dz++ {
				if dx == 0 && dy == 0 && dz == 0 {
					continue
				}
				res = append(res, Point{
					p[0] + int64(dx),
					p[1] + int64(dy),
					p[2] + int64(dz),
				})
			}
		}
	}
	return
}

func to(a, n int64) int64 {
	if a >= 0 {
		return (a + (n-1)/2) / n
	}
	return -((-a + n/2) / n)
}

func toGrid(p Point, scale int64) Point {
	return Point{to(p[0], scale), to(p[1], scale), to(p[2], scale)}
}

func fromGrid(p Point, scale int64) Point {
	return Point{p[0] * scale, p[1] * scale, p[2] * scale}
}

func AllTriangleDots(a, b, c Point, scale, r int64) (res []Point) {
	ga := toGrid(a, scale)
	gb := toGrid(b, scale)
	gc := toGrid(c, scale)

	r = r * scale
	q := []Point{ga, gb, gc}
	var q2 []Point
	m := make(map[uint64]Point)
	m[hash(ga)] = ga
	m[hash(gb)] = gb
	m[hash(gc)] = gc
	for len(q) > 0 {
		q, q2 = q2[0:0], q
		for _, p := range q2 {
			for _, p2 := range adjacent(p) {
				if _, ok := m[hash(p2)]; ok {
					continue
				}

				if !DotInTriangle(fromGrid(p2, scale), a, b, c, r) {
					continue
				}
				m[hash(p2)] = p2
				q = append(q, p2)
			}
		}
	}
	res = make([]Point, len(m))[0:0]
	for _, p := range m {
		res = append(res, p)
	}
	return
}

func findJ(p1, p2 Point, scale int64) (j uint) {
	for j = 0; j < 31; j++ {
		var r2 int64
		for z := 0; z < 3; z++ {
			diff := int64(p1[z] - p2[z])
			r2 += diff * diff
		}
		//		fmt.Fprintf(os.Stderr, "r2: %d, j: %d, scale: %d\n", r2, j, scale)
		if r2 < (int64(scale)*int64(scale))<<(2*j) {
			return
		}
	}
	panic("unreachable")
}

func peq(p1, p2 Point) bool {
	for z := 0; z < 3; z++ {
		if p1[z] != p2[z] {
			return false
		}
	}
	return true
}

type pointSlice []Point

func (ps pointSlice) Len() int {
	return len(ps)
}

func (ps pointSlice) Less(i, j int) (res bool) {
	//	defer func() {
	//		fmt.Fprintf(os.Stderr, "Less(%d,%d): %v, %v\n", i, j, res, ps)
	//	}()
	for z := 0; z < 3; z++ {
		if ps[i][z] < ps[j][z] {
			return true
		}
		if ps[i][z] > ps[j][z] {
			return false
		}
	}
	return false
}

func (ps pointSlice) Swap(i, j int) {
	//	fmt.Fprintf(os.Stderr, "Swap(%d, %d), before: %v\n", i, j, ps)
	ps[i], ps[j] = ps[j], ps[i]
	//	fmt.Fprintf(os.Stderr, "Swap(%d, %d),  after: %v\n", i, j, ps)
}

func uniq(ps []Point) (res []Point) {
	res = ps[:0]
	for i, p := range ps {
		if i > 0 && peq(ps[i-1], p) {
			continue
		}
		res = append(res, ps[i])
	}
	return
}

func AllTriangleDots1(a, b, c Point, scale, r int64) (res []Point) {
	//	fmt.Fprintf(os.Stderr, "AllTriangleDots1, 0, a=%v, b=%v, c=%v\n", a, b, c)
	j0 := findJ(a, c, scale)
	//	fmt.Fprintf(os.Stderr, "AllTriangleDots1, 10, j0=%d\n", j0)
	j1 := findJ(a, b, scale)
	//	fmt.Fprintf(os.Stderr, "AllTriangleDots1, 20, j1=%d\n", j1)
	m := j0
	if m < j1 {
		m = j1
	}
	//	fmt.Fprintf(os.Stderr, "AllTriangleDots1, 30, m=%d\n", m)
	cur0 := -1
	for i0 := 0; i0 <= 1<<j0; i0++ {
		ind0 := cur0
		cur0 = len(res)
		var last1 Point
		for i1 := 0; i0*(1<<(m-j0))+i1*(1<<(m-j1)) <= 1<<m; i1++ {
			if ind0 >= 0 && i1 > 0 {
				ind0++
			}

			i2 := 1<<m - i0*(1<<(m-j0)) - i1*(1<<(m-j1))
			var p Point
			for z := 0; z < 3; z++ {
				p[z] = int64(i0)*(int64(1)<<uint(m-j0))*a[z] +
					int64(i1)*(int64(1)<<uint(m-j1))*b[z] +
					int64(i2)*c[z]
				p[z] >>= m
			}
			//			fmt.Fprintf(os.Stderr, "AllTriangleDots1, 60, p=%v\n", p)
			p = toGrid(p, scale)
			if ind0 >= 0 && ind0 < cur0 && peq(res[ind0], p) {
				continue
			}
			if i1 > 0 && peq(last1, p) {
				continue
			}
			res = append(res, p)
			last1 = p
		}
		//		fmt.Fprintf(os.Stderr, "AllTriangleDots1, 90\n")
	}
	//	fmt.Fprintf(os.Stderr, "AllTriangleDots1, 94, res: %v\n", res)
	sort.Sort(pointSlice(res))
	//	fmt.Fprintf(os.Stderr, "AllTriangleDots1, 95, res: %v\n", res)
	res = uniq(res)
	//	fmt.Fprintf(os.Stderr, "AllTriangleDots1, 100, res: %v\n", res)
	return
}
<commit_msg>Fix triangle rasterization: don't miss the points.<commit_after>package main

import (
	"big"
	"sort"
)

type Point [3]int64
type Vector [3]int64
type Triangle [3]Point

func NewVector(p1, p2 Point) Vector {
	return Vector{p2[0] - p1[0], p2[1] - p1[1], p2[2] - p1[2]}
}

func VectorProduct(a, b Vector) Vector {
	return Vector{
		a[1]*b[2] - a[2]*b[1],
		a[2]*b[0] - a[0]*b[2],
		a[0]*b[1] - a[1]*b[0],
	}
}

func ScalarProduct(a, b Vector) (s *big.Int) {
	s = big.NewInt(0)
	for i := 0; i < 3; i++ {
		tmp := big.NewInt(0)
		s.Add(s, tmp.Mul(big.NewInt(a[i]), big.NewInt(b[i])))
	}
	return
}

func DotInPlane(p, a, b, c Point, r int64) bool {
	va := NewVector(c, a)
	vb := NewVector(c, b)
	vc := NewVector(c, p)
	v := VectorProduct(va, vb)

	s := ScalarProduct(vc, v)
	s.Mul(s, s)
	s.Mul(s, big.NewInt(4))

	r2 := big.NewInt(r)
	r2.Mul(r2, r2)

	v2 := ScalarProduct(v, v)

	t := big.NewInt(0)
	t.Mul(r2, v2)

	return t.Cmp(s) >= 0
}

func len2(v Vector) (s *big.Int) {
	s = big.NewInt(0)
	for i := 0; i < 3; i++ {
		tmp := big.NewInt(v[i])
		tmp.Mul(tmp, tmp)
		s.Add(s, tmp)
	}
	return
}

func sameSide(p, a, b, c Point, r int64) bool {
	ab := NewVector(a, b)
	ac := NewVector(a, c)
	ap := NewVector(a, p)
	v1 := VectorProduct(ab, ac)
	v2 := VectorProduct(ab, ap)
	s := ScalarProduct(v1, v2)
	if s.Cmp(big.NewInt(0)) >= 0 {
		return true
	}
	h2 := len2(v2)
	h2.Mul(h2, big.NewInt(4))
	r2 := big.NewInt(r)
	r2.Mul(r2, r2)
	r2.Mul(r2, len2(ab))
	return r2.Cmp(h2) >= 0
}

func inplaneDotInTriangle(p, a, b, c Point, r int64) bool {
	return sameSide(p, a, b, c, r) &&
		sameSide(p, b, c, a, r) &&
		sameSide(p, c, a, b, r)
}

func DotInTriangle(p, a, b, c Point, r int64) bool {
	return DotInPlane(p, a, b, c, r) && inplaneDotInTriangle(p, a, b, c, r)
}

func hash(p Point) uint64 {
	return (uint64(p[0]) << 42) + (uint64(p[1] << 21)) + uint64(p[2])
}

func adjacent(p Point) (res []Point) {
	res = make([]Point, 8)[0:0]
	for dx := -1; dx <= 1; dx++ {
		for dy := -1; dy <= 1; dy++ {
			for dz := -1; dz <= 1; dz++ {
				if dx == 0 && dy == 0 && dz == 0 {
					continue
				}
				res = append(res, Point{
					p[0] + int64(dx),
					p[1] + int64(dy),
					p[2] + int64(dz),
				})
			}
		}
	}
	return
}

func to(a, n int64) int64 {
	if a >= 0 {
		return (a + (n-1)/2) / n
	}
	return -((-a + n/2) / n)
}

func toGrid(p Point, scale int64) Point {
	return Point{to(p[0], scale), to(p[1], scale), to(p[2], scale)}
}

func fromGrid(p Point, scale int64) Point {
	return Point{p[0] * scale, p[1] * scale, p[2] * scale}
}

func AllTriangleDots(a, b, c Point, scale, r int64) (res []Point) {
	ga := toGrid(a, scale)
	gb := toGrid(b, scale)
	gc := toGrid(c, scale)

	r = r * scale
	q := []Point{ga, gb, gc}
	var q2 []Point
	m := make(map[uint64]Point)
	m[hash(ga)] = ga
	m[hash(gb)] = gb
	m[hash(gc)] = gc
	for len(q) > 0 {
		q, q2 = q2[0:0], q
		for _, p := range q2 {
			for _, p2 := range adjacent(p) {
				if _, ok := m[hash(p2)]; ok {
					continue
				}

				if !DotInTriangle(fromGrid(p2, scale), a, b, c, r) {
					continue
				}
				m[hash(p2)] = p2
				q = append(q, p2)
			}
		}
	}
	res = make([]Point, len(m))[0:0]
	for _, p := range m {
		res = append(res, p)
	}
	return
}

func findJ(p1, p2 Point, scale int64) (j uint) {
	for j = 0; j < 31; j++ {
		var r2 int64
		for z := 0; z < 3; z++ {
			diff := int64(p1[z] - p2[z])
			r2 += diff * diff
		}
		//		fmt.Fprintf(os.Stderr, "r2: %d, j: %d, scale: %d\n", r2, j, scale)
		if r2 < (int64(scale)*int64(scale))<<(2*j) {
			return j + 1
		}
	}
	panic("unreachable")
}

func peq(p1, p2 Point) bool {
	for z := 0; z < 3; z++ {
		if p1[z] != p2[z] {
			return false
		}
	}
	return true
}

type pointSlice []Point

func (ps pointSlice) Len() int {
	return len(ps)
}

func (ps pointSlice) Less(i, j int) (res bool) {
	//	defer func() {
	//		fmt.Fprintf(os.Stderr, "Less(%d,%d): %v, %v\n", i, j, res, ps)
	//	}()
	for z := 0; z < 3; z++ {
		if ps[i][z] < ps[j][z] {
			return true
		}
		if ps[i][z] > ps[j][z] {
			return false
		}
	}
	return false
}

func (ps pointSlice) Swap(i, j int) {
	//	fmt.Fprintf(os.Stderr, "Swap(%d, %d), before: %v\n", i, j, ps)
	ps[i], ps[j] = ps[j], ps[i]
	//	fmt.Fprintf(os.Stderr, "Swap(%d, %d),  after: %v\n", i, j, ps)
}

func uniq(ps []Point) (res []Point) {
	res = ps[:0]
	for i, p := range ps {
		if i > 0 && peq(ps[i-1], p) {
			continue
		}
		res = append(res, ps[i])
	}
	return
}

func AllTriangleDots1(a, b, c Point, scale, r int64) (res []Point) {
	//	fmt.Fprintf(os.Stderr, "AllTriangleDots1, 0, a=%v, b=%v, c=%v\n", a, b, c)
	j0 := findJ(a, c, scale)
	//	fmt.Fprintf(os.Stderr, "AllTriangleDots1, 10, j0=%d\n", j0)
	j1 := findJ(a, b, scale)
	//	fmt.Fprintf(os.Stderr, "AllTriangleDots1, 20, j1=%d\n", j1)
	m := j0
	if m < j1 {
		m = j1
	}
	//	fmt.Fprintf(os.Stderr, "AllTriangleDots1, 30, m=%d\n", m)
	cur0 := -1
	for i0 := 0; i0 <= 1<<j0; i0++ {
		ind0 := cur0
		cur0 = len(res)
		var last1 Point
		for i1 := 0; i0*(1<<(m-j0))+i1*(1<<(m-j1)) <= 1<<m; i1++ {
			if ind0 >= 0 && i1 > 0 {
				ind0++
			}

			i2 := 1<<m - i0*(1<<(m-j0)) - i1*(1<<(m-j1))
			var p Point
			for z := 0; z < 3; z++ {
				p[z] = int64(i0)*(int64(1)<<uint(m-j0))*a[z] +
					int64(i1)*(int64(1)<<uint(m-j1))*b[z] +
					int64(i2)*c[z]
				p[z] >>= m
			}
			//			fmt.Fprintf(os.Stderr, "AllTriangleDots1, 60, p=%v\n", p)
			p = toGrid(p, scale)
			if ind0 >= 0 && ind0 < cur0 && peq(res[ind0], p) {
				continue
			}
			if i1 > 0 && peq(last1, p) {
				continue
			}
			res = append(res, p)
			last1 = p
		}
		//		fmt.Fprintf(os.Stderr, "AllTriangleDots1, 90\n")
	}
	//	fmt.Fprintf(os.Stderr, "AllTriangleDots1, 94, res: %v\n", res)
	sort.Sort(pointSlice(res))
	//	fmt.Fprintf(os.Stderr, "AllTriangleDots1, 95, res: %v\n", res)
	res = uniq(res)
	//	fmt.Fprintf(os.Stderr, "AllTriangleDots1, 100, res: %v\n", res)
	return
}
<|endoftext|>


<commit_before>package validator

import "reflect"

// StructLevelFunc accepts all values needed for struct level validation
type StructLevelFunc func(sl StructLevel)

// StructLevel contains all the information and helper functions
// to validate a struct
type StructLevel interface {

	// returns the main validation object, in case one want to call validations internally.
	// this is so you don;t have to use anonymous functoins to get access to the validate
	// instance.
	Validator() *Validate

	// returns the top level struct, if any
	Top() reflect.Value

	// returns the current fields parent struct, if any
	Parent() reflect.Value

	// returns the current struct.
	// this is not needed when implementing 'Validatable' interface,
	// only when a StructLevel is registered
	Current() reflect.Value

	// ExtractType gets the actual underlying type of field value.
	// It will dive into pointers, customTypes and return you the
	// underlying value and it's kind.
	ExtractType(field reflect.Value) (value reflect.Value, kind reflect.Kind, nullable bool)

	// reports an error just by passing the field and tag information
	//
	// NOTES:
	//
	// fieldName and altName get appended to the existing namespace that
	// validator is on. eg. pass 'FirstName' or 'Names[0]' depending
	// on the nesting
	//
	// tag can be an existing validation tag or just something you make up
	// and process on the flip side it's up to you.
	ReportError(field interface{}, fieldName, altName, tag, param string)

	// reports an error just by passing ValidationErrors
	//
	// NOTES:
	//
	// relativeNamespace and relativeActualNamespace get appended to the
	// existing namespace that validator is on.
	// eg. pass 'User.FirstName' or 'Users[0].FirstName' depending
	// on the nesting. most of the time they will be blank, unless you validate
	// at a level lower the the current field depth
	//
	// tag can be an existing validation tag or just something you make up
	// and process on the flip side it's up to you.
	ReportValidationErrors(relativeNamespace, relativeActualNamespace string, errs ValidationErrors)
}

var _ StructLevel = new(validate)

// Top returns the top level struct
//
// NOTE: this can be the same as the current struct being validated
// if not is a nested struct.
//
// this is only called when within Struct and Field Level validation and
// should not be relied upon for an acurate value otherwise.
func (v *validate) Top() reflect.Value {
	return v.top
}

// Parent returns the current structs parent
//
// NOTE: this can be the same as the current struct being validated
// if not is a nested struct.
//
// this is only called when within Struct and Field Level validation and
// should not be relied upon for an acurate value otherwise.
func (v *validate) Parent() reflect.Value {
	return v.slflParent
}

// Current returns the current struct.
func (v *validate) Current() reflect.Value {
	return v.slCurrent
}

// Validator returns the main validation object, in case one want to call validations internally.
func (v *validate) Validator() *Validate {
	return v.v
}

// ExtractType gets the actual underlying type of field value.
func (v *validate) ExtractType(field reflect.Value) (reflect.Value, reflect.Kind, bool) {
	return v.extractTypeInternal(field, false)
}

// ReportError reports an error just by passing the field and tag information
func (v *validate) ReportError(field interface{}, fieldName, structFieldName, tag, param string) {

	fv, kind, _ := v.extractTypeInternal(reflect.ValueOf(field), false)

	if len(structFieldName) == 0 {
		structFieldName = fieldName
	}

	v.str1 = string(append(v.ns, fieldName...))

	if v.v.hasTagNameFunc || fieldName != structFieldName {
		v.str2 = string(append(v.actualNs, structFieldName...))
	} else {
		v.str2 = v.str1
	}

	switch kind {
	case reflect.Invalid:

		v.errs = append(v.errs,
			&fieldError{
				tag:         tag,
				actualTag:   tag,
				ns:          v.str1,
				structNs:    v.str2,
				field:       fieldName,
				structField: structFieldName,
				param:       param,
				kind:        kind,
			},
		)

	default:

		v.errs = append(v.errs,
			&fieldError{
				tag:         tag,
				actualTag:   tag,
				ns:          v.str1,
				structNs:    v.str2,
				field:       fieldName,
				structField: structFieldName,
				value:       fv.Interface(),
				param:       param,
				kind:        kind,
				typ:         fv.Type(),
			},
		)
	}
}

// ReportValidationErrors reports ValidationErrors obtained from running validations within the Struct Level validation.
//
// NOTE: this function prepends the current namespace to the relative ones.
func (v *validate) ReportValidationErrors(relativeNamespace, relativeStructNamespace string, errs ValidationErrors) {

	var err *fieldError

	for i := 0; i < len(errs); i++ {

		err = errs[i].(*fieldError)
		err.ns = string(append(append(v.ns, relativeNamespace...), err.ns...))
		err.structNs = string(append(append(v.actualNs, relativeStructNamespace...), err.structNs...))

		v.errs = append(v.errs, err)
	}
}
<commit_msg>convert switch to if<commit_after>package validator

import "reflect"

// StructLevelFunc accepts all values needed for struct level validation
type StructLevelFunc func(sl StructLevel)

// StructLevel contains all the information and helper functions
// to validate a struct
type StructLevel interface {

	// returns the main validation object, in case one want to call validations internally.
	// this is so you don;t have to use anonymous functoins to get access to the validate
	// instance.
	Validator() *Validate

	// returns the top level struct, if any
	Top() reflect.Value

	// returns the current fields parent struct, if any
	Parent() reflect.Value

	// returns the current struct.
	// this is not needed when implementing 'Validatable' interface,
	// only when a StructLevel is registered
	Current() reflect.Value

	// ExtractType gets the actual underlying type of field value.
	// It will dive into pointers, customTypes and return you the
	// underlying value and it's kind.
	ExtractType(field reflect.Value) (value reflect.Value, kind reflect.Kind, nullable bool)

	// reports an error just by passing the field and tag information
	//
	// NOTES:
	//
	// fieldName and altName get appended to the existing namespace that
	// validator is on. eg. pass 'FirstName' or 'Names[0]' depending
	// on the nesting
	//
	// tag can be an existing validation tag or just something you make up
	// and process on the flip side it's up to you.
	ReportError(field interface{}, fieldName, altName, tag, param string)

	// reports an error just by passing ValidationErrors
	//
	// NOTES:
	//
	// relativeNamespace and relativeActualNamespace get appended to the
	// existing namespace that validator is on.
	// eg. pass 'User.FirstName' or 'Users[0].FirstName' depending
	// on the nesting. most of the time they will be blank, unless you validate
	// at a level lower the the current field depth
	//
	// tag can be an existing validation tag or just something you make up
	// and process on the flip side it's up to you.
	ReportValidationErrors(relativeNamespace, relativeActualNamespace string, errs ValidationErrors)
}

var _ StructLevel = new(validate)

// Top returns the top level struct
//
// NOTE: this can be the same as the current struct being validated
// if not is a nested struct.
//
// this is only called when within Struct and Field Level validation and
// should not be relied upon for an acurate value otherwise.
func (v *validate) Top() reflect.Value {
	return v.top
}

// Parent returns the current structs parent
//
// NOTE: this can be the same as the current struct being validated
// if not is a nested struct.
//
// this is only called when within Struct and Field Level validation and
// should not be relied upon for an acurate value otherwise.
func (v *validate) Parent() reflect.Value {
	return v.slflParent
}

// Current returns the current struct.
func (v *validate) Current() reflect.Value {
	return v.slCurrent
}

// Validator returns the main validation object, in case one want to call validations internally.
func (v *validate) Validator() *Validate {
	return v.v
}

// ExtractType gets the actual underlying type of field value.
func (v *validate) ExtractType(field reflect.Value) (reflect.Value, reflect.Kind, bool) {
	return v.extractTypeInternal(field, false)
}

// ReportError reports an error just by passing the field and tag information
func (v *validate) ReportError(field interface{}, fieldName, structFieldName, tag, param string) {

	fv, kind, _ := v.extractTypeInternal(reflect.ValueOf(field), false)

	if len(structFieldName) == 0 {
		structFieldName = fieldName
	}

	v.str1 = string(append(v.ns, fieldName...))

	if v.v.hasTagNameFunc || fieldName != structFieldName {
		v.str2 = string(append(v.actualNs, structFieldName...))
	} else {
		v.str2 = v.str1
	}

	if kind == reflect.Invalid {

		v.errs = append(v.errs,
			&fieldError{
				tag:         tag,
				actualTag:   tag,
				ns:          v.str1,
				structNs:    v.str2,
				field:       fieldName,
				structField: structFieldName,
				param:       param,
				kind:        kind,
			},
		)
		return
	}

	v.errs = append(v.errs,
		&fieldError{
			tag:         tag,
			actualTag:   tag,
			ns:          v.str1,
			structNs:    v.str2,
			field:       fieldName,
			structField: structFieldName,
			value:       fv.Interface(),
			param:       param,
			kind:        kind,
			typ:         fv.Type(),
		},
	)
}

// ReportValidationErrors reports ValidationErrors obtained from running validations within the Struct Level validation.
//
// NOTE: this function prepends the current namespace to the relative ones.
func (v *validate) ReportValidationErrors(relativeNamespace, relativeStructNamespace string, errs ValidationErrors) {

	var err *fieldError

	for i := 0; i < len(errs); i++ {

		err = errs[i].(*fieldError)
		err.ns = string(append(append(v.ns, relativeNamespace...), err.ns...))
		err.structNs = string(append(append(v.actualNs, relativeStructNamespace...), err.structNs...))

		v.errs = append(v.errs, err)
	}
}
<|endoftext|>


<commit_before>package organisations

import (
	"fmt"
	"github.com/Financial-Times/neo-utils-go/neoutils"
	"github.com/jmcvetta/neoism"
)

type relationships []struct {
	RelationshipType string `json:"relationship"`
}

// TransferRelationships is responsible for moving relationships from node with sourceUUID to node with destinationUUID
func CreateTransferRelationshipsQueries(cypherRunner neoutils.CypherRunner, destinationUUID string, sourceUUID string) ([]*neoism.CypherQuery, error) {

	relationshipsFromSourceNode, relationshipsToSourceNode, err := getNodeRelationshipNames(cypherRunner, sourceUUID)
	if err != nil {
		return nil, err
	}

	writeQueries := []*neoism.CypherQuery{}
	for _, rel := range relationshipsFromSourceNode {
		transfQuery := constructTransferRelationshipsFromNodeQuery(sourceUUID, destinationUUID, rel.RelationshipType)
		writeQueries = append(writeQueries, transfQuery)
	}

	for _, rel := range relationshipsToSourceNode {
		transfQuery := constructTransferRelationshipsToNodeQuery(sourceUUID, destinationUUID, rel.RelationshipType)
		writeQueries = append(writeQueries, transfQuery)
	}

	return writeQueries, nil
}

func getNodeRelationshipNames(cypherRunner neoutils.CypherRunner, uuid string) (relationshipsFromNodeWithUUID relationships, relationshipsToNodeWithUUID relationships, err error) {
	// find all the -> relationships
	relationshipsFromNodeWithUUID = relationships{}
	readRelationshipsFromNodeWithUUIDQuery := &neoism.CypherQuery{
		Statement: `match (a:Thing{uuid:{uuid}})-[r]-(b)
			    where startnode(r) = a
			    return distinct type(r) as relationship`,
		Parameters: map[string]interface{}{
			"uuid": uuid,
		},
		Result: &relationshipsFromNodeWithUUID,
	}

	// find all the <- relationships
	relationshipsToNodeWithUUID = relationships{}
	readRelationshipsToNodeWithUUIDQuery := &neoism.CypherQuery{
		Statement: `match (a:Thing{uuid:{uuid}})-[r]-(b)
			    where endnode(r) = a
			    return distinct type(r) as relationship`,
		Parameters: map[string]interface{}{
			"uuid": uuid,
		},
		Result: &relationshipsToNodeWithUUID,
	}

	readQueries := []*neoism.CypherQuery{readRelationshipsFromNodeWithUUIDQuery, readRelationshipsToNodeWithUUIDQuery}

	err = cypherRunner.CypherBatch(readQueries)

	if err != nil {
		return nil, nil, err
	}

	return relationshipsFromNodeWithUUID, relationshipsToNodeWithUUID, nil
}

func constructTransferRelationshipsFromNodeQuery(fromUUID string, toUUID string, predicate string) *neoism.CypherQuery {
	transferAnnotationsQuery := &neoism.CypherQuery{
		Statement: fmt.Sprintf(`MATCH (oldNode:Thing {uuid:{fromUUID}})
					MATCH (newNode:Thing {uuid:{toUUID}})
					MATCH (oldNode)-[oldRel:%s]->(p)
					FOREACH (ignoreMe IN CASE WHEN (EXISTS (oldRel.platformVersion)) THEN [1] ELSE [] END |
						MERGE (newNode)-[newRel:%s{platformVersion:oldRel.platformVersion}]->(p)
						SET newRel = oldRel
					)
					FOREACH (ignoreMe IN CASE WHEN NOT (EXISTS (oldRel.platformVersion)) THEN [1] ELSE [] END |
						MERGE (newNode)-[newRel:%s]->(p)
						SET newRel = oldRel
					)
					DELETE oldRel`, predicate, predicate, predicate),

		Parameters: map[string]interface{}{
			"fromUUID": fromUUID,
			"toUUID":   toUUID,
		},
	}
	return transferAnnotationsQuery
}

func constructTransferRelationshipsToNodeQuery(fromUUID string, toUUID string, predicate string) *neoism.CypherQuery {
	transferAnnotationsQuery := &neoism.CypherQuery{
		Statement: fmt.Sprintf(`MATCH (oldNode:Thing {uuid:{fromUUID}})
					MATCH (newNode:Thing {uuid:{toUUID}})
					MATCH (oldNode)<-[oldRel:%s]-(p)
					FOREACH (ignoreMe IN CASE WHEN (EXISTS (oldRel.platformVersion)) THEN [1] ELSE [] END |
						MERGE (newNode)<-[newRel:%s{platformVersion:oldRel.platformVersion}]-(p)
						SET newRel = oldRel
					)
					FOREACH (ignoreMe IN CASE WHEN NOT (EXISTS (oldRel.platformVersion)) THEN [1] ELSE [] END |
						MERGE (newNode)<-[newRel:%s]-(p)
						SET newRel = oldRel
					)
					DELETE oldRel`, predicate, predicate, predicate),

		Parameters: map[string]interface{}{
			"fromUUID": fromUUID,
			"toUUID":   toUUID,
		},
	}
	return transferAnnotationsQuery
}
<commit_msg>A bit of cypher optimization.<commit_after>package organisations

import (
	"fmt"
	"github.com/Financial-Times/neo-utils-go/neoutils"
	"github.com/jmcvetta/neoism"
)

type relationships []struct {
	RelationshipType string `json:"relationship"`
}

// TransferRelationships is responsible for moving relationships from node with sourceUUID to node with destinationUUID
func CreateTransferRelationshipsQueries(cypherRunner neoutils.CypherRunner, destinationUUID string, sourceUUID string) ([]*neoism.CypherQuery, error) {

	relationshipsFromSourceNode, relationshipsToSourceNode, err := getNodeRelationshipNames(cypherRunner, sourceUUID)
	if err != nil {
		return nil, err
	}

	writeQueries := []*neoism.CypherQuery{}
	for _, rel := range relationshipsFromSourceNode {
		transfQuery := constructTransferRelationshipsFromNodeQuery(sourceUUID, destinationUUID, rel.RelationshipType)
		transfQuery2 := constructTransferRelationshipsFromNodeQueryWithoutPlatformVersion(sourceUUID, destinationUUID, rel.RelationshipType)
		writeQueries = append(writeQueries, transfQuery, transfQuery2)
	}

	for _, rel := range relationshipsToSourceNode {
		transfQuery := constructTransferRelationshipsToNodeQuery(sourceUUID, destinationUUID, rel.RelationshipType)
		transfQuery2 := constructTransferRelationshipsToNodeQueryWithoutPlatformVersion(sourceUUID, destinationUUID, rel.RelationshipType)
		writeQueries = append(writeQueries, transfQuery, transfQuery2)
	}

	return writeQueries, nil
}

func getNodeRelationshipNames(cypherRunner neoutils.CypherRunner, uuid string) (relationshipsFromNodeWithUUID relationships, relationshipsToNodeWithUUID relationships, err error) {
	// find all the -> relationships
	relationshipsFromNodeWithUUID = relationships{}
	readRelationshipsFromNodeWithUUIDQuery := &neoism.CypherQuery{
		Statement: `match (a:Thing{uuid:{uuid}})-[r]->(b)
			    return distinct type(r) as relationship`,
		Parameters: map[string]interface{}{
			"uuid": uuid,
		},
		Result: &relationshipsFromNodeWithUUID,
	}

	// find all the <- relationships
	relationshipsToNodeWithUUID = relationships{}
	readRelationshipsToNodeWithUUIDQuery := &neoism.CypherQuery{
		Statement: `match (a:Thing{uuid:{uuid}})<-[r]-(b)
			    return distinct type(r) as relationship`,
		Parameters: map[string]interface{}{
			"uuid": uuid,
		},
		Result: &relationshipsToNodeWithUUID,
	}

	readQueries := []*neoism.CypherQuery{readRelationshipsFromNodeWithUUIDQuery, readRelationshipsToNodeWithUUIDQuery}

	err = cypherRunner.CypherBatch(readQueries)

	if err != nil {
		return nil, nil, err
	}

	return relationshipsFromNodeWithUUID, relationshipsToNodeWithUUID, nil
}

func constructTransferRelationshipsFromNodeQuery(fromUUID string, toUUID string, predicate string) *neoism.CypherQuery {
	transferAnnotationsQuery := &neoism.CypherQuery{
		Statement: fmt.Sprintf(`MATCH (oldNode:Organisation {uuid:{fromUUID}})-[oldRel:%s]->(p)
					WHERE HAS(oldRel.platformVersion)
					MATCH (newNode:Organisation {uuid:{toUUID}})
					MERGE (newNode)-[newRel:%s{platformVersion:oldRel.platformVersion}]->(p)
					on create SET newRel = oldRel
					DELETE oldRel`, predicate, predicate, predicate),

		Parameters: map[string]interface{}{
			"fromUUID": fromUUID,
			"toUUID":   toUUID,
		},
	}
	return transferAnnotationsQuery
}

func constructTransferRelationshipsFromNodeQueryWithoutPlatformVersion(fromUUID string, toUUID string, predicate string) *neoism.CypherQuery {
	transferAnnotationsQuery := &neoism.CypherQuery{
		Statement: fmt.Sprintf(`MATCH (oldNode:Organisation {uuid:{fromUUID}})-[oldRel:%s]->(p)
					WHERE NOT HAS(oldRel.platformVersion)
					MATCH (newNode:Organisation {uuid:{toUUID}})
					MERGE (newNode)-[newRel:%s]->(p)
					on create SET newRel = oldRel
					DELETE oldRel`, predicate, predicate, predicate),

		Parameters: map[string]interface{}{
			"fromUUID": fromUUID,
			"toUUID":   toUUID,
		},
	}
	return transferAnnotationsQuery
}

func constructTransferRelationshipsToNodeQuery(fromUUID string, toUUID string, predicate string) *neoism.CypherQuery {
	transferAnnotationsQuery := &neoism.CypherQuery{
		Statement: fmt.Sprintf(`MATCH (oldNode:Organisation {uuid:{fromUUID}})<-[oldRel:%s]-(p)
					WHERE HAS(oldRel.platformVersion)
					MATCH (newNode:Organisation {uuid:{toUUID}})
					MERGE (newNode)<-[newRel:%s{platformVersion:oldRel.platformVersion}]-(p)
					ON create SET newRel = oldRel
					DELETE oldRel`, predicate, predicate, predicate),

		Parameters: map[string]interface{}{
			"fromUUID": fromUUID,
			"toUUID":   toUUID,
		},
	}
	return transferAnnotationsQuery
}

func constructTransferRelationshipsToNodeQueryWithoutPlatformVersion(fromUUID string, toUUID string, predicate string) *neoism.CypherQuery {
	transferAnnotationsQuery := &neoism.CypherQuery{
		Statement: fmt.Sprintf(`MATCH (oldNode:Organisation {uuid:{fromUUID}})<-[oldRel:%s]-(p)
					WHERE not HAS(oldRel.platformVersion)
					MATCH (newNode:Organisation {uuid:{toUUID}})
					MERGE (newNode)<-[newRel:%s]-(p)
					ON CREATE SET newRel = oldRel
					DELETE oldRel`, predicate, predicate, predicate),

		Parameters: map[string]interface{}{
			"fromUUID": fromUUID,
			"toUUID":   toUUID,
		},
	}
	return transferAnnotationsQuery
}<|endoftext|>


<commit_before>package telebot

import (
	"fmt"
	"net/http"
	"os"
	"testing"
)

func TestBot(t *testing.T) {
	if testing.Short() {
		t.Skip("skipping test in short mode.")
	}

	token := os.Getenv("TELEBOT_SECRET")
	if token == "" {
		fmt.Println("ERROR: " +
			"In order to test telebot functionality, you need to set up " +
			"TELEBOT_SECRET environmental variable, which represents an API " +
			"key to a Telegram bot.\n")
		t.Fatal("Could't find TELEBOT_SECRET, aborting.")
	}

	_, err := NewBot(token)
	if err != nil {
		t.Fatal("Couldn't create bot:", err)
	}
}

func TestRecipient(_ *testing.T) {
	bot := Bot{Client: &http.Client{}}

	bot.SendMessage(User{}, "", nil)
	bot.SendMessage(Chat{}, "", nil)
}

func TestFile(t *testing.T) {
	file, err := NewFile("telebot.go")
	if err != nil {
		t.Fatal(err)
	}

	if file.Exists() {
		t.Fatal("Newly created file can't exist on Telegram servers!")
	}

	file.FileID = "magic"

	if !file.Exists() {
		t.Fatal("File with defined FileID is supposed to exist, fail.")
	}

	if file.Local() != "telebot.go" {
		t.Fatal("File doesn't preserve its original filename.")
	}
}

func TestChat(t *testing.T) {
	user := Chat{Type: "group", Title: "bazinga"}

	// According to API, chat object with group Type is a group chat.
	if !user.IsGroupChat() {
		t.Fatal("Can't tell private and group chats apart!")
	}

	// Reverse.
	user.Title = ""
	user.Type = "private"

	if user.IsGroupChat() {
		t.Fatal("Can't tell private and group chats apart!")
	}
}
<commit_msg>Revert "Prevent the build from failing no more."<commit_after>package telebot

import (
	"fmt"
	"os"
	"testing"
)

func TestBot(t *testing.T) {
	if testing.Short() {
		t.Skip("skipping test in short mode.")
	}

	token := os.Getenv("TELEBOT_SECRET")
	if token == "" {
		fmt.Println("ERROR: " +
			"In order to test telebot functionality, you need to set up " +
			"TELEBOT_SECRET environmental variable, which represents an API " +
			"key to a Telegram bot.\n")
		t.Fatal("Could't find TELEBOT_SECRET, aborting.")
	}

	_, err := NewBot(token)
	if err != nil {
		t.Fatal("Couldn't create bot:", err)
	}
}

func TestRecipient(_ *testing.T) {
	bot := Bot{}
	bot.SendMessage(User{}, "", nil)
	bot.SendMessage(Chat{}, "", nil)
}

func TestFile(t *testing.T) {
	file, err := NewFile("telebot.go")
	if err != nil {
		t.Fatal(err)
	}

	if file.Exists() {
		t.Fatal("Newly created file can't exist on Telegram servers!")
	}

	file.FileID = "magic"

	if !file.Exists() {
		t.Fatal("File with defined FileID is supposed to exist, fail.")
	}

	if file.Local() != "telebot.go" {
		t.Fatal("File doesn't preserve its original filename.")
	}
}

func TestChat(t *testing.T) {
	user := Chat{Type: "group", Title: "bazinga"}

	// According to API, chat object with group Type is a group chat.
	if !user.IsGroupChat() {
		t.Fatal("Can't tell private and group chats apart!")
	}

	// Reverse.
	user.Title = ""
	user.Type = "private"

	if user.IsGroupChat() {
		t.Fatal("Can't tell private and group chats apart!")
	}
}
<|endoftext|>


<commit_before>// SPDX-License-Identifier: Apache-2.0
// Copyright Authors of Cilium

package k8sTest

import (
	"fmt"
	"strings"

	. "github.com/onsi/gomega"

	. "github.com/cilium/cilium/test/ginkgo-ext"
	"github.com/cilium/cilium/test/helpers"
)

var _ = Describe("K8sCLI", func() {
	SkipContextIf(func() bool {
		return helpers.DoesNotRunOnGKE() && helpers.DoesNotRunOnEKS()
	}, "CLI", func() {
		var kubectl *helpers.Kubectl
		var ciliumFilename string

		BeforeAll(func() {
			kubectl = helpers.CreateKubectl(helpers.K8s1VMName(), logger)

			ciliumFilename = helpers.TimestampFilename("cilium.yaml")
			DeployCiliumAndDNS(kubectl, ciliumFilename)
			ExpectCiliumReady(kubectl)
		})

		AfterAll(func() {
			UninstallCiliumFromManifest(kubectl, ciliumFilename)
		})

		JustAfterEach(func() {
			kubectl.ValidateNoErrorsInLogs(CurrentGinkgoTestDescription().Duration)
		})

		Context("Identity CLI testing", func() {
			const (
				manifestYAML = "test-cli.yaml"
				fooID        = "foo"
				fooSHA       = "a83c739e630049e46b9ac6883dc2682b31bf8472b09c8bb81d87092a51d14ddf"
				fooNode      = "k8s1"
				// These labels are automatically added to all pods in the default namespace.
				defaultLabels = "k8s:io.cilium.k8s.policy.cluster=default " +
					"k8s:io.cilium.k8s.policy.serviceaccount=default k8s:io.kubernetes.pod.namespace=default"
			)

			var (
				cliManifest string
				ciliumPod   string
				err         error
				identity    int64
			)

			BeforeAll(func() {
				cliManifest = helpers.ManifestGet(kubectl.BasePath(), manifestYAML)
				res := kubectl.ApplyDefault(cliManifest)
				res.ExpectSuccess("Unable to apply %s", cliManifest)
				err = kubectl.WaitforPods(helpers.DefaultNamespace, "-l id", helpers.HelperTimeout)
				Expect(err).Should(BeNil(), "The pods were not ready after timeout")

				ciliumPod, err = kubectl.GetCiliumPodOnNode(fooNode)
				Expect(err).Should(BeNil())

				err := kubectl.WaitForCEPIdentity(helpers.DefaultNamespace, fooID)
				Expect(err).Should(BeNil())

				ep, err := kubectl.GetCiliumEndpoint(helpers.DefaultNamespace, fooID)
				Expect(err).Should(BeNil(), fmt.Sprintf("Unable to get CEP for pod %s", fooID))
				identity = ep.Identity.ID
			})

			AfterAll(func() {
				_ = kubectl.Delete(cliManifest)
				ExpectAllPodsTerminated(kubectl)
			})

			It("Test labelsSHA256", func() {
				cmd := fmt.Sprintf("cilium identity get %d -o json", identity)
				res := kubectl.ExecPodCmd(helpers.CiliumNamespace, ciliumPod, cmd)
				res.ExpectSuccess()
				out, err := res.Filter("{[0].labelsSHA256}")
				Expect(err).Should(BeNil(), "Error getting SHA from identity")
				Expect(out.String()).Should(Equal(fooSHA))
			})

			It("Test identity list", func() {
				By("Testing 'cilium identity list' for an endpoint's identity")
				cmd := fmt.Sprintf("cilium identity list k8s:id=%s %s", fooID, defaultLabels)
				res := kubectl.ExecPodCmd(helpers.CiliumNamespace, ciliumPod, cmd)
				res.ExpectSuccess(fmt.Sprintf("Unable to get identity list output for label k8s:id=%s %s", fooID, defaultLabels))

				resSingleOut := res.SingleOut()
				containsIdentity := strings.Contains(resSingleOut, fmt.Sprintf("%d", identity))
				Expect(containsIdentity).To(BeTrue(), "Identity %d of endpoint %s not in 'cilium identity list' output", identity, resSingleOut)

				By("Testing 'cilium identity list' for reserved identities")
				res = kubectl.ExecPodCmd(helpers.CiliumNamespace, ciliumPod, "cilium identity list")
				res.ExpectSuccess("Unable to get identity list output")
				resSingleOut = res.SingleOut()

				reservedIdentities := []string{"health", "host", "world", "init"}
				for _, id := range reservedIdentities {
					By("Checking that reserved identity '%s' is in 'cilium identity list' output", id)
					containsReservedIdentity := strings.Contains(resSingleOut, id)
					Expect(containsReservedIdentity).To(BeTrue(), "Reserved identity '%s' not in 'cilium identity list' output", id)
				}
			})

			It("Test cilium bpf metrics list", func() {
				demoManifest := helpers.ManifestGet(kubectl.BasePath(), "demo-named-port.yaml")
				app1Service := "app1-service"
				l3L4DenyPolicy := helpers.ManifestGet(kubectl.BasePath(), "l3-l4-policy-deny.yaml")

				namespaceForTest := helpers.GenerateNamespaceForTest("")
				kubectl.NamespaceDelete(namespaceForTest)
				kubectl.NamespaceCreate(namespaceForTest).ExpectSuccess("could not create namespace")
				kubectl.Apply(helpers.ApplyOptions{FilePath: demoManifest, Namespace: namespaceForTest}).ExpectSuccess("could not create resource")

				err := kubectl.WaitforPods(namespaceForTest, "-l zgroup=testapp", helpers.HelperTimeout)
				Expect(err).To(BeNil(),
					"testapp pods are not ready after timeout in namespace %q", namespaceForTest)

				_, err = kubectl.CiliumPolicyAction(
					namespaceForTest, l3L4DenyPolicy, helpers.KubectlApply, helpers.HelperTimeout)
				Expect(err).Should(BeNil(), "Cannot apply L3 Deny Policy")

				ciliumPodK8s1, err := kubectl.GetCiliumPodOnNode(helpers.K8s1)
				ExpectWithOffset(2, err).Should(BeNil(), "Cannot get cilium pod on k8s1")
				ciliumPodK8s2, err := kubectl.GetCiliumPodOnNode(helpers.K8s2)
				ExpectWithOffset(2, err).Should(BeNil(), "Cannot get cilium pod on k8s2")

				countBeforeK8s1, _ := helpers.GetBPFPacketsCount(kubectl, ciliumPodK8s1, "Policy denied by denylist", "ingress")
				countBeforeK8s2, _ := helpers.GetBPFPacketsCount(kubectl, ciliumPodK8s2, "Policy denied by denylist", "ingress")

				appPods := helpers.GetAppPods([]string{helpers.App2}, namespaceForTest, kubectl, "id")

				clusterIP, _, err := kubectl.GetServiceHostPort(namespaceForTest, app1Service)
				Expect(err).To(BeNil(), "Cannot get service in %q namespace", namespaceForTest)

				res := kubectl.ExecPodCmd(
					namespaceForTest, appPods[helpers.App2],
					helpers.CurlFail("http://%s/public", clusterIP))
				res.ExpectFail("Unexpected connection from %q to 'http://%s/public'",
					appPods[helpers.App2], clusterIP)

				countAfterK8s1, _ := helpers.GetBPFPacketsCount(kubectl, ciliumPodK8s1, "Policy denied by denylist", "ingress")
				countAfterK8s2, _ := helpers.GetBPFPacketsCount(kubectl, ciliumPodK8s2, "Policy denied by denylist", "ingress")

				Expect((countAfterK8s1 + countAfterK8s2) - (countBeforeK8s1 + countBeforeK8s2)).To(Equal(3))

				_, err = kubectl.CiliumPolicyAction(
					namespaceForTest, l3L4DenyPolicy, helpers.KubectlDelete, helpers.HelperTimeout)
				Expect(err).Should(BeNil(), "Cannot delete L3 Policy")

				kubectl.NamespaceDelete(namespaceForTest)
			})
		})

		Context("stdout/stderr testing", func() {
			var (
				ciliumPod string
				err       error
			)

			BeforeAll(func() {
				ciliumPod, err = kubectl.GetCiliumPodOnNode("k8s1")
				Expect(err).Should(BeNil())
			})

			It("Root command help should print to stdout", func() {
				res := kubectl.ExecPodCmd(helpers.CiliumNamespace, ciliumPod, "cilium help")
				Expect(res.Stdout()).Should(ContainSubstring("Use \"cilium [command] --help\" for more information about a command."))
			})

			It("Subcommand help should print to stdout", func() {
				res := kubectl.ExecPodCmd(helpers.CiliumNamespace, ciliumPod, "cilium help bpf")
				Expect(res.Stdout()).Should(ContainSubstring("Use \"cilium bpf [command] --help\" for more information about a command."))
			})

			It("Failed subcommand should print help to stdout", func() {
				res := kubectl.ExecPodCmd(helpers.CiliumNamespace, ciliumPod, "cilium endpoint confi 173")
				Expect(res.Stdout()).Should(ContainSubstring("Use \"cilium endpoint [command] --help\" for more information about a command."))
			})
		})
	})
})
<commit_msg>tests: fix K8sCLI tests based on labels<commit_after>// SPDX-License-Identifier: Apache-2.0
// Copyright Authors of Cilium

package k8sTest

import (
	"fmt"
	"strings"

	. "github.com/onsi/gomega"

	. "github.com/cilium/cilium/test/ginkgo-ext"
	"github.com/cilium/cilium/test/helpers"
)

var _ = Describe("K8sCLI", func() {
	SkipContextIf(func() bool {
		return helpers.DoesNotRunOnGKE() && helpers.DoesNotRunOnEKS()
	}, "CLI", func() {
		var kubectl *helpers.Kubectl
		var ciliumFilename string

		BeforeAll(func() {
			kubectl = helpers.CreateKubectl(helpers.K8s1VMName(), logger)

			ciliumFilename = helpers.TimestampFilename("cilium.yaml")
			DeployCiliumAndDNS(kubectl, ciliumFilename)
			ExpectCiliumReady(kubectl)
		})

		AfterAll(func() {
			UninstallCiliumFromManifest(kubectl, ciliumFilename)
		})

		JustAfterEach(func() {
			kubectl.ValidateNoErrorsInLogs(CurrentGinkgoTestDescription().Duration)
		})

		Context("Identity CLI testing", func() {
			const (
				manifestYAML = "test-cli.yaml"
				fooID        = "foo"
				fooSHA       = "c97de9490c28e929fd143f1988deba185345aab2a3a171fabcb8a0d03db68240"
				fooNode      = "k8s1"
				// These labels are automatically added to all pods in the default namespace.
				defaultLabels = "k8s:io.cilium.k8s.namespace.labels.kubernetes.io/metadata.name=default " +
					"k8s:io.cilium.k8s.policy.cluster=default " +
					"k8s:io.cilium.k8s.policy.serviceaccount=default " +
					"k8s:io.kubernetes.pod.namespace=default"
			)

			var (
				cliManifest string
				ciliumPod   string
				err         error
				identity    int64
			)

			BeforeAll(func() {
				cliManifest = helpers.ManifestGet(kubectl.BasePath(), manifestYAML)
				res := kubectl.ApplyDefault(cliManifest)
				res.ExpectSuccess("Unable to apply %s", cliManifest)
				err = kubectl.WaitforPods(helpers.DefaultNamespace, "-l id", helpers.HelperTimeout)
				Expect(err).Should(BeNil(), "The pods were not ready after timeout")

				ciliumPod, err = kubectl.GetCiliumPodOnNode(fooNode)
				Expect(err).Should(BeNil())

				err := kubectl.WaitForCEPIdentity(helpers.DefaultNamespace, fooID)
				Expect(err).Should(BeNil())

				ep, err := kubectl.GetCiliumEndpoint(helpers.DefaultNamespace, fooID)
				Expect(err).Should(BeNil(), fmt.Sprintf("Unable to get CEP for pod %s", fooID))
				identity = ep.Identity.ID
			})

			AfterAll(func() {
				_ = kubectl.Delete(cliManifest)
				ExpectAllPodsTerminated(kubectl)
			})

			It("Test labelsSHA256", func() {
				cmd := fmt.Sprintf("cilium identity get %d -o json", identity)
				res := kubectl.ExecPodCmd(helpers.CiliumNamespace, ciliumPod, cmd)
				res.ExpectSuccess()
				out, err := res.Filter("{[0].labelsSHA256}")
				Expect(err).Should(BeNil(), "Error getting SHA from identity")
				Expect(out.String()).Should(Equal(fooSHA))
			})

			It("Test identity list", func() {
				By("Testing 'cilium identity list' for an endpoint's identity")
				cmd := fmt.Sprintf("cilium identity list k8s:id=%s %s", fooID, defaultLabels)
				res := kubectl.ExecPodCmd(helpers.CiliumNamespace, ciliumPod, cmd)
				res.ExpectSuccess(fmt.Sprintf("Unable to get identity list output for label k8s:id=%s %s", fooID, defaultLabels))

				resSingleOut := res.SingleOut()
				containsIdentity := strings.Contains(resSingleOut, fmt.Sprintf("%d", identity))
				Expect(containsIdentity).To(BeTrue(), "Identity %d of endpoint %s not in 'cilium identity list' output", identity, resSingleOut)

				By("Testing 'cilium identity list' for reserved identities")
				res = kubectl.ExecPodCmd(helpers.CiliumNamespace, ciliumPod, "cilium identity list")
				res.ExpectSuccess("Unable to get identity list output")
				resSingleOut = res.SingleOut()

				reservedIdentities := []string{"health", "host", "world", "init"}
				for _, id := range reservedIdentities {
					By("Checking that reserved identity '%s' is in 'cilium identity list' output", id)
					containsReservedIdentity := strings.Contains(resSingleOut, id)
					Expect(containsReservedIdentity).To(BeTrue(), "Reserved identity '%s' not in 'cilium identity list' output", id)
				}
			})

			It("Test cilium bpf metrics list", func() {
				demoManifest := helpers.ManifestGet(kubectl.BasePath(), "demo-named-port.yaml")
				app1Service := "app1-service"
				l3L4DenyPolicy := helpers.ManifestGet(kubectl.BasePath(), "l3-l4-policy-deny.yaml")

				namespaceForTest := helpers.GenerateNamespaceForTest("")
				kubectl.NamespaceDelete(namespaceForTest)
				kubectl.NamespaceCreate(namespaceForTest).ExpectSuccess("could not create namespace")
				kubectl.Apply(helpers.ApplyOptions{FilePath: demoManifest, Namespace: namespaceForTest}).ExpectSuccess("could not create resource")

				err := kubectl.WaitforPods(namespaceForTest, "-l zgroup=testapp", helpers.HelperTimeout)
				Expect(err).To(BeNil(),
					"testapp pods are not ready after timeout in namespace %q", namespaceForTest)

				_, err = kubectl.CiliumPolicyAction(
					namespaceForTest, l3L4DenyPolicy, helpers.KubectlApply, helpers.HelperTimeout)
				Expect(err).Should(BeNil(), "Cannot apply L3 Deny Policy")

				ciliumPodK8s1, err := kubectl.GetCiliumPodOnNode(helpers.K8s1)
				ExpectWithOffset(2, err).Should(BeNil(), "Cannot get cilium pod on k8s1")
				ciliumPodK8s2, err := kubectl.GetCiliumPodOnNode(helpers.K8s2)
				ExpectWithOffset(2, err).Should(BeNil(), "Cannot get cilium pod on k8s2")

				countBeforeK8s1, _ := helpers.GetBPFPacketsCount(kubectl, ciliumPodK8s1, "Policy denied by denylist", "ingress")
				countBeforeK8s2, _ := helpers.GetBPFPacketsCount(kubectl, ciliumPodK8s2, "Policy denied by denylist", "ingress")

				appPods := helpers.GetAppPods([]string{helpers.App2}, namespaceForTest, kubectl, "id")

				clusterIP, _, err := kubectl.GetServiceHostPort(namespaceForTest, app1Service)
				Expect(err).To(BeNil(), "Cannot get service in %q namespace", namespaceForTest)

				res := kubectl.ExecPodCmd(
					namespaceForTest, appPods[helpers.App2],
					helpers.CurlFail("http://%s/public", clusterIP))
				res.ExpectFail("Unexpected connection from %q to 'http://%s/public'",
					appPods[helpers.App2], clusterIP)

				countAfterK8s1, _ := helpers.GetBPFPacketsCount(kubectl, ciliumPodK8s1, "Policy denied by denylist", "ingress")
				countAfterK8s2, _ := helpers.GetBPFPacketsCount(kubectl, ciliumPodK8s2, "Policy denied by denylist", "ingress")

				Expect((countAfterK8s1 + countAfterK8s2) - (countBeforeK8s1 + countBeforeK8s2)).To(Equal(3))

				_, err = kubectl.CiliumPolicyAction(
					namespaceForTest, l3L4DenyPolicy, helpers.KubectlDelete, helpers.HelperTimeout)
				Expect(err).Should(BeNil(), "Cannot delete L3 Policy")

				kubectl.NamespaceDelete(namespaceForTest)
			})
		})

		Context("stdout/stderr testing", func() {
			var (
				ciliumPod string
				err       error
			)

			BeforeAll(func() {
				ciliumPod, err = kubectl.GetCiliumPodOnNode("k8s1")
				Expect(err).Should(BeNil())
			})

			It("Root command help should print to stdout", func() {
				res := kubectl.ExecPodCmd(helpers.CiliumNamespace, ciliumPod, "cilium help")
				Expect(res.Stdout()).Should(ContainSubstring("Use \"cilium [command] --help\" for more information about a command."))
			})

			It("Subcommand help should print to stdout", func() {
				res := kubectl.ExecPodCmd(helpers.CiliumNamespace, ciliumPod, "cilium help bpf")
				Expect(res.Stdout()).Should(ContainSubstring("Use \"cilium bpf [command] --help\" for more information about a command."))
			})

			It("Failed subcommand should print help to stdout", func() {
				res := kubectl.ExecPodCmd(helpers.CiliumNamespace, ciliumPod, "cilium endpoint confi 173")
				Expect(res.Stdout()).Should(ContainSubstring("Use \"cilium endpoint [command] --help\" for more information about a command."))
			})
		})
	})
})
<|endoftext|>


<commit_before>package emitter

import (
	"fmt"
	"log"
	"regexp"
	"strings"

	"code.cloudfoundry.org/lager"
	"github.com/DataDog/datadog-go/statsd"
	"github.com/concourse/concourse/atc/metric"
	"github.com/pkg/errors"
)

type DogstatsdEmitter struct {
	client *statsd.Client
}

type DogstatsDBConfig struct {
	Host   string `long:"datadog-agent-host" description:"Datadog agent host to expose dogstatsd metrics"`
	Port   string `long:"datadog-agent-port" description:"Datadog agent port to expose dogstatsd metrics"`
	UDS    string `long:"datadog-agent-uds-filepath" description:"Datadog agent unix domain socket (uds) filepath to expose dogstatsd metrics"`
	Prefix string `long:"datadog-prefix" description:"Prefix for all metrics to easily find them in Datadog"`
}

func init() {
	metric.Metrics.RegisterEmitter(&DogstatsDBConfig{})
}

func (config *DogstatsDBConfig) Description() string { return "Datadog" }

func (config *DogstatsDBConfig) IsConfigured() bool { return config.Host != "" && config.Port != "" }

func (config *DogstatsDBConfig) NewEmitter(_ map[string]string) (metric.Emitter, error) {
	var client *statsd.Client
	var err error
	if config.UDS != "" {
		client, err = statsd.New("unix://" + config.UDS)
	} else {
		client, err = statsd.New(fmt.Sprintf("%s:%s", config.Host, config.Port))
	}

	if err != nil {
		log.Fatal(err)
		return &DogstatsdEmitter{}, err
	}

	if config.Prefix != "" {
		if strings.HasSuffix(config.Prefix, ".") {
			client.Namespace = config.Prefix
		} else {
			client.Namespace = fmt.Sprintf("%s.", config.Prefix)
		}
	}

	return &DogstatsdEmitter{
		client: client,
	}, nil
}

var specialChars = regexp.MustCompile("[^a-zA-Z0-9_]+")

func (emitter *DogstatsdEmitter) Emit(logger lager.Logger, event metric.Event) {
	name := specialChars.ReplaceAllString(strings.Replace(strings.ToLower(event.Name), " ", "_", -1), "")

	tags := []string{
		fmt.Sprintf("host:%s", event.Host),
	}

	for k, v := range event.Attributes {
		tags = append(tags, fmt.Sprintf("%s:%s", k, v))
	}

	err := emitter.client.Gauge(name, event.Value, tags, 1)
	if err != nil {
		logger.Error("failed-to-send-metric",
			errors.Wrap(metric.ErrFailedToEmit, err.Error()))
		return
	}
}
<commit_msg>fix dogstatsd UDS file<commit_after>package emitter

import (
	"fmt"
	"log"
	"regexp"
	"strings"

	"code.cloudfoundry.org/lager"
	"github.com/DataDog/datadog-go/statsd"
	"github.com/concourse/concourse/atc/metric"
	"github.com/pkg/errors"
)

type DogstatsdEmitter struct {
	client *statsd.Client
}

type DogstatsDBConfig struct {
	Host   string `long:"datadog-agent-host" description:"Datadog agent host to expose dogstatsd metrics"`
	Port   string `long:"datadog-agent-port" description:"Datadog agent port to expose dogstatsd metrics"`
	UDS    string `long:"datadog-agent-uds-filepath" description:"Datadog agent unix domain socket (uds) filepath to expose dogstatsd metrics"`
	Prefix string `long:"datadog-prefix" description:"Prefix for all metrics to easily find them in Datadog"`
}

func init() {
	metric.Metrics.RegisterEmitter(&DogstatsDBConfig{})
}

func (config *DogstatsDBConfig) Description() string { return "Datadog" }

func (config *DogstatsDBConfig) IsConfigured() bool {
	return (config.Host != "" && config.Port != "") || config.UDS != ""
}

func (config *DogstatsDBConfig) NewEmitter(_ map[string]string) (metric.Emitter, error) {
	var client *statsd.Client
	var err error
	if config.UDS != "" {
		client, err = statsd.New("unix://" + config.UDS)
	} else {
		client, err = statsd.New(fmt.Sprintf("%s:%s", config.Host, config.Port))
	}

	if err != nil {
		log.Fatal(err)
		return &DogstatsdEmitter{}, err
	}

	if config.Prefix != "" {
		if strings.HasSuffix(config.Prefix, ".") {
			client.Namespace = config.Prefix
		} else {
			client.Namespace = fmt.Sprintf("%s.", config.Prefix)
		}
	}

	return &DogstatsdEmitter{
		client: client,
	}, nil
}

var specialChars = regexp.MustCompile("[^a-zA-Z0-9_]+")

func (emitter *DogstatsdEmitter) Emit(logger lager.Logger, event metric.Event) {
	name := specialChars.ReplaceAllString(strings.Replace(strings.ToLower(event.Name), " ", "_", -1), "")

	tags := []string{
		fmt.Sprintf("host:%s", event.Host),
	}

	for k, v := range event.Attributes {
		tags = append(tags, fmt.Sprintf("%s:%s", k, v))
	}

	err := emitter.client.Gauge(name, event.Value, tags, 1)
	if err != nil {
		logger.Error("failed-to-send-metric",
			errors.Wrap(metric.ErrFailedToEmit, err.Error()))
		return
	}
}
<|endoftext|>


<commit_before>// Copyright 2016 Documize Inc. <legal@documize.com>. All rights reserved.
//
// This software (Documize Community Edition) is licensed under
// GNU AGPL v3 http://www.gnu.org/licenses/agpl-3.0.en.html
//
// You can operate outside the AGPL restrictions by purchasing
// Documize Enterprise Edition and obtaining a commercial license
// by contacting <sales@documize.com>.
//
// https://documize.com

package core

import "fmt"

// ProdInfo describes a product
type ProdInfo struct {
	Edition string
	Title   string
	Version string
	Major   string
	Minor   string
	Patch   string
}

// Product returns product edition details
func Product() (p ProdInfo) {
	p.Major = "0"
	p.Minor = "26"
	p.Patch = "0"
	p.Version = fmt.Sprintf("%s.%s.%s", p.Major, p.Minor, p.Patch)
	p.Edition = "Community"
	p.Title = fmt.Sprintf("%s Edition", p.Edition)

	return p
}
<commit_msg>bumped version<commit_after>// Copyright 2016 Documize Inc. <legal@documize.com>. All rights reserved.
//
// This software (Documize Community Edition) is licensed under
// GNU AGPL v3 http://www.gnu.org/licenses/agpl-3.0.en.html
//
// You can operate outside the AGPL restrictions by purchasing
// Documize Enterprise Edition and obtaining a commercial license
// by contacting <sales@documize.com>.
//
// https://documize.com

package core

import "fmt"

// ProdInfo describes a product
type ProdInfo struct {
	Edition string
	Title   string
	Version string
	Major   string
	Minor   string
	Patch   string
}

// Product returns product edition details
func Product() (p ProdInfo) {
	p.Major = "0"
	p.Minor = "26"
	p.Patch = "1"
	p.Version = fmt.Sprintf("%s.%s.%s", p.Major, p.Minor, p.Patch)
	p.Edition = "Community"
	p.Title = fmt.Sprintf("%s Edition", p.Edition)

	return p
}
<|endoftext|>


<commit_before>package core

import (
	"fmt"
	"log"
	"os"
	"os/signal"
	"pilosa/config"
	"pilosa/db"
	"pilosa/hold"
	"pilosa/index"
	"pilosa/interfaces"
	"syscall"

	"github.com/coreos/go-etcd/etcd"
	"tux21b.org/v1/gocql/uuid"
)

type Service struct {
	Stopper
	Id             *uuid.UUID
	Etcd           *etcd.Client
	Cluster        *db.Cluster
	TopologyMapper *TopologyMapper
	ProcessMapper  *ProcessMapper
	ProcessMap     *ProcessMap
	Transport      interfaces.Transporter
	Dispatch       interfaces.Dispatcher
	Executor       interfaces.Executorer
	WebService     *WebService
	Index          *index.FragmentContainer
	Hold           *hold.Holder
	version        string
	name           string
}

func NewService() *Service {
	service := new(Service)
	service.init_id()
	etc_hosts := config.GetStringArrayDefault("etcd_servers", []string{})

	service.Etcd = etcd.NewClient(etc_hosts)
	service.Cluster = db.NewCluster()
	service.TopologyMapper = NewTopologyMapper(service, "/pilosa/0")
	service.ProcessMapper = NewProcessMapper(service, "/pilosa/0")
	service.ProcessMap = NewProcessMap()
	service.WebService = NewWebService(service)
	service.Index = index.NewFragmentContainer()
	service.Hold = hold.NewHolder()
	service.version = "0.0.11"
	service.name = "Cruncher"
	service.PrepareLogging()
	fmt.Printf("Pilosa %s\n", service.version)
	return service
}

func (self *Service) PrepareLogging() {
	base_path := config.GetString("log_path")
	if base_path == "" {
		base_path = "/tmp"
	}
	f, err := os.OpenFile(fmt.Sprintf("%s/%s.%s", base_path, self.name, self.Id), os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
	if err != nil {
		log.Println("error opening file: %v", err)
	}
	//defer f.Close()
	log.SetOutput(f)
}

func (service *Service) init_id() {
	var id uuid.UUID
	var err error
	id_string := config.GetString("id")
	if id_string == "" {
		log.Println("Service id not configured, generating...")
		id = uuid.RandomUUID()
		if err != nil {
			log.Fatal("problem generating uuid")
		}
	} else {
		id, err = uuid.ParseUUID(id_string)
		if err != nil {
			log.Fatalf("Service id '%s' not valid", id_string)
		}
	}
	service.Id = &id
}

func (self *Service) GetProcess() (*db.Process, error) {
	return self.ProcessMap.GetProcess(self.Id)
}

func (service *Service) GetSignals() (chan os.Signal, chan os.Signal) {
	hupChan := make(chan os.Signal, 1)
	termChan := make(chan os.Signal, 1)
	signal.Notify(hupChan, syscall.SIGHUP)
	signal.Notify(termChan, syscall.SIGINT, syscall.SIGTERM)
	return termChan, hupChan
}

func (service *Service) Run() {
	log.Println("Running service...", service.version)
	go service.TopologyMapper.Run()
	go service.ProcessMapper.Run()
	go service.WebService.Run()
	go service.Transport.Run()
	go service.Dispatch.Run()
	go service.Executor.Run()
	go service.Hold.Run()

	sigterm, sighup := service.GetSignals()
	for {
		select {
		case <-sighup:
			log.Println("SIGHUP! Reloading configuration...")
			// TODO: reload configuration
		case <-sigterm:
			log.Println("SIGTERM! Cleaning up...")
			service.Index.Shutdown()
			service.Stop()
			return
		}
	}
}

type Message interface {
	Handle(*Service)
}
<commit_msg>inc version<commit_after>package core

import (
	"fmt"
	"log"
	"os"
	"os/signal"
	"pilosa/config"
	"pilosa/db"
	"pilosa/hold"
	"pilosa/index"
	"pilosa/interfaces"
	"syscall"

	"github.com/coreos/go-etcd/etcd"
	"tux21b.org/v1/gocql/uuid"
)

type Service struct {
	Stopper
	Id             *uuid.UUID
	Etcd           *etcd.Client
	Cluster        *db.Cluster
	TopologyMapper *TopologyMapper
	ProcessMapper  *ProcessMapper
	ProcessMap     *ProcessMap
	Transport      interfaces.Transporter
	Dispatch       interfaces.Dispatcher
	Executor       interfaces.Executorer
	WebService     *WebService
	Index          *index.FragmentContainer
	Hold           *hold.Holder
	version        string
	name           string
}

func NewService() *Service {
	service := new(Service)
	service.init_id()
	etc_hosts := config.GetStringArrayDefault("etcd_servers", []string{})

	service.Etcd = etcd.NewClient(etc_hosts)
	service.Cluster = db.NewCluster()
	service.TopologyMapper = NewTopologyMapper(service, "/pilosa/0")
	service.ProcessMapper = NewProcessMapper(service, "/pilosa/0")
	service.ProcessMap = NewProcessMap()
	service.WebService = NewWebService(service)
	service.Index = index.NewFragmentContainer()
	service.Hold = hold.NewHolder()
	service.version = "0.0.12"
	service.name = "Cruncher"
	service.PrepareLogging()
	fmt.Printf("Pilosa %s\n", service.version)
	return service
}

func (self *Service) PrepareLogging() {
	base_path := config.GetString("log_path")
	if base_path == "" {
		base_path = "/tmp"
	}
	f, err := os.OpenFile(fmt.Sprintf("%s/%s.%s", base_path, self.name, self.Id), os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
	if err != nil {
		log.Println("error opening file: %v", err)
	}
	//defer f.Close()
	log.SetOutput(f)
}

func (service *Service) init_id() {
	var id uuid.UUID
	var err error
	id_string := config.GetString("id")
	if id_string == "" {
		log.Println("Service id not configured, generating...")
		id = uuid.RandomUUID()
		if err != nil {
			log.Fatal("problem generating uuid")
		}
	} else {
		id, err = uuid.ParseUUID(id_string)
		if err != nil {
			log.Fatalf("Service id '%s' not valid", id_string)
		}
	}
	service.Id = &id
}

func (self *Service) GetProcess() (*db.Process, error) {
	return self.ProcessMap.GetProcess(self.Id)
}

func (service *Service) GetSignals() (chan os.Signal, chan os.Signal) {
	hupChan := make(chan os.Signal, 1)
	termChan := make(chan os.Signal, 1)
	signal.Notify(hupChan, syscall.SIGHUP)
	signal.Notify(termChan, syscall.SIGINT, syscall.SIGTERM)
	return termChan, hupChan
}

func (service *Service) Run() {
	log.Println("Running service...", service.version)
	go service.TopologyMapper.Run()
	go service.ProcessMapper.Run()
	go service.WebService.Run()
	go service.Transport.Run()
	go service.Dispatch.Run()
	go service.Executor.Run()
	go service.Hold.Run()

	sigterm, sighup := service.GetSignals()
	for {
		select {
		case <-sighup:
			log.Println("SIGHUP! Reloading configuration...")
			// TODO: reload configuration
		case <-sigterm:
			log.Println("SIGTERM! Cleaning up...")
			service.Index.Shutdown()
			service.Stop()
			return
		}
	}
}

type Message interface {
	Handle(*Service)
}
<|endoftext|>