<commit_before>package deploy

import (
	"errors"
	"fmt"
	"os"
	"regexp"
	"strings"

	"github.com/remind101/deploy/Godeps/_workspace/src/github.com/codegangsta/cli"
	"github.com/remind101/deploy/Godeps/_workspace/src/github.com/github/hub/git"
	hub "github.com/remind101/deploy/Godeps/_workspace/src/github.com/github/hub/github"
	"github.com/remind101/deploy/Godeps/_workspace/src/github.com/google/go-github/github"
)

const (
	Name  = "deploy"
	Usage = "A command for creating GitHub deployments"
)

const DefaultRef = "master"

func init() {
	cli.AppHelpTemplate = `USAGE:
   # Deploy the master branch of remind101/acme-inc to staging
   {{.Name}} --env=staging --ref=master remind101/acme-inc

   # Deploy HEAD of the current branch to staging
   {{.Name}} --env=staging remind101/acme-inc

   # Deploy the current GitHub repo to staging
   {{.Name}} --env=staging
{{if .Flags}}
OPTIONS:
   {{range .Flags}}{{.}}
   {{end}}{{end}}
`
}

var flags = []cli.Flag{
	cli.StringFlag{
		Name:  "ref, branch, commit, tag",
		Value: "",
		Usage: "The git ref to deploy. Can be a git commit, branch or tag.",
	},
	cli.StringFlag{
		Name:  "env, e",
		Value: "",
		Usage: "The environment to deploy to.",
	},
	cli.BoolFlag{
		Name:  "force, f",
		Usage: "Ignore commit status checks.",
	},
}

// NewApp returns a new cli.App for the deploy command.
func NewApp() *cli.App {
	app := cli.NewApp()
	app.Version = "0.0.1"
	app.Name = Name
	app.Usage = Usage
	app.Flags = flags
	app.Action = func(c *cli.Context) {
		if err := RunDeploy(c); err != nil {
			msg := err.Error()
			if err, ok := err.(*github.ErrorResponse); ok {
				if strings.HasPrefix(err.Message, "Conflict: Commit status checks failed for") {
					msg = "Commit status checks failed. You can bypass commit status checks with the --force flag."
				} else if strings.HasPrefix(err.Message, "No ref found for") {
					msg = fmt.Sprintf("%s. Did you push it to GitHub?", err.Message)
				} else {
					msg = err.Message
				}
			}

			fmt.Println(msg)
			os.Exit(-1)
		}
	}

	return app
}

// RunDeploy performs a deploy.
func RunDeploy(c *cli.Context) error {
	w := c.App.Writer

	h, err := hub.CurrentConfig().PromptForHost("github.com")
	if err != nil {
		return err
	}

	client, err := newGitHubClient(h)
	if err != nil {
		return err
	}

	nwo, err := Repo(c.Args())
	if err != nil {
		return err
	}

	owner, repo, err := SplitRepo(nwo)
	if err != nil {
		return fmt.Errorf("Invalid GitHub repo: %s", nwo)
	}

	r, err := newDeploymentRequest(c)
	if err != nil {
		return err
	}

	fmt.Fprintf(w, "Creating deployment request of %s@%s to %s... ", nwo, *r.Ref, *r.Environment)

	d, _, err := client.Repositories.CreateDeployment(owner, repo, r)
	if err != nil {
		return err
	}

	ch := make(chan *github.DeploymentStatus)

	go func() {
		for {
			statuses, _, err := client.Repositories.ListDeploymentStatuses(owner, repo, *d.ID, nil)
			if err != nil {
				continue
			}

			completed := CompletedStatus(statuses)
			if completed != nil {
				ch <- completed
				break
			}
		}
	}()

	status := <-ch

	var url string
	if status.TargetURL != nil {
		url = *status.TargetURL
	}

	state := "unkown"
	if status.State != nil {
		state = *status.State
	}

	fmt.Fprintf(w, "%s: %s\n", state, url)

	return nil
}

func newDeploymentRequest(c *cli.Context) (*github.DeploymentRequest, error) {
	ref := c.String("ref")
	if ref == "" {
		r, err := git.Ref("HEAD")
		if err == nil {
			ref = r
		} else {
			ref = DefaultRef
		}
	}

	env := c.String("env")
	if env == "" {
		return nil, fmt.Errorf("--env flag is required")
	}

	var contexts *[]string
	if c.Bool("force") {
		s := []string{}
		contexts = &s
	}

	return &github.DeploymentRequest{
		Ref:              github.String(ref),
		Task:             github.String("deploy"),
		AutoMerge:        github.Bool(false),
		Environment:      github.String(env),
		RequiredContexts: contexts,
		// TODO Description:
	}, nil
}

var completedStatuses = []string{"success", "error", "failure"}

// CompletedStatus takes a slice of github.DeploymentStatus and returns the
// first "completed" status. nil is returned if there are no completed
// deployment states.
func CompletedStatus(statuses []github.DeploymentStatus) *github.DeploymentStatus {
	for _, ds := range statuses {
		for _, s := range completedStatuses {
			if ds.State != nil && *ds.State == s {
				return &ds
			}
		}
	}

	return nil
}

// Repo will determine the correct GitHub repo to deploy to, based on a set of
// arguments.
func Repo(arguments []string) (string, error) {
	if len(arguments) != 0 {
		return arguments[0], nil
	}

	remotes, err := hub.Remotes()
	if err != nil {
		return "", err
	}

	repo := GitHubRepo(remotes)
	if repo == "" {
		return repo, errors.New("no GitHub repo found in .git/config")
	}

	return repo, nil
}

// A regular expression that can convert a URL.Path into a GitHub repo name.
var remoteRegex = regexp.MustCompile(`^/(.*)\.git$`)

// GitHubRepo, given a list of git remotes, will determine what the GitHub repo
// is.
func GitHubRepo(remotes []hub.Remote) string {
	// We only want to look at the `origin` remote.
	remote := findRemote("origin", remotes)
	if remote == nil {
		return ""
	}

	// Remotes that are not pointed at a GitHub repo are not valid.
	if remote.URL.Host != "github.com" {
		return ""
	}

	// Convert `/remind101/acme-inc.git` => `remind101/acme-inc`.
	return remoteRegex.ReplaceAllString(remote.URL.Path, "$1")
}

func findRemote(name string, remotes []hub.Remote) *hub.Remote {
	for _, r := range remotes {
		if r.Name == name {
			return &r
		}
	}

	return nil
}

var errInvalidRepo = errors.New("invalid repo")

// SplitRepo splits a repo string in the form remind101/acme-inc into it's owner
// and repo components.
func SplitRepo(nwo string) (owner string, repo string, err error) {
	parts := strings.Split(nwo, "/")

	if len(parts) != 2 {
		err = errInvalidRepo
		return
	}

	owner = parts[0]
	repo = parts[1]

	return
}
<commit_msg>Show started/Completed.<commit_after>package deploy

import (
	"errors"
	"fmt"
	"os"
	"regexp"
	"strings"

	"github.com/remind101/deploy/Godeps/_workspace/src/github.com/codegangsta/cli"
	"github.com/remind101/deploy/Godeps/_workspace/src/github.com/github/hub/git"
	hub "github.com/remind101/deploy/Godeps/_workspace/src/github.com/github/hub/github"
	"github.com/remind101/deploy/Godeps/_workspace/src/github.com/google/go-github/github"
)

const (
	Name  = "deploy"
	Usage = "A command for creating GitHub deployments"
)

const DefaultRef = "master"

func init() {
	cli.AppHelpTemplate = `USAGE:
   # Deploy the master branch of remind101/acme-inc to staging
   {{.Name}} --env=staging --ref=master remind101/acme-inc

   # Deploy HEAD of the current branch to staging
   {{.Name}} --env=staging remind101/acme-inc

   # Deploy the current GitHub repo to staging
   {{.Name}} --env=staging
{{if .Flags}}
OPTIONS:
   {{range .Flags}}{{.}}
   {{end}}{{end}}
`
}

var flags = []cli.Flag{
	cli.StringFlag{
		Name:  "ref, branch, commit, tag",
		Value: "",
		Usage: "The git ref to deploy. Can be a git commit, branch or tag.",
	},
	cli.StringFlag{
		Name:  "env, e",
		Value: "",
		Usage: "The environment to deploy to.",
	},
	cli.BoolFlag{
		Name:  "force, f",
		Usage: "Ignore commit status checks.",
	},
}

// NewApp returns a new cli.App for the deploy command.
func NewApp() *cli.App {
	app := cli.NewApp()
	app.Version = "0.0.1"
	app.Name = Name
	app.Usage = Usage
	app.Flags = flags
	app.Action = func(c *cli.Context) {
		if err := RunDeploy(c); err != nil {
			msg := err.Error()
			if err, ok := err.(*github.ErrorResponse); ok {
				if strings.HasPrefix(err.Message, "Conflict: Commit status checks failed for") {
					msg = "Commit status checks failed. You can bypass commit status checks with the --force flag."
				} else if strings.HasPrefix(err.Message, "No ref found for") {
					msg = fmt.Sprintf("%s. Did you push it to GitHub?", err.Message)
				} else {
					msg = err.Message
				}
			}

			fmt.Println(msg)
			os.Exit(-1)
		}
	}

	return app
}

// RunDeploy performs a deploy.
func RunDeploy(c *cli.Context) error {
	w := c.App.Writer

	h, err := hub.CurrentConfig().PromptForHost("github.com")
	if err != nil {
		return err
	}

	client, err := newGitHubClient(h)
	if err != nil {
		return err
	}

	nwo, err := Repo(c.Args())
	if err != nil {
		return err
	}

	owner, repo, err := SplitRepo(nwo)
	if err != nil {
		return fmt.Errorf("Invalid GitHub repo: %s", nwo)
	}

	r, err := newDeploymentRequest(c)
	if err != nil {
		return err
	}

	fmt.Fprintf(w, "Creating deployment request for %s@%s to %s...\n", nwo, *r.Ref, *r.Environment)

	d, _, err := client.Repositories.CreateDeployment(owner, repo, r)
	if err != nil {
		return err
	}

	started := make(chan *github.DeploymentStatus)
	completed := make(chan *github.DeploymentStatus)

	go func() {
		started <- waitState(pendingStates, owner, repo, *d.ID, client)
	}()

	go func() {
		completed <- waitState(completedStates, owner, repo, *d.ID, client)
	}()

	status := <-started
	var url string
	if status.TargetURL != nil {
		url = *status.TargetURL
	}
	fmt.Fprintf(w, "Started: %s\n", url)

	status = <-completed

	fmt.Fprintf(w, "Completed: %s\n", *status.State)

	return nil
}

func newDeploymentRequest(c *cli.Context) (*github.DeploymentRequest, error) {
	ref := c.String("ref")
	if ref == "" {
		r, err := git.Ref("HEAD")
		if err == nil {
			ref = r
		} else {
			ref = DefaultRef
		}
	}

	env := c.String("env")
	if env == "" {
		return nil, fmt.Errorf("--env flag is required")
	}

	var contexts *[]string
	if c.Bool("force") {
		s := []string{}
		contexts = &s
	}

	return &github.DeploymentRequest{
		Ref:              github.String(ref),
		Task:             github.String("deploy"),
		AutoMerge:        github.Bool(false),
		Environment:      github.String(env),
		RequiredContexts: contexts,
		// TODO Description:
	}, nil
}

var (
	pendingStates   = []string{"pending"}
	completedStates = []string{"success", "error", "failure"}
)

// waitState waits for a deployment status that matches the given states, then
// sends on the returned channel.
func waitState(states []string, owner, repo string, deploymentID int, c *github.Client) *github.DeploymentStatus {
	for {
		statuses, _, err := c.Repositories.ListDeploymentStatuses(owner, repo, deploymentID, nil)
		if err != nil {
			continue
		}

		status := firstStatus(states, statuses)
		if status != nil {
			return status
		}
	}
}

// firstStatus takes a slice of github.DeploymentStatus and returns the
// first status that matches the provided slice of states.
func firstStatus(states []string, statuses []github.DeploymentStatus) *github.DeploymentStatus {
	for _, ds := range statuses {
		for _, s := range states {
			if ds.State != nil && *ds.State == s {
				return &ds
			}
		}
	}

	return nil
}

// Repo will determine the correct GitHub repo to deploy to, based on a set of
// arguments.
func Repo(arguments []string) (string, error) {
	if len(arguments) != 0 {
		return arguments[0], nil
	}

	remotes, err := hub.Remotes()
	if err != nil {
		return "", err
	}

	repo := GitHubRepo(remotes)
	if repo == "" {
		return repo, errors.New("no GitHub repo found in .git/config")
	}

	return repo, nil
}

// A regular expression that can convert a URL.Path into a GitHub repo name.
var remoteRegex = regexp.MustCompile(`^/(.*)\.git$`)

// GitHubRepo, given a list of git remotes, will determine what the GitHub repo
// is.
func GitHubRepo(remotes []hub.Remote) string {
	// We only want to look at the `origin` remote.
	remote := findRemote("origin", remotes)
	if remote == nil {
		return ""
	}

	// Remotes that are not pointed at a GitHub repo are not valid.
	if remote.URL.Host != "github.com" {
		return ""
	}

	// Convert `/remind101/acme-inc.git` => `remind101/acme-inc`.
	return remoteRegex.ReplaceAllString(remote.URL.Path, "$1")
}

func findRemote(name string, remotes []hub.Remote) *hub.Remote {
	for _, r := range remotes {
		if r.Name == name {
			return &r
		}
	}

	return nil
}

var errInvalidRepo = errors.New("invalid repo")

// SplitRepo splits a repo string in the form remind101/acme-inc into it's owner
// and repo components.
func SplitRepo(nwo string) (owner string, repo string, err error) {
	parts := strings.Split(nwo, "/")

	if len(parts) != 2 {
		err = errInvalidRepo
		return
	}

	owner = parts[0]
	repo = parts[1]

	return
}
<|endoftext|>


<commit_before>package api

// ecosystem_helpers_test.go has a bunch of helper functions to make setting up
// large ecosystem tests easier.
//
// List of helper functions:
//    addStorageToAllHosts // adds a storage folder to every host
//    announceAllHosts     // announce all hosts to the network (and mine a block)
//    fullyConnectNodes    // connects each server tester to all the others
//    fundAllNodes         // mines blocks until all server testers have money
//    synchronizationCheck // checks that all server testers have the same recent block
//    waitForBlock         // block until the provided block is the most recent block for all server testers

import (
	"errors"
	"net/url"
	"time"

	"github.com/NebulousLabs/Sia/types"
)

// addStorageToAllHosts adds a storage folder with a bunch of storage to each
// host.
func addStorageToAllHosts(sts []*serverTester) error {
	for _, st := range sts {
		values := url.Values{}
		values.Set("path", st.dir)
		values.Set("size", "1048576")
		err := st.stdPostAPI("/host/storage/folders/add", values)
		if err != nil {
			return err
		}
	}
	return nil
}

// announceAllHosts will announce every host in the tester set to the
// blockchain.
func announceAllHosts(sts []*serverTester) error {
	// Check that all announcements will be on the same chain.
	_, err := synchronizationCheck(sts)
	if err != nil {
		return err
	}

	// Announce each host.
	for _, st := range sts {
		// Set the host to be accepting contracts.
		acceptingContractsValues := url.Values{}
		acceptingContractsValues.Set("acceptingcontracts", "true")
		err = st.stdPostAPI("/host", acceptingContractsValues)
		if err != nil {
			return err
		}

		// Fetch the host net address.
		var hg HostGET
		err = st.getAPI("/host", &hg)
		if err != nil {
			return err
		}

		// Make the announcement.
		announceValues := url.Values{}
		announceValues.Set("address", string(hg.ExternalSettings.NetAddress))
		err = st.stdPostAPI("/host/announce", announceValues)
		if err != nil {
			return err
		}
	}

	// Wait until all of the transactions have propagated to all of the nodes.
	//
	// TODO: Replace this direct transaction pool call with a call to the
	// /transactionpool endpoint.
	//
	// TODO: At some point the number of transactions needed to make an
	// announcement may change. Currently its 2.
	for i := 0; i < 50; i++ {
		if len(sts[0].tpool.TransactionList()) == len(sts)*2 {
			break
		}
		time.Sleep(time.Millisecond * 100)
	}
	if len(sts[0].tpool.TransactionList()) != len(sts)*2 {
		return errors.New("Host announcements do not seem to have propagated to the leader's tpool")
	}

	// Mine a block and then wait for all of the nodes to syncrhonize to it.
	_, err = sts[0].miner.AddBlock()
	if err != nil {
		return err
	}
	_, err = synchronizationCheck(sts)
	if err != nil {
		return err
	}

	// Block until every node has completed the scan of every other node, so
	// that each node has a full hostdb.
	for _, st := range sts {
		var ah HostdbActiveGET
		for i := 0; i < 50; i++ {
			err = st.getAPI("/hostdb/active", &ah)
			if err != nil {
				return err
			}
			if len(ah.Hosts) >= len(sts) {
				break
			}
			time.Sleep(time.Millisecond * 100)
		}
		if len(ah.Hosts) < len(sts) {
			return errors.New("one of the nodes hostdbs was unable to find at least one host announcement")
		}
	}
	return nil
}

// fullyConnectNodes takes a bunch of tester nodes and connects each to the
// other, creating a fully connected graph so that everyone is on the same
// chain.
//
// After connecting the nodes, it verifies that all the nodes have
// synchronized.
func fullyConnectNodes(sts []*serverTester) error {
	for i, sta := range sts {
		var gg GatewayGET
		err := sta.getAPI("/gateway", &gg)
		if err != nil {
			return err
		}

		// Connect this node to every other node.
		for _, stb := range sts[i+1:] {
			// Try connecting to the other node until both have the other in
			// their peer list.
			err = retry(50, time.Millisecond*50, func() error {
				// NOTE: this check depends on string-matching an error in the
				// gateway. If that error changes at all, this string will need to
				// be updated.
				err := stb.stdPostAPI("/gateway/connect/"+string(gg.NetAddress), nil)
				if err != nil && err.Error() != "already connected to this peer" {
					return err
				}

				// Check that the gateways are connected.
				bToA := false
				aToB := false
				var ggb GatewayGET
				err = stb.getAPI("/gateway", &ggb)
				if err != nil {
					return err
				}
				for _, peer := range ggb.Peers {
					if peer.NetAddress == gg.NetAddress {
						bToA = true
						break
					}
				}
				err = sta.getAPI("/gateway", &gg)
				if err != nil {
					return err
				}
				for _, peer := range gg.Peers {
					if peer.NetAddress == ggb.NetAddress {
						aToB = true
						break
					}
				}
				if !aToB || !bToA {
					return errors.New("called connect between two nodes, but they are not peers")
				}
				return nil

			})
			if err != nil {
				return err
			}
		}
	}

	// Perform a synchronization check.
	_, err := synchronizationCheck(sts)
	return err
}

// fundAllNodes will make sure that each node has mined a block in the longest
// chain, then will mine enough blocks that the miner payouts manifest in the
// wallets of each node.
func fundAllNodes(sts []*serverTester) error {
	// Check that all of the nodes are synchronized.
	chainTip, err := synchronizationCheck(sts)
	if err != nil {
		return err
	}

	// Mine a block for each node to fund their wallet.
	for i := range sts {
		err := waitForBlock(chainTip, sts[i])
		if err != nil {
			return err
		}

		// Mine a block. The next iteration of this loop will ensure that the
		// block propagates and does not get orphaned.
		block, err := sts[i].miner.AddBlock()
		if err != nil {
			return err
		}
		chainTip = block.ID()
	}

	// Wait until the chain tip has propagated to the first node.
	err = waitForBlock(chainTip, sts[0])
	if err != nil {
		return err
	}

	// Mine types.MaturityDelay more blocks from the final node to mine a
	// block, to guarantee that all nodes have had their payouts mature, such
	// that their wallets can begin spending immediately.
	for i := types.BlockHeight(0); i <= types.MaturityDelay; i++ {
		_, err := sts[0].miner.AddBlock()
		if err != nil {
			return err
		}
	}

	// Block until every node has the full chain.
	_, err = synchronizationCheck(sts)
	return err
}

// synchronizationCheck takes a bunch of server testers as input and checks
// that they all have the same current block as the first server tester. The
// first server tester needs to have the most recent block in order for the
// check to work.
func synchronizationCheck(sts []*serverTester) (types.BlockID, error) {
	// Prefer returning an error in the event of a zero-length server tester -
	// an error should be returned if the developer accidentally uses a nil
	// slice instead of whatever value was intended, and there's no reason to
	// check for synchronization if there aren't any nodes to be synchronized.
	if len(sts) == 0 {
		return types.BlockID{}, errors.New("no server testers provided")
	}

	var cg ConsensusGET
	err := sts[0].getAPI("/consensus", &cg)
	if err != nil {
		return types.BlockID{}, err
	}
	leaderBlockID := cg.CurrentBlock
	for i := range sts {
		// Spin until the current block matches the leader block.
		success := false
		for j := 0; j < 100; j++ {
			err = sts[i].getAPI("/consensus", &cg)
			if err != nil {
				return types.BlockID{}, err
			}
			if cg.CurrentBlock == leaderBlockID {
				success = true
				break
			}
			time.Sleep(time.Millisecond * 100)
		}
		if !success {
			return types.BlockID{}, errors.New("synchronization check failed - nodes do not seem to be synchronized")
		}
	}
	return leaderBlockID, nil
}

// waitForBlock will block until the provided chain tip is the most recent
// block in the provided testing node.
func waitForBlock(chainTip types.BlockID, st *serverTester) error {
	var cg ConsensusGET
	success := false
	for j := 0; j < 100; j++ {
		err := st.getAPI("/consensus", &cg)
		if err != nil {
			return err
		}
		if cg.CurrentBlock == chainTip {
			success = true
			break
		}
		time.Sleep(time.Millisecond * 100)
	}
	if !success {
		return errors.New("node never reached the correct chain tip")
	}
	return nil
}
<commit_msg>add more information to ecosystem helper ndf<commit_after>package api

// ecosystem_helpers_test.go has a bunch of helper functions to make setting up
// large ecosystem tests easier.
//
// List of helper functions:
//    addStorageToAllHosts // adds a storage folder to every host
//    announceAllHosts     // announce all hosts to the network (and mine a block)
//    fullyConnectNodes    // connects each server tester to all the others
//    fundAllNodes         // mines blocks until all server testers have money
//    synchronizationCheck // checks that all server testers have the same recent block
//    waitForBlock         // block until the provided block is the most recent block for all server testers

import (
	"errors"
	"fmt"
	"net/url"
	"time"

	"github.com/NebulousLabs/Sia/types"
)

// addStorageToAllHosts adds a storage folder with a bunch of storage to each
// host.
func addStorageToAllHosts(sts []*serverTester) error {
	for _, st := range sts {
		values := url.Values{}
		values.Set("path", st.dir)
		values.Set("size", "1048576")
		err := st.stdPostAPI("/host/storage/folders/add", values)
		if err != nil {
			return err
		}
	}
	return nil
}

// announceAllHosts will announce every host in the tester set to the
// blockchain.
func announceAllHosts(sts []*serverTester) error {
	// Check that all announcements will be on the same chain.
	_, err := synchronizationCheck(sts)
	if err != nil {
		return err
	}

	// Announce each host.
	for _, st := range sts {
		// Set the host to be accepting contracts.
		acceptingContractsValues := url.Values{}
		acceptingContractsValues.Set("acceptingcontracts", "true")
		err = st.stdPostAPI("/host", acceptingContractsValues)
		if err != nil {
			return err
		}

		// Fetch the host net address.
		var hg HostGET
		err = st.getAPI("/host", &hg)
		if err != nil {
			return err
		}

		// Make the announcement.
		announceValues := url.Values{}
		announceValues.Set("address", string(hg.ExternalSettings.NetAddress))
		err = st.stdPostAPI("/host/announce", announceValues)
		if err != nil {
			return err
		}
	}

	// Wait until all of the transactions have propagated to all of the nodes.
	//
	// TODO: Replace this direct transaction pool call with a call to the
	// /transactionpool endpoint.
	//
	// TODO: At some point the number of transactions needed to make an
	// announcement may change. Currently its 2.
	for i := 0; i < 50; i++ {
		if len(sts[0].tpool.TransactionList()) == len(sts)*2 {
			break
		}
		time.Sleep(time.Millisecond * 100)
	}
	if len(sts[0].tpool.TransactionList()) != len(sts)*2 {
		return errors.New("Host announcements do not seem to have propagated to the leader's tpool")
	}

	// Mine a block and then wait for all of the nodes to syncrhonize to it.
	_, err = sts[0].miner.AddBlock()
	if err != nil {
		return err
	}
	_, err = synchronizationCheck(sts)
	if err != nil {
		return err
	}

	// Block until every node has completed the scan of every other node, so
	// that each node has a full hostdb.
	for _, st := range sts {
		var ah HostdbActiveGET
		for i := 0; i < 50; i++ {
			err = st.getAPI("/hostdb/active", &ah)
			if err != nil {
				return err
			}
			if len(ah.Hosts) >= len(sts) {
				break
			}
			time.Sleep(time.Millisecond * 100)
		}
		if len(ah.Hosts) < len(sts) {
			return errors.New("one of the nodes hostdbs was unable to find at least one host announcement")
		}
	}
	return nil
}

// fullyConnectNodes takes a bunch of tester nodes and connects each to the
// other, creating a fully connected graph so that everyone is on the same
// chain.
//
// After connecting the nodes, it verifies that all the nodes have
// synchronized.
func fullyConnectNodes(sts []*serverTester) error {
	for i, sta := range sts {
		var gg GatewayGET
		err := sta.getAPI("/gateway", &gg)
		if err != nil {
			return err
		}

		// Connect this node to every other node.
		for _, stb := range sts[i+1:] {
			// Try connecting to the other node until both have the other in
			// their peer list.
			err = retry(50, time.Millisecond*50, func() error {
				// NOTE: this check depends on string-matching an error in the
				// gateway. If that error changes at all, this string will need to
				// be updated.
				err := stb.stdPostAPI("/gateway/connect/"+string(gg.NetAddress), nil)
				if err != nil && err.Error() != "already connected to this peer" {
					return err
				}

				// Check that the gateways are connected.
				bToA := false
				aToB := false
				var ggb GatewayGET
				err = stb.getAPI("/gateway", &ggb)
				if err != nil {
					return err
				}
				for _, peer := range ggb.Peers {
					if peer.NetAddress == gg.NetAddress {
						bToA = true
						break
					}
				}
				err = sta.getAPI("/gateway", &gg)
				if err != nil {
					return err
				}
				for _, peer := range gg.Peers {
					if peer.NetAddress == ggb.NetAddress {
						aToB = true
						break
					}
				}
				if !aToB || !bToA {
					return fmt.Errorf("called connect between two nodes, but they are not peers: %v %v %v %v %v %v", aToB, bToA, gg.NetAddress, ggb.NetAddress, gg.Peers, ggb.Peers)
				}
				return nil

			})
			if err != nil {
				return err
			}
		}
	}

	// Perform a synchronization check.
	_, err := synchronizationCheck(sts)
	return err
}

// fundAllNodes will make sure that each node has mined a block in the longest
// chain, then will mine enough blocks that the miner payouts manifest in the
// wallets of each node.
func fundAllNodes(sts []*serverTester) error {
	// Check that all of the nodes are synchronized.
	chainTip, err := synchronizationCheck(sts)
	if err != nil {
		return err
	}

	// Mine a block for each node to fund their wallet.
	for i := range sts {
		err := waitForBlock(chainTip, sts[i])
		if err != nil {
			return err
		}

		// Mine a block. The next iteration of this loop will ensure that the
		// block propagates and does not get orphaned.
		block, err := sts[i].miner.AddBlock()
		if err != nil {
			return err
		}
		chainTip = block.ID()
	}

	// Wait until the chain tip has propagated to the first node.
	err = waitForBlock(chainTip, sts[0])
	if err != nil {
		return err
	}

	// Mine types.MaturityDelay more blocks from the final node to mine a
	// block, to guarantee that all nodes have had their payouts mature, such
	// that their wallets can begin spending immediately.
	for i := types.BlockHeight(0); i <= types.MaturityDelay; i++ {
		_, err := sts[0].miner.AddBlock()
		if err != nil {
			return err
		}
	}

	// Block until every node has the full chain.
	_, err = synchronizationCheck(sts)
	return err
}

// synchronizationCheck takes a bunch of server testers as input and checks
// that they all have the same current block as the first server tester. The
// first server tester needs to have the most recent block in order for the
// check to work.
func synchronizationCheck(sts []*serverTester) (types.BlockID, error) {
	// Prefer returning an error in the event of a zero-length server tester -
	// an error should be returned if the developer accidentally uses a nil
	// slice instead of whatever value was intended, and there's no reason to
	// check for synchronization if there aren't any nodes to be synchronized.
	if len(sts) == 0 {
		return types.BlockID{}, errors.New("no server testers provided")
	}

	var cg ConsensusGET
	err := sts[0].getAPI("/consensus", &cg)
	if err != nil {
		return types.BlockID{}, err
	}
	leaderBlockID := cg.CurrentBlock
	for i := range sts {
		// Spin until the current block matches the leader block.
		success := false
		for j := 0; j < 100; j++ {
			err = sts[i].getAPI("/consensus", &cg)
			if err != nil {
				return types.BlockID{}, err
			}
			if cg.CurrentBlock == leaderBlockID {
				success = true
				break
			}
			time.Sleep(time.Millisecond * 100)
		}
		if !success {
			return types.BlockID{}, errors.New("synchronization check failed - nodes do not seem to be synchronized")
		}
	}
	return leaderBlockID, nil
}

// waitForBlock will block until the provided chain tip is the most recent
// block in the provided testing node.
func waitForBlock(chainTip types.BlockID, st *serverTester) error {
	var cg ConsensusGET
	success := false
	for j := 0; j < 100; j++ {
		err := st.getAPI("/consensus", &cg)
		if err != nil {
			return err
		}
		if cg.CurrentBlock == chainTip {
			success = true
			break
		}
		time.Sleep(time.Millisecond * 100)
	}
	if !success {
		return errors.New("node never reached the correct chain tip")
	}
	return nil
}
<|endoftext|>


<commit_before>// ----------------------------------------------------------------------------
//
//     ***     AUTO GENERATED CODE    ***    AUTO GENERATED CODE     ***
//
// ----------------------------------------------------------------------------
//
//     This file is automatically generated by Magic Modules and manual
//     changes will be clobbered when the file is regenerated.
//
//     Please read more about how to change this file in
//     .github/CONTRIBUTING.md.
//
// ----------------------------------------------------------------------------

package google

import "reflect"

func GetLoggingMetricCaiObject(d TerraformResourceData, config *Config) (Asset, error) {
	name, err := assetName(d, config, "//logging.googleapis.com/projects/{{project}}/metrics/{{%name}}")
	if err != nil {
		return Asset{}, err
	}
	if obj, err := GetLoggingMetricApiObject(d, config); err == nil {
		return Asset{
			Name: name,
			Type: "logging.googleapis.com/Metric",
			Resource: &AssetResource{
				Version:              "v2",
				DiscoveryDocumentURI: "https://www.googleapis.com/discovery/v1/apis/logging/v2/rest",
				DiscoveryName:        "Metric",
				Data:                 obj,
			},
		}, nil
	} else {
		return Asset{}, err
	}
}

func GetLoggingMetricApiObject(d TerraformResourceData, config *Config) (map[string]interface{}, error) {
	obj := make(map[string]interface{})
	nameProp, err := expandLoggingMetricName(d.Get("name"), d, config)
	if err != nil {
		return nil, err
	} else if v, ok := d.GetOkExists("name"); !isEmptyValue(reflect.ValueOf(nameProp)) && (ok || !reflect.DeepEqual(v, nameProp)) {
		obj["name"] = nameProp
	}
	descriptionProp, err := expandLoggingMetricDescription(d.Get("description"), d, config)
	if err != nil {
		return nil, err
	} else if v, ok := d.GetOkExists("description"); !isEmptyValue(reflect.ValueOf(descriptionProp)) && (ok || !reflect.DeepEqual(v, descriptionProp)) {
		obj["description"] = descriptionProp
	}
	filterProp, err := expandLoggingMetricFilter(d.Get("filter"), d, config)
	if err != nil {
		return nil, err
	} else if v, ok := d.GetOkExists("filter"); !isEmptyValue(reflect.ValueOf(filterProp)) && (ok || !reflect.DeepEqual(v, filterProp)) {
		obj["filter"] = filterProp
	}
	metricDescriptorProp, err := expandLoggingMetricMetricDescriptor(d.Get("metric_descriptor"), d, config)
	if err != nil {
		return nil, err
	} else if v, ok := d.GetOkExists("metric_descriptor"); !isEmptyValue(reflect.ValueOf(metricDescriptorProp)) && (ok || !reflect.DeepEqual(v, metricDescriptorProp)) {
		obj["metricDescriptor"] = metricDescriptorProp
	}
	labelExtractorsProp, err := expandLoggingMetricLabelExtractors(d.Get("label_extractors"), d, config)
	if err != nil {
		return nil, err
	} else if v, ok := d.GetOkExists("label_extractors"); !isEmptyValue(reflect.ValueOf(labelExtractorsProp)) && (ok || !reflect.DeepEqual(v, labelExtractorsProp)) {
		obj["labelExtractors"] = labelExtractorsProp
	}
	valueExtractorProp, err := expandLoggingMetricValueExtractor(d.Get("value_extractor"), d, config)
	if err != nil {
		return nil, err
	} else if v, ok := d.GetOkExists("value_extractor"); !isEmptyValue(reflect.ValueOf(valueExtractorProp)) && (ok || !reflect.DeepEqual(v, valueExtractorProp)) {
		obj["valueExtractor"] = valueExtractorProp
	}
	bucketOptionsProp, err := expandLoggingMetricBucketOptions(d.Get("bucket_options"), d, config)
	if err != nil {
		return nil, err
	} else if v, ok := d.GetOkExists("bucket_options"); !isEmptyValue(reflect.ValueOf(bucketOptionsProp)) && (ok || !reflect.DeepEqual(v, bucketOptionsProp)) {
		obj["bucketOptions"] = bucketOptionsProp
	}

	return obj, nil
}

func expandLoggingMetricName(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	return v, nil
}

func expandLoggingMetricDescription(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	return v, nil
}

func expandLoggingMetricFilter(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	return v, nil
}

func expandLoggingMetricMetricDescriptor(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	l := v.([]interface{})
	if len(l) == 0 || l[0] == nil {
		return nil, nil
	}
	raw := l[0]
	original := raw.(map[string]interface{})
	transformed := make(map[string]interface{})

	transformedUnit, err := expandLoggingMetricMetricDescriptorUnit(original["unit"], d, config)
	if err != nil {
		return nil, err
	} else if val := reflect.ValueOf(transformedUnit); val.IsValid() && !isEmptyValue(val) {
		transformed["unit"] = transformedUnit
	}

	transformedValueType, err := expandLoggingMetricMetricDescriptorValueType(original["value_type"], d, config)
	if err != nil {
		return nil, err
	} else if val := reflect.ValueOf(transformedValueType); val.IsValid() && !isEmptyValue(val) {
		transformed["valueType"] = transformedValueType
	}

	transformedMetricKind, err := expandLoggingMetricMetricDescriptorMetricKind(original["metric_kind"], d, config)
	if err != nil {
		return nil, err
	} else if val := reflect.ValueOf(transformedMetricKind); val.IsValid() && !isEmptyValue(val) {
		transformed["metricKind"] = transformedMetricKind
	}

	transformedLabels, err := expandLoggingMetricMetricDescriptorLabels(original["labels"], d, config)
	if err != nil {
		return nil, err
	} else if val := reflect.ValueOf(transformedLabels); val.IsValid() && !isEmptyValue(val) {
		transformed["labels"] = transformedLabels
	}

	return transformed, nil
}

func expandLoggingMetricMetricDescriptorUnit(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	return v, nil
}

func expandLoggingMetricMetricDescriptorValueType(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	return v, nil
}

func expandLoggingMetricMetricDescriptorMetricKind(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	return v, nil
}

func expandLoggingMetricMetricDescriptorLabels(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	l := v.([]interface{})
	req := make([]interface{}, 0, len(l))
	for _, raw := range l {
		if raw == nil {
			continue
		}
		original := raw.(map[string]interface{})
		transformed := make(map[string]interface{})

		transformedKey, err := expandLoggingMetricMetricDescriptorLabelsKey(original["key"], d, config)
		if err != nil {
			return nil, err
		} else if val := reflect.ValueOf(transformedKey); val.IsValid() && !isEmptyValue(val) {
			transformed["key"] = transformedKey
		}

		transformedDescription, err := expandLoggingMetricMetricDescriptorLabelsDescription(original["description"], d, config)
		if err != nil {
			return nil, err
		} else if val := reflect.ValueOf(transformedDescription); val.IsValid() && !isEmptyValue(val) {
			transformed["description"] = transformedDescription
		}

		transformedValueType, err := expandLoggingMetricMetricDescriptorLabelsValueType(original["value_type"], d, config)
		if err != nil {
			return nil, err
		} else if val := reflect.ValueOf(transformedValueType); val.IsValid() && !isEmptyValue(val) {
			transformed["valueType"] = transformedValueType
		}

		req = append(req, transformed)
	}
	return req, nil
}

func expandLoggingMetricMetricDescriptorLabelsKey(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	return v, nil
}

func expandLoggingMetricMetricDescriptorLabelsDescription(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	return v, nil
}

func expandLoggingMetricMetricDescriptorLabelsValueType(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	return v, nil
}

func expandLoggingMetricLabelExtractors(v interface{}, d TerraformResourceData, config *Config) (map[string]string, error) {
	if v == nil {
		return map[string]string{}, nil
	}
	m := make(map[string]string)
	for k, val := range v.(map[string]interface{}) {
		m[k] = val.(string)
	}
	return m, nil
}

func expandLoggingMetricValueExtractor(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	return v, nil
}

func expandLoggingMetricBucketOptions(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	l := v.([]interface{})
	if len(l) == 0 || l[0] == nil {
		return nil, nil
	}
	raw := l[0]
	original := raw.(map[string]interface{})
	transformed := make(map[string]interface{})

	transformedLinearBuckets, err := expandLoggingMetricBucketOptionsLinearBuckets(original["linear_buckets"], d, config)
	if err != nil {
		return nil, err
	} else if val := reflect.ValueOf(transformedLinearBuckets); val.IsValid() && !isEmptyValue(val) {
		transformed["linearBuckets"] = transformedLinearBuckets
	}

	transformedExponentialBuckets, err := expandLoggingMetricBucketOptionsExponentialBuckets(original["exponential_buckets"], d, config)
	if err != nil {
		return nil, err
	} else if val := reflect.ValueOf(transformedExponentialBuckets); val.IsValid() && !isEmptyValue(val) {
		transformed["exponentialBuckets"] = transformedExponentialBuckets
	}

	transformedExplicitBuckets, err := expandLoggingMetricBucketOptionsExplicitBuckets(original["explicit_buckets"], d, config)
	if err != nil {
		return nil, err
	} else if val := reflect.ValueOf(transformedExplicitBuckets); val.IsValid() && !isEmptyValue(val) {
		transformed["explicitBuckets"] = transformedExplicitBuckets
	}

	return transformed, nil
}

func expandLoggingMetricBucketOptionsLinearBuckets(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	l := v.([]interface{})
	if len(l) == 0 || l[0] == nil {
		return nil, nil
	}
	raw := l[0]
	original := raw.(map[string]interface{})
	transformed := make(map[string]interface{})

	transformedNumFiniteBuckets, err := expandLoggingMetricBucketOptionsLinearBucketsNumFiniteBuckets(original["num_finite_buckets"], d, config)
	if err != nil {
		return nil, err
	} else if val := reflect.ValueOf(transformedNumFiniteBuckets); val.IsValid() && !isEmptyValue(val) {
		transformed["numFiniteBuckets"] = transformedNumFiniteBuckets
	}

	transformedWidth, err := expandLoggingMetricBucketOptionsLinearBucketsWidth(original["width"], d, config)
	if err != nil {
		return nil, err
	} else if val := reflect.ValueOf(transformedWidth); val.IsValid() && !isEmptyValue(val) {
		transformed["width"] = transformedWidth
	}

	transformedOffset, err := expandLoggingMetricBucketOptionsLinearBucketsOffset(original["offset"], d, config)
	if err != nil {
		return nil, err
	} else if val := reflect.ValueOf(transformedOffset); val.IsValid() && !isEmptyValue(val) {
		transformed["offset"] = transformedOffset
	}

	return transformed, nil
}

func expandLoggingMetricBucketOptionsLinearBucketsNumFiniteBuckets(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	return v, nil
}

func expandLoggingMetricBucketOptionsLinearBucketsWidth(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	return v, nil
}

func expandLoggingMetricBucketOptionsLinearBucketsOffset(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	return v, nil
}

func expandLoggingMetricBucketOptionsExponentialBuckets(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	l := v.([]interface{})
	if len(l) == 0 || l[0] == nil {
		return nil, nil
	}
	raw := l[0]
	original := raw.(map[string]interface{})
	transformed := make(map[string]interface{})

	transformedNumFiniteBuckets, err := expandLoggingMetricBucketOptionsExponentialBucketsNumFiniteBuckets(original["num_finite_buckets"], d, config)
	if err != nil {
		return nil, err
	} else if val := reflect.ValueOf(transformedNumFiniteBuckets); val.IsValid() && !isEmptyValue(val) {
		transformed["numFiniteBuckets"] = transformedNumFiniteBuckets
	}

	transformedGrowthFactor, err := expandLoggingMetricBucketOptionsExponentialBucketsGrowthFactor(original["growth_factor"], d, config)
	if err != nil {
		return nil, err
	} else if val := reflect.ValueOf(transformedGrowthFactor); val.IsValid() && !isEmptyValue(val) {
		transformed["growthFactor"] = transformedGrowthFactor
	}

	transformedScale, err := expandLoggingMetricBucketOptionsExponentialBucketsScale(original["scale"], d, config)
	if err != nil {
		return nil, err
	} else if val := reflect.ValueOf(transformedScale); val.IsValid() && !isEmptyValue(val) {
		transformed["scale"] = transformedScale
	}

	return transformed, nil
}

func expandLoggingMetricBucketOptionsExponentialBucketsNumFiniteBuckets(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	return v, nil
}

func expandLoggingMetricBucketOptionsExponentialBucketsGrowthFactor(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	return v, nil
}

func expandLoggingMetricBucketOptionsExponentialBucketsScale(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	return v, nil
}

func expandLoggingMetricBucketOptionsExplicitBuckets(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	l := v.([]interface{})
	if len(l) == 0 || l[0] == nil {
		return nil, nil
	}
	raw := l[0]
	original := raw.(map[string]interface{})
	transformed := make(map[string]interface{})

	transformedBounds, err := expandLoggingMetricBucketOptionsExplicitBucketsBounds(original["bounds"], d, config)
	if err != nil {
		return nil, err
	} else if val := reflect.ValueOf(transformedBounds); val.IsValid() && !isEmptyValue(val) {
		transformed["bounds"] = transformedBounds
	}

	return transformed, nil
}

func expandLoggingMetricBucketOptionsExplicitBucketsBounds(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	return v, nil
}
<commit_msg>Add display_name to logging_metric<commit_after>// ----------------------------------------------------------------------------
//
//     ***     AUTO GENERATED CODE    ***    AUTO GENERATED CODE     ***
//
// ----------------------------------------------------------------------------
//
//     This file is automatically generated by Magic Modules and manual
//     changes will be clobbered when the file is regenerated.
//
//     Please read more about how to change this file in
//     .github/CONTRIBUTING.md.
//
// ----------------------------------------------------------------------------

package google

import "reflect"

func GetLoggingMetricCaiObject(d TerraformResourceData, config *Config) (Asset, error) {
	name, err := assetName(d, config, "//logging.googleapis.com/projects/{{project}}/metrics/{{%name}}")
	if err != nil {
		return Asset{}, err
	}
	if obj, err := GetLoggingMetricApiObject(d, config); err == nil {
		return Asset{
			Name: name,
			Type: "logging.googleapis.com/Metric",
			Resource: &AssetResource{
				Version:              "v2",
				DiscoveryDocumentURI: "https://www.googleapis.com/discovery/v1/apis/logging/v2/rest",
				DiscoveryName:        "Metric",
				Data:                 obj,
			},
		}, nil
	} else {
		return Asset{}, err
	}
}

func GetLoggingMetricApiObject(d TerraformResourceData, config *Config) (map[string]interface{}, error) {
	obj := make(map[string]interface{})
	nameProp, err := expandLoggingMetricName(d.Get("name"), d, config)
	if err != nil {
		return nil, err
	} else if v, ok := d.GetOkExists("name"); !isEmptyValue(reflect.ValueOf(nameProp)) && (ok || !reflect.DeepEqual(v, nameProp)) {
		obj["name"] = nameProp
	}
	descriptionProp, err := expandLoggingMetricDescription(d.Get("description"), d, config)
	if err != nil {
		return nil, err
	} else if v, ok := d.GetOkExists("description"); !isEmptyValue(reflect.ValueOf(descriptionProp)) && (ok || !reflect.DeepEqual(v, descriptionProp)) {
		obj["description"] = descriptionProp
	}
	filterProp, err := expandLoggingMetricFilter(d.Get("filter"), d, config)
	if err != nil {
		return nil, err
	} else if v, ok := d.GetOkExists("filter"); !isEmptyValue(reflect.ValueOf(filterProp)) && (ok || !reflect.DeepEqual(v, filterProp)) {
		obj["filter"] = filterProp
	}
	metricDescriptorProp, err := expandLoggingMetricMetricDescriptor(d.Get("metric_descriptor"), d, config)
	if err != nil {
		return nil, err
	} else if v, ok := d.GetOkExists("metric_descriptor"); !isEmptyValue(reflect.ValueOf(metricDescriptorProp)) && (ok || !reflect.DeepEqual(v, metricDescriptorProp)) {
		obj["metricDescriptor"] = metricDescriptorProp
	}
	labelExtractorsProp, err := expandLoggingMetricLabelExtractors(d.Get("label_extractors"), d, config)
	if err != nil {
		return nil, err
	} else if v, ok := d.GetOkExists("label_extractors"); !isEmptyValue(reflect.ValueOf(labelExtractorsProp)) && (ok || !reflect.DeepEqual(v, labelExtractorsProp)) {
		obj["labelExtractors"] = labelExtractorsProp
	}
	valueExtractorProp, err := expandLoggingMetricValueExtractor(d.Get("value_extractor"), d, config)
	if err != nil {
		return nil, err
	} else if v, ok := d.GetOkExists("value_extractor"); !isEmptyValue(reflect.ValueOf(valueExtractorProp)) && (ok || !reflect.DeepEqual(v, valueExtractorProp)) {
		obj["valueExtractor"] = valueExtractorProp
	}
	bucketOptionsProp, err := expandLoggingMetricBucketOptions(d.Get("bucket_options"), d, config)
	if err != nil {
		return nil, err
	} else if v, ok := d.GetOkExists("bucket_options"); !isEmptyValue(reflect.ValueOf(bucketOptionsProp)) && (ok || !reflect.DeepEqual(v, bucketOptionsProp)) {
		obj["bucketOptions"] = bucketOptionsProp
	}

	return obj, nil
}

func expandLoggingMetricName(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	return v, nil
}

func expandLoggingMetricDescription(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	return v, nil
}

func expandLoggingMetricFilter(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	return v, nil
}

func expandLoggingMetricMetricDescriptor(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	l := v.([]interface{})
	if len(l) == 0 || l[0] == nil {
		return nil, nil
	}
	raw := l[0]
	original := raw.(map[string]interface{})
	transformed := make(map[string]interface{})

	transformedUnit, err := expandLoggingMetricMetricDescriptorUnit(original["unit"], d, config)
	if err != nil {
		return nil, err
	} else if val := reflect.ValueOf(transformedUnit); val.IsValid() && !isEmptyValue(val) {
		transformed["unit"] = transformedUnit
	}

	transformedValueType, err := expandLoggingMetricMetricDescriptorValueType(original["value_type"], d, config)
	if err != nil {
		return nil, err
	} else if val := reflect.ValueOf(transformedValueType); val.IsValid() && !isEmptyValue(val) {
		transformed["valueType"] = transformedValueType
	}

	transformedMetricKind, err := expandLoggingMetricMetricDescriptorMetricKind(original["metric_kind"], d, config)
	if err != nil {
		return nil, err
	} else if val := reflect.ValueOf(transformedMetricKind); val.IsValid() && !isEmptyValue(val) {
		transformed["metricKind"] = transformedMetricKind
	}

	transformedLabels, err := expandLoggingMetricMetricDescriptorLabels(original["labels"], d, config)
	if err != nil {
		return nil, err
	} else if val := reflect.ValueOf(transformedLabels); val.IsValid() && !isEmptyValue(val) {
		transformed["labels"] = transformedLabels
	}

	transformedDisplayName, err := expandLoggingMetricMetricDescriptorDisplayName(original["display_name"], d, config)
	if err != nil {
		return nil, err
	} else if val := reflect.ValueOf(transformedDisplayName); val.IsValid() && !isEmptyValue(val) {
		transformed["displayName"] = transformedDisplayName
	}

	return transformed, nil
}

func expandLoggingMetricMetricDescriptorUnit(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	return v, nil
}

func expandLoggingMetricMetricDescriptorValueType(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	return v, nil
}

func expandLoggingMetricMetricDescriptorMetricKind(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	return v, nil
}

func expandLoggingMetricMetricDescriptorLabels(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	l := v.([]interface{})
	req := make([]interface{}, 0, len(l))
	for _, raw := range l {
		if raw == nil {
			continue
		}
		original := raw.(map[string]interface{})
		transformed := make(map[string]interface{})

		transformedKey, err := expandLoggingMetricMetricDescriptorLabelsKey(original["key"], d, config)
		if err != nil {
			return nil, err
		} else if val := reflect.ValueOf(transformedKey); val.IsValid() && !isEmptyValue(val) {
			transformed["key"] = transformedKey
		}

		transformedDescription, err := expandLoggingMetricMetricDescriptorLabelsDescription(original["description"], d, config)
		if err != nil {
			return nil, err
		} else if val := reflect.ValueOf(transformedDescription); val.IsValid() && !isEmptyValue(val) {
			transformed["description"] = transformedDescription
		}

		transformedValueType, err := expandLoggingMetricMetricDescriptorLabelsValueType(original["value_type"], d, config)
		if err != nil {
			return nil, err
		} else if val := reflect.ValueOf(transformedValueType); val.IsValid() && !isEmptyValue(val) {
			transformed["valueType"] = transformedValueType
		}

		req = append(req, transformed)
	}
	return req, nil
}

func expandLoggingMetricMetricDescriptorLabelsKey(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	return v, nil
}

func expandLoggingMetricMetricDescriptorLabelsDescription(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	return v, nil
}

func expandLoggingMetricMetricDescriptorLabelsValueType(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	return v, nil
}

func expandLoggingMetricMetricDescriptorDisplayName(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	return v, nil
}

func expandLoggingMetricLabelExtractors(v interface{}, d TerraformResourceData, config *Config) (map[string]string, error) {
	if v == nil {
		return map[string]string{}, nil
	}
	m := make(map[string]string)
	for k, val := range v.(map[string]interface{}) {
		m[k] = val.(string)
	}
	return m, nil
}

func expandLoggingMetricValueExtractor(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	return v, nil
}

func expandLoggingMetricBucketOptions(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	l := v.([]interface{})
	if len(l) == 0 || l[0] == nil {
		return nil, nil
	}
	raw := l[0]
	original := raw.(map[string]interface{})
	transformed := make(map[string]interface{})

	transformedLinearBuckets, err := expandLoggingMetricBucketOptionsLinearBuckets(original["linear_buckets"], d, config)
	if err != nil {
		return nil, err
	} else if val := reflect.ValueOf(transformedLinearBuckets); val.IsValid() && !isEmptyValue(val) {
		transformed["linearBuckets"] = transformedLinearBuckets
	}

	transformedExponentialBuckets, err := expandLoggingMetricBucketOptionsExponentialBuckets(original["exponential_buckets"], d, config)
	if err != nil {
		return nil, err
	} else if val := reflect.ValueOf(transformedExponentialBuckets); val.IsValid() && !isEmptyValue(val) {
		transformed["exponentialBuckets"] = transformedExponentialBuckets
	}

	transformedExplicitBuckets, err := expandLoggingMetricBucketOptionsExplicitBuckets(original["explicit_buckets"], d, config)
	if err != nil {
		return nil, err
	} else if val := reflect.ValueOf(transformedExplicitBuckets); val.IsValid() && !isEmptyValue(val) {
		transformed["explicitBuckets"] = transformedExplicitBuckets
	}

	return transformed, nil
}

func expandLoggingMetricBucketOptionsLinearBuckets(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	l := v.([]interface{})
	if len(l) == 0 || l[0] == nil {
		return nil, nil
	}
	raw := l[0]
	original := raw.(map[string]interface{})
	transformed := make(map[string]interface{})

	transformedNumFiniteBuckets, err := expandLoggingMetricBucketOptionsLinearBucketsNumFiniteBuckets(original["num_finite_buckets"], d, config)
	if err != nil {
		return nil, err
	} else if val := reflect.ValueOf(transformedNumFiniteBuckets); val.IsValid() && !isEmptyValue(val) {
		transformed["numFiniteBuckets"] = transformedNumFiniteBuckets
	}

	transformedWidth, err := expandLoggingMetricBucketOptionsLinearBucketsWidth(original["width"], d, config)
	if err != nil {
		return nil, err
	} else if val := reflect.ValueOf(transformedWidth); val.IsValid() && !isEmptyValue(val) {
		transformed["width"] = transformedWidth
	}

	transformedOffset, err := expandLoggingMetricBucketOptionsLinearBucketsOffset(original["offset"], d, config)
	if err != nil {
		return nil, err
	} else if val := reflect.ValueOf(transformedOffset); val.IsValid() && !isEmptyValue(val) {
		transformed["offset"] = transformedOffset
	}

	return transformed, nil
}

func expandLoggingMetricBucketOptionsLinearBucketsNumFiniteBuckets(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	return v, nil
}

func expandLoggingMetricBucketOptionsLinearBucketsWidth(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	return v, nil
}

func expandLoggingMetricBucketOptionsLinearBucketsOffset(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	return v, nil
}

func expandLoggingMetricBucketOptionsExponentialBuckets(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	l := v.([]interface{})
	if len(l) == 0 || l[0] == nil {
		return nil, nil
	}
	raw := l[0]
	original := raw.(map[string]interface{})
	transformed := make(map[string]interface{})

	transformedNumFiniteBuckets, err := expandLoggingMetricBucketOptionsExponentialBucketsNumFiniteBuckets(original["num_finite_buckets"], d, config)
	if err != nil {
		return nil, err
	} else if val := reflect.ValueOf(transformedNumFiniteBuckets); val.IsValid() && !isEmptyValue(val) {
		transformed["numFiniteBuckets"] = transformedNumFiniteBuckets
	}

	transformedGrowthFactor, err := expandLoggingMetricBucketOptionsExponentialBucketsGrowthFactor(original["growth_factor"], d, config)
	if err != nil {
		return nil, err
	} else if val := reflect.ValueOf(transformedGrowthFactor); val.IsValid() && !isEmptyValue(val) {
		transformed["growthFactor"] = transformedGrowthFactor
	}

	transformedScale, err := expandLoggingMetricBucketOptionsExponentialBucketsScale(original["scale"], d, config)
	if err != nil {
		return nil, err
	} else if val := reflect.ValueOf(transformedScale); val.IsValid() && !isEmptyValue(val) {
		transformed["scale"] = transformedScale
	}

	return transformed, nil
}

func expandLoggingMetricBucketOptionsExponentialBucketsNumFiniteBuckets(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	return v, nil
}

func expandLoggingMetricBucketOptionsExponentialBucketsGrowthFactor(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	return v, nil
}

func expandLoggingMetricBucketOptionsExponentialBucketsScale(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	return v, nil
}

func expandLoggingMetricBucketOptionsExplicitBuckets(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	l := v.([]interface{})
	if len(l) == 0 || l[0] == nil {
		return nil, nil
	}
	raw := l[0]
	original := raw.(map[string]interface{})
	transformed := make(map[string]interface{})

	transformedBounds, err := expandLoggingMetricBucketOptionsExplicitBucketsBounds(original["bounds"], d, config)
	if err != nil {
		return nil, err
	} else if val := reflect.ValueOf(transformedBounds); val.IsValid() && !isEmptyValue(val) {
		transformed["bounds"] = transformedBounds
	}

	return transformed, nil
}

func expandLoggingMetricBucketOptionsExplicitBucketsBounds(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	return v, nil
}
<|endoftext|>


<commit_before>package pep

//go:generate bash -c "mkdir -p $GOPATH/src/github.com/infobloxopen/policy-box/pdp-service && protoc -I $GOPATH/src/github.com/infobloxopen/policy-box/proto/ $GOPATH/src/github.com/infobloxopen/policy-box/proto/service.proto --go_out=plugins=grpc:$GOPATH/src/github.com/infobloxopen/policy-box/pdp-service && ls $GOPATH/src/github.com/infobloxopen/policy-box/pdp-service"

import (
	"fmt"
	"reflect"
	"time"

	"golang.org/x/net/context"
	"google.golang.org/grpc"

	pb "github.com/infobloxopen/policy-box/pdp-service"
)

var (
	ErrorConnected    = fmt.Errorf("Connection has been already established")
	ErrorNotConnected = fmt.Errorf("No connection")
)

type Client struct {
	addr   string
	conn   *grpc.ClientConn
	client *pb.PDPClient
}

func NewClient(addr string) *Client {
	return &Client{addr: addr}
}

func (c *Client) Connect(timeout time.Duration) error {
	if c.conn != nil {
		return ErrorConnected
	}

	conn, err := grpc.Dial(c.addr, grpc.WithInsecure(), grpc.WithBlock(), grpc.WithTimeout(timeout))
	if err != nil {
		return err
	}

	c.conn = conn

	client := pb.NewPDPClient(c.conn)
	c.client = &client

	return nil
}

func (c *Client) Close() {
	if c.conn != nil {
		c.conn.Close()
		c.conn = nil
	}

	c.client = nil
}

func (c *Client) Validate(in, out interface{}) error {
	if c.client == nil {
		return ErrorNotConnected
	}

	req, err := makeRequest(in)
	if err != nil {
		return err
	}

	res, err := (*c.client).Validate(context.Background(), &req)
	if err != nil {
		return err
	}

	return fillResponse(res, out)
}

func makeRequest(v interface{}) (pb.Request, error) {
	attrs, err := marshalValue(reflect.ValueOf(v))
	if err != nil {
		return pb.Request{}, err
	}

	return pb.Request{attrs}, nil
}

func fillResponse(res *pb.Response, v interface{}) error {
	return unmarshalToValue(res, reflect.ValueOf(v))
}
<commit_msg>Allow PEP users to build their own requests<commit_after>package pep

//go:generate bash -c "mkdir -p $GOPATH/src/github.com/infobloxopen/policy-box/pdp-service && protoc -I $GOPATH/src/github.com/infobloxopen/policy-box/proto/ $GOPATH/src/github.com/infobloxopen/policy-box/proto/service.proto --go_out=plugins=grpc:$GOPATH/src/github.com/infobloxopen/policy-box/pdp-service && ls $GOPATH/src/github.com/infobloxopen/policy-box/pdp-service"

import (
	"fmt"
	"reflect"
	"time"

	"golang.org/x/net/context"
	"google.golang.org/grpc"

	pb "github.com/infobloxopen/policy-box/pdp-service"
)

var (
	ErrorConnected    = fmt.Errorf("Connection has been already established")
	ErrorNotConnected = fmt.Errorf("No connection")
)

type Client struct {
	addr   string
	conn   *grpc.ClientConn
	client *pb.PDPClient
}

func NewClient(addr string) *Client {
	return &Client{addr: addr}
}

func (c *Client) Connect(timeout time.Duration) error {
	if c.conn != nil {
		return ErrorConnected
	}

	conn, err := grpc.Dial(c.addr, grpc.WithInsecure(), grpc.WithBlock(), grpc.WithTimeout(timeout))
	if err != nil {
		return err
	}

	c.conn = conn

	client := pb.NewPDPClient(c.conn)
	c.client = &client

	return nil
}

func (c *Client) Close() {
	if c.conn != nil {
		c.conn.Close()
		c.conn = nil
	}

	c.client = nil
}

func (c *Client) Validate(in, out interface{}) error {
	if c.client == nil {
		return ErrorNotConnected
	}

	req, err := makeRequest(in)
	if err != nil {
		return err
	}

	res, err := (*c.client).Validate(context.Background(), &req)
	if err != nil {
		return err
	}

	return fillResponse(res, out)
}

func makeRequest(v interface{}) (pb.Request, error) {
	if req, ok := v.(pb.Request); ok {
		return req, nil
	}
	attrs, err := marshalValue(reflect.ValueOf(v))
	if err != nil {
		return pb.Request{}, err
	}

	return pb.Request{attrs}, nil
}

func fillResponse(res *pb.Response, v interface{}) error {
	return unmarshalToValue(res, reflect.ValueOf(v))
}
<|endoftext|>


<commit_before>/*
Copyright 2016 The Kubernetes Authors.

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

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

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

package rest

import (
	"fmt"

	"k8s.io/kubernetes/cmd/libs/go2idl/client-gen/test_apis/testgroup.k8s.io"
	"k8s.io/kubernetes/pkg/api"
	"k8s.io/kubernetes/pkg/fields"
	"k8s.io/kubernetes/pkg/labels"
	"k8s.io/kubernetes/pkg/registry/generic"
	"k8s.io/kubernetes/pkg/registry/generic/registry"
	"k8s.io/kubernetes/pkg/runtime"
	"k8s.io/kubernetes/pkg/storage"
	"k8s.io/kubernetes/pkg/storage/storagebackend"
)

type REST struct {
	*registry.Store
}

// NewREST returns a RESTStorage object that will work with testtype.
func NewREST(config *storagebackend.Config, storageDecorator generic.StorageDecorator) *REST {
	prefix := "/testtype"
	newListFunc := func() runtime.Object { return &testgroup.TestTypeList{} }
	// Usually you should reuse your RESTCreateStrategy.
	strategy := &NotNamespaceScoped{}
	storageInterface := storageDecorator(
		config, 100, &testgroup.TestType{}, prefix, strategy, newListFunc, storage.NoTriggerPublisher)
	store := &registry.Store{
		NewFunc: func() runtime.Object { return &testgroup.TestType{} },
		// NewListFunc returns an object capable of storing results of an etcd list.
		NewListFunc: newListFunc,
		// Produces a path that etcd understands, to the root of the resource
		// by combining the namespace in the context with the given prefix.
		KeyRootFunc: func(ctx api.Context) string {
			return registry.NamespaceKeyRootFunc(ctx, prefix)
		},
		// Produces a path that etcd understands, to the resource by combining
		// the namespace in the context with the given prefix.
		KeyFunc: func(ctx api.Context, name string) (string, error) {
			return registry.NamespaceKeyFunc(ctx, prefix, name)
		},
		// Retrieve the name field of the resource.
		ObjectNameFunc: func(obj runtime.Object) (string, error) {
			return obj.(*testgroup.TestType).Name, nil
		},
		// Used to match objects based on labels/fields for list.
		PredicateFunc: func(label labels.Selector, field fields.Selector) generic.Matcher {
			return &generic.SelectionPredicate{
				Label: label,
				Field: field,
				GetAttrs: func(obj runtime.Object) (labels.Set, fields.Set, error) {
					testType, ok := obj.(*testgroup.TestType)
					if !ok {
						return nil, nil, fmt.Errorf("unexpected type of given object")
					}
					return labels.Set(testType.ObjectMeta.Labels), fields.Set{}, nil
				},
			}
		},
		Storage: storageInterface,
	}
	return &REST{store}
}

type NotNamespaceScoped struct {
}

func (*NotNamespaceScoped) NamespaceScoped() bool {
	return false
}
<commit_msg>generic.Matcher -> *generic.SelectionPredicate<commit_after>/*
Copyright 2016 The Kubernetes Authors.

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

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

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

package rest

import (
	"fmt"

	"k8s.io/kubernetes/cmd/libs/go2idl/client-gen/test_apis/testgroup.k8s.io"
	"k8s.io/kubernetes/pkg/api"
	"k8s.io/kubernetes/pkg/fields"
	"k8s.io/kubernetes/pkg/labels"
	"k8s.io/kubernetes/pkg/registry/generic"
	"k8s.io/kubernetes/pkg/registry/generic/registry"
	"k8s.io/kubernetes/pkg/runtime"
	"k8s.io/kubernetes/pkg/storage"
	"k8s.io/kubernetes/pkg/storage/storagebackend"
)

type REST struct {
	*registry.Store
}

// NewREST returns a RESTStorage object that will work with testtype.
func NewREST(config *storagebackend.Config, storageDecorator generic.StorageDecorator) *REST {
	prefix := "/testtype"
	newListFunc := func() runtime.Object { return &testgroup.TestTypeList{} }
	// Usually you should reuse your RESTCreateStrategy.
	strategy := &NotNamespaceScoped{}
	storageInterface := storageDecorator(
		config, 100, &testgroup.TestType{}, prefix, strategy, newListFunc, storage.NoTriggerPublisher)
	store := &registry.Store{
		NewFunc: func() runtime.Object { return &testgroup.TestType{} },
		// NewListFunc returns an object capable of storing results of an etcd list.
		NewListFunc: newListFunc,
		// Produces a path that etcd understands, to the root of the resource
		// by combining the namespace in the context with the given prefix.
		KeyRootFunc: func(ctx api.Context) string {
			return registry.NamespaceKeyRootFunc(ctx, prefix)
		},
		// Produces a path that etcd understands, to the resource by combining
		// the namespace in the context with the given prefix.
		KeyFunc: func(ctx api.Context, name string) (string, error) {
			return registry.NamespaceKeyFunc(ctx, prefix, name)
		},
		// Retrieve the name field of the resource.
		ObjectNameFunc: func(obj runtime.Object) (string, error) {
			return obj.(*testgroup.TestType).Name, nil
		},
		// Used to match objects based on labels/fields for list.
		PredicateFunc: func(label labels.Selector, field fields.Selector) *generic.SelectionPredicate {
			return &generic.SelectionPredicate{
				Label: label,
				Field: field,
				GetAttrs: func(obj runtime.Object) (labels.Set, fields.Set, error) {
					testType, ok := obj.(*testgroup.TestType)
					if !ok {
						return nil, nil, fmt.Errorf("unexpected type of given object")
					}
					return labels.Set(testType.ObjectMeta.Labels), fields.Set{}, nil
				},
			}
		},
		Storage: storageInterface,
	}
	return &REST{store}
}

type NotNamespaceScoped struct {
}

func (*NotNamespaceScoped) NamespaceScoped() bool {
	return false
}
<|endoftext|>


<commit_before>// +build linux

package main

import (
	"bufio"
	"bytes"
	"encoding/gob"
	"fmt"
	"io"
	"os"

	"github.com/Symantec/Dominator/lib/errors"
	"github.com/Symantec/Dominator/lib/fsutil"
	"github.com/Symantec/Dominator/lib/image"
	"github.com/Symantec/Dominator/lib/log"
	"github.com/Symantec/Dominator/lib/srpc"
	proto "github.com/Symantec/Dominator/proto/imaginator"
)

func buildImageSubcommand(args []string, logger log.Logger) {
	if err := buildImage(args, logger); err != nil {
		fmt.Fprintf(os.Stderr, "Error building image: %s\n", err)
		os.Exit(1)
	}
	os.Exit(0)
}

func buildImage(args []string, logger log.Logger) error {
	srpcClient := getImaginatorClient()
	request := proto.BuildImageRequest{
		StreamName:     args[0],
		ExpiresIn:      *expiresIn,
		MaxSourceAge:   *maxSourceAge,
		StreamBuildLog: true,
	}
	if len(args) > 1 {
		request.GitBranch = args[1]
	}
	if *imageFilename != "" {
		request.ReturnImage = true
	}
	logBuffer := &bytes.Buffer{}
	var logWriter io.Writer
	if *alwaysShowBuildLog {
		fmt.Fprintln(os.Stderr, "Start of build log ==========================")
		logWriter = os.Stderr
	} else {
		logWriter = logBuffer
	}
	var reply proto.BuildImageResponse
	err := callBuildImage(srpcClient, request, &reply, logWriter)
	if err != nil {
		if !*alwaysShowBuildLog {
			os.Stderr.Write(logBuffer.Bytes())
		}
		fmt.Fprintln(os.Stderr, "End of build log ============================")
		return err
	}
	if *alwaysShowBuildLog {
		fmt.Fprintln(os.Stderr, "End of build log ============================")
	}
	if *imageFilename != "" {
		if reply.Image == nil {
			if reply.ImageName == "" {
				return errors.New("no image returned: upgrade the Imaginator")
			}
			return fmt.Errorf(
				"image: %s uploaded, not returned: upgrade the Imaginator",
				reply.ImageName)
		}
		return writeImage(reply.Image, *imageFilename)
	}
	fmt.Println(reply.ImageName)
	return nil
}

func callBuildImage(client *srpc.Client, request proto.BuildImageRequest,
	response *proto.BuildImageResponse, logWriter io.Writer) error {
	conn, err := client.Call("Imaginator.BuildImage")
	if err != nil {
		return err
	}
	defer conn.Close()
	decoder := gob.NewDecoder(conn)
	encoder := gob.NewEncoder(conn)
	if err := encoder.Encode(request); err != nil {
		return err
	}
	if err := conn.Flush(); err != nil {
		return err
	}
	str, err := conn.ReadString('\n')
	if err != nil {
		return err
	}
	if str != "\n" {
		return errors.New(str[:len(str)-1])
	}
	for {
		var reply proto.BuildImageResponse
		if err := decoder.Decode(&reply); err != nil {
			return fmt.Errorf("error reading reply: %s", err)
		}
		if err := errors.New(reply.ErrorString); err != nil {
			return err
		}
		logWriter.Write(reply.BuildLog)
		reply.BuildLog = nil
		if reply.Image != nil || reply.ImageName != "" {
			*response = reply
			return nil
		}
	}
}

func writeImage(img *image.Image, filename string) error {
	file, err := fsutil.CreateRenamingWriter(filename, fsutil.PublicFilePerms)
	if err != nil {
		return err
	}
	defer file.Close()
	writer := bufio.NewWriter(file)
	defer writer.Flush()
	encoder := gob.NewEncoder(writer)
	return encoder.Encode(img)
}
<commit_msg>Make use of imagebuilder/client package in builder-tool.<commit_after>// +build linux

package main

import (
	"bufio"
	"bytes"
	"encoding/gob"
	"fmt"
	"io"
	"os"

	"github.com/Symantec/Dominator/imagebuilder/client"
	"github.com/Symantec/Dominator/lib/errors"
	"github.com/Symantec/Dominator/lib/fsutil"
	"github.com/Symantec/Dominator/lib/image"
	"github.com/Symantec/Dominator/lib/log"
	proto "github.com/Symantec/Dominator/proto/imaginator"
)

func buildImageSubcommand(args []string, logger log.Logger) {
	if err := buildImage(args, logger); err != nil {
		fmt.Fprintf(os.Stderr, "Error building image: %s\n", err)
		os.Exit(1)
	}
	os.Exit(0)
}

func buildImage(args []string, logger log.Logger) error {
	srpcClient := getImaginatorClient()
	request := proto.BuildImageRequest{
		StreamName:     args[0],
		ExpiresIn:      *expiresIn,
		MaxSourceAge:   *maxSourceAge,
		StreamBuildLog: true,
	}
	if len(args) > 1 {
		request.GitBranch = args[1]
	}
	if *imageFilename != "" {
		request.ReturnImage = true
	}
	logBuffer := &bytes.Buffer{}
	var logWriter io.Writer
	if *alwaysShowBuildLog {
		fmt.Fprintln(os.Stderr, "Start of build log ==========================")
		logWriter = os.Stderr
	} else {
		logWriter = logBuffer
	}
	var reply proto.BuildImageResponse
	err := client.BuildImage(srpcClient, request, &reply, logWriter)
	if err != nil {
		if !*alwaysShowBuildLog {
			os.Stderr.Write(logBuffer.Bytes())
		}
		fmt.Fprintln(os.Stderr, "End of build log ============================")
		return err
	}
	if *alwaysShowBuildLog {
		fmt.Fprintln(os.Stderr, "End of build log ============================")
	}
	if *imageFilename != "" {
		if reply.Image == nil {
			if reply.ImageName == "" {
				return errors.New("no image returned: upgrade the Imaginator")
			}
			return fmt.Errorf(
				"image: %s uploaded, not returned: upgrade the Imaginator",
				reply.ImageName)
		}
		return writeImage(reply.Image, *imageFilename)
	}
	fmt.Println(reply.ImageName)
	return nil
}

func writeImage(img *image.Image, filename string) error {
	file, err := fsutil.CreateRenamingWriter(filename, fsutil.PublicFilePerms)
	if err != nil {
		return err
	}
	defer file.Close()
	writer := bufio.NewWriter(file)
	defer writer.Flush()
	encoder := gob.NewEncoder(writer)
	return encoder.Encode(img)
}
<|endoftext|>


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

package main

import (
	"bytes"
	"io/ioutil"
	"log"
	"path/filepath"
	"strings"
	"testing"

	"github.com/golang/dep"
	"github.com/golang/dep/internal/gps"
	"github.com/golang/dep/internal/test"
	"github.com/pkg/errors"
)

var (
	discardLogger = log.New(ioutil.Discard, "", 0)
)

func newTestContext(h *test.Helper) *dep.Ctx {
	h.TempDir("src")
	pwd := h.Path(".")
	return &dep.Ctx{
		GOPATH: pwd,
		Out:    discardLogger,
		Err:    discardLogger,
	}
}

func TestGlideConfig_Convert(t *testing.T) {
	testCases := map[string]struct {
		yaml                glideYaml
		lock                *glideLock
		wantConvertErr      bool
		matchPairedVersion  bool
		projectRoot         gps.ProjectRoot
		wantSourceRepo      string
		wantConstraint      string
		wantRevision        gps.Revision
		wantVersion         string
		wantLockCount       int
		wantIgnoreCount     int
		wantIgnoredPackages []string
	}{
		"project": {
			yaml: glideYaml{
				Imports: []glidePackage{
					{
						Name:       "github.com/sdboyer/deptest",
						Repository: "https://github.com/sdboyer/deptest.git",
						Reference:  "v1.0.0",
					},
				},
			},
			lock: &glideLock{
				Imports: []glideLockedPackage{
					{
						Name:       "github.com/sdboyer/deptest",
						Repository: "https://github.com/sdboyer/deptest.git",
						Reference:  "ff2948a2ac8f538c4ecd55962e919d1e13e74baf",
					},
				},
			},
			projectRoot:        "github.com/sdboyer/deptest",
			wantSourceRepo:     "https://github.com/sdboyer/deptest.git",
			matchPairedVersion: true,
			wantConstraint:     "^1.0.0",
			wantLockCount:      1,
			wantRevision:       gps.Revision("ff2948a2ac8f538c4ecd55962e919d1e13e74baf"),
			wantVersion:        "v1.0.0",
		},
		"test project": {
			yaml: glideYaml{
				Imports: []glidePackage{
					{
						Name:      "github.com/sdboyer/deptest",
						Reference: "v1.0.0",
					},
				},
			},
			lock: &glideLock{
				Imports: []glideLockedPackage{
					{
						Name:      "github.com/sdboyer/deptest",
						Reference: "ff2948a2ac8f538c4ecd55962e919d1e13e74baf",
					},
				},
			},
			projectRoot:    "github.com/sdboyer/deptest",
			wantLockCount:  1,
			wantConstraint: "^1.0.0",
			wantVersion:    "v1.0.0",
		},
		"with ignored package": {
			yaml: glideYaml{
				Ignores: []string{"github.com/sdboyer/deptest"},
			},
			projectRoot:         "github.com/sdboyer/deptest",
			wantIgnoreCount:     1,
			wantIgnoredPackages: []string{"github.com/sdboyer/deptest"},
		},
		"with exclude dir": {
			yaml: glideYaml{
				ExcludeDirs: []string{"samples"},
			},
			projectRoot:         testProjectRoot,
			wantIgnoreCount:     1,
			wantIgnoredPackages: []string{"github.com/golang/notexist/samples"},
		},
		"exclude dir ignores mismatched package name": {
			yaml: glideYaml{
				Name:        "github.com/golang/mismatched-package-name",
				ExcludeDirs: []string{"samples"},
			},
			projectRoot:         testProjectRoot,
			wantIgnoreCount:     1,
			wantIgnoredPackages: []string{"github.com/golang/notexist/samples"},
		},
		"bad input, empty package name": {
			yaml: glideYaml{
				Imports: []glidePackage{{Name: ""}},
			},
			projectRoot:    testProjectRoot,
			wantConvertErr: true,
		},
	}

	h := test.NewHelper(t)
	defer h.Cleanup()

	ctx := newTestContext(h)
	sm, err := ctx.SourceManager()
	h.Must(err)
	defer sm.Release()

	for name, testCase := range testCases {
		t.Run(name, func(t *testing.T) {
			g := newGlideImporter(discardLogger, true, sm)
			g.yaml = testCase.yaml

			if testCase.lock != nil {
				g.lock = testCase.lock
			}

			manifest, lock, err := g.convert(testCase.projectRoot)
			if err != nil {
				if testCase.wantConvertErr {
					return
				}

				t.Fatal(err)
			}

			// Lock checks.
			if lock != nil && len(lock.P) != testCase.wantLockCount {
				t.Fatalf("Expected lock to have %d project(s), got %d",
					testCase.wantLockCount,
					len(lock.P))
			}

			// Ignored projects checks.
			if len(manifest.Ignored) != testCase.wantIgnoreCount {
				t.Fatalf("Expected manifest to have %d ignored project(s), got %d",
					testCase.wantIgnoreCount,
					len(manifest.Ignored))
			}

			if !equalSlice(manifest.Ignored, testCase.wantIgnoredPackages) {
				t.Fatalf("Expected manifest to have ignore %s, got %s",
					strings.Join(testCase.wantIgnoredPackages, ", "),
					strings.Join(manifest.Ignored, ", "))
			}

			// Constraints checks below. Skip if there is no want constraint.
			if testCase.wantConstraint == "" {
				return
			}

			d, ok := manifest.Constraints[testCase.projectRoot]
			if !ok {
				t.Fatalf("Expected the manifest to have a dependency for '%s' but got none",
					testCase.projectRoot)
			}

			v := d.Constraint.String()
			if v != testCase.wantConstraint {
				t.Fatalf("Expected manifest constraint to be %s, got %s", testCase.wantConstraint, v)
			}

			p := lock.P[0]

			if p.Ident().ProjectRoot != testCase.projectRoot {
				t.Fatalf("Expected the lock to have a project for '%s' but got '%s'",
					testCase.projectRoot,
					p.Ident().ProjectRoot)
			}

			if p.Ident().Source != testCase.wantSourceRepo {
				t.Fatalf("Expected locked source to be %s, got '%s'", testCase.wantSourceRepo, p.Ident().Source)
			}

			lv := p.Version()
			lpv, ok := lv.(gps.PairedVersion)

			if !ok {
				if testCase.matchPairedVersion {
					t.Fatalf("Expected locked version to be PairedVersion but got %T", lv)
				}

				return
			}

			ver := lpv.String()
			if ver != testCase.wantVersion {
				t.Fatalf("Expected locked version to be '%s', got %s", testCase.wantVersion, ver)
			}

			if testCase.wantRevision != "" {
				rev := lpv.Revision()
				if rev != testCase.wantRevision {
					t.Fatalf("Expected locked revision to be '%s', got %s",
						testCase.wantRevision,
						rev)
				}
			}
		})
	}
}

func TestGlideConfig_Import(t *testing.T) {
	h := test.NewHelper(t)
	defer h.Cleanup()

	ctx := newTestContext(h)
	sm, err := ctx.SourceManager()
	h.Must(err)
	defer sm.Release()

	h.TempDir(filepath.Join("src", testProjectRoot))
	h.TempCopy(filepath.Join(testProjectRoot, glideYamlName), "glide/glide.yaml")
	h.TempCopy(filepath.Join(testProjectRoot, glideLockName), "glide/glide.lock")
	projectRoot := h.Path(testProjectRoot)

	// Capture stderr so we can verify output
	verboseOutput := &bytes.Buffer{}
	ctx.Err = log.New(verboseOutput, "", 0)

	g := newGlideImporter(ctx.Err, false, sm) // Disable verbose so that we don't print values that change each test run
	if !g.HasDepMetadata(projectRoot) {
		t.Fatal("Expected the importer to detect the glide configuration files")
	}

	m, l, err := g.Import(projectRoot, testProjectRoot)
	h.Must(err)

	if m == nil {
		t.Fatal("Expected the manifest to be generated")
	}

	if l == nil {
		t.Fatal("Expected the lock to be generated")
	}

	goldenFile := "glide/golden.txt"
	got := verboseOutput.String()
	want := h.GetTestFileString(goldenFile)
	if want != got {
		if *test.UpdateGolden {
			if err := h.WriteTestFile(goldenFile, got); err != nil {
				t.Fatalf("%+v", errors.Wrapf(err, "Unable to write updated golden file %s", goldenFile))
			}
		} else {
			t.Fatalf("want %s, got %s", want, got)
		}
	}
}

func TestGlideConfig_Import_MissingLockFile(t *testing.T) {
	h := test.NewHelper(t)
	defer h.Cleanup()

	ctx := newTestContext(h)
	sm, err := ctx.SourceManager()
	h.Must(err)
	defer sm.Release()

	h.TempDir(filepath.Join("src", testProjectRoot))
	h.TempCopy(filepath.Join(testProjectRoot, glideYamlName), "glide/glide.yaml")
	projectRoot := h.Path(testProjectRoot)

	g := newGlideImporter(ctx.Err, true, sm)
	if !g.HasDepMetadata(projectRoot) {
		t.Fatal("The glide importer should gracefully handle when only glide.yaml is present")
	}

	m, l, err := g.Import(projectRoot, testProjectRoot)
	h.Must(err)

	if m == nil {
		t.Fatal("Expected the manifest to be generated")
	}

	if l != nil {
		t.Fatal("Expected the lock to not be generated")
	}
}

func TestGlideConfig_Convert_WarnsForUnusedFields(t *testing.T) {
	testCases := map[string]glidePackage{
		"specified an os":   {OS: "windows"},
		"specified an arch": {Arch: "i686"},
	}

	for wantWarning, pkg := range testCases {
		t.Run(wantWarning, func(t *testing.T) {
			h := test.NewHelper(t)
			defer h.Cleanup()

			pkg.Name = "github.com/sdboyer/deptest"
			pkg.Reference = "v1.0.0"

			ctx := newTestContext(h)
			sm, err := ctx.SourceManager()
			h.Must(err)
			defer sm.Release()

			// Capture stderr so we can verify warnings
			verboseOutput := &bytes.Buffer{}
			ctx.Err = log.New(verboseOutput, "", 0)

			g := newGlideImporter(ctx.Err, true, sm)
			g.yaml = glideYaml{
				Imports: []glidePackage{pkg},
			}

			_, _, err = g.convert(testProjectRoot)
			if err != nil {
				t.Fatal(err)
			}

			warnings := verboseOutput.String()
			if !strings.Contains(warnings, wantWarning) {
				t.Errorf("Expected the output to include the warning '%s'", wantWarning)
			}
		})
	}
}

// equalSlice is comparing two slices for equality.
func equalSlice(a, b []string) bool {
	if a == nil && b == nil {
		return true
	}

	if a == nil || b == nil {
		return false
	}

	if len(a) != len(b) {
		return false
	}

	for i := range a {
		if a[i] != b[i] {
			return false
		}
	}

	return true
}

func TestGlideConfig_Convert_ConsolidateRootPackages(t *testing.T) {
	h := test.NewHelper(t)
	defer h.Cleanup()

	ctx := newTestContext(h)
	sm, err := ctx.SourceManager()
	h.Must(err)
	defer sm.Release()

	g := newGlideImporter(ctx.Err, true, sm)
	g.yaml = glideYaml{
		Imports: []glidePackage{
			{Name: "github.com/carolynvs/deptest-subpkg/subby"},
			{Name: "github.com/carolynvs/deptest-subpkg"},
		},
	}
	g.lock = &glideLock{
		Imports: []glideLockedPackage{
			{Name: "github.com/carolynvs/deptest-subpkg/subby"},
			{Name: "github.com/carolynvs/deptest-subpkg"},
		},
	}

	manifest, lock, err := g.convert(testGlideProjectRoot)
	h.Must(err)

	gotMLen := len(manifest.Constraints)
	if gotMLen != 1 {
		t.Fatalf("Expected manifest to contain 1 constraint, got %d", gotMLen)
	}

	wantRoot := gps.ProjectRoot("github.com/carolynvs/deptest-subpkg")
	if _, has := manifest.Constraints[wantRoot]; !has {
		t.Fatalf("Expected manifest to contain a constraint for %s, got %v", wantRoot, manifest.Constraints)
	}

	gotLLen := len(lock.P)
	if gotLLen != 1 {
		t.Fatalf("Expected lock to contain 1 project, got %d", gotLLen)
	}

	gotRoot := lock.P[0].Ident().ProjectRoot
	if gotRoot != wantRoot {
		t.Fatalf("Expected lock to contain a project for %s, got %v", wantRoot, gotRoot)
	}
}
<commit_msg>Fix bad merge from #978<commit_after>// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import (
	"bytes"
	"io/ioutil"
	"log"
	"path/filepath"
	"strings"
	"testing"

	"github.com/golang/dep"
	"github.com/golang/dep/internal/gps"
	"github.com/golang/dep/internal/test"
	"github.com/pkg/errors"
)

var (
	discardLogger = log.New(ioutil.Discard, "", 0)
)

func newTestContext(h *test.Helper) *dep.Ctx {
	h.TempDir("src")
	pwd := h.Path(".")
	return &dep.Ctx{
		GOPATH: pwd,
		Out:    discardLogger,
		Err:    discardLogger,
	}
}

func TestGlideConfig_Convert(t *testing.T) {
	testCases := map[string]struct {
		yaml                glideYaml
		lock                *glideLock
		wantConvertErr      bool
		matchPairedVersion  bool
		projectRoot         gps.ProjectRoot
		wantSourceRepo      string
		wantConstraint      string
		wantRevision        gps.Revision
		wantVersion         string
		wantLockCount       int
		wantIgnoreCount     int
		wantIgnoredPackages []string
	}{
		"project": {
			yaml: glideYaml{
				Imports: []glidePackage{
					{
						Name:       "github.com/sdboyer/deptest",
						Repository: "https://github.com/sdboyer/deptest.git",
						Reference:  "v1.0.0",
					},
				},
			},
			lock: &glideLock{
				Imports: []glideLockedPackage{
					{
						Name:       "github.com/sdboyer/deptest",
						Repository: "https://github.com/sdboyer/deptest.git",
						Reference:  "ff2948a2ac8f538c4ecd55962e919d1e13e74baf",
					},
				},
			},
			projectRoot:        "github.com/sdboyer/deptest",
			wantSourceRepo:     "https://github.com/sdboyer/deptest.git",
			matchPairedVersion: true,
			wantConstraint:     "^1.0.0",
			wantLockCount:      1,
			wantRevision:       gps.Revision("ff2948a2ac8f538c4ecd55962e919d1e13e74baf"),
			wantVersion:        "v1.0.0",
		},
		"test project": {
			yaml: glideYaml{
				Imports: []glidePackage{
					{
						Name:      "github.com/sdboyer/deptest",
						Reference: "v1.0.0",
					},
				},
			},
			lock: &glideLock{
				Imports: []glideLockedPackage{
					{
						Name:      "github.com/sdboyer/deptest",
						Reference: "ff2948a2ac8f538c4ecd55962e919d1e13e74baf",
					},
				},
			},
			projectRoot:    "github.com/sdboyer/deptest",
			wantLockCount:  1,
			wantConstraint: "^1.0.0",
			wantVersion:    "v1.0.0",
		},
		"with ignored package": {
			yaml: glideYaml{
				Ignores: []string{"github.com/sdboyer/deptest"},
			},
			projectRoot:         "github.com/sdboyer/deptest",
			wantIgnoreCount:     1,
			wantIgnoredPackages: []string{"github.com/sdboyer/deptest"},
		},
		"with exclude dir": {
			yaml: glideYaml{
				ExcludeDirs: []string{"samples"},
			},
			projectRoot:         testProjectRoot,
			wantIgnoreCount:     1,
			wantIgnoredPackages: []string{"github.com/golang/notexist/samples"},
		},
		"exclude dir ignores mismatched package name": {
			yaml: glideYaml{
				Name:        "github.com/golang/mismatched-package-name",
				ExcludeDirs: []string{"samples"},
			},
			projectRoot:         testProjectRoot,
			wantIgnoreCount:     1,
			wantIgnoredPackages: []string{"github.com/golang/notexist/samples"},
		},
		"bad input, empty package name": {
			yaml: glideYaml{
				Imports: []glidePackage{{Name: ""}},
			},
			projectRoot:    testProjectRoot,
			wantConvertErr: true,
		},
	}

	h := test.NewHelper(t)
	defer h.Cleanup()

	ctx := newTestContext(h)
	sm, err := ctx.SourceManager()
	h.Must(err)
	defer sm.Release()

	for name, testCase := range testCases {
		t.Run(name, func(t *testing.T) {
			g := newGlideImporter(discardLogger, true, sm)
			g.yaml = testCase.yaml

			if testCase.lock != nil {
				g.lock = testCase.lock
			}

			manifest, lock, err := g.convert(testCase.projectRoot)
			if err != nil {
				if testCase.wantConvertErr {
					return
				}

				t.Fatal(err)
			}

			// Lock checks.
			if lock != nil && len(lock.P) != testCase.wantLockCount {
				t.Fatalf("Expected lock to have %d project(s), got %d",
					testCase.wantLockCount,
					len(lock.P))
			}

			// Ignored projects checks.
			if len(manifest.Ignored) != testCase.wantIgnoreCount {
				t.Fatalf("Expected manifest to have %d ignored project(s), got %d",
					testCase.wantIgnoreCount,
					len(manifest.Ignored))
			}

			if !equalSlice(manifest.Ignored, testCase.wantIgnoredPackages) {
				t.Fatalf("Expected manifest to have ignore %s, got %s",
					strings.Join(testCase.wantIgnoredPackages, ", "),
					strings.Join(manifest.Ignored, ", "))
			}

			// Constraints checks below. Skip if there is no want constraint.
			if testCase.wantConstraint == "" {
				return
			}

			d, ok := manifest.Constraints[testCase.projectRoot]
			if !ok {
				t.Fatalf("Expected the manifest to have a dependency for '%s' but got none",
					testCase.projectRoot)
			}

			v := d.Constraint.String()
			if v != testCase.wantConstraint {
				t.Fatalf("Expected manifest constraint to be %s, got %s", testCase.wantConstraint, v)
			}

			p := lock.P[0]

			if p.Ident().ProjectRoot != testCase.projectRoot {
				t.Fatalf("Expected the lock to have a project for '%s' but got '%s'",
					testCase.projectRoot,
					p.Ident().ProjectRoot)
			}

			if p.Ident().Source != testCase.wantSourceRepo {
				t.Fatalf("Expected locked source to be %s, got '%s'", testCase.wantSourceRepo, p.Ident().Source)
			}

			lv := p.Version()
			lpv, ok := lv.(gps.PairedVersion)

			if !ok {
				if testCase.matchPairedVersion {
					t.Fatalf("Expected locked version to be PairedVersion but got %T", lv)
				}

				return
			}

			ver := lpv.String()
			if ver != testCase.wantVersion {
				t.Fatalf("Expected locked version to be '%s', got %s", testCase.wantVersion, ver)
			}

			if testCase.wantRevision != "" {
				rev := lpv.Revision()
				if rev != testCase.wantRevision {
					t.Fatalf("Expected locked revision to be '%s', got %s",
						testCase.wantRevision,
						rev)
				}
			}
		})
	}
}

func TestGlideConfig_Import(t *testing.T) {
	h := test.NewHelper(t)
	defer h.Cleanup()

	ctx := newTestContext(h)
	sm, err := ctx.SourceManager()
	h.Must(err)
	defer sm.Release()

	h.TempDir(filepath.Join("src", testProjectRoot))
	h.TempCopy(filepath.Join(testProjectRoot, glideYamlName), "glide/glide.yaml")
	h.TempCopy(filepath.Join(testProjectRoot, glideLockName), "glide/glide.lock")
	projectRoot := h.Path(testProjectRoot)

	// Capture stderr so we can verify output
	verboseOutput := &bytes.Buffer{}
	ctx.Err = log.New(verboseOutput, "", 0)

	g := newGlideImporter(ctx.Err, false, sm) // Disable verbose so that we don't print values that change each test run
	if !g.HasDepMetadata(projectRoot) {
		t.Fatal("Expected the importer to detect the glide configuration files")
	}

	m, l, err := g.Import(projectRoot, testProjectRoot)
	h.Must(err)

	if m == nil {
		t.Fatal("Expected the manifest to be generated")
	}

	if l == nil {
		t.Fatal("Expected the lock to be generated")
	}

	goldenFile := "glide/golden.txt"
	got := verboseOutput.String()
	want := h.GetTestFileString(goldenFile)
	if want != got {
		if *test.UpdateGolden {
			if err := h.WriteTestFile(goldenFile, got); err != nil {
				t.Fatalf("%+v", errors.Wrapf(err, "Unable to write updated golden file %s", goldenFile))
			}
		} else {
			t.Fatalf("want %s, got %s", want, got)
		}
	}
}

func TestGlideConfig_Import_MissingLockFile(t *testing.T) {
	h := test.NewHelper(t)
	defer h.Cleanup()

	ctx := newTestContext(h)
	sm, err := ctx.SourceManager()
	h.Must(err)
	defer sm.Release()

	h.TempDir(filepath.Join("src", testProjectRoot))
	h.TempCopy(filepath.Join(testProjectRoot, glideYamlName), "glide/glide.yaml")
	projectRoot := h.Path(testProjectRoot)

	g := newGlideImporter(ctx.Err, true, sm)
	if !g.HasDepMetadata(projectRoot) {
		t.Fatal("The glide importer should gracefully handle when only glide.yaml is present")
	}

	m, l, err := g.Import(projectRoot, testProjectRoot)
	h.Must(err)

	if m == nil {
		t.Fatal("Expected the manifest to be generated")
	}

	if l != nil {
		t.Fatal("Expected the lock to not be generated")
	}
}

func TestGlideConfig_Convert_WarnsForUnusedFields(t *testing.T) {
	testCases := map[string]glidePackage{
		"specified an os":   {OS: "windows"},
		"specified an arch": {Arch: "i686"},
	}

	for wantWarning, pkg := range testCases {
		t.Run(wantWarning, func(t *testing.T) {
			h := test.NewHelper(t)
			defer h.Cleanup()

			pkg.Name = "github.com/sdboyer/deptest"
			pkg.Reference = "v1.0.0"

			ctx := newTestContext(h)
			sm, err := ctx.SourceManager()
			h.Must(err)
			defer sm.Release()

			// Capture stderr so we can verify warnings
			verboseOutput := &bytes.Buffer{}
			ctx.Err = log.New(verboseOutput, "", 0)

			g := newGlideImporter(ctx.Err, true, sm)
			g.yaml = glideYaml{
				Imports: []glidePackage{pkg},
			}

			_, _, err = g.convert(testProjectRoot)
			if err != nil {
				t.Fatal(err)
			}

			warnings := verboseOutput.String()
			if !strings.Contains(warnings, wantWarning) {
				t.Errorf("Expected the output to include the warning '%s'", wantWarning)
			}
		})
	}
}

// equalSlice is comparing two slices for equality.
func equalSlice(a, b []string) bool {
	if a == nil && b == nil {
		return true
	}

	if a == nil || b == nil {
		return false
	}

	if len(a) != len(b) {
		return false
	}

	for i := range a {
		if a[i] != b[i] {
			return false
		}
	}

	return true
}

func TestGlideConfig_Convert_ConsolidateRootPackages(t *testing.T) {
	h := test.NewHelper(t)
	defer h.Cleanup()

	ctx := newTestContext(h)
	sm, err := ctx.SourceManager()
	h.Must(err)
	defer sm.Release()

	g := newGlideImporter(ctx.Err, true, sm)
	g.yaml = glideYaml{
		Imports: []glidePackage{
			{Name: "github.com/carolynvs/deptest-subpkg/subby"},
			{Name: "github.com/carolynvs/deptest-subpkg"},
		},
	}
	g.lock = &glideLock{
		Imports: []glideLockedPackage{
			{Name: "github.com/carolynvs/deptest-subpkg/subby"},
			{Name: "github.com/carolynvs/deptest-subpkg"},
		},
	}

	manifest, lock, err := g.convert(testProjectRoot)
	h.Must(err)

	gotMLen := len(manifest.Constraints)
	if gotMLen != 1 {
		t.Fatalf("Expected manifest to contain 1 constraint, got %d", gotMLen)
	}

	wantRoot := gps.ProjectRoot("github.com/carolynvs/deptest-subpkg")
	if _, has := manifest.Constraints[wantRoot]; !has {
		t.Fatalf("Expected manifest to contain a constraint for %s, got %v", wantRoot, manifest.Constraints)
	}

	gotLLen := len(lock.P)
	if gotLLen != 1 {
		t.Fatalf("Expected lock to contain 1 project, got %d", gotLLen)
	}

	gotRoot := lock.P[0].Ident().ProjectRoot
	if gotRoot != wantRoot {
		t.Fatalf("Expected lock to contain a project for %s, got %v", wantRoot, gotRoot)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"archive/zip"
	"fmt"
	"io"
	"log"
	"net/http"
	"os"
	"path/filepath"
	"strings"
)

const (
	fileURL       = "https://github.com/cayleygraph/web/releases/download/v0.8.0/web.zip"
	fileName      = "web.zip"
	directoryName = "ui"
)

func main() {
	log.Printf("Downloading %s to %s...", fileURL, fileName)
	if err := DownloadFile(fileName, fileURL); err != nil {
		panic(err)
	}
	log.Printf("Downloaded %s to %s", fileURL, fileName)

	log.Printf("Extracting %s to %s...", fileName, directoryName)
	err := Unzip(fileName, directoryName)
	if err != nil {
		panic(err)
	}
	log.Printf("Extracted %s to %s/", fileName, directoryName)
	err = os.Remove(fileName)
	if err != nil {
		panic(err)
	}
	log.Printf("Removed %s", fileName)
}

// DownloadFile will download a url to a local file. It's efficient because it will
// write as it downloads and not load the whole file into memory.
func DownloadFile(filepath string, url string) error {

	// Get the data
	resp, err := http.Get(url)
	if err != nil {
		return err
	}
	defer resp.Body.Close()

	if resp.StatusCode != 200 {
		return fmt.Errorf("Received %v status code instead of 200 for %v", resp.Status, url)
	}

	// Create the file
	out, err := os.Create(filepath)
	if err != nil {
		return err
	}
	defer out.Close()

	// Write the body to file
	_, err = io.Copy(out, resp.Body)
	return err
}

// Unzip will decompress a zip archive, moving all files and folders
// within the zip file (parameter 1) to an output directory (parameter 2).
func Unzip(src string, dest string) error {
	r, err := zip.OpenReader(src)
	if err != nil {
		return err
	}
	defer r.Close()

	for _, f := range r.File {

		// Store filename/path for returning and using later on
		fpath := filepath.Join(dest, f.Name)

		// Check for ZipSlip. More Info: http://bit.ly/2MsjAWE
		if !strings.HasPrefix(fpath, filepath.Clean(dest)+string(os.PathSeparator)) {
			return fmt.Errorf("%s: illegal file path", fpath)
		}

		if f.FileInfo().IsDir() {
			// Make Folder
			os.MkdirAll(fpath, 0755)
			continue
		}

		// Make File
		if err = os.MkdirAll(filepath.Dir(fpath), os.ModePerm); err != nil {
			return err
		}

		outFile, err := os.OpenFile(fpath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode())
		if err != nil {
			return err
		}

		rc, err := f.Open()
		if err != nil {
			return err
		}

		_, err = io.Copy(outFile, rc)

		// Close the file without defer to close before next iteration of loop
		outFile.Close()
		rc.Close()

		if err != nil {
			return err
		}
	}
	return nil
}
<commit_msg>Check for more errors in unzip<commit_after>package main

import (
	"archive/zip"
	"fmt"
	"io"
	"log"
	"net/http"
	"os"
	"path/filepath"
	"strings"
)

const (
	fileURL       = "https://github.com/cayleygraph/web/releases/download/v0.8.0/web.zip"
	fileName      = "web.zip"
	directoryName = "ui"
)

func main() {
	log.Printf("Downloading %s to %s...", fileURL, fileName)
	if err := DownloadFile(fileName, fileURL); err != nil {
		panic(err)
	}
	log.Printf("Downloaded %s to %s", fileURL, fileName)

	log.Printf("Extracting %s to %s...", fileName, directoryName)
	err := Unzip(fileName, directoryName)
	if err != nil {
		panic(err)
	}
	log.Printf("Extracted %s to %s/", fileName, directoryName)
	err = os.Remove(fileName)
	if err != nil {
		panic(err)
	}
	log.Printf("Removed %s", fileName)
}

// DownloadFile will download a url to a local file. It's efficient because it will
// write as it downloads and not load the whole file into memory.
func DownloadFile(filepath string, url string) error {

	// Get the data
	resp, err := http.Get(url)
	if err != nil {
		return err
	}
	defer resp.Body.Close()

	if resp.StatusCode != 200 {
		return fmt.Errorf("Received %v status code instead of 200 for %v", resp.Status, url)
	}

	// Create the file
	out, err := os.Create(filepath)
	if err != nil {
		return err
	}
	defer out.Close()

	// Write the body to file
	_, err = io.Copy(out, resp.Body)
	return err
}

// Unzip will decompress a zip archive, moving all files and folders
// within the zip file (parameter 1) to an output directory (parameter 2).
func Unzip(src string, dest string) error {
	r, err := zip.OpenReader(src)
	if err != nil {
		return err
	}
	defer r.Close()

	for _, f := range r.File {

		// Store filename/path for returning and using later on
		fpath := filepath.Join(dest, f.Name)

		// Check for ZipSlip. More Info: http://bit.ly/2MsjAWE
		if !strings.HasPrefix(fpath, filepath.Clean(dest)+string(os.PathSeparator)) {
			return fmt.Errorf("%s: illegal file path", fpath)
		}

		if f.FileInfo().IsDir() {
			// Make Folder
			os.MkdirAll(fpath, 0755)
			continue
		}

		// Make File
		if err = os.MkdirAll(filepath.Dir(fpath), os.ModePerm); err != nil {
			return err
		}

		outFile, err := os.OpenFile(fpath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode())
		if err != nil {
			return err
		}

		rc, err := f.Open()
		if err != nil {
			return err
		}

		_, err = io.Copy(outFile, rc)

		if err != nil {
			return err
		}

		// Close the file without defer to close before next iteration of loop
		err = outFile.Close()

		if err != nil {
			return err
		}

		err = rc.Close()

		if err != nil {
			return err
		}
	}
	return nil
}
<|endoftext|>