<commit_before>// Copyright 2016 The Serviced 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 service

// AggregateService is a lighter service object for providing aggregate service
// status information
type AggregateService struct {
	ServiceID    string
	DesiredState DesiredState
	Status       []StatusInstance
	NotFound     bool
}

// PublicEndpoint is a minimal service object that describes a public endpoint
// for a service
type PublicEndpoint struct {
	ServiceID   string
	ServiceName string
	Application string
	Protocol    string
	VHostName   string
	PortAddress string
	Enabled     bool
}

// IPAssignment is a minimal service object that describes an address assignment
// for a service.
type IPAssignment struct {
	ServiceID   string
	ServiceName string
	PoolID      string
	HostID      string
	HostName    string
	Type        string
	IPAddress   string
	Ports       []uint16
}

// Config displays the most basic information about a service config file
type Config struct {
	ID       string
	Filename string
}
<commit_msg>make public endpoint "name" mutually exclusive<commit_after>// Copyright 2016 The Serviced 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 service

// AggregateService is a lighter service object for providing aggregate service
// status information
type AggregateService struct {
	ServiceID    string
	DesiredState DesiredState
	Status       []StatusInstance
	NotFound     bool
}

// PublicEndpoint is a minimal service object that describes a public endpoint
// for a service
type PublicEndpoint struct {
	ServiceID   string
	ServiceName string
	Application string
	Protocol    string
	VHostName   string `json:",omitempty"`
	PortAddress string `json:",omitempty"`
	Enabled     bool
}

// IPAssignment is a minimal service object that describes an address assignment
// for a service.
type IPAssignment struct {
	ServiceID   string
	ServiceName string
	PoolID      string
	HostID      string
	HostName    string
	Type        string
	IPAddress   string
	Ports       []uint16
}

// Config displays the most basic information about a service config file
type Config struct {
	ID       string
	Filename string
}
<|endoftext|>


<commit_before>package securitygroup

import (
	"encoding/json"
	"fmt"
	"strings"

	cfclient "github.com/cloudfoundry-community/go-cfclient"
	"github.com/pivotalservices/cf-mgmt/config"
	"github.com/pivotalservices/cf-mgmt/space"
	"github.com/pkg/errors"
	"github.com/xchapter7x/lo"
)

//NewManager -
func NewManager(client CFClient, spaceMgr space.Manager, cfg config.Reader, peek bool) Manager {
	return &DefaultManager{
		Cfg:          cfg,
		Client:       client,
		SpaceManager: spaceMgr,
		Peek:         peek,
	}
}

//DefaultSecurityGroupManager -
type DefaultManager struct {
	Cfg          config.Reader
	SpaceManager space.Manager
	Client       CFClient
	Peek         bool
}

//CreateApplicationSecurityGroups -
func (m *DefaultManager) CreateApplicationSecurityGroups() error {
	spaceConfigs, err := m.Cfg.GetSpaceConfigs()
	if err != nil {
		return err
	}
	sgs, err := m.ListNonDefaultSecurityGroups()
	if err != nil {
		return err
	}

	for _, input := range spaceConfigs {
		space, err := m.SpaceManager.FindSpace(input.Org, input.Space)
		if err != nil {
			return err
		}

		existingSpaceSecurityGroups, err := m.ListSpaceSecurityGroups(space.Guid)
		if err != nil {
			return errors.Wrapf(err, "Unabled to list existing space security groups for org/space [%s/%s]", input.Org, input.Space)
		}
		lo.G.Debugf("Existing space security groups %+v", existingSpaceSecurityGroups)
		// iterate through and assign named security groups to the space - ensuring that they are up to date is
		// done elsewhere.
		for _, securityGroupName := range input.ASGs {
			if sgInfo, ok := sgs[securityGroupName]; ok {
				if _, ok := existingSpaceSecurityGroups[securityGroupName]; !ok {
					err := m.AssignSecurityGroupToSpace(space, sgInfo)
					if err != nil {
						return err
					}
				} else {
					delete(existingSpaceSecurityGroups, securityGroupName)
				}
			} else {
				return fmt.Errorf("Security group [%s] does not exist", securityGroupName)
			}
		}

		spaceSecurityGroupName := fmt.Sprintf("%s-%s", input.Org, input.Space)
		if input.EnableSecurityGroup {
			var sgInfo cfclient.SecGroup
			var ok bool
			if sgInfo, ok = sgs[spaceSecurityGroupName]; ok {
				changed, err := m.hasSecurityGroupChanged(sgInfo, input.GetSecurityGroupContents())
				if err != nil {
					return errors.Wrapf(err, "Checking if security group %s has changed", spaceSecurityGroupName)
				}
				if changed {
					if err := m.UpdateSecurityGroup(sgInfo, input.GetSecurityGroupContents()); err != nil {
						return err
					}
				}
			} else {
				securityGroup, err := m.CreateSecurityGroup(spaceSecurityGroupName, input.GetSecurityGroupContents())
				if err != nil {
					return err
				}
				sgInfo = *securityGroup
			}
			if _, ok := existingSpaceSecurityGroups[spaceSecurityGroupName]; !ok {
				err := m.AssignSecurityGroupToSpace(space, sgInfo)
				if err != nil {
					return err
				}
			} else {
				delete(existingSpaceSecurityGroups, spaceSecurityGroupName)
			}
		}

		if input.EnableUnassignSecurityGroup {
			lo.G.Debugf("Existing space security groups after %+v", existingSpaceSecurityGroups)
			for sgName, _ := range existingSpaceSecurityGroups {
				if sgInfo, ok := sgs[sgName]; ok {
					err := m.UnassignSecurityGroupToSpace(space, sgInfo)
					if err != nil {
						return err
					}
				} else {
					return fmt.Errorf("Security group [%s] does not exist", sgName)
				}
			}
		}
	}
	return nil
}

func (m *DefaultManager) ListSecurityGroups() (map[string]cfclient.SecGroup, error) {
	securityGroups := make(map[string]cfclient.SecGroup)
	secGroups, err := m.Client.ListSecGroups()
	if err != nil {
		return securityGroups, err
	}
	lo.G.Debug("Total security groups returned :", len(secGroups))
	for _, sg := range secGroups {
		securityGroups[sg.Name] = sg
	}
	return securityGroups, nil
}

//CreateGlobalSecurityGroups -
func (m *DefaultManager) CreateGlobalSecurityGroups() error {
	sgs, err := m.ListSecurityGroups()
	if err != nil {
		return err
	}
	securityGroupConfigs, err := m.Cfg.GetASGConfigs()
	if err != nil {
		return err
	}
	defaultSecurityGroupConfigs, err := m.Cfg.GetDefaultASGConfigs()
	if err != nil {
		return err
	}
	err = m.processSecurityGroups(securityGroupConfigs, sgs)
	if err != nil {
		return err
	}
	err = m.processSecurityGroups(defaultSecurityGroupConfigs, sgs)
	if err != nil {
		return err
	}

	return nil
}

//AssignDefaultSecurityGroups -
func (m *DefaultManager) AssignDefaultSecurityGroups() error {
	sgs, err := m.ListSecurityGroups()
	if err != nil {
		return err
	}
	globalConfig, err := m.Cfg.GetGlobalConfig()
	if err != nil {
		return err
	}

	for _, runningGroup := range globalConfig.RunningSecurityGroups {
		if group, ok := sgs[runningGroup]; ok {
			if !group.Running {
				err = m.AssignRunningSecurityGroup(group)
				if err != nil {
					return err
				}
			}
		} else {
			return fmt.Errorf("Running security group [%s] does not exist", runningGroup)
		}
	}

	for _, stagingGroup := range globalConfig.StagingSecurityGroups {
		if group, ok := sgs[stagingGroup]; ok {
			if !group.Staging {
				err = m.AssignStagingSecurityGroup(group)
				if err != nil {
					return err
				}
			}
		} else {
			return fmt.Errorf("Staging security group [%s] does not exist", stagingGroup)
		}
	}

	if globalConfig.EnableUnassignSecurityGroups {
		for groupName, group := range sgs {
			if group.Running && !m.contains(globalConfig.RunningSecurityGroups, groupName) {
				err = m.UnassignRunningSecurityGroup(group)
				if err != nil {
					return err
				}
			}
			if group.Staging && !m.contains(globalConfig.StagingSecurityGroups, groupName) {
				err = m.UnassignStagingSecurityGroup(group)
				if err != nil {
					return err
				}
			}
		}
	}

	return nil
}

func (m *DefaultManager) contains(list []string, groupName string) bool {
	groupNameToUpper := strings.ToUpper(groupName)
	for _, v := range list {
		if strings.ToUpper(v) == groupNameToUpper {
			return true
		}
	}
	return false
}

func (m *DefaultManager) processSecurityGroups(securityGroupConfigs []config.ASGConfig, sgs map[string]cfclient.SecGroup) error {
	for _, input := range securityGroupConfigs {
		sgName := input.Name

		// For every named security group
		// Check if it's a new group or Update
		if sgInfo, ok := sgs[sgName]; ok {
			changed, err := m.hasSecurityGroupChanged(sgInfo, input.Rules)
			if err != nil {
				return err
			}
			if changed {
				if err := m.UpdateSecurityGroup(sgInfo, input.Rules); err != nil {
					return err
				}
			}
		} else {
			if _, err := m.CreateSecurityGroup(sgName, input.Rules); err != nil {
				return err
			}
		}
	}

	return nil
}

func (m *DefaultManager) hasSecurityGroupChanged(sgInfo cfclient.SecGroup, rules string) (bool, error) {
	jsonBytes, err := json.Marshal(sgInfo.Rules)
	if err != nil {
		return false, err
	}
	secRules := []cfclient.SecGroupRule{}
	err = json.Unmarshal([]byte(rules), &secRules)
	if err != nil {
		return false, err
	}
	jsonBytesToCompare, err := json.Marshal(secRules)
	if err != nil {
		return false, err
	}
	match, err := DoesJsonMatch(string(jsonBytes), string(jsonBytesToCompare))
	if err != nil {
		return false, err
	}
	return !match, nil
}

func (m *DefaultManager) AssignSecurityGroupToSpace(space cfclient.Space, secGroup cfclient.SecGroup) error {
	for _, configuredSpace := range secGroup.SpacesData {
		if configuredSpace.Entity.Guid == space.Guid {
			return nil
		}
	}
	if m.Peek {
		lo.G.Infof("[dry-run]: assigning security group %s to space %s", secGroup.Name, space.Name)
		return nil
	}
	lo.G.Infof("assigning security group %s to space %s", secGroup.Name, space.Name)
	return m.Client.BindSecGroup(secGroup.Guid, space.Guid)
}

func (m *DefaultManager) UnassignSecurityGroupToSpace(space cfclient.Space, secGroup cfclient.SecGroup) error {
	for _, configuredSpace := range secGroup.SpacesData {
		if configuredSpace.Entity.Guid == space.Guid {
			return nil
		}
	}
	if m.Peek {
		lo.G.Infof("[dry-run]: unassigning security group %s to space %s", secGroup.Name, space.Name)
		return nil
	}
	lo.G.Infof("unassigning security group %s to space %s", secGroup.Name, space.Name)
	return m.Client.UnbindSecGroup(secGroup.Guid, space.Guid)
}

func (m *DefaultManager) CreateSecurityGroup(sgName, contents string) (*cfclient.SecGroup, error) {
	if m.Peek {
		lo.G.Infof("[dry-run]: creating securityGroup %s with contents %s", sgName, contents)
		return &cfclient.SecGroup{Name: "dry-run-name", Guid: "dry-run-guid"}, nil
	}
	securityGroupRules := []cfclient.SecGroupRule{}
	err := json.Unmarshal([]byte(contents), &securityGroupRules)
	if err != nil {
		return nil, err
	}
	lo.G.Infof("creating securityGroup %s with contents %s", sgName, contents)
	return m.Client.CreateSecGroup(sgName, securityGroupRules, nil)
}

func (m *DefaultManager) UpdateSecurityGroup(sg cfclient.SecGroup, contents string) error {
	if m.Peek {
		lo.G.Infof("[dry-run]: updating securityGroup %s with contents %s", sg.Name, contents)
		return nil
	}
	securityGroupRules := []cfclient.SecGroupRule{}
	err := json.Unmarshal([]byte(contents), &securityGroupRules)
	if err != nil {
		return err
	}
	lo.G.Infof("[dry-run]: updating securityGroup %s with contents %s", sg.Name, contents)
	_, err = m.Client.UpdateSecGroup(sg.Guid, sg.Name, securityGroupRules, nil)
	return err
}
func (m *DefaultManager) ListNonDefaultSecurityGroups() (map[string]cfclient.SecGroup, error) {
	securityGroups := make(map[string]cfclient.SecGroup)
	groupMap, err := m.ListSecurityGroups()
	if err != nil {
		return nil, err
	}
	for key, groupMap := range groupMap {
		if groupMap.Running == false && groupMap.Staging == false {
			securityGroups[key] = groupMap
		}
	}
	return securityGroups, nil
}

func (m *DefaultManager) ListDefaultSecurityGroups() (map[string]cfclient.SecGroup, error) {
	securityGroups := make(map[string]cfclient.SecGroup)
	groupMap, err := m.ListSecurityGroups()
	if err != nil {
		return nil, err
	}
	for key, groupMap := range groupMap {
		if groupMap.Running == true || groupMap.Staging == true {
			securityGroups[key] = groupMap
		}
	}
	return securityGroups, nil
}

func (m *DefaultManager) AssignRunningSecurityGroup(sg cfclient.SecGroup) error {
	if m.Peek {
		lo.G.Infof("[dry-run]: assigning sg %s as running security group", sg.Name)
		return nil
	}
	lo.G.Infof("assigning sg %s as running security group", sg.Name)
	return m.Client.BindRunningSecGroup(sg.Guid)
}
func (m *DefaultManager) AssignStagingSecurityGroup(sg cfclient.SecGroup) error {
	if m.Peek {
		lo.G.Infof("[dry-run]: assigning sg %s as staging security group", sg.Name)
		return nil
	}
	lo.G.Infof("assigning sg %s as staging security group", sg.Name)
	return m.Client.BindStagingSecGroup(sg.Guid)
}
func (m *DefaultManager) UnassignRunningSecurityGroup(sg cfclient.SecGroup) error {
	if m.Peek {
		lo.G.Infof("[dry-run]: unassinging sg %s as running security group", sg.Name)
		return nil
	}
	lo.G.Infof("unassinging sg %s as running security group", sg.Name)
	return m.Client.UnbindRunningSecGroup(sg.Guid)
}
func (m *DefaultManager) UnassignStagingSecurityGroup(sg cfclient.SecGroup) error {
	if m.Peek {
		lo.G.Infof("[dry-run]: unassigning sg %s as staging security group", sg.Name)
		return nil
	}
	lo.G.Infof("unassigning sg %s as staging security group", sg.Name)
	return m.Client.UnbindStagingSecGroup(sg.Guid)
}

func (m *DefaultManager) GetSecurityGroupRules(sgGUID string) ([]byte, error) {
	secGroup, err := m.Client.GetSecGroup(sgGUID)
	if err != nil {
		return nil, err
	}
	return json.MarshalIndent(secGroup.Rules, "", "\t")
}

func (m *DefaultManager) ListSpaceSecurityGroups(spaceGUID string) (map[string]string, error) {
	secGroups, err := m.Client.ListSpaceSecGroups(spaceGUID)
	if err != nil {
		return nil, err
	}
	lo.G.Debug("Total security groups returned :", len(secGroups))
	names := make(map[string]string)
	for _, sg := range secGroups {
		if sg.Running == false && sg.Staging == false {
			names[sg.Name] = sg.Guid
		}
	}
	return names, nil
}
<commit_msg>adding logic to allow peek to work even if security group had not been created - https://github.com/pivotalservices/cf-mgmt/issues/184<commit_after>package securitygroup

import (
	"encoding/json"
	"fmt"
	"strings"

	cfclient "github.com/cloudfoundry-community/go-cfclient"
	"github.com/pivotalservices/cf-mgmt/config"
	"github.com/pivotalservices/cf-mgmt/space"
	"github.com/pkg/errors"
	"github.com/xchapter7x/lo"
)

//NewManager -
func NewManager(client CFClient, spaceMgr space.Manager, cfg config.Reader, peek bool) Manager {
	return &DefaultManager{
		Cfg:          cfg,
		Client:       client,
		SpaceManager: spaceMgr,
		Peek:         peek,
	}
}

//DefaultSecurityGroupManager -
type DefaultManager struct {
	Cfg          config.Reader
	SpaceManager space.Manager
	Client       CFClient
	Peek         bool
}

//CreateApplicationSecurityGroups -
func (m *DefaultManager) CreateApplicationSecurityGroups() error {
	spaceConfigs, err := m.Cfg.GetSpaceConfigs()
	if err != nil {
		return err
	}
	sgs, err := m.ListNonDefaultSecurityGroups()
	if err != nil {
		return err
	}

	for _, input := range spaceConfigs {
		space, err := m.SpaceManager.FindSpace(input.Org, input.Space)
		if err != nil {
			return err
		}

		existingSpaceSecurityGroups, err := m.ListSpaceSecurityGroups(space.Guid)
		if err != nil {
			return errors.Wrapf(err, "Unabled to list existing space security groups for org/space [%s/%s]", input.Org, input.Space)
		}
		lo.G.Debugf("Existing space security groups %+v", existingSpaceSecurityGroups)
		// iterate through and assign named security groups to the space - ensuring that they are up to date is
		// done elsewhere.
		for _, securityGroupName := range input.ASGs {
			if sgInfo, ok := sgs[securityGroupName]; ok {
				if _, ok := existingSpaceSecurityGroups[securityGroupName]; !ok {
					err := m.AssignSecurityGroupToSpace(space, sgInfo)
					if err != nil {
						return err
					}
				} else {
					delete(existingSpaceSecurityGroups, securityGroupName)
				}
			} else {
				return fmt.Errorf("Security group [%s] does not exist", securityGroupName)
			}
		}

		spaceSecurityGroupName := fmt.Sprintf("%s-%s", input.Org, input.Space)
		if input.EnableSecurityGroup {
			var sgInfo cfclient.SecGroup
			var ok bool
			if sgInfo, ok = sgs[spaceSecurityGroupName]; ok {
				changed, err := m.hasSecurityGroupChanged(sgInfo, input.GetSecurityGroupContents())
				if err != nil {
					return errors.Wrapf(err, "Checking if security group %s has changed", spaceSecurityGroupName)
				}
				if changed {
					if err := m.UpdateSecurityGroup(sgInfo, input.GetSecurityGroupContents()); err != nil {
						return err
					}
				}
			} else {
				securityGroup, err := m.CreateSecurityGroup(spaceSecurityGroupName, input.GetSecurityGroupContents())
				if err != nil {
					return err
				}
				sgInfo = *securityGroup
			}
			if _, ok := existingSpaceSecurityGroups[spaceSecurityGroupName]; !ok {
				err := m.AssignSecurityGroupToSpace(space, sgInfo)
				if err != nil {
					return err
				}
			} else {
				delete(existingSpaceSecurityGroups, spaceSecurityGroupName)
			}
		}

		if input.EnableUnassignSecurityGroup {
			lo.G.Debugf("Existing space security groups after %+v", existingSpaceSecurityGroups)
			for sgName, _ := range existingSpaceSecurityGroups {
				if sgInfo, ok := sgs[sgName]; ok {
					err := m.UnassignSecurityGroupToSpace(space, sgInfo)
					if err != nil {
						return err
					}
				} else {
					return fmt.Errorf("Security group [%s] does not exist", sgName)
				}
			}
		}
	}
	return nil
}

func (m *DefaultManager) ListSecurityGroups() (map[string]cfclient.SecGroup, error) {
	securityGroups := make(map[string]cfclient.SecGroup)
	secGroups, err := m.Client.ListSecGroups()
	if err != nil {
		return securityGroups, err
	}
	lo.G.Debug("Total security groups returned :", len(secGroups))
	for _, sg := range secGroups {
		securityGroups[sg.Name] = sg
	}
	return securityGroups, nil
}

//CreateGlobalSecurityGroups -
func (m *DefaultManager) CreateGlobalSecurityGroups() error {
	sgs, err := m.ListSecurityGroups()
	if err != nil {
		return err
	}
	securityGroupConfigs, err := m.Cfg.GetASGConfigs()
	if err != nil {
		return err
	}
	defaultSecurityGroupConfigs, err := m.Cfg.GetDefaultASGConfigs()
	if err != nil {
		return err
	}
	err = m.processSecurityGroups(securityGroupConfigs, sgs)
	if err != nil {
		return err
	}
	err = m.processSecurityGroups(defaultSecurityGroupConfigs, sgs)
	if err != nil {
		return err
	}

	return nil
}

//AssignDefaultSecurityGroups -
func (m *DefaultManager) AssignDefaultSecurityGroups() error {
	sgs, err := m.ListSecurityGroups()
	if err != nil {
		return err
	}
	globalConfig, err := m.Cfg.GetGlobalConfig()
	if err != nil {
		return err
	}

	for _, runningGroup := range globalConfig.RunningSecurityGroups {
		if group, ok := sgs[runningGroup]; ok {
			if !group.Running {
				err = m.AssignRunningSecurityGroup(group)
				if err != nil {
					return err
				}
			}
		} else {
			if !m.Peek {
				return fmt.Errorf("Running security group [%s] does not exist", runningGroup)
			} else {
				lo.G.Infof("[dry-run]: assigning sg %s as running security group", runningGroup)
			}
		}
	}

	for _, stagingGroup := range globalConfig.StagingSecurityGroups {
		if group, ok := sgs[stagingGroup]; ok {
			if !group.Staging {
				err = m.AssignStagingSecurityGroup(group)
				if err != nil {
					return err
				}
			}
		} else {
			if !m.Peek {
				return fmt.Errorf("Staging security group [%s] does not exist", stagingGroup)
			} else {
				lo.G.Infof("[dry-run]: assigning sg %s as staging security group", stagingGroup)
			}
		}
	}

	if globalConfig.EnableUnassignSecurityGroups {
		for groupName, group := range sgs {
			if group.Running && !m.contains(globalConfig.RunningSecurityGroups, groupName) {
				err = m.UnassignRunningSecurityGroup(group)
				if err != nil {
					return err
				}
			}
			if group.Staging && !m.contains(globalConfig.StagingSecurityGroups, groupName) {
				err = m.UnassignStagingSecurityGroup(group)
				if err != nil {
					return err
				}
			}
		}
	}

	return nil
}

func (m *DefaultManager) contains(list []string, groupName string) bool {
	groupNameToUpper := strings.ToUpper(groupName)
	for _, v := range list {
		if strings.ToUpper(v) == groupNameToUpper {
			return true
		}
	}
	return false
}

func (m *DefaultManager) processSecurityGroups(securityGroupConfigs []config.ASGConfig, sgs map[string]cfclient.SecGroup) error {
	for _, input := range securityGroupConfigs {
		sgName := input.Name

		// For every named security group
		// Check if it's a new group or Update
		if sgInfo, ok := sgs[sgName]; ok {
			changed, err := m.hasSecurityGroupChanged(sgInfo, input.Rules)
			if err != nil {
				return err
			}
			if changed {
				if err := m.UpdateSecurityGroup(sgInfo, input.Rules); err != nil {
					return err
				}
			}
		} else {
			if _, err := m.CreateSecurityGroup(sgName, input.Rules); err != nil {
				return err
			}
		}
	}

	return nil
}

func (m *DefaultManager) hasSecurityGroupChanged(sgInfo cfclient.SecGroup, rules string) (bool, error) {
	jsonBytes, err := json.Marshal(sgInfo.Rules)
	if err != nil {
		return false, err
	}
	secRules := []cfclient.SecGroupRule{}
	err = json.Unmarshal([]byte(rules), &secRules)
	if err != nil {
		return false, err
	}
	jsonBytesToCompare, err := json.Marshal(secRules)
	if err != nil {
		return false, err
	}
	match, err := DoesJsonMatch(string(jsonBytes), string(jsonBytesToCompare))
	if err != nil {
		return false, err
	}
	return !match, nil
}

func (m *DefaultManager) AssignSecurityGroupToSpace(space cfclient.Space, secGroup cfclient.SecGroup) error {
	for _, configuredSpace := range secGroup.SpacesData {
		if configuredSpace.Entity.Guid == space.Guid {
			return nil
		}
	}
	if m.Peek {
		lo.G.Infof("[dry-run]: assigning security group %s to space %s", secGroup.Name, space.Name)
		return nil
	}
	lo.G.Infof("assigning security group %s to space %s", secGroup.Name, space.Name)
	return m.Client.BindSecGroup(secGroup.Guid, space.Guid)
}

func (m *DefaultManager) UnassignSecurityGroupToSpace(space cfclient.Space, secGroup cfclient.SecGroup) error {
	for _, configuredSpace := range secGroup.SpacesData {
		if configuredSpace.Entity.Guid == space.Guid {
			return nil
		}
	}
	if m.Peek {
		lo.G.Infof("[dry-run]: unassigning security group %s to space %s", secGroup.Name, space.Name)
		return nil
	}
	lo.G.Infof("unassigning security group %s to space %s", secGroup.Name, space.Name)
	return m.Client.UnbindSecGroup(secGroup.Guid, space.Guid)
}

func (m *DefaultManager) CreateSecurityGroup(sgName, contents string) (*cfclient.SecGroup, error) {
	if m.Peek {
		lo.G.Infof("[dry-run]: creating securityGroup %s with contents %s", sgName, contents)
		return &cfclient.SecGroup{Name: "dry-run-name", Guid: "dry-run-guid"}, nil
	}
	securityGroupRules := []cfclient.SecGroupRule{}
	err := json.Unmarshal([]byte(contents), &securityGroupRules)
	if err != nil {
		return nil, err
	}
	lo.G.Infof("creating securityGroup %s with contents %s", sgName, contents)
	return m.Client.CreateSecGroup(sgName, securityGroupRules, nil)
}

func (m *DefaultManager) UpdateSecurityGroup(sg cfclient.SecGroup, contents string) error {
	if m.Peek {
		lo.G.Infof("[dry-run]: updating securityGroup %s with contents %s", sg.Name, contents)
		return nil
	}
	securityGroupRules := []cfclient.SecGroupRule{}
	err := json.Unmarshal([]byte(contents), &securityGroupRules)
	if err != nil {
		return err
	}
	lo.G.Infof("[dry-run]: updating securityGroup %s with contents %s", sg.Name, contents)
	_, err = m.Client.UpdateSecGroup(sg.Guid, sg.Name, securityGroupRules, nil)
	return err
}
func (m *DefaultManager) ListNonDefaultSecurityGroups() (map[string]cfclient.SecGroup, error) {
	securityGroups := make(map[string]cfclient.SecGroup)
	groupMap, err := m.ListSecurityGroups()
	if err != nil {
		return nil, err
	}
	for key, groupMap := range groupMap {
		if groupMap.Running == false && groupMap.Staging == false {
			securityGroups[key] = groupMap
		}
	}
	return securityGroups, nil
}

func (m *DefaultManager) ListDefaultSecurityGroups() (map[string]cfclient.SecGroup, error) {
	securityGroups := make(map[string]cfclient.SecGroup)
	groupMap, err := m.ListSecurityGroups()
	if err != nil {
		return nil, err
	}
	for key, groupMap := range groupMap {
		if groupMap.Running == true || groupMap.Staging == true {
			securityGroups[key] = groupMap
		}
	}
	return securityGroups, nil
}

func (m *DefaultManager) AssignRunningSecurityGroup(sg cfclient.SecGroup) error {
	if m.Peek {
		lo.G.Infof("[dry-run]: assigning sg %s as running security group", sg.Name)
		return nil
	}
	lo.G.Infof("assigning sg %s as running security group", sg.Name)
	return m.Client.BindRunningSecGroup(sg.Guid)
}
func (m *DefaultManager) AssignStagingSecurityGroup(sg cfclient.SecGroup) error {
	if m.Peek {
		lo.G.Infof("[dry-run]: assigning sg %s as staging security group", sg.Name)
		return nil
	}
	lo.G.Infof("assigning sg %s as staging security group", sg.Name)
	return m.Client.BindStagingSecGroup(sg.Guid)
}
func (m *DefaultManager) UnassignRunningSecurityGroup(sg cfclient.SecGroup) error {
	if m.Peek {
		lo.G.Infof("[dry-run]: unassinging sg %s as running security group", sg.Name)
		return nil
	}
	lo.G.Infof("unassinging sg %s as running security group", sg.Name)
	return m.Client.UnbindRunningSecGroup(sg.Guid)
}
func (m *DefaultManager) UnassignStagingSecurityGroup(sg cfclient.SecGroup) error {
	if m.Peek {
		lo.G.Infof("[dry-run]: unassigning sg %s as staging security group", sg.Name)
		return nil
	}
	lo.G.Infof("unassigning sg %s as staging security group", sg.Name)
	return m.Client.UnbindStagingSecGroup(sg.Guid)
}

func (m *DefaultManager) GetSecurityGroupRules(sgGUID string) ([]byte, error) {
	secGroup, err := m.Client.GetSecGroup(sgGUID)
	if err != nil {
		return nil, err
	}
	return json.MarshalIndent(secGroup.Rules, "", "\t")
}

func (m *DefaultManager) ListSpaceSecurityGroups(spaceGUID string) (map[string]string, error) {
	secGroups, err := m.Client.ListSpaceSecGroups(spaceGUID)
	if err != nil {
		return nil, err
	}
	lo.G.Debug("Total security groups returned :", len(secGroups))
	names := make(map[string]string)
	for _, sg := range secGroups {
		if sg.Running == false && sg.Staging == false {
			names[sg.Name] = sg.Guid
		}
	}
	return names, nil
}
<|endoftext|>


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

/*
This package implements a wrapper for the Linux inotify system.

Example:
    watcher, err := inotify.NewWatcher()
    if err != nil {
        log.Exit(err)
    }
    err = watcher.Watch("/tmp")
    if err != nil {
        log.Exit(err)
    }
    for {
        select {
        case ev := <-watcher.Event:
            log.Println("event:", ev)
        case err := <-watcher.Error:
            log.Println("error:", err)
        }
    }

*/
package inotify

import (
	"fmt"
	"os"
	"strings"
	"syscall"
	"unsafe"
)

type Event struct {
	Mask   uint32 // Mask of events
	Cookie uint32 // Unique cookie associating related events (for rename(2))
	Name   string // File name (optional)
}

type watch struct {
	wd    uint32 // Watch descriptor (as returned by the inotify_add_watch() syscall)
	flags uint32 // inotify flags of this watch (see inotify(7) for the list of valid flags)
}

type Watcher struct {
	fd       int               // File descriptor (as returned by the inotify_init() syscall)
	watches  map[string]*watch // Map of inotify watches (key: path)
	paths    map[int]string    // Map of watched paths (key: watch descriptor)
	Error    chan os.Error     // Errors are sent on this channel
	Event    chan *Event       // Events are returned on this channel
	done     chan bool         // Channel for sending a "quit message" to the reader goroutine
	isClosed bool              // Set to true when Close() is first called
}

// NewWatcher creates and returns a new inotify instance using inotify_init(2)
func NewWatcher() (*Watcher, os.Error) {
	fd, errno := syscall.InotifyInit()
	if fd == -1 {
		return nil, os.NewSyscallError("inotify_init", errno)
	}
	w := &Watcher{
		fd:      fd,
		watches: make(map[string]*watch),
		paths:   make(map[int]string),
		Event:   make(chan *Event),
		Error:   make(chan os.Error),
		done:    make(chan bool, 1),
	}

	go w.readEvents()
	return w, nil
}

// Close closes an inotify watcher instance
// It sends a message to the reader goroutine to quit and removes all watches
// associated with the inotify instance
func (w *Watcher) Close() os.Error {
	if w.isClosed {
		return nil
	}
	w.isClosed = true

	// Send "quit" message to the reader goroutine
	w.done <- true
	for path := range w.watches {
		w.RemoveWatch(path)
	}

	return nil
}

// AddWatch adds path to the watched file set.
// The flags are interpreted as described in inotify_add_watch(2).
func (w *Watcher) AddWatch(path string, flags uint32) os.Error {
	if w.isClosed {
		return os.NewError("inotify instance already closed")
	}

	watchEntry, found := w.watches[path]
	if found {
		watchEntry.flags |= flags
		flags |= syscall.IN_MASK_ADD
	}
	wd, errno := syscall.InotifyAddWatch(w.fd, path, flags)
	if wd == -1 {
		return os.NewSyscallError("inotify_add_watch", errno)
	}

	if !found {
		w.watches[path] = &watch{wd: uint32(wd), flags: flags}
		w.paths[wd] = path
	}
	return nil
}

// Watch adds path to the watched file set, watching all events.
func (w *Watcher) Watch(path string) os.Error {
	return w.AddWatch(path, IN_ALL_EVENTS)
}

// RemoveWatch removes path from the watched file set.
func (w *Watcher) RemoveWatch(path string) os.Error {
	watch, ok := w.watches[path]
	if !ok {
		return os.NewError(fmt.Sprintf("can't remove non-existent inotify watch for: %s", path))
	}
	success, errno := syscall.InotifyRmWatch(w.fd, watch.wd)
	if success == -1 {
		return os.NewSyscallError("inotify_rm_watch", errno)
	}
	w.watches[path] = nil, false
	return nil
}

// readEvents reads from the inotify file descriptor, converts the
// received events into Event objects and sends them via the Event channel
func (w *Watcher) readEvents() {
	var (
		buf   [syscall.SizeofInotifyEvent * 4096]byte // Buffer for a maximum of 4096 raw events
		n     int                                     // Number of bytes read with read()
		errno int                                     // Syscall errno
	)

	for {
		n, errno = syscall.Read(w.fd, buf[0:])
		// See if there is a message on the "done" channel
		var done bool
		select {
		case done = <-w.done:
		default:
		}

		// If EOF or a "done" message is received
		if n == 0 || done {
			errno := syscall.Close(w.fd)
			if errno == -1 {
				w.Error <- os.NewSyscallError("close", errno)
			}
			close(w.Event)
			close(w.Error)
			return
		}
		if n < 0 {
			w.Error <- os.NewSyscallError("read", errno)
			continue
		}
		if n < syscall.SizeofInotifyEvent {
			w.Error <- os.NewError("inotify: short read in readEvents()")
			continue
		}

		var offset uint32 = 0
		// We don't know how many events we just read into the buffer
		// While the offset points to at least one whole event...
		for offset <= uint32(n-syscall.SizeofInotifyEvent) {
			// Point "raw" to the event in the buffer
			raw := (*syscall.InotifyEvent)(unsafe.Pointer(&buf[offset]))
			event := new(Event)
			event.Mask = uint32(raw.Mask)
			event.Cookie = uint32(raw.Cookie)
			nameLen := uint32(raw.Len)
			// If the event happened to the watched directory or the watched file, the kernel
			// doesn't append the filename to the event, but we would like to always fill the
			// the "Name" field with a valid filename. We retrieve the path of the watch from
			// the "paths" map.
			event.Name = w.paths[int(raw.Wd)]
			if nameLen > 0 {
				// Point "bytes" at the first byte of the filename
				bytes := (*[syscall.PathMax]byte)(unsafe.Pointer(&buf[offset+syscall.SizeofInotifyEvent]))
				// The filename is padded with NUL bytes. TrimRight() gets rid of those.
				event.Name += "/" + strings.TrimRight(string(bytes[0:nameLen]), "\000")
			}
			// Send the event on the events channel
			w.Event <- event

			// Move to the next event in the buffer
			offset += syscall.SizeofInotifyEvent + nameLen
		}
	}
}

// String formats the event e in the form
// "filename: 0xEventMask = IN_ACCESS|IN_ATTRIB_|..."
func (e *Event) String() string {
	var events string = ""

	m := e.Mask
	for _, b := range eventBits {
		if m&b.Value != 0 {
			m &^= b.Value
			events += "|" + b.Name
		}
	}

	if m != 0 {
		events += fmt.Sprintf("|%#x", m)
	}
	if len(events) > 0 {
		events = " == " + events[1:]
	}

	return fmt.Sprintf("%q: %#x%s", e.Name, e.Mask, events)
}

const (
	// Options for inotify_init() are not exported
	// IN_CLOEXEC    uint32 = syscall.IN_CLOEXEC
	// IN_NONBLOCK   uint32 = syscall.IN_NONBLOCK

	// Options for AddWatch
	IN_DONT_FOLLOW uint32 = syscall.IN_DONT_FOLLOW
	IN_ONESHOT     uint32 = syscall.IN_ONESHOT
	IN_ONLYDIR     uint32 = syscall.IN_ONLYDIR

	// The "IN_MASK_ADD" option is not exported, as AddWatch
	// adds it automatically, if there is already a watch for the given path
	// IN_MASK_ADD      uint32 = syscall.IN_MASK_ADD

	// Events
	IN_ACCESS        uint32 = syscall.IN_ACCESS
	IN_ALL_EVENTS    uint32 = syscall.IN_ALL_EVENTS
	IN_ATTRIB        uint32 = syscall.IN_ATTRIB
	IN_CLOSE         uint32 = syscall.IN_CLOSE
	IN_CLOSE_NOWRITE uint32 = syscall.IN_CLOSE_NOWRITE
	IN_CLOSE_WRITE   uint32 = syscall.IN_CLOSE_WRITE
	IN_CREATE        uint32 = syscall.IN_CREATE
	IN_DELETE        uint32 = syscall.IN_DELETE
	IN_DELETE_SELF   uint32 = syscall.IN_DELETE_SELF
	IN_MODIFY        uint32 = syscall.IN_MODIFY
	IN_MOVE          uint32 = syscall.IN_MOVE
	IN_MOVED_FROM    uint32 = syscall.IN_MOVED_FROM
	IN_MOVED_TO      uint32 = syscall.IN_MOVED_TO
	IN_MOVE_SELF     uint32 = syscall.IN_MOVE_SELF
	IN_OPEN          uint32 = syscall.IN_OPEN

	// Special events
	IN_ISDIR      uint32 = syscall.IN_ISDIR
	IN_IGNORED    uint32 = syscall.IN_IGNORED
	IN_Q_OVERFLOW uint32 = syscall.IN_Q_OVERFLOW
	IN_UNMOUNT    uint32 = syscall.IN_UNMOUNT
)

var eventBits = []struct {
	Value uint32
	Name  string
}{
	{IN_ACCESS, "IN_ACCESS"},
	{IN_ATTRIB, "IN_ATTRIB"},
	{IN_CLOSE, "IN_CLOSE"},
	{IN_CLOSE_NOWRITE, "IN_CLOSE_NOWRITE"},
	{IN_CLOSE_WRITE, "IN_CLOSE_WRITE"},
	{IN_CREATE, "IN_CREATE"},
	{IN_DELETE, "IN_DELETE"},
	{IN_DELETE_SELF, "IN_DELETE_SELF"},
	{IN_MODIFY, "IN_MODIFY"},
	{IN_MOVE, "IN_MOVE"},
	{IN_MOVED_FROM, "IN_MOVED_FROM"},
	{IN_MOVED_TO, "IN_MOVED_TO"},
	{IN_MOVE_SELF, "IN_MOVE_SELF"},
	{IN_OPEN, "IN_OPEN"},
	{IN_ISDIR, "IN_ISDIR"},
	{IN_IGNORED, "IN_IGNORED"},
	{IN_Q_OVERFLOW, "IN_Q_OVERFLOW"},
	{IN_UNMOUNT, "IN_UNMOUNT"},
}
<commit_msg>fix example in inotify<commit_after>// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

/*
This package implements a wrapper for the Linux inotify system.

Example:
    watcher, err := inotify.NewWatcher()
    if err != nil {
        log.Fatal(err)
    }
    err = watcher.Watch("/tmp")
    if err != nil {
        log.Fatal(err)
    }
    for {
        select {
        case ev := <-watcher.Event:
            log.Println("event:", ev)
        case err := <-watcher.Error:
            log.Println("error:", err)
        }
    }

*/
package inotify

import (
	"fmt"
	"os"
	"strings"
	"syscall"
	"unsafe"
)

type Event struct {
	Mask   uint32 // Mask of events
	Cookie uint32 // Unique cookie associating related events (for rename(2))
	Name   string // File name (optional)
}

type watch struct {
	wd    uint32 // Watch descriptor (as returned by the inotify_add_watch() syscall)
	flags uint32 // inotify flags of this watch (see inotify(7) for the list of valid flags)
}

type Watcher struct {
	fd       int               // File descriptor (as returned by the inotify_init() syscall)
	watches  map[string]*watch // Map of inotify watches (key: path)
	paths    map[int]string    // Map of watched paths (key: watch descriptor)
	Error    chan os.Error     // Errors are sent on this channel
	Event    chan *Event       // Events are returned on this channel
	done     chan bool         // Channel for sending a "quit message" to the reader goroutine
	isClosed bool              // Set to true when Close() is first called
}

// NewWatcher creates and returns a new inotify instance using inotify_init(2)
func NewWatcher() (*Watcher, os.Error) {
	fd, errno := syscall.InotifyInit()
	if fd == -1 {
		return nil, os.NewSyscallError("inotify_init", errno)
	}
	w := &Watcher{
		fd:      fd,
		watches: make(map[string]*watch),
		paths:   make(map[int]string),
		Event:   make(chan *Event),
		Error:   make(chan os.Error),
		done:    make(chan bool, 1),
	}

	go w.readEvents()
	return w, nil
}

// Close closes an inotify watcher instance
// It sends a message to the reader goroutine to quit and removes all watches
// associated with the inotify instance
func (w *Watcher) Close() os.Error {
	if w.isClosed {
		return nil
	}
	w.isClosed = true

	// Send "quit" message to the reader goroutine
	w.done <- true
	for path := range w.watches {
		w.RemoveWatch(path)
	}

	return nil
}

// AddWatch adds path to the watched file set.
// The flags are interpreted as described in inotify_add_watch(2).
func (w *Watcher) AddWatch(path string, flags uint32) os.Error {
	if w.isClosed {
		return os.NewError("inotify instance already closed")
	}

	watchEntry, found := w.watches[path]
	if found {
		watchEntry.flags |= flags
		flags |= syscall.IN_MASK_ADD
	}
	wd, errno := syscall.InotifyAddWatch(w.fd, path, flags)
	if wd == -1 {
		return os.NewSyscallError("inotify_add_watch", errno)
	}

	if !found {
		w.watches[path] = &watch{wd: uint32(wd), flags: flags}
		w.paths[wd] = path
	}
	return nil
}

// Watch adds path to the watched file set, watching all events.
func (w *Watcher) Watch(path string) os.Error {
	return w.AddWatch(path, IN_ALL_EVENTS)
}

// RemoveWatch removes path from the watched file set.
func (w *Watcher) RemoveWatch(path string) os.Error {
	watch, ok := w.watches[path]
	if !ok {
		return os.NewError(fmt.Sprintf("can't remove non-existent inotify watch for: %s", path))
	}
	success, errno := syscall.InotifyRmWatch(w.fd, watch.wd)
	if success == -1 {
		return os.NewSyscallError("inotify_rm_watch", errno)
	}
	w.watches[path] = nil, false
	return nil
}

// readEvents reads from the inotify file descriptor, converts the
// received events into Event objects and sends them via the Event channel
func (w *Watcher) readEvents() {
	var (
		buf   [syscall.SizeofInotifyEvent * 4096]byte // Buffer for a maximum of 4096 raw events
		n     int                                     // Number of bytes read with read()
		errno int                                     // Syscall errno
	)

	for {
		n, errno = syscall.Read(w.fd, buf[0:])
		// See if there is a message on the "done" channel
		var done bool
		select {
		case done = <-w.done:
		default:
		}

		// If EOF or a "done" message is received
		if n == 0 || done {
			errno := syscall.Close(w.fd)
			if errno == -1 {
				w.Error <- os.NewSyscallError("close", errno)
			}
			close(w.Event)
			close(w.Error)
			return
		}
		if n < 0 {
			w.Error <- os.NewSyscallError("read", errno)
			continue
		}
		if n < syscall.SizeofInotifyEvent {
			w.Error <- os.NewError("inotify: short read in readEvents()")
			continue
		}

		var offset uint32 = 0
		// We don't know how many events we just read into the buffer
		// While the offset points to at least one whole event...
		for offset <= uint32(n-syscall.SizeofInotifyEvent) {
			// Point "raw" to the event in the buffer
			raw := (*syscall.InotifyEvent)(unsafe.Pointer(&buf[offset]))
			event := new(Event)
			event.Mask = uint32(raw.Mask)
			event.Cookie = uint32(raw.Cookie)
			nameLen := uint32(raw.Len)
			// If the event happened to the watched directory or the watched file, the kernel
			// doesn't append the filename to the event, but we would like to always fill the
			// the "Name" field with a valid filename. We retrieve the path of the watch from
			// the "paths" map.
			event.Name = w.paths[int(raw.Wd)]
			if nameLen > 0 {
				// Point "bytes" at the first byte of the filename
				bytes := (*[syscall.PathMax]byte)(unsafe.Pointer(&buf[offset+syscall.SizeofInotifyEvent]))
				// The filename is padded with NUL bytes. TrimRight() gets rid of those.
				event.Name += "/" + strings.TrimRight(string(bytes[0:nameLen]), "\000")
			}
			// Send the event on the events channel
			w.Event <- event

			// Move to the next event in the buffer
			offset += syscall.SizeofInotifyEvent + nameLen
		}
	}
}

// String formats the event e in the form
// "filename: 0xEventMask = IN_ACCESS|IN_ATTRIB_|..."
func (e *Event) String() string {
	var events string = ""

	m := e.Mask
	for _, b := range eventBits {
		if m&b.Value != 0 {
			m &^= b.Value
			events += "|" + b.Name
		}
	}

	if m != 0 {
		events += fmt.Sprintf("|%#x", m)
	}
	if len(events) > 0 {
		events = " == " + events[1:]
	}

	return fmt.Sprintf("%q: %#x%s", e.Name, e.Mask, events)
}

const (
	// Options for inotify_init() are not exported
	// IN_CLOEXEC    uint32 = syscall.IN_CLOEXEC
	// IN_NONBLOCK   uint32 = syscall.IN_NONBLOCK

	// Options for AddWatch
	IN_DONT_FOLLOW uint32 = syscall.IN_DONT_FOLLOW
	IN_ONESHOT     uint32 = syscall.IN_ONESHOT
	IN_ONLYDIR     uint32 = syscall.IN_ONLYDIR

	// The "IN_MASK_ADD" option is not exported, as AddWatch
	// adds it automatically, if there is already a watch for the given path
	// IN_MASK_ADD      uint32 = syscall.IN_MASK_ADD

	// Events
	IN_ACCESS        uint32 = syscall.IN_ACCESS
	IN_ALL_EVENTS    uint32 = syscall.IN_ALL_EVENTS
	IN_ATTRIB        uint32 = syscall.IN_ATTRIB
	IN_CLOSE         uint32 = syscall.IN_CLOSE
	IN_CLOSE_NOWRITE uint32 = syscall.IN_CLOSE_NOWRITE
	IN_CLOSE_WRITE   uint32 = syscall.IN_CLOSE_WRITE
	IN_CREATE        uint32 = syscall.IN_CREATE
	IN_DELETE        uint32 = syscall.IN_DELETE
	IN_DELETE_SELF   uint32 = syscall.IN_DELETE_SELF
	IN_MODIFY        uint32 = syscall.IN_MODIFY
	IN_MOVE          uint32 = syscall.IN_MOVE
	IN_MOVED_FROM    uint32 = syscall.IN_MOVED_FROM
	IN_MOVED_TO      uint32 = syscall.IN_MOVED_TO
	IN_MOVE_SELF     uint32 = syscall.IN_MOVE_SELF
	IN_OPEN          uint32 = syscall.IN_OPEN

	// Special events
	IN_ISDIR      uint32 = syscall.IN_ISDIR
	IN_IGNORED    uint32 = syscall.IN_IGNORED
	IN_Q_OVERFLOW uint32 = syscall.IN_Q_OVERFLOW
	IN_UNMOUNT    uint32 = syscall.IN_UNMOUNT
)

var eventBits = []struct {
	Value uint32
	Name  string
}{
	{IN_ACCESS, "IN_ACCESS"},
	{IN_ATTRIB, "IN_ATTRIB"},
	{IN_CLOSE, "IN_CLOSE"},
	{IN_CLOSE_NOWRITE, "IN_CLOSE_NOWRITE"},
	{IN_CLOSE_WRITE, "IN_CLOSE_WRITE"},
	{IN_CREATE, "IN_CREATE"},
	{IN_DELETE, "IN_DELETE"},
	{IN_DELETE_SELF, "IN_DELETE_SELF"},
	{IN_MODIFY, "IN_MODIFY"},
	{IN_MOVE, "IN_MOVE"},
	{IN_MOVED_FROM, "IN_MOVED_FROM"},
	{IN_MOVED_TO, "IN_MOVED_TO"},
	{IN_MOVE_SELF, "IN_MOVE_SELF"},
	{IN_OPEN, "IN_OPEN"},
	{IN_ISDIR, "IN_ISDIR"},
	{IN_IGNORED, "IN_IGNORED"},
	{IN_Q_OVERFLOW, "IN_Q_OVERFLOW"},
	{IN_UNMOUNT, "IN_UNMOUNT"},
}
<|endoftext|>


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

// +build !nacl

package gc

import (
	"reflect"
	"testing"
	"unsafe"
)

// Assert that the size of important structures do not change unexpectedly.

func TestSizeof(t *testing.T) {
	const _64bit = unsafe.Sizeof(uintptr(0)) == 8

	var tests = []struct {
		val    interface{} // type as a value
		_32bit uintptr     // size on 32bit platforms
		_64bit uintptr     // size on 64bit platforms
	}{
		{Func{}, 92, 160},
		{Name{}, 44, 72},
		{Node{}, 92, 144},
		{Sym{}, 60, 112},
		{Type{}, 60, 96},
		{MapType{}, 20, 40},
		{ForwardType{}, 16, 32},
		{FuncType{}, 28, 48},
		{StructType{}, 12, 24},
		{InterType{}, 4, 8},
		{ChanType{}, 8, 16},
		{ArrayType{}, 16, 24},
		{InterMethType{}, 4, 8},
		{DDDFieldType{}, 4, 8},
		{FuncArgsType{}, 4, 8},
		{ChanArgsType{}, 4, 8},
		{PtrType{}, 4, 8},
		{SliceType{}, 4, 8},
	}

	for _, tt := range tests {
		want := tt._32bit
		if _64bit {
			want = tt._64bit
		}
		got := reflect.TypeOf(tt.val).Size()
		if want != got {
			t.Errorf("unsafe.Sizeof(%T) = %d, want %d", tt.val, got, want)
		}
	}
}
<commit_msg>cmd/compile: add Param to Sizeof test<commit_after>// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// +build !nacl

package gc

import (
	"reflect"
	"testing"
	"unsafe"
)

// Assert that the size of important structures do not change unexpectedly.

func TestSizeof(t *testing.T) {
	const _64bit = unsafe.Sizeof(uintptr(0)) == 8

	var tests = []struct {
		val    interface{} // type as a value
		_32bit uintptr     // size on 32bit platforms
		_64bit uintptr     // size on 64bit platforms
	}{
		{Func{}, 92, 160},
		{Name{}, 44, 72},
		{Param{}, 24, 48},
		{Node{}, 92, 144},
		{Sym{}, 60, 112},
		{Type{}, 60, 96},
		{MapType{}, 20, 40},
		{ForwardType{}, 16, 32},
		{FuncType{}, 28, 48},
		{StructType{}, 12, 24},
		{InterType{}, 4, 8},
		{ChanType{}, 8, 16},
		{ArrayType{}, 16, 24},
		{InterMethType{}, 4, 8},
		{DDDFieldType{}, 4, 8},
		{FuncArgsType{}, 4, 8},
		{ChanArgsType{}, 4, 8},
		{PtrType{}, 4, 8},
		{SliceType{}, 4, 8},
	}

	for _, tt := range tests {
		want := tt._32bit
		if _64bit {
			want = tt._64bit
		}
		got := reflect.TypeOf(tt.val).Size()
		if want != got {
			t.Errorf("unsafe.Sizeof(%T) = %d, want %d", tt.val, got, want)
		}
	}
}
<|endoftext|>


<commit_before>package common

import (
	"context"
	"testing"

	"github.com/hashicorp/packer/helper/multistep"
)

func TestStepRegister_impl(t *testing.T) {
	var _ multistep.Step = new(StepRegister)
}

func TestStepRegister_regularDriver(t *testing.T) {
	state := testState(t)
	step := new(StepRegister)

	state.Put("vmx_path", "foo")

	// Test the run
	if action := step.Run(context.Background(), state); action != multistep.ActionContinue {
		t.Fatalf("bad action: %#v", action)
	}
	if _, ok := state.GetOk("error"); ok {
		t.Fatal("should NOT have error")
	}

	// Cleanup
	step.Cleanup(state)
}

func TestStepRegister_remoteDriver(t *testing.T) {
	state := testState(t)
	step := &StepRegister{KeepRegistered: false}

	driver := new(RemoteDriverMock)

	state.Put("driver", driver)
	state.Put("vmx_path", "foo")

	// Test the run
	if action := step.Run(context.Background(), state); action != multistep.ActionContinue {
		t.Fatalf("bad action: %#v", action)
	}
	if _, ok := state.GetOk("error"); ok {
		t.Fatal("should NOT have error")
	}

	// verify
	if !driver.RegisterCalled {
		t.Fatal("register should be called")
	}
	if driver.RegisterPath != "foo" {
		t.Fatal("should call with correct path")
	}
	if driver.UnregisterCalled {
		t.Fatal("unregister should not be called")
	}

	// cleanup
	step.Cleanup(state)
	if !driver.UnregisterCalled {
		t.Fatal("unregister should be called")
	}
	if driver.UnregisterPath != "foo" {
		t.Fatal("should unregister proper path")
	}
}
func TestStepRegister_WithoutUnregister_remoteDriver(t *testing.T) {
	state := testState(t)
	step := &StepRegister{KeepRegistered: true}

	driver := new(RemoteDriverMock)

	state.Put("driver", driver)
	state.Put("vmx_path", "foo")

	// Test the run
	if action := step.Run(context.Background(), state); action != multistep.ActionContinue {
		t.Fatalf("bad action: %#v", action)
	}
	if _, ok := state.GetOk("error"); ok {
		t.Fatal("should NOT have error")
	}

	// cleanup
	step.Cleanup(state)
	if driver.UnregisterCalled {
		t.Fatal("unregister should not be called")
	}
}
<commit_msg>fix tests<commit_after>package common

import (
	"context"
	"testing"

	"github.com/hashicorp/packer/helper/multistep"
)

func TestStepRegister_impl(t *testing.T) {
	var _ multistep.Step = new(StepRegister)
}

func TestStepRegister_regularDriver(t *testing.T) {
	state := testState(t)
	step := new(StepRegister)

	state.Put("vmx_path", "foo")

	// Test the run
	if action := step.Run(context.Background(), state); action != multistep.ActionContinue {
		t.Fatalf("bad action: %#v", action)
	}
	if _, ok := state.GetOk("error"); ok {
		t.Fatal("should NOT have error")
	}

	// Cleanup
	step.Cleanup(state)
}

func TestStepRegister_remoteDriver(t *testing.T) {
	state := testState(t)
	step := &StepRegister{
		KeepRegistered: false,
		SkipExport:     true,
	}

	driver := new(RemoteDriverMock)

	state.Put("driver", driver)
	state.Put("vmx_path", "foo")

	// Test the run
	if action := step.Run(context.Background(), state); action != multistep.ActionContinue {
		t.Fatalf("bad action: %#v", action)
	}
	if _, ok := state.GetOk("error"); ok {
		t.Fatal("should NOT have error")
	}

	// verify
	if !driver.RegisterCalled {
		t.Fatal("register should be called")
	}
	if driver.RegisterPath != "foo" {
		t.Fatal("should call with correct path")
	}
	if driver.UnregisterCalled {
		t.Fatal("unregister should not be called")
	}

	// cleanup
	step.Cleanup(state)
	if !driver.UnregisterCalled {
		t.Fatal("unregister should be called")
	}
	if driver.UnregisterPath != "foo" {
		t.Fatal("should unregister proper path")
	}
}
func TestStepRegister_WithoutUnregister_remoteDriver(t *testing.T) {
	state := testState(t)
	step := &StepRegister{KeepRegistered: true}

	driver := new(RemoteDriverMock)

	state.Put("driver", driver)
	state.Put("vmx_path", "foo")

	// Test the run
	if action := step.Run(context.Background(), state); action != multistep.ActionContinue {
		t.Fatalf("bad action: %#v", action)
	}
	if _, ok := state.GetOk("error"); ok {
		t.Fatal("should NOT have error")
	}

	// cleanup
	step.Cleanup(state)
	if driver.UnregisterCalled {
		t.Fatal("unregister should not be called")
	}
}
<|endoftext|>


<commit_before>package main

import "fmt"
import "math"
import "math/big"

func getTestCases() []float64 {
	testCases := []float64{}
	var numberOfLines int
	fmt.Scanf("%d", &numberOfLines)

	if numberOfLines > 0 {
		for i := 0; i < numberOfLines; i++ {
			var testCase float64
			fmt.Scanf("%d", &testCase)
			testCases = append(testCases, testCase)
		}
	}
	return testCases
}

func isPerfectSquare(number float64) bool {
	floatNumber := math.Sqrt(float64(number))
	// intNumber := float64(math.Trunc(floatNumber))
	intNumber := big.NewFloat(floatNumber)
	// isPerfectSquare := (intNumber == floatNumber)
	isPerfectSquare := intNumber.IsInt()
	fmt.Println(number)
	fmt.Println(floatNumber)
	fmt.Println(intNumber)
	fmt.Println(isPerfectSquare)
	return isPerfectSquare
}

func isFibonacciNumber(number float64) bool {
	fiveByXSquare := float64(5 * number * number)
	isFibonacciNumber := isPerfectSquare(fiveByXSquare+4) || isPerfectSquare(fiveByXSquare-4)
	return isFibonacciNumber
}

func main() {

	// https://www.hackerrank.com/challenges/is-fibo
	// testCases := getTestCases()
	testCases := []float64{7778742049}
	// testCases := []float64{5,7,8}
	for _, element := range testCases {
		if isFibonacciNumber(element) {
			fmt.Println("IsFibo")
		} else {
			fmt.Println("IsNotFibo")
		}
	}
}
<commit_msg>Complete is-fibo problem.<commit_after>package main

import "fmt"
import "math"

func getTestCases() []float64 {
	testCases := []float64{}
	var numberOfLines int
	fmt.Scanf("%d", &numberOfLines)

	if numberOfLines > 0 {
		for i := 0; i < numberOfLines; i++ {
			var testCase float64
			fmt.Scanf("%f", &testCase)
			testCases = append(testCases, testCase)
		}
	}

	// fmt.Println(numberOfLines)
	// fmt.Println(testCases)

	return testCases
}

func isPerfectSquare(number float64) bool {
	floatNumber := math.Sqrt(float64(number))
	// intNumber := big.NewFloat(floatNumber) // It seems like this line only works in go 1.5
	// isPerfectSquare := intNumber.IsInt()
	intNumber := float64(math.Trunc(floatNumber))
	isPerfectSquare := (intNumber == floatNumber)
	// fmt.Println(number)
	// fmt.Println(floatNumber)
	// fmt.Println(intNumber)
	// fmt.Println(isPerfectSquare)
	return isPerfectSquare
}

func isFibonacciNumber(number float64) bool {
	fiveByXSquare := float64(5 * number * number)
	isFibonacciNumber := (isPerfectSquare(fiveByXSquare+4) || isPerfectSquare(fiveByXSquare-4))
	return isFibonacciNumber
}

func main() {

	// https://www.hackerrank.com/challenges/is-fibo
	testCases := getTestCases()
	// testCases := []float64{7778742049}
	// testCases := []float64{5,7,8}
	for _, element := range testCases {
		if isFibonacciNumber(element) {
			fmt.Println("IsFibo")
		} else {
			fmt.Println("IsNotFibo")
		}
	}
}
<|endoftext|>


<commit_before>package fasthttp

import (
	"bufio"
	"bytes"
	"io"
	"testing"
)

var strFoobar = []byte("foobar.com")

type benchReadBuf struct {
	s []byte
	n int
}

func (r *benchReadBuf) Read(p []byte) (int, error) {
	if r.n == len(r.s) {
		return 0, io.EOF
	}

	n := copy(p, r.s[r.n:])
	r.n += n
	return n, nil
}

func BenchmarkRequestHeaderRead(b *testing.B) {
	b.RunParallel(func(pb *testing.PB) {
		var h RequestHeader
		buf := &benchReadBuf{
			s: []byte("GET /foo/bar HTTP/1.1\r\nHost: foobar.com\r\nUser-Agent: aaa.bbb\r\nReferer: http://google.com/aaa/bbb\r\n\r\n"),
		}
		br := bufio.NewReader(buf)
		for pb.Next() {
			buf.n = 0
			br.Reset(buf)
			if err := h.Read(br); err != nil {
				b.Fatalf("unexpected error when reading header: %s", err)
			}
		}
	})
}

func BenchmarkResponseHeaderRead(b *testing.B) {
	b.RunParallel(func(pb *testing.PB) {
		var h ResponseHeader
		buf := &benchReadBuf{
			s: []byte("HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nContent-Length: 1256\r\nServer: aaa 1/2.3\r\nTest: 1.2.3\r\n\r\n"),
		}
		br := bufio.NewReader(buf)
		for pb.Next() {
			buf.n = 0
			br.Reset(buf)
			if err := h.Read(br); err != nil {
				b.Fatalf("unexpected error when reading header: %s", err)
			}
		}
	})
}

func BenchmarkRequestHeaderPeekBytesCanonical(b *testing.B) {
	b.RunParallel(func(pb *testing.PB) {
		var h RequestHeader
		h.SetBytesV("Host", strFoobar)
		for pb.Next() {
			v := h.PeekBytes(strHost)
			if !bytes.Equal(v, strFoobar) {
				b.Fatalf("unexpected result: %q. Expected %q", v, strFoobar)
			}
		}
	})
}

func BenchmarkRequestHeaderPeekBytesNonCanonical(b *testing.B) {
	b.RunParallel(func(pb *testing.PB) {
		var h RequestHeader
		h.SetBytesV("Host", strFoobar)
		hostBytes := []byte("HOST")
		for pb.Next() {
			v := h.PeekBytes(hostBytes)
			if !bytes.Equal(v, strFoobar) {
				b.Fatalf("unexpected result: %q. Expected %q", v, strFoobar)
			}
		}
	})
}
<commit_msg>Added tests for Header.Write<commit_after>package fasthttp

import (
	"bufio"
	"bytes"
	"io"
	"testing"
)

var strFoobar = []byte("foobar.com")

type benchReadBuf struct {
	s []byte
	n int
}

func (r *benchReadBuf) Read(p []byte) (int, error) {
	if r.n == len(r.s) {
		return 0, io.EOF
	}

	n := copy(p, r.s[r.n:])
	r.n += n
	return n, nil
}

func BenchmarkRequestHeaderRead(b *testing.B) {
	b.RunParallel(func(pb *testing.PB) {
		var h RequestHeader
		buf := &benchReadBuf{
			s: []byte("GET /foo/bar HTTP/1.1\r\nHost: foobar.com\r\nUser-Agent: aaa.bbb\r\nReferer: http://google.com/aaa/bbb\r\n\r\n"),
		}
		br := bufio.NewReader(buf)
		for pb.Next() {
			buf.n = 0
			br.Reset(buf)
			if err := h.Read(br); err != nil {
				b.Fatalf("unexpected error when reading header: %s", err)
			}
		}
	})
}

func BenchmarkResponseHeaderRead(b *testing.B) {
	b.RunParallel(func(pb *testing.PB) {
		var h ResponseHeader
		buf := &benchReadBuf{
			s: []byte("HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nContent-Length: 1256\r\nServer: aaa 1/2.3\r\nTest: 1.2.3\r\n\r\n"),
		}
		br := bufio.NewReader(buf)
		for pb.Next() {
			buf.n = 0
			br.Reset(buf)
			if err := h.Read(br); err != nil {
				b.Fatalf("unexpected error when reading header: %s", err)
			}
		}
	})
}

func BenchmarkRequestHeaderWrite(b *testing.B) {
	b.RunParallel(func (pb *testing.PB) {
		var h RequestHeader
		h.SetRequestURI("/foo/bar")
		h.SetHost("foobar.com")
		h.SetUserAgent("aaa.bbb")
		h.SetReferer("http://google.com/aaa/bbb")
		var w bytes.Buffer
		for pb.Next() {
			if _, err := h.WriteTo(&w); err != nil {
				b.Fatalf("unexpected error when writing header: %s", err)
			}
			w.Reset()
		}
	})
}

func BenchmarkResponseHeaderWrite(b *testing.B) {
	b.RunParallel(func (pb *testing.PB) {
		var h ResponseHeader
		h.SetStatusCode(200)
		h.SetContentType("text/html")
		h.SetContentLength(1256)
		h.SetServer("aaa 1/2.3")
		h.Set("Test", "1.2.3")
		var w bytes.Buffer
		for pb.Next() {
			if _, err := h.WriteTo(&w); err != nil {
				b.Fatalf("unexpected error when writing header: %s", err)
			}
			w.Reset()
		}
	})
}

func BenchmarkRequestHeaderPeekBytesCanonical(b *testing.B) {
	b.RunParallel(func(pb *testing.PB) {
		var h RequestHeader
		h.SetBytesV("Host", strFoobar)
		for pb.Next() {
			v := h.PeekBytes(strHost)
			if !bytes.Equal(v, strFoobar) {
				b.Fatalf("unexpected result: %q. Expected %q", v, strFoobar)
			}
		}
	})
}

func BenchmarkRequestHeaderPeekBytesNonCanonical(b *testing.B) {
	b.RunParallel(func(pb *testing.PB) {
		var h RequestHeader
		h.SetBytesV("Host", strFoobar)
		hostBytes := []byte("HOST")
		for pb.Next() {
			v := h.PeekBytes(hostBytes)
			if !bytes.Equal(v, strFoobar) {
				b.Fatalf("unexpected result: %q. Expected %q", v, strFoobar)
			}
		}
	})
}
<|endoftext|>


<commit_before>package repository

import (
	"io"
	"math/rand"
	"restic/backend"
	"restic/pack"
	"testing"
)

func randomSize(min, max int) int {
	return rand.Intn(max-min) + min
}

func random(t *testing.T, length int) []byte {
	src := rand.New(rand.NewSource(int64(length)))
	buf := make([]byte, length)
	_, err := io.ReadFull(src, buf)
	if err != nil {
		t.Fatalf("unable to read %d random bytes: %v", length, err)
	}

	return buf
}

func createRandomBlobs(t *testing.T, repo *Repository, blobs int, pData float32) {
	for i := 0; i < blobs; i++ {
		var (
			tpe    pack.BlobType
			length int
		)

		if rand.Float32() < pData {
			tpe = pack.Data
			length = randomSize(50*1024, 2*1024*1024) // 50KiB to 2MiB of data
		} else {
			tpe = pack.Tree
			length = randomSize(5*1024, 50*1024) // 5KiB to 50KiB
		}

		_, err := repo.SaveAndEncrypt(tpe, random(t, length), nil)
		if err != nil {
			t.Fatalf("SaveFrom() error %v", err)
		}

		if rand.Float32() < 0.2 {
			if err = repo.Flush(); err != nil {
				t.Fatalf("repo.Flush() returned error %v", err)
			}
		}
	}

	if err := repo.Flush(); err != nil {
		t.Fatalf("repo.Flush() returned error %v", err)
	}
}

// selectBlobs splits the list of all blobs randomly into two lists. A blob
// will be contained in the firstone ith probability p.
func selectBlobs(t *testing.T, repo *Repository, p float32) (list1, list2 backend.IDSet) {
	done := make(chan struct{})
	defer close(done)

	list1 = backend.NewIDSet()
	list2 = backend.NewIDSet()

	for id := range repo.List(backend.Data, done) {
		entries, err := repo.ListPack(id)
		if err != nil {
			t.Fatalf("error listing pack %v: %v", id, err)
		}

		for _, entry := range entries {
			if rand.Float32() <= p {
				list1.Insert(entry.ID)
			} else {
				list2.Insert(entry.ID)
			}
		}
	}

	return list1, list2
}

func listPacks(t *testing.T, repo *Repository) backend.IDSet {
	done := make(chan struct{})
	defer close(done)

	list := backend.NewIDSet()
	for id := range repo.List(backend.Data, done) {
		list.Insert(id)
	}

	return list
}

func findPacksForBlobs(t *testing.T, repo *Repository, blobs backend.IDSet) backend.IDSet {
	packs := backend.NewIDSet()

	idx := repo.Index()
	for id := range blobs {
		pb, err := idx.Lookup(id)
		if err != nil {
			t.Fatal(err)
		}

		packs.Insert(pb.PackID)
	}

	return packs
}

func repack(t *testing.T, repo *Repository, packs, blobs backend.IDSet) {
	err := Repack(repo, packs, blobs)
	if err != nil {
		t.Fatal(err)
	}
}

func saveIndex(t *testing.T, repo *Repository) {
	if err := repo.SaveIndex(); err != nil {
		t.Fatalf("repo.SaveIndex() %v", err)
	}
}

func rebuildIndex(t *testing.T, repo *Repository) {
	if err := RebuildIndex(repo); err != nil {
		t.Fatalf("error rebuilding index: %v", err)
	}
}

func reloadIndex(t *testing.T, repo *Repository) {
	repo.SetIndex(NewMasterIndex())
	if err := repo.LoadIndex(); err != nil {
		t.Fatalf("error loading new index: %v", err)
	}
}

func TestRepack(t *testing.T) {
	repo, cleanup := TestRepository(t)
	defer cleanup()

	createRandomBlobs(t, repo, rand.Intn(400), 0.7)

	packsBefore := listPacks(t, repo)

	// Running repack on empty ID sets should not do anything at all.
	repack(t, repo, nil, nil)

	packsAfter := listPacks(t, repo)

	if !packsAfter.Equals(packsBefore) {
		t.Fatalf("packs are not equal, Repack modified something. Before:\n  %v\nAfter:\n  %v",
			packsBefore, packsAfter)
	}

	saveIndex(t, repo)

	removeBlobs, keepBlobs := selectBlobs(t, repo, 0.2)

	removePacks := findPacksForBlobs(t, repo, removeBlobs)

	repack(t, repo, removePacks, keepBlobs)
	rebuildIndex(t, repo)
	reloadIndex(t, repo)

	packsAfter = listPacks(t, repo)
	for id := range removePacks {
		if packsAfter.Has(id) {
			t.Errorf("pack %v still present although it should have been repacked and removed", id.Str())
		}
	}

	idx := repo.Index()
	for id := range keepBlobs {
		pb, err := idx.Lookup(id)
		if err != nil {
			t.Errorf("unable to find blob %v in repo", id.Str())
		}

		if removePacks.Has(pb.PackID) {
			t.Errorf("lookup returned pack ID %v that should've been removed", pb.PackID)
		}
	}

	for id := range removeBlobs {
		if _, err := idx.Lookup(id); err == nil {
			t.Errorf("blob %v still contained in the repo", id.Str())
		}
	}
}
<commit_msg>Use RandReader instead of rand directly<commit_after>package repository

import (
	"io"
	"math/rand"
	"restic/backend"
	"restic/pack"
	"testing"
)

func randomSize(min, max int) int {
	return rand.Intn(max-min) + min
}

func random(t *testing.T, length int) []byte {
	rd := NewRandReader(rand.New(rand.NewSource(int64(length))))
	buf := make([]byte, length)
	_, err := io.ReadFull(rd, buf)
	if err != nil {
		t.Fatalf("unable to read %d random bytes: %v", length, err)
	}

	return buf
}

func createRandomBlobs(t *testing.T, repo *Repository, blobs int, pData float32) {
	for i := 0; i < blobs; i++ {
		var (
			tpe    pack.BlobType
			length int
		)

		if rand.Float32() < pData {
			tpe = pack.Data
			length = randomSize(50*1024, 2*1024*1024) // 50KiB to 2MiB of data
		} else {
			tpe = pack.Tree
			length = randomSize(5*1024, 50*1024) // 5KiB to 50KiB
		}

		_, err := repo.SaveAndEncrypt(tpe, random(t, length), nil)
		if err != nil {
			t.Fatalf("SaveFrom() error %v", err)
		}

		if rand.Float32() < 0.2 {
			if err = repo.Flush(); err != nil {
				t.Fatalf("repo.Flush() returned error %v", err)
			}
		}
	}

	if err := repo.Flush(); err != nil {
		t.Fatalf("repo.Flush() returned error %v", err)
	}
}

// selectBlobs splits the list of all blobs randomly into two lists. A blob
// will be contained in the firstone ith probability p.
func selectBlobs(t *testing.T, repo *Repository, p float32) (list1, list2 backend.IDSet) {
	done := make(chan struct{})
	defer close(done)

	list1 = backend.NewIDSet()
	list2 = backend.NewIDSet()

	for id := range repo.List(backend.Data, done) {
		entries, err := repo.ListPack(id)
		if err != nil {
			t.Fatalf("error listing pack %v: %v", id, err)
		}

		for _, entry := range entries {
			if rand.Float32() <= p {
				list1.Insert(entry.ID)
			} else {
				list2.Insert(entry.ID)
			}
		}
	}

	return list1, list2
}

func listPacks(t *testing.T, repo *Repository) backend.IDSet {
	done := make(chan struct{})
	defer close(done)

	list := backend.NewIDSet()
	for id := range repo.List(backend.Data, done) {
		list.Insert(id)
	}

	return list
}

func findPacksForBlobs(t *testing.T, repo *Repository, blobs backend.IDSet) backend.IDSet {
	packs := backend.NewIDSet()

	idx := repo.Index()
	for id := range blobs {
		pb, err := idx.Lookup(id)
		if err != nil {
			t.Fatal(err)
		}

		packs.Insert(pb.PackID)
	}

	return packs
}

func repack(t *testing.T, repo *Repository, packs, blobs backend.IDSet) {
	err := Repack(repo, packs, blobs)
	if err != nil {
		t.Fatal(err)
	}
}

func saveIndex(t *testing.T, repo *Repository) {
	if err := repo.SaveIndex(); err != nil {
		t.Fatalf("repo.SaveIndex() %v", err)
	}
}

func rebuildIndex(t *testing.T, repo *Repository) {
	if err := RebuildIndex(repo); err != nil {
		t.Fatalf("error rebuilding index: %v", err)
	}
}

func reloadIndex(t *testing.T, repo *Repository) {
	repo.SetIndex(NewMasterIndex())
	if err := repo.LoadIndex(); err != nil {
		t.Fatalf("error loading new index: %v", err)
	}
}

func TestRepack(t *testing.T) {
	repo, cleanup := TestRepository(t)
	defer cleanup()

	createRandomBlobs(t, repo, rand.Intn(400), 0.7)

	packsBefore := listPacks(t, repo)

	// Running repack on empty ID sets should not do anything at all.
	repack(t, repo, nil, nil)

	packsAfter := listPacks(t, repo)

	if !packsAfter.Equals(packsBefore) {
		t.Fatalf("packs are not equal, Repack modified something. Before:\n  %v\nAfter:\n  %v",
			packsBefore, packsAfter)
	}

	saveIndex(t, repo)

	removeBlobs, keepBlobs := selectBlobs(t, repo, 0.2)

	removePacks := findPacksForBlobs(t, repo, removeBlobs)

	repack(t, repo, removePacks, keepBlobs)
	rebuildIndex(t, repo)
	reloadIndex(t, repo)

	packsAfter = listPacks(t, repo)
	for id := range removePacks {
		if packsAfter.Has(id) {
			t.Errorf("pack %v still present although it should have been repacked and removed", id.Str())
		}
	}

	idx := repo.Index()
	for id := range keepBlobs {
		pb, err := idx.Lookup(id)
		if err != nil {
			t.Errorf("unable to find blob %v in repo", id.Str())
		}

		if removePacks.Has(pb.PackID) {
			t.Errorf("lookup returned pack ID %v that should've been removed", pb.PackID)
		}
	}

	for id := range removeBlobs {
		if _, err := idx.Lookup(id); err == nil {
			t.Errorf("blob %v still contained in the repo", id.Str())
		}
	}
}
<|endoftext|>


<commit_before>package fields

import (
	"fmt"

	"github.com/hashicorp/go-multierror"
	"github.com/mitchellh/mapstructure"
)

// FielData contains the raw data and the schema that the data should adhere to
type FieldData struct {
	Raw    map[string]interface{}
	Schema map[string]*FieldSchema
}

// Cycle through raw data and validate conversions in the schema. Also check
// for the existence and value of required fields.
func (d *FieldData) Validate() error {
	var result *multierror.Error

	// Scan for missing required fields
	for field, schema := range d.Schema {
		if schema.Required {
			_, ok := d.Raw[field]
			if !ok {
				result = multierror.Append(result, fmt.Errorf(
					"field %q is required", field))
			}
		}
	}

	// Validate field type and value
	for field, value := range d.Raw {
		schema, ok := d.Schema[field]
		if !ok {
			result = multierror.Append(result, fmt.Errorf(
				"%q is an invalid field", field))
			continue
		}

		switch schema.Type {
		case TypeBool, TypeInt, TypeMap, TypeArray, TypeString:
			val, _, err := d.getPrimitive(field, schema)
			if err != nil {
				result = multierror.Append(result, fmt.Errorf(
					"field %q with input %q doesn't seem to be of type %s",
					field, value, schema.Type))
			}
			// Check that we don't have an empty value for required fields
			if schema.Required && val == schema.Type.Zero() {
				result = multierror.Append(result, fmt.Errorf(
					"field %q is required, but no value was found", field))
			}
		default:
			result = multierror.Append(result, fmt.Errorf(
				"unknown field type %s for field %s", schema.Type, field))
		}
	}

	return result.ErrorOrNil()
}

// Get gets the value for the given field. If the key is an invalid field,
// FieldData will panic. If you want a safer version of this method, use
// GetOk. If the field k is not set, the default value (if set) will be
// returned, otherwise the zero value will be returned.
func (d *FieldData) Get(k string) interface{} {
	schema, ok := d.Schema[k]
	if !ok {
		panic(fmt.Sprintf("field %s not in the schema", k))
	}

	value, ok := d.GetOk(k)
	if !ok {
		value = schema.DefaultOrZero()
	}

	return value
}

// GetOk gets the value for the given field. The second return value
// will be false if the key is invalid or the key is not set at all.
func (d *FieldData) GetOk(k string) (interface{}, bool) {
	schema, ok := d.Schema[k]
	if !ok {
		return nil, false
	}

	result, ok, err := d.GetOkErr(k)
	if err != nil {
		panic(fmt.Sprintf("error reading %s: %s", k, err))
	}

	if ok && result == nil {
		result = schema.DefaultOrZero()
	}

	return result, ok
}

// GetOkErr is the most conservative of all the Get methods. It returns
// whether key is set or not, but also an error value. The error value is
// non-nil if the field doesn't exist or there was an error parsing the
// field value.
func (d *FieldData) GetOkErr(k string) (interface{}, bool, error) {
	schema, ok := d.Schema[k]
	if !ok {
		return nil, false, fmt.Errorf("unknown field: %s", k)
	}

	switch schema.Type {
	case TypeBool, TypeInt, TypeMap, TypeArray, TypeString:
		return d.getPrimitive(k, schema)
	default:
		return nil, false,
			fmt.Errorf("unknown field type %s for field %s", schema.Type, k)
	}
}

func (d *FieldData) getPrimitive(
	k string, schema *FieldSchema) (interface{}, bool, error) {
	raw, ok := d.Raw[k]
	if !ok {
		return nil, false, nil
	}

	switch schema.Type {
	case TypeBool:
		var result bool
		if err := mapstructure.Decode(raw, &result); err != nil {
			return nil, true, err
		}
		return result, true, nil

	case TypeInt:
		var result int
		if err := mapstructure.Decode(raw, &result); err != nil {
			return nil, true, err
		}
		return result, true, nil

	case TypeString:
		var result string
		if err := mapstructure.Decode(raw, &result); err != nil {
			return nil, true, err
		}
		return result, true, nil

	case TypeMap:
		var result map[string]interface{}
		if err := mapstructure.Decode(raw, &result); err != nil {
			return nil, true, err
		}
		return result, true, nil

	case TypeArray:
		var result []interface{}
		if err := mapstructure.Decode(raw, &result); err != nil {
			return nil, true, err
		}
		return result, true, nil

	default:
		panic(fmt.Sprintf("Unknown type: %s", schema.Type))
	}
}
<commit_msg>Add comments and fix a typo<commit_after>package fields

import (
	"fmt"

	"github.com/hashicorp/go-multierror"
	"github.com/mitchellh/mapstructure"
)

// FieldData contains the raw data and the schema that the data should adhere to
type FieldData struct {
	Raw    map[string]interface{}
	Schema map[string]*FieldSchema
}

// Validate cycles through the raw data and validates conversions in the schema.
// It also checks for the existence and value of required fields.
func (d *FieldData) Validate() error {
	var result *multierror.Error

	// Scan for missing required fields
	for field, schema := range d.Schema {
		if schema.Required {
			_, ok := d.Raw[field]
			if !ok {
				result = multierror.Append(result, fmt.Errorf(
					"field %q is required", field))
			}
		}
	}

	// Validate field type and value
	for field, value := range d.Raw {
		schema, ok := d.Schema[field]
		if !ok {
			result = multierror.Append(result, fmt.Errorf(
				"%q is an invalid field", field))
			continue
		}

		switch schema.Type {
		case TypeBool, TypeInt, TypeMap, TypeArray, TypeString:
			val, _, err := d.getPrimitive(field, schema)
			if err != nil {
				result = multierror.Append(result, fmt.Errorf(
					"field %q with input %q doesn't seem to be of type %s",
					field, value, schema.Type))
			}
			// Check that we don't have an empty value for required fields
			if schema.Required && val == schema.Type.Zero() {
				result = multierror.Append(result, fmt.Errorf(
					"field %q is required, but no value was found", field))
			}
		default:
			result = multierror.Append(result, fmt.Errorf(
				"unknown field type %s for field %s", schema.Type, field))
		}
	}

	return result.ErrorOrNil()
}

// Get gets the value for the given field. If the key is an invalid field,
// FieldData will panic. If you want a safer version of this method, use
// GetOk. If the field k is not set, the default value (if set) will be
// returned, otherwise the zero value will be returned.
func (d *FieldData) Get(k string) interface{} {
	schema, ok := d.Schema[k]
	if !ok {
		panic(fmt.Sprintf("field %s not in the schema", k))
	}

	value, ok := d.GetOk(k)
	if !ok {
		value = schema.DefaultOrZero()
	}

	return value
}

// GetOk gets the value for the given field. The second return value
// will be false if the key is invalid or the key is not set at all.
func (d *FieldData) GetOk(k string) (interface{}, bool) {
	schema, ok := d.Schema[k]
	if !ok {
		return nil, false
	}

	result, ok, err := d.GetOkErr(k)
	if err != nil {
		panic(fmt.Sprintf("error reading %s: %s", k, err))
	}

	if ok && result == nil {
		result = schema.DefaultOrZero()
	}

	return result, ok
}

// GetOkErr is the most conservative of all the Get methods. It returns
// whether key is set or not, but also an error value. The error value is
// non-nil if the field doesn't exist or there was an error parsing the
// field value.
func (d *FieldData) GetOkErr(k string) (interface{}, bool, error) {
	schema, ok := d.Schema[k]
	if !ok {
		return nil, false, fmt.Errorf("unknown field: %s", k)
	}

	switch schema.Type {
	case TypeBool, TypeInt, TypeMap, TypeArray, TypeString:
		return d.getPrimitive(k, schema)
	default:
		return nil, false,
			fmt.Errorf("unknown field type %s for field %s", schema.Type, k)
	}
}

// getPrimitive tries to convert the raw value of a field to its data type as
// defined in the schema. It does strict type checking, so the value will need
// to be able to convert to the appropriate type directly.
func (d *FieldData) getPrimitive(
	k string, schema *FieldSchema) (interface{}, bool, error) {
	raw, ok := d.Raw[k]
	if !ok {
		return nil, false, nil
	}

	switch schema.Type {
	case TypeBool:
		var result bool
		if err := mapstructure.Decode(raw, &result); err != nil {
			return nil, true, err
		}
		return result, true, nil

	case TypeInt:
		var result int
		if err := mapstructure.Decode(raw, &result); err != nil {
			return nil, true, err
		}
		return result, true, nil

	case TypeString:
		var result string
		if err := mapstructure.Decode(raw, &result); err != nil {
			return nil, true, err
		}
		return result, true, nil

	case TypeMap:
		var result map[string]interface{}
		if err := mapstructure.Decode(raw, &result); err != nil {
			return nil, true, err
		}
		return result, true, nil

	case TypeArray:
		var result []interface{}
		if err := mapstructure.Decode(raw, &result); err != nil {
			return nil, true, err
		}
		return result, true, nil

	default:
		panic(fmt.Sprintf("Unknown type: %s", schema.Type))
	}
}
<|endoftext|>


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

package packet

import (
	"bytes"
	"crypto/openpgp/error"
	"crypto/sha1"
	"encoding/hex"
	"io"
	"io/ioutil"
	"os"
	"testing"
)

// TestReader wraps a []byte and returns reads of a specific length.
type testReader struct {
	data   []byte
	stride int
}

func (t *testReader) Read(buf []byte) (n int, err os.Error) {
	n = t.stride
	if n > len(t.data) {
		n = len(t.data)
	}
	if n > len(buf) {
		n = len(buf)
	}
	copy(buf, t.data)
	t.data = t.data[n:]
	if len(t.data) == 0 {
		err = os.EOF
	}
	return
}

func testMDCReader(t *testing.T) {
	mdcPlaintext, _ := hex.DecodeString(mdcPlaintextHex)

	for stride := 1; stride < len(mdcPlaintext)/2; stride++ {
		r := &testReader{data: mdcPlaintext, stride: stride}
		mdcReader := &seMDCReader{in: r, h: sha1.New()}
		body, err := ioutil.ReadAll(mdcReader)
		if err != nil {
			t.Errorf("stride: %d, error: %s", stride, err)
			continue
		}
		if !bytes.Equal(body, mdcPlaintext[:len(mdcPlaintext)-22]) {
			t.Errorf("stride: %d: bad contents %x", stride, body)
			continue
		}

		err = mdcReader.Close()
		if err != nil {
			t.Errorf("stride: %d, error on Close: %s", stride, err)
		}
	}

	mdcPlaintext[15] ^= 80

	r := &testReader{data: mdcPlaintext, stride: 2}
	mdcReader := &seMDCReader{in: r, h: sha1.New()}
	_, err := ioutil.ReadAll(mdcReader)
	if err != nil {
		t.Errorf("corruption test, error: %s", err)
		return
	}
	err = mdcReader.Close()
	if err == nil {
		t.Error("corruption: no error")
	} else if _, ok := err.(*error.SignatureError); !ok {
		t.Errorf("corruption: expected SignatureError, got: %s", err)
	}
}

const mdcPlaintextHex = "a302789c3b2d93c4e0eb9aba22283539b3203335af44a134afb800c849cb4c4de10200aff40b45d31432c80cb384299a0655966d6939dfdeed1dddf980"

func TestSerialize(t *testing.T) {
	buf := bytes.NewBuffer(nil)
	c := CipherAES128
	key := make([]byte, c.keySize())

	w, err := SerializeSymmetricallyEncrypted(buf, c, key)
	if err != nil {
		t.Errorf("error from SerializeSymmetricallyEncrypted: %s", err)
		return
	}

	contents := []byte("hello world\n")

	w.Write(contents)
	w.Close()

	p, err := Read(buf)
	if err != nil {
		t.Errorf("error from Read: %s", err)
		return
	}

	se, ok := p.(*SymmetricallyEncrypted)
	if !ok {
		t.Errorf("didn't read a *SymmetricallyEncrypted")
		return
	}

	r, err := se.Decrypt(c, key)
	if err != nil {
		t.Errorf("error from Decrypt: %s", err)
		return
	}

	contentsCopy := bytes.NewBuffer(nil)
	_, err = io.Copy(contentsCopy, r)
	if err != nil {
		t.Errorf("error from io.Copy: %s", err)
		return
	}
	if !bytes.Equal(contentsCopy.Bytes(), contents) {
		t.Errorf("contents not equal got: %x want: %x", contentsCopy.Bytes(), contents)
	}
}
<commit_msg>crypto/openpgp: build fix (unreviewed)<commit_after>// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package packet

import (
	"bytes"
	"crypto/openpgp/error"
	"crypto/sha1"
	"encoding/hex"
	"io"
	"io/ioutil"
	"os"
	"testing"
)

// TestReader wraps a []byte and returns reads of a specific length.
type testReader struct {
	data   []byte
	stride int
}

func (t *testReader) Read(buf []byte) (n int, err os.Error) {
	n = t.stride
	if n > len(t.data) {
		n = len(t.data)
	}
	if n > len(buf) {
		n = len(buf)
	}
	copy(buf, t.data)
	t.data = t.data[n:]
	if len(t.data) == 0 {
		err = os.EOF
	}
	return
}

func testMDCReader(t *testing.T) {
	mdcPlaintext, _ := hex.DecodeString(mdcPlaintextHex)

	for stride := 1; stride < len(mdcPlaintext)/2; stride++ {
		r := &testReader{data: mdcPlaintext, stride: stride}
		mdcReader := &seMDCReader{in: r, h: sha1.New()}
		body, err := ioutil.ReadAll(mdcReader)
		if err != nil {
			t.Errorf("stride: %d, error: %s", stride, err)
			continue
		}
		if !bytes.Equal(body, mdcPlaintext[:len(mdcPlaintext)-22]) {
			t.Errorf("stride: %d: bad contents %x", stride, body)
			continue
		}

		err = mdcReader.Close()
		if err != nil {
			t.Errorf("stride: %d, error on Close: %s", stride, err)
		}
	}

	mdcPlaintext[15] ^= 80

	r := &testReader{data: mdcPlaintext, stride: 2}
	mdcReader := &seMDCReader{in: r, h: sha1.New()}
	_, err := ioutil.ReadAll(mdcReader)
	if err != nil {
		t.Errorf("corruption test, error: %s", err)
		return
	}
	err = mdcReader.Close()
	if err == nil {
		t.Error("corruption: no error")
	} else if _, ok := err.(*error.SignatureError); !ok {
		t.Errorf("corruption: expected SignatureError, got: %s", err)
	}
}

const mdcPlaintextHex = "a302789c3b2d93c4e0eb9aba22283539b3203335af44a134afb800c849cb4c4de10200aff40b45d31432c80cb384299a0655966d6939dfdeed1dddf980"

func TestSerialize(t *testing.T) {
	buf := bytes.NewBuffer(nil)
	c := CipherAES128
	key := make([]byte, c.KeySize())

	w, err := SerializeSymmetricallyEncrypted(buf, c, key)
	if err != nil {
		t.Errorf("error from SerializeSymmetricallyEncrypted: %s", err)
		return
	}

	contents := []byte("hello world\n")

	w.Write(contents)
	w.Close()

	p, err := Read(buf)
	if err != nil {
		t.Errorf("error from Read: %s", err)
		return
	}

	se, ok := p.(*SymmetricallyEncrypted)
	if !ok {
		t.Errorf("didn't read a *SymmetricallyEncrypted")
		return
	}

	r, err := se.Decrypt(c, key)
	if err != nil {
		t.Errorf("error from Decrypt: %s", err)
		return
	}

	contentsCopy := bytes.NewBuffer(nil)
	_, err = io.Copy(contentsCopy, r)
	if err != nil {
		t.Errorf("error from io.Copy: %s", err)
		return
	}
	if !bytes.Equal(contentsCopy.Bytes(), contents) {
		t.Errorf("contents not equal got: %x want: %x", contentsCopy.Bytes(), contents)
	}
}
<|endoftext|>


<commit_before>// Copyright The OpenTelemetry 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 internaldata

import (
	"strconv"
	"time"

	occommon "github.com/census-instrumentation/opencensus-proto/gen-go/agent/common/v1"
	ocresource "github.com/census-instrumentation/opencensus-proto/gen-go/resource/v1"
	"go.opencensus.io/resource/resourcekeys"
	"google.golang.org/protobuf/types/known/timestamppb"

	"go.opentelemetry.io/collector/consumer/pdata"
	"go.opentelemetry.io/collector/translator/conventions"
	tracetranslator "go.opentelemetry.io/collector/translator/trace"
)

type ocInferredResourceType struct {
	// label presence to check against
	labelKeyPresent string
	// inferred resource type
	resourceType string
}

// mapping of label presence to inferred OC resource type
// NOTE: defined in the priority order (first match wins)
var labelPresenceToResourceType = []ocInferredResourceType{
	{
		// See https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/resource/semantic_conventions/container.md
		labelKeyPresent: conventions.AttributeContainerName,
		resourceType:    resourcekeys.ContainerType,
	},
	{
		// See https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/resource/semantic_conventions/k8s.md#pod
		labelKeyPresent: conventions.AttributeK8sPod,
		// NOTE: OpenCensus is using "k8s" rather than "k8s.pod" for Pod
		resourceType: resourcekeys.K8SType,
	},
	{
		// See https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/resource/semantic_conventions/host.md
		labelKeyPresent: conventions.AttributeHostName,
		resourceType:    resourcekeys.HostType,
	},
	{
		// See https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/resource/semantic_conventions/cloud.md
		labelKeyPresent: conventions.AttributeCloudProvider,
		resourceType:    resourcekeys.CloudType,
	},
}

var langToOCLangCodeMap = getSDKLangToOCLangCodeMap()

func getSDKLangToOCLangCodeMap() map[string]int32 {
	mappings := make(map[string]int32)
	mappings[conventions.AttributeSDKLangValueCPP] = 1
	mappings[conventions.AttributeSDKLangValueDotNET] = 2
	mappings[conventions.AttributeSDKLangValueErlang] = 3
	mappings[conventions.AttributeSDKLangValueGo] = 4
	mappings[conventions.AttributeSDKLangValueJava] = 5
	mappings[conventions.AttributeSDKLangValueNodeJS] = 6
	mappings[conventions.AttributeSDKLangValuePHP] = 7
	mappings[conventions.AttributeSDKLangValuePython] = 8
	mappings[conventions.AttributeSDKLangValueRuby] = 9
	mappings[conventions.AttributeSDKLangValueWebJS] = 10
	return mappings
}

func internalResourceToOC(resource pdata.Resource) (*occommon.Node, *ocresource.Resource) {
	attrs := resource.Attributes()
	if attrs.Len() == 0 {
		return nil, nil
	}

	ocNode := &occommon.Node{}
	ocResource := &ocresource.Resource{}
	labels := make(map[string]string, attrs.Len())
	attrs.ForEach(func(k string, v pdata.AttributeValue) {
		val := tracetranslator.AttributeValueToString(v, false)

		switch k {
		case conventions.OCAttributeResourceType:
			ocResource.Type = val
		case conventions.AttributeServiceName:
			getServiceInfo(ocNode).Name = val
		case conventions.OCAttributeProcessStartTime:
			t, err := time.Parse(time.RFC3339Nano, val)
			if err != nil {
				return
			}
			ts := timestamppb.New(t)
			getProcessIdentifier(ocNode).StartTimestamp = ts
		case conventions.AttributeHostName:
			getProcessIdentifier(ocNode).HostName = val
		case conventions.OCAttributeProcessID:
			pid, err := strconv.Atoi(val)
			if err != nil {
				pid = defaultProcessID
			}
			getProcessIdentifier(ocNode).Pid = uint32(pid)
		case conventions.AttributeTelemetrySDKVersion:
			if ocNode.LibraryInfo == nil {
				ocNode.LibraryInfo = &occommon.LibraryInfo{}
			}
			getLibraryInfo(ocNode).CoreLibraryVersion = val
		case conventions.OCAttributeExporterVersion:
			getLibraryInfo(ocNode).ExporterVersion = val
		case conventions.AttributeTelemetrySDKLanguage:
			if code, ok := langToOCLangCodeMap[val]; ok {
				getLibraryInfo(ocNode).Language = occommon.LibraryInfo_Language(code)
			}
		default:
			// Not a special attribute, put it into resource labels
			labels[k] = val
		}
	})
	ocResource.Labels = labels

	// If resource type is missing, try to infer it
	// based on the presence of resource labels (semantic conventions)
	if ocResource.Type == "" {
		if resType, ok := inferResourceType(ocResource.Labels); ok {
			ocResource.Type = resType
		}
	}

	return ocNode, ocResource
}

func getProcessIdentifier(ocNode *occommon.Node) *occommon.ProcessIdentifier {
	if ocNode.Identifier == nil {
		ocNode.Identifier = &occommon.ProcessIdentifier{}
	}
	return ocNode.Identifier
}

func getLibraryInfo(ocNode *occommon.Node) *occommon.LibraryInfo {
	if ocNode.LibraryInfo == nil {
		ocNode.LibraryInfo = &occommon.LibraryInfo{}
	}
	return ocNode.LibraryInfo
}

func getServiceInfo(ocNode *occommon.Node) *occommon.ServiceInfo {
	if ocNode.ServiceInfo == nil {
		ocNode.ServiceInfo = &occommon.ServiceInfo{}
	}
	return ocNode.ServiceInfo
}

func inferResourceType(labels map[string]string) (string, bool) {
	if labels == nil {
		return "", false
	}

	for _, mapping := range labelPresenceToResourceType {
		if _, ok := labels[mapping.labelKeyPresent]; ok {
			return mapping.resourceType, true
		}
	}

	return "", false
}
<commit_msg>Remove duplicate code, same check exists in getLibraryInfo (#2247)<commit_after>// Copyright The OpenTelemetry 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 internaldata

import (
	"strconv"
	"time"

	occommon "github.com/census-instrumentation/opencensus-proto/gen-go/agent/common/v1"
	ocresource "github.com/census-instrumentation/opencensus-proto/gen-go/resource/v1"
	"go.opencensus.io/resource/resourcekeys"
	"google.golang.org/protobuf/types/known/timestamppb"

	"go.opentelemetry.io/collector/consumer/pdata"
	"go.opentelemetry.io/collector/translator/conventions"
	tracetranslator "go.opentelemetry.io/collector/translator/trace"
)

type ocInferredResourceType struct {
	// label presence to check against
	labelKeyPresent string
	// inferred resource type
	resourceType string
}

// mapping of label presence to inferred OC resource type
// NOTE: defined in the priority order (first match wins)
var labelPresenceToResourceType = []ocInferredResourceType{
	{
		// See https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/resource/semantic_conventions/container.md
		labelKeyPresent: conventions.AttributeContainerName,
		resourceType:    resourcekeys.ContainerType,
	},
	{
		// See https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/resource/semantic_conventions/k8s.md#pod
		labelKeyPresent: conventions.AttributeK8sPod,
		// NOTE: OpenCensus is using "k8s" rather than "k8s.pod" for Pod
		resourceType: resourcekeys.K8SType,
	},
	{
		// See https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/resource/semantic_conventions/host.md
		labelKeyPresent: conventions.AttributeHostName,
		resourceType:    resourcekeys.HostType,
	},
	{
		// See https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/resource/semantic_conventions/cloud.md
		labelKeyPresent: conventions.AttributeCloudProvider,
		resourceType:    resourcekeys.CloudType,
	},
}

var langToOCLangCodeMap = getSDKLangToOCLangCodeMap()

func getSDKLangToOCLangCodeMap() map[string]int32 {
	mappings := make(map[string]int32)
	mappings[conventions.AttributeSDKLangValueCPP] = 1
	mappings[conventions.AttributeSDKLangValueDotNET] = 2
	mappings[conventions.AttributeSDKLangValueErlang] = 3
	mappings[conventions.AttributeSDKLangValueGo] = 4
	mappings[conventions.AttributeSDKLangValueJava] = 5
	mappings[conventions.AttributeSDKLangValueNodeJS] = 6
	mappings[conventions.AttributeSDKLangValuePHP] = 7
	mappings[conventions.AttributeSDKLangValuePython] = 8
	mappings[conventions.AttributeSDKLangValueRuby] = 9
	mappings[conventions.AttributeSDKLangValueWebJS] = 10
	return mappings
}

func internalResourceToOC(resource pdata.Resource) (*occommon.Node, *ocresource.Resource) {
	attrs := resource.Attributes()
	if attrs.Len() == 0 {
		return nil, nil
	}

	ocNode := &occommon.Node{}
	ocResource := &ocresource.Resource{}
	labels := make(map[string]string, attrs.Len())
	attrs.ForEach(func(k string, v pdata.AttributeValue) {
		val := tracetranslator.AttributeValueToString(v, false)

		switch k {
		case conventions.OCAttributeResourceType:
			ocResource.Type = val
		case conventions.AttributeServiceName:
			getServiceInfo(ocNode).Name = val
		case conventions.OCAttributeProcessStartTime:
			t, err := time.Parse(time.RFC3339Nano, val)
			if err != nil {
				return
			}
			ts := timestamppb.New(t)
			getProcessIdentifier(ocNode).StartTimestamp = ts
		case conventions.AttributeHostName:
			getProcessIdentifier(ocNode).HostName = val
		case conventions.OCAttributeProcessID:
			pid, err := strconv.Atoi(val)
			if err != nil {
				pid = defaultProcessID
			}
			getProcessIdentifier(ocNode).Pid = uint32(pid)
		case conventions.AttributeTelemetrySDKVersion:
			getLibraryInfo(ocNode).CoreLibraryVersion = val
		case conventions.OCAttributeExporterVersion:
			getLibraryInfo(ocNode).ExporterVersion = val
		case conventions.AttributeTelemetrySDKLanguage:
			if code, ok := langToOCLangCodeMap[val]; ok {
				getLibraryInfo(ocNode).Language = occommon.LibraryInfo_Language(code)
			}
		default:
			// Not a special attribute, put it into resource labels
			labels[k] = val
		}
	})
	ocResource.Labels = labels

	// If resource type is missing, try to infer it
	// based on the presence of resource labels (semantic conventions)
	if ocResource.Type == "" {
		if resType, ok := inferResourceType(ocResource.Labels); ok {
			ocResource.Type = resType
		}
	}

	return ocNode, ocResource
}

func getProcessIdentifier(ocNode *occommon.Node) *occommon.ProcessIdentifier {
	if ocNode.Identifier == nil {
		ocNode.Identifier = &occommon.ProcessIdentifier{}
	}
	return ocNode.Identifier
}

func getLibraryInfo(ocNode *occommon.Node) *occommon.LibraryInfo {
	if ocNode.LibraryInfo == nil {
		ocNode.LibraryInfo = &occommon.LibraryInfo{}
	}
	return ocNode.LibraryInfo
}

func getServiceInfo(ocNode *occommon.Node) *occommon.ServiceInfo {
	if ocNode.ServiceInfo == nil {
		ocNode.ServiceInfo = &occommon.ServiceInfo{}
	}
	return ocNode.ServiceInfo
}

func inferResourceType(labels map[string]string) (string, bool) {
	if labels == nil {
		return "", false
	}

	for _, mapping := range labelPresenceToResourceType {
		if _, ok := labels[mapping.labelKeyPresent]; ok {
			return mapping.resourceType, true
		}
	}

	return "", false
}
<|endoftext|>