<commit_before>package control

import (
	"os/exec"
)

type PowerPointBroadcast struct {
	//Path to the presentation
	path string
	//Path to PowerPoint executable
	powerPoint string
	//Current running PowerPoint instance
	cmd *exec.Cmd
}

//Start starts PowerPoint in presentation mode.
func (b *PowerPointBroadcast) Start() error {
	if b.Status() {
		return nil
	}
	cmd := exec.Command(b.powerPoint, "/s", b.path)
	err := cmd.Start()
	if err != nil {
		return err
	}
	b.cmd = cmd
	return nil
}

//Kill ends Terminate signal to PowerPoint.
func (b *PowerPointBroadcast) Kill() error {
	if b.cmd == nil {
		return nil
	}
	err := b.cmd.Process.Kill()
	if err != nil {
		return err
	}
	b.cmd = nil
	return nil
}

func (b PowerPointBroadcast) Status() bool {
	if b.cmd == nil {
		return false
	}
	return true
}

func (b PowerPointBroadcast) Path() string {
	return b.path
}

func NewPowerPoint(ppExe, presentation string) *PowerPointBroadcast {
	return &PowerPointBroadcast{path: presentation, powerPoint: ppExe}
}
<commit_msg>Added check if PowerPoint exited to PowerPointBroadcast.Status()<commit_after>package control

import (
	"os/exec"
)

type PowerPointBroadcast struct {
	//Path to the presentation
	path string
	//Path to PowerPoint executable
	powerPoint string
	//Current running PowerPoint instance
	cmd *exec.Cmd
}

//Start starts PowerPoint in presentation mode.
func (b *PowerPointBroadcast) Start() error {
	if b.Status() {
		return nil
	}
	cmd := exec.Command(b.powerPoint, "/s", b.path)
	err := cmd.Start()
	if err != nil {
		return err
	}
	b.cmd = cmd
	return nil
}

//Kill ends Terminate signal to PowerPoint.
func (b *PowerPointBroadcast) Kill() error {
	if !b.Status() {
		return nil
	}
	err := b.cmd.Process.Kill()
	if err != nil {
		return err
	}
	b.cmd = nil
	return nil
}

func (b PowerPointBroadcast) Status() bool {
	if b.cmd == nil {
		return false
	} else if b.cmd.ProcessState.Exited() {
		return false
	}
	return true
}

func (b PowerPointBroadcast) Path() string {
	return b.path
}

func NewPowerPoint(ppExe, presentation string) *PowerPointBroadcast {
	return &PowerPointBroadcast{path: presentation, powerPoint: ppExe}
}
<|endoftext|>


<commit_before>package rep

import (
	"encoding/json"
	"errors"
	"net/url"
	"strconv"

	"code.cloudfoundry.org/bbs/models"
	"code.cloudfoundry.org/executor"
)

const (
	LifecycleTag  = "lifecycle"
	ResultFileTag = "result-file"
	DomainTag     = "domain"

	TaskLifecycle = "task"
	LRPLifecycle  = "lrp"

	ProcessGuidTag  = "process-guid"
	InstanceGuidTag = "instance-guid"
	ProcessIndexTag = "process-index"
)

var (
	ErrContainerMissingTags = errors.New("container is missing tags")
	ErrInvalidProcessIndex  = errors.New("container does not have a valid process index")
)

func ActualLRPKeyFromTags(tags executor.Tags) (*models.ActualLRPKey, error) {
	if tags == nil {
		return &models.ActualLRPKey{}, ErrContainerMissingTags
	}

	processIndex, err := strconv.Atoi(tags[ProcessIndexTag])
	if err != nil {
		return &models.ActualLRPKey{}, ErrInvalidProcessIndex
	}

	actualLRPKey := models.NewActualLRPKey(
		tags[ProcessGuidTag],
		int32(processIndex),
		tags[DomainTag],
	)

	err = actualLRPKey.Validate()
	if err != nil {
		return &models.ActualLRPKey{}, err
	}

	return &actualLRPKey, nil
}

func ActualLRPInstanceKeyFromContainer(container executor.Container, cellID string) (*models.ActualLRPInstanceKey, error) {
	if container.Tags == nil {
		return &models.ActualLRPInstanceKey{}, ErrContainerMissingTags
	}

	actualLRPInstanceKey := models.NewActualLRPInstanceKey(
		container.Tags[InstanceGuidTag],
		cellID,
	)

	err := actualLRPInstanceKey.Validate()
	if err != nil {
		return &models.ActualLRPInstanceKey{}, err
	}

	return &actualLRPInstanceKey, nil
}

func ActualLRPNetInfoFromContainer(container executor.Container) (*models.ActualLRPNetInfo, error) {
	ports := []*models.PortMapping{}
	for _, portMapping := range container.Ports {
		ports = append(ports, models.NewPortMapping(uint32(portMapping.HostPort), uint32(portMapping.ContainerPort)))
	}

	actualLRPNetInfo := models.NewActualLRPNetInfo(container.ExternalIP, container.InternalIP, ports...)

	err := actualLRPNetInfo.Validate()
	if err != nil {
		return nil, err
	}

	return &actualLRPNetInfo, nil
}

func LRPContainerGuid(processGuid, instanceGuid string) string {
	return instanceGuid
}

func NewRunRequestFromDesiredLRP(
	containerGuid string,
	desiredLRP *models.DesiredLRP,
	lrpKey *models.ActualLRPKey,
	lrpInstanceKey *models.ActualLRPInstanceKey,
) (executor.RunRequest, error) {
	diskScope, err := diskScopeForRootFS(desiredLRP.RootFs)
	if err != nil {
		return executor.RunRequest{}, err
	}

	mounts, err := convertVolumeMounts(desiredLRP.VolumeMounts)
	if err != nil {
		return executor.RunRequest{}, err
	}

	runInfo := executor.RunInfo{
		CPUWeight: uint(desiredLRP.CpuWeight),
		DiskScope: diskScope,
		Ports:     ConvertPortMappings(desiredLRP.Ports),
		LogConfig: executor.LogConfig{
			Guid:       desiredLRP.LogGuid,
			Index:      int(lrpKey.Index),
			SourceName: desiredLRP.LogSource,
		},

		MetricsConfig: executor.MetricsConfig{
			Guid:  desiredLRP.MetricsGuid,
			Index: int(lrpKey.Index),
		},
		StartTimeoutMs:     uint(desiredLRP.StartTimeoutMs),
		Privileged:         desiredLRP.Privileged,
		CachedDependencies: ConvertCachedDependencies(desiredLRP.CachedDependencies),
		Setup:              desiredLRP.Setup,
		Action:             desiredLRP.Action,
		Monitor:            desiredLRP.Monitor,
		CheckDefinition:    desiredLRP.CheckDefinition,
		EgressRules:        desiredLRP.EgressRules,
		Env: append([]executor.EnvironmentVariable{
			{Name: "INSTANCE_GUID", Value: lrpInstanceKey.InstanceGuid},
			{Name: "INSTANCE_INDEX", Value: strconv.Itoa(int(lrpKey.Index))},
			{Name: "CF_INSTANCE_GUID", Value: lrpInstanceKey.InstanceGuid},
			{Name: "CF_INSTANCE_INDEX", Value: strconv.Itoa(int(lrpKey.Index))},
		}, executor.EnvironmentVariablesFromModel(desiredLRP.EnvironmentVariables)...),
		TrustedSystemCertificatesPath: desiredLRP.TrustedSystemCertificatesPath,
		VolumeMounts:                  mounts,
		Network:                       convertNetwork(desiredLRP.Network),
		CertificateProperties:         convertCertificateProperties(desiredLRP.CertificateProperties),
		ImageUsername:                 desiredLRP.ImageUsername,
		ImagePassword:                 desiredLRP.ImagePassword,
	}
	tags := executor.Tags{}
	return executor.NewRunRequest(containerGuid, &runInfo, tags), nil
}

func NewRunRequestFromTask(task *models.Task) (executor.RunRequest, error) {
	diskScope, err := diskScopeForRootFS(task.RootFs)
	if err != nil {
		return executor.RunRequest{}, err
	}

	mounts, err := convertVolumeMounts(task.VolumeMounts)
	if err != nil {
		return executor.RunRequest{}, err
	}

	tags := executor.Tags{
		ResultFileTag: task.ResultFile,
	}
	runInfo := executor.RunInfo{
		DiskScope:  diskScope,
		CPUWeight:  uint(task.CpuWeight),
		Privileged: task.Privileged,
		LogConfig: executor.LogConfig{
			Guid:       task.LogGuid,
			SourceName: task.LogSource,
		},
		MetricsConfig: executor.MetricsConfig{
			Guid: task.MetricsGuid,
		},
		CachedDependencies:            ConvertCachedDependencies(task.CachedDependencies),
		Action:                        task.Action,
		Env:                           executor.EnvironmentVariablesFromModel(task.EnvironmentVariables),
		EgressRules:                   task.EgressRules,
		TrustedSystemCertificatesPath: task.TrustedSystemCertificatesPath,
		VolumeMounts:                  mounts,
		Network:                       convertNetwork(task.Network),
		CertificateProperties:         convertCertificateProperties(task.CertificateProperties),
		ImageUsername:                 task.ImageUsername,
		ImagePassword:                 task.ImagePassword,
	}
	return executor.NewRunRequest(task.TaskGuid, &runInfo, tags), nil
}

func ConvertCachedDependencies(modelDeps []*models.CachedDependency) []executor.CachedDependency {
	execDeps := make([]executor.CachedDependency, len(modelDeps))
	for i := range modelDeps {
		execDeps[i] = ConvertCachedDependency(modelDeps[i])
	}
	return execDeps
}

func ConvertCachedDependency(modelDep *models.CachedDependency) executor.CachedDependency {
	return executor.CachedDependency{
		Name:              modelDep.Name,
		From:              modelDep.From,
		To:                modelDep.To,
		CacheKey:          modelDep.CacheKey,
		LogSource:         modelDep.LogSource,
		ChecksumValue:     modelDep.ChecksumValue,
		ChecksumAlgorithm: modelDep.ChecksumAlgorithm,
	}
}

func convertVolumeMounts(volumeMounts []*models.VolumeMount) ([]executor.VolumeMount, error) {
	execMnts := make([]executor.VolumeMount, len(volumeMounts))
	for i := range volumeMounts {
		var err error
		execMnts[i], err = convertVolumeMount(volumeMounts[i])
		if err != nil {
			return nil, err
		}
	}
	return execMnts, nil
}

func convertVolumeMount(volumeMnt *models.VolumeMount) (executor.VolumeMount, error) {
	var config map[string]interface{}

	if len(volumeMnt.Shared.MountConfig) > 0 {
		err := json.Unmarshal([]byte(volumeMnt.Shared.MountConfig), &config)
		if err != nil {
			return executor.VolumeMount{}, err
		}
	}

	var mode executor.BindMountMode
	switch volumeMnt.Mode {
	case "r":
		mode = executor.BindMountModeRO
	case "rw":
		mode = executor.BindMountModeRW
	default:
		return executor.VolumeMount{}, errors.New("unrecognized volume mount mode")
	}

	return executor.VolumeMount{
		Driver:        volumeMnt.Driver,
		VolumeId:      volumeMnt.Shared.VolumeId,
		ContainerPath: volumeMnt.ContainerDir,
		Mode:          mode,
		Config:        config,
	}, nil
}

func convertNetwork(network *models.Network) *executor.Network {
	if network == nil {
		return nil
	}

	return &executor.Network{
		Properties: network.Properties,
	}
}

func convertCertificateProperties(props *models.CertificateProperties) executor.CertificateProperties {
	if props == nil {
		return executor.CertificateProperties{}
	}

	return executor.CertificateProperties{
		OrganizationalUnit: props.OrganizationalUnit,
	}
}

func ConvertPortMappings(containerPorts []uint32) []executor.PortMapping {
	out := []executor.PortMapping{}
	for _, port := range containerPorts {
		out = append(out, executor.PortMapping{
			ContainerPort: uint16(port),
		})
	}

	return out
}

func diskScopeForRootFS(rootFS string) (executor.DiskLimitScope, error) {
	preloaded := false

	url, err := url.Parse(rootFS)
	if err != nil {
		return executor.TotalDiskLimit, err
	}

	if url.Scheme == models.PreloadedRootFSScheme {
		preloaded = true
	}

	if preloaded {
		return executor.ExclusiveDiskLimit, nil
	}
	return executor.TotalDiskLimit, nil
}
<commit_msg>add tls proxy port mappings to the actual lrp net info<commit_after>package rep

import (
	"encoding/json"
	"errors"
	"net/url"
	"strconv"

	"code.cloudfoundry.org/bbs/models"
	"code.cloudfoundry.org/executor"
)

const (
	LifecycleTag  = "lifecycle"
	ResultFileTag = "result-file"
	DomainTag     = "domain"

	TaskLifecycle = "task"
	LRPLifecycle  = "lrp"

	ProcessGuidTag  = "process-guid"
	InstanceGuidTag = "instance-guid"
	ProcessIndexTag = "process-index"
)

var (
	ErrContainerMissingTags = errors.New("container is missing tags")
	ErrInvalidProcessIndex  = errors.New("container does not have a valid process index")
)

func ActualLRPKeyFromTags(tags executor.Tags) (*models.ActualLRPKey, error) {
	if tags == nil {
		return &models.ActualLRPKey{}, ErrContainerMissingTags
	}

	processIndex, err := strconv.Atoi(tags[ProcessIndexTag])
	if err != nil {
		return &models.ActualLRPKey{}, ErrInvalidProcessIndex
	}

	actualLRPKey := models.NewActualLRPKey(
		tags[ProcessGuidTag],
		int32(processIndex),
		tags[DomainTag],
	)

	err = actualLRPKey.Validate()
	if err != nil {
		return &models.ActualLRPKey{}, err
	}

	return &actualLRPKey, nil
}

func ActualLRPInstanceKeyFromContainer(container executor.Container, cellID string) (*models.ActualLRPInstanceKey, error) {
	if container.Tags == nil {
		return &models.ActualLRPInstanceKey{}, ErrContainerMissingTags
	}

	actualLRPInstanceKey := models.NewActualLRPInstanceKey(
		container.Tags[InstanceGuidTag],
		cellID,
	)

	err := actualLRPInstanceKey.Validate()
	if err != nil {
		return &models.ActualLRPInstanceKey{}, err
	}

	return &actualLRPInstanceKey, nil
}

func ActualLRPNetInfoFromContainer(container executor.Container) (*models.ActualLRPNetInfo, error) {
	ports := []*models.PortMapping{}

	for _, port := range container.Ports {
		// todo: do not include proxy ports
		ports = append(ports, models.NewPortMappingWithTLSProxy(
			uint32(port.HostPort),
			uint32(port.ContainerPort),
			uint32(port.HostTLSProxyPort),
			uint32(port.ContainerTLSProxyPort),
		))
	}

	actualLRPNetInfo := models.NewActualLRPNetInfo(container.ExternalIP, container.InternalIP, ports...)

	err := actualLRPNetInfo.Validate()
	if err != nil {
		return nil, err
	}

	return &actualLRPNetInfo, nil
}

func LRPContainerGuid(processGuid, instanceGuid string) string {
	return instanceGuid
}

func NewRunRequestFromDesiredLRP(
	containerGuid string,
	desiredLRP *models.DesiredLRP,
	lrpKey *models.ActualLRPKey,
	lrpInstanceKey *models.ActualLRPInstanceKey,
) (executor.RunRequest, error) {
	diskScope, err := diskScopeForRootFS(desiredLRP.RootFs)
	if err != nil {
		return executor.RunRequest{}, err
	}

	mounts, err := convertVolumeMounts(desiredLRP.VolumeMounts)
	if err != nil {
		return executor.RunRequest{}, err
	}

	runInfo := executor.RunInfo{
		CPUWeight: uint(desiredLRP.CpuWeight),
		DiskScope: diskScope,
		Ports:     ConvertPortMappings(desiredLRP.Ports),
		LogConfig: executor.LogConfig{
			Guid:       desiredLRP.LogGuid,
			Index:      int(lrpKey.Index),
			SourceName: desiredLRP.LogSource,
		},

		MetricsConfig: executor.MetricsConfig{
			Guid:  desiredLRP.MetricsGuid,
			Index: int(lrpKey.Index),
		},
		StartTimeoutMs:     uint(desiredLRP.StartTimeoutMs),
		Privileged:         desiredLRP.Privileged,
		CachedDependencies: ConvertCachedDependencies(desiredLRP.CachedDependencies),
		Setup:              desiredLRP.Setup,
		Action:             desiredLRP.Action,
		Monitor:            desiredLRP.Monitor,
		CheckDefinition:    desiredLRP.CheckDefinition,
		EgressRules:        desiredLRP.EgressRules,
		Env: append([]executor.EnvironmentVariable{
			{Name: "INSTANCE_GUID", Value: lrpInstanceKey.InstanceGuid},
			{Name: "INSTANCE_INDEX", Value: strconv.Itoa(int(lrpKey.Index))},
			{Name: "CF_INSTANCE_GUID", Value: lrpInstanceKey.InstanceGuid},
			{Name: "CF_INSTANCE_INDEX", Value: strconv.Itoa(int(lrpKey.Index))},
		}, executor.EnvironmentVariablesFromModel(desiredLRP.EnvironmentVariables)...),
		TrustedSystemCertificatesPath: desiredLRP.TrustedSystemCertificatesPath,
		VolumeMounts:                  mounts,
		Network:                       convertNetwork(desiredLRP.Network),
		CertificateProperties:         convertCertificateProperties(desiredLRP.CertificateProperties),
		ImageUsername:                 desiredLRP.ImageUsername,
		ImagePassword:                 desiredLRP.ImagePassword,
	}
	tags := executor.Tags{}
	return executor.NewRunRequest(containerGuid, &runInfo, tags), nil
}

func NewRunRequestFromTask(task *models.Task) (executor.RunRequest, error) {
	diskScope, err := diskScopeForRootFS(task.RootFs)
	if err != nil {
		return executor.RunRequest{}, err
	}

	mounts, err := convertVolumeMounts(task.VolumeMounts)
	if err != nil {
		return executor.RunRequest{}, err
	}

	tags := executor.Tags{
		ResultFileTag: task.ResultFile,
	}
	runInfo := executor.RunInfo{
		DiskScope:  diskScope,
		CPUWeight:  uint(task.CpuWeight),
		Privileged: task.Privileged,
		LogConfig: executor.LogConfig{
			Guid:       task.LogGuid,
			SourceName: task.LogSource,
		},
		MetricsConfig: executor.MetricsConfig{
			Guid: task.MetricsGuid,
		},
		CachedDependencies:            ConvertCachedDependencies(task.CachedDependencies),
		Action:                        task.Action,
		Env:                           executor.EnvironmentVariablesFromModel(task.EnvironmentVariables),
		EgressRules:                   task.EgressRules,
		TrustedSystemCertificatesPath: task.TrustedSystemCertificatesPath,
		VolumeMounts:                  mounts,
		Network:                       convertNetwork(task.Network),
		CertificateProperties:         convertCertificateProperties(task.CertificateProperties),
		ImageUsername:                 task.ImageUsername,
		ImagePassword:                 task.ImagePassword,
	}
	return executor.NewRunRequest(task.TaskGuid, &runInfo, tags), nil
}

func ConvertCachedDependencies(modelDeps []*models.CachedDependency) []executor.CachedDependency {
	execDeps := make([]executor.CachedDependency, len(modelDeps))
	for i := range modelDeps {
		execDeps[i] = ConvertCachedDependency(modelDeps[i])
	}
	return execDeps
}

func ConvertCachedDependency(modelDep *models.CachedDependency) executor.CachedDependency {
	return executor.CachedDependency{
		Name:              modelDep.Name,
		From:              modelDep.From,
		To:                modelDep.To,
		CacheKey:          modelDep.CacheKey,
		LogSource:         modelDep.LogSource,
		ChecksumValue:     modelDep.ChecksumValue,
		ChecksumAlgorithm: modelDep.ChecksumAlgorithm,
	}
}

func convertVolumeMounts(volumeMounts []*models.VolumeMount) ([]executor.VolumeMount, error) {
	execMnts := make([]executor.VolumeMount, len(volumeMounts))
	for i := range volumeMounts {
		var err error
		execMnts[i], err = convertVolumeMount(volumeMounts[i])
		if err != nil {
			return nil, err
		}
	}
	return execMnts, nil
}

func convertVolumeMount(volumeMnt *models.VolumeMount) (executor.VolumeMount, error) {
	var config map[string]interface{}

	if len(volumeMnt.Shared.MountConfig) > 0 {
		err := json.Unmarshal([]byte(volumeMnt.Shared.MountConfig), &config)
		if err != nil {
			return executor.VolumeMount{}, err
		}
	}

	var mode executor.BindMountMode
	switch volumeMnt.Mode {
	case "r":
		mode = executor.BindMountModeRO
	case "rw":
		mode = executor.BindMountModeRW
	default:
		return executor.VolumeMount{}, errors.New("unrecognized volume mount mode")
	}

	return executor.VolumeMount{
		Driver:        volumeMnt.Driver,
		VolumeId:      volumeMnt.Shared.VolumeId,
		ContainerPath: volumeMnt.ContainerDir,
		Mode:          mode,
		Config:        config,
	}, nil
}

func convertNetwork(network *models.Network) *executor.Network {
	if network == nil {
		return nil
	}

	return &executor.Network{
		Properties: network.Properties,
	}
}

func convertCertificateProperties(props *models.CertificateProperties) executor.CertificateProperties {
	if props == nil {
		return executor.CertificateProperties{}
	}

	return executor.CertificateProperties{
		OrganizationalUnit: props.OrganizationalUnit,
	}
}

func ConvertPortMappings(containerPorts []uint32) []executor.PortMapping {
	out := []executor.PortMapping{}
	for _, port := range containerPorts {
		out = append(out, executor.PortMapping{
			ContainerPort: uint16(port),
		})
	}

	return out
}

func diskScopeForRootFS(rootFS string) (executor.DiskLimitScope, error) {
	preloaded := false

	url, err := url.Parse(rootFS)
	if err != nil {
		return executor.TotalDiskLimit, err
	}

	if url.Scheme == models.PreloadedRootFSScheme {
		preloaded = true
	}

	if preloaded {
		return executor.ExclusiveDiskLimit, nil
	}
	return executor.TotalDiskLimit, nil
}
<|endoftext|>


<commit_before>package prob

// Ground operators

type Oper struct{
	Name string
	Parms []Name
	Cost float32
	Precond []Literal
	Effect []Literal
	CondEffs []CondEffect
}

type CondEffect struct{
	Cond []Literal
	Effect []Literal
}

func (a *Action) operators() (ops []Oper) {
	a.ensureDnf()

	parms := make([]Name, len(a.Parameters))
	for i := range a.Parameters {
		parms[i] = a.Parameters[i].Name
	}

	conds := gatherOrs(a.Precondition)
	ueffs, ceffs := gatherEffects(a.Effect);

	for i := range conds {
		ops = append(ops, Oper{
			Name: a.Name,
			Parms: parms,
			Cost: float32(1),	// For now
			Precond: gatherLits(conds[i]),
			Effect: ueffs,
			CondEffs: ceffs,
		})
	}
	return
}

// Get the unconditional and conditional effects
func gatherEffects(f Formula) (ueffs []Literal, ceffs []CondEffect) {
	for _, eff := range gatherOrs(f) {
		switch n := eff.(type) {
		case *WhenNode:
			ceffs = append(ceffs, CondEffect{
				Cond: gatherLits(n.Condition),
				Effect: gatherLits(n.Formula),
			})
		case *AndNode:
			ueffs = append(ueffs, gatherLits(n)...)
		case *Literal:
			ueffs = append(ueffs, *n)
		case *AssignNode:
			// Ignore assignment for now
		default:
			panic("gatherEffects: not a WhenNode, AndNode or Literal")
		}
	}
	return
}

func gatherLits(f Formula) (lits []Literal) {
	switch n := f.(type) {
	case *AndNode:
		lits = append(lits, gatherLits(n.Left)...)
		lits = append(lits, gatherLits(n.Right)...)
	case *Literal:
		lits = append(lits, *n)
	case *AssignNode:
		// Ignore an assignment
	default:
		panic("gatherLits: not an AndNode or Literal");
	}
	return
}<commit_msg>Change the error messages on unexpected node types.<commit_after>package prob

// Ground operators

type Oper struct{
	Name string
	Parms []Name
	Cost float32
	Precond []Literal
	Effect []Literal
	CondEffs []CondEffect
}

type CondEffect struct{
	Cond []Literal
	Effect []Literal
}

func (a *Action) operators() (ops []Oper) {
	a.ensureDnf()

	parms := make([]Name, len(a.Parameters))
	for i := range a.Parameters {
		parms[i] = a.Parameters[i].Name
	}

	conds := gatherOrs(a.Precondition)
	ueffs, ceffs := gatherEffects(a.Effect);

	for i := range conds {
		ops = append(ops, Oper{
			Name: a.Name,
			Parms: parms,
			Cost: float32(1),	// For now
			Precond: gatherLits(conds[i]),
			Effect: ueffs,
			CondEffs: ceffs,
		})
	}
	return
}

// Get the unconditional and conditional effects
func gatherEffects(f Formula) (ueffs []Literal, ceffs []CondEffect) {
	for _, eff := range gatherOrs(f) {
		switch n := eff.(type) {
		case *WhenNode:
			ceffs = append(ceffs, CondEffect{
				Cond: gatherLits(n.Condition),
				Effect: gatherLits(n.Formula),
			})
		case *AndNode:
			ueffs = append(ueffs, gatherLits(n)...)
		case *Literal:
			ueffs = append(ueffs, *n)
		case *AssignNode:
			// Ignore assignment for now
		default:
			panic("gatherEffects: unexpected node type")
		}
	}
	return
}

func gatherLits(f Formula) (lits []Literal) {
	switch n := f.(type) {
	case *AndNode:
		lits = append(lits, gatherLits(n.Left)...)
		lits = append(lits, gatherLits(n.Right)...)
	case *Literal:
		lits = append(lits, *n)
	case *AssignNode:
		// Ignore an assignment
	default:
		panic("gatherLits: unexpected node type");
	}
	return
}<|endoftext|>


<commit_before>package slack

import (
	"encoding/json"
	"fmt"
	"log"
	"regexp"
	"strings"
)

const (
	slackEventTypeMessage = "message"

	maxMessageSize = 4000
)

// Processor type processes inbound events from Slack
type Processor struct {
	// Connection to Slack
	con *Connection

	// Slack user information relating to the bot account
	self User

	// a sequence number to uniquely identify sent messages and correlate with acks from Slack
	sequence int

	// map of event handler functions to handle types of Slack event
	eventHandlers map[string]func(*Processor, map[string]interface{}, []byte)

	// map of users who are members of the Slack group
	users map[string]User
}

// event type represents an event sent to Slack e.g. messages
type event struct {
	Id      int    `json:"id"`
	Type    string `json:"type"`
	Channel string `json:"channel"`
	Text    string `json:"text"`
}

// user_change event type represents a user change event from Slack
type userChangeEvent struct {
	Type        string `json:"type"`
	UpdatedUser User   `json:"user"`
}

// send Event to Slack
func (p *Processor) sendEvent(eventType string, channel string, text string) error {
	p.sequence++

	response := &event{Id: p.sequence, Type: eventType, Channel: channel, Text: text}

	responseJson, err := json.Marshal(response)
	if err != nil {
		return err
	}

	p.con.Write(responseJson)

	return nil
}

// Write the message on the specified channel to Slack
func (p *Processor) Write(channel string, text string) error {
	for len(text) > 0 {
		if len(text) <= maxMessageSize {
			if err := p.sendEvent(slackEventTypeMessage, channel, text); err != nil {
				return err
			}
			text = ""
		} else {
			// split message at a convenient place
			maxSizeChunk := text[:maxMessageSize]

			var breakIndex int
			if lastLineBreak := strings.LastIndex(maxSizeChunk, "\n"); lastLineBreak > -1 {
				breakIndex = lastLineBreak
			} else if lastWordBreak := strings.LastIndexAny(maxSizeChunk, "\n\t .,/\\-(){}[]|=+*&"); lastWordBreak > -1 {
				breakIndex = lastWordBreak
			} else {
				breakIndex = maxMessageSize
			}

			if err := p.sendEvent(slackEventTypeMessage, channel, text[:breakIndex]); err != nil {
				return err
			}

			if breakIndex != maxMessageSize {
				breakIndex++
			}

			text = text[breakIndex:]
		}
	}

	return nil
}

// Start processing events from Slack
func (p *Processor) Start() {
	for {
		msg := p.con.Read()

		log.Printf("%s", msg)

		var data map[string]interface{}
		err := json.Unmarshal(msg, &data)

		if err != nil {
			fmt.Printf("%T\n%s\n%#v\n", err, err, err)
			switch v := err.(type) {
			case *json.SyntaxError:
				log.Println(string(msg[v.Offset-40 : v.Offset]))
			}
			log.Printf("%s", msg)
			continue
		}

		// if reply_to attribute is present the event is an ack' for a sent message
		_, isReply := data["reply_to"]
		subtype, ok := data["subtype"]
		var isMessageChangedEvent bool

		if ok {
			isMessageChangedEvent = (subtype.(string) == "message_changed" || subtype.(string) == "message_deleted")
		}

		if !isReply && !isMessageChangedEvent {
			handler, ok := p.eventHandlers[data["type"].(string)]

			if ok {
				handler(p, data, msg)
			}
		}
	}
}

// updateUser updates or adds (if not already existing) the specifed user
func (p *Processor) updateUser(user User) {
	p.users[user.Id] = user
}

// onConnected is a callback for when the client connects (or reconnects) to Slack.
func (p *Processor) onConnected(con *Connection) {
	log.Println("Connected to Slack")
	p.self = con.config.Self

	p.users = make(map[string]User)
	for _, user := range con.config.Users {
		p.updateUser(user)
	}
}

// type for callbacks to receive messages from Slack
type messageProcessor func(*Message)

// Starts processing events on the connection from Slack and passes any messages to the hear callback and only
// messages addressed to the bot to the respond callback
func EventProcessor(con *Connection, respond messageProcessor, hear messageProcessor) {
	p := Processor{
		con:  con,
		self: con.config.Self,
		eventHandlers: map[string]func(*Processor, map[string]interface{}, []byte){
			slackEventTypeMessage: func(p *Processor, event map[string]interface{}, rawEvent []byte) {
				filterMessage(p, event, respond, hear)
			},
			"user_change": func(p *Processor, event map[string]interface{}, rawEvent []byte) {
				var userEvent userChangeEvent
				err := json.Unmarshal(rawEvent, &userEvent)

				if err != nil {
					fmt.Printf("%T\n%s\n%#v\n", err, err, err)
					switch v := err.(type) {
					case *json.SyntaxError:
						fmt.Println(string(rawEvent[v.Offset-40 : v.Offset]))
					}
					fmt.Printf("%s", rawEvent)
				}
				p.updateUser(userEvent.UpdatedUser)
			},
			"hello": func(p *Processor, event map[string]interface{}, rawEvent []byte) {
				p.onConnected(con)
			},
		},
		users: make(map[string]User),
	}

	p.Start()
}

// Invoke one of the specified callbacks for the message if appropriate
func filterMessage(p *Processor, data map[string]interface{}, respond messageProcessor, hear messageProcessor) {
	var userFullName string
	var userId string

	user, ok := data["user"]
	if ok {
		userId = user.(string)
		user, exists := p.users[userId]
		if exists {
			userFullName = user.RealName
		}
	}

	// process messages directed at Talbot
	r, _ := regexp.Compile("^(<@" + p.self.Id + ">|@?" + p.self.Name + "):? (.+)")

	text, ok := data["text"]
	if !ok {
		return
	}

	matches := r.FindStringSubmatch(text.(string))

	if len(matches) == 3 {
		if respond != nil {
			m := &Message{eventStream: p, responseStrategy: reply, Text: matches[2], From: userFullName, fromId: userId, channel: data["channel"].(string)}
			respond(m)
		}
	} else if data["channel"].(string)[0] == 'D' {
		if respond != nil {
			// process direct messages
			m := &Message{eventStream: p, responseStrategy: send, Text: text.(string), From: userFullName, fromId: userId, channel: data["channel"].(string)}
			respond(m)
		}
	} else {
		if hear != nil {
			m := &Message{eventStream: p, responseStrategy: send, Text: text.(string), From: userFullName, fromId: userId, channel: data["channel"].(string)}
			hear(m)
		}
	}
}
<commit_msg>added handling of error events from Slack<commit_after>package slack

import (
	"encoding/json"
	"fmt"
	"log"
	"regexp"
	"strings"
)

const (
	slackEventTypeMessage = "message"

	maxMessageSize = 4000
)

// Processor type processes inbound events from Slack
type Processor struct {
	// Connection to Slack
	con *Connection

	// Slack user information relating to the bot account
	self User

	// a sequence number to uniquely identify sent messages and correlate with acks from Slack
	sequence int

	// map of event handler functions to handle types of Slack event
	eventHandlers map[string]func(*Processor, map[string]interface{}, []byte)

	// map of users who are members of the Slack group
	users map[string]User
}

// event type represents an event sent to Slack e.g. messages
type event struct {
	Id      int    `json:"id"`
	Type    string `json:"type"`
	Channel string `json:"channel"`
	Text    string `json:"text"`
}

// user_change event type represents a user change event from Slack
type userChangeEvent struct {
	Type        string `json:"type"`
	UpdatedUser User   `json:"user"`
}

// send Event to Slack
func (p *Processor) sendEvent(eventType string, channel string, text string) error {
	p.sequence++

	response := &event{Id: p.sequence, Type: eventType, Channel: channel, Text: text}

	responseJson, err := json.Marshal(response)
	if err != nil {
		return err
	}

	p.con.Write(responseJson)

	return nil
}

// Write the message on the specified channel to Slack
func (p *Processor) Write(channel string, text string) error {
	for len(text) > 0 {
		if len(text) <= maxMessageSize {
			if err := p.sendEvent(slackEventTypeMessage, channel, text); err != nil {
				return err
			}
			text = ""
		} else {
			// split message at a convenient place
			maxSizeChunk := text[:maxMessageSize]

			var breakIndex int
			if lastLineBreak := strings.LastIndex(maxSizeChunk, "\n"); lastLineBreak > -1 {
				breakIndex = lastLineBreak
			} else if lastWordBreak := strings.LastIndexAny(maxSizeChunk, "\n\t .,/\\-(){}[]|=+*&"); lastWordBreak > -1 {
				breakIndex = lastWordBreak
			} else {
				breakIndex = maxMessageSize
			}

			if err := p.sendEvent(slackEventTypeMessage, channel, text[:breakIndex]); err != nil {
				return err
			}

			if breakIndex != maxMessageSize {
				breakIndex++
			}

			text = text[breakIndex:]
		}
	}

	return nil
}

// Start processing events from Slack
func (p *Processor) Start() {
	for {
		msg := p.con.Read()

		log.Printf("%s", msg)

		var data map[string]interface{}
		err := json.Unmarshal(msg, &data)

		if err != nil {
			fmt.Printf("%T\n%s\n%#v\n", err, err, err)
			switch v := err.(type) {
			case *json.SyntaxError:
				fmt.Println(string(msg[v.Offset-40 : v.Offset]))
			}
			log.Printf("%s", msg)
			continue
		}

		// if reply_to attribute is present the event is an ack' for a sent message
		_, isReply := data["reply_to"]
		subtype, ok := data["subtype"]
		var isMessageChangedEvent bool

		//2015/05/20 02:09:37 {"text":null,"username":"Pingdom","bot_id":"B040BJ6NU","atta
		//chments":[{"title":"Broker Portal is down (Incident #16)","text":"<http://broker
		//.markelinternational.com|broker.markelinternational.com>  <https://my.pingdom.co
		//m/|View details>","fallback":"Broker Portal is down (Incident 16)","color":"FF4D
		//46"}],"type":"message","subtype":"bot_message","channel":"C030U0FGZ","ts":"14320
		//84180.000054"}
		//panic: interface conversion: interface is nil, not string

		if ok {
			isMessageChangedEvent = (subtype.(string) == "message_changed" || subtype.(string) == "message_deleted")
		}

		if !isReply && !isMessageChangedEvent {
			handler, ok := p.eventHandlers[data["type"].(string)]

			if ok {
				handler(p, data, msg)
			}
		}
	}
}

// updateUser updates or adds (if not already existing) the specifed user
func (p *Processor) updateUser(user User) {
	p.users[user.Id] = user
}

// onConnected is a callback for when the client connects (or reconnects) to Slack.
func (p *Processor) onConnected(con *Connection) {
	p.self = con.config.Self
	log.Printf("Connected to Slack as %s", p.self.Name)

	p.users = make(map[string]User)
	for _, user := range con.config.Users {
		p.updateUser(user)
	}
}

// type for callbacks to receive messages from Slack
type messageProcessor func(*Message)

// Starts processing events on the connection from Slack and passes any messages to the hear callback and only
// messages addressed to the bot to the respond callback
func EventProcessor(con *Connection, respond messageProcessor, hear messageProcessor) {
	p := Processor{
		con:  con,
		self: con.config.Self,
		eventHandlers: map[string]func(*Processor, map[string]interface{}, []byte){
			slackEventTypeMessage: func(p *Processor, event map[string]interface{}, rawEvent []byte) {
				filterMessage(p, event, respond, hear)
			},
			"user_change": func(p *Processor, event map[string]interface{}, rawEvent []byte) {
				var userEvent userChangeEvent
				err := json.Unmarshal(rawEvent, &userEvent)

				if err != nil {
					fmt.Printf("%T\n%s\n%#v\n", err, err, err)
					switch v := err.(type) {
					case *json.SyntaxError:
						fmt.Println(string(rawEvent[v.Offset-40 : v.Offset]))
					}
					log.Printf("%s", rawEvent)
				}
				p.updateUser(userEvent.UpdatedUser)
			},
			"hello": func(p *Processor, event map[string]interface{}, rawEvent []byte) {
				p.onConnected(con)
			},
			"error": func(p *Processor, event map[string]interface{}, rawEvent []byte) {
				log.Printf("Error received from Slack: %s", rawEvent)
			},
		},
		users: make(map[string]User),
	}

	p.Start()
}

// Invoke one of the specified callbacks for the message if appropriate
func filterMessage(p *Processor, data map[string]interface{}, respond messageProcessor, hear messageProcessor) {
	var userFullName string
	var userId string

	user, ok := data["user"]
	if ok {
		userId = user.(string)
		user, exists := p.users[userId]
		if exists {
			userFullName = user.RealName
		}
	}

	// process messages directed at Talbot
	r, _ := regexp.Compile("^(<@" + p.self.Id + ">|@?" + p.self.Name + "):? (.+)")

	text, ok := data["text"]
	if !ok {
		return
	}

	matches := r.FindStringSubmatch(text.(string))

	if len(matches) == 3 {
		if respond != nil {
			m := &Message{eventStream: p, responseStrategy: reply, Text: matches[2], From: userFullName, fromId: userId, channel: data["channel"].(string)}
			respond(m)
		}
	} else if data["channel"].(string)[0] == 'D' {
		if respond != nil {
			// process direct messages
			m := &Message{eventStream: p, responseStrategy: send, Text: text.(string), From: userFullName, fromId: userId, channel: data["channel"].(string)}
			respond(m)
		}
	} else {
		if hear != nil {
			m := &Message{eventStream: p, responseStrategy: send, Text: text.(string), From: userFullName, fromId: userId, channel: data["channel"].(string)}
			hear(m)
		}
	}
}
<|endoftext|>


<commit_before>package filelib

import "testing"

func Test_Exists(t *testing.T) {
	if Exists("./no-such-file.do-not-create") {
		t.Errorf("Expected false, file should not exist\n")
	}
	if !Exists("./test_data") {
		t.Errorf("Expected true, check of directory\n")
	}
	if !Exists("./test_data/file-exists") {
		t.Errorf("Expected true, check of directory\n")
	}
}
<commit_msg>fixed testing<commit_after>package filelib

import (
	"io/ioutil"
	"os"
	"testing"
)

func Test_Exists(t *testing.T) {

	os.Mkdir("./test_data", 0700)
	err := ioutil.WriteFile("./test_data/file-exists", []byte("bob\n"), 0600)
	if err != nil {
		t.Errorf("Unable to setup test file, ./test_data/file-exists")
	}

	if Exists("./no-such-file.do-not-create") {
		t.Errorf("Expected false, file should not exist\n")
	}
	if !Exists("./test_data") {
		t.Errorf("Expected true, check of directory\n")
	}
	if !Exists("./test_data/file-exists") {
		t.Errorf("Expected true, check of directory\n")
	}
}
<|endoftext|>


<commit_before>package filer2

import (
	"context"
	"fmt"
	"os"
	"path/filepath"
	"strings"
	"time"

	"github.com/chrislusf/seaweedfs/weed/glog"
	"github.com/chrislusf/seaweedfs/weed/operation"
	"github.com/chrislusf/seaweedfs/weed/pb/filer_pb"
	"github.com/chrislusf/seaweedfs/weed/wdclient"
	"github.com/karlseguin/ccache"
)

type Filer struct {
	store          FilerStore
	directoryCache *ccache.Cache
	MasterClient   *wdclient.MasterClient
}

func NewFiler(masters []string) *Filer {
	return &Filer{
		directoryCache: ccache.New(ccache.Configure().MaxSize(1000).ItemsToPrune(100)),
		MasterClient:   wdclient.NewMasterClient(context.Background(), "filer", masters),
	}
}

func (f *Filer) SetStore(store FilerStore) {
	f.store = store
}

func (f *Filer) DisableDirectoryCache() {
	f.directoryCache = nil
}

func (fs *Filer) GetMaster() string {
	return fs.MasterClient.GetMaster()
}

func (fs *Filer) KeepConnectedToMaster() {
	fs.MasterClient.KeepConnectedToMaster()
}

func (f *Filer) CreateEntry(entry *Entry) error {

	dirParts := strings.Split(string(entry.FullPath), "/")

	// fmt.Printf("directory parts: %+v\n", dirParts)

	var lastDirectoryEntry *Entry

	for i := 1; i < len(dirParts); i++ {
		dirPath := "/" + filepath.Join(dirParts[:i]...)
		// fmt.Printf("%d directory: %+v\n", i, dirPath)

		// first check local cache
		dirEntry := f.cacheGetDirectory(dirPath)

		// not found, check the store directly
		if dirEntry == nil {
			glog.V(4).Infof("find uncached directory: %s", dirPath)
			dirEntry, _ = f.FindEntry(FullPath(dirPath))
		} else {
			glog.V(4).Infof("found cached directory: %s", dirPath)
		}

		// no such existing directory
		if dirEntry == nil {

			// create the directory
			now := time.Now()

			dirEntry = &Entry{
				FullPath: FullPath(dirPath),
				Attr: Attr{
					Mtime:  now,
					Crtime: now,
					Mode:   os.ModeDir | 0770,
					Uid:    entry.Uid,
					Gid:    entry.Gid,
				},
			}

			glog.V(2).Infof("create directory: %s %v", dirPath, dirEntry.Mode)
			mkdirErr := f.store.InsertEntry(dirEntry)
			if mkdirErr != nil {
				return fmt.Errorf("mkdir %s: %v", dirPath, mkdirErr)
			}
		} else if !dirEntry.IsDirectory() {
			return fmt.Errorf("%s is a file", dirPath)
		}

		// cache the directory entry
		f.cacheSetDirectory(dirPath, dirEntry, i)

		// remember the direct parent directory entry
		if i == len(dirParts)-1 {
			lastDirectoryEntry = dirEntry
		}

	}

	if lastDirectoryEntry == nil {
		return fmt.Errorf("parent folder not found: %v", entry.FullPath)
	}

	/*
		if !hasWritePermission(lastDirectoryEntry, entry) {
			glog.V(0).Infof("directory %s: %v, entry: uid=%d gid=%d",
				lastDirectoryEntry.FullPath, lastDirectoryEntry.Attr, entry.Uid, entry.Gid)
			return fmt.Errorf("no write permission in folder %v", lastDirectoryEntry.FullPath)
		}
	*/

	oldEntry, _ := f.FindEntry(entry.FullPath)

	if err := f.store.InsertEntry(entry); err != nil {
		return fmt.Errorf("insert entry %s: %v", entry.FullPath, err)
	}

	f.deleteChunksIfNotNew(oldEntry, entry)

	return nil
}

func (f *Filer) UpdateEntry(entry *Entry) (err error) {
	return f.store.UpdateEntry(entry)
}

func (f *Filer) FindEntry(p FullPath) (entry *Entry, err error) {
	return f.store.FindEntry(p)
}

func (f *Filer) DeleteEntryMetaAndData(p FullPath, isRecursive bool, shouldDeleteChunks bool) (err error) {
	entry, err := f.FindEntry(p)
	if err != nil {
		return err
	}

	if entry.IsDirectory() {
		entries, err := f.ListDirectoryEntries(p, "", false, 1)
		if err != nil {
			return fmt.Errorf("list folder %s: %v", p, err)
		}
		if isRecursive {
			for _, sub := range entries {
				f.DeleteEntryMetaAndData(sub.FullPath, isRecursive, shouldDeleteChunks)
			}
		} else {
			if len(entries) > 0 {
				return fmt.Errorf("folder %s is not empty", p)
			}
		}
		f.cacheDelDirectory(string(p))
	}

	if shouldDeleteChunks {
		f.deleteChunks(entry.Chunks)
	}

	return f.store.DeleteEntry(p)
}

func (f *Filer) ListDirectoryEntries(p FullPath, startFileName string, inclusive bool, limit int) ([]*Entry, error) {
	if strings.HasSuffix(string(p), "/") && len(p) > 1 {
		p = p[0 : len(p)-1]
	}
	return f.store.ListDirectoryEntries(p, startFileName, inclusive, limit)
}

func (f *Filer) cacheDelDirectory(dirpath string) {
	if f.directoryCache == nil {
		return
	}
	f.directoryCache.Delete(dirpath)
	return
}

func (f *Filer) cacheGetDirectory(dirpath string) *Entry {
	if f.directoryCache == nil {
		return nil
	}
	item := f.directoryCache.Get(dirpath)
	if item == nil {
		return nil
	}
	return item.Value().(*Entry)
}

func (f *Filer) cacheSetDirectory(dirpath string, dirEntry *Entry, level int) {

	if f.directoryCache == nil {
		return
	}

	minutes := 60
	if level < 10 {
		minutes -= level * 6
	}

	f.directoryCache.Set(dirpath, dirEntry, time.Duration(minutes)*time.Minute)
}

func (f *Filer) deleteChunks(chunks []*filer_pb.FileChunk) {
	for _, chunk := range chunks {
		f.DeleteFileByFileId(chunk.FileId)
	}
}

func (f *Filer) DeleteFileByFileId(fileId string) {
	fileUrlOnVolume, err := f.MasterClient.LookupFileId(fileId)
	if err != nil {
		glog.V(0).Infof("can not find file %s: %v", fileId, err)
	}
	if err := operation.DeleteFromVolumeServer(fileUrlOnVolume, ""); err != nil {
		glog.V(0).Infof("deleting file %s: %v", fileId, err)
	}
}

func (f *Filer) deleteChunksIfNotNew(oldEntry, newEntry *Entry) {

	if oldEntry == nil {
		return
	}
	if newEntry == nil {
		f.deleteChunks(oldEntry.Chunks)
	}

	var toDelete []*filer_pb.FileChunk

	for _, oldChunk := range oldEntry.Chunks {
		found := false
		for _, newChunk := range newEntry.Chunks {
			if oldChunk.FileId == newChunk.FileId {
				found = true
				break
			}
		}
		if !found {
			toDelete = append(toDelete, oldChunk)
		}
	}
	f.deleteChunks(toDelete)
}
<commit_msg>correctly recursively delete folders<commit_after>package filer2

import (
	"context"
	"fmt"
	"os"
	"path/filepath"
	"strings"
	"time"

	"github.com/chrislusf/seaweedfs/weed/glog"
	"github.com/chrislusf/seaweedfs/weed/operation"
	"github.com/chrislusf/seaweedfs/weed/pb/filer_pb"
	"github.com/chrislusf/seaweedfs/weed/wdclient"
	"github.com/karlseguin/ccache"
	"math"
)

type Filer struct {
	store          FilerStore
	directoryCache *ccache.Cache
	MasterClient   *wdclient.MasterClient
}

func NewFiler(masters []string) *Filer {
	return &Filer{
		directoryCache: ccache.New(ccache.Configure().MaxSize(1000).ItemsToPrune(100)),
		MasterClient:   wdclient.NewMasterClient(context.Background(), "filer", masters),
	}
}

func (f *Filer) SetStore(store FilerStore) {
	f.store = store
}

func (f *Filer) DisableDirectoryCache() {
	f.directoryCache = nil
}

func (fs *Filer) GetMaster() string {
	return fs.MasterClient.GetMaster()
}

func (fs *Filer) KeepConnectedToMaster() {
	fs.MasterClient.KeepConnectedToMaster()
}

func (f *Filer) CreateEntry(entry *Entry) error {

	dirParts := strings.Split(string(entry.FullPath), "/")

	// fmt.Printf("directory parts: %+v\n", dirParts)

	var lastDirectoryEntry *Entry

	for i := 1; i < len(dirParts); i++ {
		dirPath := "/" + filepath.Join(dirParts[:i]...)
		// fmt.Printf("%d directory: %+v\n", i, dirPath)

		// first check local cache
		dirEntry := f.cacheGetDirectory(dirPath)

		// not found, check the store directly
		if dirEntry == nil {
			glog.V(4).Infof("find uncached directory: %s", dirPath)
			dirEntry, _ = f.FindEntry(FullPath(dirPath))
		} else {
			glog.V(4).Infof("found cached directory: %s", dirPath)
		}

		// no such existing directory
		if dirEntry == nil {

			// create the directory
			now := time.Now()

			dirEntry = &Entry{
				FullPath: FullPath(dirPath),
				Attr: Attr{
					Mtime:  now,
					Crtime: now,
					Mode:   os.ModeDir | 0770,
					Uid:    entry.Uid,
					Gid:    entry.Gid,
				},
			}

			glog.V(2).Infof("create directory: %s %v", dirPath, dirEntry.Mode)
			mkdirErr := f.store.InsertEntry(dirEntry)
			if mkdirErr != nil {
				return fmt.Errorf("mkdir %s: %v", dirPath, mkdirErr)
			}
		} else if !dirEntry.IsDirectory() {
			return fmt.Errorf("%s is a file", dirPath)
		}

		// cache the directory entry
		f.cacheSetDirectory(dirPath, dirEntry, i)

		// remember the direct parent directory entry
		if i == len(dirParts)-1 {
			lastDirectoryEntry = dirEntry
		}

	}

	if lastDirectoryEntry == nil {
		return fmt.Errorf("parent folder not found: %v", entry.FullPath)
	}

	/*
		if !hasWritePermission(lastDirectoryEntry, entry) {
			glog.V(0).Infof("directory %s: %v, entry: uid=%d gid=%d",
				lastDirectoryEntry.FullPath, lastDirectoryEntry.Attr, entry.Uid, entry.Gid)
			return fmt.Errorf("no write permission in folder %v", lastDirectoryEntry.FullPath)
		}
	*/

	oldEntry, _ := f.FindEntry(entry.FullPath)

	if err := f.store.InsertEntry(entry); err != nil {
		return fmt.Errorf("insert entry %s: %v", entry.FullPath, err)
	}

	f.deleteChunksIfNotNew(oldEntry, entry)

	return nil
}

func (f *Filer) UpdateEntry(entry *Entry) (err error) {
	return f.store.UpdateEntry(entry)
}

func (f *Filer) FindEntry(p FullPath) (entry *Entry, err error) {
	return f.store.FindEntry(p)
}

func (f *Filer) DeleteEntryMetaAndData(p FullPath, isRecursive bool, shouldDeleteChunks bool) (err error) {
	entry, err := f.FindEntry(p)
	if err != nil {
		return err
	}

	if entry.IsDirectory() {
		limit := int(1)
		if isRecursive {
			limit = math.MaxInt32
		}
		entries, err := f.ListDirectoryEntries(p, "", false, limit)
		if err != nil {
			return fmt.Errorf("list folder %s: %v", p, err)
		}
		if isRecursive {
			for _, sub := range entries {
				f.DeleteEntryMetaAndData(sub.FullPath, isRecursive, shouldDeleteChunks)
			}
		} else {
			if len(entries) > 0 {
				return fmt.Errorf("folder %s is not empty", p)
			}
		}
		f.cacheDelDirectory(string(p))
	}

	if shouldDeleteChunks {
		f.deleteChunks(entry.Chunks)
	}

	if p == "/" {
		return nil
	}
	glog.V(0).Infof("deleting entry %v", p)
	return f.store.DeleteEntry(p)
}

func (f *Filer) ListDirectoryEntries(p FullPath, startFileName string, inclusive bool, limit int) ([]*Entry, error) {
	if strings.HasSuffix(string(p), "/") && len(p) > 1 {
		p = p[0 : len(p)-1]
	}
	return f.store.ListDirectoryEntries(p, startFileName, inclusive, limit)
}

func (f *Filer) cacheDelDirectory(dirpath string) {
	if f.directoryCache == nil {
		return
	}
	f.directoryCache.Delete(dirpath)
	return
}

func (f *Filer) cacheGetDirectory(dirpath string) *Entry {
	if f.directoryCache == nil {
		return nil
	}
	item := f.directoryCache.Get(dirpath)
	if item == nil {
		return nil
	}
	return item.Value().(*Entry)
}

func (f *Filer) cacheSetDirectory(dirpath string, dirEntry *Entry, level int) {

	if f.directoryCache == nil {
		return
	}

	minutes := 60
	if level < 10 {
		minutes -= level * 6
	}

	f.directoryCache.Set(dirpath, dirEntry, time.Duration(minutes)*time.Minute)
}

func (f *Filer) deleteChunks(chunks []*filer_pb.FileChunk) {
	for _, chunk := range chunks {
		f.DeleteFileByFileId(chunk.FileId)
	}
}

func (f *Filer) DeleteFileByFileId(fileId string) {
	fileUrlOnVolume, err := f.MasterClient.LookupFileId(fileId)
	if err != nil {
		glog.V(0).Infof("can not find file %s: %v", fileId, err)
	}
	if err := operation.DeleteFromVolumeServer(fileUrlOnVolume, ""); err != nil {
		glog.V(0).Infof("deleting file %s: %v", fileId, err)
	}
}

func (f *Filer) deleteChunksIfNotNew(oldEntry, newEntry *Entry) {

	if oldEntry == nil {
		return
	}
	if newEntry == nil {
		f.deleteChunks(oldEntry.Chunks)
	}

	var toDelete []*filer_pb.FileChunk

	for _, oldChunk := range oldEntry.Chunks {
		found := false
		for _, newChunk := range newEntry.Chunks {
			if oldChunk.FileId == newChunk.FileId {
				found = true
				break
			}
		}
		if !found {
			toDelete = append(toDelete, oldChunk)
		}
	}
	f.deleteChunks(toDelete)
}
<|endoftext|>


<commit_before>package security

import (
	"crypto/tls"
	"crypto/x509"
	"github.com/spf13/viper"
	"io/ioutil"

	"github.com/chrislusf/seaweedfs/weed/glog"
	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials"
)

func LoadServerTLS(config *viper.Viper, component string) grpc.ServerOption {
	if config == nil {
		return nil
	}

	// load cert/key, ca cert
	cert, err := tls.LoadX509KeyPair(config.GetString(component+".cert"), config.GetString(component+".key"))
	if err != nil {
		glog.Errorf("load cert/key error: %v", err)
		return nil
	}
	caCert, err := ioutil.ReadFile(config.GetString(component + ".ca"))
	if err != nil {
		glog.Errorf("read ca cert file error: %v", err)
		return nil
	}
	caCertPool := x509.NewCertPool()
	caCertPool.AppendCertsFromPEM(caCert)
	ta := credentials.NewTLS(&tls.Config{
		Certificates: []tls.Certificate{cert},
		ClientCAs:    caCertPool,
		ClientAuth:   tls.RequireAndVerifyClientCert,
	})

	return grpc.Creds(ta)
}

func LoadClientTLS(config *viper.Viper, component string) grpc.DialOption {
	if config == nil {
		return grpc.WithInsecure()
	}

	// load cert/key, cacert
	cert, err := tls.LoadX509KeyPair(config.GetString(component+".cert"), config.GetString(component+".key"))
	if err != nil {
		glog.Errorf("load cert/key error: %v", err)
		return grpc.WithInsecure()
	}
	caCert, err := ioutil.ReadFile(config.GetString(component + ".ca"))
	if err != nil {
		glog.Errorf("read ca cert file error: %v", err)
		return grpc.WithInsecure()
	}
	caCertPool := x509.NewCertPool()
	caCertPool.AppendCertsFromPEM(caCert)

	ta := credentials.NewTLS(&tls.Config{
		Certificates:       []tls.Certificate{cert},
		RootCAs:            caCertPool,
		InsecureSkipVerify: true,
	})
	return grpc.WithTransportCredentials(ta)
}
<commit_msg>adjust log level<commit_after>package security

import (
	"crypto/tls"
	"crypto/x509"
	"io/ioutil"

	"github.com/spf13/viper"

	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials"

	"github.com/chrislusf/seaweedfs/weed/glog"
)

func LoadServerTLS(config *viper.Viper, component string) grpc.ServerOption {
	if config == nil {
		return nil
	}

	// load cert/key, ca cert
	cert, err := tls.LoadX509KeyPair(config.GetString(component+".cert"), config.GetString(component+".key"))
	if err != nil {
		glog.V(1).Infof("load cert/key error: %v", err)
		return nil
	}
	caCert, err := ioutil.ReadFile(config.GetString(component + ".ca"))
	if err != nil {
		glog.V(1).Infof("read ca cert file error: %v", err)
		return nil
	}
	caCertPool := x509.NewCertPool()
	caCertPool.AppendCertsFromPEM(caCert)
	ta := credentials.NewTLS(&tls.Config{
		Certificates: []tls.Certificate{cert},
		ClientCAs:    caCertPool,
		ClientAuth:   tls.RequireAndVerifyClientCert,
	})

	return grpc.Creds(ta)
}

func LoadClientTLS(config *viper.Viper, component string) grpc.DialOption {
	if config == nil {
		return grpc.WithInsecure()
	}

	// load cert/key, cacert
	cert, err := tls.LoadX509KeyPair(config.GetString(component+".cert"), config.GetString(component+".key"))
	if err != nil {
		glog.V(1).Infof("load cert/key error: %v", err)
		return grpc.WithInsecure()
	}
	caCert, err := ioutil.ReadFile(config.GetString(component + ".ca"))
	if err != nil {
		glog.V(1).Infof("read ca cert file error: %v", err)
		return grpc.WithInsecure()
	}
	caCertPool := x509.NewCertPool()
	caCertPool.AppendCertsFromPEM(caCert)

	ta := credentials.NewTLS(&tls.Config{
		Certificates:       []tls.Certificate{cert},
		RootCAs:            caCertPool,
		InsecureSkipVerify: true,
	})
	return grpc.WithTransportCredentials(ta)
}
<|endoftext|>


<commit_before>// Copyright 2015 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 scanner_test

import (
	"fmt"
	"strings"
	"text/scanner"
)

func Example() {
	const src = `
	// This is scanned code.
	if a > 10 {
		someParsable = text
	}`
	var s scanner.Scanner
	s.Filename = "example"
	s.Init(strings.NewReader(src))
	var tok rune
	for tok != scanner.EOF {
		tok = s.Scan()
		fmt.Println("At position", s.Pos(), ":", s.TokenText())
	}

	// Output:
	// At position example:3:4 : if
	// At position example:3:6 : a
	// At position example:3:8 : >
	// At position example:3:11 : 10
	// At position example:3:13 : {
	// At position example:4:15 : someParsable
	// At position example:4:17 : =
	// At position example:4:22 : text
	// At position example:5:3 : }
	// At position example:5:3 :
}
<commit_msg>text/scanner: use correct token position in example<commit_after>// Copyright 2015 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 scanner_test

import (
	"fmt"
	"strings"
	"text/scanner"
)

func Example() {
	const src = `
// This is scanned code.
if a > 10 {
	someParsable = text
}`
	var s scanner.Scanner
	s.Init(strings.NewReader(src))
	s.Filename = "example"
	for tok := s.Scan(); tok != scanner.EOF; tok = s.Scan() {
		fmt.Printf("%s: %s\n", s.Position, s.TokenText())
	}

	// Output:
	// example:3:1: if
	// example:3:4: a
	// example:3:6: >
	// example:3:8: 10
	// example:3:11: {
	// example:4:2: someParsable
	// example:4:15: =
	// example:4:17: text
	// example:5:1: }
}
<|endoftext|>


<commit_before>/*
 * Modern Copy, (C) 2014,2015 Minio, Inc.
 *
 * 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 main

import (
	"io"

	"github.com/cheggaaa/pb"
	"github.com/minio-io/cli"
	"github.com/minio-io/mc/pkg/console"
	"github.com/minio-io/minio/pkg/iodine"
	"github.com/minio-io/minio/pkg/utils/log"
)

func getSourceReader(sourceURLParser *parsedURL) (reader io.ReadCloser, length int64, md5hex string, err error) {
	sourceClnt, err := getNewClient(sourceURLParser, globalDebugFlag)
	if err != nil {
		return nil, 0, "", iodine.New(err, map[string]string{"sourceURL": sourceURLParser.String()})
	}
	// Get a reader for the source object
	sourceBucket := sourceURLParser.bucketName
	// check if the bucket is valid
	if err := sourceClnt.StatBucket(sourceBucket); err != nil {
		return nil, 0, "", iodine.New(err, map[string]string{"sourceURL": sourceURLParser.String()})
	}
	sourceObject := sourceURLParser.objectName
	return sourceClnt.Get(sourceBucket, sourceObject)
}

func getTargetWriter(targetURLParser *parsedURL, md5Hex string, length int64) (io.WriteCloser, error) {
	targetClnt, err := getNewClient(targetURLParser, globalDebugFlag)
	if err != nil {
		return nil, iodine.New(err, map[string]string{"failedURL": targetURLParser.String()})
	}
	targetBucket := targetURLParser.bucketName
	// check if bucket is valid
	if err := targetClnt.StatBucket(targetBucket); err != nil {
		return nil, iodine.New(err, map[string]string{"failedURL": targetURLParser.String()})
	}
	targetObject := targetURLParser.objectName
	return targetClnt.Put(targetBucket, targetObject, md5Hex, length)
}

func getTargetWriters(targetURLParsers []*parsedURL, md5Hex string, length int64) ([]io.WriteCloser, error) {
	var targetWriters []io.WriteCloser
	for _, targetURLParser := range targetURLParsers {
		writer, err := getTargetWriter(targetURLParser, md5Hex, length)
		if err != nil {
			// close all writers
			for _, targetWriter := range targetWriters {
				targetWriter.Close()
			}
			return nil, iodine.New(err, map[string]string{"failedURL": targetURLParser.String()})
		}
		targetWriters = append(targetWriters, writer)
	}
	return targetWriters, nil
}

// doCopyCmd copies objects into and from a bucket or between buckets
func runCopyCmd(ctx *cli.Context) {
	if len(ctx.Args()) < 2 {
		cli.ShowCommandHelpAndExit(ctx, "cp", 1) // last argument is exit code
	}

	// Convert arguments to URLs: expand alias, fix format...
	urls, err := parseURLs(ctx)
	if err != nil {
		log.Debug.Println(iodine.New(err, nil))
		console.Fatalln("mc: Unable to parse URL")
	}
	sourceURL := urls[0]   // First arg is source
	targetURLs := urls[1:] // 1 or more targets

	// perform copy
	if ctx.Bool("recursive") {
		doCopyCmdRecursive(ctx)
	} else {
		doCopyCmd(ctx, sourceURL, targetURLs)
	}
}

func doCopyCmd(ctx *cli.Context, sourceURL *parsedURL, targetURLs []*parsedURL) {
	reader, length, hexMd5, err := getSourceReader(sourceURL)
	if err != nil {
		log.Debug.Println(iodine.New(err, nil))
		console.Fatalln("mc: Unable to read source")
	}

	writeClosers, err := getTargetWriters(targetURLs, hexMd5, length)
	if err != nil {
		log.Debug.Println(iodine.New(err, nil))
		console.Fatalln("mc: Unable to open targets for writing")
	}

	var writers []io.Writer
	for _, writer := range writeClosers {
		writers = append(writers, writer)
	}

	// set up progress bar
	var bar *pb.ProgressBar
	if !globalQuietFlag {
		bar = startBar(length)
		bar.Start()
		writers = append(writers, bar)
	}

	// write progress bar
	multiWriter := io.MultiWriter(writers...)

	// copy data to writers
	_, err = io.CopyN(multiWriter, reader, length)

	// close writers
	for _, writer := range writeClosers {
		err := writer.Close()
		if err != nil {
			log.Debug.Println(iodine.New(err, nil))
			console.Errorln("mc: Unable to close writer, object may not of written properly.")
		}
	}
	if err != nil {
		log.Debug.Println(iodine.New(err, nil))
		console.Fatalln("mc: Unable to write to target")
	}
}
<commit_msg>Wrapping client calls around a client manager to facilitate testing<commit_after>/*
 * Modern Copy, (C) 2014,2015 Minio, Inc.
 *
 * 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 main

import (
	"io"

	"github.com/cheggaaa/pb"
	"github.com/minio-io/cli"
	"github.com/minio-io/mc/pkg/console"
	"github.com/minio-io/minio/pkg/iodine"
	"github.com/minio-io/minio/pkg/utils/log"
)

type clientManager interface {
	getSourceReader(sourceURLParser *parsedURL) (reader io.ReadCloser, length int64, md5hex string, err error)
	getTargetWriter(targetURLParser *parsedURL, md5Hex string, length int64) (io.WriteCloser, error)
}

type mcClientManager struct{}

func (manager mcClientManager) getSourceReader(sourceURLParser *parsedURL) (reader io.ReadCloser, length int64, md5hex string, err error) {
	sourceClnt, err := getNewClient(sourceURLParser, globalDebugFlag)
	if err != nil {
		return nil, 0, "", iodine.New(err, map[string]string{"sourceURL": sourceURLParser.String()})
	}
	// Get a reader for the source object
	sourceBucket := sourceURLParser.bucketName
	// check if the bucket is valid
	if err := sourceClnt.StatBucket(sourceBucket); err != nil {
		return nil, 0, "", iodine.New(err, map[string]string{"sourceURL": sourceURLParser.String()})
	}
	sourceObject := sourceURLParser.objectName
	return sourceClnt.Get(sourceBucket, sourceObject)
}

func (manager mcClientManager) getTargetWriter(targetURLParser *parsedURL, md5Hex string, length int64) (io.WriteCloser, error) {
	targetClnt, err := getNewClient(targetURLParser, globalDebugFlag)
	if err != nil {
		return nil, iodine.New(err, map[string]string{"failedURL": targetURLParser.String()})
	}
	targetBucket := targetURLParser.bucketName
	// check if bucket is valid
	if err := targetClnt.StatBucket(targetBucket); err != nil {
		return nil, iodine.New(err, map[string]string{"failedURL": targetURLParser.String()})
	}
	targetObject := targetURLParser.objectName
	return targetClnt.Put(targetBucket, targetObject, md5Hex, length)
}

func getTargetWriters(manager clientManager, targetURLParsers []*parsedURL, md5Hex string, length int64) ([]io.WriteCloser, error) {
	var targetWriters []io.WriteCloser
	for _, targetURLParser := range targetURLParsers {
		writer, err := manager.getTargetWriter(targetURLParser, md5Hex, length)
		if err != nil {
			// close all writers
			for _, targetWriter := range targetWriters {
				targetWriter.Close()
			}
			return nil, iodine.New(err, map[string]string{"failedURL": targetURLParser.String()})
		}
		targetWriters = append(targetWriters, writer)
	}
	return targetWriters, nil
}

// doCopyCmd copies objects into and from a bucket or between buckets
func runCopyCmd(ctx *cli.Context) {
	if len(ctx.Args()) < 2 {
		cli.ShowCommandHelpAndExit(ctx, "cp", 1) // last argument is exit code
	}

	// Convert arguments to URLs: expand alias, fix format...
	urls, err := parseURLs(ctx)
	if err != nil {
		log.Debug.Println(iodine.New(err, nil))
		console.Fatalln("mc: Unable to parse URL")
	}
	sourceURL := urls[0]   // First arg is source
	targetURLs := urls[1:] // 1 or more targets

	// perform copy
	if ctx.Bool("recursive") {
		doCopyCmdRecursive(ctx)
	} else {
		doCopyCmd(mcClientManager{}, ctx, sourceURL, targetURLs)
	}
}

func doCopyCmd(manager clientManager, ctx *cli.Context, sourceURL *parsedURL, targetURLs []*parsedURL) {
	reader, length, hexMd5, err := manager.getSourceReader(sourceURL)
	if err != nil {
		log.Debug.Println(iodine.New(err, nil))
		console.Fatalln("mc: Unable to read source")
	}

	writeClosers, err := getTargetWriters(manager, targetURLs, hexMd5, length)
	if err != nil {
		log.Debug.Println(iodine.New(err, nil))
		console.Fatalln("mc: Unable to open targets for writing")
	}

	var writers []io.Writer
	for _, writer := range writeClosers {
		writers = append(writers, writer)
	}

	// set up progress bar
	var bar *pb.ProgressBar
	if !globalQuietFlag {
		bar = startBar(length)
		bar.Start()
		writers = append(writers, bar)
	}

	// write progress bar
	multiWriter := io.MultiWriter(writers...)

	// copy data to writers
	_, err = io.CopyN(multiWriter, reader, length)

	// close writers
	for _, writer := range writeClosers {
		err := writer.Close()
		if err != nil {
			log.Debug.Println(iodine.New(err, nil))
			console.Errorln("mc: Unable to close writer, object may not of written properly.")
		}
	}
	if err != nil {
		log.Debug.Println(iodine.New(err, nil))
		console.Fatalln("mc: Unable to write to target")
	}
}
<|endoftext|>


<commit_before>/*
 * Minio Client (C) 2014, 2015 Minio, Inc.
 *
 * 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 main

import (
	"errors"
	"fmt"
	"runtime"
	"sync"

	"github.com/minio/cli"
	"github.com/minio/mc/pkg/console"
	"github.com/minio/minio/pkg/iodine"
)

// doCopy - Copy a singe file from source to destination
func doCopy(sourceURL string, sourceConfig *hostConfig, targetURL string, targetConfig *hostConfig, bar *barSend) error {
	reader, length, err := getSource(sourceURL, sourceConfig)
	if err != nil {
		return iodine.New(err, nil)
	}
	switch globalQuietFlag {
	case true:
		console.Infoln(fmt.Sprintf("‘%s’ -> ‘%s’", sourceURL, targetURL))
	default:
		// set up progress
		reader = bar.NewProxyReader(reader)
	}
	err = putTarget(targetURL, targetConfig, length, reader)
	if err != nil {
		return iodine.New(err, nil)
	}

	return nil
}

// args2URLs extracts source and target URLs from command-line args.
func args2URLs(args cli.Args) ([]string, error) {
	config, err := getMcConfig()
	if err != nil {
		return nil, iodine.New(err, nil)
	}
	// Convert arguments to URLs: expand alias, fix format...
	URLs, err := getExpandedURLs(args, config.Aliases)
	if err != nil {
		return nil, iodine.New(err, nil)
	}
	return URLs, nil
}

func doCopyInRoutine(cpurls *cpURLs, bar *barSend, cpQueue chan bool, ch chan error, wg *sync.WaitGroup) {
	defer wg.Done()
	srcConfig, err := getHostConfig(cpurls.SourceContent.Name)
	if err != nil {
		ch <- err
		return
	}
	tgtConfig, err := getHostConfig(cpurls.TargetContent.Name)
	if err != nil {
		ch <- err
		return
	}
	if err := doCopy(cpurls.SourceContent.Name, srcConfig, cpurls.TargetContent.Name, tgtConfig, bar); err != nil {
		ch <- err
	}
	<-cpQueue
}

func doCopyCmd(sourceURLs []string, targetURL string, bar barSend) <-chan error {
	ch := make(chan error)
	go func(sourceURLs []string, targetURL string, bar barSend, ch chan error) {
		defer close(ch)
		go func(sourceURLs []string, targetURL string) {
			for cpURLs := range prepareCopyURLs(sourceURLs, targetURL) {
				if cpURLs.Error != nil {
					// no need to print errors here, any error here
					// will be printed later during Copy()
					continue
				}
				if !globalQuietFlag {
					bar.Extend(cpURLs.SourceContent.Size)
				}
			}
		}(sourceURLs, targetURL)

		cpQueue := make(chan bool, intMax(runtime.NumCPU()-1, 1))
		wg := new(sync.WaitGroup)
		for cpURLs := range prepareCopyURLs(sourceURLs, targetURL) {
			if cpURLs.Error != nil {
				ch <- cpURLs.Error
				continue
			}
			cpQueue <- true
			wg.Add(1)
			go doCopyInRoutine(cpURLs, &bar, cpQueue, ch, wg)
		}
		close(cpQueue)
		wg.Wait()
	}(sourceURLs, targetURL, bar, ch)
	return ch
}

// runCopyCmd is bound to sub-command
func runCopyCmd(ctx *cli.Context) {
	if len(ctx.Args()) < 2 || ctx.Args().First() == "help" {
		cli.ShowCommandHelpAndExit(ctx, "cp", 1) // last argument is exit code
	}

	if !isMcConfigExist() {
		console.Fatalln(ErrorMessage{
			Message: "Please run \"mc config generate\"",
			Error:   iodine.New(errors.New("\"mc\" is not configured"), nil),
		})
	}

	// extract URLs.
	URLs, err := args2URLs(ctx.Args())
	if err != nil {
		console.Fatalln(ErrorMessage{
			Message: fmt.Sprintf("Unknown URL types: ‘%s’", URLs),
			Error:   iodine.New(err, nil),
		})
	}

	// Separate source and target. 'cp' can take only one target,
	// but any number of sources, even the recursive URLs mixed in-between.
	sourceURLs := URLs[:len(URLs)-1]
	targetURL := URLs[len(URLs)-1] // Last one is target

	var bar barSend
	// set up progress bar
	if !globalQuietFlag {
		bar = newCpBar()
	}
	for err := range doCopyCmd(sourceURLs, targetURL, bar) {
		if err != nil {
			console.Errorln(ErrorMessage{
				Message: "Failed with",
				Error:   iodine.New(err, nil),
			})
		}
	}
	if !globalQuietFlag {
		bar.Finish()
	}
}
<commit_msg>Handle too many open files, this time during reader() not being closed<commit_after>/*
 * Minio Client (C) 2014, 2015 Minio, Inc.
 *
 * 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 main

import (
	"errors"
	"fmt"
	"io"
	"runtime"
	"sync"

	"github.com/minio/cli"
	"github.com/minio/mc/pkg/console"
	"github.com/minio/minio/pkg/iodine"
)

// doCopy - Copy a singe file from source to destination
func doCopy(sourceURL string, sourceConfig *hostConfig, targetURL string, targetConfig *hostConfig, bar *barSend) error {
	reader, length, err := getSource(sourceURL, sourceConfig)
	if err != nil {
		return iodine.New(err, nil)
	}
	defer reader.Close()
	var newReader io.Reader
	switch globalQuietFlag {
	case true:
		console.Infoln(fmt.Sprintf("‘%s’ -> ‘%s’", sourceURL, targetURL))
	default:
		// set up progress
		newReader = bar.NewProxyReader(reader)
	}
	err = putTarget(targetURL, targetConfig, length, newReader)
	if err != nil {
		return iodine.New(err, nil)
	}
	return nil
}

// args2URLs extracts source and target URLs from command-line args.
func args2URLs(args cli.Args) ([]string, error) {
	config, err := getMcConfig()
	if err != nil {
		return nil, iodine.New(err, nil)
	}
	// Convert arguments to URLs: expand alias, fix format...
	URLs, err := getExpandedURLs(args, config.Aliases)
	if err != nil {
		return nil, iodine.New(err, nil)
	}
	return URLs, nil
}

func doCopyInRoutine(cpurls *cpURLs, bar *barSend, cpQueue chan bool, ch chan error, wg *sync.WaitGroup) {
	defer wg.Done()
	srcConfig, err := getHostConfig(cpurls.SourceContent.Name)
	if err != nil {
		ch <- err
		return
	}
	tgtConfig, err := getHostConfig(cpurls.TargetContent.Name)
	if err != nil {
		ch <- err
		return
	}
	if err := doCopy(cpurls.SourceContent.Name, srcConfig, cpurls.TargetContent.Name, tgtConfig, bar); err != nil {
		ch <- err
	}
	<-cpQueue
}

func doCopyCmd(sourceURLs []string, targetURL string, bar barSend) <-chan error {
	ch := make(chan error)
	go func(sourceURLs []string, targetURL string, bar barSend, ch chan error) {
		defer close(ch)
		go func(sourceURLs []string, targetURL string) {
			for cpURLs := range prepareCopyURLs(sourceURLs, targetURL) {
				if cpURLs.Error != nil {
					// no need to print errors here, any error here
					// will be printed later during Copy()
					continue
				}
				if !globalQuietFlag {
					bar.Extend(cpURLs.SourceContent.Size)
				}
			}
		}(sourceURLs, targetURL)

		cpQueue := make(chan bool, intMax(runtime.NumCPU()-1, 1))
		wg := new(sync.WaitGroup)
		for cpURLs := range prepareCopyURLs(sourceURLs, targetURL) {
			if cpURLs.Error != nil {
				ch <- cpURLs.Error
				continue
			}
			cpQueue <- true
			wg.Add(1)
			go doCopyInRoutine(cpURLs, &bar, cpQueue, ch, wg)
		}
		close(cpQueue)
		wg.Wait()
	}(sourceURLs, targetURL, bar, ch)
	return ch
}

// runCopyCmd is bound to sub-command
func runCopyCmd(ctx *cli.Context) {
	if len(ctx.Args()) < 2 || ctx.Args().First() == "help" {
		cli.ShowCommandHelpAndExit(ctx, "cp", 1) // last argument is exit code
	}

	if !isMcConfigExist() {
		console.Fatalln(ErrorMessage{
			Message: "Please run \"mc config generate\"",
			Error:   iodine.New(errors.New("\"mc\" is not configured"), nil),
		})
	}

	// extract URLs.
	URLs, err := args2URLs(ctx.Args())
	if err != nil {
		console.Fatalln(ErrorMessage{
			Message: fmt.Sprintf("Unknown URL types: ‘%s’", URLs),
			Error:   iodine.New(err, nil),
		})
	}

	// Separate source and target. 'cp' can take only one target,
	// but any number of sources, even the recursive URLs mixed in-between.
	sourceURLs := URLs[:len(URLs)-1]
	targetURL := URLs[len(URLs)-1] // Last one is target

	var bar barSend
	// set up progress bar
	if !globalQuietFlag {
		bar = newCpBar()
	}

	for err := range doCopyCmd(sourceURLs, targetURL, bar) {
		if err != nil {
			console.Errorln(ErrorMessage{
				Message: "Failed with",
				Error:   iodine.New(err, nil),
			})
			bar.Error()
		}
	}

	if !globalQuietFlag {
		bar.Finish()
	}
}
<|endoftext|>


<commit_before>package cmd

import (
	"encoding/json"
	"fmt"
	"github.com/astaxie/beego/logs"
	"github.com/spf13/cobra"
	"net/http"
	"time"
)

const (
	// IP信息查询接口地址
	TAOBAO_IP_QUERY = "http://ip.taobao.com/service/getIpInfo.php"
)

// 接口返回的IP信息
type IpInfo struct {
	Code int    `json:"code"`
	Data IpData `json:"data"`
}

func (this IpInfo) String() string {
	return fmt.Sprintf("%s", this.Data)
}

// ip 具体的信息
type IpData struct {
	Country   string `json:"country"`
	CountryId string `json:"country_id"`
	Area      string `json:"area"`
	AreaId    string `json:"area_id"`
	Region    string `json:"region"`
	RegionId  string `json:"region_id"`
	City      string `json:"city"`
	CityId    string `json:"city_id"`
	County    string `json:"county"`
	CountyId  string `json:"county_id"`
	Isp       string `json:"isp"`
	IspId     string `json:"isp_id"`
	Ip        string `json:"ip"`
}

func (this IpData) String() string {
	return fmt.Sprintf("%s\t%s\t%s\t%s\t%s\t%s",
		this.Country, this.Area, this.Region, this.City, this.County, this.Isp)
}

var ipQueryCmd = &cobra.Command{
	Use:   "ip <Ip1> [<Ip2> [<Ip3> ...]]]",
	Short: "Query the ip information",
	Args:  cobra.MinimumNArgs(1),
	Run:   IpQuery,
}

func init() {
	RootCmd.AddCommand(ipQueryCmd)
}

// 【ip】查询ip的相关信息
func IpQuery(cmd *cobra.Command, params []string) {
	for _, ip := range params {
		url := fmt.Sprintf("%s?ip=%s", TAOBAO_IP_QUERY, ip)
		var ipInfo IpInfo
		func() {
			gResp, gErr := http.Get(url)
			if gErr != nil {
				logs.Error("Query ip info failed for %s, %s", ip, gErr)
				return
			}
			defer gResp.Body.Close()
			//fmt.Println(fmt.Sprintf("Ip: %-20s => %s", ip, ipInfo))
			decoder := json.NewDecoder(gResp.Body)
			decodeErr := decoder.Decode(&ipInfo)
			if decodeErr != nil {
				logs.Error("Parse ip info body failed for %s, %s", ip, decodeErr)
				return
			}

			fmt.Println(fmt.Sprintf("%s\t%s", ip, ipInfo.String()))
		}()
		<-time.After(time.Millisecond * 500)
	}
}
<commit_msg>solve the ip cmd error<commit_after>package cmd

import (
	"encoding/json"
	"fmt"
	"github.com/astaxie/beego/logs"
	"github.com/spf13/cobra"
	"net/http"
	"time"
)

const (
	// IP信息查询接口地址
	TAOBAO_IP_QUERY = "http://ip.taobao.com/service/getIpInfo.php"
)

// 接口返回的IP信息
type IpInfo struct {
	Code int    `json:"code"`
	Data IpData `json:"data"`
}

func (this IpInfo) String() string {
	return fmt.Sprintf("%s", this.Data)
}

// ip 具体的信息
type IpData struct {
	Country   string `json:"country"`
	CountryId string `json:"country_id"`
	Area      string `json:"area"`
	AreaId    string `json:"area_id"`
	Region    string `json:"region"`
	RegionId  string `json:"region_id"`
	City      string `json:"city"`
	CityId    string `json:"city_id"`
	County    string `json:"county"`
	CountyId  string `json:"county_id"`
	Isp       string `json:"isp"`
	IspId     string `json:"isp_id"`
	Ip        string `json:"ip"`
}

func (this IpData) String() string {
	return fmt.Sprintf("%s\t%s\t%s\t%s\t%s\t%s",
		this.Country, this.Area, this.Region, this.City, this.County, this.Isp)
}

var ipQueryCmd = &cobra.Command{
	Use:   "ip <Ip1> [<Ip2> [<Ip3> ...]]]",
	Short: "Query the ip information",
	Args:  cobra.MinimumNArgs(1),
	Run:   IpQuery,
}

func init() {
	RootCmd.AddCommand(ipQueryCmd)
}

// 【ip】查询ip的相关信息
func IpQuery(cmd *cobra.Command, params []string) {
	for _, ip := range params {
		url := fmt.Sprintf("%s?accessKey=alibaba-inc&ip=%s", TAOBAO_IP_QUERY, ip)
		var ipInfo IpInfo
		func() {
			gResp, gErr := http.Get(url)
			if gErr != nil {
				logs.Error("Query ip info failed for %s, %s", ip, gErr)
				return
			}
			defer gResp.Body.Close()
			//fmt.Println(fmt.Sprintf("Ip: %-20s => %s", ip, ipInfo))
			decoder := json.NewDecoder(gResp.Body)
			decodeErr := decoder.Decode(&ipInfo)
			if decodeErr != nil {
				logs.Error("Parse ip info body failed for %s, %s", ip, decodeErr)
				return
			}

			fmt.Println(fmt.Sprintf("%s\t%s", ip, ipInfo.String()))
		}()
		<-time.After(time.Millisecond * 500)
	}
}
<|endoftext|>


<commit_before>// Copyright © 2017 Aidan Steele <aidan.steele@glassechidna.com.au>
//
// 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 cmd

import (
	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/awserr"
	"github.com/aws/aws-sdk-go/aws/credentials/stscreds"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/cloudformation"
	"github.com/fatih/color"
	"github.com/glassechidna/stackit/pkg/stackit"
	"github.com/spf13/cobra"
	"github.com/spf13/viper"
	"io/ioutil"
	"os"
	"strings"
)

// up --stack-name stackit-test --template sample.yml --param-value DockerImage=nginx --param-value Cluster=app-cluster-Cluster-1C2I18JXK9QNM --tag MyTag=Cool

var paramValues []string
var previousParamValues []string
var tags []string
var notificationArns []string

func printOrExit(tailEvent stackit.TailStackEvent, printer stackit.TailPrinter) {
	if tailEvent.StackitError != nil {
		if awsErr, ok := tailEvent.StackitError.(awserr.Error); ok {
			color.New(color.FgRed).Fprintf(os.Stderr, "%s: %s\n", awsErr.Code(), awsErr.Message())
		} else {
			color.New(color.FgRed).Fprintln(os.Stderr, tailEvent.StackitError.Error())
		}
		os.Exit(1)
	}

	printer.PrintTailEvent(tailEvent)
}

var upCmd = &cobra.Command{
	Use:   "up",
	Short: "Bring stack up to date",
	Run: func(cmd *cobra.Command, args []string) {
		region := viper.GetString("region")
		profile := viper.GetString("profile")
		stackName := viper.GetString("stack-name")

		serviceRole := viper.GetString("service-role")
		stackPolicy := viper.GetString("stack-policy")
		template := viper.GetString("template")
		previousTemplate := viper.GetBool("previous-template")
		//noDestroy := viper.GetBool("no-destroy")
		//cancelOnExit := !viper.GetBool("no-cancel-on-exit")

		showTimestamps := !viper.GetBool("no-timestamps")
		showColor := !viper.GetBool("no-color")
		printer := stackit.NewTailPrinterWithOptions(showTimestamps, showColor)

		parsed := parseCLIInput(
			serviceRole,
			stackPolicy,
			template,
			paramValues,
			previousParamValues,
			tags,
			notificationArns,
			previousTemplate)

		events := make(chan stackit.TailStackEvent)

		sess := awsSession(profile, region)
		api := cloudformation.New(sess)
		sit := stackit.NewStackit(api, stackName)

		go func() {
			err := sit.EnsureStackReady(events)
			if err == nil {
				sit.Up(parsed, events)
			}
		}()

		for tailEvent := range events {
			printOrExit(tailEvent, printer)
		}

		if success, _ := sit.IsSuccessfulState(); !success {
			os.Exit(1)
		}

		sit.PrintOutputs()
	},
}

func keyvalSliceToMap(slice []string) map[string]string {
	theMap := map[string]string{}

	for _, paramPair := range slice {
		parts := strings.SplitN(paramPair, "=", 2)
		name, value := strings.TrimSpace(parts[0]), strings.TrimSpace(parts[1])
		theMap[name] = value
	}

	return theMap
}

func parseCLIInput(
	serviceRole,
	stackPolicy,
	template string,
	cliParamValues,
	previousParamValues,
	tags,
	notificationArns []string,
	previousTemplate bool) stackit.StackitUpInput {
	input := stackit.StackitUpInput{
		PopulateMissing: true,
	}

	if len(serviceRole) > 0 {
		input.RoleARN = serviceRole
	}

	if len(stackPolicy) > 0 {
		policyBody, err := ioutil.ReadFile(stackPolicy)
		if err != nil {

		} else {
			input.StackPolicyBody = string(policyBody)
		}
	}

	if len(template) > 0 {
		templateBody, err := ioutil.ReadFile(template)
		if err != nil {

		} else {
			input.TemplateBody = string(templateBody)
		}
	}

	input.PreviousTemplate = previousTemplate

	paramMap := keyvalSliceToMap(viper.GetStringSlice("parameters"))
	for key, val := range keyvalSliceToMap(cliParamValues) {
		paramMap[key] = val
	}

	params := []*cloudformation.Parameter{}
	for name, value := range paramMap {
		params = append(params, &cloudformation.Parameter{
			ParameterKey:   aws.String(name),
			ParameterValue: aws.String(value),
		})
	}

	for _, param := range previousParamValues {
		params = append(params, &cloudformation.Parameter{
			ParameterKey:     aws.String(param),
			UsePreviousValue: aws.Bool(true),
		})
	}

	input.Parameters = params
	input.NotificationARNs = notificationArns

	if len(tags) > 0 {
		input.Tags = keyvalSliceToMap(tags)
	}

	return input
}

func awsSession(profile, region string) *session.Session {
	sessOpts := session.Options{
		SharedConfigState:       session.SharedConfigEnable,
		AssumeRoleTokenProvider: stscreds.StdinTokenProvider,
	}

	if len(profile) > 0 {
		sessOpts.Profile = profile
	}

	sess, _ := session.NewSessionWithOptions(sessOpts)
	config := aws.NewConfig()

	if len(region) > 0 {
		config.Region = aws.String(region)
		sess.Config = config
	}

	return sess
}

func init() {
	RootCmd.AddCommand(upCmd)

	upCmd.PersistentFlags().String("service-role", "", "")
	upCmd.PersistentFlags().String("stack-policy", "", "")
	upCmd.PersistentFlags().String("template", "", "")
	upCmd.PersistentFlags().StringArrayVar(&paramValues, "param-value", []string{}, "")
	upCmd.PersistentFlags().StringArrayVar(&previousParamValues, "previous-param-value", []string{}, "")
	upCmd.PersistentFlags().StringArrayVar(&tags, "tag", []string{}, "")
	upCmd.PersistentFlags().StringArrayVar(&notificationArns, "notification-arn", []string{}, "")
	upCmd.PersistentFlags().Bool("previous-template", false, "")
	upCmd.PersistentFlags().Bool("no-destroy", false, "")
	upCmd.PersistentFlags().Bool("no-cancel-on-exit", false, "")
	upCmd.PersistentFlags().Bool("no-timestamps", false, "")
	upCmd.PersistentFlags().Bool("no-color", false, "")

	viper.BindPFlags(upCmd.PersistentFlags())
}
<commit_msg>Added STACKIT_AWS_VERBOSE for verbose logging<commit_after>// Copyright © 2017 Aidan Steele <aidan.steele@glassechidna.com.au>
//
// 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 cmd

import (
	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/awserr"
	"github.com/aws/aws-sdk-go/aws/credentials/stscreds"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/cloudformation"
	"github.com/fatih/color"
	"github.com/glassechidna/stackit/pkg/stackit"
	"github.com/spf13/cobra"
	"github.com/spf13/viper"
	"io/ioutil"
	"os"
	"strings"
)

// up --stack-name stackit-test --template sample.yml --param-value DockerImage=nginx --param-value Cluster=app-cluster-Cluster-1C2I18JXK9QNM --tag MyTag=Cool

var paramValues []string
var previousParamValues []string
var tags []string
var notificationArns []string

func printOrExit(tailEvent stackit.TailStackEvent, printer stackit.TailPrinter) {
	if tailEvent.StackitError != nil {
		if awsErr, ok := tailEvent.StackitError.(awserr.Error); ok {
			color.New(color.FgRed).Fprintf(os.Stderr, "%s: %s\n", awsErr.Code(), awsErr.Message())
		} else {
			color.New(color.FgRed).Fprintln(os.Stderr, tailEvent.StackitError.Error())
		}
		os.Exit(1)
	}

	printer.PrintTailEvent(tailEvent)
}

var upCmd = &cobra.Command{
	Use:   "up",
	Short: "Bring stack up to date",
	Run: func(cmd *cobra.Command, args []string) {
		region := viper.GetString("region")
		profile := viper.GetString("profile")
		stackName := viper.GetString("stack-name")

		serviceRole := viper.GetString("service-role")
		stackPolicy := viper.GetString("stack-policy")
		template := viper.GetString("template")
		previousTemplate := viper.GetBool("previous-template")
		//noDestroy := viper.GetBool("no-destroy")
		//cancelOnExit := !viper.GetBool("no-cancel-on-exit")

		showTimestamps := !viper.GetBool("no-timestamps")
		showColor := !viper.GetBool("no-color")
		printer := stackit.NewTailPrinterWithOptions(showTimestamps, showColor)

		parsed := parseCLIInput(
			serviceRole,
			stackPolicy,
			template,
			paramValues,
			previousParamValues,
			tags,
			notificationArns,
			previousTemplate)

		events := make(chan stackit.TailStackEvent)

		sess := awsSession(profile, region)
		api := cloudformation.New(sess)
		sit := stackit.NewStackit(api, stackName)

		go func() {
			err := sit.EnsureStackReady(events)
			if err == nil {
				sit.Up(parsed, events)
			}
		}()

		for tailEvent := range events {
			printOrExit(tailEvent, printer)
		}

		if success, _ := sit.IsSuccessfulState(); !success {
			os.Exit(1)
		}

		sit.PrintOutputs()
	},
}

func keyvalSliceToMap(slice []string) map[string]string {
	theMap := map[string]string{}

	for _, paramPair := range slice {
		parts := strings.SplitN(paramPair, "=", 2)
		name, value := strings.TrimSpace(parts[0]), strings.TrimSpace(parts[1])
		theMap[name] = value
	}

	return theMap
}

func parseCLIInput(
	serviceRole,
	stackPolicy,
	template string,
	cliParamValues,
	previousParamValues,
	tags,
	notificationArns []string,
	previousTemplate bool) stackit.StackitUpInput {
	input := stackit.StackitUpInput{
		PopulateMissing: true,
	}

	if len(serviceRole) > 0 {
		input.RoleARN = serviceRole
	}

	if len(stackPolicy) > 0 {
		policyBody, err := ioutil.ReadFile(stackPolicy)
		if err != nil {

		} else {
			input.StackPolicyBody = string(policyBody)
		}
	}

	if len(template) > 0 {
		templateBody, err := ioutil.ReadFile(template)
		if err != nil {

		} else {
			input.TemplateBody = string(templateBody)
		}
	}

	input.PreviousTemplate = previousTemplate

	paramMap := keyvalSliceToMap(viper.GetStringSlice("parameters"))
	for key, val := range keyvalSliceToMap(cliParamValues) {
		paramMap[key] = val
	}

	params := []*cloudformation.Parameter{}
	for name, value := range paramMap {
		params = append(params, &cloudformation.Parameter{
			ParameterKey:   aws.String(name),
			ParameterValue: aws.String(value),
		})
	}

	for _, param := range previousParamValues {
		params = append(params, &cloudformation.Parameter{
			ParameterKey:     aws.String(param),
			UsePreviousValue: aws.Bool(true),
		})
	}

	input.Parameters = params
	input.NotificationARNs = notificationArns

	if len(tags) > 0 {
		input.Tags = keyvalSliceToMap(tags)
	}

	return input
}

func awsSession(profile, region string) *session.Session {
	sessOpts := session.Options{
		SharedConfigState:       session.SharedConfigEnable,
		AssumeRoleTokenProvider: stscreds.StdinTokenProvider,
	}

	if len(profile) > 0 {
		sessOpts.Profile = profile
	}

	if len(os.Getenv("STACKIT_AWS_VERBOSE")) > 0 {
		sessOpts.Config.LogLevel = aws.LogLevel(aws.LogDebugWithHTTPBody)
	}

	sess, _ := session.NewSessionWithOptions(sessOpts)
	config := aws.NewConfig()

	if len(region) > 0 {
		config.Region = aws.String(region)
		sess.Config = config
	}

	return sess
}

func init() {
	RootCmd.AddCommand(upCmd)

	upCmd.PersistentFlags().String("service-role", "", "")
	upCmd.PersistentFlags().String("stack-policy", "", "")
	upCmd.PersistentFlags().String("template", "", "")
	upCmd.PersistentFlags().StringArrayVar(&paramValues, "param-value", []string{}, "")
	upCmd.PersistentFlags().StringArrayVar(&previousParamValues, "previous-param-value", []string{}, "")
	upCmd.PersistentFlags().StringArrayVar(&tags, "tag", []string{}, "")
	upCmd.PersistentFlags().StringArrayVar(&notificationArns, "notification-arn", []string{}, "")
	upCmd.PersistentFlags().Bool("previous-template", false, "")
	upCmd.PersistentFlags().Bool("no-destroy", false, "")
	upCmd.PersistentFlags().Bool("no-cancel-on-exit", false, "")
	upCmd.PersistentFlags().Bool("no-timestamps", false, "")
	upCmd.PersistentFlags().Bool("no-color", false, "")

	viper.BindPFlags(upCmd.PersistentFlags())
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"fmt"
	"os"
)

func writeSlice(slice []string, filename string) error {
	mutex.Lock()
	defer mutex.Unlock()
	file, err := os.OpenFile(filename, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0660)
	if err != nil {
		return err
	}
	defer file.Close()

	w := bufio.NewWriter(file)
	for _, line := range slice {
		fmt.Fprintln(w, line)
	}
	return w.Flush()
}

func readSlice(path string) []string {
	file, err := os.Open(path)
	if err != nil {
		panic(err)
	}
	defer file.Close()

	var lines []string
	scanner := bufio.NewScanner(file)
	for scanner.Scan() {
		if len(scanner.Text()) > 0 {
			lines = append(lines, scanner.Text())
		}
	}
	return lines
}

func existsFile(file string) bool {
	_, err := os.Stat(file)
	if err == nil {
		return true
	}
	if os.IsNotExist(err) {
		return createFile(file)
	}
	return true
}

func createFile(file string) bool {
	_, err := os.Create(file)
	if err != nil {
		return false
	}
	return true
}
<commit_msg>no needed<commit_after><|endoftext|>