<commit_before>package main

import (
	"encoding/json"
	"github.com/BytemarkHosting/bytemark-client/cmd/bytemark/util"
	"github.com/BytemarkHosting/bytemark-client/lib"
	"github.com/BytemarkHosting/bytemark-client/lib/brain"
	"github.com/BytemarkHosting/bytemark-client/util/log"
	"github.com/urfave/cli"
	"net"
)

// Context is a wrapper around urfave/cli.Context which provides easy access to
// the next unused argument and can have various bytemarky types attached to it
// in order to keep code DRY
type Context struct {
	Context        *cli.Context
	Account        *lib.Account
	Authed         bool
	Definitions    *lib.Definitions
	Group          *brain.Group
	User           *brain.User
	UserName       *string
	VirtualMachine *brain.VirtualMachine

	currentArgIndex int
}

// Reset replaces the Context with a blank one (keeping the cli.Context)
func (c *Context) Reset() {
	*c = Context{
		Context: c.Context,
	}
}

// args returns all the args that were passed to the Context (i.e. all the args passed to this (sub)command)
func (c *Context) args() cli.Args {
	return c.Context.Args()
}

// Args returns all the unused arguments
func (c *Context) Args() []string {
	return c.args()[c.currentArgIndex:]
}

// NextArg returns the next unused argument, and marks it as used.
func (c *Context) NextArg() (string, error) {
	if len(c.args()) <= c.currentArgIndex {
		return "", c.Help("not enough arguments were specified")
	}
	arg := c.args()[c.currentArgIndex]
	c.currentArgIndex++
	return arg, nil
}

// Help creates a UsageDisplayedError that will output the issue and a message to consult the documentation
func (c *Context) Help(whatsyourproblem string) (err error) {
	return util.UsageDisplayedError{TheProblem: whatsyourproblem, Command: c.Context.Command.FullName()}
}

// flags below

// Bool returns the value of the named flag as a bool
func (c *Context) Bool(flagname string) bool {
	return c.Context.Bool(flagname)
}

// Discs returns the discs passed along as the named flag.
// I can't imagine why I'd ever name a disc flag anything other than --disc, but the flexibility is there just in case.
func (c *Context) Discs(flagname string) []brain.Disc {
	disc, ok := c.Context.Generic(flagname).(*util.DiscSpecFlag)
	if ok {
		return []brain.Disc(*disc)
	}
	return []brain.Disc{}
}

// FileName returns the name of the file given by the named flag
func (c *Context) FileName(flagname string) string {
	file, ok := c.Context.Generic(flagname).(*util.FileFlag)
	if ok {
		return file.FileName
	}
	return ""
}

// FileContents returns the contents of the file given by the named flag.
func (c *Context) FileContents(flagname string) string {
	file, ok := c.Context.Generic(flagname).(*util.FileFlag)
	if ok {
		return file.Value
	}
	return ""
}

func (c *Context) GroupName(flagname string) lib.GroupName {
	gpNameFlag, ok := c.Context.Generic(flagname).(*GroupNameFlag)
	if !ok {
		return lib.GroupName{}
	}
	return lib.GroupName(*gpNameFlag)
}

// Int returns the value of the named flag as an int
func (c *Context) Int(flagname string) int {
	return c.Context.Int(flagname)
}

// IPs returns the ips passed along as the named flag.
func (c *Context) IPs(flagname string) []net.IP {
	ips, ok := c.Context.Generic(flagname).(*util.IPFlag)
	if ok {
		return []net.IP(*ips)
	}
	return []net.IP{}
}

// String returns the value of the named flag as a string
func (c *Context) String(flagname string) string {
	return c.Context.String(flagname)
}

// Size returns the value of the named SizeSpecFlag as an int in megabytes
func (c *Context) Size(flagname string) int {
	size, ok := c.Context.Generic(flagname).(*util.SizeSpecFlag)
	if ok {
		return int(*size)
	}
	return 0
}
func (c *Context) VirtualMachineName(flagname string) lib.VirtualMachineName {
	vmNameFlag, ok := c.Context.Generic(flagname).(*VirtualMachineNameFlag)
	if !ok {
		return *global.Config.GetVirtualMachine()
	}
	return lib.VirtualMachineName(*vmNameFlag)
}

// IfNotMarshalJSON checks to see if the json flag was set, and outputs obj as a JSON object if so.
// if not, runs fn
func (c *Context) IfNotMarshalJSON(obj interface{}, fn func() error) error {
	if c.Bool("json") {
		js, err := json.MarshalIndent(obj, "", "    ")
		if err != nil {
			return err
		}
		log.Output(string(js))
		return nil
	}
	return fn()
}
<commit_msg>Add documentation comments for Context.GroupName, Context.VirtualMachineName<commit_after>package main

import (
	"encoding/json"
	"github.com/BytemarkHosting/bytemark-client/cmd/bytemark/util"
	"github.com/BytemarkHosting/bytemark-client/lib"
	"github.com/BytemarkHosting/bytemark-client/lib/brain"
	"github.com/BytemarkHosting/bytemark-client/util/log"
	"github.com/urfave/cli"
	"net"
)

// Context is a wrapper around urfave/cli.Context which provides easy access to
// the next unused argument and can have various bytemarky types attached to it
// in order to keep code DRY
type Context struct {
	Context        *cli.Context
	Account        *lib.Account
	Authed         bool
	Definitions    *lib.Definitions
	Group          *brain.Group
	User           *brain.User
	UserName       *string
	VirtualMachine *brain.VirtualMachine

	currentArgIndex int
}

// Reset replaces the Context with a blank one (keeping the cli.Context)
func (c *Context) Reset() {
	*c = Context{
		Context: c.Context,
	}
}

// args returns all the args that were passed to the Context (i.e. all the args passed to this (sub)command)
func (c *Context) args() cli.Args {
	return c.Context.Args()
}

// Args returns all the unused arguments
func (c *Context) Args() []string {
	return c.args()[c.currentArgIndex:]
}

// NextArg returns the next unused argument, and marks it as used.
func (c *Context) NextArg() (string, error) {
	if len(c.args()) <= c.currentArgIndex {
		return "", c.Help("not enough arguments were specified")
	}
	arg := c.args()[c.currentArgIndex]
	c.currentArgIndex++
	return arg, nil
}

// Help creates a UsageDisplayedError that will output the issue and a message to consult the documentation
func (c *Context) Help(whatsyourproblem string) (err error) {
	return util.UsageDisplayedError{TheProblem: whatsyourproblem, Command: c.Context.Command.FullName()}
}

// flags below

// Bool returns the value of the named flag as a bool
func (c *Context) Bool(flagname string) bool {
	return c.Context.Bool(flagname)
}

// Discs returns the discs passed along as the named flag.
// I can't imagine why I'd ever name a disc flag anything other than --disc, but the flexibility is there just in case.
func (c *Context) Discs(flagname string) []brain.Disc {
	disc, ok := c.Context.Generic(flagname).(*util.DiscSpecFlag)
	if ok {
		return []brain.Disc(*disc)
	}
	return []brain.Disc{}
}

// FileName returns the name of the file given by the named flag
func (c *Context) FileName(flagname string) string {
	file, ok := c.Context.Generic(flagname).(*util.FileFlag)
	if ok {
		return file.FileName
	}
	return ""
}

// FileContents returns the contents of the file given by the named flag.
func (c *Context) FileContents(flagname string) string {
	file, ok := c.Context.Generic(flagname).(*util.FileFlag)
	if ok {
		return file.Value
	}
	return ""
}

// GroupName returns the named flag as a lib.Groupname
func (c *Context) GroupName(flagname string) lib.GroupName {
	gpNameFlag, ok := c.Context.Generic(flagname).(*GroupNameFlag)
	if !ok {
		return lib.GroupName{}
	}
	return lib.GroupName(*gpNameFlag)
}

// Int returns the value of the named flag as an int
func (c *Context) Int(flagname string) int {
	return c.Context.Int(flagname)
}

// IPs returns the ips passed along as the named flag.
func (c *Context) IPs(flagname string) []net.IP {
	ips, ok := c.Context.Generic(flagname).(*util.IPFlag)
	if ok {
		return []net.IP(*ips)
	}
	return []net.IP{}
}

// String returns the value of the named flag as a string
func (c *Context) String(flagname string) string {
	return c.Context.String(flagname)
}

// Size returns the value of the named SizeSpecFlag as an int in megabytes
func (c *Context) Size(flagname string) int {
	size, ok := c.Context.Generic(flagname).(*util.SizeSpecFlag)
	if ok {
		return int(*size)
	}
	return 0
}

// VirtualMachineName returns the named flag as a lib.VirtualMachineName
func (c *Context) VirtualMachineName(flagname string) lib.VirtualMachineName {
	vmNameFlag, ok := c.Context.Generic(flagname).(*VirtualMachineNameFlag)
	if !ok {
		return *global.Config.GetVirtualMachine()
	}
	return lib.VirtualMachineName(*vmNameFlag)
}

// IfNotMarshalJSON checks to see if the json flag was set, and outputs obj as a JSON object if so.
// if not, runs fn
func (c *Context) IfNotMarshalJSON(obj interface{}, fn func() error) error {
	if c.Bool("json") {
		js, err := json.MarshalIndent(obj, "", "    ")
		if err != nil {
			return err
		}
		log.Output(string(js))
		return nil
	}
	return fn()
}
<|endoftext|>


<commit_before>package cmd

import (
	"encoding/json"
	"fmt"
	"os"
	"text/tabwriter"
	"time"

	"github.com/mobingi/mobingi-cli/pkg/cli"
	"github.com/mobingilabs/mobingi-sdk-go/mobingi/credentials"
	"github.com/mobingilabs/mobingi-sdk-go/pkg/cmdline"
	"github.com/mobingilabs/mobingi-sdk-go/pkg/pretty"
	"github.com/pkg/errors"
	"github.com/spf13/cobra"
)

func CredentialsListCmd() *cobra.Command {
	cmd := &cobra.Command{
		Use:   "list",
		Short: "list your credentials",
		Long: `List your credentials.

Supported formats: raw, json

Examples:

  $ ` + cmdline.Args0() + ` creds list
  $ ` + cmdline.Args0() + ` creds list --fmt=json
  $ ` + cmdline.Args0() + ` creds list --fmt=raw`,
		Run: credsList,
	}

	cmd.Flags().String("vendor", "aws", "credentials vendor")
	return cmd
}

func credsList(cmd *cobra.Command, args []string) {
	creds, body, err := getCredsList(cmd)
	cli.ErrorExit(err, 1)

	pfmt := cli.GetCliStringFlag(cmd, "fmt")
	switch pfmt {
	case "raw":
		fmt.Println(string(body))
	case "json":
		indent := cli.GetCliIntFlag(cmd, "indent")
		mi, err := json.MarshalIndent(creds, "", pretty.Indent(indent))
		cli.ErrorExit(err, 1)

		fmt.Println(string(mi))
	default:
		w := tabwriter.NewWriter(os.Stdout, 0, 10, 5, ' ', 0)
		fmt.Fprintf(w, "VENDOR\tID\tACCOUNT\tLAST MODIFIED\n")
		for _, cred := range creds {
			timestr := cred.LastModified
			t, err := time.Parse(time.RFC3339, cred.LastModified)
			if err == nil {
				timestr = t.Format(time.RFC1123)
			}

			fmt.Fprintf(w, "%s\t%s\t%s\t%s\n",
				cli.GetCliStringFlag(cmd, "vendor"),
				cred.Id,
				cred.Account,
				timestr)
		}

		w.Flush()
	}
}

func getCredsList(cmd *cobra.Command) ([]credentials.VendorCredentials, []byte, error) {
	vendor := cli.GetCliStringFlag(cmd, "vendor")
	sess, err := clisession()
	if err != nil {
		return nil, nil, errors.Wrap(err, "clisession failed")
	}

	svc := credentials.New(sess)
	resp, body, err := svc.List(&credentials.CredentialsListInput{
		Vendor: vendor,
	})

	if err != nil {
		return nil, body, errors.Wrap(err, "svc list failed")
	}

	exitOn401(resp)
	var creds []credentials.VendorCredentials
	err = json.Unmarshal(body, &creds)
	if err != nil {
		return nil, body, errors.Wrap(err, "unmarshal failed")
	}

	return creds, body, nil
}
<commit_msg>Unsorted creds.<commit_after>package cmd

import (
	"encoding/json"
	"fmt"
	"os"
	"text/tabwriter"
	"time"

	"github.com/mobingi/mobingi-cli/pkg/cli"
	"github.com/mobingilabs/mobingi-sdk-go/mobingi/credentials"
	"github.com/mobingilabs/mobingi-sdk-go/pkg/cmdline"
	"github.com/mobingilabs/mobingi-sdk-go/pkg/pretty"
	"github.com/pkg/errors"
	"github.com/spf13/cobra"
)

func CredentialsListCmd() *cobra.Command {
	cmd := &cobra.Command{
		Use:   "list",
		Short: "list your credentials",
		Long: `List your credentials.

Supported formats: raw, json

Examples:

  $ ` + cmdline.Args0() + ` creds list
  $ ` + cmdline.Args0() + ` creds list --fmt=json
  $ ` + cmdline.Args0() + ` creds list --fmt=raw`,
		Run: credsList,
	}

	cmd.Flags().SortFlags = false
	cmd.Flags().String("vendor", "aws", "credentials vendor")
	return cmd
}

func credsList(cmd *cobra.Command, args []string) {
	creds, body, err := getCredsList(cmd)
	cli.ErrorExit(err, 1)

	pfmt := cli.GetCliStringFlag(cmd, "fmt")
	switch pfmt {
	case "raw":
		fmt.Println(string(body))
	case "json":
		indent := cli.GetCliIntFlag(cmd, "indent")
		mi, err := json.MarshalIndent(creds, "", pretty.Indent(indent))
		cli.ErrorExit(err, 1)

		fmt.Println(string(mi))
	default:
		w := tabwriter.NewWriter(os.Stdout, 0, 10, 5, ' ', 0)
		fmt.Fprintf(w, "VENDOR\tID\tACCOUNT\tLAST MODIFIED\n")
		for _, cred := range creds {
			timestr := cred.LastModified
			t, err := time.Parse(time.RFC3339, cred.LastModified)
			if err == nil {
				timestr = t.Format(time.RFC1123)
			}

			fmt.Fprintf(w, "%s\t%s\t%s\t%s\n",
				cli.GetCliStringFlag(cmd, "vendor"),
				cred.Id,
				cred.Account,
				timestr)
		}

		w.Flush()
	}
}

func getCredsList(cmd *cobra.Command) ([]credentials.VendorCredentials, []byte, error) {
	vendor := cli.GetCliStringFlag(cmd, "vendor")
	sess, err := clisession()
	if err != nil {
		return nil, nil, errors.Wrap(err, "clisession failed")
	}

	svc := credentials.New(sess)
	resp, body, err := svc.List(&credentials.CredentialsListInput{
		Vendor: vendor,
	})

	if err != nil {
		return nil, body, errors.Wrap(err, "svc list failed")
	}

	exitOn401(resp)
	var creds []credentials.VendorCredentials
	err = json.Unmarshal(body, &creds)
	if err != nil {
		return nil, body, errors.Wrap(err, "unmarshal failed")
	}

	return creds, body, nil
}
<|endoftext|>


<commit_before>package main

import (
	contextpkg "context"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"net/url"
	"os"
	"path"
	"strings"

	"github.com/Sirupsen/logrus"
	"github.com/docker/containerd/log"
	"github.com/docker/containerd/remotes"
	digest "github.com/opencontainers/go-digest"
	"github.com/pkg/errors"
	"github.com/urfave/cli"
	"golang.org/x/net/context/ctxhttp"
)

// TODO(stevvooe): Create "multi-fetch" mode that just takes a remote
// then receives object/hint lines on stdin, returning content as
// needed.

var fetchObjectCommand = cli.Command{
	Name:        "fetch-object",
	Usage:       "retrieve objects from a remote",
	ArgsUsage:   "[flags] <remote> <object> [<hint>, ...]",
	Description: `Fetch objects by identifier from a remote.`,
	Flags: []cli.Flag{
		cli.DurationFlag{
			Name:   "timeout",
			Usage:  "total timeout for fetch",
			EnvVar: "CONTAINERD_FETCH_TIMEOUT",
		},
	},
	Action: func(context *cli.Context) error {
		var (
			ctx     = background
			timeout = context.Duration("timeout")
			locator = context.Args().First()
			args    = context.Args().Tail()
		)

		if timeout > 0 {
			var cancel func()
			ctx, cancel = contextpkg.WithTimeout(ctx, timeout)
			defer cancel()
		}

		if locator == "" {
			return errors.New("containerd: remote required")
		}

		if len(args) < 1 {
			return errors.New("containerd: object required")
		}

		object := args[0]
		hints := args[1:]

		resolver, err := getResolver(ctx)
		if err != nil {
			return err
		}

		remote, err := resolver.Resolve(ctx, locator)
		if err != nil {
			return err
		}

		ctx = log.WithLogger(ctx, log.G(ctx).WithFields(
			logrus.Fields{
				"remote": locator,
				"object": object,
			}))

		log.G(ctx).Infof("fetching")
		rc, err := remote.Fetch(ctx, object, hints...)
		if err != nil {
			return err
		}
		defer rc.Close()

		if _, err := io.Copy(os.Stdout, rc); err != nil {
			return err
		}

		return nil
	},
}

// NOTE(stevvooe): Most of the code below this point is prototype code to
// demonstrate a very simplified docker.io fetcher. We have a lot of hard coded
// values but we leave many of the details down to the fetcher, creating a lot
// of room for ways to fetch content.

// getResolver prepares the resolver from the environment and options.
func getResolver(ctx contextpkg.Context) (remotes.Resolver, error) {
	return remotes.ResolverFunc(func(ctx contextpkg.Context, locator string) (remotes.Fetcher, error) {
		if !strings.HasPrefix(locator, "docker.io") && !strings.HasPrefix(locator, "localhost:5000") {
			return nil, errors.Errorf("unsupported locator: %q", locator)
		}

		var (
			base = url.URL{
				Scheme: "https",
				Host:   "registry-1.docker.io",
			}
			prefix = strings.TrimPrefix(locator, "docker.io/")
		)

		if strings.HasPrefix(locator, "localhost:5000") {
			base.Scheme = "http"
			base.Host = "localhost:5000"
			prefix = strings.TrimPrefix(locator, "localhost:5000/")
		}

		token, err := getToken(ctx, "repository:"+prefix+":pull")
		if err != nil {
			return nil, err
		}

		return remotes.FetcherFunc(func(ctx contextpkg.Context, object string, hints ...string) (io.ReadCloser, error) {
			ctx = log.WithLogger(ctx, log.G(ctx).WithFields(
				logrus.Fields{
					"prefix": prefix, // or repo?
					"base":   base.String(),
					"hints":  hints,
				},
			))

			paths, err := getV2URLPaths(prefix, object, hints...)
			if err != nil {
				return nil, err
			}

			for _, path := range paths {
				url := base
				url.Path = path
				log.G(ctx).WithField("url", url).Debug("fetch content")

				req, err := http.NewRequest(http.MethodGet, url.String(), nil)
				if err != nil {
					return nil, err
				}

				req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", token))
				for _, mediatype := range remotes.HintValues("mediatype", hints...) {
					req.Header.Set("Accept", mediatype)
				}

				resp, err := ctxhttp.Do(ctx, http.DefaultClient, req)
				if err != nil {
					return nil, err
				}

				if resp.StatusCode > 299 {
					if resp.StatusCode == http.StatusNotFound {
						continue // try one of the other urls.
					}
					resp.Body.Close()
					return nil, errors.Errorf("unexpected status code %v: %v", url, resp.Status)
				}

				return resp.Body, nil
			}

			return nil, errors.New("not found")
		}), nil
	}), nil
}

func getToken(ctx contextpkg.Context, scopes ...string) (string, error) {
	var (
		u = url.URL{
			Scheme: "https",
			Host:   "auth.docker.io",
			Path:   "/token",
		}

		q = url.Values{
			"scope":   scopes,
			"service": []string{"registry.docker.io"}, // usually comes from auth challenge
		}
	)

	u.RawQuery = q.Encode()

	log.G(ctx).WithField("token.url", u.String()).Debug("requesting token")
	resp, err := ctxhttp.Get(ctx, http.DefaultClient, u.String())
	if err != nil {
		return "", err
	}
	defer resp.Body.Close()

	if resp.StatusCode > 299 {
		return "", errors.Errorf("unexpected status code: %v %v", resp.StatusCode, resp.Status)
	}

	p, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return "", err
	}

	var tokenResponse struct {
		Token string `json:"token"`
	}

	if err := json.Unmarshal(p, &tokenResponse); err != nil {
		return "", err
	}

	return tokenResponse.Token, nil
}

// getV2URLPaths generates the candidate urls paths for the object based on the
// set of hints and the provided object id. URLs are returned in the order of
// most to least likely succeed.
func getV2URLPaths(prefix, object string, hints ...string) ([]string, error) {
	var urls []string

	// TODO(stevvooe): We can probably define a higher-level "type" hint to
	// avoid having to do extra round trips to resolve content, as well as
	// avoid the tedium of providing media types.

	if remotes.HintExists("mediatype", "application/vnd.docker.distribution.manifest.v2+json", hints...) { // TODO(stevvooe): make this handle oci types, as well.
		// fast path out if we know we are getting a manifest. Arguably, we
		// should fallback to blobs, just in case.
		urls = append(urls, path.Join("/v2", prefix, "manifests", object))
	}

	_, err := digest.Parse(object)
	if err == nil {
		// we have a digest, use blob or manifest path, depending on hints, may
		// need to try both.
		urls = append(urls, path.Join("/v2", prefix, "blobs", object))
	}

	// probably a take, so we go through the manifests endpoint
	urls = append(urls, path.Join("/v2", prefix, "manifests", object))

	var (
		noduplicates []string
		seen         = map[string]struct{}{}
	)
	for _, u := range urls {
		if _, ok := seen[u]; !ok {
			seen[u] = struct{}{}
			noduplicates = append(noduplicates, u)
		}
	}

	return noduplicates, nil
}
<commit_msg>cmd/dist: default mediatypes to oci and docker<commit_after>package main

import (
	contextpkg "context"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"net/url"
	"os"
	"path"
	"strings"

	"github.com/Sirupsen/logrus"
	"github.com/docker/containerd/log"
	"github.com/docker/containerd/remotes"
	digest "github.com/opencontainers/go-digest"
	ocispec "github.com/opencontainers/image-spec/specs-go/v1"
	"github.com/pkg/errors"
	"github.com/urfave/cli"
	"golang.org/x/net/context/ctxhttp"
)

const (
	MediaTypeDockerSchema2Manifest     = "application/vnd.docker.distribution.manifest.v2+json"
	MediaTypeDockerSchema2ManifestList = "application/vnd.docker.distribution.manifest.list.v2+json"
)

// TODO(stevvooe): Create "multi-fetch" mode that just takes a remote
// then receives object/hint lines on stdin, returning content as
// needed.

var fetchObjectCommand = cli.Command{
	Name:        "fetch-object",
	Usage:       "retrieve objects from a remote",
	ArgsUsage:   "[flags] <remote> <object> [<hint>, ...]",
	Description: `Fetch objects by identifier from a remote.`,
	Flags: []cli.Flag{
		cli.DurationFlag{
			Name:   "timeout",
			Usage:  "total timeout for fetch",
			EnvVar: "CONTAINERD_FETCH_TIMEOUT",
		},
	},
	Action: func(context *cli.Context) error {
		var (
			ctx     = background
			timeout = context.Duration("timeout")
			locator = context.Args().First()
			args    = context.Args().Tail()
		)

		if timeout > 0 {
			var cancel func()
			ctx, cancel = contextpkg.WithTimeout(ctx, timeout)
			defer cancel()
		}

		if locator == "" {
			return errors.New("containerd: remote required")
		}

		if len(args) < 1 {
			return errors.New("containerd: object required")
		}

		object := args[0]
		hints := args[1:]

		resolver, err := getResolver(ctx)
		if err != nil {
			return err
		}

		remote, err := resolver.Resolve(ctx, locator)
		if err != nil {
			return err
		}

		ctx = log.WithLogger(ctx, log.G(ctx).WithFields(
			logrus.Fields{
				"remote": locator,
				"object": object,
			}))

		log.G(ctx).Infof("fetching")
		rc, err := remote.Fetch(ctx, object, hints...)
		if err != nil {
			return err
		}
		defer rc.Close()

		if _, err := io.Copy(os.Stdout, rc); err != nil {
			return err
		}

		return nil
	},
}

// NOTE(stevvooe): Most of the code below this point is prototype code to
// demonstrate a very simplified docker.io fetcher. We have a lot of hard coded
// values but we leave many of the details down to the fetcher, creating a lot
// of room for ways to fetch content.

// getResolver prepares the resolver from the environment and options.
func getResolver(ctx contextpkg.Context) (remotes.Resolver, error) {
	return remotes.ResolverFunc(func(ctx contextpkg.Context, locator string) (remotes.Fetcher, error) {
		if !strings.HasPrefix(locator, "docker.io") && !strings.HasPrefix(locator, "localhost:5000") {
			return nil, errors.Errorf("unsupported locator: %q", locator)
		}

		var (
			base = url.URL{
				Scheme: "https",
				Host:   "registry-1.docker.io",
			}
			prefix = strings.TrimPrefix(locator, "docker.io/")
		)

		if strings.HasPrefix(locator, "localhost:5000") {
			base.Scheme = "http"
			base.Host = "localhost:5000"
			prefix = strings.TrimPrefix(locator, "localhost:5000/")
		}

		token, err := getToken(ctx, "repository:"+prefix+":pull")
		if err != nil {
			return nil, err
		}

		return remotes.FetcherFunc(func(ctx contextpkg.Context, object string, hints ...string) (io.ReadCloser, error) {
			ctx = log.WithLogger(ctx, log.G(ctx).WithFields(
				logrus.Fields{
					"prefix": prefix, // or repo?
					"base":   base.String(),
					"hints":  hints,
				},
			))

			if _, err := digest.Parse(object); err != nil {
				// in this case, we are seeking a manifest by a tag. Let's add some hints.
				hints = append(hints, "mediatype:"+MediaTypeDockerSchema2Manifest)
				hints = append(hints, "mediatype:"+MediaTypeDockerSchema2ManifestList)
				hints = append(hints, "mediatype:"+ocispec.MediaTypeImageManifest)
				hints = append(hints, "mediatype:"+ocispec.MediaTypeImageIndex)
			}

			paths, err := getV2URLPaths(prefix, object, hints...)
			if err != nil {
				return nil, err
			}

			for _, path := range paths {
				url := base
				url.Path = path
				log.G(ctx).WithField("url", url).Debug("fetch content")

				req, err := http.NewRequest(http.MethodGet, url.String(), nil)
				if err != nil {
					return nil, err
				}

				req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", token))
				req.Header.Set("Accept", strings.Join(remotes.HintValues("mediatype", hints...), ", "))

				resp, err := ctxhttp.Do(ctx, http.DefaultClient, req)
				if err != nil {
					return nil, err
				}

				if resp.StatusCode > 299 {
					if resp.StatusCode == http.StatusNotFound {
						continue // try one of the other urls.
					}
					resp.Body.Close()
					return nil, errors.Errorf("unexpected status code %v: %v", url, resp.Status)
				}

				return resp.Body, nil
			}

			return nil, errors.New("not found")
		}), nil
	}), nil
}

func getToken(ctx contextpkg.Context, scopes ...string) (string, error) {
	var (
		u = url.URL{
			Scheme: "https",
			Host:   "auth.docker.io",
			Path:   "/token",
		}

		q = url.Values{
			"scope":   scopes,
			"service": []string{"registry.docker.io"}, // usually comes from auth challenge
		}
	)

	u.RawQuery = q.Encode()

	log.G(ctx).WithField("token.url", u.String()).Debug("requesting token")
	resp, err := ctxhttp.Get(ctx, http.DefaultClient, u.String())
	if err != nil {
		return "", err
	}
	defer resp.Body.Close()

	if resp.StatusCode > 299 {
		return "", errors.Errorf("unexpected status code: %v %v", resp.StatusCode, resp.Status)
	}

	p, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return "", err
	}

	var tokenResponse struct {
		Token string `json:"token"`
	}

	if err := json.Unmarshal(p, &tokenResponse); err != nil {
		return "", err
	}

	return tokenResponse.Token, nil
}

// getV2URLPaths generates the candidate urls paths for the object based on the
// set of hints and the provided object id. URLs are returned in the order of
// most to least likely succeed.
func getV2URLPaths(prefix, object string, hints ...string) ([]string, error) {
	var urls []string

	// TODO(stevvooe): We can probably define a higher-level "type" hint to
	// avoid having to do extra round trips to resolve content, as well as
	// avoid the tedium of providing media types.

	if remotes.HintExists("mediatype", MediaTypeDockerSchema2Manifest, hints...) ||
		remotes.HintExists("mediatype", MediaTypeDockerSchema2ManifestList, hints...) ||
		remotes.HintExists("mediatype", ocispec.MediaTypeImageManifest, hints...) ||
		remotes.HintExists("mediatype", ocispec.MediaTypeImageIndex, hints...) {
		// fast path out if we know we are getting a manifest. Arguably, we
		// should fallback to blobs, just in case.
		urls = append(urls, path.Join("/v2", prefix, "manifests", object))
	}

	// we have a digest, use blob or manifest path, depending on hints, may
	// need to try both.
	urls = append(urls, path.Join("/v2", prefix, "blobs", object))

	// probably a take, so we go through the manifests endpoint
	urls = append(urls, path.Join("/v2", prefix, "manifests", object))

	var (
		noduplicates []string
		seen         = map[string]struct{}{}
	)
	for _, u := range urls {
		if _, ok := seen[u]; !ok {
			seen[u] = struct{}{}
			noduplicates = append(noduplicates, u)
		}
	}

	return noduplicates, nil
}
<|endoftext|>


<commit_before>package ui

import (
	"github.com/gdamore/tcell"
	"github.com/gdamore/tcell/encoding"
	"github.com/tcolar/goed"
	"github.com/tcolar/goed/actions"
	"github.com/tcolar/goed/core"
	"github.com/tcolar/goed/event"
)

var _ core.Term = (*Tcell)(nil)

func Main() {
	config := goed.Initialize()
	if config == nil {
		return
	}
	term := NewTcell()
	defer goed.Terminate(term)
	goed.Start(term, config)
}

// Tcell : Term implementation using tcell
type Tcell struct {
	screen tcell.Screen
}

func NewTcell() *Tcell {
	return &Tcell{}
}

func (t *Tcell) Init() error {
	screen, err := tcell.NewScreen()
	if err != nil {
		return err
	}

	encoding.Register()

	if err = screen.Init(); err != nil {
		return err
	}
	t.screen = screen
	return nil
}

func (t *Tcell) Clear(fg, bg core.Style) {
	st := t.toTcellStyle(fg, bg)
	w, h := t.screen.Size()
	for row := 0; row < h; row++ {
		for col := 0; col < w; col++ {
			t.screen.SetContent(col, row, ' ', nil, st)
		}
	}
}

func (t *Tcell) Close() {
	t.screen.DisableMouse()
	t.screen.Fini()
}

func (t *Tcell) Flush() {
	t.screen.Show()
}

func (t *Tcell) SetExtendedColors(b bool) {
}

func (t *Tcell) SetCursor(y, x int) {
	t.screen.ShowCursor(y, x)
}

func (t *Tcell) Char(y, x int, c rune, fg, bg core.Style) {
	st := t.toTcellStyle(fg, bg)
	t.screen.SetContent(x, y, c, nil, st)
}

func (t *Tcell) toTcellStyle(fg, bg core.Style) tcell.Style {
	f := tcell.Color(fg.Color())
	b := tcell.Color(bg.Color())
	st := tcell.StyleDefault.Foreground(f).Background(b)
	if fg.IsBold() {
		st = st.Bold(true)
	}
	if fg.IsUnderlined() {
		st = st.Underline(true)
	}
	return st
}

func (t *Tcell) Size() (h, w int) {
	w, h = t.screen.Size()
	return h, w
}

func (t *Tcell) Listen() {
	t.screen.EnableMouse()
	es := event.NewEvent()
	for {
		e := t.screen.PollEvent()
		t.parseEvent(e, es)
		if es.Type == event.EvtQuit {
			return
		}
		event.Queue(es.Clone())
	}
}

func (t *Tcell) updateMouseState(es *event.Event, down bool, button event.MouseButton, y, x int) {
	if down {
		es.MouseDown(button, y, x)
	} else if es.MouseBtns[button] {
		es.MouseUp(button, y, x)
	}
}

func (t *Tcell) parseEvent(e tcell.Event, es *event.Event) {
	es.Glyph = ""
	es.Keys = []string{}
	es.MouseBtns[event.MouseWheelDown] = false // reset wheel down, no separate "up" event
	es.MouseBtns[event.MouseWheelUp] = false   // reset wheel up
	es.Type = event.Evt_None

	ctrl := func(k string) {
		es.KeyDown(event.KeyLeftControl)
		es.KeyDown(k)
	}

	switch te := e.(type) {
	case *tcell.EventResize:
		w, h := te.Size()
		actions.Ar.EdResize(h, w)
		return
	case *tcell.EventMouse:
		m := te.Modifiers()
		es.Combo = event.Combo{
			LAlt:   m&tcell.ModAlt != 0,
			LCtrl:  m&tcell.ModCtrl != 0,
			LShift: m&tcell.ModShift != 0,
			LSuper: m&tcell.ModMeta != 0,
		}
		b := te.Buttons()
		x, y := te.Position()
		t.updateMouseState(es, b&tcell.Button1 != 0, event.MouseLeft, y, x)
		t.updateMouseState(es, b&tcell.Button2 != 0, event.MouseMiddle, y, x)
		t.updateMouseState(es, b&tcell.Button3 != 0, event.MouseRight, y, x)
		t.updateMouseState(es, b&tcell.WheelUp != 0, event.MouseWheelUp, y, x)
		t.updateMouseState(es, b&tcell.WheelDown != 0, event.MouseWheelDown, y, x)
		t.updateMouseState(es, b&tcell.WheelLeft != 0, event.MouseWheelLeft, y, x)
		t.updateMouseState(es, b&tcell.WheelRight != 0, event.MouseWheelRight, y, x)

	case *tcell.EventKey:
		m := te.Modifiers()
		es.Combo = event.Combo{
			LAlt:   m&tcell.ModAlt != 0,
			LCtrl:  m&tcell.ModCtrl != 0,
			LShift: m&tcell.ModShift != 0,
			LSuper: m&tcell.ModMeta != 0,
		}
		if te.Key() == tcell.KeyRune {
			es.Glyph = string(te.Rune())
			es.KeyDown(es.Glyph)
			return
		}
		switch te.Key() {
		case tcell.KeyEsc:
			es.KeyDown(event.KeyEscape)
		case tcell.KeyBackspace2:
			es.KeyDown(event.KeyBackspace)
		case tcell.KeyTab:
			es.KeyDown(event.KeyTab)
		case tcell.KeyEnter:
			es.KeyDown(event.KeyReturn)
		case tcell.KeyF1:
			es.KeyDown(event.KeyF1)
		case tcell.KeyF2:
			es.KeyDown(event.KeyF2)
		case tcell.KeyF3:
			es.KeyDown(event.KeyF3)
		case tcell.KeyF4:
			es.KeyDown(event.KeyF4)
		case tcell.KeyF5:
			es.KeyDown(event.KeyF5)
		case tcell.KeyF6:
			es.KeyDown(event.KeyF7)
		case tcell.KeyF7:
			es.KeyDown(event.KeyF7)
		case tcell.KeyF8:
			es.KeyDown(event.KeyF8)
		case tcell.KeyF9:
			es.KeyDown(event.KeyF9)
		case tcell.KeyF10:
			es.KeyDown(event.KeyF10)
		case tcell.KeyF11:
			es.KeyDown(event.KeyF11)
		case tcell.KeyF12:
			es.KeyDown(event.KeyF12)
		case tcell.KeyInsert:
			es.KeyDown(event.KeyInsert)
		case tcell.KeyDelete:
			es.KeyDown(event.KeyDelete)
		case tcell.KeyHome:
			es.KeyDown(event.KeyHome)
		case tcell.KeyEnd:
			es.KeyDown(event.KeyEnd)
		case tcell.KeyPgUp:
			es.KeyDown(event.KeyPrior)
		case tcell.KeyPgDn:
			es.KeyDown(event.KeyNext)
		case tcell.KeyUp:
			es.KeyDown(event.KeyUpArrow)
		case tcell.KeyDown:
			es.KeyDown(event.KeyDownArrow)
		case tcell.KeyLeft:
			es.KeyDown(event.KeyLeftArrow)
		case tcell.KeyRight:
			es.KeyDown(event.KeyRightArrow)

		case tcell.KeyCtrlA:
			ctrl("a")
		case tcell.KeyCtrlB:
			ctrl("b")
		case tcell.KeyCtrlC:
			ctrl("c")
		case tcell.KeyCtrlD:
			ctrl("d")
		case tcell.KeyCtrlE:
			ctrl("e")
		case tcell.KeyCtrlF:
			ctrl("f")
		case tcell.KeyCtrlG:
			ctrl("g")
		case tcell.KeyCtrlH:
			ctrl("h")
		case tcell.KeyCtrlJ:
			ctrl("j")
		case tcell.KeyCtrlK:
			ctrl("k")
		case tcell.KeyCtrlL:
			ctrl("l")
		case tcell.KeyCtrlN:
			ctrl("n")
		case tcell.KeyCtrlO:
			ctrl("o")
		case tcell.KeyCtrlP:
			ctrl("p")
		case tcell.KeyCtrlQ:
			ctrl("q")
		case tcell.KeyCtrlR:
			ctrl("r")
		case tcell.KeyCtrlS:
			ctrl("s")
		case tcell.KeyCtrlT:
			ctrl("t")
		case tcell.KeyCtrlU:
			ctrl("u")
		case tcell.KeyCtrlV:
			ctrl("v")
		case tcell.KeyCtrlW:
			ctrl("w")
		case tcell.KeyCtrlX:
			ctrl("x")
		case tcell.KeyCtrlY:
			ctrl("y")
		case tcell.KeyCtrlZ:
			ctrl("z")
		}
	}
}
<commit_msg>Use forked version of Tcell with OSX high IDLE_WAKE workaround for now.<commit_after>package ui

import (
	"github.com/tcolar/goed"
	"github.com/tcolar/goed/actions"
	"github.com/tcolar/goed/core"
	"github.com/tcolar/goed/event"
	"github.com/tcolar/tcell"
	"github.com/tcolar/tcell/encoding"
)

var _ core.Term = (*Tcell)(nil)

func Main() {
	config := goed.Initialize()
	if config == nil {
		return
	}
	term := NewTcell()
	defer goed.Terminate(term)
	goed.Start(term, config)
}

// Tcell : Term implementation using tcell
type Tcell struct {
	screen tcell.Screen
}

func NewTcell() *Tcell {
	return &Tcell{}
}

func (t *Tcell) Init() error {
	screen, err := tcell.NewScreen()
	if err != nil {
		return err
	}

	encoding.Register()

	if err = screen.Init(); err != nil {
		return err
	}
	t.screen = screen
	return nil
}

func (t *Tcell) Clear(fg, bg core.Style) {
	st := t.toTcellStyle(fg, bg)
	w, h := t.screen.Size()
	for row := 0; row < h; row++ {
		for col := 0; col < w; col++ {
			t.screen.SetContent(col, row, ' ', nil, st)
		}
	}
}

func (t *Tcell) Close() {
	t.screen.DisableMouse()
	t.screen.Fini()
}

func (t *Tcell) Flush() {
	t.screen.Show()
}

func (t *Tcell) SetExtendedColors(b bool) {
}

func (t *Tcell) SetCursor(y, x int) {
	t.screen.ShowCursor(y, x)
}

func (t *Tcell) Char(y, x int, c rune, fg, bg core.Style) {
	st := t.toTcellStyle(fg, bg)
	t.screen.SetContent(x, y, c, nil, st)
}

func (t *Tcell) toTcellStyle(fg, bg core.Style) tcell.Style {
	f := tcell.Color(fg.Color())
	b := tcell.Color(bg.Color())
	st := tcell.StyleDefault.Foreground(f).Background(b)
	if fg.IsBold() {
		st = st.Bold(true)
	}
	if fg.IsUnderlined() {
		st = st.Underline(true)
	}
	return st
}

func (t *Tcell) Size() (h, w int) {
	w, h = t.screen.Size()
	return h, w
}

func (t *Tcell) Listen() {
	t.screen.EnableMouse()
	es := event.NewEvent()
	for {
		e := t.screen.PollEvent()
		t.parseEvent(e, es)
		if es.Type == event.EvtQuit {
			return
		}
		event.Queue(es.Clone())
	}
}

func (t *Tcell) updateMouseState(es *event.Event, down bool, button event.MouseButton, y, x int) {
	if down {
		es.MouseDown(button, y, x)
	} else if es.MouseBtns[button] {
		es.MouseUp(button, y, x)
	}
}

func (t *Tcell) parseEvent(e tcell.Event, es *event.Event) {
	es.Glyph = ""
	es.Keys = []string{}
	es.MouseBtns[event.MouseWheelDown] = false // reset wheel down, no separate "up" event
	es.MouseBtns[event.MouseWheelUp] = false   // reset wheel up
	es.Type = event.Evt_None

	ctrl := func(k string) {
		es.KeyDown(event.KeyLeftControl)
		es.KeyDown(k)
	}

	switch te := e.(type) {
	case *tcell.EventResize:
		w, h := te.Size()
		actions.Ar.EdResize(h, w)
		return
	case *tcell.EventMouse:
		m := te.Modifiers()
		es.Combo = event.Combo{
			LAlt:   m&tcell.ModAlt != 0,
			LCtrl:  m&tcell.ModCtrl != 0,
			LShift: m&tcell.ModShift != 0,
			LSuper: m&tcell.ModMeta != 0,
		}
		b := te.Buttons()
		x, y := te.Position()
		t.updateMouseState(es, b&tcell.Button1 != 0, event.MouseLeft, y, x)
		t.updateMouseState(es, b&tcell.Button2 != 0, event.MouseMiddle, y, x)
		t.updateMouseState(es, b&tcell.Button3 != 0, event.MouseRight, y, x)
		t.updateMouseState(es, b&tcell.WheelUp != 0, event.MouseWheelUp, y, x)
		t.updateMouseState(es, b&tcell.WheelDown != 0, event.MouseWheelDown, y, x)
		t.updateMouseState(es, b&tcell.WheelLeft != 0, event.MouseWheelLeft, y, x)
		t.updateMouseState(es, b&tcell.WheelRight != 0, event.MouseWheelRight, y, x)

	case *tcell.EventKey:
		m := te.Modifiers()
		es.Combo = event.Combo{
			LAlt:   m&tcell.ModAlt != 0,
			LCtrl:  m&tcell.ModCtrl != 0,
			LShift: m&tcell.ModShift != 0,
			LSuper: m&tcell.ModMeta != 0,
		}
		if te.Key() == tcell.KeyRune {
			es.Glyph = string(te.Rune())
			es.KeyDown(es.Glyph)
			return
		}
		switch te.Key() {
		case tcell.KeyEsc:
			es.KeyDown(event.KeyEscape)
		case tcell.KeyBackspace2:
			es.KeyDown(event.KeyBackspace)
		case tcell.KeyTab:
			es.KeyDown(event.KeyTab)
		case tcell.KeyEnter:
			es.KeyDown(event.KeyReturn)
		case tcell.KeyF1:
			es.KeyDown(event.KeyF1)
		case tcell.KeyF2:
			es.KeyDown(event.KeyF2)
		case tcell.KeyF3:
			es.KeyDown(event.KeyF3)
		case tcell.KeyF4:
			es.KeyDown(event.KeyF4)
		case tcell.KeyF5:
			es.KeyDown(event.KeyF5)
		case tcell.KeyF6:
			es.KeyDown(event.KeyF7)
		case tcell.KeyF7:
			es.KeyDown(event.KeyF7)
		case tcell.KeyF8:
			es.KeyDown(event.KeyF8)
		case tcell.KeyF9:
			es.KeyDown(event.KeyF9)
		case tcell.KeyF10:
			es.KeyDown(event.KeyF10)
		case tcell.KeyF11:
			es.KeyDown(event.KeyF11)
		case tcell.KeyF12:
			es.KeyDown(event.KeyF12)
		case tcell.KeyInsert:
			es.KeyDown(event.KeyInsert)
		case tcell.KeyDelete:
			es.KeyDown(event.KeyDelete)
		case tcell.KeyHome:
			es.KeyDown(event.KeyHome)
		case tcell.KeyEnd:
			es.KeyDown(event.KeyEnd)
		case tcell.KeyPgUp:
			es.KeyDown(event.KeyPrior)
		case tcell.KeyPgDn:
			es.KeyDown(event.KeyNext)
		case tcell.KeyUp:
			es.KeyDown(event.KeyUpArrow)
		case tcell.KeyDown:
			es.KeyDown(event.KeyDownArrow)
		case tcell.KeyLeft:
			es.KeyDown(event.KeyLeftArrow)
		case tcell.KeyRight:
			es.KeyDown(event.KeyRightArrow)

		case tcell.KeyCtrlA:
			ctrl("a")
		case tcell.KeyCtrlB:
			ctrl("b")
		case tcell.KeyCtrlC:
			ctrl("c")
		case tcell.KeyCtrlD:
			ctrl("d")
		case tcell.KeyCtrlE:
			ctrl("e")
		case tcell.KeyCtrlF:
			ctrl("f")
		case tcell.KeyCtrlG:
			ctrl("g")
		case tcell.KeyCtrlH:
			ctrl("h")
		case tcell.KeyCtrlJ:
			ctrl("j")
		case tcell.KeyCtrlK:
			ctrl("k")
		case tcell.KeyCtrlL:
			ctrl("l")
		case tcell.KeyCtrlN:
			ctrl("n")
		case tcell.KeyCtrlO:
			ctrl("o")
		case tcell.KeyCtrlP:
			ctrl("p")
		case tcell.KeyCtrlQ:
			ctrl("q")
		case tcell.KeyCtrlR:
			ctrl("r")
		case tcell.KeyCtrlS:
			ctrl("s")
		case tcell.KeyCtrlT:
			ctrl("t")
		case tcell.KeyCtrlU:
			ctrl("u")
		case tcell.KeyCtrlV:
			ctrl("v")
		case tcell.KeyCtrlW:
			ctrl("w")
		case tcell.KeyCtrlX:
			ctrl("x")
		case tcell.KeyCtrlY:
			ctrl("y")
		case tcell.KeyCtrlZ:
			ctrl("z")
		}
	}
}
<|endoftext|>


<commit_before>package internal

import (
	"errors"
	"fmt"

	"github.com/ready-steady/linear/matrix"
	"github.com/ready-steady/probability"
	"github.com/ready-steady/probability/gaussian"
	"github.com/ready-steady/simulation/system"
	"github.com/ready-steady/simulation/time"
	"github.com/ready-steady/statistics/correlation"

	acorrelation "../../pkg/correlation"
	aprobability "../../pkg/probability"
)

var standardGaussian = gaussian.New(0, 1)

type Problem struct {
	Config Config

	platform    *system.Platform
	application *system.Application

	time     *time.List
	schedule *time.Schedule

	tasks      []uint
	multiplier []float64
	marginals  []probability.Inverter

	nc uint
	nt uint
	nu uint
	nz uint
}

func (p *Problem) String() string {
	return fmt.Sprintf("Problem{cores: %d, tasks: %d, dvars: %d, ivars: %d}",
		p.nc, p.nt, p.nu, p.nz)
}

func NewProblem(config Config) (*Problem, error) {
	platform, application, err := system.Load(config.System)
	if err != nil {
		return nil, err
	}

	nc, nt := uint(len(platform.Cores)), uint(len(application.Tasks))

	time := time.NewList(platform, application)
	schedule := time.Compute(system.NewProfile(platform, application).Mobility)

	c := &config.Probability

	if c.MaxDelay < 0 || 1 <= c.MaxDelay {
		return nil, errors.New("the delay rate is invalid")
	}
	if c.CorrLength <= 0 {
		return nil, errors.New("the correlation length is invalid")
	}
	if c.VarThreshold <= 0 {
		return nil, errors.New("the variance-reduction threshold is invalid")
	}

	tasks := c.TaskIndex
	if len(tasks) == 0 {
		tasks = make([]uint, nt)
		for i := uint(0); i < nt; i++ {
			tasks[i] = i
		}
	}

	nu := uint(len(tasks))

	C := acorrelation.Compute(application, tasks, c.CorrLength)
	multiplier, nz, err := correlation.Decompose(C, nu, c.VarThreshold)
	if err != nil {
		return nil, err
	}

	marginalizer := aprobability.ParseInverter(c.Marginal)
	if marginalizer == nil {
		return nil, errors.New("invalid marginal distributions")
	}
	marginals := make([]probability.Inverter, nu)
	for i, tid := range tasks {
		duration := platform.Cores[schedule.Mapping[tid]].Time[application.Tasks[tid].Type]
		marginals[i] = marginalizer(0, c.MaxDelay*duration)
	}

	problem := &Problem{
		Config: config,

		platform:    platform,
		application: application,

		time:     time,
		schedule: schedule,

		tasks:      tasks,
		multiplier: multiplier,
		marginals:  marginals,

		nc: nc,
		nt: nt,
		nu: nu,
		nz: nz,
	}

	return problem, nil
}

func (p *Problem) transform(node []float64) []float64 {
	const (
		offset = 1e-8
	)

	z := make([]float64, p.nz)
	u := make([]float64, p.nu)
	d := make([]float64, p.nt)

	// Independent uniform to independent Gaussian
	for i := range z {
		switch node[i] {
		case 0:
			z[i] = standardGaussian.InvCDF(0 + offset)
		case 1:
			z[i] = standardGaussian.InvCDF(1 - offset)
		default:
			z[i] = standardGaussian.InvCDF(node[i])
		}
	}

	// Independent Gaussian to dependent Gaussian
	matrix.Multiply(p.multiplier, z, u, p.nu, p.nz, 1)

	// Dependent Gaussian to dependent uniform to dependent target
	for i, tid := range p.tasks {
		d[tid] = p.marginals[i].InvCDF(standardGaussian.CDF(u[i]))
	}

	return d
}
<commit_msg>Adjusted the verification of ProbabilityConfig<commit_after>package internal

import (
	"errors"
	"fmt"

	"github.com/ready-steady/linear/matrix"
	"github.com/ready-steady/probability"
	"github.com/ready-steady/probability/gaussian"
	"github.com/ready-steady/simulation/system"
	"github.com/ready-steady/simulation/time"
	"github.com/ready-steady/statistics/correlation"

	acorrelation "../../pkg/correlation"
	aprobability "../../pkg/probability"
)

var standardGaussian = gaussian.New(0, 1)

type Problem struct {
	Config Config

	platform    *system.Platform
	application *system.Application

	time     *time.List
	schedule *time.Schedule

	tasks      []uint
	multiplier []float64
	marginals  []probability.Inverter

	nc uint
	nt uint
	nu uint
	nz uint
}

func (p *Problem) String() string {
	return fmt.Sprintf("Problem{cores: %d, tasks: %d, dvars: %d, ivars: %d}",
		p.nc, p.nt, p.nu, p.nz)
}

func NewProblem(config Config) (*Problem, error) {
	platform, application, err := system.Load(config.System)
	if err != nil {
		return nil, err
	}

	nc, nt := uint(len(platform.Cores)), uint(len(application.Tasks))

	time := time.NewList(platform, application)
	schedule := time.Compute(system.NewProfile(platform, application).Mobility)

	c := &config.Probability

	if c.MaxDelay < 0 {
		return nil, errors.New("the maximal delay should be nonnegative")
	}
	if c.CorrLength < 0 {
		return nil, errors.New("the correlation length should be nonnegative")
	}
	if c.VarThreshold <= 0 {
		return nil, errors.New("the variance-reduction threshold should be positive")
	}

	tasks := c.TaskIndex
	if len(tasks) == 0 {
		tasks = make([]uint, nt)
		for i := uint(0); i < nt; i++ {
			tasks[i] = i
		}
	}

	nu := uint(len(tasks))

	C := acorrelation.Compute(application, tasks, c.CorrLength)
	multiplier, nz, err := correlation.Decompose(C, nu, c.VarThreshold)
	if err != nil {
		return nil, err
	}

	marginalizer := aprobability.ParseInverter(c.Marginal)
	if marginalizer == nil {
		return nil, errors.New("invalid marginal distributions")
	}
	marginals := make([]probability.Inverter, nu)
	for i, tid := range tasks {
		duration := platform.Cores[schedule.Mapping[tid]].Time[application.Tasks[tid].Type]
		marginals[i] = marginalizer(0, c.MaxDelay*duration)
	}

	problem := &Problem{
		Config: config,

		platform:    platform,
		application: application,

		time:     time,
		schedule: schedule,

		tasks:      tasks,
		multiplier: multiplier,
		marginals:  marginals,

		nc: nc,
		nt: nt,
		nu: nu,
		nz: nz,
	}

	return problem, nil
}

func (p *Problem) transform(node []float64) []float64 {
	const (
		offset = 1e-8
	)

	z := make([]float64, p.nz)
	u := make([]float64, p.nu)
	d := make([]float64, p.nt)

	// Independent uniform to independent Gaussian
	for i := range z {
		switch node[i] {
		case 0:
			z[i] = standardGaussian.InvCDF(0 + offset)
		case 1:
			z[i] = standardGaussian.InvCDF(1 - offset)
		default:
			z[i] = standardGaussian.InvCDF(node[i])
		}
	}

	// Independent Gaussian to dependent Gaussian
	matrix.Multiply(p.multiplier, z, u, p.nu, p.nz, 1)

	// Dependent Gaussian to dependent uniform to dependent target
	for i, tid := range p.tasks {
		d[tid] = p.marginals[i].InvCDF(standardGaussian.CDF(u[i]))
	}

	return d
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"os"

	. "launchpad.net/gocheck"
	"launchpad.net/goyaml"
	"launchpad.net/juju-core/cmd"
	"launchpad.net/juju-core/juju/testing"
	coretesting "launchpad.net/juju-core/testing"
)

// juju get and set tests (because one needs the other)

type ConfigSuite struct {
	testing.JujuConnSuite
}

var _ = Suite(&ConfigSuite{})

var getTests = []struct {
	service  string
	expected map[string]interface{}
}{
	{
		"dummy-service",
		map[string]interface{}{
			"service": "dummy-service",
			"charm":   "dummy",
			"settings": map[string]interface{}{
				"skill-level": map[string]interface{}{
					"description": "A number indicating skill.",
					"type":        "int",
					"default":     true,
					"value":       nil,
				},
				"title": map[string]interface{}{
					"description": "A descriptive title used for the service.",
					"type":        "string",
					"value":       "My Title",
					"default":     true,
				},
				"username": map[string]interface{}{
					"description": "The name of the initial account (given admin permissions).",
					"type":        "string",
					"value":       "admin001",
					"default":     true,
				},
				"outlook": map[string]interface{}{
					"description": "No default outlook.",
					"type":        "string",
					"default":     true,
					"value":       nil,
				},
			},
		},
	},

	// TODO(dfc) add additional services (need more charms)
	// TODO(dfc) add set tests
}

func (s *ConfigSuite) TestGetConfig(c *C) {
	sch := s.AddTestingCharm(c, "dummy")
	_, err := s.State.AddService("dummy-service", sch)
	c.Assert(err, IsNil)
	for _, t := range getTests {
		ctx := coretesting.Context(c)
		code := cmd.Main(&GetCommand{}, ctx, []string{t.service})
		c.Check(code, Equals, 0)
		c.Assert(ctx.Stderr.(*bytes.Buffer).String(), Equals, "")
		// round trip via goyaml to avoid being sucked into a quagmire of
		// map[interface{}]interface{} vs map[string]interface{}. This is
		// also required if we add json support to this command.
		buf, err := goyaml.Marshal(t.expected)
		c.Assert(err, IsNil)
		expected := make(map[string]interface{})
		err = goyaml.Unmarshal(buf, &expected)
		c.Assert(err, IsNil)

		actual := make(map[string]interface{})
		err = goyaml.Unmarshal(ctx.Stdout.(*bytes.Buffer).Bytes(), &actual)
		c.Assert(err, IsNil)
		c.Assert(actual, DeepEquals, expected)
	}
}

var setTests = []struct {
	about  string
	args   []string               // command to be executed
	expect map[string]interface{} // resulting configuration of the dummy service.
	err    string                 // error regex
}{{
	about: "invalid option",
	args:  []string{"foo", "bar"},
	err:   "error: invalid option: \"foo\"\n",
}, {
	about: "whack option",
	args:  []string{"=bar"},
	err:   "error: invalid option: \"=bar\"\n",
}, {
	about: "--config missing",
	args:  []string{"--config", "missing.yaml"},
	err:   "error.*no such file or directory\n",
}, {
	about: "set with options",
	args:  []string{"username=hello"},
	expect: map[string]interface{}{
		"username": "hello",
	},
}, {
	about: "set with option values containing =",
	args:  []string{"username=hello=foo"},
	expect: map[string]interface{}{
		"username": "hello=foo",
	},
}, {
	about: "--config $FILE test",
	args:  []string{"--config", "testconfig.yaml"},
	expect: map[string]interface{}{
		"username":    "admin001",
		"skill-level": int64(9000), // yaml int types are int64
	},
},
}

func (s *ConfigSuite) TestSetConfig(c *C) {
	sch := s.AddTestingCharm(c, "dummy")
	svc, err := s.State.AddService("dummy-service", sch)
	c.Assert(err, IsNil)
	dir := c.MkDir()
	setupConfigfile(c, dir)
	for i, t := range setTests {
		args := append([]string{"dummy-service"}, t.args...)
		c.Logf("test %d. %s", i, t.about)
		ctx := coretesting.ContextForDir(c, dir)
		code := cmd.Main(&SetCommand{}, ctx, args)
		if t.err != "" {
			c.Check(code, Not(Equals), 0)
			c.Assert(ctx.Stderr.(*bytes.Buffer).String(), Matches, t.err)
		} else {
			c.Check(code, Equals, 0)
			cfg, err := svc.Config()
			c.Assert(err, IsNil)
			c.Assert(cfg.Map(), DeepEquals, t.expect)
		}
	}
}

func setupConfigfile(c *C, dir string) {
	ctx := coretesting.ContextForDir(c, dir)
	path := ctx.AbsPath("testconfig.yaml")
	file, err := os.Create(path)
	c.Assert(err, IsNil)
	_, err = file.Write([]byte("skill-level: 9000\nusername: admin001\n\n"))
	c.Assert(err, IsNil)
	file.Close()
}
<commit_msg>cmd/juju: add config test for non-default value<commit_after>package main

import (
	"bytes"
	"os"

	. "launchpad.net/gocheck"
	"launchpad.net/goyaml"
	"launchpad.net/juju-core/cmd"
	"launchpad.net/juju-core/juju/testing"
	coretesting "launchpad.net/juju-core/testing"
)

// juju get and set tests (because one needs the other)

type ConfigSuite struct {
	testing.JujuConnSuite
}

var _ = Suite(&ConfigSuite{})

var getTests = []struct {
	service  string
	expected map[string]interface{}
}{
	{
		"dummy-service",
		map[string]interface{}{
			"service": "dummy-service",
			"charm":   "dummy",
			"settings": map[string]interface{}{
				"title": map[string]interface{}{
					"description": "A descriptive title used for the service.",
					"type":        "string",
					"value":       "Nearly There",
				},
				"skill-level": map[string]interface{}{
					"description": "A number indicating skill.",
					"type":        "int",
					"default":     true,
					"value":       nil,
				},
				"username": map[string]interface{}{
					"description": "The name of the initial account (given admin permissions).",
					"type":        "string",
					"value":       "admin001",
					"default":     true,
				},
				"outlook": map[string]interface{}{
					"description": "No default outlook.",
					"type":        "string",
					"default":     true,
					"value":       nil,
				},
			},
		},
	},

	// TODO(dfc) add additional services (need more charms)
	// TODO(dfc) add set tests
}

func (s *ConfigSuite) TestGetConfig(c *C) {
	sch := s.AddTestingCharm(c, "dummy")
	svc, err := s.State.AddService("dummy-service", sch)
	c.Assert(err, IsNil)
	err = svc.SetConfig(map[string]string{
		"title": "Nearly There",
	})
	c.Assert(err, IsNil)
	for _, t := range getTests {
		ctx := coretesting.Context(c)
		code := cmd.Main(&GetCommand{}, ctx, []string{t.service})
		c.Check(code, Equals, 0)
		c.Assert(ctx.Stderr.(*bytes.Buffer).String(), Equals, "")
		// round trip via goyaml to avoid being sucked into a quagmire of
		// map[interface{}]interface{} vs map[string]interface{}. This is
		// also required if we add json support to this command.
		buf, err := goyaml.Marshal(t.expected)
		c.Assert(err, IsNil)
		expected := make(map[string]interface{})
		err = goyaml.Unmarshal(buf, &expected)
		c.Assert(err, IsNil)

		actual := make(map[string]interface{})
		err = goyaml.Unmarshal(ctx.Stdout.(*bytes.Buffer).Bytes(), &actual)
		c.Assert(err, IsNil)
		c.Assert(actual, DeepEquals, expected)
	}
}

var setTests = []struct {
	about  string
	args   []string               // command to be executed
	expect map[string]interface{} // resulting configuration of the dummy service.
	err    string                 // error regex
}{{
	about: "invalid option",
	args:  []string{"foo", "bar"},
	err:   "error: invalid option: \"foo\"\n",
}, {
	about: "whack option",
	args:  []string{"=bar"},
	err:   "error: invalid option: \"=bar\"\n",
}, {
	about: "--config missing",
	args:  []string{"--config", "missing.yaml"},
	err:   "error.*no such file or directory\n",
}, {
	about: "set with options",
	args:  []string{"username=hello"},
	expect: map[string]interface{}{
		"username": "hello",
	},
}, {
	about: "set with option values containing =",
	args:  []string{"username=hello=foo"},
	expect: map[string]interface{}{
		"username": "hello=foo",
	},
}, {
	about: "--config $FILE test",
	args:  []string{"--config", "testconfig.yaml"},
	expect: map[string]interface{}{
		"username":    "admin001",
		"skill-level": int64(9000), // yaml int types are int64
	},
},
}

func (s *ConfigSuite) TestSetConfig(c *C) {
	sch := s.AddTestingCharm(c, "dummy")
	svc, err := s.State.AddService("dummy-service", sch)
	c.Assert(err, IsNil)
	dir := c.MkDir()
	setupConfigfile(c, dir)
	for i, t := range setTests {
		args := append([]string{"dummy-service"}, t.args...)
		c.Logf("test %d. %s", i, t.about)
		ctx := coretesting.ContextForDir(c, dir)
		code := cmd.Main(&SetCommand{}, ctx, args)
		if t.err != "" {
			c.Check(code, Not(Equals), 0)
			c.Assert(ctx.Stderr.(*bytes.Buffer).String(), Matches, t.err)
		} else {
			c.Check(code, Equals, 0)
			cfg, err := svc.Config()
			c.Assert(err, IsNil)
			c.Assert(cfg.Map(), DeepEquals, t.expect)
		}
	}
}

func setupConfigfile(c *C, dir string) {
	ctx := coretesting.ContextForDir(c, dir)
	path := ctx.AbsPath("testconfig.yaml")
	file, err := os.Create(path)
	c.Assert(err, IsNil)
	_, err = file.Write([]byte("skill-level: 9000\nusername: admin001\n\n"))
	c.Assert(err, IsNil)
	file.Close()
}
<|endoftext|>


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

// Implements ruby/bundle buildpack.
// The bundle buildpack installs dependencies using bundle.
package main

import (
	"fmt"
	"path/filepath"

	"github.com/GoogleCloudPlatform/buildpacks/pkg/buildererror"
	"github.com/GoogleCloudPlatform/buildpacks/pkg/cache"
	gcp "github.com/GoogleCloudPlatform/buildpacks/pkg/gcpbuildpack"
	"github.com/buildpacks/libcnb"
)

const (
	layerName         = "gems"
	dependencyHashKey = "dependency_hash"
	rubyVersionKey    = "ruby_version"
)

func main() {
	gcp.Main(detectFn, buildFn)
}

func detectFn(ctx *gcp.Context) (gcp.DetectResult, error) {
	gemfileExists, err := ctx.FileExists("Gemfile")
	if err != nil {
		return nil, err
	}
	if gemfileExists {
		return gcp.OptInFileFound("Gemfile"), nil
	}
	gemsRbExists, err := ctx.FileExists("gems.rb")
	if err != nil {
		return nil, err
	}
	if gemsRbExists {
		return gcp.OptInFileFound("gems.rb"), nil
	}
	return gcp.OptOut("no Gemfile or gems.rb found"), nil
}

func buildFn(ctx *gcp.Context) error {
	var lockFile string
	hasGemfile, err := ctx.FileExists("Gemfile")
	if err != nil {
		return err
	}
	hasGemsRB, err := ctx.FileExists("gems.rb")
	if err != nil {
		return err
	}
	if hasGemfile {
		if hasGemsRB {
			ctx.Warnf("Gemfile and gems.rb both exist. Using Gemfile.")
		}
		gemfileLockExists, err := ctx.FileExists("Gemfile.lock")
		if err != nil {
			return err
		}
		if !gemfileLockExists {
			return buildererror.Errorf(buildererror.StatusFailedPrecondition, "Could not find Gemfile.lock file in your app. Please make sure your bundle is up to date before deploying.")
		}
		lockFile = "Gemfile.lock"
	} else if hasGemsRB {
		gemsLockedExists, err := ctx.FileExists("gems.locked")
		if err != nil {
			return err
		}
		if !gemsLockedExists {
			return buildererror.Errorf(buildererror.StatusFailedPrecondition, "Could not find gems.locked file in your app. Please make sure your bundle is up to date before deploying.")
		}
		lockFile = "gems.locked"
	}

	// Remove any user-provided local bundle config and cache that can interfere with the build process.
	if err := ctx.RemoveAll(".bundle"); err != nil {
		return err
	}

	deps, err := ctx.Layer(layerName, gcp.BuildLayer, gcp.CacheLayer, gcp.LaunchLayer)
	if err != nil {
		return fmt.Errorf("creating %v layer: %w", layerName, err)
	}

	// This layer directory contains the files installed by bundler into the application .bundle directory
	bundleOutput := filepath.Join(deps.Path, ".bundle")

	cached, err := checkCache(ctx, deps, cache.WithFiles(lockFile))
	if err != nil {
		return fmt.Errorf("checking cache: %w", err)
	}

	localGemsDir := filepath.Join(".bundle", "gems")
	localBinDir := filepath.Join(".bundle", "bin")

	// Ensure the GCP runtime platform is present in the lockfile. This is needed for Bundler >= 2.2, in case the user's lockfile is specific to a different platform.
	ctx.Exec([]string{"bundle", "config", "--local", "without", "development test"}, gcp.WithUserAttribution)
	ctx.Exec([]string{"bundle", "config", "--local", "path", localGemsDir}, gcp.WithUserAttribution)

	// This line will override user provided BUNDLED WITH in the Gemfile.lock
	// It'll use the currently activated bundler version instead
	// This was a change in bundler 2.1+
	// https://github.com/rubygems/rubygems/issues/5683
	ctx.Exec([]string{"bundle", "lock", "--add-platform", "x86_64-linux"}, gcp.WithUserAttribution)
	ctx.Exec([]string{"bundle", "lock", "--add-platform", "ruby"}, gcp.WithUserAttribution)
	if err := ctx.RemoveAll(".bundle"); err != nil {
		return err
	}

	if cached {
		ctx.CacheHit(layerName)
	} else {
		ctx.CacheMiss(layerName)

		// Install the bundle locally into .bundle/gems
		ctx.Exec([]string{"bundle", "config", "--local", "deployment", "true"}, gcp.WithUserAttribution)
		ctx.Exec([]string{"bundle", "config", "--local", "frozen", "true"}, gcp.WithUserAttribution)
		ctx.Exec([]string{"bundle", "config", "--local", "without", "development test"}, gcp.WithUserAttribution)
		ctx.Exec([]string{"bundle", "config", "--local", "path", localGemsDir}, gcp.WithUserAttribution)
		ctx.Exec([]string{"bundle", "install"},
			gcp.WithEnv("NOKOGIRI_USE_SYSTEM_LIBRARIES=1", "MALLOC_ARENA_MAX=2", "LANG=C.utf8"), gcp.WithUserAttribution)

		// Find any gem-installed binary directory and symlink as a static path
		foundBinDirs, err := ctx.Glob(".bundle/gems/ruby/*/bin")
		if err != nil {
			return fmt.Errorf("finding bin dirs: %w", err)
		}
		if len(foundBinDirs) > 1 {
			return fmt.Errorf("unexpected multiple gem bin dirs: %v", foundBinDirs)
		} else if len(foundBinDirs) == 1 {
			if err := ctx.Symlink(filepath.Join(ctx.ApplicationRoot(), foundBinDirs[0]), localBinDir); err != nil {
				return err
			}
		}

		// Move the built .bundle directory into the layer
		if err := ctx.RemoveAll(bundleOutput); err != nil {
			return err
		}
		ctx.Exec([]string{"mv", ".bundle", bundleOutput}, gcp.WithUserTimingAttribution)
	}

	// Always link local .bundle directory to the actual installation stored in the layer.
	if err := ctx.Symlink(bundleOutput, ".bundle"); err != nil {
		return err
	}

	return nil
}

// checkCache checks whether cached dependencies exist and match.
func checkCache(ctx *gcp.Context, l *libcnb.Layer, opts ...cache.Option) (bool, error) {
	currentRubyVersion := ctx.Exec([]string{"ruby", "-v"}).Stdout
	opts = append(opts, cache.WithStrings(currentRubyVersion))
	currentDependencyHash, err := cache.Hash(ctx, opts...)
	if err != nil {
		return false, fmt.Errorf("computing dependency hash: %v", err)
	}

	// Perform install, skipping if the dependency hash matches existing metadata.
	metaDependencyHash := ctx.GetMetadata(l, dependencyHashKey)
	ctx.Debugf("Current dependency hash: %q", currentDependencyHash)
	ctx.Debugf("  Cache dependency hash: %q", metaDependencyHash)
	if currentDependencyHash == metaDependencyHash {
		ctx.Logf("Dependencies cache hit, skipping installation.")
		return true, nil
	}

	if metaDependencyHash == "" {
		ctx.Debugf("No metadata found from a previous build, skipping cache.")
	}
	ctx.Logf("Installing application dependencies.")

	// Update the layer metadata.
	ctx.SetMetadata(l, dependencyHashKey, currentDependencyHash)
	ctx.SetMetadata(l, rubyVersionKey, currentRubyVersion)

	return false, nil
}
<commit_msg>Migrate the ruby buildpack and pkg/ruby from ctx.Exec(...) to ctx.ExecWithErr(...) to reduce the usage of os.Exit(...) and enable easier unit testing<commit_after>// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Implements ruby/bundle buildpack.
// The bundle buildpack installs dependencies using bundle.
package main

import (
	"fmt"
	"path/filepath"

	"github.com/GoogleCloudPlatform/buildpacks/pkg/buildererror"
	"github.com/GoogleCloudPlatform/buildpacks/pkg/cache"
	gcp "github.com/GoogleCloudPlatform/buildpacks/pkg/gcpbuildpack"
	"github.com/buildpacks/libcnb"
)

const (
	layerName         = "gems"
	dependencyHashKey = "dependency_hash"
	rubyVersionKey    = "ruby_version"
)

func main() {
	gcp.Main(detectFn, buildFn)
}

func detectFn(ctx *gcp.Context) (gcp.DetectResult, error) {
	gemfileExists, err := ctx.FileExists("Gemfile")
	if err != nil {
		return nil, err
	}
	if gemfileExists {
		return gcp.OptInFileFound("Gemfile"), nil
	}
	gemsRbExists, err := ctx.FileExists("gems.rb")
	if err != nil {
		return nil, err
	}
	if gemsRbExists {
		return gcp.OptInFileFound("gems.rb"), nil
	}
	return gcp.OptOut("no Gemfile or gems.rb found"), nil
}

func buildFn(ctx *gcp.Context) error {
	var lockFile string
	hasGemfile, err := ctx.FileExists("Gemfile")
	if err != nil {
		return err
	}
	hasGemsRB, err := ctx.FileExists("gems.rb")
	if err != nil {
		return err
	}
	if hasGemfile {
		if hasGemsRB {
			ctx.Warnf("Gemfile and gems.rb both exist. Using Gemfile.")
		}
		gemfileLockExists, err := ctx.FileExists("Gemfile.lock")
		if err != nil {
			return err
		}
		if !gemfileLockExists {
			return buildererror.Errorf(buildererror.StatusFailedPrecondition, "Could not find Gemfile.lock file in your app. Please make sure your bundle is up to date before deploying.")
		}
		lockFile = "Gemfile.lock"
	} else if hasGemsRB {
		gemsLockedExists, err := ctx.FileExists("gems.locked")
		if err != nil {
			return err
		}
		if !gemsLockedExists {
			return buildererror.Errorf(buildererror.StatusFailedPrecondition, "Could not find gems.locked file in your app. Please make sure your bundle is up to date before deploying.")
		}
		lockFile = "gems.locked"
	}

	// Remove any user-provided local bundle config and cache that can interfere with the build process.
	if err := ctx.RemoveAll(".bundle"); err != nil {
		return err
	}

	deps, err := ctx.Layer(layerName, gcp.BuildLayer, gcp.CacheLayer, gcp.LaunchLayer)
	if err != nil {
		return fmt.Errorf("creating %v layer: %w", layerName, err)
	}

	// This layer directory contains the files installed by bundler into the application .bundle directory
	bundleOutput := filepath.Join(deps.Path, ".bundle")

	cached, err := checkCache(ctx, deps, cache.WithFiles(lockFile))
	if err != nil {
		return fmt.Errorf("checking cache: %w", err)
	}

	localGemsDir := filepath.Join(".bundle", "gems")
	localBinDir := filepath.Join(".bundle", "bin")

	// Ensure the GCP runtime platform is present in the lockfile. This is needed for Bundler >= 2.2, in case the user's lockfile is specific to a different platform.
	if _, err := ctx.ExecWithErr([]string{"bundle", "config", "--local", "without", "development test"}, gcp.WithUserAttribution); err != nil {
		return err
	}
	if _, err := ctx.ExecWithErr([]string{"bundle", "config", "--local", "path", localGemsDir}, gcp.WithUserAttribution); err != nil {
		return err
	}

	// This line will override user provided BUNDLED WITH in the Gemfile.lock
	// It'll use the currently activated bundler version instead
	// This was a change in bundler 2.1+
	// https://github.com/rubygems/rubygems/issues/5683
	if _, err := ctx.ExecWithErr([]string{"bundle", "lock", "--add-platform", "x86_64-linux"}, gcp.WithUserAttribution); err != nil {
		return err
	}
	if _, err := ctx.ExecWithErr([]string{"bundle", "lock", "--add-platform", "ruby"}, gcp.WithUserAttribution); err != nil {
		return err
	}
	if err := ctx.RemoveAll(".bundle"); err != nil {
		return err
	}

	if cached {
		ctx.CacheHit(layerName)
	} else {
		ctx.CacheMiss(layerName)

		// Install the bundle locally into .bundle/gems
		if _, err := ctx.ExecWithErr([]string{"bundle", "config", "--local", "deployment", "true"}, gcp.WithUserAttribution); err != nil {
			return err
		}
		if _, err := ctx.ExecWithErr([]string{"bundle", "config", "--local", "frozen", "true"}, gcp.WithUserAttribution); err != nil {
			return err
		}
		if _, err := ctx.ExecWithErr([]string{"bundle", "config", "--local", "without", "development test"}, gcp.WithUserAttribution); err != nil {
			return err
		}
		if _, err := ctx.ExecWithErr([]string{"bundle", "config", "--local", "path", localGemsDir}, gcp.WithUserAttribution); err != nil {
			return err
		}
		if _, err := ctx.ExecWithErr([]string{"bundle", "install"},
			gcp.WithEnv("NOKOGIRI_USE_SYSTEM_LIBRARIES=1", "MALLOC_ARENA_MAX=2", "LANG=C.utf8"), gcp.WithUserAttribution); err != nil {
			return err
		}

		// Find any gem-installed binary directory and symlink as a static path
		foundBinDirs, err := ctx.Glob(".bundle/gems/ruby/*/bin")
		if err != nil {
			return fmt.Errorf("finding bin dirs: %w", err)
		}
		if len(foundBinDirs) > 1 {
			return fmt.Errorf("unexpected multiple gem bin dirs: %v", foundBinDirs)
		} else if len(foundBinDirs) == 1 {
			if err := ctx.Symlink(filepath.Join(ctx.ApplicationRoot(), foundBinDirs[0]), localBinDir); err != nil {
				return err
			}
		}

		// Move the built .bundle directory into the layer
		if err := ctx.RemoveAll(bundleOutput); err != nil {
			return err
		}
		if _, err := ctx.ExecWithErr([]string{"mv", ".bundle", bundleOutput}, gcp.WithUserTimingAttribution); err != nil {
			return err
		}
	}

	// Always link local .bundle directory to the actual installation stored in the layer.
	if err := ctx.Symlink(bundleOutput, ".bundle"); err != nil {
		return err
	}

	return nil
}

// checkCache checks whether cached dependencies exist and match.
func checkCache(ctx *gcp.Context, l *libcnb.Layer, opts ...cache.Option) (bool, error) {
	result, err := ctx.ExecWithErr([]string{"ruby", "-v"})
	if err != nil {
		return false, err
	}
	currentRubyVersion := result.Stdout
	opts = append(opts, cache.WithStrings(currentRubyVersion))
	currentDependencyHash, err := cache.Hash(ctx, opts...)
	if err != nil {
		return false, fmt.Errorf("computing dependency hash: %v", err)
	}

	// Perform install, skipping if the dependency hash matches existing metadata.
	metaDependencyHash := ctx.GetMetadata(l, dependencyHashKey)
	ctx.Debugf("Current dependency hash: %q", currentDependencyHash)
	ctx.Debugf("  Cache dependency hash: %q", metaDependencyHash)
	if currentDependencyHash == metaDependencyHash {
		ctx.Logf("Dependencies cache hit, skipping installation.")
		return true, nil
	}

	if metaDependencyHash == "" {
		ctx.Debugf("No metadata found from a previous build, skipping cache.")
	}
	ctx.Logf("Installing application dependencies.")

	// Update the layer metadata.
	ctx.SetMetadata(l, dependencyHashKey, currentDependencyHash)
	ctx.SetMetadata(l, rubyVersionKey, currentRubyVersion)

	return false, nil
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"log"
	"os"
	"text/tabwriter"

	"github.com/dlespiau/x86db"
)

func nasmOpcodeToPlan9(op string) string {
	/*
	 * SSE
	 */
	switch op {
	// The condition is encoded as an imm8 operand of CMPPS
	case "CMPEQPS", "CMPLTPS", "CMPLEPS", "CMPUNORDPS", "CMPNEQPS", "CMPNLTPS",
		"CMPNLEPS", "CMPORDPS":
		return "CMPPS"
	// The condition is encoded as an imm8 operand of CMPSS.
	case "CMPEQSS", "CMPLTSS", "CMPLESS", "CMPUNORDSS", "CMPNEQSS", "CMPNLTSS",
		"CMPNLESS", "CMPORDSS":
		return "CMPSS"
	case "CVTSI2SS":
		return "CVTSL2SS"
	case "CVTSS2SI":
		return "CVTSS2SL"
	case "CVTTSS2SI":
		return "CVTTSS2SL"
	}

	/*
	 * PCLMULQDQ
	 */
	switch op {
	case "PCLMULLQLQDQ", "PCLMULHQLQDQ", "PCLMULLQHQDQ", "PCLMULHQHQDQ":
		return "PCLMULQDQ"
	}

	/*
	 * SSE2
	 */
	switch op {
	// The condition is encoded as an imm8 operand of CMPPD
	case "CMPEQPD", "CMPLTPD", "CMPLEPD", "CMPUNORDPD", "CMPNEQPD", "CMPNLTPD",
		"CMPNLEPD", "CMPORDPD":
		return "CMPPD"
	// The condition is encoded as an imm8 operand of CMPSD.
	case "CMPEQSD", "CMPLTSD", "CMPLESD", "CMPUNORDSD", "CMPNEQSD", "CMPNLTSD",
		"CMPNLESD", "CMPORDSD":
		return "CMPSD"
	}

	return op
}

func isAlreadyKnown(name string) bool {
	name = nasmOpcodeToPlan9(name)
	for _, opcode := range Anames {
		if name == opcode {
			return true
		}
	}
	return false
}

func isAlreadyTested(name string) bool {
	name = nasmOpcodeToPlan9(name)
	_, ok := testedMap[name]
	return ok
}

func main() {
	db := x86db.NewDB(os.Args[1])

	err := db.Open()
	if err != nil {
		log.Fatal(err)
	}
	defer db.Close()

	// SSE2 instructions, not already known by the Go's cmd/internal/obj package.
	insns := db.FindByExtension(x86db.ExtensionSSE2).Where(func(insn x86db.Instruction) bool {
		return !isAlreadyKnown(insn.Name)
	})

	w := tabwriter.NewWriter(os.Stdout, 0, 0, 1, ' ', 0)
	for _, insn := range insns {
		fmt.Fprintf(w, "%s\t%s\t%s\t%s\n", insn.Name, insn.Operands, insn.Pattern, insn.Flags)
	}
	w.Flush()
}
<commit_msg>gogen: PSUBD is PSUBL or the opposite, not sure!<commit_after>package main

import (
	"fmt"
	"log"
	"os"
	"text/tabwriter"

	"github.com/dlespiau/x86db"
)

func nasmOpcodeToPlan9(op string) string {
	/*
	 * SSE
	 */
	switch op {
	// The condition is encoded as an imm8 operand of CMPPS
	case "CMPEQPS", "CMPLTPS", "CMPLEPS", "CMPUNORDPS", "CMPNEQPS", "CMPNLTPS",
		"CMPNLEPS", "CMPORDPS":
		return "CMPPS"
	// The condition is encoded as an imm8 operand of CMPSS.
	case "CMPEQSS", "CMPLTSS", "CMPLESS", "CMPUNORDSS", "CMPNEQSS", "CMPNLTSS",
		"CMPNLESS", "CMPORDSS":
		return "CMPSS"
	case "CVTSI2SS":
		return "CVTSL2SS"
	case "CVTSS2SI":
		return "CVTSS2SL"
	case "CVTTSS2SI":
		return "CVTTSS2SL"
	}

	/*
	 * PCLMULQDQ
	 */
	switch op {
	case "PCLMULLQLQDQ", "PCLMULHQLQDQ", "PCLMULLQHQDQ", "PCLMULHQHQDQ":
		return "PCLMULQDQ"
	}

	/*
	 * SSE2
	 */
	switch op {
	// The condition is encoded as an imm8 operand of CMPPD
	case "CMPEQPD", "CMPLTPD", "CMPLEPD", "CMPUNORDPD", "CMPNEQPD", "CMPNLTPD",
		"CMPNLEPD", "CMPORDPD":
		return "CMPPD"
	// The condition is encoded as an imm8 operand of CMPSD.
	case "CMPEQSD", "CMPLTSD", "CMPLESD", "CMPUNORDSD", "CMPNEQSD", "CMPNLTSD",
		"CMPNLESD", "CMPORDSD":
		return "CMPSD"
	// D (double word) has been replaced by L (Long)
	case "PSUBD":
		return "PSUBL"
	}

	return op
}

func isAlreadyKnown(name string) bool {
	name = nasmOpcodeToPlan9(name)
	for _, opcode := range Anames {
		if name == opcode {
			return true
		}
	}
	return false
}

func isAlreadyTested(name string) bool {
	name = nasmOpcodeToPlan9(name)
	_, ok := testedMap[name]
	return ok
}

func main() {
	db := x86db.NewDB(os.Args[1])

	err := db.Open()
	if err != nil {
		log.Fatal(err)
	}
	defer db.Close()

	// SSE2 instructions, not already known by the Go's cmd/internal/obj package.
	insns := db.FindByExtension(x86db.ExtensionSSE2).Where(func(insn x86db.Instruction) bool {
		return !isAlreadyKnown(insn.Name)
	})

	w := tabwriter.NewWriter(os.Stdout, 0, 0, 1, ' ', 0)
	for _, insn := range insns {
		fmt.Fprintf(w, "%s\t%s\t%s\t%s\n", insn.Name, insn.Operands, insn.Pattern, insn.Flags)
	}
	w.Flush()
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"github.com/streadway/amqp"
	"log"
	//"os"
	"io/ioutil"
	"net/http"
)

func failOnError(err error, msg string) {
	if err != nil {
		log.Fatalf("%s: %s", msg, err)
		panic(fmt.Sprintf("%s: %s", msg, err))
	}
}

func getSensors(aggregator string) []byte {
	//var sensors []Sensor
	resp, _ := http.Get("http://" + aggregator + "/sensors")
	body, _ := ioutil.ReadAll(resp.Body)
	/*
		json.Unmarshal(body, &sensors)

		for _, sensor := range sensors {
			log.Println(sensor)
		}
	*/
	return (body)
}

func main() {

	// Aggregators to poll

	aggregators := []string{"172.17.8.101:9005", "172.17.8.101:9004", "172.17.8.101:9003", "172.17.8.101:9002", "172.17.8.101:9001", "172.17.8.101:9000"}

	rabbitHost := "amqp://guest:guest@172.17.8.102:5672/"

	conn, err := amqp.Dial(rabbitHost)
	failOnError(err, "Failed to connect to RabbitMQ")
	defer conn.Close()

	ch, err := conn.Channel()
	failOnError(err, "Failed to open a channel")
	defer ch.Close()

	err = ch.ExchangeDeclare(
		"logs",   // name
		"fanout", // type
		true,     // durable
		false,    // auto-deleted
		false,    // internal
		false,    // no-wait
		nil,      // arguments
	)
	failOnError(err, "Failed to declare an exchange")

	for _, aggregator := range aggregators {

		body := getSensors(aggregator)
		log.Println("Starting on " + aggregator)

		err = ch.Publish(
			"logs", // exchange
			"",     // routing key
			false,  // mandatory
			false,  // immediate
			amqp.Publishing{
				ContentType: "text/plain",
				Body:        []byte(body),
			})
		failOnError(err, "Failed to publish a message")

		//log.Printf(" [x] Sent %s", body)
	}
}

<commit_msg>update<commit_after>package main

import (
	"fmt"
	"github.com/streadway/amqp"
	"log"
	//"os"
	"io/ioutil"
	"net/http"
)

func failOnError(err error, msg string) {
	if err != nil {
		log.Fatalf("%s: %s", msg, err)
		panic(fmt.Sprintf("%s: %s", msg, err))
	}
}

func getSensors(aggregator string) []byte {
	//var sensors []Sensor
	resp, _ := http.Get("http://" + aggregator + "/sensors")
	body, _ := ioutil.ReadAll(resp.Body)
	/*
		json.Unmarshal(body, &sensors)

		for _, sensor := range sensors {
			log.Println(sensor)
		}
	*/
	return (body)
}

func main() {

	// Aggregators to poll

	aggregators := []string{"192.168.1.101:9000", "192.168.1.101:9001", "192.168.1.101:9002", "192.168.1.101:9003", "192.168.1.101:9004", "192.168.1.101:9005", "192.168.1.101:9006", "192.168.1.101:9007", "192.168.1.101:9008", "192.168.1.101:9009"}

	rabbitHost := "amqp://guest:guest@10.100.49.105:5672/"

	conn, err := amqp.Dial(rabbitHost)
	failOnError(err, "Failed to connect to RabbitMQ")
	defer conn.Close()

	ch, err := conn.Channel()
	failOnError(err, "Failed to open a channel")
	defer ch.Close()

	for _, aggregator := range aggregators {

		body := getSensors(aggregator)
		log.Println("Starting on " + aggregator)

		err = ch.Publish(
			"",                // exchange
			"ingestion_queue", // routing key
			false,             // mandatory
			false,             // immediate
			amqp.Publishing{
				DeliveryMode: amqp.Persistent,
				ContentType:  "text/plain",
				Body:         []byte(body),
			})
		failOnError(err, "Failed to publish a message")

		//log.Printf(" [x] Sent %s", body)
	}
}
<|endoftext|>


<commit_before>package agent

import (
	"encoding/json"
	"fmt"
	"github.com/BurntSushi/toml"
	"github.com/mitchellh/mapstructure"
	"io"
	"os"
	"path/filepath"
	"sort"
	"strings"
)

// DefaultConfig contains the defaults for configurations.
var DefaultConfig = &Config{
	LogLevel: "INFO",
	RPCAddr:  "127.0.0.1:7373",
}

type dirEnts []os.FileInfo

// Config is the configuration that can be set for an Agent. Some of these
// configurations are exposed as command-line flags to `serf agent`, whereas
// many of the more advanced configurations can only be set by creating
// a configuration file.
type Config struct {

	// ConfigDir is the directory to load process configurations from. This
	// directory will be watched for changes.
	ConfigDir string `mapstructure:"config_dir"`

	// LogLevel is the level of the logs to output.
	// This can be updated during a reload.
	LogLevel string `mapstructure:"log_level"`

	// RPCAddr is the address and port to listen on for the agent's RPC
	// interface.
	RPCAddr string `mapstructure:"rpc_addr"`

	// LogEntriesToken is used to authenticate the logging from the agent to LE.
	// This is only used for sending agent/watchdog logs, not supervised process
	// logs.
	LogEntriesToken string `mapstructure:"log_entries_token"`

	// loggingOutlet is the outlet to send logs to
	loggingOutlet io.Writer
}

// DecodeConfigFromJSON decodes a JSON config
func DecodeConfigFromJSON(r io.Reader) (*Config, error) {
	var raw interface{}
	dec := json.NewDecoder(r)
	if err := dec.Decode(&raw); err != nil {
		return nil, err
	}

	// Decode
	var md mapstructure.Metadata
	var result Config
	msdec, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{
		Metadata: &md,
		Result:   &result,
	})
	if err != nil {
		return nil, err
	}

	if err := msdec.Decode(raw); err != nil {
		return nil, err
	}

	return &result, nil
}

// DecodeConfigFromTOML decodes a TOML config
func DecodeConfigFromTOML(r io.Reader) (*Config, error) {
	var raw interface{}

	_, err := toml.DecodeReader(r, &raw)
	if err != nil {
		return nil, err
	}

	// Decode
	var md mapstructure.Metadata
	var result Config
	msdec, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{
		Metadata: &md,
		Result:   &result,
	})
	if err != nil {
		return nil, err
	}

	if err := msdec.Decode(raw); err != nil {
		return nil, err
	}

	return &result, nil
}

// MergeConfig merges two configurations together to make a single new
// configuration.
func MergeConfig(a, b *Config) *Config {
	var result Config = *a

	// Copy the strings if they're set
	if b.ConfigDir != "" {
		result.ConfigDir = b.ConfigDir
	}

	if b.LogEntriesToken != "" {
		result.LogEntriesToken = b.LogEntriesToken
	}

	if b.LogLevel != "" {
		result.LogLevel = b.LogLevel
	}

	if b.RPCAddr != "" {
		result.RPCAddr = b.RPCAddr
	}

	return &result
}

// ReadConfigPaths reads the paths in the given order to load configurations.
// The paths can be to files or directories. If the path is a directory,
// we read one directory deep and read any files ending in ".json" as
// configuration files.
func ReadConfigPaths(paths []string) (*Config, error) {
	result := new(Config)
	for _, path := range paths {
		f, err := os.Open(path)
		if err != nil {
			return nil, fmt.Errorf("error reading '%s': %s", path, err)
		}

		fi, err := f.Stat()
		if err != nil {
			f.Close()
			return nil, fmt.Errorf("error reading '%s': %s", path, err)
		}

		if !fi.IsDir() {
			config, err := decodeConfigFile(path, fi)

			if err != nil {
				return nil, err
			}

			result = MergeConfig(result, config)
			continue
		}

		contents, err := f.Readdir(-1)
		f.Close()
		if err != nil {
			return nil, fmt.Errorf("error reading '%s': %s", path, err)
		}

		// Sort the contents, ensures lexical order
		sort.Sort(dirEnts(contents))

		for _, fi := range contents {
			// Don't recursively read contents
			if fi.IsDir() {
				continue
			}

			path := filepath.Join(path, fi.Name())

			config, err := decodeConfigFile(path, fi)
			if err != nil {
				return nil, err
			}

			result = MergeConfig(result, config)
		}
	}

	return result, nil
}

func decodeConfigFile(path string, fi os.FileInfo) (*Config, error) {
	result := new(Config)
	var err error

	f, err := os.Open(path)
	defer f.Close()
	if err != nil {
		return nil, fmt.Errorf("error reading '%s': %s", path, err)
	}

	// If it isn't a JSON file, ignore it
	if strings.HasSuffix(fi.Name(), ".json") {
		result, err = DecodeConfigFromJSON(f)

		if err != nil {
			return nil, fmt.Errorf("error decoding '%s': %s", path, err)
		}
	} else if strings.HasSuffix(fi.Name(), ".toml") {
		result, err = DecodeConfigFromTOML(f)

		if err != nil {
			return nil, fmt.Errorf("error decoding '%s': %s", path, err)
		}
	} else {

		// Try decoding with json then toml, else fail
		result, err = DecodeConfigFromJSON(f)
		if err != nil {
			f.Close()
			f, err = os.Open(path)
			defer f.Close()
			if err != nil {
				return nil, fmt.Errorf("error reading '%s': %s", path, err)
			}

			result, err = DecodeConfigFromTOML(f)
			if err != nil {
				return nil, fmt.Errorf("error decoding '%s': unknown format", path)
			}
		}
		f.Close()
	}

	return result, nil
}

// Implement the sort interface for dirEnts
func (d dirEnts) Len() int {
	return len(d)
}

func (d dirEnts) Less(i, j int) bool {
	return d[i].Name() < d[j].Name()
}

func (d dirEnts) Swap(i, j int) {
	d[i], d[j] = d[j], d[i]
}
<commit_msg>Removed currently unimplemented config options<commit_after>package agent

import (
	"encoding/json"
	"fmt"
	"github.com/BurntSushi/toml"
	"github.com/mitchellh/mapstructure"
	"io"
	"os"
	"path/filepath"
	"sort"
	"strings"
)

// DefaultConfig contains the defaults for configurations.
var DefaultConfig = &Config{
	LogLevel: "INFO",
	RPCAddr:  "127.0.0.1:6673",
}

type dirEnts []os.FileInfo

// Config is the configuration that can be set for an Agent. Some of these
// configurations are exposed as command-line flags to `serf agent`, whereas
// many of the more advanced configurations can only be set by creating
// a configuration file.
type Config struct {

	// LogLevel is the level of the logs to output.
	// This can be updated during a reload.
	LogLevel string `mapstructure:"log_level"`

	// RPCAddr is the address and port to listen on for the agent's RPC
	// interface.
	RPCAddr string `mapstructure:"rpc_addr"`

	// // ConfigDir is the directory to load process configurations from. This
	// // directory will be watched for changes.
	// ConfigDir string `mapstructure:"config_dir"`
	//
	// // LogEntriesToken is used to authenticate the logging from the agent to LE.
	// // This is only used for sending agent/watchdog logs, not supervised process
	// // logs.
	// LogEntriesToken string `mapstructure:"log_entries_token"`

	// // loggingOutlet is the outlet to send logs to
	// loggingOutlet io.Writer
}

// DecodeConfigFromJSON decodes a JSON config
func DecodeConfigFromJSON(r io.Reader) (*Config, error) {
	var raw interface{}
	dec := json.NewDecoder(r)
	if err := dec.Decode(&raw); err != nil {
		return nil, err
	}

	// Decode
	var md mapstructure.Metadata
	var result Config
	msdec, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{
		Metadata: &md,
		Result:   &result,
	})
	if err != nil {
		return nil, err
	}

	if err := msdec.Decode(raw); err != nil {
		return nil, err
	}

	return &result, nil
}

// DecodeConfigFromTOML decodes a TOML config
func DecodeConfigFromTOML(r io.Reader) (*Config, error) {
	var raw interface{}

	_, err := toml.DecodeReader(r, &raw)
	if err != nil {
		return nil, err
	}

	// Decode
	var md mapstructure.Metadata
	var result Config
	msdec, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{
		Metadata: &md,
		Result:   &result,
	})
	if err != nil {
		return nil, err
	}

	if err := msdec.Decode(raw); err != nil {
		return nil, err
	}

	return &result, nil
}

// MergeConfig merges two configurations together to make a single new
// configuration.
func MergeConfig(a, b *Config) *Config {
	var result Config = *a

	// // Copy the strings if they're set
	// if b.ConfigDir != "" {
	// 	result.ConfigDir = b.ConfigDir
	// }

	// if b.LogEntriesToken != "" {
	// 	result.LogEntriesToken = b.LogEntriesToken
	// }

	if b.LogLevel != "" {
		result.LogLevel = b.LogLevel
	}

	if b.RPCAddr != "" {
		result.RPCAddr = b.RPCAddr
	}

	return &result
}

// ReadConfigPaths reads the paths in the given order to load configurations.
// The paths can be to files or directories. If the path is a directory,
// we read one directory deep and read any files ending in ".json" as
// configuration files.
func ReadConfigPaths(paths []string) (*Config, error) {
	result := new(Config)
	for _, path := range paths {
		f, err := os.Open(path)
		if err != nil {
			return nil, fmt.Errorf("error reading '%s': %s", path, err)
		}

		fi, err := f.Stat()
		if err != nil {
			f.Close()
			return nil, fmt.Errorf("error reading '%s': %s", path, err)
		}

		if !fi.IsDir() {
			config, err := decodeConfigFile(path, fi)

			if err != nil {
				return nil, err
			}

			result = MergeConfig(result, config)
			continue
		}

		contents, err := f.Readdir(-1)
		f.Close()
		if err != nil {
			return nil, fmt.Errorf("error reading '%s': %s", path, err)
		}

		// Sort the contents, ensures lexical order
		sort.Sort(dirEnts(contents))

		for _, fi := range contents {
			// Don't recursively read contents
			if fi.IsDir() {
				continue
			}

			path := filepath.Join(path, fi.Name())

			config, err := decodeConfigFile(path, fi)
			if err != nil {
				return nil, err
			}

			result = MergeConfig(result, config)
		}
	}

	return result, nil
}

func decodeConfigFile(path string, fi os.FileInfo) (*Config, error) {
	result := new(Config)
	var err error

	f, err := os.Open(path)
	defer f.Close()
	if err != nil {
		return nil, fmt.Errorf("error reading '%s': %s", path, err)
	}

	// If it isn't a JSON file, ignore it
	if strings.HasSuffix(fi.Name(), ".json") {
		result, err = DecodeConfigFromJSON(f)

		if err != nil {
			return nil, fmt.Errorf("error decoding '%s': %s", path, err)
		}
	} else if strings.HasSuffix(fi.Name(), ".toml") {
		result, err = DecodeConfigFromTOML(f)

		if err != nil {
			return nil, fmt.Errorf("error decoding '%s': %s", path, err)
		}
	} else {

		// Try decoding with json then toml, else fail
		result, err = DecodeConfigFromJSON(f)
		if err != nil {
			f.Close()
			f, err = os.Open(path)
			defer f.Close()
			if err != nil {
				return nil, fmt.Errorf("error reading '%s': %s", path, err)
			}

			result, err = DecodeConfigFromTOML(f)
			if err != nil {
				return nil, fmt.Errorf("error decoding '%s': unknown format", path)
			}
		}
		f.Close()
	}

	return result, nil
}

// Implement the sort interface for dirEnts
func (d dirEnts) Len() int {
	return len(d)
}

func (d dirEnts) Less(i, j int) bool {
	return d[i].Name() < d[j].Name()
}

func (d dirEnts) Swap(i, j int) {
	d[i], d[j] = d[j], d[i]
}
<|endoftext|>


<commit_before>package rtt

import (
	"fmt"
	"strings"
	"testing"

	"github.com/hashicorp/consul/agent"
	"github.com/hashicorp/consul/agent/structs"
	"github.com/hashicorp/consul/testutil/retry"
	"github.com/hashicorp/serf/coordinate"
	"github.com/mitchellh/cli"
)

func TestRTTCommand_noTabs(t *testing.T) {
	t.Parallel()
	if strings.ContainsRune(New(cli.NewMockUi()).Help(), '\t') {
		t.Fatal("help has tabs")
	}
}

func TestRTTCommand_BadArgs(t *testing.T) {
	t.Parallel()
	tests := []struct {
		args []string
	}{
		{args: []string{}},
		{args: []string{"node1", "node2", "node3"}},
		{args: []string{"-wan", "node1", "node2"}},
		{args: []string{"-wan", "node1.dc1", "node2"}},
		{args: []string{"-wan", "node1", "node2.dc1"}},
	}

	for _, tt := range tests {
		t.Run(strings.Join(tt.args, " "), func(t *testing.T) {
			ui := cli.NewMockUi()
			c := New(ui)
			if code := c.Run(tt.args); code != 1 {
				t.Fatalf("expected return code 1, got %d", code)
			}
		})
	}
}

func TestRTTCommand_LAN(t *testing.T) {
	t.Parallel()
	a := agent.NewTestAgent(t.Name(), `
		consul = {
			coordinate = {
				update_period = "10ms"
			}
		}
	`)
	defer a.Shutdown()

	// Inject some known coordinates.
	c1 := coordinate.NewCoordinate(coordinate.DefaultConfig())
	c2 := c1.Clone()
	c2.Vec[0] = 0.123
	distStr := fmt.Sprintf("%.3f ms", c1.DistanceTo(c2).Seconds()*1000.0)
	{
		req := structs.CoordinateUpdateRequest{
			Datacenter: a.Config.Datacenter,
			Node:       a.Config.NodeName,
			Coord:      c1,
		}
		var reply struct{}
		if err := a.RPC("Coordinate.Update", &req, &reply); err != nil {
			t.Fatalf("err: %s", err)
		}
	}
	{
		req := structs.RegisterRequest{
			Datacenter: a.Config.Datacenter,
			Node:       "dogs",
			Address:    "127.0.0.2",
		}
		var reply struct{}
		if err := a.RPC("Catalog.Register", &req, &reply); err != nil {
			t.Fatalf("err: %s", err)
		}
	}
	{
		var reply struct{}
		req := structs.CoordinateUpdateRequest{
			Datacenter: a.Config.Datacenter,
			Node:       "dogs",
			Coord:      c2,
		}
		if err := a.RPC("Coordinate.Update", &req, &reply); err != nil {
			t.Fatalf("err: %s", err)
		}
	}

	// Ask for the RTT of two known nodes
	ui := cli.NewMockUi()
	c := New(ui)
	args := []string{
		"-http-addr=" + a.HTTPAddr(),
		a.Config.NodeName,
		"dogs",
	}
	// Wait for the updates to get flushed to the data store.
	retry.Run(t, func(r *retry.R) {
		code := c.Run(args)
		if code != 0 {
			r.Fatalf("bad: %d: %#v", code, ui.ErrorWriter.String())
		}

		// Make sure the proper RTT was reported in the output.
		expected := fmt.Sprintf("rtt: %s", distStr)
		if !strings.Contains(ui.OutputWriter.String(), expected) {
			r.Fatalf("bad: %#v", ui.OutputWriter.String())
		}
	})

	// Default to the agent's node.
	{
		ui := cli.NewMockUi()
		c := New(ui)
		args := []string{
			"-http-addr=" + a.HTTPAddr(),
			"dogs",
		}
		code := c.Run(args)
		if code != 0 {
			t.Fatalf("bad: %d: %#v", code, ui.ErrorWriter.String())
		}

		// Make sure the proper RTT was reported in the output.
		expected := fmt.Sprintf("rtt: %s", distStr)
		if !strings.Contains(ui.OutputWriter.String(), expected) {
			t.Fatalf("bad: %#v", ui.OutputWriter.String())
		}
	}

	// Try an unknown node.
	{
		ui := cli.NewMockUi()
		c := New(ui)
		args := []string{
			"-http-addr=" + a.HTTPAddr(),
			a.Config.NodeName,
			"nope",
		}
		code := c.Run(args)
		if code != 1 {
			t.Fatalf("bad: %d: %#v", code, ui.ErrorWriter.String())
		}
	}
}

func TestRTTCommand_WAN(t *testing.T) {
	t.Parallel()
	a := agent.NewTestAgent(t.Name(), ``)
	defer a.Shutdown()

	node := fmt.Sprintf("%s.%s", a.Config.NodeName, a.Config.Datacenter)

	// We can't easily inject WAN coordinates, so we will just query the
	// node with itself.
	{
		ui := cli.NewMockUi()
		c := New(ui)
		args := []string{
			"-wan",
			"-http-addr=" + a.HTTPAddr(),
			node,
			node,
		}
		code := c.Run(args)
		if code != 0 {
			t.Fatalf("bad: %d: %#v", code, ui.ErrorWriter.String())
		}

		// Make sure there was some kind of RTT reported in the output.
		if !strings.Contains(ui.OutputWriter.String(), "rtt: ") {
			t.Fatalf("bad: %#v", ui.OutputWriter.String())
		}
	}

	// Default to the agent's node.
	{
		ui := cli.NewMockUi()
		c := New(ui)
		args := []string{
			"-wan",
			"-http-addr=" + a.HTTPAddr(),
			node,
		}
		code := c.Run(args)
		if code != 0 {
			t.Fatalf("bad: %d: %#v", code, ui.ErrorWriter.String())
		}

		// Make sure there was some kind of RTT reported in the output.
		if !strings.Contains(ui.OutputWriter.String(), "rtt: ") {
			t.Fatalf("bad: %#v", ui.OutputWriter.String())
		}
	}

	// Try an unknown node.
	{
		ui := cli.NewMockUi()
		c := New(ui)
		args := []string{
			"-wan",
			"-http-addr=" + a.HTTPAddr(),
			node,
			"dc1.nope",
		}
		code := c.Run(args)
		if code != 1 {
			t.Fatalf("bad: %d: %#v", code, ui.ErrorWriter.String())
		}
	}
}
<commit_msg>Fixed unstable test TestRTTCommand_LAN in command/rtt (#4585)<commit_after>package rtt

import (
	"fmt"
	"strings"
	"testing"

	"github.com/hashicorp/consul/testrpc"

	"github.com/hashicorp/consul/agent"
	"github.com/hashicorp/consul/agent/structs"
	"github.com/hashicorp/consul/testutil/retry"
	"github.com/hashicorp/serf/coordinate"
	"github.com/mitchellh/cli"
)

func TestRTTCommand_noTabs(t *testing.T) {
	t.Parallel()
	if strings.ContainsRune(New(cli.NewMockUi()).Help(), '\t') {
		t.Fatal("help has tabs")
	}
}

func TestRTTCommand_BadArgs(t *testing.T) {
	t.Parallel()
	tests := []struct {
		args []string
	}{
		{args: []string{}},
		{args: []string{"node1", "node2", "node3"}},
		{args: []string{"-wan", "node1", "node2"}},
		{args: []string{"-wan", "node1.dc1", "node2"}},
		{args: []string{"-wan", "node1", "node2.dc1"}},
	}

	for _, tt := range tests {
		t.Run(strings.Join(tt.args, " "), func(t *testing.T) {
			ui := cli.NewMockUi()
			c := New(ui)
			if code := c.Run(tt.args); code != 1 {
				t.Fatalf("expected return code 1, got %d", code)
			}
		})
	}
}

func TestRTTCommand_LAN(t *testing.T) {
	t.Parallel()
	a := agent.NewTestAgent(t.Name(), `
		consul = {
			coordinate = {
				update_period = "10ms"
			}
		}
	`)
	defer a.Shutdown()
	testrpc.WaitForLeader(t, a.RPC, "dc1")

	// Inject some known coordinates.
	c1 := coordinate.NewCoordinate(coordinate.DefaultConfig())
	c2 := c1.Clone()
	c2.Vec[0] = 0.123
	distStr := fmt.Sprintf("%.3f ms", c1.DistanceTo(c2).Seconds()*1000.0)
	{
		req := structs.CoordinateUpdateRequest{
			Datacenter: a.Config.Datacenter,
			Node:       a.Config.NodeName,
			Coord:      c1,
		}
		var reply struct{}
		if err := a.RPC("Coordinate.Update", &req, &reply); err != nil {
			t.Fatalf("err: %s", err)
		}
	}
	{
		req := structs.RegisterRequest{
			Datacenter: a.Config.Datacenter,
			Node:       "dogs",
			Address:    "127.0.0.2",
		}
		var reply struct{}
		if err := a.RPC("Catalog.Register", &req, &reply); err != nil {
			t.Fatalf("err: %s", err)
		}
	}
	{
		var reply struct{}
		req := structs.CoordinateUpdateRequest{
			Datacenter: a.Config.Datacenter,
			Node:       "dogs",
			Coord:      c2,
		}
		if err := a.RPC("Coordinate.Update", &req, &reply); err != nil {
			t.Fatalf("err: %s", err)
		}
	}

	// Ask for the RTT of two known nodes
	ui := cli.NewMockUi()
	c := New(ui)
	args := []string{
		"-http-addr=" + a.HTTPAddr(),
		a.Config.NodeName,
		"dogs",
	}
	// Wait for the updates to get flushed to the data store.
	retry.Run(t, func(r *retry.R) {
		code := c.Run(args)
		if code != 0 {
			r.Fatalf("bad: %d: %#v", code, ui.ErrorWriter.String())
		}

		// Make sure the proper RTT was reported in the output.
		expected := fmt.Sprintf("rtt: %s", distStr)
		if !strings.Contains(ui.OutputWriter.String(), expected) {
			r.Fatalf("bad: %#v", ui.OutputWriter.String())
		}
	})

	// Default to the agent's node.
	{
		ui := cli.NewMockUi()
		c := New(ui)
		args := []string{
			"-http-addr=" + a.HTTPAddr(),
			"dogs",
		}
		code := c.Run(args)
		if code != 0 {
			t.Fatalf("bad: %d: %#v", code, ui.ErrorWriter.String())
		}

		// Make sure the proper RTT was reported in the output.
		expected := fmt.Sprintf("rtt: %s", distStr)
		if !strings.Contains(ui.OutputWriter.String(), expected) {
			t.Fatalf("bad: %#v", ui.OutputWriter.String())
		}
	}

	// Try an unknown node.
	{
		ui := cli.NewMockUi()
		c := New(ui)
		args := []string{
			"-http-addr=" + a.HTTPAddr(),
			a.Config.NodeName,
			"nope",
		}
		code := c.Run(args)
		if code != 1 {
			t.Fatalf("bad: %d: %#v", code, ui.ErrorWriter.String())
		}
	}
}

func TestRTTCommand_WAN(t *testing.T) {
	t.Parallel()
	a := agent.NewTestAgent(t.Name(), ``)
	defer a.Shutdown()
	testrpc.WaitForLeader(t, a.RPC, "dc1")

	node := fmt.Sprintf("%s.%s", a.Config.NodeName, a.Config.Datacenter)

	// We can't easily inject WAN coordinates, so we will just query the
	// node with itself.
	{
		ui := cli.NewMockUi()
		c := New(ui)
		args := []string{
			"-wan",
			"-http-addr=" + a.HTTPAddr(),
			node,
			node,
		}
		code := c.Run(args)
		if code != 0 {
			t.Fatalf("bad: %d: %#v", code, ui.ErrorWriter.String())
		}

		// Make sure there was some kind of RTT reported in the output.
		if !strings.Contains(ui.OutputWriter.String(), "rtt: ") {
			t.Fatalf("bad: %#v", ui.OutputWriter.String())
		}
	}

	// Default to the agent's node.
	{
		ui := cli.NewMockUi()
		c := New(ui)
		args := []string{
			"-wan",
			"-http-addr=" + a.HTTPAddr(),
			node,
		}
		code := c.Run(args)
		if code != 0 {
			t.Fatalf("bad: %d: %#v", code, ui.ErrorWriter.String())
		}

		// Make sure there was some kind of RTT reported in the output.
		if !strings.Contains(ui.OutputWriter.String(), "rtt: ") {
			t.Fatalf("bad: %#v", ui.OutputWriter.String())
		}
	}

	// Try an unknown node.
	{
		ui := cli.NewMockUi()
		c := New(ui)
		args := []string{
			"-wan",
			"-http-addr=" + a.HTTPAddr(),
			node,
			"dc1.nope",
		}
		code := c.Run(args)
		if code != 1 {
			t.Fatalf("bad: %d: %#v", code, ui.ErrorWriter.String())
		}
	}
}
<|endoftext|>