<commit_before>package device

import (
	"fmt"

	"github.com/pkg/errors"

	deviceConfig "github.com/lxc/lxd/lxd/device/config"
	"github.com/lxc/lxd/lxd/instance"
	"github.com/lxc/lxd/lxd/instance/instancetype"
	"github.com/lxc/lxd/lxd/network"
	"github.com/lxc/lxd/lxd/revert"
	"github.com/lxc/lxd/lxd/util"
	"github.com/lxc/lxd/shared"
)

type nicPhysical struct {
	deviceCommon
}

// validateConfig checks the supplied config for correctness.
func (d *nicPhysical) validateConfig(instConf instance.ConfigReader) error {
	if !instanceSupported(instConf.Type(), instancetype.Container, instancetype.VM) {
		return ErrUnsupportedDevType
	}

	requiredFields := []string{"parent"}
	optionalFields := []string{
		"name",
		"maas.subnet.ipv4",
		"maas.subnet.ipv6",
		"boot.priority",
	}

	if instConf.Type() == instancetype.Container {
		optionalFields = append(optionalFields, "mtu", "hwaddr", "vlan")
	}

	err := d.config.Validate(nicValidationRules(requiredFields, optionalFields))
	if err != nil {
		return err
	}

	return nil
}

// validateEnvironment checks the runtime environment for correctness.
func (d *nicPhysical) validateEnvironment() error {
	if d.inst.Type() == instancetype.Container && d.config["name"] == "" {
		return fmt.Errorf("Requires name property to start")
	}

	if !shared.PathExists(fmt.Sprintf("/sys/class/net/%s", d.config["parent"])) {
		return fmt.Errorf("Parent device '%s' doesn't exist", d.config["parent"])
	}

	return nil
}

// Start is run when the device is added to a running instance or instance is starting up.
func (d *nicPhysical) Start() (*deviceConfig.RunConfig, error) {
	err := d.validateEnvironment()
	if err != nil {
		return nil, err
	}

	// Lock to avoid issues with containers starting in parallel.
	networkCreateSharedDeviceLock.Lock()
	defer networkCreateSharedDeviceLock.Unlock()

	saveData := make(map[string]string)

	revert := revert.New()
	defer revert.Fail()

	// pciSlotName, used for VM physical passthrough.
	var pciSlotName string

	// If VM, then try and load the vfio-pci module first.
	if d.inst.Type() == instancetype.VM {
		err = util.LoadModule("vfio-pci")
		if err != nil {
			return nil, errors.Wrapf(err, "Error loading %q module", "vfio-pci")
		}
	}

	// Record the host_name device used for restoration later.
	saveData["host_name"] = network.GetHostDevice(d.config["parent"], d.config["vlan"])

	if d.inst.Type() == instancetype.Container {
		statusDev, err := networkCreateVlanDeviceIfNeeded(d.state, d.config["parent"], saveData["host_name"], d.config["vlan"])
		if err != nil {
			return nil, err
		}

		// Record whether we created this device or not so it can be removed on stop.
		saveData["last_state.created"] = fmt.Sprintf("%t", statusDev != "existing")

		if shared.IsTrue(saveData["last_state.created"]) {
			revert.Add(func() {
				networkRemoveInterfaceIfNeeded(d.state, saveData["host_name"], d.inst, d.config["parent"], d.config["vlan"])
			})
		}

		// If we didn't create the device we should track various properties so we can restore them when the
		// instance is stopped or the device is detached.
		if !shared.IsTrue(saveData["last_state.created"]) {
			err = networkSnapshotPhysicalNic(saveData["host_name"], saveData)
			if err != nil {
				return nil, err
			}
		}

		// Set the MAC address.
		if d.config["hwaddr"] != "" {
			_, err := shared.RunCommand("ip", "link", "set", "dev", saveData["host_name"], "address", d.config["hwaddr"])
			if err != nil {
				return nil, fmt.Errorf("Failed to set the MAC address: %s", err)
			}
		}

		// Set the MTU.
		if d.config["mtu"] != "" {
			err = network.InterfaceSetMTU(saveData["host_name"], d.config["mtu"])
			if err != nil {
				return nil, err
			}
		}
	} else if d.inst.Type() == instancetype.VM {
		// Get PCI information about the network interface.
		ueventPath := fmt.Sprintf("/sys/class/net/%s/device/uevent", saveData["host_name"])
		pciDev, err := pciParseUeventFile(ueventPath)
		if err != nil {
			return nil, errors.Wrapf(err, "Failed to get PCI device info for %q", saveData["host_name"])
		}

		saveData["last_state.pci.slot.name"] = pciDev.SlotName
		saveData["last_state.pci.driver"] = pciDev.Driver

		err = pciDeviceDriverOverride(pciDev, "vfio-pci")
		if err != nil {
			return nil, err
		}

		pciSlotName = saveData["last_state.pci.slot.name"]
	}

	err = d.volatileSet(saveData)
	if err != nil {
		return nil, err
	}

	runConf := deviceConfig.RunConfig{}
	runConf.NetworkInterface = []deviceConfig.RunConfigItem{
		{Key: "name", Value: d.config["name"]},
		{Key: "type", Value: "phys"},
		{Key: "flags", Value: "up"},
		{Key: "link", Value: saveData["host_name"]},
	}

	if d.inst.Type() == instancetype.VM {
		runConf.NetworkInterface = append(runConf.NetworkInterface,
			[]deviceConfig.RunConfigItem{
				{Key: "devName", Value: d.name},
				{Key: "pciSlotName", Value: pciSlotName},
			}...)
	}

	revert.Success()
	return &runConf, nil
}

// Stop is run when the device is removed from the instance.
func (d *nicPhysical) Stop() (*deviceConfig.RunConfig, error) {
	v := d.volatileGet()
	runConf := deviceConfig.RunConfig{
		PostHooks: []func() error{d.postStop},
		NetworkInterface: []deviceConfig.RunConfigItem{
			{Key: "link", Value: v["host_name"]},
		},
	}

	return &runConf, nil
}

// postStop is run after the device is removed from the instance.
func (d *nicPhysical) postStop() error {
	defer d.volatileSet(map[string]string{
		"host_name":                "",
		"last_state.hwaddr":        "",
		"last_state.mtu":           "",
		"last_state.created":       "",
		"last_state.pci.slot.name": "",
		"last_state.pci.driver":    "",
	})

	v := d.volatileGet()

	// If VM physical pass through, unbind from vfio-pci and bind back to host driver.
	if d.inst.Type() == instancetype.VM && v["last_state.pci.slot.name"] != "" {
		vfioDev := pciDevice{
			Driver:   "vfio-pci",
			SlotName: v["last_state.pci.slot.name"],
		}

		err := pciDeviceDriverOverride(vfioDev, v["last_state.pci.driver"])
		if err != nil {
			return err
		}
	} else if d.inst.Type() == instancetype.Container {
		hostName := network.GetHostDevice(d.config["parent"], d.config["vlan"])

		// This will delete the parent interface if we created it for VLAN parent.
		if shared.IsTrue(v["last_state.created"]) {
			err := networkRemoveInterfaceIfNeeded(d.state, hostName, d.inst, d.config["parent"], d.config["vlan"])
			if err != nil {
				return err
			}
		} else if v["last_state.pci.slot.name"] == "" {
			err := networkRestorePhysicalNic(hostName, v)
			if err != nil {
				return err
			}
		}
	}

	return nil
}
<commit_msg>lxd/device/nic/physical: Use pci package<commit_after>package device

import (
	"fmt"

	"github.com/pkg/errors"

	deviceConfig "github.com/lxc/lxd/lxd/device/config"
	"github.com/lxc/lxd/lxd/device/pci"
	"github.com/lxc/lxd/lxd/instance"
	"github.com/lxc/lxd/lxd/instance/instancetype"
	"github.com/lxc/lxd/lxd/network"
	"github.com/lxc/lxd/lxd/revert"
	"github.com/lxc/lxd/lxd/util"
	"github.com/lxc/lxd/shared"
)

type nicPhysical struct {
	deviceCommon
}

// validateConfig checks the supplied config for correctness.
func (d *nicPhysical) validateConfig(instConf instance.ConfigReader) error {
	if !instanceSupported(instConf.Type(), instancetype.Container, instancetype.VM) {
		return ErrUnsupportedDevType
	}

	requiredFields := []string{"parent"}
	optionalFields := []string{
		"name",
		"maas.subnet.ipv4",
		"maas.subnet.ipv6",
		"boot.priority",
	}

	if instConf.Type() == instancetype.Container {
		optionalFields = append(optionalFields, "mtu", "hwaddr", "vlan")
	}

	err := d.config.Validate(nicValidationRules(requiredFields, optionalFields))
	if err != nil {
		return err
	}

	return nil
}

// validateEnvironment checks the runtime environment for correctness.
func (d *nicPhysical) validateEnvironment() error {
	if d.inst.Type() == instancetype.Container && d.config["name"] == "" {
		return fmt.Errorf("Requires name property to start")
	}

	if !shared.PathExists(fmt.Sprintf("/sys/class/net/%s", d.config["parent"])) {
		return fmt.Errorf("Parent device '%s' doesn't exist", d.config["parent"])
	}

	return nil
}

// Start is run when the device is added to a running instance or instance is starting up.
func (d *nicPhysical) Start() (*deviceConfig.RunConfig, error) {
	err := d.validateEnvironment()
	if err != nil {
		return nil, err
	}

	// Lock to avoid issues with containers starting in parallel.
	networkCreateSharedDeviceLock.Lock()
	defer networkCreateSharedDeviceLock.Unlock()

	saveData := make(map[string]string)

	revert := revert.New()
	defer revert.Fail()

	// pciSlotName, used for VM physical passthrough.
	var pciSlotName string

	// If VM, then try and load the vfio-pci module first.
	if d.inst.Type() == instancetype.VM {
		err = util.LoadModule("vfio-pci")
		if err != nil {
			return nil, errors.Wrapf(err, "Error loading %q module", "vfio-pci")
		}
	}

	// Record the host_name device used for restoration later.
	saveData["host_name"] = network.GetHostDevice(d.config["parent"], d.config["vlan"])

	if d.inst.Type() == instancetype.Container {
		statusDev, err := networkCreateVlanDeviceIfNeeded(d.state, d.config["parent"], saveData["host_name"], d.config["vlan"])
		if err != nil {
			return nil, err
		}

		// Record whether we created this device or not so it can be removed on stop.
		saveData["last_state.created"] = fmt.Sprintf("%t", statusDev != "existing")

		if shared.IsTrue(saveData["last_state.created"]) {
			revert.Add(func() {
				networkRemoveInterfaceIfNeeded(d.state, saveData["host_name"], d.inst, d.config["parent"], d.config["vlan"])
			})
		}

		// If we didn't create the device we should track various properties so we can restore them when the
		// instance is stopped or the device is detached.
		if !shared.IsTrue(saveData["last_state.created"]) {
			err = networkSnapshotPhysicalNic(saveData["host_name"], saveData)
			if err != nil {
				return nil, err
			}
		}

		// Set the MAC address.
		if d.config["hwaddr"] != "" {
			_, err := shared.RunCommand("ip", "link", "set", "dev", saveData["host_name"], "address", d.config["hwaddr"])
			if err != nil {
				return nil, fmt.Errorf("Failed to set the MAC address: %s", err)
			}
		}

		// Set the MTU.
		if d.config["mtu"] != "" {
			err = network.InterfaceSetMTU(saveData["host_name"], d.config["mtu"])
			if err != nil {
				return nil, err
			}
		}
	} else if d.inst.Type() == instancetype.VM {
		// Get PCI information about the network interface.
		ueventPath := fmt.Sprintf("/sys/class/net/%s/device/uevent", saveData["host_name"])
		pciDev, err := pci.ParseUeventFile(ueventPath)
		if err != nil {
			return nil, errors.Wrapf(err, "Failed to get PCI device info for %q", saveData["host_name"])
		}

		saveData["last_state.pci.slot.name"] = pciDev.SlotName
		saveData["last_state.pci.driver"] = pciDev.Driver

		err = pci.DeviceDriverOverride(pciDev, "vfio-pci")
		if err != nil {
			return nil, err
		}

		pciSlotName = saveData["last_state.pci.slot.name"]
	}

	err = d.volatileSet(saveData)
	if err != nil {
		return nil, err
	}

	runConf := deviceConfig.RunConfig{}
	runConf.NetworkInterface = []deviceConfig.RunConfigItem{
		{Key: "name", Value: d.config["name"]},
		{Key: "type", Value: "phys"},
		{Key: "flags", Value: "up"},
		{Key: "link", Value: saveData["host_name"]},
	}

	if d.inst.Type() == instancetype.VM {
		runConf.NetworkInterface = append(runConf.NetworkInterface,
			[]deviceConfig.RunConfigItem{
				{Key: "devName", Value: d.name},
				{Key: "pciSlotName", Value: pciSlotName},
			}...)
	}

	revert.Success()
	return &runConf, nil
}

// Stop is run when the device is removed from the instance.
func (d *nicPhysical) Stop() (*deviceConfig.RunConfig, error) {
	v := d.volatileGet()
	runConf := deviceConfig.RunConfig{
		PostHooks: []func() error{d.postStop},
		NetworkInterface: []deviceConfig.RunConfigItem{
			{Key: "link", Value: v["host_name"]},
		},
	}

	return &runConf, nil
}

// postStop is run after the device is removed from the instance.
func (d *nicPhysical) postStop() error {
	defer d.volatileSet(map[string]string{
		"host_name":                "",
		"last_state.hwaddr":        "",
		"last_state.mtu":           "",
		"last_state.created":       "",
		"last_state.pci.slot.name": "",
		"last_state.pci.driver":    "",
	})

	v := d.volatileGet()

	// If VM physical pass through, unbind from vfio-pci and bind back to host driver.
	if d.inst.Type() == instancetype.VM && v["last_state.pci.slot.name"] != "" {
		vfioDev := pci.Device{
			Driver:   "vfio-pci",
			SlotName: v["last_state.pci.slot.name"],
		}

		err := pci.DeviceDriverOverride(vfioDev, v["last_state.pci.driver"])
		if err != nil {
			return err
		}
	} else if d.inst.Type() == instancetype.Container {
		hostName := network.GetHostDevice(d.config["parent"], d.config["vlan"])

		// This will delete the parent interface if we created it for VLAN parent.
		if shared.IsTrue(v["last_state.created"]) {
			err := networkRemoveInterfaceIfNeeded(d.state, hostName, d.inst, d.config["parent"], d.config["vlan"])
			if err != nil {
				return err
			}
		} else if v["last_state.pci.slot.name"] == "" {
			err := networkRestorePhysicalNic(hostName, v)
			if err != nil {
				return err
			}
		}
	}

	return nil
}
<|endoftext|>


<commit_before>// Copyright 2018 Google LLC All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package mutate

import (
	"archive/tar"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"path/filepath"
	"strings"

	"github.com/google/go-containerregistry/v1"
	"github.com/google/go-containerregistry/v1/partial"
	"github.com/google/go-containerregistry/v1/types"
)

const whiteoutPrefix = ".wh."

// Addendum contains layers and history to be appended
// to a base image
type Addendum struct {
	Layer   v1.Layer
	History v1.History
}

// AppendLayers applies layers to a base image
func AppendLayers(base v1.Image, layers ...v1.Layer) (v1.Image, error) {
	additions := make([]Addendum, 0, len(layers))
	for _, layer := range layers {
		additions = append(additions, Addendum{Layer: layer})
	}

	return Append(base, additions...)
}

// Append will apply the list of addendums to the base image
func Append(base v1.Image, adds ...Addendum) (v1.Image, error) {
	if len(adds) == 0 {
		return base, nil
	}

	if err := validate(adds); err != nil {
		return nil, err
	}

	m, err := base.Manifest()
	if err != nil {
		return nil, err
	}

	cf, err := base.ConfigFile()
	if err != nil {
		return nil, err
	}

	image := &image{
		Image:      base,
		manifest:   m.DeepCopy(),
		configFile: cf.DeepCopy(),
		diffIDMap:  make(map[v1.Hash]v1.Layer),
		digestMap:  make(map[v1.Hash]v1.Layer),
	}

	diffIDs := image.configFile.RootFS.DiffIDs
	history := image.configFile.History

	for _, add := range adds {
		diffID, err := add.Layer.DiffID()
		if err != nil {
			return nil, err
		}
		diffIDs = append(diffIDs, diffID)
		history = append(history, add.History)
		image.diffIDMap[diffID] = add.Layer
	}

	manifestLayers := image.manifest.Layers

	for _, add := range adds {
		d := v1.Descriptor{
			MediaType: types.DockerLayer,
		}

		if d.Size, err = add.Layer.Size(); err != nil {
			return nil, err
		}

		if d.Digest, err = add.Layer.Digest(); err != nil {
			return nil, err
		}

		manifestLayers = append(manifestLayers, d)
		image.digestMap[d.Digest] = add.Layer
	}

	image.configFile.RootFS.DiffIDs = diffIDs
	image.configFile.History = history
	image.manifest.Layers = manifestLayers
	image.manifest.Config.Digest, err = image.ConfigName()
	if err != nil {
		return nil, err
	}

	return image, nil
}

// Config mutates the provided v1.Image to have the provided v1.Config
func Config(base v1.Image, cfg v1.Config) (v1.Image, error) {
	m, err := base.Manifest()
	if err != nil {
		return nil, err
	}

	cf, err := base.ConfigFile()
	if err != nil {
		return nil, err
	}

	cf.Config = cfg

	image := &image{
		Image:      base,
		manifest:   m.DeepCopy(),
		configFile: cf.DeepCopy(),
		diffIDMap:  make(map[v1.Hash]v1.Layer),
		digestMap:  make(map[v1.Hash]v1.Layer),
	}
	image.manifest.Config.Digest, err = image.ConfigName()
	if err != nil {
		return nil, err
	}
	return image, nil
}

type image struct {
	v1.Image
	configFile *v1.ConfigFile
	manifest   *v1.Manifest
	diffIDMap  map[v1.Hash]v1.Layer
	digestMap  map[v1.Hash]v1.Layer
}

// Layers returns the ordered collection of filesystem layers that comprise this image.
// The order of the list is oldest/base layer first, and most-recent/top layer last.
func (i *image) Layers() ([]v1.Layer, error) {
	diffIDs, err := partial.DiffIDs(i)
	if err != nil {
		return nil, err
	}
	ls := make([]v1.Layer, 0, len(diffIDs))
	for _, h := range diffIDs {
		l, err := i.LayerByDiffID(h)
		if err != nil {
			return nil, err
		}
		ls = append(ls, l)
	}
	return ls, nil
}

// BlobSet returns an unordered collection of all the blobs in the image.
func (i *image) BlobSet() (map[v1.Hash]struct{}, error) {
	return partial.BlobSet(i)
}

// ConfigName returns the hash of the image's config file.
func (i *image) ConfigName() (v1.Hash, error) {
	return partial.ConfigName(i)
}

// ConfigFile returns this image's config file.
func (i *image) ConfigFile() (*v1.ConfigFile, error) {
	return i.configFile, nil
}

// RawConfigFile returns the serialized bytes of ConfigFile()
func (i *image) RawConfigFile() ([]byte, error) {
	return json.Marshal(i.configFile)
}

// Digest returns the sha256 of this image's manifest.
func (i *image) Digest() (v1.Hash, error) {
	return partial.Digest(i)
}

// Manifest returns this image's Manifest object.
func (i *image) Manifest() (*v1.Manifest, error) {
	return i.manifest, nil
}

// RawManifest returns the serialized bytes of Manifest()
func (i *image) RawManifest() ([]byte, error) {
	return json.Marshal(i.manifest)
}

// LayerByDigest returns a Layer for interacting with a particular layer of
// the image, looking it up by "digest" (the compressed hash).
func (i *image) LayerByDigest(h v1.Hash) (v1.Layer, error) {
	if cn, err := i.ConfigName(); err != nil {
		return nil, err
	} else if h == cn {
		return partial.ConfigLayer(i)
	}
	if layer, ok := i.digestMap[h]; ok {
		return layer, nil
	}
	return i.Image.LayerByDigest(h)
}

// LayerByDiffID is an analog to LayerByDigest, looking up by "diff id"
// (the uncompressed hash).
func (i *image) LayerByDiffID(h v1.Hash) (v1.Layer, error) {
	if layer, ok := i.diffIDMap[h]; ok {
		return layer, nil
	}
	return i.Image.LayerByDiffID(h)
}

func validate(adds []Addendum) error {
	for _, add := range adds {
		if add.Layer == nil {
			return errors.New("Unable to add a nil layer to the image")
		}
	}
	return nil
}

// Extract takes an image and returns an io.ReadCloser containing the image's
// flattened filesystem.
//
// Callers can read the filesystem contents by passing the reader to
// tar.NewReader, or io.Copy it directly to some output.
//
// If a caller doesn't read the full contents, they should Close it to free up
// resources used during extraction.
//
// Adapted from https://github.com/google/containerregistry/blob/master/client/v2_2/docker_image_.py#L731
func Extract(img v1.Image) io.ReadCloser {
	pr, pw := io.Pipe()

	go func() {
		// Close the writer with any errors encountered during
		// extraction. These errors will be returned by the reader end
		// on subsequent reads. If err == nil, the reader will return
		// EOF.
		pw.CloseWithError(extract(img, pw))
	}()

	return pr
}

func extract(img v1.Image, w io.Writer) error {
	tarWriter := tar.NewWriter(w)
	defer tarWriter.Close()

	fileMap := map[string]bool{}

	layers, err := img.Layers()
	if err != nil {
		return fmt.Errorf("retrieving image layers: %v", err)
	}
	// we iterate through the layers in reverse order because it makes handling
	// whiteout layers more efficient, since we can just keep track of the removed
	// files as we see .wh. layers and ignore those in previous layers.
	for i := len(layers) - 1; i >= 0; i-- {
		layer := layers[i]
		layerReader, err := layer.Uncompressed()
		if err != nil {
			return fmt.Errorf("reading layer contents: %v", err)
		}
		tarReader := tar.NewReader(layerReader)
		for {
			header, err := tarReader.Next()
			if err == io.EOF {
				break
			}
			if err != nil {
				return fmt.Errorf("reading tar: %v", err)
			}

			basename := filepath.Base(header.Name)
			dirname := filepath.Dir(header.Name)
			tombstone := strings.HasPrefix(basename, whiteoutPrefix)
			if tombstone {
				basename = basename[len(whiteoutPrefix):]
			}

			// check if we have seen value before
			name := filepath.Join(dirname, basename)
			if _, ok := fileMap[name]; ok {
				continue
			}

			// check for a whited out parent directory
			if inWhiteoutDir(fileMap, name) {
				continue
			}

			// mark file as handled. non-directory implicitly tombstones
			// any entries with a matching (or child) name
			fileMap[name] = tombstone || !(header.Typeflag == tar.TypeDir)
			if !tombstone {
				tarWriter.WriteHeader(header)
				if header.Size > 0 {
					if _, err := io.Copy(tarWriter, tarReader); err != nil {
						return err
					}
				}
			}
		}
	}
	return nil
}

func inWhiteoutDir(fileMap map[string]bool, file string) bool {
	for {
		if file == "" {
			break
		}
		dirname := filepath.Dir(file)
		if file == dirname {
			break
		}
		if val, ok := fileMap[dirname]; ok && val {
			return true
		}
		file = dirname
	}
	return false
}
<commit_msg>don't filepath.Join names when splitting directories (#128)<commit_after>// Copyright 2018 Google LLC All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package mutate

import (
	"archive/tar"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"path/filepath"
	"strings"

	"github.com/google/go-containerregistry/v1"
	"github.com/google/go-containerregistry/v1/partial"
	"github.com/google/go-containerregistry/v1/types"
)

const whiteoutPrefix = ".wh."

// Addendum contains layers and history to be appended
// to a base image
type Addendum struct {
	Layer   v1.Layer
	History v1.History
}

// AppendLayers applies layers to a base image
func AppendLayers(base v1.Image, layers ...v1.Layer) (v1.Image, error) {
	additions := make([]Addendum, 0, len(layers))
	for _, layer := range layers {
		additions = append(additions, Addendum{Layer: layer})
	}

	return Append(base, additions...)
}

// Append will apply the list of addendums to the base image
func Append(base v1.Image, adds ...Addendum) (v1.Image, error) {
	if len(adds) == 0 {
		return base, nil
	}

	if err := validate(adds); err != nil {
		return nil, err
	}

	m, err := base.Manifest()
	if err != nil {
		return nil, err
	}

	cf, err := base.ConfigFile()
	if err != nil {
		return nil, err
	}

	image := &image{
		Image:      base,
		manifest:   m.DeepCopy(),
		configFile: cf.DeepCopy(),
		diffIDMap:  make(map[v1.Hash]v1.Layer),
		digestMap:  make(map[v1.Hash]v1.Layer),
	}

	diffIDs := image.configFile.RootFS.DiffIDs
	history := image.configFile.History

	for _, add := range adds {
		diffID, err := add.Layer.DiffID()
		if err != nil {
			return nil, err
		}
		diffIDs = append(diffIDs, diffID)
		history = append(history, add.History)
		image.diffIDMap[diffID] = add.Layer
	}

	manifestLayers := image.manifest.Layers

	for _, add := range adds {
		d := v1.Descriptor{
			MediaType: types.DockerLayer,
		}

		if d.Size, err = add.Layer.Size(); err != nil {
			return nil, err
		}

		if d.Digest, err = add.Layer.Digest(); err != nil {
			return nil, err
		}

		manifestLayers = append(manifestLayers, d)
		image.digestMap[d.Digest] = add.Layer
	}

	image.configFile.RootFS.DiffIDs = diffIDs
	image.configFile.History = history
	image.manifest.Layers = manifestLayers
	image.manifest.Config.Digest, err = image.ConfigName()
	if err != nil {
		return nil, err
	}

	return image, nil
}

// Config mutates the provided v1.Image to have the provided v1.Config
func Config(base v1.Image, cfg v1.Config) (v1.Image, error) {
	m, err := base.Manifest()
	if err != nil {
		return nil, err
	}

	cf, err := base.ConfigFile()
	if err != nil {
		return nil, err
	}

	cf.Config = cfg

	image := &image{
		Image:      base,
		manifest:   m.DeepCopy(),
		configFile: cf.DeepCopy(),
		diffIDMap:  make(map[v1.Hash]v1.Layer),
		digestMap:  make(map[v1.Hash]v1.Layer),
	}
	image.manifest.Config.Digest, err = image.ConfigName()
	if err != nil {
		return nil, err
	}
	return image, nil
}

type image struct {
	v1.Image
	configFile *v1.ConfigFile
	manifest   *v1.Manifest
	diffIDMap  map[v1.Hash]v1.Layer
	digestMap  map[v1.Hash]v1.Layer
}

// Layers returns the ordered collection of filesystem layers that comprise this image.
// The order of the list is oldest/base layer first, and most-recent/top layer last.
func (i *image) Layers() ([]v1.Layer, error) {
	diffIDs, err := partial.DiffIDs(i)
	if err != nil {
		return nil, err
	}
	ls := make([]v1.Layer, 0, len(diffIDs))
	for _, h := range diffIDs {
		l, err := i.LayerByDiffID(h)
		if err != nil {
			return nil, err
		}
		ls = append(ls, l)
	}
	return ls, nil
}

// BlobSet returns an unordered collection of all the blobs in the image.
func (i *image) BlobSet() (map[v1.Hash]struct{}, error) {
	return partial.BlobSet(i)
}

// ConfigName returns the hash of the image's config file.
func (i *image) ConfigName() (v1.Hash, error) {
	return partial.ConfigName(i)
}

// ConfigFile returns this image's config file.
func (i *image) ConfigFile() (*v1.ConfigFile, error) {
	return i.configFile, nil
}

// RawConfigFile returns the serialized bytes of ConfigFile()
func (i *image) RawConfigFile() ([]byte, error) {
	return json.Marshal(i.configFile)
}

// Digest returns the sha256 of this image's manifest.
func (i *image) Digest() (v1.Hash, error) {
	return partial.Digest(i)
}

// Manifest returns this image's Manifest object.
func (i *image) Manifest() (*v1.Manifest, error) {
	return i.manifest, nil
}

// RawManifest returns the serialized bytes of Manifest()
func (i *image) RawManifest() ([]byte, error) {
	return json.Marshal(i.manifest)
}

// LayerByDigest returns a Layer for interacting with a particular layer of
// the image, looking it up by "digest" (the compressed hash).
func (i *image) LayerByDigest(h v1.Hash) (v1.Layer, error) {
	if cn, err := i.ConfigName(); err != nil {
		return nil, err
	} else if h == cn {
		return partial.ConfigLayer(i)
	}
	if layer, ok := i.digestMap[h]; ok {
		return layer, nil
	}
	return i.Image.LayerByDigest(h)
}

// LayerByDiffID is an analog to LayerByDigest, looking up by "diff id"
// (the uncompressed hash).
func (i *image) LayerByDiffID(h v1.Hash) (v1.Layer, error) {
	if layer, ok := i.diffIDMap[h]; ok {
		return layer, nil
	}
	return i.Image.LayerByDiffID(h)
}

func validate(adds []Addendum) error {
	for _, add := range adds {
		if add.Layer == nil {
			return errors.New("Unable to add a nil layer to the image")
		}
	}
	return nil
}

// Extract takes an image and returns an io.ReadCloser containing the image's
// flattened filesystem.
//
// Callers can read the filesystem contents by passing the reader to
// tar.NewReader, or io.Copy it directly to some output.
//
// If a caller doesn't read the full contents, they should Close it to free up
// resources used during extraction.
//
// Adapted from https://github.com/google/containerregistry/blob/master/client/v2_2/docker_image_.py#L731
func Extract(img v1.Image) io.ReadCloser {
	pr, pw := io.Pipe()

	go func() {
		// Close the writer with any errors encountered during
		// extraction. These errors will be returned by the reader end
		// on subsequent reads. If err == nil, the reader will return
		// EOF.
		pw.CloseWithError(extract(img, pw))
	}()

	return pr
}

func extract(img v1.Image, w io.Writer) error {
	tarWriter := tar.NewWriter(w)
	defer tarWriter.Close()

	fileMap := map[string]bool{}

	layers, err := img.Layers()
	if err != nil {
		return fmt.Errorf("retrieving image layers: %v", err)
	}
	// we iterate through the layers in reverse order because it makes handling
	// whiteout layers more efficient, since we can just keep track of the removed
	// files as we see .wh. layers and ignore those in previous layers.
	for i := len(layers) - 1; i >= 0; i-- {
		layer := layers[i]
		layerReader, err := layer.Uncompressed()
		if err != nil {
			return fmt.Errorf("reading layer contents: %v", err)
		}
		tarReader := tar.NewReader(layerReader)
		for {
			header, err := tarReader.Next()
			if err == io.EOF {
				break
			}
			if err != nil {
				return fmt.Errorf("reading tar: %v", err)
			}

			basename := filepath.Base(header.Name)
			dirname := filepath.Dir(header.Name)
			tombstone := strings.HasPrefix(basename, whiteoutPrefix)
			if tombstone {
				basename = basename[len(whiteoutPrefix):]
			}

			// check if we have seen value before
			// if we're checking a directory, don't filepath.Join names
			var name string
			if header.Typeflag == tar.TypeDir {
				name = header.Name
			} else {
				name = filepath.Join(dirname, basename)
			}

			if _, ok := fileMap[name]; ok {
				continue
			}

			// check for a whited out parent directory
			if inWhiteoutDir(fileMap, name) {
				continue
			}

			// mark file as handled. non-directory implicitly tombstones
			// any entries with a matching (or child) name
			fileMap[name] = tombstone || !(header.Typeflag == tar.TypeDir)
			if !tombstone {
				tarWriter.WriteHeader(header)
				if header.Size > 0 {
					if _, err := io.Copy(tarWriter, tarReader); err != nil {
						return err
					}
				}
			}
		}
	}
	return nil
}

func inWhiteoutDir(fileMap map[string]bool, file string) bool {
	for {
		if file == "" {
			break
		}
		dirname := filepath.Dir(file)
		if file == dirname {
			break
		}
		if val, ok := fileMap[dirname]; ok && val {
			return true
		}
		file = dirname
	}
	return false
}
<|endoftext|>


<commit_before>package runlock

import (
	"context"
	"encoding/json"
	"io/ioutil"
	"os"
	"path/filepath"
	"time"

	"github.com/itchio/wharf/state"
	"github.com/itchio/wharf/werrors"
)

type Lock interface {
	Lock(ctx context.Context, task string) error
	Unlock() error
}

type lock struct {
	consumer      *state.Consumer
	installFolder string
}

type runlockPayload struct {
	Task      string `json:"task"`
	LockedAt  string `json:"lockedAt"`
	ButlerPID int64  `json:"butlerPID"`
}

func New(consumer *state.Consumer, installFolder string) Lock {
	rl := &lock{
		consumer:      consumer,
		installFolder: installFolder,
	}
	return rl
}

func (rl *lock) Lock(ctx context.Context, task string) error {
	printed := false

	isLocked := func() bool {
		rp, _ := rl.read()
		if rp == nil {
			return false
		}
		proc, _ := os.FindProcess(int(rp.ButlerPID))
		if proc != nil {
			// still running
			proc.Release()
		} else {
			// not running anymore
			rl.Unlock()
			return false
		}

		if !printed {
			printed = true
			rl.consumer.Debugf("Waiting (%s) for %s", rl.file(), task)
		}
		return true
	}

	if isLocked() {
	waitLoop:
		for {
			select {
			case <-time.After(1 * time.Second):
				if !isLocked() {
					break waitLoop
				}
			case <-ctx.Done():
				return werrors.ErrCancelled
			}
		}
	}

	rl.consumer.Debugf("Locking (%s) for %s", rl.file(), task)
	return rl.write(&runlockPayload{
		Task:      task,
		LockedAt:  time.Now().Format(time.RFC3339Nano),
		ButlerPID: int64(os.Getpid()),
	})
}

func (rl *lock) Unlock() error {
	return os.RemoveAll(rl.file())
}

func (rl *lock) file() string {
	return filepath.Join(rl.installFolder, ".itch", "runlock.json")
}

func (rl *lock) write(rp *runlockPayload) error {
	contents, err := json.Marshal(rp)
	if err != nil {
		return err
	}

	file := rl.file()
	err = os.MkdirAll(filepath.Dir(file), 0755)
	if err != nil {
		return err
	}
	return ioutil.WriteFile(file, contents, 0644)
}

func (rl *lock) read() (*runlockPayload, error) {
	var rp runlockPayload
	contents, err := ioutil.ReadFile(rl.file())
	if err != nil {
		return nil, err
	}
	err = json.Unmarshal(contents, &rp)
	if err != nil {
		return nil, err
	}
	return &rp, nil
}
<commit_msg>runlock: fix bug where an existing runlock file would hang forever on linux<commit_after>package runlock

import (
	"context"
	"encoding/json"
	"io/ioutil"
	"os"
	"path/filepath"
	"syscall"
	"time"

	"github.com/itchio/wharf/state"
	"github.com/itchio/wharf/werrors"
)

type Lock interface {
	Lock(ctx context.Context, task string) error
	Unlock() error
}

type lock struct {
	consumer      *state.Consumer
	installFolder string
}

type runlockPayload struct {
	Task      string `json:"task"`
	LockedAt  string `json:"lockedAt"`
	ButlerPID int64  `json:"butlerPID"`
}

func New(consumer *state.Consumer, installFolder string) Lock {
	rl := &lock{
		consumer:      consumer,
		installFolder: installFolder,
	}
	return rl
}

func (rl *lock) Lock(ctx context.Context, task string) error {
	printed := false

	isLocked := func() bool {
		debugf := func(f string, a ...interface{}) {
			rl.consumer.Debugf(f, a...)
			printed = true
		}
		if printed {
			debugf = func(f string, a ...interface{}) {}
		}

		rp, _ := rl.read()
		if rp == nil {
			return false
		}
		debugf("Has runlock file at (%s), PID (%d)", rl.file(), rp.ButlerPID)
		proc, _ := os.FindProcess(int(rp.ButlerPID))
		if proc != nil {
			debugf("Got a process handle, %#v", proc)

			err := proc.Signal(syscall.Signal(0))
			if err != nil {
				debugf("Got error while signalling PID (%d), assuming dead: %#v", rp.ButlerPID, err)

				// not running anymore
				rl.Unlock()
				return false
			}

			debugf("PID (%d) still running!", rp.ButlerPID, proc)
			proc.Release()
		} else {
			debugf("Didn't get a process handle, assuming dead")

			// not running anymore
			rl.Unlock()
			return false
		}

		if !printed {
			printed = true
			rl.consumer.Debugf("Waiting (%s) for %s", rl.file(), task)
		}
		return true
	}

	if isLocked() {
	waitLoop:
		for {
			select {
			case <-time.After(1 * time.Second):
				if !isLocked() {
					break waitLoop
				}
			case <-ctx.Done():
				return werrors.ErrCancelled
			}
		}
	}

	rl.consumer.Debugf("Locking (%s) for %s", rl.file(), task)
	return rl.write(&runlockPayload{
		Task:      task,
		LockedAt:  time.Now().Format(time.RFC3339Nano),
		ButlerPID: int64(os.Getpid()),
	})
}

func (rl *lock) Unlock() error {
	return os.RemoveAll(rl.file())
}

func (rl *lock) file() string {
	return filepath.Join(rl.installFolder, ".itch", "runlock.json")
}

func (rl *lock) write(rp *runlockPayload) error {
	contents, err := json.Marshal(rp)
	if err != nil {
		return err
	}

	file := rl.file()
	err = os.MkdirAll(filepath.Dir(file), 0755)
	if err != nil {
		return err
	}
	return ioutil.WriteFile(file, contents, 0644)
}

func (rl *lock) read() (*runlockPayload, error) {
	var rp runlockPayload
	contents, err := ioutil.ReadFile(rl.file())
	if err != nil {
		return nil, err
	}
	err = json.Unmarshal(contents, &rp)
	if err != nil {
		return nil, err
	}
	return &rp, nil
}
<|endoftext|>


<commit_before>// Copyright 2017 Ole Krüger.
// Licensed under the MIT license which can be found in the LICENSE file.

package dpt

import (
	"unicode"
)

// DPT_16000 represents DPT 16.000 / String ASCII.
// The string should be ASCII and contain at most 14 chars.
// A string longer than 14 chars will be silently truncated.
// Non-ASCII chars will be replaced with a space = 0x20.
type DPT_16000 string

func (d DPT_16000) Pack() []byte {
	var buf = make([]byte, 15)

	r := []rune(d)

	for i := 0; i < len(r) && i < 14; i++ {
		if rune(r[i]) > unicode.MaxASCII {
			buf[i+1] = 0x20
		} else {
			buf[i+1] = byte(r[i])
		}
	}

	return buf
}

func (d *DPT_16000) Unpack(data []byte) error {
	if len(data) != 15 {
		return ErrInvalidLength
	}

	var buf = []rune{}

	for i := 1; i < len(data) && data[i] != 0x00; i++ {
		buf = append(buf, rune(data[i]&unicode.MaxASCII))
	}

	*d = DPT_16000(buf)

	return nil
}

func (d DPT_16000) Unit() string {
	return ""
}

func (d DPT_16000) IsValid() bool {
	for _, c := range d {
		if c > unicode.MaxASCII {
			return false
		}
	}

	return len(d) <= 14
}

func (d DPT_16000) String() string {
	return string(d)
}

// DPT_16001 represents DPT 16.001 / String 8859-1.
// The string must be ISO-8859-1 and contain at most 14 chars.
// A string longer than 14 chars will be silently truncated.
// Non-ISO-8859-1 chars will be replaced with a space = 0x20.
type DPT_16001 string

func (d DPT_16001) Pack() []byte {
	buf := make([]byte, 15)

	r := []rune(d)

	for i := 0; i < len(r) && i < 14; i++ {
		if byte(r[i]) > unicode.MaxLatin1 {
			buf[i+1] = 0x20
		} else {
			buf[i+1] = byte(r[i])
		}
	}

	return buf
}

func (d *DPT_16001) Unpack(data []byte) error {
	if len(data) != 15 {
		return ErrInvalidLength
	}

	var buf = []rune{}

	for i := 1; i < len(data) && data[i] != 0x00; i++ {
		buf = append(buf, rune(data[i]))
	}

	*d = DPT_16001(buf)

	return nil
}

func (d DPT_16001) Unit() string {
	return ""
}

func (d DPT_16001) IsValid() bool {
	for _, c := range d {
		if c > unicode.MaxLatin1 {
			return false
		}
	}

	return len(d) <= 14
}

func (d DPT_16001) String() string {
	return string(d)
}
<commit_msg>Truncate 16.x DPT by rune code point, not uint8 value<commit_after>// Copyright 2017 Ole Krüger.
// Licensed under the MIT license which can be found in the LICENSE file.

package dpt

import (
	"unicode"
)

// DPT_16000 represents DPT 16.000 / String ASCII.
// The string should be ASCII and contain at most 14 chars.
// A string longer than 14 chars will be silently truncated.
// Non-ASCII chars will be replaced with a space = 0x20.
type DPT_16000 string

func (d DPT_16000) Pack() []byte {
	var buf = make([]byte, 15)

	r := []rune(d)

	for i := 0; i < len(r) && i < 14; i++ {
		if r[i] > unicode.MaxASCII {
			buf[i+1] = 0x20
		} else {
			buf[i+1] = byte(r[i])
		}
	}

	return buf
}

func (d *DPT_16000) Unpack(data []byte) error {
	if len(data) != 15 {
		return ErrInvalidLength
	}

	var buf = []rune{}

	for i := 1; i < len(data) && data[i] != 0x00; i++ {
		buf = append(buf, rune(data[i]&unicode.MaxASCII))
	}

	*d = DPT_16000(buf)

	return nil
}

func (d DPT_16000) Unit() string {
	return ""
}

func (d DPT_16000) IsValid() bool {
	for _, c := range d {
		if c > unicode.MaxASCII {
			return false
		}
	}

	return len(d) <= 14
}

func (d DPT_16000) String() string {
	return string(d)
}

// DPT_16001 represents DPT 16.001 / String 8859-1.
// The string must be ISO-8859-1 and contain at most 14 chars.
// A string longer than 14 chars will be silently truncated.
// Non-ISO-8859-1 chars will be replaced with a space = 0x20.
type DPT_16001 string

func (d DPT_16001) Pack() []byte {
	buf := make([]byte, 15)

	r := []rune(d)

	for i := 0; i < len(r) && i < 14; i++ {
		if r[i] > unicode.MaxLatin1 {
			buf[i+1] = 0x20
		} else {
			buf[i+1] = byte(r[i])
		}
	}

	return buf
}

func (d *DPT_16001) Unpack(data []byte) error {
	if len(data) != 15 {
		return ErrInvalidLength
	}

	var buf = []rune{}

	for i := 1; i < len(data) && data[i] != 0x00; i++ {
		buf = append(buf, rune(data[i]))
	}

	*d = DPT_16001(buf)

	return nil
}

func (d DPT_16001) Unit() string {
	return ""
}

func (d DPT_16001) IsValid() bool {
	for _, c := range d {
		if c > unicode.MaxLatin1 {
			return false
		}
	}

	return len(d) <= 14
}

func (d DPT_16001) String() string {
	return string(d)
}
<|endoftext|>


<commit_before>package proto

import (
	"bytes"
	"errors"
	"io"
	"github.com/vapourismo/knx-go/knx/encoding"
)

// ServiceID identifies the service that is contained in a packet.
type ServiceID uint16

// These are supported services.
const (
	ConnReqService      ServiceID = 0x0205
	ConnResService      ServiceID = 0x0206
	ConnStateReqService ServiceID = 0x0207
	ConnStateResService ServiceID = 0x0208
	DiscReqService      ServiceID = 0x0209
	DiscResService      ServiceID = 0x020a
	TunnelReqService    ServiceID = 0x0420
	TunnelResService    ServiceID = 0x0421
)

// Service describes a KNXnet/IP service.
type Service interface {
	Service() ServiceID
}

// ServiceWriterTo combines WriterTo and Service.
type ServiceWriterTo interface {
	Service
	io.WriterTo
}

// Pack generates a KNXnet/IP packet.
func Pack(w io.Writer, srv ServiceWriterTo) (int64, error) {
	dataBuffer := bytes.Buffer{}

	_, err := srv.WriteTo(&dataBuffer)
	if err != nil {
		return 0, err
	}

	return encoding.WriteSome(
		w, byte(6), byte(16), srv.Service(), uint16(dataBuffer.Len() + 6), &dataBuffer,
	)
}

// These are errors that might occur during unpacking.
var (
	ErrHeaderLength = errors.New("Header length is not 6")
	ErrHeaderVersion = errors.New("Protocol version is not 16")
	ErrUnknownService = errors.New("Unknown service identifier")
)

type serviceReaderFrom interface {
	io.ReaderFrom
	Service
}

// Unpack parses a KNXnet/IP packet and retrieves its service payload.
func Unpack(r io.Reader, srv *Service) (int64, error) {
	var headerLen, version uint8
	var srvID ServiceID
	var totalLen uint16

	n, err := encoding.ReadSome(r, &headerLen, &version, &srvID, &totalLen)
	if err != nil {
		return n, err
	}

	if headerLen != 6 {
		return n, ErrHeaderLength
	}

	if version != 16 {
		return n, ErrHeaderVersion
	}

	var body serviceReaderFrom
	switch srvID {
		case ConnResService:
			body = &ConnRes{}

		case ConnStateReqService:
			body = &ConnStateReq{}

		case ConnStateResService:
			body = &ConnStateRes{}

		case DiscReqService:
			body = &DiscReq{}

		case DiscResService:
			body = &DiscRes{}

		case TunnelReqService:
			body = &TunnelReq{}

		case TunnelResService:
			body = &TunnelRes{}

		default:
			return n, ErrUnknownService
	}

	m, err := body.ReadFrom(r)

	if err == nil {
		*srv = body
	}

	return n + m, err
}<commit_msg>proto: Add example on how to cast the Unpack result<commit_after>package proto

import (
	"bytes"
	"errors"
	"io"
	"github.com/vapourismo/knx-go/knx/encoding"
)

// ServiceID identifies the service that is contained in a packet.
type ServiceID uint16

// These are supported services.
const (
	ConnReqService      ServiceID = 0x0205
	ConnResService      ServiceID = 0x0206
	ConnStateReqService ServiceID = 0x0207
	ConnStateResService ServiceID = 0x0208
	DiscReqService      ServiceID = 0x0209
	DiscResService      ServiceID = 0x020a
	TunnelReqService    ServiceID = 0x0420
	TunnelResService    ServiceID = 0x0421
)

// Service describes a KNXnet/IP service.
type Service interface {
	Service() ServiceID
}

// ServiceWriterTo combines WriterTo and Service.
type ServiceWriterTo interface {
	Service
	io.WriterTo
}

// Pack generates a KNXnet/IP packet.
func Pack(w io.Writer, srv ServiceWriterTo) (int64, error) {
	dataBuffer := bytes.Buffer{}

	_, err := srv.WriteTo(&dataBuffer)
	if err != nil {
		return 0, err
	}

	return encoding.WriteSome(
		w, byte(6), byte(16), srv.Service(), uint16(dataBuffer.Len() + 6), &dataBuffer,
	)
}

// These are errors that might occur during unpacking.
var (
	ErrHeaderLength = errors.New("Header length is not 6")
	ErrHeaderVersion = errors.New("Protocol version is not 16")
	ErrUnknownService = errors.New("Unknown service identifier")
)

type serviceReaderFrom interface {
	io.ReaderFrom
	Service
}

// Unpack parses a KNXnet/IP packet and retrieves its service payload.
//
// On success, the variable pointed to by srv will contain a pointer to a service type.
// You can cast it to the matching against service type, like so:
//
// 	var srv Service
//
// 	_, err := Unpack(r, &srv)
// 	if err != nil {
// 		log.Fatal(err)
// 	}
//
// 	switch srv := srv.(type) {
// 		case *ConnRes:
// 			// ...
//
// 		case *TunnelReq:
// 			// ...
//
// 		// ...
// 	}
//
func Unpack(r io.Reader, srv *Service) (int64, error) {
	var headerLen, version uint8
	var srvID ServiceID
	var totalLen uint16

	n, err := encoding.ReadSome(r, &headerLen, &version, &srvID, &totalLen)
	if err != nil {
		return n, err
	}

	if headerLen != 6 {
		return n, ErrHeaderLength
	}

	if version != 16 {
		return n, ErrHeaderVersion
	}

	var body serviceReaderFrom
	switch srvID {
		case ConnResService:
			body = &ConnRes{}

		case ConnStateReqService:
			body = &ConnStateReq{}

		case ConnStateResService:
			body = &ConnStateRes{}

		case DiscReqService:
			body = &DiscReq{}

		case DiscResService:
			body = &DiscRes{}

		case TunnelReqService:
			body = &TunnelReq{}

		case TunnelResService:
			body = &TunnelRes{}

		default:
			return n, ErrUnknownService
	}

	m, err := body.ReadFrom(r)

	if err == nil {
		*srv = body
	}

	return n + m, err
}<|endoftext|>


<commit_before>/*
Copyright 2015 The Kubernetes Authors All rights reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package e2e

import (
	"fmt"
	"os/exec"
	"time"

	"k8s.io/kubernetes/pkg/api"
	"k8s.io/kubernetes/pkg/fields"
	"k8s.io/kubernetes/pkg/labels"
	"k8s.io/kubernetes/pkg/util"

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

var _ = Describe("Autoscaling", func() {
	f := NewFramework("autoscaling")
	var nodeCount int
	var coresPerNode int

	BeforeEach(func() {
		SkipUnlessProviderIs("gce")

		nodes, err := f.Client.Nodes().List(labels.Everything(), fields.Everything())
		expectNoError(err)
		nodeCount = len(nodes.Items)
		Expect(nodeCount).NotTo(BeZero())
		res := nodes.Items[0].Status.Capacity[api.ResourceCPU]
		coresPerNode = int((&res).MilliValue() / 1000)
	})

	AfterEach(func() {
		cleanUpAutoscaler()
	})

	It("[Skipped] [Autoscaling] should scale cluster size based on cpu utilization", func() {
		setUpAutoscaler("cpu/node_utilization", 0.7, nodeCount, nodeCount+1)

		ConsumeCpu(f, "cpu-utilization", nodeCount*coresPerNode)
		expectNoError(waitForClusterSize(f.Client, nodeCount+1))

		StopConsuming(f, "cpu-utilization")
		expectNoError(waitForClusterSize(f.Client, nodeCount))
	})

	It("[Skipped] should scale cluster size based on cpu reservation", func() {
		setUpAutoscaler("cpu/node_reservation", 0.7, 1, 10)

		ReserveCpu(f, "cpu-reservation", 800)
		expectNoError(waitForClusterSize(f.Client, 2))

		StopConsuming(f, "cpu-reservation")
		expectNoError(waitForClusterSize(f.Client, 1))
	})

	It("[Skipped] should scale cluster size based on memory utilization", func() {
		setUpAutoscaler("memory/node_utilization", 0.5, 1, 10)

		ConsumeMemory(f, "memory-utilization", 2)
		expectNoError(waitForClusterSize(f.Client, 2))

		StopConsuming(f, "memory-utilization")
		expectNoError(waitForClusterSize(f.Client, 1))
	})

	It("[Skipped] should scale cluster size based on memory reservation", func() {
		setUpAutoscaler("memory/node_reservation", 0.5, 1, 10)

		ReserveMemory(f, "memory-reservation", 2)
		expectNoError(waitForClusterSize(f.Client, 2))

		StopConsuming(f, "memory-reservation")
		expectNoError(waitForClusterSize(f.Client, 1))
	})
})

func setUpAutoscaler(metric string, target float64, min, max int) {
	// TODO integrate with kube-up.sh script once it will support autoscaler setup.
	By("Setting up autoscaler to scale based on " + metric)
	_, err := exec.Command("gcloud", "preview", "autoscaler",
		"--zone="+testContext.CloudConfig.Zone,
		"create", "e2e-test-autoscaler",
		"--project="+testContext.CloudConfig.ProjectID,
		"--target="+testContext.CloudConfig.NodeInstanceGroup,
		"--custom-metric=custom.cloudmonitoring.googleapis.com/kubernetes.io/"+metric,
		fmt.Sprintf("--target-custom-metric-utilization=%v", target),
		"--custom-metric-utilization-target-type=GAUGE",
		fmt.Sprintf("--min-num-replicas=%v", min),
		fmt.Sprintf("--max-num-replicas=%v", max),
	).CombinedOutput()
	expectNoError(err)
}

func cleanUpAutoscaler() {
	By("Removing autoscaler")
	_, err := exec.Command("gcloud", "preview", "autoscaler", "--zone="+testContext.CloudConfig.Zone, "delete", "e2e-test-autoscaler").CombinedOutput()
	expectNoError(err)
}

func CreateService(f *Framework, name string) {
	By("Running sevice" + name)
	service := &api.Service{
		ObjectMeta: api.ObjectMeta{
			Name: name,
		},
		Spec: api.ServiceSpec{
			Selector: map[string]string{
				"name": name,
			},
			Ports: []api.ServicePort{{
				Port:       8080,
				TargetPort: util.NewIntOrStringFromInt(8080),
			}},
		},
	}
	_, err := f.Client.Services(f.Namespace.Name).Create(service)
	Expect(err).NotTo(HaveOccurred())
}

func ConsumeCpu(f *Framework, id string, cores int) {
	CreateService(f, id)
	By(fmt.Sprintf("Running RC which consumes %v cores", cores))
	config := &RCConfig{
		Client:     f.Client,
		Name:       id,
		Namespace:  f.Namespace.Name,
		Timeout:    10 * time.Minute,
		Image:      "jess/stress",
		Command:    []string{"stress", "-c", "1"},
		Replicas:   cores,
		CpuRequest: 500,
		CpuLimit:   1000,
	}
	expectNoError(RunRC(*config))
}

func ConsumeMemory(f *Framework, id string, gigabytes int) {
	By(fmt.Sprintf("Running RC which consumes %v GB of memory", gigabytes))
	config := &RCConfig{
		Client:    f.Client,
		Name:      id,
		Namespace: f.Namespace.Name,
		Timeout:   10 * time.Minute,
		Image:     "jess/stress",
		Command:   []string{"stress", "-m", "1"},
		Replicas:  4 * gigabytes,
	}
	expectNoError(RunRC(*config))
}

func ReserveCpu(f *Framework, id string, millicores int) {
	By(fmt.Sprintf("Running RC which reserves %v millicores", millicores))
	config := &RCConfig{
		Client:    f.Client,
		Name:      id,
		Namespace: f.Namespace.Name,
		Timeout:   10 * time.Minute,
		Image:     "gcr.io/google_containers/pause",
		Replicas:  millicores / 100,
		CpuLimit:  100,
	}
	expectNoError(RunRC(*config))
}

func ReserveMemory(f *Framework, id string, gigabytes int) {
	By(fmt.Sprintf("Running RC which reserves %v GB of memory", gigabytes))
	config := &RCConfig{
		Client:    f.Client,
		Name:      id,
		Namespace: f.Namespace.Name,
		Timeout:   10 * time.Minute,
		Image:     "gcr.io/google_containers/pause",
		Replicas:  5 * gigabytes,
		MemLimit:  200 * 1024 * 1024,
	}
	expectNoError(RunRC(*config))
}

func StopConsuming(f *Framework, id string) {
	By("Stopping service " + id)
	err := f.Client.Services(f.Namespace.Name).Delete(id)
	Expect(err).NotTo(HaveOccurred())
	By("Stopping RC " + id)
	expectNoError(DeleteRC(f.Client, f.Namespace.Name, id))
}
<commit_msg>Actually enabled Autoscaling e2e test for Jenkins flaky job<commit_after>/*
Copyright 2015 The Kubernetes Authors All rights reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package e2e

import (
	"fmt"
	"os/exec"
	"time"

	"k8s.io/kubernetes/pkg/api"
	"k8s.io/kubernetes/pkg/fields"
	"k8s.io/kubernetes/pkg/labels"
	"k8s.io/kubernetes/pkg/util"

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

var _ = Describe("Autoscaling", func() {
	f := NewFramework("autoscaling")
	var nodeCount int
	var coresPerNode int

	BeforeEach(func() {
		SkipUnlessProviderIs("gce")

		nodes, err := f.Client.Nodes().List(labels.Everything(), fields.Everything())
		expectNoError(err)
		nodeCount = len(nodes.Items)
		Expect(nodeCount).NotTo(BeZero())
		res := nodes.Items[0].Status.Capacity[api.ResourceCPU]
		coresPerNode = int((&res).MilliValue() / 1000)
	})

	AfterEach(func() {
		cleanUpAutoscaler()
	})

	It("[Autoscaling] should scale cluster size based on cpu utilization", func() {
		setUpAutoscaler("cpu/node_utilization", 0.7, nodeCount, nodeCount+1)

		ConsumeCpu(f, "cpu-utilization", nodeCount*coresPerNode)
		expectNoError(waitForClusterSize(f.Client, nodeCount+1))

		StopConsuming(f, "cpu-utilization")
		expectNoError(waitForClusterSize(f.Client, nodeCount))
	})

	It("[Skipped] should scale cluster size based on cpu reservation", func() {
		setUpAutoscaler("cpu/node_reservation", 0.7, 1, 10)

		ReserveCpu(f, "cpu-reservation", 800)
		expectNoError(waitForClusterSize(f.Client, 2))

		StopConsuming(f, "cpu-reservation")
		expectNoError(waitForClusterSize(f.Client, 1))
	})

	It("[Skipped] should scale cluster size based on memory utilization", func() {
		setUpAutoscaler("memory/node_utilization", 0.5, 1, 10)

		ConsumeMemory(f, "memory-utilization", 2)
		expectNoError(waitForClusterSize(f.Client, 2))

		StopConsuming(f, "memory-utilization")
		expectNoError(waitForClusterSize(f.Client, 1))
	})

	It("[Skipped] should scale cluster size based on memory reservation", func() {
		setUpAutoscaler("memory/node_reservation", 0.5, 1, 10)

		ReserveMemory(f, "memory-reservation", 2)
		expectNoError(waitForClusterSize(f.Client, 2))

		StopConsuming(f, "memory-reservation")
		expectNoError(waitForClusterSize(f.Client, 1))
	})
})

func setUpAutoscaler(metric string, target float64, min, max int) {
	// TODO integrate with kube-up.sh script once it will support autoscaler setup.
	By("Setting up autoscaler to scale based on " + metric)
	_, err := exec.Command("gcloud", "preview", "autoscaler",
		"--zone="+testContext.CloudConfig.Zone,
		"create", "e2e-test-autoscaler",
		"--project="+testContext.CloudConfig.ProjectID,
		"--target="+testContext.CloudConfig.NodeInstanceGroup,
		"--custom-metric=custom.cloudmonitoring.googleapis.com/kubernetes.io/"+metric,
		fmt.Sprintf("--target-custom-metric-utilization=%v", target),
		"--custom-metric-utilization-target-type=GAUGE",
		fmt.Sprintf("--min-num-replicas=%v", min),
		fmt.Sprintf("--max-num-replicas=%v", max),
	).CombinedOutput()
	expectNoError(err)
}

func cleanUpAutoscaler() {
	By("Removing autoscaler")
	_, err := exec.Command("gcloud", "preview", "autoscaler", "--zone="+testContext.CloudConfig.Zone, "delete", "e2e-test-autoscaler").CombinedOutput()
	expectNoError(err)
}

func CreateService(f *Framework, name string) {
	By("Running sevice" + name)
	service := &api.Service{
		ObjectMeta: api.ObjectMeta{
			Name: name,
		},
		Spec: api.ServiceSpec{
			Selector: map[string]string{
				"name": name,
			},
			Ports: []api.ServicePort{{
				Port:       8080,
				TargetPort: util.NewIntOrStringFromInt(8080),
			}},
		},
	}
	_, err := f.Client.Services(f.Namespace.Name).Create(service)
	Expect(err).NotTo(HaveOccurred())
}

func ConsumeCpu(f *Framework, id string, cores int) {
	CreateService(f, id)
	By(fmt.Sprintf("Running RC which consumes %v cores", cores))
	config := &RCConfig{
		Client:     f.Client,
		Name:       id,
		Namespace:  f.Namespace.Name,
		Timeout:    10 * time.Minute,
		Image:      "jess/stress",
		Command:    []string{"stress", "-c", "1"},
		Replicas:   cores,
		CpuRequest: 500,
		CpuLimit:   1000,
	}
	expectNoError(RunRC(*config))
}

func ConsumeMemory(f *Framework, id string, gigabytes int) {
	By(fmt.Sprintf("Running RC which consumes %v GB of memory", gigabytes))
	config := &RCConfig{
		Client:    f.Client,
		Name:      id,
		Namespace: f.Namespace.Name,
		Timeout:   10 * time.Minute,
		Image:     "jess/stress",
		Command:   []string{"stress", "-m", "1"},
		Replicas:  4 * gigabytes,
	}
	expectNoError(RunRC(*config))
}

func ReserveCpu(f *Framework, id string, millicores int) {
	By(fmt.Sprintf("Running RC which reserves %v millicores", millicores))
	config := &RCConfig{
		Client:    f.Client,
		Name:      id,
		Namespace: f.Namespace.Name,
		Timeout:   10 * time.Minute,
		Image:     "gcr.io/google_containers/pause",
		Replicas:  millicores / 100,
		CpuLimit:  100,
	}
	expectNoError(RunRC(*config))
}

func ReserveMemory(f *Framework, id string, gigabytes int) {
	By(fmt.Sprintf("Running RC which reserves %v GB of memory", gigabytes))
	config := &RCConfig{
		Client:    f.Client,
		Name:      id,
		Namespace: f.Namespace.Name,
		Timeout:   10 * time.Minute,
		Image:     "gcr.io/google_containers/pause",
		Replicas:  5 * gigabytes,
		MemLimit:  200 * 1024 * 1024,
	}
	expectNoError(RunRC(*config))
}

func StopConsuming(f *Framework, id string) {
	By("Stopping service " + id)
	err := f.Client.Services(f.Namespace.Name).Delete(id)
	Expect(err).NotTo(HaveOccurred())
	By("Stopping RC " + id)
	expectNoError(DeleteRC(f.Client, f.Namespace.Name, id))
}
<|endoftext|>


<commit_before>package aws

import (
	"fmt"
	"testing"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/athena"

	"github.com/hashicorp/terraform/helper/acctest"
	"github.com/hashicorp/terraform/helper/resource"
	"github.com/hashicorp/terraform/terraform"
)

func TestAccAWSAthenaWorkGroup_basic(t *testing.T) {
	resource.ParallelTest(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSAthenaWorkGroupDestroy,
		Steps: []resource.TestStep{
			{
				Config: testAccAthenaWorkGroupConfig(acctest.RandString(5)),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSAthenaWorkGroupExists("aws_athena_workgroup.foo"),
				),
			},
		},
	})
}

func TestAccAWSAthenaWorkGroup_withDescription(t *testing.T) {
	rName := acctest.RandString(5)
	rDescription := acctest.RandString(20)
	resource.ParallelTest(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSAthenaWorkGroupDestroy,
		Steps: []resource.TestStep{
			{
				Config: testAccAthenaWorkGroupConfigDescription(rName, rDescription),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSAthenaWorkGroupExists("aws_athena_workgroup.foo"),
					resource.TestCheckResourceAttr(
						"aws_athena_workgroup.foo", "description", rDescription),
				),
			},
		},
	})
}

func testAccCheckAWSAthenaWorkGroupDestroy(s *terraform.State) error {
	conn := testAccProvider.Meta().(*AWSClient).athenaconn
	for _, rs := range s.RootModule().Resources {
		if rs.Type != "aws_athena_workgroup" {
			continue
		}

		input := &athena.GetWorkGroupInput{
			WorkGroup: aws.String(rs.Primary.ID),
		}

		resp, err := conn.GetWorkGroup(input)
		if err != nil {
			if isAWSErr(err, athena.ErrCodeInvalidRequestException, rs.Primary.ID) {
				return nil
			}
			return err
		}
		if resp.WorkGroup != nil {
			return fmt.Errorf("Athena WorkGroup (%s) found", rs.Primary.ID)
		}
	}
	return nil
}

func testAccCheckAWSAthenaWorkGroupExists(name string) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		rs, ok := s.RootModule().Resources[name]
		if !ok {
			return fmt.Errorf("Not found: %s", name)
		}

		conn := testAccProvider.Meta().(*AWSClient).athenaconn

		input := &athena.GetWorkGroupInput{
			WorkGroup: aws.String(rs.Primary.ID),
		}

		_, err := conn.GetWorkGroup(input)
		return err
	}
}

func testAccAthenaWorkGroupConfig(rName string) string {
	return fmt.Sprintf(`
resource "aws_athena_workgroup" "foo" {
  name = "tf-athena-workgroup-%s"
}
		`, rName)
}

func testAccAthenaWorkGroupConfigDescription(rName string, rDescription string) string {
	return fmt.Sprintf(`
	resource "aws_athena_workgroup" "foo" {
		name = "tf-athena-workgroup-%s"
		description = "%s"
	}
	`, rName, rDescription)
}
<commit_msg>Added description update test<commit_after>package aws

import (
	"fmt"
	"testing"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/athena"

	"github.com/hashicorp/terraform/helper/acctest"
	"github.com/hashicorp/terraform/helper/resource"
	"github.com/hashicorp/terraform/terraform"
)

func TestAccAWSAthenaWorkGroup_basic(t *testing.T) {
	resource.ParallelTest(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSAthenaWorkGroupDestroy,
		Steps: []resource.TestStep{
			{
				Config: testAccAthenaWorkGroupConfig(acctest.RandString(5)),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSAthenaWorkGroupExists("aws_athena_workgroup.foo"),
				),
			},
		},
	})
}

func TestAccAWSAthenaWorkGroup_withDescription(t *testing.T) {
	rName := acctest.RandString(5)
	rDescription := acctest.RandString(20)
	resource.ParallelTest(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSAthenaWorkGroupDestroy,
		Steps: []resource.TestStep{
			{
				Config: testAccAthenaWorkGroupConfigDescription(rName, rDescription),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSAthenaWorkGroupExists("aws_athena_workgroup.foo"),
					resource.TestCheckResourceAttr(
						"aws_athena_workgroup.foo", "description", rDescription),
				),
			},
		},
	})
}

func TestAccAWSAthenaWorkGroup_withDescriptionUpdate(t *testing.T) {
	rName := acctest.RandString(5)
	rDescription := acctest.RandString(20)
	rDescriptionUpdate := acctest.RandString(20)

	resource.ParallelTest(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSAthenaWorkGroupDestroy,
		Steps: []resource.TestStep{
			{
				Config: testAccAthenaWorkGroupConfigDescription(rName, rDescription),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSAthenaWorkGroupExists("aws_athena_workgroup.foo"),
					resource.TestCheckResourceAttr(
						"aws_athena_workgroup.foo", "description", rDescription),
				),
			},
			{
				Config: testAccAthenaWorkGroupConfigDescription(rName, rDescriptionUpdate),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSAthenaWorkGroupExists("aws_athena_workgroup.foo"),
					resource.TestCheckResourceAttr(
						"aws_athena_workgroup.foo", "description", rDescriptionUpdate),
				),
			},
		},
	})
}

func testAccCheckAWSAthenaWorkGroupDestroy(s *terraform.State) error {
	conn := testAccProvider.Meta().(*AWSClient).athenaconn
	for _, rs := range s.RootModule().Resources {
		if rs.Type != "aws_athena_workgroup" {
			continue
		}

		input := &athena.GetWorkGroupInput{
			WorkGroup: aws.String(rs.Primary.ID),
		}

		resp, err := conn.GetWorkGroup(input)
		if err != nil {
			if isAWSErr(err, athena.ErrCodeInvalidRequestException, rs.Primary.ID) {
				return nil
			}
			return err
		}
		if resp.WorkGroup != nil {
			return fmt.Errorf("Athena WorkGroup (%s) found", rs.Primary.ID)
		}
	}
	return nil
}

func testAccCheckAWSAthenaWorkGroupExists(name string) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		rs, ok := s.RootModule().Resources[name]
		if !ok {
			return fmt.Errorf("Not found: %s", name)
		}

		conn := testAccProvider.Meta().(*AWSClient).athenaconn

		input := &athena.GetWorkGroupInput{
			WorkGroup: aws.String(rs.Primary.ID),
		}

		_, err := conn.GetWorkGroup(input)
		return err
	}
}

func testAccAthenaWorkGroupConfig(rName string) string {
	return fmt.Sprintf(`
resource "aws_athena_workgroup" "foo" {
  name = "tf-athena-workgroup-%s"
}
		`, rName)
}

func testAccAthenaWorkGroupConfigDescription(rName string, rDescription string) string {
	return fmt.Sprintf(`
	resource "aws_athena_workgroup" "foo" {
		name = "tf-athena-workgroup-%s"
		description = "%s"
	}
	`, rName, rDescription)
}
<|endoftext|>


<commit_before>package model_loader_test

import (
	"github.com/centurylinkcloud/clc-go-cli/model_loader"
	"reflect"
	"testing"
	"time"
)

type modelLoaderTestCase struct {
	args map[string]interface{}
	res  interface{}
	err  string
	skip bool
}

type testModel struct {
	FieldString   string
	FieldInt      int
	FieldFloat    float64
	FieldBool     bool
	FieldDateTime time.Time
	FieldObject   testFieldObject
	FieldArray    []testFieldObject
}

type testFieldObject struct {
	FieldString      string
	FieldInnerObject testFieldInnerObject
}

type testFieldInnerObject struct {
	FieldString string
}

var testCases = []modelLoaderTestCase{
	// Loads one string.
	{
		args: map[string]interface{}{
			"FieldString": "some string",
		},
		res: testModel{
			FieldString: "some string",
		},
	},
	// Parses JSON and loads it into object field.
	{
		args: map[string]interface{}{
			"FieldObject": `{"FieldString": "some string","FieldInnerObject":{"FieldString":"another string"}}`,
		},
		res: testModel{
			FieldObject: testFieldObject{
				FieldString: "some string",
				FieldInnerObject: testFieldInnerObject{
					FieldString: "another string",
				},
			},
		},
	},
	{
		args: map[string]interface{}{
			"FieldArray": `[{"FieldString": "string 1"},{"FieldString": "string 2"}]`,
		},
		res: testModel{
			FieldArray: []testFieldObject{
				testFieldObject{FieldString: "string 1"},
				testFieldObject{FieldString: "string 2"},
			},
		},
	},
	// Parses k1=v1,k2=v2,.. notation and loads it into object field.
	{
		args: map[string]interface{}{
			"FieldObject": `FieldString=some string`,
		},
		res: testModel{
			FieldObject: testFieldObject{
				FieldString: "some string",
			},
		},
	},
	// Fails to load string into object field if it is neither JSON nor k1=v1,.. notation.
	{
		args: map[string]interface{}{
			"FieldObject": `can not be parsed into object`,
		},
		err: "`can not be parsed into object` is neither in JSON nor in key=value,.. format.",
	},
	// Loads JSON into string field as string.
	{
		args: map[string]interface{}{
			"FieldString": `{"a":"b"}`,
		},
		res: testModel{
			FieldString: `{"a":"b"}`,
		},
	},
	// Loads k1=v1,k2=v2.. notation into string field as string.
	{
		args: map[string]interface{}{
			"FieldString": `a=b,c=d`,
		},
		res: testModel{
			FieldString: `a=b,c=d`,
		},
	},
	// Fails with unknown fields.
	{
		args: map[string]interface{}{
			"UnknownField": "some value",
		},
		err: "Field `UnknownField` does not exist.",
	},
	// Fails with different type mismatches.
	{
		args: map[string]interface{}{
			"FieldInt": "string",
		},
		err: "Type mismatch: FieldInt value must be integer.",
	},
	{
		args: map[string]interface{}{
			"FieldBool": "Fal",
		},
		err: "Type mismatch: FieldBool value must be either true or false.",
	},
	{
		args: map[string]interface{}{
			"FieldDateTime": "2012 04 05",
		},
		err: "Type mismatch: FieldDateTime value must be datetime in UTC format.",
	},
}

func TestModelLoader(t *testing.T) {
	for i, testCase := range testCases {
		if testCase.skip {
			t.Logf("Skipping %d test case.", i+1)
			continue
		}
		t.Logf("Executing %d test case.", i+1)
		res := testModel{}
		err := model_loader.LoadModel(testCase.args, res)
		if testCase.err != "" && err.Error() != testCase.err {
			t.Errorf("Invalid error.\n Expected: %s,\n obtained %s", testCase.err, err.Error())
		}
		if testCase.res != nil && !reflect.DeepEqual(testCase.res, res) {
			t.Errorf("Invalid result.\n expected %#v,\n obtained %#v", testCase.res, res)
		}
	}
}
<commit_msg>use more specific integer type<commit_after>package model_loader_test

import (
	"github.com/centurylinkcloud/clc-go-cli/model_loader"
	"reflect"
	"testing"
	"time"
)

type modelLoaderTestCase struct {
	args map[string]interface{}
	res  interface{}
	err  string
	skip bool
}

type testModel struct {
	FieldString   string
	FieldInt      int64
	FieldFloat    float64
	FieldBool     bool
	FieldDateTime time.Time
	FieldObject   testFieldObject
	FieldArray    []testFieldObject
}

type testFieldObject struct {
	FieldString      string
	FieldInnerObject testFieldInnerObject
}

type testFieldInnerObject struct {
	FieldString string
}

var testCases = []modelLoaderTestCase{
	// Loads one string.
	{
		args: map[string]interface{}{
			"FieldString": "some string",
		},
		res: testModel{
			FieldString: "some string",
		},
	},
	// Parses JSON and loads it into object field.
	{
		args: map[string]interface{}{
			"FieldObject": `{"FieldString": "some string","FieldInnerObject":{"FieldString":"another string"}}`,
		},
		res: testModel{
			FieldObject: testFieldObject{
				FieldString: "some string",
				FieldInnerObject: testFieldInnerObject{
					FieldString: "another string",
				},
			},
		},
	},
	{
		args: map[string]interface{}{
			"FieldArray": `[{"FieldString": "string 1"},{"FieldString": "string 2"}]`,
		},
		res: testModel{
			FieldArray: []testFieldObject{
				testFieldObject{FieldString: "string 1"},
				testFieldObject{FieldString: "string 2"},
			},
		},
	},
	// Parses k1=v1,k2=v2,.. notation and loads it into object field.
	{
		args: map[string]interface{}{
			"FieldObject": `FieldString=some string`,
		},
		res: testModel{
			FieldObject: testFieldObject{
				FieldString: "some string",
			},
		},
	},
	// Fails to load string into object field if it is neither JSON nor k1=v1,.. notation.
	{
		args: map[string]interface{}{
			"FieldObject": `can not be parsed into object`,
		},
		err: "`can not be parsed into object` is neither in JSON nor in key=value,.. format.",
	},
	// Loads JSON into string field as string.
	{
		args: map[string]interface{}{
			"FieldString": `{"a":"b"}`,
		},
		res: testModel{
			FieldString: `{"a":"b"}`,
		},
	},
	// Loads k1=v1,k2=v2.. notation into string field as string.
	{
		args: map[string]interface{}{
			"FieldString": `a=b,c=d`,
		},
		res: testModel{
			FieldString: `a=b,c=d`,
		},
	},
	// Fails with unknown fields.
	{
		args: map[string]interface{}{
			"UnknownField": "some value",
		},
		err: "Field `UnknownField` does not exist.",
	},
	// Fails with different type mismatches.
	{
		args: map[string]interface{}{
			"FieldInt": "string",
		},
		err: "Type mismatch: FieldInt value must be integer.",
	},
	{
		args: map[string]interface{}{
			"FieldBool": "Fal",
		},
		err: "Type mismatch: FieldBool value must be either true or false.",
	},
	{
		args: map[string]interface{}{
			"FieldDateTime": "2012 04 05",
		},
		err: "Type mismatch: FieldDateTime value must be datetime in UTC format.",
	},
}

func TestModelLoader(t *testing.T) {
	for i, testCase := range testCases {
		if testCase.skip {
			t.Logf("Skipping %d test case.", i+1)
			continue
		}
		t.Logf("Executing %d test case.", i+1)
		res := testModel{}
		err := model_loader.LoadModel(testCase.args, res)
		if testCase.err != "" && err.Error() != testCase.err {
			t.Errorf("Invalid error.\n Expected: %s,\n obtained %s", testCase.err, err.Error())
		}
		if testCase.res != nil && !reflect.DeepEqual(testCase.res, res) {
			t.Errorf("Invalid result.\n expected %#v,\n obtained %#v", testCase.res, res)
		}
	}
}
<|endoftext|>


<commit_before>package model

import (
	"appengine"
	"appengine/datastore"
	"log"
	"encoding/csv"
	"strings"
)

type Player struct {
	Name string
	Email string
	Phone string
	Faction string
	Injuries []string
	Bonds string `datastore:",noindex"`
}

func playerKey(c appengine.Context, s *Season, email string) *datastore.Key {
	var sKey *datastore.Key
	sKey = nil
	if s != nil {
		sKey = seasonKey(c, s.Name, s.Year)
	}
	return datastore.NewKey(c, "Player", email, 0, sKey)
}

func SavePlayer(c appengine.Context, s *Season, name string, email string, phone string, faction string) error {
	p := Player {
		Name: name,
		Email: email,
		Faction: faction,
		Phone: phone,
	}
	key := playerKey(c, s, email)
	_, err := datastore.Put(c, key, &p)
	return err
}

func LoadPlayer(c appengine.Context, s *Season, email string) *Player {
	key := playerKey(c, s, email)
	var p Player
	err := datastore.Get(c, key, &p)
	if err == datastore.ErrNoSuchEntity {
		return nil
	} else if err != nil {
		log.Printf("Got an unexpected error looking up a season: %v", err)
	}
	return &p
}

func CreatePlayersFromCsv(c appengine.Context, owningSeason *Season, csvData string) {
	strReader := strings.NewReader(csvData)
	csvReader := csv.NewReader(strReader)
	records, err := csvReader.ReadAll()
	if err != nil {
		log.Printf("Got an unexpected error [%v] reading csv data:\n%v", err, csvData)
		panic(err)
	}
	for _, row := range records {
		SavePlayer(c, owningSeason, row[0], row[2], row[3], row[1])
	}
}
<commit_msg>Changed a type to properly handle json entities<commit_after>package model

import (
	"appengine"
	"appengine/datastore"
	"log"
	"encoding/csv"
	"strings"
)

type Player struct {
	Name string
	Email string
	Phone string
	Faction string
	Injuries []string
	Bonds []byte `datastore:",noindex"`
}

func playerKey(c appengine.Context, s *Season, email string) *datastore.Key {
	var sKey *datastore.Key
	sKey = nil
	if s != nil {
		sKey = seasonKey(c, s.Name, s.Year)
	}
	return datastore.NewKey(c, "Player", email, 0, sKey)
}

func SavePlayer(c appengine.Context, s *Season, name string, email string, phone string, faction string) error {
	p := Player {
		Name: name,
		Email: email,
		Faction: faction,
		Phone: phone,
	}
	key := playerKey(c, s, email)
	_, err := datastore.Put(c, key, &p)
	return err
}

func LoadPlayer(c appengine.Context, s *Season, email string) *Player {
	key := playerKey(c, s, email)
	var p Player
	err := datastore.Get(c, key, &p)
	if err == datastore.ErrNoSuchEntity {
		return nil
	} else if err != nil {
		log.Printf("Got an unexpected error looking up a season: %v", err)
	}
	return &p
}

func CreatePlayersFromCsv(c appengine.Context, owningSeason *Season, csvData string) {
	strReader := strings.NewReader(csvData)
	csvReader := csv.NewReader(strReader)
	records, err := csvReader.ReadAll()
	if err != nil {
		log.Printf("Got an unexpected error [%v] reading csv data:\n%v", err, csvData)
		panic(err)
	}
	for _, row := range records {
		SavePlayer(c, owningSeason, row[0], row[2], row[3], row[1])
	}
}
<|endoftext|>


<commit_before>package main

import (
	. "github.com/conclave/pcduino/core"
)

func init() {
	Init()
	setup()
}

func main() {
	for {
		loop()
	}
}

func setup() {
}

func loop() {
	Delay(100)
}
<commit_msg>update test/linker_light_sensor_test<commit_after>package main

import (
	"fmt"

	. "github.com/conclave/pcduino/core"
)

func init() {
	Init()
	setup()
}

func main() {
	for {
		loop()
	}
}

var ledPin byte = 0
var thresholdValue = 10
var adcIn byte = 0

var filter []int
var sampleCount int

func setup() {
	println("Light sensor test code!")
	println("Using I/O_0=Drive LED, ADC_0=Sensor output.")
	PinMode(ledPin, OUTPUT)
	filter = make([]int, 4)
	filter[0] = AnalogRead(adcIn)
	filter[1] = AnalogRead(adcIn)
	filter[2] = AnalogRead(adcIn)
	filter[3] = AnalogRead(adcIn)
	sampleCount = 0
}

func loop() {
	sensorValue := AnalogRead(adcIn)
	var Rsensor int

	if sampleCount >= 3 {
		sampleCount = 0
	} else {
		sampleCount++
	}
	fmt.Printf("adc %d :%d!\n", sampleCount, sensorValue)
	filter[sampleCount] = sensorValue
	sensorValue = (filter[0] + filter[1] + filter[2] + filter[3]) / 4
	Rsensor = (sensorValue * 100) / 64
	if Rsensor < thresholdValue {
		DigitalWrite(ledPin, HIGH)
	} else {
		DigitalWrite(ledPin, LOW)
	}
	fmt.Printf("adc:%d!\n", sensorValue)
	Delay(200)
}
<|endoftext|>


<commit_before>package nptl

import (
	"fmt"
	"io"

	"github.com/krasin/g3"
	"github.com/krasin/voxel/raster"
	"github.com/krasin/voxel/volume"
)

func Write(w io.Writer, vol volume.Space16, grid raster.Grid) (err error) {
	stepX := (grid.P1[0] - grid.P0[0]) / float64(vol.N())
	stepY := (grid.P1[1] - grid.P0[1]) / float64(vol.N())
	stepZ := (grid.P1[2] - grid.P0[2]) / float64(vol.N())

	vol.MapBoundary(func(node g3.Node) {
		nv := volume.Normal(vol, node)
		if _, err = fmt.Fprintf(w, "%f %f %f %f %f %f\n",
			grid.P0[0]+float64(node[0])*stepX,
			grid.P0[1]+float64(node[1])*stepY,
			grid.P0[2]+float64(node[2])*stepZ,
			nv[0], nv[1], nv[2]); err != nil {
			return
		}
	})
	return
}
<commit_msg>Convert ntpl.Write to use g3.Grid<commit_after>package nptl

import (
	"fmt"
	"io"

	"github.com/krasin/g3"
	"github.com/krasin/voxel/volume"
)

func Write(w io.Writer, vol volume.Space16, grid g3.Grid) (err error) {
	vol.MapBoundary(func(node g3.Node) {
		nv := volume.Normal(vol, node)
		cur := grid.At(node)
		if _, err = fmt.Fprintf(w, "%f %f %f %f %f %f\n",
			cur[0], cur[1], cur[2], nv[0], nv[1], nv[2]); err != nil {
			return
		}
	})
	return
}
<|endoftext|>


<commit_before>// +build linux

package nsinit

import (
	"fmt"
	"github.com/dotcloud/docker/pkg/libcontainer"
	"github.com/dotcloud/docker/pkg/libcontainer/network"
	"github.com/dotcloud/docker/pkg/libcontainer/utils"
	"github.com/dotcloud/docker/pkg/system"
	"github.com/dotcloud/docker/pkg/term"
	"io"
	"io/ioutil"
	"log"
	"os"
	"os/exec"
	"syscall"
)

// Exec performes setup outside of a namespace so that a container can be
// executed.  Exec is a high level function for working with container namespaces.
func Exec(container *libcontainer.Container, stdin io.Reader, stdout, stderr io.Writer, master *os.File, logFile string, args []string) (int, error) {
	var (
		console string
		err     error

		inPipe           io.WriteCloser
		outPipe, errPipe io.ReadCloser
	)

	if container.Tty {
		log.Printf("setting up master and console")
		master, console, err = createMasterAndConsole()
		if err != nil {
			return -1, err
		}
	}

	// create a pipe so that we can syncronize with the namespaced process and
	// pass the veth name to the child
	r, w, err := os.Pipe()
	if err != nil {
		return -1, err
	}
	system.UsetCloseOnExec(r.Fd())

	command := createCommand(container, console, logFile, r.Fd(), args)
	if !container.Tty {
		log.Printf("opening pipes on command")
		if inPipe, err = command.StdinPipe(); err != nil {
			return -1, err
		}
		if outPipe, err = command.StdoutPipe(); err != nil {
			return -1, err
		}
		if errPipe, err = command.StderrPipe(); err != nil {
			return -1, err
		}
	}

	log.Printf("staring init")
	if err := command.Start(); err != nil {
		return -1, err
	}
	log.Printf("writting state file")
	if err := writePidFile(command); err != nil {
		command.Process.Kill()
		return -1, err
	}
	defer deletePidFile()

	// Do this before syncing with child so that no children
	// can escape the cgroup
	if container.Cgroups != nil {
		log.Printf("setting up cgroups")
		if err := container.Cgroups.Apply(command.Process.Pid); err != nil {
			command.Process.Kill()
			return -1, err
		}
	}

	if container.Network != nil {
		log.Printf("creating veth pair")
		vethPair, err := initializeContainerVeth(container.Network.Bridge, container.Network.Mtu, command.Process.Pid)
		if err != nil {
			return -1, err
		}
		log.Printf("sending %s as veth pair name", vethPair)
		sendVethName(w, vethPair)
	}

	// Sync with child
	log.Printf("closing sync pipes")
	w.Close()
	r.Close()

	if container.Tty {
		log.Printf("starting copy for tty")
		go io.Copy(stdout, master)
		go io.Copy(master, stdin)

		state, err := setupWindow(master)
		if err != nil {
			command.Process.Kill()
			return -1, err
		}
		defer term.RestoreTerminal(uintptr(syscall.Stdin), state)
	} else {
		log.Printf("starting copy for std pipes")
		go func() {
			defer inPipe.Close()
			io.Copy(inPipe, stdin)
		}()
		go io.Copy(stdout, outPipe)
		go io.Copy(stderr, errPipe)
	}

	log.Printf("waiting on process")
	if err := command.Wait(); err != nil {
		if _, ok := err.(*exec.ExitError); !ok {
			return -1, err
		}
	}
	log.Printf("process ended")
	return command.ProcessState.Sys().(syscall.WaitStatus).ExitStatus(), nil
}

// sendVethName writes the veth pair name to the child's stdin then closes the
// pipe so that the child stops waiting for more data
func sendVethName(pipe io.Writer, name string) {
	fmt.Fprint(pipe, name)
}

// initializeContainerVeth will create a veth pair and setup the host's
// side of the pair by setting the specified bridge as the master and bringing
// up the interface.
//
// Then will with set the other side of the veth pair into the container's namespaced
// using the pid and returns the veth's interface name to provide to the container to
// finish setting up the interface inside the namespace
func initializeContainerVeth(bridge string, mtu, nspid int) (string, error) {
	name1, name2, err := createVethPair()
	if err != nil {
		return "", err
	}
	log.Printf("veth pair created %s <> %s", name1, name2)
	if err := network.SetInterfaceMaster(name1, bridge); err != nil {
		return "", err
	}
	if err := network.SetMtu(name1, mtu); err != nil {
		return "", err
	}
	if err := network.InterfaceUp(name1); err != nil {
		return "", err
	}
	log.Printf("setting %s inside %d namespace", name2, nspid)
	if err := network.SetInterfaceInNamespacePid(name2, nspid); err != nil {
		return "", err
	}
	return name2, nil
}

func setupWindow(master *os.File) (*term.State, error) {
	ws, err := term.GetWinsize(os.Stdin.Fd())
	if err != nil {
		return nil, err
	}
	if err := term.SetWinsize(master.Fd(), ws); err != nil {
		return nil, err
	}
	return term.SetRawTerminal(os.Stdin.Fd())
}

// createMasterAndConsole will open /dev/ptmx on the host and retreive the
// pts name for use as the pty slave inside the container
func createMasterAndConsole() (*os.File, string, error) {
	master, err := os.OpenFile("/dev/ptmx", syscall.O_RDWR|syscall.O_NOCTTY|syscall.O_CLOEXEC, 0)
	if err != nil {
		return nil, "", err
	}
	console, err := system.Ptsname(master)
	if err != nil {
		return nil, "", err
	}
	if err := system.Unlockpt(master); err != nil {
		return nil, "", err
	}
	return master, console, nil
}

// createVethPair will automatically generage two random names for
// the veth pair and ensure that they have been created
func createVethPair() (name1 string, name2 string, err error) {
	name1, err = utils.GenerateRandomName("dock", 4)
	if err != nil {
		return
	}
	name2, err = utils.GenerateRandomName("dock", 4)
	if err != nil {
		return
	}
	if err = network.CreateVethPair(name1, name2); err != nil {
		return
	}
	return
}

// writePidFile writes the namespaced processes pid to .nspid in the rootfs for the container
func writePidFile(command *exec.Cmd) error {
	return ioutil.WriteFile(".nspid", []byte(fmt.Sprint(command.Process.Pid)), 0655)
}

func deletePidFile() error {
	return os.Remove(".nspid")
}

// createCommand will return an exec.Cmd with the Cloneflags set to the proper namespaces
// defined on the container's configuration and use the current binary as the init with the
// args provided
func createCommand(container *libcontainer.Container, console, logFile string, pipe uintptr, args []string) *exec.Cmd {
	// get our binary name so we can always reexec ourself
	name := os.Args[0]
	command := exec.Command(name, append([]string{
		"-console", console,
		"-pipe", fmt.Sprint(pipe),
		"-log", logFile,
		"init"}, args...)...)

	command.SysProcAttr = &syscall.SysProcAttr{
		Cloneflags: uintptr(GetNamespaceFlags(container.Namespaces)),
	}
	command.Env = container.Env
	return command
}
<commit_msg>Export functions of nsinit Docker-DCO-1.1-Signed-off-by: Michael Crosby <michael@crosbymichael.com> (github: crosbymichael)<commit_after>// +build linux

package nsinit

import (
	"fmt"
	"github.com/dotcloud/docker/pkg/libcontainer"
	"github.com/dotcloud/docker/pkg/libcontainer/network"
	"github.com/dotcloud/docker/pkg/libcontainer/utils"
	"github.com/dotcloud/docker/pkg/system"
	"github.com/dotcloud/docker/pkg/term"
	"io"
	"io/ioutil"
	"log"
	"os"
	"os/exec"
	"syscall"
)

// Exec performes setup outside of a namespace so that a container can be
// executed.  Exec is a high level function for working with container namespaces.
func Exec(container *libcontainer.Container, stdin io.Reader, stdout, stderr io.Writer, master *os.File, logFile string, args []string) (int, error) {
	var (
		console string
		err     error

		inPipe           io.WriteCloser
		outPipe, errPipe io.ReadCloser
	)

	if container.Tty {
		log.Printf("setting up master and console")
		master, console, err = CreateMasterAndConsole()
		if err != nil {
			return -1, err
		}
	}

	// create a pipe so that we can syncronize with the namespaced process and
	// pass the veth name to the child
	r, w, err := os.Pipe()
	if err != nil {
		return -1, err
	}
	system.UsetCloseOnExec(r.Fd())

	command := CreateCommand(container, console, logFile, r.Fd(), args)
	if !container.Tty {
		log.Printf("opening pipes on command")
		if inPipe, err = command.StdinPipe(); err != nil {
			return -1, err
		}
		if outPipe, err = command.StdoutPipe(); err != nil {
			return -1, err
		}
		if errPipe, err = command.StderrPipe(); err != nil {
			return -1, err
		}
	}

	log.Printf("staring init")
	if err := command.Start(); err != nil {
		return -1, err
	}
	log.Printf("writting state file")
	if err := writePidFile(command); err != nil {
		command.Process.Kill()
		return -1, err
	}
	defer deletePidFile()

	// Do this before syncing with child so that no children
	// can escape the cgroup
	if container.Cgroups != nil {
		log.Printf("setting up cgroups")
		if err := container.Cgroups.Apply(command.Process.Pid); err != nil {
			command.Process.Kill()
			return -1, err
		}
	}

	if container.Network != nil {
		log.Printf("creating veth pair")
		vethPair, err := InitializeContainerVeth(container.Network.Bridge, container.Network.Mtu, command.Process.Pid)
		if err != nil {
			return -1, err
		}
		log.Printf("sending %s as veth pair name", vethPair)
		SendVethName(w, vethPair)
	}

	// Sync with child
	log.Printf("closing sync pipes")
	w.Close()
	r.Close()

	if container.Tty {
		log.Printf("starting copy for tty")
		go io.Copy(stdout, master)
		go io.Copy(master, stdin)

		state, err := SetupWindow(master, os.Stdin)
		if err != nil {
			command.Process.Kill()
			return -1, err
		}
		defer term.RestoreTerminal(uintptr(syscall.Stdin), state)
	} else {
		log.Printf("starting copy for std pipes")
		go func() {
			defer inPipe.Close()
			io.Copy(inPipe, stdin)
		}()
		go io.Copy(stdout, outPipe)
		go io.Copy(stderr, errPipe)
	}

	log.Printf("waiting on process")
	if err := command.Wait(); err != nil {
		if _, ok := err.(*exec.ExitError); !ok {
			return -1, err
		}
	}
	log.Printf("process ended")
	return command.ProcessState.Sys().(syscall.WaitStatus).ExitStatus(), nil
}

// SendVethName writes the veth pair name to the child's stdin then closes the
// pipe so that the child stops waiting for more data
func SendVethName(pipe io.Writer, name string) {
	fmt.Fprint(pipe, name)
}

// initializeContainerVeth will create a veth pair and setup the host's
// side of the pair by setting the specified bridge as the master and bringing
// up the interface.
//
// Then will with set the other side of the veth pair into the container's namespaced
// using the pid and returns the veth's interface name to provide to the container to
// finish setting up the interface inside the namespace
func InitializeContainerVeth(bridge string, mtu, nspid int) (string, error) {
	name1, name2, err := createVethPair()
	if err != nil {
		return "", err
	}
	log.Printf("veth pair created %s <> %s", name1, name2)
	if err := network.SetInterfaceMaster(name1, bridge); err != nil {
		return "", err
	}
	if err := network.SetMtu(name1, mtu); err != nil {
		return "", err
	}
	if err := network.InterfaceUp(name1); err != nil {
		return "", err
	}
	log.Printf("setting %s inside %d namespace", name2, nspid)
	if err := network.SetInterfaceInNamespacePid(name2, nspid); err != nil {
		return "", err
	}
	return name2, nil
}

// SetupWindow gets the parent window size and sets the master
// pty to the current size and set the parents mode to RAW
func SetupWindow(master, parent *os.File) (*term.State, error) {
	ws, err := term.GetWinsize(parent.Fd())
	if err != nil {
		return nil, err
	}
	if err := term.SetWinsize(master.Fd(), ws); err != nil {
		return nil, err
	}
	return term.SetRawTerminal(parent.Fd())
}

// CreateMasterAndConsole will open /dev/ptmx on the host and retreive the
// pts name for use as the pty slave inside the container
func CreateMasterAndConsole() (*os.File, string, error) {
	master, err := os.OpenFile("/dev/ptmx", syscall.O_RDWR|syscall.O_NOCTTY|syscall.O_CLOEXEC, 0)
	if err != nil {
		return nil, "", err
	}
	console, err := system.Ptsname(master)
	if err != nil {
		return nil, "", err
	}
	if err := system.Unlockpt(master); err != nil {
		return nil, "", err
	}
	return master, console, nil
}

// createVethPair will automatically generage two random names for
// the veth pair and ensure that they have been created
func createVethPair() (name1 string, name2 string, err error) {
	name1, err = utils.GenerateRandomName("dock", 4)
	if err != nil {
		return
	}
	name2, err = utils.GenerateRandomName("dock", 4)
	if err != nil {
		return
	}
	if err = network.CreateVethPair(name1, name2); err != nil {
		return
	}
	return
}

// writePidFile writes the namespaced processes pid to .nspid in the rootfs for the container
func writePidFile(command *exec.Cmd) error {
	return ioutil.WriteFile(".nspid", []byte(fmt.Sprint(command.Process.Pid)), 0655)
}

func deletePidFile() error {
	return os.Remove(".nspid")
}

// createCommand will return an exec.Cmd with the Cloneflags set to the proper namespaces
// defined on the container's configuration and use the current binary as the init with the
// args provided
func CreateCommand(container *libcontainer.Container, console, logFile string, pipe uintptr, args []string) *exec.Cmd {
	// get our binary name so we can always reexec ourself
	name := os.Args[0]
	command := exec.Command(name, append([]string{
		"-console", console,
		"-pipe", fmt.Sprint(pipe),
		"-log", logFile,
		"init"}, args...)...)

	command.SysProcAttr = &syscall.SysProcAttr{
		Cloneflags: uintptr(GetNamespaceFlags(container.Namespaces)),
	}
	command.Env = container.Env
	return command
}
<|endoftext|>


<commit_before>package lfs

import (
	"testing"

	"github.com/github/git-lfs/vendor/_nuts/github.com/technoweenie/assert"
)

func TestBatcherSizeMet(t *testing.T) {
	runBatcherTests([]batcherTestCase{
		{2, 4, false},
		{3, 5, false},
		{0, 0, false},
	}, t)
}

func TestBatcherExit(t *testing.T) {
	runBatcherTests([]batcherTestCase{
		{2, 4, true},
		{3, 5, true},
		{0, 0, true},
	}, t)
}

// batcherTestCase specifies information about how to run a particular test
// around the type lfs.Batcher.
type batcherTestCase struct {
	BatchSize  int
	ItemCount  int
	ShouldExit bool
}

// Batcher makes and retunrs a lfs.Batcher according to the specification given
// in this instance of batcherTestCase. When returned, it is filled with the
// given amount of items, and has exited if it was told to.
func (b batcherTestCase) Batcher() *Batcher {
	batcher := NewBatcher(b.BatchSize)
	for i := 0; i < b.ItemCount; i++ {
		batcher.Add(&Downloadable{})
	}

	if b.ShouldExit {
		batcher.Exit()
	}

	return batcher
}

// Batches returns the number of individual batches expected to be processed by
// the batcher under test.
func (b batcherTestCase) Batches() int {
	if b.BatchSize == 0 {
		return b.ItemCount
	}

	return b.ItemCount / b.BatchSize
}

// runBatcherTests processes all test cases, throwing assertion errors if they
// fail.
func runBatcherTests(cases []batcherTestCase, t *testing.T) {
	for _, c := range cases {
		b := c.Batcher()

		items := c.ItemCount
		for i := 0; i < c.Batches(); i++ {
			group := b.Next()
			assert.Equal(t, c.BatchSize, len(group))
			items -= c.BatchSize
		}
	}
}
<commit_msg>ンンン ンンン ンン<commit_after>package lfs

import (
	"testing"

	"github.com/github/git-lfs/vendor/_nuts/github.com/technoweenie/assert"
)

func TestBatcherSizeMet(t *testing.T) {
	runBatcherTests([]batcherTestCase{
		{2, 4, false},
		{3, 5, false},
		{0, 0, false},
	}, t)
}

func TestBatcherExit(t *testing.T) {
	runBatcherTests([]batcherTestCase{
		{2, 4, true},
		{3, 5, true},
		{0, 0, true},
	}, t)
}

// batcherTestCase specifies information about how to run a particular test
// around the type lfs.Batcher.
type batcherTestCase struct {
	BatchSize  int
	ItemCount  int
	ShouldExit bool
}

// Batcher makes and returns a lfs.Batcher according to the specification given
// in this instance of batcherTestCase. When returned, it is filled with the
// given amount of items, and has exited if it was told to.
func (b batcherTestCase) Batcher() *Batcher {
	batcher := NewBatcher(b.BatchSize)
	for i := 0; i < b.ItemCount; i++ {
		batcher.Add(&Downloadable{})
	}

	if b.ShouldExit {
		batcher.Exit()
	}

	return batcher
}

// Batches returns the number of individual batches expected to be processed by
// the batcher under test.
func (b batcherTestCase) Batches() int {
	if b.BatchSize == 0 {
		return b.ItemCount
	}

	return b.ItemCount / b.BatchSize
}

// runBatcherTests processes all test cases, throwing assertion errors if they
// fail.
func runBatcherTests(cases []batcherTestCase, t *testing.T) {
	for _, c := range cases {
		b := c.Batcher()

		items := c.ItemCount
		for i := 0; i < c.Batches(); i++ {
			group := b.Next()
			assert.Equal(t, c.BatchSize, len(group))
			items -= c.BatchSize
		}
	}
}
<|endoftext|>


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

import (
	"io/ioutil"
	"os"
	"path/filepath"
	"testing"
	"time"

	. "github.com/control-center/serviced/volume"
	. "gopkg.in/check.v1"
)

func TestUtils(t *testing.T) { TestingT(t) }

type UtilsSuite struct{}

var _ = Suite(&UtilsSuite{})

func (s *UtilsSuite) TestIsDir(c *C) {
	root := c.MkDir()

	// Test a directory
	ok, err := IsDir(root)
	c.Assert(ok, Equals, true)
	c.Assert(err, IsNil)

	// Test a file
	file := filepath.Join(root, "afile")
	ioutil.WriteFile(file, []byte("hi"), 0664)
	ok, err = IsDir(file)
	c.Assert(ok, Equals, false)
	c.Assert(err, ErrorMatches, ".*is not a directory")

	// Test a nonexistent path
	ok, err = IsDir(root + "/notafile")
	c.Assert(ok, Equals, false)
	c.Assert(err, IsNil)
}

func (s *UtilsSuite) TestFileInfoSlice(c *C) {
	root := c.MkDir()

	var (
		slice    FileInfoSlice
		stats    []os.FileInfo
		expected []string
		data     = []byte("hi")
	)

	expected = append(expected, "file1")
	expected = append(expected, "file2")
	expected = append(expected, "file3")

	for _, fname := range expected {
		file := filepath.Join(root, fname)
		ioutil.WriteFile(file, data, 0664)
		if fi, err := os.Stat(file); err == nil {
			stats = append(stats, fi)
		}
		time.Sleep(5 * time.Millisecond)
	}

	// Append the FileInfos in non-sorted order
	slice = append(slice, stats[2])
	slice = append(slice, stats[0])
	slice = append(slice, stats[1])

	labels := slice.Labels()

	c.Assert(labels, DeepEquals, expected)
}
<commit_msg>Fix unmatching test<commit_after>// Copyright 2015 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 volume_test

import (
	"io/ioutil"
	"os"
	"path/filepath"
	"testing"
	"time"

	. "github.com/control-center/serviced/volume"
	. "gopkg.in/check.v1"
)

func TestUtils(t *testing.T) { TestingT(t) }

type UtilsSuite struct{}

var _ = Suite(&UtilsSuite{})

func (s *UtilsSuite) TestIsDir(c *C) {
	root := c.MkDir()

	// Test a directory
	ok, err := IsDir(root)
	c.Assert(ok, Equals, true)
	c.Assert(err, IsNil)

	// Test a file
	file := filepath.Join(root, "afile")
	ioutil.WriteFile(file, []byte("hi"), 0664)
	ok, err = IsDir(file)
	c.Assert(ok, Equals, false)
	c.Assert(err, ErrorMatches, ErrNotADirectory.Error())

	// Test a nonexistent path
	ok, err = IsDir(root + "/notafile")
	c.Assert(ok, Equals, false)
	c.Assert(err, IsNil)
}

func (s *UtilsSuite) TestFileInfoSlice(c *C) {
	root := c.MkDir()

	var (
		slice    FileInfoSlice
		stats    []os.FileInfo
		expected []string
		data     = []byte("hi")
	)

	expected = append(expected, "file1")
	expected = append(expected, "file2")
	expected = append(expected, "file3")

	for _, fname := range expected {
		file := filepath.Join(root, fname)
		ioutil.WriteFile(file, data, 0664)
		if fi, err := os.Stat(file); err == nil {
			stats = append(stats, fi)
		}
		time.Sleep(5 * time.Millisecond)
	}

	// Append the FileInfos in non-sorted order
	slice = append(slice, stats[2])
	slice = append(slice, stats[0])
	slice = append(slice, stats[1])

	labels := slice.Labels()

	c.Assert(labels, DeepEquals, expected)
}
<|endoftext|>