<commit_before>package firego_test

import (
	"log"
	"time"

	"github.com/CloudCom/firego"
)

func ExampleFirebase_Auth() {
	fb := firego.New("https://someapp.firebaseio.com")
	fb.Auth("my-token")
}

func ExampleFirebase_Child() {
	fb := firego.New("https://someapp.firebaseio.com")
	childFB := fb.Child("some/child/path")

	log.Printf("My new ref %s\n", childFB)
}

func ExampleFirebase_Shallow() {
	fb := firego.New("https://someapp.firebaseio.com")
	// turn on
	fb.Shallow(true)
	// turn off
	fb.Shallow(false)
}

func ExampleFirebase_IncludePriority() {
	fb := firego.New("https://someapp.firebaseio.com")
	// turn on
	fb.IncludePriority(true)
	// turn off
	fb.IncludePriority(false)
}

func ExampleFirebase_Push() {
	fb := firego.New("https://someapp.firebaseio.com")
	newRef, err := fb.Push("my-value")
	if err != nil {
		log.Fatal(err)
	}

	log.Printf("My new ref %s\n", newRef)
}

func ExampleFirebase_Remove() {
	fb := firego.New("https://someapp.firebaseio.com/some/value")
	if err := fb.Remove(); err != nil {
		log.Fatal(err)
	}
}

func ExampleFirebase_Set() {
	fb := firego.New("https://someapp.firebaseio.com")

	v := map[string]interface{}{
		"foo": "bar",
		"bar": 1,
		"bez": []string{"hello", "world"},
	}
	if err := fb.Set(v); err != nil {
		log.Fatal(err)
	}
}

func ExampleFirebase_Update() {
	fb := firego.New("https://someapp.firebaseio.com/some/value")
	if err := fb.Update("new-value"); err != nil {
		log.Fatal(err)
	}
}

func ExampleFirebase_Value() {
	fb := firego.New("https://someapp.firebaseio.com/some/value")
	var v interface{}
	if err := fb.Value(v); err != nil {
		log.Fatal(err)
	}

	log.Printf("My value %v\n", v)
}

func ExampleFirebase_Watch() {
	fb := firego.New("https://someapp.firebaseio.com/some/value")
	notifications := make(chan firego.Event)
	if err := fb.Watch(notifications); err != nil {
		log.Fatal(err)
	}

	for event := range notifications {
		log.Println("Event Received")
		log.Printf("Type: %s\n", event.Type)
		log.Printf("Type: %s\n", event.Path)
		log.Printf("Type: %v\n", event.Data)
		if event.Type == firego.EventTypeError {
			log.Print("Error occurred, loop ending")
		}
	}
}

func ExampleFirebase_StopWatching() {
	fb := firego.New("https://someapp.firebaseio.com/some/value")
	notifications := make(chan firego.Event)
	if err := fb.Watch(notifications); err != nil {
		log.Fatal(err)
	}

	go func() {
		for _ = range notifications {
		}
		log.Println("Channel closed")
	}()
	time.Sleep(10 * time.Millisecond) // let go routine start

	fb.StopWatching()
}
<commit_msg>fixing docs<commit_after>package firego_test

import (
	"log"
	"time"

	"github.com/CloudCom/firego"
)

func ExampleFirebase_Auth() {
	fb := firego.New("https://someapp.firebaseio.com")
	fb.Auth("my-token")
}

func ExampleFirebase_Child() {
	fb := firego.New("https://someapp.firebaseio.com")
	childFB := fb.Child("some/child/path")

	log.Printf("My new ref %s\n", childFB)
}

func ExampleFirebase_Shallow() {
	fb := firego.New("https://someapp.firebaseio.com")
	// turn on
	fb.Shallow(true)
	// turn off
	fb.Shallow(false)
}

func ExampleFirebase_IncludePriority() {
	fb := firego.New("https://someapp.firebaseio.com")
	// turn on
	fb.IncludePriority(true)
	// turn off
	fb.IncludePriority(false)
}

func ExampleFirebase_Push() {
	fb := firego.New("https://someapp.firebaseio.com")
	newRef, err := fb.Push("my-value")
	if err != nil {
		log.Fatal(err)
	}

	log.Printf("My new ref %s\n", newRef)
}

func ExampleFirebase_Remove() {
	fb := firego.New("https://someapp.firebaseio.com/some/value")
	if err := fb.Remove(); err != nil {
		log.Fatal(err)
	}
}

func ExampleFirebase_Set() {
	fb := firego.New("https://someapp.firebaseio.com")

	v := map[string]interface{}{
		"foo": "bar",
		"bar": 1,
		"bez": []string{"hello", "world"},
	}
	if err := fb.Set(v); err != nil {
		log.Fatal(err)
	}
}

func ExampleFirebase_Update() {
	fb := firego.New("https://someapp.firebaseio.com/some/value")
	if err := fb.Update("new-value"); err != nil {
		log.Fatal(err)
	}
}

func ExampleFirebase_Value() {
	fb := firego.New("https://someapp.firebaseio.com/some/value")
	var v interface{}
	if err := fb.Value(v); err != nil {
		log.Fatal(err)
	}

	log.Printf("My value %v\n", v)
}

func ExampleFirebase_Watch() {
	fb := firego.New("https://someapp.firebaseio.com/some/value")
	notifications := make(chan firego.Event)
	if err := fb.Watch(notifications); err != nil {
		log.Fatal(err)
	}

	for event := range notifications {
		log.Println("Event Received")
		log.Printf("Type: %s\n", event.Type)
		log.Printf("Path: %s\n", event.Path)
		log.Printf("Data: %v\n", event.Data)
		if event.Type == firego.EventTypeError {
			log.Print("Error occurred, loop ending")
		}
	}
}

func ExampleFirebase_StopWatching() {
	fb := firego.New("https://someapp.firebaseio.com/some/value")
	notifications := make(chan firego.Event)
	if err := fb.Watch(notifications); err != nil {
		log.Fatal(err)
	}

	go func() {
		for _ = range notifications {
		}
		log.Println("Channel closed")
	}()
	time.Sleep(10 * time.Millisecond) // let go routine start

	fb.StopWatching()
}
<|endoftext|>


<commit_before>package shlex_test

import (
	"fmt"
	"log"

	"github.com/anmitsu/go-shlex"
)

func ExampleSplit() {
	cmd := `cp -Rdp "file name" 'file name2' dir\ name`

	words1, err := shlex.Split(cmd, true)
	if err != nil {
		log.Fatal(err)
	}
	words2, err := shlex.Split(cmd, false)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println("Source command:")
	fmt.Println(`cp -Rdp "file name" 'file name2' dir\ name`)
	fmt.Println()

	fmt.Println("POSIX mode:")
	for _, word := range words1 {
		fmt.Println(word)
	}
	fmt.Println()
	fmt.Println("Non-POSIX mode:")
	for _, word := range words2 {
		fmt.Println(word)
	}

	// Output:
	// Source command:
	// cp -Rdp "file name" 'file name2' dir\ name
	//
	// POSIX mode:
	// cp
	// -Rdp
	// file name
	// file name2
	// dir name
	//
	// Non-POSIX mode:
	// cp
	// -Rdp
	// "file name"
	// 'file name2'
	// dir\
	// name
}
<commit_msg>example: add comparison with github.com/flynn/go-shlex<commit_after>package shlex_test

import (
	"fmt"
	"log"

	"github.com/anmitsu/go-shlex"
	flynn_shlex "github.com/flynn/go-shlex"
)

func ExampleSplit() {
	cmd := `cp -Rdp "file name" 'file name2' dir\ name`

	// Split of cmd with POSIX mode.
	words1, err := shlex.Split(cmd, true)
	if err != nil {
		log.Fatal(err)
	}
	// Split of cmd with Non-POSIX mode.
	words2, err := shlex.Split(cmd, false)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println("Source command:")
	fmt.Println(`cp -Rdp "file name" 'file name2' dir\ name`)
	fmt.Println()

	fmt.Println("POSIX mode:")
	for _, word := range words1 {
		fmt.Println(word)
	}
	fmt.Println()
	fmt.Println("Non-POSIX mode:")
	for _, word := range words2 {
		fmt.Println(word)
	}

	// Output:
	// Source command:
	// cp -Rdp "file name" 'file name2' dir\ name
	//
	// POSIX mode:
	// cp
	// -Rdp
	// file name
	// file name2
	// dir name
	//
	// Non-POSIX mode:
	// cp
	// -Rdp
	// "file name"
	// 'file name2'
	// dir\
	// name
}

func ExampleSplit_compareFlynn() {
	cmd := `English and 日本語`

	// Split for github.com/flynn/go-shlex imported as flynn_shlex
	words_flynn, err1 := flynn_shlex.Split(cmd)

	// Split for github.com/anmitsu/go-shlex
	words_anmitsu, err2 := shlex.Split(cmd, true)

	fmt.Println("Source string:")
	fmt.Println(cmd)
	fmt.Println()

	fmt.Println("Result of github.com/flynn/go-shlex:")
	for _, word := range words_flynn {
		fmt.Println(word)
	}
	fmt.Println(err1.Error())

	fmt.Println()
	fmt.Println("Result of github.com/anmitsu/go-shlex:")
	for _, word := range words_anmitsu {
		fmt.Println(word)
	}
	if err2 != nil {
		fmt.Println(err2.Error())
	}

	// Output:
	// Source string:
	// English and 日本語
	//
	// Result of github.com/flynn/go-shlex:
	// English
	// and
	// Unknown rune: 26085
	//
	// Result of github.com/anmitsu/go-shlex:
	// English
	// and
	// 日本語
}
<|endoftext|>


<commit_before>//  Copyright 2021 Google Inc. All Rights Reserved.
//
//  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 ospolicies are OSPolicy osconfig agent tests.
package ospolicies

import (
	"context"
	"fmt"
	"log"
	"path"
	"regexp"
	"strings"
	"sync"
	"time"

	"github.com/GoogleCloudPlatform/compute-image-tools/go/e2e_test_utils/junitxml"
	osconfigZonalV1alpha "github.com/GoogleCloudPlatform/osconfig/e2e_tests/api/cloud.google.com/go/osconfig/apiv1alpha"
	"github.com/GoogleCloudPlatform/osconfig/e2e_tests/compute"
	"github.com/GoogleCloudPlatform/osconfig/e2e_tests/config"
	gcpclients "github.com/GoogleCloudPlatform/osconfig/e2e_tests/gcp_clients"
	testconfig "github.com/GoogleCloudPlatform/osconfig/e2e_tests/test_config"
	"github.com/GoogleCloudPlatform/osconfig/e2e_tests/utils"
	"github.com/google/go-cmp/cmp"
	"github.com/kylelemons/godebug/pretty"
	computeApi "google.golang.org/api/compute/v1"
	"google.golang.org/protobuf/testing/protocmp"

	osconfigpb "github.com/GoogleCloudPlatform/osconfig/e2e_tests/api/google.golang.org/genproto/googleapis/cloud/osconfig/v1alpha"
)

var (
	testSuiteName = "OSPolicies"
	dump          = &pretty.Config{IncludeUnexported: true}
)

const (
	packageResourceApt       = "packageresourceapt"
	packageResourceYum       = "packageresourceyum"
	packageResourceZypper    = "packageresourcezypper"
	packageResourceGoo       = "packageresourcegoo"
	repositoryResourceApt    = "repositoryresourceapt"
	repositoryResourceYum    = "repositoryresourceyum"
	repositoryResourceZypper = "repositoryresourcezypper"
	repositoryResourceGoo    = "repositoryresourcegoo"
	fileResource             = "fileresource"
	linuxExecResource        = "linuxexecresource"
	windowsExecResource      = "windowsexecresource"
)

type osPolicyTestSetup struct {
	image                string
	imageName            string
	osPolicyAssignmentID string
	instanceName         string
	testName             string
	osPolicyAssignment   *osconfigpb.OSPolicyAssignment
	startup              *computeApi.MetadataItems
	machineType          string
	queryPaths           []string
	assertTimeout        time.Duration
	wantCompliances      []*osconfigpb.InstanceOSPoliciesCompliance_OSPolicyCompliance
}

func newOsPolicyTestSetup(image, imageName, instanceName, testName string, queryPaths []string, machineType string, ospa *osconfigpb.OSPolicyAssignment, startup *computeApi.MetadataItems, assertTimeout time.Duration, wantCompliances []*osconfigpb.InstanceOSPoliciesCompliance_OSPolicyCompliance) *osPolicyTestSetup {
	return &osPolicyTestSetup{
		image:                image,
		imageName:            imageName,
		osPolicyAssignmentID: instanceName,
		instanceName:         instanceName,
		osPolicyAssignment:   ospa,
		testName:             testName,
		machineType:          machineType,
		queryPaths:           queryPaths,
		assertTimeout:        assertTimeout,
		startup:              startup,
		wantCompliances:      wantCompliances,
	}
}

// TestSuite is a OSPackage test suite.
func TestSuite(ctx context.Context, tswg *sync.WaitGroup, testSuites chan *junitxml.TestSuite, logger *log.Logger, testSuiteRegex, testCaseRegex *regexp.Regexp) {
	defer tswg.Done()

	if !strings.Contains(config.SvcEndpoint(), "staging") {
		return
	}
	if testSuiteRegex != nil && !testSuiteRegex.MatchString(testSuiteName) {
		return
	}

	testSuite := junitxml.NewTestSuite(testSuiteName)
	defer testSuite.Finish(testSuites)

	logger.Printf("Running TestSuite %q", testSuite.Name)
	testSetup := generateAllTestSetup()
	var wg sync.WaitGroup
	tests := make(chan *junitxml.TestCase)
	for _, setup := range testSetup {
		wg.Add(1)
		go testCase(ctx, setup, tests, &wg, logger, testCaseRegex)
	}

	go func() {
		wg.Wait()
		close(tests)
	}()

	for ret := range tests {
		testSuite.TestCase = append(testSuite.TestCase, ret)
	}

	logger.Printf("Finished TestSuite %q", testSuite.Name)
}

// We only want to create one GuestPolicy at a time to limit QPS.
var gpMx sync.Mutex

func createOSPolicyAssignment(ctx context.Context, client *osconfigZonalV1alpha.OsConfigZonalClient, req *osconfigpb.CreateOSPolicyAssignmentRequest) (*osconfigpb.OSPolicyAssignment, error) {
	gpMx.Lock()
	defer gpMx.Unlock()
	op, err := client.CreateOSPolicyAssignment(ctx, req)
	if err != nil {
		return nil, fmt.Errorf("error running CreateOSPolicyAssignment: %s", utils.GetStatusFromError(err))
	}
	// Wait up to 5 min for this to complete.
	ctx, cncl := context.WithTimeout(ctx, 5*time.Minute)
	defer cncl()
	ospa, err := op.Wait(ctx)
	if err != nil {
		return nil, fmt.Errorf("error waiting for operation to complete: %s", utils.GetStatusFromError(err))
	}
	return ospa, nil
}

func runTest(ctx context.Context, testCase *junitxml.TestCase, testSetup *osPolicyTestSetup, logger *log.Logger) {
	// No test should take longer than 30 min
	ctx, cncl := context.WithTimeout(ctx, 30*time.Minute)
	defer cncl()
	computeClient, err := gcpclients.GetComputeClient()
	if err != nil {
		testCase.WriteFailure("Error getting compute client: %v", err)
		return
	}

	var metadataItems []*computeApi.MetadataItems
	metadataItems = append(metadataItems, testSetup.startup)
	metadataItems = append(metadataItems, compute.BuildInstanceMetadataItem("enable-osconfig", "true"))
	metadataItems = append(metadataItems, compute.BuildInstanceMetadataItem("osconfig-disabled-features", "guestpolicies,osinventory"))
	metadataItems = append(metadataItems, compute.BuildInstanceMetadataItem("osconfig-enabled-prerelease-features", "ospolicies"))
	testProjectConfig := testconfig.GetProject()
	zone := testProjectConfig.AcquireZone()
	defer testProjectConfig.ReleaseZone(zone)
	testCase.Logf("Creating instance %q with image %q", testSetup.instanceName, testSetup.image)
	inst, err := utils.CreateComputeInstance(metadataItems, computeClient, testSetup.machineType, testSetup.image, testSetup.instanceName, testProjectConfig.TestProjectID, zone, testProjectConfig.ServiceAccountEmail, testProjectConfig.ServiceAccountScopes)
	if err != nil {
		testCase.WriteFailure("Error creating instance: %s", utils.GetStatusFromError(err))
		return
	}
	defer inst.Cleanup()
	defer inst.RecordSerialOutput(ctx, path.Join(*config.OutDir, testSuiteName), 1)

	testCase.Logf("Waiting for agent install to complete")
	if _, err := inst.WaitForGuestAttributes("osconfig_tests/install_done", 5*time.Second, 10*time.Minute); err != nil {
		testCase.WriteFailure("Error waiting for osconfig agent install: %v", err)
		return
	}

	client, err := gcpclients.GetOsConfigClientV1Alpha()
	if err != nil {
		testCase.WriteFailure("Error getting osconfig client: %v", err)
		return
	}

	req := &osconfigpb.CreateOSPolicyAssignmentRequest{
		Parent:               fmt.Sprintf("projects/%s/locations/%s", testProjectConfig.TestProjectID, zone),
		OsPolicyAssignmentId: testSetup.osPolicyAssignmentID,
		OsPolicyAssignment:   testSetup.osPolicyAssignment,
	}

	testCase.Logf("Creating OSPolicyAssignment")
	ospa, err := createOSPolicyAssignment(ctx, client, req)
	if err != nil {
		testCase.WriteFailure("Error running createOSPolicyAssignment: %s", err)
		return
	}
	defer cleanupOSPolicyAssignment(ctx, testCase, ospa.GetName())

	// Check that the compliance output meets expectations.
	compReq := &osconfigpb.GetInstanceOSPoliciesComplianceRequest{Name: fmt.Sprintf("projects/%s/locations/%s/instanceOSPoliciesCompliances/%d", testProjectConfig.TestProjectID, zone, inst.Id)}
	compliance, err := client.GetInstanceOSPoliciesCompliance(ctx, compReq)
	if err != nil {
		testCase.WriteFailure("Error running GetInstanceOSPoliciesCompliance: %s", err)
		return
	}
	if diff := cmp.Diff(testSetup.wantCompliances, compliance.OsPolicyCompliances, protocmp.Transform(), cmp.FilterPath(func(p cmp.Path) bool {
		if p.Last().String() == `["os_policy_assignment"]` {
			return true
		}
		return false
	}, cmp.Ignore())); diff != "" {
		testCase.WriteFailure("Did not get expected OsPolicyCompliances (-want +got):\n%s", diff)
		return
	}

	for _, p := range testSetup.queryPaths {
		if _, err := inst.WaitForGuestAttributes(p, 10*time.Second, testSetup.assertTimeout); err != nil {
			testCase.WriteFailure("Error while asserting: %v", err)
			return
		}
	}
}

func testCase(ctx context.Context, testSetup *osPolicyTestSetup, tests chan *junitxml.TestCase, wg *sync.WaitGroup, logger *log.Logger, regex *regexp.Regexp) {
	defer wg.Done()

	tc, err := getTestCaseFromTestSetUp(testSetup)
	if err != nil {
		logger.Fatalf("invalid testcase: %+v", err)
		return
	}
	if tc.FilterTestCase(regex) {
		tc.Finish(tests)
	} else {
		logger.Printf("Running TestCase %q", tc.Name)
		runTest(ctx, tc, testSetup, logger)
		if tc.Failure != nil {
			rerunTC := junitxml.NewTestCase(testSuiteName, strings.TrimPrefix(tc.Name, fmt.Sprintf("[%s] ", testSuiteName)))
			wg.Add(1)
			go func() {
				defer wg.Done()
				logger.Printf("Rerunning TestCase %q", rerunTC.Name)
				runTest(ctx, rerunTC, testSetup, logger)
				rerunTC.Finish(tests)
				logger.Printf("TestCase %q finished in %fs", rerunTC.Name, rerunTC.Time)
			}()
		}
		tc.Finish(tests)
		logger.Printf("TestCase %q finished in %fs", tc.Name, tc.Time)
	}
}

// factory method to get testcase from the testsetup
func getTestCaseFromTestSetUp(testSetup *osPolicyTestSetup) (*junitxml.TestCase, error) {
	var tc *junitxml.TestCase

	switch testSetup.testName {
	case packageResourceApt:
		tc = junitxml.NewTestCase(testSuiteName, fmt.Sprintf("[PackageResource Apt] [%s]", testSetup.imageName))
	case packageResourceYum:
		tc = junitxml.NewTestCase(testSuiteName, fmt.Sprintf("[PackageResource Yum] [%s]", testSetup.imageName))
	case packageResourceZypper:
		tc = junitxml.NewTestCase(testSuiteName, fmt.Sprintf("[PackageResource Zypper] [%s]", testSetup.imageName))
	case packageResourceGoo:
		tc = junitxml.NewTestCase(testSuiteName, fmt.Sprintf("[PackageResource GooGet] [%s]", testSetup.imageName))
	case repositoryResourceApt:
		tc = junitxml.NewTestCase(testSuiteName, fmt.Sprintf("[RepositoryResource Apt] [%s]", testSetup.imageName))
	case repositoryResourceYum:
		tc = junitxml.NewTestCase(testSuiteName, fmt.Sprintf("[RepositoryResource Yum] [%s]", testSetup.imageName))
	case repositoryResourceZypper:
		tc = junitxml.NewTestCase(testSuiteName, fmt.Sprintf("[RepositoryResource Zypper] [%s]", testSetup.imageName))
	case repositoryResourceGoo:
		tc = junitxml.NewTestCase(testSuiteName, fmt.Sprintf("[RepositoryResource GooGet] [%s]", testSetup.imageName))
	case fileResource:
		tc = junitxml.NewTestCase(testSuiteName, fmt.Sprintf("[FileResource] [%s]", testSetup.imageName))
	case linuxExecResource:
		tc = junitxml.NewTestCase(testSuiteName, fmt.Sprintf("[Linux ExecResource] [%s]", testSetup.imageName))
	case windowsExecResource:
		tc = junitxml.NewTestCase(testSuiteName, fmt.Sprintf("[Windows ExecResource] [%s]", testSetup.imageName))
	default:
		return nil, fmt.Errorf("unknown test function name: %s", testSetup.testName)
	}

	return tc, nil
}

func cleanupOSPolicyAssignment(ctx context.Context, testCase *junitxml.TestCase, name string) {
	client, err := gcpclients.GetOsConfigClientV1Alpha()
	if err != nil {
		testCase.WriteFailure(fmt.Sprintf("Error while deleting guest policy: %s", utils.GetStatusFromError(err)))
	}

	op, err := client.DeleteOSPolicyAssignment(ctx, &osconfigpb.DeleteOSPolicyAssignmentRequest{Name: name})
	if err != nil {
		testCase.WriteFailure(fmt.Sprintf("Error calling DeleteOSPolicyAssignment: %s", utils.GetStatusFromError(err)))
	}
	ctx, cncl := context.WithTimeout(ctx, 5*time.Minute)
	defer cncl()
	op.Wait(ctx)
}
<commit_msg>e2e_tests: (#330)<commit_after>//  Copyright 2021 Google Inc. All Rights Reserved.
//
//  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 ospolicies are OSPolicy osconfig agent tests.
package ospolicies

import (
	"context"
	"fmt"
	"log"
	"path"
	"regexp"
	"strings"
	"sync"
	"time"

	"github.com/GoogleCloudPlatform/compute-image-tools/go/e2e_test_utils/junitxml"
	osconfigZonalV1alpha "github.com/GoogleCloudPlatform/osconfig/e2e_tests/api/cloud.google.com/go/osconfig/apiv1alpha"
	"github.com/GoogleCloudPlatform/osconfig/e2e_tests/compute"
	"github.com/GoogleCloudPlatform/osconfig/e2e_tests/config"
	gcpclients "github.com/GoogleCloudPlatform/osconfig/e2e_tests/gcp_clients"
	testconfig "github.com/GoogleCloudPlatform/osconfig/e2e_tests/test_config"
	"github.com/GoogleCloudPlatform/osconfig/e2e_tests/utils"
	"github.com/google/go-cmp/cmp"
	"github.com/kylelemons/godebug/pretty"
	computeApi "google.golang.org/api/compute/v1"
	"google.golang.org/protobuf/testing/protocmp"

	osconfigpb "github.com/GoogleCloudPlatform/osconfig/e2e_tests/api/google.golang.org/genproto/googleapis/cloud/osconfig/v1alpha"
)

var (
	testSuiteName = "OSPolicies"
	dump          = &pretty.Config{IncludeUnexported: true}
)

const (
	packageResourceApt       = "packageresourceapt"
	packageResourceYum       = "packageresourceyum"
	packageResourceZypper    = "packageresourcezypper"
	packageResourceGoo       = "packageresourcegoo"
	repositoryResourceApt    = "repositoryresourceapt"
	repositoryResourceYum    = "repositoryresourceyum"
	repositoryResourceZypper = "repositoryresourcezypper"
	repositoryResourceGoo    = "repositoryresourcegoo"
	fileResource             = "fileresource"
	linuxExecResource        = "linuxexecresource"
	windowsExecResource      = "windowsexecresource"
)

type osPolicyTestSetup struct {
	image                string
	imageName            string
	osPolicyAssignmentID string
	instanceName         string
	testName             string
	osPolicyAssignment   *osconfigpb.OSPolicyAssignment
	startup              *computeApi.MetadataItems
	machineType          string
	queryPaths           []string
	assertTimeout        time.Duration
	wantCompliances      []*osconfigpb.InstanceOSPoliciesCompliance_OSPolicyCompliance
}

func newOsPolicyTestSetup(image, imageName, instanceName, testName string, queryPaths []string, machineType string, ospa *osconfigpb.OSPolicyAssignment, startup *computeApi.MetadataItems, assertTimeout time.Duration, wantCompliances []*osconfigpb.InstanceOSPoliciesCompliance_OSPolicyCompliance) *osPolicyTestSetup {
	return &osPolicyTestSetup{
		image:                image,
		imageName:            imageName,
		osPolicyAssignmentID: instanceName,
		instanceName:         instanceName,
		osPolicyAssignment:   ospa,
		testName:             testName,
		machineType:          machineType,
		queryPaths:           queryPaths,
		assertTimeout:        assertTimeout,
		startup:              startup,
		wantCompliances:      wantCompliances,
	}
}

// TestSuite is a OSPackage test suite.
func TestSuite(ctx context.Context, tswg *sync.WaitGroup, testSuites chan *junitxml.TestSuite, logger *log.Logger, testSuiteRegex, testCaseRegex *regexp.Regexp) {
	defer tswg.Done()

	if !strings.Contains(config.SvcEndpoint(), "staging") {
		return
	}
	if testSuiteRegex != nil && !testSuiteRegex.MatchString(testSuiteName) {
		return
	}

	testSuite := junitxml.NewTestSuite(testSuiteName)
	defer testSuite.Finish(testSuites)

	logger.Printf("Running TestSuite %q", testSuite.Name)
	testSetup := generateAllTestSetup()
	var wg sync.WaitGroup
	tests := make(chan *junitxml.TestCase)
	for _, setup := range testSetup {
		wg.Add(1)
		go testCase(ctx, setup, tests, &wg, logger, testCaseRegex)
	}

	go func() {
		wg.Wait()
		close(tests)
	}()

	for ret := range tests {
		testSuite.TestCase = append(testSuite.TestCase, ret)
	}

	logger.Printf("Finished TestSuite %q", testSuite.Name)
}

// We only want to create one GuestPolicy at a time to limit QPS.
var gpMx sync.Mutex

func createOSPolicyAssignment(ctx context.Context, client *osconfigZonalV1alpha.OsConfigZonalClient, req *osconfigpb.CreateOSPolicyAssignmentRequest) (*osconfigpb.OSPolicyAssignment, error) {
	gpMx.Lock()
	defer gpMx.Unlock()
	op, err := client.CreateOSPolicyAssignment(ctx, req)
	if err != nil {
		return nil, fmt.Errorf("error running CreateOSPolicyAssignment: %s", utils.GetStatusFromError(err))
	}
	// Wait up to 5 min for this to complete.
	ctx, cncl := context.WithTimeout(ctx, 5*time.Minute)
	defer cncl()
	ospa, err := op.Wait(ctx)
	if err != nil {
		return nil, fmt.Errorf("error waiting for create operation to complete for %q: %s", ospa.GetName(), utils.GetStatusFromError(err))
	}
	return ospa, nil
}

func runTest(ctx context.Context, testCase *junitxml.TestCase, testSetup *osPolicyTestSetup, logger *log.Logger) {
	// No test should take longer than 30 min
	ctx, cncl := context.WithTimeout(ctx, 30*time.Minute)
	defer cncl()
	computeClient, err := gcpclients.GetComputeClient()
	if err != nil {
		testCase.WriteFailure("Error getting compute client: %v", err)
		return
	}

	var metadataItems []*computeApi.MetadataItems
	metadataItems = append(metadataItems, testSetup.startup)
	metadataItems = append(metadataItems, compute.BuildInstanceMetadataItem("enable-osconfig", "true"))
	metadataItems = append(metadataItems, compute.BuildInstanceMetadataItem("osconfig-disabled-features", "guestpolicies,osinventory"))
	metadataItems = append(metadataItems, compute.BuildInstanceMetadataItem("osconfig-enabled-prerelease-features", "ospolicies"))
	testProjectConfig := testconfig.GetProject()
	zone := testProjectConfig.AcquireZone()
	defer testProjectConfig.ReleaseZone(zone)
	testCase.Logf("Creating instance %q with image %q", testSetup.instanceName, testSetup.image)
	inst, err := utils.CreateComputeInstance(metadataItems, computeClient, testSetup.machineType, testSetup.image, testSetup.instanceName, testProjectConfig.TestProjectID, zone, testProjectConfig.ServiceAccountEmail, testProjectConfig.ServiceAccountScopes)
	if err != nil {
		testCase.WriteFailure("Error creating instance: %s", utils.GetStatusFromError(err))
		return
	}
	defer inst.Cleanup()
	defer inst.RecordSerialOutput(ctx, path.Join(*config.OutDir, testSuiteName), 1)

	testCase.Logf("Waiting for agent install to complete")
	if _, err := inst.WaitForGuestAttributes("osconfig_tests/install_done", 5*time.Second, 10*time.Minute); err != nil {
		testCase.WriteFailure("Error waiting for osconfig agent install: %v", err)
		return
	}

	client, err := gcpclients.GetOsConfigClientV1Alpha()
	if err != nil {
		testCase.WriteFailure("Error getting osconfig client: %v", err)
		return
	}

	req := &osconfigpb.CreateOSPolicyAssignmentRequest{
		Parent:               fmt.Sprintf("projects/%s/locations/%s", testProjectConfig.TestProjectID, zone),
		OsPolicyAssignmentId: testSetup.osPolicyAssignmentID,
		OsPolicyAssignment:   testSetup.osPolicyAssignment,
	}

	testCase.Logf("Creating OSPolicyAssignment")
	ospa, err := createOSPolicyAssignment(ctx, client, req)
	if err != nil {
		testCase.WriteFailure("Error running createOSPolicyAssignment: %s", err)
		return
	}
	defer cleanupOSPolicyAssignment(ctx, client, testCase, ospa.GetName())

	// Check that the compliance output meets expectations.
	compReq := &osconfigpb.GetInstanceOSPoliciesComplianceRequest{Name: fmt.Sprintf("projects/%s/locations/%s/instanceOSPoliciesCompliances/%d", testProjectConfig.TestProjectID, zone, inst.Id)}
	compliance, err := client.GetInstanceOSPoliciesCompliance(ctx, compReq)
	if err != nil {
		testCase.WriteFailure("Error running GetInstanceOSPoliciesCompliance: %s", err)
		return
	}
	if diff := cmp.Diff(testSetup.wantCompliances, compliance.OsPolicyCompliances, protocmp.Transform(), cmp.FilterPath(func(p cmp.Path) bool {
		if p.Last().String() == `["os_policy_assignment"]` {
			return true
		}
		return false
	}, cmp.Ignore())); diff != "" {
		testCase.WriteFailure("Did not get expected OsPolicyCompliances (-want +got):\n%s", diff)
		return
	}

	for _, p := range testSetup.queryPaths {
		if _, err := inst.WaitForGuestAttributes(p, 10*time.Second, testSetup.assertTimeout); err != nil {
			testCase.WriteFailure("Error while asserting: %v", err)
			return
		}
	}
}

func testCase(ctx context.Context, testSetup *osPolicyTestSetup, tests chan *junitxml.TestCase, wg *sync.WaitGroup, logger *log.Logger, regex *regexp.Regexp) {
	defer wg.Done()

	tc, err := getTestCaseFromTestSetUp(testSetup)
	if err != nil {
		logger.Fatalf("invalid testcase: %+v", err)
		return
	}
	if tc.FilterTestCase(regex) {
		tc.Finish(tests)
	} else {
		logger.Printf("Running TestCase %q", tc.Name)
		runTest(ctx, tc, testSetup, logger)
		if tc.Failure != nil {
			rerunTC := junitxml.NewTestCase(testSuiteName, strings.TrimPrefix(tc.Name, fmt.Sprintf("[%s] ", testSuiteName)))
			wg.Add(1)
			go func() {
				defer wg.Done()
				logger.Printf("Rerunning TestCase %q", rerunTC.Name)
				runTest(ctx, rerunTC, testSetup, logger)
				rerunTC.Finish(tests)
				logger.Printf("TestCase %q finished in %fs", rerunTC.Name, rerunTC.Time)
			}()
		}
		tc.Finish(tests)
		logger.Printf("TestCase %q finished in %fs", tc.Name, tc.Time)
	}
}

// factory method to get testcase from the testsetup
func getTestCaseFromTestSetUp(testSetup *osPolicyTestSetup) (*junitxml.TestCase, error) {
	var tc *junitxml.TestCase

	switch testSetup.testName {
	case packageResourceApt:
		tc = junitxml.NewTestCase(testSuiteName, fmt.Sprintf("[PackageResource Apt] [%s]", testSetup.imageName))
	case packageResourceYum:
		tc = junitxml.NewTestCase(testSuiteName, fmt.Sprintf("[PackageResource Yum] [%s]", testSetup.imageName))
	case packageResourceZypper:
		tc = junitxml.NewTestCase(testSuiteName, fmt.Sprintf("[PackageResource Zypper] [%s]", testSetup.imageName))
	case packageResourceGoo:
		tc = junitxml.NewTestCase(testSuiteName, fmt.Sprintf("[PackageResource GooGet] [%s]", testSetup.imageName))
	case repositoryResourceApt:
		tc = junitxml.NewTestCase(testSuiteName, fmt.Sprintf("[RepositoryResource Apt] [%s]", testSetup.imageName))
	case repositoryResourceYum:
		tc = junitxml.NewTestCase(testSuiteName, fmt.Sprintf("[RepositoryResource Yum] [%s]", testSetup.imageName))
	case repositoryResourceZypper:
		tc = junitxml.NewTestCase(testSuiteName, fmt.Sprintf("[RepositoryResource Zypper] [%s]", testSetup.imageName))
	case repositoryResourceGoo:
		tc = junitxml.NewTestCase(testSuiteName, fmt.Sprintf("[RepositoryResource GooGet] [%s]", testSetup.imageName))
	case fileResource:
		tc = junitxml.NewTestCase(testSuiteName, fmt.Sprintf("[FileResource] [%s]", testSetup.imageName))
	case linuxExecResource:
		tc = junitxml.NewTestCase(testSuiteName, fmt.Sprintf("[Linux ExecResource] [%s]", testSetup.imageName))
	case windowsExecResource:
		tc = junitxml.NewTestCase(testSuiteName, fmt.Sprintf("[Windows ExecResource] [%s]", testSetup.imageName))
	default:
		return nil, fmt.Errorf("unknown test function name: %s", testSetup.testName)
	}

	return tc, nil
}

func cleanupOSPolicyAssignment(ctx context.Context, client *osconfigZonalV1alpha.OsConfigZonalClient, testCase *junitxml.TestCase, name string) {
	op, err := client.DeleteOSPolicyAssignment(ctx, &osconfigpb.DeleteOSPolicyAssignmentRequest{Name: name})
	if err != nil {
		testCase.WriteFailure(fmt.Sprintf("Error calling DeleteOSPolicyAssignment: %s", utils.GetStatusFromError(err)))
		return
	}
	ctx, cncl := context.WithTimeout(ctx, 5*time.Minute)
	defer cncl()
	op.Wait(ctx)
}
<|endoftext|>


<commit_before>package term

import (
	"log"
	"time"
)

// Reset an Arduino by lowering the DTR signal.
func ExampleStatusSetDTR(t *Term) {
	status, err := t.Status()
	if err != nil {
		log.Fatal(err)
	}
	status.SetDTR(false)
	if err := t.SetStatus(status); err != nil {
		log.Fatal(err)
	}
	time.Sleep(1 * time.Second)
	status.SetDTR(true)
	if err := t.SetStatus(status); err != nil {
		log.Fatal(err)
	}
}
<commit_msg>updated example<commit_after>package term

import (
	"log"
	"time"
)

// Reset an Arduino by lowering the DTR signal.
func ExampleStatusSetDTR() {
	t, err := Open("/dev/USB0")
	if err != nil {
		log.Fatal(err)
	}
	defer t.Close()
	status, err := t.Status()
	if err != nil {
		log.Fatal(err)
	}
	status.SetDTR(false)
	if err := t.SetStatus(status); err != nil {
		log.Fatal(err)
	}
	time.Sleep(1 * time.Second)
	status.SetDTR(true)
	if err := t.SetStatus(status); err != nil {
		log.Fatal(err)
	}
}
<|endoftext|>


<commit_before>package modules

import (
	"fmt"
)

// The KVClient interface models a simple key/value store.
type KVClient interface {
	Get(key string) string
	Put(key, value string)
}

// A MapDBClient is a simple mock KVClient implementation backed by a map and configured with a default value for missing keys.
type MapDBClient struct {
	defaultValue string
	db           map[string]string
}

func (client *MapDBClient) Get(key string) string {
	if value, ok := client.db[key]; ok {
		return value
	} else {
		return client.defaultValue
	}
}

func (client *MapDBClient) Put(key, value string) {
	client.db[key] = value
}

// A service module has a 'GetData' service which utilizes an injected DBClient.
type ServiceModule struct {
	KVClient KVClient `inject:""`
}

func (service *ServiceModule) GetData(key string) string {
	return service.KVClient.Get(key)
}

func (service *ServiceModule) StoreData(key, value string) {
	service.KVClient.Put(key, value)
}

type defaultValue string

// This data module provides a Client function for retrieving a KVClient, which returns a DBClient configured with the
// injected default value.
type DataModule struct {
	DefaultValue defaultValue
	KVClient KVClient `provide:""`
}

func (data *DataModule) Provide() error {
	data.KVClient = &MapDBClient{defaultValue: string(data.DefaultValue), db: make(map[string]string)}
	return nil
}

func Example() {
	serviceModule := &ServiceModule{}

	dataModule := &DataModule{DefaultValue: "default"}

	binder := NewBinder()
	if err := binder.Bind(serviceModule, dataModule); err != nil {
		panic(err)
	}

	fmt.Println(serviceModule.GetData("key"))

	serviceModule.StoreData("key", "value")
	fmt.Println(serviceModule.GetData("key"))

	// Output:
	// default
	// value
}
<commit_msg>fixing docs<commit_after>package modules

import (
	"fmt"
)

// The KVClient interface models a simple key/value store.
type KVClient interface {
	Get(key string) string
	Put(key, value string)
}

// A MapDBClient is a simple mock KVClient implementation backed by a map and configured with a default value for missing keys.
type MapDBClient struct {
	defaultValue string
	db           map[string]string
}

func (client *MapDBClient) Get(key string) string {
	if value, ok := client.db[key]; ok {
		return value
	} else {
		return client.defaultValue
	}
}

func (client *MapDBClient) Put(key, value string) {
	client.db[key] = value
}

// A service module has a 'GetData' service which utilizes an injected DBClient.
type ServiceModule struct {
	KVClient KVClient `inject:""`
}

func (service *ServiceModule) GetData(key string) string {
	return service.KVClient.Get(key)
}

func (service *ServiceModule) StoreData(key, value string) {
	service.KVClient.Put(key, value)
}

type defaultValue string

// This data module provides a KVClient.
type DataModule struct {
	DefaultValue defaultValue
	KVClient KVClient `provide:""`
}

func (data *DataModule) Provide() error {
	data.KVClient = &MapDBClient{defaultValue: string(data.DefaultValue), db: make(map[string]string)}
	return nil
}

func Example() {
	serviceModule := &ServiceModule{}

	dataModule := &DataModule{DefaultValue: "default"}

	binder := NewBinder()
	if err := binder.Bind(serviceModule, dataModule); err != nil {
		panic(err)
	}

	fmt.Println(serviceModule.GetData("key"))

	serviceModule.StoreData("key", "value")
	fmt.Println(serviceModule.GetData("key"))

	// Output:
	// default
	// value
}
<|endoftext|>


<commit_before>package main

import (
	"context"
	"fmt"
	"io/ioutil"
	"log"
	"reflect"
	"time"

	"github.com/cucumber/godog"
	envoy_config_core_v3 "github.com/envoyproxy/go-control-plane/envoy/config/core/v3"
	cluster_service "github.com/envoyproxy/go-control-plane/envoy/service/cluster/v3"
	envoy_service_discovery_v3 "github.com/envoyproxy/go-control-plane/envoy/service/discovery/v3"
	"google.golang.org/grpc"
	"gopkg.in/yaml.v2"

	pb "github.com/zachmandeville/tester-prototype/api/adapter"
	"github.com/zachmandeville/tester-prototype/internal/parser"
)

const configFile string = "config.yaml"

var (
	opts []grpc.DialOption = []grpc.DialOption{
		grpc.WithInsecure(),
		grpc.WithBlock(),
		grpc.WithTimeout(time.Second * 5),
	}
)

type ClientConfig struct {
	Port string
	Conn *grpc.ClientConn
}

type CDS struct {
	Stream    cluster_service.ClusterDiscoveryService_StreamClustersClient
	Responses *envoy_service_discovery_v3.DiscoveryResponse
}

type Runner struct {
	Adapter           *ClientConfig
	Target            *ClientConfig
	DiscoveryResponse *envoy_service_discovery_v3.DiscoveryResponse
	CDS               *CDS
}

func (r *Runner) addPorts(*godog.Scenario) {
	configYaml, err := ioutil.ReadFile(configFile)
	if err != nil {
		fmt.Printf("Error reading setup file: %v", err)
	}
	config, err := parser.ParseInitConfig(configYaml)
	if err != nil {
		fmt.Printf("Error parsing yaml file: %v", err)
	}
	r.Adapter = &ClientConfig{
		Port: config.Adapter,
	}
	r.Target = &ClientConfig{
		Port: config.Target,
	}
}

func (r *Runner) aTargetSetupWithSnapshotMatchingYaml(snapYaml *godog.DocString) error {
	snapshot, err := parser.YamlToSnapshot(snapYaml.Content)
	if err != nil {
		err = fmt.Errorf("Error parsing snapshot yaml: %v", err)
		return err
	}

	c := pb.NewAdapterClient(r.Adapter.Conn)
	_, err = c.SetState(context.Background(), snapshot)
	if err != nil {
		err = fmt.Errorf("Cannot Set Target with State: %v\n", err)
		return err
	}
	return nil
}

func (r *Runner) aCDSStreamWasInitiatedWithADiscoveryRequestMatchingYaml(arg1 *godog.DocString) error {
	drdata, err := parser.ParseDiscoveryRequest(arg1.Content)
	if err != nil {
		err = fmt.Errorf("error parsing discovery request: %v\n", err)
		return err
	}
	dreq := &envoy_service_discovery_v3.DiscoveryRequest{
		VersionInfo: drdata.VersionInfo,
		Node: &envoy_config_core_v3.Node{
			Id: drdata.Node.ID,
		},
		ResourceNames: drdata.ResourceNames,
		TypeUrl:       drdata.TypeURL,
		ResponseNonce: drdata.ResponseNonce,
	}
	c := cluster_service.NewClusterDiscoveryServiceClient(r.Target.Conn)
	stream, err := c.StreamClusters(context.Background())
	if err != nil {
		err = fmt.Errorf("Error starting CDS stream: %v\n", err)
		return err
	}
	r.CDS.Stream = stream
	r.CDS.Stream.Send(dreq)
	res, err := stream.Recv()
	r.CDS.Responses = res
	return nil
}

func (r *Runner) theStreamWasACKedWithADiscoveryRequestMatchingYaml(arg1 *godog.DocString) error {
	drdata, err := parser.ParseDiscoveryRequest(arg1.Content)
	if err != nil {
		err = fmt.Errorf("error parsing discovery request: %v\n", err)
		return err
	}
	dreq := &envoy_service_discovery_v3.DiscoveryRequest{
		VersionInfo: drdata.VersionInfo,
		Node: &envoy_config_core_v3.Node{
			Id: drdata.Node.ID,
		},
		ResourceNames: drdata.ResourceNames,
		TypeUrl:       drdata.TypeURL,
		ResponseNonce: drdata.ResponseNonce,
	}
	fmt.Printf("dreq: %v\n", dreq)
	r.CDS.Stream.Send(dreq)
	return nil
}

func (r *Runner) iSendADiscoveryRequestMatchingYaml(dryaml *godog.DocString) error {
	drdata, err := parser.ParseDiscoveryRequest(dryaml.Content)
	if err != nil {
		err = fmt.Errorf("error parsing discovery request: %v\n", err)
		return err
	}
	dreq := &envoy_service_discovery_v3.DiscoveryRequest{
		VersionInfo: drdata.VersionInfo,
		Node: &envoy_config_core_v3.Node{
			Id: drdata.Node.ID,
		},
		ResourceNames: drdata.ResourceNames,
		TypeUrl:       drdata.TypeURL,
		ResponseNonce: drdata.ResponseNonce,
	}
	c := cluster_service.NewClusterDiscoveryServiceClient(r.Target.Conn)
	dres, err := c.FetchClusters(context.Background(), dreq)
	if err != nil {
		log.Printf("err fetching clusters: %v", err.Error())
		return err
	}
	r.DiscoveryResponse = dres
	return nil
}

func (r *Runner) iGetADiscoveryResponseMatchingYaml(arg1 *godog.DocString) error {
	var expected parser.DiscoveryResponse
	if err := yaml.Unmarshal([]byte(arg1.Content), &expected); err != nil {
		return err
	}
	actual, _ := parser.ParseDiscoveryResponse(r.DiscoveryResponse)
	if !reflect.DeepEqual(expected, *actual) {
		return fmt.Errorf("expected yaml does not match actual, %v vs. %v", expected, *actual)
	}
	return nil
}

func connectViaGRPC(client *ClientConfig, server string) error {
	conn, err := grpc.Dial(client.Port, opts...)
	if err != nil {
		err = fmt.Errorf("Cannot connect to %v: %v", server, err)
		return err
	}
	client.Conn = conn
	return nil
}

func (r *Runner) isReachableViaGRPC(server string) error {
	switch server {
	case "adapter":
		err := connectViaGRPC(r.Adapter, server)
		return err
	case "target":
		err := connectViaGRPC(r.Target, server)
		return err
	default:
		err := fmt.Errorf("unexpected server name: %v", server)
		return err
	}
}

func (r *Runner) targetIsUpdatedToMatchYaml(yml *godog.DocString) error {
	snapshot, err := parser.YamlToSnapshot(yml.Content)
	if err != nil {
		err = fmt.Errorf("Error parsing snapshot yaml: %v", err)
		return err
	}
	c := pb.NewAdapterClient(r.Adapter.Conn)
	_, err = c.SetState(context.Background(), snapshot)
	if err != nil {
		err = fmt.Errorf("Cannot Set Target with State: %v\n", err)
		return err
	}
	return nil
}

func (r *Runner) theClientReceivesADiscoveryResponseMatchingYaml(yml *godog.DocString) error {
	dreq := &envoy_service_discovery_v3.DiscoveryRequest{
		VersionInfo: "1",
		Node: &envoy_config_core_v3.Node{
			Id: "test-id",
		},
		ResourceNames: []string{},
		TypeUrl:       "type.googleapis.com/envoy.config.cluster.v3.Cluster",
		ResponseNonce: "1",
	}
	fmt.Printf("dreq: %v\n", dreq)
	r.CDS.Stream.Send(dreq)
	res, err := r.CDS.Stream.Recv()
	if err != nil {
		err = fmt.Errorf("error receiving discovery response: %v\n", err)
		return err
	}
	fmt.Printf("res: %v\n", res)
	var expected parser.DiscoveryResponse
	if err := yaml.Unmarshal([]byte(yml.Content), &expected); err != nil {
		return err
	}
	actual, _ := parser.ParseDiscoveryResponse(res)
	if !reflect.DeepEqual(expected, *actual) {
		return fmt.Errorf("expected yaml does not match actual, %v vs. %v", expected, *actual)
	}
	return nil
}

func InitializeScenario(ctx *godog.ScenarioContext) {
	runner := &Runner{}

	ctx.BeforeScenario(runner.addPorts)

	ctx.Step(`^a Target setup with snapshot matching yaml:$`, runner.aTargetSetupWithSnapshotMatchingYaml)
	ctx.Step(`^I get a discovery response matching yaml:$`, runner.iGetADiscoveryResponseMatchingYaml)
	ctx.Step(`^I send a discovery request matching yaml:$`, runner.iSendADiscoveryRequestMatchingYaml)
	ctx.Step(`^"([^"]*)" is reachable via gRPC$`, runner.isReachableViaGRPC)
	ctx.Step(`^Target is updated to match yaml:$`, runner.targetIsUpdatedToMatchYaml)
	ctx.Step(`^the client receives a discovery response matching yaml:$`, runner.theClientReceivesADiscoveryResponseMatchingYaml)
	ctx.Step(`^a CDS stream was initiated with a discovery request matching yaml:$`, runner.aCDSStreamWasInitiatedWithADiscoveryRequestMatchingYaml)
	ctx.Step(`^the stream was ACKed with a discovery request matching yaml:$`, runner.theStreamWasACKedWithADiscoveryRequestMatchingYaml)
}
<commit_msg>fil nil panic error<commit_after>package main

import (
	"context"
	"fmt"
	"io/ioutil"
	"log"
	"reflect"
	"time"

	"github.com/cucumber/godog"
	envoy_config_core_v3 "github.com/envoyproxy/go-control-plane/envoy/config/core/v3"
	cluster_service "github.com/envoyproxy/go-control-plane/envoy/service/cluster/v3"
	envoy_service_discovery_v3 "github.com/envoyproxy/go-control-plane/envoy/service/discovery/v3"
	"google.golang.org/grpc"
	"gopkg.in/yaml.v2"

	pb "github.com/zachmandeville/tester-prototype/api/adapter"
	"github.com/zachmandeville/tester-prototype/internal/parser"
)

const configFile string = "config.yaml"

var (
	opts []grpc.DialOption = []grpc.DialOption{
		grpc.WithInsecure(),
		grpc.WithBlock(),
		grpc.WithTimeout(time.Second * 5),
	}
)

type ClientConfig struct {
	Port string
	Conn *grpc.ClientConn
}

type Runner struct {
	Adapter           *ClientConfig
	Target            *ClientConfig
	DiscoveryResponse *envoy_service_discovery_v3.DiscoveryResponse
	CDS               struct {
		Stream    cluster_service.ClusterDiscoveryService_StreamClustersClient
		Responses *envoy_service_discovery_v3.DiscoveryResponse
	}
}

func (r *Runner) addPorts(*godog.Scenario) {
	configYaml, err := ioutil.ReadFile(configFile)
	if err != nil {
		fmt.Printf("Error reading setup file: %v", err)
	}
	config, err := parser.ParseInitConfig(configYaml)
	if err != nil {
		fmt.Printf("Error parsing yaml file: %v", err)
	}
	r.Adapter = &ClientConfig{
		Port: config.Adapter,
	}
	r.Target = &ClientConfig{
		Port: config.Target,
	}
}

func (r *Runner) aTargetSetupWithSnapshotMatchingYaml(snapYaml *godog.DocString) error {
	snapshot, err := parser.YamlToSnapshot(snapYaml.Content)
	if err != nil {
		err = fmt.Errorf("Error parsing snapshot yaml: %v", err)
		return err
	}

	c := pb.NewAdapterClient(r.Adapter.Conn)
	_, err = c.SetState(context.Background(), snapshot)
	if err != nil {
		err = fmt.Errorf("Cannot Set Target with State: %v\n", err)
		return err
	}
	return nil
}

func (r *Runner) aCDSStreamWasInitiatedWithADiscoveryRequestMatchingYaml(arg1 *godog.DocString) error {
	drdata, err := parser.ParseDiscoveryRequest(arg1.Content)
	if err != nil {
		err = fmt.Errorf("error parsing discovery request: %v\n", err)
		return err
	}
	dreq := &envoy_service_discovery_v3.DiscoveryRequest{
		VersionInfo: drdata.VersionInfo,
		Node: &envoy_config_core_v3.Node{
			Id: drdata.Node.ID,
		},
		ResourceNames: drdata.ResourceNames,
		TypeUrl:       drdata.TypeURL,
		ResponseNonce: drdata.ResponseNonce,
	}
	c := cluster_service.NewClusterDiscoveryServiceClient(r.Target.Conn)
	stream, err := c.StreamClusters(context.Background())
	if err != nil {
		err = fmt.Errorf("Error starting CDS stream: %v\n", err)
		return err
	}
	r.CDS.Stream = stream
	r.CDS.Stream.Send(dreq)
	res, err := stream.Recv()
	r.CDS.Responses = res
	return nil
}

func (r *Runner) theStreamWasACKedWithADiscoveryRequestMatchingYaml(arg1 *godog.DocString) error {
	drdata, err := parser.ParseDiscoveryRequest(arg1.Content)
	if err != nil {
		err = fmt.Errorf("error parsing discovery request: %v\n", err)
		return err
	}
	dreq := &envoy_service_discovery_v3.DiscoveryRequest{
		VersionInfo: drdata.VersionInfo,
		Node: &envoy_config_core_v3.Node{
			Id: drdata.Node.ID,
		},
		ResourceNames: drdata.ResourceNames,
		TypeUrl:       drdata.TypeURL,
		ResponseNonce: drdata.ResponseNonce,
	}
	fmt.Printf("dreq: %v\n", dreq)
	r.CDS.Stream.Send(dreq)
	return nil
}

func (r *Runner) iSendADiscoveryRequestMatchingYaml(dryaml *godog.DocString) error {
	drdata, err := parser.ParseDiscoveryRequest(dryaml.Content)
	if err != nil {
		err = fmt.Errorf("error parsing discovery request: %v\n", err)
		return err
	}
	dreq := &envoy_service_discovery_v3.DiscoveryRequest{
		VersionInfo: drdata.VersionInfo,
		Node: &envoy_config_core_v3.Node{
			Id: drdata.Node.ID,
		},
		ResourceNames: drdata.ResourceNames,
		TypeUrl:       drdata.TypeURL,
		ResponseNonce: drdata.ResponseNonce,
	}
	c := cluster_service.NewClusterDiscoveryServiceClient(r.Target.Conn)
	dres, err := c.FetchClusters(context.Background(), dreq)
	if err != nil {
		log.Printf("err fetching clusters: %v", err.Error())
		return err
	}
	r.DiscoveryResponse = dres
	return nil
}

func (r *Runner) iGetADiscoveryResponseMatchingYaml(arg1 *godog.DocString) error {
	var expected parser.DiscoveryResponse
	if err := yaml.Unmarshal([]byte(arg1.Content), &expected); err != nil {
		return err
	}
	actual, _ := parser.ParseDiscoveryResponse(r.DiscoveryResponse)
	if !reflect.DeepEqual(expected, *actual) {
		return fmt.Errorf("expected yaml does not match actual, %v vs. %v", expected, *actual)
	}
	return nil
}

func connectViaGRPC(client *ClientConfig, server string) error {
	conn, err := grpc.Dial(client.Port, opts...)
	if err != nil {
		err = fmt.Errorf("Cannot connect to %v: %v", server, err)
		return err
	}
	client.Conn = conn
	return nil
}

func (r *Runner) isReachableViaGRPC(server string) error {
	switch server {
	case "adapter":
		err := connectViaGRPC(r.Adapter, server)
		return err
	case "target":
		err := connectViaGRPC(r.Target, server)
		return err
	default:
		err := fmt.Errorf("unexpected server name: %v", server)
		return err
	}
}

func (r *Runner) targetIsUpdatedToMatchYaml(yml *godog.DocString) error {
	snapshot, err := parser.YamlToSnapshot(yml.Content)
	if err != nil {
		err = fmt.Errorf("Error parsing snapshot yaml: %v", err)
		return err
	}
	c := pb.NewAdapterClient(r.Adapter.Conn)
	_, err = c.SetState(context.Background(), snapshot)
	if err != nil {
		err = fmt.Errorf("Cannot Set Target with State: %v\n", err)
		return err
	}
	return nil
}

func (r *Runner) theClientReceivesADiscoveryResponseMatchingYaml(yml *godog.DocString) error {
	dreq := &envoy_service_discovery_v3.DiscoveryRequest{
		VersionInfo: "1",
		Node: &envoy_config_core_v3.Node{
			Id: "test-id",
		},
		ResourceNames: []string{},
		TypeUrl:       "type.googleapis.com/envoy.config.cluster.v3.Cluster",
		ResponseNonce: "1",
	}
	fmt.Printf("dreq: %v\n", dreq)
	r.CDS.Stream.Send(dreq)
	res, err := r.CDS.Stream.Recv()
	if err != nil {
		err = fmt.Errorf("error receiving discovery response: %v\n", err)
		return err
	}
	fmt.Printf("res: %v\n", res)
	var expected parser.DiscoveryResponse
	if err := yaml.Unmarshal([]byte(yml.Content), &expected); err != nil {
		return err
	}
	actual, _ := parser.ParseDiscoveryResponse(res)
	if !reflect.DeepEqual(expected, *actual) {
		return fmt.Errorf("expected yaml does not match actual, %v vs. %v", expected, *actual)
	}
	return nil
}

func InitializeScenario(ctx *godog.ScenarioContext) {
	runner := &Runner{}

	ctx.BeforeScenario(runner.addPorts)

	ctx.Step(`^a Target setup with snapshot matching yaml:$`, runner.aTargetSetupWithSnapshotMatchingYaml)
	ctx.Step(`^I get a discovery response matching yaml:$`, runner.iGetADiscoveryResponseMatchingYaml)
	ctx.Step(`^I send a discovery request matching yaml:$`, runner.iSendADiscoveryRequestMatchingYaml)
	ctx.Step(`^"([^"]*)" is reachable via gRPC$`, runner.isReachableViaGRPC)
	ctx.Step(`^Target is updated to match yaml:$`, runner.targetIsUpdatedToMatchYaml)
	ctx.Step(`^the client receives a discovery response matching yaml:$`, runner.theClientReceivesADiscoveryResponseMatchingYaml)
	ctx.Step(`^a CDS stream was initiated with a discovery request matching yaml:$`, runner.aCDSStreamWasInitiatedWithADiscoveryRequestMatchingYaml)
	ctx.Step(`^the stream was ACKed with a discovery request matching yaml:$`, runner.theStreamWasACKedWithADiscoveryRequestMatchingYaml)
}
<|endoftext|>


<commit_before>/*
 Copyright 2016 Padduck, LLC

 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 server

import (
	"encoding/json"
	"io"
	"io/ioutil"
	"net/http"
	"os"
	"path/filepath"

	"github.com/gin-gonic/gin"
	"github.com/gorilla/websocket"
	"github.com/itsjamie/gin-cors"
	"github.com/pufferpanel/pufferd/httphandlers"
	"github.com/pufferpanel/pufferd/logging"
	"github.com/pufferpanel/pufferd/programs"
	"github.com/pufferpanel/pufferd/utils"
	"github.com/pkg/errors"
	"strings"
	"strconv"
)

var wsupgrader = websocket.Upgrader{
	ReadBufferSize:  1024,
	WriteBufferSize: 1024,
	CheckOrigin: func(r *http.Request) bool {
		return true
	},
}

func RegisterRoutes(e *gin.Engine) {
	l := e.Group("/server")
	{
		e.Handle("CONNECT", "/:id/console", func(c *gin.Context) {
			c.Header("Access-Control-Allow-Origin", "*")
			c.Header("Access-Control-Allow-Credentials", "false")
		})
		l.Use(httphandlers.OAuth2Handler)
		l.PUT("/:id", CreateServer)
		l.DELETE("/:id", DeleteServer)
		l.POST("/:id", EditServer)
		l.GET("/:id/start", StartServer)
		l.GET("/:id/stop", StopServer)
		l.POST("/:id/install", InstallServer)
		l.GET("/:id/file/*filename", GetFile)
		l.PUT("/:id/file/*filename", PutFile)
		l.DELETE("/:id/file/*filename", DeleteFile)
		l.POST("/:id/console", PostConsole)
		l.GET("/:id/stats", GetStats)
		l.POST("/:id/reload", ReloadServer)
		l.GET("/:id/console", cors.Middleware(cors.Config{
			Origins:     "*",
			Credentials: true,
		}), GetConsole)
		l.GET("/:id/logs", GetLogs)
	}
	e.GET("/network", httphandlers.OAuth2Handler, NetworkServer)
}

func StartServer(c *gin.Context) {
	valid, existing := handleInitialCallServer(c, "server.start", true)

	if !valid {
		c.Status(404)
		return
	}

	existing.Start()
}

func StopServer(c *gin.Context) {
	valid, existing := handleInitialCallServer(c, "server.stop", true)
	wait := c.Param("wait")
	if wait == "" || (wait != "true" && wait != "false") {
		wait = "true"
	}

	if !valid {
		c.Status(401)
		return
	}

	err := existing.Stop()
	if err != nil {
		c.Error(err)
	}

	if wait == "true" {
		err = existing.GetEnvironment().WaitForMainProcess()
		if err != nil {
			c.AbortWithError(500, err)
		}
	}
	c.Status(204)
}

func CreateServer(c *gin.Context) {
	serverId := c.Param("id")
	handleInitialCallServer(c, "server.create", false)

	existing := programs.GetFromCache(serverId)

	if existing != nil {
		c.AbortWithStatus(409)
		return
	}

	data := make(map[string]interface{}, 0)
	err := json.NewDecoder(c.Request.Body).Decode(&data)

	if err != nil {
		logging.Error("Error decoding JSON body", err)
		c.AbortWithError(400, err)
		return
	}

	serverType := data["type"].(string)

	if !programs.Create(serverId, serverType, data) {
		c.AbortWithStatus(500)
	}
}

func DeleteServer(c *gin.Context) {
	valid, existing := handleInitialCallServer(c, "server.delete", true)

	if !valid {
		return
	}

	programs.Delete(existing.Id())
	c.Status(204)
}

func InstallServer(c *gin.Context) {
	valid, existing := handleInitialCallServer(c, "server.install", true)

	if !valid {
		return
	}

	c.Status(204)
	go func() {
		existing.Install()
	}()
}

func EditServer(c *gin.Context) {
	valid, existing := handleInitialCallServer(c, "server.edit", true)

	if !valid {
		return
	}

	data := make(map[string]interface{}, 0)
	json.NewDecoder(c.Request.Body).Decode(&data)

	existing.Edit(data)
	c.Status(204)
}

func GetFile(c *gin.Context) {

	valid, server := handleInitialCallServer(c, "server.file.get", true)

	if !valid {
		return
	}

	targetPath := c.Param("filename")

	targetFile := utils.JoinPath(server.GetEnvironment().GetRootDirectory(), targetPath)

	if !utils.EnsureAccess(targetFile, server.GetEnvironment().GetRootDirectory()) {
		return
	}

	info, err := os.Stat(targetFile)

	if os.IsNotExist(err) {
		c.Status(404)
		return
	}

	if info.IsDir() {
		type FileDesc struct {
			Name      string    `json:"name"`
			Modified  int64     `json:"modifyTime"`
			Size      int64     `json:"size,omitempty"`
			File      bool      `json:"isFile"`
			Extension string    `json:"extension,omitempty"`
		}

		files, _ := ioutil.ReadDir(targetFile)
		fileNames := make([]interface{}, 0)
		if targetPath != "" && targetPath != "." && targetPath != "/" {
			newFile := &FileDesc{
				Name:      "..",
				File:      false,
			}
			fileNames = append(fileNames, newFile)
		}
		for _, file := range files {
			newFile := &FileDesc{
				Name:      file.Name(),
				File:      !file.IsDir(),
			}

			if newFile.File {
				newFile.Size = file.Size()
				newFile.Modified = file.ModTime().Unix()
				newFile.Extension = filepath.Ext(file.Name())
			}

			fileNames = append(fileNames, newFile)
		}
		c.JSON(200, fileNames)
	} else {
		_, err := os.Open(targetFile)
		if err != nil {
			if err == os.ErrNotExist {
				c.AbortWithStatus(404)
			} else {
				c.AbortWithStatus(500)
			}
		}
		c.File(targetFile)
	}
}

func PutFile(c *gin.Context) {
	valid, server := handleInitialCallServer(c, "server.file.put", true)

	if !valid {
		return
	}

	targetPath := c.Param("filename")

	if targetPath == "" {
		c.Status(404)
		return
	}

	targetFile := utils.JoinPath(server.GetEnvironment().GetRootDirectory(), targetPath)

	if !utils.EnsureAccess(targetFile, server.GetEnvironment().GetRootDirectory()) {
		c.Status(401)
		return
	}

	file, err := os.Create(targetFile)

	if err != nil {
		c.AbortWithError(500, err)
		logging.Error("Error writing file", err)
		return
	}

	c.Request.ParseMultipartForm(32 << 20)
	sourceFile, _, err := c.Request.FormFile("file")
	_, err = io.Copy(file, sourceFile)

	if err != nil {
		c.AbortWithError(500, err)
		logging.Error("Error writing file", err)
	} else {
		c.Status(204)
	}
}

func DeleteFile (c *gin.Context) {
	valid, server := handleInitialCallServer(c, "server.file.delete", true)

	if !valid {
		return
	}

	targetPath := c.Param("filename")

	targetFile := utils.JoinPath(server.GetEnvironment().GetRootDirectory(), targetPath)

	if !utils.EnsureAccess(targetFile, server.GetEnvironment().GetRootDirectory()) {
		return
	}

	err := os.Remove(targetFile)
	if err != nil {
		c.Status(500)
		logging.Error("Failed to delete file", err)
	} else {
		c.Status(204)
	}
}

func PostConsole(c *gin.Context) {
	valid, program := handleInitialCallServer(c, "server.console.send", true)
	if !valid {
		return
	}
	d, _ := ioutil.ReadAll(c.Request.Body)
	cmd := string(d)
	err := program.Execute(cmd)
	if err != nil {
		c.AbortWithError(500, err)
	} else {
		c.Status(200)
	}
}

func GetConsole(c *gin.Context) {
	valid, program := handleInitialCallServer(c, "server.console", true)
	if !valid {
		return
	}
	conn, err := wsupgrader.Upgrade(c.Writer, c.Request, nil)
	if err != nil {
		logging.Error("Error creating websocket", err)
		c.AbortWithError(500, err)
		return
	}
	console, _ := program.GetEnvironment().GetConsole()
	for _, v := range console {
		conn.WriteMessage(websocket.TextMessage, []byte(v))
	}
	program.GetEnvironment().AddListener(conn)
}

func GetStats(c *gin.Context) {
	valid, server := handleInitialCallServer(c, "server.stats", true)

	if !valid {
		return
	}

	results, err := server.GetEnvironment().GetStats()
	if err != nil {
		result := make(map[string]interface{})
		result["error"] = err.Error()
		c.JSON(200, result)
	} else {
		c.JSON(200, results)
	}
}

func ReloadServer(c *gin.Context) {
	valid, existing := handleInitialCallServer(c, "server.reload", true)

	if !valid {
		c.Status(404)
		return
	}

	err := programs.Reload(existing.Id())
	if err != nil {
		c.AbortWithError(500, err)
		return
	}
	c.Status(204)
}

func NetworkServer(c *gin.Context) {

	scopes, _ := c.Get("scopes")
	valid := false
	for _, v := range scopes.([]string) {
		if v == "server.network"{
			valid = true
		}
	}
	if !valid {
		c.AbortWithStatus(401)
		return
	}

	servers := c.DefaultQuery("ids", "")
	if servers == "" {
		c.AbortWithError(400, errors.New("Server ids required"))
		return
	}
	serverIds := strings.Split(servers, ",")
	result := make(map[string]string)
	for _, v := range serverIds {
		program, _ := programs.Get(v)
		if program == nil {
			continue
		}
		result[program.Id()] = program.GetNetwork()
	}
	c.JSON(200, result)
}

func GetLogs (c *gin.Context) {
	valid, program := handleInitialCallServer(c, "server.console", true)
	if !valid {
		return
	}

	time := c.DefaultQuery("time", "0")

	castedTime, ok := strconv.ParseInt(time, 10, 64)

	if ok != nil {
		c.AbortWithError(400, errors.New("Time provided is not a valid UNIX time"))
		return
	}

	console, epoch := program.GetEnvironment().GetConsoleFrom(castedTime)
	msg := ""
	for _, k := range console {
		msg += k + "\n"
	}
	result := make(map[string]interface{})
	result["epoch"] = epoch
	result["logs"] = msg;
	c.JSON(200, result)
}

func handleInitialCallServer(c *gin.Context, perm string, requireServer bool) (valid bool, program programs.Program) {
	valid = false

	serverId := c.Param("id")
	canAccessId, _ := c.Get("server_id")

	accessId := canAccessId.(string)

	if accessId != serverId && accessId != "*" {
		c.AbortWithStatus(401)
		return
	}

	if accessId == "*" {
		program, _ = programs.Get(serverId)
	} else {
		program, _ = programs.Get(accessId)
	}

	if requireServer && program == nil {
		c.AbortWithStatus(404)
		valid = false
		return
	}

	scopes, _ := c.Get("scopes")

	for _, v := range scopes.([]string) {
		if v == perm {
			valid = true
		}
	}

	valid = true

	return
}
<commit_msg>Allow creation of folders through API Done through passing ?folder as query string<commit_after>/*
 Copyright 2016 Padduck, LLC

 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 server

import (
	"encoding/json"
	"io"
	"io/ioutil"
	"net/http"
	"os"
	"path/filepath"

	"github.com/gin-gonic/gin"
	"github.com/gorilla/websocket"
	"github.com/itsjamie/gin-cors"
	"github.com/pufferpanel/pufferd/httphandlers"
	"github.com/pufferpanel/pufferd/logging"
	"github.com/pufferpanel/pufferd/programs"
	"github.com/pufferpanel/pufferd/utils"
	"github.com/pkg/errors"
	"strings"
	"strconv"
)

var wsupgrader = websocket.Upgrader{
	ReadBufferSize:  1024,
	WriteBufferSize: 1024,
	CheckOrigin: func(r *http.Request) bool {
		return true
	},
}

func RegisterRoutes(e *gin.Engine) {
	l := e.Group("/server")
	{
		e.Handle("CONNECT", "/:id/console", func(c *gin.Context) {
			c.Header("Access-Control-Allow-Origin", "*")
			c.Header("Access-Control-Allow-Credentials", "false")
		})
		l.Use(httphandlers.OAuth2Handler)
		l.PUT("/:id", CreateServer)
		l.DELETE("/:id", DeleteServer)
		l.POST("/:id", EditServer)
		l.GET("/:id/start", StartServer)
		l.GET("/:id/stop", StopServer)
		l.POST("/:id/install", InstallServer)
		l.GET("/:id/file/*filename", GetFile)
		l.PUT("/:id/file/*filename", PutFile)
		l.DELETE("/:id/file/*filename", DeleteFile)
		l.POST("/:id/console", PostConsole)
		l.GET("/:id/stats", GetStats)
		l.POST("/:id/reload", ReloadServer)
		l.GET("/:id/console", cors.Middleware(cors.Config{
			Origins:     "*",
			Credentials: true,
		}), GetConsole)
		l.GET("/:id/logs", GetLogs)
	}
	e.GET("/network", httphandlers.OAuth2Handler, NetworkServer)
}

func StartServer(c *gin.Context) {
	valid, existing := handleInitialCallServer(c, "server.start", true)

	if !valid {
		c.Status(404)
		return
	}

	existing.Start()
}

func StopServer(c *gin.Context) {
	valid, existing := handleInitialCallServer(c, "server.stop", true)
	wait := c.Param("wait")
	if wait == "" || (wait != "true" && wait != "false") {
		wait = "true"
	}

	if !valid {
		c.Status(401)
		return
	}

	err := existing.Stop()
	if err != nil {
		c.Error(err)
	}

	if wait == "true" {
		err = existing.GetEnvironment().WaitForMainProcess()
		if err != nil {
			c.AbortWithError(500, err)
		}
	}
	c.Status(204)
}

func CreateServer(c *gin.Context) {
	serverId := c.Param("id")
	handleInitialCallServer(c, "server.create", false)

	existing := programs.GetFromCache(serverId)

	if existing != nil {
		c.AbortWithStatus(409)
		return
	}

	data := make(map[string]interface{}, 0)
	err := json.NewDecoder(c.Request.Body).Decode(&data)

	if err != nil {
		logging.Error("Error decoding JSON body", err)
		c.AbortWithError(400, err)
		return
	}

	serverType := data["type"].(string)

	if !programs.Create(serverId, serverType, data) {
		c.AbortWithStatus(500)
	}
}

func DeleteServer(c *gin.Context) {
	valid, existing := handleInitialCallServer(c, "server.delete", true)

	if !valid {
		return
	}

	programs.Delete(existing.Id())
	c.Status(204)
}

func InstallServer(c *gin.Context) {
	valid, existing := handleInitialCallServer(c, "server.install", true)

	if !valid {
		return
	}

	c.Status(204)
	go func() {
		existing.Install()
	}()
}

func EditServer(c *gin.Context) {
	valid, existing := handleInitialCallServer(c, "server.edit", true)

	if !valid {
		return
	}

	data := make(map[string]interface{}, 0)
	json.NewDecoder(c.Request.Body).Decode(&data)

	existing.Edit(data)
	c.Status(204)
}

func GetFile(c *gin.Context) {

	valid, server := handleInitialCallServer(c, "server.file.get", true)

	if !valid {
		return
	}

	targetPath := c.Param("filename")

	targetFile := utils.JoinPath(server.GetEnvironment().GetRootDirectory(), targetPath)

	if !utils.EnsureAccess(targetFile, server.GetEnvironment().GetRootDirectory()) {
		return
	}

	info, err := os.Stat(targetFile)

	if os.IsNotExist(err) {
		c.Status(404)
		return
	}

	if info.IsDir() {
		type FileDesc struct {
			Name      string    `json:"name"`
			Modified  int64     `json:"modifyTime"`
			Size      int64     `json:"size,omitempty"`
			File      bool      `json:"isFile"`
			Extension string    `json:"extension,omitempty"`
		}

		files, _ := ioutil.ReadDir(targetFile)
		fileNames := make([]interface{}, 0)
		if targetPath != "" && targetPath != "." && targetPath != "/" {
			newFile := &FileDesc{
				Name:      "..",
				File:      false,
			}
			fileNames = append(fileNames, newFile)
		}
		for _, file := range files {
			newFile := &FileDesc{
				Name:      file.Name(),
				File:      !file.IsDir(),
			}

			if newFile.File {
				newFile.Size = file.Size()
				newFile.Modified = file.ModTime().Unix()
				newFile.Extension = filepath.Ext(file.Name())
			}

			fileNames = append(fileNames, newFile)
		}
		c.JSON(200, fileNames)
	} else {
		_, err := os.Open(targetFile)
		if err != nil {
			if err == os.ErrNotExist {
				c.AbortWithStatus(404)
			} else {
				c.AbortWithStatus(500)
			}
		}
		c.File(targetFile)
	}
}

func PutFile(c *gin.Context) {
	valid, server := handleInitialCallServer(c, "server.file.put", true)

	if !valid {
		return
	}

	targetPath := c.Param("filename")

	if targetPath == "" {
		c.Status(404)
		return
	}

	targetFile := utils.JoinPath(server.GetEnvironment().GetRootDirectory(), targetPath)

	if !utils.EnsureAccess(targetFile, server.GetEnvironment().GetRootDirectory()) {
		c.Status(401)
		return
	}

	_, mkFolder := c.GetQuery("folder")
	if (mkFolder) {
		err := os.Mkdir(targetFile, 0644)
		if err != nil {
			c.AbortWithError(500, err)
		} else {
			c.Status(204)
		}
		return
	}
	file, err := os.Create(targetFile)

	if err != nil {
		c.AbortWithError(500, err)
		logging.Error("Error writing file", err)
		return
	}

	c.Request.ParseMultipartForm(32 << 20)
	sourceFile, _, err := c.Request.FormFile("file")
	_, err = io.Copy(file, sourceFile)

	if err != nil {
		c.AbortWithError(500, err)
		logging.Error("Error writing file", err)
	} else {
		c.Status(204)
	}
}

func DeleteFile (c *gin.Context) {
	valid, server := handleInitialCallServer(c, "server.file.delete", true)

	if !valid {
		return
	}

	targetPath := c.Param("filename")

	targetFile := utils.JoinPath(server.GetEnvironment().GetRootDirectory(), targetPath)

	if !utils.EnsureAccess(targetFile, server.GetEnvironment().GetRootDirectory()) {
		return
	}

	err := os.Remove(targetFile)
	if err != nil {
		c.Status(500)
		logging.Error("Failed to delete file", err)
	} else {
		c.Status(204)
	}
}

func PostConsole(c *gin.Context) {
	valid, program := handleInitialCallServer(c, "server.console.send", true)
	if !valid {
		return
	}
	d, _ := ioutil.ReadAll(c.Request.Body)
	cmd := string(d)
	err := program.Execute(cmd)
	if err != nil {
		c.AbortWithError(500, err)
	} else {
		c.Status(200)
	}
}

func GetConsole(c *gin.Context) {
	valid, program := handleInitialCallServer(c, "server.console", true)
	if !valid {
		return
	}
	conn, err := wsupgrader.Upgrade(c.Writer, c.Request, nil)
	if err != nil {
		logging.Error("Error creating websocket", err)
		c.AbortWithError(500, err)
		return
	}
	console, _ := program.GetEnvironment().GetConsole()
	for _, v := range console {
		conn.WriteMessage(websocket.TextMessage, []byte(v))
	}
	program.GetEnvironment().AddListener(conn)
}

func GetStats(c *gin.Context) {
	valid, server := handleInitialCallServer(c, "server.stats", true)

	if !valid {
		return
	}

	results, err := server.GetEnvironment().GetStats()
	if err != nil {
		result := make(map[string]interface{})
		result["error"] = err.Error()
		c.JSON(200, result)
	} else {
		c.JSON(200, results)
	}
}

func ReloadServer(c *gin.Context) {
	valid, existing := handleInitialCallServer(c, "server.reload", true)

	if !valid {
		c.Status(404)
		return
	}

	err := programs.Reload(existing.Id())
	if err != nil {
		c.AbortWithError(500, err)
		return
	}
	c.Status(204)
}

func NetworkServer(c *gin.Context) {

	scopes, _ := c.Get("scopes")
	valid := false
	for _, v := range scopes.([]string) {
		if v == "server.network"{
			valid = true
		}
	}
	if !valid {
		c.AbortWithStatus(401)
		return
	}

	servers := c.DefaultQuery("ids", "")
	if servers == "" {
		c.AbortWithError(400, errors.New("Server ids required"))
		return
	}
	serverIds := strings.Split(servers, ",")
	result := make(map[string]string)
	for _, v := range serverIds {
		program, _ := programs.Get(v)
		if program == nil {
			continue
		}
		result[program.Id()] = program.GetNetwork()
	}
	c.JSON(200, result)
}

func GetLogs (c *gin.Context) {
	valid, program := handleInitialCallServer(c, "server.console", true)
	if !valid {
		return
	}

	time := c.DefaultQuery("time", "0")

	castedTime, ok := strconv.ParseInt(time, 10, 64)

	if ok != nil {
		c.AbortWithError(400, errors.New("Time provided is not a valid UNIX time"))
		return
	}

	console, epoch := program.GetEnvironment().GetConsoleFrom(castedTime)
	msg := ""
	for _, k := range console {
		msg += k + "\n"
	}
	result := make(map[string]interface{})
	result["epoch"] = epoch
	result["logs"] = msg;
	c.JSON(200, result)
}

func handleInitialCallServer(c *gin.Context, perm string, requireServer bool) (valid bool, program programs.Program) {
	valid = false

	serverId := c.Param("id")
	canAccessId, _ := c.Get("server_id")

	accessId := canAccessId.(string)

	if accessId != serverId && accessId != "*" {
		c.AbortWithStatus(401)
		return
	}

	if accessId == "*" {
		program, _ = programs.Get(serverId)
	} else {
		program, _ = programs.Get(accessId)
	}

	if requireServer && program == nil {
		c.AbortWithStatus(404)
		valid = false
		return
	}

	scopes, _ := c.Get("scopes")

	for _, v := range scopes.([]string) {
		if v == perm {
			valid = true
		}
	}

	valid = true

	return
}
<|endoftext|>


<commit_before>// $G $D/$F.go && $L $F.$A && ./$A.out

// Copyright 2009 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	main

export func
setpd(a *[]int)
{
//	print("setpd a=", a, " len=", len(a), " cap=", cap(a), "\n");
	for i:=0; i<len(a); i++ {
		a[i] = i;
	}
}

export func
sumpd(a *[]int) int
{
//	print("sumpd a=", a, " len=", len(a), " cap=", cap(a), "\n");
	t := 0;
	for i:=0; i<len(a); i++ {
		t += a[i];
	}
//	print("sumpd t=", t, "\n");
	return t;
}

export func
setpf(a *[20]int)
{
//	print("setpf a=", a, " len=", len(a), " cap=", cap(a), "\n");
	for i:=0; i<len(a); i++ {
		a[i] = i;
	}
}

export func
sumpf(a *[20]int) int
{
//	print("sumpf a=", a, " len=", len(a), " cap=", cap(a), "\n");
	t := 0;
	for i:=0; i<len(a); i++ {
		t += a[i];
	}
//	print("sumpf t=", t, "\n");
	return t;
}

func
res(t int, lb, hb int)
{
	sb := (hb-lb)*(hb+lb-1)/2;
	if t != sb {
		print(	"lb=", lb,
			"; hb=", hb,
			"; t=", t,
			"; sb=", sb,
			"\n");
		panic("res")
	}
}

// call ptr dynamic with ptr dynamic
func
testpdpd()
{
	a := new([]int, 10, 100);
	if len(a) != 10 && cap(a) != 100 {
		panic("len and cap from new: ", len(a), " ", cap(a), "\n");
	}

	a = a[0:100];
	setpd(a);

	a = a[0:10];
	res(sumpd(a), 0, 10);

	a = a[5:25];
	res(sumpd(a), 5, 25);
}

// call ptr fixed with ptr fixed
func
testpfpf()
{
	var a [20]int;

	setpf(&a);
	res(sumpf(&a), 0, 20);
}

// call ptr dynamic with ptr fixed from new
func
testpdpf1()
{
	a := new([40]int);
	setpd(a);
	res(sumpd(a), 0, 40);

	b := a[5:30];
	res(sumpd(b), 5, 30);
}

// call ptr dynamic with ptr fixed from var
func
testpdpf2()
{
	var a [80]int;

	setpd(&a);
	res(sumpd(&a), 0, 80);
}

// generate bounds error with ptr dynamic
func
testpdfault()
{
	a := new([]int, 100);

	print("good\n");
	for i:=0; i<100; i++ {
		a[i] = 0;
	}
	print("should fault\n");
	a[100] = 0;
	print("bad\n");
}

// generate bounds error with ptr fixed
func
testfdfault()
{
	var a [80]int;

	print("good\n");
	for i:=0; i<80; i++ {
		a[i] = 0;
	}
	print("should fault\n");
	a[80] = 0;
	print("bad\n");
}

func
main()
{
	testpdpd();
	testpfpf();
	testpdpf1();
	testpdpf2();
//	print("testpdfault\n");	testpdfault();
//	print("testfdfault\n");	testfdfault();
}
<commit_msg>compiler catches out of bounds; work around<commit_after>// $G $D/$F.go && $L $F.$A && ./$A.out

// Copyright 2009 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	main

export func
setpd(a *[]int)
{
//	print("setpd a=", a, " len=", len(a), " cap=", cap(a), "\n");
	for i:=0; i<len(a); i++ {
		a[i] = i;
	}
}

export func
sumpd(a *[]int) int
{
//	print("sumpd a=", a, " len=", len(a), " cap=", cap(a), "\n");
	t := 0;
	for i:=0; i<len(a); i++ {
		t += a[i];
	}
//	print("sumpd t=", t, "\n");
	return t;
}

export func
setpf(a *[20]int)
{
//	print("setpf a=", a, " len=", len(a), " cap=", cap(a), "\n");
	for i:=0; i<len(a); i++ {
		a[i] = i;
	}
}

export func
sumpf(a *[20]int) int
{
//	print("sumpf a=", a, " len=", len(a), " cap=", cap(a), "\n");
	t := 0;
	for i:=0; i<len(a); i++ {
		t += a[i];
	}
//	print("sumpf t=", t, "\n");
	return t;
}

func
res(t int, lb, hb int)
{
	sb := (hb-lb)*(hb+lb-1)/2;
	if t != sb {
		print(	"lb=", lb,
			"; hb=", hb,
			"; t=", t,
			"; sb=", sb,
			"\n");
		panic("res")
	}
}

// call ptr dynamic with ptr dynamic
func
testpdpd()
{
	a := new([]int, 10, 100);
	if len(a) != 10 && cap(a) != 100 {
		panic("len and cap from new: ", len(a), " ", cap(a), "\n");
	}

	a = a[0:100];
	setpd(a);

	a = a[0:10];
	res(sumpd(a), 0, 10);

	a = a[5:25];
	res(sumpd(a), 5, 25);
}

// call ptr fixed with ptr fixed
func
testpfpf()
{
	var a [20]int;

	setpf(&a);
	res(sumpf(&a), 0, 20);
}

// call ptr dynamic with ptr fixed from new
func
testpdpf1()
{
	a := new([40]int);
	setpd(a);
	res(sumpd(a), 0, 40);

	b := a[5:30];
	res(sumpd(b), 5, 30);
}

// call ptr dynamic with ptr fixed from var
func
testpdpf2()
{
	var a [80]int;

	setpd(&a);
	res(sumpd(&a), 0, 80);
}

// generate bounds error with ptr dynamic
func
testpdfault()
{
	a := new([]int, 100);

	print("good\n");
	for i:=0; i<100; i++ {
		a[i] = 0;
	}
	print("should fault\n");
	a[100] = 0;
	print("bad\n");
}

// generate bounds error with ptr fixed
func
testfdfault()
{
	var a [80]int;

	print("good\n");
	for i:=0; i<80; i++ {
		a[i] = 0;
	}
	print("should fault\n");
	x := 80;
	a[x] = 0;
	print("bad\n");
}

func
main()
{
	testpdpd();
	testpfpf();
	testpdpf1();
	testpdpf2();
//	print("testpdfault\n");	testpdfault();
//	print("testfdfault\n");	testfdfault();
}
<|endoftext|>


<commit_before>package xco

import "testing"

var nilAddress Address

var parseAddressTests = []struct {
	Input  string
	Output Address
	Error  string
}{
	{"", nilAddress, "Address is empty"},
	{"           ", nilAddress, "Address is empty"},
	{"@example.com", nilAddress, "Localpart is empty"},
	{"example.com/", nilAddress, "Resourcepart is empty"},
	{"@example.com/", nilAddress, "Multiple errors: [Localpart is empty Resourcepart is empty]"},
	{"@/", nilAddress, "Multiple errors: [Domain is empty Localpart is empty Resourcepart is empty]"},

	{"example.com", Address{"", "example.com", ""}, ""},
	{"hello@example.com", Address{"hello", "example.com", ""}, ""},
	{"example.com/home", Address{"", "example.com", "home"}, ""},
	{"hello@example.com/home", Address{"hello", "example.com", "home"}, ""},

	{"goodbye@example.com/home", Address{"goodbye", "example.com", "home"}, ""},
}

func TestParseAddress(t *testing.T) {
	for _, pat := range parseAddressTests {
		addr, err := ParseAddress(pat.Input)
		matches := addr.Equals(&pat.Output) && (err == nil && pat.Error == "" || err.Error() == pat.Error)
		if !matches {
			t.Errorf("ParseAddress(%s) => {%s,%v}, expected {%s,%s}",
				pat.Input, addr, err, pat.Output, pat.Error)
		}
	}
}

var stringAddressTests = []struct {
	Input  *Address
	Output string
}{
	{&Address{"", "example.com", ""}, "example.com"},
	{&Address{"hello", "example.com", ""}, "hello@example.com"},
	{&Address{"", "example.com", "home"}, "example.com/home"},
	{&Address{"hello", "example.com", "home"}, "hello@example.com/home"},
	{&Address{"goodbye", "example.com", "home"}, "goodbye@example.com/home"},
}

func TestStringAddress(t *testing.T) {
	for _, sat := range stringAddressTests {
		out := sat.Input.String()
		matches := out == sat.Output
		if !matches {
			t.Errorf("%v.String() => {%s}, expected {%s}",
				sat.Input, out, sat.Output)
		}
	}
}
<commit_msg>Fix address tests<commit_after>package xco

import "testing"

var nilAddress = Address{}
var withDomain = Address{DomainPart: "example.com"}

var parseAddressTests = []struct {
	Input  string
	Output Address
	Error  string
}{
	{"", nilAddress, "Address is empty"},
	{"           ", nilAddress, "Address is empty"},
	{"@example.com", withDomain, "Localpart is empty"},
	{"example.com/", withDomain, "Resourcepart is empty"},
	{"@example.com/", withDomain, "Multiple errors: [Localpart is empty Resourcepart is empty]"},
	{"@/", nilAddress, "Multiple errors: [Domain is empty Localpart is empty Resourcepart is empty]"},

	{"example.com", Address{"", "example.com", ""}, ""},
	{"hello@example.com", Address{"hello", "example.com", ""}, ""},
	{"example.com/home", Address{"", "example.com", "home"}, ""},
	{"hello@example.com/home", Address{"hello", "example.com", "home"}, ""},

	{"goodbye@example.com/home", Address{"goodbye", "example.com", "home"}, ""},
}

func TestParseAddress(t *testing.T) {
	for _, pat := range parseAddressTests {
		addr, err := ParseAddress(pat.Input)
		matches := addr.Equals(&pat.Output) && (err == nil && pat.Error == "" || err.Error() == pat.Error)
		if !matches {
			t.Errorf("ParseAddress(%s) => {%s,%v}, expected {%s,%s}",
				pat.Input, addr, err, pat.Output, pat.Error)
		}
	}
}

var stringAddressTests = []struct {
	Input  *Address
	Output string
}{
	{&Address{"", "example.com", ""}, "example.com"},
	{&Address{"hello", "example.com", ""}, "hello@example.com"},
	{&Address{"", "example.com", "home"}, "example.com/home"},
	{&Address{"hello", "example.com", "home"}, "hello@example.com/home"},
	{&Address{"goodbye", "example.com", "home"}, "goodbye@example.com/home"},
}

func TestStringAddress(t *testing.T) {
	for _, sat := range stringAddressTests {
		out := sat.Input.String()
		matches := out == sat.Output
		if !matches {
			t.Errorf("%v.String() => {%s}, expected {%s}",
				sat.Input, out, sat.Output)
		}
	}
}
<|endoftext|>