<commit_before>package chlib

import (
	"fmt"
	"os/user"
	"path"

	"github.com/boltdb/bolt"
	"github.com/kfeofantov/chkit-v2/helpers"
)

const configDir = ".containerum"
const configFile = "config.db"

var configDb *bolt.DB

var initializers map[string]helpers.MappedStruct = make(map[string]helpers.MappedStruct)

func OpenOrCreateConfig() error {
	currentUser, err := user.Current()
	if err != nil {
		return fmt.Errorf("get current user: %s", err)
	}

	configPath := path.Join(currentUser.HomeDir, configDir, configFile)
	configDb, err = bolt.Open(configPath, 0600, nil)
	if err != nil {
		return fmt.Errorf("config db open: %s", err)
	}

	return runInitializers()
}

func recursiveInitialize(startBucket *bolt.Bucket, initializer helpers.MappedStruct) error {
	for key, value := range initializer {
		switch value.(type) {
		case []byte:
			err := startBucket.Put([]byte(key), value.([]byte))
			if err != nil {
				return err
			}
		case helpers.MappedStruct:
			newBucket, err := startBucket.CreateBucketIfNotExists([]byte(key))
			if err != nil {
				return fmt.Errorf("bucket create: %s", err)
			}
			err = recursiveInitialize(newBucket, value.(helpers.MappedStruct))
			if err != nil {
				return err
			}
		}
	}
	return nil
}

func runInitializers() error {
	return configDb.Update(func(tx *bolt.Tx) error {
		for bucketName, initializer := range initializers {
			bucket := tx.Bucket([]byte(bucketName))
			if bucket == nil {
				bucket, err := tx.CreateBucket([]byte(bucketName))
				if err != nil {
					return fmt.Errorf("bucket create: %s", err)
				}
				recursiveInitialize(bucket, initializer)
			}
			return nil
		}
		return nil
	})
}

func recursivePush(startBucket *bolt.Bucket, data helpers.MappedStruct) error {
	for key, value := range data {
		var err error
		switch value.(type) {
		case []byte:
			err = startBucket.Put([]byte(key), value.([]byte))
		case helpers.MappedStruct:
			newBucket, err := startBucket.CreateBucket([]byte(key))
			if err != nil {
				return err
			}
			err = recursivePush(newBucket, value.(helpers.MappedStruct))
		}
		if err != nil {
			return fmt.Errorf("value for key %s push: %s", key, err)
		}
	}
	return nil
}

func pushToBucket(bucketName string, data helpers.MappedStruct) error {
	return configDb.Update(func(tx *bolt.Tx) error {
		bucket := tx.Bucket([]byte(bucketName))
		return recursivePush(bucket, data)
	})
}

func recursiveRead(startBucket *bolt.Bucket) (data helpers.MappedStruct, err error) {
	data = make(helpers.MappedStruct)
	err = startBucket.ForEach(func(k []byte, v []byte) error {
		if v != nil {
			data[string(k)] = v
		} else {
			// it`s a bucket
			newBucket := startBucket.Bucket(k)
			var err error
			data[string(k)], err = recursiveRead(newBucket)
			if err != nil {
				return err
			}
		}
		return nil
	})
	return
}

func readFromBucket(bucketName string) (data helpers.MappedStruct, err error) {
	err = configDb.View(func(tx *bolt.Tx) error {
		bucket := tx.Bucket([]byte(bucketName))
		if bucket == nil {
			return fmt.Errorf("bucket %s not exist", bucketName)
		}
		data, err = recursiveRead(bucket)
		return err
	})
	return
}

func Close() {
	configDb.Close()
}
<commit_msg>Fix error with db init<commit_after>package chlib

import (
	"fmt"
	"os/user"
	"path"

	"github.com/boltdb/bolt"
	"github.com/kfeofantov/chkit-v2/helpers"
)

const configDir = ".containerum"
const configFile = "config.db"

var configDb *bolt.DB

var initializers map[string]helpers.MappedStruct = make(map[string]helpers.MappedStruct)

func OpenOrCreateConfig() error {
	currentUser, err := user.Current()
	if err != nil {
		return fmt.Errorf("get current user: %s", err)
	}

	configPath := path.Join(currentUser.HomeDir, configDir, configFile)
	configDb, err = bolt.Open(configPath, 0600, nil)
	if err != nil {
		return fmt.Errorf("config db open: %s", err)
	}
	return runInitializers()
}

func recursiveInitialize(startBucket *bolt.Bucket, initializer helpers.MappedStruct) error {
	for key, value := range initializer {
		switch value.(type) {
		case []byte:
			err := startBucket.Put([]byte(key), value.([]byte))
			if err != nil {
				return err
			}
		case helpers.MappedStruct:
			newBucket, err := startBucket.CreateBucketIfNotExists([]byte(key))
			if err != nil {
				return fmt.Errorf("bucket create: %s", err)
			}
			err = recursiveInitialize(newBucket, value.(helpers.MappedStruct))
			if err != nil {
				return err
			}
		}
	}
	return nil
}

func runInitializers() error {
	return configDb.Update(func(tx *bolt.Tx) error {
		for bucketName, initializer := range initializers {
			bucket := tx.Bucket([]byte(bucketName))
			if bucket == nil {
				bucket, err := tx.CreateBucket([]byte(bucketName))
				if err != nil {
					return fmt.Errorf("bucket create: %s", err)
				}
				recursiveInitialize(bucket, initializer)
			}
		}
		return nil
	})
}

func recursivePush(startBucket *bolt.Bucket, data helpers.MappedStruct) error {
	for key, value := range data {
		var err error
		switch value.(type) {
		case []byte:
			err = startBucket.Put([]byte(key), value.([]byte))
		case helpers.MappedStruct:
			newBucket, err := startBucket.CreateBucket([]byte(key))
			if err != nil {
				return err
			}
			err = recursivePush(newBucket, value.(helpers.MappedStruct))
		}
		if err != nil {
			return fmt.Errorf("value for key %s push: %s", key, err)
		}
	}
	return nil
}

func pushToBucket(bucketName string, data helpers.MappedStruct) error {
	return configDb.Update(func(tx *bolt.Tx) error {
		bucket := tx.Bucket([]byte(bucketName))
		return recursivePush(bucket, data)
	})
}

func recursiveRead(startBucket *bolt.Bucket) (data helpers.MappedStruct, err error) {
	data = make(helpers.MappedStruct)
	err = startBucket.ForEach(func(k []byte, v []byte) error {
		if v != nil {
			data[string(k)] = v
		} else {
			// it`s a bucket
			newBucket := startBucket.Bucket(k)
			var err error
			data[string(k)], err = recursiveRead(newBucket)
			if err != nil {
				return err
			}
		}
		return nil
	})
	return
}

func readFromBucket(bucketName string) (data helpers.MappedStruct, err error) {
	err = configDb.View(func(tx *bolt.Tx) error {
		bucket := tx.Bucket([]byte(bucketName))
		if bucket == nil {
			return fmt.Errorf("bucket %s not exist", bucketName)
		}
		data, err = recursiveRead(bucket)
		return err
	})
	return
}

func Close() {
	configDb.Close()
}
<|endoftext|>


<commit_before>// Copyright 2013 docker-cluster 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 cluster

import (
	"errors"
	"math/rand"
	"net/http"
	"net/http/httptest"
	"runtime"
	"sync"
	"testing"
)

func TestNewCluster(t *testing.T) {
	var tests = []struct {
		scheduler Scheduler
		input     []Node
		fail      bool
	}{
		{
			&roundRobin{},
			[]Node{{ID: "something", Address: "http://localhost:8083"}},
			false,
		},
		{
			&roundRobin{},
			[]Node{{ID: "something", Address: ""}, {ID: "otherthing", Address: "http://localhost:8083"}},
			true,
		},
		{
			nil,
			[]Node{{ID: "something", Address: "http://localhost:8083"}},
			false,
		},
	}
	for _, tt := range tests {
		_, err := New(&roundRobin{}, tt.input...)
		if tt.fail && err == nil || !tt.fail && err != nil {
			t.Errorf("cluster.New() for input %#v. Expect failure: %v. Got: %v.", tt.input, tt.fail, err)
		}
	}
}

func TestRegister(t *testing.T) {
	var scheduler roundRobin
	cluster, err := New(&scheduler)
	if err != nil {
		t.Fatal(err)
	}
	err = cluster.Register(Node{ID: "abcdef", Address: "http://localhost:4243"})
	if err != nil {
		t.Fatal(err)
	}
	node := scheduler.next()
	if node.id != "abcdef" {
		t.Errorf("Register failed. Got wrong ID. Want %q. Got %q.", "abcdef", node.id)
	}
	err = cluster.Register(Node{ID: "abcdefg", Address: "http://localhost:4243"})
	if err != nil {
		t.Fatal(err)
	}
	node = scheduler.next()
	if node.id != "abcdefg" {
		t.Errorf("Register failed. Got wrong ID. Want %q. Got %q.", "abcdefg", node.id)
	}
	node = scheduler.next()
	if node.id != "abcdef" {
		t.Errorf("Register failed. Got wrong ID. Want %q. Got %q.", "abcdef", node.id)
	}
}

func TestRegisterFailure(t *testing.T) {
	cluster, err := New(&roundRobin{})
	if err != nil {
		t.Fatal(err)
	}
	err = cluster.Register(Node{ID: "abcdef", Address: ""})
	if err == nil {
		t.Error("Expected non-nil error, got <nil>.")
	}
}

func TestRunOnNodesStress(t *testing.T) {
	n := 1000
	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(16))
	body := `{"Id":"e90302","Path":"date","Args":[]}`
	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Type", "application/json")
		w.Write([]byte(body))
	}))
	defer server.Close()
	cluster, err := New(nil, Node{ID: "server0", Address: server.URL})
	if err != nil {
		t.Fatal(err)
	}
	id := "e90302"
	for i := 0; i < rand.Intn(10)+n; i++ {
		container, err := cluster.InspectContainer(id)
		if err != nil {
			t.Fatal(err)
		}
		if container.ID != id {
			t.Errorf("InspectContainer(%q): Wrong ID. Want %q. Got %q.", id, id, container.ID)
		}
		if container.Path != "date" {
			t.Errorf("InspectContainer(%q): Wrong Path. Want %q. Got %q.", id, "date", container.Path)
		}
	}
}

func TestSetStorage(t *testing.T) {
	var c Cluster
	var storage, other mapStorage
	c.SetStorage(&storage)
	if c.storage() != &storage {
		t.Errorf("Cluster.SetStorage(): did not change the storage")
	}
	c.SetStorage(&other)
	if c.storage() != &other {
		t.Errorf("Cluster.SetStorage(): did not change the storage")
	}
}

type mapStorage struct {
	m map[string]string
	sync.Mutex
}

func (s *mapStorage) Store(containerID, hostID string) error {
    s.Lock()
    defer s.Unlock()
    s.m[containerID] = hostID
    return nil
}

func (s *mapStorage) Retrieve(containerID string) (string, error) {
    s.Lock()
    defer s.Unlock()
    host, ok := s.m[containerID]
    if !ok {
        return "", errors.New("No such container")
    }
    return host, nil
}
<commit_msg>cluster/test: fix mapStorage<commit_after>// Copyright 2013 docker-cluster 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 cluster

import (
	"errors"
	"math/rand"
	"net/http"
	"net/http/httptest"
	"runtime"
	"sync"
	"testing"
)

func TestNewCluster(t *testing.T) {
	var tests = []struct {
		scheduler Scheduler
		input     []Node
		fail      bool
	}{
		{
			&roundRobin{},
			[]Node{{ID: "something", Address: "http://localhost:8083"}},
			false,
		},
		{
			&roundRobin{},
			[]Node{{ID: "something", Address: ""}, {ID: "otherthing", Address: "http://localhost:8083"}},
			true,
		},
		{
			nil,
			[]Node{{ID: "something", Address: "http://localhost:8083"}},
			false,
		},
	}
	for _, tt := range tests {
		_, err := New(&roundRobin{}, tt.input...)
		if tt.fail && err == nil || !tt.fail && err != nil {
			t.Errorf("cluster.New() for input %#v. Expect failure: %v. Got: %v.", tt.input, tt.fail, err)
		}
	}
}

func TestRegister(t *testing.T) {
	var scheduler roundRobin
	cluster, err := New(&scheduler)
	if err != nil {
		t.Fatal(err)
	}
	err = cluster.Register(Node{ID: "abcdef", Address: "http://localhost:4243"})
	if err != nil {
		t.Fatal(err)
	}
	node := scheduler.next()
	if node.id != "abcdef" {
		t.Errorf("Register failed. Got wrong ID. Want %q. Got %q.", "abcdef", node.id)
	}
	err = cluster.Register(Node{ID: "abcdefg", Address: "http://localhost:4243"})
	if err != nil {
		t.Fatal(err)
	}
	node = scheduler.next()
	if node.id != "abcdefg" {
		t.Errorf("Register failed. Got wrong ID. Want %q. Got %q.", "abcdefg", node.id)
	}
	node = scheduler.next()
	if node.id != "abcdef" {
		t.Errorf("Register failed. Got wrong ID. Want %q. Got %q.", "abcdef", node.id)
	}
}

func TestRegisterFailure(t *testing.T) {
	cluster, err := New(&roundRobin{})
	if err != nil {
		t.Fatal(err)
	}
	err = cluster.Register(Node{ID: "abcdef", Address: ""})
	if err == nil {
		t.Error("Expected non-nil error, got <nil>.")
	}
}

func TestRunOnNodesStress(t *testing.T) {
	n := 1000
	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(16))
	body := `{"Id":"e90302","Path":"date","Args":[]}`
	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Type", "application/json")
		w.Write([]byte(body))
	}))
	defer server.Close()
	cluster, err := New(nil, Node{ID: "server0", Address: server.URL})
	if err != nil {
		t.Fatal(err)
	}
	id := "e90302"
	for i := 0; i < rand.Intn(10)+n; i++ {
		container, err := cluster.InspectContainer(id)
		if err != nil {
			t.Fatal(err)
		}
		if container.ID != id {
			t.Errorf("InspectContainer(%q): Wrong ID. Want %q. Got %q.", id, id, container.ID)
		}
		if container.Path != "date" {
			t.Errorf("InspectContainer(%q): Wrong Path. Want %q. Got %q.", id, "date", container.Path)
		}
	}
}

func TestSetStorage(t *testing.T) {
	var c Cluster
	var storage, other mapStorage
	c.SetStorage(&storage)
	if c.storage() != &storage {
		t.Errorf("Cluster.SetStorage(): did not change the storage")
	}
	c.SetStorage(&other)
	if c.storage() != &other {
		t.Errorf("Cluster.SetStorage(): did not change the storage")
	}
}

type mapStorage struct {
	m map[string]string
	sync.Mutex
}

func (s *mapStorage) Store(containerID, hostID string) error {
    s.Lock()
    defer s.Unlock()
    if s.m == nil {
	    s.m = make(map[string]string)
    }
    s.m[containerID] = hostID
    return nil
}

func (s *mapStorage) Retrieve(containerID string) (string, error) {
    s.Lock()
    defer s.Unlock()
    host, ok := s.m[containerID]
    if !ok {
        return "", errors.New("No such container")
    }
    return host, nil
}
<|endoftext|>


<commit_before>package checker

import (
	"encoding/json"
	"fmt"
	"io"
	"os"
	"strings"
	"sync"

	"github.com/mackerelio/mackerel-agent/config"
	cli "gopkg.in/urfave/cli.v1"
	yaml "gopkg.in/yaml.v2"
)

var Command = cli.Command{
	Name:  "run-checks",
	Usage: "run check commands in mackerel-agent.conf",
	Description: `
    Execute command of check plugins in mackerel-agent.conf all at once.
    It is used for checking setting and operation of the check plugins.
`,
	Action: doRunChecks,
}

func doRunChecks(c *cli.Context) error {
	confFile := c.GlobalString("conf")
	conf, err := config.LoadConfig(confFile)
	if err != nil {
		return err
	}
	checkers := make([]checker, len(conf.CheckPlugins))
	i := 0
	for name, p := range conf.CheckPlugins {
		checkers[i] = &checkPluginChecker{
			name: name,
			cp:   p,
		}
		i++
	}
	return runChecks(checkers, os.Stdout)
}

type result struct {
	Name     string `yaml:"-"`
	Memo     string `yaml:"memo,omitempty"`
	Cmd      string `yaml:"command"`
	Stdout   string `yaml:"stdout,omitempty"`
	Stderr   string `yaml:"stderr,omitempty"`
	ExitCode int    `yaml:"exitCode,omitempty"`
	ErrMsg   string `yaml:"error,omitempty"`
}

func (re *result) tapFormat(num int) string {
	okOrNot := "ok"
	if re.ExitCode != 0 || re.ErrMsg != "" {
		okOrNot = "not ok"
	}
	b, _ := yaml.Marshal(re)
	// indent
	yamlStr := "  " + strings.Replace(strings.TrimSpace(string(b)), "\n", "\n  ", -1)
	return fmt.Sprintf("%s %d - %s\n  ---\n%s\n  ...",
		okOrNot, num, re.Name, yamlStr)
}

type checkPluginChecker struct {
	name string
	cp   *config.CheckPlugin
}

func (cpc *checkPluginChecker) check() *result {
	p := cpc.cp
	stdout, stderr, exitCode, err := p.Command.Run()
	cmdStr := p.Command.Cmd
	if cmdStr == "" {
		b, _ := json.Marshal(p.Command.Args)
		cmdStr = string(b)
	}
	errMsg := ""
	if err != nil {
		errMsg = err.Error()
	}
	return &result{
		Name:     cpc.name,
		Memo:     p.Memo,
		Cmd:      cmdStr,
		ExitCode: exitCode,
		Stdout:   strings.TrimSpace(stdout),
		Stderr:   strings.TrimSpace(stderr),
		ErrMsg:   errMsg,
	}
}

type checker interface {
	check() *result
}

func runChecks(checkers []checker, w io.Writer) error {
	ch := make(chan *result)
	total := len(checkers)
	go func() {
		wg := &sync.WaitGroup{}
		wg.Add(total)
		for _, c := range checkers {
			go func(c checker) {
				defer wg.Done()
				ch <- c.check()
			}(c)
		}
		wg.Wait()
		close(ch)
	}()
	fmt.Fprintln(w, "TAP version 13")
	fmt.Fprintf(w, "1..%d\n", total)
	testNum := 1
	for re := range ch {
		fmt.Fprintln(w, re.tapFormat(testNum))
		testNum++
	}
	return nil
}
<commit_msg>[run-checks] return error if any command faileds<commit_after>package checker

import (
	"encoding/json"
	"fmt"
	"io"
	"os"
	"strings"
	"sync"

	"github.com/mackerelio/mackerel-agent/config"
	cli "gopkg.in/urfave/cli.v1"
	yaml "gopkg.in/yaml.v2"
)

var Command = cli.Command{
	Name:  "run-checks",
	Usage: "run check commands in mackerel-agent.conf",
	Description: `
    Execute command of check plugins in mackerel-agent.conf all at once.
    It is used for checking setting and operation of the check plugins.
`,
	Action: doRunChecks,
}

func doRunChecks(c *cli.Context) error {
	confFile := c.GlobalString("conf")
	conf, err := config.LoadConfig(confFile)
	if err != nil {
		return err
	}
	checkers := make([]checker, len(conf.CheckPlugins))
	i := 0
	for name, p := range conf.CheckPlugins {
		checkers[i] = &checkPluginChecker{
			name: name,
			cp:   p,
		}
		i++
	}
	return runChecks(checkers, os.Stdout)
}

type result struct {
	Name     string `yaml:"-"`
	Memo     string `yaml:"memo,omitempty"`
	Cmd      string `yaml:"command"`
	Stdout   string `yaml:"stdout,omitempty"`
	Stderr   string `yaml:"stderr,omitempty"`
	ExitCode int    `yaml:"exitCode,omitempty"`
	ErrMsg   string `yaml:"error,omitempty"`
}

func (re *result) ok() bool {
	return re.ExitCode == 0 && re.ErrMsg == ""
}

func (re *result) tapFormat(num int) string {
	okOrNot := "ok"
	if !re.ok() {
		okOrNot = "not ok"
	}
	b, _ := yaml.Marshal(re)
	// indent
	yamlStr := "  " + strings.Replace(strings.TrimSpace(string(b)), "\n", "\n  ", -1)
	return fmt.Sprintf("%s %d - %s\n  ---\n%s\n  ...",
		okOrNot, num, re.Name, yamlStr)
}

type checkPluginChecker struct {
	name string
	cp   *config.CheckPlugin
}

func (cpc *checkPluginChecker) check() *result {
	p := cpc.cp
	stdout, stderr, exitCode, err := p.Command.Run()
	cmdStr := p.Command.Cmd
	if cmdStr == "" {
		b, _ := json.Marshal(p.Command.Args)
		cmdStr = string(b)
	}
	errMsg := ""
	if err != nil {
		errMsg = err.Error()
	}
	return &result{
		Name:     cpc.name,
		Memo:     p.Memo,
		Cmd:      cmdStr,
		ExitCode: exitCode,
		Stdout:   strings.TrimSpace(stdout),
		Stderr:   strings.TrimSpace(stderr),
		ErrMsg:   errMsg,
	}
}

type checker interface {
	check() *result
}

func runChecks(checkers []checker, w io.Writer) error {
	ch := make(chan *result)
	total := len(checkers)
	go func() {
		wg := &sync.WaitGroup{}
		wg.Add(total)
		for _, c := range checkers {
			go func(c checker) {
				defer wg.Done()
				ch <- c.check()
			}(c)
		}
		wg.Wait()
		close(ch)
	}()
	fmt.Fprintln(w, "TAP version 13")
	fmt.Fprintf(w, "1..%d\n", total)
	testNum, errNum := 1, 0
	for re := range ch {
		fmt.Fprintln(w, re.tapFormat(testNum))
		testNum++
		if !re.ok() {
			errNum++
		}
	}
	if errNum > 0 {
		return fmt.Errorf("Failed %d/%d tests, %3.2f%% okay",
			errNum, total, float64(100*(total-errNum))/float64(total))
	}
	return nil
}
<|endoftext|>


<commit_before>/*
mainthread package initializes Python interpreter and lock the goroutine to a
specific OS thread so that the interpreter can keep using the same OS thread
as a main thread. It also provides Exec function to run any function on the
main thread.

This is provided as a separate package to guarantee that the init function in
this package is executed before all other init functions in py package.
*/
package mainthread

/*
#cgo pkg-config: python-2.7
#include "Python.h"
*/
import "C"
import (
	"errors"
	"runtime"
)

func init() {
	ch := make(chan error)
	go func() {
		// Python interpreter needs to run on the same OS thread.
		runtime.LockOSThread()
		if C.Py_IsInitialized() != 0 {
			ch <- errors.New("python has already been initialized by another module" +
				" but sensorbee/py needs to initialize python by itself to keep using the same main thread")
			return
		}
		C.Py_Initialize()
		if C.Py_IsInitialized() == 0 {
			ch <- errors.New("cannot initialize python")
			return
		}
		defer func() {
			C.Py_Finalize()
		}()

		// TODO: as long as mainthread uses a single goroutine, there might be no
		// need to acquire GIL because other threads never touch the interpreter.
		if C.PyEval_ThreadsInitialized() != 0 { // just in case
			ch <- errors.New("python threads are already initialized although the interpreter wasn't initialized")
			return
		}

		C.PyEval_InitThreads()                  // This call acquires the GIL.
		if C.PyEval_ThreadsInitialized() == 0 { // again, just in case
			ch <- errors.New("cannot initialize GIL")
			return
		}
		defer func() {
			C.PyEval_ReleaseThread(C.PyGILState_GetThisThreadState())
		}()

		if err := importSys(); err != nil {
			ch <- err
			return
		}
		ch <- nil
		process()
	}()

	if err := <-ch; err != nil {
		panic(err)
	}
}
<commit_msg>modify mainthread package discription (applying golint)<commit_after>/*
Package mainthread initializes Python interpreter and lock the goroutine to a
specific OS thread so that the interpreter can keep using the same OS thread
as a main thread. It also provides Exec function to run any function on the
main thread.

This is provided as a separate package to guarantee that the init function in
this package is executed before all other init functions in py package.
*/
package mainthread

/*
#cgo pkg-config: python-2.7
#include "Python.h"
*/
import "C"
import (
	"errors"
	"runtime"
)

func init() {
	ch := make(chan error)
	go func() {
		// Python interpreter needs to run on the same OS thread.
		runtime.LockOSThread()
		if C.Py_IsInitialized() != 0 {
			ch <- errors.New("python has already been initialized by another module" +
				" but sensorbee/py needs to initialize python by itself to keep using the same main thread")
			return
		}
		C.Py_Initialize()
		if C.Py_IsInitialized() == 0 {
			ch <- errors.New("cannot initialize python")
			return
		}
		defer func() {
			C.Py_Finalize()
		}()

		// TODO: as long as mainthread uses a single goroutine, there might be no
		// need to acquire GIL because other threads never touch the interpreter.
		if C.PyEval_ThreadsInitialized() != 0 { // just in case
			ch <- errors.New("python threads are already initialized although the interpreter wasn't initialized")
			return
		}

		C.PyEval_InitThreads()                  // This call acquires the GIL.
		if C.PyEval_ThreadsInitialized() == 0 { // again, just in case
			ch <- errors.New("cannot initialize GIL")
			return
		}
		defer func() {
			C.PyEval_ReleaseThread(C.PyGILState_GetThisThreadState())
		}()

		if err := importSys(); err != nil {
			ch <- err
			return
		}
		ch <- nil
		process()
	}()

	if err := <-ch; err != nil {
		panic(err)
	}
}
<|endoftext|>


<commit_before>package bob

import (
	//"errors"
	//"fmt"
	"io"
	//"io/ioutil"
	"os"
	"os/exec"
)

/*
CopyFile copies one file from source to dest.  Copied from
https://gist.github.com/elazarl/5507969 and modified.
*/
func CopyFile(src, dest string) (err error) {
	//open source
	in, err := os.Open(src)
	if err != nil {
		return
	}
	defer in.Close()

	//create dest
	out, err := os.Create(dest)
	if err != nil {
		return
	}
	defer func() {
		cerr := out.Close()
		if err == nil {
			err = cerr
		}
	}()

	//copy to dest from source
	if _, err = io.Copy(out, in); err != nil {
		return
	}

	//duplicate source permissions on dest
	si, err := os.Stat(src)
	if err != nil {
		return
	}

	if err = out.Chmod(si.Mode()); err != nil {
		return
	}

	//sync dest to disk
	err = out.Sync()

	return
}

/*
CopyDir recursively copies one dir from source to dest.  Copied from
https://github.com/opesun/copyrecur.
*/
func CopyDir(source string, dest string) (err error) {
	return exec.Command("cp", "-af", source, dest).Run()

	/*
		THE CODE BELOW IS BROKEN - FIX IT!
	*/

	//// get properties of source dir
	//sourceInfo, err := os.Stat(source)
	//if err != nil {
	//return
	//}

	//if !sourceInfo.IsDir() {
	//return errors.New("source is not a directory")
	//}

	//// ensure dest dir does not already exist
	//if _, err = os.Open(dest); !os.IsNotExist(err) {
	//return errors.New("destination already exists")
	//}
	//// create dest dir
	//if err = os.MkdirAll(dest, sourceInfo.Mode()); err != nil {
	//return
	//}

	//files, err := ioutil.ReadDir(source)

	//for _, file := range files {
	//sourceFilePath := fmt.Sprintf("%s/%s", source, file.Name())
	//destFilePath := fmt.Sprintf("%s/%s", dest, file.Name())

	//if file.IsDir() {
	//if err = CopyDir(sourceFilePath, destFilePath); err != nil {
	//return
	//}
	//} else {
	//if err = CopyFile(sourceFilePath, destFilePath); err != nil {
	//return
	//}
	//}

	//}
	//return
}
<commit_msg>Reinstating the native dir-copying (over `cp -R`) after fixing the issue<commit_after>package bob

import (
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"os"
)

/*
CopyFile copies one file from source to dest.  Copied from
https://gist.github.com/elazarl/5507969 and modified.
*/
func CopyFile(src, dest string) (err error) {
	//open source
	in, err := os.Open(src)
	if err != nil {
		return
	}
	defer in.Close()

	//create dest
	out, err := os.Create(dest)
	if err != nil {
		return
	}
	defer func() {
		cerr := out.Close()
		if err == nil {
			err = cerr
		}
	}()

	//copy to dest from source
	if _, err = io.Copy(out, in); err != nil {
		return
	}

	//duplicate source permissions on dest
	si, err := os.Stat(src)
	if err != nil {
		return
	}

	if err = out.Chmod(si.Mode()); err != nil {
		return
	}

	//sync dest to disk
	err = out.Sync()

	return
}

/*
CopyDir recursively copies one dir from source to dest.  Copied from
https://github.com/opesun/copyrecur.
*/
func CopyDir(source, dest string) (err error) {
	// get properties of source dir
	sourceInfo, err := os.Stat(source)
	if err != nil {
		return
	}

	if !sourceInfo.IsDir() {
		return errors.New("source is not a directory")
	}

	// ensure dest dir does not already exist
	if _, err = os.Open(dest); !os.IsNotExist(err) {
		return errors.New("destination already exists")
	}

	// create dest dir
	if err = os.MkdirAll(dest, sourceInfo.Mode()); err != nil {
		return
	}

	files, err := ioutil.ReadDir(source)

	for _, file := range files {
		sourceFilePath := fmt.Sprintf("%s/%s", source, file.Name())
		destFilePath := fmt.Sprintf("%s/%s", dest, file.Name())

		if file.IsDir() {
			if err = CopyDir(sourceFilePath, destFilePath); err != nil {
				return
			}
		} else {
			if err = CopyFile(sourceFilePath, destFilePath); err != nil {
				return
			}
		}

	}
	return
}
<|endoftext|>


<commit_before>package main

import (
	"errors"
	"fmt"
	"os"
	"runtime"
	"strings"

	"github.com/Microsoft/go-winio/pkg/etwlogrus"
	specs "github.com/opencontainers/runtime-spec/specs-go"
	"github.com/sirupsen/logrus"
	"github.com/urfave/cli"
)

const usage = ``

// Add a manifest to get proper Windows version detection.
//
// goversioninfo can be installed with "go get github.com/josephspurrier/goversioninfo/cmd/goversioninfo"

//go:generate goversioninfo -platform-specific

// version will be populated by the Makefile, read from
// VERSION file of the source code.
var version = ""

// gitCommit will be the hash that the binary was built from
// and will be populated by the Makefile
var gitCommit = ""

var (
	namespaceFlag        string
	addressFlag          string
	containerdBinaryFlag string

	idFlag string
)

func stack() []byte {
	buf := make([]byte, 1024)
	for {
		n := runtime.Stack(buf, true) // true means all goroutines
		if n < len(buf) {
			return buf[:n]
		}
		buf = make([]byte, 2*len(buf))
	}
}

func panicRecover() {
	if r := recover(); r != nil {
		logrus.Errorf("containerd-shim-runhcs-v1: panic: %s", r)
		s := string(stack())
		split := strings.Split(s, "\n")
		for _, line := range split {
			logrus.Error(line)
		}
	}
}

func main() {
	// Provider ID: 0b52781f-b24d-5685-ddf6-69830ed40ec3
	// Hook isn't closed explicitly, as it will exist until process exit.
	if hook, err := etwlogrus.NewHook("Microsoft.Virtualization.RunHCS"); err == nil {
		logrus.AddHook(hook)
	} else {
		logrus.Error(err)
	}

	defer panicRecover()

	app := cli.NewApp()
	app.Name = "containerd-shim-runhcs-v1"
	app.Usage = usage

	var v []string
	if version != "" {
		v = append(v, version)
	}
	if gitCommit != "" {
		v = append(v, fmt.Sprintf("commit: %s", gitCommit))
	}
	v = append(v, fmt.Sprintf("spec: %s", specs.Version))
	app.Version = strings.Join(v, "\n")

	app.Flags = []cli.Flag{
		cli.StringFlag{
			Name:  "namespace",
			Usage: "the namespace of the container",
		},
		cli.StringFlag{
			Name:  "address",
			Usage: "the address of the containerd's main socket",
		},
		cli.StringFlag{
			Name:  "publish-binary",
			Usage: "the binary path to publish events back to containerd",
		},
		cli.StringFlag{
			Name:  "id",
			Usage: "the id of the container",
		},
		cli.StringFlag{
			Name:  "bundle",
			Usage: "the bundle path to delete (delete command only).",
		},
		cli.BoolFlag{
			Name:  "debug",
			Usage: "run the shim in debug mode",
		},
	}
	app.Commands = []cli.Command{
		startCommand,
		deleteCommand,
		serveCommand,
	}
	app.Before = func(context *cli.Context) error {
		if namespaceFlag = context.GlobalString("namespace"); namespaceFlag == "" {
			return errors.New("namespace is required")
		}
		if addressFlag = context.GlobalString("address"); addressFlag == "" {
			return errors.New("address is required")
		}
		if containerdBinaryFlag = context.GlobalString("publish-binary"); containerdBinaryFlag == "" {
			return errors.New("publish-binary is required")
		}
		if idFlag = context.GlobalString("id"); idFlag == "" {
			return errors.New("id is required")
		}
		return nil
	}

	// Setup the event for stack dump
	setupDumpStacks()

	if err := app.Run(os.Args); err != nil {
		fmt.Fprintln(cli.ErrWriter, err)
		os.Exit(1)
	}
}
<commit_msg>Log event at shim launch<commit_after>package main

import (
	"errors"
	"fmt"
	"os"
	"runtime"
	"strings"

	"github.com/Microsoft/go-winio/pkg/etw"
	"github.com/Microsoft/go-winio/pkg/etwlogrus"
	specs "github.com/opencontainers/runtime-spec/specs-go"
	"github.com/sirupsen/logrus"
	"github.com/urfave/cli"
)

const usage = ``

// Add a manifest to get proper Windows version detection.
//
// goversioninfo can be installed with "go get github.com/josephspurrier/goversioninfo/cmd/goversioninfo"

//go:generate goversioninfo -platform-specific

// version will be populated by the Makefile, read from
// VERSION file of the source code.
var version = ""

// gitCommit will be the hash that the binary was built from
// and will be populated by the Makefile
var gitCommit = ""

var (
	namespaceFlag        string
	addressFlag          string
	containerdBinaryFlag string

	idFlag string
)

func stack() []byte {
	buf := make([]byte, 1024)
	for {
		n := runtime.Stack(buf, true) // true means all goroutines
		if n < len(buf) {
			return buf[:n]
		}
		buf = make([]byte, 2*len(buf))
	}
}

func panicRecover() {
	if r := recover(); r != nil {
		logrus.Errorf("containerd-shim-runhcs-v1: panic: %s", r)
		s := string(stack())
		split := strings.Split(s, "\n")
		for _, line := range split {
			logrus.Error(line)
		}
	}
}

func main() {
	// Provider ID: 0b52781f-b24d-5685-ddf6-69830ed40ec3
	// Provider and hook aren't closed explicitly, as they will exist until process exit.
	provider, err := etw.NewProvider("Microsoft.Virtualization.RunHCS", nil)
	if err != nil {
		logrus.Error(err)
	} else {
		if hook, err := etwlogrus.NewHookFromProvider(provider); err == nil {
			logrus.AddHook(hook)
		} else {
			logrus.Error(err)
		}
	}

	defer panicRecover()

	provider.WriteEvent(
		"ShimLaunched",
		nil,
		etw.WithFields(
			etw.StringArray("Args", os.Args),
		),
	)

	app := cli.NewApp()
	app.Name = "containerd-shim-runhcs-v1"
	app.Usage = usage

	var v []string
	if version != "" {
		v = append(v, version)
	}
	if gitCommit != "" {
		v = append(v, fmt.Sprintf("commit: %s", gitCommit))
	}
	v = append(v, fmt.Sprintf("spec: %s", specs.Version))
	app.Version = strings.Join(v, "\n")

	app.Flags = []cli.Flag{
		cli.StringFlag{
			Name:  "namespace",
			Usage: "the namespace of the container",
		},
		cli.StringFlag{
			Name:  "address",
			Usage: "the address of the containerd's main socket",
		},
		cli.StringFlag{
			Name:  "publish-binary",
			Usage: "the binary path to publish events back to containerd",
		},
		cli.StringFlag{
			Name:  "id",
			Usage: "the id of the container",
		},
		cli.StringFlag{
			Name:  "bundle",
			Usage: "the bundle path to delete (delete command only).",
		},
		cli.BoolFlag{
			Name:  "debug",
			Usage: "run the shim in debug mode",
		},
	}
	app.Commands = []cli.Command{
		startCommand,
		deleteCommand,
		serveCommand,
	}
	app.Before = func(context *cli.Context) error {
		if namespaceFlag = context.GlobalString("namespace"); namespaceFlag == "" {
			return errors.New("namespace is required")
		}
		if addressFlag = context.GlobalString("address"); addressFlag == "" {
			return errors.New("address is required")
		}
		if containerdBinaryFlag = context.GlobalString("publish-binary"); containerdBinaryFlag == "" {
			return errors.New("publish-binary is required")
		}
		if idFlag = context.GlobalString("id"); idFlag == "" {
			return errors.New("id is required")
		}
		return nil
	}

	// Setup the event for stack dump
	setupDumpStacks()

	if err := app.Run(os.Args); err != nil {
		fmt.Fprintln(cli.ErrWriter, err)
		os.Exit(1)
	}
}
<|endoftext|>


<commit_before>package terraform

import (
	"fmt"
	"strings"
	"sync"

	"github.com/hashicorp/terraform/config"
	"github.com/hashicorp/terraform/depgraph"
)

// Terraform is the primary structure that is used to interact with
// Terraform from code, and can perform operations such as returning
// all resources, a resource tree, a specific resource, etc.
type Terraform struct {
	config    *config.Config
	graph     *depgraph.Graph
	mapping   map[*config.Resource]ResourceProvider
	variables map[string]string
}

// Config is the configuration that must be given to instantiate
// a Terraform structure.
type Config struct {
	Config    *config.Config
	Providers map[string]ResourceProviderFactory
	Variables map[string]string
}

// New creates a new Terraform structure, initializes resource providers
// for the given configuration, etc.
//
// Semantic checks of the entire configuration structure are done at this
// time, as well as richer checks such as verifying that the resource providers
// can be properly initialized, can be configured, etc.
func New(c *Config) (*Terraform, error) {
	var errs []error

	// Validate that all required variables have values
	required := make(map[string]struct{})
	for k, v := range c.Config.Variables {
		if v.Required() {
			required[k] = struct{}{}
		}
	}
	for k, _ := range c.Variables {
		delete(required, k)
	}
	if len(required) > 0 {
		for k, _ := range required {
			errs = append(errs, fmt.Errorf(
				"Required variable not set: %s", k))
		}
	}

	// TODO(mitchellh): variables that are unknown

	// Go through each resource and match it up to a provider
	mapping := make(map[*config.Resource]ResourceProvider)
	providers := make(map[string]ResourceProvider)
	for _, r := range c.Config.Resources {
		// Find the prefixes that match this in the order of
		// longest matching first (most specific)
		prefixes := matchingPrefixes(r.Type, c.Providers)

		// Go through each prefix and instantiate if necessary, then
		// verify if this provider is of use to us or not.
		var provider ResourceProvider = nil
		for _, prefix := range prefixes {
			p, ok := providers[prefix]
			if !ok {
				var err error
				p, err = c.Providers[prefix]()
				if err != nil {
					err = fmt.Errorf(
						"Error instantiating resource provider for "+
							"prefix %s: %s", prefix, err)
					return nil, err
				}

				providers[prefix] = p
			}

			// Test if this provider matches what we need
			if !ProviderSatisfies(p, r.Type) {
				continue
			}

			// A match! Set it and break
			provider = p
			break
		}

		if provider == nil {
			// We never found a matching provider.
			errs = append(errs, fmt.Errorf(
				"Provider for resource %s not found.",
				r.Id()))
		}

		mapping[r] = provider
	}

	// Build the resource graph
	graph := c.Config.ResourceGraph()
	if err := graph.Validate(); err != nil {
		errs = append(errs, fmt.Errorf(
			"Resource graph has an error: %s", err))
	}

	// If we accumulated any errors, then return them all
	if len(errs) > 0 {
		return nil, &MultiError{Errors: errs}
	}

	return &Terraform{
		config:    c.Config,
		graph:     graph,
		mapping:   mapping,
		variables: c.Variables,
	}, nil
}

func (t *Terraform) Apply(*State, *Diff) (*State, error) {
	return nil, nil
}

func (t *Terraform) Diff(s *State) (*Diff, error) {
	result := new(Diff)
	err := t.graph.Walk(t.diffWalkFn(s, result))
	if err != nil {
		return nil, err
	}

	return result, nil
}

func (t *Terraform) Refresh(*State) (*State, error) {
	return nil, nil
}

func (t *Terraform) diffWalkFn(
	state *State, result *Diff) depgraph.WalkFunc {
	var l sync.RWMutex

	// Initialize the state since we always read it
	if state == nil {
		state = new(State)
		state.init()
	}

	// Initialize the result diff so we can write to it
	result.init()

	// This is the value that will be used for computed properties
	computedId := "computed"

	// Initialize the variables for application
	vars := make(map[string]string)
	for k, v := range t.variables {
		vars[k] = v
	}

	return func(n *depgraph.Noun) error {
		// If it is the root node, ignore
		if n.Name == config.ResourceGraphRoot {
			return nil
		}

		r := n.Meta.(*config.Resource)
		p := t.mapping[r]
		if p == nil {
			panic(fmt.Sprintf("No provider for resource: %s", r.Id()))
		}

		l.RLock()
		rs := state.resources[r.Id()]
		if len(vars) > 0 {
			r = r.ReplaceVariables(vars)
		}
		l.RUnlock()

		diff, err := p.Diff(rs, r.Config)
		if err != nil {
			return err
		}

		// If there were no diff items, return right away
		if len(diff.Attributes) == 0 {
			return nil
		}

		// Acquire a lock since this function is called in parallel
		l.Lock()
		defer l.Unlock()

		// Update the resulting diff
		result.Resources[r.Id()] = diff.Attributes

		// Determine the new state and update variables
		rs = rs.MergeDiff(diff.Attributes, computedId)
		for ak, av := range rs.Attributes {
			vars[fmt.Sprintf("%s.%s", r.Id(), ak)] = av
		}

		return nil
	}
}

// matchingPrefixes takes a resource type and a set of resource
// providers we know about by prefix and returns a list of prefixes
// that might be valid for that resource.
//
// The list returned is in the order that they should be attempted.
func matchingPrefixes(
	t string,
	ps map[string]ResourceProviderFactory) []string {
	result := make([]string, 0, 1)
	for prefix, _ := range ps {
		if strings.HasPrefix(t, prefix) {
			result = append(result, prefix)
		}
	}

	// TODO(mitchellh): Order by longest prefix first

	return result
}
<commit_msg>terraform: no need to init state if we don't use<commit_after>package terraform

import (
	"fmt"
	"strings"
	"sync"

	"github.com/hashicorp/terraform/config"
	"github.com/hashicorp/terraform/depgraph"
)

// Terraform is the primary structure that is used to interact with
// Terraform from code, and can perform operations such as returning
// all resources, a resource tree, a specific resource, etc.
type Terraform struct {
	config    *config.Config
	graph     *depgraph.Graph
	mapping   map[*config.Resource]ResourceProvider
	variables map[string]string
}

// Config is the configuration that must be given to instantiate
// a Terraform structure.
type Config struct {
	Config    *config.Config
	Providers map[string]ResourceProviderFactory
	Variables map[string]string
}

// New creates a new Terraform structure, initializes resource providers
// for the given configuration, etc.
//
// Semantic checks of the entire configuration structure are done at this
// time, as well as richer checks such as verifying that the resource providers
// can be properly initialized, can be configured, etc.
func New(c *Config) (*Terraform, error) {
	var errs []error

	// Validate that all required variables have values
	required := make(map[string]struct{})
	for k, v := range c.Config.Variables {
		if v.Required() {
			required[k] = struct{}{}
		}
	}
	for k, _ := range c.Variables {
		delete(required, k)
	}
	if len(required) > 0 {
		for k, _ := range required {
			errs = append(errs, fmt.Errorf(
				"Required variable not set: %s", k))
		}
	}

	// TODO(mitchellh): variables that are unknown

	// Go through each resource and match it up to a provider
	mapping := make(map[*config.Resource]ResourceProvider)
	providers := make(map[string]ResourceProvider)
	for _, r := range c.Config.Resources {
		// Find the prefixes that match this in the order of
		// longest matching first (most specific)
		prefixes := matchingPrefixes(r.Type, c.Providers)

		// Go through each prefix and instantiate if necessary, then
		// verify if this provider is of use to us or not.
		var provider ResourceProvider = nil
		for _, prefix := range prefixes {
			p, ok := providers[prefix]
			if !ok {
				var err error
				p, err = c.Providers[prefix]()
				if err != nil {
					err = fmt.Errorf(
						"Error instantiating resource provider for "+
							"prefix %s: %s", prefix, err)
					return nil, err
				}

				providers[prefix] = p
			}

			// Test if this provider matches what we need
			if !ProviderSatisfies(p, r.Type) {
				continue
			}

			// A match! Set it and break
			provider = p
			break
		}

		if provider == nil {
			// We never found a matching provider.
			errs = append(errs, fmt.Errorf(
				"Provider for resource %s not found.",
				r.Id()))
		}

		mapping[r] = provider
	}

	// Build the resource graph
	graph := c.Config.ResourceGraph()
	if err := graph.Validate(); err != nil {
		errs = append(errs, fmt.Errorf(
			"Resource graph has an error: %s", err))
	}

	// If we accumulated any errors, then return them all
	if len(errs) > 0 {
		return nil, &MultiError{Errors: errs}
	}

	return &Terraform{
		config:    c.Config,
		graph:     graph,
		mapping:   mapping,
		variables: c.Variables,
	}, nil
}

func (t *Terraform) Apply(*State, *Diff) (*State, error) {
	return nil, nil
}

func (t *Terraform) Diff(s *State) (*Diff, error) {
	result := new(Diff)
	err := t.graph.Walk(t.diffWalkFn(s, result))
	if err != nil {
		return nil, err
	}

	return result, nil
}

func (t *Terraform) Refresh(*State) (*State, error) {
	return nil, nil
}

func (t *Terraform) diffWalkFn(
	state *State, result *Diff) depgraph.WalkFunc {
	var l sync.RWMutex

	// Initialize the result diff so we can write to it
	result.init()

	// This is the value that will be used for computed properties
	computedId := "computed"

	// Initialize the variables for application
	vars := make(map[string]string)
	for k, v := range t.variables {
		vars[k] = v
	}

	return func(n *depgraph.Noun) error {
		// If it is the root node, ignore
		if n.Name == config.ResourceGraphRoot {
			return nil
		}

		r := n.Meta.(*config.Resource)
		p := t.mapping[r]
		if p == nil {
			panic(fmt.Sprintf("No provider for resource: %s", r.Id()))
		}

		l.RLock()
		var rs *ResourceState
		if state != nil {
			rs = state.resources[r.Id()]
		}
		if len(vars) > 0 {
			r = r.ReplaceVariables(vars)
		}
		l.RUnlock()

		diff, err := p.Diff(rs, r.Config)
		if err != nil {
			return err
		}

		// If there were no diff items, return right away
		if len(diff.Attributes) == 0 {
			return nil
		}

		// Acquire a lock since this function is called in parallel
		l.Lock()
		defer l.Unlock()

		// Update the resulting diff
		result.Resources[r.Id()] = diff.Attributes

		// Determine the new state and update variables
		rs = rs.MergeDiff(diff.Attributes, computedId)
		for ak, av := range rs.Attributes {
			vars[fmt.Sprintf("%s.%s", r.Id(), ak)] = av
		}

		return nil
	}
}

// matchingPrefixes takes a resource type and a set of resource
// providers we know about by prefix and returns a list of prefixes
// that might be valid for that resource.
//
// The list returned is in the order that they should be attempted.
func matchingPrefixes(
	t string,
	ps map[string]ResourceProviderFactory) []string {
	result := make([]string, 0, 1)
	for prefix, _ := range ps {
		if strings.HasPrefix(t, prefix) {
			result = append(result, prefix)
		}
	}

	// TODO(mitchellh): Order by longest prefix first

	return result
}
<|endoftext|>


<commit_before>package physical

import (
	"strings"
	"sync"

	log "github.com/mgutz/logxi/v1"

	"github.com/armon/go-radix"
)

// InmemBackend is an in-memory only physical backend. It is useful
// for testing and development situations where the data is not
// expected to be durable.
type InmemBackend struct {
	root       *radix.Tree
	l          sync.RWMutex
	permitPool *PermitPool
	logger     log.Logger
}

// NewInmem constructs a new in-memory backend
func NewInmem(logger log.Logger) *InmemBackend {
	in := &InmemBackend{
		root:       radix.New(),
		permitPool: NewPermitPool(DefaultParallelOperations),
	}
	return in
}

// Put is used to insert or update an entry
func (i *InmemBackend) Put(entry *Entry) error {
	i.permitPool.Acquire()
	defer i.permitPool.Release()

	i.l.Lock()
	defer i.l.Unlock()

	i.root.Insert(entry.Key, entry)
	return nil
}

// Get is used to fetch an entry
func (i *InmemBackend) Get(key string) (*Entry, error) {
	i.permitPool.Acquire()
	defer i.permitPool.Release()

	i.l.RLock()
	defer i.l.RUnlock()

	if raw, ok := i.root.Get(key); ok {
		return raw.(*Entry), nil
	}
	return nil, nil
}

// Delete is used to permanently delete an entry
func (i *InmemBackend) Delete(key string) error {
	i.permitPool.Acquire()
	defer i.permitPool.Release()

	i.l.Lock()
	defer i.l.Unlock()

	i.root.Delete(key)
	return nil
}

// List is used ot list all the keys under a given
// prefix, up to the next prefix.
func (i *InmemBackend) List(prefix string) ([]string, error) {
	i.permitPool.Acquire()
	defer i.permitPool.Release()

	i.l.RLock()
	defer i.l.RUnlock()

	var out []string
	seen := make(map[string]interface{})
	walkFn := func(s string, v interface{}) bool {
		trimmed := strings.TrimPrefix(s, prefix)
		sep := strings.Index(trimmed, "/")
		if sep == -1 {
			out = append(out, trimmed)
		} else {
			trimmed = trimmed[:sep+1]
			if _, ok := seen[trimmed]; !ok {
				out = append(out, trimmed)
				seen[trimmed] = struct{}{}
			}
		}
		return false
	}
	i.root.WalkPrefix(prefix, walkFn)

	return out, nil
}
<commit_msg>Actually give the logger to inmem backend<commit_after>package physical

import (
	"strings"
	"sync"

	log "github.com/mgutz/logxi/v1"

	"github.com/armon/go-radix"
)

// InmemBackend is an in-memory only physical backend. It is useful
// for testing and development situations where the data is not
// expected to be durable.
type InmemBackend struct {
	root       *radix.Tree
	l          sync.RWMutex
	permitPool *PermitPool
	logger     log.Logger
}

// NewInmem constructs a new in-memory backend
func NewInmem(logger log.Logger) *InmemBackend {
	in := &InmemBackend{
		root:       radix.New(),
		permitPool: NewPermitPool(DefaultParallelOperations),
		logger:     logger,
	}
	return in
}

// Put is used to insert or update an entry
func (i *InmemBackend) Put(entry *Entry) error {
	i.permitPool.Acquire()
	defer i.permitPool.Release()

	i.l.Lock()
	defer i.l.Unlock()

	i.root.Insert(entry.Key, entry)
	return nil
}

// Get is used to fetch an entry
func (i *InmemBackend) Get(key string) (*Entry, error) {
	i.permitPool.Acquire()
	defer i.permitPool.Release()

	i.l.RLock()
	defer i.l.RUnlock()

	if raw, ok := i.root.Get(key); ok {
		return raw.(*Entry), nil
	}
	return nil, nil
}

// Delete is used to permanently delete an entry
func (i *InmemBackend) Delete(key string) error {
	i.permitPool.Acquire()
	defer i.permitPool.Release()

	i.l.Lock()
	defer i.l.Unlock()

	i.root.Delete(key)
	return nil
}

// List is used ot list all the keys under a given
// prefix, up to the next prefix.
func (i *InmemBackend) List(prefix string) ([]string, error) {
	i.permitPool.Acquire()
	defer i.permitPool.Release()

	i.l.RLock()
	defer i.l.RUnlock()

	var out []string
	seen := make(map[string]interface{})
	walkFn := func(s string, v interface{}) bool {
		trimmed := strings.TrimPrefix(s, prefix)
		sep := strings.Index(trimmed, "/")
		if sep == -1 {
			out = append(out, trimmed)
		} else {
			trimmed = trimmed[:sep+1]
			if _, ok := seen[trimmed]; !ok {
				out = append(out, trimmed)
				seen[trimmed] = struct{}{}
			}
		}
		return false
	}
	i.root.WalkPrefix(prefix, walkFn)

	return out, nil
}
<|endoftext|>


<commit_before>package pgsql

import (
	"database/sql"
	"time"

	"github.com/coreos/clair/database"
	cerrors "github.com/coreos/clair/utils/errors"
	"github.com/guregu/null/zero"
	"github.com/pborman/uuid"
)

// do it in tx so we won't insert/update a vuln without notification and vice-versa.
// name and created doesn't matter.
func createNotification(tx *sql.Tx, oldVulnerabilityID, newVulnerabilityID int) error {
	defer observeQueryTime("createNotification", "all", time.Now())

	// Insert Notification.
	oldVulnerabilityNullableID := sql.NullInt64{Int64: int64(oldVulnerabilityID), Valid: oldVulnerabilityID != 0}
	newVulnerabilityNullableID := sql.NullInt64{Int64: int64(newVulnerabilityID), Valid: newVulnerabilityID != 0}
	_, err := tx.Exec(insertNotification, uuid.New(), oldVulnerabilityNullableID, newVulnerabilityNullableID)
	if err != nil {
		tx.Rollback()
		return handleError("insertNotification", err)
	}

	return nil
}

// Get one available notification name (!locked && !deleted && (!notified || notified_but_timed-out)).
// Does not fill new/old vuln.
func (pgSQL *pgSQL) GetAvailableNotification(renotifyInterval time.Duration) (database.VulnerabilityNotification, error) {
	defer observeQueryTime("GetAvailableNotification", "all", time.Now())

	before := time.Now().Add(-renotifyInterval)
	row := pgSQL.QueryRow(searchNotificationAvailable, before)
	notification, err := pgSQL.scanNotification(row, false)

	return notification, handleError("searchNotificationAvailable", err)
}

func (pgSQL *pgSQL) GetNotification(name string, limit int, page database.VulnerabilityNotificationPageNumber) (database.VulnerabilityNotification, database.VulnerabilityNotificationPageNumber, error) {
	defer observeQueryTime("GetNotification", "all", time.Now())

	// Get Notification.
	notification, err := pgSQL.scanNotification(pgSQL.QueryRow(searchNotification, name), true)
	if err != nil {
		return notification, page, handleError("searchNotification", err)
	}

	// Load vulnerabilities' LayersIntroducingVulnerability.
	page.OldVulnerability, err = pgSQL.loadLayerIntroducingVulnerability(
		notification.OldVulnerability,
		limit,
		page.OldVulnerability,
	)

	if err != nil {
		return notification, page, err
	}

	page.NewVulnerability, err = pgSQL.loadLayerIntroducingVulnerability(
		notification.NewVulnerability,
		limit,
		page.NewVulnerability,
	)

	if err != nil {
		return notification, page, err
	}

	return notification, page, nil
}

func (pgSQL *pgSQL) scanNotification(row *sql.Row, hasVulns bool) (database.VulnerabilityNotification, error) {
	var notification database.VulnerabilityNotification
	var created zero.Time
	var notified zero.Time
	var deleted zero.Time
	var oldVulnerabilityNullableID sql.NullInt64
	var newVulnerabilityNullableID sql.NullInt64

	// Scan notification.
	if hasVulns {
		err := row.Scan(
			&notification.ID,
			&notification.Name,
			&created,
			&notified,
			&deleted,
			&oldVulnerabilityNullableID,
			&newVulnerabilityNullableID,
		)

		if err != nil {
			return notification, err
		}
	} else {
		err := row.Scan(&notification.ID, &notification.Name, &created, &notified, &deleted)

		if err != nil {
			return notification, err
		}
	}

	notification.Created = created.Time
	notification.Notified = notified.Time
	notification.Deleted = deleted.Time

	if hasVulns {
		if oldVulnerabilityNullableID.Valid {
			vulnerability, err := pgSQL.findVulnerabilityByIDWithDeleted(int(oldVulnerabilityNullableID.Int64))
			if err != nil {
				return notification, err
			}

			notification.OldVulnerability = &vulnerability
		}

		if newVulnerabilityNullableID.Valid {
			vulnerability, err := pgSQL.findVulnerabilityByIDWithDeleted(int(newVulnerabilityNullableID.Int64))
			if err != nil {
				return notification, err
			}

			notification.NewVulnerability = &vulnerability
		}
	}

	return notification, nil
}

// Fills Vulnerability.LayersIntroducingVulnerability.
// limit -1: won't do anything
// limit 0: will just get the startID of the second page
func (pgSQL *pgSQL) loadLayerIntroducingVulnerability(vulnerability *database.Vulnerability, limit, startID int) (int, error) {
	tf := time.Now()

	if vulnerability == nil {
		return -1, nil
	}

	// A startID equals to -1 means that we reached the end already.
	if startID == -1 || limit == -1 {
		return -1, nil
	}

	// We do `defer observeQueryTime` here because we don't want to observe invalid calls.
	defer observeQueryTime("loadLayerIntroducingVulnerability", "all", tf)

	// Query with limit + 1, the last item will be used to know the next starting ID.
	rows, err := pgSQL.Query(searchNotificationLayerIntroducingVulnerability,
		vulnerability.ID, startID, limit+1)
	if err != nil {
		return 0, handleError("searchVulnerabilityFixedInFeature", err)
	}
	defer rows.Close()

	var layers []database.Layer
	for rows.Next() {
		var layer database.Layer

		if err := rows.Scan(&layer.ID, &layer.Name); err != nil {
			return -1, handleError("searchNotificationLayerIntroducingVulnerability.Scan()", err)
		}

		layers = append(layers, layer)
	}
	if err = rows.Err(); err != nil {
		return -1, handleError("searchNotificationLayerIntroducingVulnerability.Rows()", err)
	}

	size := limit
	if len(layers) < limit {
		size = len(layers)
	}
	vulnerability.LayersIntroducingVulnerability = layers[:size]

	nextID := -1
	if len(layers) > limit {
		nextID = layers[limit].ID
	}

	return nextID, nil
}

func (pgSQL *pgSQL) SetNotificationNotified(name string) error {
	defer observeQueryTime("SetNotificationNotified", "all", time.Now())

	if _, err := pgSQL.Exec(updatedNotificationNotified, name); err != nil {
		return handleError("updatedNotificationNotified", err)
	}
	return nil
}

func (pgSQL *pgSQL) DeleteNotification(name string) error {
	defer observeQueryTime("DeleteNotification", "all", time.Now())

	result, err := pgSQL.Exec(removeNotification, name)
	if err != nil {
		return handleError("removeNotification", err)
	}

	affected, err := result.RowsAffected()
	if err != nil {
		return handleError("removeNotification.RowsAffected()", err)
	}

	if affected <= 0 {
		return cerrors.ErrNotFound
	}

	return nil
}
<commit_msg>database: Fix invalid error message<commit_after>package pgsql

import (
	"database/sql"
	"time"

	"github.com/coreos/clair/database"
	cerrors "github.com/coreos/clair/utils/errors"
	"github.com/guregu/null/zero"
	"github.com/pborman/uuid"
)

// do it in tx so we won't insert/update a vuln without notification and vice-versa.
// name and created doesn't matter.
func createNotification(tx *sql.Tx, oldVulnerabilityID, newVulnerabilityID int) error {
	defer observeQueryTime("createNotification", "all", time.Now())

	// Insert Notification.
	oldVulnerabilityNullableID := sql.NullInt64{Int64: int64(oldVulnerabilityID), Valid: oldVulnerabilityID != 0}
	newVulnerabilityNullableID := sql.NullInt64{Int64: int64(newVulnerabilityID), Valid: newVulnerabilityID != 0}
	_, err := tx.Exec(insertNotification, uuid.New(), oldVulnerabilityNullableID, newVulnerabilityNullableID)
	if err != nil {
		tx.Rollback()
		return handleError("insertNotification", err)
	}

	return nil
}

// Get one available notification name (!locked && !deleted && (!notified || notified_but_timed-out)).
// Does not fill new/old vuln.
func (pgSQL *pgSQL) GetAvailableNotification(renotifyInterval time.Duration) (database.VulnerabilityNotification, error) {
	defer observeQueryTime("GetAvailableNotification", "all", time.Now())

	before := time.Now().Add(-renotifyInterval)
	row := pgSQL.QueryRow(searchNotificationAvailable, before)
	notification, err := pgSQL.scanNotification(row, false)

	return notification, handleError("searchNotificationAvailable", err)
}

func (pgSQL *pgSQL) GetNotification(name string, limit int, page database.VulnerabilityNotificationPageNumber) (database.VulnerabilityNotification, database.VulnerabilityNotificationPageNumber, error) {
	defer observeQueryTime("GetNotification", "all", time.Now())

	// Get Notification.
	notification, err := pgSQL.scanNotification(pgSQL.QueryRow(searchNotification, name), true)
	if err != nil {
		return notification, page, handleError("searchNotification", err)
	}

	// Load vulnerabilities' LayersIntroducingVulnerability.
	page.OldVulnerability, err = pgSQL.loadLayerIntroducingVulnerability(
		notification.OldVulnerability,
		limit,
		page.OldVulnerability,
	)

	if err != nil {
		return notification, page, err
	}

	page.NewVulnerability, err = pgSQL.loadLayerIntroducingVulnerability(
		notification.NewVulnerability,
		limit,
		page.NewVulnerability,
	)

	if err != nil {
		return notification, page, err
	}

	return notification, page, nil
}

func (pgSQL *pgSQL) scanNotification(row *sql.Row, hasVulns bool) (database.VulnerabilityNotification, error) {
	var notification database.VulnerabilityNotification
	var created zero.Time
	var notified zero.Time
	var deleted zero.Time
	var oldVulnerabilityNullableID sql.NullInt64
	var newVulnerabilityNullableID sql.NullInt64

	// Scan notification.
	if hasVulns {
		err := row.Scan(
			&notification.ID,
			&notification.Name,
			&created,
			&notified,
			&deleted,
			&oldVulnerabilityNullableID,
			&newVulnerabilityNullableID,
		)

		if err != nil {
			return notification, err
		}
	} else {
		err := row.Scan(&notification.ID, &notification.Name, &created, &notified, &deleted)

		if err != nil {
			return notification, err
		}
	}

	notification.Created = created.Time
	notification.Notified = notified.Time
	notification.Deleted = deleted.Time

	if hasVulns {
		if oldVulnerabilityNullableID.Valid {
			vulnerability, err := pgSQL.findVulnerabilityByIDWithDeleted(int(oldVulnerabilityNullableID.Int64))
			if err != nil {
				return notification, err
			}

			notification.OldVulnerability = &vulnerability
		}

		if newVulnerabilityNullableID.Valid {
			vulnerability, err := pgSQL.findVulnerabilityByIDWithDeleted(int(newVulnerabilityNullableID.Int64))
			if err != nil {
				return notification, err
			}

			notification.NewVulnerability = &vulnerability
		}
	}

	return notification, nil
}

// Fills Vulnerability.LayersIntroducingVulnerability.
// limit -1: won't do anything
// limit 0: will just get the startID of the second page
func (pgSQL *pgSQL) loadLayerIntroducingVulnerability(vulnerability *database.Vulnerability, limit, startID int) (int, error) {
	tf := time.Now()

	if vulnerability == nil {
		return -1, nil
	}

	// A startID equals to -1 means that we reached the end already.
	if startID == -1 || limit == -1 {
		return -1, nil
	}

	// We do `defer observeQueryTime` here because we don't want to observe invalid calls.
	defer observeQueryTime("loadLayerIntroducingVulnerability", "all", tf)

	// Query with limit + 1, the last item will be used to know the next starting ID.
	rows, err := pgSQL.Query(searchNotificationLayerIntroducingVulnerability,
		vulnerability.ID, startID, limit+1)
	if err != nil {
		return 0, handleError("searchNotificationLayerIntroducingVulnerability", err)
	}
	defer rows.Close()

	var layers []database.Layer
	for rows.Next() {
		var layer database.Layer

		if err := rows.Scan(&layer.ID, &layer.Name); err != nil {
			return -1, handleError("searchNotificationLayerIntroducingVulnerability.Scan()", err)
		}

		layers = append(layers, layer)
	}
	if err = rows.Err(); err != nil {
		return -1, handleError("searchNotificationLayerIntroducingVulnerability.Rows()", err)
	}

	size := limit
	if len(layers) < limit {
		size = len(layers)
	}
	vulnerability.LayersIntroducingVulnerability = layers[:size]

	nextID := -1
	if len(layers) > limit {
		nextID = layers[limit].ID
	}

	return nextID, nil
}

func (pgSQL *pgSQL) SetNotificationNotified(name string) error {
	defer observeQueryTime("SetNotificationNotified", "all", time.Now())

	if _, err := pgSQL.Exec(updatedNotificationNotified, name); err != nil {
		return handleError("updatedNotificationNotified", err)
	}
	return nil
}

func (pgSQL *pgSQL) DeleteNotification(name string) error {
	defer observeQueryTime("DeleteNotification", "all", time.Now())

	result, err := pgSQL.Exec(removeNotification, name)
	if err != nil {
		return handleError("removeNotification", err)
	}

	affected, err := result.RowsAffected()
	if err != nil {
		return handleError("removeNotification.RowsAffected()", err)
	}

	if affected <= 0 {
		return cerrors.ErrNotFound
	}

	return nil
}
<|endoftext|>


<commit_before>package action

import (
	"context"
	"fmt"

	"github.com/gopasspw/gopass/pkg/notify"
	"github.com/gopasspw/gopass/pkg/out"
	"github.com/gopasspw/gopass/pkg/store"

	"github.com/fatih/color"
	"github.com/pkg/errors"
	"github.com/urfave/cli"
)

// Sync all stores with their remotes
func (s *Action) Sync(ctx context.Context, c *cli.Context) error {
	store := c.String("store")
	return s.sync(ctx, c, store)
}

func (s *Action) sync(ctx context.Context, c *cli.Context, store string) error {
	out.Green(ctx, "Sync starting ...")

	numEntries := 0
	if l, err := s.Store.Tree(ctx); err == nil {
		numEntries = len(l.List(0))
	}
	numMPs := 0

	mps := s.Store.MountPoints()
	mps = append([]string{""}, mps...)

	// sync all stores (root and all mounted sub stores)
	for _, mp := range mps {
		if store != "" {
			if store != "root" && mp != store {
				continue
			}
			if store == "root" && mp != "" {
				continue
			}
		}

		numMPs++
		_ = s.syncMount(ctx, mp)
	}
	out.Green(ctx, "All done")

	// calculate number of changes entries
	if l, err := s.Store.Tree(ctx); err == nil {
		numEntries = len(l.List(0)) - numEntries
	}
	diff := ""
	if numEntries > 0 {
		diff = fmt.Sprintf(" Added %d entries", numEntries)
	} else if numEntries < 0 {
		diff = fmt.Sprintf(" Removed %d entries", -1*numEntries)
	}
	_ = notify.Notify(ctx, "gopass - sync", fmt.Sprintf("Finished. Synced %d remotes.%s", numMPs, diff))

	return nil
}

// syncMount syncs a single mount
func (s *Action) syncMount(ctx context.Context, mp string) error {
	ctxno := out.WithNewline(ctx, false)
	name := mp
	if mp == "" {
		name = "<root>"
	}
	out.Print(ctxno, color.GreenString("[%s] ", name))

	sub, err := s.Store.GetSubStore(mp)
	if err != nil {
		out.Red(ctx, "Failed to get sub store '%s': %s", name, err)
		return fmt.Errorf("failed to get sub stores (%s)", err)
	}

	if sub == nil {
		out.Red(ctx, "Failed to get sub stores '%s: nil'", name)
		return fmt.Errorf("failed to get sub stores (nil)")
	}

	numMP := 0
	if l, err := sub.List(ctx, ""); err == nil {
		numMP = len(l)
	}

	out.Print(ctxno, "\n   "+color.GreenString("git pull and push ... "))
	if err := sub.RCS().Push(ctx, "", ""); err != nil {
		if errors.Cause(err) == store.ErrGitNoRemote {
			out.Yellow(ctx, "Skipped (no remote)")
			out.Debug(ctx, "Failed to push '%s' to it's remote: %s", name, err)
			return err
		}

		out.Red(ctx, "Failed to push '%s' to it's remote: %s", name, err)
		return err
	}
	out.Print(ctxno, color.GreenString("OK"))

	if l, err := sub.List(ctx, ""); err == nil {
		diff := len(l) - numMP
		if diff > 0 {
			out.Print(ctxno, color.GreenString(" (Added %d entries)", diff))
		} else if diff < 0 {
			out.Print(ctxno, color.GreenString(" (Removed %d entries)", -1*diff))
		} else {
			out.Print(ctxno, color.GreenString(" (no changes)"))
		}
	}

	// import keys
	out.Print(ctxno, "\n   "+color.GreenString("importing missing keys ... "))
	if err := sub.ImportMissingPublicKeys(ctx); err != nil {
		out.Red(ctx, "Failed to import missing public keys for '%s': %s", name, err)
		return err
	}
	out.Print(ctxno, color.GreenString("OK"))

	// export keys
	out.Print(ctxno, "\n   "+color.GreenString("exporting missing keys ... "))
	rs, err := sub.GetRecipients(ctx, "")
	if err != nil {
		out.Red(ctx, "Failed to load recipients for '%s': %s", name, err)
		return err
	}
	exported, err := sub.ExportMissingPublicKeys(ctx, rs)
	if err != nil {
		out.Red(ctx, "Failed to export missing public keys for '%s': %s", name, err)
		return err
	}

	// only run second push if we did export any keys
	if exported {
		if err := sub.RCS().Push(ctx, "", ""); err != nil {
			out.Red(ctx, "Failed to push '%s' to it's remote: %s", name, err)
			return err
		}
		out.Print(ctxno, color.GreenString("OK"))
	} else {
		out.Print(ctxno, color.GreenString("nothing to do"))
	}
	out.Print(ctx, "\n   "+color.GreenString("done"))
	return nil
}
<commit_msg>Warn if RCS backend is noop on sync (#825)<commit_after>package action

import (
	"context"
	"fmt"

	"github.com/gopasspw/gopass/pkg/backend/rcs/noop"
	"github.com/gopasspw/gopass/pkg/notify"
	"github.com/gopasspw/gopass/pkg/out"
	"github.com/gopasspw/gopass/pkg/store"

	"github.com/fatih/color"
	"github.com/pkg/errors"
	"github.com/urfave/cli"
)

// Sync all stores with their remotes
func (s *Action) Sync(ctx context.Context, c *cli.Context) error {
	store := c.String("store")
	return s.sync(ctx, c, store)
}

func (s *Action) sync(ctx context.Context, c *cli.Context, store string) error {
	out.Green(ctx, "Sync starting ...")

	numEntries := 0
	if l, err := s.Store.Tree(ctx); err == nil {
		numEntries = len(l.List(0))
	}
	numMPs := 0

	mps := s.Store.MountPoints()
	mps = append([]string{""}, mps...)

	// sync all stores (root and all mounted sub stores)
	for _, mp := range mps {
		if store != "" {
			if store != "root" && mp != store {
				continue
			}
			if store == "root" && mp != "" {
				continue
			}
		}

		numMPs++
		_ = s.syncMount(ctx, mp)
	}
	out.Green(ctx, "All done")

	// calculate number of changes entries
	if l, err := s.Store.Tree(ctx); err == nil {
		numEntries = len(l.List(0)) - numEntries
	}
	diff := ""
	if numEntries > 0 {
		diff = fmt.Sprintf(" Added %d entries", numEntries)
	} else if numEntries < 0 {
		diff = fmt.Sprintf(" Removed %d entries", -1*numEntries)
	}
	_ = notify.Notify(ctx, "gopass - sync", fmt.Sprintf("Finished. Synced %d remotes.%s", numMPs, diff))

	return nil
}

// syncMount syncs a single mount
func (s *Action) syncMount(ctx context.Context, mp string) error {
	ctxno := out.WithNewline(ctx, false)
	name := mp
	if mp == "" {
		name = "<root>"
	}
	out.Print(ctxno, color.GreenString("[%s] ", name))

	sub, err := s.Store.GetSubStore(mp)
	if err != nil {
		out.Red(ctx, "Failed to get sub store '%s': %s", name, err)
		return fmt.Errorf("failed to get sub stores (%s)", err)
	}

	if sub == nil {
		out.Red(ctx, "Failed to get sub stores '%s: nil'", name)
		return fmt.Errorf("failed to get sub stores (nil)")
	}

	numMP := 0
	if l, err := sub.List(ctx, ""); err == nil {
		numMP = len(l)
	}

	if sub.RCS().Name() == noop.New().Name() {
		out.Red(ctxno, "\n   WARNING: Mount uses noop RCS backend. Not syncing!")
	}

	out.Print(ctxno, "\n   "+color.GreenString("git pull and push ... "))
	if err := sub.RCS().Push(ctx, "", ""); err != nil {
		if errors.Cause(err) == store.ErrGitNoRemote {
			out.Yellow(ctx, "Skipped (no remote)")
			out.Debug(ctx, "Failed to push '%s' to it's remote: %s", name, err)
			return err
		}

		out.Red(ctx, "Failed to push '%s' to it's remote: %s", name, err)
		return err
	}
	out.Print(ctxno, color.GreenString("OK"))

	if l, err := sub.List(ctx, ""); err == nil {
		diff := len(l) - numMP
		if diff > 0 {
			out.Print(ctxno, color.GreenString(" (Added %d entries)", diff))
		} else if diff < 0 {
			out.Print(ctxno, color.GreenString(" (Removed %d entries)", -1*diff))
		} else {
			out.Print(ctxno, color.GreenString(" (no changes)"))
		}
	}

	// import keys
	out.Print(ctxno, "\n   "+color.GreenString("importing missing keys ... "))
	if err := sub.ImportMissingPublicKeys(ctx); err != nil {
		out.Red(ctx, "Failed to import missing public keys for '%s': %s", name, err)
		return err
	}
	out.Print(ctxno, color.GreenString("OK"))

	// export keys
	out.Print(ctxno, "\n   "+color.GreenString("exporting missing keys ... "))
	rs, err := sub.GetRecipients(ctx, "")
	if err != nil {
		out.Red(ctx, "Failed to load recipients for '%s': %s", name, err)
		return err
	}
	exported, err := sub.ExportMissingPublicKeys(ctx, rs)
	if err != nil {
		out.Red(ctx, "Failed to export missing public keys for '%s': %s", name, err)
		return err
	}

	// only run second push if we did export any keys
	if exported {
		if err := sub.RCS().Push(ctx, "", ""); err != nil {
			out.Red(ctx, "Failed to push '%s' to it's remote: %s", name, err)
			return err
		}
		out.Print(ctxno, color.GreenString("OK"))
	} else {
		out.Print(ctxno, color.GreenString("nothing to do"))
	}
	out.Print(ctx, "\n   "+color.GreenString("done"))
	return nil
}
<|endoftext|>


<commit_before>// Copyright (c) 2014 The btcsuite developers
// Copyright (c) 2015-2016 The Decred developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.

package chaincfg

// BlockOneLedgerMainNet is the block one output ledger for the main
// network.
var BlockOneLedgerMainNet = []*TokenPayout{
	{"HsMNycPD277U4Zw2qNHNqY8r3MSsnhhiiGW", 10000 * 1e8}, //wancc
	{"HsN4DLc5n7kKyfUMKm5SW56J8LJGTK6u91h", 10000 * 1e8}, //fanlq
	{"HsF4tYLz9JpUFk9aPLC7U2AN8Deq6LkyoWc", 10000 * 1e8}, //shanyl
	{"HsZKbCUvcpjfHAJpDfWikD7E2oXUGR4ge6q", 10000 * 1e8}, //panc
	{"HsNu7JN9SeNb3cH7BJWMiSSpPqY6rz8BSXW", 10000 * 1e8}, //guxy
	{"HsC2xCjKQTDBQZUGXUevZTrWYZZC4J1aNJk", 10000 * 1e8}, //dengcg
	{"HsLwT4E2ZdqMDwtrtaQKqp98wVaHrJfyEYM", 10000 * 1e8}, //lixm
	{"HsS6Hqt7yB5Fr2HDBz5gRhK75q7ciuxa7au", 10000 * 1e8}, //yaoyq
}

// BlockOneLedgerTestNet is the block one output ledger for the test
// network.
var BlockOneLedgerTestNet = []*TokenPayout{
}

// BlockOneLedgerTestNet2 is the block one output ledger for the 2nd test
// network.
var BlockOneLedgerTestNet2 = []*TokenPayout{
}

// BlockOneLedgerSimNet is the block one output ledger for the simulation
// network. See under "Hypercash organization related parameters" in params.go
// for information on how to spend these outputs.
var BlockOneLedgerSimNet = []*TokenPayout{
}
<commit_msg>update premine address<commit_after>// Copyright (c) 2014 The btcsuite developers
// Copyright (c) 2015-2016 The Decred developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.

package chaincfg

// BlockOneLedgerMainNet is the block one output ledger for the main
// network.
var BlockOneLedgerMainNet = []*TokenPayout{
	{"HsMNycPD277U4Zw2qNHNqY8r3MSsnhhiiGW", 10000 * 1e8}, //wancc
	{"HsN4DLc5n7kKyfUMKm5SW56J8LJGTK6u91h", 10000 * 1e8}, //fanlq
	{"HsF4tYLz9JpUFk9aPLC7U2AN8Deq6LkyoWc", 10000 * 1e8}, //shanyl
	{"HsZKbCUvcpjfHAJpDfWikD7E2oXUGR4ge6q", 10000 * 1e8}, //panc
	{"HsNu7JN9SeNb3cH7BJWMiSSpPqY6rz8BSXW", 10000 * 1e8}, //guxy
	{"HsamDEnZXPRczM4tNTrKbvUZA8fUSe2TqPk", 10000 * 1e8}, //dengcg
	{"HsLwT4E2ZdqMDwtrtaQKqp98wVaHrJfyEYM", 10000 * 1e8}, //lixm
	{"HsS6Hqt7yB5Fr2HDBz5gRhK75q7ciuxa7au", 10000 * 1e8}, //yaoyq
}

// BlockOneLedgerTestNet is the block one output ledger for the test
// network.
var BlockOneLedgerTestNet = []*TokenPayout{
}

// BlockOneLedgerTestNet2 is the block one output ledger for the 2nd test
// network.
var BlockOneLedgerTestNet2 = []*TokenPayout{
}

// BlockOneLedgerSimNet is the block one output ledger for the simulation
// network. See under "Hypercash organization related parameters" in params.go
// for information on how to spend these outputs.
var BlockOneLedgerSimNet = []*TokenPayout{
}
<|endoftext|>


<commit_before>// Copyright 2018 The Terraformer 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 terraform_utils

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

	"github.com/hashicorp/hcl/hcl/ast"
	hcl_printer "github.com/hashicorp/hcl/hcl/printer"
	hcl_parcer "github.com/hashicorp/hcl/json/parser"
)

// Copy code from https://github.com/kubernetes/kops project with few changes for support many provider and heredoc

const safeChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_"

// sanitizer fixes up an invalid HCL AST, as produced by the HCL parser for JSON
type astSanitizer struct{}

// output prints creates b printable HCL output and returns it.
func (v *astSanitizer) visit(n interface{}) {
	switch t := n.(type) {
	case *ast.File:
		v.visit(t.Node)
	case *ast.ObjectList:
		var index int
		for {
			if index == len(t.Items) {
				break
			}
			v.visit(t.Items[index])
			index++
		}
	case *ast.ObjectKey:
	case *ast.ObjectItem:
		v.visitObjectItem(t)
	case *ast.LiteralType:
	case *ast.ListType:
	case *ast.ObjectType:
		v.visit(t.List)
	default:
		fmt.Printf(" unknown type: %T\n", n)
	}

}

func (v *astSanitizer) visitObjectItem(o *ast.ObjectItem) {
	for i, k := range o.Keys {
		if i == 0 {
			text := k.Token.Text
			if text != "" && text[0] == '"' && text[len(text)-1] == '"' {
				v := text[1 : len(text)-1]
				safe := true
				for _, c := range v {
					if !strings.ContainsRune(safeChars, c) {
						safe = false
						break
					}
				}
				if safe {
					k.Token.Text = v
				}
			}
		}
	}
	switch t := o.Val.(type) {
	case *ast.LiteralType: // heredoc support
		if strings.HasPrefix(t.Token.Text, `"<<`) {
			t.Token.Text = t.Token.Text[1:]
			t.Token.Text = t.Token.Text[:len(t.Token.Text)-1]
			t.Token.Text = strings.Replace(t.Token.Text, `\n`, "\n", -1)
			t.Token.Text = strings.Replace(t.Token.Text, `\t`, "", -1)
			t.Token.Type = 10
			// check if text json for Unquote and Indent
			tmp := map[string]interface{}{}
			jsonTest := t.Token.Text
			lines := strings.Split(jsonTest, "\n")
			jsonTest = strings.Join(lines[1:len(lines)-1], "\n")
			jsonTest = strings.Replace(jsonTest, "\\\"", "\"", -1)
			// it's json we convert to heredoc back
			err := json.Unmarshal([]byte(jsonTest), &tmp)
			if err == nil {
				dataJsonBytes, err := json.MarshalIndent(tmp, "", "  ")
				if err == nil {
					jsonData := strings.Split(string(dataJsonBytes), "\n")
					// first line for heredoc
					jsonData = append([]string{lines[0]}, jsonData...)
					// last line for heredoc
					jsonData = append(jsonData, lines[len(lines)-1])
					hereDoc := strings.Join(jsonData, "\n")
					t.Token.Text = hereDoc
				}
			}
		}
	default:
	}

	// A hack so that Assign.IsValid is true, so that the printer will output =
	o.Assign.Line = 1

	v.visit(o.Val)
}

func HclPrint(data interface{}) ([]byte, error) {
	dataJsonBytes, err := json.MarshalIndent(data, "", "  ")
	dataJson := string(dataJsonBytes)
	dataJson = strings.Replace(dataJson, "\\u003c", "<", -1)
	if err != nil {
		return []byte{}, fmt.Errorf("error marshalling terraform data to json: %v", err)
	}
	nodes, err := hcl_parcer.Parse([]byte(dataJson))
	if err != nil {
		return []byte{}, fmt.Errorf("error parsing terraform json: %v", err)
	}
	var sanitizer astSanitizer
	sanitizer.visit(nodes)

	var b bytes.Buffer
	err = hcl_printer.Fprint(&b, nodes)
	if err != nil {
		return nil, fmt.Errorf("error writing HCL: %v", err)
	}
	s := b.String()

	// Remove extra whitespace...
	s = strings.Replace(s, "\n\n", "\n", -1)

	// ...but leave whitespace between resources
	s = strings.Replace(s, "}\nresource", "}\n\nresource", -1)

	// We don't need to escape > or <
	s = strings.Replace(s, "\\u003c", "<", -1)
	s = strings.Replace(s, "\\u003e", ">", -1)

	// Apply Terraform style (alignment etc.)
	formatted, err := hcl_printer.Format([]byte(s))
	if err != nil {
		log.Println("Invalid HCL follows:")
		for i, line := range strings.Split(s, "\n") {
			fmt.Printf("%d\t%s", i+1, line)
		}
		return nil, fmt.Errorf("error formatting HCL: %v", err)
	}

	return formatted, nil
}

// Sanitize name for terraform style
func TfSanitize(name string) string {
	name = strings.Replace(name, "*.", "", -1)
	name = strings.Replace(name, "-", "_", -1)
	name = strings.Replace(name, ".", "-", -1)
	name = strings.Replace(name, "/", "--", -1)
	return name
}

// Print hcl file from TerraformResource + provider
func HclPrintResource(resources []Resource, providerData map[string]interface{}) ([]byte, error) {
	resourcesByType := map[string]map[string]interface{}{}

	for _, res := range resources {

		r := resourcesByType[res.InstanceInfo.Type]
		if r == nil {
			r = make(map[string]interface{})
			resourcesByType[res.InstanceInfo.Type] = r
		}

		if r[res.ResourceName] != nil {
			return []byte{}, fmt.Errorf("[ERR]: duplicate resource found: %s.%s", res.InstanceInfo.Type, res.ResourceName)
		}

		r[res.ResourceName] = res.Item
	}

	data := map[string]interface{}{}
	if len(resourcesByType) > 0 {
		data["resource"] = resourcesByType
	}
	if len(providerData) > 0 {
		data["provider"] = providerData
	}
	var err error

	hclBytes, err := HclPrint(data)
	if err != nil {
		return []byte{}, err
	}
	return hclBytes, nil
}
<commit_msg>add support terraform 0.12 hcl files<commit_after>// Copyright 2018 The Terraformer 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 terraform_utils

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

	"github.com/hashicorp/hcl/hcl/ast"
	hcl_printer "github.com/hashicorp/hcl/hcl/printer"
	hcl_parcer "github.com/hashicorp/hcl/json/parser"
)

// Copy code from https://github.com/kubernetes/kops project with few changes for support many provider and heredoc

const safeChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_"

// sanitizer fixes up an invalid HCL AST, as produced by the HCL parser for JSON
type astSanitizer struct{}

// output prints creates b printable HCL output and returns it.
func (v *astSanitizer) visit(n interface{}) {
	switch t := n.(type) {
	case *ast.File:
		v.visit(t.Node)
	case *ast.ObjectList:
		var index int
		for {
			if index == len(t.Items) {
				break
			}
			v.visit(t.Items[index])
			index++
		}
	case *ast.ObjectKey:
	case *ast.ObjectItem:
		v.visitObjectItem(t)
	case *ast.LiteralType:
	case *ast.ListType:
	case *ast.ObjectType:
		v.visit(t.List)
	default:
		fmt.Printf(" unknown type: %T\n", n)
	}

}

func (v *astSanitizer) visitObjectItem(o *ast.ObjectItem) {
	for i, k := range o.Keys {
		if i == 0 {
			text := k.Token.Text
			if text != "" && text[0] == '"' && text[len(text)-1] == '"' {
				v := text[1 : len(text)-1]
				safe := true
				for _, c := range v {
					if !strings.ContainsRune(safeChars, c) {
						safe = false
						break
					}
				}
				if safe {
					k.Token.Text = v
				}
			}
		}
	}
	switch t := o.Val.(type) {
	case *ast.LiteralType: // heredoc support
		if strings.HasPrefix(t.Token.Text, `"<<`) {
			t.Token.Text = t.Token.Text[1:]
			t.Token.Text = t.Token.Text[:len(t.Token.Text)-1]
			t.Token.Text = strings.Replace(t.Token.Text, `\n`, "\n", -1)
			t.Token.Text = strings.Replace(t.Token.Text, `\t`, "", -1)
			t.Token.Type = 10
			// check if text json for Unquote and Indent
			tmp := map[string]interface{}{}
			jsonTest := t.Token.Text
			lines := strings.Split(jsonTest, "\n")
			jsonTest = strings.Join(lines[1:len(lines)-1], "\n")
			jsonTest = strings.Replace(jsonTest, "\\\"", "\"", -1)
			// it's json we convert to heredoc back
			err := json.Unmarshal([]byte(jsonTest), &tmp)
			if err == nil {
				dataJsonBytes, err := json.MarshalIndent(tmp, "", "  ")
				if err == nil {
					jsonData := strings.Split(string(dataJsonBytes), "\n")
					// first line for heredoc
					jsonData = append([]string{lines[0]}, jsonData...)
					// last line for heredoc
					jsonData = append(jsonData, lines[len(lines)-1])
					hereDoc := strings.Join(jsonData, "\n")
					t.Token.Text = hereDoc
				}
			}
		}
	default:
	}

	// A hack so that Assign.IsValid is true, so that the printer will output =
	o.Assign.Line = 1

	v.visit(o.Val)
}

func HclPrint(data interface{}) ([]byte, error) {
	dataJsonBytes, err := json.MarshalIndent(data, "", "  ")
	dataJson := string(dataJsonBytes)
	dataJson = strings.Replace(dataJson, "\\u003c", "<", -1)
	if err != nil {
		return []byte{}, fmt.Errorf("error marshalling terraform data to json: %v", err)
	}
	nodes, err := hcl_parcer.Parse([]byte(dataJson))
	if err != nil {
		return []byte{}, fmt.Errorf("error parsing terraform json: %v", err)
	}
	var sanitizer astSanitizer
	sanitizer.visit(nodes)

	var b bytes.Buffer
	err = hcl_printer.Fprint(&b, nodes)
	if err != nil {
		return nil, fmt.Errorf("error writing HCL: %v", err)
	}
	s := b.String()

	// Remove extra whitespace...
	s = strings.Replace(s, "\n\n", "\n", -1)

	// ...but leave whitespace between resources
	s = strings.Replace(s, "}\nresource", "}\n\nresource", -1)

	// We don't need to escape > or <
	s = strings.Replace(s, "\\u003c", "<", -1)
	s = strings.Replace(s, "\\u003e", ">", -1)
	s = strings.Replace(s, " = {", " {", -1) // hack for terraform 0.12

	// Apply Terraform style (alignment etc.)
	formatted, err := hcl_printer.Format([]byte(s))
	if err != nil {
		log.Println("Invalid HCL follows:")
		for i, line := range strings.Split(s, "\n") {
			fmt.Printf("%d\t%s", i+1, line)
		}
		return nil, fmt.Errorf("error formatting HCL: %v", err)
	}

	return formatted, nil
}

// Sanitize name for terraform style
func TfSanitize(name string) string {
	name = strings.Replace(name, "*.", "", -1)
	name = strings.Replace(name, "-", "_", -1)
	name = strings.Replace(name, ".", "-", -1)
	name = strings.Replace(name, "/", "--", -1)
	return name
}

// Print hcl file from TerraformResource + provider
func HclPrintResource(resources []Resource, providerData map[string]interface{}) ([]byte, error) {
	resourcesByType := map[string]map[string]interface{}{}

	for _, res := range resources {

		r := resourcesByType[res.InstanceInfo.Type]
		if r == nil {
			r = make(map[string]interface{})
			resourcesByType[res.InstanceInfo.Type] = r
		}

		if r[res.ResourceName] != nil {
			return []byte{}, fmt.Errorf("[ERR]: duplicate resource found: %s.%s", res.InstanceInfo.Type, res.ResourceName)
		}

		r[res.ResourceName] = res.Item
	}

	data := map[string]interface{}{}
	if len(resourcesByType) > 0 {
		data["resource"] = resourcesByType
	}
	if len(providerData) > 0 {
		data["provider"] = providerData
	}
	var err error

	hclBytes, err := HclPrint(data)
	if err != nil {
		return []byte{}, err
	}
	return hclBytes, nil
}
<|endoftext|>


<commit_before>package cli

import (
	"crypto/x509"
	"strconv"
	"strings"
	"time"

	"github.com/dcos/dcos-cli/pkg/config"
	"github.com/spf13/afero"
	"github.com/spf13/cast"
)

// Cluster is a subset representation of a DC/OS CLI configuration.
//
// It is a proxy struct on top of a config which provides user-friendly getters and setters for common
// configurations such as "core.dcos_url" or "core.ssl_verify". It leverages Go types as much as possible.
type Cluster struct {
	config *config.Config
}

// NewCluster returns a new cluster for a given config, if omitted it uses an empty config.
func NewCluster(conf *config.Config) *Cluster {
	if conf == nil {
		conf = config.Empty()
	}
	return &Cluster{config: conf}
}

// URL returns the public master URL of the DC/OS cluster.
func (c *Cluster) URL() string {
	url := cast.ToString(c.config.Get("core.dcos_url"))
	return strings.TrimRight(url, "/")
}

// SetURL sets the public master URL of the DC/OS cluster.
func (c *Cluster) SetURL(url string) {
	c.config.Set("core.dcos_url", url)
}

// ACSToken returns the token generated by authenticating
// to DC/OS using the Admin Router Access Control Service.
func (c *Cluster) ACSToken() string {
	return cast.ToString(c.config.Get("core.dcos_acs_token"))
}

// SetACSToken sets the token generated by authenticating
// to DC/OS using the Admin Router Access Control Service.
func (c *Cluster) SetACSToken(acsToken string) {
	c.config.Set("core.dcos_acs_token", acsToken)
}

// TLS returns the configuration for TLS clients.
func (c *Cluster) TLS() TLS {
	tlsVal := cast.ToString(c.config.Get("core.ssl_verify"))

	// Try to cast the value to a bool, true means we verify
	// server certificates, false means we skip verification.
	if verify, err := strconv.ParseBool(tlsVal); err == nil {
		return TLS{Insecure: !verify}
	}

	// The value is not a string representing a bool thus it is a path to a root CA bundle.
	rootCAsPEM, err := afero.ReadFile(c.config.Fs(), tlsVal)
	if err != nil {
		return TLS{
			Insecure:    true,
			RootCAsPath: tlsVal,
		}
	}

	// Decode the PEM root certificate(s) into a cert pool.
	certPool := x509.NewCertPool()
	if !certPool.AppendCertsFromPEM(rootCAsPEM) {
		return TLS{
			Insecure:    true,
			RootCAsPath: tlsVal,
		}
	}

	// The cert pool has been successfully created, store it in the TLS config.
	return TLS{
		RootCAs:     certPool,
		RootCAsPath: tlsVal,
	}
}

// SetTLS returns the configuration for TLS clients.
func (c *Cluster) SetTLS(tls TLS) {
	c.config.Set("core.ssl_verify", tls.String())
}

// Timeout returns the HTTP request timeout once the connection is established.
func (c *Cluster) Timeout() time.Duration {
	timeout := c.config.Get("core.timeout")
	return time.Duration(cast.ToInt64(timeout)) * time.Second
}

// SetTimeout sets the HTTP request timeout once the connection is established.
func (c *Cluster) SetTimeout(timeout time.Duration) {
	c.config.Set("core.timeout", timeout.Seconds())
}

// Name returns the custom name for the cluster.
func (c *Cluster) Name() string {
	return cast.ToString(c.config.Get("cluster.name"))
}

// SetName sets a custom name for the cluster.
func (c *Cluster) SetName(name string) {
	c.config.Set("cluster.name", name)
}

// Config returns the cluster's config.
func (c *Cluster) Config() *config.Config {
	return c.config
}

// TLS holds the configuration for TLS clients.
type TLS struct {
	// Insecure specifies if server certificates should be accepted without verification.
	//
	// Skipping verification against the system's CA bundle or a cluster-specific CA is highly discouraged
	// and should only be done during testing/development.
	Insecure bool

	// Path to the root CA bundle.
	RootCAsPath string

	// A pool of root CAs to verify server certificates against.
	RootCAs *x509.CertPool
}

// String creates a string from a TLS struct.
func (tls *TLS) String() string {
	if tls.RootCAsPath != "" {
		return tls.RootCAsPath
	}
	return strconv.FormatBool(!tls.Insecure)
}
<commit_msg>Add ID() function to Cluster.<commit_after>package cli

import (
	"crypto/x509"
	"path/filepath"
	"strconv"
	"strings"
	"time"

	"github.com/dcos/dcos-cli/pkg/config"
	"github.com/spf13/afero"
	"github.com/spf13/cast"
)

// Cluster is a subset representation of a DC/OS CLI configuration.
//
// It is a proxy struct on top of a config which provides user-friendly getters and setters for common
// configurations such as "core.dcos_url" or "core.ssl_verify". It leverages Go types as much as possible.
type Cluster struct {
	config *config.Config
}

// NewCluster returns a new cluster for a given config, if omitted it uses an empty config.
func NewCluster(conf *config.Config) *Cluster {
	if conf == nil {
		conf = config.Empty()
	}
	return &Cluster{config: conf}
}

// URL returns the public master URL of the DC/OS cluster.
func (c *Cluster) URL() string {
	url := cast.ToString(c.config.Get("core.dcos_url"))
	return strings.TrimRight(url, "/")
}

// SetURL sets the public master URL of the DC/OS cluster.
func (c *Cluster) SetURL(url string) {
	c.config.Set("core.dcos_url", url)
}

// ACSToken returns the token generated by authenticating
// to DC/OS using the Admin Router Access Control Service.
func (c *Cluster) ACSToken() string {
	return cast.ToString(c.config.Get("core.dcos_acs_token"))
}

// SetACSToken sets the token generated by authenticating
// to DC/OS using the Admin Router Access Control Service.
func (c *Cluster) SetACSToken(acsToken string) {
	c.config.Set("core.dcos_acs_token", acsToken)
}

// TLS returns the configuration for TLS clients.
func (c *Cluster) TLS() TLS {
	tlsVal := cast.ToString(c.config.Get("core.ssl_verify"))

	// Try to cast the value to a bool, true means we verify
	// server certificates, false means we skip verification.
	if verify, err := strconv.ParseBool(tlsVal); err == nil {
		return TLS{Insecure: !verify}
	}

	// The value is not a string representing a bool thus it is a path to a root CA bundle.
	rootCAsPEM, err := afero.ReadFile(c.config.Fs(), tlsVal)
	if err != nil {
		return TLS{
			Insecure:    true,
			RootCAsPath: tlsVal,
		}
	}

	// Decode the PEM root certificate(s) into a cert pool.
	certPool := x509.NewCertPool()
	if !certPool.AppendCertsFromPEM(rootCAsPEM) {
		return TLS{
			Insecure:    true,
			RootCAsPath: tlsVal,
		}
	}

	// The cert pool has been successfully created, store it in the TLS config.
	return TLS{
		RootCAs:     certPool,
		RootCAsPath: tlsVal,
	}
}

// SetTLS returns the configuration for TLS clients.
func (c *Cluster) SetTLS(tls TLS) {
	c.config.Set("core.ssl_verify", tls.String())
}

// Timeout returns the HTTP request timeout once the connection is established.
func (c *Cluster) Timeout() time.Duration {
	timeout := c.config.Get("core.timeout")
	return time.Duration(cast.ToInt64(timeout)) * time.Second
}

// SetTimeout sets the HTTP request timeout once the connection is established.
func (c *Cluster) SetTimeout(timeout time.Duration) {
	c.config.Set("core.timeout", timeout.Seconds())
}

// ID returns the ID of the cluster.
func (c *Cluster) ID() string {
	path := c.Config().Path()
	return filepath.Base(filepath.Dir(path))
}

// Name returns the custom name for the cluster.
func (c *Cluster) Name() string {
	return cast.ToString(c.config.Get("cluster.name"))
}

// SetName sets a custom name for the cluster.
func (c *Cluster) SetName(name string) {
	c.config.Set("cluster.name", name)
}

// Config returns the cluster's config.
func (c *Cluster) Config() *config.Config {
	return c.config
}

// TLS holds the configuration for TLS clients.
type TLS struct {
	// Insecure specifies if server certificates should be accepted without verification.
	//
	// Skipping verification against the system's CA bundle or a cluster-specific CA is highly discouraged
	// and should only be done during testing/development.
	Insecure bool

	// Path to the root CA bundle.
	RootCAsPath string

	// A pool of root CAs to verify server certificates against.
	RootCAs *x509.CertPool
}

// String creates a string from a TLS struct.
func (tls *TLS) String() string {
	if tls.RootCAsPath != "" {
		return tls.RootCAsPath
	}
	return strconv.FormatBool(!tls.Insecure)
}
<|endoftext|>


<commit_before>package basic

func init() {
}

func ExportedA() error {
	return nil
}

func ExportedB() error {
	return nil
}

func unexported() error {
	return nil
}
<commit_msg>Add fixtures<commit_after>package basic

func init() {
}

func ExportedA() error {
	return nil
}

func ExportedB() error {
	return nil
}

func ExportedC() error {
	return nil
}

func ExportedD() error {
	return nil
}

func unexported() error {
	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"net/http"
	"testing"
)

// Should send request to origin by default
func TestNoCacheNewRequestOrigin(t *testing.T) {
	uuid := NewUUID()
	originServer.SwitchHandler(func(w http.ResponseWriter, r *http.Request) {
		if r.Method == "GET" && r.URL.Path == fmt.Sprintf("/%s", uuid) {
			w.Header().Set("EnsureOriginServed", uuid)
		}
	})

	sourceUrl := fmt.Sprintf("https://%s/%s", *edgeHost, uuid)

	req, _ := http.NewRequest("GET", sourceUrl, nil)
	resp, err := client.RoundTrip(req)

	if err != nil {
		t.Fatal(err)
	}
	if resp.StatusCode != 200 {
		t.Errorf("Status code expected 200, got %d", resp.StatusCode)
	}
	if d := resp.Header.Get("EnsureOriginServed"); d != uuid {
		t.Errorf("EnsureOriginServed header has not come from Origin: expected %q, got %q", uuid, d)
	}
}

// Should not cache the response to a POST request.
func TestNoCachePOST(t *testing.T) {
	url := fmt.Sprintf("https://%s/%s", *edgeHost, NewUUID())
	req, _ := http.NewRequest("POST", url, nil)

	testThreeRequestsNotCached(t, req, nil)
}

// Should not cache the response to a request with a `Authorization` header.
func TestNoCacheHeaderAuthorization(t *testing.T) {
	url := fmt.Sprintf("https://%s/%s", *edgeHost, NewUUID())
	req, _ := http.NewRequest("GET", url, nil)
	req.Header.Set("Authorization", "Basic YXJlbnR5b3U6aW5xdWlzaXRpdmU=")

	testThreeRequestsNotCached(t, req, nil)
}

// Should not cache the response to a request with a `Cookie` header.
func TestNoCacheHeaderCookie(t *testing.T) {
	t.Error("Not implemented")
}

// Should not cache a response with a `Set-Cookie` header.
func TestNoCacheHeaderSetCookie(t *testing.T) {
	handler := func(h http.Header) {
		h.Set("Set-Cookie", "sekret=mekmitasdigoat")
	}

	url := fmt.Sprintf("https://%s/%s", *edgeHost, NewUUID())
	req, _ := http.NewRequest("GET", url, nil)

	testThreeRequestsNotCached(t, req, handler)
}

// Should not cache a response with a `Cache-Control: private` header.
func TestNoCacheHeaderCacheControlPrivate(t *testing.T) {
	t.Error("Not implemented")
}
<commit_msg>Implement TestNoCacheHeaderCookie<commit_after>package main

import (
	"fmt"
	"net/http"
	"testing"
)

// Should send request to origin by default
func TestNoCacheNewRequestOrigin(t *testing.T) {
	uuid := NewUUID()
	originServer.SwitchHandler(func(w http.ResponseWriter, r *http.Request) {
		if r.Method == "GET" && r.URL.Path == fmt.Sprintf("/%s", uuid) {
			w.Header().Set("EnsureOriginServed", uuid)
		}
	})

	sourceUrl := fmt.Sprintf("https://%s/%s", *edgeHost, uuid)

	req, _ := http.NewRequest("GET", sourceUrl, nil)
	resp, err := client.RoundTrip(req)

	if err != nil {
		t.Fatal(err)
	}
	if resp.StatusCode != 200 {
		t.Errorf("Status code expected 200, got %d", resp.StatusCode)
	}
	if d := resp.Header.Get("EnsureOriginServed"); d != uuid {
		t.Errorf("EnsureOriginServed header has not come from Origin: expected %q, got %q", uuid, d)
	}
}

// Should not cache the response to a POST request.
func TestNoCachePOST(t *testing.T) {
	url := fmt.Sprintf("https://%s/%s", *edgeHost, NewUUID())
	req, _ := http.NewRequest("POST", url, nil)

	testThreeRequestsNotCached(t, req, nil)
}

// Should not cache the response to a request with a `Authorization` header.
func TestNoCacheHeaderAuthorization(t *testing.T) {
	url := fmt.Sprintf("https://%s/%s", *edgeHost, NewUUID())
	req, _ := http.NewRequest("GET", url, nil)
	req.Header.Set("Authorization", "Basic YXJlbnR5b3U6aW5xdWlzaXRpdmU=")

	testThreeRequestsNotCached(t, req, nil)
}

// Should not cache the response to a request with a `Cookie` header.
func TestNoCacheHeaderCookie(t *testing.T) {
	url := fmt.Sprintf("https://%s/%s", *edgeHost, NewUUID())
	req, _ := http.NewRequest("GET", url, nil)
	req.Header.Set("Cookie", "sekret=mekmitasdigoat")

	testThreeRequestsNotCached(t, req, nil)
}

// Should not cache a response with a `Set-Cookie` header.
func TestNoCacheHeaderSetCookie(t *testing.T) {
	handler := func(h http.Header) {
		h.Set("Set-Cookie", "sekret=mekmitasdigoat")
	}

	url := fmt.Sprintf("https://%s/%s", *edgeHost, NewUUID())
	req, _ := http.NewRequest("GET", url, nil)

	testThreeRequestsNotCached(t, req, handler)
}

// Should not cache a response with a `Cache-Control: private` header.
func TestNoCacheHeaderCacheControlPrivate(t *testing.T) {
	t.Error("Not implemented")
}
<|endoftext|>