<commit_before>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

// Package vect implements a 3D vector type useful in physics and computational
// geometry calculations.
package vect

import (
	"math"
)

// A three component cartesian vector
type Vector []float64

// Create new zero vector
func NewZeroVector() Vector {

	return Vector(make([]float64, 3))
}

// Create new vector
func NewVector(x, y, z float64) Vector {

	v := NewZeroVector()

	v[0], v[1], v[2] = x, y, z

	return v
}

var (
	// A zero vector
	Zero = NewZeroVector()
	// An unit vector along the Cartesian X axis
	UnitX = NewVector(1, 0, 0)
	// An unit vector along the Cartesian Y axis
	UnitY = NewVector(0, 1, 0)
	// An unit vector along the Cartesian Z axis
	UnitZ = NewVector(0, 0, 1)
)

// Copy the vector
func (v Vector) Copy() (u Vector) {

	u = NewZeroVector()

	for i, vComp := range v {

		u[i] = vComp
	}

	return u
}

// Add two vectors
func (a Vector) Plus(b Vector) (c Vector) {

	c = NewZeroVector()

	for i, _ := range a {

		c[i] = a[i] + b[i]
	}

	return c
}

// Invert a vector's direction
func (a Vector) Negate() (minusA Vector) {

	minusA = NewZeroVector()

	for i, aComponent := range a {

		minusA[i] = -aComponent
	}

	return minusA
}

// Subtract two vectors
func (a Vector) Minus(b Vector) Vector {

	return a.Plus(b.Negate())
}

// Take the dot product of two vectors
func (a Vector) Dot(b Vector) float64 {

	sum := 0.0

	for i, _ := range a {

		sum += a[i] * b[i]
	}

	return sum
}

// Calculate the norm of a vector
func (a Vector) Norm() float64 {

	return math.Sqrt(a.Dot(a))
}

// Scale a vector by s
func (a Vector) Scale(s float64) (b Vector) {

	b = a.Copy()

	for i, _ := range a {

		b[i] *= s
	}

	return b
}

// Produce the unit vector oriented the same as a
//
// If the vector is zero -- returns itself
func (a Vector) Unit() Vector {

	if a.Equal(Zero) {

		return a
	}

	return a.Scale(1 / a.Norm())
}

// Calculate a unit vector and the vector norm at once
func (a Vector) UnitAndNorm() (aU Vector, norm float64) {

	return a.Unit(), a.Norm()
}

// Take the cross product of two vectors
func (a Vector) Cross(b Vector) (c Vector) {

	c = NewZeroVector()

	for i, _ := range a {

		c[i] += a[(i+1)%3] * b[(i+2)%3]

		c[i] -= a[(i+2)%3] * b[(i+1)%3]
	}

	return c
}

// Compare two vectors for equality
func (a Vector) Equal(b Vector) bool {

	for i, _ := range a {

		if a[i] != b[i] {

			return false
		}
	}

	return true
}

// Decompose a vector into the part parallel and orthogonal to another one.
func (a Vector) ProjectionRejection(wRespectTo Vector) (prj, rej Vector) {

	prj = wRespectTo.Unit().Scale(a.Dot(wRespectTo))

	rej = a.Minus(prj)

	return prj, rej
}

// Component vector parallel to another one.
func (a Vector) Projection(onto Vector) (prj Vector) {

	prj, _ = a.ProjectionRejection(onto)

	return prj
}

// Component vector orthogonal to another one.
func (a Vector) Rejection(ofOf Vector) (rej Vector) {

	_, rej = a.ProjectionRejection(ofOf)

	return rej
}
<commit_msg>Change vector representation<commit_after>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

// Package vect implements a 3D vector type useful in physics and computational
// geometry calculations.
package vect

import (
	"math"
)

// A three component cartesian vector
type Vector struct {
	x, y, z float64
}

// Create new zero vector
func NewZeroVector() Vector {

	return Vector{}
}

// Create new vector
func NewVector(x, y, z float64) Vector {

	return Vector{x: x, y: y, z: z}
}

var (
	// A zero vector
	Zero = NewZeroVector()
	// An unit vector along the Cartesian X axis
	UnitX = NewVector(1, 0, 0)
	// An unit vector along the Cartesian Y axis
	UnitY = NewVector(0, 1, 0)
	// An unit vector along the Cartesian Z axis
	UnitZ = NewVector(0, 0, 1)
)

// Copy the vector
func (v Vector) Copy() Vector {

	return v
}

// Add two vectors
func (a Vector) Plus(b Vector) Vector {

	return Vector{
		x: a.x + b.x,
		y: a.y + b.y,
		z: a.z + b.z,
	}
}

// Invert a vector's direction
func (a Vector) Negate() Vector {

	return Vector{x: -a.x, y: -a.y, z: -a.z}
}

// Subtract two vectors
func (a Vector) Minus(b Vector) Vector {

	return a.Plus(b.Negate())
}

// Take the dot product of two vectors
func (a Vector) Dot(b Vector) float64 {

	return a.x*b.x + a.y*b.y + a.z*b.z
}

// Calculate the norm of a vector
func (a Vector) Norm() float64 {

	return math.Sqrt(a.Dot(a))
}

// Scale a vector by s
func (a Vector) Scale(s float64) (b Vector) {

	return Vector{x: s * a.x, y: s * a.y, z: s * a.z}
}

// Produce the unit vector oriented the same as a
//
// If the vector is zero -- returns itself
func (a Vector) Unit() Vector {

	if a.Equal(Zero) {

		return a
	}

	return a.Scale(1 / a.Norm())
}

// Calculate a unit vector and the vector norm at once
func (a Vector) UnitAndNorm() (aU Vector, norm float64) {

	return a.Unit(), a.Norm()
}

// Take the cross product of two vectors
func (a Vector) Cross(b Vector) (c Vector) {

	return Vector{
		x: a.y*b.z - a.z*b.y,
		y: a.z*b.x - a.x*b.z,
		z: a.x*b.y - a.y*b.x,
	}
}

// Compare two vectors for equality
func (a Vector) Equal(b Vector) bool {

	return a == b
}

// Decompose a vector into the part parallel and orthogonal to another one.
func (a Vector) ProjectionRejection(wRespectTo Vector) (prj, rej Vector) {

	prj = wRespectTo.Unit().Scale(a.Dot(wRespectTo))

	rej = a.Minus(prj)

	return prj, rej
}

// Component vector parallel to another one.
func (a Vector) Projection(onto Vector) (prj Vector) {

	prj, _ = a.ProjectionRejection(onto)

	return prj
}

// Component vector orthogonal to another one.
func (a Vector) Rejection(ofOf Vector) (rej Vector) {

	_, rej = a.ProjectionRejection(ofOf)

	return rej
}
<|endoftext|>


<commit_before>// Copyright (c) Ilia Kravets, 2015. All rights reserved. PROVIDED "AS IS"
// WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED. See LICENSE file for details.

package main

import (
	"fmt"
	"log"
	"my/itto/verify/cmd"
	"os"

	"github.com/jessevdk/go-flags"
)

func processArgs() {
	var opts struct {
		Verbose     []bool `short:"v" long:"verbose" description:"show verbose debug information"`
		LogFileName string `short:"l" long:"log" value-name:"FILE" default:"/dev/stderr" default-mask:"stderr" description:"log file"`
	}

	parser := flags.NewParser(&opts, flags.PassDoubleDash|flags.HelpFlag|flags.IgnoreUnknown)
	cmd.Registry.ConfigParser(parser)
	if _, err := parser.Parse(); err != nil {
		fmt.Println(err.(*flags.Error).Message)
		os.Exit(1)
	}
	logFile, err := os.OpenFile(opts.LogFileName, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0644)
	if err != nil {
		log.Fatal(err)
	}
	log.SetOutput(logFile)
	defer logFile.Close()
	cmd.Registry.ParsingFinished()
}

func main() {
	os.Setenv("PATH", os.ExpandEnv("$HOME/my/proj/ekaline/esniff/wireshark/build/run:$HOME/wireshark/build/run:$PATH"))
	log.SetFlags(log.Ldate | log.Ltime | log.Lshortfile)
	processArgs()
}
<commit_msg>add --profile-{cpu,mem} options<commit_after>// Copyright (c) Ilia Kravets, 2015. All rights reserved. PROVIDED "AS IS"
// WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED. See LICENSE file for details.

package main

import (
	"fmt"
	"log"
	"my/itto/verify/cmd"
	"os"
	"runtime/pprof"

	"github.com/jessevdk/go-flags"
)

func processArgs() {
	var opts struct {
		Verbose     []bool `short:"v" long:"verbose" description:"show verbose debug information"`
		LogFileName string `short:"l" long:"log" value-name:"FILE" default:"/dev/stderr" default-mask:"stderr" description:"log file"`
		ProfileCpu  string `long:"profile-cpu" value-name:"FILE"`
		ProfileMem  string `long:"profile-mem" value-name:"FILE"`
	}

	parser := flags.NewParser(&opts, flags.PassDoubleDash|flags.HelpFlag|flags.IgnoreUnknown)
	cmd.Registry.ConfigParser(parser)
	if _, err := parser.Parse(); err != nil {
		fmt.Println(err.(*flags.Error).Message)
		os.Exit(1)
	}

	logFile, err := os.OpenFile(opts.LogFileName, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0644)
	if err != nil {
		log.Fatal(err)
	}
	log.SetOutput(logFile)
	defer logFile.Close()

	if opts.ProfileCpu != "" {
		profFile, err := os.Create(opts.ProfileCpu)
		if err != nil {
			log.Fatal(err)
		}
		pprof.StartCPUProfile(profFile)
		defer pprof.StopCPUProfile()
	}

	cmd.Registry.ParsingFinished()

	if opts.ProfileMem != "" {
		profFile, err := os.Create(opts.ProfileMem)
		if err != nil {
			log.Fatal(err)
		}
		pprof.WriteHeapProfile(profFile)
		profFile.Close()
	}
}

func main() {
	os.Setenv("PATH", os.ExpandEnv("$HOME/my/proj/ekaline/esniff/wireshark/build/run:$HOME/wireshark/build/run:$PATH"))
	log.SetFlags(log.Ldate | log.Ltime | log.Lshortfile)
	processArgs()
}
<|endoftext|>


<commit_before>package response

import (
	"sort"
	"strings"

	version "github.com/hashicorp/go-version"
)

// TerraformProvider is the response structure for all required information for
// Terraform to choose a download URL. It must include all versions and all
// platforms for Terraform to perform version and os/arch constraint matching
// locally.
type TerraformProvider struct {
	ID       string `json:"id"`
	Verified bool   `json:"verified"`

	Versions []*TerraformProviderVersion `json:"versions"`
}

// TerraformProviderVersion is the Terraform-specific response structure for a
// provider version.
type TerraformProviderVersion struct {
	Version   string   `json:"version"`
	Protocols []string `json:"protocols"`

	Platforms []*TerraformProviderPlatform `json:"platforms"`
}

// TerraformProviderVersions is the Terraform-specific response structure for an
// array of provider versions
type TerraformProviderVersions struct {
	ID       string                      `json:"id"`
	Versions []*TerraformProviderVersion `json:"versions"`
	Warnings []string                    `json:"warnings"`
}

// TerraformProviderPlatform is the Terraform-specific response structure for a
// provider platform.
type TerraformProviderPlatform struct {
	OS   string `json:"os"`
	Arch string `json:"arch"`
}

// TerraformProviderPlatformLocation is the Terraform-specific response
// structure for a provider platform with all details required to perform a
// download.
type TerraformProviderPlatformLocation struct {
	Protocols           []string `json:"protocols"`
	OS                  string   `json:"os"`
	Arch                string   `json:"arch"`
	Filename            string   `json:"filename"`
	DownloadURL         string   `json:"download_url"`
	ShasumsURL          string   `json:"shasums_url"`
	ShasumsSignatureURL string   `json:"shasums_signature_url"`
	Shasum              string   `json:"shasum"`

	SigningKeys SigningKeyList `json:"signing_keys"`
}

// SigningKeyList is the response structure for a list of signing keys.
type SigningKeyList struct {
	GPGKeys []*GPGKey `json:"gpg_public_keys"`
}

// GPGKey is the response structure for a GPG key.
type GPGKey struct {
	ASCIIArmor string  `json:"ascii_armor"`
	Source     string  `json:"source"`
	SourceURL  *string `json:"source_url"`
}

// Collection type for TerraformProviderVersion
type ProviderVersionCollection []*TerraformProviderVersion

// GPGASCIIArmor returns an ASCII-armor-formatted string for all of the gpg
// keys in the response.
func (signingKeys *SigningKeyList) GPGASCIIArmor() string {
	keys := []string{}

	for _, gpgKey := range signingKeys.GPGKeys {
		keys = append(keys, gpgKey.ASCIIArmor)
	}

	return strings.Join(keys, "\n")
}

// Sort sorts versions from newest to oldest.
func (v ProviderVersionCollection) Sort() {
	sort.Slice(v, func(i, j int) bool {
		versionA, _ := version.NewVersion(v[i].Version)
		versionB, _ := version.NewVersion(v[j].Version)

		return versionA.GreaterThan(versionB)
	})
}
<commit_msg>registry/response: Remove unused verified bool<commit_after>package response

import (
	"sort"
	"strings"

	version "github.com/hashicorp/go-version"
)

// TerraformProvider is the response structure for all required information for
// Terraform to choose a download URL. It must include all versions and all
// platforms for Terraform to perform version and os/arch constraint matching
// locally.
type TerraformProvider struct {
	ID string `json:"id"`

	Versions []*TerraformProviderVersion `json:"versions"`
}

// TerraformProviderVersion is the Terraform-specific response structure for a
// provider version.
type TerraformProviderVersion struct {
	Version   string   `json:"version"`
	Protocols []string `json:"protocols"`

	Platforms []*TerraformProviderPlatform `json:"platforms"`
}

// TerraformProviderVersions is the Terraform-specific response structure for an
// array of provider versions
type TerraformProviderVersions struct {
	ID       string                      `json:"id"`
	Versions []*TerraformProviderVersion `json:"versions"`
	Warnings []string                    `json:"warnings"`
}

// TerraformProviderPlatform is the Terraform-specific response structure for a
// provider platform.
type TerraformProviderPlatform struct {
	OS   string `json:"os"`
	Arch string `json:"arch"`
}

// TerraformProviderPlatformLocation is the Terraform-specific response
// structure for a provider platform with all details required to perform a
// download.
type TerraformProviderPlatformLocation struct {
	Protocols           []string `json:"protocols"`
	OS                  string   `json:"os"`
	Arch                string   `json:"arch"`
	Filename            string   `json:"filename"`
	DownloadURL         string   `json:"download_url"`
	ShasumsURL          string   `json:"shasums_url"`
	ShasumsSignatureURL string   `json:"shasums_signature_url"`
	Shasum              string   `json:"shasum"`

	SigningKeys SigningKeyList `json:"signing_keys"`
}

// SigningKeyList is the response structure for a list of signing keys.
type SigningKeyList struct {
	GPGKeys []*GPGKey `json:"gpg_public_keys"`
}

// GPGKey is the response structure for a GPG key.
type GPGKey struct {
	ASCIIArmor string  `json:"ascii_armor"`
	Source     string  `json:"source"`
	SourceURL  *string `json:"source_url"`
}

// Collection type for TerraformProviderVersion
type ProviderVersionCollection []*TerraformProviderVersion

// GPGASCIIArmor returns an ASCII-armor-formatted string for all of the gpg
// keys in the response.
func (signingKeys *SigningKeyList) GPGASCIIArmor() string {
	keys := []string{}

	for _, gpgKey := range signingKeys.GPGKeys {
		keys = append(keys, gpgKey.ASCIIArmor)
	}

	return strings.Join(keys, "\n")
}

// Sort sorts versions from newest to oldest.
func (v ProviderVersionCollection) Sort() {
	sort.Slice(v, func(i, j int) bool {
		versionA, _ := version.NewVersion(v[i].Version)
		versionB, _ := version.NewVersion(v[j].Version)

		return versionA.GreaterThan(versionB)
	})
}
<|endoftext|>


<commit_before>// Copyright 2014 The Serviced 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 web

import (
	"github.com/control-center/serviced/domain"
)

//profile defines meta-data for the host/pool resource's metrics and graphs
var (
	zero       int = 0
	onehundred int = 100

	zeroInt64 int64 = 0

	hostPoolProfile = domain.MonitorProfile{
		MetricConfigs: []domain.MetricConfig{
			//CPU
			domain.MetricConfig{
				ID:          "cpu",
				Name:        "CPU Usage",
				Description: "CPU Statistics",
				Metrics: []domain.Metric{
					domain.Metric{ID: "cpu.user", Name: "CPU User", Unit: "Percent", Counter: true},
					domain.Metric{ID: "cpu.nice", Name: "CPU Nice", Unit: "Percent", Counter: true},
					domain.Metric{ID: "cpu.system", Name: "CPU System", Unit: "Percent", Counter: true},
					domain.Metric{ID: "cpu.idle", Name: "CPU Idle", Unit: "Percent", Counter: true},
					domain.Metric{ID: "cpu.iowait", Name: "CPU IO Wait", Unit: "Percent", Counter: true},
					domain.Metric{ID: "cpu.irq", Name: "IRQ", Unit: "Percent", Counter: true},
					domain.Metric{ID: "cpu.softirq", Name: "Soft IRQ", Unit: "Percent", Counter: true},
					domain.Metric{ID: "cpu.steal", Name: "CPU Steal", Unit: "Percent", Counter: true},
				},
			},
			//Memory
			domain.MetricConfig{
				ID:          "memory",
				Name:        "Memory Usage",
				Description: "Memory Usage Statistics -- /proc/meminfo",
				Metrics: []domain.Metric{
					domain.Metric{ID: "memory.buffers", Name: "Memory Buffer", Unit: "Bytes"},
					domain.Metric{ID: "memory.cached", Name: "Memory Cache", Unit: "Bytes"},
					domain.Metric{ID: "memory.free", Name: "Memory Free", Unit: "Bytes"},
					domain.Metric{ID: "memory.total", Name: "Total Memory", Unit: "Bytes"},
					domain.Metric{ID: "memory.actualfree", Name: "Actual Free Memory", Unit: "Bytes"},
					domain.Metric{ID: "memory.actualused", Name: "Actual Used Memory", Unit: "Bytes"},
					domain.Metric{ID: "swap.total", Name: "Total Swap", Unit: "Bytes"},
					domain.Metric{ID: "swap.free", Name: "Free Swap", Unit: "Bytes"},
				},
			},
			//Virtual Memory
			domain.MetricConfig{
				ID:          "virtual.memory",
				Name:        "Virtual Memory Usage",
				Description: "Virtual Memory Usage Statistics -- /proc/vmstat",
				Metrics: []domain.Metric{
					domain.Metric{ID: "vmstat.pgfault", Name: "Minor Page Fault", Unit: "Page Faults", Counter: true},
					domain.Metric{ID: "vmstat.pgmajfault", Name: "Major Page Fault", Unit: "Page Faults", Counter: true},
				},
			},
			//Files
			domain.MetricConfig{
				ID:          "files",
				Name:        "File Usage",
				Description: "File Statistics",
				Metrics: []domain.Metric{
					domain.Metric{ID: "Serviced.OpenFileDescriptors", Name: "OpenFileDescriptors", Unit: "Open File Descriptors"},
				},
			},
		},
		ThresholdConfigs: []domain.ThresholdConfig{
			domain.ThresholdConfig{
				ID:           "swap.empty",
				Name:         "Swap empty",
				Description:  "Alert when swap reaches zero",
				MetricSource: "memory",
				DataPoints:   []string{"swap.free", "memory.free"},
				Type:         "MinMax",
				Threshold:    domain.MinMaxThreshold{Min: &zeroInt64, Max: nil},
				EventTags: map[string]interface{}{
					"Severity":    1,
					"Resolution":  "Increase swap or memory",
					"Explanation": "Ran out of all available memory space",
					"EventClass":  "/Perf/Memory",
				},
			},
		},
	}
)

//Open File Descriptors
func newOpenFileDescriptorsGraph(tags map[string][]string) domain.GraphConfig {
	return domain.GraphConfig{
		DataPoints: []domain.DataPoint{
			domain.DataPoint{
				ID:           "ofd",
				Aggregator:   "avg",
				Color:        "#aec7e8",
				Fill:         false,
				Format:       "%4.2f",
				Legend:       "Serviced Open File Descriptors",
				Metric:       "Serviced.OpenFileDescriptors",
				MetricSource: "files",
				Name:         "Serviced Open File Descriptors",
				Rate:         false,
				Type:         "line",
			},
		},
		ID:     "serviced.ofd",
		Name:   "Serviced Open File Descriptors",
		Footer: false,
		Format: "%d",
		MinY:   &zero,
		Range: &domain.GraphConfigRange{
			End:   "0s-ago",
			Start: "1h-ago",
		},
		ReturnSet:   "EXACT",
		Type:        "line",
		Tags:        tags,
		Units:       "File Descriptors",
		Description: "For the serviced process",
	}
}

//Major Page Faults
func newMajorPageFaultGraph(tags map[string][]string) domain.GraphConfig {
	return domain.GraphConfig{
		DataPoints: []domain.DataPoint{
			domain.DataPoint{
				Aggregator:   "avg",
				ID:           "pgfault",
				Color:        "#aec7e8",
				Fill:         false,
				Format:       "%.2f",
				Legend:       "Major Page Faults",
				Metric:       "vmstat.pgmajfault",
				MetricSource: "virtual.memory",
				Name:         "Major Page Faults",
				Rate:         true,
				Type:         "line",
			},
		},
		ID:     "memory.major.pagefault",
		Name:   "Memory Major Page Faults",
		Footer: false,
		Format: "%.2f",
		MinY:   &zero,
		Range: &domain.GraphConfigRange{
			End:   "0s-ago",
			Start: "1h-ago",
		},
		YAxisLabel:  "Faults / Min",
		ReturnSet:   "EXACT",
		Type:        "line",
		Tags:        tags,
		Units:       "Page Faults",
		Description: "Faults per minute",
	}
}

//Cpu Usage
func newCpuConfigGraph(tags map[string][]string, totalCores int) domain.GraphConfig {
	return domain.GraphConfig{
		DataPoints: []domain.DataPoint{
			domain.DataPoint{
				Aggregator:   "avg",
				Color:        "#aee8cf",
				Fill:         false,
				Format:       "%4.2f",
				ID:           "user",
				Legend:       "User",
				Metric:       "cpu.user",
				MetricSource: "cpu",
				Name:         "User",
				Rate:         true,
				Type:         "area",
			},
			domain.DataPoint{
				Aggregator:   "avg",
				Color:        "#729ed7",
				Fill:         false,
				Format:       "%4.2f",
				ID:           "system",
				Legend:       "System",
				Metric:       "cpu.system",
				MetricSource: "cpu",
				Name:         "System",
				Rate:         true,
				Type:         "area",
			},
			domain.DataPoint{
				Aggregator:   "avg",
				Fill:         false,
				Color:        "#d7729e",
				Format:       "%4.2f",
				ID:           "nice",
				Legend:       "Nice",
				Metric:       "cpu.nice",
				MetricSource: "cpu",
				Name:         "Nice",
				Rate:         true,
				Type:         "area",
			},
			domain.DataPoint{
				Aggregator:   "avg",
				Color:        "#e8aec7",
				Fill:         false,
				Format:       "%4.2f",
				ID:           "iowait",
				Legend:       "IOWait",
				Metric:       "cpu.iowait",
				MetricSource: "cpu",
				Name:         "IOWait",
				Rate:         true,
				Type:         "area",
			},
			domain.DataPoint{
				Aggregator:   "avg",
				Color:        "#e8cfae",
				Fill:         false,
				Format:       "%4.2f",
				ID:           "irq",
				Legend:       "IRQ",
				Metric:       "cpu.irq",
				MetricSource: "cpu",
				Name:         "IRQ",
				Rate:         true,
				Type:         "area",
			},
			domain.DataPoint{
				Aggregator:   "avg",
				Color:        "#ff0000",
				Fill:         false,
				Format:       "%4.2f",
				ID:           "steal",
				Legend:       "Steal",
				Metric:       "cpu.steal",
				MetricSource: "cpu",
				Name:         "Steal",
				Rate:         true,
				Type:         "area",
			},
			domain.DataPoint{
				Aggregator:   "avg",
				Color:        "#EBE6EA",
				Fill:         false,
				Format:       "%6.2f",
				ID:           "idle",
				Legend:       "Idle",
				Metric:       "cpu.idle",
				MetricSource: "cpu",
				Name:         "Idle",
				Rate:         true,
				Type:         "area",
			},
		},
		ID:     "cpu.usage",
		Name:   "CPU Usage",
		Footer: false,
		Format: "%d",
		MinY:   &zero,
		Range: &domain.GraphConfigRange{
			End:   "0s-ago",
			Start: "1h-ago",
		},
		YAxisLabel:  "% Used",
		ReturnSet:   "EXACT",
		Type:        "area",
		Tags:        tags,
		Units:       "Percent",
		Description: "Total cpu utilization (all cores)",
	}
}

func newRSSConfigGraph(tags map[string][]string, totalMemory uint64) domain.GraphConfig {
	MaxY := int(totalMemory)
	return domain.GraphConfig{
		DataPoints: []domain.DataPoint{
			domain.DataPoint{
				Aggregator:   "avg",
				Color:        "#e8aec7",
				Fill:         true,
				Format:       "%4.2f",
				Legend:       "Used",
				Metric:       "memory.actualused",
				MetricSource: "memory",
				Name:         "Used",
				Type:         "area",
				ID:           "used",
			},
			domain.DataPoint{
				Aggregator:   "avg",
				Color:        "#b2aee8",
				Fill:         true,
				Format:       "%4.2f",
				Legend:       "Cached",
				Metric:       "memory.cached",
				MetricSource: "memory",
				Name:         "Cached",
				Type:         "area",
				ID:           "cached",
			},
			domain.DataPoint{
				Aggregator:   "avg",
				Color:        "#aec7e8",
				Fill:         true,
				Format:       "%4.2f",
				Legend:       "Buffers",
				Metric:       "memory.buffers",
				MetricSource: "memory",
				Name:         "Buffers",
				Type:         "area",
				ID:           "buffers",
			},
			domain.DataPoint{
				Aggregator:   "avg",
				Color:        "#aee4e8",
				Fill:         true,
				Format:       "%4.2f",
				Legend:       "Free",
				Metric:       "memory.free",
				MetricSource: "memory",
				Name:         "Free",
				Type:         "area",
				ID:           "free",
			},
		},
		ID:     "memory.usage",
		Name:   "Memory Usage",
		Footer: false,
		Format: "%4.2f",
		MaxY:   &MaxY,
		MinY:   &zero,
		Range: &domain.GraphConfigRange{
			End:   "0s-ago",
			Start: "1h-ago",
		},
		YAxisLabel:  "bytes",
		ReturnSet:   "EXACT",
		Type:        "area",
		Tags:        tags,
		Units:       "bytes",
		Description: "Bytes used",
	}
}
<commit_msg>removed serviced from the title so it would fit better<commit_after>// Copyright 2014 The Serviced 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 web

import (
	"github.com/control-center/serviced/domain"
)

//profile defines meta-data for the host/pool resource's metrics and graphs
var (
	zero       int = 0
	onehundred int = 100

	zeroInt64 int64 = 0

	hostPoolProfile = domain.MonitorProfile{
		MetricConfigs: []domain.MetricConfig{
			//CPU
			domain.MetricConfig{
				ID:          "cpu",
				Name:        "CPU Usage",
				Description: "CPU Statistics",
				Metrics: []domain.Metric{
					domain.Metric{ID: "cpu.user", Name: "CPU User", Unit: "Percent", Counter: true},
					domain.Metric{ID: "cpu.nice", Name: "CPU Nice", Unit: "Percent", Counter: true},
					domain.Metric{ID: "cpu.system", Name: "CPU System", Unit: "Percent", Counter: true},
					domain.Metric{ID: "cpu.idle", Name: "CPU Idle", Unit: "Percent", Counter: true},
					domain.Metric{ID: "cpu.iowait", Name: "CPU IO Wait", Unit: "Percent", Counter: true},
					domain.Metric{ID: "cpu.irq", Name: "IRQ", Unit: "Percent", Counter: true},
					domain.Metric{ID: "cpu.softirq", Name: "Soft IRQ", Unit: "Percent", Counter: true},
					domain.Metric{ID: "cpu.steal", Name: "CPU Steal", Unit: "Percent", Counter: true},
				},
			},
			//Memory
			domain.MetricConfig{
				ID:          "memory",
				Name:        "Memory Usage",
				Description: "Memory Usage Statistics -- /proc/meminfo",
				Metrics: []domain.Metric{
					domain.Metric{ID: "memory.buffers", Name: "Memory Buffer", Unit: "Bytes"},
					domain.Metric{ID: "memory.cached", Name: "Memory Cache", Unit: "Bytes"},
					domain.Metric{ID: "memory.free", Name: "Memory Free", Unit: "Bytes"},
					domain.Metric{ID: "memory.total", Name: "Total Memory", Unit: "Bytes"},
					domain.Metric{ID: "memory.actualfree", Name: "Actual Free Memory", Unit: "Bytes"},
					domain.Metric{ID: "memory.actualused", Name: "Actual Used Memory", Unit: "Bytes"},
					domain.Metric{ID: "swap.total", Name: "Total Swap", Unit: "Bytes"},
					domain.Metric{ID: "swap.free", Name: "Free Swap", Unit: "Bytes"},
				},
			},
			//Virtual Memory
			domain.MetricConfig{
				ID:          "virtual.memory",
				Name:        "Virtual Memory Usage",
				Description: "Virtual Memory Usage Statistics -- /proc/vmstat",
				Metrics: []domain.Metric{
					domain.Metric{ID: "vmstat.pgfault", Name: "Minor Page Fault", Unit: "Page Faults", Counter: true},
					domain.Metric{ID: "vmstat.pgmajfault", Name: "Major Page Fault", Unit: "Page Faults", Counter: true},
				},
			},
			//Files
			domain.MetricConfig{
				ID:          "files",
				Name:        "File Usage",
				Description: "File Statistics",
				Metrics: []domain.Metric{
					domain.Metric{ID: "Serviced.OpenFileDescriptors", Name: "OpenFileDescriptors", Unit: "Open File Descriptors"},
				},
			},
		},
		ThresholdConfigs: []domain.ThresholdConfig{
			domain.ThresholdConfig{
				ID:           "swap.empty",
				Name:         "Swap empty",
				Description:  "Alert when swap reaches zero",
				MetricSource: "memory",
				DataPoints:   []string{"swap.free", "memory.free"},
				Type:         "MinMax",
				Threshold:    domain.MinMaxThreshold{Min: &zeroInt64, Max: nil},
				EventTags: map[string]interface{}{
					"Severity":    1,
					"Resolution":  "Increase swap or memory",
					"Explanation": "Ran out of all available memory space",
					"EventClass":  "/Perf/Memory",
				},
			},
		},
	}
)

//Open File Descriptors
func newOpenFileDescriptorsGraph(tags map[string][]string) domain.GraphConfig {
	return domain.GraphConfig{
		DataPoints: []domain.DataPoint{
			domain.DataPoint{
				ID:           "ofd",
				Aggregator:   "avg",
				Color:        "#aec7e8",
				Fill:         false,
				Format:       "%4.2f",
				Legend:       "Serviced Open File Descriptors",
				Metric:       "Serviced.OpenFileDescriptors",
				MetricSource: "files",
				Name:         "Serviced Open File Descriptors",
				Rate:         false,
				Type:         "line",
			},
		},
		ID:     "serviced.ofd",
		Name:   "Open File Descriptors",
		Footer: false,
		Format: "%d",
		MinY:   &zero,
		Range: &domain.GraphConfigRange{
			End:   "0s-ago",
			Start: "1h-ago",
		},
		ReturnSet:   "EXACT",
		Type:        "line",
		Tags:        tags,
		Units:       "File Descriptors",
		Description: "For the serviced process",
	}
}

//Major Page Faults
func newMajorPageFaultGraph(tags map[string][]string) domain.GraphConfig {
	return domain.GraphConfig{
		DataPoints: []domain.DataPoint{
			domain.DataPoint{
				Aggregator:   "avg",
				ID:           "pgfault",
				Color:        "#aec7e8",
				Fill:         false,
				Format:       "%.2f",
				Legend:       "Major Page Faults",
				Metric:       "vmstat.pgmajfault",
				MetricSource: "virtual.memory",
				Name:         "Major Page Faults",
				Rate:         true,
				Type:         "line",
			},
		},
		ID:     "memory.major.pagefault",
		Name:   "Memory Major Page Faults",
		Footer: false,
		Format: "%.2f",
		MinY:   &zero,
		Range: &domain.GraphConfigRange{
			End:   "0s-ago",
			Start: "1h-ago",
		},
		YAxisLabel:  "Faults / Min",
		ReturnSet:   "EXACT",
		Type:        "line",
		Tags:        tags,
		Units:       "Page Faults",
		Description: "Faults per minute",
	}
}

//Cpu Usage
func newCpuConfigGraph(tags map[string][]string, totalCores int) domain.GraphConfig {
	return domain.GraphConfig{
		DataPoints: []domain.DataPoint{
			domain.DataPoint{
				Aggregator:   "avg",
				Color:        "#aee8cf",
				Fill:         false,
				Format:       "%4.2f",
				ID:           "user",
				Legend:       "User",
				Metric:       "cpu.user",
				MetricSource: "cpu",
				Name:         "User",
				Rate:         true,
				Type:         "area",
			},
			domain.DataPoint{
				Aggregator:   "avg",
				Color:        "#729ed7",
				Fill:         false,
				Format:       "%4.2f",
				ID:           "system",
				Legend:       "System",
				Metric:       "cpu.system",
				MetricSource: "cpu",
				Name:         "System",
				Rate:         true,
				Type:         "area",
			},
			domain.DataPoint{
				Aggregator:   "avg",
				Fill:         false,
				Color:        "#d7729e",
				Format:       "%4.2f",
				ID:           "nice",
				Legend:       "Nice",
				Metric:       "cpu.nice",
				MetricSource: "cpu",
				Name:         "Nice",
				Rate:         true,
				Type:         "area",
			},
			domain.DataPoint{
				Aggregator:   "avg",
				Color:        "#e8aec7",
				Fill:         false,
				Format:       "%4.2f",
				ID:           "iowait",
				Legend:       "IOWait",
				Metric:       "cpu.iowait",
				MetricSource: "cpu",
				Name:         "IOWait",
				Rate:         true,
				Type:         "area",
			},
			domain.DataPoint{
				Aggregator:   "avg",
				Color:        "#e8cfae",
				Fill:         false,
				Format:       "%4.2f",
				ID:           "irq",
				Legend:       "IRQ",
				Metric:       "cpu.irq",
				MetricSource: "cpu",
				Name:         "IRQ",
				Rate:         true,
				Type:         "area",
			},
			domain.DataPoint{
				Aggregator:   "avg",
				Color:        "#ff0000",
				Fill:         false,
				Format:       "%4.2f",
				ID:           "steal",
				Legend:       "Steal",
				Metric:       "cpu.steal",
				MetricSource: "cpu",
				Name:         "Steal",
				Rate:         true,
				Type:         "area",
			},
			domain.DataPoint{
				Aggregator:   "avg",
				Color:        "#EBE6EA",
				Fill:         false,
				Format:       "%6.2f",
				ID:           "idle",
				Legend:       "Idle",
				Metric:       "cpu.idle",
				MetricSource: "cpu",
				Name:         "Idle",
				Rate:         true,
				Type:         "area",
			},
		},
		ID:     "cpu.usage",
		Name:   "CPU Usage",
		Footer: false,
		Format: "%d",
		MinY:   &zero,
		Range: &domain.GraphConfigRange{
			End:   "0s-ago",
			Start: "1h-ago",
		},
		YAxisLabel:  "% Used",
		ReturnSet:   "EXACT",
		Type:        "area",
		Tags:        tags,
		Units:       "Percent",
		Description: "Total cpu utilization (all cores)",
	}
}

func newRSSConfigGraph(tags map[string][]string, totalMemory uint64) domain.GraphConfig {
	MaxY := int(totalMemory)
	return domain.GraphConfig{
		DataPoints: []domain.DataPoint{
			domain.DataPoint{
				Aggregator:   "avg",
				Color:        "#e8aec7",
				Fill:         true,
				Format:       "%4.2f",
				Legend:       "Used",
				Metric:       "memory.actualused",
				MetricSource: "memory",
				Name:         "Used",
				Type:         "area",
				ID:           "used",
			},
			domain.DataPoint{
				Aggregator:   "avg",
				Color:        "#b2aee8",
				Fill:         true,
				Format:       "%4.2f",
				Legend:       "Cached",
				Metric:       "memory.cached",
				MetricSource: "memory",
				Name:         "Cached",
				Type:         "area",
				ID:           "cached",
			},
			domain.DataPoint{
				Aggregator:   "avg",
				Color:        "#aec7e8",
				Fill:         true,
				Format:       "%4.2f",
				Legend:       "Buffers",
				Metric:       "memory.buffers",
				MetricSource: "memory",
				Name:         "Buffers",
				Type:         "area",
				ID:           "buffers",
			},
			domain.DataPoint{
				Aggregator:   "avg",
				Color:        "#aee4e8",
				Fill:         true,
				Format:       "%4.2f",
				Legend:       "Free",
				Metric:       "memory.free",
				MetricSource: "memory",
				Name:         "Free",
				Type:         "area",
				ID:           "free",
			},
		},
		ID:     "memory.usage",
		Name:   "Memory Usage",
		Footer: false,
		Format: "%4.2f",
		MaxY:   &MaxY,
		MinY:   &zero,
		Range: &domain.GraphConfigRange{
			End:   "0s-ago",
			Start: "1h-ago",
		},
		YAxisLabel:  "bytes",
		ReturnSet:   "EXACT",
		Type:        "area",
		Tags:        tags,
		Units:       "bytes",
		Description: "Bytes used",
	}
}
<|endoftext|>


<commit_before>package main

import (
"strconv"
"testing"
)

func TestWorkerFunc(t *testing.T) {
	var jobTest jobInfo
	jobTest.Action = "mtr"
	jobTest.Rc = "2"

	fn := worker(jobTest)

	if fn.Status != "error"{
		t.Errorf("Expected error, got %s", fn.Status)
	}

	if fn.Message != "Host is needed"{
		t.Errorf("Expected no host message, got %s", fn.Message)
	}

	jobTest.Host = "8.8.8.8"
	jobTest.Rc = "fsdfs"
	fn = worker(jobTest)

	if fn.Status != "error"{
		t.Errorf("Expected error, got %s", fn.Status)
	}

	if fn.Message != "rc needs to be an integer"{
		t.Errorf("Expected bad rc message, got %s", fn.Message)
	}

	jobTest.Rc = "3"
	jobTest.Action = "fdsfasdfsd"
	fn = worker(jobTest)

	if fn.Status != "error"{
		t.Errorf("Expected error, got %s", fn.Status)
	}

	if fn.Message != "Action not found"{
		t.Errorf("Expected action not found message, got %s", fn.Message)
	}

	jobTest.Action = ""
	fn = worker(jobTest)

	if fn.Status != "error"{
		t.Errorf("Expected error, got %s", fn.Status)
	}

	if fn.Message != "Action is needed"{
		t.Errorf("Expected action needed message, got %s", fn.Message)
	}

}

func TestWorkerMTRFunc(t *testing.T) {
	var jobTest jobInfo
	jobTest.Action = "mtr"
	jobTest.Host = "8.8.8.8"
	jobTest.Rc = "2"

	rcInt, err := strconv.Atoi(jobTest.Rc)

	if err != nil{
		t.Errorf("Error parsing rc: %s", err)
	}

	fn := worker(jobTest)

	if fn.Status != "ok" {
		t.Errorf("ok status not returned, got %s", fn.Status)
	}

	if fn.Message != "" {
		t.Errorf("Message was returned when it should not of been, got %s", fn.Message)
	}

	if fn.Host != jobTest.Host {
		t.Errorf("Host was not returned with the same as sent, got %s", fn.Host)
	}

	if len(fn.MtrLogs) == 0{
		t.Errorf("No logs recieved")
	}

	for k, v := range fn.MtrLogs {
		if k != v.Id {
			t.Errorf("ID does not match for number")
		}

		if v.Host == "" {
			t.Errorf("No host recieved")
		}

		if v.Loss == "" {
			t.Errorf("No lost recieved")
		}

		if v.Loss == "" {
			t.Errorf("No lost recieved")
		}

		if v.Sent != rcInt {
			t.Errorf("Number of packets sent doesn't match requested, got %d", v.Sent)
		}

		if v.Last == "" {
			t.Errorf("No last recieved")
		}

		if v.Avg == "" {
			t.Errorf("No average recieved")
		}

		if v.Best == "" {
			t.Errorf("No best recieved")
		}

		if v.Wrst == "" {
			t.Errorf("No worst recieved")
		}

		if v.StDev == "" {
			t.Errorf("No st_deviation recieved")
		}

	}

}

func TestWorkerPingFunc(t *testing.T) {

	var jobTest jobInfo
	jobTest.Action = "ping"
	jobTest.Host = "127.0.0.1"
	jobTest.Rc = "3"

	rcInt, err := strconv.Atoi(jobTest.Rc)

	if err != nil{
		t.Errorf("Error parsing rc: %s", err)
	}

	fn := worker(jobTest)

	if fn.Status != "ok" {
		t.Errorf("ok status not returned, got %s", fn.Status)
	}

	if fn.Message != "" {
		t.Errorf("Message was returned when it should not of been, got %s", fn.Message)
	}

	if fn.Host != jobTest.Host {
		t.Errorf("Host was not returned with the same as sent, got %s", fn.Host)
	}

	if fn.Stats.Transmitted != rcInt {
		t.Errorf("Incorrect number of packets sent, got %d", fn.Stats.Transmitted)
	}

	if fn.Stats.Received != rcInt {
		t.Errorf("Incorrect number of packets recieved, got %d", fn.Stats.Received)
	}

	if fn.Stats.Loss != "0" {
		t.Errorf("Incorrect packet loss, got %s", fn.Stats.Loss)
	}

	if fn.Stats.Time == rcInt {
		t.Errorf("Total ping time was 0")
	}

	if fn.Rtt.Min == ""{
		t.Errorf("min returned empty")
	}

	if fn.Rtt.Avg == ""{
		t.Errorf("avg returned empty")
	}

	if fn.Rtt.Max == ""{
		t.Errorf("max returned empty")
	}

	if fn.Rtt.Mdev == ""{
		t.Errorf("mdev returned empty")
	}

	if len(fn.Logs) != rcInt{
		t.Errorf("Expecting 3 logs back, got %d", len(fn.Logs))
	}

	for k, v := range fn.Logs {
		if k+1 != v.Id{
			t.Errorf("Incorrect log id, got %d", v.Id)
		}

		if v.Size != 64{
			t.Errorf("Incorrect packet size, got %d", v.Size)
		}

		if v.Host != jobTest.Host {
			t.Errorf("Host was not returned with the same as sent, got %s", v.Host)
		}

		if v.Ttl == 0 {
			t.Errorf("TTL not recieved")
		}

		if v.Time == ""  {
			t.Errorf("Time not recieved")
		}

	}
}<commit_msg>Travis-CI didn't like pinging local host, google DNS it is<commit_after>package main

import (
"strconv"
"testing"
)

func TestWorkerFunc(t *testing.T) {
	var jobTest jobInfo
	jobTest.Action = "mtr"
	jobTest.Rc = "2"

	fn := worker(jobTest)

	if fn.Status != "error"{
		t.Errorf("Expected error, got %s", fn.Status)
	}

	if fn.Message != "Host is needed"{
		t.Errorf("Expected no host message, got %s", fn.Message)
	}

	jobTest.Host = "8.8.8.8"
	jobTest.Rc = "fsdfs"
	fn = worker(jobTest)

	if fn.Status != "error"{
		t.Errorf("Expected error, got %s", fn.Status)
	}

	if fn.Message != "rc needs to be an integer"{
		t.Errorf("Expected bad rc message, got %s", fn.Message)
	}

	jobTest.Rc = "3"
	jobTest.Action = "fdsfasdfsd"
	fn = worker(jobTest)

	if fn.Status != "error"{
		t.Errorf("Expected error, got %s", fn.Status)
	}

	if fn.Message != "Action not found"{
		t.Errorf("Expected action not found message, got %s", fn.Message)
	}

	jobTest.Action = ""
	fn = worker(jobTest)

	if fn.Status != "error"{
		t.Errorf("Expected error, got %s", fn.Status)
	}

	if fn.Message != "Action is needed"{
		t.Errorf("Expected action needed message, got %s", fn.Message)
	}

}

func TestWorkerMTRFunc(t *testing.T) {
	var jobTest jobInfo
	jobTest.Action = "mtr"
	jobTest.Host = "8.8.8.8"
	jobTest.Rc = "2"

	rcInt, err := strconv.Atoi(jobTest.Rc)

	if err != nil{
		t.Errorf("Error parsing rc: %s", err)
	}

	fn := worker(jobTest)

	if fn.Status != "ok" {
		t.Errorf("ok status not returned, got %s", fn.Status)
	}

	if fn.Message != "" {
		t.Errorf("Message was returned when it should not of been, got %s", fn.Message)
	}

	if fn.Host != jobTest.Host {
		t.Errorf("Host was not returned with the same as sent, got %s", fn.Host)
	}

	if len(fn.MtrLogs) == 0{
		t.Errorf("No logs recieved")
	}

	for k, v := range fn.MtrLogs {
		if k != v.Id {
			t.Errorf("ID does not match for number")
		}

		if v.Host == "" {
			t.Errorf("No host recieved")
		}

		if v.Loss == "" {
			t.Errorf("No lost recieved")
		}

		if v.Loss == "" {
			t.Errorf("No lost recieved")
		}

		if v.Sent != rcInt {
			t.Errorf("Number of packets sent doesn't match requested, got %d", v.Sent)
		}

		if v.Last == "" {
			t.Errorf("No last recieved")
		}

		if v.Avg == "" {
			t.Errorf("No average recieved")
		}

		if v.Best == "" {
			t.Errorf("No best recieved")
		}

		if v.Wrst == "" {
			t.Errorf("No worst recieved")
		}

		if v.StDev == "" {
			t.Errorf("No st_deviation recieved")
		}

	}

}

func TestWorkerPingFunc(t *testing.T) {

	var jobTest jobInfo
	jobTest.Action = "ping"
	jobTest.Host = "8.8.8.8"
	jobTest.Rc = "3"

	rcInt, err := strconv.Atoi(jobTest.Rc)

	if err != nil{
		t.Errorf("Error parsing rc: %s", err)
	}

	fn := worker(jobTest)

	if fn.Status != "ok" {
		t.Errorf("ok status not returned, got %s", fn.Status)
	}

	if fn.Message != "" {
		t.Errorf("Message was returned when it should not of been, got %s", fn.Message)
	}

	if fn.Host != jobTest.Host {
		t.Errorf("Host was not returned with the same as sent, got %s", fn.Host)
	}

	if fn.Stats.Transmitted != rcInt {
		t.Errorf("Incorrect number of packets sent, got %d", fn.Stats.Transmitted)
	}

	if fn.Stats.Received != rcInt {
		t.Errorf("Incorrect number of packets recieved, got %d", fn.Stats.Received)
	}

	if fn.Stats.Loss != "0" {
		t.Errorf("Incorrect packet loss, got %s", fn.Stats.Loss)
	}

	if fn.Stats.Time == rcInt {
		t.Errorf("Total ping time was 0")
	}

	if fn.Rtt.Min == ""{
		t.Errorf("min returned empty")
	}

	if fn.Rtt.Avg == ""{
		t.Errorf("avg returned empty")
	}

	if fn.Rtt.Max == ""{
		t.Errorf("max returned empty")
	}

	if fn.Rtt.Mdev == ""{
		t.Errorf("mdev returned empty")
	}

	if len(fn.Logs) != rcInt{
		t.Errorf("Expecting 3 logs back, got %d", len(fn.Logs))
	}

	for k, v := range fn.Logs {
		if k+1 != v.Id{
			t.Errorf("Incorrect log id, got %d", v.Id)
		}

		if v.Size != 64{
			t.Errorf("Incorrect packet size, got %d", v.Size)
		}

		if v.Host != jobTest.Host {
			t.Errorf("Host was not returned with the same as sent, got %s", v.Host)
		}

		if v.Ttl == 0 {
			t.Errorf("TTL not recieved")
		}

		if v.Time == ""  {
			t.Errorf("Time not recieved")
		}

	}
}<|endoftext|>


<commit_before>// Copyright 2016 The Snappy-Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// +build !amd64 appengine !gc noasm

package snappy

func load32(b []byte, i int) uint32 {
	b = b[i : i+4 : len(b)] // Help the compiler eliminate bounds checks on the next line.
	return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24
}

func load64(b []byte, i int) uint64 {
	b = b[i : i+8 : len(b)] // Help the compiler eliminate bounds checks on the next line.
	return uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 |
		uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56
}

// emitLiteral writes a literal chunk and returns the number of bytes written.
//
// It assumes that:
//	dst is long enough to hold the encoded bytes
//	1 <= len(lit) && len(lit) <= 65536
func emitLiteral(dst, lit []byte) int {
	i, n := 0, uint(len(lit)-1)
	switch {
	case n < 60:
		dst[0] = uint8(n)<<2 | tagLiteral
		i = 1
	case n < 1<<8:
		dst[0] = 60<<2 | tagLiteral
		dst[1] = uint8(n)
		i = 2
	default:
		dst[0] = 61<<2 | tagLiteral
		dst[1] = uint8(n)
		dst[2] = uint8(n >> 8)
		i = 3
	}
	return i + copy(dst[i:], lit)
}

// emitCopy writes a copy chunk and returns the number of bytes written.
//
// It assumes that:
//	dst is long enough to hold the encoded bytes
//	1 <= offset && offset <= 65535
//	4 <= length && length <= 65535
func emitCopy(dst []byte, offset, length int) int {
	i := 0
	// The maximum length for a single tagCopy1 or tagCopy2 op is 64 bytes. The
	// threshold for this loop is a little higher (at 68 = 64 + 4), and the
	// length emitted down below is is a little lower (at 60 = 64 - 4), because
	// it's shorter to encode a length 67 copy as a length 60 tagCopy2 followed
	// by a length 7 tagCopy1 (which encodes as 3+2 bytes) than to encode it as
	// a length 64 tagCopy2 followed by a length 3 tagCopy2 (which encodes as
	// 3+3 bytes). The magic 4 in the 64±4 is because the minimum length for a
	// tagCopy1 op is 4 bytes, which is why a length 3 copy has to be an
	// encodes-as-3-bytes tagCopy2 instead of an encodes-as-2-bytes tagCopy1.
	for length >= 68 {
		// Emit a length 64 copy, encoded as 3 bytes.
		dst[i+0] = 63<<2 | tagCopy2
		dst[i+1] = uint8(offset)
		dst[i+2] = uint8(offset >> 8)
		i += 3
		length -= 64
	}
	if length > 64 {
		// Emit a length 60 copy, encoded as 3 bytes.
		dst[i+0] = 59<<2 | tagCopy2
		dst[i+1] = uint8(offset)
		dst[i+2] = uint8(offset >> 8)
		i += 3
		length -= 60
	}
	if length >= 12 || offset >= 2048 {
		// Emit the remaining copy, encoded as 3 bytes.
		dst[i+0] = uint8(length-1)<<2 | tagCopy2
		dst[i+1] = uint8(offset)
		dst[i+2] = uint8(offset >> 8)
		return i + 3
	}
	// Emit the remaining copy, encoded as 2 bytes.
	dst[i+0] = uint8(offset>>8)<<5 | uint8(length-4)<<2 | tagCopy1
	dst[i+1] = uint8(offset)
	return i + 2
}

// extendMatch returns the largest k such that k <= len(src) and that
// src[i:i+k-j] and src[j:k] have the same contents.
//
// It assumes that:
//	0 <= i && i < j && j <= len(src)
func extendMatch(src []byte, i, j int) int {
	for ; j < len(src) && src[i] == src[j]; i, j = i+1, j+1 {
	}
	return j
}

func hash(u, shift uint32) uint32 {
	return (u * 0x1e35a7bd) >> shift
}

// encodeBlock encodes a non-empty src to a guaranteed-large-enough dst. It
// assumes that the varint-encoded length of the decompressed bytes has already
// been written.
//
// It also assumes that:
//	len(dst) >= MaxEncodedLen(len(src)) &&
// 	minNonLiteralBlockSize <= len(src) && len(src) <= maxBlockSize
func encodeBlock(dst, src []byte) (d int) {
	// Initialize the hash table. Its size ranges from 1<<8 to 1<<14 inclusive.
	// The table element type is uint16, as s < sLimit and sLimit < len(src)
	// and len(src) <= maxBlockSize and maxBlockSize == 65536.
	const (
		maxTableSize = 1 << 14
		// tableMask is redundant, but helps the compiler eliminate bounds
		// checks.
		tableMask = maxTableSize - 1
	)
	shift := uint32(32 - 8)
	for tableSize := 1 << 8; tableSize < maxTableSize && tableSize < len(src); tableSize *= 2 {
		shift--
	}
	// In Go, all array elements are zero-initialized, so there is no advantage
	// to a smaller tableSize per se. However, it matches the C++ algorithm,
	// and in the asm versions of this code, we can get away with zeroing only
	// the first tableSize elements.
	var table [maxTableSize]uint16

	// sLimit is when to stop looking for offset/length copies. The inputMargin
	// lets us use a fast path for emitLiteral in the main loop, while we are
	// looking for copies.
	sLimit := len(src) - inputMargin

	// nextEmit is where in src the next emitLiteral should start from.
	nextEmit := 0

	// The encoded form must start with a literal, as there are no previous
	// bytes to copy, so we start looking for hash matches at s == 1.
	s := 1
	nextHash := hash(load32(src, s), shift)

	for {
		// Copied from the C++ snappy implementation:
		//
		// Heuristic match skipping: If 32 bytes are scanned with no matches
		// found, start looking only at every other byte. If 32 more bytes are
		// scanned (or skipped), look at every third byte, etc.. When a match
		// is found, immediately go back to looking at every byte. This is a
		// small loss (~5% performance, ~0.1% density) for compressible data
		// due to more bookkeeping, but for non-compressible data (such as
		// JPEG) it's a huge win since the compressor quickly "realizes" the
		// data is incompressible and doesn't bother looking for matches
		// everywhere.
		//
		// The "skip" variable keeps track of how many bytes there are since
		// the last match; dividing it by 32 (ie. right-shifting by five) gives
		// the number of bytes to move ahead for each iteration.
		skip := 32

		nextS := s
		candidate := 0
		for {
			s = nextS
			bytesBetweenHashLookups := skip >> 5
			nextS = s + bytesBetweenHashLookups
			skip += bytesBetweenHashLookups
			if nextS > sLimit {
				goto emitRemainder
			}
			candidate = int(table[nextHash&tableMask])
			table[nextHash&tableMask] = uint16(s)
			nextHash = hash(load32(src, nextS), shift)
			if load32(src, s) == load32(src, candidate) {
				break
			}
		}

		// A 4-byte match has been found. We'll later see if more than 4 bytes
		// match. But, prior to the match, src[nextEmit:s] are unmatched. Emit
		// them as literal bytes.
		d += emitLiteral(dst[d:], src[nextEmit:s])

		// Call emitCopy, and then see if another emitCopy could be our next
		// move. Repeat until we find no match for the input immediately after
		// what was consumed by the last emitCopy call.
		//
		// If we exit this loop normally then we need to call emitLiteral next,
		// though we don't yet know how big the literal will be. We handle that
		// by proceeding to the next iteration of the main loop. We also can
		// exit this loop via goto if we get close to exhausting the input.
		for {
			// Invariant: we have a 4-byte match at s, and no need to emit any
			// literal bytes prior to s.
			base := s
			// Extend the 4-byte match as long as possible.
			s = extendMatch(src, candidate+4, s+4)
			d += emitCopy(dst[d:], base-candidate, s-base)
			nextEmit = s
			if s >= sLimit {
				goto emitRemainder
			}

			// We could immediately start working at s now, but to improve
			// compression we first update the hash table at s-1 and at s. If
			// another emitCopy is not our next move, also calculate nextHash
			// at s+1. At least on GOARCH=amd64, these three hash calculations
			// are faster as one load64 call (with some shifts) instead of
			// three load32 calls.
			x := load64(src, s-1)
			prevHash := hash(uint32(x>>0), shift)
			table[prevHash&tableMask] = uint16(s - 1)
			currHash := hash(uint32(x>>8), shift)
			candidate = int(table[currHash&tableMask])
			table[currHash&tableMask] = uint16(s)
			if uint32(x>>8) != load32(src, candidate) {
				nextHash = hash(uint32(x>>16), shift)
				s++
				break
			}
		}
	}

emitRemainder:
	if nextEmit < len(src) {
		d += emitLiteral(dst[d:], src[nextEmit:])
	}
	return d
}
<commit_msg>Inline extendMatch for the noasm encoder.<commit_after>// Copyright 2016 The Snappy-Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// +build !amd64 appengine !gc noasm

package snappy

func load32(b []byte, i int) uint32 {
	b = b[i : i+4 : len(b)] // Help the compiler eliminate bounds checks on the next line.
	return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24
}

func load64(b []byte, i int) uint64 {
	b = b[i : i+8 : len(b)] // Help the compiler eliminate bounds checks on the next line.
	return uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 |
		uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56
}

// emitLiteral writes a literal chunk and returns the number of bytes written.
//
// It assumes that:
//	dst is long enough to hold the encoded bytes
//	1 <= len(lit) && len(lit) <= 65536
func emitLiteral(dst, lit []byte) int {
	i, n := 0, uint(len(lit)-1)
	switch {
	case n < 60:
		dst[0] = uint8(n)<<2 | tagLiteral
		i = 1
	case n < 1<<8:
		dst[0] = 60<<2 | tagLiteral
		dst[1] = uint8(n)
		i = 2
	default:
		dst[0] = 61<<2 | tagLiteral
		dst[1] = uint8(n)
		dst[2] = uint8(n >> 8)
		i = 3
	}
	return i + copy(dst[i:], lit)
}

// emitCopy writes a copy chunk and returns the number of bytes written.
//
// It assumes that:
//	dst is long enough to hold the encoded bytes
//	1 <= offset && offset <= 65535
//	4 <= length && length <= 65535
func emitCopy(dst []byte, offset, length int) int {
	i := 0
	// The maximum length for a single tagCopy1 or tagCopy2 op is 64 bytes. The
	// threshold for this loop is a little higher (at 68 = 64 + 4), and the
	// length emitted down below is is a little lower (at 60 = 64 - 4), because
	// it's shorter to encode a length 67 copy as a length 60 tagCopy2 followed
	// by a length 7 tagCopy1 (which encodes as 3+2 bytes) than to encode it as
	// a length 64 tagCopy2 followed by a length 3 tagCopy2 (which encodes as
	// 3+3 bytes). The magic 4 in the 64±4 is because the minimum length for a
	// tagCopy1 op is 4 bytes, which is why a length 3 copy has to be an
	// encodes-as-3-bytes tagCopy2 instead of an encodes-as-2-bytes tagCopy1.
	for length >= 68 {
		// Emit a length 64 copy, encoded as 3 bytes.
		dst[i+0] = 63<<2 | tagCopy2
		dst[i+1] = uint8(offset)
		dst[i+2] = uint8(offset >> 8)
		i += 3
		length -= 64
	}
	if length > 64 {
		// Emit a length 60 copy, encoded as 3 bytes.
		dst[i+0] = 59<<2 | tagCopy2
		dst[i+1] = uint8(offset)
		dst[i+2] = uint8(offset >> 8)
		i += 3
		length -= 60
	}
	if length >= 12 || offset >= 2048 {
		// Emit the remaining copy, encoded as 3 bytes.
		dst[i+0] = uint8(length-1)<<2 | tagCopy2
		dst[i+1] = uint8(offset)
		dst[i+2] = uint8(offset >> 8)
		return i + 3
	}
	// Emit the remaining copy, encoded as 2 bytes.
	dst[i+0] = uint8(offset>>8)<<5 | uint8(length-4)<<2 | tagCopy1
	dst[i+1] = uint8(offset)
	return i + 2
}

// extendMatch returns the largest k such that k <= len(src) and that
// src[i:i+k-j] and src[j:k] have the same contents.
//
// It assumes that:
//	0 <= i && i < j && j <= len(src)
func extendMatch(src []byte, i, j int) int {
	for ; j < len(src) && src[i] == src[j]; i, j = i+1, j+1 {
	}
	return j
}

func hash(u, shift uint32) uint32 {
	return (u * 0x1e35a7bd) >> shift
}

// encodeBlock encodes a non-empty src to a guaranteed-large-enough dst. It
// assumes that the varint-encoded length of the decompressed bytes has already
// been written.
//
// It also assumes that:
//	len(dst) >= MaxEncodedLen(len(src)) &&
// 	minNonLiteralBlockSize <= len(src) && len(src) <= maxBlockSize
func encodeBlock(dst, src []byte) (d int) {
	// Initialize the hash table. Its size ranges from 1<<8 to 1<<14 inclusive.
	// The table element type is uint16, as s < sLimit and sLimit < len(src)
	// and len(src) <= maxBlockSize and maxBlockSize == 65536.
	const (
		maxTableSize = 1 << 14
		// tableMask is redundant, but helps the compiler eliminate bounds
		// checks.
		tableMask = maxTableSize - 1
	)
	shift := uint32(32 - 8)
	for tableSize := 1 << 8; tableSize < maxTableSize && tableSize < len(src); tableSize *= 2 {
		shift--
	}
	// In Go, all array elements are zero-initialized, so there is no advantage
	// to a smaller tableSize per se. However, it matches the C++ algorithm,
	// and in the asm versions of this code, we can get away with zeroing only
	// the first tableSize elements.
	var table [maxTableSize]uint16

	// sLimit is when to stop looking for offset/length copies. The inputMargin
	// lets us use a fast path for emitLiteral in the main loop, while we are
	// looking for copies.
	sLimit := len(src) - inputMargin

	// nextEmit is where in src the next emitLiteral should start from.
	nextEmit := 0

	// The encoded form must start with a literal, as there are no previous
	// bytes to copy, so we start looking for hash matches at s == 1.
	s := 1
	nextHash := hash(load32(src, s), shift)

	for {
		// Copied from the C++ snappy implementation:
		//
		// Heuristic match skipping: If 32 bytes are scanned with no matches
		// found, start looking only at every other byte. If 32 more bytes are
		// scanned (or skipped), look at every third byte, etc.. When a match
		// is found, immediately go back to looking at every byte. This is a
		// small loss (~5% performance, ~0.1% density) for compressible data
		// due to more bookkeeping, but for non-compressible data (such as
		// JPEG) it's a huge win since the compressor quickly "realizes" the
		// data is incompressible and doesn't bother looking for matches
		// everywhere.
		//
		// The "skip" variable keeps track of how many bytes there are since
		// the last match; dividing it by 32 (ie. right-shifting by five) gives
		// the number of bytes to move ahead for each iteration.
		skip := 32

		nextS := s
		candidate := 0
		for {
			s = nextS
			bytesBetweenHashLookups := skip >> 5
			nextS = s + bytesBetweenHashLookups
			skip += bytesBetweenHashLookups
			if nextS > sLimit {
				goto emitRemainder
			}
			candidate = int(table[nextHash&tableMask])
			table[nextHash&tableMask] = uint16(s)
			nextHash = hash(load32(src, nextS), shift)
			if load32(src, s) == load32(src, candidate) {
				break
			}
		}

		// A 4-byte match has been found. We'll later see if more than 4 bytes
		// match. But, prior to the match, src[nextEmit:s] are unmatched. Emit
		// them as literal bytes.
		d += emitLiteral(dst[d:], src[nextEmit:s])

		// Call emitCopy, and then see if another emitCopy could be our next
		// move. Repeat until we find no match for the input immediately after
		// what was consumed by the last emitCopy call.
		//
		// If we exit this loop normally then we need to call emitLiteral next,
		// though we don't yet know how big the literal will be. We handle that
		// by proceeding to the next iteration of the main loop. We also can
		// exit this loop via goto if we get close to exhausting the input.
		for {
			// Invariant: we have a 4-byte match at s, and no need to emit any
			// literal bytes prior to s.
			base := s

			// Extend the 4-byte match as long as possible.
			//
			// This is an inlined version of:
			//	s = extendMatch(src, candidate+4, s+4)
			s += 4
			for i := candidate + 4; s < len(src) && src[i] == src[s]; i, s = i+1, s+1 {
			}

			d += emitCopy(dst[d:], base-candidate, s-base)
			nextEmit = s
			if s >= sLimit {
				goto emitRemainder
			}

			// We could immediately start working at s now, but to improve
			// compression we first update the hash table at s-1 and at s. If
			// another emitCopy is not our next move, also calculate nextHash
			// at s+1. At least on GOARCH=amd64, these three hash calculations
			// are faster as one load64 call (with some shifts) instead of
			// three load32 calls.
			x := load64(src, s-1)
			prevHash := hash(uint32(x>>0), shift)
			table[prevHash&tableMask] = uint16(s - 1)
			currHash := hash(uint32(x>>8), shift)
			candidate = int(table[currHash&tableMask])
			table[currHash&tableMask] = uint16(s)
			if uint32(x>>8) != load32(src, candidate) {
				nextHash = hash(uint32(x>>16), shift)
				s++
				break
			}
		}
	}

emitRemainder:
	if nextEmit < len(src) {
		d += emitLiteral(dst[d:], src[nextEmit:])
	}
	return d
}
<|endoftext|>


<commit_before>package runoncehandler_test

import (
	"reflect"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"

	"github.com/cloudfoundry-incubator/runtime-schema/bbs"
	"github.com/cloudfoundry-incubator/runtime-schema/models"
	steno "github.com/cloudfoundry/gosteno"
	"github.com/vito/gordon/fake_gordon"

	"github.com/cloudfoundry-incubator/executor/action_runner"
	"github.com/cloudfoundry-incubator/executor/downloader/fakedownloader"
	"github.com/cloudfoundry-incubator/executor/linuxplugin"
	"github.com/cloudfoundry-incubator/executor/logstreamer"
	"github.com/cloudfoundry-incubator/executor/run_once_transformer"
	. "github.com/cloudfoundry-incubator/executor/runoncehandler"
	"github.com/cloudfoundry-incubator/executor/taskregistry/faketaskregistry"
	"github.com/cloudfoundry-incubator/executor/uploader/fakeuploader"
)

var _ = Describe("RunOnceHandler", func() {
	Describe("RunOnce", func() {
		var (
			handler          *RunOnceHandler
			performedActions []string
			runOnce          models.RunOnce
		)

		spyPerformer := func(actions ...action_runner.Action) error {
			for _, action := range actions {
				actionType := reflect.TypeOf(action).String()
				performedActions = append(performedActions, actionType)
			}

			return nil
		}

		BeforeEach(func() {
			performedActions = []string{}
			runOnce = models.RunOnce{}

			bbs := bbs.BBS{}
			wardenClient := &fake_gordon.FakeGordon{}
			taskRegistry := &faketaskregistry.FakeTaskRegistry{}
			logStreamerFactory := func(models.LogConfig) logstreamer.LogStreamer {
				return nil
			}
			logger := &steno.Logger{}

			backendPlugin := linuxplugin.New()
			downloader := &fakedownloader.FakeDownloader{}
			uploader := &fakeuploader.FakeUploader{}

			runOnceTransformer := run_once_transformer.NewRunOnceTransformer(
				logStreamerFactory,
				downloader,
				uploader,
				backendPlugin,
				wardenClient,
				logger,
				"/fake/temp/dir",
			)

			handler = New(
				bbs,
				wardenClient,
				taskRegistry,
				runOnceTransformer,
				spyPerformer,
				logStreamerFactory,
				logger,
			)
		})

		It("performs a sequence of runOnce actions on the specified executor", func() {
			handler.RunOnce(runOnce, "fake-executor-id")

			Ω(performedActions).To(Equal([]string{
				"*register_action.RegisterAction",
				"*claim_action.ClaimAction",
				"*create_container_action.ContainerAction",
				"*start_action.StartAction",
				"*execute_action.ExecuteAction",
				"*complete_action.CompleteAction",
			}))
		})
	})
})
<commit_msg>RunOnceHandler tests happy path, instead of types<commit_after>package runoncehandler_test

import (
	"io/ioutil"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"

	"code.google.com/p/gogoprotobuf/proto"
	"github.com/cloudfoundry-incubator/runtime-schema/models"
	steno "github.com/cloudfoundry/gosteno"
	"github.com/vito/gordon/fake_gordon"
	"github.com/vito/gordon/warden"

	"github.com/cloudfoundry-incubator/executor/action_runner"
	"github.com/cloudfoundry-incubator/executor/downloader/fakedownloader"
	"github.com/cloudfoundry-incubator/executor/linuxplugin"
	"github.com/cloudfoundry-incubator/executor/logstreamer"
	"github.com/cloudfoundry-incubator/executor/run_once_transformer"
	. "github.com/cloudfoundry-incubator/executor/runoncehandler"
	"github.com/cloudfoundry-incubator/executor/taskregistry/faketaskregistry"
	"github.com/cloudfoundry-incubator/executor/uploader/fakeuploader"
	"github.com/cloudfoundry-incubator/runtime-schema/bbs/fakebbs"
)

var _ = Describe("RunOnceHandler", func() {
	Describe("RunOnce", func() {
		var (
			handler *RunOnceHandler
			runOnce models.RunOnce

			bbs          *fakebbs.FakeExecutorBBS
			wardenClient *fake_gordon.FakeGordon
			downloader   *fakedownloader.FakeDownloader
			uploader     *fakeuploader.FakeUploader
			transformer  *run_once_transformer.RunOnceTransformer
			taskRegistry *faketaskregistry.FakeTaskRegistry
		)

		BeforeEach(func() {
			runOnce = models.RunOnce{
				Guid: "run-once-guid",
				Actions: []models.ExecutorAction{
					{
						Action: models.DownloadAction{
							From: "http://download-src.com",
							To:   "/download-dst",
						},
					},
					{
						Action: models.RunAction{
							Script: "sudo reboot",
						},
					},
					{
						Action: models.UploadAction{
							From: "/upload-src",
							To:   "http://upload-dst.com",
						},
					},
				},
			}

			bbs = fakebbs.NewFakeExecutorBBS()
			wardenClient = fake_gordon.New()
			taskRegistry = faketaskregistry.New()

			logStreamerFactory := func(models.LogConfig) logstreamer.LogStreamer {
				return nil
			}

			logger := steno.NewLogger("test-logger")

			backendPlugin := linuxplugin.New()
			downloader = &fakedownloader.FakeDownloader{}
			uploader = &fakeuploader.FakeUploader{}

			tmpDir, err := ioutil.TempDir("", "run-once-handler-tmp")
			Ω(err).ShouldNot(HaveOccurred())

			transformer = run_once_transformer.NewRunOnceTransformer(
				logStreamerFactory,
				downloader,
				uploader,
				backendPlugin,
				wardenClient,
				logger,
				tmpDir,
			)

			handler = New(
				bbs,
				wardenClient,
				taskRegistry,
				transformer,
				action_runner.Run,
				logStreamerFactory,
				logger,
			)
		})

		setupSuccessfulRuns := func() {
			processPayloadStream := make(chan *warden.ProcessPayload, 1000)

			wardenClient.SetRunReturnValues(0, processPayloadStream, nil)

			successfulExit := &warden.ProcessPayload{ExitStatus: proto.Uint32(0)}

			go func() {
				processPayloadStream <- successfulExit
			}()
		}

		BeforeEach(setupSuccessfulRuns)

		It("registers, claims, creates container, starts, (executes...), completes", func() {
			handler.RunOnce(runOnce, "fake-executor-id")

			// register
			Ω(taskRegistry.RegisteredRunOnces).Should(ContainElement(runOnce))

			// claim
			Ω(bbs.ClaimedRunOnce.Guid).Should(Equal("run-once-guid"))
			Ω(bbs.ClaimedRunOnce.ExecutorID).Should(Equal("fake-executor-id"))

			// create container
			Ω(wardenClient.CreatedHandles()).ShouldNot(BeEmpty())

			// start
			Ω(bbs.StartedRunOnce.Guid).Should(Equal("run-once-guid"))
			Ω(bbs.StartedRunOnce.ExecutorID).Should(Equal("fake-executor-id"))
			Ω(bbs.StartedRunOnce.ContainerHandle).ShouldNot(BeZero())

			// execute download action
			Ω(downloader.DownloadedUrls).ShouldNot(BeEmpty())
			Ω(downloader.DownloadedUrls[0].String()).Should(Equal("http://download-src.com"))

			// execute run action
			ranScripts := []string{}
			for _, script := range wardenClient.ScriptsThatRan() {
				Ω(script.Handle).Should(Equal(bbs.StartedRunOnce.ContainerHandle))

				ranScripts = append(ranScripts, script.Script)
			}

			Ω(ranScripts).Should(ContainElement("sudo reboot"))

			// execute upload action
			Ω(uploader.UploadUrls).ShouldNot(BeEmpty())
			Ω(uploader.UploadUrls[0].String()).Should(Equal("http://upload-dst.com"))

			// complete
			Ω(bbs.CompletedRunOnce.Guid).Should(Equal("run-once-guid"))
			Ω(bbs.CompletedRunOnce.ExecutorID).Should(Equal("fake-executor-id"))
			Ω(bbs.CompletedRunOnce.ContainerHandle).ShouldNot(BeZero())
		})
	})
})
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"os/exec"
	"path"
	"path/filepath"
	"strings"
	"text/template"
)

type copyfiles struct {
	dir  string
	spec string
}

const (
	goList = `{{.Gosrcroot}}
go/pkg/include
go/src
go/VERSION.cache
go/misc
go/pkg/tool/{{.Goos}}_{{.Arch}}/{{.Letter}}g
go/pkg/tool/{{.Goos}}_{{.Arch}}/{{.Letter}}l
go/pkg/tool/{{.Goos}}_{{.Arch}}/asm
go/pkg/tool/{{.Goos}}_{{.Arch}}/old{{.Letter}}a`

	initList = `{{.Gopath}}/src/cmds/init
init`
	urootList = `{{.Gopath}}
src`
)

var (
	config struct {
		Goroot    string
		Gosrcroot string
		Arch      string
		Goos      string
		Letter    string
		Gopath    string
		TempDir   string
		Go        string
		Debug     bool
	}
	letter = map[string]string{
		"amd64": "6",
		"arm":   "5",
		"ppc":   "9",
	}
)

func getenv(e, d string) string {
	v := os.Getenv(e)
	if v == "" {
		v = d
	}
	return v
}

func lsr(n string, w *os.File) error {
	n = n + "/"
	err := filepath.Walk(n, func(name string, fi os.FileInfo, err error) error {
		if err != nil {
			return err
		}
		cn := strings.TrimPrefix(name, n)
		fmt.Fprintf(w, "%v\n", cn)
		return nil
	})
	return err
}

// we'll keep using cpio and hope the kernel gets fixed some day.
func cpiop(c string) error {

	t := template.Must(template.New("filelist").Parse(c))
	var b bytes.Buffer
	if err := t.Execute(&b, config); err != nil {
		log.Fatalf("spec %v: %v\n", c, err)
	}

	n := strings.Split(b.String(), "\n")
	if config.Debug {
		fmt.Fprintf(os.Stderr, "Strings :%v:\n", n)
	}

	r, w, err := os.Pipe()
	if err != nil {
		log.Fatalf("%v\n", err)
	}
	cmd := exec.Command("cpio", "--make-directories", "-p", config.TempDir)
	cmd.Dir = n[0]
	cmd.Stdin = r
	cmd.Stderr = os.Stderr
	cmd.Stdout = os.Stdout
	if config.Debug {
		log.Printf("Run %v @ %v", cmd, cmd.Dir)
	}
	err = cmd.Start()
	if err != nil {
		fmt.Fprintf(os.Stderr, "%v\n", err)
	}

	for _, v := range n[1:] {
		if config.Debug {
			fmt.Fprintf(os.Stderr, "%v\n", v)
		}
		err := filepath.Walk(path.Join(n[0], v), func(name string, fi os.FileInfo, err error) error {
			if err != nil {
				fmt.Printf(" WALK FAIL%v: %v\n", name, err)
				// That's ok, sometimes things are not there.
				return filepath.SkipDir
			}
			cn := strings.TrimPrefix(name, n[0]+"/")
			if cn == ".git" {
				return filepath.SkipDir
			}
			fmt.Fprintf(w, "%v\n", cn)
			//fmt.Printf("c.dir %v %v %v\n", n[0], name, cn)
			return nil
		})
		if err != nil {
			fmt.Printf("%s: %v\n", v, err)
		}
	}
	w.Close()
	err = cmd.Wait()
	if err != nil {
		fmt.Fprintf(os.Stderr, "%v\n", err)
	}
	return nil
}

func sanity() {
	goBinGo := path.Join(config.Goroot, "bin/go")
	_, err := os.Stat(goBinGo)
	if err == nil {
		config.Go = goBinGo
	}
	// but does the one in go/bin/OS_ARCH exist too?
	goBinGo = path.Join(config.Goroot, fmt.Sprintf("bin/%s_%s/go", config.Goos, config.Arch))
	_, err = os.Stat(goBinGo)
	if err == nil {
		config.Go = goBinGo
	}
	if config.Go == "" {
		log.Fatalf("Can't find a go binary! Is GOROOT set correctly?")
	}
}

// sad news. If I concat the Go cpio with the other cpios, for reasons I don't understand,
// the kernel can't unpack it. Don't know why, don't care. Need to create one giant cpio and unpack that.
// It's not size related: if the go archive is first or in the middle it still fails.
func main() {
	flag.BoolVar(&config.Debug, "d", false, "Debugging")
	flag.Parse()
	var err error
	config.Arch = getenv("GOARCH", "amd64")
	config.Goroot = getenv("GOROOT", "/")
	config.Gosrcroot = path.Dir(config.Goroot)
	config.Gopath = getenv("GOPATH", "")
	config.Goos = "linux"
	config.Letter = letter[config.Arch]
	config.TempDir, err = ioutil.TempDir("", "u-root")
	config.Go = ""
	if err != nil {
		log.Fatalf("%v", err)
	}

	// sanity checking: do /go/bin/go, and some basic source files exist?
	sanity()
	// Build init
	cmd := exec.Command("go", "build", "init.go")
	cmd.Stderr = os.Stderr
	cmd.Stdout = os.Stdout
	cmd.Dir = path.Join(config.Gopath, "src/cmds/init")

	err = cmd.Run()
	if err != nil {
		log.Fatalf("%v\n", err)
		os.Exit(1)
	}

	// These produce arrays of strings, the first element being the
	// directory to walk from.
	cpio := []string{
		goList,
		urootList,
		"{{.Gopath}}/src/cmds/init\ninit",
	}
	for _, c := range cpio {
		if err := cpiop(c); err != nil {
			log.Printf("Things went south. TempDir is %v", config.TempDir)
			log.Fatalf("Bailing out near line 666")
		}
	}

	r, w, err := os.Pipe()
	if err != nil {
		log.Fatalf("%v\n", err)
	}

	// First create the archive and put the device cpio in it.
	dev, err := ioutil.ReadFile("dev.cpio")
	if err != nil {
		log.Fatal("%v %v\n", dev, err)
	}

	oname := fmt.Sprintf("/tmp/initramfs.%v_%v.cpio", config.Goos, config.Arch)
	if err := ioutil.WriteFile(oname, dev, 0600); err != nil {
		log.Fatal("%v\n", err)
	}

	// Now use the append option for cpio to append to it.
	// That way we get one cpio.
	cmd = exec.Command("cpio", "-H", "newc", "-o", "-A", "-F", oname)
	cmd.Dir = config.TempDir
	cmd.Stdin = r
	cmd.Stderr = os.Stderr
	cmd.Stdout = os.Stdout
	if config.Debug {
		fmt.Fprintf(os.Stderr, "Run %v @ %v", cmd, cmd.Dir)
	}
	err = cmd.Start()
	if err != nil {
		log.Fatalf("%v\n", err)
	}
	if err := lsr(config.TempDir, w); err != nil {
		log.Fatal("%v\n", err)
	}
	w.Close()
	err = cmd.Wait()
	if err != nil {
		fmt.Fprintf(os.Stderr, "%v\n", err)
	}
	fmt.Printf("Output file is in %v\n", oname)
}
<commit_msg>Create an initramfs for the simple bbsh case<commit_after>package main

import (
	"bytes"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"os/exec"
	"path"
	"path/filepath"
	"strings"
	"text/template"
)

type copyfiles struct {
	dir  string
	spec string
}

const (
	bbList = `{{.Uroot}}/src/bb/bbsh
bbsh`
)

var (
	config struct {
		Goroot    string
		Gosrcroot string
		Uroot	  string
		Arch      string
		Goos      string
		Letter    string
		Gopath    string
		TempDir   string
		Go        string
		Debug     bool
	}
	letter = map[string]string{
		"amd64": "6",
		"arm":   "5",
		"ppc":   "9",
	}
)

func getenv(e, d string) string {
	v := os.Getenv(e)
	if v == "" {
		v = d
	}
	return v
}

func lsr(n string, w *os.File) error {
	n = n + "/"
	err := filepath.Walk(n, func(name string, fi os.FileInfo, err error) error {
		if err != nil {
			return err
		}
		cn := strings.TrimPrefix(name, n)
		fmt.Fprintf(w, "%v\n", cn)
		return nil
	})
	return err
}

// we'll keep using cpio and hope the kernel gets fixed some day.
func cpiop(c string) error {

	t := template.Must(template.New("filelist").Parse(c))
	var b bytes.Buffer
	if err := t.Execute(&b, config); err != nil {
		log.Fatalf("spec %v: %v\n", c, err)
	}

	n := strings.Split(b.String(), "\n")
	if config.Debug {
		fmt.Fprintf(os.Stderr, "Strings :%v:\n", n)
	}

	r, w, err := os.Pipe()
	if err != nil {
		log.Fatalf("%v\n", err)
	}
	cmd := exec.Command("cpio", "--make-directories", "-p", config.TempDir)
	cmd.Dir = n[0]
	cmd.Stdin = r
	cmd.Stderr = os.Stderr
	cmd.Stdout = os.Stdout
	if config.Debug {
		log.Printf("Run %v @ %v", cmd, cmd.Dir)
	}
	err = cmd.Start()
	if err != nil {
		fmt.Fprintf(os.Stderr, "%v\n", err)
	}

	for _, v := range n[1:] {
		if config.Debug {
			fmt.Fprintf(os.Stderr, "%v\n", v)
		}
		err := filepath.Walk(path.Join(n[0], v), func(name string, fi os.FileInfo, err error) error {
			if err != nil {
				fmt.Printf(" WALK FAIL%v: %v\n", name, err)
				// That's ok, sometimes things are not there.
				return filepath.SkipDir
			}
			cn := strings.TrimPrefix(name, n[0]+"/")
			if cn == ".git" {
				return filepath.SkipDir
			}
			fmt.Fprintf(w, "%v\n", cn)
			fmt.Printf("c.dir %v %v %v\n", n[0], name, cn)
			return nil
		})
		if err != nil {
			fmt.Printf("%s: %v\n", v, err)
		}
	}
	w.Close()
	err = cmd.Wait()
	if err != nil {
		fmt.Fprintf(os.Stderr, "%v\n", err)
	}
	return nil
}

func sanity() {
	goBinGo := path.Join(config.Goroot, "bin/go")
	_, err := os.Stat(goBinGo)
	if err == nil {
		config.Go = goBinGo
	}
	// but does the one in go/bin/OS_ARCH exist too?
	goBinGo = path.Join(config.Goroot, fmt.Sprintf("bin/%s_%s/go", config.Goos, config.Arch))
	_, err = os.Stat(goBinGo)
	if err == nil {
		config.Go = goBinGo
	}
	if config.Go == "" {
		log.Fatalf("Can't find a go binary! Is GOROOT set correctly?")
	}
}

// sad news. If I concat the Go cpio with the other cpios, for reasons I don't understand,
// the kernel can't unpack it. Don't know why, don't care. Need to create one giant cpio and unpack that.
// It's not size related: if the go archive is first or in the middle it still fails.
func main() {
	flag.BoolVar(&config.Debug, "d", false, "Debugging")
	flag.Parse()
	var err error
	config.Arch = getenv("GOARCH", "amd64")
	config.Goroot = getenv("GOROOT", "/")
	config.Gosrcroot = path.Dir(config.Goroot)
	config.Gopath = getenv("GOPATH", "")
	config.Uroot = getenv("UROOT", "")
	config.Goos = "linux"
	config.Letter = letter[config.Arch]
	config.TempDir, err = ioutil.TempDir("", "u-root")
	config.Go = ""
	if err != nil {
		log.Fatalf("%v", err)
	}

	// Build init
	cmd := exec.Command("go", "build", ".")
	cmd.Stderr = os.Stderr
	cmd.Stdout = os.Stdout
	cmd.Dir = path.Join(config.Uroot, "src/bb/bbsh")
fmt.Printf("cmd.DIr %v\n", cmd.Dir)
fmt.Printf("cmd %v\n", cmd)

	err = cmd.Run()
	if err != nil {
		log.Fatalf("%v\n", err)
		os.Exit(1)
	}
fmt.Printf("BUILT bbsh\n")

	r, w, err := os.Pipe()
	if err != nil {
		log.Fatalf("%v\n", err)
	}

	// First create the archive and put the device cpio in it.
	dev, err := ioutil.ReadFile("dev.cpio")
	if err != nil {
		log.Fatal("%v %v\n", dev, err)
	}

	oname := fmt.Sprintf("/tmp/initramfs.%v_%v.cpio", config.Goos, config.Arch)
	if err := ioutil.WriteFile(oname, dev, 0600); err != nil {
		log.Fatal("%v\n", err)
	}

	// Now use the append option for cpio to append to it.
	// That way we get one cpio.
	cmd = exec.Command("cpio", "-H", "newc", "-o", "-A", "-F", oname)
	cmd.Dir = path.Join(config.Uroot, "src/bb/bbsh")
	cmd.Stdin = r
	cmd.Stderr = os.Stderr
	cmd.Stdout = os.Stdout
	if config.Debug {
		fmt.Fprintf(os.Stderr, "Run %v @ %v", cmd, cmd.Dir)
	}
	err = cmd.Start()
	if err != nil {
		log.Fatalf("%v\n", err)
	}
	w.Write([]byte("bbsh\n"))
	w.Close()
	err = cmd.Wait()
	if err != nil {
		fmt.Fprintf(os.Stderr, "%v\n", err)
	}
	fmt.Printf("Output file is in %v\n", oname)
}
<|endoftext|>


<commit_before>package webhook

import (
	"encoding/json"
	"errors"
	"socialapi/models"
	"time"

	"github.com/jinzhu/gorm"
	"github.com/koding/bongo"
	"github.com/nu7hatch/gouuid"
)

var (
	ErrIntegrationIdIsNotSet      = errors.New("integration id is not set")
	ErrGroupChannelIdIsNotSet     = errors.New("group channel id is not set")
	ErrChannelIntegrationNotFound = errors.New("channel integration is not found")
	ErrTokenNotSet                = errors.New("token is not set")
)

type ChannelIntegration struct {
	// unique identifier of the channel integration
	Id int64 `json:"id,string"`

	// Description of the channel integration
	Description string `json:"description" sql:"TYPE:TEXT"`

	// Unique token value of the channel integration
	Token string `json:"token" sql:"NOT NULL;TYPE:VARCHAR(20)"`

	// Id of the integration
	IntegrationId int64 `json:"integrationId,string" sql:"NOT NULL;TYPE:BIGINT"`

	// Group name of the integration
	GroupName string `json:"groupName" sql:"NOT NULL;TYPE:VARCHAR(200)"`

	// Id of the channel
	ChannelId int64 `json:"channelId,string" sql:"NOT NULL;TYPE:BIGINT"`

	// Id of the creator
	CreatorId int64 `json:"creatorId" sql:"NOT NULL;TYPE:BIGINT"`

	// Flag to enable/disable a channel integration
	IsDisabled bool `json:"isDisabled" sql:"NOT NULL;TYPE:BOOLEAN"`

	// Settings field used for storing custom bot name, icon path and various
	// other data
	Settings gorm.Hstore `json:"settings"`

	// Creation date of the integration
	CreatedAt time.Time `json:"createdAt" sql:"NOT NULL"`

	// Modification date of the integration
	UpdatedAt time.Time `json:"updatedAt" sql:"NOT NULL"`

	// Deletion date of the integration
	DeletedAt time.Time `json:"deletedAt" sql:"NOT NULL"`

	// Options is used for providing optional data
	Options map[string]interface{} `json:"optional" sql:"-"`
}

func NewChannelIntegration() *ChannelIntegration {
	return &ChannelIntegration{}
}

func (i *ChannelIntegration) Create() error {
	if err := i.Validate(); err != nil {
		return err
	}

	token, err := uuid.NewV4()
	if err != nil {
		return err
	}
	i.Token = token.String()

	return bongo.B.Create(i)
}

func (i *ChannelIntegration) ByToken(token string) error {
	query := &bongo.Query{
		Selector: map[string]interface{}{
			"token": token,
		},
	}

	err := i.One(query)
	if err == bongo.RecordNotFound {
		return ErrChannelIntegrationNotFound
	}

	if err != nil {
		return err
	}

	return nil
}

func (i *ChannelIntegration) Validate() error {
	if i.GroupName == "" {
		return models.ErrGroupNameIsNotSet
	}

	if i.ChannelId == 0 {
		return models.ErrChannelIsNotSet
	}

	if i.IntegrationId == 0 {
		return ErrIntegrationIdIsNotSet
	}

	if i.CreatorId == 0 {
		return models.ErrCreatorIdIsNotSet
	}

	return nil
}

func (i *ChannelIntegration) RegenerateToken() error {
	var token string
	for {
		ci := NewChannelIntegration()
		t, err := uuid.NewV4()
		if err != nil {
			return err
		}

		token = t.String()
		tokenErr := ci.ByToken(token)
		if tokenErr == ErrChannelIntegrationNotFound {
			break
		}

		if tokenErr != nil {
			return tokenErr
		}
	}

	i.Token = token

	return i.Update()
}

func (i *ChannelIntegration) ByGroupName(groupName string) ([]ChannelIntegration, error) {
	var ints []ChannelIntegration
	if groupName == "" {
		return ints, nil
	}

	query := &bongo.Query{
		Selector: map[string]interface{}{
			"group_name": groupName,
		},
	}

	if err := i.Some(&ints, query); err != nil {
		return nil, err
	}

	return ints, nil
}

func (i *ChannelIntegration) AddSettings(name string, value interface{}) error {
	if i.Settings == nil {
		i.Settings = gorm.Hstore{}
	}

	switch value.(type) {
	case string:
		result := value.(string)
		i.Settings[name] = &result
		return nil
	}

	settings, err := json.Marshal(value)
	if err != nil {
		return err
	}

	settingsStr := string(settings)

	i.Settings[name] = &settingsStr

	return nil
}

func (i *ChannelIntegration) GetSettings(name string) (*string, error) {
	if i.Settings == nil {
		return nil, ErrSettingNotFound
	}

	v, ok := i.Settings[name]
	if !ok {
		return nil, ErrSettingNotFound
	}

	return v, nil
}
<commit_msg>pivotal: one of the same error is removed<commit_after>package webhook

import (
	"encoding/json"
	"errors"
	"socialapi/models"
	"time"

	"github.com/jinzhu/gorm"
	"github.com/koding/bongo"
	"github.com/nu7hatch/gouuid"
)

var (
	ErrIntegrationIdIsNotSet      = errors.New("integration id is not set")
	ErrGroupChannelIdIsNotSet     = errors.New("group channel id is not set")
	ErrChannelIntegrationNotFound = errors.New("channel integration is not found")
)

type ChannelIntegration struct {
	// unique identifier of the channel integration
	Id int64 `json:"id,string"`

	// Description of the channel integration
	Description string `json:"description" sql:"TYPE:TEXT"`

	// Unique token value of the channel integration
	Token string `json:"token" sql:"NOT NULL;TYPE:VARCHAR(20)"`

	// Id of the integration
	IntegrationId int64 `json:"integrationId,string" sql:"NOT NULL;TYPE:BIGINT"`

	// Group name of the integration
	GroupName string `json:"groupName" sql:"NOT NULL;TYPE:VARCHAR(200)"`

	// Id of the channel
	ChannelId int64 `json:"channelId,string" sql:"NOT NULL;TYPE:BIGINT"`

	// Id of the creator
	CreatorId int64 `json:"creatorId" sql:"NOT NULL;TYPE:BIGINT"`

	// Flag to enable/disable a channel integration
	IsDisabled bool `json:"isDisabled" sql:"NOT NULL;TYPE:BOOLEAN"`

	// Settings field used for storing custom bot name, icon path and various
	// other data
	Settings gorm.Hstore `json:"settings"`

	// Creation date of the integration
	CreatedAt time.Time `json:"createdAt" sql:"NOT NULL"`

	// Modification date of the integration
	UpdatedAt time.Time `json:"updatedAt" sql:"NOT NULL"`

	// Deletion date of the integration
	DeletedAt time.Time `json:"deletedAt" sql:"NOT NULL"`

	// Options is used for providing optional data
	Options map[string]interface{} `json:"optional" sql:"-"`
}

func NewChannelIntegration() *ChannelIntegration {
	return &ChannelIntegration{}
}

func (i *ChannelIntegration) Create() error {
	if err := i.Validate(); err != nil {
		return err
	}

	token, err := uuid.NewV4()
	if err != nil {
		return err
	}
	i.Token = token.String()

	return bongo.B.Create(i)
}

func (i *ChannelIntegration) ByToken(token string) error {
	query := &bongo.Query{
		Selector: map[string]interface{}{
			"token": token,
		},
	}

	err := i.One(query)
	if err == bongo.RecordNotFound {
		return ErrChannelIntegrationNotFound
	}

	if err != nil {
		return err
	}

	return nil
}

func (i *ChannelIntegration) Validate() error {
	if i.GroupName == "" {
		return models.ErrGroupNameIsNotSet
	}

	if i.ChannelId == 0 {
		return models.ErrChannelIsNotSet
	}

	if i.IntegrationId == 0 {
		return ErrIntegrationIdIsNotSet
	}

	if i.CreatorId == 0 {
		return models.ErrCreatorIdIsNotSet
	}

	return nil
}

func (i *ChannelIntegration) RegenerateToken() error {
	var token string
	for {
		ci := NewChannelIntegration()
		t, err := uuid.NewV4()
		if err != nil {
			return err
		}

		token = t.String()
		tokenErr := ci.ByToken(token)
		if tokenErr == ErrChannelIntegrationNotFound {
			break
		}

		if tokenErr != nil {
			return tokenErr
		}
	}

	i.Token = token

	return i.Update()
}

func (i *ChannelIntegration) ByGroupName(groupName string) ([]ChannelIntegration, error) {
	var ints []ChannelIntegration
	if groupName == "" {
		return ints, nil
	}

	query := &bongo.Query{
		Selector: map[string]interface{}{
			"group_name": groupName,
		},
	}

	if err := i.Some(&ints, query); err != nil {
		return nil, err
	}

	return ints, nil
}

func (i *ChannelIntegration) AddSettings(name string, value interface{}) error {
	if i.Settings == nil {
		i.Settings = gorm.Hstore{}
	}

	switch value.(type) {
	case string:
		result := value.(string)
		i.Settings[name] = &result
		return nil
	}

	settings, err := json.Marshal(value)
	if err != nil {
		return err
	}

	settingsStr := string(settings)

	i.Settings[name] = &settingsStr

	return nil
}

func (i *ChannelIntegration) GetSettings(name string) (*string, error) {
	if i.Settings == nil {
		return nil, ErrSettingNotFound
	}

	v, ok := i.Settings[name]
	if !ok {
		return nil, ErrSettingNotFound
	}

	return v, nil
}
<|endoftext|>