<commit_before>// Copyright © 2016 The Things Network
// Use of this source code is governed by the MIT license that can be found in the LICENSE file.

package handler

import (
	"fmt"
	"reflect"
	"time"

	pb_broker "github.com/TheThingsNetwork/ttn/api/broker"
	"github.com/TheThingsNetwork/ttn/core/types"
	"github.com/TheThingsNetwork/ttn/utils/errors"
	"github.com/apex/log"
	"github.com/robertkrimen/otto"
)

// ConvertFieldsUp converts the payload to fields using payload functions
func (h *handler) ConvertFieldsUp(ctx log.Interface, ttnUp *pb_broker.DeduplicatedUplinkMessage, appUp *types.UplinkMessage) error {
	// Find Application
	app, err := h.applications.Get(ttnUp.AppId)
	if err != nil {
		return nil // Do not process if application not found
	}

	functions := &UplinkFunctions{
		Decoder:   app.Decoder,
		Converter: app.Converter,
		Validator: app.Validator,
	}

	fields, valid, err := functions.Process(appUp.PayloadRaw, appUp.FPort)
	if err != nil {
		return nil // Do not set fields if processing failed
	}

	if !valid {
		return errors.NewErrInvalidArgument("Payload", "payload validator function returned false")
	}

	appUp.PayloadFields = fields

	return nil
}

// UplinkFunctions decodes, converts and validates payload using JavaScript functions
type UplinkFunctions struct {
	// Decoder is a JavaScript function that accepts the payload as byte array and
	// returns an object containing the decoded values
	Decoder string
	// Converter is a JavaScript function that accepts the data as decoded by
	// Decoder and returns an object containing the converted values
	Converter string
	// Validator is a JavaScript function that validates the data is converted by
	// Converter and returns a boolean value indicating the validity of the data
	Validator string
}

// timeOut is the maximum allowed time a payload function is allowed to run
var timeOut = 100 * time.Millisecond

// Decode decodes the payload using the Decoder function into a map
func (f *UplinkFunctions) Decode(payload []byte, port uint8) (map[string]interface{}, error) {
	if f.Decoder == "" {
		return nil, errors.NewErrInternal("Decoder function not set")
	}

	vm := otto.New()
	vm.Set("payload", payload)
	vm.Set("port", port)
	value, err := runUnsafeCode(vm, fmt.Sprintf("(%s)(payload.slice(0), port)", f.Decoder), timeOut)
	if err != nil {
		return nil, err
	}

	if !value.IsObject() {
		return nil, errors.NewErrInvalidArgument("Decoder", "does not return an object")
	}

	v, _ := value.Export()
	m, ok := v.(map[string]interface{})
	if !ok {
		return nil, errors.NewErrInvalidArgument("Decoder", "does not return an object")
	}
	return m, nil
}

// Convert converts the values in the specified map to a another map using the
// Converter function. If the Converter function is not set, this function
// returns the data as-is
func (f *UplinkFunctions) Convert(data map[string]interface{}, port uint8) (map[string]interface{}, error) {
	if f.Converter == "" {
		return data, nil
	}

	vm := otto.New()
	vm.Set("data", data)
	vm.Set("port", port)
	value, err := runUnsafeCode(vm, fmt.Sprintf("(%s)(data, port)", f.Converter), timeOut)
	if err != nil {
		return nil, err
	}

	if !value.IsObject() {
		return nil, errors.NewErrInvalidArgument("Converter", "does not return an object")
	}

	v, _ := value.Export()
	m, ok := v.(map[string]interface{})
	if !ok {
		return nil, errors.NewErrInvalidArgument("Converter", "does not return an object")
	}

	return m, nil
}

// Validate validates the values in the specified map using the Validator
// function. If the Validator function is not set, this function returns true
func (f *UplinkFunctions) Validate(data map[string]interface{}, port uint8) (bool, error) {
	if f.Validator == "" {
		return true, nil
	}

	vm := otto.New()
	vm.Set("data", data)
	vm.Set("port", port)
	value, err := runUnsafeCode(vm, fmt.Sprintf("(%s)(data, port)", f.Validator), timeOut)
	if err != nil {
		return false, err
	}

	if !value.IsBoolean() {
		return false, errors.NewErrInvalidArgument("Validator", "does not return a boolean")
	}

	return value.ToBoolean()
}

// Process decodes the specified payload, converts it and test the validity
func (f *UplinkFunctions) Process(payload []byte, port uint8) (map[string]interface{}, bool, error) {
	decoded, err := f.Decode(payload, port)
	if err != nil {
		return nil, false, err
	}

	converted, err := f.Convert(decoded, port)
	if err != nil {
		return nil, false, err
	}

	valid, err := f.Validate(converted, port)
	return converted, valid, err
}

var errTimeOutExceeded = errors.NewErrInternal("Code has been running to long")

func runUnsafeCode(vm *otto.Otto, code string, timeOut time.Duration) (value otto.Value, err error) {
	start := time.Now()
	defer func() {
		duration := time.Since(start)
		if caught := recover(); caught != nil {
			if caught == errTimeOutExceeded {
				value = otto.Value{}
				err = errors.NewErrInternal(fmt.Sprintf("Interrupted javascript execution after %v", duration))
				return
			}
			// if this is not the our timeout interrupt, raise the panic again
			// so someone else can handle it
			panic(caught)
		}
	}()

	vm.Interrupt = make(chan func(), 1)

	go func() {
		time.Sleep(timeOut)
		vm.Interrupt <- func() {
			panic(errTimeOutExceeded)
		}
	}()
	return vm.Run(code)
}

// DownlinkFunctions encodes payload using JavaScript functions
type DownlinkFunctions struct {
	// Encoder is a JavaScript function that accepts the payload as JSON and
	// returns an array of bytes
	Encoder string
}

// Encode encodes the map into a byte slice using the encoder payload function
// If no encoder function is set, this function returns an array.
func (f *DownlinkFunctions) Encode(payload map[string]interface{}, port uint8) ([]byte, error) {
	if f.Encoder == "" {
		return nil, errors.NewErrInternal("Encoder function not set")
	}

	vm := otto.New()
	vm.Set("payload", payload)
	vm.Set("port", port)
	value, err := runUnsafeCode(vm, fmt.Sprintf("(%s)(payload, port)", f.Encoder), timeOut)
	if err != nil {
		return nil, err
	}

	if !value.IsObject() {
		return nil, errors.NewErrInvalidArgument("Encoder", "does not return an object")
	}

	v, err := value.Export()
	if err != nil {
		return nil, err
	}

	if reflect.TypeOf(v).Kind() != reflect.Slice {
		return nil, errors.NewErrInvalidArgument("Encoder", "does not return an Array")
	}

	s := reflect.ValueOf(v)
	l := s.Len()

	res := make([]byte, l)

	var n int64
	for i := 0; i < l; i++ {
		el := s.Index(i).Interface()

		// type switch does not have fallthrough so we need
		// to check every element individually
		switch t := el.(type) {
		case byte:
			n = int64(t)
		case int:
			n = int64(t)
		case int8:
			n = int64(t)
		case int16:
			n = int64(t)
		case uint16:
			n = int64(t)
		case int32:
			n = int64(t)
		case uint32:
			n = int64(t)
		case int64:
			n = int64(t)
		case uint64:
			n = int64(t)
		case float32:
			n = int64(t)
			if float32(n) != t {
				return nil, errors.NewErrInvalidArgument("Encoder", "should return an Array of integer numbers")
			}
		case float64:
			n = int64(t)
			if float64(n) != t {
				return nil, errors.NewErrInvalidArgument("Encoder", "should return an Array of integer numbers")
			}
		default:
			return nil, errors.NewErrInvalidArgument("Encoder", "should return an Array of integer numbers")
		}

		if n < 0 || n > 255 {
			return nil, errors.NewErrInvalidArgument("Encoder Output", "Numbers in Array should be between 0 and 255")
		}

		res[i] = byte(n)
	}

	return res, nil
}

// Process encode the specified field, converts it into a valid payload
func (f *DownlinkFunctions) Process(payload map[string]interface{}, port uint8) ([]byte, bool, error) {
	encoded, err := f.Encode(payload, port)
	if err != nil {
		return nil, false, err
	}

	return encoded, true, nil
}

// ConvertFieldsDown converts the fields into a payload
func (h *handler) ConvertFieldsDown(ctx log.Interface, appDown *types.DownlinkMessage, ttnDown *pb_broker.DownlinkMessage) error {
	if appDown.PayloadFields == nil {
		return nil
	}

	if appDown.PayloadRaw != nil {
		return errors.NewErrInvalidArgument("Downlink", "Both Fields and Payload provided")
	}

	app, err := h.applications.Get(appDown.AppID)
	if err != nil {
		return nil
	}

	functions := &DownlinkFunctions{
		Encoder: app.Encoder,
	}

	message, _, err := functions.Process(appDown.PayloadFields, appDown.FPort)
	if err != nil {
		return err
	}

	appDown.PayloadRaw = message

	return nil
}
<commit_msg>Use logger when process payloads<commit_after>// Copyright © 2016 The Things Network
// Use of this source code is governed by the MIT license that can be found in the LICENSE file.

package handler

import (
	"fmt"
	"reflect"
	"time"

	pb_broker "github.com/TheThingsNetwork/ttn/api/broker"
	"github.com/TheThingsNetwork/ttn/core/types"
	"github.com/TheThingsNetwork/ttn/utils/errors"
	"github.com/apex/log"
	"github.com/robertkrimen/otto"
)

// ConvertFieldsUp converts the payload to fields using payload functions
func (h *handler) ConvertFieldsUp(ctx log.Interface, ttnUp *pb_broker.DeduplicatedUplinkMessage, appUp *types.UplinkMessage) error {
	// Find Application
	app, err := h.applications.Get(ttnUp.AppId)
	if err != nil {
		return nil // Do not process if application not found
	}

	functions := &UplinkFunctions{
		Decoder:   app.Decoder,
		Converter: app.Converter,
		Validator: app.Validator,
		Logger:    &ignore{},
	}

	fields, valid, err := functions.Process(appUp.PayloadRaw, appUp.FPort)
	if err != nil {
		return nil // Do not set fields if processing failed
	}

	if !valid {
		return errors.NewErrInvalidArgument("Payload", "payload validator function returned false")
	}

	appUp.PayloadFields = fields

	return nil
}

// UplinkFunctions decodes, converts and validates payload using JavaScript functions
type UplinkFunctions struct {
	// Decoder is a JavaScript function that accepts the payload as byte array and
	// returns an object containing the decoded values
	Decoder string
	// Converter is a JavaScript function that accepts the data as decoded by
	// Decoder and returns an object containing the converted values
	Converter string
	// Validator is a JavaScript function that validates the data is converted by
	// Converter and returns a boolean value indicating the validity of the data
	Validator string

	// Logger is the logger that will be used to store logs
	Logger Logger
}

// timeOut is the maximum allowed time a payload function is allowed to run
var timeOut = 100 * time.Millisecond

// Decode decodes the payload using the Decoder function into a map
func (f *UplinkFunctions) Decode(payload []byte, port uint8) (map[string]interface{}, error) {
	if f.Decoder == "" {
		return nil, errors.NewErrInternal("Decoder function not set")
	}

	vm := otto.New()
	vm.Set("payload", payload)
	vm.Set("port", port)
	value, err := runUnsafeCodeWithLogger(vm, fmt.Sprintf("(%s)(payload.slice(0), port)", f.Decoder), timeOut, f.Logger)
	if err != nil {
		return nil, err
	}

	if !value.IsObject() {
		return nil, errors.NewErrInvalidArgument("Decoder", "does not return an object")
	}

	v, _ := value.Export()
	m, ok := v.(map[string]interface{})
	if !ok {
		return nil, errors.NewErrInvalidArgument("Decoder", "does not return an object")
	}
	return m, nil
}

// Convert converts the values in the specified map to a another map using the
// Converter function. If the Converter function is not set, this function
// returns the data as-is
func (f *UplinkFunctions) Convert(data map[string]interface{}, port uint8) (map[string]interface{}, error) {
	if f.Converter == "" {
		return data, nil
	}

	vm := otto.New()
	vm.Set("data", data)
	vm.Set("port", port)
	value, err := runUnsafeCodeWithLogger(vm, fmt.Sprintf("(%s)(data, port)", f.Converter), timeOut, f.Logger)
	if err != nil {
		return nil, err
	}

	if !value.IsObject() {
		return nil, errors.NewErrInvalidArgument("Converter", "does not return an object")
	}

	v, _ := value.Export()
	m, ok := v.(map[string]interface{})
	if !ok {
		return nil, errors.NewErrInvalidArgument("Converter", "does not return an object")
	}

	return m, nil
}

// Validate validates the values in the specified map using the Validator
// function. If the Validator function is not set, this function returns true
func (f *UplinkFunctions) Validate(data map[string]interface{}, port uint8) (bool, error) {
	if f.Validator == "" {
		return true, nil
	}

	vm := otto.New()
	vm.Set("data", data)
	vm.Set("port", port)
	value, err := runUnsafeCodeWithLogger(vm, fmt.Sprintf("(%s)(data, port)", f.Validator), timeOut, f.Logger)
	if err != nil {
		return false, err
	}

	if !value.IsBoolean() {
		return false, errors.NewErrInvalidArgument("Validator", "does not return a boolean")
	}

	return value.ToBoolean()
}

// Process decodes the specified payload, converts it and test the validity
func (f *UplinkFunctions) Process(payload []byte, port uint8) (map[string]interface{}, bool, error) {
	decoded, err := f.Decode(payload, port)
	if err != nil {
		return nil, false, err
	}

	converted, err := f.Convert(decoded, port)
	if err != nil {
		return nil, false, err
	}

	valid, err := f.Validate(converted, port)
	return converted, valid, err
}

var errTimeOutExceeded = errors.NewErrInternal("Code has been running to long")

// DownlinkFunctions encodes payload using JavaScript functions
type DownlinkFunctions struct {
	// Encoder is a JavaScript function that accepts the payload as JSON and
	// returns an array of bytes
	Encoder string

	// Logger is the logger that will be used to store logs
	Logger Logger
}

// Encode encodes the map into a byte slice using the encoder payload function
// If no encoder function is set, this function returns an array.
func (f *DownlinkFunctions) Encode(payload map[string]interface{}, port uint8) ([]byte, error) {
	if f.Encoder == "" {
		return nil, errors.NewErrInternal("Encoder function not set")
	}

	vm := otto.New()
	vm.Set("payload", payload)
	vm.Set("port", port)
	value, err := runUnsafeCodeWithLogger(vm, fmt.Sprintf("(%s)(payload, port)", f.Encoder), timeOut, f.Logger)
	if err != nil {
		return nil, err
	}

	if !value.IsObject() {
		return nil, errors.NewErrInvalidArgument("Encoder", "does not return an object")
	}

	v, err := value.Export()
	if err != nil {
		return nil, err
	}

	if reflect.TypeOf(v).Kind() != reflect.Slice {
		return nil, errors.NewErrInvalidArgument("Encoder", "does not return an Array")
	}

	s := reflect.ValueOf(v)
	l := s.Len()

	res := make([]byte, l)

	var n int64
	for i := 0; i < l; i++ {
		el := s.Index(i).Interface()

		// type switch does not have fallthrough so we need
		// to check every element individually
		switch t := el.(type) {
		case byte:
			n = int64(t)
		case int:
			n = int64(t)
		case int8:
			n = int64(t)
		case int16:
			n = int64(t)
		case uint16:
			n = int64(t)
		case int32:
			n = int64(t)
		case uint32:
			n = int64(t)
		case int64:
			n = int64(t)
		case uint64:
			n = int64(t)
		case float32:
			n = int64(t)
			if float32(n) != t {
				return nil, errors.NewErrInvalidArgument("Encoder", "should return an Array of integer numbers")
			}
		case float64:
			n = int64(t)
			if float64(n) != t {
				return nil, errors.NewErrInvalidArgument("Encoder", "should return an Array of integer numbers")
			}
		default:
			return nil, errors.NewErrInvalidArgument("Encoder", "should return an Array of integer numbers")
		}

		if n < 0 || n > 255 {
			return nil, errors.NewErrInvalidArgument("Encoder Output", "Numbers in Array should be between 0 and 255")
		}

		res[i] = byte(n)
	}

	return res, nil
}

// Process encode the specified field, converts it into a valid payload
func (f *DownlinkFunctions) Process(payload map[string]interface{}, port uint8) ([]byte, bool, error) {
	encoded, err := f.Encode(payload, port)
	if err != nil {
		return nil, false, err
	}

	return encoded, true, nil
}

// ConvertFieldsDown converts the fields into a payload
func (h *handler) ConvertFieldsDown(ctx log.Interface, appDown *types.DownlinkMessage, ttnDown *pb_broker.DownlinkMessage) error {
	if appDown.PayloadFields == nil {
		return nil
	}

	if appDown.PayloadRaw != nil {
		return errors.NewErrInvalidArgument("Downlink", "Both Fields and Payload provided")
	}

	app, err := h.applications.Get(appDown.AppID)
	if err != nil {
		return nil
	}

	functions := &DownlinkFunctions{
		Encoder: app.Encoder,
	}

	message, _, err := functions.Process(appDown.PayloadFields, appDown.FPort)
	if err != nil {
		return err
	}

	appDown.PayloadRaw = message

	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/solo-io/go-utils/githubutils"
	"github.com/solo-io/go-utils/logger"
	"github.com/solo-io/go-utils/pkgmgmtutils"
)

func main() {
	const buildDir = "_output"
	const repoOwner = "solo-io"
	const repoName = "squash"

	assets := make([]githubutils.ReleaseAssetSpec, 3)
	assets[0] = githubutils.ReleaseAssetSpec{
		Name:       "squashctl-darwin",
		ParentPath: buildDir,
		UploadSHA:  true,
	}
	assets[1] = githubutils.ReleaseAssetSpec{
		Name:       "squashctl-linux",
		ParentPath: buildDir,
		UploadSHA:  true,
	}
	assets[2] = githubutils.ReleaseAssetSpec{
		Name:       "squashctl-windows.exe",
		ParentPath: buildDir,
		UploadSHA:  true,
	}

	spec := githubutils.UploadReleaseAssetSpec{
		Owner:             repoOwner,
		Repo:              repoName,
		Assets:            assets,
		SkipAlreadyExists: true,
	}
	githubutils.UploadReleaseAssetCli(&spec)

	fOpts := []pkgmgmtutils.FormulaOptions{
		{
			Name:           "homebrew-tap/squashctl",
			FormulaName:    "squashctl",
			Path:           "Formula/squashctl.rb",
			RepoOwner:      repoOwner,      // Make change in this repo owner
			RepoName:       "homebrew-tap", //   expects this repo is forked from PRRepoOwner if PRRepoOwner != RepoOwner
			PRRepoOwner:    repoOwner,      // Make PR to this repo owner
			PRRepoName:     "homebrew-tap", //   and this repo
			PRBranch:       "master",       //   and merge into this branch
			PRDescription:  "",
			PRCommitName:   "Solo-io Bot",
			PRCommitEmail:  "bot@solo.io",
			VersionRegex:   `version\s*"([0-9.]+)"`,
			DarwinShaRegex: `url\s*".*-darwin.*\W*sha256\s*"(.*)"`,
			LinuxShaRegex:  `url\s*".*-linux.*\W*sha256\s*"(.*)"`,
		},
		{
			Name:            "fish-food/squashctl",
			FormulaName:     "squashctl",
			Path:            "Food/squashctl.lua",
			RepoOwner:       repoOwner,
			RepoName:        "fish-food",
			PRRepoOwner:     "fishworks",
			PRRepoName:      "fish-food",
			PRBranch:        "master",
			PRDescription:   "",
			PRCommitName:    "Solo-io Bot",
			PRCommitEmail:   "bot@solo.io",
			VersionRegex:    `version\s*=\s*"([0-9.]+)"`,
			DarwinShaRegex:  `os\s*=\s*"darwin",\W*.*\W*.*\W*.*\W*sha256\s*=\s*"(.*)",`,
			LinuxShaRegex:   `os\s*=\s*"linux",\W*.*\W*.*\W*.*\W*sha256\s*=\s*"(.*)",`,
			WindowsShaRegex: `os\s*=\s*"windows",\W*.*\W*.*\W*.*\W*sha256\s*=\s*"(.*)",`,
		},
	}

	// Update package manager install formulas
	status, err := pkgmgmtutils.UpdateFormulas(repoOwner, repoName, buildDir,
		`squashctl-(darwin|linux|windows).*\.sha256`, fOpts)
	if err != nil {
		logger.Fatalf("Error trying to update package manager formulas. Error was: %s", err.Error())
	}
	for _, s := range status {
		if !s.Updated {
			if s.Err != nil {
				logger.Fatalf("Error while trying to update formula %s. Error was: %s", s.Name, s.Err.Error())
			} else {
				logger.Fatalf("Error while trying to update formula %s. Error was nil", s.Name) // Shouldn't happen; really bad if it does
			}
		}
		if s.Err != nil {
			if s.Err == pkgmgmtutils.ErrAlreadyUpdated {
				logger.Warnf("Formula %s was updated externally, so no updates applied during this release", s.Name)
			} else {
				logger.Fatalf("Error updating Formula %s. Error was: %s", s.Name, s.Err.Error())
			}
		}
	}
}
<commit_msg>disable gofish release (#229)<commit_after>package main

import (
	"github.com/solo-io/go-utils/githubutils"
	"github.com/solo-io/go-utils/logger"
	"github.com/solo-io/go-utils/pkgmgmtutils"
)

func main() {
	const buildDir = "_output"
	const repoOwner = "solo-io"
	const repoName = "squash"

	assets := make([]githubutils.ReleaseAssetSpec, 3)
	assets[0] = githubutils.ReleaseAssetSpec{
		Name:       "squashctl-darwin",
		ParentPath: buildDir,
		UploadSHA:  true,
	}
	assets[1] = githubutils.ReleaseAssetSpec{
		Name:       "squashctl-linux",
		ParentPath: buildDir,
		UploadSHA:  true,
	}
	assets[2] = githubutils.ReleaseAssetSpec{
		Name:       "squashctl-windows.exe",
		ParentPath: buildDir,
		UploadSHA:  true,
	}

	spec := githubutils.UploadReleaseAssetSpec{
		Owner:             repoOwner,
		Repo:              repoName,
		Assets:            assets,
		SkipAlreadyExists: true,
	}
	githubutils.UploadReleaseAssetCli(&spec)

	fOpts := []pkgmgmtutils.FormulaOptions{
		{
			Name:           "homebrew-tap/squashctl",
			FormulaName:    "squashctl",
			Path:           "Formula/squashctl.rb",
			RepoOwner:      repoOwner,      // Make change in this repo owner
			RepoName:       "homebrew-tap", //   expects this repo is forked from PRRepoOwner if PRRepoOwner != RepoOwner
			PRRepoOwner:    repoOwner,      // Make PR to this repo owner
			PRRepoName:     "homebrew-tap", //   and this repo
			PRBranch:       "master",       //   and merge into this branch
			PRDescription:  "",
			PRCommitName:   "Solo-io Bot",
			PRCommitEmail:  "bot@solo.io",
			VersionRegex:   `version\s*"([0-9.]+)"`,
			DarwinShaRegex: `url\s*".*-darwin.*\W*sha256\s*"(.*)"`,
			LinuxShaRegex:  `url\s*".*-linux.*\W*sha256\s*"(.*)"`,
		},
		// {
		// 	Name:            "fish-food/squashctl",
		// 	FormulaName:     "squashctl",
		// 	Path:            "Food/squashctl.lua",
		// 	RepoOwner:       repoOwner,
		// 	RepoName:        "fish-food",
		// 	PRRepoOwner:     "fishworks",
		// 	PRRepoName:      "fish-food",
		// 	PRBranch:        "master",
		// 	PRDescription:   "",
		// 	PRCommitName:    "Solo-io Bot",
		// 	PRCommitEmail:   "bot@solo.io",
		// 	VersionRegex:    `version\s*=\s*"([0-9.]+)"`,
		// 	DarwinShaRegex:  `os\s*=\s*"darwin",\W*.*\W*.*\W*.*\W*sha256\s*=\s*"(.*)",`,
		// 	LinuxShaRegex:   `os\s*=\s*"linux",\W*.*\W*.*\W*.*\W*sha256\s*=\s*"(.*)",`,
		// 	WindowsShaRegex: `os\s*=\s*"windows",\W*.*\W*.*\W*.*\W*sha256\s*=\s*"(.*)",`,
		// },
	}

	// Update package manager install formulas
	status, err := pkgmgmtutils.UpdateFormulas(repoOwner, repoName, buildDir,
		`squashctl-(darwin|linux|windows).*\.sha256`, fOpts)
	if err != nil {
		logger.Fatalf("Error trying to update package manager formulas. Error was: %s", err.Error())
	}
	for _, s := range status {
		if !s.Updated {
			if s.Err != nil {
				logger.Fatalf("Error while trying to update formula %s. Error was: %s", s.Name, s.Err.Error())
			} else {
				logger.Fatalf("Error while trying to update formula %s. Error was nil", s.Name) // Shouldn't happen; really bad if it does
			}
		}
		if s.Err != nil {
			if s.Err == pkgmgmtutils.ErrAlreadyUpdated {
				logger.Warnf("Formula %s was updated externally, so no updates applied during this release", s.Name)
			} else {
				logger.Fatalf("Error updating Formula %s. Error was: %s", s.Name, s.Err.Error())
			}
		}
	}
}
<|endoftext|>


<commit_before>// Copyright 2017 tsuru 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 app

import (
	"errors"

	tsuruErrors "github.com/tsuru/tsuru/errors"
)

type Platform struct {
	Name     string `bson:"_id"`
	Disabled bool   `bson:",omitempty"`
}

type PlatformService interface {
	Insert(Platform) error
	FindByName(string) (*Platform, error)
	FindAll() ([]Platform, error)
	FindEnabled() ([]Platform, error)
	Update(Platform) error
	Delete(Platform) error
}

var (
	ErrPlatformNameMissing    = errors.New("Platform name is required.")
	ErrPlatformNotFound       = errors.New("Platform doesn't exist.")
	DuplicatePlatformError    = errors.New("Duplicate platform")
	InvalidPlatformError      = errors.New("Invalid platform")
	ErrDeletePlatformWithApps = errors.New("Platform has apps. You should remove them before remove the platform.")
	ErrInvalidPlatformName    = &tsuruErrors.ValidationError{
		Message: "Invalid platform name, should have at most 63 " +
			"characters, containing only lower case letters, numbers or dashes, " +
			"starting with a letter.",
	}
)
<commit_msg>types/app: remove bson tags from platform struct<commit_after>// Copyright 2017 tsuru 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 app

import (
	"errors"

	tsuruErrors "github.com/tsuru/tsuru/errors"
)

type Platform struct {
	Name     string
	Disabled bool
}

type PlatformService interface {
	Insert(Platform) error
	FindByName(string) (*Platform, error)
	FindAll() ([]Platform, error)
	FindEnabled() ([]Platform, error)
	Update(Platform) error
	Delete(Platform) error
}

var (
	ErrPlatformNameMissing    = errors.New("Platform name is required.")
	ErrPlatformNotFound       = errors.New("Platform doesn't exist.")
	DuplicatePlatformError    = errors.New("Duplicate platform")
	InvalidPlatformError      = errors.New("Invalid platform")
	ErrDeletePlatformWithApps = errors.New("Platform has apps. You should remove them before remove the platform.")
	ErrInvalidPlatformName    = &tsuruErrors.ValidationError{
		Message: "Invalid platform name, should have at most 63 " +
			"characters, containing only lower case letters, numbers or dashes, " +
			"starting with a letter.",
	}
)
<|endoftext|>


<commit_before>package moderatorController

import (
	"fmt"
	"html"
	"net/http"
	"strconv"

	"github.com/NyaaPantsu/nyaa/controllers/router"
	"github.com/NyaaPantsu/nyaa/models"
	"github.com/NyaaPantsu/nyaa/models/activities"
	"github.com/NyaaPantsu/nyaa/models/reports"
	"github.com/NyaaPantsu/nyaa/models/torrents"
	"github.com/NyaaPantsu/nyaa/templates"
	"github.com/NyaaPantsu/nyaa/utils/log"
	msg "github.com/NyaaPantsu/nyaa/utils/messages"
	"github.com/NyaaPantsu/nyaa/utils/search"
	"github.com/NyaaPantsu/nyaa/utils/upload"
	"github.com/NyaaPantsu/nyaa/utils/validator/torrent"
	"github.com/gin-gonic/gin"
)

// TorrentsListPanel : Controller for listing torrents, can accept common search arguments
func TorrentsListPanel(c *gin.Context) {
	page := c.Param("page")
	messages := msg.GetMessages(c)
	deleted := c.Request.URL.Query()["deleted"]
	unblocked := c.Request.URL.Query()["unblocked"]
	blocked := c.Request.URL.Query()["blocked"]
	if deleted != nil {
		messages.AddInfoTf("infos", "torrent_deleted", "")
	}
	if blocked != nil {
		messages.AddInfoT("infos", "torrent_blocked")
	}
	if unblocked != nil {
		messages.AddInfoT("infos", "torrent_unblocked")
	}

	var err error
	pagenum := 1
	if page != "" {
		pagenum, err = strconv.Atoi(html.EscapeString(page))
		if !log.CheckError(err) {
			c.AbortWithError(http.StatusInternalServerError, err)
			return
		}
	}

	searchParam, torrents, count, err := search.ByQueryWithUser(c, pagenum)
	if err != nil {
		messages.Error(err)
	}
	category := ""
	if len(searchParam.Category) > 0 {
		category = searchParam.Category[0].String()
	}
	searchForm := templates.SearchForm{
		TorrentParam:     searchParam,
		Category:         category,
		ShowItemsPerPage: true,
	}

	nav := templates.Navigation{count, int(searchParam.Max), pagenum, "mod/torrents/p"}

	templates.ModelList(c, "admin/torrentlist.jet.html", torrents, nav, searchForm)
}

// TorrentEditModPanel : Controller for editing a torrent after GET request
func TorrentEditModPanel(c *gin.Context) {
	id, _ := strconv.ParseInt(c.Query("id"), 10, 32)
	torrent, _ := torrents.FindUnscopeByID(uint(id))
	torrent.LoadTags()

	torrentJSON := torrent.ToJSON()
	uploadForm := upload.NewTorrentRequest()
	uploadForm.ID = torrentJSON.ID
	uploadForm.Name = torrentJSON.Name
	uploadForm.Category = torrentJSON.Category + "_" + torrentJSON.SubCategory
	uploadForm.Status = torrentJSON.Status
	uploadForm.Hidden = torrent.Hidden
	uploadForm.WebsiteLink = string(torrentJSON.WebsiteLink)
	uploadForm.Description = string(torrentJSON.Description)
	uploadForm.Languages = torrent.Languages
	uploadForm.Tags.Bind(&torrent)

	templates.Form(c, "admin/paneltorrentedit.jet.html", uploadForm)
}

// TorrentPostEditModPanel : Controller for editing a torrent after POST request
func TorrentPostEditModPanel(c *gin.Context) {
	var uploadForm torrentValidator.UpdateRequest
	id, _ := strconv.ParseInt(c.Query("id"), 10, 32)
	messages := msg.GetMessages(c)
	torrent, _ := torrents.FindUnscopeByID(uint(id))
	torrent.LoadTags()
	currentUser := router.GetUser(c)
	if torrent.ID > 0 {
		errUp := upload.ExtractEditInfo(c, &uploadForm.Update)
		uploadForm.ID = torrent.ID
		uploadForm.Update.ID = torrent.ID

		if errUp != nil {
			messages.AddErrorT("errors", "fail_torrent_update")
		}
		if !messages.HasErrors() {
			_, err := upload.UpdateUnscopeTorrent(&uploadForm, &torrent, currentUser).UpdateUnscope()
			messages.AddInfoT("infos", "torrent_updated")
			if err == nil { // We only log edit torrent for admins
				if torrent.Uploader == nil {
					torrent.Uploader = &models.User{}
				}
				_, username := torrents.HideUser(torrent.UploaderID, torrent.Uploader.Username, torrent.Hidden)
				activities.Log(&models.User{}, torrent.Identifier(), "edit", "torrent_edited_by", strconv.Itoa(int(torrent.ID)), username, currentUser.Username)
			}
		}
	}
	templates.Form(c, "admin/paneltorrentedit.jet.html", uploadForm.Update)
}

// TorrentDeleteModPanel : Controller for deleting a torrent
func TorrentDeleteModPanel(c *gin.Context) {
	id, _ := strconv.ParseInt(c.PostForm("id"), 10, 32)
	definitely := c.Request.URL.Query()["definitely"]

	var returnRoute = "/mod/torrents"
	torrent, errFind := torrents.FindByID(uint(id))
	if errFind == nil {
		var err error
		if definitely != nil {
			_, _, err = torrent.DefinitelyDelete()

			//delete reports of torrent
			query := &search.Query{}
			query.Append("torrent_id", id)
			reports, _, _ := reports.FindOrderBy(query, "", 0, 0)
			for _, report := range reports {
				report.Delete(true)
			}
			returnRoute = "/mod/torrents/deleted"
		} else {
			_, _, err = torrent.Delete(false)

			//delete reports of torrent
			query := &search.Query{}
			query.Append("torrent_id", id)
			reports, _, _ := reports.FindOrderBy(query, "", 0, 0)
			for _, report := range reports {
				report.Delete(false)
			}
		}
		if err == nil {
			if torrent.Uploader == nil {
				torrent.Uploader = &models.User{}
			}
			_, username := torrents.HideUser(torrent.UploaderID, torrent.Uploader.Username, torrent.Hidden)
			activities.Log(&models.User{}, torrent.Identifier(), "delete", "torrent_deleted_by", strconv.Itoa(int(torrent.ID)), username, router.GetUser(c).Username)
		}
	}

	c.Redirect(http.StatusSeeOther, returnRoute+"?deleted")
}

// DeleteTagsModPanel : Controller for deleting all torrent tags
func DeleteTagsModPanel(c *gin.Context) {
	id, _ := strconv.ParseInt(c.Query("id"), 10, 32)

	torrent, errFind := torrents.FindByID(uint(id))
	if errFind == nil {
		// delete all tags
		torrent.DeleteTags()
	}
	// redirect to edit form
	c.Redirect(http.StatusSeeOther, fmt.Sprintf("/mod/torrent?id=%d", id))
}

// TorrentBlockModPanel : Controller to lock torrents, redirecting to previous page
func TorrentBlockModPanel(c *gin.Context) {
	id, _ := strconv.ParseInt(c.Query("id"), 10, 32)
	torrent, _, err := torrents.ToggleBlock(uint(id))
	var returnRoute, action string
	if torrent.IsDeleted() {
		returnRoute = "/mod/torrents/deleted"
	} else {
		returnRoute = "/mod/torrents"
	}
	if torrent.IsBlocked() {
		action = "blocked"
	} else {
		action = "unblocked"
	}
	if err == nil {
		if torrent.Uploader == nil {
			torrent.Uploader = &models.User{}
		}
		_, username := torrents.HideUser(torrent.UploaderID, torrent.Uploader.Username, torrent.Hidden)
		activities.Log(&models.User{}, torrent.Identifier(), action, "torrent_"+action+"_by", strconv.Itoa(int(torrent.ID)), username, router.GetUser(c).Username)
	}

	c.Redirect(http.StatusSeeOther, returnRoute+"?"+action)
}

// TorrentsPostListPanel : Controller for listing torrents, after POST request when mass update
func TorrentsPostListPanel(c *gin.Context) {
	torrentManyAction(c)
	TorrentsListPanel(c)
}
<commit_msg>Update torrents.go<commit_after>package moderatorController

import (
	"fmt"
	"html"
	"net/http"
	"strconv"

	"github.com/NyaaPantsu/nyaa/controllers/router"
	"github.com/NyaaPantsu/nyaa/models"
	"github.com/NyaaPantsu/nyaa/models/activities"
	"github.com/NyaaPantsu/nyaa/models/reports"
	"github.com/NyaaPantsu/nyaa/models/torrents"
	"github.com/NyaaPantsu/nyaa/templates"
	"github.com/NyaaPantsu/nyaa/utils/log"
	msg "github.com/NyaaPantsu/nyaa/utils/messages"
	"github.com/NyaaPantsu/nyaa/utils/search"
	"github.com/NyaaPantsu/nyaa/utils/upload"
	"github.com/NyaaPantsu/nyaa/utils/validator/torrent"
	"github.com/gin-gonic/gin"
)

// TorrentsListPanel : Controller for listing torrents, can accept common search arguments
func TorrentsListPanel(c *gin.Context) {
	page := c.Param("page")
	messages := msg.GetMessages(c)
	deleted := c.Request.URL.Query()["deleted"]
	unblocked := c.Request.URL.Query()["unblocked"]
	blocked := c.Request.URL.Query()["blocked"]
	if deleted != nil {
		messages.AddInfoTf("infos", "torrent_deleted", "")
	}
	if blocked != nil {
		messages.AddInfoT("infos", "torrent_blocked")
	}
	if unblocked != nil {
		messages.AddInfoT("infos", "torrent_unblocked")
	}

	var err error
	pagenum := 1
	if page != "" {
		pagenum, err = strconv.Atoi(html.EscapeString(page))
		if !log.CheckError(err) {
			c.AbortWithError(http.StatusInternalServerError, err)
			return
		}
	}

	searchParam, torrents, count, err := search.ByQueryWithUser(c, pagenum)
	if err != nil {
		messages.Error(err)
	}
	category := ""
	if len(searchParam.Category) > 0 {
		category = searchParam.Category[0].String()
	}
	searchForm := templates.SearchForm{
		TorrentParam:     searchParam,
		Category:         category,
		ShowItemsPerPage: true,
	}

	nav := templates.Navigation{count, int(searchParam.Max), pagenum, "mod/torrents/p"}

	templates.ModelList(c, "admin/torrentlist.jet.html", torrents, nav, searchForm)
}

// TorrentEditModPanel : Controller for editing a torrent after GET request
func TorrentEditModPanel(c *gin.Context) {
	id, _ := strconv.ParseInt(c.Query("id"), 10, 32)
	torrent, _ := torrents.FindUnscopeByID(uint(id))
	torrent.LoadTags()

	torrentJSON := torrent.ToJSON()
	uploadForm := upload.NewTorrentRequest()
	uploadForm.ID = torrentJSON.ID
	uploadForm.Name = torrentJSON.Name
	uploadForm.Category = torrentJSON.Category + "_" + torrentJSON.SubCategory
	uploadForm.Status = torrentJSON.Status
	uploadForm.Hidden = torrent.Hidden
	uploadForm.WebsiteLink = string(torrentJSON.WebsiteLink)
	uploadForm.Description = string(torrentJSON.Description)
	uploadForm.Languages = torrent.Languages
	uploadForm.Tags.Bind(&torrent)

	templates.Form(c, "admin/paneltorrentedit.jet.html", uploadForm)
}

// TorrentPostEditModPanel : Controller for editing a torrent after POST request
func TorrentPostEditModPanel(c *gin.Context) {
	var uploadForm torrentValidator.UpdateRequest
	id, _ := strconv.ParseInt(c.Query("id"), 10, 32)
	messages := msg.GetMessages(c)
	torrent, _ := torrents.FindUnscopeByID(uint(id))
	torrent.LoadTags()
	currentUser := router.GetUser(c)
	if torrent.ID > 0 {
		errUp := upload.ExtractEditInfo(c, &uploadForm.Update)
		uploadForm.ID = torrent.ID
		uploadForm.Update.ID = torrent.ID

		if errUp != nil {
			messages.AddErrorT("errors", "fail_torrent_update")
		}
		if !messages.HasErrors() {
			_, err := upload.UpdateUnscopeTorrent(&uploadForm, &torrent, currentUser).UpdateUnscope()
			messages.AddInfoT("infos", "torrent_updated")
			if err == nil { // We only log edit torrent for admins
				if torrent.Uploader == nil {
					torrent.Uploader = &models.User{}
				}
				_, username := torrents.HideUser(torrent.UploaderID, torrent.Uploader.Username, torrent.Hidden)
				activities.Log(&models.User{}, torrent.Identifier(), "edit", "torrent_edited_by", strconv.Itoa(int(torrent.ID)), username, currentUser.Username)
			}
		}
	}
	templates.Form(c, "admin/paneltorrentedit.jet.html", uploadForm.Update)
}

// TorrentDeleteModPanel : Controller for deleting a torrent
func TorrentDeleteModPanel(c *gin.Context) {
	id, _ := strconv.ParseInt(c.PostForm("id"), 10, 32)

	var returnRoute = "/mod/torrents"
	torrent, errFind := torrents.FindByID(uint(id))
	if errFind == nil {
		var err error
			_, _, err = torrent.Delete(false)

		//delete reports of torrent
		query := &search.Query{}
		query.Append("torrent_id", id)
		reports, _, _ := reports.FindOrderBy(query, "", 0, 0)
		for _, report := range reports {
			report.Delete()
		}

		if err == nil {
			if torrent.Uploader == nil {
				torrent.Uploader = &models.User{}
			}
			_, username := torrents.HideUser(torrent.UploaderID, torrent.Uploader.Username, torrent.Hidden)
			activities.Log(&models.User{}, torrent.Identifier(), "delete", "torrent_deleted_by", strconv.Itoa(int(torrent.ID)), username, router.GetUser(c).Username)
		}
	}

	c.Redirect(http.StatusSeeOther, returnRoute+"?deleted")
}

// DeleteTagsModPanel : Controller for deleting all torrent tags
func DeleteTagsModPanel(c *gin.Context) {
	id, _ := strconv.ParseInt(c.Query("id"), 10, 32)

	torrent, errFind := torrents.FindByID(uint(id))
	if errFind == nil {
		// delete all tags
		torrent.DeleteTags()
	}
	// redirect to edit form
	c.Redirect(http.StatusSeeOther, fmt.Sprintf("/mod/torrent?id=%d", id))
}

// TorrentBlockModPanel : Controller to lock torrents, redirecting to previous page
func TorrentBlockModPanel(c *gin.Context) {
	id, _ := strconv.ParseInt(c.Query("id"), 10, 32)
	torrent, _, err := torrents.ToggleBlock(uint(id))
	var returnRoute, action string
	if torrent.IsDeleted() {
		returnRoute = "/mod/torrents/deleted"
	} else {
		returnRoute = "/mod/torrents"
	}
	if torrent.IsBlocked() {
		action = "blocked"
	} else {
		action = "unblocked"
	}
	if err == nil {
		if torrent.Uploader == nil {
			torrent.Uploader = &models.User{}
		}
		_, username := torrents.HideUser(torrent.UploaderID, torrent.Uploader.Username, torrent.Hidden)
		activities.Log(&models.User{}, torrent.Identifier(), action, "torrent_"+action+"_by", strconv.Itoa(int(torrent.ID)), username, router.GetUser(c).Username)
	}

	c.Redirect(http.StatusSeeOther, returnRoute+"?"+action)
}

// TorrentsPostListPanel : Controller for listing torrents, after POST request when mass update
func TorrentsPostListPanel(c *gin.Context) {
	torrentManyAction(c)
	TorrentsListPanel(c)
}
<|endoftext|>


<commit_before>// +build windows

package windows

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

	"github.com/Sirupsen/logrus"
	"github.com/docker/libnetwork/datastore"
	"github.com/docker/libnetwork/discoverapi"
	"github.com/docker/libnetwork/netlabel"
	"github.com/docker/libnetwork/types"
)

const (
	windowsPrefix         = "windows"
	windowsEndpointPrefix = "windows-endpoint"
)

func (d *driver) initStore(option map[string]interface{}) error {
	if data, ok := option[netlabel.LocalKVClient]; ok {
		var err error
		dsc, ok := data.(discoverapi.DatastoreConfigData)
		if !ok {
			return types.InternalErrorf("incorrect data in datastore configuration: %v", data)
		}
		d.store, err = datastore.NewDataStoreFromConfig(dsc)
		if err != nil {
			return types.InternalErrorf("windows driver failed to initialize data store: %v", err)
		}

		err = d.populateNetworks()
		if err != nil {
			return err
		}

		err = d.populateEndpoints()
		if err != nil {
			return err
		}
	}

	return nil
}

func (d *driver) populateNetworks() error {
	kvol, err := d.store.List(datastore.Key(windowsPrefix), &networkConfiguration{Type: d.name})
	if err != nil && err != datastore.ErrKeyNotFound {
		return fmt.Errorf("failed to get windows network configurations from store: %v", err)
	}

	// It's normal for network configuration state to be empty. Just return.
	if err == datastore.ErrKeyNotFound {
		return nil
	}

	for _, kvo := range kvol {
		ncfg := kvo.(*networkConfiguration)
		if ncfg.Type != d.name {
			continue
		}
		if err = d.createNetwork(ncfg); err != nil {
			logrus.Warnf("could not create windows network for id %s hnsid %s while booting up from persistent state: %v", ncfg.ID, ncfg.HnsID, err)
		}
		logrus.Debugf("Network (%s) restored", ncfg.ID[0:7])
	}

	return nil
}

func (d *driver) populateEndpoints() error {
	kvol, err := d.store.List(datastore.Key(windowsEndpointPrefix), &hnsEndpoint{Type: d.name})
	if err != nil && err != datastore.ErrKeyNotFound {
		return fmt.Errorf("failed to get endpoints from store: %v", err)
	}

	if err == datastore.ErrKeyNotFound {
		return nil
	}

	for _, kvo := range kvol {
		ep := kvo.(*hnsEndpoint)
		if ep.Type != d.name {
			continue
		}
		n, ok := d.networks[ep.nid]
		if !ok {
			logrus.Debugf("Network (%s) not found for restored endpoint (%s)", ep.nid[0:7], ep.id[0:7])
			logrus.Debugf("Deleting stale endpoint (%s) from store", ep.id[0:7])
			if err := d.storeDelete(ep); err != nil {
				logrus.Debugf("Failed to delete stale endpoint (%s) from store", ep.id[0:7])
			}
			continue
		}
		n.endpoints[ep.id] = ep
		logrus.Debugf("Endpoint (%s) restored to network (%s)", ep.id[0:7], ep.nid[0:7])
	}

	return nil
}

func (d *driver) storeUpdate(kvObject datastore.KVObject) error {
	if d.store == nil {
		logrus.Warnf("store not initialized. kv object %s is not added to the store", datastore.Key(kvObject.Key()...))
		return nil
	}

	if err := d.store.PutObjectAtomic(kvObject); err != nil {
		return fmt.Errorf("failed to update store for object type %T: %v", kvObject, err)
	}

	return nil
}

func (d *driver) storeDelete(kvObject datastore.KVObject) error {
	if d.store == nil {
		logrus.Debugf("store not initialized. kv object %s is not deleted from store", datastore.Key(kvObject.Key()...))
		return nil
	}

retry:
	if err := d.store.DeleteObjectAtomic(kvObject); err != nil {
		if err == datastore.ErrKeyModified {
			if err := d.store.GetObject(datastore.Key(kvObject.Key()...), kvObject); err != nil {
				return fmt.Errorf("could not update the kvobject to latest when trying to delete: %v", err)
			}
			goto retry
		}
		return err
	}

	return nil
}

func (ncfg *networkConfiguration) MarshalJSON() ([]byte, error) {
	nMap := make(map[string]interface{})

	nMap["ID"] = ncfg.ID
	nMap["Type"] = ncfg.Type
	nMap["Name"] = ncfg.Name
	nMap["HnsID"] = ncfg.HnsID
	nMap["VLAN"] = ncfg.VLAN
	nMap["VSID"] = ncfg.VSID
	nMap["DNSServers"] = ncfg.DNSServers
	nMap["DNSSuffix"] = ncfg.DNSSuffix
	nMap["SourceMac"] = ncfg.SourceMac
	nMap["NetworkAdapterName"] = ncfg.NetworkAdapterName

	return json.Marshal(nMap)
}

func (ncfg *networkConfiguration) UnmarshalJSON(b []byte) error {
	var (
		err  error
		nMap map[string]interface{}
	)

	if err = json.Unmarshal(b, &nMap); err != nil {
		return err
	}

	ncfg.ID = nMap["ID"].(string)
	ncfg.Type = nMap["Type"].(string)
	ncfg.Name = nMap["Name"].(string)
	ncfg.HnsID = nMap["HnsID"].(string)
	ncfg.VLAN = uint(nMap["VLAN"].(float64))
	ncfg.VSID = uint(nMap["VSID"].(float64))
	ncfg.DNSServers = nMap["DNSServers"].(string)
	ncfg.DNSSuffix = nMap["DNSSuffix"].(string)
	ncfg.SourceMac = nMap["SourceMac"].(string)
	ncfg.NetworkAdapterName = nMap["NetworkAdapterName"].(string)
	return nil
}

func (ncfg *networkConfiguration) Key() []string {
	return []string{windowsPrefix + ncfg.Type, ncfg.ID}
}

func (ncfg *networkConfiguration) KeyPrefix() []string {
	return []string{windowsPrefix + ncfg.Type}
}

func (ncfg *networkConfiguration) Value() []byte {
	b, err := json.Marshal(ncfg)
	if err != nil {
		return nil
	}
	return b
}

func (ncfg *networkConfiguration) SetValue(value []byte) error {
	return json.Unmarshal(value, ncfg)
}

func (ncfg *networkConfiguration) Index() uint64 {
	return ncfg.dbIndex
}

func (ncfg *networkConfiguration) SetIndex(index uint64) {
	ncfg.dbIndex = index
	ncfg.dbExists = true
}

func (ncfg *networkConfiguration) Exists() bool {
	return ncfg.dbExists
}

func (ncfg *networkConfiguration) Skip() bool {
	return false
}

func (ncfg *networkConfiguration) New() datastore.KVObject {
	return &networkConfiguration{Type: ncfg.Type}
}

func (ncfg *networkConfiguration) CopyTo(o datastore.KVObject) error {
	dstNcfg := o.(*networkConfiguration)
	*dstNcfg = *ncfg
	return nil
}

func (ncfg *networkConfiguration) DataScope() string {
	return datastore.LocalScope
}

func (ep *hnsEndpoint) MarshalJSON() ([]byte, error) {
	epMap := make(map[string]interface{})
	epMap["id"] = ep.id
	epMap["nid"] = ep.nid
	epMap["Type"] = ep.Type
	epMap["profileID"] = ep.profileID
	epMap["MacAddress"] = ep.macAddress.String()
	epMap["Addr"] = ep.addr.String()
	epMap["gateway"] = ep.gateway.String()

	epMap["epOption"] = ep.epOption
	epMap["epConnectivity"] = ep.epConnectivity
	epMap["PortMapping"] = ep.portMapping

	return json.Marshal(epMap)
}

func (ep *hnsEndpoint) UnmarshalJSON(b []byte) error {
	var (
		err   error
		epMap map[string]interface{}
	)

	if err = json.Unmarshal(b, &epMap); err != nil {
		return fmt.Errorf("Failed to unmarshal to endpoint: %v", err)
	}

	if v, ok := epMap["MacAddress"]; ok {
		if ep.macAddress, err = net.ParseMAC(v.(string)); err != nil {
			return types.InternalErrorf("failed to decode endpoint MAC address (%s) after json unmarshal: %v", v.(string), err)
		}
	}
	if v, ok := epMap["Addr"]; ok {
		if ep.addr, err = types.ParseCIDR(v.(string)); err != nil {
			return types.InternalErrorf("failed to decode endpoint IPv4 address (%s) after json unmarshal: %v", v.(string), err)
		}
	}

	ep.id = epMap["id"].(string)
	ep.Type = epMap["Type"].(string)
	ep.nid = epMap["nid"].(string)
	ep.profileID = epMap["profileID"].(string)
	d, _ := json.Marshal(epMap["epOption"])
	if err := json.Unmarshal(d, &ep.epOption); err != nil {
		logrus.Warnf("Failed to decode endpoint container config %v", err)
	}
	d, _ = json.Marshal(epMap["epConnectivity"])
	if err := json.Unmarshal(d, &ep.epConnectivity); err != nil {
		logrus.Warnf("Failed to decode endpoint external connectivity configuration %v", err)
	}
	d, _ = json.Marshal(epMap["PortMapping"])
	if err := json.Unmarshal(d, &ep.portMapping); err != nil {
		logrus.Warnf("Failed to decode endpoint port mapping %v", err)
	}

	return nil
}

func (ep *hnsEndpoint) Key() []string {
	return []string{windowsEndpointPrefix + ep.Type, ep.id}
}

func (ep *hnsEndpoint) KeyPrefix() []string {
	return []string{windowsEndpointPrefix + ep.Type}
}

func (ep *hnsEndpoint) Value() []byte {
	b, err := json.Marshal(ep)
	if err != nil {
		return nil
	}
	return b
}

func (ep *hnsEndpoint) SetValue(value []byte) error {
	return json.Unmarshal(value, ep)
}

func (ep *hnsEndpoint) Index() uint64 {
	return ep.dbIndex
}

func (ep *hnsEndpoint) SetIndex(index uint64) {
	ep.dbIndex = index
	ep.dbExists = true
}

func (ep *hnsEndpoint) Exists() bool {
	return ep.dbExists
}

func (ep *hnsEndpoint) Skip() bool {
	return false
}

func (ep *hnsEndpoint) New() datastore.KVObject {
	return &hnsEndpoint{Type: ep.Type}
}

func (ep *hnsEndpoint) CopyTo(o datastore.KVObject) error {
	dstEp := o.(*hnsEndpoint)
	*dstEp = *ep
	return nil
}

func (ep *hnsEndpoint) DataScope() string {
	return datastore.LocalScope
}
<commit_msg>Fixes docker daemon not restarting after endpoint leak on windows with transaprent network<commit_after>// +build windows

package windows

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

	"github.com/Sirupsen/logrus"
	"github.com/docker/libnetwork/datastore"
	"github.com/docker/libnetwork/discoverapi"
	"github.com/docker/libnetwork/netlabel"
	"github.com/docker/libnetwork/types"
)

const (
	windowsPrefix         = "windows"
	windowsEndpointPrefix = "windows-endpoint"
)

func (d *driver) initStore(option map[string]interface{}) error {
	if data, ok := option[netlabel.LocalKVClient]; ok {
		var err error
		dsc, ok := data.(discoverapi.DatastoreConfigData)
		if !ok {
			return types.InternalErrorf("incorrect data in datastore configuration: %v", data)
		}
		d.store, err = datastore.NewDataStoreFromConfig(dsc)
		if err != nil {
			return types.InternalErrorf("windows driver failed to initialize data store: %v", err)
		}

		err = d.populateNetworks()
		if err != nil {
			return err
		}

		err = d.populateEndpoints()
		if err != nil {
			return err
		}
	}

	return nil
}

func (d *driver) populateNetworks() error {
	kvol, err := d.store.List(datastore.Key(windowsPrefix), &networkConfiguration{Type: d.name})
	if err != nil && err != datastore.ErrKeyNotFound {
		return fmt.Errorf("failed to get windows network configurations from store: %v", err)
	}

	// It's normal for network configuration state to be empty. Just return.
	if err == datastore.ErrKeyNotFound {
		return nil
	}

	for _, kvo := range kvol {
		ncfg := kvo.(*networkConfiguration)
		if ncfg.Type != d.name {
			continue
		}
		if err = d.createNetwork(ncfg); err != nil {
			logrus.Warnf("could not create windows network for id %s hnsid %s while booting up from persistent state: %v", ncfg.ID, ncfg.HnsID, err)
		}
		logrus.Debugf("Network (%s) restored", ncfg.ID[0:7])
	}

	return nil
}

func (d *driver) populateEndpoints() error {
	kvol, err := d.store.List(datastore.Key(windowsEndpointPrefix), &hnsEndpoint{Type: d.name})
	if err != nil && err != datastore.ErrKeyNotFound {
		return fmt.Errorf("failed to get endpoints from store: %v", err)
	}

	if err == datastore.ErrKeyNotFound {
		return nil
	}

	for _, kvo := range kvol {
		ep := kvo.(*hnsEndpoint)
		if ep.Type != d.name {
			continue
		}
		n, ok := d.networks[ep.nid]
		if !ok {
			logrus.Debugf("Network (%s) not found for restored endpoint (%s)", ep.nid[0:7], ep.id[0:7])
			logrus.Debugf("Deleting stale endpoint (%s) from store", ep.id[0:7])
			if err := d.storeDelete(ep); err != nil {
				logrus.Debugf("Failed to delete stale endpoint (%s) from store", ep.id[0:7])
			}
			continue
		}
		n.endpoints[ep.id] = ep
		logrus.Debugf("Endpoint (%s) restored to network (%s)", ep.id[0:7], ep.nid[0:7])
	}

	return nil
}

func (d *driver) storeUpdate(kvObject datastore.KVObject) error {
	if d.store == nil {
		logrus.Warnf("store not initialized. kv object %s is not added to the store", datastore.Key(kvObject.Key()...))
		return nil
	}

	if err := d.store.PutObjectAtomic(kvObject); err != nil {
		return fmt.Errorf("failed to update store for object type %T: %v", kvObject, err)
	}

	return nil
}

func (d *driver) storeDelete(kvObject datastore.KVObject) error {
	if d.store == nil {
		logrus.Debugf("store not initialized. kv object %s is not deleted from store", datastore.Key(kvObject.Key()...))
		return nil
	}

retry:
	if err := d.store.DeleteObjectAtomic(kvObject); err != nil {
		if err == datastore.ErrKeyModified {
			if err := d.store.GetObject(datastore.Key(kvObject.Key()...), kvObject); err != nil {
				return fmt.Errorf("could not update the kvobject to latest when trying to delete: %v", err)
			}
			goto retry
		}
		return err
	}

	return nil
}

func (ncfg *networkConfiguration) MarshalJSON() ([]byte, error) {
	nMap := make(map[string]interface{})

	nMap["ID"] = ncfg.ID
	nMap["Type"] = ncfg.Type
	nMap["Name"] = ncfg.Name
	nMap["HnsID"] = ncfg.HnsID
	nMap["VLAN"] = ncfg.VLAN
	nMap["VSID"] = ncfg.VSID
	nMap["DNSServers"] = ncfg.DNSServers
	nMap["DNSSuffix"] = ncfg.DNSSuffix
	nMap["SourceMac"] = ncfg.SourceMac
	nMap["NetworkAdapterName"] = ncfg.NetworkAdapterName

	return json.Marshal(nMap)
}

func (ncfg *networkConfiguration) UnmarshalJSON(b []byte) error {
	var (
		err  error
		nMap map[string]interface{}
	)

	if err = json.Unmarshal(b, &nMap); err != nil {
		return err
	}

	ncfg.ID = nMap["ID"].(string)
	ncfg.Type = nMap["Type"].(string)
	ncfg.Name = nMap["Name"].(string)
	ncfg.HnsID = nMap["HnsID"].(string)
	ncfg.VLAN = uint(nMap["VLAN"].(float64))
	ncfg.VSID = uint(nMap["VSID"].(float64))
	ncfg.DNSServers = nMap["DNSServers"].(string)
	ncfg.DNSSuffix = nMap["DNSSuffix"].(string)
	ncfg.SourceMac = nMap["SourceMac"].(string)
	ncfg.NetworkAdapterName = nMap["NetworkAdapterName"].(string)
	return nil
}

func (ncfg *networkConfiguration) Key() []string {
	return []string{windowsPrefix + ncfg.Type, ncfg.ID}
}

func (ncfg *networkConfiguration) KeyPrefix() []string {
	return []string{windowsPrefix + ncfg.Type}
}

func (ncfg *networkConfiguration) Value() []byte {
	b, err := json.Marshal(ncfg)
	if err != nil {
		return nil
	}
	return b
}

func (ncfg *networkConfiguration) SetValue(value []byte) error {
	return json.Unmarshal(value, ncfg)
}

func (ncfg *networkConfiguration) Index() uint64 {
	return ncfg.dbIndex
}

func (ncfg *networkConfiguration) SetIndex(index uint64) {
	ncfg.dbIndex = index
	ncfg.dbExists = true
}

func (ncfg *networkConfiguration) Exists() bool {
	return ncfg.dbExists
}

func (ncfg *networkConfiguration) Skip() bool {
	return false
}

func (ncfg *networkConfiguration) New() datastore.KVObject {
	return &networkConfiguration{Type: ncfg.Type}
}

func (ncfg *networkConfiguration) CopyTo(o datastore.KVObject) error {
	dstNcfg := o.(*networkConfiguration)
	*dstNcfg = *ncfg
	return nil
}

func (ncfg *networkConfiguration) DataScope() string {
	return datastore.LocalScope
}

func (ep *hnsEndpoint) MarshalJSON() ([]byte, error) {
	epMap := make(map[string]interface{})
	epMap["id"] = ep.id
	epMap["nid"] = ep.nid
	epMap["Type"] = ep.Type
	epMap["profileID"] = ep.profileID
	epMap["MacAddress"] = ep.macAddress.String()
	if ep.addr.IP != nil {
		epMap["Addr"] = ep.addr.String()
	}
	if ep.gateway != nil {
		epMap["gateway"] = ep.gateway.String()
	}
	epMap["epOption"] = ep.epOption
	epMap["epConnectivity"] = ep.epConnectivity
	epMap["PortMapping"] = ep.portMapping

	return json.Marshal(epMap)
}

func (ep *hnsEndpoint) UnmarshalJSON(b []byte) error {
	var (
		err   error
		epMap map[string]interface{}
	)

	if err = json.Unmarshal(b, &epMap); err != nil {
		return fmt.Errorf("Failed to unmarshal to endpoint: %v", err)
	}
	if v, ok := epMap["MacAddress"]; ok {
		if ep.macAddress, err = net.ParseMAC(v.(string)); err != nil {
			return types.InternalErrorf("failed to decode endpoint MAC address (%s) after json unmarshal: %v", v.(string), err)
		}
	}
	if v, ok := epMap["Addr"]; ok {
		if ep.addr, err = types.ParseCIDR(v.(string)); err != nil {
			return types.InternalErrorf("failed to decode endpoint IPv4 address (%s) after json unmarshal: %v", v.(string), err)
		}
	}
	if v, ok := epMap["gateway"]; ok {
		ep.gateway = net.ParseIP(v.(string))
	}
	ep.id = epMap["id"].(string)
	ep.Type = epMap["Type"].(string)
	ep.nid = epMap["nid"].(string)
	ep.profileID = epMap["profileID"].(string)
	d, _ := json.Marshal(epMap["epOption"])
	if err := json.Unmarshal(d, &ep.epOption); err != nil {
		logrus.Warnf("Failed to decode endpoint container config %v", err)
	}
	d, _ = json.Marshal(epMap["epConnectivity"])
	if err := json.Unmarshal(d, &ep.epConnectivity); err != nil {
		logrus.Warnf("Failed to decode endpoint external connectivity configuration %v", err)
	}
	d, _ = json.Marshal(epMap["PortMapping"])
	if err := json.Unmarshal(d, &ep.portMapping); err != nil {
		logrus.Warnf("Failed to decode endpoint port mapping %v", err)
	}

	return nil
}

func (ep *hnsEndpoint) Key() []string {
	return []string{windowsEndpointPrefix + ep.Type, ep.id}
}

func (ep *hnsEndpoint) KeyPrefix() []string {
	return []string{windowsEndpointPrefix + ep.Type}
}

func (ep *hnsEndpoint) Value() []byte {
	b, err := json.Marshal(ep)
	if err != nil {
		return nil
	}
	return b
}

func (ep *hnsEndpoint) SetValue(value []byte) error {
	return json.Unmarshal(value, ep)
}

func (ep *hnsEndpoint) Index() uint64 {
	return ep.dbIndex
}

func (ep *hnsEndpoint) SetIndex(index uint64) {
	ep.dbIndex = index
	ep.dbExists = true
}

func (ep *hnsEndpoint) Exists() bool {
	return ep.dbExists
}

func (ep *hnsEndpoint) Skip() bool {
	return false
}

func (ep *hnsEndpoint) New() datastore.KVObject {
	return &hnsEndpoint{Type: ep.Type}
}

func (ep *hnsEndpoint) CopyTo(o datastore.KVObject) error {
	dstEp := o.(*hnsEndpoint)
	*dstEp = *ep
	return nil
}

func (ep *hnsEndpoint) DataScope() string {
	return datastore.LocalScope
}
<|endoftext|>


<commit_before>package dynect

import (
	"strings"
	"testing"

	"github.com/dnaeon/go-vcr/recorder"
)

// test helper to setup convenient client with vcr cassette
func withConvenientClient(cassetteName string, f func(*ConvenientClient)) {
	withCassette(cassetteName, func(r *recorder.Recorder) {
		c := NewConvenientClient(DynCustomerName)
		c.SetTransport(r)
		c.Verbose(true)

		f(c)
	})
}

// test helper to setup authenticated convenient client with vcr cassette
func testWithConvenientClientSession(cassetteName string, t *testing.T, f func(*ConvenientClient)) {
	withConvenientClient(cassetteName, func(c *ConvenientClient) {
		if err := c.Login(DynUsername, DynPassword); err != nil {
			t.Error(err)
		}

		defer func() {
			if err := c.Logout(); err != nil {
				t.Error(err)
			}
		}()

		f(c)
	})
}

func TestConvenientLoginLogout(t *testing.T) {
	withConvenientClient("fixtures/login_logout", func(c *ConvenientClient) {
		if err := c.Login(DynUsername, DynPassword); err != nil {
			t.Error(err)
		}

		if err := c.Logout(); err != nil {
			t.Error(err)
		}
	})
}

func TestConvenientGetA(t *testing.T) {
	testWithConvenientClientSession("fixtures/convenient_get_a", t, func(c *ConvenientClient) {
		actual := Record{
			Zone: testZone,
			Type: "A",
			FQDN: "foobar." + testZone,
		}

		if err := c.GetRecordID(&actual); err != nil {
			t.Fatal(err)
		}

		if err := c.GetRecord(&actual); err != nil {
			t.Fatal(err)
		}

		if actual.Value != "10.9.8.7" {
			t.Fatalf("Incorrect value %q for %q (expected %q)", actual.Value, actual.FQDN, "foobar.go-dynect.test.")
		}

		t.Log("OK")
	})
}

func TestConvenientGetANotFound(t *testing.T) {
	testWithConvenientClientSession("fixtures/convenient_get_a_not_found", t, func(c *ConvenientClient) {
		actual := Record{
			Zone: testZone,
			Type: "A",
			FQDN: "unknown." + testZone,
		}

		if err := c.GetRecordID(&actual); err == nil {
			t.Fatalf("Expected error getting %q", actual.FQDN)
		} else if !strings.HasPrefix(err.Error(), "Failed to find Dyn record id:") {
			t.Fatalf("Expected error %q for %q (actual error %q)", "Failed to find Dyn record id:", actual.FQDN, err.Error())
		}

		t.Log("OK")
	})
}

func TestConvenientGetCNAME(t *testing.T) {
	testWithConvenientClientSession("fixtures/convenient_get_cname", t, func(c *ConvenientClient) {
		actual := Record{
			Zone: testZone,
			Type: "CNAME",
			FQDN: "foo." + testZone,
		}

		if err := c.GetRecordID(&actual); err != nil {
			t.Fatal(err)
		}

		if err := c.GetRecord(&actual); err != nil {
			t.Fatal(err)
		}

		if actual.Value != "foobar.go-dynect.test." {
			t.Fatalf("Incorrect value %q (expected %q)", actual.Value, "foobar.go-dynect.test.")
		}

		t.Log("OK")
	})
}
<commit_msg>Add test for ConvenientClient create and publish<commit_after>package dynect

import (
	"strconv"
	"strings"
	"testing"

	"github.com/dnaeon/go-vcr/recorder"
)

// test helper to setup convenient client with vcr cassette
func withConvenientClient(cassetteName string, f func(*ConvenientClient)) {
	withCassette(cassetteName, func(r *recorder.Recorder) {
		c := NewConvenientClient(DynCustomerName)
		c.SetTransport(r)
		c.Verbose(true)

		f(c)
	})
}

// test helper to setup authenticated convenient client with vcr cassette
func testWithConvenientClientSession(cassetteName string, t *testing.T, f func(*ConvenientClient)) {
	withConvenientClient(cassetteName, func(c *ConvenientClient) {
		if err := c.Login(DynUsername, DynPassword); err != nil {
			t.Error(err)
		}

		defer func() {
			if err := c.Logout(); err != nil {
				t.Error(err)
			}
		}()

		f(c)
	})
}

func TestConvenientLoginLogout(t *testing.T) {
	withConvenientClient("fixtures/login_logout", func(c *ConvenientClient) {
		if err := c.Login(DynUsername, DynPassword); err != nil {
			t.Error(err)
		}

		if err := c.Logout(); err != nil {
			t.Error(err)
		}
	})
}

func TestConvenientGetA(t *testing.T) {
	testWithConvenientClientSession("fixtures/convenient_get_a", t, func(c *ConvenientClient) {
		actual := Record{
			Zone: testZone,
			Type: "A",
			FQDN: "foobar." + testZone,
		}

		if err := c.GetRecordID(&actual); err != nil {
			t.Fatal(err)
		}

		if err := c.GetRecord(&actual); err != nil {
			t.Fatal(err)
		}

		if actual.Value != "10.9.8.7" {
			t.Fatalf("Incorrect value %q for %q (expected %q)", actual.Value, actual.FQDN, "foobar.go-dynect.test.")
		}

		t.Log("OK")
	})
}

func TestConvenientGetANotFound(t *testing.T) {
	testWithConvenientClientSession("fixtures/convenient_get_a_not_found", t, func(c *ConvenientClient) {
		actual := Record{
			Zone: testZone,
			Type: "A",
			FQDN: "unknown." + testZone,
		}

		if err := c.GetRecordID(&actual); err == nil {
			t.Fatalf("Expected error getting %q", actual.FQDN)
		} else if !strings.HasPrefix(err.Error(), "Failed to find Dyn record id:") {
			t.Fatalf("Expected error %q for %q (actual error %q)", "Failed to find Dyn record id:", actual.FQDN, err.Error())
		}

		t.Log("OK")
	})
}

func TestConvenientGetCNAME(t *testing.T) {
	testWithConvenientClientSession("fixtures/convenient_get_cname", t, func(c *ConvenientClient) {
		actual := Record{
			Zone: testZone,
			Type: "CNAME",
			FQDN: "foo." + testZone,
		}

		if err := c.GetRecordID(&actual); err != nil {
			t.Fatal(err)
		}

		if err := c.GetRecord(&actual); err != nil {
			t.Fatal(err)
		}

		if actual.Value != "foobar.go-dynect.test." {
			t.Fatalf("Incorrect value %q (expected %q)", actual.Value, "foobar.go-dynect.test.")
		}

		t.Log("OK")
	})
}

func TestConvenientCreateMX(t *testing.T) {
	testWithConvenientClientSession("fixtures/convenient_create_mx", t, func(c *ConvenientClient) {
		record := Record{
			Zone:  testZone,
			Type:  "MX",
			Value: "123 mx.example.com.",
			TTL:   "12345",
		}

		if err := c.CreateRecord(&record); err != nil {
			t.Fatal(err)
		}

		if err := c.PublishZone(testZone); err != nil {
			t.Fatal(err)
		}

		if err := c.GetRecordID(&record); err != nil {
			t.Fatal(err)
		}

		if err := c.GetRecord(&record); err != nil {
			t.Fatal(err)
		}

		if record.FQDN != testZone {
			t.Fatalf("Expected FQDN %q (actual %q)", testZone, record.FQDN)
		}

		id, err := strconv.Atoi(record.ID)
		if err != nil || id <= 0 {
			t.Fatalf("Expected ID to be positive integer (actual %q)", record.ID)
		}

		ttl, err := strconv.Atoi(record.TTL)
		if err != nil || ttl != 12345 {
			t.Fatalf("Expected ID to be 12345 (actual %q)", record.TTL)
		}

		t.Log("OK")
	})
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"github.com/nbari/violetear"
	"strings"
)

func main() {
	trie := violetear.NewTrie()

	trie.Set([]string{""}, "root", "GET")
	trie.Set([]string{":uuid"}, "h_uuid", "ALL")
	trie.Set([]string{"hello", "world", ":uuid", "cuatro"}, "h_hello_world", "GET, POST,     PUT")
	trie.Set([]string{"hello", "world", ":uuidXY"}, "h_hello_world", "GET, POST,     PUT")
	trie.Set([]string{"hello", "world", "last", ":uuid"}, "h_hello_world", "GET, POST,     PUT")
	trie.Set([]string{"hello", "world", "last", "cuad"}, "h_hello_world", "GET, POST,     PUT")
	trie.Set([]string{"hello", "world", "last", "cuatro"}, "h_hello_world", "GET, POST,     PUT")
	trie.Set([]string{"hello", "world", "last"}, "h_hello_world_sopas", "DELETE")
	trie.Set([]string{"hello", "world", "last"}, "h_hello_world_sopas_default", "OPTIONS")
	trie.Set([]string{"hello", "world"}, "h_hello_world", "GET")
	trie.Set([]string{"hello"}, "h_hello", "GET")
	trie.Set([]string{"hola", ":ip", ":uuid"}, "h_uuid", "ALL")
	trie.Set([]string{"hola", ":ip", "last"}, "h_uuid", "ALL")
	trie.Set([]string{"hola", ":uuid", "last"}, "h_uuid", "ALL")
	trie.Set([]string{"hola", ":uuid", ":last"}, "h_uuid", "ALL")

	r, l := trie.Get([]string{"hello", "worldX"})

	if len(r.Handler) > 0 && l {
		fmt.Println(r.Handler, l)
	} else if r.HasRegex {

		//	trie.GetLevel(3)

		fmt.Println("----> ", r, r.HasRegex, l)
		for k, _ := range r.Node {
			if strings.HasPrefix(k, ":") {
				fmt.Println(k)
			}
		}

	}

}
<commit_msg>	modified:   trie.go<commit_after>package main

import (
	"fmt"
	"github.com/nbari/violetear"
	"strings"
)

func main() {
	trie := violetear.NewTrie()

	trie.Set([]string{""}, "root", "GET")
	trie.Set([]string{":uuid", ":uuid2"}, "h_uuid", "ALL")
	trie.Set([]string{":uuid"}, "h_uuid", "ALL")
	trie.Set([]string{"hello", "world", ":uuid", "cuatro"}, "h_hello_world", "GET, POST,     PUT")
	trie.Set([]string{"hello", "world", ":uuidXY"}, "h_hello_world", "GET, POST,     PUT")
	trie.Set([]string{"hello", "world", "last", ":uuid"}, "h_hello_world", "GET, POST,     PUT")
	trie.Set([]string{"hello", "world", "last", "cuad"}, "h_hello_world", "GET, POST,     PUT")
	trie.Set([]string{"hello", "world", "last", "cuatro"}, "h_hello_world", "GET, POST,     PUT")
	trie.Set([]string{"hello", "world", "last"}, "h_hello_world_sopas", "DELETE")
	trie.Set([]string{"hello", "world", "last"}, "h_hello_world_sopas_default", "OPTIONS")
	trie.Set([]string{"hello", "world"}, "h_hello_world", "GET")
	trie.Set([]string{"hello"}, "h_hello", "GET")
	trie.Set([]string{"hola", ":ip", ":uuid"}, "h_uuid", "ALL")
	trie.Set([]string{"hola", ":ip", "last"}, "h_uuid", "ALL")
	trie.Set([]string{"hola", ":uuid", ":last"}, "h_uuid", "ALL")
	trie.Set([]string{"hola", ":uuid", "last"}, "h_uuid", "ALL")

	r, l := trie.Get([]string{"hell3o"})

	if len(r.Handler) > 0 && l {
		fmt.Println(r.Handler, l)
	} else if r.HasRegex {
		// search for regex
		fmt.Println("----> ", r, r.HasRegex, l)
		for k, _ := range r.Node {
			if strings.HasPrefix(k, ":") {
				fmt.Println(k)
			}
		}

	} else {
		fmt.Println("no path", r)
	}

}
<|endoftext|>


<commit_before>package merkledag

import (
	"fmt"
	"sort"

	mh "gx/ipfs/QmYf7ng2hG5XBtJA3tN34DQ2GUN5HNksEw1rLDkmr6vGku/go-multihash"

	pb "github.com/ipfs/go-ipfs/merkledag/pb"
	u "gx/ipfs/QmZNVWh8LLjAavuQ2JXuFmuYH3C11xo988vSgp7UQrTRj1/go-ipfs-util"
)

// for now, we use a PBNode intermediate thing.
// because native go objects are nice.

// unmarshal decodes raw data into a *Node instance.
// The conversion uses an intermediate PBNode.
func (n *Node) unmarshal(encoded []byte) error {
	var pbn pb.PBNode
	if err := pbn.Unmarshal(encoded); err != nil {
		return fmt.Errorf("Unmarshal failed. %v", err)
	}

	pbnl := pbn.GetLinks()
	n.Links = make([]*Link, len(pbnl))
	for i, l := range pbnl {
		n.Links[i] = &Link{Name: l.GetName(), Size: l.GetTsize()}
		h, err := mh.Cast(l.GetHash())
		if err != nil {
			return fmt.Errorf("Link hash #%d is not valid multihash. %v", i, err)
		}
		n.Links[i].Hash = h
	}
	sort.Stable(LinkSlice(n.Links)) // keep links sorted

	n.Data = pbn.GetData()
	return nil
}

// Marshal encodes a *Node instance into a new byte slice.
// The conversion uses an intermediate PBNode.
func (n *Node) Marshal() ([]byte, error) {
	pbn := n.GetPBNode()
	data, err := pbn.Marshal()
	if err != nil {
		return data, fmt.Errorf("Marshal failed. %v", err)
	}
	return data, nil
}

func (n *Node) GetPBNode() *pb.PBNode {
	pbn := &pb.PBNode{}
	if len(n.Links) > 0 {
		pbn.Links = make([]*pb.PBLink, len(n.Links))
	}

	sort.Stable(LinkSlice(n.Links)) // keep links sorted
	for i, l := range n.Links {
		pbn.Links[i] = &pb.PBLink{}
		pbn.Links[i].Name = &l.Name
		pbn.Links[i].Tsize = &l.Size
		pbn.Links[i].Hash = []byte(l.Hash)
	}

	if len(n.Data) > 0 {
		pbn.Data = n.Data
	}

	return pbn
}

// EncodeProtobuf returns the encoded raw data version of a Node instance.
// It may use a cached encoded version, unless the force flag is given.
func (n *Node) EncodeProtobuf(force bool) ([]byte, error) {
	sort.Stable(LinkSlice(n.Links)) // keep links sorted
	if n.encoded == nil || force {
		var err error
		n.encoded, err = n.Marshal()
		if err != nil {
			return nil, err
		}
		n.cached = u.Hash(n.encoded)
	}

	return n.encoded, nil
}

// Decoded decodes raw data and returns a new Node instance.
func DecodeProtobuf(encoded []byte) (*Node, error) {
	n := new(Node)
	err := n.unmarshal(encoded)
	if err != nil {
		return nil, fmt.Errorf("incorrectly formatted merkledag node: %s", err)
	}
	return n, nil
}
<commit_msg>Filestore: Cleanup<commit_after>package merkledag

import (
	"fmt"
	"sort"

	mh "gx/ipfs/QmYf7ng2hG5XBtJA3tN34DQ2GUN5HNksEw1rLDkmr6vGku/go-multihash"

	pb "github.com/ipfs/go-ipfs/merkledag/pb"
	u "gx/ipfs/QmZNVWh8LLjAavuQ2JXuFmuYH3C11xo988vSgp7UQrTRj1/go-ipfs-util"
)

// for now, we use a PBNode intermediate thing.
// because native go objects are nice.

// unmarshal decodes raw data into a *Node instance.
// The conversion uses an intermediate PBNode.
func (n *Node) unmarshal(encoded []byte) error {
	var pbn pb.PBNode
	if err := pbn.Unmarshal(encoded); err != nil {
		return fmt.Errorf("Unmarshal failed. %v", err)
	}

	pbnl := pbn.GetLinks()
	n.Links = make([]*Link, len(pbnl))
	for i, l := range pbnl {
		n.Links[i] = &Link{Name: l.GetName(), Size: l.GetTsize()}
		h, err := mh.Cast(l.GetHash())
		if err != nil {
			return fmt.Errorf("Link hash #%d is not valid multihash. %v", i, err)
		}
		n.Links[i].Hash = h
	}
	sort.Stable(LinkSlice(n.Links)) // keep links sorted

	n.Data = pbn.GetData()
	return nil
}

// Marshal encodes a *Node instance into a new byte slice.
// The conversion uses an intermediate PBNode.
func (n *Node) Marshal() ([]byte, error) {
	pbn := n.getPBNode()
	data, err := pbn.Marshal()
	if err != nil {
		return data, fmt.Errorf("Marshal failed. %v", err)
	}
	return data, nil
}

func (n *Node) getPBNode() *pb.PBNode {
	pbn := &pb.PBNode{}
	if len(n.Links) > 0 {
		pbn.Links = make([]*pb.PBLink, len(n.Links))
	}

	sort.Stable(LinkSlice(n.Links)) // keep links sorted
	for i, l := range n.Links {
		pbn.Links[i] = &pb.PBLink{}
		pbn.Links[i].Name = &l.Name
		pbn.Links[i].Tsize = &l.Size
		pbn.Links[i].Hash = []byte(l.Hash)
	}

	if len(n.Data) > 0 {
		pbn.Data = n.Data
	}
	return pbn
}

// EncodeProtobuf returns the encoded raw data version of a Node instance.
// It may use a cached encoded version, unless the force flag is given.
func (n *Node) EncodeProtobuf(force bool) ([]byte, error) {
	sort.Stable(LinkSlice(n.Links)) // keep links sorted
	if n.encoded == nil || force {
		var err error
		n.encoded, err = n.Marshal()
		if err != nil {
			return nil, err
		}
		n.cached = u.Hash(n.encoded)
	}

	return n.encoded, nil
}

// Decoded decodes raw data and returns a new Node instance.
func DecodeProtobuf(encoded []byte) (*Node, error) {
	n := new(Node)
	err := n.unmarshal(encoded)
	if err != nil {
		return nil, fmt.Errorf("incorrectly formatted merkledag node: %s", err)
	}
	return n, nil
}
<|endoftext|>


<commit_before>// +build linux

package fs

import (
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"path/filepath"
	"sync"

	"github.com/opencontainers/runc/libcontainer/cgroups"
	"github.com/opencontainers/runc/libcontainer/configs"
	libcontainerUtils "github.com/opencontainers/runc/libcontainer/utils"
)

var (
	subsystems = subsystemSet{
		&CpusetGroup{},
		&DevicesGroup{},
		&MemoryGroup{},
		&CpuGroup{},
		&CpuacctGroup{},
		&PidsGroup{},
		&BlkioGroup{},
		&HugetlbGroup{},
		&NetClsGroup{},
		&NetPrioGroup{},
		&PerfEventGroup{},
		&FreezerGroup{},
		&NameGroup{GroupName: "name=systemd", Join: true},
	}
	HugePageSizes, _ = cgroups.GetHugePageSize()
)

var errSubsystemDoesNotExist = errors.New("cgroup: subsystem does not exist")

type subsystemSet []subsystem

func (s subsystemSet) Get(name string) (subsystem, error) {
	for _, ss := range s {
		if ss.Name() == name {
			return ss, nil
		}
	}
	return nil, errSubsystemDoesNotExist
}

type subsystem interface {
	// Name returns the name of the subsystem.
	Name() string
	// Returns the stats, as 'stats', corresponding to the cgroup under 'path'.
	GetStats(path string, stats *cgroups.Stats) error
	// Removes the cgroup represented by 'cgroupData'.
	Remove(*cgroupData) error
	// Creates and joins the cgroup represented by 'cgroupData'.
	Apply(*cgroupData) error
	// Set the cgroup represented by cgroup.
	Set(path string, cgroup *configs.Cgroup) error
}

type Manager struct {
	mu      sync.Mutex
	Cgroups *configs.Cgroup
	Paths   map[string]string
}

// The absolute path to the root of the cgroup hierarchies.
var cgroupRootLock sync.Mutex
var cgroupRoot string

// Gets the cgroupRoot.
func getCgroupRoot() (string, error) {
	cgroupRootLock.Lock()
	defer cgroupRootLock.Unlock()

	if cgroupRoot != "" {
		return cgroupRoot, nil
	}

	root, err := cgroups.FindCgroupMountpointDir()
	if err != nil {
		return "", err
	}

	if _, err := os.Stat(root); err != nil {
		return "", err
	}

	cgroupRoot = root
	return cgroupRoot, nil
}

type cgroupData struct {
	root      string
	innerPath string
	config    *configs.Cgroup
	pid       int
}

func (m *Manager) Apply(pid int) (err error) {
	if m.Cgroups == nil {
		return nil
	}
	m.mu.Lock()
	defer m.mu.Unlock()

	var c = m.Cgroups

	d, err := getCgroupData(m.Cgroups, pid)
	if err != nil {
		return err
	}

	if c.Paths != nil {
		paths := make(map[string]string)
		for name, path := range c.Paths {
			_, err := d.path(name)
			if err != nil {
				if cgroups.IsNotFound(err) {
					continue
				}
				return err
			}
			paths[name] = path
		}
		m.Paths = paths
		return cgroups.EnterPid(m.Paths, pid)
	}

	paths := make(map[string]string)
	for _, sys := range subsystems {
		if err := sys.Apply(d); err != nil {
			return err
		}
		// TODO: Apply should, ideally, be reentrant or be broken up into a separate
		// create and join phase so that the cgroup hierarchy for a container can be
		// created then join consists of writing the process pids to cgroup.procs
		p, err := d.path(sys.Name())
		if err != nil {
			// The non-presence of the devices subsystem is
			// considered fatal for security reasons.
			if cgroups.IsNotFound(err) && sys.Name() != "devices" {
				continue
			}
			return err
		}
		paths[sys.Name()] = p
	}
	m.Paths = paths
	return nil
}

func (m *Manager) Destroy() error {
	if m.Cgroups.Paths != nil {
		return nil
	}
	m.mu.Lock()
	defer m.mu.Unlock()
	if err := cgroups.RemovePaths(m.Paths); err != nil {
		return err
	}
	m.Paths = make(map[string]string)
	return nil
}

func (m *Manager) GetPaths() map[string]string {
	m.mu.Lock()
	paths := m.Paths
	m.mu.Unlock()
	return paths
}

func (m *Manager) GetStats() (*cgroups.Stats, error) {
	m.mu.Lock()
	defer m.mu.Unlock()
	stats := cgroups.NewStats()
	for name, path := range m.Paths {
		sys, err := subsystems.Get(name)
		if err == errSubsystemDoesNotExist || !cgroups.PathExists(path) {
			continue
		}
		if err := sys.GetStats(path, stats); err != nil {
			return nil, err
		}
	}
	return stats, nil
}

func (m *Manager) Set(container *configs.Config) error {
	// If Paths are set, then we are just joining cgroups paths
	// and there is no need to set any values.
	if m.Cgroups.Paths != nil {
		return nil
	}
	for _, sys := range subsystems {
		// Generate fake cgroup data.
		d, err := getCgroupData(container.Cgroups, -1)
		if err != nil {
			return err
		}
		// Get the path, but don't error out if the cgroup wasn't found.
		path, err := d.path(sys.Name())
		if err != nil && !cgroups.IsNotFound(err) {
			return err
		}

		if err := sys.Set(path, container.Cgroups); err != nil {
			return err
		}
	}

	if m.Paths["cpu"] != "" {
		if err := CheckCpushares(m.Paths["cpu"], container.Cgroups.Resources.CpuShares); err != nil {
			return err
		}
	}
	return nil
}

// Freeze toggles the container's freezer cgroup depending on the state
// provided
func (m *Manager) Freeze(state configs.FreezerState) error {
	d, err := getCgroupData(m.Cgroups, 0)
	if err != nil {
		return err
	}
	dir, err := d.path("freezer")
	if err != nil {
		return err
	}
	prevState := m.Cgroups.Resources.Freezer
	m.Cgroups.Resources.Freezer = state
	freezer, err := subsystems.Get("freezer")
	if err != nil {
		return err
	}
	err = freezer.Set(dir, m.Cgroups)
	if err != nil {
		m.Cgroups.Resources.Freezer = prevState
		return err
	}
	return nil
}

func (m *Manager) GetPids() ([]int, error) {
	dir, err := getCgroupPath(m.Cgroups)
	if err != nil {
		return nil, err
	}
	return cgroups.GetPids(dir)
}

func (m *Manager) GetAllPids() ([]int, error) {
	dir, err := getCgroupPath(m.Cgroups)
	if err != nil {
		return nil, err
	}
	return cgroups.GetAllPids(dir)
}

func getCgroupPath(c *configs.Cgroup) (string, error) {
	d, err := getCgroupData(c, 0)
	if err != nil {
		return "", err
	}

	return d.path("devices")
}

func getCgroupData(c *configs.Cgroup, pid int) (*cgroupData, error) {
	root, err := getCgroupRoot()
	if err != nil {
		return nil, err
	}

	if (c.Name != "" || c.Parent != "") && c.Path != "" {
		return nil, fmt.Errorf("cgroup: either Path or Name and Parent should be used")
	}

	// XXX: Do not remove this code. Path safety is important! -- cyphar
	cgPath := libcontainerUtils.CleanPath(c.Path)
	cgParent := libcontainerUtils.CleanPath(c.Parent)
	cgName := libcontainerUtils.CleanPath(c.Name)

	innerPath := cgPath
	if innerPath == "" {
		innerPath = filepath.Join(cgParent, cgName)
	}

	return &cgroupData{
		root:      root,
		innerPath: innerPath,
		config:    c,
		pid:       pid,
	}, nil
}

func (raw *cgroupData) parentPath(subsystem, mountpoint, root string) (string, error) {
	// Use GetThisCgroupDir instead of GetInitCgroupDir, because the creating
	// process could in container and shared pid namespace with host, and
	// /proc/1/cgroup could point to whole other world of cgroups.
	initPath, err := cgroups.GetThisCgroupDir(subsystem)
	if err != nil {
		return "", err
	}
	// This is needed for nested containers, because in /proc/self/cgroup we
	// see pathes from host, which don't exist in container.
	relDir, err := filepath.Rel(root, initPath)
	if err != nil {
		return "", err
	}
	return filepath.Join(mountpoint, relDir), nil
}

func (raw *cgroupData) path(subsystem string) (string, error) {
	mnt, root, err := cgroups.FindCgroupMountpointAndRoot(subsystem)
	// If we didn't mount the subsystem, there is no point we make the path.
	if err != nil {
		return "", err
	}

	// If the cgroup name/path is absolute do not look relative to the cgroup of the init process.
	if filepath.IsAbs(raw.innerPath) {
		// Sometimes subsystems can be mounted togethger as 'cpu,cpuacct'.
		return filepath.Join(raw.root, filepath.Base(mnt), raw.innerPath), nil
	}

	parentPath, err := raw.parentPath(subsystem, mnt, root)
	if err != nil {
		return "", err
	}

	return filepath.Join(parentPath, raw.innerPath), nil
}

func (raw *cgroupData) join(subsystem string) (string, error) {
	path, err := raw.path(subsystem)
	if err != nil {
		return "", err
	}
	if err := os.MkdirAll(path, 0755); err != nil {
		return "", err
	}
	if err := cgroups.WriteCgroupProc(path, raw.pid); err != nil {
		return "", err
	}
	return path, nil
}

func writeFile(dir, file, data string) error {
	// Normally dir should not be empty, one case is that cgroup subsystem
	// is not mounted, we will get empty dir, and we want it fail here.
	if dir == "" {
		return fmt.Errorf("no such directory for %s", file)
	}
	if err := ioutil.WriteFile(filepath.Join(dir, file), []byte(data), 0700); err != nil {
		return fmt.Errorf("failed to write %v to %v: %v", data, file, err)
	}
	return nil
}

func readFile(dir, file string) (string, error) {
	data, err := ioutil.ReadFile(filepath.Join(dir, file))
	return string(data), err
}

func removePath(p string, err error) error {
	if err != nil {
		return err
	}
	if p != "" {
		return os.RemoveAll(p)
	}
	return nil
}

func CheckCpushares(path string, c int64) error {
	var cpuShares int64

	if c == 0 {
		return nil
	}

	fd, err := os.Open(filepath.Join(path, "cpu.shares"))
	if err != nil {
		return err
	}
	defer fd.Close()

	_, err = fmt.Fscanf(fd, "%d", &cpuShares)
	if err != nil && err != io.EOF {
		return err
	}

	if c > cpuShares {
		return fmt.Errorf("The maximum allowed cpu-shares is %d", cpuShares)
	} else if c < cpuShares {
		return fmt.Errorf("The minimum allowed cpu-shares is %d", cpuShares)
	}

	return nil
}
<commit_msg>Fix runc ps issue<commit_after>// +build linux

package fs

import (
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"path/filepath"
	"sync"

	"github.com/opencontainers/runc/libcontainer/cgroups"
	"github.com/opencontainers/runc/libcontainer/configs"
	libcontainerUtils "github.com/opencontainers/runc/libcontainer/utils"
)

var (
	subsystems = subsystemSet{
		&CpusetGroup{},
		&DevicesGroup{},
		&MemoryGroup{},
		&CpuGroup{},
		&CpuacctGroup{},
		&PidsGroup{},
		&BlkioGroup{},
		&HugetlbGroup{},
		&NetClsGroup{},
		&NetPrioGroup{},
		&PerfEventGroup{},
		&FreezerGroup{},
		&NameGroup{GroupName: "name=systemd", Join: true},
	}
	HugePageSizes, _ = cgroups.GetHugePageSize()
)

var errSubsystemDoesNotExist = errors.New("cgroup: subsystem does not exist")

type subsystemSet []subsystem

func (s subsystemSet) Get(name string) (subsystem, error) {
	for _, ss := range s {
		if ss.Name() == name {
			return ss, nil
		}
	}
	return nil, errSubsystemDoesNotExist
}

type subsystem interface {
	// Name returns the name of the subsystem.
	Name() string
	// Returns the stats, as 'stats', corresponding to the cgroup under 'path'.
	GetStats(path string, stats *cgroups.Stats) error
	// Removes the cgroup represented by 'cgroupData'.
	Remove(*cgroupData) error
	// Creates and joins the cgroup represented by 'cgroupData'.
	Apply(*cgroupData) error
	// Set the cgroup represented by cgroup.
	Set(path string, cgroup *configs.Cgroup) error
}

type Manager struct {
	mu      sync.Mutex
	Cgroups *configs.Cgroup
	Paths   map[string]string
}

// The absolute path to the root of the cgroup hierarchies.
var cgroupRootLock sync.Mutex
var cgroupRoot string

// Gets the cgroupRoot.
func getCgroupRoot() (string, error) {
	cgroupRootLock.Lock()
	defer cgroupRootLock.Unlock()

	if cgroupRoot != "" {
		return cgroupRoot, nil
	}

	root, err := cgroups.FindCgroupMountpointDir()
	if err != nil {
		return "", err
	}

	if _, err := os.Stat(root); err != nil {
		return "", err
	}

	cgroupRoot = root
	return cgroupRoot, nil
}

type cgroupData struct {
	root      string
	innerPath string
	config    *configs.Cgroup
	pid       int
}

func (m *Manager) Apply(pid int) (err error) {
	if m.Cgroups == nil {
		return nil
	}
	m.mu.Lock()
	defer m.mu.Unlock()

	var c = m.Cgroups

	d, err := getCgroupData(m.Cgroups, pid)
	if err != nil {
		return err
	}

	if c.Paths != nil {
		paths := make(map[string]string)
		for name, path := range c.Paths {
			_, err := d.path(name)
			if err != nil {
				if cgroups.IsNotFound(err) {
					continue
				}
				return err
			}
			paths[name] = path
		}
		m.Paths = paths
		return cgroups.EnterPid(m.Paths, pid)
	}

	paths := make(map[string]string)
	for _, sys := range subsystems {
		if err := sys.Apply(d); err != nil {
			return err
		}
		// TODO: Apply should, ideally, be reentrant or be broken up into a separate
		// create and join phase so that the cgroup hierarchy for a container can be
		// created then join consists of writing the process pids to cgroup.procs
		p, err := d.path(sys.Name())
		if err != nil {
			// The non-presence of the devices subsystem is
			// considered fatal for security reasons.
			if cgroups.IsNotFound(err) && sys.Name() != "devices" {
				continue
			}
			return err
		}
		paths[sys.Name()] = p
	}
	m.Paths = paths
	return nil
}

func (m *Manager) Destroy() error {
	if m.Cgroups.Paths != nil {
		return nil
	}
	m.mu.Lock()
	defer m.mu.Unlock()
	if err := cgroups.RemovePaths(m.Paths); err != nil {
		return err
	}
	m.Paths = make(map[string]string)
	return nil
}

func (m *Manager) GetPaths() map[string]string {
	m.mu.Lock()
	paths := m.Paths
	m.mu.Unlock()
	return paths
}

func (m *Manager) GetStats() (*cgroups.Stats, error) {
	m.mu.Lock()
	defer m.mu.Unlock()
	stats := cgroups.NewStats()
	for name, path := range m.Paths {
		sys, err := subsystems.Get(name)
		if err == errSubsystemDoesNotExist || !cgroups.PathExists(path) {
			continue
		}
		if err := sys.GetStats(path, stats); err != nil {
			return nil, err
		}
	}
	return stats, nil
}

func (m *Manager) Set(container *configs.Config) error {
	// If Paths are set, then we are just joining cgroups paths
	// and there is no need to set any values.
	if m.Cgroups.Paths != nil {
		return nil
	}
	for _, sys := range subsystems {
		// Generate fake cgroup data.
		d, err := getCgroupData(container.Cgroups, -1)
		if err != nil {
			return err
		}
		// Get the path, but don't error out if the cgroup wasn't found.
		path, err := d.path(sys.Name())
		if err != nil && !cgroups.IsNotFound(err) {
			return err
		}

		if err := sys.Set(path, container.Cgroups); err != nil {
			return err
		}
	}

	if m.Paths["cpu"] != "" {
		if err := CheckCpushares(m.Paths["cpu"], container.Cgroups.Resources.CpuShares); err != nil {
			return err
		}
	}
	return nil
}

// Freeze toggles the container's freezer cgroup depending on the state
// provided
func (m *Manager) Freeze(state configs.FreezerState) error {
	d, err := getCgroupData(m.Cgroups, 0)
	if err != nil {
		return err
	}
	dir, err := d.path("freezer")
	if err != nil {
		return err
	}
	prevState := m.Cgroups.Resources.Freezer
	m.Cgroups.Resources.Freezer = state
	freezer, err := subsystems.Get("freezer")
	if err != nil {
		return err
	}
	err = freezer.Set(dir, m.Cgroups)
	if err != nil {
		m.Cgroups.Resources.Freezer = prevState
		return err
	}
	return nil
}

func (m *Manager) GetPids() ([]int, error) {
	paths := m.GetPaths()
	return cgroups.GetPids(paths["devices"])
}

func (m *Manager) GetAllPids() ([]int, error) {
	paths := m.GetPaths()
	return cgroups.GetAllPids(paths["devices"])
}

func getCgroupData(c *configs.Cgroup, pid int) (*cgroupData, error) {
	root, err := getCgroupRoot()
	if err != nil {
		return nil, err
	}

	if (c.Name != "" || c.Parent != "") && c.Path != "" {
		return nil, fmt.Errorf("cgroup: either Path or Name and Parent should be used")
	}

	// XXX: Do not remove this code. Path safety is important! -- cyphar
	cgPath := libcontainerUtils.CleanPath(c.Path)
	cgParent := libcontainerUtils.CleanPath(c.Parent)
	cgName := libcontainerUtils.CleanPath(c.Name)

	innerPath := cgPath
	if innerPath == "" {
		innerPath = filepath.Join(cgParent, cgName)
	}

	return &cgroupData{
		root:      root,
		innerPath: innerPath,
		config:    c,
		pid:       pid,
	}, nil
}

func (raw *cgroupData) parentPath(subsystem, mountpoint, root string) (string, error) {
	// Use GetThisCgroupDir instead of GetInitCgroupDir, because the creating
	// process could in container and shared pid namespace with host, and
	// /proc/1/cgroup could point to whole other world of cgroups.
	initPath, err := cgroups.GetThisCgroupDir(subsystem)
	if err != nil {
		return "", err
	}
	// This is needed for nested containers, because in /proc/self/cgroup we
	// see pathes from host, which don't exist in container.
	relDir, err := filepath.Rel(root, initPath)
	if err != nil {
		return "", err
	}
	return filepath.Join(mountpoint, relDir), nil
}

func (raw *cgroupData) path(subsystem string) (string, error) {
	mnt, root, err := cgroups.FindCgroupMountpointAndRoot(subsystem)
	// If we didn't mount the subsystem, there is no point we make the path.
	if err != nil {
		return "", err
	}

	// If the cgroup name/path is absolute do not look relative to the cgroup of the init process.
	if filepath.IsAbs(raw.innerPath) {
		// Sometimes subsystems can be mounted togethger as 'cpu,cpuacct'.
		return filepath.Join(raw.root, filepath.Base(mnt), raw.innerPath), nil
	}

	parentPath, err := raw.parentPath(subsystem, mnt, root)
	if err != nil {
		return "", err
	}

	return filepath.Join(parentPath, raw.innerPath), nil
}

func (raw *cgroupData) join(subsystem string) (string, error) {
	path, err := raw.path(subsystem)
	if err != nil {
		return "", err
	}
	if err := os.MkdirAll(path, 0755); err != nil {
		return "", err
	}
	if err := cgroups.WriteCgroupProc(path, raw.pid); err != nil {
		return "", err
	}
	return path, nil
}

func writeFile(dir, file, data string) error {
	// Normally dir should not be empty, one case is that cgroup subsystem
	// is not mounted, we will get empty dir, and we want it fail here.
	if dir == "" {
		return fmt.Errorf("no such directory for %s", file)
	}
	if err := ioutil.WriteFile(filepath.Join(dir, file), []byte(data), 0700); err != nil {
		return fmt.Errorf("failed to write %v to %v: %v", data, file, err)
	}
	return nil
}

func readFile(dir, file string) (string, error) {
	data, err := ioutil.ReadFile(filepath.Join(dir, file))
	return string(data), err
}

func removePath(p string, err error) error {
	if err != nil {
		return err
	}
	if p != "" {
		return os.RemoveAll(p)
	}
	return nil
}

func CheckCpushares(path string, c int64) error {
	var cpuShares int64

	if c == 0 {
		return nil
	}

	fd, err := os.Open(filepath.Join(path, "cpu.shares"))
	if err != nil {
		return err
	}
	defer fd.Close()

	_, err = fmt.Fscanf(fd, "%d", &cpuShares)
	if err != nil && err != io.EOF {
		return err
	}

	if c > cpuShares {
		return fmt.Errorf("The maximum allowed cpu-shares is %d", cpuShares)
	} else if c < cpuShares {
		return fmt.Errorf("The minimum allowed cpu-shares is %d", cpuShares)
	}

	return nil
}
<|endoftext|>