<commit_before>// SelectionAlgo project main.go
package main

import (
	"code.google.com/p/gorest"
	"fmt"
	"net/http"
)

type Configuration struct {
	RedisIp   string
	RedisDb   int
	RedisPort string
	Port      string
}

type EnvConfiguration struct {
	RedisIp   string
	RedisDb   string
	RedisPort string
	Port      string
}

type AttributeData struct {
	AttributeCode     []string
	AttributeClass    string
	AttributeType     string
	AttributeCategory string
	WeightPrecentage  string
}

type Request struct {
	Company       int
	Tenant        int
	Class         string
	Type          string
	Category      string
	SessionId     string
	AttributeInfo []AttributeData
}

type ConcurrencyInfo struct {
	ResourceId        string
	LastConnectedTime string
}

func main() {
	fmt.Println("Initializting Main")
	InitiateRedis()
	gorest.RegisterService(new(SelectionAlgo))
	http.Handle("/", gorest.Handle())
	http.ListenAndServe(":2228", nil)
}
<commit_msg>add custom-environment-variables<commit_after>// SelectionAlgo project main.go
package main

import (
	"code.google.com/p/gorest"
	"fmt"
	"net/http"
)

type Configuration struct {
	RedisIp   string
	RedisDb   int
	RedisPort string
	Port      string
}

type EnvConfiguration struct {
	RedisIp   string
	RedisDb   string
	RedisPort string
	Port      string
}

type AttributeData struct {
	AttributeCode     []string
	AttributeClass    string
	AttributeType     string
	AttributeCategory string
	WeightPrecentage  string
}

type Request struct {
	Company       int
	Tenant        int
	Class         string
	Type          string
	Category      string
	SessionId     string
	AttributeInfo []AttributeData
}

type ConcurrencyInfo struct {
	ResourceId        string
	LastConnectedTime string
}

func main() {
	fmt.Println("Initializting Main")
	InitiateRedis()
	gorest.RegisterService(new(SelectionAlgo))
	http.Handle("/", gorest.Handle())
	addr := fmt.Sprintf(":%s", port)
	http.ListenAndServe(addr, nil)
}
<|endoftext|>


<commit_before>package drivers

import (
	"fmt"
	"os"
	"os/exec"
	"path/filepath"
	"strings"

	"github.com/pkg/errors"
	"golang.org/x/sys/unix"

	"github.com/lxc/lxd/lxd/migration"
	"github.com/lxc/lxd/lxd/operations"
	"github.com/lxc/lxd/lxd/util"
	"github.com/lxc/lxd/shared"
	"github.com/lxc/lxd/shared/api"
	"github.com/lxc/lxd/shared/units"
)

var btrfsVersion string
var btrfsLoaded bool

type btrfs struct {
	common
}

// load is used to run one-time action per-driver rather than per-pool.
func (d *btrfs) load() error {
	// Register the patches.
	d.patches = map[string]func() error{
		"storage_create_vm": nil,
	}

	// Done if previously loaded.
	if btrfsLoaded {
		return nil
	}

	// Validate the required binaries.
	for _, tool := range []string{"btrfs"} {
		_, err := exec.LookPath(tool)
		if err != nil {
			return fmt.Errorf("Required tool '%s' is missing", tool)
		}
	}

	// Detect and record the version.
	if btrfsVersion == "" {
		out, err := shared.RunCommand("btrfs", "version")
		if err != nil {
			return err
		}

		count, err := fmt.Sscanf(strings.SplitN(out, " ", 2)[1], "v%s\n", &btrfsVersion)
		if err != nil || count != 1 {
			return fmt.Errorf("The 'btrfs' tool isn't working properly")
		}
	}

	btrfsLoaded = true
	return nil
}

// Info returns info about the driver and its environment.
func (d *btrfs) Info() Info {
	return Info{
		Name:                  "btrfs",
		Version:               btrfsVersion,
		OptimizedImages:       true,
		PreservesInodes:       !d.state.OS.RunningInUserNS,
		Remote:                false,
		VolumeTypes:           []VolumeType{VolumeTypeCustom, VolumeTypeImage, VolumeTypeContainer, VolumeTypeVM},
		BlockBacking:          false,
		RunningQuotaResize:    true,
		RunningSnapshotFreeze: false,
	}
}

// Create is called during pool creation and is effectively using an empty driver struct.
// WARNING: The Create() function cannot rely on any of the struct attributes being set.
func (d *btrfs) Create() error {
	// Store the provided source as we are likely to be mangling it.
	d.config["volatile.initial_source"] = d.config["source"]

	loopPath := loopFilePath(d.name)
	if d.config["source"] == "" || d.config["source"] == loopPath {
		// Create a loop based pool.
		d.config["source"] = loopPath

		// Create the loop file itself.
		size, err := units.ParseByteSizeString(d.config["size"])
		if err != nil {
			return err
		}

		err = createSparseFile(d.config["source"], size)
		if err != nil {
			return errors.Wrap(err, "Failed to create the sparse file")
		}

		// Format the file.
		_, err = makeFSType(d.config["source"], "btrfs", &mkfsOptions{Label: d.name})
		if err != nil {
			return errors.Wrap(err, "Failed to format sparse file")
		}
	} else if shared.IsBlockdevPath(d.config["source"]) {
		// Format the block device.
		_, err := makeFSType(d.config["source"], "btrfs", &mkfsOptions{Label: d.name})
		if err != nil {
			return errors.Wrap(err, "Failed to format block device")
		}

		// Record the UUID as the source.
		devUUID, err := fsUUID(d.config["source"])
		if err != nil {
			return err
		}

		// Confirm that the symlink is appearing (give it 10s).
		if tryExists(fmt.Sprintf("/dev/disk/by-uuid/%s", devUUID)) {
			// Override the config to use the UUID.
			d.config["source"] = devUUID
		}
	} else if d.config["source"] != "" {
		hostPath := shared.HostPath(d.config["source"])
		if d.isSubvolume(hostPath) {
			// Existing btrfs subvolume.
			subvols, err := d.getSubvolumes(hostPath)
			if err != nil {
				return errors.Wrap(err, "Could not determine if existing btrfs subvolume is empty")
			}

			// Check that the provided subvolume is empty.
			if len(subvols) > 0 {
				return fmt.Errorf("Requested btrfs subvolume exists but is not empty")
			}
		} else {
			// New btrfs subvolume on existing btrfs filesystem.
			cleanSource := filepath.Clean(hostPath)
			lxdDir := shared.VarPath()

			if shared.PathExists(hostPath) && !hasFilesystem(hostPath, util.FilesystemSuperMagicBtrfs) {
				return fmt.Errorf("Provided path does not reside on a btrfs filesystem")
			} else if strings.HasPrefix(cleanSource, lxdDir) {
				if cleanSource != GetPoolMountPath(d.name) {
					return fmt.Errorf("Only allowed source path under %s is %s", shared.VarPath(), GetPoolMountPath(d.name))
				} else if !hasFilesystem(shared.VarPath("storage-pools"), util.FilesystemSuperMagicBtrfs) {
					return fmt.Errorf("Provided path does not reside on a btrfs filesystem")
				}

				// Delete the current directory to replace by subvolume.
				err := os.Remove(cleanSource)
				if err != nil && !os.IsNotExist(err) {
					return errors.Wrapf(err, "Failed to remove '%s'", cleanSource)
				}
			}

			// Create the subvolume.
			_, err := shared.RunCommand("btrfs", "subvolume", "create", hostPath)
			if err != nil {
				return err
			}
		}
	} else {
		return fmt.Errorf("Invalid \"source\" property")
	}

	return nil
}

// Delete removes the storage pool from the storage device.
func (d *btrfs) Delete(op *operations.Operation) error {
	// If the user completely destroyed it, call it done.
	if !shared.PathExists(GetPoolMountPath(d.name)) {
		return nil
	}

	// Delete potential intermediate btrfs subvolumes.
	for _, volType := range d.Info().VolumeTypes {
		for _, dir := range BaseDirectories[volType] {
			path := filepath.Join(GetPoolMountPath(d.name), dir)
			if !shared.PathExists(path) {
				continue
			}

			if !d.isSubvolume(path) {
				continue
			}

			err := d.deleteSubvolume(path, true)
			if err != nil {
				return fmt.Errorf("Could not delete btrfs subvolume: %s", path)
			}
		}
	}

	// On delete, wipe everything in the directory.
	err := wipeDirectory(GetPoolMountPath(d.name))
	if err != nil {
		return err
	}

	// Unmount the path.
	_, err = d.Unmount()
	if err != nil {
		return err
	}

	// If the pool path is a subvolume itself, delete it.
	if d.isSubvolume(GetPoolMountPath(d.name)) {
		err := d.deleteSubvolume(GetPoolMountPath(d.name), false)
		if err != nil {
			return err
		}

		// And re-create as an empty directory to make the backend happy.
		err = os.Mkdir(GetPoolMountPath(d.name), 0700)
		if err != nil {
			return errors.Wrapf(err, "Failed to create directory '%s'", GetPoolMountPath(d.name))
		}
	}

	// Delete any loop file we may have used.
	loopPath := loopFilePath(d.name)
	err = os.Remove(loopPath)
	if err != nil && !os.IsNotExist(err) {
		return errors.Wrapf(err, "Failed to remove '%s'", loopPath)
	}

	return nil
}

// Validate checks that all provide keys are supported and that no conflicting or missing configuration is present.
func (d *btrfs) Validate(config map[string]string) error {
	return nil
}

// Update applies any driver changes required from a configuration change.
func (d *btrfs) Update(changedConfig map[string]string) error {
	// We only care about btrfs.mount_options.
	val, ok := changedConfig["btrfs.mount_options"]
	if !ok {
		return nil
	}

	// Trigger a re-mount.
	d.config["btrfs.mount_options"] = val
	mntFlags, mntOptions := resolveMountOptions(d.getMountOptions())
	mntFlags |= unix.MS_REMOUNT

	err := TryMount("", GetPoolMountPath(d.name), "none", mntFlags, mntOptions)
	if err != nil {
		return err
	}

	return nil
}

// Mount mounts the storage pool.
func (d *btrfs) Mount() (bool, error) {
	// Check if already mounted.
	if shared.IsMountPoint(GetPoolMountPath(d.name)) {
		return false, nil
	}

	// Setup mount options.
	loopPath := loopFilePath(d.name)
	mntSrc := ""
	mntDst := GetPoolMountPath(d.name)
	mntFilesystem := "btrfs"
	if d.config["source"] == loopPath {
		// Bring up the loop device.
		loopF, err := PrepareLoopDev(d.config["source"], LoFlagsAutoclear)
		if err != nil {
			return false, err
		}
		defer loopF.Close()

		mntSrc = loopF.Name()
	} else if filepath.IsAbs(d.config["source"]) {
		// Bring up an existing device or path.
		mntSrc = shared.HostPath(d.config["source"])

		if !shared.IsBlockdevPath(mntSrc) {
			mntFilesystem = "none"

			if !hasFilesystem(mntSrc, util.FilesystemSuperMagicBtrfs) {
				return false, fmt.Errorf("Source path '%s' isn't btrfs", mntSrc)
			}
		}
	} else {
		// Mount using UUID.
		mntSrc = fmt.Sprintf("/dev/disk/by-uuid/%s", d.config["source"])
	}

	// Get the custom mount flags/options.
	mntFlags, mntOptions := resolveMountOptions(d.getMountOptions())

	// Handle bind-mounts first.
	if mntFilesystem == "none" {
		// Setup the bind-mount itself.
		err := TryMount(mntSrc, mntDst, mntFilesystem, unix.MS_BIND, "")
		if err != nil {
			return false, err
		}

		// Now apply the custom options.
		mntFlags |= unix.MS_REMOUNT
		err = TryMount("", mntDst, mntFilesystem, mntFlags, mntOptions)
		if err != nil {
			return false, err
		}

		return true, nil
	}

	// Handle traditional mounts.
	err := TryMount(mntSrc, mntDst, mntFilesystem, mntFlags, mntOptions)
	if err != nil {
		return false, err
	}

	return true, nil
}

// Unmount unmounts the storage pool.
func (d *btrfs) Unmount() (bool, error) {
	// Unmount the pool.
	ourUnmount, err := forceUnmount(GetPoolMountPath(d.name))
	if err != nil {
		return false, err
	}

	// If loop backed, force release the loop device.
	loopPath := loopFilePath(d.name)
	if d.config["source"] == loopPath {
		releaseLoopDev(loopPath)
	}

	return ourUnmount, nil
}

// GetResources returns the pool resource usage information.
func (d *btrfs) GetResources() (*api.ResourcesStoragePool, error) {
	return d.vfsGetResources()
}

// MigrationType returns the type of transfer methods to be used when doing migrations between pools in preference order.
func (d *btrfs) MigrationTypes(contentType ContentType, refresh bool) []migration.Type {
	if contentType != ContentTypeFS {
		return nil
	}

	// Only use rsync for refreshes and if running in an unprivileged container.
	if refresh || d.state.OS.RunningInUserNS {
		return []migration.Type{
			{
				FSType:   migration.MigrationFSType_RSYNC,
				Features: []string{"xattrs", "delete", "compress", "bidirectional"},
			},
		}
	}

	return []migration.Type{
		{
			FSType: migration.MigrationFSType_BTRFS,
		},
		{
			FSType:   migration.MigrationFSType_RSYNC,
			Features: []string{"xattrs", "delete", "compress", "bidirectional"},
		},
	}
}
<commit_msg>lxd/storage/btrfs: Fix usage inside containers<commit_after>package drivers

import (
	"fmt"
	"os"
	"os/exec"
	"path/filepath"
	"strings"

	"github.com/pkg/errors"
	"golang.org/x/sys/unix"

	"github.com/lxc/lxd/lxd/migration"
	"github.com/lxc/lxd/lxd/operations"
	"github.com/lxc/lxd/lxd/util"
	"github.com/lxc/lxd/shared"
	"github.com/lxc/lxd/shared/api"
	"github.com/lxc/lxd/shared/units"
)

var btrfsVersion string
var btrfsLoaded bool

type btrfs struct {
	common
}

// load is used to run one-time action per-driver rather than per-pool.
func (d *btrfs) load() error {
	// Register the patches.
	d.patches = map[string]func() error{
		"storage_create_vm": nil,
	}

	// Done if previously loaded.
	if btrfsLoaded {
		return nil
	}

	// Validate the required binaries.
	for _, tool := range []string{"btrfs"} {
		_, err := exec.LookPath(tool)
		if err != nil {
			return fmt.Errorf("Required tool '%s' is missing", tool)
		}
	}

	// Detect and record the version.
	if btrfsVersion == "" {
		out, err := shared.RunCommand("btrfs", "version")
		if err != nil {
			return err
		}

		count, err := fmt.Sscanf(strings.SplitN(out, " ", 2)[1], "v%s\n", &btrfsVersion)
		if err != nil || count != 1 {
			return fmt.Errorf("The 'btrfs' tool isn't working properly")
		}
	}

	btrfsLoaded = true
	return nil
}

// Info returns info about the driver and its environment.
func (d *btrfs) Info() Info {
	return Info{
		Name:                  "btrfs",
		Version:               btrfsVersion,
		OptimizedImages:       true,
		PreservesInodes:       !d.state.OS.RunningInUserNS,
		Remote:                false,
		VolumeTypes:           []VolumeType{VolumeTypeCustom, VolumeTypeImage, VolumeTypeContainer, VolumeTypeVM},
		BlockBacking:          false,
		RunningQuotaResize:    true,
		RunningSnapshotFreeze: false,
	}
}

// Create is called during pool creation and is effectively using an empty driver struct.
// WARNING: The Create() function cannot rely on any of the struct attributes being set.
func (d *btrfs) Create() error {
	// Store the provided source as we are likely to be mangling it.
	d.config["volatile.initial_source"] = d.config["source"]

	loopPath := loopFilePath(d.name)
	if d.config["source"] == "" || d.config["source"] == loopPath {
		// Create a loop based pool.
		d.config["source"] = loopPath

		// Create the loop file itself.
		size, err := units.ParseByteSizeString(d.config["size"])
		if err != nil {
			return err
		}

		err = createSparseFile(d.config["source"], size)
		if err != nil {
			return errors.Wrap(err, "Failed to create the sparse file")
		}

		// Format the file.
		_, err = makeFSType(d.config["source"], "btrfs", &mkfsOptions{Label: d.name})
		if err != nil {
			return errors.Wrap(err, "Failed to format sparse file")
		}
	} else if shared.IsBlockdevPath(d.config["source"]) {
		// Format the block device.
		_, err := makeFSType(d.config["source"], "btrfs", &mkfsOptions{Label: d.name})
		if err != nil {
			return errors.Wrap(err, "Failed to format block device")
		}

		// Record the UUID as the source.
		devUUID, err := fsUUID(d.config["source"])
		if err != nil {
			return err
		}

		// Confirm that the symlink is appearing (give it 10s).
		if tryExists(fmt.Sprintf("/dev/disk/by-uuid/%s", devUUID)) {
			// Override the config to use the UUID.
			d.config["source"] = devUUID
		}
	} else if d.config["source"] != "" {
		hostPath := shared.HostPath(d.config["source"])
		if d.isSubvolume(hostPath) {
			// Existing btrfs subvolume.
			subvols, err := d.getSubvolumes(hostPath)
			if err != nil {
				return errors.Wrap(err, "Could not determine if existing btrfs subvolume is empty")
			}

			// Check that the provided subvolume is empty.
			if len(subvols) > 0 {
				return fmt.Errorf("Requested btrfs subvolume exists but is not empty")
			}
		} else {
			// New btrfs subvolume on existing btrfs filesystem.
			cleanSource := filepath.Clean(hostPath)
			lxdDir := shared.VarPath()

			if shared.PathExists(hostPath) && !hasFilesystem(hostPath, util.FilesystemSuperMagicBtrfs) {
				return fmt.Errorf("Provided path does not reside on a btrfs filesystem")
			} else if strings.HasPrefix(cleanSource, lxdDir) {
				if cleanSource != GetPoolMountPath(d.name) {
					return fmt.Errorf("Only allowed source path under %s is %s", shared.VarPath(), GetPoolMountPath(d.name))
				} else if !hasFilesystem(shared.VarPath("storage-pools"), util.FilesystemSuperMagicBtrfs) {
					return fmt.Errorf("Provided path does not reside on a btrfs filesystem")
				}

				// Delete the current directory to replace by subvolume.
				err := os.Remove(cleanSource)
				if err != nil && !os.IsNotExist(err) {
					return errors.Wrapf(err, "Failed to remove '%s'", cleanSource)
				}
			}

			// Create the subvolume.
			_, err := shared.RunCommand("btrfs", "subvolume", "create", hostPath)
			if err != nil {
				return err
			}
		}
	} else {
		return fmt.Errorf("Invalid \"source\" property")
	}

	return nil
}

// Delete removes the storage pool from the storage device.
func (d *btrfs) Delete(op *operations.Operation) error {
	// If the user completely destroyed it, call it done.
	if !shared.PathExists(GetPoolMountPath(d.name)) {
		return nil
	}

	// Delete potential intermediate btrfs subvolumes.
	for _, volType := range d.Info().VolumeTypes {
		for _, dir := range BaseDirectories[volType] {
			path := filepath.Join(GetPoolMountPath(d.name), dir)
			if !shared.PathExists(path) {
				continue
			}

			if !d.isSubvolume(path) {
				continue
			}

			err := d.deleteSubvolume(path, true)
			if err != nil {
				return fmt.Errorf("Could not delete btrfs subvolume: %s", path)
			}
		}
	}

	// On delete, wipe everything in the directory.
	err := wipeDirectory(GetPoolMountPath(d.name))
	if err != nil {
		return err
	}

	// Unmount the path.
	_, err = d.Unmount()
	if err != nil {
		return err
	}

	// If the pool path is a subvolume itself, delete it.
	if d.isSubvolume(GetPoolMountPath(d.name)) {
		err := d.deleteSubvolume(GetPoolMountPath(d.name), false)
		if err != nil {
			return err
		}

		// And re-create as an empty directory to make the backend happy.
		err = os.Mkdir(GetPoolMountPath(d.name), 0700)
		if err != nil {
			return errors.Wrapf(err, "Failed to create directory '%s'", GetPoolMountPath(d.name))
		}
	}

	// Delete any loop file we may have used.
	loopPath := loopFilePath(d.name)
	err = os.Remove(loopPath)
	if err != nil && !os.IsNotExist(err) {
		return errors.Wrapf(err, "Failed to remove '%s'", loopPath)
	}

	return nil
}

// Validate checks that all provide keys are supported and that no conflicting or missing configuration is present.
func (d *btrfs) Validate(config map[string]string) error {
	return nil
}

// Update applies any driver changes required from a configuration change.
func (d *btrfs) Update(changedConfig map[string]string) error {
	// We only care about btrfs.mount_options.
	val, ok := changedConfig["btrfs.mount_options"]
	if !ok {
		return nil
	}

	// Custom mount options don't work inside containers
	if d.state.OS.RunningInUserNS {
		return nil
	}

	// Trigger a re-mount.
	d.config["btrfs.mount_options"] = val
	mntFlags, mntOptions := resolveMountOptions(d.getMountOptions())
	mntFlags |= unix.MS_REMOUNT

	err := TryMount("", GetPoolMountPath(d.name), "none", mntFlags, mntOptions)
	if err != nil {
		return err
	}

	return nil
}

// Mount mounts the storage pool.
func (d *btrfs) Mount() (bool, error) {
	// Check if already mounted.
	if shared.IsMountPoint(GetPoolMountPath(d.name)) {
		return false, nil
	}

	// Setup mount options.
	loopPath := loopFilePath(d.name)
	mntSrc := ""
	mntDst := GetPoolMountPath(d.name)
	mntFilesystem := "btrfs"
	if d.config["source"] == loopPath {
		// Bring up the loop device.
		loopF, err := PrepareLoopDev(d.config["source"], LoFlagsAutoclear)
		if err != nil {
			return false, err
		}
		defer loopF.Close()

		mntSrc = loopF.Name()
	} else if filepath.IsAbs(d.config["source"]) {
		// Bring up an existing device or path.
		mntSrc = shared.HostPath(d.config["source"])

		if !shared.IsBlockdevPath(mntSrc) {
			mntFilesystem = "none"

			if !hasFilesystem(mntSrc, util.FilesystemSuperMagicBtrfs) {
				return false, fmt.Errorf("Source path '%s' isn't btrfs", mntSrc)
			}
		}
	} else {
		// Mount using UUID.
		mntSrc = fmt.Sprintf("/dev/disk/by-uuid/%s", d.config["source"])
	}

	// Get the custom mount flags/options.
	mntFlags, mntOptions := resolveMountOptions(d.getMountOptions())

	// Handle bind-mounts first.
	if mntFilesystem == "none" {
		// Setup the bind-mount itself.
		err := TryMount(mntSrc, mntDst, mntFilesystem, unix.MS_BIND, "")
		if err != nil {
			return false, err
		}

		// Custom mount options don't work inside containers
		if !d.state.OS.RunningInUserNS {
			return true, nil
		}

		// Now apply the custom options.
		mntFlags |= unix.MS_REMOUNT
		err = TryMount("", mntDst, mntFilesystem, mntFlags, mntOptions)
		if err != nil {
			return false, err
		}

		return true, nil
	}

	// Handle traditional mounts.
	err := TryMount(mntSrc, mntDst, mntFilesystem, mntFlags, mntOptions)
	if err != nil {
		return false, err
	}

	return true, nil
}

// Unmount unmounts the storage pool.
func (d *btrfs) Unmount() (bool, error) {
	// Unmount the pool.
	ourUnmount, err := forceUnmount(GetPoolMountPath(d.name))
	if err != nil {
		return false, err
	}

	// If loop backed, force release the loop device.
	loopPath := loopFilePath(d.name)
	if d.config["source"] == loopPath {
		releaseLoopDev(loopPath)
	}

	return ourUnmount, nil
}

// GetResources returns the pool resource usage information.
func (d *btrfs) GetResources() (*api.ResourcesStoragePool, error) {
	return d.vfsGetResources()
}

// MigrationType returns the type of transfer methods to be used when doing migrations between pools in preference order.
func (d *btrfs) MigrationTypes(contentType ContentType, refresh bool) []migration.Type {
	if contentType != ContentTypeFS {
		return nil
	}

	// Only use rsync for refreshes and if running in an unprivileged container.
	if refresh || d.state.OS.RunningInUserNS {
		return []migration.Type{
			{
				FSType:   migration.MigrationFSType_RSYNC,
				Features: []string{"xattrs", "delete", "compress", "bidirectional"},
			},
		}
	}

	return []migration.Type{
		{
			FSType: migration.MigrationFSType_BTRFS,
		},
		{
			FSType:   migration.MigrationFSType_RSYNC,
			Features: []string{"xattrs", "delete", "compress", "bidirectional"},
		},
	}
}
<|endoftext|>


<commit_before>package command

import (
	"bytes"
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"reflect"
	"sync"
)

type CommandsInfo struct {
	Port int
}

type CommandInfo map[string]*struct {
	Token string
}

type CommandRuntimeInfo struct {
	Token   string
	Handler interface{}
}

type CommandServer struct {
	Common   CommandsInfo
	Command  CommandInfo
	Handlers map[string]*CommandRuntimeInfo
}

func NewServer(commands CommandsInfo, command CommandInfo) *CommandServer {
	server := &CommandServer{commands, command, map[string]*CommandRuntimeInfo{}}

	for k, v := range command {
		server.Handlers[k] = &CommandRuntimeInfo{v.Token, nil}
	}

	server.registHandler("/echo", EchoCommand)
	server.registHandler("/namu", NamuCommand)
	server.registHandler("/zzal", ZzalCommand)

	return server
}

func (server *CommandServer) registHandler(key string, handler interface{}) {
	if val, ok := server.Handlers[key]; ok {
		val.Handler = handler
	} else {
		log.Println("Warning : config not found for ", key)
		server.Handlers[key] = &CommandRuntimeInfo{"", handler}
	}
}

func requestFormToRequestObj(r *http.Request) *Request {
	ret := new(Request)

	val := reflect.Indirect(reflect.ValueOf(ret))
	typ := reflect.TypeOf(*ret)

	for i := 0; i < typ.NumField(); i++ {
		field := val.Field(i)
		field_info := typ.Field(i)
		field_name := field_info.Tag.Get("param")
		field.Set(reflect.ValueOf(r.FormValue(field_name)))
	}

	return ret
}

func (server *CommandServer) commandHandler(w http.ResponseWriter, r *http.Request) {
	req := requestFormToRequestObj(r)
	handlerInfo := server.Handlers[req.Command]

	if handlerInfo != nil {
		if handlerInfo.Token == "" || handlerInfo.Token == req.Token {
			fun := reflect.ValueOf(handlerInfo.Handler)
			in := make([]reflect.Value, 1)
			in[0] = reflect.ValueOf(*req)
			response := fun.Call(in)[0].Interface().(*Response)

			var e error
			w.Header().Set("Content-Type", "application/json")
			if response.ResponseType != deffered_in_channel {
				encoder := json.NewEncoder(w)
				e = encoder.Encode(response)
			} else {
				var buf []byte
				buf, e = json.Marshal(response)
				http.Post(req.ResponseUrl, "application/json", bytes.NewBuffer(buf))
				log.Println("Deffered : ", string(buf))
			}

			if e != nil {
				log.Println("Error occured : ", req, e)
			}
		}
	}
}

func (server *CommandServer) Start(wg *sync.WaitGroup) {
	http.HandleFunc("/", server.commandHandler)
	http.ListenAndServe(fmt.Sprintf(":%d", server.Common.Port), nil)

	wg.Done()
}
<commit_msg>Add Command handler initializer<commit_after>package command

import (
	"bytes"
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"reflect"
	"strings"
	"sync"
)

type CommandsInfo struct {
	Port int
}

type CommandInfo map[string]*struct {
	Token   string
	Options []string
}

type CommandRuntimeInfo struct {
	Token   string
	Handler interface{}
	Options map[string]string
}

type CommandServer struct {
	Common   CommandsInfo
	Command  CommandInfo
	Handlers map[string]*CommandRuntimeInfo
}

func NewServer(commands CommandsInfo, command CommandInfo) *CommandServer {
	server := &CommandServer{commands, command, map[string]*CommandRuntimeInfo{}}

	for k, v := range command {
		var parsed_options map[string]string
		for _, val := range v.Options {
			vals := strings.Split(val, ":")
			parsed_options[vals[0]] = vals[1]
		}
		server.Handlers[k] = &CommandRuntimeInfo{v.Token, nil, parsed_options}
	}

	server.registHandler("/echo", EchoCommand, nil)
	server.registHandler("/namu", NamuCommand, nil)
	server.registHandler("/zzal", ZzalCommand, nil)

	return server
}

type HandlerInitializer func(*map[string]string)

func (server *CommandServer) registHandler(key string, handler interface{}, initializer HandlerInitializer) {
	if val, ok := server.Handlers[key]; ok {
		val.Handler = handler
	} else {
		log.Println("Warning : config not found for ", key)
		server.Handlers[key] = &CommandRuntimeInfo{"", handler, nil}
	}
	if initializer != nil {
		initializer(&server.Handlers[key].Options)
	}
}

func requestFormToRequestObj(r *http.Request) *Request {
	ret := new(Request)

	val := reflect.Indirect(reflect.ValueOf(ret))
	typ := reflect.TypeOf(*ret)

	for i := 0; i < typ.NumField(); i++ {
		field := val.Field(i)
		field_info := typ.Field(i)
		field_name := field_info.Tag.Get("param")
		field.Set(reflect.ValueOf(r.FormValue(field_name)))
	}

	return ret
}

func (server *CommandServer) commandHandler(w http.ResponseWriter, r *http.Request) {
	req := requestFormToRequestObj(r)
	handlerInfo := server.Handlers[req.Command]

	if handlerInfo != nil {
		if handlerInfo.Token == "" || handlerInfo.Token == req.Token {
			fun := reflect.ValueOf(handlerInfo.Handler)
			in := make([]reflect.Value, 1)
			in[0] = reflect.ValueOf(*req)
			response := fun.Call(in)[0].Interface().(*Response)

			var e error
			w.Header().Set("Content-Type", "application/json")
			if response.ResponseType != deffered_in_channel {
				encoder := json.NewEncoder(w)
				e = encoder.Encode(response)
			} else {
				var buf []byte
				buf, e = json.Marshal(response)
				http.Post(req.ResponseUrl, "application/json", bytes.NewBuffer(buf))
				log.Println("Deffered : ", string(buf))
			}

			if e != nil {
				log.Println("Error occured : ", req, e)
			}
		}
	}
}

func (server *CommandServer) Start(wg *sync.WaitGroup) {
	http.HandleFunc("/", server.commandHandler)
	http.ListenAndServe(fmt.Sprintf(":%d", server.Common.Port), nil)

	wg.Done()
}
<|endoftext|>


<commit_before>package command

import (
	"fmt"
	"sort"
)

type deviceData struct {
	ProjectId  uint64 `json:"project_id"`
	DeviceId   string `json:"device_id,omitempty"`
	DeviceName string `json:"device_name,omitempty"`
	DeviceType string `json:"device_type,omitempty"`
	Created    string `json:"created,omitempty"`
	// Private fields, not marshalled into JSON
	isUpdate bool
}

func (d *deviceData) IsValid() bool {
	if d.isUpdate {
		return len(d.DeviceId) > 0 &&
			(len(d.DeviceName) > 0 || len(d.DeviceType) > 0)
	}
	return d.ProjectId != 0
}

// deviceId is a simpler struct for calls that just consist of a device id
// and optionally projectId
type deviceId struct {
	id        string
	projectId uint64
}

func (d *deviceId) IsValid() bool {
	return len(d.id) > 0
}

// NewDevicesCommand returns the base 'device' command.
func NewDevicesCommand(ctx *Context) *Command {
	cmd := &Command{
		Name:  "device",
		Usage: "Commands for managing devices.",
		SubCommands: Mux{
			"create": newCreateDeviceCmd(ctx),
			"delete": newDeleteDeviceCmd(ctx),
			"get":    newGetDeviceCmd(ctx),
			"list":   newListDevicesCmd(ctx),
			"update": newUpdateDeviceCmd(ctx),
		},
	}
	cmd.NewFlagSet("iobeam device")

	return cmd
}

func newCreateOrUpdateDeviceCmd(ctx *Context, update bool, name string, action Action) *Command {
	device := deviceData{
		isUpdate: update,
	}

	cmd := &Command{
		Name:    name,
		ApiPath: "/v1/devices",
		Usage:   name + " device",
		Data:    &device,
		Action:  action,
	}
	flags := cmd.NewFlagSet("iobeam device " + name)
	var idDesc string
	if update {
		idDesc = "ID of the device to be updated"
	} else {
		idDesc = "Device ID, if omitted a random one will be assigned (must be > 16 chars)"
	}
	flags.StringVar(&device.DeviceId, "id", "", idDesc)
	flags.StringVar(&device.DeviceName, "name", "", "The device name")
	flags.StringVar(&device.DeviceType, "type", "", "The type of device")
	flags.Uint64Var(&device.ProjectId, "projectId", ctx.Profile.ActiveProject, "Project ID associated with the device (if omitted, defaults to active project).")

	return cmd
}

func newCreateDeviceCmd(ctx *Context) *Command {
	return newCreateOrUpdateDeviceCmd(ctx, false, "create", createDevice)
}

func newUpdateDeviceCmd(ctx *Context) *Command {
	return newCreateOrUpdateDeviceCmd(ctx, true, "update", updateDevice)
}

func createDevice(c *Command, ctx *Context) error {
	data := c.Data.(*deviceData)
	_, err := ctx.Client.
		Post(c.ApiPath).
		Expect(201).
		ProjectToken(ctx.Profile, data.ProjectId).
		Body(data).
		ResponseBody(c.Data).
		ResponseBodyHandler(func(body interface{}) error {

		device := body.(*deviceData)
		fmt.Println("New device created.")
		fmt.Printf("Device ID: %v\n", device.DeviceId)
		fmt.Printf("Device Name: %v\n", device.DeviceName)
		fmt.Println()

		return nil
	}).Execute()

	return err
}

func updateDevice(c *Command, ctx *Context) error {

	device := c.Data.(*deviceData)

	rsp, err := ctx.Client.
		Patch(c.ApiPath+"/"+device.DeviceId).
		Expect(200).
		ProjectToken(ctx.Profile, device.ProjectId).
		Body(c.Data).
		Execute()

	if err == nil {
		fmt.Println("Device successfully updated")
	} else if rsp.Http().StatusCode == 204 {
		fmt.Println("Device not modified")
		return nil
	}

	return err
}

func newGetDeviceCmd(ctx *Context) *Command {
	data := new(deviceId)

	cmd := &Command{
		Name:    "get",
		ApiPath: "/v1/devices",
		Usage:   "get device information",
		Data:    data,
		Action:  getDevice,
	}
	flags := cmd.NewFlagSet("iobeam device get")
	flags.StringVar(&data.id, "id", "", "Device ID to query (REQUIRED)")
	flags.Uint64Var(&data.projectId, "projectId", ctx.Profile.ActiveProject,
		"Project ID to get devices from (if omitted, defaults to active project)")

	return cmd
}

func getDevice(c *Command, ctx *Context) error {
	data := c.Data.(*deviceId)
	path := c.ApiPath + "/" + data.id

	device := new(deviceData)
	_, err := ctx.Client.
		Get(path).
		Expect(200).
		ProjectToken(ctx.Profile, data.projectId).
		ResponseBody(device).
		ResponseBodyHandler(func(body interface{}) error {
		device = body.(*deviceData)
		fmt.Printf("Device name: %v\n"+
			"Device ID: %v\n"+
			"Project ID: %v\n"+
			"Type: %v\n"+
			"Created: %v\n",
			device.DeviceName,
			device.DeviceId,
			device.ProjectId,
			device.DeviceType,
			device.Created)

		return nil
	}).Execute()

	return err
}

const (
	orderName        = "name"
	orderNameReverse = "name-r"
	orderId          = "id"
	orderIdReverse   = "id-r"
	orderDate        = "date"
	orderDateReverse = "date-r"
)

var orders = []string{orderName, orderNameReverse, orderId, orderIdReverse,
	orderDate, orderDateReverse}

type listData struct {
	projectId uint64
	order     string
}

func (d *listData) IsValid() bool {
	pidOk := d.projectId > 0
	orderOk := isInList(d.order, orders)
	return pidOk && orderOk
}

func newListDevicesCmd(ctx *Context) *Command {
	data := new(listData)

	cmd := &Command{
		Name:    "list",
		ApiPath: "/v1/devices",
		Usage:   "List devices for a given project.",
		Data:    data,
		Action:  listDevices,
	}
	flags := cmd.NewFlagSet("iobeam device list")
	flags.Uint64Var(&data.projectId, "projectId", ctx.Profile.ActiveProject,
		"Project ID to get devices from (if omitted, defaults to active project)")
	flags.StringVar(&data.order, "order", orderDate,
		"Sort order for results. Valid values: date(-r), id(-r), name(-r). Values ending with -r are reverse ordering.")

	return cmd
}

type deviceSort struct {
	items []deviceData
	order string
}

func (a deviceSort) Len() int      { return len(a.items) }
func (a deviceSort) Swap(i, j int) { a.items[i], a.items[j] = a.items[j], a.items[i] }
func (a deviceSort) Less(i, j int) bool {
	switch a.order {
	case "name":
		return a.items[i].DeviceName < a.items[j].DeviceName
	case "name-r":
		return a.items[j].DeviceName < a.items[i].DeviceName
	case "id":
		return a.items[i].DeviceId < a.items[j].DeviceId
	case "id-r":
		return a.items[i].DeviceId < a.items[j].DeviceId
	case "date-r":
		return a.items[j].Created < a.items[i].Created
	case "date":
		fallthrough
	default:
		return a.items[i].Created < a.items[j].Created
	}
	return false
}

func listDevices(c *Command, ctx *Context) error {
	type deviceList struct {
		Devices []deviceData
	}

	cmdArgs := c.Data.(*listData)
	pid := cmdArgs.projectId

	_, err := ctx.Client.
		Get(c.ApiPath).
		ParamUint64("project_id", pid).
		Expect(200).
		ProjectToken(ctx.Profile, pid).
		ResponseBody(new(deviceList)).
		ResponseBodyHandler(func(body interface{}) error {

		list := body.(*deviceList)

		fmt.Printf("Devices in project %v\n", pid)
		fmt.Println("-----")

		sorted := &deviceSort{items: list.Devices, order: cmdArgs.order}
		sort.Sort(sorted)
		for _, device := range sorted.items {

			fmt.Printf("Name: %v\n"+
				"Device ID: %v\n"+
				"Type: %v\n"+
				"Created: %v\n\n",
				device.DeviceName,
				device.DeviceId,
				device.DeviceType,
				device.Created)
		}

		return nil
	}).Execute()

	return err
}

func newDeleteDeviceCmd(ctx *Context) *Command {
	data := new(deviceId)

	cmd := &Command{
		Name:    "delete",
		ApiPath: "/v1/devices",
		Usage:   "delete device",
		Data:    data,
		Action:  deleteDevice,
	}
	flags := cmd.NewFlagSet("iobeam device delete")
	flags.StringVar(&data.id, "id", "", "The ID of the device to delete (REQUIRED)")
	flags.Uint64Var(&data.projectId, "projectId", ctx.Profile.ActiveProject, "The ID of the project the device belongs to (defaults to active project)")

	return cmd
}

func deleteDevice(c *Command, ctx *Context) error {
	data := c.Data.(*deviceId)
	path := c.ApiPath + "/" + data.id
	_, err := ctx.Client.
		Delete(path).
		Expect(204).
		ProjectToken(ctx.Profile, data.projectId).
		Execute()

	if err == nil {
		fmt.Println("Device successfully deleted")
	}

	return err
}
<commit_msg>Use constants for device sort matching<commit_after>package command

import (
	"fmt"
	"sort"
)

type deviceData struct {
	ProjectId  uint64 `json:"project_id"`
	DeviceId   string `json:"device_id,omitempty"`
	DeviceName string `json:"device_name,omitempty"`
	DeviceType string `json:"device_type,omitempty"`
	Created    string `json:"created,omitempty"`
	// Private fields, not marshalled into JSON
	isUpdate bool
}

func (d *deviceData) IsValid() bool {
	if d.isUpdate {
		return len(d.DeviceId) > 0 &&
			(len(d.DeviceName) > 0 || len(d.DeviceType) > 0)
	}
	return d.ProjectId != 0
}

// deviceId is a simpler struct for calls that just consist of a device id
// and optionally projectId
type deviceId struct {
	id        string
	projectId uint64
}

func (d *deviceId) IsValid() bool {
	return len(d.id) > 0
}

// NewDevicesCommand returns the base 'device' command.
func NewDevicesCommand(ctx *Context) *Command {
	cmd := &Command{
		Name:  "device",
		Usage: "Commands for managing devices.",
		SubCommands: Mux{
			"create": newCreateDeviceCmd(ctx),
			"delete": newDeleteDeviceCmd(ctx),
			"get":    newGetDeviceCmd(ctx),
			"list":   newListDevicesCmd(ctx),
			"update": newUpdateDeviceCmd(ctx),
		},
	}
	cmd.NewFlagSet("iobeam device")

	return cmd
}

func newCreateOrUpdateDeviceCmd(ctx *Context, update bool, name string, action Action) *Command {
	device := deviceData{
		isUpdate: update,
	}

	cmd := &Command{
		Name:    name,
		ApiPath: "/v1/devices",
		Usage:   name + " device",
		Data:    &device,
		Action:  action,
	}
	flags := cmd.NewFlagSet("iobeam device " + name)
	var idDesc string
	if update {
		idDesc = "ID of the device to be updated"
	} else {
		idDesc = "Device ID, if omitted a random one will be assigned (must be > 16 chars)"
	}
	flags.StringVar(&device.DeviceId, "id", "", idDesc)
	flags.StringVar(&device.DeviceName, "name", "", "The device name")
	flags.StringVar(&device.DeviceType, "type", "", "The type of device")
	flags.Uint64Var(&device.ProjectId, "projectId", ctx.Profile.ActiveProject, "Project ID associated with the device (if omitted, defaults to active project).")

	return cmd
}

func newCreateDeviceCmd(ctx *Context) *Command {
	return newCreateOrUpdateDeviceCmd(ctx, false, "create", createDevice)
}

func newUpdateDeviceCmd(ctx *Context) *Command {
	return newCreateOrUpdateDeviceCmd(ctx, true, "update", updateDevice)
}

func createDevice(c *Command, ctx *Context) error {
	data := c.Data.(*deviceData)
	_, err := ctx.Client.
		Post(c.ApiPath).
		Expect(201).
		ProjectToken(ctx.Profile, data.ProjectId).
		Body(data).
		ResponseBody(c.Data).
		ResponseBodyHandler(func(body interface{}) error {

		device := body.(*deviceData)
		fmt.Println("New device created.")
		fmt.Printf("Device ID: %v\n", device.DeviceId)
		fmt.Printf("Device Name: %v\n", device.DeviceName)
		fmt.Println()

		return nil
	}).Execute()

	return err
}

func updateDevice(c *Command, ctx *Context) error {

	device := c.Data.(*deviceData)

	rsp, err := ctx.Client.
		Patch(c.ApiPath+"/"+device.DeviceId).
		Expect(200).
		ProjectToken(ctx.Profile, device.ProjectId).
		Body(c.Data).
		Execute()

	if err == nil {
		fmt.Println("Device successfully updated")
	} else if rsp.Http().StatusCode == 204 {
		fmt.Println("Device not modified")
		return nil
	}

	return err
}

func newGetDeviceCmd(ctx *Context) *Command {
	data := new(deviceId)

	cmd := &Command{
		Name:    "get",
		ApiPath: "/v1/devices",
		Usage:   "get device information",
		Data:    data,
		Action:  getDevice,
	}
	flags := cmd.NewFlagSet("iobeam device get")
	flags.StringVar(&data.id, "id", "", "Device ID to query (REQUIRED)")
	flags.Uint64Var(&data.projectId, "projectId", ctx.Profile.ActiveProject,
		"Project ID to get devices from (if omitted, defaults to active project)")

	return cmd
}

func getDevice(c *Command, ctx *Context) error {
	data := c.Data.(*deviceId)
	path := c.ApiPath + "/" + data.id

	device := new(deviceData)
	_, err := ctx.Client.
		Get(path).
		Expect(200).
		ProjectToken(ctx.Profile, data.projectId).
		ResponseBody(device).
		ResponseBodyHandler(func(body interface{}) error {
		device = body.(*deviceData)
		fmt.Printf("Device name: %v\n"+
			"Device ID: %v\n"+
			"Project ID: %v\n"+
			"Type: %v\n"+
			"Created: %v\n",
			device.DeviceName,
			device.DeviceId,
			device.ProjectId,
			device.DeviceType,
			device.Created)

		return nil
	}).Execute()

	return err
}

const (
	orderName        = "name"
	orderNameReverse = orderName + "-r"
	orderId          = "id"
	orderIdReverse   = orderId + "-r"
	orderDate        = "date"
	orderDateReverse = orderDate + "-r"
)

var orders = []string{orderName, orderNameReverse, orderId, orderIdReverse,
	orderDate, orderDateReverse}

type listData struct {
	projectId uint64
	order     string
}

func (d *listData) IsValid() bool {
	pidOk := d.projectId > 0
	orderOk := isInList(d.order, orders)
	return pidOk && orderOk
}

func newListDevicesCmd(ctx *Context) *Command {
	data := new(listData)

	cmd := &Command{
		Name:    "list",
		ApiPath: "/v1/devices",
		Usage:   "List devices for a given project.",
		Data:    data,
		Action:  listDevices,
	}
	flags := cmd.NewFlagSet("iobeam device list")
	flags.Uint64Var(&data.projectId, "projectId", ctx.Profile.ActiveProject,
		"Project ID to get devices from (if omitted, defaults to active project)")
	flags.StringVar(&data.order, "order", orderDate,
		"Sort order for results. Valid values: date(-r), id(-r), name(-r). Values ending with -r are reverse ordering.")

	return cmd
}

type deviceSort struct {
	items []deviceData
	order string
}

func (a deviceSort) Len() int      { return len(a.items) }
func (a deviceSort) Swap(i, j int) { a.items[i], a.items[j] = a.items[j], a.items[i] }
func (a deviceSort) Less(i, j int) bool {
	switch a.order {
	case orderName:
		return a.items[i].DeviceName < a.items[j].DeviceName
	case orderNameReverse:
		return a.items[j].DeviceName < a.items[i].DeviceName
	case orderId:
		return a.items[i].DeviceId < a.items[j].DeviceId
	case orderIdReverse:
		return a.items[i].DeviceId < a.items[j].DeviceId
	case orderDateReverse:
		return a.items[j].Created < a.items[i].Created
	case orderDate:
		fallthrough
	default:
		return a.items[i].Created < a.items[j].Created
	}
	return false
}

func listDevices(c *Command, ctx *Context) error {
	type deviceList struct {
		Devices []deviceData
	}

	cmdArgs := c.Data.(*listData)
	pid := cmdArgs.projectId

	_, err := ctx.Client.
		Get(c.ApiPath).
		ParamUint64("project_id", pid).
		Expect(200).
		ProjectToken(ctx.Profile, pid).
		ResponseBody(new(deviceList)).
		ResponseBodyHandler(func(body interface{}) error {

		list := body.(*deviceList)

		fmt.Printf("Devices in project %v\n", pid)
		fmt.Println("-----")

		sorted := &deviceSort{items: list.Devices, order: cmdArgs.order}
		sort.Sort(sorted)
		for _, device := range sorted.items {

			fmt.Printf("Name: %v\n"+
				"Device ID: %v\n"+
				"Type: %v\n"+
				"Created: %v\n\n",
				device.DeviceName,
				device.DeviceId,
				device.DeviceType,
				device.Created)
		}

		return nil
	}).Execute()

	return err
}

func newDeleteDeviceCmd(ctx *Context) *Command {
	data := new(deviceId)

	cmd := &Command{
		Name:    "delete",
		ApiPath: "/v1/devices",
		Usage:   "delete device",
		Data:    data,
		Action:  deleteDevice,
	}
	flags := cmd.NewFlagSet("iobeam device delete")
	flags.StringVar(&data.id, "id", "", "The ID of the device to delete (REQUIRED)")
	flags.Uint64Var(&data.projectId, "projectId", ctx.Profile.ActiveProject, "The ID of the project the device belongs to (defaults to active project)")

	return cmd
}

func deleteDevice(c *Command, ctx *Context) error {
	data := c.Data.(*deviceId)
	path := c.ApiPath + "/" + data.id
	_, err := ctx.Client.
		Delete(path).
		Expect(204).
		ProjectToken(ctx.Profile, data.projectId).
		Execute()

	if err == nil {
		fmt.Println("Device successfully deleted")
	}

	return err
}
<|endoftext|>


<commit_before>package command

import (
	"fmt"
	"sync"
	"time"

	"github.com/hashicorp/nomad/api"
	"github.com/hashicorp/nomad/nomad/structs"
	"github.com/mitchellh/cli"
)

const (
	// dateFmt is the format we use when printing the date in
	// status update messages during monitoring.
	dateFmt = "2006/01/02 15:04:05"
)

// monitor wraps an evaluation monitor and holds metadata and
// state information.
type monitor struct {
	ui     cli.Ui
	client *api.Client
	state  *evalState

	sync.Mutex
}

// newMonitor returns a new monitor. The returned monitor will
// write output information to the provided ui.
func newMonitor(ui cli.Ui, client *api.Client) *monitor {
	return &monitor{
		ui: &cli.PrefixedUi{
			InfoPrefix:   "==> ",
			OutputPrefix: "    ",
			ErrorPrefix:  "==> ",
			Ui:           ui,
		},
		client: client,
		state: &evalState{
			allocs: make(map[string]*allocState),
		},
	}
}

// output is used to write informational messages to the ui.
func (m *monitor) output(msg string) {
	m.ui.Output(fmt.Sprintf("%s %s", time.Now().Format(dateFmt), msg))
}

// evalState is used to store the current "state of the world"
// in the context of monitoring an evaluation.
type evalState struct {
	status string
	desc   string
	nodeID string
	allocs map[string]*allocState
	wait   time.Duration
	index  uint64
}

// allocState is used to track the state of an allocation
type allocState struct {
	id          string
	group       string
	node        string
	desired     string
	desiredDesc string
	client      string
	index       uint64
}

// update is used to update our monitor with new state. It can be
// called whether the passed information is new or not, and will
// only dump update messages when state changes.
func (m *monitor) update(eval *api.Evaluation, allocs []*api.AllocationListStub) {
	m.Lock()
	defer m.Unlock()

	existing := m.state

	// Create the new state
	update := &evalState{
		status: eval.Status,
		desc:   eval.StatusDescription,
		nodeID: eval.NodeID,
		allocs: make(map[string]*allocState),
		wait:   eval.Wait,
		index:  eval.CreateIndex,
	}
	for _, alloc := range allocs {
		update.allocs[alloc.ID] = &allocState{
			id:          alloc.ID,
			group:       alloc.TaskGroup,
			node:        alloc.NodeID,
			desired:     alloc.DesiredStatus,
			desiredDesc: alloc.DesiredDescription,
			client:      alloc.ClientStatus,
			index:       alloc.CreateIndex,
		}
	}
	defer func() { m.state = update }()

	// Check the allocations
	for allocID, alloc := range update.allocs {
		if existing, ok := existing.allocs[allocID]; !ok {
			switch {
			case alloc.desired == structs.AllocDesiredStatusFailed:
				// New allocs with desired state failed indicate
				// scheduling failure.
				m.output(fmt.Sprintf("Scheduling error for group %q (%s)",
					alloc.group, alloc.desiredDesc))

			case alloc.index < update.index:
				// New alloc with create index lower than the eval
				// create index indicates modification
				m.output(fmt.Sprintf(
					"Allocation %q modified: node %q, group %q",
					alloc.id, alloc.node, alloc.group))

			case alloc.desired == structs.AllocDesiredStatusRun:
				// New allocation with desired status running
				m.output(fmt.Sprintf(
					"Allocation %q created: node %q, group %q",
					alloc.id, alloc.node, alloc.group))
			}
		} else {
			switch {
			case existing.client != alloc.client:
				// Allocation status has changed
				m.output(fmt.Sprintf(
					"Allocation %q status changed: %q -> %q",
					alloc.id, existing.client, alloc.client))
			}
		}
	}

	// Check if the status changed
	if existing.status != update.status {
		m.output(fmt.Sprintf("Evaluation status changed: %q -> %q",
			existing.status, eval.Status))
	}

	// Check if the wait time is different
	if existing.wait == 0 && update.wait != 0 {
		m.output(fmt.Sprintf("Waiting %s before running eval",
			eval.Wait))
	}

	// Check if the nodeID changed
	if existing.nodeID == "" && update.nodeID != "" {
		m.output(fmt.Sprintf("Evaluation was assigned node ID %q",
			eval.NodeID))
	}
}

// monitor is used to start monitoring the given evaluation ID. It
// writes output directly to the monitor's ui, and returns the
// exit code for the command. The return code indicates monitoring
// success or failure ONLY. It is no indication of the outcome of
// the evaluation, since conflating these values obscures things.
func (m *monitor) monitor(evalID string) int {
	// Check if the eval has already completed and fast-path it.
	eval, _, err := m.client.Evaluations().Info(evalID, nil)
	if err != nil {
		m.ui.Error(fmt.Sprintf("Error reading evaluation: %s", err))
		return 1
	}
	switch eval.Status {
	case structs.EvalStatusComplete, structs.EvalStatusFailed:
		m.ui.Info(fmt.Sprintf("Evaluation %q already finished with status %q",
			evalID, eval.Status))
		return 0
	}

	m.ui.Info(fmt.Sprintf("Monitoring evaluation %q", evalID))
	for {
		// Query the evaluation
		eval, _, err := m.client.Evaluations().Info(evalID, nil)
		if err != nil {
			m.ui.Error(fmt.Sprintf("Error reading evaluation: %s", err))
			return 1
		}

		// Query the allocations associated with the evaluation
		allocs, _, err := m.client.Evaluations().Allocations(evalID, nil)
		if err != nil {
			m.ui.Error(fmt.Sprintf("Error reading allocations: %s", err))
			return 1
		}

		// Update the state
		m.update(eval, allocs)

		switch eval.Status {
		case structs.EvalStatusComplete, structs.EvalStatusFailed:
			m.ui.Info(fmt.Sprintf("Evaluation %q finished with status %q",
				eval.ID, eval.Status))
		default:
			// Wait for the next update
			time.Sleep(time.Second)
			continue
		}

		// Monitor the next eval, if it exists.
		if eval.NextEval != "" {
			mon := newMonitor(m.ui, m.client)
			return mon.monitor(eval.NextEval)
		}
		break
	}

	return 0
}
<commit_msg>command/monitor: cleanup<commit_after>package command

import (
	"fmt"
	"sync"
	"time"

	"github.com/hashicorp/nomad/api"
	"github.com/hashicorp/nomad/nomad/structs"
	"github.com/mitchellh/cli"
)

const (
	// updateWait is the amount of time to wait between status
	// updates. Because the monitor is poll-based, we use this
	// delay to avoid overwhelming the API server.
	updateWait = time.Second
)

// evalState is used to store the current "state of the world"
// in the context of monitoring an evaluation.
type evalState struct {
	status string
	desc   string
	nodeID string
	allocs map[string]*allocState
	wait   time.Duration
	index  uint64
}

// allocState is used to track the state of an allocation
type allocState struct {
	id          string
	group       string
	node        string
	desired     string
	desiredDesc string
	client      string
	index       uint64
}

// monitor wraps an evaluation monitor and holds metadata and
// state information.
type monitor struct {
	ui     cli.Ui
	client *api.Client
	state  *evalState

	sync.Mutex
}

// newMonitor returns a new monitor. The returned monitor will
// write output information to the provided ui.
func newMonitor(ui cli.Ui, client *api.Client) *monitor {
	mon := &monitor{
		ui: &cli.PrefixedUi{
			InfoPrefix:   "==> ",
			OutputPrefix: "    ",
			ErrorPrefix:  "==> ",
			Ui:           ui,
		},
		client: client,
	}
	mon.init()
	return mon
}

// init allocates substructures
func (m *monitor) init() {
	m.state = &evalState{
		allocs: make(map[string]*allocState),
	}
}

// update is used to update our monitor with new state. It can be
// called whether the passed information is new or not, and will
// only dump update messages when state changes.
func (m *monitor) update(eval *api.Evaluation, allocs []*api.AllocationListStub) {
	m.Lock()
	defer m.Unlock()

	existing := m.state

	// Create the new state
	update := &evalState{
		status: eval.Status,
		desc:   eval.StatusDescription,
		nodeID: eval.NodeID,
		allocs: make(map[string]*allocState),
		wait:   eval.Wait,
		index:  eval.CreateIndex,
	}
	for _, alloc := range allocs {
		update.allocs[alloc.ID] = &allocState{
			id:          alloc.ID,
			group:       alloc.TaskGroup,
			node:        alloc.NodeID,
			desired:     alloc.DesiredStatus,
			desiredDesc: alloc.DesiredDescription,
			client:      alloc.ClientStatus,
			index:       alloc.CreateIndex,
		}
	}
	defer func() { m.state = update }()

	// Check the allocations
	for allocID, alloc := range update.allocs {
		if existing, ok := existing.allocs[allocID]; !ok {
			switch {
			case alloc.desired == structs.AllocDesiredStatusFailed:
				// New allocs with desired state failed indicate
				// scheduling failure.
				m.ui.Output(fmt.Sprintf("Scheduling error for group %q (%s)",
					alloc.group, alloc.desiredDesc))

			case alloc.index < update.index:
				// New alloc with create index lower than the eval
				// create index indicates modification
				m.ui.Output(fmt.Sprintf(
					"Allocation %q modified: node %q, group %q",
					alloc.id, alloc.node, alloc.group))

			case alloc.desired == structs.AllocDesiredStatusRun:
				// New allocation with desired status running
				m.ui.Output(fmt.Sprintf(
					"Allocation %q created: node %q, group %q",
					alloc.id, alloc.node, alloc.group))
			}
		} else {
			switch {
			case existing.client != alloc.client:
				// Allocation status has changed
				m.ui.Output(fmt.Sprintf(
					"Allocation %q status changed: %q -> %q",
					alloc.id, existing.client, alloc.client))
			}
		}
	}

	// Check if the status changed
	if existing.status != update.status {
		m.ui.Output(fmt.Sprintf("Evaluation status changed: %q -> %q",
			existing.status, eval.Status))
	}

	// Check if the wait time is different
	if existing.wait == 0 && update.wait != 0 {
		m.ui.Output(fmt.Sprintf("Waiting %s before running eval",
			eval.Wait))
	}

	// Check if the nodeID changed
	if existing.nodeID == "" && update.nodeID != "" {
		m.ui.Output(fmt.Sprintf("Evaluation was assigned node ID %q",
			eval.NodeID))
	}
}

// monitor is used to start monitoring the given evaluation ID. It
// writes output directly to the monitor's ui, and returns the
// exit code for the command. The return code indicates monitoring
// success or failure ONLY. It is no indication of the outcome of
// the evaluation, since conflating these values obscures things.
func (m *monitor) monitor(evalID string) int {
	// Check if the eval has already completed and fast-path it.
	eval, _, err := m.client.Evaluations().Info(evalID, nil)
	if err != nil {
		m.ui.Error(fmt.Sprintf("Error reading evaluation: %s", err))
		return 1
	}
	switch eval.Status {
	case structs.EvalStatusComplete, structs.EvalStatusFailed:
		m.ui.Info(fmt.Sprintf("Evaluation %q finished with status %q",
			evalID, eval.Status))
		return 0
	}

	m.ui.Info(fmt.Sprintf("Monitoring evaluation %q", evalID))
	for {
		// Query the evaluation
		eval, _, err := m.client.Evaluations().Info(evalID, nil)
		if err != nil {
			m.ui.Error(fmt.Sprintf("Error reading evaluation: %s", err))
			return 1
		}

		// Query the allocations associated with the evaluation
		allocs, _, err := m.client.Evaluations().Allocations(evalID, nil)
		if err != nil {
			m.ui.Error(fmt.Sprintf("Error reading allocations: %s", err))
			return 1
		}

		// Update the state
		m.update(eval, allocs)

		switch eval.Status {
		case structs.EvalStatusComplete, structs.EvalStatusFailed:
			m.ui.Info(fmt.Sprintf("Evaluation %q finished with status %q",
				eval.ID, eval.Status))
		default:
			// Wait for the next update
			time.Sleep(updateWait)
			continue
		}

		// Monitor the next eval, if it exists.
		if eval.NextEval != "" {
			m.init()
			return m.monitor(eval.NextEval)
		}
		break
	}

	return 0
}
<|endoftext|>


<commit_before>package commands

import (
	"errors"

	"github.com/bndw/pick/utils"
	"github.com/spf13/cobra"
	"github.com/spf13/pflag"
)

func init() {
	rootCmd.AddCommand(&cobra.Command{
		Use:   "export",
		Short: "Export decrypted credentials in JSON format",
		Long:  "The export command is used to export decrypted credentials in JSON format.",
		Run: func(cmd *cobra.Command, args []string) {
			runCommand(Export, cmd, args)
		},
	})

}

func Export(args []string, flags *pflag.FlagSet) error {
	safe, err := newSafeLoader().Load()
	if err != nil {
		return err
	}

	accounts := safe.List()
	if len(accounts) < 1 {
		return errors.New("No accounts to export")
	}

	utils.PrettyPrint(accounts)
	return nil
}
<commit_msg>Add confirmation prompt before exporting<commit_after>package commands

import (
	"errors"

	"github.com/bndw/pick/utils"
	"github.com/spf13/cobra"
	"github.com/spf13/pflag"
)

func init() {
	rootCmd.AddCommand(&cobra.Command{
		Use:   "export",
		Short: "Export decrypted credentials in JSON format",
		Long:  "The export command is used to export decrypted credentials in JSON format.",
		Run: func(cmd *cobra.Command, args []string) {
			runCommand(Export, cmd, args)
		},
	})

}

func Export(args []string, flags *pflag.FlagSet) error {
	if !utils.Confirm("Do you really want to dump your whole pick safe?", false) {
		return errors.New("Aborted as requested")
	}

	safe, err := newSafeLoader().Load()
	if err != nil {
		return err
	}

	accounts := safe.List()
	if len(accounts) < 1 {
		return errors.New("No accounts to export")
	}

	utils.PrettyPrint(accounts)
	return nil
}
<|endoftext|>


<commit_before>// Copyright (c) 2016 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

package common

import (
	"regexp"
	"sync"

	"github.com/uber/cherami-thrift/.generated/go/metadata"
)

type (
	// UUIDResolver maps UUIDs to IP addrs and vice-versa
	UUIDResolver interface {
		// Lookup returns the host addr corresponding to the uuid
		Lookup(uuid string) (string, error)
		// Reverse lookup returns the uuid corresponding to the host addr
		ReverseLookup(addr string) (string, error)
		// Clears the in-memory cache
		ClearCache()
	}

	// resolverImpl is an implementation of UUIDResolver that uses
	// cassandra as the underlying mapping store.
	resolverImpl struct {
		rwLock  sync.RWMutex
		cache   map[string]string
		mClient metadata.TChanMetadataService
	}
)

// NewUUIDResolver returns an instance of UUIDResolver
// that can be used to resovle host uuids to ip:port addresses
// and vice-versa. The returned resolver uses Cassandra as the backend
// store for persisting the mapping.  The resolver also
// maintains an in-memory cache for fast-lookups. Thread safe.
func NewUUIDResolver(mClient metadata.TChanMetadataService) UUIDResolver {
	instance := &resolverImpl{
		mClient: mClient,
		cache:   make(map[string]string),
	}
	return instance
}

// Resolve resolves the given uuid to a hostid
// On success, returns the host:port for the uuid
// On failure, error is returned
func (r *resolverImpl) Lookup(uuid string) (string, error) {

	if addr, ok := r.cacheGet(uuid); ok {
		return addr, nil
	}

	addr, err := r.mClient.UUIDToHostAddr(nil, uuid)
	if err == nil && len(addr) > 0 {
		r.cachePut(uuid, addr)
		r.cachePut(addr, uuid)
		return addr, nil
	}

	return "", err
}

// Resolve resolves the given addr to a uuid
// On success, returns the uuid for the addr
// On failure, error is returned
func (r *resolverImpl) ReverseLookup(addr string) (string, error) {

	if uuid, ok := r.cacheGet(addr); ok {
		return uuid, nil
	}

	uuid, err := r.mClient.HostAddrToUUID(nil, addr)
	if err == nil && len(uuid) > 0 {
		r.cachePut(uuid, addr)
		r.cachePut(addr, uuid)
		return uuid, nil
	}

	return "", err
}

// Clear caches clears the in-memory resolver cache
func (r *resolverImpl) ClearCache() {
	r.rwLock.Lock()
	defer r.rwLock.Unlock()
	r.cache = make(map[string]string)
}

func (r *resolverImpl) cacheGet(key string) (string, bool) {
	r.rwLock.RLock()
	defer r.rwLock.RUnlock()
	v, ok := r.cache[key]
	return v, ok
}

func (r *resolverImpl) cachePut(key string, value string) {
	r.rwLock.Lock()
	defer r.rwLock.Unlock()
	r.cache[key] = value
}

// Paths and consumer groups are of the form "/foo.bar/bax". Although we don't
// currently support "folders", relative paths, or other filesystem-like
// operations, it is best to enforce this style of naming up front in case we would
// like to in the future. We don't allow our clients to encroach directly on the
// root, so that destinations and consumer groups are at least grouped under a team
// or project name. We also require these names to have one letter character at least,
// so names like /./. aren't valid

// PathRegex regex for destination path
var PathRegex = regexp.MustCompile(`^/[\w.]*[a-zA-Z][\w.]*/[\w.]*[a-zA-Z][\w.]*$`)

// PathDLQRegex regex for dlq destination path
var PathDLQRegex = regexp.MustCompile(`^/[\w.]*[a-zA-Z][\w.]*/[\w.]*[a-zA-Z][\w.]*.dlq$`)

// PathRegexAllowUUID For special destinations (e.g. Dead letter queues) we allow a string UUID as path
var PathRegexAllowUUID, _ = regexp.Compile(`^(/[\w.]*[a-zA-Z][\w.]*/[\w.]*[a-zA-Z][\w.]*|[[:xdigit:]]{8}-[[:xdigit:]]{4}-[[:xdigit:]]{4}-[[:xdigit:]]{4}-[[:xdigit:]]{12})$`)

// ConsumerGroupRegex regex for consumer group path
var ConsumerGroupRegex = PathRegex

// UUIDRegex regex for uuid
var UUIDRegex, _ = regexp.Compile(`^[[:xdigit:]]{8}-[[:xdigit:]]{4}-[[:xdigit:]]{4}-[[:xdigit:]]{4}-[[:xdigit:]]{12}$`)
<commit_msg>Fix path-regex to allow for number only strings (#216)<commit_after>// Copyright (c) 2016 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

package common

import (
	"regexp"
	"sync"

	"github.com/uber/cherami-thrift/.generated/go/metadata"
)

type (
	// UUIDResolver maps UUIDs to IP addrs and vice-versa
	UUIDResolver interface {
		// Lookup returns the host addr corresponding to the uuid
		Lookup(uuid string) (string, error)
		// Reverse lookup returns the uuid corresponding to the host addr
		ReverseLookup(addr string) (string, error)
		// Clears the in-memory cache
		ClearCache()
	}

	// resolverImpl is an implementation of UUIDResolver that uses
	// cassandra as the underlying mapping store.
	resolverImpl struct {
		rwLock  sync.RWMutex
		cache   map[string]string
		mClient metadata.TChanMetadataService
	}
)

// NewUUIDResolver returns an instance of UUIDResolver
// that can be used to resovle host uuids to ip:port addresses
// and vice-versa. The returned resolver uses Cassandra as the backend
// store for persisting the mapping.  The resolver also
// maintains an in-memory cache for fast-lookups. Thread safe.
func NewUUIDResolver(mClient metadata.TChanMetadataService) UUIDResolver {
	instance := &resolverImpl{
		mClient: mClient,
		cache:   make(map[string]string),
	}
	return instance
}

// Resolve resolves the given uuid to a hostid
// On success, returns the host:port for the uuid
// On failure, error is returned
func (r *resolverImpl) Lookup(uuid string) (string, error) {

	if addr, ok := r.cacheGet(uuid); ok {
		return addr, nil
	}

	addr, err := r.mClient.UUIDToHostAddr(nil, uuid)
	if err == nil && len(addr) > 0 {
		r.cachePut(uuid, addr)
		r.cachePut(addr, uuid)
		return addr, nil
	}

	return "", err
}

// Resolve resolves the given addr to a uuid
// On success, returns the uuid for the addr
// On failure, error is returned
func (r *resolverImpl) ReverseLookup(addr string) (string, error) {

	if uuid, ok := r.cacheGet(addr); ok {
		return uuid, nil
	}

	uuid, err := r.mClient.HostAddrToUUID(nil, addr)
	if err == nil && len(uuid) > 0 {
		r.cachePut(uuid, addr)
		r.cachePut(addr, uuid)
		return uuid, nil
	}

	return "", err
}

// Clear caches clears the in-memory resolver cache
func (r *resolverImpl) ClearCache() {
	r.rwLock.Lock()
	defer r.rwLock.Unlock()
	r.cache = make(map[string]string)
}

func (r *resolverImpl) cacheGet(key string) (string, bool) {
	r.rwLock.RLock()
	defer r.rwLock.RUnlock()
	v, ok := r.cache[key]
	return v, ok
}

func (r *resolverImpl) cachePut(key string, value string) {
	r.rwLock.Lock()
	defer r.rwLock.Unlock()
	r.cache[key] = value
}

// Paths and consumer groups are of the form "/foo.bar/bax". Although we don't
// currently support "folders", relative paths, or other filesystem-like
// operations, it is best to enforce this style of naming up front in case we would
// like to in the future. We don't allow our clients to encroach directly on the
// root, so that destinations and consumer groups are at least grouped under a team
// or project name. We also require these names to have one letter character at least,
// so names like /./. aren't valid

// PathRegex regex for destination path
var PathRegex = regexp.MustCompile(`^/[\w.]*[[:alnum:]][\w.]*/[\w.]*[[:alnum:]][\w.]*$`)

// PathDLQRegex regex for dlq destination path
var PathDLQRegex = regexp.MustCompile(`^/[\w.]*[[:alnum:]][\w.]*/[\w.]*[[:alnum:]][\w.]*.dlq$`)

// PathRegexAllowUUID For special destinations (e.g. Dead letter queues) we allow a string UUID as path
var PathRegexAllowUUID, _ = regexp.Compile(`^(/[\w.]*[[:alnum:]][\w.]*/[\w.]*[[:alnum:]][\w.]*|[[:xdigit:]]{8}-[[:xdigit:]]{4}-[[:xdigit:]]{4}-[[:xdigit:]]{4}-[[:xdigit:]]{12})$`)

// ConsumerGroupRegex regex for consumer group path
var ConsumerGroupRegex = PathRegex

// UUIDRegex regex for uuid
var UUIDRegex, _ = regexp.Compile(`^[[:xdigit:]]{8}-[[:xdigit:]]{4}-[[:xdigit:]]{4}-[[:xdigit:]]{4}-[[:xdigit:]]{12}$`)
<|endoftext|>


<commit_before>// +build linux

package daemon

import (
	"testing"

	"github.com/containerd/containerd/pkg/apparmor"
	containertypes "github.com/docker/docker/api/types/container"
	"github.com/docker/docker/container"
	"github.com/docker/docker/daemon/exec"
	specs "github.com/opencontainers/runtime-spec/specs-go"
	"gotest.tools/v3/assert"
)

func TestExecSetPlatformOpt(t *testing.T) {
	if !apparmor.HostSupports() {
		t.Skip("requires AppArmor to be enabled")
	}
	d := &Daemon{}
	c := &container.Container{AppArmorProfile: "my-custom-profile"}
	ec := &exec.Config{}
	p := &specs.Process{}

	err := d.execSetPlatformOpt(c, ec, p)
	assert.NilError(t, err)
	assert.Equal(t, "my-custom-profile", p.ApparmorProfile)
}

// TestExecSetPlatformOptPrivileged verifies that `docker exec --privileged`
// does not disable AppArmor profiles. Exec currently inherits the `Privileged`
// configuration of the container. See https://github.com/moby/moby/pull/31773#discussion_r105586900
//
// This behavior may change in future, but test for the behavior to prevent it
// from being changed accidentally.
func TestExecSetPlatformOptPrivileged(t *testing.T) {
	if !apparmor.HostSupports() {
		t.Skip("requires AppArmor to be enabled")
	}
	d := &Daemon{}
	c := &container.Container{AppArmorProfile: "my-custom-profile"}
	ec := &exec.Config{Privileged: true}
	p := &specs.Process{}

	err := d.execSetPlatformOpt(c, ec, p)
	assert.NilError(t, err)
	assert.Equal(t, "my-custom-profile", p.ApparmorProfile)

	c.HostConfig = &containertypes.HostConfig{Privileged: true}
	err = d.execSetPlatformOpt(c, ec, p)
	assert.NilError(t, err)
	assert.Equal(t, unconfinedAppArmorProfile, p.ApparmorProfile)
}
<commit_msg>Fix panic in TestExecSetPlatformOpt, TestExecSetPlatformOptPrivileged<commit_after>// +build linux

package daemon

import (
	"testing"

	"github.com/containerd/containerd/pkg/apparmor"
	containertypes "github.com/docker/docker/api/types/container"
	"github.com/docker/docker/container"
	"github.com/docker/docker/daemon/config"
	"github.com/docker/docker/daemon/exec"
	specs "github.com/opencontainers/runtime-spec/specs-go"
	"gotest.tools/v3/assert"
)

func TestExecSetPlatformOptAppArmor(t *testing.T) {
	appArmorEnabled := apparmor.HostSupports()

	tests := []struct {
		doc             string
		privileged      bool
		appArmorProfile string
		expectedProfile string
	}{
		{
			doc:             "default options",
			expectedProfile: defaultAppArmorProfile,
		},
		{
			doc:             "custom profile",
			appArmorProfile: "my-custom-profile",
			expectedProfile: "my-custom-profile",
		},
		{
			doc:             "privileged container",
			privileged:      true,
			expectedProfile: unconfinedAppArmorProfile,
		},
		{
			doc:             "privileged container, custom profile",
			privileged:      true,
			appArmorProfile: "my-custom-profile",
			expectedProfile: "my-custom-profile",
			// FIXME: execSetPlatformOpts prefers custom profiles over "privileged",
			//        which looks like a bug (--privileged on the container should
			//        disable apparmor, seccomp, and selinux); see the code at:
			//        https://github.com/moby/moby/blob/46cdcd206c56172b95ba5c77b827a722dab426c5/daemon/exec_linux.go#L32-L40
			// expectedProfile: unconfinedAppArmorProfile,
		},
	}

	d := &Daemon{configStore: &config.Config{}}

	// Currently, `docker exec --privileged` inherits the Privileged configuration
	// of the container, and does not disable AppArmor.
	// See https://github.com/moby/moby/pull/31773#discussion_r105586900
	//
	// This behavior may change in future, but to verify the current behavior,
	// we run the test both with "exec" and "exec --privileged", which should
	// both give the same result.
	for _, execPrivileged := range []bool{false, true} {
		for _, tc := range tests {
			tc := tc
			doc := tc.doc
			if !appArmorEnabled {
				// no profile should be set if the host does not support AppArmor
				doc += " (apparmor disabled)"
				tc.expectedProfile = ""
			}
			if execPrivileged {
				doc += " (exec privileged)"
			}
			t.Run(doc, func(t *testing.T) {
				c := &container.Container{
					AppArmorProfile: tc.appArmorProfile,
					HostConfig: &containertypes.HostConfig{
						Privileged: tc.privileged,
					},
				}
				ec := &exec.Config{Privileged: execPrivileged}
				p := &specs.Process{}

				err := d.execSetPlatformOpt(c, ec, p)
				assert.NilError(t, err)
				assert.Equal(t, p.ApparmorProfile, tc.expectedProfile)
			})
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"errors"
	"fmt"
	exif "github.com/garyhouston/exif44"
	jseg "github.com/garyhouston/jpegsegs"
	tiff "github.com/garyhouston/tiff66"
	"io"
	"io/ioutil"
	"log"
	"os"
)

func processTIFF(infile io.Reader, outfile io.Writer) error {
	buf, err := ioutil.ReadAll(infile)
	if err != nil {
		return err
	}
	validTIFF, order, ifdPos := tiff.GetHeader(buf)
	if !validTIFF {
		return errors.New("processTIFF: invalid TIFF header")
	}
	root, err := tiff.GetIFDTree(buf, order, ifdPos, tiff.TIFFSpace)
	if err != nil {
		return err
	}
	root.Fix()
	fileSize := tiff.HeaderSize + root.TreeSize()
	out := make([]byte, fileSize)
	tiff.PutHeader(out, order, tiff.HeaderSize)
	_, err = root.PutIFDTree(out, tiff.HeaderSize)
	if err != nil {
		return err
	}
	_, err = outfile.Write(out)
	return err
}

func processJPEG(infile io.Reader, outfile io.Writer) error {
	scanner, err := jseg.NewScanner(infile)
	if err != nil {
		return err
	}
	dumper, err := jseg.NewDumper(outfile)
	if err != nil {
		return err
	}
	for {
		marker, buf, err := scanner.Scan()
		if err != nil {
			return err
		}
		if marker == jseg.SOS {
			// Start of scan data, no more metadata expected.
			if err := dumper.Dump(marker, nil); err != nil {
				return err
			}
			err := dumper.Copy(scanner)
			return err
		}
		if marker == jseg.APP0+1 {
			isExif, next := exif.GetHeader(buf)
			if isExif {
				tree, err := exif.GetExifTree(buf[next:])
				if err != nil {
					return err
				}
				tree.Tree.Fix()
				app1 := make([]byte, exif.HeaderSize+tree.TreeSize())
				next := exif.PutHeader(app1)
				_, err = tree.Put(app1[next:])
				if err != nil {
					return err
				}
				buf = app1
			}

		}
		if err := dumper.Dump(marker, buf); err != nil {
			return err
		}
	}
}

const (
	TIFFFile = 1
	JPEGFile = 2
)

// Determine if file is TIFF, JPEG or neither (error)
func fileType(file io.Reader) (int, error) {
	buf := make([]byte, tiff.HeaderSize)
	if _, err := io.ReadFull(file, buf); err != nil {
		return 0, err
	}
	if jseg.IsJPEGHeader(buf) {
		return JPEGFile, nil
	}
	if validTIFF, _, _ := tiff.GetHeader(buf); validTIFF {
		return TIFFFile, nil
	}
	return 0, errors.New("File doesn't have a TIFF or JPEG header")
}

// Decode a TIFF file, or the Exif segment in a JPEG file, then re-encode
// it and write to a new file.
func main() {
	if len(os.Args) != 3 {
		fmt.Printf("Usage: %s file outfile\n", os.Args[0])
		return
	}
	infile, err := os.Open(os.Args[1])
	if err != nil {
		log.Fatal(err)
	}
	defer infile.Close()
	fileType, err := fileType(infile)
	if err != nil {
		log.Fatal(err)
	}
	if _, err := infile.Seek(0, 0); err != nil {
		log.Fatal(err)
	}
	outfile, err := os.Create(os.Args[2])
	if err != nil {
		log.Fatal(err)
	}
	defer outfile.Close()
	if fileType == TIFFFile {
		err = processTIFF(infile, outfile)
		if err != nil {
			log.Fatal(err)
		}
	} else {
		err = processJPEG(infile, outfile)
		if err != nil {
			log.Fatal(err)
		}
	}
}
<commit_msg>adjust for changes to lib<commit_after>package main

import (
	"errors"
	"fmt"
	exif "github.com/garyhouston/exif44"
	jseg "github.com/garyhouston/jpegsegs"
	tiff "github.com/garyhouston/tiff66"
	"io"
	"io/ioutil"
	"log"
	"os"
)

func processTIFF(infile io.Reader, outfile io.Writer) error {
	buf, err := ioutil.ReadAll(infile)
	if err != nil {
		return err
	}
	validTIFF, order, ifdPos := tiff.GetHeader(buf)
	if !validTIFF {
		return errors.New("processTIFF: invalid TIFF header")
	}
	root, err := tiff.GetIFDTree(buf, order, ifdPos, tiff.TIFFSpace)
	if err != nil {
		return err
	}
	root.Fix()
	fileSize := tiff.HeaderSize + root.TreeSize()
	out := make([]byte, fileSize)
	tiff.PutHeader(out, order, tiff.HeaderSize)
	_, err = root.PutIFDTree(out, tiff.HeaderSize)
	if err != nil {
		return err
	}
	_, err = outfile.Write(out)
	return err
}

func processJPEG(infile io.Reader, outfile io.Writer) error {
	scanner, err := jseg.NewScanner(infile)
	if err != nil {
		return err
	}
	dumper, err := jseg.NewDumper(outfile)
	if err != nil {
		return err
	}
	for {
		marker, buf, err := scanner.Scan()
		if err != nil {
			return err
		}
		if marker == jseg.SOS {
			// Start of scan data, no more metadata expected.
			if err := dumper.Dump(marker, nil); err != nil {
				return err
			}
			err := dumper.Copy(scanner)
			return err
		}
		if marker == jseg.APP0+1 {
			isExif, next := exif.GetHeader(buf)
			if isExif {
				tree, err := exif.GetExifTree(buf[next:])
				if err != nil {
					return err
				}
				tree.TIFF.Fix()
				app1 := make([]byte, exif.HeaderSize+tree.TreeSize())
				next := exif.PutHeader(app1)
				_, err = tree.Put(app1[next:])
				if err != nil {
					return err
				}
				buf = app1
			}

		}
		if err := dumper.Dump(marker, buf); err != nil {
			return err
		}
	}
}

const (
	TIFFFile = 1
	JPEGFile = 2
)

// Determine if file is TIFF, JPEG or neither (error)
func fileType(file io.Reader) (int, error) {
	buf := make([]byte, tiff.HeaderSize)
	if _, err := io.ReadFull(file, buf); err != nil {
		return 0, err
	}
	if jseg.IsJPEGHeader(buf) {
		return JPEGFile, nil
	}
	if validTIFF, _, _ := tiff.GetHeader(buf); validTIFF {
		return TIFFFile, nil
	}
	return 0, errors.New("File doesn't have a TIFF or JPEG header")
}

// Decode a TIFF file, or the Exif segment in a JPEG file, then re-encode
// it and write to a new file.
func main() {
	if len(os.Args) != 3 {
		fmt.Printf("Usage: %s file outfile\n", os.Args[0])
		return
	}
	infile, err := os.Open(os.Args[1])
	if err != nil {
		log.Fatal(err)
	}
	defer infile.Close()
	fileType, err := fileType(infile)
	if err != nil {
		log.Fatal(err)
	}
	if _, err := infile.Seek(0, 0); err != nil {
		log.Fatal(err)
	}
	outfile, err := os.Create(os.Args[2])
	if err != nil {
		log.Fatal(err)
	}
	defer outfile.Close()
	if fileType == TIFFFile {
		err = processTIFF(infile, outfile)
		if err != nil {
			log.Fatal(err)
		}
	} else {
		err = processJPEG(infile, outfile)
		if err != nil {
			log.Fatal(err)
		}
	}
}
<|endoftext|>


<commit_before>package service

import (
	"sync"

	"github.com/slok/ragnarok/master/model"
)

// FailureRepository is the way the master keeps track of the failures.
type FailureRepository interface {
	// Store adds a failure to the registry.
	Store(failure *model.Failure) error

	// Delete deletes a failure from the registry.
	Delete(id string)

	// Get gets a failure from the registry.
	Get(id string) (*model.Failure, bool)

	// GetAll gets all the failures from the registry.
	GetAll() map[string]*model.Failure

	// GetAllByNode gets all the failures of a node from the registry.
	GetAllByNode(nodeID string) map[string]*model.Failure
}

// MemFailureRepository is a represententation of the failure regsitry using a memory map.
type MemFailureRepository struct {
	reg       map[string]*model.Failure
	regByNode map[string]map[string]*model.Failure
	sync.Mutex
}

// NewMemFailureRepository returns a new MemFailureRepository
func NewMemFailureRepository() *MemFailureRepository {
	return &MemFailureRepository{
		reg:       map[string]*model.Failure{},
		regByNode: map[string]map[string]*model.Failure{},
	}
}

// Store satisfies FailureRepository interface.
func (m *MemFailureRepository) Store(failure *model.Failure) error {
	m.Lock()
	defer m.Unlock()
	m.reg[failure.ID] = failure
	if _, ok := m.regByNode[failure.NodeID]; !ok {
		m.regByNode[failure.NodeID] = map[string]*model.Failure{}
	}
	m.regByNode[failure.NodeID][failure.ID] = failure

	return nil
}

// Delete satisfies FailureRepository interface.
func (m *MemFailureRepository) Delete(id string) {
	m.Lock()
	defer m.Unlock()

	f, ok := m.reg[id]
	if !ok {
		return
	}

	delete(m.reg, id)
	delete(m.regByNode[f.NodeID], id)
}

// Get satisfies FailureRepository interface.
func (m *MemFailureRepository) Get(id string) (*model.Failure, bool) {
	m.Lock()
	defer m.Unlock()

	f, ok := m.reg[id]

	return f, ok
}

// GetAll satisfies FailureRepository interface.
func (m *MemFailureRepository) GetAll() map[string]*model.Failure {
	m.Lock()
	defer m.Unlock()

	return m.reg
}

// GetAllByNode satisfies FailureRepository interface.
func (m *MemFailureRepository) GetAllByNode(nodeID string) map[string]*model.Failure {
	m.Lock()
	defer m.Unlock()
	reg, ok := m.regByNode[nodeID]
	if !ok {
		reg = make(map[string]*model.Failure)
	}
	return reg
}
<commit_msg>Return slice instead of map on failure list getters<commit_after>package service

import (
	"sync"

	"github.com/slok/ragnarok/master/model"
)

// FailureRepository is the way the master keeps track of the failures.
type FailureRepository interface {
	// Store adds a failure to the registry.
	Store(failure *model.Failure) error

	// Delete deletes a failure from the registry.
	Delete(id string)

	// Get gets a failure from the registry.
	Get(id string) (*model.Failure, bool)

	// GetAll gets all the failures from the registry.
	GetAll() []*model.Failure

	// GetAllByNode gets all the failures of a node from the registry.
	GetAllByNode(nodeID string) []*model.Failure
}

// MemFailureRepository is a represententation of the failure regsitry using a memory map.
type MemFailureRepository struct {
	reg       map[string]*model.Failure
	regByNode map[string]map[string]*model.Failure
	sync.Mutex
}

// NewMemFailureRepository returns a new MemFailureRepository
func NewMemFailureRepository() *MemFailureRepository {
	return &MemFailureRepository{
		reg:       map[string]*model.Failure{},
		regByNode: map[string]map[string]*model.Failure{},
	}
}

// Store satisfies FailureRepository interface.
func (m *MemFailureRepository) Store(failure *model.Failure) error {
	m.Lock()
	defer m.Unlock()
	m.reg[failure.ID] = failure
	if _, ok := m.regByNode[failure.NodeID]; !ok {
		m.regByNode[failure.NodeID] = map[string]*model.Failure{}
	}
	m.regByNode[failure.NodeID][failure.ID] = failure

	return nil
}

// Delete satisfies FailureRepository interface.
func (m *MemFailureRepository) Delete(id string) {
	m.Lock()
	defer m.Unlock()

	f, ok := m.reg[id]
	if !ok {
		return
	}

	delete(m.reg, id)
	delete(m.regByNode[f.NodeID], id)
}

// Get satisfies FailureRepository interface.
func (m *MemFailureRepository) Get(id string) (*model.Failure, bool) {
	m.Lock()
	defer m.Unlock()

	f, ok := m.reg[id]

	return f, ok
}

// GetAll satisfies FailureRepository interface.
func (m *MemFailureRepository) GetAll() []*model.Failure {
	m.Lock()
	defer m.Unlock()
	res := []*model.Failure{}
	for _, f := range m.reg {
		res = append(res, f)
	}
	return res
}

// GetAllByNode satisfies FailureRepository interface.
func (m *MemFailureRepository) GetAllByNode(nodeID string) []*model.Failure {
	m.Lock()
	defer m.Unlock()
	res := []*model.Failure{}
	tmpReg, ok := m.regByNode[nodeID]
	if ok {
		for _, f := range tmpReg {
			res = append(res, f)
		}
	}
	return res
}
<|endoftext|>


<commit_before>package molecule

import (
	"sync"

	cmn "github.com/RxnWeaver/rxnweaver/common"
)

// nextMolIdHolder is a synchronised struct used to assign a
// globally-unique ID to each molecule.
type nextMolIdHolder struct {
	mu     sync.Mutex
	nextId uint32
}

var nextMolId nextMolIdHolder

func nextMoleculeId() uint32 {
	nextMolId.mu.Lock()
	defer nextMolId.mu.Unlock()

	nextMolId.nextId++
	return nextMolId.nextId
}

// Attribute represents a (key, value) pair that annotates this
// molecule.
//
// A given molecule can have zero or more such attributes.
type Attribute struct {
	name  string
	value string
}

// Molecule represents a chemical molecule.
//
// It holds information concerning its atom, bonds, rings, etc.  Note
// that a molecule is expected to be a single connected component.
type Molecule struct {
	id uint32 // The globally-unique ID of this molecule.

	atoms       []*_Atom       // List of atoms in this molecule.
	bonds       []*_Bond       // List of bonds in this molecule.
	rings       []*_Ring       // List of rings in this molecule.
	ringSystems []*_RingSystem // List of ring systems in this molecule.

	nextAtomIid      uint16 // Running number for atom input IDs.
	nextBondId       uint16 // Running number for bond IDs.
	nextRingId       uint8  // Running number for ring IDs.
	nextRingSystemId uint8  // Running number for ring system IDs.

	vendor           string // Optional string identifying the supplier.
	vendorMoleculeId string // Optional supplier-specified ID.

	attributes []Attribute // Optional list of annotations.

	dists [][]int // Matrix of pair-wise distances between atoms.
	paths [][]int // Lists of pair-wise paths between atoms.
}

// New creates and initialises a molecule.
func New() *Molecule {
	mol := new(Molecule)
	mol.id = nextMoleculeId()

	mol.atoms = make([]*_Atom, 0, cmn.ListSizeLarge)
	mol.bonds = make([]*_Bond, 0, cmn.ListSizeLarge)
	mol.rings = make([]*_Ring, 0, cmn.ListSizeSmall)
	mol.ringSystems = make([]*_RingSystem, 0, cmn.ListSizeSmall)

	mol.nextAtomIid = 1
	mol.nextBondId = 1
	mol.nextRingId = 1
	mol.nextRingSystemId = 1

	mol.attributes = make([]Attribute, 0, cmn.ListSizeTiny)

	return mol
}

// NewAtomBuilder answers a new atom builder.
func (m *Molecule) NewAtomBuilder() *AtomBuilder {
	return &AtomBuilder{m, nil}
}

// Id answers the globally-unique ID of this molecule.
func (m *Molecule) Id() uint32 {
	return m.id
}

// atomWithIid answers the atom for the given input ID, if found.
// Answers `nil` otherwise.
func (m *Molecule) atomWithIid(id uint16) *_Atom {
	for _, a := range m.atoms {
		if a.iId == id {
			return a
		}
	}

	return nil
}

// atomWithNid answers the atom for the given normalised ID, if found.
// Answers `nil` otherwise.
func (m *Molecule) atomWithNid(id uint16) *_Atom {
	for _, a := range m.atoms {
		if a.nId == id {
			return a
		}
	}

	return nil
}

// bondWithId answers the bond for the given ID, if found.  Answers
// `nil` otherwise.
func (m *Molecule) bondWithId(id uint16) *_Bond {
	for _, b := range m.bonds {
		if b.id == id {
			return b
		}
	}

	return nil
}

// ringWithId answers the ring for the given ID, if found.  Answers
// `nil` otherwise.
func (m *Molecule) ringWithId(id uint8) *_Ring {
	for _, r := range m.rings {
		if r.id == id {
			return r
		}
	}

	return nil
}

// bondBetween answers the bond between the two given atoms, if one
// such exists.  Answers `nil` otherwise.
//
// Note that the two given atoms are represented by their input IDs,
// NOT normalised IDs.
func (m *Molecule) bondBetween(a1id, a2id uint16) *_Bond {
	for _, b := range m.bonds {
		if (b.a1 == a1id && b.a2 == a2id) || (b.a2 == a1id && b.a1 == a2id) {
			return b
		}
	}

	return nil
}

// bondCount answers the total number of bonds of the given type in
// this molecule.
func (m *Molecule) bondCount(typ cmn.BondType) int {
	c := 0
	for _, b := range m.bonds {
		if b.bType == typ {
			c++
		}
	}

	return c
}

// singleBondCount answers the total number of single bonds in this
// molecule.
func (m *Molecule) singleBondCount() int {
	return m.bondCount(cmn.BondTypeSingle)
}

// doubleBondCount answers the total number of double bonds in this
// molecule.
func (m *Molecule) doubleBondCount() int {
	return m.bondCount(cmn.BondTypeDouble)
}

// tripleBondCount answers the total number of triple bonds in this
// molecule.
func (m *Molecule) tripleBondCount() int {
	return m.bondCount(cmn.BondTypeTriple)
}

// aromaticRingCount answers the number of aromatic rings in this
// molecule.
func (m *Molecule) aromaticRingCount() int {
	c := 0
	for _, r := range m.rings {
		if r.isAro {
			c++
		}
	}

	return c
}

// aromaticRingSystemCount answers the number of aromatic ring systems
// in this molecule.
func (m *Molecule) aromaticRingSystemCount() int {
	c := 0
	for _, rs := range m.ringSystems {
		if rs.isAro {
			c++
		}
	}

	return c
}
<commit_msg>Add a method to `Molecule` to create a new bond builder<commit_after>package molecule

import (
	"sync"

	cmn "github.com/RxnWeaver/rxnweaver/common"
)

// nextMolIdHolder is a synchronised struct used to assign a
// globally-unique ID to each molecule.
type nextMolIdHolder struct {
	mu     sync.Mutex
	nextId uint32
}

var nextMolId nextMolIdHolder

func nextMoleculeId() uint32 {
	nextMolId.mu.Lock()
	defer nextMolId.mu.Unlock()

	nextMolId.nextId++
	return nextMolId.nextId
}

// Attribute represents a (key, value) pair that annotates this
// molecule.
//
// A given molecule can have zero or more such attributes.
type Attribute struct {
	name  string
	value string
}

// Molecule represents a chemical molecule.
//
// It holds information concerning its atom, bonds, rings, etc.  Note
// that a molecule is expected to be a single connected component.
type Molecule struct {
	id uint32 // The globally-unique ID of this molecule.

	atoms       []*_Atom       // List of atoms in this molecule.
	bonds       []*_Bond       // List of bonds in this molecule.
	rings       []*_Ring       // List of rings in this molecule.
	ringSystems []*_RingSystem // List of ring systems in this molecule.

	nextAtomIid      uint16 // Running number for atom input IDs.
	nextBondId       uint16 // Running number for bond IDs.
	nextRingId       uint8  // Running number for ring IDs.
	nextRingSystemId uint8  // Running number for ring system IDs.

	vendor           string // Optional string identifying the supplier.
	vendorMoleculeId string // Optional supplier-specified ID.

	attributes []Attribute // Optional list of annotations.

	dists [][]int // Matrix of pair-wise distances between atoms.
	paths [][]int // Lists of pair-wise paths between atoms.
}

// New creates and initialises a molecule.
func New() *Molecule {
	mol := new(Molecule)
	mol.id = nextMoleculeId()

	mol.atoms = make([]*_Atom, 0, cmn.ListSizeLarge)
	mol.bonds = make([]*_Bond, 0, cmn.ListSizeLarge)
	mol.rings = make([]*_Ring, 0, cmn.ListSizeSmall)
	mol.ringSystems = make([]*_RingSystem, 0, cmn.ListSizeSmall)

	mol.nextAtomIid = 1
	mol.nextBondId = 1
	mol.nextRingId = 1
	mol.nextRingSystemId = 1

	mol.attributes = make([]Attribute, 0, cmn.ListSizeTiny)

	return mol
}

// NewAtomBuilder answers a new atom builder.
func (m *Molecule) NewAtomBuilder() *AtomBuilder {
	return &AtomBuilder{m, nil}
}

// NewBondBuilder answers a new bond builder.
func (m *Molecule) NewBondBuilder() *BondBuilder {
	return &BondBuilder{m, nil}
}

// Id answers the globally-unique ID of this molecule.
func (m *Molecule) Id() uint32 {
	return m.id
}

// atomWithIid answers the atom for the given input ID, if found.
// Answers `nil` otherwise.
func (m *Molecule) atomWithIid(id uint16) *_Atom {
	for _, a := range m.atoms {
		if a.iId == id {
			return a
		}
	}

	return nil
}

// atomWithNid answers the atom for the given normalised ID, if found.
// Answers `nil` otherwise.
func (m *Molecule) atomWithNid(id uint16) *_Atom {
	for _, a := range m.atoms {
		if a.nId == id {
			return a
		}
	}

	return nil
}

// bondWithId answers the bond for the given ID, if found.  Answers
// `nil` otherwise.
func (m *Molecule) bondWithId(id uint16) *_Bond {
	for _, b := range m.bonds {
		if b.id == id {
			return b
		}
	}

	return nil
}

// ringWithId answers the ring for the given ID, if found.  Answers
// `nil` otherwise.
func (m *Molecule) ringWithId(id uint8) *_Ring {
	for _, r := range m.rings {
		if r.id == id {
			return r
		}
	}

	return nil
}

// bondBetween answers the bond between the two given atoms, if one
// such exists.  Answers `nil` otherwise.
//
// Note that the two given atoms are represented by their input IDs,
// NOT normalised IDs.
func (m *Molecule) bondBetween(a1id, a2id uint16) *_Bond {
	for _, b := range m.bonds {
		if (b.a1 == a1id && b.a2 == a2id) || (b.a2 == a1id && b.a1 == a2id) {
			return b
		}
	}

	return nil
}

// bondCount answers the total number of bonds of the given type in
// this molecule.
func (m *Molecule) bondCount(typ cmn.BondType) int {
	c := 0
	for _, b := range m.bonds {
		if b.bType == typ {
			c++
		}
	}

	return c
}

// singleBondCount answers the total number of single bonds in this
// molecule.
func (m *Molecule) singleBondCount() int {
	return m.bondCount(cmn.BondTypeSingle)
}

// doubleBondCount answers the total number of double bonds in this
// molecule.
func (m *Molecule) doubleBondCount() int {
	return m.bondCount(cmn.BondTypeDouble)
}

// tripleBondCount answers the total number of triple bonds in this
// molecule.
func (m *Molecule) tripleBondCount() int {
	return m.bondCount(cmn.BondTypeTriple)
}

// aromaticRingCount answers the number of aromatic rings in this
// molecule.
func (m *Molecule) aromaticRingCount() int {
	c := 0
	for _, r := range m.rings {
		if r.isAro {
			c++
		}
	}

	return c
}

// aromaticRingSystemCount answers the number of aromatic ring systems
// in this molecule.
func (m *Molecule) aromaticRingSystemCount() int {
	c := 0
	for _, rs := range m.ringSystems {
		if rs.isAro {
			c++
		}
	}

	return c
}
<|endoftext|>


<commit_before>// Copyright 2015 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package featuretests

import (
	"flag"
	"testing"

	gc "gopkg.in/check.v1"

	coretesting "github.com/juju/juju/testing"
)

var runFeatureTests = flag.Bool("featuretests", true, "Run long-running feature tests.")

func init() {

	flag.Parse()

	if *runFeatureTests == false {
		return
	}
	// Initialize all suites here.
	gc.Suite(&cmdJujuSuite{})
	gc.Suite(&annotationsSuite{})
	gc.Suite(&apiEnvironmentSuite{})
	gc.Suite(&blockSuite{})
	gc.Suite(&apiCharmsSuite{})
	gc.Suite(&cmdEnvironmentSuite{})
	gc.Suite(&cmdStorageSuite{})
	gc.Suite(&cmdSystemSuite{})
	gc.Suite(&dblogSuite{})
	gc.Suite(&cloudImageMetadataSuite{})
	gc.Suite(&cmdSpaceSuite{})
	gc.Suite(&cmdSubnetSuite{})
	gc.Suite(&dumpLogsCommandSuite{})
}

func Test(t *testing.T) {
	coretesting.MgoTestPackage(t)
}
<commit_msg>featuretests: disable test under -race<commit_after>// Copyright 2015 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package featuretests

import (
	"flag"
	stdtesting "testing"

	"github.com/juju/testing"
	gc "gopkg.in/check.v1"

	coretesting "github.com/juju/juju/testing"
)

var runFeatureTests = flag.Bool("featuretests", true, "Run long-running feature tests.")

func init() {

	flag.Parse()

	if *runFeatureTests == false {
		return
	}
	// Initialize all suites here.
	gc.Suite(&cmdJujuSuite{})
	gc.Suite(&annotationsSuite{})
	gc.Suite(&apiEnvironmentSuite{})
	gc.Suite(&blockSuite{})
	gc.Suite(&apiCharmsSuite{})
	gc.Suite(&cmdEnvironmentSuite{})
	gc.Suite(&cmdStorageSuite{})
	gc.Suite(&cmdSystemSuite{})
	gc.Suite(&dblogSuite{})
	gc.Suite(&cloudImageMetadataSuite{})
	gc.Suite(&cmdSpaceSuite{})
	gc.Suite(&cmdSubnetSuite{})
	gc.Suite(&dumpLogsCommandSuite{})
}

func TestPackage(t *stdtesting.T) {
	if testing.RaceEnabled {
		t.Skip("skipping package under -race, see LP 1519183")
	}
	coretesting.MgoTestPackage(t)
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2016, 1&1 Internet SE
 * Written by Jörg Pernfuß <joerg.pernfuss@1und1.de>
 * All rights reserved.
 */

package main

import (
	"encoding/json"
	"fmt"
	"net/http"
	"net/url"
	"path/filepath"
	"time"

	"gopkg.in/resty.v0"

	"github.com/asaskevich/govalidator"
	"github.com/julienschmidt/httprouter"
)

type NotifyMessage struct {
	Uuid string `json:"uuid" valid:"uuidv4"`
	Path string `json:"path" valid:"abspath"`
}

func FetchConfigurationItems(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
	var (
		dec    *json.Decoder
		msg    NotifyMessage
		err    error
		soma   *url.URL
		client *resty.Client
		resp   *resty.Response
		res    proto.Result
	)
	dec = json.NewDecoder(r.Body)
	if err = dec.Decode(msg); err != nil {
		dispatchBadRequest(&w, err.Error())
		return
	}
	govalidator.SetFieldsRequiredByDefault(true)
	govalidator.TagMap["abspath"] = govalidator.Validator(func(str string) bool {
		return filepath.IsAbs(str)
	})
	if ok, err := govalidator.ValidateStruct(msg); !ok {
		dispatchBadRequest(&w, err.Error())
		return
	}

	soma, _ = url.Parse(Eye.Soma.url.String())
	soma.Path = fmt.Sprintf("%s/%s", msg.Path, msg.Uuid)
	client = resty.New().SetTimeout(500 * time.Millisecond)
	if resp, err = client.R().Get(soma.String()); err != nil || resp.StatusCode() > 299 {
		if err == nil {
			err = fmt.Errorf(resp.Status())
		}
		dispatchPrecondition(&w, err.Error())
		return
	}
	if err = json.Unmarshal(resp.Body(), res); err != nil {
		dispatchUnprocessable(&w, err.Error())
		return
	}
	if res.StatusCode != 200 {
		dispatchGone(&w, err.Error())
		return
	}
	if len(*res.Deployments) != 1 {
		dispatchPrecondition(&w, err.Error())
		return
	}
	if err = CheckUpdateOrInsertOrDelete(&(*res.Deployments)[0]); err != nil {
		dispatchInternalServerError(&w, err.Error())
		return
	}
	dispatchNoContent(&w)
}

// vim: ts=4 sw=4 sts=4 noet fenc=utf-8 ffs=unix
<commit_msg>FIX: json.Decode target must be pointer value<commit_after>/*
 * Copyright (c) 2016, 1&1 Internet SE
 * Written by Jörg Pernfuß <joerg.pernfuss@1und1.de>
 * All rights reserved.
 */

package main

import (
	"encoding/json"
	"fmt"
	"net/http"
	"net/url"
	"path/filepath"
	"time"

	"gopkg.in/resty.v0"

	"github.com/asaskevich/govalidator"
	"github.com/julienschmidt/httprouter"
)

type NotifyMessage struct {
	Uuid string `json:"uuid" valid:"uuidv4"`
	Path string `json:"path" valid:"abspath"`
}

func FetchConfigurationItems(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
	var (
		dec    *json.Decoder
		msg    NotifyMessage
		err    error
		soma   *url.URL
		client *resty.Client
		resp   *resty.Response
		res    proto.Result
	)
	dec = json.NewDecoder(r.Body)
	if err = dec.Decode(&msg); err != nil {
		dispatchBadRequest(&w, err.Error())
		return
	}
	govalidator.SetFieldsRequiredByDefault(true)
	govalidator.TagMap["abspath"] = govalidator.Validator(func(str string) bool {
		return filepath.IsAbs(str)
	})
	if ok, err := govalidator.ValidateStruct(msg); !ok {
		dispatchBadRequest(&w, err.Error())
		return
	}

	soma, _ = url.Parse(Eye.Soma.url.String())
	soma.Path = fmt.Sprintf("%s/%s", msg.Path, msg.Uuid)
	client = resty.New().SetTimeout(500 * time.Millisecond)
	if resp, err = client.R().Get(soma.String()); err != nil || resp.StatusCode() > 299 {
		if err == nil {
			err = fmt.Errorf(resp.Status())
		}
		dispatchPrecondition(&w, err.Error())
		return
	}
	if err = json.Unmarshal(resp.Body(), &res); err != nil {
		dispatchUnprocessable(&w, err.Error())
		return
	}
	if res.StatusCode != 200 {
		dispatchGone(&w, err.Error())
		return
	}
	if len(*res.Deployments) != 1 {
		dispatchPrecondition(&w, err.Error())
		return
	}
	if err = CheckUpdateOrInsertOrDelete(&(*res.Deployments)[0]); err != nil {
		dispatchInternalServerError(&w, err.Error())
		return
	}
	dispatchNoContent(&w)
}

// vim: ts=4 sw=4 sts=4 noet fenc=utf-8 ffs=unix
<|endoftext|>