<commit_before>/*
Copyright 2017 The Kubernetes 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 discovery

import (
	"fmt"
	"path/filepath"
	"testing"

	"github.com/kubernetes-incubator/external-storage/local-volume/provisioner/pkg/cache"
	"github.com/kubernetes-incubator/external-storage/local-volume/provisioner/pkg/common"
	"github.com/kubernetes-incubator/external-storage/local-volume/provisioner/pkg/util"

	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/client-go/pkg/api/v1"
	v1helper "k8s.io/client-go/pkg/api/v1/helper"
)

const (
	testHostDir         = "/mnt/disks"
	testMountDir        = "/discoveryPath"
	testNodeName        = "test-node"
	testProvisionerName = "test-provisioner"
)

var testNode = &v1.Node{
	ObjectMeta: metav1.ObjectMeta{
		Name: testNodeName,
		Labels: map[string]string{
			common.NodeLabelKey: testNodeName,
		},
	},
}

var scMapping = map[string]string{
	"sc1": "dir1",
	"sc2": "dir2",
}

type testConfig struct {
	// The directory layout for the test
	// Key = directory, Value = list of volumes under that directory
	dirLayout map[string][]*util.FakeFile
	// The volumes that are expected to be created as PVs
	// Key = directory, Value = list of volumes under that directory
	expectedVolumes map[string][]*util.FakeFile
	// True if testing api failure
	apiShouldFail bool
	// The rest are set during setup
	volUtil *util.FakeVolumeUtil
	apiUtil *util.FakeAPIUtil
	cache   *cache.VolumeCache
}

func TestDiscoverVolumes_Basic(t *testing.T) {
	vols := map[string][]*util.FakeFile{
		"dir1": {
			{Name: "mount1", Hash: 0xaaaafef5, Capacity: 100 * 1024},
			{Name: "mount2", Hash: 0x79412c38, Capacity: 100 * 1024 * 1024},
		},
		"dir2": {
			{Name: "mount1", Hash: 0xa7aafa3c},
			{Name: "mount2", Hash: 0x7c4130f1},
		},
	}
	test := &testConfig{
		dirLayout:       vols,
		expectedVolumes: vols,
	}
	d := testSetup(t, test)

	d.DiscoverLocalVolumes()
	verifyCreatedPVs(t, test)
}

func TestDiscoverVolumes_BasicTwice(t *testing.T) {
	vols := map[string][]*util.FakeFile{
		"dir1": {
			{Name: "mount1", Hash: 0xaaaafef5},
			{Name: "mount2", Hash: 0x79412c38},
		},
		"dir2": {
			{Name: "mount1", Hash: 0xa7aafa3c},
			{Name: "mount2", Hash: 0x7c4130f1},
		},
	}
	test := &testConfig{
		dirLayout:       vols,
		expectedVolumes: vols,
	}
	d := testSetup(t, test)

	d.DiscoverLocalVolumes()
	verifyCreatedPVs(t, test)

	// Second time should not create any new volumes
	test.expectedVolumes = map[string][]*util.FakeFile{}
	d.DiscoverLocalVolumes()
	verifyCreatedPVs(t, test)
}

func TestDiscoverVolumes_NoDir(t *testing.T) {
	vols := map[string][]*util.FakeFile{}
	test := &testConfig{
		dirLayout:       vols,
		expectedVolumes: vols,
	}
	d := testSetup(t, test)

	d.DiscoverLocalVolumes()
	verifyCreatedPVs(t, test)
}

func TestDiscoverVolumes_EmptyDir(t *testing.T) {
	vols := map[string][]*util.FakeFile{
		"dir1": {},
	}
	test := &testConfig{
		dirLayout:       vols,
		expectedVolumes: vols,
	}
	d := testSetup(t, test)

	d.DiscoverLocalVolumes()
	verifyCreatedPVs(t, test)
}

func TestDiscoverVolumes_NewVolumesLater(t *testing.T) {
	vols := map[string][]*util.FakeFile{
		"dir1": {
			{Name: "mount1", Hash: 0xaaaafef5},
			{Name: "mount2", Hash: 0x79412c38},
		},
		"dir2": {
			{Name: "mount1", Hash: 0xa7aafa3c},
			{Name: "mount2", Hash: 0x7c4130f1},
		},
	}
	test := &testConfig{
		dirLayout:       vols,
		expectedVolumes: vols,
	}
	d := testSetup(t, test)

	d.DiscoverLocalVolumes()

	verifyCreatedPVs(t, test)

	// Some new mount points show up
	newVols := map[string][]*util.FakeFile{
		"dir1": {
			{Name: "mount3", Hash: 0xf34b8003},
			{Name: "mount4", Hash: 0x144e29de},
		},
	}
	test.volUtil.AddNewFiles(testMountDir, newVols)
	test.expectedVolumes = newVols

	d.DiscoverLocalVolumes()

	verifyCreatedPVs(t, test)
}

func TestDiscoverVolumes_CreatePVFails(t *testing.T) {
	vols := map[string][]*util.FakeFile{
		"dir1": {
			{Name: "mount1", Hash: 0xaaaafef5},
			{Name: "mount2", Hash: 0x79412c38},
		},
		"dir2": {
			{Name: "mount1", Hash: 0xa7aafa3c},
			{Name: "mount2", Hash: 0x7c4130f1},
		},
	}
	test := &testConfig{
		apiShouldFail:   true,
		dirLayout:       vols,
		expectedVolumes: map[string][]*util.FakeFile{},
	}
	d := testSetup(t, test)

	d.DiscoverLocalVolumes()

	verifyCreatedPVs(t, test)
	verifyPVsNotInCache(t, test)
}

func TestDiscoverVolumes_BadVolume(t *testing.T) {
	vols := map[string][]*util.FakeFile{
		"dir1": {
			{Name: "mount1", IsNotDir: true},
		},
	}
	test := &testConfig{
		dirLayout:       vols,
		expectedVolumes: map[string][]*util.FakeFile{},
	}
	d := testSetup(t, test)

	d.DiscoverLocalVolumes()

	verifyCreatedPVs(t, test)
	verifyPVsNotInCache(t, test)
}

func testSetup(t *testing.T, test *testConfig) *Discoverer {
	test.cache = cache.NewVolumeCache()
	test.volUtil = util.NewFakeVolumeUtil(false)
	test.volUtil.AddNewFiles(testMountDir, test.dirLayout)
	test.apiUtil = util.NewFakeAPIUtil(test.apiShouldFail, test.cache)

	userConfig := &common.UserConfig{
		Node:         testNode,
		MountDir:     testMountDir,
		HostDir:      testHostDir,
		DiscoveryMap: scMapping,
	}
	runConfig := &common.RuntimeConfig{
		UserConfig: userConfig,
		Cache:      test.cache,
		VolUtil:    test.volUtil,
		APIUtil:    test.apiUtil,
		Name:       testProvisionerName,
	}
	d, err := NewDiscoverer(runConfig)
	if err != nil {
		t.Fatalf("Error setting up test discoverer: %v", err)
	}
	return d
}

func findSCName(t *testing.T, targetDir string, test *testConfig) string {
	for sc, dir := range scMapping {
		if dir == targetDir {
			return sc
		}
	}
	t.Fatalf("Failed to find SC Name for directory %v", targetDir)
	return ""
}

func verifyNodeAffinity(t *testing.T, pv *v1.PersistentVolume) {
	affinity, err := v1helper.GetStorageNodeAffinityFromAnnotation(pv.Annotations)
	if err != nil {
		t.Errorf("Could not get node affinity from annotation: %v", err)
		return
	}
	if affinity == nil {
		t.Errorf("No node affinity found")
		return
	}

	selector := affinity.RequiredDuringSchedulingIgnoredDuringExecution
	if selector == nil {
		t.Errorf("NodeAffinity node selector is nil")
		return
	}
	terms := selector.NodeSelectorTerms
	if len(terms) != 1 {
		t.Errorf("Node selector term count is %v, expected 1", len(terms))
		return
	}
	reqs := terms[0].MatchExpressions
	if len(reqs) != 1 {
		t.Errorf("Node selector term requirements count is %v, expected 1", len(reqs))
		return
	}

	req := reqs[0]
	if req.Key != common.NodeLabelKey {
		t.Errorf("Node selector requirement key is %v, expected %v", req.Key, common.NodeLabelKey)
	}
	if req.Operator != v1.NodeSelectorOpIn {
		t.Errorf("Node selector requirement operator is %v, expected %v", req.Operator, v1.NodeSelectorOpIn)
	}
	if len(req.Values) != 1 {
		t.Errorf("Node selector requirement value count is %v, expected 1", len(req.Values))
		return
	}
	if req.Values[0] != testNodeName {
		t.Errorf("Node selector requirement value is %v, expected %v", req.Values[0], testNodeName)
	}
}

func verifyProvisionerName(t *testing.T, pv *v1.PersistentVolume) {
	if len(pv.Annotations) == 0 {
		t.Errorf("Annotations not set")
		return
	}
	name, found := pv.Annotations[common.AnnProvisionedBy]
	if !found {
		t.Errorf("Provisioned by annotations not set")
		return
	}
	if name != testProvisionerName {
		t.Errorf("Provisioned name is %q, expected %q", name, testProvisionerName)
	}
}

func verifyCapacity(t *testing.T, createdPV *v1.PersistentVolume, expectedPV *testPVInfo) {
	capacity, ok := createdPV.Spec.Capacity[v1.ResourceStorage]
	if !ok {
		t.Errorf("Unexpected empty resource storage")
	}
	capacityInt, ok := capacity.AsInt64()
	if !ok {
		t.Errorf("Unable to convert resource storage into int64")
	}
	if uint64(capacityInt) != expectedPV.capacity {
		t.Errorf("Expected capacity %d, got %d", expectedPV.capacity, capacityInt)
	}
}

// testPVInfo contains all the fields we are intested in validating.
type testPVInfo struct {
	pvName       string
	path         string
	capacity     uint64
	storageClass string
}

func verifyCreatedPVs(t *testing.T, test *testConfig) {
	expectedPVs := map[string]*testPVInfo{}
	for dir, files := range test.expectedVolumes {
		for _, file := range files {
			pvName := fmt.Sprintf("local-pv-%x", file.Hash)
			path := filepath.Join(testHostDir, dir, file.Name)
			expectedPVs[pvName] = &testPVInfo{
				pvName:       pvName,
				path:         path,
				capacity:     file.Capacity,
				storageClass: findSCName(t, dir, test),
			}
		}
	}

	createdPVs := test.apiUtil.GetAndResetCreatedPVs()
	expectedLen := len(expectedPVs)
	actualLen := len(createdPVs)
	if expectedLen != actualLen {
		t.Errorf("Expected %v created PVs, got %v", expectedLen, actualLen)
	}

	for pvName, createdPV := range createdPVs {
		expectedPV, found := expectedPVs[pvName]
		if !found {
			t.Errorf("Did not expect created PVs %v", pvName)
		}
		if createdPV.Spec.PersistentVolumeSource.Local.Path != expectedPV.path {
			t.Errorf("Expected path %q, got %q", expectedPV.path, createdPV.Spec.PersistentVolumeSource.Local.Path)
		}
		if createdPV.Spec.StorageClassName != expectedPV.storageClass {
			t.Errorf("Expected storage class %q, got %q", expectedPV.storageClass, createdPV.Spec.StorageClassName)
		}
		_, exists := test.cache.GetPV(pvName)
		if !exists {
			t.Errorf("PV %q not in cache", pvName)
		}

		// TODO: verify storage class
		verifyProvisionerName(t, createdPV)
		verifyNodeAffinity(t, createdPV)
		verifyCapacity(t, createdPV, expectedPV)
	}
}

func verifyPVsNotInCache(t *testing.T, test *testConfig) {
	for _, files := range test.dirLayout {
		for _, file := range files {
			pvName := fmt.Sprintf("local-pv-%x", file.Hash)
			_, exists := test.cache.GetPV(pvName)
			if exists {
				t.Errorf("Expected PV %q to not be in cache", pvName)
			}
		}
	}
}
<commit_msg>Add storage class verification<commit_after>/*
Copyright 2017 The Kubernetes 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 discovery

import (
	"fmt"
	"path/filepath"
	"testing"

	"github.com/kubernetes-incubator/external-storage/local-volume/provisioner/pkg/cache"
	"github.com/kubernetes-incubator/external-storage/local-volume/provisioner/pkg/common"
	"github.com/kubernetes-incubator/external-storage/local-volume/provisioner/pkg/util"

	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/client-go/pkg/api/v1"
	v1helper "k8s.io/client-go/pkg/api/v1/helper"
)

const (
	testHostDir         = "/mnt/disks"
	testMountDir        = "/discoveryPath"
	testNodeName        = "test-node"
	testProvisionerName = "test-provisioner"
)

var testNode = &v1.Node{
	ObjectMeta: metav1.ObjectMeta{
		Name: testNodeName,
		Labels: map[string]string{
			common.NodeLabelKey: testNodeName,
		},
	},
}

var scMapping = map[string]string{
	"sc1": "dir1",
	"sc2": "dir2",
}

type testConfig struct {
	// The directory layout for the test
	// Key = directory, Value = list of volumes under that directory
	dirLayout map[string][]*util.FakeFile
	// The volumes that are expected to be created as PVs
	// Key = directory, Value = list of volumes under that directory
	expectedVolumes map[string][]*util.FakeFile
	// True if testing api failure
	apiShouldFail bool
	// The rest are set during setup
	volUtil *util.FakeVolumeUtil
	apiUtil *util.FakeAPIUtil
	cache   *cache.VolumeCache
}

func TestDiscoverVolumes_Basic(t *testing.T) {
	vols := map[string][]*util.FakeFile{
		"dir1": {
			{Name: "mount1", Hash: 0xaaaafef5, Capacity: 100 * 1024},
			{Name: "mount2", Hash: 0x79412c38, Capacity: 100 * 1024 * 1024},
		},
		"dir2": {
			{Name: "mount1", Hash: 0xa7aafa3c},
			{Name: "mount2", Hash: 0x7c4130f1},
		},
	}
	test := &testConfig{
		dirLayout:       vols,
		expectedVolumes: vols,
	}
	d := testSetup(t, test)

	d.DiscoverLocalVolumes()
	verifyCreatedPVs(t, test)
}

func TestDiscoverVolumes_BasicTwice(t *testing.T) {
	vols := map[string][]*util.FakeFile{
		"dir1": {
			{Name: "mount1", Hash: 0xaaaafef5},
			{Name: "mount2", Hash: 0x79412c38},
		},
		"dir2": {
			{Name: "mount1", Hash: 0xa7aafa3c},
			{Name: "mount2", Hash: 0x7c4130f1},
		},
	}
	test := &testConfig{
		dirLayout:       vols,
		expectedVolumes: vols,
	}
	d := testSetup(t, test)

	d.DiscoverLocalVolumes()
	verifyCreatedPVs(t, test)

	// Second time should not create any new volumes
	test.expectedVolumes = map[string][]*util.FakeFile{}
	d.DiscoverLocalVolumes()
	verifyCreatedPVs(t, test)
}

func TestDiscoverVolumes_NoDir(t *testing.T) {
	vols := map[string][]*util.FakeFile{}
	test := &testConfig{
		dirLayout:       vols,
		expectedVolumes: vols,
	}
	d := testSetup(t, test)

	d.DiscoverLocalVolumes()
	verifyCreatedPVs(t, test)
}

func TestDiscoverVolumes_EmptyDir(t *testing.T) {
	vols := map[string][]*util.FakeFile{
		"dir1": {},
	}
	test := &testConfig{
		dirLayout:       vols,
		expectedVolumes: vols,
	}
	d := testSetup(t, test)

	d.DiscoverLocalVolumes()
	verifyCreatedPVs(t, test)
}

func TestDiscoverVolumes_NewVolumesLater(t *testing.T) {
	vols := map[string][]*util.FakeFile{
		"dir1": {
			{Name: "mount1", Hash: 0xaaaafef5},
			{Name: "mount2", Hash: 0x79412c38},
		},
		"dir2": {
			{Name: "mount1", Hash: 0xa7aafa3c},
			{Name: "mount2", Hash: 0x7c4130f1},
		},
	}
	test := &testConfig{
		dirLayout:       vols,
		expectedVolumes: vols,
	}
	d := testSetup(t, test)

	d.DiscoverLocalVolumes()

	verifyCreatedPVs(t, test)

	// Some new mount points show up
	newVols := map[string][]*util.FakeFile{
		"dir1": {
			{Name: "mount3", Hash: 0xf34b8003},
			{Name: "mount4", Hash: 0x144e29de},
		},
	}
	test.volUtil.AddNewFiles(testMountDir, newVols)
	test.expectedVolumes = newVols

	d.DiscoverLocalVolumes()

	verifyCreatedPVs(t, test)
}

func TestDiscoverVolumes_CreatePVFails(t *testing.T) {
	vols := map[string][]*util.FakeFile{
		"dir1": {
			{Name: "mount1", Hash: 0xaaaafef5},
			{Name: "mount2", Hash: 0x79412c38},
		},
		"dir2": {
			{Name: "mount1", Hash: 0xa7aafa3c},
			{Name: "mount2", Hash: 0x7c4130f1},
		},
	}
	test := &testConfig{
		apiShouldFail:   true,
		dirLayout:       vols,
		expectedVolumes: map[string][]*util.FakeFile{},
	}
	d := testSetup(t, test)

	d.DiscoverLocalVolumes()

	verifyCreatedPVs(t, test)
	verifyPVsNotInCache(t, test)
}

func TestDiscoverVolumes_BadVolume(t *testing.T) {
	vols := map[string][]*util.FakeFile{
		"dir1": {
			{Name: "mount1", IsNotDir: true},
		},
	}
	test := &testConfig{
		dirLayout:       vols,
		expectedVolumes: map[string][]*util.FakeFile{},
	}
	d := testSetup(t, test)

	d.DiscoverLocalVolumes()

	verifyCreatedPVs(t, test)
	verifyPVsNotInCache(t, test)
}

func testSetup(t *testing.T, test *testConfig) *Discoverer {
	test.cache = cache.NewVolumeCache()
	test.volUtil = util.NewFakeVolumeUtil(false)
	test.volUtil.AddNewFiles(testMountDir, test.dirLayout)
	test.apiUtil = util.NewFakeAPIUtil(test.apiShouldFail, test.cache)

	userConfig := &common.UserConfig{
		Node:         testNode,
		MountDir:     testMountDir,
		HostDir:      testHostDir,
		DiscoveryMap: scMapping,
	}
	runConfig := &common.RuntimeConfig{
		UserConfig: userConfig,
		Cache:      test.cache,
		VolUtil:    test.volUtil,
		APIUtil:    test.apiUtil,
		Name:       testProvisionerName,
	}
	d, err := NewDiscoverer(runConfig)
	if err != nil {
		t.Fatalf("Error setting up test discoverer: %v", err)
	}
	return d
}

func findSCName(t *testing.T, targetDir string, test *testConfig) string {
	for sc, dir := range scMapping {
		if dir == targetDir {
			return sc
		}
	}
	t.Fatalf("Failed to find SC Name for directory %v", targetDir)
	return ""
}

func verifyNodeAffinity(t *testing.T, pv *v1.PersistentVolume) {
	affinity, err := v1helper.GetStorageNodeAffinityFromAnnotation(pv.Annotations)
	if err != nil {
		t.Errorf("Could not get node affinity from annotation: %v", err)
		return
	}
	if affinity == nil {
		t.Errorf("No node affinity found")
		return
	}

	selector := affinity.RequiredDuringSchedulingIgnoredDuringExecution
	if selector == nil {
		t.Errorf("NodeAffinity node selector is nil")
		return
	}
	terms := selector.NodeSelectorTerms
	if len(terms) != 1 {
		t.Errorf("Node selector term count is %v, expected 1", len(terms))
		return
	}
	reqs := terms[0].MatchExpressions
	if len(reqs) != 1 {
		t.Errorf("Node selector term requirements count is %v, expected 1", len(reqs))
		return
	}

	req := reqs[0]
	if req.Key != common.NodeLabelKey {
		t.Errorf("Node selector requirement key is %v, expected %v", req.Key, common.NodeLabelKey)
	}
	if req.Operator != v1.NodeSelectorOpIn {
		t.Errorf("Node selector requirement operator is %v, expected %v", req.Operator, v1.NodeSelectorOpIn)
	}
	if len(req.Values) != 1 {
		t.Errorf("Node selector requirement value count is %v, expected 1", len(req.Values))
		return
	}
	if req.Values[0] != testNodeName {
		t.Errorf("Node selector requirement value is %v, expected %v", req.Values[0], testNodeName)
	}
}

func verifyProvisionerName(t *testing.T, pv *v1.PersistentVolume) {
	if len(pv.Annotations) == 0 {
		t.Errorf("Annotations not set")
		return
	}
	name, found := pv.Annotations[common.AnnProvisionedBy]
	if !found {
		t.Errorf("Provisioned by annotations not set")
		return
	}
	if name != testProvisionerName {
		t.Errorf("Provisioned name is %q, expected %q", name, testProvisionerName)
	}
}

func verifyCapacity(t *testing.T, createdPV *v1.PersistentVolume, expectedPV *testPVInfo) {
	capacity, ok := createdPV.Spec.Capacity[v1.ResourceStorage]
	if !ok {
		t.Errorf("Unexpected empty resource storage")
	}
	capacityInt, ok := capacity.AsInt64()
	if !ok {
		t.Errorf("Unable to convert resource storage into int64")
	}
	if uint64(capacityInt) != expectedPV.capacity {
		t.Errorf("Expected capacity %d, got %d", expectedPV.capacity, capacityInt)
	}
}

// testPVInfo contains all the fields we are intested in validating.
type testPVInfo struct {
	pvName       string
	path         string
	capacity     uint64
	storageClass string
}

func verifyCreatedPVs(t *testing.T, test *testConfig) {
	expectedPVs := map[string]*testPVInfo{}
	for dir, files := range test.expectedVolumes {
		for _, file := range files {
			pvName := fmt.Sprintf("local-pv-%x", file.Hash)
			path := filepath.Join(testHostDir, dir, file.Name)
			expectedPVs[pvName] = &testPVInfo{
				pvName:       pvName,
				path:         path,
				capacity:     file.Capacity,
				storageClass: findSCName(t, dir, test),
			}
		}
	}

	createdPVs := test.apiUtil.GetAndResetCreatedPVs()
	expectedLen := len(expectedPVs)
	actualLen := len(createdPVs)
	if expectedLen != actualLen {
		t.Errorf("Expected %v created PVs, got %v", expectedLen, actualLen)
	}

	for pvName, createdPV := range createdPVs {
		expectedPV, found := expectedPVs[pvName]
		if !found {
			t.Errorf("Did not expect created PVs %v", pvName)
		}
		if createdPV.Spec.PersistentVolumeSource.Local.Path != expectedPV.path {
			t.Errorf("Expected path %q, got %q", expectedPV.path, createdPV.Spec.PersistentVolumeSource.Local.Path)
		}
		if createdPV.Spec.StorageClassName != expectedPV.storageClass {
			t.Errorf("Expected storage class %q, got %q", expectedPV.storageClass, createdPV.Spec.StorageClassName)
		}
		_, exists := test.cache.GetPV(pvName)
		if !exists {
			t.Errorf("PV %q not in cache", pvName)
		}

		verifyProvisionerName(t, createdPV)
		verifyNodeAffinity(t, createdPV)
		verifyCapacity(t, createdPV, expectedPV)
	}
}

func verifyPVsNotInCache(t *testing.T, test *testConfig) {
	for _, files := range test.dirLayout {
		for _, file := range files {
			pvName := fmt.Sprintf("local-pv-%x", file.Hash)
			_, exists := test.cache.GetPV(pvName)
			if exists {
				t.Errorf("Expected PV %q to not be in cache", pvName)
			}
		}
	}
}
<|endoftext|>


<commit_before>package components

import (
	. "mater"
	"box2d"
	"json"
	"os"
)

//wrapper around box2d.Transform
type Transform struct {
	*box2d.Transform
}

func (xf *Transform) Name () string {
	return "Transform"
}

//If the Transform is set and the owner has a body attached, we replace its transform
//else if the Transform is not set we try to take it from the owners body or create a new one
func (xf *Transform) Init (owner *Entity) {
	//check if we already have a transform
	if xf.Transform == nil {
		//we don't, see if our owner has a body attached
		if bcomp, ok := owner.Components["Body"]; ok {
			body := bcomp.(*Body)
			//take its transform
			xf.Transform = body.Transform()
		} else {
			//create a new one
			xf.Transform = new(box2d.Transform)
		}
	} else {
		//we do, check if our owner has a body attached
		if bcomp, ok := owner.Components["Body"]; ok {
			body := bcomp.(*Body)
			//set its transform
			body.SetTransform(&xf.Position, xf.Angle())
			//take the address of the bodies transform
			xf.Transform = body.Transform()
		}
	}
}

func (xf *Transform) Update (owner *Entity, dt float64) {

}

func (xf *Transform) Destroy (owner *Entity) {

}

func (xf *Transform) Marshal(owner *Entity) ([]byte, os.Error) {
	return json.Marshal(xf.Transform)
}

func (xf *Transform) Unmarshal(owner *Entity, data []byte) (os.Error) {
	return json.Unmarshal(data, xf.Transform)
}

func init() {
	RegisterComponent(&Transform{})
}
<commit_msg>fixed Transform component deserialization<commit_after>package components

import (
	. "mater"
	"box2d"
	"json"
	"os"
)

//wrapper around box2d.Transform
type Transform struct {
	*box2d.Transform
}

func (xf *Transform) Name () string {
	return "Transform"
}

//If the Transform is set and the owner has a body attached, we replace its transform
//else if the Transform is not set we try to take it from the owners body or create a new one
func (xf *Transform) Init (owner *Entity) {
	//check if we already have a transform
	if xf.Transform == nil {
		//we don't, see if our owner has a body attached
		if bcomp, ok := owner.Components["Body"]; ok {
			body := bcomp.(*Body)
			//take its transform
			xf.Transform = body.Transform()
		} else {
			//create a new one
			xf.Transform = new(box2d.Transform)
		}
	} else {
		//we do, check if our owner has a body attached
		if bcomp, ok := owner.Components["Body"]; ok {
			body := bcomp.(*Body)
			//set its transform
			body.SetTransform(&xf.Position, xf.Angle())
			//take the address of the bodies transform
			xf.Transform = body.Transform()
		}
	}
}

func (xf *Transform) Update (owner *Entity, dt float64) {

}

func (xf *Transform) Destroy (owner *Entity) {

}

func (xf *Transform) Marshal(owner *Entity) ([]byte, os.Error) {
	return json.Marshal(xf.Transform)
}

func (xf *Transform) Unmarshal(owner *Entity, data []byte) (os.Error) {
	if xf.Transform == nil {
		xf.Transform = new(box2d.Transform)
	}
	return json.Unmarshal(data, xf.Transform)
}

func init() {
	RegisterComponent(&Transform{})
}
<|endoftext|>


<commit_before>// Package acctest provides the ability to opt in to the new binary test driver. The binary
// test driver allows you to run your acceptance tests with a binary of Terraform instead of
// an emulated version packaged inside the SDK. This allows for a number of important
// enhancements, but most notably a more realistic testing experience and matrix testing
// against multiple versions of Terraform CLI. This also allows the SDK to be completely
// separated, at a dependency level, from the Terraform CLI, as long as it is >= 0.12.0
//
// The new test driver must be enabled by initialising the test helper in your TestMain
// function in all provider packages that run acceptance tests. Most providers have only
// one package.
//
// In v2 of the SDK, the binary test driver will be mandatory.
//
// After importing this package, you can add code similar to the following:
//
//   func TestMain(m *testing.M) {
//     acctest.UseBinaryDriver("provider_name", Provider)
//     resource.TestMain(m)
//   }
//
// Where `Provider` is the function that returns the instance of a configured `terraform.ResourceProvider`
// Some providers already have a TestMain defined, usually for the purpose of enabling test
// sweepers. These additional occurrences should be removed.
//
// Initialising the binary test helper using UseBinaryDriver causes all tests to be run using
// the new binary driver. Until SDK v2, the DisableBinaryDriver boolean property can be used
// to use the legacy test driver for an individual TestCase.
//
// It is no longer necessary to import other Terraform providers as Go modules: these
// imports should be removed.
package acctest
<commit_msg>Update wording for a V2 context<commit_after>// Package acctest provides the ability to use the binary test driver. The binary
// test driver allows you to run your acceptance tests with a binary of Terraform.
// This is currently the only mechanism for driving tests. It provides a realistic testing
// experience and matrix testing against multiple versions of Terraform CLI,
// as long as they are >= 0.12.0
//
// The driver must be enabled by initialising the test helper in your TestMain
// function in all provider packages that run acceptance tests. Most providers have only
// one package.
//
// After importing this package, you must define a TestMain and have the following:
//
//   func TestMain(m *testing.M) {
//     acctest.UseBinaryDriver("provider_name", Provider)
//     resource.TestMain(m)
//   }
//
// Where `Provider` is the function that returns the instance of a configured `*schema.Provider`
// Some providers already have a TestMain defined, usually for the purpose of enabling test
// sweepers. These additional occurrences should be removed.
//
// It is no longer necessary to import other Terraform providers as Go modules: these
// imports should be removed.
package acctest
<|endoftext|>


<commit_before>// +build nobootstrap

package follow

import (
	"time"

	"github.com/shirou/gopsutil/cpu"
	"github.com/shirou/gopsutil/mem"

	"core"
)

// resourceUpdateFrequency is the frequency that we re-check CPU usage etc at.
// We don't want to sample too often; it will actually make CPU usage less accurate, and
// we don't want to spend all our time looking at it anyway.
var resourceUpdateFrequency = 500 * time.Millisecond

// UpdateResources continuously updates the resources that we store on the BuildState object.
// It should probably be run in a goroutine since it never returns.
func UpdateResources(state *core.BuildState) {
	lastTime := time.Now()
	// Assume this doesn't change through the process lifetime.
	count, _ := cpu.Counts(true)
	state.Stats.CPU.Count = count
	// Top out max CPU; sometimes we get our maths slightly wrong, probably because of
	// mild uncertainty in times.
	maxCPU := float64(100 * count)
	// CPU is a bit of a fiddle since the kernel only gives us totals,
	// so we have to sample how busy we think it's been.
	lastTotal, lastIO := getCPUTimes()
	for timeNow := range time.NewTicker(resourceUpdateFrequency).C {
		if thisTotal, thisIO := getCPUTimes(); thisTotal > 0.0 {
			elapsed := timeNow.Sub(lastTime).Seconds()
			state.Stats.CPU.Used = 100.0 * (thisTotal - lastTotal) / elapsed
			state.Stats.CPU.IOWait = 100.0 * (thisIO - lastIO) / elapsed
			if state.Stats.CPU.Used > maxCPU {
				state.Stats.CPU.Used = maxCPU
			}
			lastTotal, lastIO = thisTotal, thisIO
		}
		// Thank goodness memory is a simpler beast.
		if vm, err := mem.VirtualMemory(); err != nil {
			log.Error("Error getting memory usage: %s", err)
		} else {
			state.Stats.Memory.Total = vm.Total
			state.Stats.Memory.Used = vm.Used
			state.Stats.Memory.UsedPercent = vm.UsedPercent
		}
		lastTime = timeNow
	}
}

func getCPUTimes() (float64, float64) {
	ts, err := cpu.Times(false) // not per CPU
	if err != nil || len(ts) == 0 {
		log.Error("Error getting CPU info: %s", err)
		return 0.0, 0.0
	}
	t := ts[0]
	return t.Total() - t.Idle - t.Iowait, t.Iowait
}
<commit_msg>Clamp CPU figures more rigorously<commit_after>// +build nobootstrap

package follow

import (
	"time"

	"github.com/shirou/gopsutil/cpu"
	"github.com/shirou/gopsutil/mem"

	"core"
)

// resourceUpdateFrequency is the frequency that we re-check CPU usage etc at.
// We don't want to sample too often; it will actually make CPU usage less accurate, and
// we don't want to spend all our time looking at it anyway.
var resourceUpdateFrequency = 500 * time.Millisecond

// UpdateResources continuously updates the resources that we store on the BuildState object.
// It should probably be run in a goroutine since it never returns.
func UpdateResources(state *core.BuildState) {
	lastTime := time.Now()
	// Assume this doesn't change through the process lifetime.
	count, _ := cpu.Counts(true)
	state.Stats.CPU.Count = count
	// Top out max CPU; sometimes we get our maths slightly wrong, probably because of
	// mild uncertainty in times.
	maxCPU := float64(100 * count)
	clamp := func(f float64) float64 {
		if f >= maxCPU {
			return maxCPU
		} else if f <= 0.0 {
			return 0.0
		}
		return f
	}
	// CPU is a bit of a fiddle since the kernel only gives us totals,
	// so we have to sample how busy we think it's been.
	lastTotal, lastIO := getCPUTimes()
	for timeNow := range time.NewTicker(resourceUpdateFrequency).C {
		if thisTotal, thisIO := getCPUTimes(); thisTotal > 0.0 {
			elapsed := timeNow.Sub(lastTime).Seconds()
			state.Stats.CPU.Used = clamp(100.0 * (thisTotal - lastTotal) / elapsed)
			state.Stats.CPU.IOWait = clamp(100.0 * (thisIO - lastIO) / elapsed)
			lastTotal, lastIO = thisTotal, thisIO
		}
		// Thank goodness memory is a simpler beast.
		if vm, err := mem.VirtualMemory(); err != nil {
			log.Error("Error getting memory usage: %s", err)
		} else {
			state.Stats.Memory.Total = vm.Total
			state.Stats.Memory.Used = vm.Used
			state.Stats.Memory.UsedPercent = vm.UsedPercent
		}
		lastTime = timeNow
	}
}

func getCPUTimes() (float64, float64) {
	ts, err := cpu.Times(false) // not per CPU
	if err != nil || len(ts) == 0 {
		log.Error("Error getting CPU info: %s", err)
		return 0.0, 0.0
	}
	t := ts[0]
	return t.Total() - t.Idle - t.Iowait, t.Iowait
}
<|endoftext|>


<commit_before>// Copyright 2016, RadiantBlue Technologies, 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 workflow

import (
	"net/http"

	"github.com/gin-gonic/gin"
	"github.com/venicegeo/pz-gocommon/gocommon"
	"fmt"
	"bytes"
)

//---------------------------------------------------------------------------

type Server struct {
	//sysConfig *piazza.SystemConfig

	Routes  []piazza.RouteData
	service *Service
	origin  string
}

const Version = "1.0.0"

//---------------------------------------------------------------------------

func (server *Server) Init(service *Service) error {

	server.service = service

	server.Routes = []piazza.RouteData{
		{Verb: "GET", Path: "/", Handler: server.handleGetRoot},
		{Verb: "GET", Path: "/version", Handler: server.handleGetVersion},

		{Verb: "GET", Path: "/eventType", Handler: server.handleGetAllEventTypes},
		{Verb: "GET", Path: "/eventType/:id", Handler: server.handleGetEventType},
		{Verb: "POST", Path: "/eventType", Handler: server.handlePostEventType},
		{Verb: "DELETE", Path: "/eventType/:id", Handler: server.handleDeleteEventType},

		{Verb: "GET", Path: "/event/:id", Handler: server.handleGetEvent},
		{Verb: "GET", Path: "/event", Handler: server.handleGetAllEvents},
		{Verb: "POST", Path: "/event", Handler: server.handlePostEvent},
		{Verb: "POST", Path: "/event/query", Handler: server.handleEventQuery},
		{Verb: "DELETE", Path: "/event/:id", Handler: server.handleDeleteEvent},

		{Verb: "GET", Path: "/trigger/:id", Handler: server.handleGetTrigger},
		{Verb: "GET", Path: "/trigger", Handler: server.handleGetAllTriggers},
		{Verb: "POST", Path: "/trigger", Handler: server.handlePostTrigger},
		{Verb: "PUT", Path: "/trigger/:id", Handler: server.handlePutTrigger},
		{Verb: "DELETE", Path: "/trigger/:id", Handler: server.handleDeleteTrigger},

		{Verb: "GET", Path: "/alert/:id", Handler: server.handleGetAlert},
		{Verb: "GET", Path: "/alert", Handler: server.handleGetAllAlerts},
		{Verb: "POST", Path: "/alert", Handler: server.handlePostAlert},
		{Verb: "DELETE", Path: "/alert/:id", Handler: server.handleDeleteAlert},

		{Verb: "GET", Path: "/admin/stats", Handler: server.handleGetStats},
	}

	server.origin = service.origin

	return nil
}

//---------------------------------------------------------------------------

func (server *Server) handleGetRoot(c *gin.Context) {
	message := "Hi! I'm pz-workflow."
	resp := &piazza.JsonResponse{StatusCode: http.StatusOK, Data: message}
	piazza.GinReturnJson(c, resp)
}

func (server *Server) handleGetVersion(c *gin.Context) {
	version := piazza.Version{Version: Version}
	resp := &piazza.JsonResponse{StatusCode: http.StatusOK, Data: version}
	piazza.GinReturnJson(c, resp)
}

func (server *Server) handleGetStats(c *gin.Context) {
	resp := server.service.GetStats()
	piazza.GinReturnJson(c, resp)
}

//---------------------------------------------------------------------------

func (server *Server) handleGetEventType(c *gin.Context) {
	id := piazza.Ident(c.Param("id"))
	resp := server.service.GetEventType(id)
	piazza.GinReturnJson(c, resp)
}

func (server *Server) handleGetAllEventTypes(c *gin.Context) {
	params := piazza.NewQueryParams(c.Request)
	resp := server.service.GetAllEventTypes(params)
	piazza.GinReturnJson(c, resp)
}

func (server *Server) handlePostEventType(c *gin.Context) {
	eventType := &EventType{}
	err := c.BindJSON(eventType)
	if err != nil {
		resp := &piazza.JsonResponse{
			StatusCode: http.StatusBadRequest,
			Message:    err.Error(),
			Origin:     server.origin,
		}
		piazza.GinReturnJson(c, resp)
		return
	}
	resp := server.service.PostEventType(eventType)
	piazza.GinReturnJson(c, resp)
}

func (server *Server) handleDeleteEventType(c *gin.Context) {
	id := piazza.Ident(c.Param("id"))
	resp := server.service.DeleteEventType(id)
	piazza.GinReturnJson(c, resp)
}

//---------------------------------------------------------------------------

func (server *Server) handleGetEvent(c *gin.Context) {
	id := piazza.Ident(c.Param("id"))
	resp := server.service.GetEvent(id)
	piazza.GinReturnJson(c, resp)
}

func (server *Server) handleGetAllEvents(c *gin.Context) {
	params := piazza.NewQueryParams(c.Request)
	resp := server.service.GetAllEvents(params)
	piazza.GinReturnJson(c, resp)
}

func (server *Server) handlePostEvent(c *gin.Context) {
	event := &Event{}
	err := c.BindJSON(event)
	if err != nil {
		resp := &piazza.JsonResponse{
			StatusCode: http.StatusBadRequest,
			Message:    err.Error(),
			Origin:     server.origin,
		}
		piazza.GinReturnJson(c, resp)
		return
	}

	var resp *piazza.JsonResponse

	if event.CronSchedule != "" {
		resp = server.service.PostRepeatingEvent(event)
	} else {
		resp = server.service.PostEvent(event)
	}
	piazza.GinReturnJson(c, resp)
}

func (server *Server) handleEventQuery(c *gin.Context) {
	buf := new(bytes.Buffer)
	_, err := buf.ReadFrom(c.Request.Body)
	if err != nil {
		resp := &piazza.JsonResponse{
			StatusCode: http.StatusBadRequest,
			Message:    err.Error(),
			Origin:     server.origin,
		}
		piazza.GinReturnJson(c, resp)
		return
	}

	jsonString := buf.String()
	fmt.Printf("c.Request=%s\n\n", jsonString)
	params := piazza.NewQueryParams(c.Request)
	fmt.Printf("params=%s\n\n", params)

	var resp *piazza.JsonResponse

	resp = server.service.QueryEvents(jsonString, params)
	piazza.GinReturnJson(c, resp)
}

func (server *Server) handleDeleteEvent(c *gin.Context) {
	id := piazza.Ident(c.Param("id"))
	resp := server.service.DeleteEvent(id)
	piazza.GinReturnJson(c, resp)
}

//---------------------------------------------------------------------------

func (server *Server) handleGetTrigger(c *gin.Context) {
	id := piazza.Ident(c.Param("id"))
	resp := server.service.GetTrigger(id)
	piazza.GinReturnJson(c, resp)
}

func (server *Server) handleGetAllTriggers(c *gin.Context) {
	params := piazza.NewQueryParams(c.Request)
	resp := server.service.GetAllTriggers(params)
	piazza.GinReturnJson(c, resp)
}

func (server *Server) handlePostTrigger(c *gin.Context) {
	trigger := &Trigger{Enabled: true}
	err := c.BindJSON(trigger)
	if err != nil {
		resp := &piazza.JsonResponse{
			StatusCode: http.StatusBadRequest,
			Message:    err.Error(),
			Origin:     server.origin,
		}
		piazza.GinReturnJson(c, resp)
		return
	}
	resp := server.service.PostTrigger(trigger)
	piazza.GinReturnJson(c, resp)
}

func (server *Server) handlePutTrigger(c *gin.Context) {
	id := piazza.Ident(c.Param("id"))
	update := &TriggerUpdate{}
	err := c.BindJSON(update)
	if err != nil {
		resp := &piazza.JsonResponse{
			StatusCode: http.StatusBadRequest,
			Message:    err.Error(),
			Origin:     server.origin,
		}
		piazza.GinReturnJson(c, resp)
		return
	}
	resp := server.service.PutTrigger(id, update)
	piazza.GinReturnJson(c, resp)
}

func (server *Server) handleDeleteTrigger(c *gin.Context) {
	id := piazza.Ident(c.Param("id"))
	resp := server.service.DeleteTrigger(id)
	piazza.GinReturnJson(c, resp)
}

//---------------------------------------------------------------------------

func (server *Server) handleGetAlert(c *gin.Context) {
	id := piazza.Ident(c.Param("id"))
	resp := server.service.GetAlert(id)
	piazza.GinReturnJson(c, resp)
}

func (server *Server) handleGetAllAlerts(c *gin.Context) {
	params := piazza.NewQueryParams(c.Request)
	resp := server.service.GetAllAlerts(params)
	piazza.GinReturnJson(c, resp)
}

func (server *Server) handlePostAlert(c *gin.Context) {
	alert := &Alert{}
	err := c.BindJSON(alert)
	if err != nil {
		resp := &piazza.JsonResponse{
			StatusCode: http.StatusBadRequest,
			Message:    err.Error(),
			Origin:     server.origin,
		}
		piazza.GinReturnJson(c, resp)
		return
	}
	resp := server.service.PostAlert(alert)
	piazza.GinReturnJson(c, resp)
}

func (server *Server) handleDeleteAlert(c *gin.Context) {
	id := piazza.Ident(c.Param("id"))
	resp := server.service.DeleteAlert(id)
	piazza.GinReturnJson(c, resp)
}
<commit_msg>Remove debug prints<commit_after>// Copyright 2016, RadiantBlue Technologies, 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 workflow

import (
	"net/http"

	"github.com/gin-gonic/gin"
	"github.com/venicegeo/pz-gocommon/gocommon"
	"bytes"
)

//---------------------------------------------------------------------------

type Server struct {
	//sysConfig *piazza.SystemConfig

	Routes  []piazza.RouteData
	service *Service
	origin  string
}

const Version = "1.0.0"

//---------------------------------------------------------------------------

func (server *Server) Init(service *Service) error {

	server.service = service

	server.Routes = []piazza.RouteData{
		{Verb: "GET", Path: "/", Handler: server.handleGetRoot},
		{Verb: "GET", Path: "/version", Handler: server.handleGetVersion},

		{Verb: "GET", Path: "/eventType", Handler: server.handleGetAllEventTypes},
		{Verb: "GET", Path: "/eventType/:id", Handler: server.handleGetEventType},
		{Verb: "POST", Path: "/eventType", Handler: server.handlePostEventType},
		{Verb: "DELETE", Path: "/eventType/:id", Handler: server.handleDeleteEventType},

		{Verb: "GET", Path: "/event/:id", Handler: server.handleGetEvent},
		{Verb: "GET", Path: "/event", Handler: server.handleGetAllEvents},
		{Verb: "POST", Path: "/event", Handler: server.handlePostEvent},
		{Verb: "POST", Path: "/event/query", Handler: server.handleEventQuery},
		{Verb: "DELETE", Path: "/event/:id", Handler: server.handleDeleteEvent},

		{Verb: "GET", Path: "/trigger/:id", Handler: server.handleGetTrigger},
		{Verb: "GET", Path: "/trigger", Handler: server.handleGetAllTriggers},
		{Verb: "POST", Path: "/trigger", Handler: server.handlePostTrigger},
		{Verb: "PUT", Path: "/trigger/:id", Handler: server.handlePutTrigger},
		{Verb: "DELETE", Path: "/trigger/:id", Handler: server.handleDeleteTrigger},

		{Verb: "GET", Path: "/alert/:id", Handler: server.handleGetAlert},
		{Verb: "GET", Path: "/alert", Handler: server.handleGetAllAlerts},
		{Verb: "POST", Path: "/alert", Handler: server.handlePostAlert},
		{Verb: "DELETE", Path: "/alert/:id", Handler: server.handleDeleteAlert},

		{Verb: "GET", Path: "/admin/stats", Handler: server.handleGetStats},
	}

	server.origin = service.origin

	return nil
}

//---------------------------------------------------------------------------

func (server *Server) handleGetRoot(c *gin.Context) {
	message := "Hi! I'm pz-workflow."
	resp := &piazza.JsonResponse{StatusCode: http.StatusOK, Data: message}
	piazza.GinReturnJson(c, resp)
}

func (server *Server) handleGetVersion(c *gin.Context) {
	version := piazza.Version{Version: Version}
	resp := &piazza.JsonResponse{StatusCode: http.StatusOK, Data: version}
	piazza.GinReturnJson(c, resp)
}

func (server *Server) handleGetStats(c *gin.Context) {
	resp := server.service.GetStats()
	piazza.GinReturnJson(c, resp)
}

//---------------------------------------------------------------------------

func (server *Server) handleGetEventType(c *gin.Context) {
	id := piazza.Ident(c.Param("id"))
	resp := server.service.GetEventType(id)
	piazza.GinReturnJson(c, resp)
}

func (server *Server) handleGetAllEventTypes(c *gin.Context) {
	params := piazza.NewQueryParams(c.Request)
	resp := server.service.GetAllEventTypes(params)
	piazza.GinReturnJson(c, resp)
}

func (server *Server) handlePostEventType(c *gin.Context) {
	eventType := &EventType{}
	err := c.BindJSON(eventType)
	if err != nil {
		resp := &piazza.JsonResponse{
			StatusCode: http.StatusBadRequest,
			Message:    err.Error(),
			Origin:     server.origin,
		}
		piazza.GinReturnJson(c, resp)
		return
	}
	resp := server.service.PostEventType(eventType)
	piazza.GinReturnJson(c, resp)
}

func (server *Server) handleDeleteEventType(c *gin.Context) {
	id := piazza.Ident(c.Param("id"))
	resp := server.service.DeleteEventType(id)
	piazza.GinReturnJson(c, resp)
}

//---------------------------------------------------------------------------

func (server *Server) handleGetEvent(c *gin.Context) {
	id := piazza.Ident(c.Param("id"))
	resp := server.service.GetEvent(id)
	piazza.GinReturnJson(c, resp)
}

func (server *Server) handleGetAllEvents(c *gin.Context) {
	params := piazza.NewQueryParams(c.Request)
	resp := server.service.GetAllEvents(params)
	piazza.GinReturnJson(c, resp)
}

func (server *Server) handlePostEvent(c *gin.Context) {
	event := &Event{}
	err := c.BindJSON(event)
	if err != nil {
		resp := &piazza.JsonResponse{
			StatusCode: http.StatusBadRequest,
			Message:    err.Error(),
			Origin:     server.origin,
		}
		piazza.GinReturnJson(c, resp)
		return
	}

	var resp *piazza.JsonResponse

	if event.CronSchedule != "" {
		resp = server.service.PostRepeatingEvent(event)
	} else {
		resp = server.service.PostEvent(event)
	}
	piazza.GinReturnJson(c, resp)
}

func (server *Server) handleEventQuery(c *gin.Context) {
	buf := new(bytes.Buffer)
	_, err := buf.ReadFrom(c.Request.Body)
	if err != nil {
		resp := &piazza.JsonResponse{
			StatusCode: http.StatusBadRequest,
			Message:    err.Error(),
			Origin:     server.origin,
		}
		piazza.GinReturnJson(c, resp)
		return
	}

	jsonString := buf.String()
	params := piazza.NewQueryParams(c.Request)

	var resp *piazza.JsonResponse

	resp = server.service.QueryEvents(jsonString, params)
	piazza.GinReturnJson(c, resp)
}

func (server *Server) handleDeleteEvent(c *gin.Context) {
	id := piazza.Ident(c.Param("id"))
	resp := server.service.DeleteEvent(id)
	piazza.GinReturnJson(c, resp)
}

//---------------------------------------------------------------------------

func (server *Server) handleGetTrigger(c *gin.Context) {
	id := piazza.Ident(c.Param("id"))
	resp := server.service.GetTrigger(id)
	piazza.GinReturnJson(c, resp)
}

func (server *Server) handleGetAllTriggers(c *gin.Context) {
	params := piazza.NewQueryParams(c.Request)
	resp := server.service.GetAllTriggers(params)
	piazza.GinReturnJson(c, resp)
}

func (server *Server) handlePostTrigger(c *gin.Context) {
	trigger := &Trigger{Enabled: true}
	err := c.BindJSON(trigger)
	if err != nil {
		resp := &piazza.JsonResponse{
			StatusCode: http.StatusBadRequest,
			Message:    err.Error(),
			Origin:     server.origin,
		}
		piazza.GinReturnJson(c, resp)
		return
	}
	resp := server.service.PostTrigger(trigger)
	piazza.GinReturnJson(c, resp)
}

func (server *Server) handlePutTrigger(c *gin.Context) {
	id := piazza.Ident(c.Param("id"))
	update := &TriggerUpdate{}
	err := c.BindJSON(update)
	if err != nil {
		resp := &piazza.JsonResponse{
			StatusCode: http.StatusBadRequest,
			Message:    err.Error(),
			Origin:     server.origin,
		}
		piazza.GinReturnJson(c, resp)
		return
	}
	resp := server.service.PutTrigger(id, update)
	piazza.GinReturnJson(c, resp)
}

func (server *Server) handleDeleteTrigger(c *gin.Context) {
	id := piazza.Ident(c.Param("id"))
	resp := server.service.DeleteTrigger(id)
	piazza.GinReturnJson(c, resp)
}

//---------------------------------------------------------------------------

func (server *Server) handleGetAlert(c *gin.Context) {
	id := piazza.Ident(c.Param("id"))
	resp := server.service.GetAlert(id)
	piazza.GinReturnJson(c, resp)
}

func (server *Server) handleGetAllAlerts(c *gin.Context) {
	params := piazza.NewQueryParams(c.Request)
	resp := server.service.GetAllAlerts(params)
	piazza.GinReturnJson(c, resp)
}

func (server *Server) handlePostAlert(c *gin.Context) {
	alert := &Alert{}
	err := c.BindJSON(alert)
	if err != nil {
		resp := &piazza.JsonResponse{
			StatusCode: http.StatusBadRequest,
			Message:    err.Error(),
			Origin:     server.origin,
		}
		piazza.GinReturnJson(c, resp)
		return
	}
	resp := server.service.PostAlert(alert)
	piazza.GinReturnJson(c, resp)
}

func (server *Server) handleDeleteAlert(c *gin.Context) {
	id := piazza.Ident(c.Param("id"))
	resp := server.service.DeleteAlert(id)
	piazza.GinReturnJson(c, resp)
}
<|endoftext|>


<commit_before>package workers

import (
	"fmt"
	"github.com/APTrust/exchange/config"
	"github.com/APTrust/exchange/context"
	"github.com/APTrust/exchange/constants"
	"github.com/APTrust/exchange/models"
	"github.com/APTrust/exchange/util"
	"github.com/APTrust/exchange/util/fileutil"
)

type BagValidator struct {
	Context              *context.Context
	PathToBag            string
	BagValidationConfig  *config.BagValidationConfig
	virtualBag           *models.VirtualBag
	validationSummary    *models.WorkSummary
	intelObj             *models.IntellectualObject
}

// NewBagValidator creates a new BagValidator. Param pathToBag
// should be an absolute path to either the tarred bag (.tar file)
// or to the untarred bag (a directory). Param bagValidationConfig
// defines what we need to validate, in addition to the checksums in the
// manifests.
func NewBagValidator(_context *context.Context, pathToBag string, bagValidationConfig *config.BagValidationConfig) (*BagValidator, error) {
	if _context == nil {
		return nil, fmt.Errorf("Context cannot be nil")
	}
	if !fileutil.FileExists(pathToBag) {
		return nil, fmt.Errorf("Bag does not exist at %s", pathToBag)
	}
	if bagValidationConfig == nil {
		return nil, fmt.Errorf("Param bagValidationConfig cannot be nil")
	}
	calculateMd5 := util.StringListContains(bagValidationConfig.FixityAlgorithms, constants.AlgMd5)
	calculateSha256 := util.StringListContains(bagValidationConfig.FixityAlgorithms, constants.AlgSha256)
	tagFilesToParse := make([]string, 0)
	for pathToFile, filespec := range bagValidationConfig.FileSpecs {
		if filespec.ParseAsTagFile {
			tagFilesToParse = append(tagFilesToParse, pathToFile)
		}
	}
	bagValidator := &BagValidator{
		Context: _context,
		PathToBag: pathToBag,
		BagValidationConfig: bagValidationConfig,
	    virtualBag: models.NewVirtualBag(pathToBag, tagFilesToParse, calculateMd5, calculateSha256),
	}
	return bagValidator, nil
}

// Reads the bag, produces a list of generic files, parses tags,
// and calculates checksums, producing an IntellectualObject.
// Call Validator.Validate() after this if you want to validate
// the bag. Returns a WorkSummary describing any issues with the
// read operation, which may fail if the directory can't be read,
// if the tar file is corrupt, etc.
func (validator *BagValidator) ReadBag() (*models.WorkSummary) {
	var vbagSummary *models.WorkSummary
	validator.intelObj, vbagSummary = validator.virtualBag.Read()
	return vbagSummary
}

// Validates the bag and returns a WorkSummary.
// You must call Validator.Read() before calling this, since
// the read operation reads the bag and sets up the IntellectualObject.
// This returns a WorkSummary describing any validation problems.
func (validator *BagValidator) Validate() (*models.WorkSummary) {
	validator.validationSummary = models.NewWorkSummary()
	validator.validationSummary.Start()
	if validator.intelObj == nil {
		validator.validationSummary.AddError("IntellectualObject is nil; cannot validate.")
	} else {
		validator.verifyFileSpecs()
		validator.verifyTagSpecs()
		validator.verifyChecksums()
	}
	validator.validationSummary.Finish()
	return validator.validationSummary
}

func (validator *BagValidator) verifyFileSpecs() {
	for gfPath, fileSpec := range validator.BagValidationConfig.FileSpecs {
		gf := validator.intelObj.FindGenericFile(gfPath)
		if gf == nil && fileSpec.Presence == config.REQUIRED {
			validator.validationSummary.AddError("Required file '%s' is missing.", gfPath)
		} else if gf != nil && fileSpec.Presence == config.FORBIDDEN {
			validator.validationSummary.AddError("Bag contains forbidden file '%s'.", gfPath)
		}
	}
}

func (validator *BagValidator) verifyTagSpecs() {
	for tagName, tagSpec := range validator.BagValidationConfig.TagSpecs {
		tags := obj.FindTag(tagName)
		if tagSpec.Presence == config.FORBIDDEN {
			validator.validationSummary.AddError("Forbidden tag '%s' found in file '%s'.", tagName, tag.FilePath)
			continue
		}
		if tagSpec.Presence == config.REQUIRED {
			validator.checkRequiredTag(tagName, tags, tagSpec)
		}
		if tag != nil && tagSpec.AllowedValues != nil && len(tagSpec.AllowedValues) > 0 {
			validator.checkAllowedValue(tagName, tags, tagSpec)
		}
	}
}

func (validator *BagValidator) checkRequiredTag(tagName string, tags []*models.Tag, tagSpec *models.TagSpec) {
	if tags == nil {
		validator.validationSummary.AddError("Required tag '%s' is missing.", tagName)
		continue
	}
	if !tagSpec.EmptyOK {
		tagHasValue := false
		for _, tag := range tags {
			if tag.Value != "" {
				tagHasValue = true
				break
			}
		}
		if !tagHasValue {
			validator.validationSummary.AddError("Value for tag '%s' is missing.", tagName)
		}
	}
}

func (validator *BagValidator) checkAllowedTagValue(tagName string, tags []*models.Tag, tagSpec *models.TagSpec) {
	for _, value := range tagSpec.AllowedValues {
		for _, tag := range tags {
			lcValue := strings.TrimSpace(strings.ToLower(value))
			tagValue := strings.TrimSpace(strings.ToLower(tag.Value))
			if lcValue != tagValue {
				validator.validationSummary.AddError("Tag '%s' has illegal value '%s'.",
					tagName, tag.Value)
			}
		}
	}
}

func (validator *BagValidator) verifyChecksums() {
	// TODO: START HERE
}
<commit_msg>Interim commit. Working on BagValidator<commit_after>package workers

import (
	"fmt"
	"github.com/APTrust/exchange/config"
	"github.com/APTrust/exchange/context"
	"github.com/APTrust/exchange/constants"
	"github.com/APTrust/exchange/models"
	"github.com/APTrust/exchange/util"
	"github.com/APTrust/exchange/util/fileutil"
	"strings"
)

type BagValidator struct {
	Context              *context.Context
	PathToBag            string
	BagValidationConfig  *config.BagValidationConfig
	virtualBag           *models.VirtualBag
	validationSummary    *models.WorkSummary
	intelObj             *models.IntellectualObject
}

// NewBagValidator creates a new BagValidator. Param pathToBag
// should be an absolute path to either the tarred bag (.tar file)
// or to the untarred bag (a directory). Param bagValidationConfig
// defines what we need to validate, in addition to the checksums in the
// manifests.
func NewBagValidator(_context *context.Context, pathToBag string, bagValidationConfig *config.BagValidationConfig) (*BagValidator, error) {
	if _context == nil {
		return nil, fmt.Errorf("Context cannot be nil")
	}
	if !fileutil.FileExists(pathToBag) {
		return nil, fmt.Errorf("Bag does not exist at %s", pathToBag)
	}
	if bagValidationConfig == nil {
		return nil, fmt.Errorf("Param bagValidationConfig cannot be nil")
	}
	calculateMd5 := util.StringListContains(bagValidationConfig.FixityAlgorithms, constants.AlgMd5)
	calculateSha256 := util.StringListContains(bagValidationConfig.FixityAlgorithms, constants.AlgSha256)
	tagFilesToParse := make([]string, 0)
	for pathToFile, filespec := range bagValidationConfig.FileSpecs {
		if filespec.ParseAsTagFile {
			tagFilesToParse = append(tagFilesToParse, pathToFile)
		}
	}
	bagValidator := &BagValidator{
		Context: _context,
		PathToBag: pathToBag,
		BagValidationConfig: bagValidationConfig,
	    virtualBag: models.NewVirtualBag(pathToBag, tagFilesToParse, calculateMd5, calculateSha256),
	}
	return bagValidator, nil
}

// Reads the bag, produces a list of generic files, parses tags,
// and calculates checksums, producing an IntellectualObject.
// Call Validator.Validate() after this if you want to validate
// the bag. Returns a WorkSummary describing any issues with the
// read operation, which may fail if the directory can't be read,
// if the tar file is corrupt, etc.
func (validator *BagValidator) ReadBag() (*models.IntellectualObject, *models.WorkSummary) {
	var vbagSummary *models.WorkSummary
	validator.intelObj, vbagSummary = validator.virtualBag.Read()
	return validator.intelObj, vbagSummary
}

// Validates the bag and returns a WorkSummary.
// You must call Validator.Read() before calling this, since
// the read operation reads the bag and sets up the IntellectualObject.
// This returns a WorkSummary describing any validation problems.
func (validator *BagValidator) Validate() (*models.WorkSummary) {
	validator.validationSummary = models.NewWorkSummary()
	validator.validationSummary.Start()
	if validator.intelObj == nil {
		validator.validationSummary.AddError(
			"IntellectualObject is nil; cannot validate. Did you call Read() first?")
	} else {
		validator.verifyFileSpecs()
		validator.verifyTagSpecs()
		validator.verifyChecksums()
	}
	validator.validationSummary.Finish()
	return validator.validationSummary
}

func (validator *BagValidator) verifyFileSpecs() {
	for gfPath, fileSpec := range validator.BagValidationConfig.FileSpecs {
		gf := validator.intelObj.FindGenericFile(gfPath)
		if gf == nil && fileSpec.Presence == config.REQUIRED {
			validator.validationSummary.AddError("Required file '%s' is missing.", gfPath)
		} else if gf != nil && fileSpec.Presence == config.FORBIDDEN {
			validator.validationSummary.AddError("Bag contains forbidden file '%s'.", gfPath)
		}
	}
}

func (validator *BagValidator) verifyTagSpecs() {
	for tagName, tagSpec := range validator.BagValidationConfig.TagSpecs {
		tags := validator.intelObj.FindTag(tagName)
		if tagSpec.Presence == config.FORBIDDEN {
			validator.validationSummary.AddError(
				"Forbidden tag '%s' found in file '%s'.", tagName, tags[0].SourceFile)
			continue
		}
		if tagSpec.Presence == config.REQUIRED {
			validator.checkRequiredTag(tagName, tags, tagSpec)
		}
		if tags != nil && tagSpec.AllowedValues != nil && len(tagSpec.AllowedValues) > 0 {
			validator.checkAllowedTagValue(tagName, tags, tagSpec)
		}
	}
}

func (validator *BagValidator) checkRequiredTag(tagName string, tags []*models.Tag, tagSpec config.TagSpec) {
	if tags == nil {
		validator.validationSummary.AddError("Required tag '%s' is missing.", tagName)
		return
	}
	if !tagSpec.EmptyOK {
		tagHasValue := false
		for _, tag := range tags {
			if tag.Value != "" {
				tagHasValue = true
				break
			}
		}
		if !tagHasValue {
			validator.validationSummary.AddError("Value for tag '%s' is missing.", tagName)
		}
	}
}

func (validator *BagValidator) checkAllowedTagValue(tagName string, tags []*models.Tag, tagSpec config.TagSpec) {
	for _, value := range tagSpec.AllowedValues {
		for _, tag := range tags {
			lcValue := strings.TrimSpace(strings.ToLower(value))
			tagValue := strings.TrimSpace(strings.ToLower(tag.Value))
			if lcValue != tagValue {
				validator.validationSummary.AddError("Tag '%s' has illegal value '%s'.",
					tagName, tag.Value)
			}
		}
	}
}

func (validator *BagValidator) verifyChecksums() {
	// TODO: START HERE
}
<|endoftext|>


<commit_before>package util

import (
	"fmt"
	"io"
	"os"
	"strings"

	"github.com/mundipagg/boleto-api/config"
)

func ListCert() error {

	list := []string{
		config.Get().CertBoletoPathCrt,
		config.Get().CertBoletoPathKey,
		config.Get().CertBoletoPathCa,
		config.Get().CertICP_PathPkey,
		config.Get().CertICP_PathChainCertificates,
	}

	var err error

	for _, v := range list {

		fmt.Println(v)
		err = copyCert(v)

		if err != nil {
			return err
		}

	}

	return err

}

func copyCert(c string) error {
	execPath, _ := os.Getwd()

	f := strings.Split(c, "/")

	fName := f[len(f)-1]

	srcFile, err := os.Open(execPath + "/boleto_orig/" + fName)
	if err != nil {
		fmt.Println("Error:", err.Error())
		return err
	}
	defer srcFile.Close()

	destFile, err := os.Create(execPath + "/boleto_cert/" + fName)
	if err != nil {
		fmt.Println("Error:", err.Error())
		return err
	}
	defer destFile.Close()

	_, err = io.Copy(destFile, srcFile)
	if err != nil {
		fmt.Println("Error:", err.Error())
		return err
	}

	err = destFile.Sync()
	if err != nil {
		fmt.Println("Error:", err.Error())
		return err
	}

	err = os.Chmod(execPath+"/boleto_cert/"+fName, 0777)
	if err != nil {
		fmt.Println("Error: ", err.Error())
		return err
	}

	return err
}
<commit_msg>:recycle: Ajusta destwd para variavel<commit_after>package util

import (
	"fmt"
	"io"
	"os"
	"strings"

	"github.com/mundipagg/boleto-api/config"
)

func ListCert() error {

	list := []string{
		config.Get().CertBoletoPathCrt,
		config.Get().CertBoletoPathKey,
		config.Get().CertBoletoPathCa,
		config.Get().CertICP_PathPkey,
		config.Get().CertICP_PathChainCertificates,
	}

	var err error

	for _, v := range list {

		err = copyCert(v)

		if err != nil {
			return err
		}

	}

	return err

}

func copyCert(c string) error {
	execPath, _ := os.Getwd()

	f := strings.Split(c, "/")

	fName := f[len(f)-1]

	destwd := fmt.Sprintf("%s/boleto_cert/%s", execPath, fName)

	srcFile, err := os.Open(execPath + "/boleto_orig/" + fName)
	if err != nil {
		fmt.Println("Error:", err.Error())
		return err
	}
	defer srcFile.Close()

	destFile, err := os.Create(destwd)
	if err != nil {
		fmt.Println("Error:", err.Error())
		return err
	}
	defer destFile.Close()

	_, err = io.Copy(destFile, srcFile)
	if err != nil {
		fmt.Println("Error:", err.Error())
		return err
	}

	err = destFile.Sync()
	if err != nil {
		fmt.Println("Error:", err.Error())
		return err
	}

	err = os.Chmod(destwd, 0777)
	if err != nil {
		fmt.Println("Error: ", err.Error())
		return err
	}

	fmt.Println("Cert Copy Sucessful: ", destwd)

	return err
}
<|endoftext|>


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

package util

import (
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"
	"runtime"
	"strings"
	"testing"
	"time"

	git "github.com/libgit2/git2go"
)

var TimeTrackEnable = false

//TimeTrack is used for profiling execution time
func TimeTrack(start time.Time, name string) {
	if TimeTrackEnable {
		elapsed := time.Since(start)
		log.Printf("%s took %s", name, elapsed)
	}
}

// TestRepo represents a test git repo used in testing
type TestRepo struct {
	repo *git.Repository
	test *testing.T
}

// NewTestRepo creates a new instance of TestRepo
func NewTestRepo(t *testing.T, bare bool) TestRepo {
	path, err := ioutil.TempDir("", "gtm")
	CheckFatal(t, err)
	repo, err := git.InitRepository(path, bare)
	CheckFatal(t, err)
	return TestRepo{repo: repo, test: t}
}

// Seed creates test data for the git repo
func (t TestRepo) Seed() {
	t.SaveFile("README", "", "foo\n")
	treeOid := t.Stage("README")
	t.Commit(treeOid)
	return
}

// Remove deletes temp directories, files and git repo
func (t TestRepo) Remove() {
	var repoPath string

	if t.repo.IsBare() {
		repoPath = t.repo.Path()
	} else {
		repoPath = t.repo.Workdir()
	}

	// assert it's in a temp dir just in case
	if !strings.Contains(filepath.Clean(repoPath), filepath.Clean(os.TempDir())) {
		CheckFatal(t.test, fmt.Errorf("Unable to remove, repoPath %s is not within %s", repoPath, os.TempDir()))
		return
	}

	err := os.RemoveAll(repoPath)
	if err != nil {
		// this could be just the issue with Windows os.RemoveAll() and privileges, ignore
		fmt.Fprintln(os.Stderr, err)
	}
	t.repo.Free()

	return
}

// PathIn returns full path of file within repo
func (t TestRepo) PathIn(name string) string {
	return filepath.ToSlash(filepath.Join(filepath.Dir(filepath.Dir(t.repo.Path())), name))
}

// Stage adds files to staging for git repo
func (t TestRepo) Stage(files ...string) *git.Oid {
	idx, err := t.repo.Index()
	CheckFatal(t.test, err)
	for _, f := range files {
		err = idx.AddByPath(filepath.ToSlash(f))
		CheckFatal(t.test, err)
	}
	treeID, err := idx.WriteTreeTo(t.repo)
	CheckFatal(t.test, err)
	err = idx.Write()
	CheckFatal(t.test, err)
	return treeID
}

// Commit commits staged files
func (t TestRepo) Commit(treeID *git.Oid) *git.Oid {
	loc, err := time.LoadLocation("America/Chicago")
	CheckFatal(t.test, err)
	sig := &git.Signature{
		Name:  "Rand Om Hacker",
		Email: "random@hacker.com",
		When:  time.Date(2013, 03, 06, 14, 30, 0, 0, loc),
	}

	headUnborn, err := t.repo.IsHeadUnborn()
	CheckFatal(t.test, err)
	var currentTip *git.Commit

	if !headUnborn {
		currentBranch, err := t.repo.Head()
		CheckFatal(t.test, err)
		currentTip, err = t.repo.LookupCommit(currentBranch.Target())
		CheckFatal(t.test, err)
	}

	message := "This is a commit\n"
	tree, err := t.repo.LookupTree(treeID)
	CheckFatal(t.test, err)

	var commitID *git.Oid
	if headUnborn {
		commitID, err = t.repo.CreateCommit("HEAD", sig, sig, message, tree)
	} else {
		commitID, err = t.repo.CreateCommit("HEAD", sig, sig, message, tree,
			currentTip)
	}
	CheckFatal(t.test, err)

	return commitID
}

// SaveFile creates a file within the git repo project
func (t TestRepo) SaveFile(filename, subdir, content string) {
	d := filepath.Join(t.PathIn(""), subdir)
	err := os.MkdirAll(d, 0700)
	CheckFatal(t.test, err)
	err = ioutil.WriteFile(filepath.Join(d, filename), []byte(content), 0644)
	CheckFatal(t.test, err)
}

// CheckFatal raises a fatal error if error is not nil
func CheckFatal(t *testing.T, err error) {
	if err == nil {
		return
	}

	// The failure happens at wherever we were called, not here
	_, file, line, ok := runtime.Caller(1)
	if !ok {
		t.Fatalf("Unable to get caller")
	}
	t.Fatalf("Fail at %v:%v; %v", file, line, err)
}
<commit_msg>Remove git package alias<commit_after>// Copyright 2016 Michael Schenk. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package util

import (
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"
	"runtime"
	"strings"
	"testing"
	"time"

	"github.com/libgit2/git2go"
)

var TimeTrackEnable = false

//TimeTrack is used for profiling execution time
func TimeTrack(start time.Time, name string) {
	if TimeTrackEnable {
		elapsed := time.Since(start)
		log.Printf("%s took %s", name, elapsed)
	}
}

// TestRepo represents a test git repo used in testing
type TestRepo struct {
	repo *git.Repository
	test *testing.T
}

// NewTestRepo creates a new instance of TestRepo
func NewTestRepo(t *testing.T, bare bool) TestRepo {
	path, err := ioutil.TempDir("", "gtm")
	CheckFatal(t, err)
	repo, err := git.InitRepository(path, bare)
	CheckFatal(t, err)
	return TestRepo{repo: repo, test: t}
}

// Seed creates test data for the git repo
func (t TestRepo) Seed() {
	t.SaveFile("README", "", "foo\n")
	treeOid := t.Stage("README")
	t.Commit(treeOid)
	return
}

// Remove deletes temp directories, files and git repo
func (t TestRepo) Remove() {
	var repoPath string

	if t.repo.IsBare() {
		repoPath = t.repo.Path()
	} else {
		repoPath = t.repo.Workdir()
	}

	// assert it's in a temp dir just in case
	if !strings.Contains(filepath.Clean(repoPath), filepath.Clean(os.TempDir())) {
		CheckFatal(t.test, fmt.Errorf("Unable to remove, repoPath %s is not within %s", repoPath, os.TempDir()))
		return
	}

	err := os.RemoveAll(repoPath)
	if err != nil {
		// this could be just the issue with Windows os.RemoveAll() and privileges, ignore
		fmt.Fprintln(os.Stderr, err)
	}
	t.repo.Free()

	return
}

// PathIn returns full path of file within repo
func (t TestRepo) PathIn(name string) string {
	return filepath.ToSlash(filepath.Join(filepath.Dir(filepath.Dir(t.repo.Path())), name))
}

// Stage adds files to staging for git repo
func (t TestRepo) Stage(files ...string) *git.Oid {
	idx, err := t.repo.Index()
	CheckFatal(t.test, err)
	for _, f := range files {
		err = idx.AddByPath(filepath.ToSlash(f))
		CheckFatal(t.test, err)
	}
	treeID, err := idx.WriteTreeTo(t.repo)
	CheckFatal(t.test, err)
	err = idx.Write()
	CheckFatal(t.test, err)
	return treeID
}

// Commit commits staged files
func (t TestRepo) Commit(treeID *git.Oid) *git.Oid {
	loc, err := time.LoadLocation("America/Chicago")
	CheckFatal(t.test, err)
	sig := &git.Signature{
		Name:  "Rand Om Hacker",
		Email: "random@hacker.com",
		When:  time.Date(2013, 03, 06, 14, 30, 0, 0, loc),
	}

	headUnborn, err := t.repo.IsHeadUnborn()
	CheckFatal(t.test, err)
	var currentTip *git.Commit

	if !headUnborn {
		currentBranch, err := t.repo.Head()
		CheckFatal(t.test, err)
		currentTip, err = t.repo.LookupCommit(currentBranch.Target())
		CheckFatal(t.test, err)
	}

	message := "This is a commit\n"
	tree, err := t.repo.LookupTree(treeID)
	CheckFatal(t.test, err)

	var commitID *git.Oid
	if headUnborn {
		commitID, err = t.repo.CreateCommit("HEAD", sig, sig, message, tree)
	} else {
		commitID, err = t.repo.CreateCommit("HEAD", sig, sig, message, tree,
			currentTip)
	}
	CheckFatal(t.test, err)

	return commitID
}

// SaveFile creates a file within the git repo project
func (t TestRepo) SaveFile(filename, subdir, content string) {
	d := filepath.Join(t.PathIn(""), subdir)
	err := os.MkdirAll(d, 0700)
	CheckFatal(t.test, err)
	err = ioutil.WriteFile(filepath.Join(d, filename), []byte(content), 0644)
	CheckFatal(t.test, err)
}

// CheckFatal raises a fatal error if error is not nil
func CheckFatal(t *testing.T, err error) {
	if err == nil {
		return
	}

	// The failure happens at wherever we were called, not here
	_, file, line, ok := runtime.Caller(1)
	if !ok {
		t.Fatalf("Unable to get caller")
	}
	t.Fatalf("Fail at %v:%v; %v", file, line, err)
}
<|endoftext|>


<commit_before>package fuse

import (
	"os"
	"sync"

	"bazil.org/fuse"
	"bazil.org/fuse/fs"
	pfsclient "github.com/pachyderm/pachyderm/src/client/pfs"
)

const (
	namePrefix = "pfs://"
	subtype    = "pfs"
)

type mounter struct {
	address   string
	apiClient pfsclient.APIClient
}

func newMounter(address string, apiClient pfsclient.APIClient) Mounter {
	return &mounter{
		address,
		apiClient,
	}
}

func (m *mounter) Mount(
	mountPoint string,
	shard *pfsclient.Shard,
	commitMounts []*CommitMount,
	ready chan bool,
) (retErr error) {
	var once sync.Once
	defer once.Do(func() {
		if ready != nil {
			close(ready)
		}
	})
	// TODO: should we make the caller do this?
	if err := os.MkdirAll(mountPoint, 0777); err != nil {
		return err
	}
	name := namePrefix + m.address
	conn, err := fuse.Mount(
		mountPoint,
		fuse.FSName(name),
		fuse.VolumeName(name),
		fuse.Subtype(subtype),
		fuse.AllowOther(),
		fuse.WritebackCache(),
		fuse.MaxReadahead(1<<32-1),
	)
	if err != nil {
		return err
	}
	defer func() {
		if err := conn.Close(); err != nil && retErr == nil {
			retErr = err
		}
	}()
	once.Do(func() {
		if ready != nil {
			close(ready)
		}
	})
	if err := fs.Serve(conn, newFilesystem(m.apiClient, shard, commitMounts)); err != nil {
		return err
	}
	<-conn.Ready
	return conn.MountError
}

func (m *mounter) Unmount(mountPoint string) error {
	return fuse.Unmount(mountPoint)
}
<commit_msg>Adds fuse debug printing.<commit_after>package fuse

import (
	"encoding/json"
	"os"
	"sync"

	"bazil.org/fuse"
	"bazil.org/fuse/fs"
	pfsclient "github.com/pachyderm/pachyderm/src/client/pfs"
	"go.pedge.io/lion"
)

const (
	namePrefix = "pfs://"
	subtype    = "pfs"
)

type mounter struct {
	address   string
	apiClient pfsclient.APIClient
}

func newMounter(address string, apiClient pfsclient.APIClient) Mounter {
	return &mounter{
		address,
		apiClient,
	}
}

func (m *mounter) Mount(
	mountPoint string,
	shard *pfsclient.Shard,
	commitMounts []*CommitMount,
	ready chan bool,
) (retErr error) {
	var once sync.Once
	defer once.Do(func() {
		if ready != nil {
			close(ready)
		}
	})
	// TODO: should we make the caller do this?
	if err := os.MkdirAll(mountPoint, 0777); err != nil {
		return err
	}
	name := namePrefix + m.address
	conn, err := fuse.Mount(
		mountPoint,
		fuse.FSName(name),
		fuse.VolumeName(name),
		fuse.Subtype(subtype),
		fuse.AllowOther(),
		fuse.WritebackCache(),
		fuse.MaxReadahead(1<<32-1),
	)
	if err != nil {
		return err
	}
	defer func() {
		if err := conn.Close(); err != nil && retErr == nil {
			retErr = err
		}
	}()
	once.Do(func() {
		if ready != nil {
			close(ready)
		}
	})
	config := &fs.Config{Debug: debug}
	if err := fs.New(conn, config).Serve(newFilesystem(m.apiClient, shard, commitMounts)); err != nil {
		return err
	}
	<-conn.Ready
	return conn.MountError
}

func debug(msg interface{}) {
	marshalled, err := json.Marshal(msg)
	if err != nil {
		lion.Printf("error from json.Marshal: %s", err.Error())
	}
	lion.Printf(string(marshalled))
}

func (m *mounter) Unmount(mountPoint string) error {
	return fuse.Unmount(mountPoint)
}
<|endoftext|>


<commit_before>package vm

import (
	"../types"
	"sync"
	"sync/atomic"
)

type State uint32

const (
	VALUE State = iota
	LOCKED
	APP
)

type Thunk struct {
	result, function, args types.Object
	state                  State
	blackHole              sync.WaitGroup
}

func (t *Thunk) Wait() {
	t.blackHole.Wait()
}

func (t *Thunk) SaveResult(o types.Object) {
	if t.state != LOCKED {
		panic("Thunk is not locked yet.")
	}

	t.result = o
	t.function = nil
	t.args = nil

	t.storeState(VALUE)
}

func (t *Thunk) storeState(new State) {
	atomic.StoreUint32((*uint32)(&t.state), uint32(new))
}
<commit_msg>Update thunk.go<commit_after>package vm

import (
	"../types"
	"sync"
	"sync/atomic"
)

type State uint32

const (
	VALUE State = iota
	LOCKED
	APP
)

type Thunk struct {
	result, function, args types.Object
	state                  State
	blackHole              sync.WaitGroup
}

func NewValueThunk(v types.Object) *Thunk {
	return &Thunk{result: v, state: VALUE}
}

func NewAppThunk(f types.Object, as types.Object) *Thunk {
	return &Thunk{function: f, args: as, state: APP}
}

func (t *Thunk) Wait() {
	t.blackHole.Wait()
}

func (t *Thunk) Lock() bool {
	return t.compareAndSwapState(APP, LOCKED)
}

func (t *Thunk) SaveResult(o types.Object) {
	if t.state != LOCKED {
		panic("Thunk is not locked yet.")
	}

	t.result = o
	t.function = nil
	t.args = nil

	t.storeState(VALUE)
}

func (t *Thunk) compareAndSwapState(old, new State) bool {
	return atomic.CompareAndSwapUint32((*uint32)(&t.state), uint32(old), uint32(new))
}

func (t *Thunk) storeState(new State) {
	atomic.StoreUint32((*uint32)(&t.state), uint32(new))
}
<|endoftext|>


<commit_before>package spf

import "strings"

const (
	// SpfPrexif is a constant value for term indicating start of the SPF query
	spfPrefix     = "v=spf1 "
	spfPrefixTrim = "v=spf1"

	Nameserver = "172.17.0.3:53"
)

func checkSPFVersion(spf []string) bool {
	if len(spf) == 0 {
		return false
	}

	first := spf[0]

	if len(first) >= len(spfPrefix) && strings.HasPrefix(first, spfPrefix) {
		return true
	}

	if len(first) == len(spfPrefixTrim) && first == spfPrefixTrim {
		return true
	}

	return false
}

// IsDomainName is a 1:1 copy of implementation from
// original golang codebase:
// https://github.com/golang/go/blob/master/src/net/dnsclient.go#L116
// It validates s string for conditions specified in RFC 1035 and RFC 3696
func IsDomainName(s string) bool {
	// See RFC 1035, RFC 3696.
	if len(s) == 0 {
		return false
	}
	if len(s) > 255 {
		return false
	}

	last := byte('.')
	ok := false // Ok once we've seen a letter.
	partlen := 0
	for i := 0; i < len(s); i++ {
		c := s[i]
		switch {
		default:
			return false
		case 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z' || c == '_':
			ok = true
			partlen++
		case '0' <= c && c <= '9':
			// fine
			partlen++
		case c == '-':
			// Byte before dash cannot be dot.
			if last == '.' {
				return false
			}
			partlen++
		case c == '.':
			// Byte before dot cannot be dot, dash.
			if last == '.' || last == '-' {
				return false
			}
			if partlen > 63 || partlen == 0 {
				return false
			}
			partlen = 0
		}
		last = c
	}
	if last == '-' || partlen > 63 {
		return false
	}

	return ok
}

// NormalizeHost appends a root domain (a dot) to the FQDN.
func NormalizeHost(host string) string {
	if isEmpty(&host) {
		return "."
	}
	if host[len(host)-1] != '.' {
		return host + "."
	}
	return host
}
<commit_msg>Add comment to exported const Nameserver.<commit_after>package spf

import "strings"

const (
	// SpfPrexif is a constant value for term indicating start of the SPF query
	spfPrefix     = "v=spf1 "
	spfPrefixTrim = "v=spf1"

	// Nameserver is a constant defining entrypoint of the DNS server.
	// In the future this value should be configurable
	Nameserver = "172.17.0.3:53"
)

func checkSPFVersion(spf []string) bool {
	if len(spf) == 0 {
		return false
	}

	first := spf[0]

	if len(first) >= len(spfPrefix) && strings.HasPrefix(first, spfPrefix) {
		return true
	}

	if len(first) == len(spfPrefixTrim) && first == spfPrefixTrim {
		return true
	}

	return false
}

// IsDomainName is a 1:1 copy of implementation from
// original golang codebase:
// https://github.com/golang/go/blob/master/src/net/dnsclient.go#L116
// It validates s string for conditions specified in RFC 1035 and RFC 3696
func IsDomainName(s string) bool {
	// See RFC 1035, RFC 3696.
	if len(s) == 0 {
		return false
	}
	if len(s) > 255 {
		return false
	}

	last := byte('.')
	ok := false // Ok once we've seen a letter.
	partlen := 0
	for i := 0; i < len(s); i++ {
		c := s[i]
		switch {
		default:
			return false
		case 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z' || c == '_':
			ok = true
			partlen++
		case '0' <= c && c <= '9':
			// fine
			partlen++
		case c == '-':
			// Byte before dash cannot be dot.
			if last == '.' {
				return false
			}
			partlen++
		case c == '.':
			// Byte before dot cannot be dot, dash.
			if last == '.' || last == '-' {
				return false
			}
			if partlen > 63 || partlen == 0 {
				return false
			}
			partlen = 0
		}
		last = c
	}
	if last == '-' || partlen > 63 {
		return false
	}

	return ok
}

// NormalizeHost appends a root domain (a dot) to the FQDN.
func NormalizeHost(host string) string {
	if isEmpty(&host) {
		return "."
	}
	if host[len(host)-1] != '.' {
		return host + "."
	}
	return host
}
<|endoftext|>