<commit_before>// Copyright 2015 The Cockroach 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.
//
// Author: Andrew Bonventre (andybons@gmail.com)
// Author: Spencer Kimball (spencer.kimball@gmail.com)

package cli

import (
	"errors"
	"flag"
	"fmt"
	"net"
	"os"
	"os/signal"
	"path/filepath"
	"syscall"
	"text/tabwriter"
	"time"

	"github.com/cockroachdb/cockroach/build"
	"github.com/cockroachdb/cockroach/client"
	"github.com/cockroachdb/cockroach/security"
	"github.com/cockroachdb/cockroach/server"
	"github.com/cockroachdb/cockroach/storage/engine"
	"github.com/cockroachdb/cockroach/util"
	"github.com/cockroachdb/cockroach/util/log"
	"github.com/cockroachdb/cockroach/util/stop"

	"github.com/spf13/cobra"
)

var errMissingParams = errors.New("missing or invalid parameters")

// panicGuard wraps an errorless command into one wrapping panics into errors.
// This simplifies error handling for many commands for which more elaborate
// error handling isn't needed and would otherwise bloat the code.
//
// Deprecated: When introducing a new cobra.Command, simply return an error.
func panicGuard(cmdFn func(*cobra.Command, []string)) func(*cobra.Command, []string) error {
	return func(c *cobra.Command, args []string) (err error) {
		defer func() {
			if r := recover(); r != nil {
				err = fmt.Errorf("%v", r)
			}
		}()
		cmdFn(c, args)
		return nil
	}
}

// panicf is only to be used when wrapped through panicGuard, since the
// stack trace doesn't matter then.
func panicf(format string, args ...interface{}) {
	panic(fmt.Sprintf(format, args...))
}

// getJSON is a convenience wrapper around util.GetJSON that uses our Context to populate
// parts of the request.
func getJSON(hostport, path string, v interface{}) error {
	httpClient, err := cliContext.GetHTTPClient()
	if err != nil {
		return err
	}
	return util.GetJSON(httpClient, cliContext.HTTPRequestScheme(), hostport, path, v)
}

// startCmd starts a node by initializing the stores and joining
// the cluster.
var startCmd = &cobra.Command{
	Use:   "start",
	Short: "start a node",
	Long: `
Start a CockroachDB node, which will export data from one or more
storage devices, specified via --store flags.

If no cluster exists yet and this is the first node, no additional
flags are required. If the cluster already exists, and this node is
uninitialized, specify the --join flag to point to any healthy node
(or list of nodes) already part of the cluster.
`,
	Example:      `  cockroach start --insecure --store=attrs=ssd,path=/mnt/ssd1 [--join=host:port,[host:port]]`,
	SilenceUsage: true,
	RunE:         runStart,
}

func setDefaultCacheSize(ctx *server.Context) {
	if size, err := server.GetTotalMemory(); err == nil {
		// Default the cache size to 1/4 of total memory. A larger cache size
		// doesn't necessarily improve performance as this is memory that is
		// dedicated to uncompressed blocks in RocksDB. A larger value here will
		// compete with the OS buffer cache which holds compressed blocks.
		ctx.CacheSize = size / 4
	}
}

func initInsecure() error {
	if !cliContext.Insecure || insecure.isSet {
		return nil
	}
	// The --insecure flag was not specified on the command line, verify that the
	// host refers to a loopback address.
	if connHost != "" {
		addr, err := net.ResolveIPAddr("ip", connHost)
		if err != nil {
			return err
		}
		if !addr.IP.IsLoopback() {
			return fmt.Errorf("specify --insecure to listen on external address %s", connHost)
		}
	} else {
		cliContext.Addr = net.JoinHostPort("localhost", connPort)
		cliContext.HTTPAddr = net.JoinHostPort("localhost", httpPort)
	}
	return nil
}

// runStart starts the cockroach node using --store as the list of
// storage devices ("stores") on this machine and --join as the list
// of other active nodes used to join this node to the cockroach
// cluster, if this is its first time connecting.
func runStart(_ *cobra.Command, _ []string) error {
	info := build.GetInfo()
	// We log build information to stdout (for the short summary), but also
	// to stderr to coincide with the full logs.
	log.Infof(info.Short())

	if err := initInsecure(); err != nil {
		return err
	}

	// Default the log directory to the the "logs" subdirectory of the first
	// non-memory store. We only do this for the "start" command which is why
	// this work occurs here and not in an OnInitialize function.
	f := flag.Lookup("log-dir")
	if !log.DirSet() {
		for _, spec := range cliContext.Stores.Specs {
			if spec.InMemory {
				continue
			}
			if err := f.Value.Set(filepath.Join(spec.Path, "logs")); err != nil {
				return err
			}
			break
		}
	}

	// Make sure the path exists
	if err := os.MkdirAll(f.Value.String(), 0755); err != nil {
		return err
	}

	// Default user for servers.
	cliContext.User = security.NodeUser

	stopper := stop.NewStopper()
	if err := cliContext.InitStores(stopper); err != nil {
		return fmt.Errorf("failed to initialize stores: %s", err)
	}

	if err := cliContext.InitNode(); err != nil {
		return fmt.Errorf("failed to initialize node: %s", err)
	}

	log.Info("starting cockroach node")
	s, err := server.NewServer(&cliContext.Context, stopper)
	if err != nil {
		return fmt.Errorf("failed to start Cockroach server: %s", err)
	}

	// We don't do this in NewServer since we don't want it in tests.
	if err := s.SetupReportingURLs(); err != nil {
		return err
	}

	if err := s.Start(); err != nil {
		return fmt.Errorf("cockroach server exited with error: %s", err)
	}

	pgURL, err := cliContext.PGURL(connUser)
	if err != nil {
		return err
	}

	tw := tabwriter.NewWriter(os.Stdout, 2, 1, 2, ' ', 0)
	fmt.Fprintf(tw, "build:\t%s @ %s (%s)\n", info.Tag, info.Time, info.GoVersion)
	fmt.Fprintf(tw, "admin:\t%s\n", cliContext.AdminURL())
	fmt.Fprintf(tw, "sql:\t%s\n", pgURL)
	if len(cliContext.SocketFile) != 0 {
		fmt.Fprintf(tw, "socket:\t%s\n", cliContext.SocketFile)
	}
	fmt.Fprintf(tw, "logs:\t%s\n", flag.Lookup("log-dir").Value)
	for i, spec := range cliContext.Stores.Specs {
		fmt.Fprintf(tw, "store[%d]:\t%s\n", i, spec)
	}
	if err := tw.Flush(); err != nil {
		return err
	}

	signalCh := make(chan os.Signal, 1)
	signal.Notify(signalCh, os.Interrupt, os.Kill)
	// TODO(spencer): move this behind a build tag.
	signal.Notify(signalCh, syscall.SIGTERM)

	// Block until one of the signals above is received or the stopper
	// is stopped externally (for example, via the quit endpoint).
	select {
	case <-stopper.ShouldStop():
	case <-signalCh:
		go s.Stop()
	}

	const msgDrain = "initiating graceful shutdown of server"
	log.Info(msgDrain)
	fmt.Fprintln(os.Stdout, msgDrain)

	go func() {
		ticker := time.NewTicker(5 * time.Second)
		defer ticker.Stop()
		for {
			select {
			case <-ticker.C:
				if log.V(1) {
					log.Infof("running tasks:\n%s", stopper.RunningTasks())
				}
				log.Infof("%d running tasks", stopper.NumTasks())
			case <-stopper.ShouldStop():
				return
			}
		}
	}()

	select {
	case <-signalCh:
		log.Errorf("second signal received, initiating hard shutdown")
	case <-time.After(time.Minute):
		log.Errorf("time limit reached, initiating hard shutdown")
	case <-stopper.IsStopped():
		const msgDone = "server drained and shutdown completed"
		log.Infof(msgDone)
		fmt.Fprintln(os.Stdout, msgDone)
	}
	log.Flush()
	return nil
}

// exterminateCmd command shuts down the node server and
// destroys all data held by the node.
var exterminateCmd = &cobra.Command{
	Use:   "exterminate",
	Short: "destroy all data held by the node",
	Long: `
First shuts down the system and then destroys all data held by the
node, cycling through each store specified by --store flags.
`,
	SilenceUsage: true,
	RunE:         runExterminate,
}

// runExterminate destroys the data held in the specified stores.
func runExterminate(_ *cobra.Command, _ []string) error {
	stopper := stop.NewStopper()
	defer stopper.Stop()
	if err := cliContext.InitStores(stopper); err != nil {
		return util.Errorf("failed to initialize context: %s", err)
	}

	if err := runQuit(nil, nil); err != nil {
		return util.Errorf("shutdown node error: %s", err)
	}

	// Exterminate all data held in specified stores.
	for _, e := range cliContext.Engines {
		if rocksdb, ok := e.(*engine.RocksDB); ok {
			log.Infof("exterminating data from store %s", e)
			if err := rocksdb.Destroy(); err != nil {
				return util.Errorf("unable to destroy store %s: %s", e, err)
			}
		}
	}
	log.Infof("exterminated all data from stores %s", cliContext.Engines)
	return nil
}

// quitCmd command shuts down the node server.
var quitCmd = &cobra.Command{
	Use:   "quit",
	Short: "drain and shutdown node\n",
	Long: `
Shutdown the server. The first stage is drain, where any new requests
will be ignored by the server. When all extant requests have been
completed, the server exits.
`,
	SilenceUsage: true,
	RunE:         runQuit,
}

// runQuit accesses the quit shutdown path.
func runQuit(_ *cobra.Command, _ []string) error {
	admin, err := client.NewAdminClient(&cliContext.Context.Context, cliContext.HTTPAddr, client.Quit)
	if err != nil {
		return err
	}
	body, err := admin.Get()
	// TODO(tschottdorf): needs cleanup. An error here can happen if the shutdown
	// happened faster than the HTTP request made it back.
	if err != nil {
		return err
	}
	fmt.Printf("node drained and shutdown: %s\n", body)
	return nil
}
<commit_msg>cli: Delay first log line in `start`<commit_after>// Copyright 2015 The Cockroach 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.
//
// Author: Andrew Bonventre (andybons@gmail.com)
// Author: Spencer Kimball (spencer.kimball@gmail.com)

package cli

import (
	"errors"
	"flag"
	"fmt"
	"net"
	"os"
	"os/signal"
	"path/filepath"
	"syscall"
	"text/tabwriter"
	"time"

	"github.com/cockroachdb/cockroach/build"
	"github.com/cockroachdb/cockroach/client"
	"github.com/cockroachdb/cockroach/security"
	"github.com/cockroachdb/cockroach/server"
	"github.com/cockroachdb/cockroach/storage/engine"
	"github.com/cockroachdb/cockroach/util"
	"github.com/cockroachdb/cockroach/util/log"
	"github.com/cockroachdb/cockroach/util/stop"

	"github.com/spf13/cobra"
)

var errMissingParams = errors.New("missing or invalid parameters")

// panicGuard wraps an errorless command into one wrapping panics into errors.
// This simplifies error handling for many commands for which more elaborate
// error handling isn't needed and would otherwise bloat the code.
//
// Deprecated: When introducing a new cobra.Command, simply return an error.
func panicGuard(cmdFn func(*cobra.Command, []string)) func(*cobra.Command, []string) error {
	return func(c *cobra.Command, args []string) (err error) {
		defer func() {
			if r := recover(); r != nil {
				err = fmt.Errorf("%v", r)
			}
		}()
		cmdFn(c, args)
		return nil
	}
}

// panicf is only to be used when wrapped through panicGuard, since the
// stack trace doesn't matter then.
func panicf(format string, args ...interface{}) {
	panic(fmt.Sprintf(format, args...))
}

// getJSON is a convenience wrapper around util.GetJSON that uses our Context to populate
// parts of the request.
func getJSON(hostport, path string, v interface{}) error {
	httpClient, err := cliContext.GetHTTPClient()
	if err != nil {
		return err
	}
	return util.GetJSON(httpClient, cliContext.HTTPRequestScheme(), hostport, path, v)
}

// startCmd starts a node by initializing the stores and joining
// the cluster.
var startCmd = &cobra.Command{
	Use:   "start",
	Short: "start a node",
	Long: `
Start a CockroachDB node, which will export data from one or more
storage devices, specified via --store flags.

If no cluster exists yet and this is the first node, no additional
flags are required. If the cluster already exists, and this node is
uninitialized, specify the --join flag to point to any healthy node
(or list of nodes) already part of the cluster.
`,
	Example:      `  cockroach start --insecure --store=attrs=ssd,path=/mnt/ssd1 [--join=host:port,[host:port]]`,
	SilenceUsage: true,
	RunE:         runStart,
}

func setDefaultCacheSize(ctx *server.Context) {
	if size, err := server.GetTotalMemory(); err == nil {
		// Default the cache size to 1/4 of total memory. A larger cache size
		// doesn't necessarily improve performance as this is memory that is
		// dedicated to uncompressed blocks in RocksDB. A larger value here will
		// compete with the OS buffer cache which holds compressed blocks.
		ctx.CacheSize = size / 4
	}
}

func initInsecure() error {
	if !cliContext.Insecure || insecure.isSet {
		return nil
	}
	// The --insecure flag was not specified on the command line, verify that the
	// host refers to a loopback address.
	if connHost != "" {
		addr, err := net.ResolveIPAddr("ip", connHost)
		if err != nil {
			return err
		}
		if !addr.IP.IsLoopback() {
			return fmt.Errorf("specify --insecure to listen on external address %s", connHost)
		}
	} else {
		cliContext.Addr = net.JoinHostPort("localhost", connPort)
		cliContext.HTTPAddr = net.JoinHostPort("localhost", httpPort)
	}
	return nil
}

// runStart starts the cockroach node using --store as the list of
// storage devices ("stores") on this machine and --join as the list
// of other active nodes used to join this node to the cockroach
// cluster, if this is its first time connecting.
func runStart(_ *cobra.Command, _ []string) error {
	if err := initInsecure(); err != nil {
		return err
	}

	// Default the log directory to the the "logs" subdirectory of the first
	// non-memory store. We only do this for the "start" command which is why
	// this work occurs here and not in an OnInitialize function.
	//
	// It is important that no logging occur before this point or the log files
	// will be created in $TMPDIR instead of their expected location.
	f := flag.Lookup("log-dir")
	if !log.DirSet() {
		for _, spec := range cliContext.Stores.Specs {
			if spec.InMemory {
				continue
			}
			if err := f.Value.Set(filepath.Join(spec.Path, "logs")); err != nil {
				return err
			}
			break
		}
	}

	// Make sure the path exists.
	if err := os.MkdirAll(f.Value.String(), 0755); err != nil {
		return err
	}

	// We log build information to stdout (for the short summary), but also
	// to stderr to coincide with the full logs.
	info := build.GetInfo()
	log.Infof(info.Short())

	// Default user for servers.
	cliContext.User = security.NodeUser

	stopper := stop.NewStopper()
	if err := cliContext.InitStores(stopper); err != nil {
		return fmt.Errorf("failed to initialize stores: %s", err)
	}

	if err := cliContext.InitNode(); err != nil {
		return fmt.Errorf("failed to initialize node: %s", err)
	}

	log.Info("starting cockroach node")
	s, err := server.NewServer(&cliContext.Context, stopper)
	if err != nil {
		return fmt.Errorf("failed to start Cockroach server: %s", err)
	}

	// We don't do this in NewServer since we don't want it in tests.
	if err := s.SetupReportingURLs(); err != nil {
		return err
	}

	if err := s.Start(); err != nil {
		return fmt.Errorf("cockroach server exited with error: %s", err)
	}

	pgURL, err := cliContext.PGURL(connUser)
	if err != nil {
		return err
	}

	tw := tabwriter.NewWriter(os.Stdout, 2, 1, 2, ' ', 0)
	fmt.Fprintf(tw, "build:\t%s @ %s (%s)\n", info.Tag, info.Time, info.GoVersion)
	fmt.Fprintf(tw, "admin:\t%s\n", cliContext.AdminURL())
	fmt.Fprintf(tw, "sql:\t%s\n", pgURL)
	if len(cliContext.SocketFile) != 0 {
		fmt.Fprintf(tw, "socket:\t%s\n", cliContext.SocketFile)
	}
	fmt.Fprintf(tw, "logs:\t%s\n", flag.Lookup("log-dir").Value)
	for i, spec := range cliContext.Stores.Specs {
		fmt.Fprintf(tw, "store[%d]:\t%s\n", i, spec)
	}
	if err := tw.Flush(); err != nil {
		return err
	}

	signalCh := make(chan os.Signal, 1)
	signal.Notify(signalCh, os.Interrupt, os.Kill)
	// TODO(spencer): move this behind a build tag.
	signal.Notify(signalCh, syscall.SIGTERM)

	// Block until one of the signals above is received or the stopper
	// is stopped externally (for example, via the quit endpoint).
	select {
	case <-stopper.ShouldStop():
	case <-signalCh:
		go s.Stop()
	}

	const msgDrain = "initiating graceful shutdown of server"
	log.Info(msgDrain)
	fmt.Fprintln(os.Stdout, msgDrain)

	go func() {
		ticker := time.NewTicker(5 * time.Second)
		defer ticker.Stop()
		for {
			select {
			case <-ticker.C:
				if log.V(1) {
					log.Infof("running tasks:\n%s", stopper.RunningTasks())
				}
				log.Infof("%d running tasks", stopper.NumTasks())
			case <-stopper.ShouldStop():
				return
			}
		}
	}()

	select {
	case <-signalCh:
		log.Errorf("second signal received, initiating hard shutdown")
	case <-time.After(time.Minute):
		log.Errorf("time limit reached, initiating hard shutdown")
	case <-stopper.IsStopped():
		const msgDone = "server drained and shutdown completed"
		log.Infof(msgDone)
		fmt.Fprintln(os.Stdout, msgDone)
	}
	log.Flush()
	return nil
}

// exterminateCmd command shuts down the node server and
// destroys all data held by the node.
var exterminateCmd = &cobra.Command{
	Use:   "exterminate",
	Short: "destroy all data held by the node",
	Long: `
First shuts down the system and then destroys all data held by the
node, cycling through each store specified by --store flags.
`,
	SilenceUsage: true,
	RunE:         runExterminate,
}

// runExterminate destroys the data held in the specified stores.
func runExterminate(_ *cobra.Command, _ []string) error {
	stopper := stop.NewStopper()
	defer stopper.Stop()
	if err := cliContext.InitStores(stopper); err != nil {
		return util.Errorf("failed to initialize context: %s", err)
	}

	if err := runQuit(nil, nil); err != nil {
		return util.Errorf("shutdown node error: %s", err)
	}

	// Exterminate all data held in specified stores.
	for _, e := range cliContext.Engines {
		if rocksdb, ok := e.(*engine.RocksDB); ok {
			log.Infof("exterminating data from store %s", e)
			if err := rocksdb.Destroy(); err != nil {
				return util.Errorf("unable to destroy store %s: %s", e, err)
			}
		}
	}
	log.Infof("exterminated all data from stores %s", cliContext.Engines)
	return nil
}

// quitCmd command shuts down the node server.
var quitCmd = &cobra.Command{
	Use:   "quit",
	Short: "drain and shutdown node\n",
	Long: `
Shutdown the server. The first stage is drain, where any new requests
will be ignored by the server. When all extant requests have been
completed, the server exits.
`,
	SilenceUsage: true,
	RunE:         runQuit,
}

// runQuit accesses the quit shutdown path.
func runQuit(_ *cobra.Command, _ []string) error {
	admin, err := client.NewAdminClient(&cliContext.Context.Context, cliContext.HTTPAddr, client.Quit)
	if err != nil {
		return err
	}
	body, err := admin.Get()
	// TODO(tschottdorf): needs cleanup. An error here can happen if the shutdown
	// happened faster than the HTTP request made it back.
	if err != nil {
		return err
	}
	fmt.Printf("node drained and shutdown: %s\n", body)
	return nil
}
<|endoftext|>


<commit_before>package gcvgo

import (
	"bytes"
	"compress/gzip"
	"encoding/base64"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"net/url"
	"strconv"
)

// NewClient creates a new API client with the provided credentials
func NewClient(credentials Credentials) (Client, error) {

	return Client{
		httpClient:  &http.Client{},
		Credentials: credentials,
	}, nil
}

func (reqs *RequestBatch) Add(request Request) {
	*reqs = append(*reqs, request)
}

func (request *Request) AddImageFromBase64(base64Content string) {
	request.Image.Content = base64Content
}

func (request *Request) AddImageFromFile(filePath string) error {
	imageData, err := ioutil.ReadFile(filePath)
	if err != nil {
		return err
	}
	base64Content := base64.StdEncoding.EncodeToString(imageData)
	request.Image.Content = base64Content
	return nil
}

func (features *Features) Add(featureType FeatureType, MaxResults int64) {
	*features = append(*features, Feature{
		Type:       featureType,
		MaxResults: MaxResults,
	})
}

func (client *Client) Do(reqs RequestBatch) ([]Response, error) {
	payload := struct {
		Requests RequestBatch `json:"requests"`
	}{
		Requests: reqs,
	}
	JSONPayload, err := json.Marshal(payload)
	if err != nil {
		return []Response{}, err
	}
	//fmt.Println(string(JSONPayload))

	response, _, err := client.fetchAndReturnPage(JSONPayload)
	if err != nil {
		return []Response{}, err
	}

	//fmt.Println(string(response))

	var result struct {
		Responses []Response `json:"responses"`
	}
	err = json.Unmarshal(response, &result)
	if err != nil {
		return []Response{}, err
	}

	return result.Responses, nil
}

func (client *Client) fetchAndReturnPage(body []byte) ([]byte, http.Header, error) {

	domain := fmt.Sprintf("https://vision.googleapis.com/v1/images:annotate?key=%s", client.Credentials.APIkey)
	requestURL, err := url.Parse(domain)
	if err != nil {
		return []byte(""), http.Header{}, err
	}
	requestURL.Path = "/v1/images:annotate"

	//fmt.Println(requestURL)

	request, err := http.NewRequest("POST", requestURL.String(), bytes.NewBuffer(body))
	if err != nil {
		return []byte(""), http.Header{}, fmt.Errorf("Failed to get the URL %s: %s", requestURL, err)
	}
	request.Header.Add("Content-Length", strconv.Itoa(len(body)))

	request.Header.Add("Connection", "Keep-Alive")
	request.Header.Add("Accept-Encoding", "gzip, deflate")
	request.Header.Add("Content-Type", "application/json")

	response, err := client.httpClient.Do(request)
	if err != nil {
		return []byte(""), http.Header{}, fmt.Errorf("Failed to get the URL %s: %s", requestURL, err)
	}
	defer response.Body.Close()

	var responseReader io.ReadCloser
	switch response.Header.Get("Content-Encoding") {
	case "gzip":
		decompressedBodyReader, err := gzip.NewReader(response.Body)
		if err != nil {
			return []byte(""), http.Header{}, err
		}
		responseReader = decompressedBodyReader
		defer responseReader.Close()
	default:
		responseReader = response.Body
	}

	responseBody, err := ioutil.ReadAll(responseReader)
	if err != nil {
		return []byte(""), http.Header{}, err
	}

	if response.StatusCode > 299 || response.StatusCode < 199 {
		var apiError Status
		err = json.Unmarshal(responseBody, &apiError)
		if err != nil {
			return []byte(""), http.Header{}, nil
		}
		fmt.Println(response.StatusCode)
		fmt.Println(string(responseBody))
		return responseBody, response.Header, fmt.Errorf("%s", responseBody)
	}

	return responseBody, response.Header, nil
}
<commit_msg>Add AddImageFromGCSURI(gcsURI string) error<commit_after>package gcvgo

import (
	"bytes"
	"compress/gzip"
	"encoding/base64"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"net/url"
	"strconv"
)

// NewClient creates a new API client with the provided credentials
func NewClient(credentials Credentials) (Client, error) {

	return Client{
		httpClient:  &http.Client{},
		Credentials: credentials,
	}, nil
}

func (reqs *RequestBatch) Add(request Request) {
	*reqs = append(*reqs, request)
}

func (request *Request) AddImageFromBase64(base64Content string) {
	request.Image.Content = base64Content
}

func (request *Request) AddImageFromFile(filePath string) error {
	imageData, err := ioutil.ReadFile(filePath)
	if err != nil {
		return err
	}
	base64Content := base64.StdEncoding.EncodeToString(imageData)
	request.Image.Content = base64Content
	return nil
}

func (request *Request) AddImageFromGCSURI(gcsURI string) error {
	request.Image.Source.GcsImageUri = gcsUri
	return nil
}

func (features *Features) Add(featureType FeatureType, MaxResults int64) {
	*features = append(*features, Feature{
		Type:       featureType,
		MaxResults: MaxResults,
	})
}

func (client *Client) Do(reqs RequestBatch) ([]Response, error) {
	payload := struct {
		Requests RequestBatch `json:"requests"`
	}{
		Requests: reqs,
	}
	JSONPayload, err := json.Marshal(payload)
	if err != nil {
		return []Response{}, err
	}
	//fmt.Println(string(JSONPayload))

	response, _, err := client.fetchAndReturnPage(JSONPayload)
	if err != nil {
		return []Response{}, err
	}

	//fmt.Println(string(response))

	var result struct {
		Responses []Response `json:"responses"`
	}
	err = json.Unmarshal(response, &result)
	if err != nil {
		return []Response{}, err
	}

	return result.Responses, nil
}

func (client *Client) fetchAndReturnPage(body []byte) ([]byte, http.Header, error) {

	domain := fmt.Sprintf("https://vision.googleapis.com/v1/images:annotate?key=%s", client.Credentials.APIkey)
	requestURL, err := url.Parse(domain)
	if err != nil {
		return []byte(""), http.Header{}, err
	}
	requestURL.Path = "/v1/images:annotate"

	//fmt.Println(requestURL)

	request, err := http.NewRequest("POST", requestURL.String(), bytes.NewBuffer(body))
	if err != nil {
		return []byte(""), http.Header{}, fmt.Errorf("Failed to get the URL %s: %s", requestURL, err)
	}
	request.Header.Add("Content-Length", strconv.Itoa(len(body)))

	request.Header.Add("Connection", "Keep-Alive")
	request.Header.Add("Accept-Encoding", "gzip, deflate")
	request.Header.Add("Content-Type", "application/json")

	response, err := client.httpClient.Do(request)
	if err != nil {
		return []byte(""), http.Header{}, fmt.Errorf("Failed to get the URL %s: %s", requestURL, err)
	}
	defer response.Body.Close()

	var responseReader io.ReadCloser
	switch response.Header.Get("Content-Encoding") {
	case "gzip":
		decompressedBodyReader, err := gzip.NewReader(response.Body)
		if err != nil {
			return []byte(""), http.Header{}, err
		}
		responseReader = decompressedBodyReader
		defer responseReader.Close()
	default:
		responseReader = response.Body
	}

	responseBody, err := ioutil.ReadAll(responseReader)
	if err != nil {
		return []byte(""), http.Header{}, err
	}

	if response.StatusCode > 299 || response.StatusCode < 199 {
		var apiError Status
		err = json.Unmarshal(responseBody, &apiError)
		if err != nil {
			return []byte(""), http.Header{}, nil
		}
		fmt.Println(response.StatusCode)
		fmt.Println(string(responseBody))
		return responseBody, response.Header, fmt.Errorf("%s", responseBody)
	}

	return responseBody, response.Header, nil
}
<|endoftext|>


<commit_before>// Package to read and write FASTQ format files
package fastq

// Modified under the terms of GPL3 from
// Dan Kortschak github.com/kortschak/BioGo

import (
	"bufio"
	"bytes"
	"errors"
	"github.com/MG-RAST/Shock/shock-server/conf"
	"github.com/MG-RAST/Shock/shock-server/node/file"
	"github.com/MG-RAST/Shock/shock-server/node/file/format/seq"
	"io"
	"os"
	"regexp"
)

var (
	Regex = regexp.MustCompile(`^[\n\r]*@\S+[\S\t ]+[\n\r]+[A-Za-z\-]+[\n\r]+\+[\S\t ]*[\n\r]+\S*[\n\r]+`)
)

// Fastq sequence format reader type.
type Reader struct {
	f file.SectionReader
	r *bufio.Reader
}

// Returns a new fastq format reader using r.
func NewReader(f file.SectionReader) seq.ReadRewinder {
	return &Reader{
		f: f,
		r: nil,
	}
}

// Returns a new fastq format reader using a filename.
func NewReaderName(name string) (r seq.ReadRewinder, err error) {
	var f *os.File
	if f, err = os.Open(name); err != nil {
		return
	}
	return NewReader(f), nil
}

// Read a single sequence and return it or an error.
func (self *Reader) Read() (sequence *seq.Seq, err error) {
	if self.r == nil {
		self.r = bufio.NewReader(self.f)
	}
	var seqId, seqBody, qualId, qualBody []byte

	// skip empty lines only at eof
	empty := false
	for {
		seqId, err = self.r.ReadBytes('\n')
		if err != nil {
			break
		}
		if len(seqId) > 1 {
			break
		}
		empty = true
	}

	if empty {
		err = errors.New("Invalid format: empty line(s) between records")
		return
	} else if (err == io.EOF) && (len(seqId) > 1) {
		err = errors.New("Invalid format: truncated fastq record")
		return
	} else if err != nil {
		return
	} else if !bytes.HasPrefix(seqId, []byte{'@'}) {
		err = errors.New("Invalid format: id line does not start with @")
		return
	}
	seqId = bytes.TrimSpace(seqId[1:])
	if len(seqId) == 0 {
		err = errors.New("Invalid format: missing sequence ID")
		return
	}

	seqBody, err = self.r.ReadBytes('\n')
	if err == io.EOF {
		err = errors.New("Invalid format: truncated fastq record")
		return
	} else if err != nil {
		return
	}
	seqBody = bytes.TrimSpace(seqBody)
	if len(seqBody) == 0 {
		err = errors.New("Invalid format: empty sequence")
		return
	}

	qualId, err = self.r.ReadBytes('\n')
	if err == io.EOF {
		err = errors.New("Invalid format: truncated fastq record")
		return
	} else if err != nil {
		return
	} else if !bytes.HasPrefix(qualId, []byte{'+'}) {
		err = errors.New("Invalid format: plus line does not start with +")
		return
	}
	qualId = bytes.TrimSpace(qualId)
	if (len(qualId) > 1) && (bytes.Compare(seqId, qualId[1:]) != 0) {
		err = errors.New("Invalid format: quality ID does not match sequence ID")
		return
	}

	qualBody, err = self.r.ReadBytes('\n')
	if (err == io.EOF) && (len(seqBody) != len(qualBody)) {
		err = errors.New("Invalid format: length of sequence and quality lines do not match")
		return
	} else if err != nil {
		return
	} else if len(seqBody) != len(qualBody)-1 {
		err = errors.New("Invalid format: length of sequence and quality lines do not match")
		return
	}
	qualBody = bytes.TrimSpace(qualBody)

	sequence = seq.New(seqId, seqBody, qualBody)
	return
}

// Read a single sequence and return read offset for indexing.
func (self *Reader) GetReadOffset() (n int, err error) {
	if self.r == nil {
		self.r = bufio.NewReader(self.f)
	}
	var seqId, seqBody, qualId, qualBody []byte
	curr := 0

	// skip empty lines only at eof
	empty := false
	for {
		seqId, err = self.r.ReadBytes('\n')
		if err != nil {
			break
		}
		if len(seqId) > 1 {
			break
		}
		empty = true
	}

	if empty {
		err = errors.New("Invalid format: empty line(s) between records")
		return
	} else if (err == io.EOF) && (len(seqId) > 1) {
		err = errors.New("Invalid format: truncated fastq record")
		return
	} else if err != nil {
		return
	} else if !bytes.HasPrefix(seqId, []byte{'@'}) {
		err = errors.New("Invalid format: id line does not start with @")
		return
	} else if len(seqId) == 2 {
		err = errors.New("Invalid format: missing sequence ID")
		return
	}
	curr += len(seqId)

	seqBody, err = self.r.ReadBytes('\n')
	if err == io.EOF {
		err = errors.New("Invalid format: truncated fastq record")
		return
	} else if err != nil {
		return
	} else if len(seqBody) == 1 {
		err = errors.New("Invalid format: empty sequence")
		return
	}
	curr += len(seqBody)

	qualId, err = self.r.ReadBytes('\n')
	if err == io.EOF {
		err = errors.New("Invalid format: truncated fastq record")
		return
	} else if err != nil {
		return
	} else if !bytes.HasPrefix(qualId, []byte{'+'}) {
		err = errors.New("Invalid format: plus line does not start with +")
		return
	}
	qualIdTrim := bytes.TrimSpace(qualId)
	if (len(qualIdTrim) > 1) && (bytes.Compare(bytes.TrimSpace(seqId[1:]), qualIdTrim[1:]) != 0) {
		err = errors.New("Invalid format: quality ID does not match sequence ID")
		return
	}
	curr += len(qualId)

	qualBody, err = self.r.ReadBytes('\n')
	if (err == io.EOF) && (len(seqBody)-1 != len(qualBody)) {
		err = errors.New("Invalid format: length of sequence and quality lines do not match")
		return
	} else if err != nil {
		return
	} else if len(seqBody) != len(qualBody) {
		err = errors.New("Invalid format: length of sequence and quality lines do not match")
		return
	}

	n = curr + len(qualBody)
	return
}

// seek sequences which add up to a size close to the configured chunk size (conf.CHUNK_SIZE, e.g. 1M)
func (self *Reader) SeekChunk(offSet int64) (n int64, err error) {
	winSize := int64(32768)
	r := io.NewSectionReader(self.f, offSet+conf.CHUNK_SIZE-winSize, winSize)
	buf := make([]byte, winSize)
	if n, err := r.Read(buf); err != nil {
		// EOF reached
		return int64(n), err
	}
	// recursivly extend by window size until start of new record found
	// try both /n and /r
	var pos int
	pos = bytes.LastIndex(buf, []byte("\n@"))
	if pos == -1 {
		pos = bytes.LastIndex(buf, []byte("\r@"))
	}
	if pos == -1 {
		indexPos, err := self.SeekChunk(offSet + winSize)
		return (winSize + indexPos), err
	}
	// done, start new record found
	return conf.CHUNK_SIZE - winSize + int64(pos+1), nil
}

// Rewind the reader.
func (self *Reader) Rewind() (err error) {
	if s, ok := self.f.(io.Seeker); ok {
		_, err = s.Seek(0, 0)
		self.r = bufio.NewReader(self.f)
	} else {
		err = errors.New("Not a Seeker")
	}
	return
}

// Fastq sequence format writer type.
type Writer struct {
	f io.WriteCloser
	w *bufio.Writer
}

// Returns a new fastq format writer using w.
func NewWriter(f io.WriteCloser) *Writer {
	return &Writer{
		f: f,
		w: bufio.NewWriter(f),
	}
}

// Returns a new fastq format writer using a filename, truncating any existing file.
// If appending is required use NewWriter and os.OpenFile.
func NewWriterName(name string) (w *Writer, err error) {
	var f *os.File
	if f, err = os.Create(name); err != nil {
		return
	}
	return NewWriter(f), nil
}

// Write a single sequence and return the number of bytes written and any error.
func (self *Writer) Write(s *seq.Seq) (n int, err error) {
	if s.Qual == nil {
		return 0, errors.New("No quality associated with sequence")
	}
	if len(s.Seq) == len(s.Qual) {
		n, err = Format(s, self.w)
		return
	} else {
		return 0, errors.New("Sequence length and quality length do not match")
	}

	return
}

// Format a single sequence into fastq string
func Format(s *seq.Seq, w io.Writer) (n int, err error) {
	return w.Write([]byte("@" + string(s.ID) + "\n" + string(s.Seq) + "\n+\n" + string(s.Qual) + "\n"))
}

// Flush the writer.
func (self *Writer) Flush() error {
	return self.w.Flush()
}

// Close the writer, flushing any unwritten sequence.
func (self *Writer) Close() (err error) {
	if err = self.w.Flush(); err != nil {
		return
	}
	return self.f.Close()
}
<commit_msg>fix fastq last record index<commit_after>// Package to read and write FASTQ format files
package fastq

// Modified under the terms of GPL3 from
// Dan Kortschak github.com/kortschak/BioGo

import (
	"bufio"
	"bytes"
	"errors"
	"fmt"
	"github.com/MG-RAST/Shock/shock-server/conf"
	"github.com/MG-RAST/Shock/shock-server/node/file"
	"github.com/MG-RAST/Shock/shock-server/node/file/format/seq"
	"io"
	"os"
	"regexp"
)

var (
	Regex = regexp.MustCompile(`^[\n\r]*@\S+[\S\t ]+[\n\r]+[A-Za-z\-]+[\n\r]+\+[\S\t ]*[\n\r]+\S*[\n\r]+`)
)

// Fastq sequence format reader type.
type Reader struct {
	f file.SectionReader
	r *bufio.Reader
}

// Returns a new fastq format reader using r.
func NewReader(f file.SectionReader) seq.ReadRewinder {
	return &Reader{
		f: f,
		r: nil,
	}
}

// Returns a new fastq format reader using a filename.
func NewReaderName(name string) (r seq.ReadRewinder, err error) {
	var f *os.File
	if f, err = os.Open(name); err != nil {
		return
	}
	return NewReader(f), nil
}

// Read a single sequence and return it or an error.
func (self *Reader) Read() (sequence *seq.Seq, err error) {
	if self.r == nil {
		self.r = bufio.NewReader(self.f)
	}
	var seqId, seqBody, qualId, qualBody []byte

	// skip empty lines only at eof
	empty := false
	for {
		seqId, err = self.r.ReadBytes('\n')
		if err != nil {
			break
		}
		if len(seqId) > 1 {
			break
		}
		empty = true
	}

	if err == io.EOF {
		if len(seqId) > 0 {
			err = errors.New("Invalid format: truncated fastq record")
		}
		return
	} else if err != nil {
		return
	} else if empty {
		err = errors.New("Invalid format: empty line(s) between records")
		return
	} else if !bytes.HasPrefix(seqId, []byte{'@'}) {
		err = errors.New("Invalid format: id line does not start with @")
		return
	}
	seqId = bytes.TrimSpace(seqId[1:])
	if len(seqId) == 0 {
		err = errors.New("Invalid format: missing sequence ID")
		return
	}

	seqBody, err = self.r.ReadBytes('\n')
	if err == io.EOF {
		err = errors.New("Invalid format: truncated fastq record")
		return
	} else if err != nil {
		return
	}
	seqBody = bytes.TrimSpace(seqBody)
	if len(seqBody) == 0 {
		err = errors.New("Invalid format: empty sequence")
		return
	}

	qualId, err = self.r.ReadBytes('\n')
	if err == io.EOF {
		err = errors.New("Invalid format: truncated fastq record")
		return
	} else if err != nil {
		return
	} else if !bytes.HasPrefix(qualId, []byte{'+'}) {
		err = errors.New("Invalid format: plus line does not start with +")
		return
	}
	qualId = bytes.TrimSpace(qualId)
	if (len(qualId) > 1) && (bytes.Compare(seqId, qualId[1:]) != 0) {
		err = errors.New("Invalid format: quality ID does not match sequence ID")
		return
	}

	qualBody, err = self.r.ReadBytes('\n')
	if (err != nil) && (err != io.EOF) {
		return
	}
	qualBody = bytes.TrimSpace(qualBody)
	if len(seqBody) != len(qualBody) {
		err = errors.New("Invalid format: length of sequence and quality lines do not match")
		return
	}

	sequence = seq.New(seqId, seqBody, qualBody)
	return
}

// Read a single sequence and return read offset for indexing.
func (self *Reader) GetReadOffset() (n int, err error) {
	if self.r == nil {
		self.r = bufio.NewReader(self.f)
	}
	var seqId, seqBody, qualId, qualBody []byte
	curr := 0

	// skip empty lines only at eof
	empty := false
	for {
		seqId, err = self.r.ReadBytes('\n')
		if err != nil {
			break
		}
		if len(seqId) > 1 {
			break
		}
		empty = true
	}

	if err == io.EOF {
		if len(seqId) > 0 {
			err = errors.New("Invalid format: truncated fastq record")
		}
		return
	} else if err != nil {
		return
	} else if empty {
		err = errors.New("Invalid format: empty line(s) between records")
		return
	} else if !bytes.HasPrefix(seqId, []byte{'@'}) {
		err = errors.New("Invalid format: id line does not start with @")
		return
	} else if len(seqId) == 2 {
		err = errors.New("Invalid format: missing sequence ID")
		return
	}
	curr += len(seqId)

	seqBody, err = self.r.ReadBytes('\n')
	if err == io.EOF {
		err = errors.New("Invalid format: truncated fastq record")
		return
	} else if err != nil {
		return
	} else if len(seqBody) == 1 {
		err = errors.New("Invalid format: empty sequence")
		return
	}
	curr += len(seqBody)

	qualId, err = self.r.ReadBytes('\n')
	if err == io.EOF {
		err = errors.New("Invalid format: truncated fastq record")
		return
	} else if err != nil {
		return
	} else if !bytes.HasPrefix(qualId, []byte{'+'}) {
		err = errors.New("Invalid format: plus line does not start with +")
		return
	}
	qualIdTrim := bytes.TrimSpace(qualId)
	if (len(qualIdTrim) > 1) && (bytes.Compare(bytes.TrimSpace(seqId[1:]), qualIdTrim[1:]) != 0) {
		err = errors.New("Invalid format: quality ID does not match sequence ID")
		return
	}
	curr += len(qualId)

	qualBody, err = self.r.ReadBytes('\n')
	if (err != nil) && (err != io.EOF) {
		return
	}
	if len(bytes.TrimSpace(seqBody)) != len(bytes.TrimSpace(qualBody)) {
		err = errors.New("Invalid format: length of sequence and quality lines do not match")
		return
	}

	n = curr + len(qualBody)
	return
}

// seek sequences which add up to a size close to the configured chunk size (conf.CHUNK_SIZE, e.g. 1M)
func (self *Reader) SeekChunk(offSet int64) (n int64, err error) {
	winSize := int64(32768)
	r := io.NewSectionReader(self.f, offSet+conf.CHUNK_SIZE-winSize, winSize)
	buf := make([]byte, winSize)
	if n, err := r.Read(buf); err != nil {
		// EOF reached
		return int64(n), err
	}
	// recursivly extend by window size until start of new record found
	// try both /n and /r
	var pos int
	pos = bytes.LastIndex(buf, []byte("\n@"))
	if pos == -1 {
		pos = bytes.LastIndex(buf, []byte("\r@"))
	}
	if pos == -1 {
		indexPos, err := self.SeekChunk(offSet + winSize)
		return (winSize + indexPos), err
	}
	// done, start new record found
	return conf.CHUNK_SIZE - winSize + int64(pos+1), nil
}

// Rewind the reader.
func (self *Reader) Rewind() (err error) {
	if s, ok := self.f.(io.Seeker); ok {
		_, err = s.Seek(0, 0)
		self.r = bufio.NewReader(self.f)
	} else {
		err = errors.New("Not a Seeker")
	}
	return
}

// Fastq sequence format writer type.
type Writer struct {
	f io.WriteCloser
	w *bufio.Writer
}

// Returns a new fastq format writer using w.
func NewWriter(f io.WriteCloser) *Writer {
	return &Writer{
		f: f,
		w: bufio.NewWriter(f),
	}
}

// Returns a new fastq format writer using a filename, truncating any existing file.
// If appending is required use NewWriter and os.OpenFile.
func NewWriterName(name string) (w *Writer, err error) {
	var f *os.File
	if f, err = os.Create(name); err != nil {
		return
	}
	return NewWriter(f), nil
}

// Write a single sequence and return the number of bytes written and any error.
func (self *Writer) Write(s *seq.Seq) (n int, err error) {
	if s.Qual == nil {
		return 0, errors.New("No quality associated with sequence")
	}
	if len(s.Seq) == len(s.Qual) {
		n, err = Format(s, self.w)
		return
	} else {
		return 0, errors.New("Sequence length and quality length do not match")
	}

	return
}

// Format a single sequence into fastq string
func Format(s *seq.Seq, w io.Writer) (n int, err error) {
	return w.Write([]byte("@" + string(s.ID) + "\n" + string(s.Seq) + "\n+\n" + string(s.Qual) + "\n"))
}

// Flush the writer.
func (self *Writer) Flush() error {
	return self.w.Flush()
}

// Close the writer, flushing any unwritten sequence.
func (self *Writer) Close() (err error) {
	if err = self.w.Flush(); err != nil {
		return
	}
	return self.f.Close()
}
<|endoftext|>


<commit_before>// +build containerd

package control

import (
	"fmt"
	"net"
	"os"
	"path/filepath"
	"strings"
	"time"

	contentapi "github.com/containerd/containerd/api/services/content"
	diffapi "github.com/containerd/containerd/api/services/diff"
	snapshotapi "github.com/containerd/containerd/api/services/snapshot"
	contentservice "github.com/containerd/containerd/services/content"
	diffservice "github.com/containerd/containerd/services/diff"
	snapshotservice "github.com/containerd/containerd/services/snapshot"
	"github.com/pkg/errors"
	"github.com/tonistiigi/buildkit_poc/worker/runcworker"
	"google.golang.org/grpc"
)

func NewContainerd(root, address string) (*Controller, error) {
	if err := os.MkdirAll(root, 0700); err != nil {
		return nil, errors.Wrapf(err, "failed to create %s", root)
	}

	// TODO: take lock to make sure there are no duplicates

	gopts := []grpc.DialOption{
		grpc.WithBlock(),
		grpc.WithInsecure(),
		grpc.WithTimeout(100 * time.Second),
		grpc.WithDialer(dialer),
		grpc.FailOnNonTempDialError(true),
	}
	conn, err := grpc.Dial(dialAddress(address), gopts...)
	if err != nil {
		return nil, errors.Wrapf(err, "failed to connect to %q . make sure containerd is running", address)
	}

	pd, err := newPullDeps(conn)
	if err != nil {
		return nil, err
	}

	opt, err := defaultControllerOpts(root, *pd)
	if err != nil {
		return nil, err
	}

	w, err := runcworker.New(filepath.Join(root, "runc"))
	if err != nil {
		return nil, err
	}

	opt.Worker = w

	return NewController(*opt)
}

func newPullDeps(conn *grpc.ClientConn) (*pullDeps, error) {
	s := snapshotservice.NewSnapshotterFromClient(snapshotapi.NewSnapshotClient(conn))
	c := contentservice.NewStoreFromClient(contentapi.NewContentClient(conn))
	a := diffservice.NewDiffServiceFromClient(diffapi.NewDiffClient(conn))

	return &pullDeps{
		Snapshotter:  s,
		ContentStore: c,
		Applier:      a,
	}, nil
}

func dialer(address string, timeout time.Duration) (net.Conn, error) {
	address = strings.TrimPrefix(address, "unix://")
	return net.DialTimeout("unix", address, timeout)
}

func dialAddress(address string) string {
	return fmt.Sprintf("unix://%s", address)
}
<commit_msg>Use containerd client and default namespace<commit_after>// +build containerd

package control

import (
	"fmt"
	"net"
	"os"
	"path/filepath"
	"strings"
	"time"

	"github.com/containerd/containerd"
	"github.com/pkg/errors"
	"github.com/tonistiigi/buildkit_poc/worker/runcworker"
)

func NewContainerd(root, address string) (*Controller, error) {
	if err := os.MkdirAll(root, 0700); err != nil {
		return nil, errors.Wrapf(err, "failed to create %s", root)
	}

	// TODO: take lock to make sure there are no duplicates
	client, err := containerd.New(address, containerd.WithDefaultNamespace("buildkit"))
	if err != nil {
		return nil, errors.Wrapf(err, "failed to connect client to %q . make sure containerd is running", address)
	}

	pd := newPullDeps(client)

	opt, err := defaultControllerOpts(root, *pd)
	if err != nil {
		return nil, err
	}

	w, err := runcworker.New(filepath.Join(root, "runc"))
	if err != nil {
		return nil, err
	}

	opt.Worker = w

	return NewController(*opt)
}

func newPullDeps(client *containerd.Client) *pullDeps {
	return &pullDeps{
		Snapshotter:  client.SnapshotService(),
		ContentStore: client.ContentStore(),
		Applier:      client.DiffService(),
	}
}

func dialer(address string, timeout time.Duration) (net.Conn, error) {
	address = strings.TrimPrefix(address, "unix://")
	return net.DialTimeout("unix", address, timeout)
}

func dialAddress(address string) string {
	return fmt.Sprintf("unix://%s", address)
}
<|endoftext|>


<commit_before>package aws

import (
	"fmt"
	"math/rand"
	"testing"
	"time"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/elasticache"
	"github.com/hashicorp/terraform/helper/resource"
	"github.com/hashicorp/terraform/terraform"
)

func TestAccAWSElasticacheCluster_basic(t *testing.T) {
	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSElasticacheClusterDestroy,
		Steps: []resource.TestStep{
			resource.TestStep{
				Config: testAccAWSElasticacheClusterConfig,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSElasticacheSecurityGroupExists("aws_elasticache_security_group.bar"),
					testAccCheckAWSElasticacheClusterExists("aws_elasticache_cluster.bar"),
					resource.TestCheckResourceAttr(
						"aws_elasticache_cluster.bar", "cache_nodes.0.id", "0001"),
				),
			},
		},
	})
}

func TestAccAWSElasticacheCluster_vpc(t *testing.T) {
	var csg elasticache.CacheSubnetGroup
	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSElasticacheClusterDestroy,
		Steps: []resource.TestStep{
			resource.TestStep{
				Config: testAccAWSElasticacheClusterInVPCConfig,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSElasticacheSubnetGroupExists("aws_elasticache_subnet_group.bar", &csg),
					testAccCheckAWSElasticacheClusterExists("aws_elasticache_cluster.bar"),
				),
			},
		},
	})
}

func testAccCheckAWSElasticacheClusterDestroy(s *terraform.State) error {
	conn := testAccProvider.Meta().(*AWSClient).elasticacheconn

	for _, rs := range s.RootModule().Resources {
		if rs.Type != "aws_elasticache_cluster" {
			continue
		}
		res, err := conn.DescribeCacheClusters(&elasticache.DescribeCacheClustersInput{
			CacheClusterId: aws.String(rs.Primary.ID),
		})
		if err != nil {
			return err
		}
		if len(res.CacheClusters) > 0 {
			return fmt.Errorf("still exist.")
		}
	}
	return nil
}

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

		if rs.Primary.ID == "" {
			return fmt.Errorf("No cache cluster ID is set")
		}

		conn := testAccProvider.Meta().(*AWSClient).elasticacheconn
		_, err := conn.DescribeCacheClusters(&elasticache.DescribeCacheClustersInput{
			CacheClusterId: aws.String(rs.Primary.ID),
		})
		if err != nil {
			return fmt.Errorf("Elasticache error: %v", err)
		}
		return nil
	}
}

func genRandInt() int {
	return rand.New(rand.NewSource(time.Now().UnixNano())).Int() % 1000
}

var testAccAWSElasticacheClusterConfig = fmt.Sprintf(`
provider "aws" {
	region = "us-east-1"
}
resource "aws_security_group" "bar" {
    name = "tf-test-security-group-%03d"
    description = "tf-test-security-group-descr"
    ingress {
        from_port = -1
        to_port = -1
        protocol = "icmp"
        cidr_blocks = ["0.0.0.0/0"]
    }
}

resource "aws_elasticache_security_group" "bar" {
    name = "tf-test-security-group-%03d"
    description = "tf-test-security-group-descr"
    security_group_names = ["${aws_security_group.bar.name}"]
}

resource "aws_elasticache_cluster" "bar" {
    cluster_id = "tf-test-%03d"
    engine = "memcached"
    node_type = "cache.m1.small"
    num_cache_nodes = 1
    port = 11211
    parameter_group_name = "default.memcached1.4"
    security_group_names = ["${aws_elasticache_security_group.bar.name}"]
}
`, genRandInt(), genRandInt(), genRandInt())

var testAccAWSElasticacheClusterInVPCConfig = fmt.Sprintf(`
resource "aws_vpc" "foo" {
    cidr_block = "192.168.0.0/16"
    tags {
            Name = "tf-test"
    }
}

resource "aws_subnet" "foo" {
    vpc_id = "${aws_vpc.foo.id}"
    cidr_block = "192.168.0.0/20"
    availability_zone = "us-west-2a"
    tags {
            Name = "tf-test"
    }
}

resource "aws_elasticache_subnet_group" "bar" {
    name = "tf-test-cache-subnet-%03d"
    description = "tf-test-cache-subnet-group-descr"
    subnet_ids = ["${aws_subnet.foo.id}"]
}

resource "aws_security_group" "bar" {
    name = "tf-test-security-group-%03d"
    description = "tf-test-security-group-descr"
    vpc_id = "${aws_vpc.foo.id}"
    ingress {
        from_port = -1
        to_port = -1
        protocol = "icmp"
        cidr_blocks = ["0.0.0.0/0"]
    }
}

resource "aws_elasticache_cluster" "bar" {
    // Including uppercase letters in this name to ensure
    // that we correctly handle the fact that the API
    // normalizes names to lowercase.
    cluster_id = "tf-TEST-%03d"
    node_type = "cache.m1.small"
    num_cache_nodes = 1
    engine = "redis"
    engine_version = "2.8.19"
    port = 6379
    subnet_group_name = "${aws_elasticache_subnet_group.bar.name}"
    security_group_ids = ["${aws_security_group.bar.id}"]
    parameter_group_name = "default.redis2.8"
}
`, genRandInt(), genRandInt(), genRandInt())
<commit_msg>add test for elasticache cluster and topic arn<commit_after>package aws

import (
	"fmt"
	"math/rand"
	"strings"
	"testing"
	"time"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/elasticache"
	"github.com/hashicorp/terraform/helper/resource"
	"github.com/hashicorp/terraform/terraform"
)

func TestAccAWSElasticacheCluster_basic(t *testing.T) {
	var ec elasticache.CacheCluster
	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSElasticacheClusterDestroy,
		Steps: []resource.TestStep{
			resource.TestStep{
				Config: testAccAWSElasticacheClusterConfig,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSElasticacheSecurityGroupExists("aws_elasticache_security_group.bar"),
					testAccCheckAWSElasticacheClusterExists("aws_elasticache_cluster.bar", &ec),
					resource.TestCheckResourceAttr(
						"aws_elasticache_cluster.bar", "cache_nodes.0.id", "0001"),
				),
			},
		},
	})
}

func TestAccAWSElasticacheCluster_vpc(t *testing.T) {
	var csg elasticache.CacheSubnetGroup
	var ec elasticache.CacheCluster
	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSElasticacheClusterDestroy,
		Steps: []resource.TestStep{
			resource.TestStep{
				Config: testAccAWSElasticacheClusterInVPCConfig,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSElasticacheSubnetGroupExists("aws_elasticache_subnet_group.bar", &csg),
					testAccCheckAWSElasticacheClusterExists("aws_elasticache_cluster.bar", &ec),
					testAccCheckAWSElasticacheClusterAttributes(&ec),
				),
			},
		},
	})
}

func testAccCheckAWSElasticacheClusterAttributes(v *elasticache.CacheCluster) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		if v.NotificationConfiguration == nil {
			return fmt.Errorf("Expected NotificationConfiguration for ElastiCache Cluster (%s)", *v.CacheClusterId)
		}

		if strings.ToLower(*v.NotificationConfiguration.TopicStatus) != "active" {
			return fmt.Errorf("Expected NotificationConfiguration status to be 'active', got (%s)", *v.NotificationConfiguration.TopicStatus)
		}

		return nil
	}
}

func testAccCheckAWSElasticacheClusterDestroy(s *terraform.State) error {
	conn := testAccProvider.Meta().(*AWSClient).elasticacheconn

	for _, rs := range s.RootModule().Resources {
		if rs.Type != "aws_elasticache_cluster" {
			continue
		}
		res, err := conn.DescribeCacheClusters(&elasticache.DescribeCacheClustersInput{
			CacheClusterId: aws.String(rs.Primary.ID),
		})
		if err != nil {
			return err
		}
		if len(res.CacheClusters) > 0 {
			return fmt.Errorf("still exist.")
		}
	}
	return nil
}

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

		if rs.Primary.ID == "" {
			return fmt.Errorf("No cache cluster ID is set")
		}

		conn := testAccProvider.Meta().(*AWSClient).elasticacheconn
		resp, err := conn.DescribeCacheClusters(&elasticache.DescribeCacheClustersInput{
			CacheClusterId: aws.String(rs.Primary.ID),
		})
		if err != nil {
			return fmt.Errorf("Elasticache error: %v", err)
		}

		for _, c := range resp.CacheClusters {
			if *c.CacheClusterId == rs.Primary.ID {
				*v = *c
			}
		}

		return nil
	}
}

func genRandInt() int {
	return rand.New(rand.NewSource(time.Now().UnixNano())).Int() % 1000
}

var testAccAWSElasticacheClusterConfig = fmt.Sprintf(`
provider "aws" {
	region = "us-east-1"
}
resource "aws_security_group" "bar" {
    name = "tf-test-security-group-%03d"
    description = "tf-test-security-group-descr"
    ingress {
        from_port = -1
        to_port = -1
        protocol = "icmp"
        cidr_blocks = ["0.0.0.0/0"]
    }
}

resource "aws_elasticache_security_group" "bar" {
    name = "tf-test-security-group-%03d"
    description = "tf-test-security-group-descr"
    security_group_names = ["${aws_security_group.bar.name}"]
}

resource "aws_elasticache_cluster" "bar" {
    cluster_id = "tf-test-%03d"
    engine = "memcached"
    node_type = "cache.m1.small"
    num_cache_nodes = 1
    port = 11211
    parameter_group_name = "default.memcached1.4"
    security_group_names = ["${aws_elasticache_security_group.bar.name}"]
}
`, genRandInt(), genRandInt(), genRandInt())

var testAccAWSElasticacheClusterInVPCConfig = fmt.Sprintf(`
resource "aws_vpc" "foo" {
    cidr_block = "192.168.0.0/16"
    tags {
            Name = "tf-test"
    }
}

resource "aws_subnet" "foo" {
    vpc_id = "${aws_vpc.foo.id}"
    cidr_block = "192.168.0.0/20"
    availability_zone = "us-west-2a"
    tags {
            Name = "tf-test"
    }
}

resource "aws_elasticache_subnet_group" "bar" {
    name = "tf-test-cache-subnet-%03d"
    description = "tf-test-cache-subnet-group-descr"
    subnet_ids = ["${aws_subnet.foo.id}"]
}

resource "aws_security_group" "bar" {
    name = "tf-test-security-group-%03d"
    description = "tf-test-security-group-descr"
    vpc_id = "${aws_vpc.foo.id}"
    ingress {
        from_port = -1
        to_port = -1
        protocol = "icmp"
        cidr_blocks = ["0.0.0.0/0"]
    }
}

resource "aws_elasticache_cluster" "bar" {
    // Including uppercase letters in this name to ensure
    // that we correctly handle the fact that the API
    // normalizes names to lowercase.
    cluster_id = "tf-TEST-%03d"
    node_type = "cache.m1.small"
    num_cache_nodes = 1
    engine = "redis"
    engine_version = "2.8.19"
    port = 6379
    subnet_group_name = "${aws_elasticache_subnet_group.bar.name}"
    security_group_ids = ["${aws_security_group.bar.id}"]
    parameter_group_name = "default.redis2.8"
    notification_topic_arn      = "${aws_sns_topic.topic_example.arn}"
}

resource "aws_sns_topic" "topic_example" {
  name = "tf-ecache-cluster-test"
}
`, genRandInt(), genRandInt(), genRandInt())
<|endoftext|>


<commit_before>package gutil_test

import (
	"testing"

	"github.com/gogf/gf/g/test/gtest"
	"github.com/gogf/gf/g/util/gutil"
)

func Test_ComparatorString(t *testing.T) {

	gtest.Assert(gutil.ComparatorString(1, 1), 0)
	gtest.Assert(gutil.ComparatorString(1, 2), -1)
	gtest.Assert(gutil.ComparatorString(2, 1), 1)
}

func Test_ComparatorInt(t *testing.T) {

	gtest.Assert(gutil.ComparatorInt(1, 1), 0)
	gtest.Assert(gutil.ComparatorInt(1, 2), -1)
	gtest.Assert(gutil.ComparatorInt(2, 1), 1)
}

func Test_ComparatorInt8(t *testing.T) {

	gtest.Assert(gutil.ComparatorInt8(1, 1), 0)
	gtest.Assert(gutil.ComparatorInt8(1, 2), -1)
	gtest.Assert(gutil.ComparatorInt8(2, 1), 1)
}

func Test_ComparatorInt16(t *testing.T) {

	gtest.Assert(gutil.ComparatorInt16(1, 1), 0)
	gtest.Assert(gutil.ComparatorInt16(1, 2), -1)
	gtest.Assert(gutil.ComparatorInt16(2, 1), 1)
}

func Test_ComparatorInt32(t *testing.T) {

	gtest.Assert(gutil.ComparatorInt32(1, 1), 0)
	gtest.Assert(gutil.ComparatorInt32(1, 2), -1)
	gtest.Assert(gutil.ComparatorInt32(2, 1), 1)
}

func Test_ComparatorInt64(t *testing.T) {

	gtest.Assert(gutil.ComparatorInt64(1, 1), 0)
	gtest.Assert(gutil.ComparatorInt64(1, 2), -1)
	gtest.Assert(gutil.ComparatorInt64(2, 1), 1)
}

func Test_ComparatorUint(t *testing.T) {
	j := gutil.ComparatorUint(1, 1)
	gtest.Assert(j, 0)

	gtest.Assert(gutil.ComparatorUint(1, 1), 0)
	gtest.Assert(gutil.ComparatorUint(1, 2), -1)
	gtest.Assert(gutil.ComparatorUint(2, 1), 1)
}

func Test_ComparatorUint8(t *testing.T) {

	gtest.Assert(gutil.ComparatorUint8(1, 1), 0)
	gtest.Assert(gutil.ComparatorUint8(1, 2), 255)
	gtest.Assert(gutil.ComparatorUint8(2, 1), 1)
}

func Test_ComparatorUint16(t *testing.T) {

	gtest.Assert(gutil.ComparatorUint16(1, 1), 0)
	gtest.Assert(gutil.ComparatorUint16(1, 2), 65535)
	gtest.Assert(gutil.ComparatorUint16(2, 1), 1)
}

func Test_ComparatorUint32(t *testing.T) {

	gtest.Assert(gutil.ComparatorUint32(1, 1), 0)
	gtest.Assert(gutil.ComparatorUint32(1, 2), 4294967295)
	gtest.Assert(gutil.ComparatorUint32(2, 1), 1)
}

func Test_ComparatorUint64(t *testing.T) {

	gtest.Assert(gutil.ComparatorUint64(1, 1), 0)
	gtest.Assert(gutil.ComparatorUint64(1, 2), -1)
	gtest.Assert(gutil.ComparatorUint64(2, 1), 1)
}

func Test_ComparatorFloat32(t *testing.T) {

	gtest.Assert(gutil.ComparatorFloat32(1, 1), 0)
	gtest.Assert(gutil.ComparatorFloat32(1, 2), -1)
	gtest.Assert(gutil.ComparatorFloat32(2, 1), 1)
}

func Test_ComparatorFloat64(t *testing.T) {

	gtest.Assert(gutil.ComparatorFloat64(1, 1), 0)
	gtest.Assert(gutil.ComparatorFloat64(1, 2), -1)
	gtest.Assert(gutil.ComparatorFloat64(2, 1), 1)
}

func Test_ComparatorByte(t *testing.T) {

	gtest.Assert(gutil.ComparatorByte(1, 1), 0)
	gtest.Assert(gutil.ComparatorByte(1, 2), 255)
	gtest.Assert(gutil.ComparatorByte(2, 1), 1)
}

func Test_ComparatorRune(t *testing.T) {

	gtest.Assert(gutil.ComparatorRune(1, 1), 0)
	gtest.Assert(gutil.ComparatorRune(1, 2), -1)
	gtest.Assert(gutil.ComparatorRune(2, 1), 1)
}

func Test_ComparatorTime(t *testing.T) {

	j := gutil.ComparatorTime("2019-06-14", "2019-06-14")
	gtest.Assert(j, 0)
	k := gutil.ComparatorTime("2019-06-15", "2019-06-14")
	gtest.Assert(k, 1)
	l := gutil.ComparatorTime("2019-06-13", "2019-06-14")
	gtest.Assert(l, -1)
}
<commit_msg>gutil test 20190623 20:41<commit_after>package gutil_test

import (
	"testing"

	"github.com/gogf/gf/g/test/gtest"
	"github.com/gogf/gf/g/util/gutil"
)

func Test_ComparatorString(t *testing.T) {

	gtest.Assert(gutil.ComparatorString(1, 1), 0)
	gtest.Assert(gutil.ComparatorString(1, 2), -1)
	gtest.Assert(gutil.ComparatorString(2, 1), 1)
}

func Test_ComparatorInt(t *testing.T) {

	gtest.Assert(gutil.ComparatorInt(1, 1), 0)
	gtest.Assert(gutil.ComparatorInt(1, 2), -1)
	gtest.Assert(gutil.ComparatorInt(2, 1), 1)
}

func Test_ComparatorInt8(t *testing.T) {

	gtest.Assert(gutil.ComparatorInt8(1, 1), 0)
	gtest.Assert(gutil.ComparatorInt8(1, 2), -1)
	gtest.Assert(gutil.ComparatorInt8(2, 1), 1)
}

func Test_ComparatorInt16(t *testing.T) {

	gtest.Assert(gutil.ComparatorInt16(1, 1), 0)
	gtest.Assert(gutil.ComparatorInt16(1, 2), -1)
	gtest.Assert(gutil.ComparatorInt16(2, 1), 1)
}

func Test_ComparatorInt32(t *testing.T) {

	gtest.Assert(gutil.ComparatorInt32(1, 1), 0)
	gtest.Assert(gutil.ComparatorInt32(1, 2), -1)
	gtest.Assert(gutil.ComparatorInt32(2, 1), 1)
}

func Test_ComparatorInt64(t *testing.T) {

	gtest.Assert(gutil.ComparatorInt64(1, 1), 0)
	gtest.Assert(gutil.ComparatorInt64(1, 2), -1)
	gtest.Assert(gutil.ComparatorInt64(2, 1), 1)
}

func Test_ComparatorUint(t *testing.T) {

	gtest.Assert(gutil.ComparatorUint(1, 1), 0)
	gtest.Assert(gutil.ComparatorUint(1, 2), -1)
	gtest.Assert(gutil.ComparatorUint(2, 1), 1)
}

func Test_ComparatorUint8(t *testing.T) {

	gtest.Assert(gutil.ComparatorUint8(1, 1), 0)
	gtest.Assert(gutil.ComparatorUint8(1, 2), 255)
	gtest.Assert(gutil.ComparatorUint8(2, 1), 1)
}

func Test_ComparatorUint16(t *testing.T) {

	gtest.Assert(gutil.ComparatorUint16(1, 1), 0)
	gtest.Assert(gutil.ComparatorUint16(1, 2), 65535)
	gtest.Assert(gutil.ComparatorUint16(2, 1), 1)
}

func Test_ComparatorUint32(t *testing.T) {

	gtest.Assert(gutil.ComparatorUint32(1, 1), 0)
	gtest.Assert(gutil.ComparatorUint32(1, 2), 4294967295)
	gtest.Assert(gutil.ComparatorUint32(2, 1), 1)
}

func Test_ComparatorUint64(t *testing.T) {

	gtest.Assert(gutil.ComparatorUint64(1, 1), 0)
	gtest.Assert(gutil.ComparatorUint64(1, 2), -1)
	gtest.Assert(gutil.ComparatorUint64(2, 1), 1)
}

func Test_ComparatorFloat32(t *testing.T) {

	gtest.Assert(gutil.ComparatorFloat32(1, 1), 0)
	gtest.Assert(gutil.ComparatorFloat32(1, 2), -1)
	gtest.Assert(gutil.ComparatorFloat32(2, 1), 1)
}

func Test_ComparatorFloat64(t *testing.T) {

	gtest.Assert(gutil.ComparatorFloat64(1, 1), 0)
	gtest.Assert(gutil.ComparatorFloat64(1, 2), -1)
	gtest.Assert(gutil.ComparatorFloat64(2, 1), 1)
}

func Test_ComparatorByte(t *testing.T) {

	gtest.Assert(gutil.ComparatorByte(1, 1), 0)
	gtest.Assert(gutil.ComparatorByte(1, 2), 255)
	gtest.Assert(gutil.ComparatorByte(2, 1), 1)
}

func Test_ComparatorRune(t *testing.T) {

	gtest.Assert(gutil.ComparatorRune(1, 1), 0)
	gtest.Assert(gutil.ComparatorRune(1, 2), -1)
	gtest.Assert(gutil.ComparatorRune(2, 1), 1)
}

func Test_ComparatorTime(t *testing.T) {

	j := gutil.ComparatorTime("2019-06-14", "2019-06-14")
	gtest.Assert(j, 0)
	k := gutil.ComparatorTime("2019-06-15", "2019-06-14")
	gtest.Assert(k, 1)
	l := gutil.ComparatorTime("2019-06-13", "2019-06-14")
	gtest.Assert(l, -1)
}
<|endoftext|>


<commit_before>package cmd

import (
	"bytes"
	"fmt"
	"github.com/smira/aptly/deb"
	"github.com/smira/commander"
	"io"
	"io/ioutil"
	"os"
	"os/exec"
)

func aptlyGraph(cmd *commander.Command, args []string) error {
	var err error

	if len(args) != 0 {
		cmd.Usage()
		return commander.ErrCommandError
	}

	fmt.Printf("Generating graph...\n")
	graph, err := deb.BuildGraph(context.CollectionFactory())
	if err != nil {
		return err
	}

	buf := bytes.NewBufferString(graph.String())

	tempfile, err := ioutil.TempFile("", "aptly-graph")
	if err != nil {
		return err
	}
	tempfile.Close()
	os.Remove(tempfile.Name())

	format := context.Flags().Lookup("format").Value.String()
	output := context.Flags().Lookup("output").Value.String()

	tempfilename := tempfile.Name() + "." + format
	if output != "" {
		fmt.Printf("set file name option as  %s .  will output as %s.%s .\n", output, output, format)
		tempfilename = output + "." + format
	}

	command := exec.Command("dot", "-T"+format, "-o"+tempfilename)
	command.Stderr = os.Stderr

	stdin, err := command.StdinPipe()
	if err != nil {
		return err
	}

	err = command.Start()
	if err != nil {
		return fmt.Errorf("unable to execute dot: %s (is graphviz package installed?)", err)
	}

	_, err = io.Copy(stdin, buf)
	if err != nil {
		return err
	}

	err = stdin.Close()
	if err != nil {
		return err
	}

	err = command.Wait()
	if err != nil {
		return err
	}

	fmt.Printf("Rendered to %s file: %s, trying to open it...\n", format, tempfilename)

	_ = exec.Command("open", tempfilename).Run()

	return err
}

func makeCmdGraph() *commander.Command {
	cmd := &commander.Command{
		Run:       aptlyGraph,
		UsageLine: "graph",
		Short:     "render graph of relationships",
		Long: `
Command graph displays relationship between mirrors, local repositories,
snapshots and published repositories using graphviz package to render
graph as an image.

Example:

  $ aptly graph
`,
	}

	cmd.Flag.String("format", "png", "render graph to specified format (png, svg, pdf, etc.)")
	cmd.Flag.String("output", "", "specically output filename , default is output /tmp/aptlyxxxx.png")

	return cmd
}
<commit_msg>Update custom output filename generation. #242<commit_after>package cmd

import (
	"bytes"
	"fmt"
	"github.com/smira/aptly/deb"
	"github.com/smira/aptly/utils"
	"github.com/smira/commander"
	"io"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
)

func aptlyGraph(cmd *commander.Command, args []string) error {
	var err error

	if len(args) != 0 {
		cmd.Usage()
		return commander.ErrCommandError
	}

	fmt.Printf("Generating graph...\n")
	graph, err := deb.BuildGraph(context.CollectionFactory())
	if err != nil {
		return err
	}

	buf := bytes.NewBufferString(graph.String())

	tempfile, err := ioutil.TempFile("", "aptly-graph")
	if err != nil {
		return err
	}
	tempfile.Close()
	os.Remove(tempfile.Name())

	format := context.Flags().Lookup("format").Value.String()
	output := context.Flags().Lookup("output").Value.String()

	if filepath.Ext(output) != "" {
		format = filepath.Ext(output)[1:]
	}

	tempfilename := tempfile.Name() + "." + format

	command := exec.Command("dot", "-T"+format, "-o"+tempfilename)
	command.Stderr = os.Stderr

	stdin, err := command.StdinPipe()
	if err != nil {
		return err
	}

	err = command.Start()
	if err != nil {
		return fmt.Errorf("unable to execute dot: %s (is graphviz package installed?)", err)
	}

	_, err = io.Copy(stdin, buf)
	if err != nil {
		return err
	}

	err = stdin.Close()
	if err != nil {
		return err
	}

	err = command.Wait()
	if err != nil {
		return err
	}

	if output != "" {
		err = utils.CopyFile(tempfilename, output)
		if err != nil {
			return fmt.Errorf("unable to copy %s -> %s: %s", tempfilename, output, err)
		}
		_ = os.Remove(tempfilename)

		fmt.Printf("Output saved to %s\n", output)
	} else {
		fmt.Printf("Rendered to %s file: %s, trying to open it...\n", format, tempfilename)

		_ = exec.Command("open", tempfilename).Run()
	}

	return err
}

func makeCmdGraph() *commander.Command {
	cmd := &commander.Command{
		Run:       aptlyGraph,
		UsageLine: "graph",
		Short:     "render graph of relationships",
		Long: `
Command graph displays relationship between mirrors, local repositories,
snapshots and published repositories using graphviz package to render
graph as an image.

Example:

  $ aptly graph
`,
	}

	cmd.Flag.String("format", "png", "render graph to specified format (png, svg, pdf, etc.)")
	cmd.Flag.String("output", "", "specify output filename, default is to open result in viewer")

	return cmd
}
<|endoftext|>


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

package cmd

import (
	"fmt"
	"os/user"
	"path/filepath"
	"runtime"

	"github.com/hexya-erp/hexya/hexya/tools/logging"
	"github.com/spf13/cobra"
	"github.com/spf13/viper"
)

var log *logging.Logger

// HexyaCmd is the base 'hexya' command of the commander
var HexyaCmd = &cobra.Command{
	Use:   "hexya",
	Short: "Hexya is an open source modular ERP",
	Long: `Hexya is an open source modular ERP written in Go.
It is designed for high demand business data processing while being easily customizable`,
}

func init() {
	log = logging.GetLogger("init")
	cobra.OnInitialize(initConfig)

	HexyaCmd.PersistentFlags().StringP("config", "c", "", "Alternate configuration file to read. Defaults to $HOME/.hexya/")
	viper.BindPFlag("ConfigFileName", HexyaCmd.PersistentFlags().Lookup("config"))

	HexyaCmd.PersistentFlags().StringSliceP("modules", "m", []string{"github.com/hexya-erp/hexya-base/web"}, "List of module paths to load. Defaults to ['github.com/hexya-erp/hexya-base/web']")
	viper.BindPFlag("Modules", HexyaCmd.PersistentFlags().Lookup("modules"))

	HexyaCmd.PersistentFlags().StringP("log-level", "L", "info", "Log level. Should be one of 'debug', 'info', 'warn', 'error' or 'crit'")
	viper.BindPFlag("LogLevel", HexyaCmd.PersistentFlags().Lookup("log-level"))
	HexyaCmd.PersistentFlags().String("log-file", "", "File to which the log will be written")
	viper.BindPFlag("LogFile", HexyaCmd.PersistentFlags().Lookup("log-file"))
	HexyaCmd.PersistentFlags().BoolP("log-stdout", "o", false, "Enable stdout logging. Use for development or debugging.")
	viper.BindPFlag("LogStdout", HexyaCmd.PersistentFlags().Lookup("log-stdout"))
	HexyaCmd.PersistentFlags().Bool("debug", false, "Enable server debug mode for development")
	viper.BindPFlag("Debug", HexyaCmd.PersistentFlags().Lookup("debug"))

	HexyaCmd.PersistentFlags().String("data-dir", "", "Path to the directory where Hexya should store its data")
	viper.BindPFlag("DataDir", HexyaCmd.PersistentFlags().Lookup("data-dir"))

	HexyaCmd.PersistentFlags().String("db-driver", "postgres", "Database driver to use")
	viper.BindPFlag("DB.Driver", HexyaCmd.PersistentFlags().Lookup("db-driver"))
	HexyaCmd.PersistentFlags().String("db-host", "/var/run/postgresql",
		"The database host to connect to. Values that start with / are for unix domain sockets directory")
	viper.BindPFlag("DB.Host", HexyaCmd.PersistentFlags().Lookup("db-host"))
	HexyaCmd.PersistentFlags().String("db-port", "5432", "Database port. Value is ignored if db-host is not set")
	viper.BindPFlag("DB.Port", HexyaCmd.PersistentFlags().Lookup("db-port"))
	HexyaCmd.PersistentFlags().String("db-user", "", "Database user. Defaults to current user")
	viper.BindPFlag("DB.User", HexyaCmd.PersistentFlags().Lookup("db-user"))
	HexyaCmd.PersistentFlags().String("db-password", "", "Database password. Leave empty when connecting through socket")
	viper.BindPFlag("DB.Password", HexyaCmd.PersistentFlags().Lookup("db-password"))
	HexyaCmd.PersistentFlags().String("db-name", "hexya", "Database name")
	viper.BindPFlag("DB.Name", HexyaCmd.PersistentFlags().Lookup("db-name"))
}

func initConfig() {
	cfgFile := viper.GetString("ConfigFileName")
	if runtime.GOOS != "windows" {
		viper.AddConfigPath("/etc/hexya")
	}

	osUser, err := user.Current()
	if err != nil {
		panic(fmt.Errorf("unable to retrieve current user. Error: %s", err))
	}
	defaultHexyaDir := filepath.Join(osUser.HomeDir, ".hexya")
	viper.SetDefault("DataDir", defaultHexyaDir)
	viper.AddConfigPath(defaultHexyaDir)
	viper.AddConfigPath(".")

	viper.SetConfigName("hexya")

	if cfgFile != "" {
		viper.SetConfigFile(cfgFile)
	}

	err = viper.ReadInConfig()
	if err != nil {
		fmt.Println(err)
	}
}
<commit_msg>Added env vars configuration<commit_after>// Copyright 2017 NDP Systèmes. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package cmd

import (
	"fmt"
	"os/user"
	"path/filepath"
	"runtime"

	"github.com/hexya-erp/hexya/hexya/tools/logging"
	"github.com/spf13/cobra"
	"github.com/spf13/viper"
)

var log *logging.Logger

// HexyaCmd is the base 'hexya' command of the commander
var HexyaCmd = &cobra.Command{
	Use:   "hexya",
	Short: "Hexya is an open source modular ERP",
	Long: `Hexya is an open source modular ERP written in Go.
It is designed for high demand business data processing while being easily customizable`,
}

func init() {
	log = logging.GetLogger("init")
	cobra.OnInitialize(initConfig)

	HexyaCmd.PersistentFlags().StringP("config", "c", "", "Alternate configuration file to read. Defaults to $HOME/.hexya/")
	viper.BindPFlag("ConfigFileName", HexyaCmd.PersistentFlags().Lookup("config"))

	HexyaCmd.PersistentFlags().StringSliceP("modules", "m", []string{"github.com/hexya-erp/hexya-base/web"}, "List of module paths to load. Defaults to ['github.com/hexya-erp/hexya-base/web']")
	viper.BindPFlag("Modules", HexyaCmd.PersistentFlags().Lookup("modules"))

	HexyaCmd.PersistentFlags().StringP("log-level", "L", "info", "Log level. Should be one of 'debug', 'info', 'warn', 'error' or 'crit'")
	viper.BindPFlag("LogLevel", HexyaCmd.PersistentFlags().Lookup("log-level"))
	HexyaCmd.PersistentFlags().String("log-file", "", "File to which the log will be written")
	viper.BindPFlag("LogFile", HexyaCmd.PersistentFlags().Lookup("log-file"))
	HexyaCmd.PersistentFlags().BoolP("log-stdout", "o", false, "Enable stdout logging. Use for development or debugging.")
	viper.BindPFlag("LogStdout", HexyaCmd.PersistentFlags().Lookup("log-stdout"))
	HexyaCmd.PersistentFlags().Bool("debug", false, "Enable server debug mode for development")
	viper.BindPFlag("Debug", HexyaCmd.PersistentFlags().Lookup("debug"))

	HexyaCmd.PersistentFlags().String("data-dir", "", "Path to the directory where Hexya should store its data")
	viper.BindPFlag("DataDir", HexyaCmd.PersistentFlags().Lookup("data-dir"))

	HexyaCmd.PersistentFlags().String("db-driver", "postgres", "Database driver to use")
	viper.BindPFlag("DB.Driver", HexyaCmd.PersistentFlags().Lookup("db-driver"))
	HexyaCmd.PersistentFlags().String("db-host", "/var/run/postgresql",
		"The database host to connect to. Values that start with / are for unix domain sockets directory")
	viper.BindPFlag("DB.Host", HexyaCmd.PersistentFlags().Lookup("db-host"))
	HexyaCmd.PersistentFlags().String("db-port", "5432", "Database port. Value is ignored if db-host is not set")
	viper.BindPFlag("DB.Port", HexyaCmd.PersistentFlags().Lookup("db-port"))
	HexyaCmd.PersistentFlags().String("db-user", "", "Database user. Defaults to current user")
	viper.BindPFlag("DB.User", HexyaCmd.PersistentFlags().Lookup("db-user"))
	HexyaCmd.PersistentFlags().String("db-password", "", "Database password. Leave empty when connecting through socket")
	viper.BindPFlag("DB.Password", HexyaCmd.PersistentFlags().Lookup("db-password"))
	HexyaCmd.PersistentFlags().String("db-name", "hexya", "Database name")
	viper.BindPFlag("DB.Name", HexyaCmd.PersistentFlags().Lookup("db-name"))
}

func initConfig() {
	viper.SetEnvPrefix("hexya")
	viper.AutomaticEnv()
	cfgFile := viper.GetString("ConfigFileName")
	if runtime.GOOS != "windows" {
		viper.AddConfigPath("/etc/hexya")
	}

	osUser, err := user.Current()
	if err != nil {
		panic(fmt.Errorf("unable to retrieve current user. Error: %s", err))
	}
	defaultHexyaDir := filepath.Join(osUser.HomeDir, ".hexya")
	viper.SetDefault("DataDir", defaultHexyaDir)
	viper.AddConfigPath(defaultHexyaDir)
	viper.AddConfigPath(".")

	viper.SetConfigName("hexya")

	if cfgFile != "" {
		viper.SetConfigFile(cfgFile)
	}

	err = viper.ReadInConfig()
	if err != nil {
		fmt.Println(err)
	}
}
<|endoftext|>


<commit_before>// Copyright © 2016 Skatteetaten <utvpaas@skatteetaten.no>

package cmd

import (
	"fmt"
	"github.com/skatteetaten/aoc/pkg/openshift"
	"github.com/skatteetaten/aoc/pkg/updatecmd"
	"github.com/spf13/cobra"
	"github.com/spf13/viper"
	"os"
	"strings"
)

var userName string
var tokenFile string
var recreateConfig bool
var useCurrentOcLogin bool
var apiCluster string

// loginCmd represents the login command
var loginCmd = &cobra.Command{
	Use:   "login <Affiliation>",
	Short: "Login to openshift clusters",
	Long:  `This command will log in to all avilable clusters and store the tokens in the .aoc config file `,
	Run: func(cmd *cobra.Command, args []string) {
		if len(args) != 1 {
			fmt.Println("Please specify affiliation to log in to")
			os.Exit(1)
		}
		affiliation := args[0]
		var configLocation = viper.GetString("HOME") + "/.aoc.json"
		if recreateConfig || useCurrentOcLogin {
			err := os.Remove(configLocation)
			if err != nil {
				if !strings.Contains(err.Error(), "no such file or directory") {
					fmt.Println(err.Error())
					os.Exit(1)
				}
			}
		}
		initConfig(useCurrentOcLogin)
		openshift.Login(configLocation, userName, affiliation, apiCluster)
		output, _ := updatecmd.UpdateSelf(args, true, "", false)
		if strings.Contains(output, "New version detected") {
			fmt.Println(output)
		}
	},
}

func init() {
	RootCmd.AddCommand(loginCmd)
	viper.BindEnv("USER")
	viper.BindEnv("HOME")
	loginCmd.Flags().StringVarP(&userName, "username", "u", viper.GetString("USER"), "the username to log in with, standard is $USER")
	loginCmd.Flags().StringVarP(&tokenFile, "tokenfile", "", "", "Read OC token from this file")
	loginCmd.Flags().BoolVarP(&recreateConfig, "recreate-config", "", false, "Removes current cluster config and recreates")
	loginCmd.Flags().BoolVarP(&useCurrentOcLogin, "use-current-oclogin", "", false, "Recreates config based on current OC login")
	loginCmd.Flags().StringVarP(&apiCluster, "apicluster", "a", "", "Set a specific API cluster to use")
}
<commit_msg>Added a do-update flag to aoc login (#11)<commit_after>// Copyright © 2016 Skatteetaten <utvpaas@skatteetaten.no>

package cmd

import (
	"fmt"
	"github.com/skatteetaten/aoc/pkg/openshift"
	"github.com/skatteetaten/aoc/pkg/updatecmd"
	"github.com/spf13/cobra"
	"github.com/spf13/viper"
	"os"
	"strings"
)

var userName string
var tokenFile string
var recreateConfig bool
var useCurrentOcLogin bool
var apiCluster string
var doUpdate bool

// loginCmd represents the login command
var loginCmd = &cobra.Command{
	Use:   "login <Affiliation>",
	Short: "Login to openshift clusters",
	Long:  `This command will log in to all avilable clusters and store the tokens in the .aoc config file `,
	Run: func(cmd *cobra.Command, args []string) {
		if len(args) != 1 {
			fmt.Println("Please specify affiliation to log in to")
			os.Exit(1)
		}
		affiliation := args[0]
		var configLocation = viper.GetString("HOME") + "/.aoc.json"
		if recreateConfig || useCurrentOcLogin {
			err := os.Remove(configLocation)
			if err != nil {
				if !strings.Contains(err.Error(), "no such file or directory") {
					fmt.Println(err.Error())
					os.Exit(1)
				}
			}
		}
		initConfig(useCurrentOcLogin)
		openshift.Login(configLocation, userName, affiliation, apiCluster)
		output, _ := updatecmd.UpdateSelf(args, !doUpdate, "", false)
		if strings.Contains(output, "New version detected") {
			fmt.Println(output)
		}
	},
}

func init() {
	RootCmd.AddCommand(loginCmd)
	viper.BindEnv("USER")
	viper.BindEnv("HOME")
	loginCmd.Flags().StringVarP(&userName, "username", "u", viper.GetString("USER"), "the username to log in with, standard is $USER")
	loginCmd.Flags().StringVarP(&tokenFile, "tokenfile", "", "", "Read OC token from this file")
	loginCmd.Flags().BoolVarP(&recreateConfig, "recreate-config", "", false, "Removes current cluster config and recreates")
	loginCmd.Flags().BoolVarP(&useCurrentOcLogin, "use-current-oclogin", "", false, "Recreates config based on current OC login")
	loginCmd.Flags().StringVarP(&apiCluster, "apicluster", "a", "", "Set a specific API cluster to use")
	loginCmd.Flags().BoolVarP(&doUpdate, "do-update", "", false, "Do an update if available")
}
<|endoftext|>


<commit_before>/*
Copyright © 2020 NAME HERE <EMAIL ADDRESS>

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 cmd

import (
	"bufio"
	"fmt"
	"os"
	"strings"

	"github.com/howeyc/gopass"
	"github.com/ondevice/ondevice/api"
	"github.com/ondevice/ondevice/config"
	"github.com/sirupsen/logrus"
	"github.com/spf13/cobra"
)

// loginCmd represents the login command
var loginCmd = &cobra.Command{
	Use:   "login",
	Short: "Log in to the ondevice.io service",
	Long: `Log in to the ondevice.io service using one of your API keys.

Example:
  $ ondevice login
  User: <enter your user name>
  Auth: <enter your credentials>
`,
	Run: loginRun,
}

func init() {
	rootCmd.AddCommand(loginCmd)
	loginCmd.Flags().String("batch", "", `Run in batch mode, using the given username and reading the authentication key
from stdin, e.g.:
  echo '5h42l5xylznw'|ondevice login --batch=demo`)
	// Here you will define your flags and configuration settings.

	// Cobra supports Persistent Flags which will work for this command
	// and all subcommands, e.g.:
	// loginCmd.PersistentFlags().String("foo", "", "A help for foo")

	// Cobra supports local flags which will only run when this command
	// is called directly, e.g.:
	// loginCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
}

func loginRun(cmd *cobra.Command, args []string) {
	var user, auth string
	var err error

	user = cmd.Flag("batch").Value.String()

	reader := bufio.NewReader(os.Stdin)

	if user != "" {
		// run in batch mode
		if auth, err = reader.ReadString('\n'); err != nil {
			logrus.WithError(err).Fatal("failed to read auth key from stdin")
		}
		auth = strings.TrimSpace(auth)
	} else {
		fmt.Print("Please login using one of your ondevice.io Auth Keys.\n\n")

		fmt.Println("-----")
		fmt.Println("DO NOT use your account password - it won't work.")
		fmt.Println("If you haven't set one up yet, visit https://my.ondevice.io/me/keys")
		fmt.Println("(see https://docs.ondevice.io/basics/auth-keys/ for details)")
		fmt.Print("-----\n\n")

		fmt.Print("User: ")
		user, err = reader.ReadString('\n')
		if err != nil {
			logrus.WithError(err).Fatal("failed to read user name")
		}
		user = strings.TrimSpace(user)

		fmt.Printf("Auth key: ")
		var authBytes []byte
		if authBytes, err = gopass.GetPasswd(); err != nil {
			logrus.WithError(err).Fatal("failed to read auth key")
		}
		auth = string(authBytes)
	}

	info, err := api.GetKeyInfo(api.NewAuth(user, auth))
	if err != nil {
		logrus.WithError(err).Fatal("failed to verify login info")
	}

	if info.Key != "" {
		// the API server wants us to use a different auth key
		// (most likely because the user has used their account password)
		auth = info.Key
	}

	// display any messages the server might have for us
	for _, msg := range info.Messages {
		var parts = strings.SplitN(msg, ":", 2)
		switch parts[0] {
		case "info":
			logrus.Info(parts[1])
		case "warn":
			logrus.Warning(parts[1])
		case "err":
			logrus.Error(parts[1])
		default:
			logrus.Info("Got server message: ", msg)
		}
	}

	// update auth
	if info.IsType("client") {
		logrus.Info("updating client auth")
		if err := config.SetAuth("client", user, string(auth)); err != nil {
			logrus.WithError(err).Fatal("failed to set client auth")
		}
	}
	if info.IsType("device") {
		logrus.Info("updating device auth")
		if err := config.SetAuth("device", user, string(auth)); err != nil {
			logrus.WithError(err).Fatal("failed to set device auth")
		}
	}
}
<commit_msg>ondevice help login: fixed formatting<commit_after>/*
Copyright © 2020 NAME HERE <EMAIL ADDRESS>

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 cmd

import (
	"bufio"
	"fmt"
	"os"
	"strings"

	"github.com/howeyc/gopass"
	"github.com/ondevice/ondevice/api"
	"github.com/ondevice/ondevice/config"
	"github.com/sirupsen/logrus"
	"github.com/spf13/cobra"
)

// loginCmd represents the login command
var loginCmd = &cobra.Command{
	Use:   "login",
	Short: "log in to the ondevice.io service",
	Long:  `log in to the ondevice.io service using one of your API keys.`,
	Example: `  $ ondevice login
  User: <enter your user name>
  Auth: <enter your credentials>`,
	Run: loginRun,
}

func init() {
	rootCmd.AddCommand(loginCmd)
	loginCmd.Flags().String("batch", "", `Run in batch mode, using the given username and reading the authentication key
from stdin, e.g.:
  echo '5h42l5xylznw'|ondevice login --batch=demo`)
	// Here you will define your flags and configuration settings.

	// Cobra supports Persistent Flags which will work for this command
	// and all subcommands, e.g.:
	// loginCmd.PersistentFlags().String("foo", "", "A help for foo")

	// Cobra supports local flags which will only run when this command
	// is called directly, e.g.:
	// loginCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
}

func loginRun(cmd *cobra.Command, args []string) {
	var user, auth string
	var err error

	user = cmd.Flag("batch").Value.String()

	reader := bufio.NewReader(os.Stdin)

	if user != "" {
		// run in batch mode
		if auth, err = reader.ReadString('\n'); err != nil {
			logrus.WithError(err).Fatal("failed to read auth key from stdin")
		}
		auth = strings.TrimSpace(auth)
	} else {
		fmt.Print("Please login using one of your ondevice.io Auth Keys.\n\n")

		fmt.Println("-----")
		fmt.Println("DO NOT use your account password - it won't work.")
		fmt.Println("If you haven't set one up yet, visit https://my.ondevice.io/me/keys")
		fmt.Println("(see https://docs.ondevice.io/basics/auth-keys/ for details)")
		fmt.Print("-----\n\n")

		fmt.Print("User: ")
		user, err = reader.ReadString('\n')
		if err != nil {
			logrus.WithError(err).Fatal("failed to read user name")
		}
		user = strings.TrimSpace(user)

		fmt.Printf("Auth key: ")
		var authBytes []byte
		if authBytes, err = gopass.GetPasswd(); err != nil {
			logrus.WithError(err).Fatal("failed to read auth key")
		}
		auth = string(authBytes)
	}

	info, err := api.GetKeyInfo(api.NewAuth(user, auth))
	if err != nil {
		logrus.WithError(err).Fatal("failed to verify login info")
	}

	if info.Key != "" {
		// the API server wants us to use a different auth key
		// (most likely because the user has used their account password)
		auth = info.Key
	}

	// display any messages the server might have for us
	for _, msg := range info.Messages {
		var parts = strings.SplitN(msg, ":", 2)
		switch parts[0] {
		case "info":
			logrus.Info(parts[1])
		case "warn":
			logrus.Warning(parts[1])
		case "err":
			logrus.Error(parts[1])
		default:
			logrus.Info("Got server message: ", msg)
		}
	}

	// update auth
	if info.IsType("client") {
		logrus.Info("updating client auth")
		if err := config.SetAuth("client", user, string(auth)); err != nil {
			logrus.WithError(err).Fatal("failed to set client auth")
		}
	}
	if info.IsType("device") {
		logrus.Info("updating device auth")
		if err := config.SetAuth("device", user, string(auth)); err != nil {
			logrus.WithError(err).Fatal("failed to set device auth")
		}
	}
}
<|endoftext|>