<commit_before>package metrics

import (
	"fmt"
	"sort"

	"github.com/bazelbuild/continuous-integration/metrics/clients"
	"github.com/bazelbuild/continuous-integration/metrics/data"
	"github.com/buildkite/go-buildkite/buildkite"
)

type CriticalPath struct {
	client      clients.BuildkiteClient
	pipelines   []*data.PipelineID
	columns     []Column
	lastNBuilds int
	debug       bool
}

func (cp *CriticalPath) Name() string {
	return "critical_path"
}

func (cp *CriticalPath) Columns() []Column {
	return cp.columns
}

func (*CriticalPath) Type() MetricType {
	return BuildBasedMetric
}

func (*CriticalPath) RelevantDelta() int {
	return 200 // builds
}

func (cp *CriticalPath) Collect() (data.DataSet, error) {
	result := data.CreateDataSet(GetColumnNames(cp.columns))
	for _, pipeline := range cp.pipelines {
		builds, err := cp.client.GetMostRecentBuilds(pipeline, cp.lastNBuilds)
		if err != nil {
			return nil, fmt.Errorf("Cannot collect critical path statistics for pipeline %s: %v", pipeline, err)
		}
		for _, build := range builds {
			if build.FinishedAt == nil {
				continue
			}
			// TODO(fweikert): remove
			if cp.debug {
				fmt.Printf("%v -> %v -> %v -> %v (%d)\n", *build.ScheduledAt, *build.CreatedAt, *build.StartedAt, *build.FinishedAt, *build.Number)
				for _, job := range build.Jobs {
					if job.Name != nil {
						fmt.Printf("%v -> %v -> %v -> %v -> %v (%s)\n", *job.ScheduledAt, *job.CreatedAt, *job.RunnableAt, *job.StartedAt, *job.FinishedAt, *job.Name)
					}
				}
			}

			// Caveat: The Buildkite API only returns the latest invocation of each job within a given build,
			// which causes a problem when a failing build is retried via the web UI. In this case the time
			// between the original run and the retry will be counted as wait time by this code.
			wait_time_seconds, longest_task_name, longest_task_time_seconds, err := analyzeJobs(build.ScheduledAt, build.Jobs)
			if err != nil {
				return nil, fmt.Errorf("Could not calculate waiting time for build %d: %v", *build.Number, err)
			}

			run_time_seconds := getDifferenceSeconds(build.CreatedAt, build.FinishedAt) - wait_time_seconds
			err = result.AddRow(pipeline.Org, pipeline.Slug, *build.Number, wait_time_seconds, run_time_seconds, longest_task_name, longest_task_time_seconds, *build.State)
			if err != nil {
				return nil, fmt.Errorf("Failed to add result for build %d: %v", *build.Number, err)
			}
		}
	}
	return result, nil
}

type event struct {
	*buildkite.Timestamp
	runDelta int
}

func analyzeJobs(scheduleTime *buildkite.Timestamp, jobs []*buildkite.Job) (wait_time_seconds float64, longest_task_name string, longest_task_time_seconds float64, err error) {
	events := make([]event, 0)
	for _, job := range jobs {
		if job.Name == nil || job.FinishedAt == nil {
			continue
		}
		// Job lifecycle: scheduled -> created -> runnable -> started -> finished
		// wait time = started - runnable
		// run time = finished - started
		// total time = finished - runnable
		// Scheduled and created are affected by "wait" steps, so we don't look at them here.
		duration := getDifferenceSeconds(job.RunnableAt, job.FinishedAt)
		if duration > longest_task_time_seconds {
			longest_task_name = *job.Name
			longest_task_time_seconds = duration
		}
		events = append(events, event{job.StartedAt, 1}, event{job.FinishedAt, -1})
	}
	sortFunc := func(i, j int) bool { return events[i].Time.Before(events[j].Time) }
	sort.Slice(events, sortFunc)

	runningTasks := 0
	prevTime := scheduleTime
	for _, evt := range events {
		if runningTasks == 0 {
			wait_time_seconds += getDifferenceSeconds(prevTime, evt.Timestamp)
		}
		runningTasks += evt.runDelta
		prevTime = evt.Timestamp
	}
	if runningTasks > 0 {
		err = fmt.Errorf("There are %d unfinished jobs", runningTasks)
	}
	return
}

// CREATE TABLE critical_path (org VARCHAR(255), pipeline VARCHAR(255), build INT, wait_time_seconds FLOAT, run_time_seconds FLOAT, longest_task_name VARCHAR(255), longest_task_time_seconds FLOAT, result VARCHAR(255), PRIMARY KEY(org, pipeline, build));
func CreateCriticalPath(client clients.BuildkiteClient, lastNBuilds int, pipelines ...*data.PipelineID) *CriticalPath {
	columns := []Column{Column{"org", true}, Column{"pipeline", true}, Column{"build", true}, Column{"wait_time_seconds", false}, Column{"run_time_seconds", false}, Column{"longest_task_name", false}, Column{"longest_task_time_seconds", false}, Column{"result", false}}
	return &CriticalPath{client: client, pipelines: pipelines, columns: columns, lastNBuilds: lastNBuilds, debug: false}
}
<commit_msg>Fix nil pointer dereference in critical_path (#831)<commit_after>package metrics

import (
	"fmt"
	"sort"

	"github.com/bazelbuild/continuous-integration/metrics/clients"
	"github.com/bazelbuild/continuous-integration/metrics/data"
	"github.com/buildkite/go-buildkite/buildkite"
)

type CriticalPath struct {
	client      clients.BuildkiteClient
	pipelines   []*data.PipelineID
	columns     []Column
	lastNBuilds int
	debug       bool
}

func (cp *CriticalPath) Name() string {
	return "critical_path"
}

func (cp *CriticalPath) Columns() []Column {
	return cp.columns
}

func (*CriticalPath) Type() MetricType {
	return BuildBasedMetric
}

func (*CriticalPath) RelevantDelta() int {
	return 200 // builds
}

func (cp *CriticalPath) Collect() (data.DataSet, error) {
	result := data.CreateDataSet(GetColumnNames(cp.columns))
	for _, pipeline := range cp.pipelines {
		builds, err := cp.client.GetMostRecentBuilds(pipeline, cp.lastNBuilds)
		if err != nil {
			return nil, fmt.Errorf("Cannot collect critical path statistics for pipeline %s: %v", pipeline, err)
		}
		for _, build := range builds {
			if build.FinishedAt == nil {
				continue
			}
			// TODO(fweikert): remove
			if cp.debug {
				fmt.Printf("%v -> %v -> %v -> %v (%d)\n", *build.ScheduledAt, *build.CreatedAt, *build.StartedAt, *build.FinishedAt, *build.Number)
				for _, job := range build.Jobs {
					if job.Name != nil {
						fmt.Printf("%v -> %v -> %v -> %v -> %v (%s)\n", *job.ScheduledAt, *job.CreatedAt, *job.RunnableAt, *job.StartedAt, *job.FinishedAt, *job.Name)
					}
				}
			}

			// Caveat: The Buildkite API only returns the latest invocation of each job within a given build,
			// which causes a problem when a failing build is retried via the web UI. In this case the time
			// between the original run and the retry will be counted as wait time by this code.
			wait_time_seconds, longest_task_name, longest_task_time_seconds, err := analyzeJobs(build.ScheduledAt, build.Jobs)
			if err != nil {
				return nil, fmt.Errorf("Could not calculate waiting time for build %d: %v", *build.Number, err)
			}

			run_time_seconds := getDifferenceSeconds(build.CreatedAt, build.FinishedAt) - wait_time_seconds
			err = result.AddRow(pipeline.Org, pipeline.Slug, *build.Number, wait_time_seconds, run_time_seconds, longest_task_name, longest_task_time_seconds, *build.State)
			if err != nil {
				return nil, fmt.Errorf("Failed to add result for build %d: %v", *build.Number, err)
			}
		}
	}
	return result, nil
}

type event struct {
	*buildkite.Timestamp
	runDelta int
}

func analyzeJobs(scheduleTime *buildkite.Timestamp, jobs []*buildkite.Job) (wait_time_seconds float64, longest_task_name string, longest_task_time_seconds float64, err error) {
	events := make([]event, 0)
	for _, job := range jobs {
		// Name == nil -> "wait" step
		// StartedAt == nil -> step was cancelled while waiting for an agent
		// FinishedAt == nil -> step is still running
		if job.Name == nil || job.StartedAt == nil || job.FinishedAt == nil {
			continue
		}

		// Job lifecycle: scheduled -> created -> runnable -> started -> finished
		// wait time = started - runnable
		// run time = finished - started
		// total time = finished - runnable
		// Scheduled and created are affected by "wait" steps, so we don't look at them here.
		duration := getDifferenceSeconds(job.RunnableAt, job.FinishedAt)
		if duration > longest_task_time_seconds {
			longest_task_name = *job.Name
			longest_task_time_seconds = duration
		}
		events = append(events, event{job.StartedAt, 1}, event{job.FinishedAt, -1})
	}
	sortFunc := func(i, j int) bool { return events[i].Time.Before(events[j].Time) }
	sort.Slice(events, sortFunc)

	runningTasks := 0
	prevTime := scheduleTime
	for _, evt := range events {
		if runningTasks == 0 {
			wait_time_seconds += getDifferenceSeconds(prevTime, evt.Timestamp)
		}
		runningTasks += evt.runDelta
		prevTime = evt.Timestamp
	}
	if runningTasks > 0 {
		err = fmt.Errorf("There are %d unfinished jobs", runningTasks)
	}
	return
}

// CREATE TABLE critical_path (org VARCHAR(255), pipeline VARCHAR(255), build INT, wait_time_seconds FLOAT, run_time_seconds FLOAT, longest_task_name VARCHAR(255), longest_task_time_seconds FLOAT, result VARCHAR(255), PRIMARY KEY(org, pipeline, build));
func CreateCriticalPath(client clients.BuildkiteClient, lastNBuilds int, pipelines ...*data.PipelineID) *CriticalPath {
	columns := []Column{Column{"org", true}, Column{"pipeline", true}, Column{"build", true}, Column{"wait_time_seconds", false}, Column{"run_time_seconds", false}, Column{"longest_task_name", false}, Column{"longest_task_time_seconds", false}, Column{"result", false}}
	return &CriticalPath{client: client, pipelines: pipelines, columns: columns, lastNBuilds: lastNBuilds, debug: false}
}
<|endoftext|>


<commit_before>package getter

import (
	"crypto/md5"
	"encoding/hex"
	"io"
	"io/ioutil"
	"os"
	"path/filepath"
	"reflect"
	"runtime"
	"sort"
	"strings"
	"testing"
)

// TestDecompressCase is a single test case for testing decompressors
type TestDecompressCase struct {
	Input   string   // Input is the complete path to the input file
	Dir     bool     // Dir is whether or not we're testing directory mode
	Err     bool     // Err is whether we expect an error or not
	DirList []string // DirList is the list of files for Dir mode
	FileMD5 string   // FileMD5 is the expected MD5 for a single file
}

// TestDecompressor is a helper function for testing generic decompressors.
func TestDecompressor(t *testing.T, d Decompressor, cases []TestDecompressCase) {
	for _, tc := range cases {
		t.Logf("Testing: %s", tc.Input)

		// Temporary dir to store stuff
		td, err := ioutil.TempDir("", "getter")
		if err != nil {
			t.Fatalf("err: %s", err)
		}

		// Destination is always joining result so that we have a new path
		dst := filepath.Join(td, "subdir", "result")

		// We use a function so defers work
		func() {
			defer os.RemoveAll(td)

			// Decompress
			err := d.Decompress(dst, tc.Input, tc.Dir)
			if (err != nil) != tc.Err {
				t.Fatalf("err %s: %s", tc.Input, err)
			}
			if tc.Err {
				return
			}

			// If it isn't a directory, then check for a single file
			if !tc.Dir {
				fi, err := os.Stat(dst)
				if err != nil {
					t.Fatalf("err %s: %s", tc.Input, err)
				}
				if fi.IsDir() {
					t.Fatalf("err %s: expected file, got directory", tc.Input)
				}
				if tc.FileMD5 != "" {
					actual := testMD5(t, dst)
					expected := tc.FileMD5
					if actual != expected {
						t.Fatalf("err %s: expected MD5 %s, got %s", tc.Input, expected, actual)
					}
				}

				return
			}

			// Convert expected for windows
			expected := tc.DirList
			if runtime.GOOS == "windows" {
				for i, v := range expected {
					expected[i] = strings.Replace(v, "/", "\\", -1)
				}
			}

			// Directory, check for the correct contents
			actual := testListDir(t, dst)
			if !reflect.DeepEqual(actual, expected) {
				t.Fatalf("bad %s\n\n%#v\n\n%#v", tc.Input, actual, expected)
			}
		}()
	}
}

func testListDir(t *testing.T, path string) []string {
	var result []string
	err := filepath.Walk(path, func(sub string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}

		sub = strings.TrimPrefix(sub, path)
		if sub == "" {
			return nil
		}
		sub = sub[1:] // Trim the leading path sep.

		// If it is a dir, add trailing sep
		if info.IsDir() {
			sub += string(os.PathSeparator)
		}

		result = append(result, sub)
		return nil
	})
	if err != nil {
		t.Fatalf("err: %s", err)
	}

	sort.Strings(result)
	return result
}

func testMD5(t *testing.T, path string) string {
	f, err := os.Open(path)
	if err != nil {
		t.Fatalf("err: %s", err)
	}
	defer f.Close()

	h := md5.New()
	_, err = io.Copy(h, f)
	if err != nil {
		t.Fatalf("err: %s", err)
	}

	result := h.Sum(nil)
	return hex.EncodeToString(result)
}
<commit_msg>Use mitchellh/go-testing-interface instead of "testing"<commit_after>package getter

import (
	"crypto/md5"
	"encoding/hex"
	"io"
	"io/ioutil"
	"os"
	"path/filepath"
	"reflect"
	"runtime"
	"sort"
	"strings"

	"github.com/mitchellh/go-testing-interface"
)

// TestDecompressCase is a single test case for testing decompressors
type TestDecompressCase struct {
	Input   string   // Input is the complete path to the input file
	Dir     bool     // Dir is whether or not we're testing directory mode
	Err     bool     // Err is whether we expect an error or not
	DirList []string // DirList is the list of files for Dir mode
	FileMD5 string   // FileMD5 is the expected MD5 for a single file
}

// TestDecompressor is a helper function for testing generic decompressors.
func TestDecompressor(t testing.T, d Decompressor, cases []TestDecompressCase) {
	for _, tc := range cases {
		t.Logf("Testing: %s", tc.Input)

		// Temporary dir to store stuff
		td, err := ioutil.TempDir("", "getter")
		if err != nil {
			t.Fatalf("err: %s", err)
		}

		// Destination is always joining result so that we have a new path
		dst := filepath.Join(td, "subdir", "result")

		// We use a function so defers work
		func() {
			defer os.RemoveAll(td)

			// Decompress
			err := d.Decompress(dst, tc.Input, tc.Dir)
			if (err != nil) != tc.Err {
				t.Fatalf("err %s: %s", tc.Input, err)
			}
			if tc.Err {
				return
			}

			// If it isn't a directory, then check for a single file
			if !tc.Dir {
				fi, err := os.Stat(dst)
				if err != nil {
					t.Fatalf("err %s: %s", tc.Input, err)
				}
				if fi.IsDir() {
					t.Fatalf("err %s: expected file, got directory", tc.Input)
				}
				if tc.FileMD5 != "" {
					actual := testMD5(t, dst)
					expected := tc.FileMD5
					if actual != expected {
						t.Fatalf("err %s: expected MD5 %s, got %s", tc.Input, expected, actual)
					}
				}

				return
			}

			// Convert expected for windows
			expected := tc.DirList
			if runtime.GOOS == "windows" {
				for i, v := range expected {
					expected[i] = strings.Replace(v, "/", "\\", -1)
				}
			}

			// Directory, check for the correct contents
			actual := testListDir(t, dst)
			if !reflect.DeepEqual(actual, expected) {
				t.Fatalf("bad %s\n\n%#v\n\n%#v", tc.Input, actual, expected)
			}
		}()
	}
}

func testListDir(t testing.T, path string) []string {
	var result []string
	err := filepath.Walk(path, func(sub string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}

		sub = strings.TrimPrefix(sub, path)
		if sub == "" {
			return nil
		}
		sub = sub[1:] // Trim the leading path sep.

		// If it is a dir, add trailing sep
		if info.IsDir() {
			sub += string(os.PathSeparator)
		}

		result = append(result, sub)
		return nil
	})
	if err != nil {
		t.Fatalf("err: %s", err)
	}

	sort.Strings(result)
	return result
}

func testMD5(t testing.T, path string) string {
	f, err := os.Open(path)
	if err != nil {
		t.Fatalf("err: %s", err)
	}
	defer f.Close()

	h := md5.New()
	_, err = io.Copy(h, f)
	if err != nil {
		t.Fatalf("err: %s", err)
	}

	result := h.Sum(nil)
	return hex.EncodeToString(result)
}
<|endoftext|>


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

import (
	"os"
	"os/exec"
	"testing"

	"github.com/golang/glog"
	"github.com/onsi/ginkgo"
	"github.com/onsi/ginkgo/config"
	"github.com/onsi/gomega"
	_ "k8s.io/client-go/plugin/pkg/client/auth"

	"github.com/jetstack/cert-manager/pkg/logs"
	_ "github.com/jetstack/cert-manager/test/e2e/certificate"
	_ "github.com/jetstack/cert-manager/test/e2e/clusterissuer"
	"github.com/jetstack/cert-manager/test/e2e/framework"
	_ "github.com/jetstack/cert-manager/test/e2e/ingress"
	_ "github.com/jetstack/cert-manager/test/e2e/issuer"
)

// TestE2E checks configuration parameters (specified through flags) and then runs
// E2E tests using the Ginkgo runner.
func RunE2ETests(t *testing.T) {
	logs.InitLogs()
	defer logs.FlushLogs()

	gomega.RegisterFailHandler(ginkgo.Fail)
	// Disable skipped tests unless they are explicitly requested.
	if config.GinkgoConfig.FocusString == "" && config.GinkgoConfig.SkipString == "" {
		config.GinkgoConfig.SkipString = `\[Flaky\]|\[Feature:.+\]`
	}

	glog.Infof("Installing cert-manager helm chart")
	InstallHelmChart(t, releaseName, "./contrib/charts/cert-manager", "cert-manager", "./test/fixtures/cert-manager-values.yaml")

	glog.Infof("Installing boulder chart")
	extraArgs := []string{}
	if framework.TestContext.BoulderImageRepo != "" {
		extraArgs = append(extraArgs, "--set image.repository="+framework.TestContext.BoulderImageRepo)
	}
	if framework.TestContext.BoulderImageTag != "" {
		extraArgs = append(extraArgs, "--set image.tag="+framework.TestContext.BoulderImageTag)
	}
	InstallHelmChart(t, "boulder", "./contrib/charts/boulder", "boulder", "./test/fixtures/boulder-values.yaml", extraArgs...)
	glog.Infof("Starting e2e run %q on Ginkgo node %d", framework.RunId, config.GinkgoConfig.ParallelNode)

	if !ginkgo.RunSpecs(t, "cert-manager e2e suite") {
		PrintPodLogs(t)
	}
}

const releaseName = "cm"

func InstallHelmChart(t *testing.T, releaseName, chartName, namespace, values string, extraArgs ...string) {
	args := []string{"install", chartName, "--namespace", namespace, "--name", releaseName, "--values", values, "--wait"}
	args = append(args, extraArgs...)
	cmd := exec.Command("helm", args...)
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	err := cmd.Run()
	if err != nil {
		t.Errorf("Error installing cert-manager: %s", err)
		t.FailNow()
		return
	}
}

func PrintPodLogs(t *testing.T) {
	glog.Infof("Printing cert-manager logs")
	cmd := exec.Command("kubectl", "logs", "--namespace", "cert-manager", "-l", "app=cert-manager", "-l", "release=cm", "-c", "cert-manager")
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	err := cmd.Run()
	if err != nil {
		t.Errorf("Error printing cert-manager logs: %s", err)
	}
	glog.Infof("Printing ingress-shim logs")
	cmdShim := exec.Command("kubectl", "logs", "--namespace", "cert-manager", "-l", "app=cert-manager", "-l", "release=cm", "-c", "ingress-shim")
	cmdShim.Stdout = os.Stdout
	cmdShim.Stderr = os.Stderr
	err = cmdShim.Run()
	if err != nil {
		t.Errorf("Error printing ingress-shim logs: %s", err)
	}
}
<commit_msg>Fix passing boulder image args<commit_after>/*
Copyright 2015 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 e2e

import (
	"os"
	"os/exec"
	"testing"

	"github.com/golang/glog"
	"github.com/onsi/ginkgo"
	"github.com/onsi/ginkgo/config"
	"github.com/onsi/gomega"
	_ "k8s.io/client-go/plugin/pkg/client/auth"

	"github.com/jetstack/cert-manager/pkg/logs"
	_ "github.com/jetstack/cert-manager/test/e2e/certificate"
	_ "github.com/jetstack/cert-manager/test/e2e/clusterissuer"
	"github.com/jetstack/cert-manager/test/e2e/framework"
	_ "github.com/jetstack/cert-manager/test/e2e/ingress"
	_ "github.com/jetstack/cert-manager/test/e2e/issuer"
)

// TestE2E checks configuration parameters (specified through flags) and then runs
// E2E tests using the Ginkgo runner.
func RunE2ETests(t *testing.T) {
	logs.InitLogs()
	defer logs.FlushLogs()

	gomega.RegisterFailHandler(ginkgo.Fail)
	// Disable skipped tests unless they are explicitly requested.
	if config.GinkgoConfig.FocusString == "" && config.GinkgoConfig.SkipString == "" {
		config.GinkgoConfig.SkipString = `\[Flaky\]|\[Feature:.+\]`
	}

	glog.Infof("Installing cert-manager helm chart")
	InstallHelmChart(t, releaseName, "./contrib/charts/cert-manager", "cert-manager", "./test/fixtures/cert-manager-values.yaml")

	glog.Infof("Installing boulder chart")
	extraArgs := []string{}
	if framework.TestContext.BoulderImageRepo != "" {
		extraArgs = append(extraArgs, "--set", "image.repository="+framework.TestContext.BoulderImageRepo)
	}
	if framework.TestContext.BoulderImageTag != "" {
		extraArgs = append(extraArgs, "--set", "image.tag="+framework.TestContext.BoulderImageTag)
	}
	InstallHelmChart(t, "boulder", "./contrib/charts/boulder", "boulder", "./test/fixtures/boulder-values.yaml", extraArgs...)
	glog.Infof("Starting e2e run %q on Ginkgo node %d", framework.RunId, config.GinkgoConfig.ParallelNode)

	if !ginkgo.RunSpecs(t, "cert-manager e2e suite") {
		PrintPodLogs(t)
	}
}

const releaseName = "cm"

func InstallHelmChart(t *testing.T, releaseName, chartName, namespace, values string, extraArgs ...string) {
	args := []string{"install", chartName, "--namespace", namespace, "--name", releaseName, "--values", values, "--wait"}
	args = append(args, extraArgs...)
	cmd := exec.Command("helm", args...)
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	err := cmd.Run()
	if err != nil {
		t.Errorf("Error installing cert-manager: %s", err)
		t.FailNow()
		return
	}
}

func PrintPodLogs(t *testing.T) {
	glog.Infof("Printing cert-manager logs")
	cmd := exec.Command("kubectl", "logs", "--namespace", "cert-manager", "-l", "app=cert-manager", "-l", "release=cm", "-c", "cert-manager")
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	err := cmd.Run()
	if err != nil {
		t.Errorf("Error printing cert-manager logs: %s", err)
	}
	glog.Infof("Printing ingress-shim logs")
	cmdShim := exec.Command("kubectl", "logs", "--namespace", "cert-manager", "-l", "app=cert-manager", "-l", "release=cm", "-c", "ingress-shim")
	cmdShim.Stdout = os.Stdout
	cmdShim.Stderr = os.Stderr
	err = cmdShim.Run()
	if err != nil {
		t.Errorf("Error printing ingress-shim logs: %s", err)
	}
}
<|endoftext|>


<commit_before>package jobs

import (
	"bytes"
	"encoding/base64"
	"encoding/json"
	"fmt"
	"regexp"
	"strconv"
	"strings"

	"github.com/juju/errgo"

	"arvika.pulcy.com/pulcy/deployit/units"
)

var (
	taskNamePattern = regexp.MustCompile(`^([a-z0-9_]{2,30})$`)
)

type TaskName string

func (tn TaskName) String() string {
	return string(tn)
}

func (tn TaskName) Validate() error {
	if !taskNamePattern.MatchString(string(tn)) {
		return maskAny(errgo.WithCausef(nil, InvalidNameError, "task name must match '%s', got '%s'", taskNamePattern, tn))
	}
	return nil
}

type Task struct {
	Name   TaskName   `json:"name", maspstructure:"-"`
	group  *TaskGroup `json:"-", mapstructure:"-"`
	Count  uint       `json:"-"` // This value is used during parsing only
	Global bool       `json:"-"` // This value is used during parsing only

	Image         DockerImage       `json:"image"`
	VolumesFrom   []TaskName        `json:"volumes-from,omitempty"`
	Volumes       []string          `json:"volumes,omitempty"`
	Args          []string          `json:"args,omitempty"`
	Environment   map[string]string `json:"environment,omitempty"`
	Ports         []string          `json:"ports,omitempty"`
	FrontEnds     []FrontEnd        `json:"frontends,omitempty"`
	HttpCheckPath string            `json:"http-check-path,omitempty" mapstructure:"http-check-path,omitempty"`
}

type TaskList []*Task

// Check for errors
func (t *Task) Validate() error {
	if err := t.Name.Validate(); err != nil {
		return maskAny(err)
	}
	for _, name := range t.VolumesFrom {
		_, err := t.group.Task(name)
		if err != nil {
			return maskAny(err)
		}
	}

	return nil
}

// createUnits creates all units needed to run this task.
func (t *Task) createUnits(scalingGroup uint) ([]*units.Unit, error) {
	units := []*units.Unit{}
	main, err := t.createMainUnit(scalingGroup)
	if err != nil {
		return nil, maskAny(err)
	}
	units = append(units, main)

	return units, nil
}

// createMainUnit
func (t *Task) createMainUnit(scalingGroup uint) (*units.Unit, error) {
	name := t.containerName(scalingGroup)
	serviceName := t.serviceName()
	image := t.Image.String()
	execStart := []string{
		"/usr/bin/docker",
		"run",
		"--rm",
		fmt.Sprintf("--name %s", name),
	}
	if len(t.Ports) > 0 {
		for _, p := range t.Ports {
			execStart = append(execStart, fmt.Sprintf("-p %s", p))
		}
	} else {
		execStart = append(execStart, "-P")
	}
	after := []string{}
	for _, v := range t.Volumes {
		execStart = append(execStart, fmt.Sprintf("-v %s", v))
	}
	for _, name := range t.VolumesFrom {
		other, err := t.group.Task(name)
		if err != nil {
			return nil, maskAny(err)
		}
		execStart = append(execStart, fmt.Sprintf("--volumes-from %s", other.containerName(scalingGroup)))
		after = append(after, other.unitName(strconv.Itoa(int(scalingGroup)))+".service")
	}
	for k, v := range t.Environment {
		execStart = append(execStart, "-e "+strconv.Quote(fmt.Sprintf("%s=%s", k, v)))
	}
	execStart = append(execStart, fmt.Sprintf("-e SERVICE_NAME=%s", serviceName)) // Support registrator
	execStart = append(execStart, image)
	execStart = append(execStart, t.Args...)
	main := &units.Unit{
		Name:         t.unitName(strconv.Itoa(int(scalingGroup))),
		FullName:     t.unitName(strconv.Itoa(int(scalingGroup))) + ".service",
		Description:  fmt.Sprintf("Main unit for %s slice %v", t.fullName(), scalingGroup),
		Type:         "service",
		Scalable:     t.group.IsScalable(),
		ScalingGroup: scalingGroup,
		ExecOptions:  units.NewExecOptions(execStart...),
		FleetOptions: units.NewFleetOptions(),
	}
	//main.FleetOptions.IsGlobal = ds.global
	main.ExecOptions.ExecStartPre = []string{
		fmt.Sprintf("/usr/bin/docker pull %s", image),
		fmt.Sprintf("-/usr/bin/docker stop -t %v %s", main.ExecOptions.ContainerTimeoutStopSec, name),
		fmt.Sprintf("-/usr/bin/docker rm -f %s", name),
	}
	for _, v := range t.Volumes {
		dir := strings.Split(v, ":")
		mkdir := fmt.Sprintf("/bin/sh -c 'test -e %s || mkdir -p %s'", dir[0], dir[0])
		main.ExecOptions.ExecStartPre = append(main.ExecOptions.ExecStartPre, mkdir)
	}
	for _, name := range t.VolumesFrom {
		other, err := t.group.Task(name)
		if err != nil {
			return nil, maskAny(err)
		}
		main.ExecOptions.Require(other.containerName(scalingGroup))
	}
	main.ExecOptions.ExecStop = fmt.Sprintf("-/usr/bin/docker stop -t %v %s", main.ExecOptions.ContainerTimeoutStopSec, name)
	main.ExecOptions.ExecStopPost = []string{
		fmt.Sprintf("-/usr/bin/docker rm -f %s", name),
	}
	main.FleetOptions.IsGlobal = t.group.Global
	if t.group.IsScalable() {
		main.FleetOptions.Conflicts(t.unitName("*") + ".service")
	}
	//main.ExecOptions.Require("flanneld.service")
	main.ExecOptions.Require("docker.service")
	main.ExecOptions.After("docker.service")
	main.ExecOptions.After(after...)

	if err := t.addFrontEndRegistration(main); err != nil {
		return nil, maskAny(err)
	}

	return main, nil
}

// Gets the full name of this task: job/taskgroup/task
func (t *Task) fullName() string {
	return fmt.Sprintf("%s/%s", t.group.fullName(), t.Name)
}

// unitName returns the name of the systemd unit for this task.
func (t *Task) unitName(scalingGroup string) string {
	base := strings.Replace(t.fullName(), "/", "-", -1)
	if !t.group.IsScalable() {
		return base
	}
	return fmt.Sprintf("%s@%s", base, scalingGroup)
}

// containerName returns the name of the docker contained used for this task.
func (t *Task) containerName(scalingGroup uint) string {
	base := strings.Replace(t.fullName(), "/", "-", -1)
	if !t.group.IsScalable() {
		return base
	}
	return fmt.Sprintf("%s-%v", base, scalingGroup)
}

// serviceName returns the name used to register this service.
func (t *Task) serviceName() string {
	return strings.Replace(t.fullName(), "/", "-", -1)
}

type frontendRecord struct {
	Selectors     []frontendSelectorRecord `json:"selectors"`
	Service       string                   `json:"service,omitempty"`
	HttpCheckPath string                   `json:"http-check-path,omitempty"`
}

type frontendSelectorRecord struct {
	Domain     string `json:"domain,omitempty"`
	PathPrefix string `json:"path-prefix,omitempty"`
	SslCert    string `json:"ssl-cert,omitempty"`
}

// addFrontEndRegistration adds registration code for frontends to the given units
func (t *Task) addFrontEndRegistration(main *units.Unit) error {
	if len(t.FrontEnds) == 0 {
		return nil
	}
	key := "/pulcy/frontend/" + t.serviceName()
	record := frontendRecord{
		Service:       t.serviceName(),
		HttpCheckPath: t.HttpCheckPath,
	}
	for _, fr := range t.FrontEnds {
		record.Selectors = append(record.Selectors, frontendSelectorRecord{
			Domain:     fr.Domain,
			PathPrefix: fr.PathPrefix,
			SslCert:    fr.SslCert,
		})
	}
	json, err := json.Marshal(&record)
	if err != nil {
		return maskAny(err)
	}
	main.ExecOptions.ExecStartPost = append(main.ExecOptions.ExecStartPost,
		fmt.Sprintf("/bin/sh -c 'echo %s | base64 -d | /usr/bin/etcdctl set %s'", base64.StdEncoding.EncodeToString(json), key),
	)
	return nil
}

func (l TaskList) Len() int {
	return len(l)
}

func (l TaskList) Less(i, j int) bool {
	return bytes.Compare([]byte(l[i].Name.String()), []byte(l[j].Name.String())) < 0
}

func (l TaskList) Swap(i, j int) {
	tmp := l[i]
	l[i] = l[j]
	l[j] = tmp
}
<commit_msg>Added `After=yard.service`<commit_after>package jobs

import (
	"bytes"
	"encoding/base64"
	"encoding/json"
	"fmt"
	"regexp"
	"strconv"
	"strings"

	"github.com/juju/errgo"

	"arvika.pulcy.com/pulcy/deployit/units"
)

var (
	taskNamePattern = regexp.MustCompile(`^([a-z0-9_]{2,30})$`)
)

type TaskName string

func (tn TaskName) String() string {
	return string(tn)
}

func (tn TaskName) Validate() error {
	if !taskNamePattern.MatchString(string(tn)) {
		return maskAny(errgo.WithCausef(nil, InvalidNameError, "task name must match '%s', got '%s'", taskNamePattern, tn))
	}
	return nil
}

type Task struct {
	Name   TaskName   `json:"name", maspstructure:"-"`
	group  *TaskGroup `json:"-", mapstructure:"-"`
	Count  uint       `json:"-"` // This value is used during parsing only
	Global bool       `json:"-"` // This value is used during parsing only

	Image         DockerImage       `json:"image"`
	VolumesFrom   []TaskName        `json:"volumes-from,omitempty"`
	Volumes       []string          `json:"volumes,omitempty"`
	Args          []string          `json:"args,omitempty"`
	Environment   map[string]string `json:"environment,omitempty"`
	Ports         []string          `json:"ports,omitempty"`
	FrontEnds     []FrontEnd        `json:"frontends,omitempty"`
	HttpCheckPath string            `json:"http-check-path,omitempty" mapstructure:"http-check-path,omitempty"`
}

type TaskList []*Task

// Check for errors
func (t *Task) Validate() error {
	if err := t.Name.Validate(); err != nil {
		return maskAny(err)
	}
	for _, name := range t.VolumesFrom {
		_, err := t.group.Task(name)
		if err != nil {
			return maskAny(err)
		}
	}

	return nil
}

// createUnits creates all units needed to run this task.
func (t *Task) createUnits(scalingGroup uint) ([]*units.Unit, error) {
	units := []*units.Unit{}
	main, err := t.createMainUnit(scalingGroup)
	if err != nil {
		return nil, maskAny(err)
	}
	units = append(units, main)

	return units, nil
}

// createMainUnit
func (t *Task) createMainUnit(scalingGroup uint) (*units.Unit, error) {
	name := t.containerName(scalingGroup)
	serviceName := t.serviceName()
	image := t.Image.String()
	execStart := []string{
		"/usr/bin/docker",
		"run",
		"--rm",
		fmt.Sprintf("--name %s", name),
	}
	if len(t.Ports) > 0 {
		for _, p := range t.Ports {
			execStart = append(execStart, fmt.Sprintf("-p %s", p))
		}
	} else {
		execStart = append(execStart, "-P")
	}
	after := []string{}
	for _, v := range t.Volumes {
		execStart = append(execStart, fmt.Sprintf("-v %s", v))
	}
	for _, name := range t.VolumesFrom {
		other, err := t.group.Task(name)
		if err != nil {
			return nil, maskAny(err)
		}
		execStart = append(execStart, fmt.Sprintf("--volumes-from %s", other.containerName(scalingGroup)))
		after = append(after, other.unitName(strconv.Itoa(int(scalingGroup)))+".service")
	}
	for k, v := range t.Environment {
		execStart = append(execStart, "-e "+strconv.Quote(fmt.Sprintf("%s=%s", k, v)))
	}
	execStart = append(execStart, fmt.Sprintf("-e SERVICE_NAME=%s", serviceName)) // Support registrator
	execStart = append(execStart, image)
	execStart = append(execStart, t.Args...)
	main := &units.Unit{
		Name:         t.unitName(strconv.Itoa(int(scalingGroup))),
		FullName:     t.unitName(strconv.Itoa(int(scalingGroup))) + ".service",
		Description:  fmt.Sprintf("Main unit for %s slice %v", t.fullName(), scalingGroup),
		Type:         "service",
		Scalable:     t.group.IsScalable(),
		ScalingGroup: scalingGroup,
		ExecOptions:  units.NewExecOptions(execStart...),
		FleetOptions: units.NewFleetOptions(),
	}
	//main.FleetOptions.IsGlobal = ds.global
	main.ExecOptions.ExecStartPre = []string{
		fmt.Sprintf("/usr/bin/docker pull %s", image),
		fmt.Sprintf("-/usr/bin/docker stop -t %v %s", main.ExecOptions.ContainerTimeoutStopSec, name),
		fmt.Sprintf("-/usr/bin/docker rm -f %s", name),
	}
	for _, v := range t.Volumes {
		dir := strings.Split(v, ":")
		mkdir := fmt.Sprintf("/bin/sh -c 'test -e %s || mkdir -p %s'", dir[0], dir[0])
		main.ExecOptions.ExecStartPre = append(main.ExecOptions.ExecStartPre, mkdir)
	}
	for _, name := range t.VolumesFrom {
		other, err := t.group.Task(name)
		if err != nil {
			return nil, maskAny(err)
		}
		main.ExecOptions.Require(other.containerName(scalingGroup))
	}
	main.ExecOptions.ExecStop = fmt.Sprintf("-/usr/bin/docker stop -t %v %s", main.ExecOptions.ContainerTimeoutStopSec, name)
	main.ExecOptions.ExecStopPost = []string{
		fmt.Sprintf("-/usr/bin/docker rm -f %s", name),
	}
	main.FleetOptions.IsGlobal = t.group.Global
	if t.group.IsScalable() {
		main.FleetOptions.Conflicts(t.unitName("*") + ".service")
	}
	//main.ExecOptions.Require("flanneld.service")
	main.ExecOptions.Require("docker.service")
	main.ExecOptions.After("docker.service")
	main.ExecOptions.After("yard.service")
	main.ExecOptions.After(after...)

	if err := t.addFrontEndRegistration(main); err != nil {
		return nil, maskAny(err)
	}

	return main, nil
}

// Gets the full name of this task: job/taskgroup/task
func (t *Task) fullName() string {
	return fmt.Sprintf("%s/%s", t.group.fullName(), t.Name)
}

// unitName returns the name of the systemd unit for this task.
func (t *Task) unitName(scalingGroup string) string {
	base := strings.Replace(t.fullName(), "/", "-", -1)
	if !t.group.IsScalable() {
		return base
	}
	return fmt.Sprintf("%s@%s", base, scalingGroup)
}

// containerName returns the name of the docker contained used for this task.
func (t *Task) containerName(scalingGroup uint) string {
	base := strings.Replace(t.fullName(), "/", "-", -1)
	if !t.group.IsScalable() {
		return base
	}
	return fmt.Sprintf("%s-%v", base, scalingGroup)
}

// serviceName returns the name used to register this service.
func (t *Task) serviceName() string {
	return strings.Replace(t.fullName(), "/", "-", -1)
}

type frontendRecord struct {
	Selectors     []frontendSelectorRecord `json:"selectors"`
	Service       string                   `json:"service,omitempty"`
	HttpCheckPath string                   `json:"http-check-path,omitempty"`
}

type frontendSelectorRecord struct {
	Domain     string `json:"domain,omitempty"`
	PathPrefix string `json:"path-prefix,omitempty"`
	SslCert    string `json:"ssl-cert,omitempty"`
}

// addFrontEndRegistration adds registration code for frontends to the given units
func (t *Task) addFrontEndRegistration(main *units.Unit) error {
	if len(t.FrontEnds) == 0 {
		return nil
	}
	key := "/pulcy/frontend/" + t.serviceName()
	record := frontendRecord{
		Service:       t.serviceName(),
		HttpCheckPath: t.HttpCheckPath,
	}
	for _, fr := range t.FrontEnds {
		record.Selectors = append(record.Selectors, frontendSelectorRecord{
			Domain:     fr.Domain,
			PathPrefix: fr.PathPrefix,
			SslCert:    fr.SslCert,
		})
	}
	json, err := json.Marshal(&record)
	if err != nil {
		return maskAny(err)
	}
	main.ExecOptions.ExecStartPost = append(main.ExecOptions.ExecStartPost,
		fmt.Sprintf("/bin/sh -c 'echo %s | base64 -d | /usr/bin/etcdctl set %s'", base64.StdEncoding.EncodeToString(json), key),
	)
	return nil
}

func (l TaskList) Len() int {
	return len(l)
}

func (l TaskList) Less(i, j int) bool {
	return bytes.Compare([]byte(l[i].Name.String()), []byte(l[j].Name.String())) < 0
}

func (l TaskList) Swap(i, j int) {
	tmp := l[i]
	l[i] = l[j]
	l[j] = tmp
}
<|endoftext|>


<commit_before>package list

import (
	"github.com/spf13/cobra"
	"github.com/BluePecker/JwtAuth/dialog/client"
	"fmt"
	"strings"
	"encoding/json"
	"github.com/BluePecker/JwtAuth/dialog/server/parameter/token/request"
)

func NewCommand() *cobra.Command {
	cmd := &cobra.Command{
		Use:   "ls",
		Short: "list user's json-web-token",
		RunE: func(cmd *cobra.Command, args []string) error {
			unixSock, err := cmd.Parent().Flags().GetString("unix-sock")
			if err != nil {
				return err
			}
			body, _ := json.Marshal(request.List{Unique: args[0]})
			cli := client.NewClient(unixSock)
			if body, err := cli.Post("/v1.0/token/list",
				"application/json", strings.NewReader(string(body))); err != nil {
				return err
			} else {
				fmt.Printf("result: %s\n", body)
			}

			return nil
		},
	}

	return cmd
}
<commit_msg>debug<commit_after>package list

import (
	"github.com/spf13/cobra"
	"github.com/BluePecker/JwtAuth/dialog/client"
	"fmt"
	"encoding/json"
	"github.com/BluePecker/JwtAuth/dialog/server/parameter/token/request"
	"bytes"
)

func NewCommand() *cobra.Command {
	cmd := &cobra.Command{
		Use:   "ls",
		Short: "list user's json-web-token",
		RunE: func(cmd *cobra.Command, args []string) error {
			unixSock, err := cmd.Parent().Flags().GetString("unix-sock")
			if err != nil {
				return err
			}
			body, _ := json.Marshal(request.List{Unique: args[0]})
			cli := client.NewClient(unixSock)
			if body, err := cli.Post("/v1.0/token/list",
				"application/json", bytes.NewBuffer([]byte(body))); err != nil {
				return err
			} else {
				fmt.Printf("result: %s\n", body)
			}

			return nil
		},
	}

	return cmd
}
<|endoftext|>


<commit_before>package irma

import (
	"encoding/base64"
	"encoding/json"
	"math/big"
	"strings"

	"bytes"

	"fmt"

	"github.com/go-errors/errors"
)

// Status encodes the status of an IRMA session (e.g., connected).
type Status string

// ProtocolVersion encodes the IRMA protocol version of an IRMA session.
type ProtocolVersion struct {
	major int
	minor int
}

func NewVersion(major, minor int) *ProtocolVersion {
	return &ProtocolVersion{major, minor}
}

func (v *ProtocolVersion) String() string {
	return fmt.Sprintf("%d.%d", v.major, v.minor)
}

// Returns true if v is below the given version.
func (v *ProtocolVersion) Below(major, minor int) bool {
	if v.major < major {
		return true
	}
	return v.major == major && v.minor < minor
}

// Action encodes the session type of an IRMA session (e.g., disclosing).
type Action string

// ErrorType are session errors.
type ErrorType string

// SessionError is a protocol error.
type SessionError struct {
	Err error
	ErrorType
	*ApiError
	Info          string
	Status        int
	StatusMessage string
}

// ApiError is an error message returned by the API server on errors.
type ApiError struct {
	Status      int    `json:"status"`
	ErrorName   string `json:"error"`
	Description string `json:"description"`
	Message     string `json:"message"`
	Stacktrace  string `json:"stacktrace"`
}

func (err *ApiError) Error() string {
	var msg string
	if err.Message != "" {
		msg = fmt.Sprintf(" (%s)", err.Message)
	}
	return fmt.Sprintf("%s%s: %s", err.ErrorName, msg, err.Description)
}

// Qr contains the data of an IRMA session QR (as generated by irma_js),
// suitable for NewSession().
type Qr struct {
	// Server with which to perform the session
	URL string `json:"u"`
	// Session type (disclosing, signing, issuing)
	Type               Action `json:"irmaqr"`
	ProtocolVersion    string `json:"v"`
	ProtocolMaxVersion string `json:"vmax"`
}

// A SessionInfo is the first message in the IRMA protocol (i.e., GET on the server URL),
// containing the session request info.
type SessionInfo struct {
	Jwt     string                   `json:"jwt"`
	Nonce   *big.Int                 `json:"nonce"`
	Context *big.Int                 `json:"context"`
	Keys    map[IssuerIdentifier]int `json:"keys"`
}

// Statuses
const (
	StatusConnected     = Status("connected")
	StatusCommunicating = Status("communicating")
	StatusManualStarted = Status("manualStarted")
)

// Actions
const (
	ActionSchemeManager = Action("schememanager")
	ActionDisclosing    = Action("disclosing")
	ActionSigning       = Action("signing")
	ActionIssuing       = Action("issuing")
	ActionUnknown       = Action("unknown")
)

// Protocol errors
const (
	// Protocol version not supported
	ErrorProtocolVersionNotSupported = ErrorType("protocolVersionNotSupported")
	// Error in HTTP communication
	ErrorTransport = ErrorType("transport")
	// Invalid client JWT in first IRMA message
	ErrorInvalidJWT = ErrorType("invalidJwt")
	// Unkown session type (not disclosing, signing, or issuing)
	ErrorUnknownAction = ErrorType("unknownAction")
	// Crypto error during calculation of our response (second IRMA message)
	ErrorCrypto = ErrorType("crypto")
	// Server rejected our response (second IRMA message)
	ErrorRejected = ErrorType("rejected")
	// (De)serializing of a message failed
	ErrorSerialization = ErrorType("serialization")
	// Error in keyshare protocol
	ErrorKeyshare = ErrorType("keyshare")
	// API server error
	ErrorApi = ErrorType("api")
	// Server returned unexpected or malformed response
	ErrorServerResponse = ErrorType("serverResponse")
	// Credential type not present in our Configuration
	ErrorUnknownCredentialType = ErrorType("unknownCredentialType")
	// Error during downloading of credential type, issuer, or public keys
	ErrorConfigurationDownload = ErrorType("configurationDownload")
	// IRMA requests refers to unknown scheme manager
	ErrorUnknownSchemeManager = ErrorType("unknownSchemeManager")
	// A session is requested involving a scheme manager that has some problem
	ErrorInvalidSchemeManager = ErrorType("invalidSchemeManager")
	// Recovered panic
	ErrorPanic = ErrorType("panic")
)

func (e *SessionError) Error() string {
	var buffer bytes.Buffer
	typ := e.ErrorType
	if typ == "" {
		typ = ErrorType("unknown")
	}

	buffer.WriteString("Error type: ")
	buffer.WriteString(string(typ))
	if e.Err != nil {
		buffer.WriteString("\nDescription: ")
		buffer.WriteString(e.Err.Error())
	}
	if e.Status != 200 && e.StatusMessage != "" {
		buffer.WriteString("\nConnection: ")
		buffer.WriteString(e.StatusMessage)
	}
	if e.ApiError != nil {
		buffer.WriteString("\nIRMA server error: ")
		buffer.WriteString(e.ApiError.Error())
	}

	return buffer.String()
}

func JwtDecode(jwt string, body interface{}) error {
	jwtparts := strings.Split(jwt, ".")
	if jwtparts == nil || len(jwtparts) < 2 {
		return errors.New("Not a JWT")
	}
	bodybytes, err := base64.RawStdEncoding.DecodeString(jwtparts[1])
	if err != nil {
		return err
	}
	return json.Unmarshal(bodybytes, body)
}

func ParseRequestorJwt(action Action, jwt string) (RequestorJwt, error) {
	var retval RequestorJwt
	switch action {
	case ActionDisclosing:
		retval = &ServiceProviderJwt{}
	case ActionSigning:
		retval = &SignatureRequestorJwt{}
	case ActionIssuing:
		retval = &IdentityProviderJwt{}
	default:
		return nil, errors.New("Invalid session type")
	}
	err := JwtDecode(jwt, retval)
	if err != nil {
		return nil, err
	}
	return retval, nil
}
<commit_msg>Add a Stack method to SessionError to get strack traces out, if any.<commit_after>package irma

import (
	"encoding/base64"
	"encoding/json"
	"math/big"
	"strings"

	"bytes"

	"fmt"

	"github.com/go-errors/errors"
)

// Status encodes the status of an IRMA session (e.g., connected).
type Status string

// ProtocolVersion encodes the IRMA protocol version of an IRMA session.
type ProtocolVersion struct {
	major int
	minor int
}

func NewVersion(major, minor int) *ProtocolVersion {
	return &ProtocolVersion{major, minor}
}

func (v *ProtocolVersion) String() string {
	return fmt.Sprintf("%d.%d", v.major, v.minor)
}

// Returns true if v is below the given version.
func (v *ProtocolVersion) Below(major, minor int) bool {
	if v.major < major {
		return true
	}
	return v.major == major && v.minor < minor
}

// Action encodes the session type of an IRMA session (e.g., disclosing).
type Action string

// ErrorType are session errors.
type ErrorType string

// SessionError is a protocol error.
type SessionError struct {
	Err error
	ErrorType
	*ApiError
	Info          string
	Status        int
	StatusMessage string
}

// ApiError is an error message returned by the API server on errors.
type ApiError struct {
	Status      int    `json:"status"`
	ErrorName   string `json:"error"`
	Description string `json:"description"`
	Message     string `json:"message"`
	Stacktrace  string `json:"stacktrace"`
}

func (err *ApiError) Error() string {
	var msg string
	if err.Message != "" {
		msg = fmt.Sprintf(" (%s)", err.Message)
	}
	return fmt.Sprintf("%s%s: %s", err.ErrorName, msg, err.Description)
}

// Qr contains the data of an IRMA session QR (as generated by irma_js),
// suitable for NewSession().
type Qr struct {
	// Server with which to perform the session
	URL string `json:"u"`
	// Session type (disclosing, signing, issuing)
	Type               Action `json:"irmaqr"`
	ProtocolVersion    string `json:"v"`
	ProtocolMaxVersion string `json:"vmax"`
}

// A SessionInfo is the first message in the IRMA protocol (i.e., GET on the server URL),
// containing the session request info.
type SessionInfo struct {
	Jwt     string                   `json:"jwt"`
	Nonce   *big.Int                 `json:"nonce"`
	Context *big.Int                 `json:"context"`
	Keys    map[IssuerIdentifier]int `json:"keys"`
}

// Statuses
const (
	StatusConnected     = Status("connected")
	StatusCommunicating = Status("communicating")
	StatusManualStarted = Status("manualStarted")
)

// Actions
const (
	ActionSchemeManager = Action("schememanager")
	ActionDisclosing    = Action("disclosing")
	ActionSigning       = Action("signing")
	ActionIssuing       = Action("issuing")
	ActionUnknown       = Action("unknown")
)

// Protocol errors
const (
	// Protocol version not supported
	ErrorProtocolVersionNotSupported = ErrorType("protocolVersionNotSupported")
	// Error in HTTP communication
	ErrorTransport = ErrorType("transport")
	// Invalid client JWT in first IRMA message
	ErrorInvalidJWT = ErrorType("invalidJwt")
	// Unkown session type (not disclosing, signing, or issuing)
	ErrorUnknownAction = ErrorType("unknownAction")
	// Crypto error during calculation of our response (second IRMA message)
	ErrorCrypto = ErrorType("crypto")
	// Server rejected our response (second IRMA message)
	ErrorRejected = ErrorType("rejected")
	// (De)serializing of a message failed
	ErrorSerialization = ErrorType("serialization")
	// Error in keyshare protocol
	ErrorKeyshare = ErrorType("keyshare")
	// API server error
	ErrorApi = ErrorType("api")
	// Server returned unexpected or malformed response
	ErrorServerResponse = ErrorType("serverResponse")
	// Credential type not present in our Configuration
	ErrorUnknownCredentialType = ErrorType("unknownCredentialType")
	// Error during downloading of credential type, issuer, or public keys
	ErrorConfigurationDownload = ErrorType("configurationDownload")
	// IRMA requests refers to unknown scheme manager
	ErrorUnknownSchemeManager = ErrorType("unknownSchemeManager")
	// A session is requested involving a scheme manager that has some problem
	ErrorInvalidSchemeManager = ErrorType("invalidSchemeManager")
	// Recovered panic
	ErrorPanic = ErrorType("panic")
)

func (e *SessionError) Error() string {
	var buffer bytes.Buffer
	typ := e.ErrorType
	if typ == "" {
		typ = ErrorType("unknown")
	}

	buffer.WriteString("Error type: ")
	buffer.WriteString(string(typ))
	if e.Err != nil {
		buffer.WriteString("\nDescription: ")
		buffer.WriteString(e.Err.Error())
	}
	if e.Status != 200 && e.StatusMessage != "" {
		buffer.WriteString("\nConnection: ")
		buffer.WriteString(e.StatusMessage)
	}
	if e.ApiError != nil {
		buffer.WriteString("\nIRMA server error: ")
		buffer.WriteString(e.ApiError.Error())
	}

	return buffer.String()
}

func (e *SessionError) Stack() string {
	if withStack, ok := e.Err.(*errors.Error); ok {
		return string(withStack.Stack())
	}

	return ""
}

func JwtDecode(jwt string, body interface{}) error {
	jwtparts := strings.Split(jwt, ".")
	if jwtparts == nil || len(jwtparts) < 2 {
		return errors.New("Not a JWT")
	}
	bodybytes, err := base64.RawStdEncoding.DecodeString(jwtparts[1])
	if err != nil {
		return err
	}
	return json.Unmarshal(bodybytes, body)
}

func ParseRequestorJwt(action Action, jwt string) (RequestorJwt, error) {
	var retval RequestorJwt
	switch action {
	case ActionDisclosing:
		retval = &ServiceProviderJwt{}
	case ActionSigning:
		retval = &SignatureRequestorJwt{}
	case ActionIssuing:
		retval = &IdentityProviderJwt{}
	default:
		return nil, errors.New("Invalid session type")
	}
	err := JwtDecode(jwt, retval)
	if err != nil {
		return nil, err
	}
	return retval, nil
}
<|endoftext|>


<commit_before>package ike

import (
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"net"

	"github.com/msgboxio/ike/protocol"
	"github.com/msgboxio/log"
)

var (
	InitPayloads = []protocol.PayloadType{
		protocol.PayloadTypeSA,
		protocol.PayloadTypeKE,
		protocol.PayloadTypeNonce,
	}

	AuthIPayloads = []protocol.PayloadType{
		protocol.PayloadTypeIDi,
		protocol.PayloadTypeAUTH,
		protocol.PayloadTypeSA,
		protocol.PayloadTypeTSi,
		protocol.PayloadTypeTSr,
	}
	AuthRPayloads = []protocol.PayloadType{
		protocol.PayloadTypeIDr,
		protocol.PayloadTypeAUTH,
		protocol.PayloadTypeSA,
		protocol.PayloadTypeTSi,
		protocol.PayloadTypeTSr,
	}
)

type Message struct {
	IkeHeader  *protocol.IkeHeader
	Payloads   *protocol.Payloads
	LocalIp    net.IP
	RemoteAddr net.Addr

	Data []byte // used to carry raw bytes
}

func DecodeMessage(b []byte) (msg *Message, err error) {
	msg = &Message{}
	if err = msg.DecodeHeader(b); err != nil {
		return
	}
	if len(b) < int(msg.IkeHeader.MsgLength) {
		err = io.ErrShortBuffer
		return
	}
	// further decode
	if err = msg.DecodePayloads(b[protocol.IKE_HEADER_LEN:msg.IkeHeader.MsgLength], msg.IkeHeader.NextPayload); err != nil {
		return
	}
	// decrypt later
	msg.Data = b
	return
}

func (s *Message) DecodeHeader(b []byte) (err error) {
	s.IkeHeader, err = protocol.DecodeIkeHeader(b)
	return
}

func (s *Message) DecodePayloads(b []byte, nextPayload protocol.PayloadType) (err error) {
	if s.Payloads, err = protocol.DecodePayloads(b, nextPayload); err != nil {
		return
	}
	log.V(1).Infof("Received %s: payloads %s", s.IkeHeader.ExchangeType, *s.Payloads)
	if log.V(protocol.LOG_PACKET_JS) {
		js, _ := json.MarshalIndent(s, " ", " ")
		log.Info("Rx:\n" + string(js))
	}
	return
}

func (s *Message) Encode(tkm *Tkm) (b []byte, err error) {
	log.V(1).Infof("Sending %s: payloads %s", s.IkeHeader.ExchangeType, s.Payloads)
	if log.V(protocol.LOG_PACKET_JS) {
		js, _ := json.MarshalIndent(s, " ", " ")
		log.Info("Tx:\n" + string(js))
	}
	nextPayload := s.IkeHeader.NextPayload
	if nextPayload == protocol.PayloadTypeSK {
		if tkm == nil {
			err = errors.New("cant encrypt, no tkm found")
			return
		}
		payload := protocol.EncodePayloads(s.Payloads)
		plen := len(payload) + tkm.CryptoOverhead(payload)
		// payload header
		firstPayload := protocol.PayloadTypeNone // no payloads are one possibility
		if len(s.Payloads.Array) > 0 {
			firstPayload = s.Payloads.Array[0].Type()
		}
		ph := protocol.PayloadHeader{
			NextPayload:   firstPayload,
			PayloadLength: uint16(plen),
		}.Encode()
		// prepare proper ike header
		s.IkeHeader.MsgLength = uint32(protocol.IKE_HEADER_LEN + len(ph) + plen)
		// encode ike header, and add to protocol header
		headers := append(s.IkeHeader.Encode(), ph...)
		// finally ask the tkm to apply secrets
		b, err = tkm.EncryptMac(headers, payload)
	} else {
		b = protocol.EncodePayloads(s.Payloads)
		s.IkeHeader.MsgLength = uint32(len(b) + protocol.IKE_HEADER_LEN)
		b = append(s.IkeHeader.Encode(), b...)
	}
	return
}

func (msg *Message) ensurePayloads(payloadTypes []protocol.PayloadType) bool {
	mp := msg.Payloads
	for _, pt := range payloadTypes {
		if mp.Get(pt) == nil {
			return false
		}
	}
	return true
}

func (msg *Message) EnsurePayloads(payloadTypes []protocol.PayloadType) error {
	if !msg.ensurePayloads(payloadTypes) {
		return fmt.Errorf("essential payload is missing from %s message", msg.IkeHeader.ExchangeType)
	}
	return nil
}
<commit_msg>add child sa payloads<commit_after>package ike

import (
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"net"

	"github.com/msgboxio/ike/protocol"
	"github.com/msgboxio/log"
)

var (
	InitPayloads = []protocol.PayloadType{
		protocol.PayloadTypeSA,
		protocol.PayloadTypeKE,
		protocol.PayloadTypeNonce,
	}

	AuthIPayloads = []protocol.PayloadType{
		protocol.PayloadTypeIDi,
		protocol.PayloadTypeAUTH,
		protocol.PayloadTypeSA,
		protocol.PayloadTypeTSi,
		protocol.PayloadTypeTSr,
	}
	AuthRPayloads = []protocol.PayloadType{
		protocol.PayloadTypeIDr,
		protocol.PayloadTypeAUTH,
		protocol.PayloadTypeSA,
		protocol.PayloadTypeTSi,
		protocol.PayloadTypeTSr,
	}

	NewChilSaIPayloads = []protocol.PayloadType{
		protocol.PayloadTypeSA,
		protocol.PayloadTypeNonce,
		protocol.PayloadTypeTSi,
		protocol.PayloadTypeTSr,
	}
	NewChilSaRPayloads = []protocol.PayloadType{
		protocol.PayloadTypeSA,
		protocol.PayloadTypeNonce,
	}

	RekeyIkeSaPaylods = InitPayloads

	RekeyChildSaIPaylods = []protocol.PayloadType{
		protocol.PayloadTypeN,
		protocol.PayloadTypeSA,
		protocol.PayloadTypeNonce,
		protocol.PayloadTypeTSi,
		protocol.PayloadTypeTSr,
	}
	RekeyChildSaRPaylods = []protocol.PayloadType{
		protocol.PayloadTypeSA,
		protocol.PayloadTypeNonce,
		protocol.PayloadTypeTSi,
		protocol.PayloadTypeTSr,
	}
)

type Message struct {
	IkeHeader  *protocol.IkeHeader
	Payloads   *protocol.Payloads
	LocalIp    net.IP
	RemoteAddr net.Addr

	Data []byte // used to carry raw bytes
}

func DecodeMessage(b []byte) (msg *Message, err error) {
	msg = &Message{}
	if err = msg.DecodeHeader(b); err != nil {
		return
	}
	if len(b) < int(msg.IkeHeader.MsgLength) {
		err = io.ErrShortBuffer
		return
	}
	// further decode
	if err = msg.DecodePayloads(b[protocol.IKE_HEADER_LEN:msg.IkeHeader.MsgLength], msg.IkeHeader.NextPayload); err != nil {
		return
	}
	// decrypt later
	msg.Data = b
	return
}

func (s *Message) DecodeHeader(b []byte) (err error) {
	s.IkeHeader, err = protocol.DecodeIkeHeader(b)
	return
}

func (s *Message) DecodePayloads(b []byte, nextPayload protocol.PayloadType) (err error) {
	if s.Payloads, err = protocol.DecodePayloads(b, nextPayload); err != nil {
		return
	}
	log.V(1).Infof("Received %s: payloads %s", s.IkeHeader.ExchangeType, *s.Payloads)
	if log.V(protocol.LOG_PACKET_JS) {
		js, _ := json.MarshalIndent(s, " ", " ")
		log.Info("Rx:\n" + string(js))
	}
	return
}

func (s *Message) Encode(tkm *Tkm) (b []byte, err error) {
	log.V(1).Infof("Sending %s: payloads %s", s.IkeHeader.ExchangeType, s.Payloads)
	if log.V(protocol.LOG_PACKET_JS) {
		js, _ := json.MarshalIndent(s, " ", " ")
		log.Info("Tx:\n" + string(js))
	}
	nextPayload := s.IkeHeader.NextPayload
	if nextPayload == protocol.PayloadTypeSK {
		if tkm == nil {
			err = errors.New("cant encrypt, no tkm found")
			return
		}
		payload := protocol.EncodePayloads(s.Payloads)
		plen := len(payload) + tkm.CryptoOverhead(payload)
		// payload header
		firstPayload := protocol.PayloadTypeNone // no payloads are one possibility
		if len(s.Payloads.Array) > 0 {
			firstPayload = s.Payloads.Array[0].Type()
		}
		ph := protocol.PayloadHeader{
			NextPayload:   firstPayload,
			PayloadLength: uint16(plen),
		}.Encode()
		// prepare proper ike header
		s.IkeHeader.MsgLength = uint32(protocol.IKE_HEADER_LEN + len(ph) + plen)
		// encode ike header, and add to protocol header
		headers := append(s.IkeHeader.Encode(), ph...)
		// finally ask the tkm to apply secrets
		b, err = tkm.EncryptMac(headers, payload)
	} else {
		b = protocol.EncodePayloads(s.Payloads)
		s.IkeHeader.MsgLength = uint32(len(b) + protocol.IKE_HEADER_LEN)
		b = append(s.IkeHeader.Encode(), b...)
	}
	return
}

func (msg *Message) ensurePayloads(payloadTypes []protocol.PayloadType) bool {
	mp := msg.Payloads
	for _, pt := range payloadTypes {
		if mp.Get(pt) == nil {
			return false
		}
	}
	return true
}

func (msg *Message) EnsurePayloads(payloadTypes []protocol.PayloadType) error {
	if !msg.ensurePayloads(payloadTypes) {
		return fmt.Errorf("essential payload is missing from %s message", msg.IkeHeader.ExchangeType)
	}
	return nil
}
<|endoftext|>


<commit_before>package diff

import "testing"
import "fmt"
import "path"

func TestWalk(t *testing.T) {
  fmt.Println("Ejecutando test walk...")
  list := []string{}
  list = FindFilesIn(list, "/home/mechon/go")
  if (len(list) == 0) {
    t.Error("Error en test walk")
  }
}

func TestAbs(t *testing.T) {
  fmt.Println("Ejecutanto test de Abs...")
  falseExpected := path.IsAbs("./some/path")
  trueExpected := path.IsAbs("/dev/nul")
  if falseExpected == true || trueExpected == false {
    t.Error("Fallo en test de Abs.")
  }
}
<commit_msg>Avances<commit_after>package diff

import "testing"
import "fmt"
import "path"

func TestWalk(t *testing.T) {
  fmt.Println("Ejecutando test walk...")
  list := []string{}
  list = FindFilesIn(list, "./")
  if (len(list) == 0) {
    t.Error("Error en test walk")
  }
}

func TestAbs(t *testing.T) {
  fmt.Println("Ejecutanto test de Abs...")
  falseExpected := path.IsAbs("./some/path")
  trueExpected := path.IsAbs("/dev/nul")
  if falseExpected == true || trueExpected == false {
    t.Error("Fallo en test de Abs.")
  }
}
<|endoftext|>


<commit_before>package hoverfly

import (
	"bytes"
	"fmt"

	"github.com/boltdb/bolt"
)

// Metadata - interface to store and retrieve any metadata that is related to Hoverfly
type Metadata interface {
	Set(key, value []byte) error
	Get(key []byte) ([]byte, error)
	Delete(key []byte) error
	GetAll() ([]MetaObject, error)
	CloseDB()
}

// NewBoltDBMetadata - default metadata store
func NewBoltDBMetadata(db *bolt.DB, bucket []byte) *BoltMeta {
	return &BoltMeta{
		DS:             db,
		MetadataBucket: []byte(bucket),
	}
}

const MetadataBucketName = "metadataBucket"

type BoltMeta struct {
	DS             *bolt.DB
	MetadataBucket []byte
}

// CloseDB - closes database
func (m *BoltMeta) CloseDB() {
	m.DS.Close()
}

// Set - saves given key and value pair to BoltDB
func (m *BoltMeta) Set(key, value []byte) error {
	err := m.DS.Update(func(tx *bolt.Tx) error {
		bucket, err := tx.CreateBucketIfNotExists(m.MetadataBucket)
		if err != nil {
			return err
		}
		err = bucket.Put(key, value)
		if err != nil {
			return err
		}
		return nil
	})

	return err
}

// Get - gets value for given key
func (m *BoltMeta) Get(key []byte) (value []byte, err error) {
	err = m.DS.View(func(tx *bolt.Tx) error {
		bucket := tx.Bucket(m.MetadataBucket)
		if bucket == nil {
			return fmt.Errorf("Bucket %q not found!", m.MetadataBucket)
		}
		var buffer bytes.Buffer
		val := bucket.Get(key)

		// If it doesn't exist then it will return nil
		if val == nil {
			return fmt.Errorf("key %q not found \n", key)
		}

		buffer.Write(val)
		value = buffer.Bytes()
		return nil
	})

	return
}

// MetaObject - container to store both keys and values of captured objects
type MetaObject struct {
	Key   []byte
	Value []byte
}

// GetAll - returns all key/value pairs
func (m *BoltMeta) GetAll() (objects []MetaObject, err error) {
	err = m.DS.View(func(tx *bolt.Tx) error {
		b := tx.Bucket(m.MetadataBucket)
		if b == nil {
			// bucket doesn't exist
			return nil
		}
		c := b.Cursor()

		for k, v := c.First(); k != nil; k, v = c.Next() {
			obj := &MetaObject{Key: k, Value: v}
			objects = append(objects, *obj)
		}
		return nil
	})
	return
}

// Delete - deletes given metadata key
func (m *BoltMeta) Delete(key []byte) error {
	err := m.DS.Update(func(tx *bolt.Tx) error {
		bucket, err := tx.CreateBucketIfNotExists(m.MetadataBucket)
		if err != nil {
			return err
		}
		err = bucket.Delete(key)
		if err != nil {
			return err
		}
		return nil
	})

	return err
}
<commit_msg>delete all metadata<commit_after>package hoverfly

import (
	"bytes"
	"fmt"

	log "github.com/Sirupsen/logrus"
	"github.com/boltdb/bolt"
)

// Metadata - interface to store and retrieve any metadata that is related to Hoverfly
type Metadata interface {
	Set(key, value []byte) error
	Get(key []byte) ([]byte, error)
	Delete(key []byte) error
	GetAll() ([]MetaObject, error)
	DeleteData() error
	CloseDB()
}

// NewBoltDBMetadata - default metadata store
func NewBoltDBMetadata(db *bolt.DB, bucket []byte) *BoltMeta {
	return &BoltMeta{
		DS:             db,
		MetadataBucket: []byte(bucket),
	}
}

const MetadataBucketName = "metadataBucket"

type BoltMeta struct {
	DS             *bolt.DB
	MetadataBucket []byte
}

// CloseDB - closes database
func (m *BoltMeta) CloseDB() {
	m.DS.Close()
}

// Set - saves given key and value pair to BoltDB
func (m *BoltMeta) Set(key, value []byte) error {
	err := m.DS.Update(func(tx *bolt.Tx) error {
		bucket, err := tx.CreateBucketIfNotExists(m.MetadataBucket)
		if err != nil {
			return err
		}
		err = bucket.Put(key, value)
		if err != nil {
			return err
		}
		return nil
	})

	return err
}

// Get - gets value for given key
func (m *BoltMeta) Get(key []byte) (value []byte, err error) {
	err = m.DS.View(func(tx *bolt.Tx) error {
		bucket := tx.Bucket(m.MetadataBucket)
		if bucket == nil {
			return fmt.Errorf("Bucket %q not found!", m.MetadataBucket)
		}
		var buffer bytes.Buffer
		val := bucket.Get(key)

		// If it doesn't exist then it will return nil
		if val == nil {
			return fmt.Errorf("key %q not found \n", key)
		}

		buffer.Write(val)
		value = buffer.Bytes()
		return nil
	})

	return
}

// MetaObject - container to store both keys and values of captured objects
type MetaObject struct {
	Key   string `json:"key"`
	Value string `json:"value"`
}

// GetAll - returns all key/value pairs
func (m *BoltMeta) GetAll() (objects []MetaObject, err error) {
	err = m.DS.View(func(tx *bolt.Tx) error {
		b := tx.Bucket(m.MetadataBucket)
		if b == nil {
			// bucket doesn't exist
			return nil
		}
		c := b.Cursor()

		for k, v := c.First(); k != nil; k, v = c.Next() {
			obj := &MetaObject{Key: string(k), Value: string(v)}
			objects = append(objects, *obj)
		}
		return nil
	})
	return
}

// Delete - deletes given metadata key
func (m *BoltMeta) Delete(key []byte) error {
	err := m.DS.Update(func(tx *bolt.Tx) error {
		bucket, err := tx.CreateBucketIfNotExists(m.MetadataBucket)
		if err != nil {
			return err
		}
		err = bucket.Delete(key)
		if err != nil {
			return err
		}
		return nil
	})

	return err
}

// DeleteData - deletes bucket with all saved data
func (m *BoltMeta) DeleteData() error {
	err := m.deleteBucket(m.MetadataBucket)
	return err
}

// DeleteBucket - deletes bucket with all saved data
func (m *BoltMeta) deleteBucket(name []byte) (err error) {
	err = m.DS.Update(func(tx *bolt.Tx) error {
		err = tx.DeleteBucket(name)
		if err != nil {
			log.WithFields(log.Fields{
				"error": err.Error(),
				"name":  string(name),
			}).Warning("Failed to delete bucket")

		}
		return err
	})
	return
}
<|endoftext|>


<commit_before>package main

import (
  "database/sql"
  "encoding/json"
  "fmt"
  "net/http"
  "net/url"
  "os"
  "strconv"
  _ "github.com/lib/pq"
  "github.com/rcrowley/go-tigertonic"
  "github.com/rkbodenner/parallel_universe/collection"
  "github.com/rkbodenner/parallel_universe/game"
  "github.com/rkbodenner/parallel_universe/session"
)

var players = make([]*game.Player, 0)
var playerIndex = make(map[uint64]*game.Player)

func initPlayerData(db *sql.DB) {
  rows, err := db.Query("SELECT * FROM players")
  if nil != err {
    fmt.Print(err)
  }
  for rows.Next() {
    var name string
    var id int
    if err := rows.Scan(&id, &name); err != nil {
      fmt.Print(err)
    }
    players = append(players, &game.Player{id, name})
    fmt.Printf("%s\n", name)
  }

  for _,player := range players {
    playerIndex[(uint64)(player.Id)] = player
  }
}

var gameCollection = collection.NewCollection()
var gameIndex = make(map[uint64]*game.Game)

func initGameData() {
  for i,game := range gameCollection.Games {
    game.Id = (uint)(i+1)
    gameIndex[(uint64)(i+1)] = game
  }
}

var sessions []*session.Session
var sessionIndex = make(map[uint64]*session.Session)

func initSessionData() {
  sessions = make([]*session.Session, 2)
  sessions[0] = session.NewSession(gameCollection.Games[0], players)
  sessions[0].Step(players[0])
  sessions[0].Step(players[1])

  sessions[1] = session.NewSession(gameCollection.Games[1], players)
  sessions[1].Step(players[0])
  sessions[1].Step(players[1])

  for i,session := range sessions {
    session.Id = (uint)(i+1)
    sessionIndex[(uint64)(i+1)] = session
  }
}

type CollectionHandler struct{}
func (h CollectionHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
  err := json.NewEncoder(w).Encode(gameCollection)
  if ( nil != err ) {
    fmt.Fprintln(w, err)
  }
}

type GameHandler struct{}
func (h GameHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
  id_str := r.URL.Query().Get("id")
  id, err := strconv.ParseUint(id_str, 10, 64)
  if nil != err {
    http.Error(w, "Not found", http.StatusNotFound)
    return
  }

  game, ok := gameIndex[id]
  if ok {
    err := json.NewEncoder(w).Encode(game)
    if ( nil != err ) {
      http.Error(w, "Error", http.StatusInternalServerError)
    }
  } else {
    http.Error(w, "Not found", http.StatusNotFound)
  }
}

type PlayersHandler struct{}
func (h PlayersHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
  err := json.NewEncoder(w).Encode(players)
  if ( nil != err ) {
    fmt.Fprintln(w, err)
  }
}

type PlayerHandler struct{}
func (h PlayerHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
  player_id_str := r.URL.Query().Get("player_id")
  player_id, err := strconv.ParseUint(player_id_str, 10, 64)
  if nil != err {
    http.Error(w, "Not found", http.StatusNotFound)
    return
  }

  player, ok := playerIndex[player_id]
  if ok {
    err = json.NewEncoder(w).Encode(player)
    if ( nil != err ) {
      http.Error(w, "Error", http.StatusInternalServerError)
    }
  } else {
    http.Error(w, "Not found", http.StatusNotFound)
  }
}

type SessionsHandler struct{}
func (h SessionsHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
  err := json.NewEncoder(w).Encode(sessions)
  if ( nil != err ) {
    http.Error(w, "Error", http.StatusInternalServerError)
  }
}

type SessionCreateHandler struct{
  db *sql.DB
}

func (h SessionCreateHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
  if nil != r.ParseForm() {
    http.Error(w, "Error", http.StatusBadRequest)
    return
  }

  game_id_str := r.FormValue("game")
  game_id, err := strconv.ParseUint(game_id_str, 10, 64)
  if nil != err {
    http.Error(w, "Error: Expected integer game ID", http.StatusBadRequest)
    return
  }

  var session_id int
  err = h.db.QueryRow("INSERT INTO sessions(id, game_id) VALUES(default, $1) RETURNING id", game_id).Scan(&session_id)
  if nil != err {
    http.Error(w, "Error", http.StatusInternalServerError)
    return
  }

  w.WriteHeader(http.StatusCreated)
  fmt.Fprintf(w, "%d\n", session_id)
}

type SessionHandler struct{}
func (h SessionHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
  id_str := r.URL.Query().Get("session_id")
  id, err := strconv.ParseUint(id_str, 10, 64)
  if nil != err {
    http.Error(w, "Not found", http.StatusNotFound)
    return
  }

  session, ok := sessionIndex[id]
  if ok {
    err := json.NewEncoder(w).Encode(session)
    if ( nil != err ) {
      http.Error(w, "Error", http.StatusInternalServerError)
    }
  } else {
    http.Error(w, "Not found", http.StatusNotFound)
  }
}

type StepHandler struct{}
func (h StepHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
  session_id_str := r.URL.Query().Get("session_id")
  session_id, err := strconv.ParseUint(session_id_str, 10, 64)
  if nil != err {
    http.Error(w, "Session not found", http.StatusNotFound)
    return
  }
  session,ok := sessionIndex[session_id]
  if !ok {
    http.Error(w, "Session not found", http.StatusNotFound)
    return
  }

  player_id_str := r.URL.Query().Get("player_id")
  player_id, err := strconv.ParseUint(player_id_str, 10, 64)
  if nil != err {
    http.Error(w, "Player not found", http.StatusNotFound)
    return
  }
  player, ok := playerIndex[player_id]
  if !ok {
    http.Error(w, "Player not found", http.StatusNotFound)
    return
  }

  step_desc,err := url.QueryUnescape(r.URL.Query().Get("step_desc"))
  for _,step := range session.SetupSteps {
    if ( step.GetRule().Description == step_desc && step.CanBeOwnedBy(player) ) {
      step.Finish()  // FIXME. Should look in request data to see what to change.
      session.Step(player)
      session.Print()  // FIXME
      return
    }
  }
  http.Error(w, "Step not found", http.StatusNotFound)
}

func main() {
  db, err := sql.Open("postgres", "user=ralph dbname=meeple_mover sslmode=disable")
  if err != nil {
    fmt.Print(err)
  }

  initPlayerData(db)
  initGameData()
  initSessionData()

  var origin string
  origin = os.Getenv("MEEPLE_MOVER_ORIGIN_URL")
  if "" == origin {
    origin = "http://localhost:8000"
  }
  cors := tigertonic.NewCORSBuilder().AddAllowedOrigins(origin)

  mux := tigertonic.NewTrieServeMux()
  mux.Handle("GET", "/games", cors.Build(CollectionHandler{}))
  mux.Handle("GET", "/games/{id}", cors.Build(GameHandler{}))
  mux.Handle("GET", "/players", cors.Build(PlayersHandler{}))
  mux.Handle("GET", "/players/{player_id}", cors.Build(PlayerHandler{}))
  mux.Handle("GET", "/sessions", cors.Build(SessionsHandler{}))
  mux.Handle("POST", "/sessions", cors.Build(SessionCreateHandler{db}))
  mux.Handle("GET", "/sessions/{session_id}", cors.Build(SessionHandler{}))
  mux.Handle("PUT", "/sessions/{session_id}/players/{player_id}/steps/{step_desc}", cors.Build(StepHandler{}))

  var port string
  port = os.Getenv("PORT")
  if "" == port {
    port = "8080"
  }

  http.ListenAndServe(fmt.Sprintf(":%s", port), mux)

  db.Close()
}
<commit_msg>Create sessions from JSON instead of form data<commit_after>package main

import (
  "database/sql"
  "encoding/json"
  "errors"
  "fmt"
  "net/http"
  "net/url"
  "os"
  "strconv"
  _ "github.com/lib/pq"
  "github.com/rcrowley/go-tigertonic"
  "github.com/rkbodenner/parallel_universe/collection"
  "github.com/rkbodenner/parallel_universe/game"
  "github.com/rkbodenner/parallel_universe/session"
)

var players = make([]*game.Player, 0)
var playerIndex = make(map[uint64]*game.Player)

func initPlayerData(db *sql.DB) {
  rows, err := db.Query("SELECT * FROM players")
  if nil != err {
    fmt.Print(err)
  }
  for rows.Next() {
    var name string
    var id int
    if err := rows.Scan(&id, &name); err != nil {
      fmt.Print(err)
    }
    players = append(players, &game.Player{id, name})
    fmt.Printf("%s\n", name)
  }

  for _,player := range players {
    playerIndex[(uint64)(player.Id)] = player
  }
}

var gameCollection = collection.NewCollection()
var gameIndex = make(map[uint64]*game.Game)

func initGameData() {
  for i,game := range gameCollection.Games {
    game.Id = (uint)(i+1)
    gameIndex[(uint64)(i+1)] = game
  }
}

var sessions []*session.Session
var sessionIndex = make(map[uint64]*session.Session)

func initSessionData() {
  sessions = make([]*session.Session, 2)
  sessions[0] = session.NewSession(gameCollection.Games[0], players)
  sessions[0].Step(players[0])
  sessions[0].Step(players[1])

  sessions[1] = session.NewSession(gameCollection.Games[1], players)
  sessions[1].Step(players[0])
  sessions[1].Step(players[1])

  for i,session := range sessions {
    session.Id = (uint)(i+1)
    sessionIndex[(uint64)(i+1)] = session
  }
}

type CollectionHandler struct{}
func (h CollectionHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
  err := json.NewEncoder(w).Encode(gameCollection)
  if ( nil != err ) {
    fmt.Fprintln(w, err)
  }
}

type GameHandler struct{}
func (h GameHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
  id_str := r.URL.Query().Get("id")
  id, err := strconv.ParseUint(id_str, 10, 64)
  if nil != err {
    http.Error(w, "Not found", http.StatusNotFound)
    return
  }

  game, ok := gameIndex[id]
  if ok {
    err := json.NewEncoder(w).Encode(game)
    if ( nil != err ) {
      http.Error(w, "Error", http.StatusInternalServerError)
    }
  } else {
    http.Error(w, "Not found", http.StatusNotFound)
  }
}

type PlayersHandler struct{}
func (h PlayersHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
  err := json.NewEncoder(w).Encode(players)
  if ( nil != err ) {
    fmt.Fprintln(w, err)
  }
}

type PlayerHandler struct{}
func (h PlayerHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
  player_id_str := r.URL.Query().Get("player_id")
  player_id, err := strconv.ParseUint(player_id_str, 10, 64)
  if nil != err {
    http.Error(w, "Not found", http.StatusNotFound)
    return
  }

  player, ok := playerIndex[player_id]
  if ok {
    err = json.NewEncoder(w).Encode(player)
    if ( nil != err ) {
      http.Error(w, "Error", http.StatusInternalServerError)
    }
  } else {
    http.Error(w, "Not found", http.StatusNotFound)
  }
}

type SessionsHandler struct{}
func (h SessionsHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
  err := json.NewEncoder(w).Encode(sessions)
  if ( nil != err ) {
    http.Error(w, "Error", http.StatusInternalServerError)
  }
}

type SessionCreateHandler struct {
  db *sql.DB
}
type SessionCreateHash struct {
  StartedDate string `json:"started_date"`
  Game string `json:"game"`
  Players []string `json:"players"`
}
type SessionCreateRequest struct {
  Session SessionCreateHash `json:"session"`
}

func (handler SessionCreateHandler) marshalFunc() (func(*url.URL, http.Header, *SessionCreateRequest) (int, http.Header, *session.Session, error)) {
  return func(u *url.URL, h http.Header, rq *SessionCreateRequest) (int, http.Header, *session.Session, error) {
    var err error

    var game_id uint64
    game_id, err = strconv.ParseUint(rq.Session.Game, 10, 64)
    if nil != err {
      return http.StatusBadRequest, nil, nil, errors.New("Expected integer game ID")
    }

    var session_id int
    err = handler.db.QueryRow("INSERT INTO sessions(id, game_id) VALUES(default, $1) RETURNING id", game_id).Scan(&session_id)
    if nil != err {
      return http.StatusInternalServerError, nil, nil, errors.New("Failed to create session")
    }
    players := make([]*game.Player, 0)
    session := session.NewSession(gameIndex[game_id], players)
    session.Id = (uint)(session_id)
    return http.StatusCreated, nil, session, nil
  }
}

type SessionHandler struct{}
func (h SessionHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
  id_str := r.URL.Query().Get("session_id")
  id, err := strconv.ParseUint(id_str, 10, 64)
  if nil != err {
    http.Error(w, "Not found", http.StatusNotFound)
    return
  }

  session, ok := sessionIndex[id]
  if ok {
    err := json.NewEncoder(w).Encode(session)
    if ( nil != err ) {
      http.Error(w, "Error", http.StatusInternalServerError)
    }
  } else {
    http.Error(w, "Not found", http.StatusNotFound)
  }
}

type StepHandler struct{}
func (h StepHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
  session_id_str := r.URL.Query().Get("session_id")
  session_id, err := strconv.ParseUint(session_id_str, 10, 64)
  if nil != err {
    http.Error(w, "Session not found", http.StatusNotFound)
    return
  }
  session,ok := sessionIndex[session_id]
  if !ok {
    http.Error(w, "Session not found", http.StatusNotFound)
    return
  }

  player_id_str := r.URL.Query().Get("player_id")
  player_id, err := strconv.ParseUint(player_id_str, 10, 64)
  if nil != err {
    http.Error(w, "Player not found", http.StatusNotFound)
    return
  }
  player, ok := playerIndex[player_id]
  if !ok {
    http.Error(w, "Player not found", http.StatusNotFound)
    return
  }

  step_desc,err := url.QueryUnescape(r.URL.Query().Get("step_desc"))
  for _,step := range session.SetupSteps {
    if ( step.GetRule().Description == step_desc && step.CanBeOwnedBy(player) ) {
      step.Finish()  // FIXME. Should look in request data to see what to change.
      session.Step(player)
      session.Print()  // FIXME
      return
    }
  }
  http.Error(w, "Step not found", http.StatusNotFound)
}

func main() {
  db, err := sql.Open("postgres", "user=ralph dbname=meeple_mover sslmode=disable")
  if err != nil {
    fmt.Print(err)
  }

  initPlayerData(db)
  initGameData()
  initSessionData()

  var origin string
  origin = os.Getenv("MEEPLE_MOVER_ORIGIN_URL")
  if "" == origin {
    origin = "http://localhost:8000"
  }
  cors := tigertonic.NewCORSBuilder().AddAllowedOrigins(origin).AddAllowedHeaders("Content-Type")

  mux := tigertonic.NewTrieServeMux()
  mux.Handle("GET", "/games", cors.Build(CollectionHandler{}))
  mux.Handle("GET", "/games/{id}", cors.Build(GameHandler{}))
  mux.Handle("GET", "/players", cors.Build(PlayersHandler{}))
  mux.Handle("GET", "/players/{player_id}", cors.Build(PlayerHandler{}))
  mux.Handle("GET", "/sessions", cors.Build(SessionsHandler{}))
  mux.Handle("POST", "/sessions", cors.Build(tigertonic.Marshaled(SessionCreateHandler{db}.marshalFunc())))
  mux.Handle("GET", "/sessions/{session_id}", cors.Build(SessionHandler{}))
  mux.Handle("PUT", "/sessions/{session_id}/players/{player_id}/steps/{step_desc}", cors.Build(StepHandler{}))

  var port string
  port = os.Getenv("PORT")
  if "" == port {
    port = "8080"
  }

  http.ListenAndServe(fmt.Sprintf(":%s", port), mux)

  db.Close()
}
<|endoftext|>