<commit_before>package sftp

import (
	"bytes"
	"errors"
	"io"
	"os"
	"reflect"
	"testing"

	"github.com/kr/fs"
)

// assert that *Client implements fs.FileSystem
var _ fs.FileSystem = new(Client)

// assert that *File implements io.ReadWriteCloser
var _ io.ReadWriteCloser = new(File)

func TestNormaliseError(t *testing.T) {
	var (
		ok         = &StatusError{Code: sshFxOk}
		eof        = &StatusError{Code: sshFxEOF}
		fail       = &StatusError{Code: sshFxFailure}
		noSuchFile = &StatusError{Code: sshFxNoSuchFile}
		foo        = errors.New("foo")
	)

	var tests = []struct {
		desc string
		err  error
		want error
	}{
		{
			desc: "nil error",
		},
		{
			desc: "not *StatusError",
			err:  foo,
			want: foo,
		},
		{
			desc: "*StatusError with ssh_FX_EOF",
			err:  eof,
			want: io.EOF,
		},
		{
			desc: "*StatusError with ssh_FX_NO_SUCH_FILE",
			err:  noSuchFile,
			want: os.ErrNotExist,
		},
		{
			desc: "*StatusError with ssh_FX_OK",
			err:  ok,
		},
		{
			desc: "*StatusError with ssh_FX_FAILURE",
			err:  fail,
			want: fail,
		},
	}

	for _, tt := range tests {
		got := normaliseError(tt.err)
		if got != tt.want {
			t.Errorf("normaliseError(%#v), test %q\n- want: %#v\n-  got: %#v",
				tt.err, tt.desc, tt.want, got)
		}
	}
}

var flagsTests = []struct {
	flags int
	want  uint32
}{
	{os.O_RDONLY, sshFxfRead},
	{os.O_WRONLY, sshFxfWrite},
	{os.O_RDWR, sshFxfRead | sshFxfWrite},
	{os.O_RDWR | os.O_CREATE | os.O_TRUNC, sshFxfRead | sshFxfWrite | sshFxfCreat | sshFxfTrunc},
	{os.O_WRONLY | os.O_APPEND, sshFxfWrite | sshFxfAppend},
}

func TestFlags(t *testing.T) {
	for i, tt := range flagsTests {
		got := flags(tt.flags)
		if got != tt.want {
			t.Errorf("test %v: flags(%x): want: %x, got: %x", i, tt.flags, tt.want, got)
		}
	}
}

func TestUnmarshalStatus(t *testing.T) {
	requestID := uint32(1)

	id := marshalUint32([]byte{}, requestID)
	idCode := marshalUint32(id, sshFxFailure)
	idCodeMsg := marshalString(idCode, "err msg")
	idCodeMsgLang := marshalString(idCodeMsg, "lang tag")

	var tests = []struct {
		desc   string
		reqID  uint32
		status []byte
		want   error
	}{
		{
			desc:   "well-formed status",
			reqID:  1,
			status: idCodeMsgLang,
			want: &StatusError{
				Code: sshFxFailure,
				msg:  "err msg",
				lang: "lang tag",
			},
		},
		{
			desc:   "missing error message and language tag",
			reqID:  1,
			status: idCode,
			want: &StatusError{
				Code: sshFxFailure,
			},
		},
		{
			desc:   "missing language tag",
			reqID:  1,
			status: idCodeMsg,
			want: &StatusError{
				Code: sshFxFailure,
				msg:  "err msg",
			},
		},
		{
			desc:   "request identifier mismatch",
			reqID:  2,
			status: idCodeMsgLang,
			want:   &unexpectedIDErr{2, requestID},
		},
	}

	for _, tt := range tests {
		got := unmarshalStatus(tt.reqID, tt.status)
		if !reflect.DeepEqual(got, tt.want) {
			t.Errorf("unmarshalStatus(%v, %v), test %q\n- want: %#v\n-  got: %#v",
				requestID, tt.status, tt.desc, tt.want, got)
		}
	}
}

type packetSizeTest struct {
	size  int
	valid bool
}

var maxPacketCheckedTests = []packetSizeTest{
	{size: 0, valid: false},
	{size: 1, valid: true},
	{size: 32768, valid: true},
	{size: 32769, valid: false},
}

var maxPacketUncheckedTests = []packetSizeTest{
	{size: 0, valid: false},
	{size: 1, valid: true},
	{size: 32768, valid: true},
	{size: 32769, valid: true},
}

func TestMaxPacketChecked(t *testing.T) {
	for _, tt := range maxPacketCheckedTests {
		testMaxPacketOption(t, MaxPacketChecked(tt.size), tt)
	}
}

func TestMaxPacketUnchecked(t *testing.T) {
	for _, tt := range maxPacketUncheckedTests {
		testMaxPacketOption(t, MaxPacketUnchecked(tt.size), tt)
	}
}

func TestMaxPacket(t *testing.T) {
	for _, tt := range maxPacketCheckedTests {
		testMaxPacketOption(t, MaxPacket(tt.size), tt)
	}
}

func testMaxPacketOption(t *testing.T, o ClientOption, tt packetSizeTest) {
	var c Client

	err := o(&c)
	if (err == nil) != tt.valid {
		t.Errorf("MaxPacketChecked(%v)\n- want: %v\n- got: %v", tt.size, tt.valid, err == nil)
	}
	if c.maxPacket != tt.size && tt.valid {
		t.Errorf("MaxPacketChecked(%v)\n- want: %v\n- got: %v", tt.size, tt.size, c.maxPacket)
	}
}

func testFstatOption(t *testing.T, o ClientOption, value bool) {
	var c Client

	err := o(&c)
	if err == nil && c.useFstat != value {
		t.Errorf("UseFStat(%v)\n- want: %v\n- got: %v", value, value, c.useFstat)
	}
}

func TestUseFstatChecked(t *testing.T) {
	testFstatOption(t, UseFstat(true), true)
	testFstatOption(t, UseFstat(false), false)
}

type sink struct{}

func (*sink) Close() error                { return nil }
func (*sink) Write(p []byte) (int, error) { return len(p), nil }

func TestClientZeroLengthPacket(t *testing.T) {
	// Packet length zero (never valid). This used to crash the client.
	packet := []byte{0, 0, 0, 0}

	r := bytes.NewReader(packet)
	c, err := NewClientPipe(r, &sink{})
	if err == nil {
		t.Error("expected an error, got nil")
	}
	if c != nil {
		c.Close()
	}
}
<commit_msg>client: add a test case for init packet too short<commit_after>package sftp

import (
	"bytes"
	"errors"
	"io"
	"os"
	"reflect"
	"testing"

	"github.com/kr/fs"
)

// assert that *Client implements fs.FileSystem
var _ fs.FileSystem = new(Client)

// assert that *File implements io.ReadWriteCloser
var _ io.ReadWriteCloser = new(File)

func TestNormaliseError(t *testing.T) {
	var (
		ok         = &StatusError{Code: sshFxOk}
		eof        = &StatusError{Code: sshFxEOF}
		fail       = &StatusError{Code: sshFxFailure}
		noSuchFile = &StatusError{Code: sshFxNoSuchFile}
		foo        = errors.New("foo")
	)

	var tests = []struct {
		desc string
		err  error
		want error
	}{
		{
			desc: "nil error",
		},
		{
			desc: "not *StatusError",
			err:  foo,
			want: foo,
		},
		{
			desc: "*StatusError with ssh_FX_EOF",
			err:  eof,
			want: io.EOF,
		},
		{
			desc: "*StatusError with ssh_FX_NO_SUCH_FILE",
			err:  noSuchFile,
			want: os.ErrNotExist,
		},
		{
			desc: "*StatusError with ssh_FX_OK",
			err:  ok,
		},
		{
			desc: "*StatusError with ssh_FX_FAILURE",
			err:  fail,
			want: fail,
		},
	}

	for _, tt := range tests {
		got := normaliseError(tt.err)
		if got != tt.want {
			t.Errorf("normaliseError(%#v), test %q\n- want: %#v\n-  got: %#v",
				tt.err, tt.desc, tt.want, got)
		}
	}
}

var flagsTests = []struct {
	flags int
	want  uint32
}{
	{os.O_RDONLY, sshFxfRead},
	{os.O_WRONLY, sshFxfWrite},
	{os.O_RDWR, sshFxfRead | sshFxfWrite},
	{os.O_RDWR | os.O_CREATE | os.O_TRUNC, sshFxfRead | sshFxfWrite | sshFxfCreat | sshFxfTrunc},
	{os.O_WRONLY | os.O_APPEND, sshFxfWrite | sshFxfAppend},
}

func TestFlags(t *testing.T) {
	for i, tt := range flagsTests {
		got := flags(tt.flags)
		if got != tt.want {
			t.Errorf("test %v: flags(%x): want: %x, got: %x", i, tt.flags, tt.want, got)
		}
	}
}

func TestUnmarshalStatus(t *testing.T) {
	requestID := uint32(1)

	id := marshalUint32([]byte{}, requestID)
	idCode := marshalUint32(id, sshFxFailure)
	idCodeMsg := marshalString(idCode, "err msg")
	idCodeMsgLang := marshalString(idCodeMsg, "lang tag")

	var tests = []struct {
		desc   string
		reqID  uint32
		status []byte
		want   error
	}{
		{
			desc:   "well-formed status",
			reqID:  1,
			status: idCodeMsgLang,
			want: &StatusError{
				Code: sshFxFailure,
				msg:  "err msg",
				lang: "lang tag",
			},
		},
		{
			desc:   "missing error message and language tag",
			reqID:  1,
			status: idCode,
			want: &StatusError{
				Code: sshFxFailure,
			},
		},
		{
			desc:   "missing language tag",
			reqID:  1,
			status: idCodeMsg,
			want: &StatusError{
				Code: sshFxFailure,
				msg:  "err msg",
			},
		},
		{
			desc:   "request identifier mismatch",
			reqID:  2,
			status: idCodeMsgLang,
			want:   &unexpectedIDErr{2, requestID},
		},
	}

	for _, tt := range tests {
		got := unmarshalStatus(tt.reqID, tt.status)
		if !reflect.DeepEqual(got, tt.want) {
			t.Errorf("unmarshalStatus(%v, %v), test %q\n- want: %#v\n-  got: %#v",
				requestID, tt.status, tt.desc, tt.want, got)
		}
	}
}

type packetSizeTest struct {
	size  int
	valid bool
}

var maxPacketCheckedTests = []packetSizeTest{
	{size: 0, valid: false},
	{size: 1, valid: true},
	{size: 32768, valid: true},
	{size: 32769, valid: false},
}

var maxPacketUncheckedTests = []packetSizeTest{
	{size: 0, valid: false},
	{size: 1, valid: true},
	{size: 32768, valid: true},
	{size: 32769, valid: true},
}

func TestMaxPacketChecked(t *testing.T) {
	for _, tt := range maxPacketCheckedTests {
		testMaxPacketOption(t, MaxPacketChecked(tt.size), tt)
	}
}

func TestMaxPacketUnchecked(t *testing.T) {
	for _, tt := range maxPacketUncheckedTests {
		testMaxPacketOption(t, MaxPacketUnchecked(tt.size), tt)
	}
}

func TestMaxPacket(t *testing.T) {
	for _, tt := range maxPacketCheckedTests {
		testMaxPacketOption(t, MaxPacket(tt.size), tt)
	}
}

func testMaxPacketOption(t *testing.T, o ClientOption, tt packetSizeTest) {
	var c Client

	err := o(&c)
	if (err == nil) != tt.valid {
		t.Errorf("MaxPacketChecked(%v)\n- want: %v\n- got: %v", tt.size, tt.valid, err == nil)
	}
	if c.maxPacket != tt.size && tt.valid {
		t.Errorf("MaxPacketChecked(%v)\n- want: %v\n- got: %v", tt.size, tt.size, c.maxPacket)
	}
}

func testFstatOption(t *testing.T, o ClientOption, value bool) {
	var c Client

	err := o(&c)
	if err == nil && c.useFstat != value {
		t.Errorf("UseFStat(%v)\n- want: %v\n- got: %v", value, value, c.useFstat)
	}
}

func TestUseFstatChecked(t *testing.T) {
	testFstatOption(t, UseFstat(true), true)
	testFstatOption(t, UseFstat(false), false)
}

type sink struct{}

func (*sink) Close() error                { return nil }
func (*sink) Write(p []byte) (int, error) { return len(p), nil }

func TestClientZeroLengthPacket(t *testing.T) {
	// Packet length zero (never valid). This used to crash the client.
	packet := []byte{0, 0, 0, 0}

	r := bytes.NewReader(packet)
	c, err := NewClientPipe(r, &sink{})
	if err == nil {
		t.Error("expected an error, got nil")
	}
	if c != nil {
		c.Close()
	}
}

func TestClientShortPacket(t *testing.T) {
	// init packet too short.
	packet := []byte{0, 0, 0, 1, 2}

	r := bytes.NewReader(packet)
	_, err := NewClientPipe(r, &sink{})
	if !errors.Is(err, errShortPacket) {
		t.Fatalf("expected error: %v, got: %v", errShortPacket, err)
	}
}
<|endoftext|>


<commit_before>package paranoidhttp

import "testing"
import "net"

func TestIsBadHost(t *testing.T) {
	badHosts := []string{
		"localhost",
		"host has space",
	}

	for _, h := range badHosts {
		if !isBadHost(h) {
			t.Errorf("%s should be bad", h)
		}
	}

	notBadHosts := []string{
		"www.hatena.ne.jp",
		"www.google.com",
		"xn--t8jx73hngb.jp",
	}

	for _, h := range notBadHosts {
		if isBadHost(h) {
			t.Errorf("%s should not be bad", h)
		}
	}
}

func TestIsBadIPv4(t *testing.T) {
	badIPs := []string{
		"0.0.0.0",                      // Unspecified
		"127.0.0.0", "127.255.255.255", // Loopback
		"10.0.0.0", "10.255.255.255", // Private A
		"172.16.0.0", "172.31.255.255", // Private B
		"192.168.0.0", "192.168.255.255", // Private C
		"192.0.2.0", "192.0.2.255", // Test-Net
		"192.88.99.0", "192.88.99.255", // 6to4 relay
		"224.0.0.0", "239.255.255.255", // Multicast
		"169.254.0.0", "169.254.255.255", // Link local
	}

	for _, ip := range badIPs {
		if !isBadIPv4(net.ParseIP(ip)) {
			t.Errorf("%s should be bad", ip)
		}
	}

	notBadIPs := []string{
		"0.0.0.1", "8.8.8.8",
		"126.255.255.255", "128.0.0.0",
		"9.255.255.255", "11.0.0.0",
		"172.15.255.255", "172.32.0.0",
		"192.167.255.255", "192.169.0.0",
		"192.88.98.255", "192.88.100.0",
		"223.255.255.255", "240.0.0.0",
		"169.253.255.255", "169.255.0.0",
	}

	for _, ip := range notBadIPs {
		if isBadIPv4(net.ParseIP(ip)) {
			t.Errorf("%s should not be bad", ip)
		}
	}
}
<commit_msg>add test for request<commit_after>package paranoidhttp

import "testing"
import "net"

func TestRequest(t *testing.T) {
	resp, err := DefaultClient.Get("http://www.example.org")
	if err != nil && resp.StatusCode == 200 {
		t.Error("The request with an ordinal url should be successful")
	}

	resp, err = DefaultClient.Get("http://localhost")
	if err == nil {
		t.Errorf("The request for localhost should be fail")
	}
}

func TestIsBadHost(t *testing.T) {
	badHosts := []string{
		"localhost",
		"host has space",
	}

	for _, h := range badHosts {
		if !isBadHost(h) {
			t.Errorf("%s should be bad", h)
		}
	}

	notBadHosts := []string{
		"www.hatena.ne.jp",
		"www.google.com",
		"xn--t8jx73hngb.jp",
	}

	for _, h := range notBadHosts {
		if isBadHost(h) {
			t.Errorf("%s should not be bad", h)
		}
	}
}

func TestIsBadIPv4(t *testing.T) {
	badIPs := []string{
		"0.0.0.0",                      // Unspecified
		"127.0.0.0", "127.255.255.255", // Loopback
		"10.0.0.0", "10.255.255.255", // Private A
		"172.16.0.0", "172.31.255.255", // Private B
		"192.168.0.0", "192.168.255.255", // Private C
		"192.0.2.0", "192.0.2.255", // Test-Net
		"192.88.99.0", "192.88.99.255", // 6to4 relay
		"224.0.0.0", "239.255.255.255", // Multicast
		"169.254.0.0", "169.254.255.255", // Link local
	}

	for _, ip := range badIPs {
		if !isBadIPv4(net.ParseIP(ip)) {
			t.Errorf("%s should be bad", ip)
		}
	}

	notBadIPs := []string{
		"0.0.0.1", "8.8.8.8",
		"126.255.255.255", "128.0.0.0",
		"9.255.255.255", "11.0.0.0",
		"172.15.255.255", "172.32.0.0",
		"192.167.255.255", "192.169.0.0",
		"192.88.98.255", "192.88.100.0",
		"223.255.255.255", "240.0.0.0",
		"169.253.255.255", "169.255.0.0",
	}

	for _, ip := range notBadIPs {
		if isBadIPv4(net.ParseIP(ip)) {
			t.Errorf("%s should not be bad", ip)
		}
	}
}
<|endoftext|>


<commit_before>package dockertest

import (
	"context"
	"fmt"
	"os"
	"strings"
	"time"

	. "gopkg.in/check.v1"
)

type ClientTest struct{}

var _ = Suite(&ClientTest{})

func (s *ClientTest) TestNewClient(c *C) {
	dc, err := NewClient(context.Background())
	defer dc.docker.Close() // nolint: errcheck
	c.Assert(err, IsNil)

	dockerhost := os.Getenv("DOCKER_HOST")
	if dockerhost != "" {
		defer os.Setenv("DOCKER_HOST", dockerhost) // nolint: errcheck
	} else {
		defer os.Unsetenv("DOCKER_HOST") // nolint: errcheck
	}

	c.Assert(os.Setenv("DOCKER_HOST", "/////"), IsNil)
	_, err = NewClient(context.Background())
	c.Assert(err, ErrorMatches, "unable to parse docker host `/////`")
}

func (s *ClientTest) TestRunAndRemoveContainer(c *C) {
	dc, err := NewClient(context.Background())
	defer dc.docker.Close() // nolint: errcheck
	c.Assert(err, IsNil)
	input := NewClientInput(testImage)

	info, err := dc.RunContainer(input)
	c.Assert(err, IsNil)
	c.Assert(info.Refresh(), IsNil)
	c.Assert(dc.RemoveContainer(info.Data.ID), IsNil)
}

func (s *ClientTest) TestRunContainerAttemptsToRetrieveImage(c *C) {
	dc, err := NewClient(context.Background())
	c.Assert(err, IsNil)

	// Some random image so it will force the client to try to pull the
	// image down.
	input := NewClientInput("abcdefgzyn")
	_, err = dc.RunContainer(input)
	c.Assert(err, NotNil)
	c.Assert(strings.Contains(err.Error(), "does not exist"), Equals, true)
}

func (s *ClientTest) TestRemoveContainer(c *C) {
	dc, err := NewClient(context.Background())
	defer dc.docker.Close() // nolint: errcheck
	c.Assert(err, IsNil)
	input := NewClientInput(testImage)
	info, err := dc.RunContainer(input)
	c.Assert(err, IsNil)
	c.Assert(dc.RemoveContainer(info.Data.ID), IsNil)
	c.Assert(dc.RemoveContainer(info.Data.ID), IsNil)
}

func (s *ClientTest) TestListContainers(c *C) {
	dc, err := NewClient(context.Background())
	c.Assert(err, IsNil)
	defer dc.docker.Close() // nolint: errcheck

	label := fmt.Sprintf("%d", time.Now().Nanosecond())
	infos := map[string]*ContainerInfo{}
	for i := 0; i < 4; i++ {
		input := NewClientInput(testImage)
		input.SetLabel("time", label)
		info, err := dc.RunContainer(input)
		c.Assert(err, IsNil)
		infos[info.Data.ID] = info
	}

	input := NewClientInput(testImage)
	input.SetLabel("time", label)

	containers, err := dc.ListContainers(input)
	c.Assert(err, IsNil)
	for _, entry := range containers {
		_, ok := infos[entry.Data.ID]
		c.Assert(ok, Equals, true)
	}

	for key := range infos {
		c.Assert(dc.RemoveContainer(key), IsNil)
	}
}

func (s *ClientTest) TestService(c *C) {
	dc, err := NewClient(context.Background())
	c.Assert(err, IsNil)
	defer dc.docker.Close() // nolint: errcheck
	input := NewClientInput(testImage)
	svc := dc.Service(input)
	c.Assert(svc.Input, DeepEquals, input)
}
<commit_msg>simplifying tests<commit_after>package dockertest

import (
	"context"
	"fmt"
	"os"
	"strings"
	"time"

	. "gopkg.in/check.v1"
)

type ClientTest struct {
	cleanups []func() error
}

var _ = Suite(&ClientTest{})

func (s *ClientTest) TearDownSuite(c *C) {
	for _, function := range s.cleanups {
		c.Assert(function(), IsNil)
	}
}

func (s *ClientTest) addCleanup(f func() error) {
	s.cleanups = append(s.cleanups, f)
}

func (s *ClientTest) newClient(c *C) *DockerClient {
	ctx, cancel := context.WithTimeout(context.Background(), time.Minute*1)
	s.addCleanup(func() error {
		cancel()
		return nil
	})

	dc, err := NewClient(ctx)
	s.addCleanup(dc.docker.Close)
	c.Assert(err, IsNil)
	return dc
}

func (s *ClientTest) TestNewClient(c *C) {
	dc := s.newClient(c)
	dc, err := NewClient(context.Background())
	s.addCleanup(dc.docker.Close)
	c.Assert(err, IsNil)

	dockerhost := os.Getenv("DOCKER_HOST")
	if dockerhost != "" {
		defer os.Setenv("DOCKER_HOST", dockerhost) // nolint: errcheck
	} else {
		defer os.Unsetenv("DOCKER_HOST") // nolint: errcheck
	}

	c.Assert(os.Setenv("DOCKER_HOST", "/////"), IsNil)
	_, err = NewClient(context.Background())
	c.Assert(err, ErrorMatches, "unable to parse docker host `/////`")
}

func (s *ClientTest) TestRunAndRemoveContainer(c *C) {
	dc := s.newClient(c)
	input := NewClientInput(testImage)

	info, err := dc.RunContainer(input)
	c.Assert(err, IsNil)
	c.Assert(info.Refresh(), IsNil)
	c.Assert(dc.RemoveContainer(info.Data.ID), IsNil)
}

func (s *ClientTest) TestRunContainerAttemptsToRetrieveImage(c *C) {
	dc := s.newClient(c)

	// Some random image so it will force the client to try to pull the
	// image down.
	input := NewClientInput("988881adc9fc3655077dc2d4d757d480b5ea0e11")
	_, err := dc.RunContainer(input)
	c.Assert(err, NotNil)
	c.Assert(strings.Contains(err.Error(), "does not exist"), Equals, true)
}

func (s *ClientTest) TestRemoveContainer(c *C) {
	dc := s.newClient(c)
	input := NewClientInput(testImage)
	info, err := dc.RunContainer(input)
	c.Assert(err, IsNil)
	c.Assert(dc.RemoveContainer(info.Data.ID), IsNil)
	c.Assert(dc.RemoveContainer(info.Data.ID), IsNil)
}

func (s *ClientTest) TestListContainers(c *C) {
	dc := s.newClient(c)

	label := fmt.Sprintf("%d", time.Now().Nanosecond())
	infos := map[string]*ContainerInfo{}
	for i := 0; i < 4; i++ {
		input := NewClientInput(testImage)
		input.SetLabel("time", label)
		info, err := dc.RunContainer(input)
		c.Assert(err, IsNil)
		infos[info.Data.ID] = info
	}

	input := NewClientInput(testImage)
	input.SetLabel("time", label)

	containers, err := dc.ListContainers(input)
	c.Assert(err, IsNil)
	for _, entry := range containers {
		_, ok := infos[entry.Data.ID]
		c.Assert(ok, Equals, true)
	}

	for key := range infos {
		c.Assert(dc.RemoveContainer(key), IsNil)
	}
}

func (s *ClientTest) TestService(c *C) {
	dc := s.newClient(c)
	input := NewClientInput(testImage)
	svc := dc.Service(input)
	c.Assert(svc.Input, DeepEquals, input)
}
<|endoftext|>


<commit_before>package main
import (
    "net/rpc"
    "fmt"
    "bufio"
    "os"
)

type Args struct {
  Name string;
  Price float64
}

var in *bufio.Reader

func readFruit () Args {
    var a string
    var b float64
    fmt.Printf("Name: ")
    bytes, _, _ := in.ReadLine()
    a = string(bytes)
    fmt.Printf("Price: ")
    fmt.Scanln(&b)
    return Args{a, b}
}

func readName () Args {
    var a string
    fmt.Printf("Name: ")
    bytes, _, _ := in.ReadLine()
    a = string(bytes)
    fmt.Printf("Price: ")
    return Args{a, 0}
}

func readKg () Args {
    var a string
    var b float64
    fmt.Printf("Name: ")
    bytes, _, _ := in.ReadLine()
    a = string(bytes)
    fmt.Printf("Price: ")
    fmt.Printf("Kg: ")
    fmt.Scanln(&b)
    return Args{a, b}
}

func checkError(st string, err error) {
    if err != nil {
        fmt.Println(st, err)
        os.Exit(1)
    }
}

func main () {
    service := "localhost:1234"
    client, err := rpc.Dial("tcp", service)
    defer client.Close()
    checkError("Dial: ", err)
    in = bufio.NewReader(os.Stdin)
    var op byte
    for {
        fmt.Println("\n MENU")
        fmt.Println("1 - Adicionar Fruta")
        fmt.Println("2 - Calcular Preço")
        fmt.Println("3 - Preço por Quilo")
        fmt.Println("4 - Remover Fruta")
        fmt.Println("5 - Atualizar Preço")
        fmt.Println("6 - Sair")
        fmt.Scanf("%c\n", &op)
        switch op {
        case '1':
                args := readFruit()
                Call := client.Go("Fruit.AddFruit",	args, nil, nil)
                replyerr := <- Call.Done
                checkError("AddFruit: ", replyerr.Error)
                // fmt.Printf("%d * %d = %d\n", args.A, args.B, reply)
                break
            case '2':
                args := readKg()
                var reply float64
                Call := client.Go("Fruit.GetPrice", args, &reply, nil)
                replyerr := <- Call.Done
                checkError("GetPrice: ", replyerr.Error)
                fmt.Printf("R$ %.2f\n", reply)
                break
            case '3':
                args := readName()
                var reply float64
                Call := client.Go("Fruit.GetPriceKg", args, &reply, nil)
                replyerr := <- Call.Done
                checkError("GetPriceKg: ", replyerr.Error)
                fmt.Printf("R$ %.2f\n", reply)
                break
            case '4':
                args := readName()
                Call := client.Go("Fruit.RemoveFruit", args, nil, nil)
                replyerr := <- Call.Done
                checkError("Remove: ", replyerr.Error)
                break
            case '5':
                args := readFruit()
                Call := client.Go("Fruit.UpdatePrice", args, nil, nil)
                replyerr := <- Call.Done
                checkError("Update: ", replyerr.Error)
                break
            case '6':
                os.Exit(0)
        }
    }
    os.Exit(0)
}
<commit_msg>Não sair ao executar erro no cliente, correção no calcula preço<commit_after>package main
import (
    "net/rpc"
    "fmt"
    "bufio"
    "os"
)

type Args struct {
  Name string;
  Price float64
}

var in *bufio.Reader

func readFruit () Args {
    var a string
    var b float64
    fmt.Printf("Name: ")
    bytes, _, _ := in.ReadLine()
    a = string(bytes)
    fmt.Printf("Price: ")
    fmt.Scanln(&b)
    return Args{a, b}
}

func readName () Args {
    var a string
    fmt.Printf("Name: ")
    bytes, _, _ := in.ReadLine()
    a = string(bytes)
    fmt.Printf("Price: ")
    return Args{a, 0}
}

func readKg () Args {
    var a string
    var b float64
    fmt.Printf("Name: ")
    bytes, _, _ := in.ReadLine()
    a = string(bytes)
    fmt.Printf("Kg: ")
    fmt.Scanln(&b)
    return Args{a, b}
}

func checkError(st string, err error) {
    if err != nil {
        fmt.Println(st, err)
    }
}

func main () {
    service := "localhost:1234"
    client, err := rpc.Dial("tcp", service)
    defer client.Close()
    checkError("Dial: ", err)
    in = bufio.NewReader(os.Stdin)
    var op byte
    for {
        fmt.Println("\n MENU")
        fmt.Println("1 - Adicionar Fruta")
        fmt.Println("2 - Calcular Preço")
        fmt.Println("3 - Preço por Quilo")
        fmt.Println("4 - Remover Fruta")
        fmt.Println("5 - Atualizar Preço")
        fmt.Println("6 - Sair")
        fmt.Scanf("%c\n", &op)
        switch op {
        case '1':
                args := readFruit()
                Call := client.Go("Fruit.AddFruit",	args, nil, nil)
                replyerr := <- Call.Done
                checkError("AddFruit: ", replyerr.Error)
                // fmt.Printf("%d * %d = %d\n", args.A, args.B, reply)
                break
            case '2':
                args := readKg()
                var reply float64
                Call := client.Go("Fruit.GetPrice", args, &reply, nil)
                replyerr := <- Call.Done
                checkError("GetPrice: ", replyerr.Error)
                fmt.Printf("R$ %.2f\n", reply)
                break
            case '3':
                args := readName()
                var reply float64
                Call := client.Go("Fruit.GetPriceKg", args, &reply, nil)
                replyerr := <- Call.Done
                checkError("GetPriceKg: ", replyerr.Error)
                fmt.Printf("R$ %.2f\n", reply)
                break
            case '4':
                args := readName()
                Call := client.Go("Fruit.RemoveFruit", args, nil, nil)
                replyerr := <- Call.Done
                checkError("Remove: ", replyerr.Error)
                break
            case '5':
                args := readFruit()
                Call := client.Go("Fruit.UpdatePrice", args, nil, nil)
                replyerr := <- Call.Done
                checkError("Update: ", replyerr.Error)
                break
            case '6':
                os.Exit(0)
        }
    }
    os.Exit(0)
}
<|endoftext|>


<commit_before>package clocky

import (
	"fmt"
	"io"
	"os"
	"regexp"
	"strconv"
	"strings"
	"template"
	"xml"

	"appengine"
	"appengine/memcache"
)

func newParser(b []byte) (p *xml.Parser) {
	// NWS serves XML in ISO-8859-1 for no reason; the data is really ASCII.
	p = xml.NewParser(strings.NewReader(string(b)))
	p.CharsetReader = func(charset string, input io.Reader) (io.Reader, os.Error) {
		return input, nil
	}
	return p
}

func Conditions(w io.Writer, c appengine.Context) {
	item, err := memcache.Get(c, "conditions")
	if err != nil {
		c.Errorf("%s", err)
		return
	}

	data := struct {
		Temp_c      string
		WindChill_c string
		Wind_Mph    string
	}{}
	p := newParser(item.Value)
	if err = p.Unmarshal(&data, nil); err != nil {
		c.Errorf("%s", err)
		return
	}

	io.WriteString(w, `<div class=header>`)
	if len(data.Temp_c) != 0 {
		io.WriteString(w, `<span class=larger>`)
		template.HTMLEscape(w, []byte(data.Temp_c))
		io.WriteString(w, `°</span> `)
	}
	if len(data.WindChill_c) != 0 {
		io.WriteString(w, `wind chill `)
		template.HTMLEscape(w, []byte(data.WindChill_c))
		io.WriteString(w, `°`)
	} else if data.Wind_Mph != "" {
		mph, err := strconv.Atof64(data.Wind_Mph)
		if err == nil {
			if mph == 0 {
				io.WriteString(w, "wind calm")
			} else {
				fmt.Fprintf(w, "wind %d km/h", int(mph*1.609344))
			}
		}
	}
	io.WriteString(w, `</div>`)
}

var (
	nbspRegexp   = regexp.MustCompile(` [0-9]+\.`)
	thinspRegexp = regexp.MustCompile(`[0-9] (am|pm|km/h)`)
)

func Forecast(w io.Writer, c appengine.Context) {
	item, err := memcache.Get(c, "forecast")
	if err != nil {
		c.Errorf("%s", err)
		return
	}

	data := struct {
		Data []struct {
			Type       string `xml:"attr"`
			TimeLayout []struct {
				LayoutKey      string `xml:"layout-key"`
				StartValidTime []struct {
					PeriodName string `xml:"attr"`
				}
			}
			Parameters struct {
				WordedForecast struct {
					TimeLayout string   `xml:"attr"`
					Text       []string `xml:"name>text"`
				}
			}
		}
	}{}
	p := newParser(item.Value)
	if err = p.Unmarshal(&data, nil); err != nil {
		c.Errorf("%s", err)
		return
	}

	io.WriteString(w, `<div class=smaller style="text-align: left">`)
	for _, d := range data.Data {
		if d.Type != "forecast" {
			continue
		}
		var periods []string
		for _, tl := range d.TimeLayout {
			if tl.LayoutKey != d.Parameters.WordedForecast.TimeLayout {
				continue
			}
			for _, svt := range tl.StartValidTime {
				pn := svt.PeriodName
				pn = strings.Replace(pn, " Morning", " morning", -1)
				pn = strings.Replace(pn, " Afternoon", " afternoon", -1)
				pn = strings.Replace(pn, " Night", " night", -1)
				periods = append(periods, pn)
			}
		}
		texts := d.Parameters.WordedForecast.Text
		if len(texts) != len(periods) {
			c.Errorf("weather: len(texts) = %d, len(periods) = %d",
				len(texts), len(periods))
			continue
		}
		if len(texts) > 3 {
			texts = texts[:3]
		}
		for i, text := range texts {
			io.WriteString(w, `<div style="margin-bottom: 8px"><span class=header>`)
			template.HTMLEscape(w, []byte(periods[i]))
			io.WriteString(w, `:</span> `)

			spaceSubs := make(map[int]string)
			matches := nbspRegexp.FindAllStringIndex(text, -1)
			if len(matches) > 0 {
				for i := 0; i < len(matches[0]); i += 2 {
					spaceSubs[matches[0][i]] = " "
				}
			}
			matches = thinspRegexp.FindAllStringIndex(text, -1)
			if len(matches) > 0 {
				for i := 0; i < len(matches[0]); i += 2 {
					spaceSubs[matches[0][i]+1] = `<span style="white-space: nowrap"> </span>`
				}
			}
			for i, ch := range text {
				sub, ok := spaceSubs[i]
				if ok {
					io.WriteString(w, sub)
				} else {
					io.WriteString(w, string(ch))
				}
			}

			io.WriteString(w, `</div>`)
		}
	}
	io.WriteString(w, `</div>`)
}
<commit_msg>Display four forecasts.<commit_after>package clocky

import (
	"fmt"
	"io"
	"os"
	"regexp"
	"strconv"
	"strings"
	"template"
	"xml"

	"appengine"
	"appengine/memcache"
)

func newParser(b []byte) (p *xml.Parser) {
	// NWS serves XML in ISO-8859-1 for no reason; the data is really ASCII.
	p = xml.NewParser(strings.NewReader(string(b)))
	p.CharsetReader = func(charset string, input io.Reader) (io.Reader, os.Error) {
		return input, nil
	}
	return p
}

func Conditions(w io.Writer, c appengine.Context) {
	item, err := memcache.Get(c, "conditions")
	if err != nil {
		c.Errorf("%s", err)
		return
	}

	data := struct {
		Temp_c      string
		WindChill_c string
		Wind_Mph    string
	}{}
	p := newParser(item.Value)
	if err = p.Unmarshal(&data, nil); err != nil {
		c.Errorf("%s", err)
		return
	}

	io.WriteString(w, `<div class=header>`)
	if len(data.Temp_c) != 0 {
		io.WriteString(w, `<span class=larger>`)
		template.HTMLEscape(w, []byte(data.Temp_c))
		io.WriteString(w, `°</span> `)
	}
	if len(data.WindChill_c) != 0 {
		io.WriteString(w, `wind chill `)
		template.HTMLEscape(w, []byte(data.WindChill_c))
		io.WriteString(w, `°`)
	} else if data.Wind_Mph != "" {
		mph, err := strconv.Atof64(data.Wind_Mph)
		if err == nil {
			if mph == 0 {
				io.WriteString(w, "wind calm")
			} else {
				fmt.Fprintf(w, "wind %d km/h", int(mph*1.609344))
			}
		}
	}
	io.WriteString(w, `</div>`)
}

var (
	nbspRegexp   = regexp.MustCompile(` [0-9]+\.`)
	thinspRegexp = regexp.MustCompile(`[0-9] (am|pm|km/h)`)
)

func Forecast(w io.Writer, c appengine.Context) {
	item, err := memcache.Get(c, "forecast")
	if err != nil {
		c.Errorf("%s", err)
		return
	}

	data := struct {
		Data []struct {
			Type       string `xml:"attr"`
			TimeLayout []struct {
				LayoutKey      string `xml:"layout-key"`
				StartValidTime []struct {
					PeriodName string `xml:"attr"`
				}
			}
			Parameters struct {
				WordedForecast struct {
					TimeLayout string   `xml:"attr"`
					Text       []string `xml:"name>text"`
				}
			}
		}
	}{}
	p := newParser(item.Value)
	if err = p.Unmarshal(&data, nil); err != nil {
		c.Errorf("%s", err)
		return
	}

	io.WriteString(w, `<div class=smaller style="text-align: left">`)
	for _, d := range data.Data {
		if d.Type != "forecast" {
			continue
		}
		var periods []string
		for _, tl := range d.TimeLayout {
			if tl.LayoutKey != d.Parameters.WordedForecast.TimeLayout {
				continue
			}
			for _, svt := range tl.StartValidTime {
				pn := svt.PeriodName
				pn = strings.Replace(pn, " Morning", " morning", -1)
				pn = strings.Replace(pn, " Afternoon", " afternoon", -1)
				pn = strings.Replace(pn, " Night", " night", -1)
				periods = append(periods, pn)
			}
		}
		texts := d.Parameters.WordedForecast.Text
		if len(texts) != len(periods) {
			c.Errorf("weather: len(texts) = %d, len(periods) = %d",
				len(texts), len(periods))
			continue
		}
		if len(texts) > 4 {
			texts = texts[:4]
		}
		for i, text := range texts {
			io.WriteString(w, `<div style="margin-bottom: 8px"><span class=header>`)
			template.HTMLEscape(w, []byte(periods[i]))
			io.WriteString(w, `:</span> `)

			spaceSubs := make(map[int]string)
			matches := nbspRegexp.FindAllStringIndex(text, -1)
			if len(matches) > 0 {
				for i := 0; i < len(matches[0]); i += 2 {
					spaceSubs[matches[0][i]] = " "
				}
			}
			matches = thinspRegexp.FindAllStringIndex(text, -1)
			if len(matches) > 0 {
				for i := 0; i < len(matches[0]); i += 2 {
					spaceSubs[matches[0][i]+1] = `<span style="white-space: nowrap"> </span>`
				}
			}
			for i, ch := range text {
				sub, ok := spaceSubs[i]
				if ok {
					io.WriteString(w, sub)
				} else {
					io.WriteString(w, string(ch))
				}
			}

			io.WriteString(w, `</div>`)
		}
	}
	io.WriteString(w, `</div>`)
}
<|endoftext|>


<commit_before>package cluster

import (
	"errors"
	"sync"
	"time"

	"github.com/flynn/flynn-host/types"
	"github.com/flynn/go-discoverd"
	"github.com/flynn/go-flynn/attempt"
	"github.com/flynn/rpcplus"
)

// ErrNoServers is returned if no host servers are found
var ErrNoServers = errors.New("cluster: no servers found")

// Attempts is the attempt strategy that is used to connect to the leader.
// It must not be modified after the first call to NewClient.
var Attempts = attempt.Strategy{
	Min:   5,
	Total: 5 * time.Second,
	Delay: 200 * time.Millisecond,
}

func NewClient() (*Client, error) {
	return NewClientWithDial(nil, nil)
}

func NewClientWithDial(dial rpcplus.DialFunc, services func(name string) (discoverd.ServiceSet, error)) (*Client, error) {
	if services == nil {
		services = discoverd.NewServiceSet
	}
	ss, err := services("flynn-host")
	if err != nil {
		return nil, err
	}
	client := &Client{dial: dial, service: ss}
	firstErr := make(chan error)
	go client.followLeader(firstErr)
	return client, <-firstErr
}

func (c *Client) followLeader(firstErr chan<- error) {
	for update := range c.service.Leaders() {
		if update == nil {
			if firstErr != nil {
				firstErr <- ErrNoServers
				firstErr = nil
			}
			continue
		}
		c.mtx.Lock()
		if c.c != nil {
			c.c.Close()
		}
		c.leaderID = update.Attrs["id"]
		c.err = Attempts.Run(func() (err error) {
			c.c, err = rpcplus.DialHTTPPath("tcp", update.Addr, rpcplus.DefaultRPCPath, c.dial)
			return
		})
		c.mtx.Unlock()
		if firstErr != nil {
			firstErr <- c.err
			firstErr = nil
		}
	}
	// TODO: reconnect to discoverd here
}

type Client struct {
	service  discoverd.ServiceSet
	leaderID string

	dial rpcplus.DialFunc
	c    RPCClient
	mtx  sync.RWMutex
	err  error
}

func (c *Client) Close() error {
	c.service.Close()
	return c.c.Close()
}

func (c *Client) LeaderID() string {
	c.mtx.RLock()
	defer c.mtx.RUnlock()
	return c.leaderID
}

func (c *Client) ListHosts() (map[string]host.Host, error) {
	c.mtx.RLock()
	if err := c.err; err != nil {
		c.mtx.RUnlock()
		return nil, err
	}
	client := c.c
	c.mtx.RUnlock()

	var state map[string]host.Host
	err := client.Call("Cluster.ListHosts", struct{}{}, &state)
	return state, err
}

func (c *Client) AddJobs(req *host.AddJobsReq) (*host.AddJobsRes, error) {
	c.mtx.RLock()
	if err := c.err; err != nil {
		c.mtx.RUnlock()
		return nil, err
	}
	client := c.c
	c.mtx.RUnlock()

	var res host.AddJobsRes
	err := client.Call("Cluster.AddJobs", req, &res)
	return &res, err
}

func (c *Client) ConnectHost(id string) (Host, error) {
	// TODO: reuse connection if leader id == id
	services := c.service.Select(map[string]string{"id": id})
	if len(services) == 0 {
		return nil, ErrNoServers
	}
	rc, err := rpcplus.DialHTTPPath("tcp", services[0].Addr, rpcplus.DefaultRPCPath, c.dial)
	return newHostClient(c.service, rc, c.dial), err
}

func (c *Client) RPCClient() (RPCClient, error) {
	c.mtx.RLock()
	defer c.mtx.RUnlock()
	return c.c, c.err
}

type RPCClient interface {
	Call(serviceMethod string, args interface{}, reply interface{}) error
	Go(serviceMethod string, args interface{}, reply interface{}, done chan *rpcplus.Call) *rpcplus.Call
	StreamGo(serviceMethod string, args interface{}, replyStream interface{}) *rpcplus.Call
	Close() error
}
<commit_msg>cluster: Clean up if we get an error while starting<commit_after>package cluster

import (
	"errors"
	"sync"
	"time"

	"github.com/flynn/flynn-host/types"
	"github.com/flynn/go-discoverd"
	"github.com/flynn/go-flynn/attempt"
	"github.com/flynn/rpcplus"
)

// ErrNoServers is returned if no host servers are found
var ErrNoServers = errors.New("cluster: no servers found")

// Attempts is the attempt strategy that is used to connect to the leader.
// It must not be modified after the first call to NewClient.
var Attempts = attempt.Strategy{
	Min:   5,
	Total: 5 * time.Second,
	Delay: 200 * time.Millisecond,
}

func NewClient() (*Client, error) {
	return NewClientWithDial(nil, nil)
}

func NewClientWithDial(dial rpcplus.DialFunc, services func(name string) (discoverd.ServiceSet, error)) (*Client, error) {
	if services == nil {
		services = discoverd.NewServiceSet
	}
	ss, err := services("flynn-host")
	if err != nil {
		return nil, err
	}
	client := &Client{dial: dial, service: ss}
	firstErr := make(chan error)
	go client.followLeader(firstErr)
	return client, <-firstErr
}

func (c *Client) followLeader(firstErr chan<- error) {
	for update := range c.service.Leaders() {
		if update == nil {
			if firstErr != nil {
				firstErr <- ErrNoServers
				c.Close()
				return
			}
			continue
		}
		c.mtx.Lock()
		if c.c != nil {
			c.c.Close()
		}
		c.leaderID = update.Attrs["id"]
		c.err = Attempts.Run(func() (err error) {
			c.c, err = rpcplus.DialHTTPPath("tcp", update.Addr, rpcplus.DefaultRPCPath, c.dial)
			return
		})
		c.mtx.Unlock()
		if firstErr != nil {
			firstErr <- c.err
			if c.err != nil {
				c.Close()
				return
			}
			firstErr = nil
		}
	}
	// TODO: reconnect to discoverd here
}

type Client struct {
	service  discoverd.ServiceSet
	leaderID string

	dial rpcplus.DialFunc
	c    RPCClient
	mtx  sync.RWMutex
	err  error
}

func (c *Client) Close() error {
	c.mtx.Lock()
	defer c.mtx.Unlock()
	if c.c != nil {
		c.c.Close()
	}
	return c.service.Close()
}

func (c *Client) LeaderID() string {
	c.mtx.RLock()
	defer c.mtx.RUnlock()
	return c.leaderID
}

func (c *Client) ListHosts() (map[string]host.Host, error) {
	c.mtx.RLock()
	if err := c.err; err != nil {
		c.mtx.RUnlock()
		return nil, err
	}
	client := c.c
	c.mtx.RUnlock()

	var state map[string]host.Host
	err := client.Call("Cluster.ListHosts", struct{}{}, &state)
	return state, err
}

func (c *Client) AddJobs(req *host.AddJobsReq) (*host.AddJobsRes, error) {
	c.mtx.RLock()
	if err := c.err; err != nil {
		c.mtx.RUnlock()
		return nil, err
	}
	client := c.c
	c.mtx.RUnlock()

	var res host.AddJobsRes
	err := client.Call("Cluster.AddJobs", req, &res)
	return &res, err
}

func (c *Client) ConnectHost(id string) (Host, error) {
	// TODO: reuse connection if leader id == id
	services := c.service.Select(map[string]string{"id": id})
	if len(services) == 0 {
		return nil, ErrNoServers
	}
	rc, err := rpcplus.DialHTTPPath("tcp", services[0].Addr, rpcplus.DefaultRPCPath, c.dial)
	return newHostClient(c.service, rc, c.dial), err
}

func (c *Client) RPCClient() (RPCClient, error) {
	c.mtx.RLock()
	defer c.mtx.RUnlock()
	return c.c, c.err
}

type RPCClient interface {
	Call(serviceMethod string, args interface{}, reply interface{}) error
	Go(serviceMethod string, args interface{}, reply interface{}, done chan *rpcplus.Call) *rpcplus.Call
	StreamGo(serviceMethod string, args interface{}, replyStream interface{}) *rpcplus.Call
	Close() error
}
<|endoftext|>


<commit_before>package orchestrators

import (
	"encoding/json"
	"io/ioutil"
	"net"
	"net/http"
	"net/url"
	"sort"
	"strings"
	"time"
	"unicode/utf8"

	"github.com/camptocamp/bivac/handler"
	"github.com/camptocamp/bivac/volume"

	log "github.com/Sirupsen/logrus"
	"github.com/rancher/go-rancher/v2"
	"golang.org/x/net/websocket"
)

// CattleOrchestrator implements a container orchestrator for Cattle
type CattleOrchestrator struct {
	Handler *handler.Bivac
	Client  *client.RancherClient
}

// NewCattleOrchestrator creates a Cattle client
func NewCattleOrchestrator(c *handler.Bivac) (o *CattleOrchestrator) {
	var err error
	o = &CattleOrchestrator{
		Handler: c,
	}

	o.Client, err = client.NewRancherClient(&client.ClientOpts{
		Url:       o.Handler.Config.Cattle.URL,
		AccessKey: o.Handler.Config.Cattle.AccessKey,
		SecretKey: o.Handler.Config.Cattle.SecretKey,
	})
	if err != nil {
		log.Errorf("failed to create a new Rancher client: %s", err)
	}

	return
}

// GetName returns the orchestrator name
func (*CattleOrchestrator) GetName() string {
	return "Cattle"
}

// GetHandler returns the Orchestrator's handler
func (o *CattleOrchestrator) GetHandler() *handler.Bivac {
	return o.Handler
}

// GetVolumes returns the Cattle volumes
func (o *CattleOrchestrator) GetVolumes() (volumes []*volume.Volume, err error) {
	c := o.Handler

	vs, err := o.Client.Volume.List(&client.ListOpts{
		Filters: map[string]interface{}{
			"limit": -2,
			"all":   true,
		},
	})
	if err != nil {
		log.Errorf("failed to list volumes: %s", err)
	}

	var mountpoint string
	for _, v := range vs.Data {
		if len(v.Mounts) < 1 {
			mountpoint = "/data"
		} else {
			mountpoint = v.Mounts[0].Path
		}

		var hostID, hostname string
		var spc *client.StoragePoolCollection
		err := o.rawAPICall("GET", v.Links["storagePools"], &spc)
		if err != nil {
			log.Errorf("failed to retrieve storage pool from volume %s: %s", v.Name, err)
			continue
		}

		if len(spc.Data) == 0 {
			log.Errorf("no storage pool for the volume %s: %s", v.Name, err)
			continue
		}

		if len(spc.Data[0].HostIds) == 0 {
			log.Errorf("no host for the volume %s: %s", v.Name, err)
			continue
		}

		hostID = spc.Data[0].HostIds[0]

		h, err := o.Client.Host.ById(hostID)
		if err != nil {
			log.Errorf("failed to retrieve host from id %s: %s", hostID, err)
			hostname = ""
		} else {
			hostname = h.Hostname
		}

		nv := &volume.Volume{
			Config:     &volume.Config{},
			Mountpoint: mountpoint,
			Name:       v.Name,
			HostBind:   hostID,
			Hostname:   hostname,
		}

		v := volume.NewVolume(nv, c.Config, c.Hostname)
		if b, r, s := o.blacklistedVolume(v); b {
			log.WithFields(log.Fields{
				"volume": v.Name,
				"reason": r,
				"source": s,
			}).Info("Ignoring volume")
			continue
		}
		volumes = append(volumes, v)
	}
	return
}

// LaunchContainer starts a containe using the Cattle orchestrator
func (o *CattleOrchestrator) LaunchContainer(image string, env map[string]string, cmd []string, volumes []*volume.Volume) (state int, stdout string, err error) {
	environment := make(map[string]interface{}, len(env))
	for envKey, envVal := range env {
		environment[envKey] = envVal
	}

	var hostbind string
	if len(volumes) > 0 {
		hostbind = volumes[0].HostBind
	} else {
		hostbind = ""
	}

	cvs := []string{}
	for _, v := range volumes {
		cvs = append(cvs, v.Name+":"+v.Mountpoint)
	}

	container, err := o.Client.Container.Create(&client.Container{
		HostId:      hostbind,
		ImageUuid:   "docker:" + image,
		Command:     cmd,
		Environment: environment,
		RestartPolicy: &client.RestartPolicy{
			MaximumRetryCount: 1,
			Name:              "on-failure",
		},
		DataVolumes: cvs,
	})
	if err != nil {
		log.Errorf("failed to create worker container: %s", err)
	}

	defer o.DeleteWorker(container)

	stopped := false
	terminated := false
	for !terminated {
		container, err := o.Client.Container.ById(container.Id)
		if err != nil {
			log.Errorf("failed to inspect worker: %s", err)
		}

		// This workaround is awful but it's the only way to know if the container failed.
		if container.State == "stopped" {
			if container.StartCount == 1 {
				if stopped == false {
					stopped = true
					time.Sleep(5 * time.Second)
				} else {
					terminated = true
					state = 0
				}
			} else {
				state = 1
				terminated = true
			}
		}
	}

	var hostAccess *client.HostAccess
	err = o.rawAPICall("POST", container.Links["self"]+"/?action=logs", &hostAccess)
	if err != nil {
		log.Errorf("failed to read response from rancher: %s", err)
	}

	origin := o.Handler.Config.Cattle.URL

	u, err := url.Parse(hostAccess.Url)
	if err != nil {
		log.Errorf("failed to parse rancher server url: %s", err)
	}
	q := u.Query()
	q.Set("token", hostAccess.Token)
	u.RawQuery = q.Encode()

	ws, err := websocket.Dial(u.String(), "", origin)
	if err != nil {
		log.Errorf("failed to open websocket with rancher server: %s", err)
	}

	var data = make([]byte, 1024)
	var n int
	if n, err = ws.Read(data); err != nil && err.Error() != "EOF" {
		log.Errorf("failed to retrieve logs: %s", err)
	}
	stdout = string(data[:n])
	log.WithFields(log.Fields{
		"container": container.Id,
		"volumes":   strings.Join(cvs[:], ","),
		"cmd":       strings.Join(cmd[:], " "),
	}).Debug(stdout)
	return
}

// DeleteWorker deletes a worker
func (o *CattleOrchestrator) DeleteWorker(container *client.Container) {
	err := o.Client.Container.Delete(container)
	if err != nil {
		log.Errorf("failed to delete worker: %s", err)
	}
	removed := false
	for !removed {
		container, err := o.Client.Container.ById(container.Id)
		if err != nil {
			log.Errorf("failed to inspect worker: %s", err)
		}
		if container.Removed != "" {
			removed = true
		}
	}
	return
}

// GetMountedVolumes returns mounted volumes
func (o *CattleOrchestrator) GetMountedVolumes() (containers []*volume.MountedVolumes, err error) {
	c, err := o.Client.Container.List(&client.ListOpts{
		Filters: map[string]interface{}{
			"limit": -2,
			"all":   true,
		},
	})

	if err != nil {
		log.Errorf("failed to list containers: %s", err)
	}

	for _, container := range c.Data {
		mv := &volume.MountedVolumes{
			ContainerID: container.Id,
			Volumes:     make(map[string]string),
		}
		for _, mount := range container.Mounts {
			mv.Volumes[mount.VolumeName] = mount.Path
		}
		containers = append(containers, mv)
	}
	return
}

// ContainerExec executes a command in a container
func (o *CattleOrchestrator) ContainerExec(mountedVolumes *volume.MountedVolumes, command []string) (err error) {

	container, err := o.Client.Container.ById(mountedVolumes.ContainerID)
	if err != nil {
		log.Errorf("failed to retrieve container: %s", err)
		return
	}

	hostAccess, err := o.Client.Container.ActionExecute(container, &client.ContainerExec{
		AttachStdin:  false,
		AttachStdout: true,
		Command:      command,
		Tty:          false,
	})
	if err != nil {
		log.Errorf("failed to prepare command execution in container: %s", err)
		return
	}

	origin := o.Handler.Config.Cattle.URL

	u, err := url.Parse(hostAccess.Url)
	if err != nil {
		log.Errorf("failed to parse rancher server url: %s", err)
	}
	q := u.Query()
	q.Set("token", hostAccess.Token)
	u.RawQuery = q.Encode()

	ws, err := websocket.Dial(u.String(), "", origin)
	if err != nil {
		log.Errorf("failed to open websocket with rancher server: %s", err)
	}

	var data = make([]byte, 1024)
	var n int
	if n, err = ws.Read(data); err != nil && err.Error() != "EOF" {
		log.Errorf("failed to retrieve logs: %s", err)
	}
	log.WithFields(log.Fields{
		"container": mountedVolumes.ContainerID,
		"cmd":       strings.Join(command[:], " "),
	}).Debug(string(data[:n]))
	return
}

func (o *CattleOrchestrator) blacklistedVolume(vol *volume.Volume) (bool, string, string) {

	defaultBlacklistedVolumes := []string{
		"duplicity_cache",
		"restic_cache",
		"duplicity-cache",
		"restic-cache",
		"lost+found",
	}

	if utf8.RuneCountInString(vol.Name) == 64 || utf8.RuneCountInString(vol.Name) == 0 {
		return true, "unnamed", ""
	}

	if strings.Contains(vol.Name, "/") {
		return true, "blacklisted", "path"
	}

	list := o.Handler.Config.VolumesBlacklist
	list = append(list, defaultBlacklistedVolumes...)
	sort.Strings(list)
	i := sort.SearchStrings(list, vol.Name)
	if i < len(list) && list[i] == vol.Name {
		return true, "blacklisted", "blacklist config"
	}

	if vol.Config.Ignore {
		return true, "blacklisted", "volume config"
	}

	return false, "", ""
}

func (o *CattleOrchestrator) rawAPICall(method, endpoint string, object interface{}) (err error) {
	// TODO: Use go-rancher.
	// It was impossible to use it, maybe a problem in go-rancher or a lack of documentation.
	clientHTTP := &http.Client{}
	v := url.Values{}
	req, err := http.NewRequest(method, endpoint, strings.NewReader(v.Encode()))
	req.SetBasicAuth(o.Handler.Config.Cattle.AccessKey, o.Handler.Config.Cattle.SecretKey)
	resp, err := clientHTTP.Do(req)
	if err != nil {
		log.Errorf("failed to execute POST request: %s", err)
	}
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		log.Errorf("failed to read response from rancher: %s", err)
	}
	err = json.Unmarshal(body, object)
	if err != nil {
		log.Errorf("failed to unmarshal: %s", err)
	}
	return
}

func detectCattle() bool {
	_, err := net.LookupHost("rancher-metadata")
	if err != nil {
		return false
	}
	return true
}
<commit_msg>Don't declare default volumes to blacklist in Cattle orchestrator (#189)<commit_after>package orchestrators

import (
	"encoding/json"
	"io/ioutil"
	"net"
	"net/http"
	"net/url"
	"sort"
	"strings"
	"time"
	"unicode/utf8"

	"github.com/camptocamp/bivac/handler"
	"github.com/camptocamp/bivac/volume"

	log "github.com/Sirupsen/logrus"
	"github.com/rancher/go-rancher/v2"
	"golang.org/x/net/websocket"
)

// CattleOrchestrator implements a container orchestrator for Cattle
type CattleOrchestrator struct {
	Handler *handler.Bivac
	Client  *client.RancherClient
}

// NewCattleOrchestrator creates a Cattle client
func NewCattleOrchestrator(c *handler.Bivac) (o *CattleOrchestrator) {
	var err error
	o = &CattleOrchestrator{
		Handler: c,
	}

	o.Client, err = client.NewRancherClient(&client.ClientOpts{
		Url:       o.Handler.Config.Cattle.URL,
		AccessKey: o.Handler.Config.Cattle.AccessKey,
		SecretKey: o.Handler.Config.Cattle.SecretKey,
	})
	if err != nil {
		log.Errorf("failed to create a new Rancher client: %s", err)
	}

	return
}

// GetName returns the orchestrator name
func (*CattleOrchestrator) GetName() string {
	return "Cattle"
}

// GetHandler returns the Orchestrator's handler
func (o *CattleOrchestrator) GetHandler() *handler.Bivac {
	return o.Handler
}

// GetVolumes returns the Cattle volumes
func (o *CattleOrchestrator) GetVolumes() (volumes []*volume.Volume, err error) {
	c := o.Handler

	vs, err := o.Client.Volume.List(&client.ListOpts{
		Filters: map[string]interface{}{
			"limit": -2,
			"all":   true,
		},
	})
	if err != nil {
		log.Errorf("failed to list volumes: %s", err)
	}

	var mountpoint string
	for _, v := range vs.Data {
		if len(v.Mounts) < 1 {
			mountpoint = "/data"
		} else {
			mountpoint = v.Mounts[0].Path
		}

		var hostID, hostname string
		var spc *client.StoragePoolCollection
		err := o.rawAPICall("GET", v.Links["storagePools"], &spc)
		if err != nil {
			log.Errorf("failed to retrieve storage pool from volume %s: %s", v.Name, err)
			continue
		}

		if len(spc.Data) == 0 {
			log.Errorf("no storage pool for the volume %s: %s", v.Name, err)
			continue
		}

		if len(spc.Data[0].HostIds) == 0 {
			log.Errorf("no host for the volume %s: %s", v.Name, err)
			continue
		}

		hostID = spc.Data[0].HostIds[0]

		h, err := o.Client.Host.ById(hostID)
		if err != nil {
			log.Errorf("failed to retrieve host from id %s: %s", hostID, err)
			hostname = ""
		} else {
			hostname = h.Hostname
		}

		nv := &volume.Volume{
			Config:     &volume.Config{},
			Mountpoint: mountpoint,
			Name:       v.Name,
			HostBind:   hostID,
			Hostname:   hostname,
		}

		v := volume.NewVolume(nv, c.Config, c.Hostname)
		if b, r, s := o.blacklistedVolume(v); b {
			log.WithFields(log.Fields{
				"volume": v.Name,
				"reason": r,
				"source": s,
			}).Info("Ignoring volume")
			continue
		}
		volumes = append(volumes, v)
	}
	return
}

// LaunchContainer starts a containe using the Cattle orchestrator
func (o *CattleOrchestrator) LaunchContainer(image string, env map[string]string, cmd []string, volumes []*volume.Volume) (state int, stdout string, err error) {
	environment := make(map[string]interface{}, len(env))
	for envKey, envVal := range env {
		environment[envKey] = envVal
	}

	var hostbind string
	if len(volumes) > 0 {
		hostbind = volumes[0].HostBind
	} else {
		hostbind = ""
	}

	cvs := []string{}
	for _, v := range volumes {
		cvs = append(cvs, v.Name+":"+v.Mountpoint)
	}

	container, err := o.Client.Container.Create(&client.Container{
		HostId:      hostbind,
		ImageUuid:   "docker:" + image,
		Command:     cmd,
		Environment: environment,
		RestartPolicy: &client.RestartPolicy{
			MaximumRetryCount: 1,
			Name:              "on-failure",
		},
		DataVolumes: cvs,
	})
	if err != nil {
		log.Errorf("failed to create worker container: %s", err)
	}

	defer o.DeleteWorker(container)

	stopped := false
	terminated := false
	for !terminated {
		container, err := o.Client.Container.ById(container.Id)
		if err != nil {
			log.Errorf("failed to inspect worker: %s", err)
		}

		// This workaround is awful but it's the only way to know if the container failed.
		if container.State == "stopped" {
			if container.StartCount == 1 {
				if stopped == false {
					stopped = true
					time.Sleep(5 * time.Second)
				} else {
					terminated = true
					state = 0
				}
			} else {
				state = 1
				terminated = true
			}
		}
	}

	var hostAccess *client.HostAccess
	err = o.rawAPICall("POST", container.Links["self"]+"/?action=logs", &hostAccess)
	if err != nil {
		log.Errorf("failed to read response from rancher: %s", err)
	}

	origin := o.Handler.Config.Cattle.URL

	u, err := url.Parse(hostAccess.Url)
	if err != nil {
		log.Errorf("failed to parse rancher server url: %s", err)
	}
	q := u.Query()
	q.Set("token", hostAccess.Token)
	u.RawQuery = q.Encode()

	ws, err := websocket.Dial(u.String(), "", origin)
	if err != nil {
		log.Errorf("failed to open websocket with rancher server: %s", err)
	}

	var data = make([]byte, 1024)
	var n int
	if n, err = ws.Read(data); err != nil && err.Error() != "EOF" {
		log.Errorf("failed to retrieve logs: %s", err)
	}
	stdout = string(data[:n])
	log.WithFields(log.Fields{
		"container": container.Id,
		"volumes":   strings.Join(cvs[:], ","),
		"cmd":       strings.Join(cmd[:], " "),
	}).Debug(stdout)
	return
}

// DeleteWorker deletes a worker
func (o *CattleOrchestrator) DeleteWorker(container *client.Container) {
	err := o.Client.Container.Delete(container)
	if err != nil {
		log.Errorf("failed to delete worker: %s", err)
	}
	removed := false
	for !removed {
		container, err := o.Client.Container.ById(container.Id)
		if err != nil {
			log.Errorf("failed to inspect worker: %s", err)
		}
		if container.Removed != "" {
			removed = true
		}
	}
	return
}

// GetMountedVolumes returns mounted volumes
func (o *CattleOrchestrator) GetMountedVolumes() (containers []*volume.MountedVolumes, err error) {
	c, err := o.Client.Container.List(&client.ListOpts{
		Filters: map[string]interface{}{
			"limit": -2,
			"all":   true,
		},
	})

	if err != nil {
		log.Errorf("failed to list containers: %s", err)
	}

	for _, container := range c.Data {
		mv := &volume.MountedVolumes{
			ContainerID: container.Id,
			Volumes:     make(map[string]string),
		}
		for _, mount := range container.Mounts {
			mv.Volumes[mount.VolumeName] = mount.Path
		}
		containers = append(containers, mv)
	}
	return
}

// ContainerExec executes a command in a container
func (o *CattleOrchestrator) ContainerExec(mountedVolumes *volume.MountedVolumes, command []string) (err error) {

	container, err := o.Client.Container.ById(mountedVolumes.ContainerID)
	if err != nil {
		log.Errorf("failed to retrieve container: %s", err)
		return
	}

	hostAccess, err := o.Client.Container.ActionExecute(container, &client.ContainerExec{
		AttachStdin:  false,
		AttachStdout: true,
		Command:      command,
		Tty:          false,
	})
	if err != nil {
		log.Errorf("failed to prepare command execution in container: %s", err)
		return
	}

	origin := o.Handler.Config.Cattle.URL

	u, err := url.Parse(hostAccess.Url)
	if err != nil {
		log.Errorf("failed to parse rancher server url: %s", err)
	}
	q := u.Query()
	q.Set("token", hostAccess.Token)
	u.RawQuery = q.Encode()

	ws, err := websocket.Dial(u.String(), "", origin)
	if err != nil {
		log.Errorf("failed to open websocket with rancher server: %s", err)
	}

	var data = make([]byte, 1024)
	var n int
	if n, err = ws.Read(data); err != nil && err.Error() != "EOF" {
		log.Errorf("failed to retrieve logs: %s", err)
	}
	log.WithFields(log.Fields{
		"container": mountedVolumes.ContainerID,
		"cmd":       strings.Join(command[:], " "),
	}).Debug(string(data[:n]))
	return
}

func (o *CattleOrchestrator) blacklistedVolume(vol *volume.Volume) (bool, string, string) {
	if utf8.RuneCountInString(vol.Name) == 64 || utf8.RuneCountInString(vol.Name) == 0 {
		return true, "unnamed", ""
	}

	if strings.Contains(vol.Name, "/") {
		return true, "blacklisted", "path"
	}

	list := o.Handler.Config.VolumesBlacklist
	sort.Strings(list)
	i := sort.SearchStrings(list, vol.Name)
	if i < len(list) && list[i] == vol.Name {
		return true, "blacklisted", "blacklist config"
	}

	if vol.Config.Ignore {
		return true, "blacklisted", "volume config"
	}

	return false, "", ""
}

func (o *CattleOrchestrator) rawAPICall(method, endpoint string, object interface{}) (err error) {
	// TODO: Use go-rancher.
	// It was impossible to use it, maybe a problem in go-rancher or a lack of documentation.
	clientHTTP := &http.Client{}
	v := url.Values{}
	req, err := http.NewRequest(method, endpoint, strings.NewReader(v.Encode()))
	req.SetBasicAuth(o.Handler.Config.Cattle.AccessKey, o.Handler.Config.Cattle.SecretKey)
	resp, err := clientHTTP.Do(req)
	if err != nil {
		log.Errorf("failed to execute POST request: %s", err)
	}
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		log.Errorf("failed to read response from rancher: %s", err)
	}
	err = json.Unmarshal(body, object)
	if err != nil {
		log.Errorf("failed to unmarshal: %s", err)
	}
	return
}

func detectCattle() bool {
	_, err := net.LookupHost("rancher-metadata")
	if err != nil {
		return false
	}
	return true
}
<|endoftext|>


<commit_before>package main

import (
	"context"
	"errors"
	"fmt"
	"io/ioutil"
	"os"
	"strings"

	"github.com/leeola/fixity"
	"github.com/leeola/fixity/reader/blobreader"
	"github.com/urfave/cli"
)

func WriteCmd(clictx *cli.Context) error {
	useStdin := clictx.Bool("stdin")
	if !useStdin {
		return errors.New("only stdin currently supported")
	}

	s, err := storeFromCli(clictx)
	if err != nil {
		// no wrap above helper errs
		return err
	}

	preview := clictx.Bool("preview")
	allowUnsafe := clictx.Bool("allow-unsafe")

	id := "foo"

	hashes, err := s.Write(context.Background(), id, nil, strings.NewReader("foo"))
	if err != nil {
		return fmt.Errorf("write: %v", err)
	}

	for _, h := range hashes {
		fmt.Println(h)

		if preview {
			if err := previewBlob(context.Background(), s, h, allowUnsafe); err != nil {
				return fmt.Errorf("previewblob: %v", err)
			}
		}
	}

	return nil
}

func previewBlob(ctx context.Context, s store, ref fixity.Ref, notSafe bool) error {
	rc, err := s.Blob(ctx, ref)
	if err != nil {
		return fmt.Errorf("blob: %v", err)
	}
	defer rc.Close()

	r, bt, err := blobreader.BlobType(rc)
	if err != nil {
		return fmt.Errorf("blobtype: %v", err)
	}

	b, err := ioutil.ReadAll(r)
	if err != nil {
		return fmt.Errorf("readall: %v", err)
	}

	switch {
	case bt != fixity.BlobTypeSchemaless:
		if err := printJsonBytes(os.Stdout, b); err != nil {
			return fmt.Errorf("printjsonbytes: %v", err)
		}
	case notSafe:
		fmt.Println(string(b))
	}

	return nil
}
<commit_msg>feat: impl stdin writing<commit_after>package main

import (
	"context"
	"fmt"
	"io"
	"io/ioutil"
	"os"

	"github.com/leeola/fixity"
	"github.com/leeola/fixity/reader/blobreader"
	"github.com/urfave/cli"
)

func WriteCmd(clictx *cli.Context) error {
	useStdin := clictx.Bool("stdin")

	var r io.Reader
	switch {
	case useStdin:
		r = os.Stdin
	}

	s, err := storeFromCli(clictx)
	if err != nil {
		// no wrap above helper errs
		return err
	}

	preview := clictx.Bool("preview")
	allowUnsafe := clictx.Bool("allow-unsafe")

	id := "foo"

	hashes, err := s.Write(context.Background(), id, nil, r)
	if err != nil {
		return fmt.Errorf("write: %v", err)
	}

	for _, h := range hashes {
		fmt.Println(h)

		if preview {
			if err := previewBlob(context.Background(), s, h, allowUnsafe); err != nil {
				return fmt.Errorf("previewblob: %v", err)
			}
		}
	}

	return nil
}

func previewBlob(ctx context.Context, s store, ref fixity.Ref, notSafe bool) error {
	rc, err := s.Blob(ctx, ref)
	if err != nil {
		return fmt.Errorf("blob: %v", err)
	}
	defer rc.Close()

	r, bt, err := blobreader.BlobType(rc)
	if err != nil {
		return fmt.Errorf("blobtype: %v", err)
	}

	b, err := ioutil.ReadAll(r)
	if err != nil {
		return fmt.Errorf("readall: %v", err)
	}

	switch {
	case bt != fixity.BlobTypeSchemaless:
		if err := printJsonBytes(os.Stdout, b); err != nil {
			return fmt.Errorf("printjsonbytes: %v", err)
		}
	case notSafe:
		fmt.Println(string(b))
	}

	// newline
	fmt.Println("")

	return nil
}
<|endoftext|>


<commit_before>/*
Copyright The Helm 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 main

import (
	"fmt"
	"strings"

	"github.com/spf13/cobra"
	"github.com/spf13/pflag"

	"helm.sh/helm/v3/internal/completion"
	"helm.sh/helm/v3/pkg/action"
	"helm.sh/helm/v3/pkg/cli/output"
	"helm.sh/helm/v3/pkg/cli/values"
	"helm.sh/helm/v3/pkg/postrender"
)

const outputFlag = "output"
const postRenderFlag = "post-renderer"

func addValueOptionsFlags(f *pflag.FlagSet, v *values.Options) {
	f.StringSliceVarP(&v.ValueFiles, "values", "f", []string{}, "specify values in a YAML file or a URL (can specify multiple)")
	f.StringArrayVar(&v.Values, "set", []string{}, "set values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2)")
	f.StringArrayVar(&v.StringValues, "set-string", []string{}, "set STRING values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2)")
	f.StringArrayVar(&v.FileValues, "set-file", []string{}, "set values from respective files specified via the command line (can specify multiple or separate values with commas: key1=path1,key2=path2)")
}

func addChartPathOptionsFlags(f *pflag.FlagSet, c *action.ChartPathOptions) {
	f.StringVar(&c.Version, "version", "", "specify the exact chart version to install. If this is not specified, the latest version is installed")
	f.BoolVar(&c.Verify, "verify", false, "verify the package before installing it")
	f.StringVar(&c.Keyring, "keyring", defaultKeyring(), "location of public keys used for verification")
	f.StringVar(&c.RepoURL, "repo", "", "chart repository url where to locate the requested chart")
	f.StringVar(&c.Username, "username", "", "chart repository username where to locate the requested chart")
	f.StringVar(&c.Password, "password", "", "chart repository password where to locate the requested chart")
	f.StringVar(&c.CertFile, "cert-file", "", "identify HTTPS client using this SSL certificate file")
	f.StringVar(&c.KeyFile, "key-file", "", "identify HTTPS client using this SSL key file")
	f.StringVar(&c.CaFile, "ca-file", "", "verify certificates of HTTPS-enabled servers using this CA bundle")
}

// bindOutputFlag will add the output flag to the given command and bind the
// value to the given format pointer
func bindOutputFlag(cmd *cobra.Command, varRef *output.Format) {
	f := cmd.Flags()
	flag := f.VarPF(newOutputValue(output.Table, varRef), outputFlag, "o",
		fmt.Sprintf("prints the output in the specified format. Allowed values: %s", strings.Join(output.Formats(), ", ")))

	completion.RegisterFlagCompletionFunc(flag, func(cmd *cobra.Command, args []string, toComplete string) ([]string, completion.BashCompDirective) {
		var formatNames []string
		for _, format := range output.Formats() {
			if strings.HasPrefix(format, toComplete) {
				formatNames = append(formatNames, format)
			}
		}
		return formatNames, completion.BashCompDirectiveDefault
	})
}

type outputValue output.Format

func newOutputValue(defaultValue output.Format, p *output.Format) *outputValue {
	*p = defaultValue
	return (*outputValue)(p)
}

func (o *outputValue) String() string {
	// It is much cleaner looking (and technically less allocations) to just
	// convert to a string rather than type asserting to the underlying
	// output.Format
	return string(*o)
}

func (o *outputValue) Type() string {
	return "format"
}

func (o *outputValue) Set(s string) error {
	outfmt, err := output.ParseFormat(s)
	if err != nil {
		return err
	}
	*o = outputValue(outfmt)
	return nil
}

func bindPostRenderFlag(cmd *cobra.Command, varRef *postrender.PostRenderer) {
	cmd.Flags().Var(&postRenderer{varRef}, postRenderFlag, "the path to an executable to be used for post rendering. If it exists in $PATH, the binary will be used, otherwise it will try to look for the executable at the given path")
}

type postRenderer struct {
	renderer *postrender.PostRenderer
}

func (p postRenderer) String() string {
	return "exec"
}

func (p postRenderer) Type() string {
	return "postrenderer"
}

func (p postRenderer) Set(s string) error {
	if s == "" {
		return nil
	}
	pr, err := postrender.NewExec(s)
	if err != nil {
		return err
	}
	*p.renderer = pr
	return nil
}
<commit_msg>fix(doc): generic description for --version/verify<commit_after>/*
Copyright The Helm 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 main

import (
	"fmt"
	"strings"

	"github.com/spf13/cobra"
	"github.com/spf13/pflag"

	"helm.sh/helm/v3/internal/completion"
	"helm.sh/helm/v3/pkg/action"
	"helm.sh/helm/v3/pkg/cli/output"
	"helm.sh/helm/v3/pkg/cli/values"
	"helm.sh/helm/v3/pkg/postrender"
)

const outputFlag = "output"
const postRenderFlag = "post-renderer"

func addValueOptionsFlags(f *pflag.FlagSet, v *values.Options) {
	f.StringSliceVarP(&v.ValueFiles, "values", "f", []string{}, "specify values in a YAML file or a URL (can specify multiple)")
	f.StringArrayVar(&v.Values, "set", []string{}, "set values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2)")
	f.StringArrayVar(&v.StringValues, "set-string", []string{}, "set STRING values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2)")
	f.StringArrayVar(&v.FileValues, "set-file", []string{}, "set values from respective files specified via the command line (can specify multiple or separate values with commas: key1=path1,key2=path2)")
}

func addChartPathOptionsFlags(f *pflag.FlagSet, c *action.ChartPathOptions) {
	f.StringVar(&c.Version, "version", "", "specify the exact chart version to use. If this is not specified, the latest version is used")
	f.BoolVar(&c.Verify, "verify", false, "verify the package before using it")
	f.StringVar(&c.Keyring, "keyring", defaultKeyring(), "location of public keys used for verification")
	f.StringVar(&c.RepoURL, "repo", "", "chart repository url where to locate the requested chart")
	f.StringVar(&c.Username, "username", "", "chart repository username where to locate the requested chart")
	f.StringVar(&c.Password, "password", "", "chart repository password where to locate the requested chart")
	f.StringVar(&c.CertFile, "cert-file", "", "identify HTTPS client using this SSL certificate file")
	f.StringVar(&c.KeyFile, "key-file", "", "identify HTTPS client using this SSL key file")
	f.StringVar(&c.CaFile, "ca-file", "", "verify certificates of HTTPS-enabled servers using this CA bundle")
}

// bindOutputFlag will add the output flag to the given command and bind the
// value to the given format pointer
func bindOutputFlag(cmd *cobra.Command, varRef *output.Format) {
	f := cmd.Flags()
	flag := f.VarPF(newOutputValue(output.Table, varRef), outputFlag, "o",
		fmt.Sprintf("prints the output in the specified format. Allowed values: %s", strings.Join(output.Formats(), ", ")))

	completion.RegisterFlagCompletionFunc(flag, func(cmd *cobra.Command, args []string, toComplete string) ([]string, completion.BashCompDirective) {
		var formatNames []string
		for _, format := range output.Formats() {
			if strings.HasPrefix(format, toComplete) {
				formatNames = append(formatNames, format)
			}
		}
		return formatNames, completion.BashCompDirectiveDefault
	})
}

type outputValue output.Format

func newOutputValue(defaultValue output.Format, p *output.Format) *outputValue {
	*p = defaultValue
	return (*outputValue)(p)
}

func (o *outputValue) String() string {
	// It is much cleaner looking (and technically less allocations) to just
	// convert to a string rather than type asserting to the underlying
	// output.Format
	return string(*o)
}

func (o *outputValue) Type() string {
	return "format"
}

func (o *outputValue) Set(s string) error {
	outfmt, err := output.ParseFormat(s)
	if err != nil {
		return err
	}
	*o = outputValue(outfmt)
	return nil
}

func bindPostRenderFlag(cmd *cobra.Command, varRef *postrender.PostRenderer) {
	cmd.Flags().Var(&postRenderer{varRef}, postRenderFlag, "the path to an executable to be used for post rendering. If it exists in $PATH, the binary will be used, otherwise it will try to look for the executable at the given path")
}

type postRenderer struct {
	renderer *postrender.PostRenderer
}

func (p postRenderer) String() string {
	return "exec"
}

func (p postRenderer) Type() string {
	return "postrenderer"
}

func (p postRenderer) Set(s string) error {
	if s == "" {
		return nil
	}
	pr, err := postrender.NewExec(s)
	if err != nil {
		return err
	}
	*p.renderer = pr
	return nil
}
<|endoftext|>


<commit_before>package main

import (
	cmds "github.com/jbenet/go-ipfs/commands"
	commands "github.com/jbenet/go-ipfs/core/commands2"
)

var Root = &cmds.Command{
	Options: commands.Root.Options,
	Help:    commands.Root.Help,
}

var rootSubcommands = map[string]*cmds.Command{
	"daemon": daemonCmd, // TODO name
	"init":   initCmd,   // TODO name
	"tour":   cmdTour,
}

func init() {
	// setting here instead of in literal to prevent initialization loop
	// (some commands make references to Root)
	Root.Subcommands = rootSubcommands

	// copy all subcommands from commands.Root into this root (if they aren't already present)
	for k, v := range commands.Root.Subcommands {
		if _, found := Root.Subcommands[k]; !found {
			Root.Subcommands[k] = v
		}
	}
}
<commit_msg>cmd/ipfs2: Added a 'commands' command for CLI root<commit_after>package main

import (
	cmds "github.com/jbenet/go-ipfs/commands"
	commands "github.com/jbenet/go-ipfs/core/commands2"
)

var Root = &cmds.Command{
	Options: commands.Root.Options,
	Help:    commands.Root.Help,
}

var rootSubcommands = map[string]*cmds.Command{
	"daemon":   daemonCmd, // TODO name
	"init":     initCmd,   // TODO name
	"tour":     cmdTour,
	"commands": commands.CommandsCmd(Root),
}

func init() {
	// setting here instead of in literal to prevent initialization loop
	// (some commands make references to Root)
	Root.Subcommands = rootSubcommands

	// copy all subcommands from commands.Root into this root (if they aren't already present)
	for k, v := range commands.Root.Subcommands {
		if _, found := Root.Subcommands[k]; !found {
			Root.Subcommands[k] = v
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"errors"
	"fmt"
	"io"
	"os"
	"os/signal"
	"runtime/pprof"

	logging "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-logging"
	ma "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr"
	manet "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr/net"

	cmds "github.com/jbenet/go-ipfs/commands"
	cmdsCli "github.com/jbenet/go-ipfs/commands/cli"
	cmdsHttp "github.com/jbenet/go-ipfs/commands/http"
	config "github.com/jbenet/go-ipfs/config"
	core "github.com/jbenet/go-ipfs/core"
	daemon "github.com/jbenet/go-ipfs/daemon2"
	updates "github.com/jbenet/go-ipfs/updates"
	u "github.com/jbenet/go-ipfs/util"
	"github.com/jbenet/go-ipfs/util/debugerror"
)

// log is the command logger
var log = u.Logger("cmd/ipfs")

// signal to output help
var errHelpRequested = errors.New("Help Requested")

const (
	cpuProfile  = "ipfs.cpuprof"
	heapProfile = "ipfs.memprof"
	errorFormat = "ERROR: %v\n\n"
)

type cmdInvocation struct {
	path []string
	cmd  *cmds.Command
	req  cmds.Request
}

// main roadmap:
// - parse the commandline to get a cmdInvocation
// - if user requests, help, print it and exit.
// - run the command invocation
// - output the response
// - if anything fails, print error, maybe with help
func main() {
	var invoc cmdInvocation
	var err error

	// we'll call this local helper to output errors.
	// this is so we control how to print errors in one place.
	printErr := func(err error) {
		fmt.Fprintf(os.Stderr, "Error: %s\n", err.Error())
	}

	// this is a local helper to print out help text.
	// there's some considerations that this makes easier.
	printHelp := func(long bool) {
		helpFunc := cmdsCli.ShortHelp
		if long {
			helpFunc = cmdsCli.LongHelp
		}

		helpFunc("ipfs", Root, invoc.path, os.Stderr)
	}

	// parse the commandline into a command invocation
	parseErr := invoc.Parse(os.Args[1:])

	// BEFORE handling the parse error, if we have enough information
	// AND the user requested help, print it out and exit
	if invoc.req != nil {
		longH, shortH, err := invoc.requestedHelp()
		if err != nil {
			printErr(err)
			os.Exit(1)
		}
		if longH || shortH {
			printHelp(longH)
			os.Exit(0)
		}
	}

	// here we handle the cases where
	// - commands with no Run func are invoked directly.
	// - the main command is invoked.
	if invoc.cmd == nil || invoc.cmd.Run == nil {
		printHelp(false)
		os.Exit(0)
	}

	// ok now handle parse error (which means cli input was wrong,
	// e.g. incorrect number of args, or nonexistent subcommand)
	if parseErr != nil {
		printErr(parseErr)

		// this was a user error, print help.
		if invoc.cmd != nil {
			// we need a newline space.
			fmt.Fprintf(os.Stderr, "\n")
			printHelp(false)
		}
		os.Exit(1)
	}

	// ok, finally, run the command invocation.
	output, err := invoc.Run()
	if err != nil {
		printErr(err)

		// if this error was a client error, print short help too.
		if isClientError(err) {
			printHelp(false)
		}
		os.Exit(1)
	}

	// everything went better than expected :)
	io.Copy(os.Stdout, output)
}

func (i *cmdInvocation) Run() (output io.Reader, err error) {
	handleInterrupt()

	// check if user wants to debug. option OR env var.
	debug, _, err := i.req.Option("debug").Bool()
	if err != nil {
		return nil, err
	}
	if debug || u.GetenvBool("DEBUG") || os.Getenv("IPFS_LOGGING") == "debug" {
		u.Debug = true
		u.SetAllLoggers(logging.DEBUG)
	}

	// if debugging, let's profile.
	// TODO maybe change this to its own option... profiling makes it slower.
	if u.Debug {
		stopProfilingFunc, err := startProfiling()
		if err != nil {
			return nil, err
		}
		defer stopProfilingFunc() // to be executed as late as possible
	}

	res, err := callCommand(i.req, Root)
	if err != nil {
		return nil, err
	}

	if err := res.Error(); err != nil {
		return nil, err
	}

	return res.Reader()
}

func (i *cmdInvocation) Parse(args []string) error {
	var err error

	i.req, i.cmd, i.path, err = cmdsCli.Parse(args, os.Stdin, Root)
	if err != nil {
		return err
	}

	configPath, err := getConfigRoot(i.req)
	if err != nil {
		return err
	}
	log.Debugf("config path is %s", configPath)

	// this sets up the function that will initialize the config lazily.
	ctx := i.req.Context()
	ctx.ConfigRoot = configPath
	ctx.LoadConfig = loadConfig

	// if no encoding was specified by user, default to plaintext encoding
	// (if command doesn't support plaintext, use JSON instead)
	if !i.req.Option("encoding").Found() {
		if i.req.Command().Marshalers != nil && i.req.Command().Marshalers[cmds.Text] != nil {
			i.req.SetOption("encoding", cmds.Text)
		} else {
			i.req.SetOption("encoding", cmds.JSON)
		}
	}

	return nil
}

func (i *cmdInvocation) requestedHelp() (short bool, long bool, err error) {
	longHelp, _, err := i.req.Option("help").Bool()
	if err != nil {
		return false, false, err
	}
	shortHelp, _, err := i.req.Option("h").Bool()
	if err != nil {
		return false, false, err
	}
	return longHelp, shortHelp, nil
}

func callPreCommandHooks(details cmdDetails, req cmds.Request, root *cmds.Command) error {

	log.Debug("Calling pre-command hooks...")

	// some hooks only run when the command is executed locally
	daemon, err := commandShouldRunOnDaemon(details, req, root)
	if err != nil {
		return err
	}

	// check for updates when 1) commands is going to be run locally, 2) the
	// command does not initialize the config, and 3) the command does not
	// pre-empt updates
	if !daemon && !details.initializesConfig && !details.preemptsAutoUpdate {

		log.Debug("Calling hook: Check for updates")

		cfg, err := req.Context().GetConfig()
		if err != nil {
			return err
		}
		// Check for updates and potentially install one.
		if err := updates.CliCheckForUpdates(cfg, req.Context().ConfigRoot); err != nil {
			return err
		}
	}

	return nil
}

func callCommand(req cmds.Request, root *cmds.Command) (cmds.Response, error) {
	var res cmds.Response

	details, err := commandDetails(req.Path(), root)
	if err != nil {
		return nil, err
	}

	useDaemon, err := commandShouldRunOnDaemon(*details, req, root)
	if err != nil {
		return nil, err
	}

	err = callPreCommandHooks(*details, req, root)
	if err != nil {
		return nil, err
	}

	if useDaemon {

		cfg, err := req.Context().GetConfig()
		if err != nil {
			return nil, err
		}

		addr, err := ma.NewMultiaddr(cfg.Addresses.API)
		if err != nil {
			return nil, err
		}

		log.Infof("Executing command on daemon running at %s", addr)
		_, host, err := manet.DialArgs(addr)
		if err != nil {
			return nil, err
		}

		client := cmdsHttp.NewClient(host)

		res, err = client.Send(req)
		if err != nil {
			return nil, err
		}

	} else {
		log.Info("Executing command locally")

		// this sets up the function that will initialize the node
		// this is so that we can construct the node lazily.
		ctx := req.Context()
		ctx.ConstructNode = func() (*core.IpfsNode, error) {
			cfg, err := ctx.GetConfig()
			if err != nil {
				return nil, err
			}
			return core.NewIpfsNode(cfg, false)
		}

		// Okay!!!!! NOW we can call the command.
		res = root.Call(req)

		// let's not forget teardown. If a node was initialized, we must close it.
		// Note that this means the underlying req.Context().Node variable is exposed.
		// this is gross, and should be changed when we extract out the exec Context.
		node := req.Context().NodeWithoutConstructing()
		if node != nil {
			node.Close()
		}
	}
	return res, nil
}

// commandDetails returns a command's details for the command given by |path|
// within the |root| command tree.
//
// Returns an error if the command is not found in the Command tree.
func commandDetails(path []string, root *cmds.Command) (*cmdDetails, error) {
	var details cmdDetails
	// find the last command in path that has a cmdDetailsMap entry
	cmd := root
	for _, cmp := range path {
		var found bool
		cmd, found = cmd.Subcommands[cmp]
		if !found {
			return nil, debugerror.Errorf("subcommand %s should be in root", cmp)
		}

		if cmdDetails, found := cmdDetailsMap[cmd]; found {
			details = cmdDetails
		}
	}
	log.Debugf("cmd perms for +%v: %s", path, details.String())
	return &details, nil
}

// commandShouldRunOnDaemon determines, from commmand details, whether a
// command ought to be executed on an IPFS daemon.
//
// It returns true if the command should be executed on a daemon and false if
// it should be executed on a client. It returns an error if the command must
// NOT be executed on either.
func commandShouldRunOnDaemon(details cmdDetails, req cmds.Request, root *cmds.Command) (bool, error) {
	path := req.Path()
	// root command.
	if len(path) < 1 {
		return false, nil
	}

	if details.cannotRunOnClient && details.cannotRunOnDaemon {
		return false, fmt.Errorf("command disabled: %s", path[0])
	}

	if details.doesNotUseRepo && details.canRunOnClient() {
		return false, nil
	}

	// at this point need to know whether daemon is running. we defer
	// to this point so that some commands dont open files unnecessarily.
	daemonLocked := daemon.Locked(req.Context().ConfigRoot)
	log.Info("Daemon is running.")

	if daemonLocked {

		if details.cannotRunOnDaemon {
			e := "ipfs daemon is running. please stop it to run this command"
			return false, cmds.ClientError(e)
		}

		return true, nil
	}

	if details.cannotRunOnClient {
		return false, cmds.ClientError("must run on the ipfs daemon")
	}

	return false, nil
}

func isClientError(err error) bool {

	// Somewhat suprisingly, the pointer cast fails to recognize commands.Error
	// passed as values, so we check both.

	// cast to cmds.Error
	switch e := err.(type) {
	case *cmds.Error:
		return e.Code == cmds.ErrClient
	case cmds.Error:
		return e.Code == cmds.ErrClient
	}
	return false
}

func getConfigRoot(req cmds.Request) (string, error) {
	configOpt, found, err := req.Option("config").String()
	if err != nil {
		return "", err
	}
	if found && configOpt != "" {
		return configOpt, nil
	}

	configPath, err := config.PathRoot()
	if err != nil {
		return "", err
	}
	return configPath, nil
}

func loadConfig(path string) (*config.Config, error) {
	configFile, err := config.Filename(path)
	if err != nil {
		return nil, err
	}

	return config.Load(configFile)
}

// startProfiling begins CPU profiling and returns a `stop` function to be
// executed as late as possible. The stop function captures the memprofile.
func startProfiling() (func(), error) {

	// start CPU profiling as early as possible
	ofi, err := os.Create(cpuProfile)
	if err != nil {
		return nil, err
	}
	pprof.StartCPUProfile(ofi)

	stopProfiling := func() {
		pprof.StopCPUProfile()
		defer ofi.Close() // captured by the closure
		err := writeHeapProfileToFile()
		if err != nil {
			log.Critical(err)
		}
	}
	return stopProfiling, nil
}

func writeHeapProfileToFile() error {
	mprof, err := os.Create(heapProfile)
	if err != nil {
		return err
	}
	defer mprof.Close() // _after_ writing the heap profile
	return pprof.WriteHeapProfile(mprof)
}

// listen for and handle SIGTERM
func handleInterrupt() {
	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt)

	go func() {
		for _ = range c {
			log.Info("Received interrupt signal, terminating...")
			os.Exit(0)
		}
	}()
}
<commit_msg>cmds: fixed help stdio use<commit_after>package main

import (
	"errors"
	"fmt"
	"io"
	"os"
	"os/signal"
	"runtime/pprof"

	logging "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-logging"
	ma "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr"
	manet "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr/net"

	cmds "github.com/jbenet/go-ipfs/commands"
	cmdsCli "github.com/jbenet/go-ipfs/commands/cli"
	cmdsHttp "github.com/jbenet/go-ipfs/commands/http"
	config "github.com/jbenet/go-ipfs/config"
	core "github.com/jbenet/go-ipfs/core"
	daemon "github.com/jbenet/go-ipfs/daemon2"
	updates "github.com/jbenet/go-ipfs/updates"
	u "github.com/jbenet/go-ipfs/util"
	"github.com/jbenet/go-ipfs/util/debugerror"
)

// log is the command logger
var log = u.Logger("cmd/ipfs")

// signal to output help
var errHelpRequested = errors.New("Help Requested")

const (
	cpuProfile  = "ipfs.cpuprof"
	heapProfile = "ipfs.memprof"
	errorFormat = "ERROR: %v\n\n"
)

type cmdInvocation struct {
	path []string
	cmd  *cmds.Command
	req  cmds.Request
}

// main roadmap:
// - parse the commandline to get a cmdInvocation
// - if user requests, help, print it and exit.
// - run the command invocation
// - output the response
// - if anything fails, print error, maybe with help
func main() {
	var invoc cmdInvocation
	var err error

	// we'll call this local helper to output errors.
	// this is so we control how to print errors in one place.
	printErr := func(err error) {
		fmt.Fprintf(os.Stderr, "Error: %s\n", err.Error())
	}

	// this is a local helper to print out help text.
	// there's some considerations that this makes easier.
	printHelp := func(long bool, w io.Writer) {
		helpFunc := cmdsCli.ShortHelp
		if long {
			helpFunc = cmdsCli.LongHelp
		}

		helpFunc("ipfs", Root, invoc.path, w)
	}

	// parse the commandline into a command invocation
	parseErr := invoc.Parse(os.Args[1:])

	// BEFORE handling the parse error, if we have enough information
	// AND the user requested help, print it out and exit
	if invoc.req != nil {
		longH, shortH, err := invoc.requestedHelp()
		if err != nil {
			printErr(err)
			os.Exit(1)
		}
		if longH || shortH {
			printHelp(longH, os.Stdout)
			os.Exit(0)
		}
	}

	// here we handle the cases where
	// - commands with no Run func are invoked directly.
	// - the main command is invoked.
	if invoc.cmd == nil || invoc.cmd.Run == nil {
		printHelp(false, os.Stdout)
		os.Exit(0)
	}

	// ok now handle parse error (which means cli input was wrong,
	// e.g. incorrect number of args, or nonexistent subcommand)
	if parseErr != nil {
		printErr(parseErr)

		// this was a user error, print help.
		if invoc.cmd != nil {
			// we need a newline space.
			fmt.Fprintf(os.Stderr, "\n")
			printHelp(false, os.Stderr)
		}
		os.Exit(1)
	}

	// ok, finally, run the command invocation.
	output, err := invoc.Run()
	if err != nil {
		printErr(err)

		// if this error was a client error, print short help too.
		if isClientError(err) {
			printHelp(false, os.Stderr)
		}
		os.Exit(1)
	}

	// everything went better than expected :)
	io.Copy(os.Stdout, output)
}

func (i *cmdInvocation) Run() (output io.Reader, err error) {
	handleInterrupt()

	// check if user wants to debug. option OR env var.
	debug, _, err := i.req.Option("debug").Bool()
	if err != nil {
		return nil, err
	}
	if debug || u.GetenvBool("DEBUG") || os.Getenv("IPFS_LOGGING") == "debug" {
		u.Debug = true
		u.SetAllLoggers(logging.DEBUG)
	}

	// if debugging, let's profile.
	// TODO maybe change this to its own option... profiling makes it slower.
	if u.Debug {
		stopProfilingFunc, err := startProfiling()
		if err != nil {
			return nil, err
		}
		defer stopProfilingFunc() // to be executed as late as possible
	}

	res, err := callCommand(i.req, Root)
	if err != nil {
		return nil, err
	}

	if err := res.Error(); err != nil {
		return nil, err
	}

	return res.Reader()
}

func (i *cmdInvocation) Parse(args []string) error {
	var err error

	i.req, i.cmd, i.path, err = cmdsCli.Parse(args, os.Stdin, Root)
	if err != nil {
		return err
	}

	configPath, err := getConfigRoot(i.req)
	if err != nil {
		return err
	}
	log.Debugf("config path is %s", configPath)

	// this sets up the function that will initialize the config lazily.
	ctx := i.req.Context()
	ctx.ConfigRoot = configPath
	ctx.LoadConfig = loadConfig

	// if no encoding was specified by user, default to plaintext encoding
	// (if command doesn't support plaintext, use JSON instead)
	if !i.req.Option("encoding").Found() {
		if i.req.Command().Marshalers != nil && i.req.Command().Marshalers[cmds.Text] != nil {
			i.req.SetOption("encoding", cmds.Text)
		} else {
			i.req.SetOption("encoding", cmds.JSON)
		}
	}

	return nil
}

func (i *cmdInvocation) requestedHelp() (short bool, long bool, err error) {
	longHelp, _, err := i.req.Option("help").Bool()
	if err != nil {
		return false, false, err
	}
	shortHelp, _, err := i.req.Option("h").Bool()
	if err != nil {
		return false, false, err
	}
	return longHelp, shortHelp, nil
}

func callPreCommandHooks(details cmdDetails, req cmds.Request, root *cmds.Command) error {

	log.Debug("Calling pre-command hooks...")

	// some hooks only run when the command is executed locally
	daemon, err := commandShouldRunOnDaemon(details, req, root)
	if err != nil {
		return err
	}

	// check for updates when 1) commands is going to be run locally, 2) the
	// command does not initialize the config, and 3) the command does not
	// pre-empt updates
	if !daemon && !details.initializesConfig && !details.preemptsAutoUpdate {

		log.Debug("Calling hook: Check for updates")

		cfg, err := req.Context().GetConfig()
		if err != nil {
			return err
		}
		// Check for updates and potentially install one.
		if err := updates.CliCheckForUpdates(cfg, req.Context().ConfigRoot); err != nil {
			return err
		}
	}

	return nil
}

func callCommand(req cmds.Request, root *cmds.Command) (cmds.Response, error) {
	var res cmds.Response

	details, err := commandDetails(req.Path(), root)
	if err != nil {
		return nil, err
	}

	useDaemon, err := commandShouldRunOnDaemon(*details, req, root)
	if err != nil {
		return nil, err
	}

	err = callPreCommandHooks(*details, req, root)
	if err != nil {
		return nil, err
	}

	if useDaemon {

		cfg, err := req.Context().GetConfig()
		if err != nil {
			return nil, err
		}

		addr, err := ma.NewMultiaddr(cfg.Addresses.API)
		if err != nil {
			return nil, err
		}

		log.Infof("Executing command on daemon running at %s", addr)
		_, host, err := manet.DialArgs(addr)
		if err != nil {
			return nil, err
		}

		client := cmdsHttp.NewClient(host)

		res, err = client.Send(req)
		if err != nil {
			return nil, err
		}

	} else {
		log.Info("Executing command locally")

		// this sets up the function that will initialize the node
		// this is so that we can construct the node lazily.
		ctx := req.Context()
		ctx.ConstructNode = func() (*core.IpfsNode, error) {
			cfg, err := ctx.GetConfig()
			if err != nil {
				return nil, err
			}
			return core.NewIpfsNode(cfg, false)
		}

		// Okay!!!!! NOW we can call the command.
		res = root.Call(req)

		// let's not forget teardown. If a node was initialized, we must close it.
		// Note that this means the underlying req.Context().Node variable is exposed.
		// this is gross, and should be changed when we extract out the exec Context.
		node := req.Context().NodeWithoutConstructing()
		if node != nil {
			node.Close()
		}
	}
	return res, nil
}

// commandDetails returns a command's details for the command given by |path|
// within the |root| command tree.
//
// Returns an error if the command is not found in the Command tree.
func commandDetails(path []string, root *cmds.Command) (*cmdDetails, error) {
	var details cmdDetails
	// find the last command in path that has a cmdDetailsMap entry
	cmd := root
	for _, cmp := range path {
		var found bool
		cmd, found = cmd.Subcommands[cmp]
		if !found {
			return nil, debugerror.Errorf("subcommand %s should be in root", cmp)
		}

		if cmdDetails, found := cmdDetailsMap[cmd]; found {
			details = cmdDetails
		}
	}
	log.Debugf("cmd perms for +%v: %s", path, details.String())
	return &details, nil
}

// commandShouldRunOnDaemon determines, from commmand details, whether a
// command ought to be executed on an IPFS daemon.
//
// It returns true if the command should be executed on a daemon and false if
// it should be executed on a client. It returns an error if the command must
// NOT be executed on either.
func commandShouldRunOnDaemon(details cmdDetails, req cmds.Request, root *cmds.Command) (bool, error) {
	path := req.Path()
	// root command.
	if len(path) < 1 {
		return false, nil
	}

	if details.cannotRunOnClient && details.cannotRunOnDaemon {
		return false, fmt.Errorf("command disabled: %s", path[0])
	}

	if details.doesNotUseRepo && details.canRunOnClient() {
		return false, nil
	}

	// at this point need to know whether daemon is running. we defer
	// to this point so that some commands dont open files unnecessarily.
	daemonLocked := daemon.Locked(req.Context().ConfigRoot)
	log.Info("Daemon is running.")

	if daemonLocked {

		if details.cannotRunOnDaemon {
			e := "ipfs daemon is running. please stop it to run this command"
			return false, cmds.ClientError(e)
		}

		return true, nil
	}

	if details.cannotRunOnClient {
		return false, cmds.ClientError("must run on the ipfs daemon")
	}

	return false, nil
}

func isClientError(err error) bool {

	// Somewhat suprisingly, the pointer cast fails to recognize commands.Error
	// passed as values, so we check both.

	// cast to cmds.Error
	switch e := err.(type) {
	case *cmds.Error:
		return e.Code == cmds.ErrClient
	case cmds.Error:
		return e.Code == cmds.ErrClient
	}
	return false
}

func getConfigRoot(req cmds.Request) (string, error) {
	configOpt, found, err := req.Option("config").String()
	if err != nil {
		return "", err
	}
	if found && configOpt != "" {
		return configOpt, nil
	}

	configPath, err := config.PathRoot()
	if err != nil {
		return "", err
	}
	return configPath, nil
}

func loadConfig(path string) (*config.Config, error) {
	configFile, err := config.Filename(path)
	if err != nil {
		return nil, err
	}

	return config.Load(configFile)
}

// startProfiling begins CPU profiling and returns a `stop` function to be
// executed as late as possible. The stop function captures the memprofile.
func startProfiling() (func(), error) {

	// start CPU profiling as early as possible
	ofi, err := os.Create(cpuProfile)
	if err != nil {
		return nil, err
	}
	pprof.StartCPUProfile(ofi)

	stopProfiling := func() {
		pprof.StopCPUProfile()
		defer ofi.Close() // captured by the closure
		err := writeHeapProfileToFile()
		if err != nil {
			log.Critical(err)
		}
	}
	return stopProfiling, nil
}

func writeHeapProfileToFile() error {
	mprof, err := os.Create(heapProfile)
	if err != nil {
		return err
	}
	defer mprof.Close() // _after_ writing the heap profile
	return pprof.WriteHeapProfile(mprof)
}

// listen for and handle SIGTERM
func handleInterrupt() {
	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt)

	go func() {
		for _ = range c {
			log.Info("Received interrupt signal, terminating...")
			os.Exit(0)
		}
	}()
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"log"
	"time"

	"github.com/koron/go-kmoni"
)

func data2str(d *kmoni.Data) string {
	if d.ReportID == "" {
		return ""
	}
	n := fmt.Sprintf("第%s報", d.ReportNum)
	if d.IsFinal {
		n = "最終報"
	}
	return fmt.Sprintf("%s %s %s M%s 深さ%s 最大予測震度%s", d.ReportTime, n,
		d.RegionName, d.Maginitude, d.Depth, d.Calcintensity)
}

func put(d *kmoni.Data) {
	s := data2str(d)
	if s == "" {
		return
	}
	fmt.Println(s)
}

func main() {
	var last *kmoni.Data
	retry := 0
	for {
		d, err := kmoni.Now()
		if err != nil {
			if retry >= 3 {
				panic(err)
			}
			retry++
			log.Printf("INFO: retry#%d for: %s", retry, err.Error())
			time.Sleep(5 * time.Second)
			continue
		}
		retry = 0
		if !d.Equals(last) {
			put(d)
			last = d
		}
		time.Sleep(5 * time.Second)
	}
}
<commit_msg>silent retry<commit_after>package main

import (
	"fmt"
	"log"
	"time"

	"github.com/koron/go-kmoni"
)

func data2str(d *kmoni.Data) string {
	if d.ReportID == "" {
		return ""
	}
	n := fmt.Sprintf("第%s報", d.ReportNum)
	if d.IsFinal {
		n = "最終報"
	}
	return fmt.Sprintf("%s %s %s M%s 深さ%s 最大予測震度%s", d.ReportTime, n,
		d.RegionName, d.Maginitude, d.Depth, d.Calcintensity)
}

func put(d *kmoni.Data) {
	s := data2str(d)
	if s == "" {
		return
	}
	fmt.Println(s)
}

func main() {
	var last *kmoni.Data
	retry := 0
	for {
		d, err := kmoni.Now()
		if err != nil {
			if retry >= 3 {
				log.Fatalf("ERROR: much retry: %s", err.Error())
			}
			retry++
			time.Sleep(5 * time.Second)
			continue
		}
		retry = 0
		if !d.Equals(last) {
			put(d)
			last = d
		}
		time.Sleep(5 * time.Second)
	}
}
<|endoftext|>